1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2026-01-02 02:19:02 +00:00

reverts are now string-based

This commit is contained in:
Zeno Rogue
2025-12-05 22:03:44 +01:00
parent c09c87b851
commit 7a57ea0a1d
7 changed files with 81 additions and 17 deletions

View File

@@ -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;
}

View File

@@ -162,11 +162,15 @@ void render_the_map();
void shuffle_all();
void assign_potion_powers();
using revert_stack = vector<reaction_t>;
using revert_type = vector<string>;
using revert_stack = vector<revert_type>;
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<struct xy, ld, int> 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) {} };
}

View File

@@ -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) {

View File

@@ -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");
}
}

49
rogueviz/ru/reverts.cpp Normal file
View File

@@ -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<class T> 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());
}
}
}

View File

@@ -35,6 +35,7 @@ Have fun!
#include "save.cpp"
#include "stats.cpp"
#include "randeff.cpp"
#include "reverts.cpp"
namespace rogue_unlike {

View File

@@ -313,6 +313,8 @@ void load_room(fhstream& f, cell *c) {
}
}
map<string, entity*> 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) {