From c1de923454c44ae95e120d9eb1ff14861ff57f88 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Fri, 21 Sep 2018 19:51:13 +0200 Subject: [PATCH] extra features related to expansion --- expansion.cpp | 250 +++++++++++++++++++++++++++++++++++++------------- geom-exp.cpp | 3 +- graph.cpp | 27 +----- hyper.h | 14 ++- pattern2.cpp | 35 +++++-- 5 files changed, 226 insertions(+), 103 deletions(-) diff --git a/expansion.cpp b/expansion.cpp index b54635d7..45b59099 100644 --- a/expansion.cpp +++ b/expansion.cpp @@ -327,8 +327,6 @@ template int type_in(expansion_analyzer& ea, cell *c, const T& f) { return ret; } -bool show_ea_types; - template int type_in_quick(expansion_analyzer& ea, cell *c, const T& f) { vector res; res.push_back(subtype(c) * 4 + 2); @@ -368,9 +366,35 @@ string expansion_analyzer::approximate_descendants(int d, int max_length) { return XLAT("about ") + fts(pow(10, log_10 - more_digits)) + "E" + its(more_digits); } -int expansion_method=4, nopage; +enum eDistanceFrom { dfPlayer, dfStart, dfWorld }; +string dfnames[3] = { "player", "start", "land" }; -string expansion_methods[5] = { "celllister", "celllister/verify", "celldistance", "expansion_analyzer", "automatic" }; +eDistanceFrom distance_from = dfPlayer; + +enum eNumberCoding { ncNone, ncDistance, ncType, ncDebug }; +string ncnames[4] = { "NO", "distance", "type", "debug" }; +eNumberCoding number_coding = ncDistance; + +bool mod_allowed() { + return cheater || autocheat || archimedean || tour::on; + } + +int curr_dist(cell *c) { + switch(distance_from) { + case dfPlayer: + return c->cpdist < INFD ? c->cpdist : celldistance(cwt.at, c); + case dfStart: + return celldist(c); + case dfWorld: + if(!mod_allowed() && !among(c->land, laOcean, laIvoryTower, laEndorian, laDungeon, laTemple, laWhirlpool)) + return 0; + if(c->master->alt) return celldistAlt(c); + return inmirror(c) ? (c->landparam & 255) : c->landparam; + } + return 0; + } + +int position; template int type_in_reduced(expansion_analyzer& ea, cell *c, const T& f) { int a = ea.N; @@ -382,75 +406,167 @@ template int type_in_reduced(expansion_analyzer& ea, cell *c, const T& return t; } +bool viewdists = false, use_color_codes = true, use_analyzer = true; + +int first_distance = 0, scrolltime = 0; +bool scrolling_distances = false; + +color_t distribute_color(int id) { + color_t v = 0xFFFFFF; + for(int z=0; z<24; z++) if(id & (1<= 0) label = its(t), dc = distribute_color(t); + break; + } + case ncDebug: { + int d = celldistance(c, distance_from == dfPlayer ? cwt.at : currentmap->gamestart()); + dc = (d != cd) ? 0xFF0000 : 0x00FF00; + label = its(d); + } + case ncNone: ; + } + + // string label = its(fieldpattern::getriverdistleft(c)) + its(fieldpattern::getriverdistright(c)); + /* queuepolyat(V, shFloor[ct6], darkena(gradient(0, distcolors[cd&7], 0, .25, 1), fd, 0xC0), + PPR::TEXT); */ + if(label != "") + queuestr(V, (isize(label) > 1 ? .6 : 1), label, 0xFF000000 + dc, 1); + } + +void viewdist_configure_dialog() { + dialog::init(""); + cmode |= sm::SIDE | sm::MAYDARK | sm::EXPANSION; + gamescreen(0); + + dialog::addSelItem("which distance", dfnames[distance_from], 'c'); + dialog::add_action([] () { distance_from = mod_allowed() ? eDistanceFrom(2 - distance_from) : eDistanceFrom((distance_from + 1) % 3); }); + + dialog::addSelItem("number codes", ncnames[number_coding], 'n'); + dialog::add_action([] () { number_coding = eNumberCoding((number_coding + 1) % (mod_allowed() ? 4 : 2)); }); + + dialog::addBoolItem("color codes", use_color_codes, 'u'); + dialog::add_action([] () { use_color_codes = !use_color_codes; }); + + dialog::addBoolItem("use analyzer", use_analyzer, 'a'); + dialog::add_action([] () { use_analyzer = !use_analyzer; }); + + dialog::addSelItem("display distances from", its(first_distance), 'd'); + dialog::add_action([] () { + scrolling_distances = false; + dialog::editNumber(first_distance, 0, 3000, 0, 1, "display distances from", ""); + }); + + auto& cp = linepatterns::patterns; + using namespace linepatterns; + for(int numpat=0; cp[numpat].lpname; numpat++) { + auto &pn = cp[numpat]; + if(among(pn.id, patTriTree, patTriRings, patTriOther)) { + dialog::addColorItem(XLAT(pn.lpname), pn.color, '1'+numpat); + dialog::add_action([&pn] () { + dialog::openColorDialog(pn.color, NULL); + dialog::dialogflags |= sm::MAYDARK | sm::SIDE | sm::EXPANSION; + }); + } + } + + if(!mod_allowed()) + dialog::addInfo(XLAT("note: enable the cheat mode for additional options")); + else + dialog::addBreak(100); + + if(distance_from) + dialog::addInfo("numbers show the descendants of current player position"); + else + dialog::addBreak(100); + + dialog::addBack(); + dialog::display(); + } + +bool is_descendant(cell *c) { + if(c == cwt.at) return true; + if(curr_dist(c) < curr_dist(cwt.at)) return false; + return is_descendant(chosenDown(c, -1, 0, curr_dist)); + } + +const int scrollspeed = 100; + void expansion_analyzer::view_distances_dialog() { + static int lastticks; + if(scrolling_distances && !bounded) { + scrolltime += SDL_GetTicks() - lastticks; + first_distance += scrolltime / scrollspeed; + scrolltime %= scrollspeed; + } + lastticks = SDL_GetTicks(); + distcolors[0] = forecolor; dialog::init(""); cmode |= sm::DIALOG_STRICT_X | sm::EXPANSION; - int maxlen = bounded ? 128 : 16 + 8 * nopage; + int maxlen = bounded ? 128 : 16 + first_distance; vector qty(maxlen); - int aem = expansion_method; - if(aem == 4) aem = (bounded || !sizes_known()) ? 0 : 3; - int errors = 0; + bool really_use_analyzer = use_analyzer && sizes_known(); - // method 0: celllister - switch(aem) { - case 0: { + if(really_use_analyzer) { + int t = type_in_reduced(expansion, cwt.at, curr_dist); + for(int r=0; r= 0 && d < maxlen) qty[d]++; - break; } - case 1: { - celllister cl(cwt.at, gamerange(), 100000, NULL); - for(int i=0; i= 0 && d < maxlen) qty[d]++; - if(expansion_method == 1 && celldistance(cwt.at, cl.lst[d]) != d) - errors++; + else { + celllister cl(cwt.at, bounded ? maxlen-1 : gamerange(), 100000, NULL); + for(cell *c: cl.lst) if(is_descendant(c)) qty[curr_dist(c)]++; + } + if(sizes_known()) { + find_coefficients(); + if(gamerange()+1 >= valid_from && coefficients_known == 2) { + for(int i=gamerange()+1; i= 0 && d < maxlen) qty[d]++; - } - break; - } - case 3: { - int t = type_in_reduced(expansion, cwt.at, [] (cell *c) { return celldistance(cwt.at, c); }); - for(int r=0; r= valid_from && coefficients_known == 2) { - for(int i=gamerange()+1; i 0) nopage--; - else if(uni == 'S') show_ea_types = !show_ea_types; + if((cmode & sm::EXPANSION) && (cmode & sm::NORMAL)) { + if(uni == 'S') scrolling_distances = !scrolling_distances; + else if(uni == 'C') pushScreen(viewdist_configure_dialog); + else if(sym == SDLK_ESCAPE) first_distance = 0, viewdists = false; else return false; return true; } diff --git a/geom-exp.cpp b/geom-exp.cpp index 80474a4b..9a1133cd 100644 --- a/geom-exp.cpp +++ b/geom-exp.cpp @@ -452,7 +452,8 @@ void showEuclideanMenu() { gp::configure(); } else if(uni == '2' || sym == SDLK_F1) gotoHelp(euchelp); - else if(uni == '3') { viewdists = !viewdists; if(viewdists) popScreenAll(); } + else if(uni == '3' && !viewdists) { enable_viewdists(); popScreenAll(); } + else if(uni == '3' && viewdists) { viewdists = false; } else if(uni == '1' && !euclid) { if(sphere) { if(vid.alpha < 10) { vid.alpha = 999; vid.scale = 998; } diff --git a/graph.cpp b/graph.cpp index 775fd475..d0712cbb 100644 --- a/graph.cpp +++ b/graph.cpp @@ -3343,8 +3343,6 @@ int shallow(cell *c) { return 7; } -bool viewdists = false; - bool allemptynear(cell *c) { if(c->wall) return false; forCellEx(c2, c) if(c2->wall) return false; @@ -3663,30 +3661,9 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { string label = its(c->landparam); queuestr(V, 1 * .2, label, 0xFFFFFFFF, 1); } - - if(viewdists && !behindsphere(V)) { - int cd = - among(expansion_method, 1, 2) ? celldistance(c, cwt.at) : - (cwt.at == currentmap->gamestart() && numplayers() == 1 && !binarytiling) ? celldist(c) : - (c->cpdist < INFD) ? c->cpdist : - celldistance(c, cwt.at); - string label = its(cd); - - if(c->cpdist < INFD && show_ea_types) { - int t = type_in_quick(expansion, c, [] (cell *c) { return c->cpdist; }); - if(t >= 0) - label = label + ":" + its(t); - } + + if(viewdists) do_viewdist(c, V, wcol, fcol); - // string label = its(fieldpattern::getriverdistleft(c)) + its(fieldpattern::getriverdistright(c)); - int dc = distcolors[cd&7]; - wcol = gradient(wcol, dc, 0, .4, 1); - fcol = gradient(fcol, dc, 0, .4, 1); - /* queuepolyat(V, shFloor[ct6], darkena(gradient(0, distcolors[cd&7], 0, .25, 1), fd, 0xC0), - PPR::TEXT); */ - queuestr(V, (cd > 9 ? .6 : 1) * .2, label, 0xFF000000 + distcolors[cd&7], 1); - } - if(cmode & sm::TORUSCONFIG) { using namespace torusconfig; string label; diff --git a/hyper.h b/hyper.h index 7a586851..65a9e68a 100644 --- a/hyper.h +++ b/hyper.h @@ -2170,7 +2170,7 @@ namespace linepatterns { patPalace, patZebraTriangles, patZebraLines, - patTriNet, + patTriTree, patTriRings, patHepta, patRhomb, @@ -2182,7 +2182,9 @@ namespace linepatterns { patTrihepta, patBigTriangles, patBigRings, - patHorocycles + patHorocycles, + patTriOther, + patDual }; void clearAll(); @@ -2190,6 +2192,14 @@ namespace linepatterns { void drawAll(); void showMenu(); void switchAlpha(ePattern id, color_t col); + + struct linepattern { + int id; + const char *lpname; + color_t color; + }; + + extern linepattern patterns[]; }; transmatrix ddspin(cell *c, int d, ld bonus = 0); diff --git a/pattern2.cpp b/pattern2.cpp index d9d3c616..8fc2b67e 100644 --- a/pattern2.cpp +++ b/pattern2.cpp @@ -1952,14 +1952,10 @@ namespace linepatterns { return col; } - struct { - int id; - const char *lpname; - color_t color; - } patterns[] = { + linepattern patterns[] = { + + {patDual, "dual grid", 0xFFFFFF00}, - {patTriNet, "triangle grid: not rings", 0xFFFFFF00}, - {patTriRings, "triangle grid: rings", 0xFFFFFF00}, {patHepta, "heptagonal grid", 0x0000C000}, {patRhomb, "rhombic tesselation", 0x0000C000}, {patTrihepta, "triheptagonal tesselation", 0x0000C000}, @@ -1977,6 +1973,11 @@ namespace linepatterns { {patPalace, "firewall lines: Palace", 0xFFD50000}, {patPower, "firewall lines: Power", 0xFFFF0000}, {patHorocycles, "horocycles", 0xd060d000}, + + {patTriRings, "triangle grid: rings", 0xFFFFFF00}, + {patTriTree, "triangle grid: tree edges", 0xFFFFFF00}, + {patTriOther, "triangle grid: other edges", 0xFFFFFF00}, + {0, NULL, 0} }; @@ -2066,8 +2067,8 @@ namespace linepatterns { col, 1 + vid.linequality); break; - case patTriNet: - forCellEx(c2, c) if(c2 > c) if(gmatrix.count(c2)) if(celldist(c) != celldist(c2)) { + case patDual: + forCellEx(c2, c) if(c2 > c) if(gmatrix.count(c2)) { queuelinef(tC0(V), gmatrix[c2]*C0, col, 2 + vid.linequality); } break; @@ -2075,11 +2076,25 @@ namespace linepatterns { case patTriRings: forCellIdEx(c2, i, c) { if(S3 == 4) c2 = (cellwalker(c, i) + wstep + 1).cpeek(); - if(c2 > c) if(gmatrix.count(c2) && celldist(c) == celldist(c2)) + if(c2 > c) if(gmatrix.count(c2) && curr_dist(c) == curr_dist(c2)) queuelinef(tC0(V), gmatrix[c2]*C0, col, 2 + vid.linequality); } break; + case patTriTree: { + cell *parent = chosenDown(c, -1, 0, curr_dist); + if(gmatrix.count(parent)) + queuelinef(tC0(V), gmatrix[parent]*C0, col, 2 + vid.linequality); + break; + } + + case patTriOther: { + cell *parent = chosenDown(c, -1, 0, curr_dist); + forCellEx(c2, c) if(gmatrix.count(c2) && curr_dist(c2) < curr_dist(c) && c2 != parent) + queuelinef(tC0(V), gmatrix[c2]*C0, col, 2 + vid.linequality); + break; + } + case patHepta: forCellEx(c2, c) if(c2 > c) if(gmatrix.count(c2) && pseudohept(c) == pseudohept(c2)) queuelinef(tC0(V), gmatrix[c2]*C0, col, 2 + vid.linequality);