refactoring: sval/aitmp is no more, celllister(manual) used instead

This commit is contained in:
Zeno Rogue 2018-06-28 12:59:35 +02:00
parent ed8ff63ce4
commit d11044a80a
12 changed files with 225 additions and 237 deletions

View File

@ -59,7 +59,7 @@ vector<blizzardcell*> bcells;
int N;
blizzardcell* getbcell(cell *c) {
int i = c->aitmp;
int i = c->listindex;
if(i<0 || i >= N) return NULL;
if(bcells[i]->c != c) return NULL;
return bcells[i];
@ -80,8 +80,8 @@ void drawBlizzards() {
N = isize(bcells);
for(int i=0; i<N; i++) {
auto& bc = *bcells[i];
bc.tmp = bc.c->aitmp,
bc.c->aitmp = i;
bc.tmp = bc.c->listindex,
bc.c->listindex = i;
bc.gm = &gmatrix[bc.c];
bc.wmap = windmap::at(bc.c);
}
@ -223,7 +223,7 @@ void drawBlizzards() {
}
for(auto bc: bcells)
bc->c->aitmp = bc->tmp;
bc->c->listindex = bc->tmp;
}
vector<cell*> arrowtraps;

View File

@ -104,8 +104,8 @@ namespace whirlwind {
}
}
void moveAt(cell *c) {
if(eq(c->aitmp, sval)) return;
void moveAt(cell *c, celllister& cl) {
if(cl.listed(c)) return;
calcdirs(c);
if(qdirs != 1) return;
vector<cell*> whirlline;
@ -129,7 +129,7 @@ namespace whirlwind {
// printf("Cycle built from %p, length = %d\n", c, z);
for(int i=0; i<z; i++) {
// printf("%d%c", whirlline[i]->mpdist, whirlline[i]->item ? '*' : ' ');
whirlline[i]->aitmp = sval;
cl.add(whirlline[i]);
if(whirlline[i]->mpdist == BARLEV)
switchTreasure(whirlline[i]);
}
@ -143,16 +143,16 @@ namespace whirlwind {
}
void move() {
sval++;
celllister cl(manual);
for(int i=0; i<isize(dcal); i++) {
cell *c = dcal[i];
moveAt(c);
moveAt(c, cl);
}
// Keys and Orbs of Yendor always move
using namespace yendor;
for(int i=0; i<isize(yi); i++) {
moveAt(yi[i].path[0]);
moveAt(yi[i].path[YDIST-1]);
moveAt(yi[i].path[0], cl);
moveAt(yi[i].path[YDIST-1], cl);
}
}
@ -265,23 +265,23 @@ namespace elec {
vector<cell*> chargecells;
bool hasdata(cell *c) {
return c->aitmp >= 0 && c->aitmp < isize(charges) && charges[c->aitmp].c == c;
return c->listindex >= 0 && c->listindex < isize(charges) && charges[c->listindex].c == c;
}
void connect(int from, cell *c) {
if(hasdata(c)) {
// seen again: set the lowlink
if(!charges[c->aitmp].instack) return;
// printf("edge %d-%d\n", from, c->aitmp);
if(c->aitmp < charges[from].lowlink)
charges[from].lowlink = c->aitmp;
if(!charges[c->listindex].instack) return;
// printf("edge %d-%d\n", from, c->listindex);
if(c->listindex < charges[from].lowlink)
charges[from].lowlink = c->listindex;
}
else {
int id = isize(charges);
charges.push_back(chargedata());
{chargedata& ch(charges[id]);
ch.c = c; ch.otmp = c->aitmp; ch.lowlink = id; c->aitmp = id;
ch.c = c; ch.otmp = c->listindex; ch.lowlink = id; c->listindex = id;
ch.instack = true; ch.fire = false;
}
// c->landparam = id;
@ -304,7 +304,7 @@ namespace elec {
for(int i=0; i<c->type; i++) {
cell *c2 = c->mov[i];
if(!c2) continue;
if(c2->aitmp == from) continue;
if(c2->listindex == from) continue;
eCharge ct = getCharge(c2);
if(conduct(chh, ct))
connect(id, c2);
@ -349,29 +349,29 @@ namespace elec {
c->wall = waMetal; */
}
void listChargedCells(cell *c, eCharge last = ecConductor) {
if(eq(c->aitmp, sval)) return;
void listChargedCells(cell *c, celllister& cl, eCharge last = ecConductor) {
if(cl.listed(c)) return;
eCharge here = getCharge(c);
/* if(c->cpdist <= 2) {
printf("monst=%s ", dnameof(c->monst));
printf("wall=%s ", dnameof(c->wall));
printf("c=%p here=%d last=%d\n", c, here, last);
} */
if(here == ecIsolator) c->aitmp = sval;
if(here == ecIsolator) cl.add(c);
if(!conduct(last, here)) return;
if(here == ecCharged) chargecells.push_back(c);
c->aitmp = sval;
cl.add(c);
for(int i=0; i<c->type; i++) {
cell *c2 = c->mov[i];
if(c2) listChargedCells(c2, here);
if(c2) listChargedCells(c2, cl, here);
}
}
void init() {
chargecells.clear();
if(!haveelec && !afterOrb) return;
sval++;
for(int i=0; i<isize(dcal); i++) listChargedCells(dcal[i]);
celllister cl(manual);
for(int i=0; i<isize(dcal); i++) listChargedCells(dcal[i], cl);
charges.resize(2);
charges[0].lowlink = 0; charges[1].lowlink = 1;
@ -406,7 +406,7 @@ namespace elec {
void cleanup() {
for(int i=2; i<isize(charges); i++)
charges[i].c->aitmp = charges[i].otmp;
charges[i].c->listindex = charges[i].otmp;
charges.resize(0);
}
@ -429,8 +429,8 @@ namespace elec {
}
bool affected(cell *c) {
if(c->aitmp >= 0 && c->aitmp < isize(charges) && charges[c->aitmp].c == c)
return charges[c->aitmp].fire;
if(c->listindex >= 0 && c->listindex < isize(charges) && charges[c->listindex].c == c)
return charges[c->listindex].fire;
return false;
}
@ -1011,9 +1011,9 @@ namespace whirlpool {
generate(wto);
}
void moveAt(cell *c) {
void moveAt(cell *c, celllister& cl) {
if(c->land != laWhirlpool) return;
if(eq(c->aitmp, sval)) return;
if(cl.listed(c)) return;
if(!(euclid || c->master->alt)) return;
cell *c2 = get(c, 1);
if(!c2) return;
@ -1027,7 +1027,7 @@ namespace whirlpool {
int z = isize(whirlline);
for(int i=0; i<z; i++)
whirlline[i]->aitmp = sval;
cl.add(whirlline[i]);
whirlMove(NULL, whirlline[0]);
@ -1038,16 +1038,16 @@ namespace whirlpool {
}
void move() {
sval++;
celllister cl(manual);
for(int i=0; i<isize(dcal); i++) {
cell *c = dcal[i];
moveAt(c);
moveAt(c, cl);
}
// Keys and Orbs of Yendor always move
using namespace yendor;
for(int i=0; i<isize(yi); i++) {
moveAt(yi[i].path[0]);
moveAt(yi[i].path[YDIST-1]);
moveAt(yi[i].path[0], cl);
moveAt(yi[i].path[YDIST-1], cl);
}
}
}
@ -1466,7 +1466,7 @@ namespace hive {
}
void bugcell(cell *c) {
short& i(c->aitmp);
int& i(c->listindex);
if(i >= 0 && i < isize(buginfo) && buginfo[i].where == c)
return;
i = isize(buginfo);
@ -1528,9 +1528,9 @@ namespace hive {
for(int dir=0; dir<c->type; dir++) {
cell *c2 = c->mov[dir];
if(!c2) continue;
if(c2->aitmp < 0 || c2->aitmp >= isize(buginfo)) continue;
if(c2->listindex < 0 || c2->listindex >= isize(buginfo)) continue;
if(!passable(c, c2, P_MONSTER)) continue;
int j = c2->aitmp;
int j = c2->listindex;
if(buginfo[j].where != c2) continue;
if(buginfo[j].dist[k] < d) goodmoves++;
bugQueueInsert(k, j, d+1);
@ -1610,11 +1610,11 @@ namespace hive {
qual = c2->monst == moDeadBug ? -60: isBugEnemy(c2,k) ? 2 : -20;
else if(!passable(c2, c, 0))
qual = passable(c2, c, P_DEADLY) ? -30 : -60;
else if(c2->aitmp < 0 || c2->aitmp >= isize(buginfo)) qual = -15;
else if(buginfo[c2->aitmp].where != c2) qual = -15;
else if(buginfo[c2->aitmp].dist[k] < b.dist[k])
else if(c2->listindex < 0 || c2->listindex >= isize(buginfo)) qual = -15;
else if(buginfo[c2->listindex].where != c2) qual = -15;
else if(buginfo[c2->listindex].dist[k] < b.dist[k])
qual = 1;
else if(buginfo[c2->aitmp].dist[k] == b.dist[k])
else if(buginfo[c2->listindex].dist[k] == b.dist[k])
qual = 0;
// printf("%d->#%d %d: %d\n", i, dir, c2->tmp, qual);
if(qual > bqual) bqual = qual, q=0;
@ -1664,7 +1664,7 @@ namespace hive {
}
void bugcitycell(cell *c, int d) {
short& i = c->aitmp;
int& i = c->listindex;
if(i >= 0 && i < isize(buginfo) && buginfo[i].where == c)
return;
i = isize(buginfo);
@ -1793,14 +1793,13 @@ namespace heat {
vector<cell*> offscreen2;
sval++;
celllister cl(manual);
int gr = gamerange();
for(cell *c: offscreen_heat) {
if(c->cpdist > gr && !doall) {
if(eq(c->aitmp, sval)) continue;
c->aitmp = sval;
if(!cl.add(c)) continue;
if(isIcyLand(c)) {
if(HEAT(c) < .01 && HEAT(c) > -.01)
HEAT(c) = 0;
@ -1941,13 +1940,12 @@ namespace heat {
vector<cell*> offscreen2;
sval++;
celllister cl(manual);
vector<cell*>& allcells = currentmap->allcells();
for(int x: {0,1}) for(cell *c: x==0 ? allcells : offscreen_fire) {
if(eq(c->aitmp, sval)) continue;
c->aitmp = sval;
if(!cl.add(c)) continue;
if(isFireOrMagma(c)) {
if(c->wall == waMagma) c->wparam = 20;
@ -2046,94 +2044,98 @@ void livecaves() {
vector<cell*> bringlife;
int gr = gamerange();
int heatvals[dcs];
for(int i=0; i<dcs; i++) {
cell *c = allcells[i];
if(!doall && c->cpdist > gr+1) break;
int & hv = heatvals[i];
if(c->wall == waCavefloor || c->wall == waCavewall || c->wall == waDeadTroll) {
c->aitmp = 0;
hv = 0;
if(c->monst == moDarkTroll) c->monst = moTroll;
if(c->item || c->monst || c->cpdist == 0) continue;
forCellEx(c2, c) {
eWall w = c2->wall;
if(w == waDeadfloor) c->aitmp++, bringlife.push_back(c2);
if(w == waDeadfloor) hv++, bringlife.push_back(c2);
else if(w == waDeadwall || (w == waDeadfloor2 && !c2->monst))
c->aitmp--, bringlife.push_back(c2);
else if(w == waCavefloor) c->aitmp++;
else if(w == waCavewall) c->aitmp--;
else if(w == waRubble) c->aitmp--;
else if(w == waGargoyle) c->aitmp--;
else if(w == waGargoyleFloor) c->aitmp--;
else if(w == waGargoyleBridge) c->aitmp--;
hv--, bringlife.push_back(c2);
else if(w == waCavefloor) hv++;
else if(w == waCavewall) hv--;
else if(w == waRubble) hv--;
else if(w == waGargoyle) hv--;
else if(w == waGargoyleFloor) hv--;
else if(w == waGargoyleBridge) hv--;
else if(w == waStone) ;
else if(w == waDeadTroll) c->aitmp -= 5;
else if(w == waDeadTroll2) c->aitmp -= 3;
else if(w == waPetrified || w == waPetrifiedBridge) c->aitmp -= 2;
else if(w == waVinePlant) c->aitmp--;
else if(w == waDeadTroll) hv -= 5;
else if(w == waDeadTroll2) hv -= 3;
else if(w == waPetrified || w == waPetrifiedBridge) hv -= 2;
else if(w == waVinePlant) hv--;
else if(chaosmode && c2->land != laCaves && c2->land != laEmerald) ;
else if(c2->land == laTrollheim) ; // trollheim floor does not count
else if(w != waBarrier) c->aitmp += 5;
else if(w != waBarrier) hv += 5;
if(sword::at(c)) c->aitmp += 500;
if(sword::at(c)) hv += 500;
if(c2->cpdist == 0 && markOrb(itOrbDigging)) c->aitmp+=100;
if(c2->cpdist == 0 && markOrb(itOrbDigging)) hv+=100;
if(items[itOrbEmpathy] && isFriendly(c2) && markEmpathy(itOrbDigging))
c->aitmp+=100;
if(w == waThumperOn) c->aitmp+=100;
if(w == waFire) c->aitmp+=100;
if(w == waBigStatue) c->aitmp-=100;
if(c2->item && !peace::on) c->aitmp+=2;
if(c2->monst == moZombie) c->aitmp += 10;
if(c2->monst == moGhost) c->aitmp += 10;
if(c2->monst == moTentacleGhost) c->aitmp += 10;
if(c2->monst == moFriendlyGhost) c->aitmp += 10;
if(c2->monst == moSkeleton) c->aitmp ++;
if(c2->monst == moGargoyle) c->aitmp--;
if(c2->monst == moDraugr) c->aitmp--;
if(isDragon(c2->monst)) c->aitmp++;
if(c2->monst == moNecromancer) c->aitmp += 10;
if(c2->monst == moWormtail) c->aitmp++;
if(c2->monst == moTentacletail) c->aitmp-=2;
if(isIvy(c2)) c->aitmp--;
if(isDemon(c2)) c->aitmp-=3;
hv+=100;
if(w == waThumperOn) hv+=100;
if(w == waFire) hv+=100;
if(w == waBigStatue) hv-=100;
if(c2->item && !peace::on) hv+=2;
if(c2->monst == moZombie) hv += 10;
if(c2->monst == moGhost) hv += 10;
if(c2->monst == moTentacleGhost) hv += 10;
if(c2->monst == moFriendlyGhost) hv += 10;
if(c2->monst == moSkeleton) hv ++;
if(c2->monst == moGargoyle) hv--;
if(c2->monst == moDraugr) hv--;
if(isDragon(c2->monst)) hv++;
if(c2->monst == moNecromancer) hv += 10;
if(c2->monst == moWormtail) hv++;
if(c2->monst == moTentacletail) hv-=2;
if(isIvy(c2)) hv--;
if(isDemon(c2)) hv-=3;
// if(c2->monst) c->tmp++;
// if(c2->monst == moTroll) c->tmp -= 3;
}
}
else if(c->land == laLivefjord) {
c->aitmp = 0;
hv = 0;
if(c->monst == moWaterElemental)
c->aitmp += 1000;
hv += 1000;
if(isPlayerInBoatOn(c) && markOrb(itOrbWater))
c->aitmp += 1000;
hv += 1000;
if(c->monst == moEarthElemental)
c->aitmp -= 1000;
hv -= 1000;
if(isPlayerOn(c) && markOrb(itOrbDigging))
c->aitmp -= 1000;
hv -= 1000;
for(int j=0; j<c->type; j++) if(c->mov[j]) {
cell *c2 = c->mov[j];
if(c2->wall == waNone || c2->wall == waStrandedBoat)
c->aitmp -= (c2->land == laLivefjord ? 1 : 100);
hv -= (c2->land == laLivefjord ? 1 : 100);
if(c2->wall == waTempFloor || c2->wall == waTempBridge || c2->wall == waTempBridgeBlocked)
;
else if(c2->wall == waDeadTroll || c2->wall == waDeadTroll2 || c2->wall == waThumperOn || isFire(c2) || snakelevel(c2))
c->aitmp -= 10;
hv -= 10;
else if(c2->wall == waPetrified || c2->wall == waPetrifiedBridge)
c->aitmp -= 10;
hv -= 10;
if(c2->wall == waBigStatue)
c->aitmp -= 10;
hv -= 10;
if(c2->wall == waSea || c2->wall == waBoat)
c->aitmp += (c2->land == laLivefjord ? 1 : 100);
hv += (c2->land == laLivefjord ? 1 : 100);
if(c2->monst == moWaterElemental)
c->aitmp += 1000;
hv += 1000;
if(isPlayerOn(c2) && c2->wall == waBoat && markOrb(itOrbWater))
c->aitmp += 1000;
hv += 1000;
if(c2->monst == moEarthElemental)
c->aitmp -= 1000;
hv -= 1000;
if(isPlayerOn(c2) && markOrb(itOrbDigging))
c->aitmp -= 1000;
hv -= 1000;
if(items[itOrbEmpathy] && isFriendly(c2) && markEmpathy(itOrbDigging))
c->aitmp -= 1000;
hv -= 1000;
if(c2->wall == waBarrier) {
bool landbar = false;
@ -2143,8 +2145,8 @@ void livecaves() {
if(!isSealand(c3->land))
landbar = true;
}
if(landbar) c->aitmp -= 5;
else c->aitmp += 5;
if(landbar) hv -= 5;
else hv += 5;
}
}
}
@ -2153,13 +2155,14 @@ void livecaves() {
for(int i=0; i<dcs; i++) {
cell *c = allcells[i];
if(!doall && c->cpdist > gr+1) break;
int hv = heatvals[i];
if(c->wall == waCavefloor || c->wall == waCavewall) {
// if(c->land != laCaves) continue;
// if(c->wall == waThumper || c->wall == waBonfire) continue;
if(c->aitmp > 0) c->wall = waCavefloor;
if(c->aitmp < 0) {
if(hv > 0) c->wall = waCavefloor;
if(hv < 0) {
c->wall = waCavewall;
if(c->land != laCaves && c->land != laDeadCaves && c->land != laEmerald && !gardener) {
gardener = true;
@ -2168,14 +2171,14 @@ void livecaves() {
}
}
else if(c->land == laLivefjord) {
if(c->aitmp > 0 && c->wall == waStrandedBoat) c->wall = waBoat;
if(c->aitmp > 0 && c->wall == waNone) {
if(hv > 0 && c->wall == waStrandedBoat) c->wall = waBoat;
if(hv > 0 && c->wall == waNone) {
if(c->item && c->cpdist == 1 && markOrb(itOrbWater))
collectItem(c);
c->wall = waSea;
}
if(c->aitmp < 0 && c->wall == waBoat) c->wall = waStrandedBoat;
if(c->aitmp < 0 && c->wall == waSea) c->wall = waNone;
if(hv < 0 && c->wall == waBoat) c->wall = waStrandedBoat;
if(hv < 0 && c->wall == waSea) c->wall = waNone;
}
}
@ -2573,6 +2576,7 @@ namespace kraken {
}
void attacks() {
pathdata pd(2);
bool offboat[MAXPLAYER];
for(int i=0; i<MAXPLAYER; i++) offboat[i] = false;
for(int i=0; i<isize(dcal); i++) {
@ -2632,8 +2636,7 @@ namespace kraken {
vector<pair<cell*, cell*> > acells;
acells.push_back(make_pair(c2, c));
forCellIdEx(c3, i, c) {
c3->monst = moKrakenT, c3->mondir = c->spn(i),
c3->aitmp = sval;
c3->monst = moKrakenT, c3->mondir = c->spn(i), onpath(c3, 0);
int i0 = (i+c->spn(c->mondir)-c->mondir+99) % c2->type;
c3->hitpoints = hpcount[i0];
acells.push_back(make_pair(c2->mov[i0], c3));
@ -2665,7 +2668,7 @@ namespace kraken {
}
commitAnimations(LAYER_BIG);
sleep(c);
c->aitmp = sval;
onpath(c, 0);
return;
}
@ -2834,23 +2837,21 @@ namespace prairie {
if(c2) c->mondir = neighborId(c, c2);
}
void moveAt(cell *c) {
if(eq(c->aitmp, sval)) return;
void moveAt(cell *c, celllister& cl) {
if(!cl.add(c)) return;
vector<cell*> whirlline;
whirlline.push_back(c);
c->aitmp = sval;
cell *c2 = prev(c);
while(c2 && !eq(c2->aitmp, sval)) {
whirlline.push_back(c2), c2->aitmp = sval;
while(c2 && !cl.add(c2)) {
whirlline.push_back(c2);
c2 = prev(c2);
// in sphere/quotient geometries, never break before a bull
if((sphere || quotient) && !c2->monst) break;
}
reverse(whirlline.begin(), whirlline.end());
c2 = next(c);
while(c2 && !eq(c2->aitmp, sval)) whirlline.push_back(c2), c2->aitmp = sval, c2 = next(c2);
while(c2 && cl.add(c2)) whirlline.push_back(c2), c2 = next(c2);
int qty = isize(whirlline);
// for(int i=0; i<qty; i++) whirlline[i]->aitmp = sval;
if(shmup::on) {
for(int i=0; i<qty; i++) if(whirlline[i]->cpdist <= gamerange()) {
generateBeast(whirlline[i]);
@ -2887,10 +2888,10 @@ namespace prairie {
}
void move() {
sval++;
celllister cl(manual);
for(int i=0; i<isize(dcal); i++) {
cell *c = dcal[i];
if(isriver(c)) moveAt(c);
if(isriver(c)) moveAt(c, cl);
}
for(int i=0; i<isize(beaststogen); i++)
generateBeast(beaststogen[i]);

View File

@ -823,24 +823,28 @@ namespace conformal {
else if(doexiton(sym, uni)) popScreen();
}
set<cell*> inmovehistory, inkillhistory, infindhistory;
void restore() {
sval++;
inmovehistory.clear();
inkillhistory.clear();
infindhistory.clear();
for(int i=0; i<isize(movehistory); i++)
movehistory[i]->aitmp = sval;
inmovehistory.insert(movehistory[i]);
sval++;
int sk = isize(killhistory);
for(int i=0; i<sk; i++) {
eMonster m = killhistory[i].second;
killhistory[i].second = killhistory[i].first->monst;
killhistory[i].first->monst = m;
killhistory[i].first->aitmp = sval;
inkillhistory.insert(killhistory[i].first);
}
int si = isize(findhistory);
for(int i=0; i<si; i++) {
eItem m = findhistory[i].second;
findhistory[i].second = findhistory[i].first->item;
findhistory[i].first->item = m;
findhistory[i].first->aitmp = sval;
infindhistory.insert(findhistory[i].first);
}
}

View File

@ -333,7 +333,7 @@ void debugScreen() {
dialog::addSelItem("celldist", its(celldist(mouseover)), 0);
dialog::addSelItem("pathdist", its(mouseover->pathdist), 0);
dialog::addSelItem("celldistAlt", mouseover->master->alt ? its(celldistAlt(mouseover)) : "--", 0);
dialog::addSelItem("temporary", its(mouseover->aitmp), 0);
dialog::addSelItem("temporary", its(mouseover->listindex), 0);
if(gp::on)
dialog::addSelItem("whirl", gp::disp(gp::get_local_info(mouseover).relative), 0);
dialog::addBreak(50);

View File

@ -170,7 +170,7 @@ void initcell(cell *c) {
c->cpdist = INFD; // current distance from the player
c->pathdist = PINFD;// current distance from the player, along paths (used by yetis)
c->landparam = 0; c->landflags = 0; c->wparam = 0;
c->aitmp = 0;
c->listindex = -1;
c->wall = waNone;
c->item = itNone;
c->monst = moNone;
@ -2836,26 +2836,6 @@ void computePathdist(eMonster param) {
}
// pathdist end
struct pathdata {
void checklock() {
if(pd_from) pd_from = NULL, clear_pathdata();
if(pathlock) printf("path error\n");
pathlock++;
}
~pathdata() {
pathlock--;
clear_pathdata();
}
pathdata(eMonster m) {
checklock();
computePathdist(m);
}
pathdata(int i) {
checklock();
}
};
vector<pair<cell*, int> > butterflies;
void addButterfly(cell *c) {
@ -5786,12 +5766,11 @@ void moveNormals(eMonster param) {
}
}
void markAmbush(cell *c) {
if(eq(c->aitmp, sval)) return;
c->aitmp = sval;
void markAmbush(cell *c, celllister& cl) {
if(!cl.add(c)) return;
forCellEx(c2, c)
if(c2->cpdist < c->cpdist)
markAmbush(c2);
markAmbush(c2, cl);
}
int ambush_distance;
@ -5799,30 +5778,30 @@ bool ambushed;
void checkAmbushState() {
if(havewhat & HF_HUNTER) {
sval++;
celllister cl(manual);
for(cell *c: dcal) {
if(c->monst == moHunterDog) {
if(c->cpdist > ambush_distance)
ambush_distance = c->cpdist;
markAmbush(c);
markAmbush(c, cl);
}
if(c->monst == moHunterGuard && c->cpdist <= 4)
markAmbush(c);
markAmbush(c, cl);
}
if(items[itHunting] > 5 && items[itHunting] <= 22) {
int q = 0;
for(int i=0; i<numplayers(); i++)
forCellEx(c2, playerpos(i))
if(eq(c2->aitmp, sval))
q++;
if(cl.listed(c2))
q++;
if(q == 1) havewhat |= HF_FAILED_AMBUSH;
if(q == 2) {
for(int i=0; i<numplayers(); i++)
forCellEx(c2, playerpos(i))
if(eq(c2->aitmp, sval))
if(cl.listed(c2))
forCellEx(c3, playerpos(i))
if(c3 != c2 && isNeighbor(c2,c3))
if(eq(c3->aitmp, sval))
if(cl.listed(c3))
havewhat |= HF_FAILED_AMBUSH;
}
if(havewhat & HF_FAILED_AMBUSH && ambushed) {
@ -6546,7 +6525,6 @@ int ambush(cell *c, eItem what) {
celllister cl(c, maxdist, 1000000, NULL);
cell *c0 = c;
int d = 0;
cl.prepare();
int dogs0 = 0;
for(cell *cx: cl.lst) {
int dh = cl.getdist(cx);

View File

@ -586,7 +586,7 @@ bool drawItemType(eItem it, cell *c, const transmatrix& V, int icol, int ticks,
poly_outline = OUTLINE_OTHER;
}
if(c && conformal::includeHistory && eq(c->aitmp, sval)) poly_outline = OUTLINE_DEAD;
if(c && conformal::includeHistory && conformal::infindhistory.count(c)) poly_outline = OUTLINE_DEAD;
if(!mmitem && it) return true;
@ -1809,7 +1809,7 @@ bool dont_face_pc = false;
bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
bool darkhistory = conformal::includeHistory && eq(c->aitmp, sval);
bool darkhistory = conformal::includeHistory && conformal::inkillhistory.count(c);
if(doHighlight())
poly_outline =
@ -2981,7 +2981,7 @@ void setcolors(cell *c, int& wcol, int &fcol) {
}
case waFloorA: case waFloorB: // isAlch
if(c->item && !(conformal::includeHistory && eq(c->aitmp, sval)))
if(c->item && !(conformal::includeHistory && conformal::infindhistory.count(c)))
fcol = wcol = iinf[c->item].color;
else
fcol = wcol;
@ -3648,7 +3648,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
bool hidden = itemHidden(c);
bool hiddens = itemHiddenFromSight(c);
if(conformal::includeHistory && eq(c->aitmp, sval)) {
if(conformal::includeHistory && conformal::infindhistory.count(c)) {
hidden = true;
hiddens = false;
}
@ -4211,7 +4211,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
queuepoly((*Vdp), shHeptaMarker, wmblack ? 0x80808080 : 0x00000080);
}
if(conformal::includeHistory && eq(c->aitmp, sval-1))
if(conformal::includeHistory && conformal::inmovehistory.count(c))
queuepoly((*Vdp), shHeptaMarker, 0x000000C0);
char xch = winf[c->wall].glyph;

71
hyper.h
View File

@ -369,10 +369,7 @@ struct cell : gcell {
// wall parameter, used for remaining power of Bonfires and Thumpers
char wparam;
// 'tmp' is used for:
// pathfinding algorithm used by monsters with atypical movement (which do not use pathdist)
// bugs' pathfinding algorithm
short aitmp;
int listindex;
uint32_t spintable;
int spin(int d) { return tspin(spintable, d); }
@ -1064,6 +1061,7 @@ namespace conformal {
extern vector<pair<cell*, eMonster> > killhistory;
extern vector<pair<cell*, eItem> > findhistory;
extern vector<cell*> movehistory;
extern set<cell*> inmovehistory, inkillhistory, infindhistory;
extern bool includeHistory;
extern ld rotation;
extern int do_rotate;
@ -1199,7 +1197,6 @@ bool isAlchAny(cell *c);
#define MODECODES 255
extern cellwalker cwt; // player character position
extern int sval;
extern array<int, ittypes> items;
extern array<int, motypes> kills;
@ -2546,28 +2543,37 @@ extern vector<hrmap*> allmaps;
// list all cells in distance at most maxdist, or until when maxcount cells are reached
extern struct manual_t {} manual;
struct celllister {
vector<cell*> lst;
vector<int> tmps;
vector<int> dists;
void add(cell *c, int d) {
if(eq(c->aitmp, sval)) return;
c->aitmp = sval;
tmps.push_back(c->aitmp);
bool listed(cell *c) {
return c->listindex >= 0 && c->listindex < isize(lst) && lst[c->listindex] == c;
}
bool add(cell *c) {
if(listed(c)) return false;
tmps.push_back(c->listindex);
lst.push_back(c);
dists.push_back(d);
c->listindex = isize(lst);
return true;
}
void add(cell *c, int d) {
if(add(c)) dists.push_back(d);
}
~celllister() {
for(int i=0; i<isize(lst); i++) lst[i]->aitmp = tmps[i];
for(int i=0; i<isize(lst); i++) lst[i]->listindex = tmps[i];
}
celllister(manual_t) {
}
celllister(cell *orig, int maxdist, int maxcount, cell *breakon) {
lst.clear();
tmps.clear();
dists.clear();
sval++;
add(orig, 0);
cell *last = orig;
for(int i=0; i<isize(lst); i++) {
@ -2583,16 +2589,7 @@ struct celllister {
}
}
void prepare() {
for(int i=0; i<isize(lst); i++) lst[i]->aitmp = i;
}
int getdist(cell *c) { return dists[c->aitmp]; }
bool listed(cell *c) {
return c->aitmp >= 0 && c->aitmp < isize(lst) && lst[c->aitmp] == c;
}
int getdist(cell *c) { return dists[c->listindex]; }
};
hrmap *newAltMap(heptagon *o);
@ -3569,4 +3566,28 @@ bool confusingGeometry();
int revhint(cell *c, int hint);
extern int pathlock;
extern void computePathdist(eMonster m);
extern void onpath(cell *c, int d);
extern void clear_pathdata();
struct pathdata {
void checklock() {
if(pd_from) pd_from = NULL, clear_pathdata();
if(pathlock) printf("path error\n");
pathlock++;
}
~pathdata() {
pathlock--;
clear_pathdata();
}
pathdata(eMonster m) {
checklock();
computePathdist(m);
}
pathdata(int i) {
checklock();
}
};
}

View File

@ -60,12 +60,8 @@ bool reptilecheat = false;
#define ONEMPTY if(d == 7 && passable(c, NULL, 0) && !safety)
vector<cell*> noescape_list;
bool blizzard_no_escape1(cell *c) {
if(c->aitmp >= 0 && c->aitmp < isize(noescape_list) && noescape_list[c->aitmp] == c)
return true;
c->aitmp = isize(noescape_list); noescape_list.push_back(c);
bool blizzard_no_escape1(cell *c, celllister &cl) {
if(!cl.add(c)) return true;
if(c->item == itOrbSafety)
return false;
forCellEx(c2, c) {
@ -73,16 +69,15 @@ bool blizzard_no_escape1(cell *c) {
continue;
if(c2->land != laBlizzard && passable(c2, NULL, 0))
return false;
if(!againstWind(c2, c) && !blizzard_no_escape1(c2))
if(!againstWind(c2, c) && !blizzard_no_escape1(c2, cl))
return false;
}
return true;
}
bool blizzard_no_escape(cell *c) {
sval++;
noescape_list.resize(0);
return blizzard_no_escape1(c);
celllister cl(manual);
return blizzard_no_escape1(c, cl);
}
bool out_ruin(cell *c) {

View File

@ -267,8 +267,9 @@ namespace mapstream {
c->bardir = NOBARRIERS;
// fixspin(rspin, loadChar(), c->type);
if(vernum < 7400) {
load(c->aitmp);
c->wparam = c->aitmp;
short z;
load(z);
c->wparam = z;
}
else load(c->wparam);
load(c->landparam);
@ -620,7 +621,7 @@ namespace mapeditor {
vector<pair<cellwalker, cellwalker> > spill_list;
void list_spill(cellwalker tgt, cellwalker src) {
void list_spill(cellwalker tgt, cellwalker src, celllister& cl) {
spill_list.clear(); sval++;
spill_list.emplace_back(tgt, src);
int crad = 0, nextstepat = 0;
@ -633,8 +634,7 @@ namespace mapeditor {
for(int i=0; i<sd.first.c->type; i++) {
auto sd2 = sd;
sd2.first = sd2.first + i + wstep;
if(eq(sd2.first.c->aitmp, sval)) continue;
sd2.first.c->aitmp = sval;
if(!cl.add(sd2.first.c)) continue;
if(sd2.second.c) {
sd2.second = sd2.second + i + wstep;
if(sd2.second.c->land == laNone) continue;
@ -668,7 +668,7 @@ namespace mapeditor {
}
#endif
void editAt(cellwalker where) {
void editAt(cellwalker where, celllister& cl) {
if(painttype == 4 && radius) {
if(where.c->type != copysource.c->type) return;
@ -677,7 +677,7 @@ namespace mapeditor {
where += 1;
}
if(painttype != 4) copysource.c = NULL;
list_spill(where, copysource);
list_spill(where, copysource, cl);
for(auto& st: spill_list)
editCell(st);
@ -685,34 +685,30 @@ namespace mapeditor {
void allInPattern(cellwalker where) {
celllister cl(manual);
if(!patterns::whichPattern) {
editAt(where);
editAt(where, cl);
return;
}
vector<cell*> v;
v.push_back(where.c);
sval++;
where.c->aitmp = sval;
cl.add(where.c);
int at = 0;
while(at < isize(v)) {
cell *c2 = v[at];
while(at < isize(cl.lst)) {
cell *c2 = cl.lst[at];
at++;
forCellEx(c3, c2)
if(!eq(c3->aitmp, sval))
c3->aitmp = sval, v.push_back(c3);
forCellEx(c3, c2) cl.add(c3);
}
auto si = patterns::getpatterninfo0(where.c);
int cdir = where.spin;
if(cdir >= 0) cdir = cdir - si.dir;
for(cell* c2: v) {
for(cell* c2: cl.lst) {
auto si2 = patterns::getpatterninfo0(c2);
if(si2.id == si.id) {
editAt(cellwalker(c2, cdir>=0 ? fixdir(cdir + si2.dir, c2) : -1));
editAt(cellwalker(c2, cdir>=0 ? fixdir(cdir + si2.dir, c2) : -1), cl);
modelcell[si2.id] = c2;
}
}

View File

@ -242,18 +242,17 @@ int getSeepcount() {
}
bool canReachPlayer(cell *cf, eMonster m) {
vector<cell*> v;
sval++;
v.push_back(cf); cf->aitmp = sval;
for(int i=0; i<isize(v); i++) {
cell *c = v[i];
celllister cl(manual);
cl.add(cf);
for(int i=0; i<isize(cl.lst) && i < 10000; i++) {
cell *c = cl.lst[i];
for(int j=0; j<c->type; j++) {
cell *c2 = c->mov[j];
if(!c2) continue;
if(eq(c2->aitmp, sval)) continue;
if(cl.listed(c2)) continue;
if(!passable_for(m, c2, c, P_MONSTER | P_ONPLAYER | P_CHAIN)) continue;
if(isPlayerOn(c2)) return true;
c2->aitmp = sval; v.push_back(c2);
cl.add(c2);
}
}
return false;

View File

@ -247,19 +247,16 @@ bool distanceBound(cell *c1, cell *c2, int d) {
}
void checkFreedom(cell *cf) {
sval++;
static vector<cell*> avcells;
avcells.clear();
avcells.push_back(cf);
cf->aitmp = sval;
for(int i=0; i<isize(avcells); i++) {
cell *c = avcells[i];
celllister cl(manual);
cl.add(cf);
for(int i=0; i<isize(cl.lst); i++) {
cell *c = cl.lst[i];
if(c->cpdist >= 5) return;
for(int i=0; i<c->type; i++) {
cell *c2 = c->mov[i];
// todo leader
if(cl.listed(c2)) continue;
if(!passable(c2, c, P_ISPLAYER | P_MIRROR | P_LEADER)) continue;
if(eq(c2->aitmp, sval)) continue;
if(c2->wall == waArrowTrap && c2->wparam == 2) continue;
bool monsterhere = false;
for(int j=0; j<c2->type; j++) {
@ -267,10 +264,7 @@ void checkFreedom(cell *cf) {
if(c3 && c3->monst && !isFriendly(c3))
monsterhere = true;
}
if(!monsterhere) {
c2->aitmp = sval;
avcells.push_back(c2);
}
if(!monsterhere) cl.add(c2);
}
}
addMessage(XLAT("Your %1 activates!", itOrbFreedom));

View File

@ -1011,14 +1011,14 @@ namespace peace {
clister.emplace_back(cp, cp);
int id = 0;
sval++;
celllister cl(manual);
while(id < isize(clister)) {
cell *c = clister[id].first;
cell *fr = clister[id].second;
setdist(c, 5, NULL);
forCellEx(c2,c)
if(!eq(c2->aitmp, sval) && passable(c2, c, 0) && (c2->land == specialland || c2->land == laTemple) && !c2->item) {
if(!cl.listed(c2) && passable(c2, c, 0) && (c2->land == specialland || c2->land == laTemple) && !c2->item) {
if(!id) fr = c2;
bool next;
if(specialland == laRlyeh)
@ -1031,7 +1031,7 @@ namespace peace {
goto again;
}
clister.emplace_back(c2, fr);
c2->aitmp = sval;
cl.add(c2);
}
id++;
}