replaced chosenDown with a better set of functions

This commit is contained in:
Zeno Rogue 2018-09-27 21:52:13 +02:00
parent 08e6990d23
commit dee2b23991
6 changed files with 143 additions and 101 deletions

View File

@ -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; i<c->type; 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; i<c->type; 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;
}

View File

@ -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) {

View File

@ -315,7 +315,7 @@ void expansion_analyzer::reset() {
descendants.clear();
}
template<class T> 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<int> res;
res.push_back(subtype(c) * 4 + 2);
@ -336,7 +336,7 @@ template<class T> int type_in(expansion_analyzer& ea, cell *c, const T& f) {
return ret;
}
template<class T> 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<int> res;
res.push_back(subtype(c) * 4 + 2);
int d = f(c);
@ -409,7 +409,7 @@ int curr_dist(cell *c) {
int position;
template<class T> 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<class T> 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; i<c->type; 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--;
}
}

View File

@ -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) {

30
hyper.h
View File

@ -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<int(cell*)> 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<int(cell*)>& 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);
}

View File

@ -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;