1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-06-06 08:24:06 +00:00
2025-05-11 01:37:14 +02:00

266 lines
8.6 KiB
C++

namespace rogue_unlike {
map<cell*, int> in_queue;
queue<cell*> q;
void visit(cell *c, int d) {
if(in_queue.count(c)) return;
in_queue[c] = d;
q.push(c);
}
void save_map(string fname) {
in_queue.clear();
q = {};
visit(currentmap->gamestart(), -1);
fhstream f(fname, "w");
while(!q.empty()) {
auto c = q.front();
q.pop();
auto& r = rooms[c];
if(!r.infile) continue;
auto inq = in_queue[c];
if(inq != -1) {
println(f, "MOVE ", c->c.spin(inq), " ", rooms[c->move(inq)].roomname);
}
println(f, "ROOM ", r.roomname);
map<int, char> code_for;
map<char, int> code_used;
char next_code = 'A';
for(int y=0; y<room_y; y++)
for(int x=0; x<room_x; x++) {
auto i = r.block_at[y][x] >> 3;
auto& c = code_for[i];
if(c == 0 && !code_used.count(walls[i].glyph[0])) c = walls[i].glyph[0];
if(c == 0) c = next_code++;
code_used[c] = i;
}
for(auto [key, id]: code_used) println(f, format("%c", key), " ", walls[id].name);
println(f, "MAP");
for(int y=0; y<room_y; y++) {
for(int x=0; x<room_x; x++) {
auto v = r.block_at[y][x];
print(f, format("%c", (v & 7) == 7 ? 'b' : code_for[v>>3]));
}
println(f);
}
println(f, "OK\n");
for(int i=0; i<c->type; i++) visit(c->cmove(i), c->c.spin(i));
}
}
void err(string s, string context) {
println(hlog, "while: ", context, " reading: ", s);
throw hr_exception("ru read error");
}
void load_room(fhstream& f, cell *c) {
setdist(c, 7, nullptr);
auto& r = *get_room_at(c);
string s = scanline_noblank(f);
if(s.substr(0, 5) == "ROOM ") r.roomname = s.substr(5);
else err("load_room name ", s);
println(hlog, "loading room named: ", r.roomname);
map<char, int> codes;
while(true) {
string s = scanline_noblank(f);
if(s == "") continue;
if(s == "MAP") break;
string t = s.substr(2);
if(s.size() < 3 || s[1] != ' ') err("load codes", s);
for(int i=0; i<qwall; i++) if(walls[i].name == t) {
codes[s[0]] = i;
break;
}
}
if(1) {
vector<string> bmap;
for(int y=0; y<room_y; y++) bmap.push_back(scanline_noblank(f));
for(int y=0; y<room_y; y++) for(int x=0; x<room_x; x++) {
if(bmap[y][x] == 'b') ;
else if(y < room_y-1 && bmap[y+1][x] == 'b') ;
else if(x < room_x-1 && bmap[y][x+1] == 'b') ;
else if(y < room_y-1 && x < room_x-1 && bmap[y+1][x+1] == 'b')
r.place_block_full(x, y, 8 * codes.at(bmap[y][x]) + 4);
else
r.place_block_full(x, y, 8 * codes.at(bmap[y][x]));
}
}
while(true) {
s = scanline_noblank(f);
if(s == "OK") break;
println(hlog, "s = ", s);
auto pos = s.find(" ");
if(pos != string::npos) {
string cap = s.substr(0, pos);
string param = s.substr(pos+1);
if(cap == "START") {
fountain_room = current_room = &r;
sscanf(param.c_str(), "%lf%lf", &m.where.x, &m.where.y);
fountain_where = m.where;
}
else if(cap == "ITEM") {
auto b = std::make_unique<item>();
b->qty = 1;
sscanf(param.c_str(), "%lf%lf%d", &b->where.x, &b->where.y, &b->qty);
s = scanline_noblank(f);
b->id = -1;
for(int i=0; i<isize(powers); i++) if(powers[i].name == s) b->id = i;
if(b->id == -1) println(hlog, "error: unknown item name ", s), b->id = 0;
b->pickup_message = scanline_noblank(f);
r.entities.emplace_back(std::move(b));
}
else if(cap == "SHOPITEM") {
auto b = std::make_unique<shopitem>();
b->qty = 1; b->qty1 = 0;
sscanf(param.c_str(), "%lf%lf%d%d%d", &b->where.x, &b->where.y, &b->price, &b->qty, &b->qty1);
s = scanline_noblank(f);
b->id = -1;
for(int i=0; i<isize(powers); i++) if(powers[i].name == s) b->id = i;
if(b->id == -1) println(hlog, "error: unknown item name ", s), b->id = 0;
b->pickup_message = scanline_noblank(f);
r.entities.emplace_back(std::move(b));
}
else if(cap == "NPC") {
auto b = std::make_unique<npc>();
sscanf(param.c_str(), "%lf%lf%08x", &b->where.x, &b->where.y, &b->col);
s = scanline_noblank(f);
b->sglyph = s[0];
b->name = s.substr(1);
b->text = scanline_noblank(f);
r.entities.emplace_back(std::move(b));
}
else if(cap == "TRADER") {
auto b = std::make_unique<trader>();
sscanf(param.c_str(), "%lf%lf", &b->where.x, &b->where.y);
b->name = scanline_noblank(f);
b->text = scanline_noblank(f);
r.entities.emplace_back(std::move(b));
}
else if(cap == "BOAR") {
auto b = std::make_unique<boar>();
sscanf(param.c_str(), "%lf%lf", &b->where.x, &b->where.y);
b->respawn = b->where; b->postfix();
r.entities.emplace_back(std::move(b));
}
else if(cap == "BAT") {
auto b = std::make_unique<bat>();
sscanf(param.c_str(), "%lf%lf", &b->where.x, &b->where.y);
b->respawn = b->where; b->postfix();
r.entities.emplace_back(std::move(b));
}
else if(cap == "GRIDBUG") {
auto b = std::make_unique<gridbug>();
sscanf(param.c_str(), "%lf%lf", &b->where.x, &b->where.y);
b->respawn = b->where; b->postfix();
r.entities.emplace_back(std::move(b));
}
else if(cap == "KESTREL") {
auto b = std::make_unique<kestrel>();
sscanf(param.c_str(), "%lf%lf%lf%lf", &b->where.x, &b->where.y, &b->vel.x, &b->vel.y);
b->vel *= xy(block_x, block_y) / game_fps;
b->respawn = b->where; b->respawn_vel = b->vel; b->postfix();
r.entities.emplace_back(std::move(b));
}
else if(cap == "SNAKE") {
auto b = std::make_unique<snake>();
sscanf(param.c_str(), "%lf%lf%d", &b->where.x, &b->where.y, &b->dir);
b->respawn = b->where; b->respawn_dir = b->dir; b->postfix();
r.entities.emplace_back(std::move(b));
}
else if(cap == "FERRIS") {
ld cx, cy, radius; int qty;
sscanf(param.c_str(), "%lf%lf%lf%d", &cx, &cy, &radius, &qty);
for(int i=0; i<qty; i++) {
auto b = std::make_unique<ferris_platform>();
b->ctr = {cx, cy}; b->radius = radius;
b->shift = i * TAU / qty;
r.entities.emplace_back(std::move(b));
}
}
else if(cap == "PENDULUM") {
auto b = std::make_unique<pendulum_platform>();
sscanf(param.c_str(), "%lf%lf%lf%lf%lf%lf", &b->a.x, &b->a.y, &b->b.x, &b->b.y, &b->period, &b->shift);
r.entities.emplace_back(std::move(b));
}
else if(cap == "HINT") {
auto b = std::make_unique<hint>();
sscanf(param.c_str(), "%lf%lf%lf%lf", &b->where.x, &b->where.y, &b->size.x, &b->size.y);
b->hint_text = scanline_noblank(f);
r.entities.emplace_back(std::move(b));
}
else println(hlog, "unknown mapline ", s);
}
else println(hlog, "unknown mapline ", s);
}
}
void load_map(string fname) {
fhstream f(fname, "r");
load_room(f, currentmap->gamestart());
while(!feof(f.f)) {
string s = scanline_noblank(f);
if(s == "") continue;
if(s.substr(0, 4) == "MOVE") {
int i = s[5] - '0';
string roomname = s.substr(7);
for(auto& [c,r]: rooms) if(r.roomname == roomname) load_room(f, c->move(i));
}
else err("load_map", s);
}
}
void load_cheat(string fname) {
fhstream f(fname, "r");
auto power_edited = &powers[0];
while(!feof(f.f)) {
string s = scanline_noblank(f);
auto pos = s.find(" ");
if(pos != string::npos) {
string cap = s.substr(0, pos);
string param = s.substr(pos+1);
if(cap == "START") {
for(auto& [c,r]: rooms) if(r.roomname == param) current_room = &r;
}
else if(cap == "POS") {
sscanf(param.c_str(), "%lf%lf", &m.where.x, &m.where.y);
}
else if(cap == "ITEM") {
bool found = false;
for(int i=0; i<isize(powers); i++) if(powers[i].name == param) found = true, power_edited = &powers[i];
if(!found) println(hlog, "cheat item not found: ", param);
}
else if(cap == "GAIN") {
int a, b;
sscanf(param.c_str(), "%d%d", &a, &b);
power_edited->qty_owned += a;
power_edited->qty_filled += b;
println(hlog, "gain ", power_edited->name, " qty ", tie(a,b));
}
else println(hlog, "unrecognized cheat: ", s);
}
else if(s == "IDENTIFY") {
power_edited->flags |= IDENTIFIED;
}
else if(s == "ACTIVATE") {
power_edited->flags |= ACTIVE;
}
else if(s == "") {}
else println(hlog, "unrecognized cheat: ", s);
}
}
}