1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-12-25 17:40:36 +00:00

Merge branch 'zenorogue:master' into main

This commit is contained in:
Charlotte Peppers 2022-02-01 09:23:13 -07:00 committed by GitHub
commit 0a9d671bd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 135 additions and 28 deletions

View File

@ -49,7 +49,7 @@ struct shape {
/** list of edge connections */
vector<connection_t> connections;
int size() const { return isize(vertices); }
void build_from_angles_edges();
void build_from_angles_edges(bool is_comb);
vector<pair<int, int> > sublines;
vector<pair<ld, ld>> stretch_shear;
int repeat_value;
@ -74,7 +74,17 @@ struct slider {
struct arbi_tiling {
int order;
bool have_line, have_ph, have_tree, is_star;
/* have_line and have_ph: line and ph flags have been marked for tiles */
bool have_line, have_ph;
/* is the tree structure given in the tes file */
bool have_tree;
/* use "star." if the tessellation includs star polygons */
bool is_star;
/* use "combinatorial." for combinatorial tessellations; vertex valences computed based on their angles. Currently only rulegen works for combinatorial tessellations */
bool is_combinatorial;
/* reserved for future flags */
bool res0, res1, res2, res3;
int yendor_backsteps;
vector<shape> shapes;
@ -187,7 +197,7 @@ void start_poly_debugger(hr_polygon_error& err) {
#endif
}
void shape::build_from_angles_edges() {
void shape::build_from_angles_edges(bool is_comb) {
transmatrix at = Id;
vertices.clear();
int n = isize(angles);
@ -202,6 +212,8 @@ void shape::build_from_angles_edges() {
at = at * xpush(edges[i]) * spin(angles[i]);
}
matrices.push_back(at);
if(!legacy) for(auto& a: angles) a -= M_PI;
if(is_comb) return;
if(!eqmatrix(at, Id)) {
throw hr_polygon_error(matrices, id, at);
}
@ -215,7 +227,6 @@ void shape::build_from_angles_edges() {
}
if(debugflags & DF_GEOM) println(hlog, "ctr = ", ctr);
}
if(!legacy) for(auto& a: angles) a -= M_PI;
ctr = normalize(ctr);
for(auto& v: vertices) v = gpushxto0(ctr) * v;
}
@ -247,7 +258,7 @@ EX void load_tile(exp_parser& ep, arbi_tiling& c, bool unit) {
else throw hr_parse_exception("expecting , or )");
}
try {
cc.build_from_angles_edges();
cc.build_from_angles_edges(c.is_combinatorial);
}
catch(hr_parse_exception& ex) {
throw hr_parse_exception(ex.s + ep.where());
@ -423,6 +434,7 @@ EX void load(const string& fname, bool after_sliding IS(false)) {
c.have_tree = false;
c.yendor_backsteps = 0;
c.is_star = false;
c.is_combinatorial = false;
exp_parser ep;
ep.s = s;
ld angleunit = 1, distunit = 1, angleofs = 0;
@ -490,6 +502,9 @@ EX void load(const string& fname, bool after_sliding IS(false)) {
else if(ep.eat("star.")) {
c.is_star = true;
}
else if(ep.eat("combinatorial.")) {
c.is_combinatorial = true;
}
else if(ep.eat("option(\"")) {
next:
string s = "";
@ -841,7 +856,7 @@ EX transmatrix get_adj(arbi_tiling& c, int t, int dl, int t1, int xdl) {
if(co.mirror) swap(vl, vr);
if(hdist(vl, Res*xvr) + hdist(vr, Res*xvl) > .1) {
if(hdist(vl, Res*xvr) + hdist(vr, Res*xvl) > .1 && !c.is_combinatorial) {
println(hlog, "s1 = ", kz(spintox(rm*vr)), " s2 = ", kz(rspintox(xrm*xvr)));
println(hlog, tie(t, dl), " = ", kz(Res));
println(hlog, hdist(vl, Res * xvr), " # ", hdist(vr, Res * xvl));

View File

@ -184,6 +184,43 @@ void move_to(twalker dw) {
move_to(cellwalker(m->clone(dw.at)->c7, dw.spin, dw.mirrored));
}
vector<twalker> old_givers;
void try_sprawling(tcell *c) {
twalker cw = c;
cw = get_parent_dir(cw);
ufind(cw);
auto aid = get_aid(cw);
auto a_ptr = &(analyzers[aid.first][aid.second]);
vector<twalker> sprawl = { cw };
vector<analyzer_state*> states = { nullptr };
while(true) {
auto& a = *a_ptr;
if(!a) {
println(hlog, "analyzer not allocated");
return;
}
states.push_back(a);
if(isize(sprawl) <= cw.at->type) {
a->id = 0, a->dir = isize(sprawl)-1;
}
if(a->id == MYSTERY) {
println(hlog, "reached codeid ", a->analyzer_id, " which is state ", a->dir);
return;
}
auto t = sprawl[a->id];
twalker tw = t + a->dir;
ufind(tw);
tw.cpeek();
ufind(tw);
int mc = move_code(tw + wstep);
sprawl.push_back(tw + wstep);
println(hlog, "codeid ", a->analyzer_id, ": going from ", tw, " in direction ", a->dir, " reaching ", sprawl.back(), " of movecode ", mc);
a_ptr = &(a->substates[mc]);
}
}
void debug_menu() {
cmode = sm::SIDE | sm::MAYDARK;
gamescreen(0);
@ -266,6 +303,33 @@ void debug_menu() {
dialog::addItem("irradiate x10", 'I');
dialog::add_action([] { for(int i=0; i<10; i++) irradiate(); });
dialog::addItem("record givers", 'g');
dialog::add_action([] {
old_givers.clear();
for(int i=0; i<isize(treestates); i++) old_givers.push_back(treestates[i].giver);
println(hlog, "old_givers = ", old_givers);
debuglist = old_givers;
});
dialog::addItem("compare givers", 'G');
dialog::add_action([] {
int Q = isize(old_givers);
debuglist = {};
for(int i=0; i<Q; i++)
for(int j=0; j<i; j++) {
auto c1 = get_treestate_id(old_givers[i]);
auto c2 = get_treestate_id(old_givers[j]);
if(c1.second == c2.second) {
println(hlog, "old state ", i, " at ", old_givers[i], " and old state ", j, " at ", old_givers[j], " have now code ", c1);
debuglist.push_back(old_givers[i]);
debuglist.push_back(old_givers[j]);
}
}
});
dialog::addItem("sprawl", 's');
dialog::add_action([m] { try_sprawling(m->counterpart[cwt.at->master]); });
dialog::addItem("name", 'n');
dialog::add_action([m] { println(hlog, "name = ", index_pointer(m->counterpart[cwt.at->master])); });
@ -287,9 +351,12 @@ void view_debug() {
auto label = (tc->dist == MYSTERY ? "?" : its(tc->dist));
if(show_codes) {
string code = (tc->code == MYSTERY ? "?" : its(tc->code));
if(show_dist) label = label + "/" + code;
else label = code;
int code = tc->code;
if(code != MYSTERY_LARGE) code = all_analyzers[code]->dir;
else code = MYSTERY;
string codestr = (code == MYSTERY ? "?" : its(code));
if(show_dist) label = label + "/" + codestr;
else label = codestr;
}
color_t col = label_color == 1 ? 0xFFFFFF + 0x512960 * tc->code : label_color;
@ -743,6 +810,16 @@ void setup_fork(int m, string fname) {
test_out = new fhstream(fname, "wt");
}
int max_dist() {
int result = -1;
tcell* c1 = first_tcell;
while(c1) {
if(c1->dist != MYSTERY && c1->dist > result) result = c1->dist;
c1 = c1->next;
}
return result;
}
void test_current(string tesname) {
disable_bigstuff = true;
@ -968,6 +1045,7 @@ void test_current(string tesname) {
case 'U': Out("vshapes;vverts;vedges;ushapes;uverts;uedges;xea;xeb;xec", count_uniform());
case 'L': Out("mirror_rules", arb::current.mirror_rules);
case 'B': Out("listshape;listvalence", format("%lld;%lld", get_shapelist(), get_valence_list()));
case 'F': Out("maxdist", max_dist());
case 'f': Out("file", tesname);
case 'l': Out("shortcut", longest_shortcut());
@ -986,7 +1064,7 @@ void test_current(string tesname) {
// for(auto& sh: shortcuts) println(hlog, sh.first, " : ", isize(sh.second), " shortcuts (CSV)");
/*if(status == "ACC")*/ print_rules();
if(status == "ACC" && !forked) print_rules();
if(status != "ACC") treestates = alt_treestates;
/* for(auto& a: analyzers)
println(hlog, "analyzer ", a.first, " size is ", isize(a.second.spread)); */
@ -1156,6 +1234,7 @@ void test_from_file(string list) {
if(forked && id > 1) exit(0);
if(forked && id == 1) stop_game();
}
while(children) { int pid; wait(&pid); children--; }
}
void rulecat(string list) {
@ -1404,6 +1483,10 @@ int testargs() {
}
}
else if(argis("-veb")) {
view_examine_branch = true;
}
else if(argis("-dseek")) {
shift();
int i = argi();

View File

@ -50,7 +50,7 @@ struct hpcshape {
#define SIDE_BSHA 12
#define SIDEPARS 13
/** GOLDBERG_BITS controls the size of tables for Goldberg: 2*(x+y) should be below (1<<GOLDBERG_BITS) */
/** GOLDBERG_BITS controls the size of tables for Goldberg. see gp::check_limits */
#ifndef GOLDBERG_BITS
#define GOLDBERG_BITS 5

View File

@ -1171,10 +1171,12 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
// 4 pi / 2pi = M_PI
if(pmodel == mdEquivolume)
if(md == mdEquivolume)
d = pow(volume_auto(d), 1/3.) * pow(M_PI / 2, 1/3.);
else if(pmodel == mdEquiarea && sphere)
else if(md == mdEquiarea && sphere) {
d = sqrt(2*(1 - cos(d))) * M_PI / 2;
//d = sin((d+90*degree)/2);
}
else if(pmodel == mdEquiarea && hyperbolic)
d = sqrt(2*(cosh(d) - 1)) / 1.5;

View File

@ -1551,7 +1551,7 @@ EX map<char, colortable> colortables = {
0xFFFF80, 0xC040C0, 0xFFD500, 0x000080,
0x404040, 0x606060, 0x808080
}},
{'a', {0x800000, 0x503000, 0x206000, 0x007010, 0x004040, 0x001070, 0x200060, 0x500030}},
{'a', {0x800000, 0x503000, 0x206000, 0x202020, 0x004040, 0x001070, 0x606060, 0x500030}},
{'e', {0x404040, 0x1800000, 0x1008000, 0x000080 }},
{'b', {0x404040, 0x1800000, 0x1008000, 0x000080 }},
{'z', {0x1C0C0C0, 0x1E0E0E0, 0x404040, 0x606060 }},

View File

@ -19,6 +19,8 @@ EX int max_examine_branch = 5040;
EX int max_bdata = 1000;
EX int max_getside = 10000;
EX int rulegen_timeout = 60;
EX int max_shortcut_length = 1200;
EX int first_restart_on = 512;
#if HDR
/** exception thrown by this algoritm in case of any problems */
@ -502,7 +504,7 @@ EX void shortcut_found(tcell *c, tcell *alt, vector<twalker> &walkers, vector<tw
if(debugflags & DF_GEOM)
println(hlog, "new shortcut found, pre = ", pre, " post = ", post, " pre reaches ", walkers[wpos], " post reaches ", walkers2.back(), " of type ", walkers[wpos].at->id, " sample = ", c);
if(isize(pre) > 500) {
if(isize(pre) > max_shortcut_length) {
debuglist = { c };
throw rulegen_failure("shortcut too long");
}
@ -1215,10 +1217,11 @@ int get_side(twalker what) {
bool gl = wl.at->dist <= wr.at->dist;
bool gr = wl.at->dist >= wr.at->dist;
if(gl) {
if(get_sidecache(wl) == 1) wl += wstep;
if(side && get_sidecache(wl) == 1) wl += wstep;
treewalk(wl, -1);
if(wl == to_what) { res = 1; }
if(lstack.back() == wl+wstep) {
if(!side) ;
else if(lstack.back() == wl+wstep) {
set_sidecache(lstack.back(), 1);
set_sidecache(wl, -1);
lstack.pop_back();
@ -1226,10 +1229,11 @@ int get_side(twalker what) {
else if(wl.at->parent_dir != wl.spin && (wl+wstep).at->parent_dir != (wl+wstep).spin) lstack.push_back(wl);
}
if(gr) {
if(get_sidecache(wr) == -1) wr += wstep;
if(side && get_sidecache(wr) == -1) wr += wstep;
treewalk(wr, +1);
if(wr == to_what) {res = -1; }
if(rstack.back() == wr+wstep) {
if(!side) ;
else if(rstack.back() == wr+wstep) {
set_sidecache(rstack.back(), -1);
set_sidecache(wr, +1);
rstack.pop_back();
@ -1243,7 +1247,7 @@ int get_side(twalker what) {
return res;
}
int move_code(twalker cs) {
EX int move_code(twalker cs) {
bool child = false;
if(cs.at->dist) {
auto csd = get_parent_dir(cs);
@ -1631,6 +1635,8 @@ void verified_treewalk(twalker& tw, int id, int dir) {
treewalk(tw, dir);
}
EX bool view_examine_branch = false;
bool examine_branch(int id, int left, int right) {
auto rg = treestates[id].giver;
@ -1672,7 +1678,7 @@ bool examine_branch(int id, int left, int right) {
auto rl = get_rule(wl, tsl);
auto rr = get_rule(wr, tsr);
if(0) if(debugflags & DF_GEOM)
if(view_examine_branch) if(debugflags & DF_GEOM)
println(hlog, "wl = ", wl, " -> ", wl+wstep, " R", rl, " wr = ", wr, " -> ", wr+wstep, " R", rr, " lstack = ", lstack, " rstack = ", rstack);
if(rl == DIR_RIGHT && rr == DIR_LEFT && lstack.empty() && rstack.empty()) {
@ -1680,7 +1686,7 @@ bool examine_branch(int id, int left, int right) {
push_deadstack(hash, wl, tsl, -1);
hash.emplace_back(-1, wl.at->dist - wr.at->dist);
push_deadstack(hash, wr, tsr, +1);
if(0) if(debugflags & DF_GEOM)
if(view_examine_branch) if(debugflags & DF_GEOM)
println(hlog, "got hash: ", hash);
if(verified_branches.count(hash)) {
return true;
@ -1866,8 +1872,6 @@ EX void rules_iteration() {
println(hlog, "deadend states found: ", new_deadends);
}
// print_rules();
handle_distance_errors();
verified_branches.clear();
@ -2020,9 +2024,9 @@ EX void generate_rules() {
treestates.clear();
hard_parents = single_live_branches = double_live_branches = all_solid_errors = solid_errors = 0;
next_distance_warning = 512;
current_getside = 512;
current_examine_branch = 512;
next_distance_warning = first_restart_on;
current_getside = first_restart_on;
current_examine_branch = first_restart_on;
int NS = isize(arb::current.shapes);
shortcuts.resize(NS);
@ -2033,6 +2037,7 @@ EX void generate_rules() {
cell_to_tcell.clear();
tcell_to_cell.clear();
branch_conflicts_seen.clear();
sidecaches_to_clear.clear();
clear_sidecache_and_codes();
fix_queue = queue<reaction_t>();; in_fixing = false;
@ -2374,7 +2379,9 @@ auto hooks = addHook(hooks_configfile, 100, [] {
param_i(max_examine_branch, "max_examine_branch");
param_i(max_getside, "max_getside");
param_i(max_bdata, "max_bdata");
param_i(max_shortcut_length, "max_shortcut_length");
param_i(rulegen_timeout, "rulegen_timeout");
param_i(first_restart_on, "first_restart_on");
});
EX void parse_treestate(arb::arbi_tiling& c, exp_parser& ep) {

View File

@ -2998,7 +2998,7 @@ bool celldrawer::draw_shmup_monster() {
bool ths = subscreens::is_current_player(m->pid);
if(!ths || !h) {
drawPlayerEffects(view, c, true);
drawPlayerEffects(view, c, m->type);
if(WDIM == 3) {
if(prod) {
hyperpoint h = m->ori * C0; // ztangent(1)