1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-10-19 16:07:40 +00:00

rewritten undo: part 1

This commit is contained in:
Zeno Rogue
2020-02-29 17:58:59 +01:00
parent eb15070ac4
commit e564622a48
17 changed files with 428 additions and 400 deletions

View File

@@ -42,79 +42,13 @@ EX bool hasSafeOrb(cell *c) {
struct stalemate1 {
eMonster who;
cell *moveto;
cell *killed;
cell *pushto;
cell *comefrom;
cell *swordlast[2], *swordtransit[2], *swordnext[2];
bool isKilled(cell *c);
stalemate1(eMonster w, cell *mt, cell *ki, cell *pt, cell *cf) : who(w), moveto(mt), killed(ki), pushto(pt), comefrom(cf) {}
stalemate1(eMonster w, cell *mt, cell *pt, cell *cf) : who(w), moveto(mt), pushto(pt), comefrom(cf) {}
};
#endif
EX bool used_impact;
bool stalemate1::isKilled(cell *w) {
if(w->monst == moNone || w == killed) return true;
if(!moveto) return false;
for(int b=0; b<2; b++)
if((w == swordnext[b] || w == swordtransit[b]) && canAttack(moveto, who, w, w->monst, AF_SWORD))
return true;
if(logical_adjacent(moveto, who, w) && moveto != comefrom) {
int wid = neighborId(moveto, w);
int wfrom = neighborId(moveto, comefrom);
int flag = AF_APPROACH;
if(wid >= 0 && wfrom >= 0 && anglestraight(moveto, wfrom, wid)) flag |= AF_HORNS;
if(canAttack(moveto, who, w, w->monst, flag)) return true;
}
if(used_impact && !isMultitile(w) && isNeighbor(w, moveto))
return true;
if(isNeighbor(w, comefrom) && comefrom == moveto && killed) {
int d1 = neighborId(comefrom, w);
int d2 = neighborId(comefrom, killed);
int di = angledist(comefrom->type, d1, d2);
if(di && items[itOrbSide1-1+di] && canAttack(moveto, who, w, w->monst, AF_SIDE))
return true;
}
if(logical_adjacent(comefrom, who, w) && logical_adjacent(moveto, who, w) && moveto != comefrom)
if(canAttack(moveto, who, w, w->monst, AF_STAB))
return true;
if(who == moPlayer && (killed || moveto != comefrom) && mirror::isKilledByMirror(w)) return true;
if(w->monst == moIvyHead || w->monst == moIvyBranch || isMutantIvy(w))
return isChild(w, killed);
if(isDragon(w->monst) && killed && isDragon(killed->monst) && killed->hitpoints) {
cell *head1 = dragon::findhead(w);
cell *head2 = dragon::findhead(killed);
if(head1 == head2 && dragon::totalhp(head1) ==1) return true;
}
if((w->monst == moPair || isMagneticPole(w->monst)) && killed && w->move(w->mondir) == killed)
return true;
if(w->monst == moKrakenT && killed && killed->monst == moKrakenT && killed->hitpoints) {
cell *head1 = w->move(w->mondir);
cell *head2 = killed->move(killed->mondir);
if(head1 == head2 && kraken::totalhp(head1) == 1) return true;
}
return false;
}
EX namespace stalemate {
EX bool isKilled(cell *w) {
for(int f=0; f<isize(moves); f++)
if(moves[f].isKilled(w)) return true;
return false;
};
EX }
EX bool krakensafe(cell *c) {
return items[itOrbFish] || items[itOrbAether] ||
(c->item == itOrbFish && c->wall == waBoat) ||
@@ -149,7 +83,7 @@ EX bool monstersnear(stalemate1& sm) {
if(havewhat&HF_OUTLAW) {
for(cell *c1: gun_targets(c))
if(c1->monst == moOutlaw && !c1->stuntime && !stalemate::isKilled(c1)) {
if(c1->monst == moOutlaw && !c1->stuntime) {
res++; who_kills_me = moOutlaw;
}
}
@@ -166,7 +100,7 @@ EX bool monstersnear(stalemate1& sm) {
if(c3->monst != moWitchFlash)
if(!logical_adjacent(c3, c3->monst, c2) || !logical_adjacent(c2, c3->monst, c))
continue;
if(elec::affected(c3) || stalemate::isKilled(c3)) continue;
if(elec::affected(c3)) continue;
if(c3->stuntime > (sm.who == moPlayer ? 0 : 1)) continue;
// speedwitches can only attack not-fastened monsters,
// others can only attack if the move is not fastened
@@ -174,7 +108,7 @@ EX bool monstersnear(stalemate1& sm) {
if(c3->monst != moWitchSpeed && fast) continue;
// cannot attack if the immediate cell is impassable (except flashwitches)
if(c3->monst != moWitchFlash) {
if(!passable(c2, c3, stalemate::isKilled(c2)?P_MONSTER:0)) continue;
if(!passable(c2, c3, 0)) continue;
if(isPlayerOn(c2) && items[itOrbFire]) continue;
}
// flashwitches cannot attack if it would kill another enemy
@@ -185,7 +119,6 @@ EX bool monstersnear(stalemate1& sm) {
// consider normal monsters
if(c2 &&
isArmedEnemy(c2, sm.who) &&
!stalemate::isKilled(c2) &&
(c2->monst != moLancer || isUnarmed(sm.who) || !logical_adjacent(c, sm.who, c2))) {
eMonster m = c2->monst;
if(elec::affected(c2)) continue;
@@ -267,11 +200,11 @@ EX bool monstersnear2() {
return b;
}
EX bool monstersnear(cell *c, cell *nocount, eMonster who, cell *pushto, cell *comefrom) {
EX bool monstersnear(cell *c, eMonster who, cell *pushto, cell *comefrom) {
if(peace::on) return 0; // you are safe
stalemate1 sm(who, c, nocount, pushto, comefrom);
stalemate1 sm(who, c, pushto, comefrom);
if(who == moPlayer) for(int b=0; b<2; b++) sm.swordlast[b] = sword::pos(multi::cpid, b);
@@ -340,11 +273,6 @@ EX namespace stalemate {
return false;
}
EX bool isKilledDirectlyAt(cell *c) {
for(int i=0; i<isize(moves); i++) if(moves[i].killed == c) return true;
return false;
}
EX bool isPushto(cell *c) {
for(int i=0; i<isize(moves); i++) if(moves[i].pushto == c) return true;
return false;