1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-02-03 04:39:17 +00:00

nilrider:: RLE encode manual replays, also do not save headings offsurface

This commit is contained in:
Zeno Rogue 2024-08-20 14:45:09 +02:00
parent f29104db50
commit 4fcc12fe91
3 changed files with 58 additions and 19 deletions

View File

@ -502,15 +502,8 @@ void replays() {
dialog::init(XLAT(planning_mode ? "saved plans" : "replays"), 0xC0C0FFFF, 150, 100); dialog::init(XLAT(planning_mode ? "saved plans" : "replays"), 0xC0C0FFFF, 150, 100);
if(!planning_mode) replays_of_type(curlev->manual_replays, [] (manual_replay& r) { if(!planning_mode) replays_of_type(curlev->manual_replays, [] (manual_replay& r) {
view_replay = false; view_replay = false;
curlev->history.clear();
auto& current = curlev->current;
current = curlev->start;
loaded_or_planned = true; loaded_or_planned = true;
for(auto h: r.headings) { curlev->history = curlev->headings_to_history(r);
current.heading_angle = int_to_heading(h);
curlev->history.push_back(current);
if(!current.tick(curlev)) break;
}
toggle_replay(); toggle_replay();
popScreen(); popScreen();
}); });
@ -556,12 +549,7 @@ void main_menu() {
#if CAP_SAVE #if CAP_SAVE
dialog::addItem("save the replay", 's'); dialog::addItem("save the replay", 's');
dialog::add_action([] { dialog::add_action(save_manual_replay);
vector<int> ang;
for(auto& h: curlev->history) ang.push_back(heading_to_int(h.heading_angle));
curlev->manual_replays.emplace_back(manual_replay{new_replay_name(), my_scheme, std::move(ang)});
save();
});
dialog::addItem("saved replays", 'l'); dialog::addItem("saved replays", 'l');
dialog::add_action(pop_and_push_replays); dialog::add_action(pop_and_push_replays);

View File

@ -91,7 +91,7 @@ struct triangledata {
struct manual_replay { struct manual_replay {
string name; string name;
colorscheme cs; colorscheme cs;
vector<int> headings; vector<pair<int, int>> headings;
}; };
struct plan_replay { struct plan_replay {
@ -245,7 +245,9 @@ struct level {
vector<level*> res; gen_layer_list(res); return res; vector<level*> res; gen_layer_list(res); return res;
} }
vector<timestamp> headings_to_history(manual_replay&);
void load_plan_as_ghost(plan_replay&); void load_plan_as_ghost(plan_replay&);
void load_manual_as_ghost(manual_replay&);
}; };
/** wheel radius */ /** wheel radius */

View File

@ -27,6 +27,7 @@ void save() {
} }
} }
println(f, "*COLORS\n"); println(f, "*COLORS\n");
println(f, "*RLE\n");
for(auto l: all_levels) { for(auto l: all_levels) {
for(auto& p: l->manual_replays) { for(auto& p: l->manual_replays) {
println(f, "*MANUAL"); println(f, "*MANUAL");
@ -34,7 +35,7 @@ void save() {
println(f, p.name); println(f, p.name);
fprintf(f.f, "%08x %08x %08x %08x\n", p.cs.wheel1, p.cs.wheel2, p.cs.seat, p.cs.seatpost); fprintf(f.f, "%08x %08x %08x %08x\n", p.cs.wheel1, p.cs.wheel2, p.cs.seat, p.cs.seatpost);
println(f, isize(p.headings)); println(f, isize(p.headings));
for(auto t: p.headings) println(f, t); for(auto t: p.headings) println(f, t.first, " ", t.second);
println(f); println(f);
} }
for(auto& p: l->plan_replays) { for(auto& p: l->plan_replays) {
@ -68,9 +69,22 @@ colorscheme load_colors(fhstream& f, bool have_colors) {
} }
} }
vector<pair<int, int>> apply_rle(const vector<int>& data) {
vector<pair<int, int>> rle;
if(data.empty()) return rle;
int last = data[0], count = 0;
for(int v: data) {
if(v != last) { rle.emplace_back(count, last); count = 0; last = v; }
count++;
}
rle.emplace_back(count, last);
return rle;
}
void load() { void load() {
#if CAP_SAVE #if CAP_SAVE
bool have_colors = false; bool have_colors = false;
bool have_rle = false;
println(hlog, "load called"); println(hlog, "load called");
fhstream f("nilrider.save", "rt"); fhstream f("nilrider.save", "rt");
if(!f.f) return; if(!f.f) return;
@ -78,15 +92,25 @@ void load() {
while(!feof(f.f)) { while(!feof(f.f)) {
string s = scanline_noblank(f); string s = scanline_noblank(f);
if(s == "") continue; if(s == "") continue;
if(s == "*COLORS") { have_colors = true; } if(s == "*COLORS") { have_colors = true; continue; }
if(s == "*RLE") { have_rle = true; continue; }
if(s == "*MANUAL") { if(s == "*MANUAL") {
string lev = scanline_noblank(f); string lev = scanline_noblank(f);
string name = scanline_noblank(f); string name = scanline_noblank(f);
colorscheme cs = load_colors(f, have_colors); colorscheme cs = load_colors(f, have_colors);
vector<int> headings; vector<pair<int, int>> headings;
int size = scan<int> (f); int size = scan<int> (f);
if(size < 0 || size > 1000000) throw hstream_exception(); if(size < 0 || size > 1000000) throw hstream_exception();
for(int i=0; i<size; i++) headings.push_back(scan<int>(f)); if(have_rle) {
println(hlog, "reading a RLE replay");
for(int i=0; i<size; i++) { int rep = scan<int>(f); headings.emplace_back(rep, scan<int>(f)); }
}
else {
vector<int> h;
for(int i=0; i<size; i++) h.emplace_back(scan<int>(f));
headings = apply_rle(h);
println(hlog, "converted ", isize(h), " to ", isize(headings));
}
auto l = level_by_name(lev); auto l = level_by_name(lev);
if(l) l->manual_replays.emplace_back(manual_replay{name, cs, std::move(headings)}); if(l) l->manual_replays.emplace_back(manual_replay{name, cs, std::move(headings)});
continue; continue;
@ -143,4 +167,29 @@ void level::load_plan_as_ghost(plan_replay& r) {
swap(r.plan, plan); swap(r.plan, plan);
} }
vector<timestamp> level::headings_to_history(manual_replay& r) {
vector<timestamp> history;
timestamp cur = start;
for(auto [qty, h]: r.headings) {
println(hlog, "pair: ", tie(qty, h));
for(int i=0; i<qty; i++) {
cur.heading_angle = int_to_heading(h);
history.push_back(cur);
if(!cur.tick(this)) return history;
}
}
return history;
}
void level::load_manual_as_ghost(manual_replay& r) {
ghosts.emplace_back(ghost{r.cs, headings_to_history(r) });
}
void save_manual_replay() {
vector<int> ang;
for(auto& h: curlev->history) ang.push_back(h.on_surface ? heading_to_int(h.heading_angle) : 0);
curlev->manual_replays.emplace_back(manual_replay{new_replay_name(), my_scheme, apply_rle(ang)});
save();
}
} }