mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-01-11 18:00:34 +00:00
improved the checkmove.cpp, also works for golems now
This commit is contained in:
parent
2e236be695
commit
63f895974e
20
attack.cpp
20
attack.cpp
@ -1183,19 +1183,19 @@ EX void killThePlayerAt(eMonster m, cell *c, flagtype flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if HDR
|
#if HDR
|
||||||
template<class T> void do_swords(cell *mf, cell *mt, eMonster who, const T& f) {
|
template<class T> void do_swords(movei mi, eMonster who, const T& f) {
|
||||||
for(int bb=0; bb<2; bb++) if(who == moPlayer && sword::orbcount(bb)) {
|
for(int bb=0; bb<2; bb++) if(who == moPlayer && sword::orbcount(bb)) {
|
||||||
cell *sf = sword::pos(mf, sword::dir[multi::cpid], bb);
|
cell *sf = sword::pos(mi.s, sword::dir[multi::cpid], bb);
|
||||||
cell *st = sword::pos(mt, sword::shift(mf, mt, sword::dir[multi::cpid]), bb);
|
cell *st = sword::pos(mi.t, sword::shift(mi, sword::dir[multi::cpid]), bb);
|
||||||
f(st, bb);
|
f(st, bb);
|
||||||
if(sf != st && !isNeighbor(sf,st)) {
|
if(sf != st && !isNeighbor(sf,st)) {
|
||||||
// also attack the in-transit cell
|
// also attack the in-transit cell
|
||||||
if(S3 == 3) {
|
if(S3 == 3) {
|
||||||
forCellEx(sb, sf) if(isNeighbor(sb, st) && sb != mf && sb != mt) f(sb, bb);
|
forCellEx(sb, sf) if(isNeighbor(sb, st) && sb != mi.s && sb != mi.t) f(sb, bb);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
forCellEx(sb, mf) if(isNeighbor(sb, st) && sb != mt) f(sb, bb);
|
forCellEx(sb, mi.s) if(isNeighbor(sb, st) && sb != mi.t) f(sb, bb);
|
||||||
forCellEx(sb, mt) if(isNeighbor(sb, sf) && sb != mf) f(sb, bb);
|
forCellEx(sb, mi.t) if(isNeighbor(sb, sf) && sb != mi.s) f(sb, bb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1204,14 +1204,16 @@ template<class T> void do_swords(cell *mf, cell *mt, eMonster who, const T& f) {
|
|||||||
|
|
||||||
int lastdouble = -3;
|
int lastdouble = -3;
|
||||||
|
|
||||||
EX void stabbingAttack(cell *mf, cell *mt, eMonster who, int bonuskill IS(0)) {
|
EX void stabbingAttack(movei mi, eMonster who, int bonuskill IS(0)) {
|
||||||
int numsh = 0, numflail = 0, numlance = 0, numslash = 0, numbb[2];
|
int numsh = 0, numflail = 0, numlance = 0, numslash = 0, numbb[2];
|
||||||
|
|
||||||
numbb[0] = numbb[1] = 0;
|
numbb[0] = numbb[1] = 0;
|
||||||
|
|
||||||
int backdir = neighborId(mt, mf);
|
cell *mf = mi.s;
|
||||||
|
cell *mt = mi.t;
|
||||||
|
int backdir = mi.rev_dir();
|
||||||
|
|
||||||
do_swords(mf, mt, who, [&] (cell *c, int bb) { if(swordAttack(mt, who, c, bb)) numbb[bb]++, numslash++; });
|
do_swords(mi, who, [&] (cell *c, int bb) { if(swordAttack(mt, who, c, bb)) numbb[bb]++, numslash++; });
|
||||||
|
|
||||||
for(int bb=0; bb<2; bb++) achievement_count("SLASH", numbb[bb], 0);
|
for(int bb=0; bb<2; bb++) achievement_count("SLASH", numbb[bb], 0);
|
||||||
|
|
||||||
|
183
checkmove.cpp
183
checkmove.cpp
@ -39,28 +39,47 @@ EX bool hasSafeOrb(cell *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if HDR
|
#if HDR
|
||||||
struct stalemate1 {
|
struct player_move_info {
|
||||||
eMonster who;
|
movei mi;
|
||||||
cell *moveto;
|
|
||||||
cell *pushto;
|
|
||||||
cell *comefrom;
|
|
||||||
cell *swordlast[2], *swordtransit[2], *swordnext[2];
|
cell *swordlast[2], *swordtransit[2], *swordnext[2];
|
||||||
stalemate1(eMonster w, cell *mt, cell *pt, cell *cf) : who(w), moveto(mt), pushto(pt), comefrom(cf) {}
|
player_move_info(movei mi);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
EX vector<player_move_info> pmi;
|
||||||
|
EX vector<cell*> pushes;
|
||||||
|
|
||||||
|
player_move_info::player_move_info(movei _mi) : mi(_mi) {
|
||||||
|
for(int b=0; b<2; b++) swordlast[b] = sword::pos(multi::cpid, b);
|
||||||
|
|
||||||
|
dynamicval<sword::sworddir> x7(sword::dir[multi::cpid], sword::shift(mi, sword::dir[multi::cpid]));
|
||||||
|
|
||||||
|
for(int b=0; b<2; b++) {
|
||||||
|
swordnext[b] = sword::pos(multi::cpid, b);
|
||||||
|
swordtransit[b] = NULL;
|
||||||
|
if(swordnext[b] && swordnext[b] != swordlast[b] && !isNeighbor(swordlast[b], swordnext[b])) {
|
||||||
|
forCellEx(c2, swordnext[b])
|
||||||
|
if(c2 != mi.t && c2 != mi.s && isNeighbor(c2, S3==3 ? swordlast[b] : mi.t))
|
||||||
|
swordtransit[b] = c2;
|
||||||
|
if(S3 == 4)
|
||||||
|
forCellEx(c2, mi.s)
|
||||||
|
if(c2 != mi.s && isNeighbor(c2, swordlast[b]))
|
||||||
|
swordtransit[b] = c2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
EX bool krakensafe(cell *c) {
|
EX bool krakensafe(cell *c) {
|
||||||
return items[itOrbFish] || items[itOrbAether] ||
|
return items[itOrbFish] || items[itOrbAether] ||
|
||||||
(c->item == itOrbFish && c->wall == waBoat) ||
|
(c->item == itOrbFish && c->wall == waBoat) ||
|
||||||
(c->item == itOrbAether && c->wall == waBoat);
|
(c->item == itOrbAether && c->wall == waBoat);
|
||||||
}
|
}
|
||||||
|
|
||||||
EX bool monstersnear(stalemate1& sm) {
|
EX bool monstersnear(cell *c, eMonster who) {
|
||||||
|
|
||||||
cell *c = sm.moveto;
|
|
||||||
bool eaten = false;
|
bool eaten = false;
|
||||||
|
|
||||||
if(hardcore && sm.who == moPlayer) return false;
|
if(hardcore && who == moPlayer) return false;
|
||||||
|
|
||||||
int res = 0;
|
int res = 0;
|
||||||
bool fast = false;
|
bool fast = false;
|
||||||
@ -76,9 +95,9 @@ EX bool monstersnear(stalemate1& sm) {
|
|||||||
who_kills_me = moCrusher; res++;
|
who_kills_me = moCrusher; res++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sm.who == moPlayer || items[itOrbEmpathy]) {
|
if(who == moPlayer || items[itOrbEmpathy]) {
|
||||||
fast = (items[itOrbSpeed] && (items[itOrbSpeed] & 1));
|
fast = (items[itOrbSpeed] && (items[itOrbSpeed] & 1));
|
||||||
if(sm.who == moPlayer && sm.moveto->item == itOrbSpeed && !items[itOrbSpeed]) fast = true;
|
if(who == moPlayer && c->item == itOrbSpeed && !items[itOrbSpeed]) fast = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(havewhat&HF_OUTLAW) {
|
if(havewhat&HF_OUTLAW) {
|
||||||
@ -103,7 +122,7 @@ EX bool monstersnear(stalemate1& sm) {
|
|||||||
if(!logical_adjacent(c3, c3->monst, c2) || !logical_adjacent(c2, c3->monst, c) || (c3->monst == moWitchSpeed && c2->land != laPower))
|
if(!logical_adjacent(c3, c3->monst, c2) || !logical_adjacent(c2, c3->monst, c) || (c3->monst == moWitchSpeed && c2->land != laPower))
|
||||||
continue;
|
continue;
|
||||||
if(elec::affected(c3)) continue;
|
if(elec::affected(c3)) continue;
|
||||||
if(c3->stuntime > (sm.who == moPlayer ? 0 : 1)) continue;
|
if(c3->stuntime > (who == moPlayer ? 0 : 1)) continue;
|
||||||
// speedwitches can only attack not-fastened monsters,
|
// speedwitches can only attack not-fastened monsters,
|
||||||
// others can only attack if the move is not fastened
|
// others can only attack if the move is not fastened
|
||||||
if(c3->monst == moWitchSpeed && items[itOrbSpeed]) continue;
|
if(c3->monst == moWitchSpeed && items[itOrbSpeed]) continue;
|
||||||
@ -120,19 +139,19 @@ EX bool monstersnear(stalemate1& sm) {
|
|||||||
|
|
||||||
// consider normal monsters
|
// consider normal monsters
|
||||||
if(c2 &&
|
if(c2 &&
|
||||||
isArmedEnemy(c2, sm.who) &&
|
isArmedEnemy(c2, who) &&
|
||||||
(c2->monst != moLancer || isUnarmed(sm.who) || !logical_adjacent(c, sm.who, c2))) {
|
(c2->monst != moLancer || isUnarmed(who) || !logical_adjacent(c, who, c2))) {
|
||||||
eMonster m = c2->monst;
|
eMonster m = c2->monst;
|
||||||
if(elec::affected(c2)) continue;
|
if(elec::affected(c2)) continue;
|
||||||
if(fast && c2->monst != moWitchSpeed) continue;
|
if(fast && c2->monst != moWitchSpeed) continue;
|
||||||
// Krakens just destroy boats
|
// Krakens just destroy boats
|
||||||
if(c2->monst == moKrakenT && onboat(sm)) {
|
if(c2->monst == moKrakenT && c->wall == waBoat) {
|
||||||
if(krakensafe(c)) continue;
|
if(krakensafe(c)) continue;
|
||||||
else if(warningprotection(XLAT("This move appears dangerous -- are you sure?")) && res == 0) m = moWarning;
|
else if(warningprotection(XLAT("This move appears dangerous -- are you sure?")) && res == 0) m = moWarning;
|
||||||
else continue;
|
else continue;
|
||||||
}
|
}
|
||||||
// they cannot attack through vines
|
// they cannot attack through vines
|
||||||
if(!canAttack(c2, c2->monst, c, sm.who, AF_NEXTTURN)) continue;
|
if(!canAttack(c2, c2->monst, c, who, AF_NEXTTURN)) continue;
|
||||||
if(c2->monst == moWorm || c2->monst == moTentacle || c2->monst == moHexSnake) {
|
if(c2->monst == moWorm || c2->monst == moTentacle || c2->monst == moHexSnake) {
|
||||||
if(passable_for(c2->monst, c, c2, 0))
|
if(passable_for(c2->monst, c, c2, 0))
|
||||||
eaten = true;
|
eaten = true;
|
||||||
@ -142,18 +161,16 @@ EX bool monstersnear(stalemate1& sm) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sm.who == moPlayer && res && (markOrb2(itOrbShield) || markOrb2(itOrbShell)) && !eaten)
|
if(who == moPlayer && res && (markOrb2(itOrbShield) || markOrb2(itOrbShell)) && !eaten)
|
||||||
res = 0;
|
res = 0;
|
||||||
|
|
||||||
if(sm.who == moPlayer && res && markOrb2(itOrbDomination) && c->monst)
|
if(who == moPlayer && res && markOrb2(itOrbDomination) && c->monst)
|
||||||
res = 0;
|
res = 0;
|
||||||
|
|
||||||
return !!res;
|
return !!res;
|
||||||
}
|
}
|
||||||
|
|
||||||
EX bool monstersnear2();
|
EX bool monstersnear_aux() {
|
||||||
|
|
||||||
EX bool monstersnear2() {
|
|
||||||
changes.value_set(passive_switch, (gold() & 1) ? moSwitch1 : moSwitch2);
|
changes.value_set(passive_switch, (gold() & 1) ? moSwitch1 : moSwitch2);
|
||||||
multi::cpid++;
|
multi::cpid++;
|
||||||
bool b = false;
|
bool b = false;
|
||||||
@ -162,22 +179,33 @@ EX bool monstersnear2() {
|
|||||||
if(multi::cpid == multi::players || multi::players == 1 || multi::checkonly) {
|
if(multi::cpid == multi::players || multi::players == 1 || multi::checkonly) {
|
||||||
|
|
||||||
if(shmup::delayed_safety) return false;
|
if(shmup::delayed_safety) return false;
|
||||||
dynamicval<eMonster> sw(passive_switch, passive_switch);
|
|
||||||
|
for(int i=0; i<isize(pmi); i++)
|
||||||
for(int i=0; i<isize(stalemate::moves); i++)
|
for(int j=0; j<isize(pmi); j++) if(i != j) {
|
||||||
for(int j=0; j<isize(stalemate::moves); j++) if(i != j) {
|
if(swordConflict(pmi[i], pmi[j])) {
|
||||||
if(swordConflict(stalemate::moves[i], stalemate::moves[j])) {
|
|
||||||
b = true;
|
b = true;
|
||||||
who_kills_me = moEnergySword;
|
who_kills_me = moEnergySword;
|
||||||
}
|
}
|
||||||
if(multi::player[i].at == multi::player[j].at)
|
if(pmi[i].mi.t == pmi[j].mi.t)
|
||||||
{ b = true; who_kills_me = moFireball; }
|
{ b = true; who_kills_me = moFireball; }
|
||||||
if(celldistance(multi::player[i].at, multi::player[j].at) > 8)
|
if(celldistance(pmi[i].mi.t, pmi[j].mi.t) > 8)
|
||||||
{ b = true; who_kills_me = moAirball; }
|
{ b = true; who_kills_me = moAirball; }
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0; !b && i<isize(stalemate::moves); i++)
|
for(auto& pushto: pushes)
|
||||||
b = monstersnear(stalemate::moves[i]);
|
for(auto& mi: pmi)
|
||||||
|
if(pushto == mi.mi.t) {
|
||||||
|
b = true; who_kills_me = moTongue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0; i<isize(pushes); i++)
|
||||||
|
for(int j=0; j<i; j++)
|
||||||
|
if(pushes[i] == pushes[j]) {
|
||||||
|
b = true; who_kills_me = moCrushball;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0; !b && i<isize(pmi); i++)
|
||||||
|
b = monstersnear(pmi[i].mi.t, moPlayer);
|
||||||
}
|
}
|
||||||
else b = !multimove();
|
else b = !multimove();
|
||||||
multi::cpid--;
|
multi::cpid--;
|
||||||
@ -185,94 +213,17 @@ EX bool monstersnear2() {
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
EX bool monstersnear(cell *c, eMonster who, cell *pushto, cell *comefrom) {
|
/** like monstersnear but add the potential moves of other players into account */
|
||||||
|
EX bool monstersnear_add_pmi(player_move_info pmi0) {
|
||||||
if(peace::on) return 0; // you are safe
|
pmi.push_back(pmi0);
|
||||||
|
bool b = monstersnear_aux();
|
||||||
stalemate1 sm(who, c, pushto, comefrom);
|
pmi.pop_back();
|
||||||
|
|
||||||
if(who == moPlayer) for(int b=0; b<2; b++) sm.swordlast[b] = sword::pos(multi::cpid, b);
|
|
||||||
|
|
||||||
cell *none = NULL;
|
|
||||||
cell **wcw = &cwt.at;
|
|
||||||
if(who != moPlayer) wcw = &none;
|
|
||||||
else if(multi::players > 1) wcw = &multi::player[multi::cpid].at;
|
|
||||||
|
|
||||||
dynamicval<cell*> x5(*wcw, c);
|
|
||||||
dynamicval<bool> x6(stalemate::nextturn, true);
|
|
||||||
dynamicval<sword::sworddir> x7(sword::dir[multi::cpid],
|
|
||||||
who == moPlayer ? sword::shift(comefrom, c, sword::dir[multi::cpid]) :
|
|
||||||
sword::dir[multi::cpid]);
|
|
||||||
|
|
||||||
for(int b=0; b<2; b++) {
|
|
||||||
if(who == moPlayer) {
|
|
||||||
sm.swordnext[b] = sword::pos(multi::cpid, b);
|
|
||||||
sm.swordtransit[b] = NULL;
|
|
||||||
if(sm.swordnext[b] && sm.swordnext[b] != sm.swordlast[b] && !isNeighbor(sm.swordlast[b], sm.swordnext[b])) {
|
|
||||||
forCellEx(c2, sm.swordnext[b])
|
|
||||||
if(c2 != c && c2 != comefrom && isNeighbor(c2, S3==3 ? sm.swordlast[b] : *wcw))
|
|
||||||
sm.swordtransit[b] = c2;
|
|
||||||
if(S3 == 4)
|
|
||||||
forCellEx(c2, c)
|
|
||||||
if(c2 != comefrom && isNeighbor(c2, sm.swordlast[b]))
|
|
||||||
sm.swordtransit[b] = c2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sm.swordnext[b] = sm.swordtransit[b] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stalemate::moves.push_back(sm);
|
|
||||||
|
|
||||||
// dynamicval<eMonster> x7(stalemate::who, who);
|
|
||||||
|
|
||||||
bool b;
|
|
||||||
if(who == moPlayer && c->wall == waBigStatue) {
|
|
||||||
eWall w = comefrom->wall;
|
|
||||||
c->wall = waNone;
|
|
||||||
if(doesnotFall(comefrom)) comefrom->wall = waBigStatue;
|
|
||||||
b = monstersnear2();
|
|
||||||
comefrom->wall = w;
|
|
||||||
c->wall = waBigStatue;
|
|
||||||
}
|
|
||||||
else if(who == moPlayer && isPushable(c->wall)) {
|
|
||||||
eWall w = c->wall;
|
|
||||||
c->wall = waNone;
|
|
||||||
b = monstersnear2();
|
|
||||||
c->wall = w;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
b = monstersnear2();
|
|
||||||
}
|
|
||||||
stalemate::moves.pop_back();
|
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
EX namespace stalemate {
|
|
||||||
EX vector<stalemate1> moves;
|
|
||||||
EX bool nextturn;
|
|
||||||
|
|
||||||
EX bool isMoveto(cell *c) {
|
|
||||||
for(int i=0; i<isize(moves); i++) if(moves[i].moveto == 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;
|
|
||||||
}
|
|
||||||
EX }
|
|
||||||
|
|
||||||
EX bool onboat(stalemate1& sm) {
|
|
||||||
cell *c = sm.moveto;
|
|
||||||
cell *cf = sm.comefrom;
|
|
||||||
return (c->wall == waBoat) || (cf->wall == waBoat && c->wall == waSea);
|
|
||||||
}
|
|
||||||
|
|
||||||
EX bool multimove() {
|
EX bool multimove() {
|
||||||
if(multi::cpid == 0) lastkills = tkills();
|
if(multi::cpid == 0) lastkills = tkills();
|
||||||
if(!multi::playerActive(multi::cpid)) return !monstersnear2();
|
if(!multi::playerActive(multi::cpid)) return !monstersnear_aux();
|
||||||
cellwalker bcwt = cwt;
|
cellwalker bcwt = cwt;
|
||||||
cwt = multi::player[multi::cpid];
|
cwt = multi::player[multi::cpid];
|
||||||
bool b = movepcto(multi::whereto[multi::cpid]);
|
bool b = movepcto(multi::whereto[multi::cpid]);
|
||||||
@ -293,11 +244,11 @@ EX namespace multi {
|
|||||||
EX bool aftermove;
|
EX bool aftermove;
|
||||||
EX }
|
EX }
|
||||||
|
|
||||||
EX bool swordConflict(const stalemate1& sm1, const stalemate1& sm2) {
|
EX bool swordConflict(const player_move_info& sm1, const player_move_info& sm2) {
|
||||||
if(items[itOrbSword] || items[itOrbSword2])
|
if(items[itOrbSword] || items[itOrbSword2])
|
||||||
for(int b=0; b<2; b++)
|
for(int b=0; b<2; b++)
|
||||||
if(sm1.comefrom == sm2.swordlast[b] || sm1.comefrom == sm2.swordtransit[b] || sm1.comefrom == sm2.swordnext[b])
|
if(sm1.mi.s == sm2.swordlast[b] || sm1.mi.s == sm2.swordtransit[b] || sm1.mi.s == sm2.swordnext[b])
|
||||||
if(sm1.moveto == sm2.swordlast[b] || sm1.moveto == sm2.swordtransit[b] || sm1.moveto == sm2.swordnext[b])
|
if(sm1.mi.t == sm2.swordlast[b] || sm1.mi.t == sm2.swordtransit[b] || sm1.mi.t == sm2.swordnext[b])
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
11
complex.cpp
11
complex.cpp
@ -2867,10 +2867,13 @@ EX namespace sword {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// from c1 to c2
|
// from c1 to c2
|
||||||
EX sworddir shift(cell *c1, cell *c2, sworddir d) {
|
EX sworddir shift(movei mi, sworddir d) {
|
||||||
if(!c1 || !c2) return d;
|
cell *c1 = mi.s;
|
||||||
int s1 = neighborId(c1, c2);
|
cell *c2 = mi.t;
|
||||||
int s2 = neighborId(c2, c1);
|
if(!mi.proper()) return d;
|
||||||
|
int s1 = mi.d;
|
||||||
|
int s2 = mi.rev_dir();
|
||||||
|
neighborId(c2, c1);
|
||||||
if(s1 < 0 || s2 < 0) return d;
|
if(s1 < 0 || s2 < 0) return d;
|
||||||
if(SWORDDIM == 2) {
|
if(SWORDDIM == 2) {
|
||||||
int sub = (hybri) ? 2 : 0;
|
int sub = (hybri) ? 2 : 0;
|
||||||
|
2
game.cpp
2
game.cpp
@ -182,7 +182,7 @@ EX bool activateRecall() {
|
|||||||
|
|
||||||
killFriendlyIvy();
|
killFriendlyIvy();
|
||||||
movecost(cwt.at, recallCell.at, 3);
|
movecost(cwt.at, recallCell.at, 3);
|
||||||
playerMoveEffects(cwt.at, recallCell.at);
|
playerMoveEffects(movei(cwt.at, recallCell.at, TELEPORT));
|
||||||
mirror::destroyAll();
|
mirror::destroyAll();
|
||||||
|
|
||||||
sword::reset();
|
sword::reset();
|
||||||
|
@ -313,6 +313,8 @@ EX void dropGreenStone(cell *c) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(items[itGreenStone] && c->item == itNone) {
|
if(items[itGreenStone] && c->item == itNone) {
|
||||||
|
changes.ccell(c);
|
||||||
|
changes.value_keep(items[itGreenStone]);
|
||||||
items[itGreenStone]--;
|
items[itGreenStone]--;
|
||||||
if(false) {
|
if(false) {
|
||||||
c->item = itNone;
|
c->item = itNone;
|
||||||
|
@ -459,6 +459,7 @@ constexpr int FALL = 98;
|
|||||||
constexpr int NO_SPACE = 97;
|
constexpr int NO_SPACE = 97;
|
||||||
constexpr int TELEPORT = 96;
|
constexpr int TELEPORT = 96;
|
||||||
constexpr int JUMP = 95;
|
constexpr int JUMP = 95;
|
||||||
|
constexpr int STAY = 94;
|
||||||
|
|
||||||
namespace whirlwind { cell *jumpDestination(cell*); }
|
namespace whirlwind { cell *jumpDestination(cell*); }
|
||||||
|
|
||||||
|
@ -108,6 +108,8 @@ EX void moveMonster(const movei& mi) {
|
|||||||
auto& cf = mi.s;
|
auto& cf = mi.s;
|
||||||
auto& ct = mi.t;
|
auto& ct = mi.t;
|
||||||
eMonster m = cf->monst;
|
eMonster m = cf->monst;
|
||||||
|
changes.ccell(cf);
|
||||||
|
changes.ccell(ct);
|
||||||
bool fri = isFriendly(cf);
|
bool fri = isFriendly(cf);
|
||||||
if(isDragon(m)) {
|
if(isDragon(m)) {
|
||||||
printf("called for Dragon\n");
|
printf("called for Dragon\n");
|
||||||
@ -117,6 +119,7 @@ EX void moveMonster(const movei& mi) {
|
|||||||
// the following line is necessary because otherwise plates disappear only inside the sight range
|
// the following line is necessary because otherwise plates disappear only inside the sight range
|
||||||
if(cellUnstable(cf) && !ignoresPlates(m)) {
|
if(cellUnstable(cf) && !ignoresPlates(m)) {
|
||||||
fallingFloorAnimation(cf);
|
fallingFloorAnimation(cf);
|
||||||
|
changes.ccell(cf);
|
||||||
cf->wall = waChasm;
|
cf->wall = waChasm;
|
||||||
}
|
}
|
||||||
moveEffect(mi, m);
|
moveEffect(mi, m);
|
||||||
@ -124,6 +127,7 @@ EX void moveMonster(const movei& mi) {
|
|||||||
(m == moShark || m == moCShark || m == moGreaterShark))
|
(m == moShark || m == moCShark || m == moGreaterShark))
|
||||||
achievement_gain_once("MOATSHARK");
|
achievement_gain_once("MOATSHARK");
|
||||||
if(m == moTentacleGhost) {
|
if(m == moTentacleGhost) {
|
||||||
|
changes.ccell(cf);
|
||||||
cf->monst = moTentacletail;
|
cf->monst = moTentacletail;
|
||||||
m = moGhost;
|
m = moGhost;
|
||||||
}
|
}
|
||||||
@ -156,10 +160,11 @@ EX void moveMonster(const movei& mi) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fri || isBug(m) || items[itOrbDiscord]) stabbingAttack(cf, ct, m);
|
if(fri || isBug(m) || items[itOrbDiscord]) stabbingAttack(mi, m);
|
||||||
|
|
||||||
if(mi.d == JUMP && m == moVaulter) {
|
if(mi.d == JUMP && m == moVaulter) {
|
||||||
cell *cm = common_neighbor(cf, ct);
|
cell *cm = common_neighbor(cf, ct);
|
||||||
|
changes.ccell(cm);
|
||||||
if(cm->wall == waShrub) cm->wall = waNone;
|
if(cm->wall == waShrub) cm->wall = waNone;
|
||||||
if(cm->wall == waSmallTree) cm->wall = waNone;
|
if(cm->wall == waSmallTree) cm->wall = waNone;
|
||||||
if(cm->wall == waBigTree) cm->wall = waSmallTree;
|
if(cm->wall == waBigTree) cm->wall = waSmallTree;
|
||||||
@ -1518,7 +1523,10 @@ EX int stayvalue(eMonster m, cell *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** for an ally m at c, evaluate moving to c2 */
|
/** for an ally m at c, evaluate moving to c2 */
|
||||||
EX int movevalue(eMonster m, cell *c, cell *c2, flagtype flags) {
|
EX int movevalue(eMonster m, cell *c, int dir, flagtype flags) {
|
||||||
|
|
||||||
|
auto mi = movei(c, dir);
|
||||||
|
auto& c2 = mi.t;
|
||||||
int val = 0;
|
int val = 0;
|
||||||
|
|
||||||
if(isPlayerOn(c2)) val = -3000;
|
if(isPlayerOn(c2)) val = -3000;
|
||||||
@ -1537,7 +1545,6 @@ EX int movevalue(eMonster m, cell *c, cell *c2, flagtype flags) {
|
|||||||
isInactiveEnemy(c2,m) ? 1000 :
|
isInactiveEnemy(c2,m) ? 1000 :
|
||||||
-500;
|
-500;
|
||||||
|
|
||||||
else if(monstersnear(c2, m, NULL, c)) val = 50; // linked with mouse suicide!
|
|
||||||
else if(passable_for(m, c2, c, 0)) {
|
else if(passable_for(m, c2, c, 0)) {
|
||||||
#if CAP_COMPLEX2
|
#if CAP_COMPLEX2
|
||||||
if(mine::marked_mine(c2) && !ignoresPlates(m))
|
if(mine::marked_mine(c2) && !ignoresPlates(m))
|
||||||
@ -1545,6 +1552,12 @@ EX int movevalue(eMonster m, cell *c, cell *c2, flagtype flags) {
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
val = 4000;
|
val = 4000;
|
||||||
|
|
||||||
|
changes.init(true);
|
||||||
|
moveMonster(mi);
|
||||||
|
bool b = monstersnear(mi.t, m);
|
||||||
|
changes.rollback();
|
||||||
|
if(b) val = 50;
|
||||||
}
|
}
|
||||||
else if(passable_for(m, c2, c, P_DEADLY)) val = -1100;
|
else if(passable_for(m, c2, c, P_DEADLY)) val = -1100;
|
||||||
else val = -1750;
|
else val = -1750;
|
||||||
@ -1636,8 +1649,7 @@ EX void movegolems(flagtype flags) {
|
|||||||
|
|
||||||
DEBB(DF_TURN, ("moveval"));
|
DEBB(DF_TURN, ("moveval"));
|
||||||
for(int k=0; k<c->type; k++) if(c->move(k)) {
|
for(int k=0; k<c->type; k++) if(c->move(k)) {
|
||||||
cell *c2 = c->move(k);
|
int val = movevalue(m, c, k, flags);
|
||||||
int val = movevalue(m, c, c2, flags);
|
|
||||||
|
|
||||||
if(val > bestv) bestv = val, bdirs.clear();
|
if(val > bestv) bestv = val, bdirs.clear();
|
||||||
if(val == bestv) bdirs.push_back(k);
|
if(val == bestv) bdirs.push_back(k);
|
||||||
@ -1646,7 +1658,7 @@ EX void movegolems(flagtype flags) {
|
|||||||
if(m == moTameBomberbird) {
|
if(m == moTameBomberbird) {
|
||||||
cell *c2 = whirlwind::jumpDestination(c);
|
cell *c2 = whirlwind::jumpDestination(c);
|
||||||
if(c2 && !c2->monst) {
|
if(c2 && !c2->monst) {
|
||||||
int val = movevalue(m, c, c2, flags);
|
int val = movevalue(m, c, STRONGWIND, flags);
|
||||||
// printf("val = %d bestv = %d\n",
|
// printf("val = %d bestv = %d\n",
|
||||||
if(val > bestv) bestv = val, bdirs.clear();
|
if(val > bestv) bestv = val, bdirs.clear();
|
||||||
if(val == bestv) bdirs.push_back(STRONGWIND);
|
if(val == bestv) bdirs.push_back(STRONGWIND);
|
||||||
|
23
orbs.cpp
23
orbs.cpp
@ -567,8 +567,8 @@ EX void teleportTo(cell *dest) {
|
|||||||
if(b) {
|
if(b) {
|
||||||
killFriendlyIvy();
|
killFriendlyIvy();
|
||||||
drainOrb(itOrbTeleport);
|
drainOrb(itOrbTeleport);
|
||||||
movecost(cwt.at, dest, 3);
|
movecost(cwt.at, dest, 3);
|
||||||
playerMoveEffects(cwt.at, dest);
|
playerMoveEffects(movei(cwt.at, dest, TELEPORT));
|
||||||
afterplayermoved();
|
afterplayermoved();
|
||||||
bfs();
|
bfs();
|
||||||
}
|
}
|
||||||
@ -580,7 +580,7 @@ EX void teleportTo(cell *dest) {
|
|||||||
killFriendlyIvy();
|
killFriendlyIvy();
|
||||||
cell *from = cwt.at;
|
cell *from = cwt.at;
|
||||||
movecost(from, dest, 1);
|
movecost(from, dest, 1);
|
||||||
playerMoveEffects(cwt.at, dest);
|
playerMoveEffects(movei(cwt.at, dest, TELEPORT));
|
||||||
current_display->which_copy = unshift(ggmatrix(dest));
|
current_display->which_copy = unshift(ggmatrix(dest));
|
||||||
cwt.at = dest; cwt.spin = hrand(dest->type); flipplayer = !!(hrand(2));
|
cwt.at = dest; cwt.spin = hrand(dest->type); flipplayer = !!(hrand(2));
|
||||||
drainOrb(itOrbTeleport);
|
drainOrb(itOrbTeleport);
|
||||||
@ -638,8 +638,9 @@ EX bool jumpTo(orbAction a, cell *dest, eItem byWhat, int bonuskill IS(0), eMons
|
|||||||
}
|
}
|
||||||
|
|
||||||
sword::reset();
|
sword::reset();
|
||||||
stabbingAttack(c1, dest, moPlayer, bonuskill);
|
auto mi = movei(c1, dest, JUMP);
|
||||||
playerMoveEffects(c1, dest);
|
stabbingAttack(mi, moPlayer, bonuskill);
|
||||||
|
playerMoveEffects(mi);
|
||||||
|
|
||||||
if(itemclass(byWhat) == IC_ORB)
|
if(itemclass(byWhat) == IC_ORB)
|
||||||
apply_impact(dest);
|
apply_impact(dest);
|
||||||
@ -658,7 +659,7 @@ EX bool jumpTo(orbAction a, cell *dest, eItem byWhat, int bonuskill IS(0), eMons
|
|||||||
|
|
||||||
mirror::destroyAll();
|
mirror::destroyAll();
|
||||||
|
|
||||||
if(monstersnearO(a, dest, moPlayer, NULL, c1)) {
|
if(monstersnearO(a, dest)) {
|
||||||
changes.rollback();
|
changes.rollback();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -939,7 +940,7 @@ bool gun_attack(orbAction a, cell *dest) {
|
|||||||
attackMonster(dest, AF_GUN, moNone);
|
attackMonster(dest, AF_GUN, moNone);
|
||||||
apply_impact(dest);
|
apply_impact(dest);
|
||||||
|
|
||||||
if(monstersnearO(a, cwt.at, moPlayer, NULL, cwt.at)) {
|
if(monstersnearO(a, cwt.at)) {
|
||||||
changes.rollback();
|
changes.rollback();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1068,13 +1069,13 @@ void useOrbOfDragon(cell *c) {
|
|||||||
checkmoveO();
|
checkmoveO();
|
||||||
}
|
}
|
||||||
|
|
||||||
EX bool monstersnearO(orbAction a, cell *c, eMonster who, cell *pushto, cell *comefrom) {
|
EX bool monstersnearO(orbAction a, cell *c) {
|
||||||
// printf("[a = %d] ", a);
|
// printf("[a = %d] ", a);
|
||||||
if(shmup::on) return false;
|
if(shmup::on) return false;
|
||||||
if(a == roCheck && multi::players > 1)
|
if(a == roCheck && multi::players > 1)
|
||||||
return true;
|
return true;
|
||||||
else if(a == roMultiCheck) return false;
|
else if(a == roMultiCheck) return false;
|
||||||
else return monstersnear(c, who, pushto, comefrom);
|
else return monstersnear(c, moPlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
EX bool isCheck(orbAction a) { return a == roCheck || a == roMultiCheck; }
|
EX bool isCheck(orbAction a) { return a == roCheck || a == roMultiCheck; }
|
||||||
@ -1241,12 +1242,12 @@ EX eItem targetRangedOrb(cell *c, orbAction a) {
|
|||||||
|
|
||||||
if(c->monst) {
|
if(c->monst) {
|
||||||
if(!canAttack(cf, moFriendlyIvy, c, c->monst, 0)) continue;
|
if(!canAttack(cf, moFriendlyIvy, c, c->monst, 0)) continue;
|
||||||
if(monstersnear(cwt.at, moPlayer, NULL, cwt.at)) continue;
|
if(monstersnear(cwt.at, moPlayer)) continue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(!passable(c, cf, P_ISPLAYER | P_MONSTER)) continue;
|
if(!passable(c, cf, P_ISPLAYER | P_MONSTER)) continue;
|
||||||
if(strictlyAgainstGravity(c, cf, false, MF_IVY)) continue;
|
if(strictlyAgainstGravity(c, cf, false, MF_IVY)) continue;
|
||||||
if(monstersnear(cwt.at, moPlayer, c, cwt.at)) continue;
|
if(monstersnear(cwt.at, moPlayer)) continue;
|
||||||
}
|
}
|
||||||
dirs.push_back(d);
|
dirs.push_back(d);
|
||||||
}
|
}
|
||||||
|
93
pcmove.cpp
93
pcmove.cpp
@ -357,8 +357,8 @@ bool pcmove::swing() {
|
|||||||
sideAttack(cwt.at, d, moPlayer, 0);
|
sideAttack(cwt.at, d, moPlayer, 0);
|
||||||
|
|
||||||
mirror::act(origd, mirror::SPINMULTI | mirror::ATTACK);
|
mirror::act(origd, mirror::SPINMULTI | mirror::ATTACK);
|
||||||
|
|
||||||
if(monstersnear(cwt.at, moPlayer, nullptr, cwt.at)) {
|
if(monstersnear_add_pmi(movei(cwt.at, STAY))) {
|
||||||
if(vmsg())
|
if(vmsg())
|
||||||
wouldkill("You would be killed by %the1!");
|
wouldkill("You would be killed by %the1!");
|
||||||
return false;
|
return false;
|
||||||
@ -510,6 +510,11 @@ struct changes_t {
|
|||||||
void at_rollback(reaction_t act) {
|
void at_rollback(reaction_t act) {
|
||||||
if(on) rollbacks.emplace_back(act);
|
if(on) rollbacks.emplace_back(act);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void push_push(cell *tgt) {
|
||||||
|
pushes.push_back(tgt);
|
||||||
|
rollbacks.push_back([] { pushes.pop_back(); });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -601,7 +606,7 @@ bool pcmove::actual_move() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(items[itOrbDomination] > ORBBASE && isMountable(c2->monst) && !monstersnear2() && fmsMove) {
|
if(items[itOrbDomination] > ORBBASE && isMountable(c2->monst) && fmsMove) {
|
||||||
if(checkonly) { nextmovetype = lmMove; return true; }
|
if(checkonly) { nextmovetype = lmMove; return true; }
|
||||||
if(!isMountable(cwt.at->monst)) dragon::target = NULL;
|
if(!isMountable(cwt.at->monst)) dragon::target = NULL;
|
||||||
movecost(cwt.at, c2, 3);
|
movecost(cwt.at, c2, 3);
|
||||||
@ -629,6 +634,7 @@ bool pcmove::actual_move() {
|
|||||||
addMessage(XLAT("You push %the1.", c2->wall));
|
addMessage(XLAT("You push %the1.", c2->wall));
|
||||||
lastmovetype = lmPush; lastmove = cwt.at;
|
lastmovetype = lmPush; lastmove = cwt.at;
|
||||||
pushThumper(mip);
|
pushThumper(mip);
|
||||||
|
changes.push_push(mip.t);
|
||||||
return perform_actual_move();
|
return perform_actual_move();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -646,8 +652,6 @@ bool pcmove::actual_move() {
|
|||||||
|
|
||||||
if(!c2->monst && cwt.at->wall == waBoat && cwt.at->item != itOrbYendor && boatGoesThrough(c2) && markOrb(itOrbWater) && !nonAdjacentPlayer(c2, cwt.at) && fmsMove) {
|
if(!c2->monst && cwt.at->wall == waBoat && cwt.at->item != itOrbYendor && boatGoesThrough(c2) && markOrb(itOrbWater) && !nonAdjacentPlayer(c2, cwt.at) && fmsMove) {
|
||||||
|
|
||||||
if(havePushConflict(cwt.at, checkonly)) return false;
|
|
||||||
|
|
||||||
if(c2->item && !cwt.at->item) moveItem(c2, cwt.at, false), boatmove = true;
|
if(c2->item && !cwt.at->item) moveItem(c2, cwt.at, false), boatmove = true;
|
||||||
placeWater(c2, cwt.at);
|
placeWater(c2, cwt.at);
|
||||||
moveBoat(mi);
|
moveBoat(mi);
|
||||||
@ -663,7 +667,6 @@ bool pcmove::actual_move() {
|
|||||||
bool pcmove::boat_move() {
|
bool pcmove::boat_move() {
|
||||||
|
|
||||||
cell *& c2 = mi.t;
|
cell *& c2 = mi.t;
|
||||||
if(havePushConflict(cwt.at, checkonly)) return false;
|
|
||||||
|
|
||||||
if(againstWind(c2, cwt.at)) {
|
if(againstWind(c2, cwt.at)) {
|
||||||
if(vmsg()) addMessage(XLAT(airdist(c2) < 3 ? "The Air Elemental blows you away!" : "You cannot go against the wind!"));
|
if(vmsg()) addMessage(XLAT(airdist(c2) < 3 ? "The Air Elemental blows you away!" : "You cannot go against the wind!"));
|
||||||
@ -744,8 +747,6 @@ bool pcmove::after_escape() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(havePushConflict(cwt.at, checkonly)) return false;
|
|
||||||
|
|
||||||
changes.ccell(c2);
|
changes.ccell(c2);
|
||||||
changes.ccell(cwt.at);
|
changes.ccell(cwt.at);
|
||||||
|
|
||||||
@ -849,7 +850,7 @@ bool pcmove::move_if_okay() {
|
|||||||
|
|
||||||
if(switchplace_prevent(cwt.at, c2, checkonly))
|
if(switchplace_prevent(cwt.at, c2, checkonly))
|
||||||
return false;
|
return false;
|
||||||
if(!checkonly && warningprotection_hit(do_we_stab_a_friend(cwt.at, c2, moPlayer)))
|
if(!checkonly && warningprotection_hit(do_we_stab_a_friend(mi, moPlayer)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
nextmovetype = lmMove;
|
nextmovetype = lmMove;
|
||||||
@ -899,7 +900,7 @@ bool pcmove::attack() {
|
|||||||
|
|
||||||
if(!ca) {
|
if(!ca) {
|
||||||
if(forcedmovetype == fmAttack) {
|
if(forcedmovetype == fmAttack) {
|
||||||
if(monstersnear(cwt.at,moPlayer,NULL,cwt.at)) {
|
if(monstersnear_add_pmi(movei(cwt.at, STAY))) {
|
||||||
if(vmsg()) wouldkill("%The1 would get you!");
|
if(vmsg()) wouldkill("%The1 would get you!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -922,10 +923,9 @@ bool pcmove::attack() {
|
|||||||
else
|
else
|
||||||
mip.t = c2;
|
mip.t = c2;
|
||||||
if(mip.t) changes.ccell(mip.t);
|
if(mip.t) changes.ccell(mip.t);
|
||||||
|
changes.push_push(mip.t);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(havePushConflict(mip.t, checkonly)) return false;
|
|
||||||
|
|
||||||
if(!(isWatery(cwt.at) && c2->monst == moWaterElemental) && checkNeedMove(checkonly, true))
|
if(!(isWatery(cwt.at) && c2->monst == moWaterElemental) && checkNeedMove(checkonly, true))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -982,7 +982,7 @@ bool pcmove::attack() {
|
|||||||
lastmovetype = lmAttack; lastmove = c2;
|
lastmovetype = lmAttack; lastmove = c2;
|
||||||
swordAttackStatic();
|
swordAttackStatic();
|
||||||
|
|
||||||
if(monstersnear(cwt.at, moPlayer, nullptr, cwt.at)) {
|
if(monstersnear_add_pmi(movei(cwt.at, STAY))) {
|
||||||
if(vmsg()) wouldkill("You would be killed by %the1!");
|
if(vmsg()) wouldkill("You would be killed by %the1!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1090,18 +1090,18 @@ bool pcmove::perform_move_or_jump() {
|
|||||||
lastmovetype = lmMove; lastmove = cwt.at;
|
lastmovetype = lmMove; lastmove = cwt.at;
|
||||||
apply_chaos();
|
apply_chaos();
|
||||||
|
|
||||||
stabbingAttack(cwt.at, mi.t, moPlayer);
|
stabbingAttack(mi, moPlayer);
|
||||||
cell *c1 = cwt.at;
|
|
||||||
changes.value_keep(cwt);
|
changes.value_keep(cwt);
|
||||||
cwt += wstep;
|
cwt += wstep;
|
||||||
|
|
||||||
mirror::act(origd, mirror::SPINMULTI | mirror::ATTACK | mirror::GO);
|
mirror::act(origd, mirror::SPINMULTI | mirror::ATTACK | mirror::GO);
|
||||||
|
|
||||||
playerMoveEffects(c1, mi.t);
|
auto pmi = player_move_info(mi);
|
||||||
|
playerMoveEffects(mi);
|
||||||
|
|
||||||
if(mi.t->monst == moFriendlyIvy) changes.ccell(mi.t), mi.t->monst = moNone;
|
if(mi.t->monst == moFriendlyIvy) changes.ccell(mi.t), mi.t->monst = moNone;
|
||||||
|
|
||||||
if(monstersnear(cwt.at, moPlayer, nullptr, c1)) {
|
if(monstersnear_add_pmi(pmi)) {
|
||||||
if(vmsg()) wouldkill("%The1 would kill you there!");
|
if(vmsg()) wouldkill("%The1 would kill you there!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1135,19 +1135,21 @@ bool pcmove::stay() {
|
|||||||
return false;
|
return false;
|
||||||
swordAttackStatic();
|
swordAttackStatic();
|
||||||
nextmovetype = lmSkip;
|
nextmovetype = lmSkip;
|
||||||
if(monstersnear(cwt.at, moPlayer, nullptr, cwt.at)) {
|
|
||||||
|
mi = movei(cwt.at, STAY);
|
||||||
|
if(last_gravity_state && !gravity_state)
|
||||||
|
playerMoveEffects(mi);
|
||||||
|
if(d == -2)
|
||||||
|
dropGreenStone(cwt.at);
|
||||||
|
|
||||||
|
if(monstersnear_add_pmi(mi)) {
|
||||||
if(vmsg()) wouldkill("%The1 would get you!");
|
if(vmsg()) wouldkill("%The1 would get you!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(checkonly) return true;
|
if(checkonly) return true;
|
||||||
if(changes.on) changes.commit();
|
if(changes.on) changes.commit();
|
||||||
if(d == -2)
|
|
||||||
dropGreenStone(cwt.at);
|
|
||||||
if(cellUnstable(cwt.at) && !markOrb(itOrbAether))
|
if(cellUnstable(cwt.at) && !markOrb(itOrbAether))
|
||||||
doesFallSound(cwt.at);
|
doesFallSound(cwt.at);
|
||||||
|
|
||||||
if(last_gravity_state && !gravity_state)
|
|
||||||
playerMoveEffects(cwt.at, cwt.at);
|
|
||||||
|
|
||||||
return after_move();
|
return after_move();
|
||||||
}
|
}
|
||||||
@ -1246,12 +1248,14 @@ EX bool playerInPower() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
EX void playerMoveEffects(cell *c1, cell *c2) {
|
EX void playerMoveEffects(movei mi) {
|
||||||
|
cell *c1 = mi.s;
|
||||||
|
cell *c2 = mi.t;
|
||||||
|
|
||||||
if(peace::on) items[itOrbSword] = c2->land == laBurial ? 100 : 0;
|
if(peace::on) items[itOrbSword] = c2->land == laBurial ? 100 : 0;
|
||||||
|
|
||||||
changes.value_keep(sword::dir[multi::cpid]);
|
changes.value_keep(sword::dir[multi::cpid]);
|
||||||
sword::dir[multi::cpid] = sword::shift(c1, c2, sword::dir[multi::cpid]);
|
sword::dir[multi::cpid] = sword::shift(mi, sword::dir[multi::cpid]);
|
||||||
|
|
||||||
destroyWeakBranch(c1, c2, moPlayer);
|
destroyWeakBranch(c1, c2, moPlayer);
|
||||||
|
|
||||||
@ -1457,20 +1461,20 @@ EX void sideAttack(cell *mf, int dir, eMonster who, int bonuskill) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EX eMonster do_we_stab_a_friend(cell *mf, cell *mt, eMonster who) {
|
EX eMonster do_we_stab_a_friend(movei mi, eMonster who) {
|
||||||
eMonster m = moNone;
|
eMonster m = moNone;
|
||||||
do_swords(mf, mt, who, [&] (cell *c, int bb) {
|
do_swords(mi, who, [&] (cell *c, int bb) {
|
||||||
if(!peace::on && canAttack(mt, who, c, c->monst, AF_SWORD) && c->monst && isFriendly(c)) m = c->monst;
|
if(!peace::on && canAttack(mi.t, who, c, c->monst, AF_SWORD) && c->monst && isFriendly(c)) m = c->monst;
|
||||||
});
|
});
|
||||||
|
|
||||||
for(int t=0; t<mf->type; t++) {
|
for(int t=0; t<mi.s->type; t++) {
|
||||||
cell *c = mf->move(t);
|
cell *c = mi.s->move(t);
|
||||||
if(!c) continue;
|
if(!c) continue;
|
||||||
|
|
||||||
bool stabthere = false;
|
bool stabthere = false;
|
||||||
if(logical_adjacent(mt, who, c)) stabthere = true;
|
if(logical_adjacent(mi.t, who, c)) stabthere = true;
|
||||||
|
|
||||||
if(stabthere && canAttack(mt,who,c,c->monst,AF_STAB) && isFriendly(c))
|
if(stabthere && canAttack(mi.t,who,c,c->monst,AF_STAB) && isFriendly(c))
|
||||||
return c->monst;
|
return c->monst;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1484,27 +1488,14 @@ EX void wouldkill(const char *msg) {
|
|||||||
addMessage(XLAT("Cannot move into the current location of another player!"));
|
addMessage(XLAT("Cannot move into the current location of another player!"));
|
||||||
else if(who_kills_me == moAirball)
|
else if(who_kills_me == moAirball)
|
||||||
addMessage(XLAT("Players cannot get that far away!"));
|
addMessage(XLAT("Players cannot get that far away!"));
|
||||||
|
else if(who_kills_me == moTongue)
|
||||||
|
addMessage(XLAT("Cannot push into another player!"));
|
||||||
|
else if(who_kills_me == moCrushball)
|
||||||
|
addMessage(XLAT("Cannot push into the same location!"));
|
||||||
else
|
else
|
||||||
addMessage(XLAT(msg, who_kills_me));
|
addMessage(XLAT(msg, who_kills_me));
|
||||||
}
|
}
|
||||||
|
|
||||||
EX bool havePushConflict(cell *pushto, bool checkonly) {
|
|
||||||
if(pushto && multi::activePlayers() > 1) {
|
|
||||||
for(int i=0; i<multi::players; i++) if(i != multi::cpid && multi::playerActive(i))
|
|
||||||
if(multi::origpos[i] == pushto || multi::origtarget[i] == pushto) {
|
|
||||||
addMessage(XLAT("Cannot push into another player!"));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
for(int i=0; i<isize(stalemate::moves); i++) {
|
|
||||||
if(pushto == stalemate::moves[i].pushto) {
|
|
||||||
addMessage(XLAT("Cannot push into the same location!"));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
EX void movecost(cell* from, cell *to, int phase) {
|
EX void movecost(cell* from, cell *to, int phase) {
|
||||||
if(from->land == laPower && to->land != laPower && (phase & 1)) {
|
if(from->land == laPower && to->land != laPower && (phase & 1)) {
|
||||||
int n=0;
|
int n=0;
|
||||||
|
Loading…
Reference in New Issue
Block a user