namespace rogue_unlike { map in_queue; queue 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 code_for; map code_used; char next_code = 'A'; for(int y=0; y> 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>3])); } println(f); } println(f, "OK\n"); for(int i=0; itype; 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 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 bmap; for(int y=0; y(); 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; iid = 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(); 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; iid = 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(); 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(); 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(); 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(); 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(); 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(); 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(); 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(); 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(); 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(); 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; iqty_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); } } }