diff --git a/bigstuff.cpp b/bigstuff.cpp index 69f1856d..bc2cc4d7 100644 --- a/bigstuff.cpp +++ b/bigstuff.cpp @@ -648,38 +648,6 @@ cell *randomDown(cell *c) { return tab[hrand(q)]; } -// which=1 => right, which=-1 => left - -typedef int cellfunction(cell*); - -int chosenDownId(cell *c, int which, cellfunction* cf) { - int d = (*cf)(c)-1; - for(int i=0; itype; i++) { - if(!c->move(i)) createMov(c, i); - if(c->move(i)->mpdist > BARLEV && cf == coastvalEdge) setdist(c->move(i), BARLEV, c); - - if((*cf)(c->move(i)) == d) { - again: - int i2 = (i+which+MODFIXER)%c->type; - createMov(c, i2); - if((*cf)(c->move(i2)) == d) { - i = i2; goto again; - } - else return i; - } - } - - return -1; - } - -// set which=1,bonus=1 to get right neighbor on level - -cell *chosenDown(cell *c, int which, int bonus, cellfunction* cf) { - int id = chosenDownId(c, which, cf); - if(id == -1) return NULL; - return createMovR(c, id + bonus); - } - int edgeDepth(cell *c) { if(c->land == laIvoryTower || c->land == laEndorian || c->land == laDungeon) return coastvalEdge(c); @@ -698,28 +666,12 @@ int getHauntedDepth(cell *c) { return -100; } -int towerval(cell *c, cellfunction* cf) { - // if(c->land != laEdge) return 0; - cell *cp1 = chosenDown(c, 1, 1, cf); - if(!cp1) return 0; - /* cell *cp2 = chosenDown(cp1, 1, 1); - if(!cp2) return 0; - cell *cm1 = chosenDown(c, -1, -1); - if(!cm1) return 0; - cell *cm2 = chosenDown(cm1, -1, -1); - if(!cm2) return 0; */ - - /* return - (c->type-6) - + 2*(cp1->type-6) + 4*(cp2->type-6) - + 8*(cm1->type-6) +16*(cm2->type-6); */ - +int towerval(cell *c, const cellfunction& cf) { + cell *cp1 = ts::left_of(c, cf); + if(!cp1) return 0; int under = 0; - int cfc = (*cf)(c); - for(int i=0; itype; i++) { - if(c->move(i) && (*cf)(c->move(i)) < cfc) - under++; - } + int cfc = cf(c); + forCellEx(c2, c) if(cf(c2) < cfc) under++; return (c->type-6) + 2*(cp1->type-6) + 4*under; } diff --git a/complex.cpp b/complex.cpp index c72c9c5c..4cfea027 100644 --- a/complex.cpp +++ b/complex.cpp @@ -3590,8 +3590,10 @@ namespace dungeon { c4 = c2->move(i); } rdepths[i] = c2 && c3 && c4 && (c2->landflags == 3 || c3->landflags == 3 || c4->landflags == 3); - c2 = chosenDown(c2, 1, 0); // if(!c2) break; - c3 = chosenDown(c3, -1, 0); + if(c2) generate_around(c2); + if(c3) generate_around(c3); + c2 = ts::left_parent(c2, coastvalEdge); + c3 = ts::right_parent(c3, coastvalEdge); if(!c2) { towerError(c); return; } if(!c3) { towerError(c); return; } } @@ -3604,19 +3606,22 @@ namespace dungeon { else if(!rdepths[2] && !rdepths[4] && !rdepths[1]) { c2 = c; c3 = c; - cell *c4 = chosenDown(c, 1, 1); - cell *c5 = chosenDown(c, -1, -1); + generate_around(c); + cell *c4 = ts::left_of(c, coastvalEdge); + cell *c5 = ts::right_of(c, coastvalEdge); for(int i=0; i<3; i++) { if(coastvalEdge(c2) == 0) break; - if(c2 && c4 && c4->landflags == 3 && c2->landflags != 3 && c4 == chosenDown(c2, 1, 1)) + for(cell *cx: {c2, c3, c4, c5}) if(cx) generate_around(cx); + + if(c2 && c4 && c4->landflags == 3 && c2->landflags != 3 && c4 == ts::left_of(c2, coastvalEdge)) c->wall = waLadder; - if(c3 && c5 && c5->landflags == 3 && c3->landflags != 3 && c5 == chosenDown(c3, -1, -1)) + if(c3 && c5 && c5->landflags == 3 && c3->landflags != 3 && c5 == ts::right_of(c3, coastvalEdge)) c->wall = waLadder; buildEquidistant(c4); buildEquidistant(c5); - if(c2) c2 = chosenDown(c2, 1, 0); - if(c3) c3 = chosenDown(c3, -1, 0); - if(c4) c4 = chosenDown(c4, 1, 0); - if(c5) c5 = chosenDown(c5, -1, 0); + if(c2) c2 = ts::left_parent(c2, coastvalEdge); + if(c3) c3 = ts::right_parent(c3, coastvalEdge); + if(c4) c4 = ts::left_parent(c4, coastvalEdge); + if(c5) c5 = ts::right_parent(c5, coastvalEdge); } } } @@ -3645,8 +3650,10 @@ namespace dungeon { rdepths[i] = c2 && c3 && c4 && (c2->landflags == 3 || c3->landflags == 3 || c4->landflags == 3); if((c2&&c2->landflags == 1) || (c3&&c3->landflags == 1) || (c4&&c4->landflags == 1)) switchcount++; - c2 = chosenDown(c2, 1, 0); // if(!c2) break; - c3 = chosenDown(c3, -1, 0); + generate_around(c2); + generate_around(c3); + c2 = ts::left_parent(c2, coastvalEdge); + c3 = ts::right_parent(c3, coastvalEdge); if(!c2) { towerError(c); return 0; } if(!c3) { towerError(c); return 0; } } @@ -3696,8 +3703,9 @@ namespace dungeon { int df = dungeonFlags(c); if(df&1) { - int df1 = dungeonFlags(chosenDown(c,1,1)); - int df2 = dungeonFlags(chosenDown(c,-1,-1)); + generate_around(c); + int df1 = dungeonFlags(ts::left_of(c, coastvalEdge)); + int df2 = dungeonFlags(ts::right_of(c, coastvalEdge)); c->wparam = 0; if(hrand(100) < (c->landparam % 5 == 0 ? 80 : 20)) { @@ -3725,10 +3733,10 @@ namespace dungeon { if(q) downs[hrand(q)]->wall = waLadder; */ cell *c2 = - c->wparam == 1 ? chosenDown(c, 1, 2) : - c->wparam == 2 ? chosenDown(c, -1, -2) : - c->wparam == 3 ? chosenDown(c, 1, 3) : - c->wparam == 4 ? chosenDown(c, -1, -3) : + c->wparam == 1 ? ts::add(c, 1, 2, coastvalEdge) : + c->wparam == 2 ? ts::add(c, -1, -2, coastvalEdge) : + c->wparam == 3 ? ts::add(c, 1, 3, coastvalEdge) : + c->wparam == 4 ? ts::add(c, -1, -3, coastvalEdge) : NULL; if(c2) { diff --git a/expansion.cpp b/expansion.cpp index c3f4bca2..71f8ec3f 100644 --- a/expansion.cpp +++ b/expansion.cpp @@ -315,7 +315,7 @@ void expansion_analyzer::reset() { descendants.clear(); } -template int type_in(expansion_analyzer& ea, cell *c, const T& f) { +int type_in(expansion_analyzer& ea, cell *c, const cellfunction& f) { if(!ea.N) ea.preliminary_grouping(), ea.reduce_grouping(); vector res; res.push_back(subtype(c) * 4 + 2); @@ -336,7 +336,7 @@ template int type_in(expansion_analyzer& ea, cell *c, const T& f) { return ret; } -template int type_in_quick(expansion_analyzer& ea, cell *c, const T& f) { +int type_in_quick(expansion_analyzer& ea, cell *c, const cellfunction& f) { vector res; res.push_back(subtype(c) * 4 + 2); int d = f(c); @@ -409,7 +409,7 @@ int curr_dist(cell *c) { int position; -template int type_in_reduced(expansion_analyzer& ea, cell *c, const T& f) { +int type_in_reduced(expansion_analyzer& ea, cell *c, const cellfunction& f) { int a = ea.N; int t = type_in(ea, c, f); if(expansion.N != a) { @@ -419,6 +419,69 @@ template int type_in_reduced(expansion_analyzer& ea, cell *c, const T& return t; } +// which=1 => right, which=-1 => left + +int parent_id(cell *c, int which, const cellfunction& cf) { + int d = cf(c)-1; + for(int i=0; itype; i++) { + + if(cf(c->cmove(i)) == d) { + again: + int i2 = c->c.fix(i+which); + if(cf(c->cmove(i2)) == d) { + i = i2; goto again; + } + else return i; + } + } + + return -1; + } + +// set which=1,bonus=1 to get right neighbor on level + +void generate_around(cell *c) { + forCellCM(c2, c) if(c2->mpdist > BARLEV) setdist(c2, BARLEV, c); + } + +namespace ts { + cell *verified_add(cell *c, int which, int bonus, const cellfunction& cf) { + int id = parent_id(c, which, cf); + if(id == -1) return NULL; + return c->cmodmove(id + bonus); + } + + cell *verified_add_gen(cell *c, int which, int bonus, const cellfunction& cf) { + return verified_add(c, which, bonus, cf); + } + + cell *add(cell *c, int which, int bonus, const cellfunction& cf) { + int pid = parent_id(c, which, cf); + if(pid == -1) pid = 0; + return c->cmodmove(pid + bonus); + } + + cell *left_of(cell *c, const cellfunction& cf) { + int pid = parent_id(c, 1, cf); + if(pid == -1) return c; + if(VALENCE == 3) return c->cmodmove(pid+1); + else return (cellwalker(c, pid) + wstep - 1).cpeek(); + } + + cell *right_of(cell *c, const cellfunction& cf) { + int pid = parent_id(c, -1, cf); + if(pid == -1) return c; + if(VALENCE == 3) return c->cmodmove(pid-1); + else return (cellwalker(c, pid) + wstep + 1).cpeek(); + } + + cell *child_number(cell *c, int id, const cellfunction& cf) { + int pid = parent_id(c, 1, cf); + if(pid == -1) return c->cmove(id); + return c->cmodmove(pid + (VALENCE == 3 ? 2 : 1) + id); + } + } + bool viewdists = false, use_color_codes = true, use_analyzer = true, show_distance_lists = true; int first_distance = 0, scrolltime = 0; @@ -526,7 +589,7 @@ void viewdist_configure_dialog() { 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)); + return is_descendant(ts::right_parent(c, curr_dist)); } const int scrollspeed = 100; @@ -763,9 +826,7 @@ bool in_segment(cell *left, cell *mid, cell *right) { while(true) { if(mid == left) return true; if(left == right) return false; - int v = chosenDownId(left, 1, celldist); - if(S3 == 3) left = (cellwalker(left, v) + 1).cpeek(); - else left = (cellwalker(left, v) + wstep - 1).cpeek(); + left = ts::right_of(left, celldist); } } @@ -775,7 +836,7 @@ int sibling_distance(cell *a, cell *b, int limit) { if(a == b) return counting; if(limit == 0) return INF; counting++; limit--; - a = chosenDown(a, 1, 1, celldist); + a = ts::right_of(a, celldist); } } @@ -828,18 +889,20 @@ int hyperbolic_celldistance(cell *c1, cell *c2) { } if(d >= found_distance) { - if(sl_used == sibling_limit) { printf("sibling_limit used: %d\n", sibling_limit); sibling_limit++; } + if(sl_used == sibling_limit && IRREGULAR) { + printf("sibling_limit used: %d\n", sibling_limit); sibling_limit++; + } return found_distance; } if(d1 >= d2) { - cl1 = chosenDown(cl1, -1, 0, celldist); - cr1 = chosenDown(cr1, 1, 0, celldist); + cl1 = ts::left_parent(cl1, celldist); + cr1 = ts::right_parent(cr1, celldist); d++; d1--; } if(d1 < d2) { - cl2 = chosenDown(cl2, -1, 0, celldist); - cr2 = chosenDown(cr2, 1, 0, celldist); + cl2 = ts::left_parent(cl2, celldist); + cr2 = ts::right_parent(cr2, celldist); d++; d2--; } } diff --git a/graph.cpp b/graph.cpp index 4d26ec6d..778f436b 100644 --- a/graph.cpp +++ b/graph.cpp @@ -2424,11 +2424,11 @@ transmatrix applyPatterndir(cell *c, const patterns::patterninfo& si) { return V * iddspin(c, 0, M_PI); } -transmatrix applyDowndir(cell *c, cellfunction *cf) { +transmatrix applyDowndir(cell *c, const cellfunction& cf) { return ddspin(c, patterns::downdir(c, cf), M_PI); } -void set_towerfloor(cell *c, cellfunction *cf = coastvalEdge) { +void set_towerfloor(cell *c, const cellfunction& cf = coastvalEdge) { if(weirdhyperbolic || sphere) { set_floor(shFloor); return; @@ -2436,7 +2436,7 @@ void set_towerfloor(cell *c, cellfunction *cf = coastvalEdge) { int j = -1; if(masterless) j = 10; - else if((*cf)(c) > 1) { + else if(cf(c) > 1) { int i = towerval(c, cf); if(i == 4) j = 0; if(i == 5) j = 1; @@ -4007,7 +4007,8 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { // queuepoly(Vf, shLeafFloor[ct6], darkena(fcol, fd, 0xFF)); /* else if(c->land == laPrairie && prairie::isriver(c)) - set_towerfloor(Vf, c, darkena(fcol, fd, 0xFF), + + set_towerfloor(Vf, c, darkena(fcol, fd, 0xFF), prairie::isleft(c) ? river::towerleft : river::towerright); */ else switch(c->land) { diff --git a/hyper.h b/hyper.h index c231d09e..64c51481 100644 --- a/hyper.h +++ b/hyper.h @@ -518,6 +518,7 @@ struct heptagon { heptagon () { heptacount++; } ~heptagon () { heptacount--; } heptagon *cmove(int d) { return createStep(this, d); } + heptagon *cmodmove(int d) { return createStep(this, c.fix(d)); } inline int degree(); // prevent accidental copying @@ -541,6 +542,7 @@ struct cell : gcell { cell*& move(int d) { return c.move(d); } cell*& modmove(int d) { return c.modmove(d); } cell* cmove(int d) { return createMov(this, d); } + cell* cmodmove(int d) { return createMov(this, c.fix(d)); } cell() {} // prevent accidental copying @@ -643,8 +645,6 @@ int numplayers(); void removeIvy(cell *c); bool cellEdgeUnstable(cell *c, flagtype flags = 0); int coastvalEdge(cell *c); -typedef int cellfunction(cell*); -int towerval(cell *c, cellfunction* cf = &coastvalEdge); #define HRANDMAX 0x7FFFFFFF int hrandpos(); // 0 to HRANDMAX @@ -1064,6 +1064,8 @@ extern string mouseovers; extern struct SDL_Surface *s; +typedef function cellfunction; + namespace patterns { extern char whichShape; extern int canvasback; @@ -1128,7 +1130,7 @@ namespace patterns { void showPattern(); void val38(cell *c, patterninfo &si, int sub, int pat); - int downdir(cell *c, cellfunction *cf = coastvalEdge); + int downdir(cell *c, const cellfunction& cf = coastvalEdge); } namespace mapeditor { @@ -1372,7 +1374,6 @@ extern bool buggyGeneration; int buildIvy(cell *c, int children, int minleaf); int celldistAltRelative(cell *c); int roundTableRadius(cell *c); -cell *chosenDown(cell *c, int which, int bonus, cellfunction* cf = &coastvalEdge); eLand pickLandRPM(eLand old); bool bearsCamelot(eLand l); @@ -4203,7 +4204,26 @@ struct expansion_analyzer { extern expansion_analyzer expansion; -int chosenDownId(cell *c, int which, cellfunction* cf); +int towerval(cell *c, const cellfunction& cf); + +int parent_id(cell *c, int which, const cellfunction& cf); + +extern int sibling_limit; +extern void set_sibling_limit(); +int type_in_reduced(expansion_analyzer& ea, cell *c, const function& f); + +namespace ts { + cell *verified_add(cell *c, int which, int bonus, const cellfunction& cf); + cell *add(cell *c, int which, int bonus, const cellfunction& cf); + + inline cell *left_parent(cell *c, const cellfunction& cf) { return verified_add(c, 1, 0, cf); } + inline cell *right_parent(cell *c, const cellfunction& cf) { return verified_add(c, -1, 0, cf); } + cell *left_of(cell *c, const cellfunction& cf); + cell *right_of(cell *c, const cellfunction& cf); + cell *child_number(cell *c, int id, const cellfunction& cf); + } + +void generate_around(cell *c); } diff --git a/pattern2.cpp b/pattern2.cpp index 58d8825c..a2193342 100644 --- a/pattern2.cpp +++ b/pattern2.cpp @@ -543,10 +543,8 @@ namespace patterns { } } - int downdir(cell *c, cellfunction *cf) { - cell *c2 = chosenDown(c, 1, 1, cf); - if(!c2) return 0; - return neighborId(c, c2); + int downdir(cell *c, const cellfunction& cf) { + return parent_id(c, 1, cf) + 1; } void applySym0123(int& i, int sub) { @@ -1025,8 +1023,8 @@ namespace patterns { } else if(pat == PAT_DOWN) { - si.id = towerval(c); - si.dir = downdir(c); + si.id = towerval(c, coastvalEdge); + si.dir = downdir(c, coastvalEdge); } else if(pat == PAT_FIELD) { @@ -2082,14 +2080,14 @@ namespace linepatterns { break; case patTriTree: { - cell *parent = chosenDown(c, -1, 0, curr_dist); + cell *parent = ts::right_parent(c, 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); + cell *parent = ts::right_parent(c, 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;