diff --git a/rogueviz/banachtarski.cpp b/rogueviz/banachtarski.cpp index e399166a..bd32531d 100644 --- a/rogueviz/banachtarski.cpp +++ b/rogueviz/banachtarski.cpp @@ -477,6 +477,32 @@ void init_bantar_map() { } } +// see: https://twitter.com/ZenoRogue/status/1001127253747658752 +// see also: https://twitter.com/ZenoRogue/status/1000043540985057280 (older version) + +void bantar_record() { + int TSIZE = rug::texturesize; // recommended 2048 + resetbuffer rb; + renderbuffer rbuf(TSIZE, TSIZE, true); + + int fr = 0; + + for(int i=0; i < 10000; i += 33) { + if(i % 1000 == 999) i++; + ticks = i; + + rbuf.enable(); + vid.xres = vid.yres = TSIZE; + banachtarski::bantar_frame(); + + IMAGESAVE(rbuf.render(), ("bantar/" + format("%05d", fr) + IMAGEEXT).c_str()); + printf("GL %5d/%5d\n", i, 10000); + fr++; + } + + rb.reset(); + } + int readArgs() { using namespace arg; @@ -512,6 +538,15 @@ int readArgs() { else if(argis("-btry")) { shift(); notry = argi(); } + else if(argis("-bantar_record")) { + using namespace banachtarski; + PHASE(3); + peace::on = true; + airmap.clear(); + ForInfos if(cci.second.c->monst == moAirElemental) + cci.second.c->monst = moFireElemental; + bantar_record(); + } else return 1; return 0; } diff --git a/rogueviz/grigorchuk.cpp b/rogueviz/grigorchuk.cpp index 5e29504e..ad647ef9 100644 --- a/rogueviz/grigorchuk.cpp +++ b/rogueviz/grigorchuk.cpp @@ -429,7 +429,7 @@ void create_grigorchuk_geometry() { gi.shortname = "Grig"; } -int args() { +int readArgsG() { using namespace arg; if(0) ; @@ -459,7 +459,7 @@ int args() { return 0; } -auto hook = addHook(hooks_args, 100, args) +auto hook = addHook(hooks_args, 100, readArgsG) + addHook(hooks_newmap, 100, [] { return geometry == gGrigorchuk ? new hrmap_grigorchuk : nullptr; }) + addHook(patterns::hooks_generate_canvas, 100, [] (cell* c) { if(patterns::whichCanvas == 'G' && geometry == gGrigorchuk) diff --git a/rogueviz/kohonen.cpp b/rogueviz/kohonen.cpp index 24a7b11e..0a891a8d 100644 --- a/rogueviz/kohonen.cpp +++ b/rogueviz/kohonen.cpp @@ -1197,7 +1197,14 @@ void steps() { } } +void shift_color(int i) { + whattodraw[i]++; + if(whattodraw[i] == columns) whattodraw[i] = -5; + coloring(); + } + void showMenu() { + if(kind != kKohonen) return; string parts[3] = {"red", "green", "blue"}; for(int i=0; i<3; i++) { string c; @@ -1209,28 +1216,15 @@ void showMenu() { else if(whattodraw[i] == -6) c = "sample names to colors"; else c = colnames[whattodraw[i]]; dialog::addSelItem(XLAT("coloring (%1)", parts[i]), c, '1'+i); + dialog::add_action([i] { shift_color(i); }); } dialog::addItem("coloring (all)", '0'); + dialog::add_action([] { + shift_color(0); shift_color(1); shift_color(2); + }); + dialog::addItem("level lines", '4'); - } - -bool handleMenu(int sym, int uni) { - if(uni >= '1' && uni <= '3') { - int i = uni - '1'; - whattodraw[i]++; - if(whattodraw[i] == columns) whattodraw[i] = -5; - coloring(); - return true; - } - if(uni == '0') { - for(char x: {'1','2','3'}) handleMenu(x, x); - return true; - } - if(uni == '4') { - pushScreen(levelline::show); - return true; - } - return false; + dialog::add_action_push(levelline::show); } void save_compressed(string name) { @@ -1530,8 +1524,17 @@ int readArgs() { auto hooks = addHook(hooks_args, 100, readArgs); #endif +bool turn(int delta) { + if(!on) return false; + if(kind == kKohonen) kohonen::steps(), timetowait = 0; + return false; + // shmup::pc[0]->rebase(); + } + auto hooks2 = addHook(hooks_frame, 50, levelline::draw) - + addHook(hooks_mouseover, 100, describe_cell); + + addHook(hooks_mouseover, 100, describe_cell) + + addHook(shmup::hooks_turn, 100, turn) + + addHook(rogueviz::hooks_rvmenu, 100, showMenu); void clear() { printf("clearing Kohonen...\n"); diff --git a/rogueviz/rogueviz.cpp b/rogueviz/rogueviz.cpp index c15a17d2..f9dffc0d 100644 --- a/rogueviz/rogueviz.cpp +++ b/rogueviz/rogueviz.cpp @@ -15,9 +15,6 @@ // https://bitbucket.org/HaiZhung/hyperbolic-embedder/overview // (it uses the same format) -// hyper -tol -- visualize the tree of life, -// based on a XML dump from https://tree.opentreeoflife.org/ - // hyper -tess -- visualize a horocyclic tesselation, #include "../hyper.h" @@ -322,78 +319,6 @@ namespace spiral { } } -namespace collatz { - - double s2, s3, p2, p3; - double cshift = -1; - - transmatrix T2, T3; - - edgetype *collatz1, *collatz2; - - void start() { - init(); kind = kCollatz; - collatz1 = add_edgetype("1"); - collatz2 = add_edgetype("2"); - vdata.resize(1); - vertexdata& vd = vdata[0]; - createViz(0, cwt.at, xpush(cshift)); - virtualRebase(vd.m); - vd.cp = dftcolor; - vd.data = 0; - addedge(0, 0, 1, false, collatz::collatz1); - vd.name = "1"; - storeall(); - - T2 = spin(collatz::s2) * xpush(collatz::p2); - T3 = spin(collatz::s3) * xpush(collatz::p3); - } - - void lookup(long long reached, int bits) { - while(reached < (1ll< seq; - while(reached>1) { - seq.push_back(llts(reached)); - if(reached&1) reached += (reached>>1)+1; - else reached >>= 1; - } - // seq.push_back("1"); - reverse(seq.begin(), seq.end()); - - int id = 0; - int next = 0; - - int steps = 0; - while(true) { - steps++; - if(std::isnan(View[0][0])) exit(1); - shmup::turn(100); - drawthemap(); - centerpc(100); optimizeview(); - fixmatrix(View); - bfs(); setdist(cwt.at, 7 - getDistLimit() - genrange_bonus, NULL); - vertexdata& vd = vdata[id]; - for(int e=0; ebase; - if(shmup::on) shmup::pc[0]->base = cwt.at; - if(next == isize(seq)) goto found; - } - } - } - - found: - printf("steps = %d\n", steps); - } - } - int readLabel(fhstream& f) { string s = scan(f); if(s == "") return -1; @@ -483,575 +408,8 @@ namespace anygraph { } -namespace tree { - - edgetype *tree_edge; - - struct treevertex { - int origid; - int parent; - int depth; - int spos, epos; - vector children; - }; - - vector tol; - - void child(int pid, int id) { - if(isize(tol) <= id) tol.resize(id+1); - - treevertex& v = tol[id]; - v.parent = pid; - tol.push_back(v); - if(pid >= 0) tol[pid].children.push_back(id); - } - - void readnode(FILE *f, int pid) { - string lab = ""; - while(true) { - int c = fgetc(f); - if(c == EOF) { fprintf(stderr, "Ended prematurely\n"); exit(1); } - if(c == ',') break; - if(c == ')') { int id = getnewid(lab); child(pid, id); return; } - lab += c; - } - int id = getnewid(lab); - child(pid, id); - while(true) { - int c = fgetc(f); -// printf("c=%c at %d/%d\n", c, pid, id); - if(c == EOF) { fprintf(stderr, "Ended prematurely\n"); exit(1); } - if(c == ' ' || c == 10 || c == 13 || c == 9 || c == ',') continue; - else if(c == '(') readnode(f, id); - else if(c == ')') break; - } - } - - int xpos; - void spos(int at, int d) { - tol[at].spos = xpos++; - tol[at].depth = d; - for(int i=0; ipid = i; - vd.data = lv.parent; - createViz(i, cwt.at, h); - vd.cp = dftcolor; - - if(tol[i].parent >= 0) - addedge(i, tol[i].parent, 1, true, tree_edge); - } - - for(int i=0; i snakecells; - vector snakefirst, snakelast; - vector snakenode; - vector snakeid; - vector lpbak; - vector wpbak; - - bool snake_enabled; - - void setsnake(cellwalker& cw, int i) { - lpbak[i] = cw.at->landparam; - wpbak[i] = cw.at->wparam; - cw.at->landparam = i; cw.at->wparam = INSNAKE; - // cw.at->monst = moWormtail; cw.at->mondir = cw.spin; - snakecells[i] = cw.at; - } - - void snakeswitch() { - for(int i=0; ilandparam; c->landparam = x; - x = wpbak[i]; wpbak[i] = c->wparam; c->wparam = x; - } - snake_enabled = !snake_enabled; - } - - void enable_snake() { if(!snake_enabled) snakeswitch(); } - - void disable_snake() { if(snake_enabled) snakeswitch(); } - - int snakedist(int i, int j) { - if(i < insnaketab && j < insnaketab) return sdist[i][j]; - if(bounded) return celldistance(snakecells[i], snakecells[j]); - int i0 = i, i1 = i, j0 = j, j1 = j; - int cost = 0; - // intersect - while(true) { - if(j0 > i1+1) { j0 = snakefirst[j0], j1 = snakelast[j1]; cost++; } - else if(i0 > j1+1) { i0 = snakefirst[i0], i1 = snakelast[i1]; cost++; } - else if(j1+1 == i0) return cost+1; - else if(i1+1 == j0) return cost+1; - else return cost; - } - } - - void initSnake(int n) { - if(bounded) n = isize(currentmap->allcells()); - numsnake = n; - snakecells.resize(numsnake); - snakefirst.resize(numsnake); - snakelast.resize(numsnake); - snakenode.resize(numsnake); - lpbak.resize(numsnake); - wpbak.resize(numsnake); - if(bounded) { - for(int i=0; iallcells()[i], 0); - setsnake(cw, i); - } - } - else { - cellwalker cw = cwt; - setsnake(cw, 0); - cw += wstep; - setsnake(cw, 1); - for(int i=2; i<=numsnake; i++) { - if(i == numsnake && sphere) break; - cw += wstep; - snakefirst[i-1] = cw.at->landparam; - while(cw.at->wparam == INSNAKE) { - snakelast[i-1] = cw.at->landparam; - cw = cw + wstep + 1 + wstep; - } - if(i == numsnake) break; - setsnake(cw, i); cw += 1; - } - } - int stab = min(numsnake, MAXSNAKETAB); - for(int i=0; iweight2; - } - /* cell *c = snakecells[id]; - for(int i=0; itype; i++) { - cell *c2 = c->move(i); - if(c2 && c2->wparam == INSNAKE && snakenode[c2->landparam] >= 0) - cost += 100; - } */ - return cost; - } - - // std::mt19937 los; - - bool infullsa; - - double cost; - int N; - - vector chgs; - - edgetype *sag_edge; - - void forgetedges(int id) { - for(int i=0; iorig = NULL; - } - - bool chance(double p) { - p *= double(hrngen.max()) + 1; - auto l = hrngen(); - auto pv = (decltype(l)) p; - if(l < pv) return true; - if(l == pv) return chance(p-pv); - return false; - } - - void saiter() { - aiter: - - int t1 = hrand(N); - int sid1 = snakeid[t1]; - - int sid2; - - int s = hrand(6); - - if(s == 3) s = 2; - if(s == 4) s = 5; - - if((sagpar&1) && (s == 2 || s == 3 || s == 4)) return; - - if(s == 5) sid2 = hrand(numsnake); - - else { - cell *c; - if(s>=2 && isize(vdata[t1].edges)) c = snakecells[snakeid[hrand(isize(vdata[t1].edges))]]; - else c = snakecells[sid1]; - - int it = s<2 ? (s+1) : s-2; - for(int ii=0; iitype); - c = c->move(d); - if(!c) goto aiter; - if(c->wparam != INSNAKE) goto aiter; - } - sid2 = c->landparam; - } - int t2 = snakenode[sid2]; - - snakenode[sid1] = -1; snakeid[t1] = -1; - snakenode[sid2] = -1; if(t2 >= 0) snakeid[t2] = -1; - - double change = - costat(t1,sid2) + costat(t2,sid1) - costat(t1,sid1) - costat(t2,sid2); - - snakenode[sid1] = t1; snakeid[t1] = sid1; - snakenode[sid2] = t2; if(t2 >= 0) snakeid[t2] = sid2; - - if(change < 0) chgs.push_back(-change); - - if(change > 0 && (sagmode == sagHC || !chance(exp(-change * exp(-temperature))))) return; - - snakenode[sid1] = t2; snakenode[sid2] = t1; - snakeid[t1] = sid2; if(t2 >= 0) snakeid[t2] = sid1; - if(vdata[t1].m) vdata[t1].m->base = snakecells[sid2]; - if(t2 >= 0 && vdata[t2].m) vdata[t2].m->base = snakecells[sid1]; - cost += 2*change; - - if(t1 >= 0) forgetedges(t1); - if(t2 >= 0) forgetedges(t2); - } - - void organize() { - for(int i=0; i freenodes; - for(int i=0; i= numsnake || err < 1) sid = -1; - if(!labeler.count(lab)) { - printf("unknown vertex: %s\n", lab.c_str()); - } - else { - int id = getid(lab); - snakeid[id] = sid; - } - } - afterload: - if(sf) fclose(sf); - - organize(); - for(int i=0; ibase = snakecells[sag::snakeid[i]]; - forgetedges(i); - } - - shmup::fixStorage(); - } - - vector sagedges; - - /* bool totcmp(int i, int j) { - return totwei[i] > totwei[j]; - } */ - - int ipturn = 100; - int numiter = 0; - - int hightemp = 10; - int lowtemp = -15; - - void dofullsa(int satime) { - sagmode = sagSA; - enable_snake(); - int t1 = SDL_GetTicks(); - - while(true) { - int t2 = SDL_GetTicks(); - double d = (t2-t1) / (1000. * satime); - if(d > 1) break; - temperature = hightemp - (d*(hightemp-lowtemp)); - chgs.clear(); - for(int i=0; i<50000; i++) { - numiter++; - sag::saiter(); - } - DEBB(DF_LOG, (format("it %8d temp %6.4f [1/e at %13.6f] cost = %f ", - numiter, double(sag::temperature), (double) exp(sag::temperature), - double(sag::cost)))); - - sort(chgs.begin(), chgs.end()); - int cc = chgs.size() - 1; - DEBB(DF_LOG, (format("%9.4f .. %9.4f .. %9.4f .. %9.4f .. %9.4f\n", - double(chgs[0]), double(chgs[cc/4]), double(chgs[cc/2]), double(chgs[cc*3/4]), double(chgs[cc])))); - fflush(stdout); - } - - temperature = -5; - disable_snake(); - sagmode = sagOff; - } - - void iterate() { - if(!sagmode) return; - int t1 = SDL_GetTicks(); - enable_snake(); - for(int i=0; i 200) ipturn /= 2; - else ipturn = ipturn * 100 / t; - DEBB(DF_LOG, ("it %8d temp %6.4f [2:%8.6f,10:%8.6f,50:%8.6f] cost = %f\n", - numiter, double(sag::temperature), - (double) exp(-2 * exp(-sag::temperature)), - (double) exp(-10 * exp(-sag::temperature)), - (double) exp(-50 * exp(-sag::temperature)), - (double) sag::cost)); - } - - void savesnake(const string& fname) { - FILE *f = fopen(fname.c_str(), "wt"); - for(int i=0; i= sag_edge->visible_from) - pedge[snakedist(snakeid[ei.i], snakeid[ei.j])]++; - } - - for(int d=0; d<30; d++) - if(indist[d]) - printf("%2d: %7d/%7d %7.3lf\n", - d, pedge[d], indist[d], double(pedge[d] * 100. / indist[d])); - - ld loglik = 0; - for(int d=0; d<30; d++) { - int p = pedge[d], pq = indist[d]; - int q = pq - p; - if(p && q) - loglik += p * log(p) + q * log(q) - pq * log(pq); - } - - println(hlog, "loglikelihood = ", fts(loglik)); - } - - void readsag(const char *fname) { - maxweight = 0; - sag_edge = add_edgetype("SAG edge"); - fhstream f(fname, "rt"); - if(!f.f) { printf("Failed to open SAG file: %s\n", fname); exit(1); } - // while(fgetc(f) != 10 && fgetc(f) != 13 && !feof(f)) ; - while(!feof(f.f)) { - string l1, l2; - while(true) { - int c = fgetc(f.f); - if(c == EOF) return; - else if(c == ';') break; - else if(c == 10 || c == 13 || c == 32 || c == 9) ; - else l1 += c; - } - while(true) { - int c = fgetc(f.f); - if(c == EOF) return; - else if(c == ';') break; - else if(c == 10 || c == 13 || c == 32 || c == 9) ; - else l2 += c; - } - ld wei; - if(!scan(f, wei)) continue; - edgeinfo ei(sag_edge); - ei.i = getid(l1); - ei.j = getid(l2); - ei.weight = wei; - sagedges.push_back(ei); - } - } - - ld edgepower=1, edgemul=1; - - void read(string fn) { - fname = fn; - init(); kind = kSAG; - temperature = 0; sagmode = sagOff; - readsag(fname.c_str()); - - N = isize(vdata); - // totwei.resize(N); - // for(int i=0; i= maxwei[ei.i] / 5 || ei.weight >= maxwei[ei.j] / 5); - - ei.weight2 = pow((double) ei.weight, (double) edgepower) * edgemul; - // LANG:: pow(ei.weight, .4) / 50; - - // ei.weight2 = 0; int w = ei.weight; while(w) { w >>= 1; ei.weight2++; } - /* if(totwei[ei.i] <= 0 || totwei[ei.j] <= 0) { - printf("BAD TOTWEI\n"); - exit(1); - } - ei.weight2 = 3 * ( - sqrt(ei.weight * 1. / totwei[ei.i]) * log(totwei[ei.i]) * log(totwei[ei.i]) + - sqrt(ei.weight * 1. / totwei[ei.j]) * log(totwei[ei.j]) * log(totwei[ei.j])); */ - // printf("%f\n", ei.weight2); - addedge0(ei.i, ei.j, &ei); - } - - initSnake(N*2); - printf("numsnake = %d\n", numsnake); - if(numsnake < N) { - printf("Error: snake does not fit\n"); - exit(1); - } - snakeid.resize(N); - for(int i=0; iweight > e2->weight; } @@ -1464,66 +822,8 @@ bool drawVertex(const transmatrix &V, cell *c, shmup::monster *m) { } } - if(kind == kCollatz) { - if(c->cpdist > 7 && euclid) ; - else if(vd.data == 2) { - // doubler vertex - string s = vd.name; - colorpair cp = vd.cp; - vd.data = 20; - int i0 = isize(vdata); - vdata.resize(i0+1); - vertexdata& vdn = vdata[i0]; - createViz(i0, m->base, m->at * collatz::T2); - - virtualRebase(vdn.m); - vdn.cp = perturb(cp); - vdn.data = 0; - addedge(i, i0, 1, false, collatz::collatz1); - vdn.m->store(); - int carry = 0; - string s2 = s; - for(int i=isize(s2)-1; i>=0; i--) { - int x = 2*(s2[i] - '0') + carry; - carry = x>=10; - if(carry) x-=10; - s2[i] = '0'+x; - } - if(carry) s2 = "1" + s2; - vdn.name = s2; - - int m3 = 0; - for(int i=0; ibase, m->at * collatz::T3); - virtualRebase(vdn.m); - vdn.cp = perturb(cp); - vdn.data = 0; - addedge(i, i0+1, 1, false, collatz::collatz2); - vdn.m->store(); - int carry = -1; - string s2 = s; - for(int i=isize(s2)-1; i>=0; i--) { - carry += 2 * (s2[i] - '0'); - int ncarry = 0; - while(carry % 3) carry += 10, ncarry--; - if(carry >= 30) carry -= 30, ncarry += 3; - s2[i] = '0'+carry/3; - carry = ncarry; - } - if(s2[0] == '0') s2 = s2.substr(1); - vdn.name = s2; - vdn.cp = perturb(vdn.cp); - } - } - else if(vd.data < 2) { - vd.data++; - fixmatrix(vd.m->at); - } - } + if(kind == kCollatz) + collatz::act(vd, c, m, i); return true; } @@ -1723,6 +1023,8 @@ void init() { int search_for = -1; +purehookset hooks_close; + void close() { search_for = -1; for(int i=0; irebase(); - } - #ifndef CAP_RVSLIDES #define CAP_RVSLIDES (CAP_TOUR && !ISWEB) #endif @@ -1771,65 +1065,6 @@ int readArgs() { shift(); dftcolor = parse(args()); } -// tree visualizer (e.g. Tree of Life) -//------------------------------------- - - else if(argis("-tree")) { - PHASE(3); shift(); tree::read(args()); - } - -// SAG visualizer (e.g. Reddit roguelikes, GitHub languages) -//----------------------------------------------------------- - -// (1) configure edge weights - else if(argis("-edgepower")) { - shift_arg_formula(sag::edgepower); - shift_arg_formula(sag::edgemul); - } -// (1) configure temperature (high, low) - else if(argis("-sagtemp")) { - shift(); sag::hightemp = argi(); - shift(); sag::lowtemp = argi(); - } - else if(argis("-sagmin")) { - shift_arg_formula(default_edgetype.visible_from); - default_edgetype.visible_from_hi = default_edgetype.visible_from; - default_edgetype.visible_from_help = default_edgetype.visible_from; - } - else if(argis("-sagminhi")) { - shift_arg_formula(default_edgetype.visible_from_hi); - } - else if(argis("-sagminhelp")) { - shift_arg_formula(default_edgetype.visible_from_help); - } -// (2) read the edge data - else if(argis("-sagpar")) { - PHASE(3); - shift(); - sag::sagpar = argi(); - } - else if(argis("-sag")) { - PHASE(3); - shift(); sag::read(args()); - } -// (3) load the initial positioning - else if(argis("-gload")) { - PHASE(3); shift(); sag::loadsnake(args()); - } -// (4) perform simulated annealing: -fullsa