From 7a57ea0a1deb4c4fb501c8d14f416e3767b21dca Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Fri, 5 Dec 2025 22:03:44 +0100 Subject: [PATCH] reverts are now string-based --- rogueviz/ru/classes.cpp | 7 +++--- rogueviz/ru/globals.cpp | 11 +++++++-- rogueviz/ru/man.cpp | 4 ++-- rogueviz/ru/powers.cpp | 16 ++++++-------- rogueviz/ru/reverts.cpp | 49 +++++++++++++++++++++++++++++++++++++++++ rogueviz/ru/ru.cpp | 1 + rogueviz/ru/save.cpp | 10 +++++++++ 7 files changed, 81 insertions(+), 17 deletions(-) create mode 100644 rogueviz/ru/reverts.cpp diff --git a/rogueviz/ru/classes.cpp b/rogueviz/ru/classes.cpp index f12b4e5a..de144957 100644 --- a/rogueviz/ru/classes.cpp +++ b/rogueviz/ru/classes.cpp @@ -151,7 +151,7 @@ struct room { void replace_block_frev(int x, int y, eWall w) { auto orig = at(x, y); replace_block(x, y, w); - add_revert(fountain_revert, [this, x, y, orig] { replace_block(x, y, orig); }); + add_revert(fountain_revert, {"BLOCK", roomname, its(x), its(y), its(orig)}); } void replace_block_frev(intxy xy, eWall w) { replace_block_frev(xy.x, xy.y, w); } @@ -688,9 +688,8 @@ struct item : public entity { kino(); if(intersect(get_pixel_bbox(), m.get_pixel_bbox())) { addMessage(pickup_message); - int q0 = powers[id].qty_filled; - int q1 = powers[id].qty_owned; - add_revert(death_revert, [this, q0, q1] { existing = true; powers[id].qty_filled = q0; powers[id].qty_owned = q1; }); + add_revert(death_revert, {"ITEM", powers[id].name, its(powers[id].qty_filled), its(powers[id].qty_owned)}); + add_revert(death_revert, {"EXIST", name}); powers[id].picked_up(qty); existing = false; } diff --git a/rogueviz/ru/globals.cpp b/rogueviz/ru/globals.cpp index 8cb34f2c..950aaf28 100644 --- a/rogueviz/ru/globals.cpp +++ b/rogueviz/ru/globals.cpp @@ -162,11 +162,15 @@ void render_the_map(); void shuffle_all(); void assign_potion_powers(); -using revert_stack = vector; +using revert_type = vector; + +using revert_stack = vector; revert_stack death_revert, fountain_revert; -void add_revert(revert_stack& s, const reaction_t& what); +void add_revert(revert_stack& s, const revert_type& what); + +void revert(const revert_type& r); void revert_all(revert_stack& s); @@ -177,4 +181,7 @@ struct power& find_power(string name); tuple get_next_room(struct xy w, room *r, int which = -1); extern shiftmatrix scrm; + +struct hr_name_error : hr_exception { hr_name_error(const char *s) : hr_exception(s) {} }; + } diff --git a/rogueviz/ru/man.cpp b/rogueviz/ru/man.cpp index afdf8054..8361421e 100644 --- a/rogueviz/ru/man.cpp +++ b/rogueviz/ru/man.cpp @@ -116,12 +116,12 @@ void man::on_kill() { addMessage("You die... permanently. You will have to create a new character. Or just press [key:Extra Life] for a narrative cheat."); } -void add_revert(revert_stack& s, const reaction_t& what) { +void add_revert(revert_stack& s, const revert_type& what) { s.push_back(what); } void revert_all(revert_stack& s) { - while(!s.empty()) { s.back()(); s.pop_back(); } + while(!s.empty()) { revert(s.back()); s.pop_back(); } } void man::launch_attack(power *p, int fac, boxfun f) { diff --git a/rogueviz/ru/powers.cpp b/rogueviz/ru/powers.cpp index 55aa7a77..0e1f2648 100644 --- a/rogueviz/ru/powers.cpp +++ b/rogueviz/ru/powers.cpp @@ -215,9 +215,7 @@ int gold_id; power *dexmode; void power_death_revert(power& p) { - int q0 = p.qty_filled; - int q1 = p.qty_owned; - add_revert(death_revert, [&p, q0, q1] { p.qty_filled = q0; p.qty_owned = q1; }); + add_revert(death_revert, {"ITEM", p.name, its(p.qty_filled), its(p.qty_owned)}); } void gen_powers() { @@ -515,7 +513,7 @@ void gen_powers() { addMessage(si->pickup_message); power_death_revert(powers[si->id]); powers[si->id].qty_owned += si->qty; powers[si->id].qty_filled += si->qty1; - add_revert(death_revert, [si] { si->existing = true; }); + add_revert(death_revert, {"EXIST", si->name}); si->existing = false; } else if(it == 0 && on && si->existing && si->bought) { @@ -523,7 +521,7 @@ void gen_powers() { addMessage("You get some gold."); power_death_revert(powers[gold_id]); powers[gold_id].qty_owned += si->price; powers[gold_id].qty_filled += si->price; - add_revert(death_revert, [si] { si->existing = true; }); + add_revert(death_revert, {"EXIST", si->name}); si->existing = false; } else if((it ? !done_something : on) && !si->existing && !si->bought) { @@ -531,7 +529,7 @@ void gen_powers() { addMessage("You rethink your purchase."); power_death_revert(powers[si->id]); powers[si->id].qty_owned -= si->qty; powers[si->id].qty_filled -= si->qty1; - add_revert(death_revert, [si] { si->existing = false; }); + add_revert(death_revert, {"UNEXIST", si->name}); si->existing = true; } else if((it ? !done_something : on) && !si->existing && si->bought) { @@ -539,7 +537,7 @@ void gen_powers() { addMessage("You rethink your actions."); power_death_revert(powers[gold_id]); powers[gold_id].qty_owned -= si->price; powers[gold_id].qty_filled -= si->price; - add_revert(death_revert, [si] { si->existing = false; }); + add_revert(death_revert, {"UNEXIST", si->name}); si->existing = true; } else if(it == 0 && on_trader && !si->existing && d.p->qty_owned >= si->price) { @@ -548,7 +546,7 @@ void gen_powers() { power_death_revert(powers[gold_id]); powers[gold_id].qty_owned -= si->price; powers[gold_id].qty_filled -= si->price; si->existing = true; si->bought = true; - add_revert(death_revert, [si] { si->existing = false; si->bought = false; }); + add_revert(death_revert, {"UNBOUGHT", si->name}); } else if(it == 0 && on_trader && !si->existing && !si->bought) { done_something = true; @@ -627,7 +625,7 @@ void shuffle_all() { power& find_power(string name) { for(auto& p: powers) if(p.name == name) return p; - throw hr_exception("unknown power"); + throw hr_name_error("unknown power"); } } diff --git a/rogueviz/ru/reverts.cpp b/rogueviz/ru/reverts.cpp new file mode 100644 index 00000000..2c98c8c7 --- /dev/null +++ b/rogueviz/ru/reverts.cpp @@ -0,0 +1,49 @@ +namespace rogue_unlike { + +room fake_room; + +room *find_room(string s) { + for(auto& [c,r]: rooms) if(r.roomname == s) return &r; + throw hr_name_error("find_room"); + } + +entity* find_entity(string s) { + auto e = entity_by_name[s]; + if(!e) throw hr_name_error("find_entity"); + return e; + } + +template T force_exist(const T& c) { if(!c) throw hr_name_error("check"); return c; } + +void revert(const revert_type& r) { + // auto rf = [] (string s) { return atof(s.c_str()); }; + auto ri = [] (string s) { return atoi(s.c_str()); }; + + try { + + if(r[0] == "BLOCK") find_room(r[1])->replace_block(ri(r[2]), ri(r[3]), (eWall) ri(r[4])); + else if(r[0] == "ITEM") { + auto& p = find_power(r[1]); + p.qty_filled = ri(r[2]); + p.qty_owned = ri(r[3]); + } + else if(r[0] == "EXIST") { + auto e = find_entity(r[1]); + if(e) e->existing = true; + } + else if(r[0] == "UNEXIST") { + auto e = find_entity(r[1]); + if(e) e->existing = false; + } + else if(r[0] == "UNBOUGHT") { + auto e = find_entity(r[1]); + if(e) e->existing = false; + force_exist(e->as_shopitem())->bought = false; + } + + } catch(hr_name_error& e) { + println(hlog, "a name error occured while reverting: ", e.what()); + } + } + +} diff --git a/rogueviz/ru/ru.cpp b/rogueviz/ru/ru.cpp index b5edde76..7a709ed3 100644 --- a/rogueviz/ru/ru.cpp +++ b/rogueviz/ru/ru.cpp @@ -35,6 +35,7 @@ Have fun! #include "save.cpp" #include "stats.cpp" #include "randeff.cpp" +#include "reverts.cpp" namespace rogue_unlike { diff --git a/rogueviz/ru/save.cpp b/rogueviz/ru/save.cpp index 147cbc9b..25e24e82 100644 --- a/rogueviz/ru/save.cpp +++ b/rogueviz/ru/save.cpp @@ -313,6 +313,8 @@ void load_room(fhstream& f, cell *c) { } } +map entity_by_name; + void load_map(string fname) { fhstream f(fname, "r"); load_room(f, currentmap->gamestart()); @@ -326,6 +328,14 @@ void load_map(string fname) { } else err("load_map", s); } + for(auto& [c,r]: rooms) + for(auto& e: r.entities) if(e->name != "") { + while(entity_by_name.count(e->name)) { + println(hlog, "error: double entity name: ", e->name); + e->name += "'"; + } + entity_by_name[e->name] = &*e; + } } void load_cheat(string fname) {