mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-26 01:50:36 +00:00
Merge branch 'master' of https://github.com/zenorogue/hyperrogue
This commit is contained in:
commit
017a4750ed
@ -567,7 +567,8 @@ EX void killMonster(cell *c, eMonster who, flagtype deathflags IS(0)) {
|
||||
forCellEx(c1, c) {
|
||||
changes.ccell(c1);
|
||||
c1->item = itNone;
|
||||
if(c1->wall == waDeadwall || c1->wall == waDeadfloor2) c1->wall = waCavewall;
|
||||
if(c1->wall == waDeadwall) c1->wall = waCavewall;
|
||||
if(c1->wall == waDeadfloor2 && !c1->monst && !isPlayerOn(c1)) c1->wall = waCavewall;
|
||||
if(c1->wall == waDeadfloor) c1->wall = waCavefloor;
|
||||
}
|
||||
}
|
||||
@ -1050,6 +1051,7 @@ EX void killFriendlyIvy() {
|
||||
|
||||
EX bool monsterPushable(cell *c2) {
|
||||
if(markOrb(itCurseWeakness) && (c2->stuntime < 2 || attackJustStuns(c2, 0, moPlayer))) return false;
|
||||
if(isMultitile(c2->monst)) return false;
|
||||
return (c2->monst != moFatGuard && !(isMetalBeast(c2->monst) && c2->stuntime < 2) && c2->monst != moTortoise && c2->monst != moTerraWarrior && c2->monst != moVizier && c2->monst != moWorldTurtle);
|
||||
}
|
||||
|
||||
|
@ -2300,7 +2300,7 @@ void celldrawer::draw_item_full() {
|
||||
|
||||
color_t icol = 0;
|
||||
|
||||
if(specialland == laMotion && items[itOrbInvis] && c->wall == waChasm) {
|
||||
if(ls::single() && specialland == laMotion && items[itOrbInvis] && c->wall == waChasm) {
|
||||
if(c->mondir < c->type) {
|
||||
vid.linewidth *= 3;
|
||||
queueline(V*C0, V*currentmap->adj(c, c->mondir) * C0, 0xFFD500FF, 4);
|
||||
|
@ -105,6 +105,7 @@ EX bool monstersnear(cell *c, eMonster who) {
|
||||
|
||||
int res = 0;
|
||||
bool fast = false;
|
||||
bool kraken_will_destroy_boat = false;
|
||||
|
||||
elec::builder b;
|
||||
if(elec::affected(c)) { who_kills_me = moLightningBolt; res++; }
|
||||
@ -119,7 +120,7 @@ EX bool monstersnear(cell *c, eMonster who) {
|
||||
|
||||
if(who == moPlayer || items[itOrbEmpathy]) {
|
||||
fast = (items[itOrbSpeed] && (items[itOrbSpeed] & 1));
|
||||
if(who == moPlayer && c->item == itOrbSpeed && !items[itOrbSpeed]) fast = true;
|
||||
if(who == moPlayer && !isPlayerOn(c) && c->item == itOrbSpeed && !items[itOrbSpeed]) fast = true;
|
||||
}
|
||||
|
||||
if(havewhat&HF_OUTLAW) {
|
||||
@ -167,10 +168,9 @@ EX bool monstersnear(cell *c, eMonster who) {
|
||||
if(elec::affected(c2)) continue;
|
||||
if(fast && c2->monst != moWitchSpeed) continue;
|
||||
// Krakens just destroy boats
|
||||
if(c2->monst == moKrakenT && c->wall == waBoat) {
|
||||
if(krakensafe(c)) continue;
|
||||
else if(warningprotection(XLAT("This move appears dangerous -- are you sure?")) && res == 0) m = moWarning;
|
||||
else continue;
|
||||
if(who == moPlayer && c2->monst == moKrakenT && c->wall == waBoat) {
|
||||
kraken_will_destroy_boat = true;
|
||||
continue;
|
||||
}
|
||||
// they cannot attack through vines
|
||||
if(!canAttack(c2, c2->monst, c, who, AF_NEXTTURN)) continue;
|
||||
@ -183,11 +183,15 @@ EX bool monstersnear(cell *c, eMonster who) {
|
||||
}
|
||||
}
|
||||
|
||||
if(kraken_will_destroy_boat && !krakensafe(c) && warningprotection(XLAT("This move appears dangerous -- are you sure?"))) {
|
||||
if (res == 0) who_kills_me = moWarning;
|
||||
res++;
|
||||
} else {
|
||||
if(who == moPlayer && res && (markOrb2(itOrbShield) || markOrb2(itOrbShell)) && !eaten)
|
||||
res = 0;
|
||||
|
||||
if(who == moPlayer && res && markOrb2(itOrbDomination) && c->monst)
|
||||
res = 0;
|
||||
}
|
||||
|
||||
return !!res;
|
||||
}
|
||||
|
@ -367,8 +367,8 @@ int arg::readCommon() {
|
||||
printf(" -offline - don't connect to Steam (for Steam versions)\n");
|
||||
printf(" -I ITEM n - start with n of ITEM (activates cheat and disables ghosts)\n");
|
||||
printf(" -fix - fix the seed\n");
|
||||
printf("Toggles: -o0 disables, -o1 enables, -o switches");
|
||||
printf("Not all options are documented, see hyper.cpp");
|
||||
printf("Toggles: -o0 disables, -o1 enables, -o switches\n");
|
||||
printf("Not all options are documented, see hyper.cpp\n");
|
||||
exit(0);
|
||||
}
|
||||
else return 1;
|
||||
|
@ -2349,7 +2349,7 @@ EX void livecaves() {
|
||||
for(cell *c2: adj_minefield_cells(c)) {
|
||||
eWall w = c2->wall;
|
||||
if(w == waDeadfloor) hv++, bringlife.push_back(c2);
|
||||
else if(w == waDeadwall || (w == waDeadfloor2 && !c2->monst))
|
||||
else if(w == waDeadwall || (w == waDeadfloor2 && !c2->monst && !isPlayerOn(c2)))
|
||||
hv--, bringlife.push_back(c2);
|
||||
else if(w == waCavefloor) hv++;
|
||||
else if(w == waCavewall) hv--;
|
||||
@ -2597,7 +2597,7 @@ EX }
|
||||
EX namespace dragon {
|
||||
|
||||
EX int whichturn; // which turn has the target been set on
|
||||
EX cell *target; // actually for all Orb of Control
|
||||
EX cell *target; // actually for all Orb of Domination
|
||||
|
||||
void pullback(cell *c) {
|
||||
int maxlen = iteration_limit;
|
||||
@ -2977,6 +2977,7 @@ EX namespace kraken {
|
||||
for(int i=0; i<isize(dcal); i++) {
|
||||
cell *c = dcal[i];
|
||||
if(c->monst == moKrakenT && !c->stuntime) forCellEx(c2, c) {
|
||||
if (!logical_adjacent(c2,moKrakenT,c)) continue;
|
||||
bool dboat = false;
|
||||
if(c2->monst && canAttack(c, moKrakenT, c2, c2->monst, AF_ONLY_FBUG)) {
|
||||
attackMonster(c2, AF_NORMAL | AF_MSG, c->monst);
|
||||
@ -3467,6 +3468,7 @@ auto ccm = addHook(hooks_clearmemory, 0, [] () {
|
||||
clearing::score.clear();
|
||||
tortoise::emap.clear();
|
||||
tortoise::babymap.clear();
|
||||
dragon::target = NULL;
|
||||
#if CAP_FIELD
|
||||
prairie::lasttreasure = NULL;
|
||||
prairie::enter = NULL;
|
||||
@ -3510,6 +3512,7 @@ auto ccm = addHook(hooks_clearmemory, 0, [] () {
|
||||
}
|
||||
return false;
|
||||
});
|
||||
set_if_removed(dragon::target, NULL);
|
||||
#if CAP_FIELD
|
||||
set_if_removed(prairie::lasttreasure, NULL);
|
||||
set_if_removed(prairie::enter, NULL);
|
||||
|
@ -320,7 +320,7 @@ array<feature, 21> features {{
|
||||
if(buildIvy(c, 0, c->type) && !peace::on) c->item = itVarTreasure;
|
||||
}},
|
||||
{0x000A08, 0, moNone, VF { if(c->wall == waNone && !c->monst && hrand(5000) < 100) c->wall = waSmallTree; }},
|
||||
{0x100A10, 1, moRagingBull, VF { if(c->wall == waNone && hrand(10000) < 10 + items[itVarTreasure]) c->monst = moSleepBull, c->hitpoints = 3; }},
|
||||
{0x100A10, 1, moRagingBull, VF { if(c->wall == waNone && !c->monst && hrand(10000) < 10 + items[itVarTreasure]) c->monst = moSleepBull, c->hitpoints = 3; }},
|
||||
{0x00110C, 0, moNone, VF { if(c->wall == waNone && !c->monst && hrand(5000) < 100) c->wall = waBigTree; }},
|
||||
{0x000A28, 1, moNone, VF { if(hrand(500) < 10) build_pool(c, false); } },
|
||||
{0x100A00, 2, moVariantWarrior, VF { if(c->wall == waNone && !c->monst && hrand_var(40000)) c->monst = moVariantWarrior; }},
|
||||
@ -458,7 +458,7 @@ EX void knightFlavorMessage(cell *c2) {
|
||||
else if(cryst)
|
||||
s = crystal::get_table_boundary();
|
||||
#endif
|
||||
else if(!quotient)
|
||||
else if(!quotient && rad)
|
||||
s = expansion.get_descendants(rad).get_str(100);
|
||||
if(s == "") { msgid++; goto retry; }
|
||||
addMessage(XLAT("\"Our Table seats %1 Knights!\"", s));
|
||||
@ -470,7 +470,7 @@ EX void knightFlavorMessage(cell *c2) {
|
||||
else if(cryst)
|
||||
s = crystal::get_table_volume();
|
||||
#endif
|
||||
else if(!quotient)
|
||||
else if(!quotient && rad)
|
||||
s = expansion.get_descendants(rad-1, expansion.diskid).get_str(100);
|
||||
if(s == "") { msgid++; goto retry; }
|
||||
addMessage(XLAT("\"There are %1 floor tiles inside our Table!\"", s));
|
||||
|
@ -125,7 +125,7 @@ MONSTER( 'D', 0xFF0000, "Greater Demon", moGreater, CF_FACE_UP | CF_DEMON | CF_S
|
||||
MONSTER( 'D', 0x800000, "Greater Demon", moGreaterM, CF_FACE_UP | CF_DEMON | CF_INACTIVE | CF_SPAM, RESERVED, moLesser, gdemonhelp)
|
||||
MONSTER( 'd', 0xFF2020, "Lesser Demon", moLesser, CF_FACE_UP | CF_DEMON | CF_SLOWMOVER | CF_SPAM, RESERVED, moYeti, ldemonhelp)
|
||||
MONSTER( 'd', 0x802020, "Lesser Demon", moLesserM, CF_FACE_UP | CF_DEMON | CF_INACTIVE | CF_SPAM, RESERVED, moLesser, ldemonhelp)
|
||||
MONSTER( 'S', 0x2070C0, "Ice Shark", moShark, CF_FACE_SIDE | CF_SHARK, RESERVED, moShark,
|
||||
MONSTER( 'S', 0x2070C0, "Ice Shark", moShark, CF_FACE_SIDE | CF_NOBLOW | CF_SHARK, RESERVED, moShark,
|
||||
"This dangerous predator has killed many people, and has been sent to Cocytus."
|
||||
)
|
||||
MONSTER( 'W', 0xFFFFFF, "Running Dog", moRunDog, CF_FACE_SIDE, RESERVED, moYeti,
|
||||
@ -221,7 +221,7 @@ MONSTER( '@', 0x8B4513, "Illusion", moIllusion, CF_FACE_SIDE | CF_NOGHOST | CF_N
|
||||
)
|
||||
MONSTER( 'P', 0xD00000, "Pirate", moPirate, CF_FACE_UP | CF_LEADER, RESERVED, moPirate,
|
||||
"Just a typical hyperbolic pirate." )
|
||||
MONSTER( 'S', 0x8080C0, "Shark", moCShark, CF_FACE_SIDE | CF_SHARK, RESERVED, moShark, "Just a nasty shark.")
|
||||
MONSTER( 'S', 0x8080C0, "Shark", moCShark, CF_FACE_SIDE | CF_NOBLOW | CF_SHARK, RESERVED, moShark, "Just a nasty shark.")
|
||||
MONSTER( 'P', 0x0000FF, "Parrot", moParrot, CF_FACE_SIDE | CF_NOBLOW | CF_SLIME | CF_IGNORE_SMELL, RESERVED, moSlime, "Parrots feel safe in the forests of Caribbean, so they "
|
||||
"never leave them. But they will help the Pirates by attacking the intruders.")
|
||||
MONSTER( 'S', 0xE09000, "Rock Snake", moHexSnake, ZERO | CF_NOGHOST | CF_NOBLOW | CF_MOUNTABLE | CF_IGNORE_SMELL | CF_MULTITILE | CF_WORM | CF_HIGH_THREAT, RESERVED, moNone, redsnakedes )
|
||||
@ -329,7 +329,7 @@ MONSTER( 'D', 0xF09090, "Draugr", moDraugr, CF_FACE_UP | CF_NONLIVING | CF_SLOWM
|
||||
"Animated corpses of ancient Viking warriors. They are immune to mundane weapons, "
|
||||
"but they can be destroyed by your Orb of the Sword."
|
||||
)
|
||||
MONSTER( 'C', 0xC08000, "Friendly Ivy", moFriendlyIvy, ZERO | CF_NOGHOST | CF_NOBLOW | CF_FRIENDLY | CF_FACING | CF_ANYIVY, RESERVED, moNone, naturedesc )
|
||||
MONSTER( 'C', 0xC08000, "Friendly Ivy", moFriendlyIvy, ZERO | CF_NOGHOST | CF_NOBLOW | CF_MULTITILE | CF_FRIENDLY | CF_FACING | CF_ANYIVY, RESERVED, moNone, naturedesc )
|
||||
MONSTER( 'V', 0xC000C0, "Vampire Bat", moVampire, CF_FACE_SIDE | CF_BIRD | CF_FLYING | CF_UNARMED | CF_IGNORE_PLATE, RESERVED, moEagle,
|
||||
"Vampire Bats don't attack normally, but they drain your magical powers if "
|
||||
"they are at distance at most 2 from you."
|
||||
@ -1562,7 +1562,7 @@ WALL( '=', 0x00C0C0, "shallow water", waShallow, ZERO, RESERVED, 0, sgWater,
|
||||
)
|
||||
WALL( '=', 0x0000A0, "deep water", waDeepWater, WF_WATER, RESERVED, 0, sgWater,
|
||||
"This body of water is calm and beautiful, but too deep to pass.")
|
||||
MONSTER( 'P', 0xC08080, "Pike", moPike, CF_FACE_SIDE | CF_SHARK, RESERVED, moShark,
|
||||
MONSTER( 'P', 0xC08080, "Pike", moPike, CF_FACE_SIDE | CF_NOBLOW | CF_SHARK, RESERVED, moShark,
|
||||
"You remember anglers from your hometown showing the impressive pikes they have caught. This one is much larger."
|
||||
)
|
||||
MONSTER( 'T', 0xFF00FF, "World Turtle", moWorldTurtle, CF_FACE_SIDE | CF_STUNNABLE | CF_SLOWMOVER | CF_SPAM, RESERVED, moYeti,
|
||||
|
@ -19,6 +19,36 @@ bool sameland(eLand ll, eLand ln) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cell *cellToTarget() {
|
||||
if (isCrossroads(cwt.at->land)) {
|
||||
for (cell *c: dcal) {
|
||||
if (c->land == laCamelot && c->wall == waNone) {
|
||||
printf("Trying to teleport into Camelot\n");
|
||||
items[itOrbTeleport] += 1;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(cwt.at->land == laCamelot) {
|
||||
int oldDist = celldistAltRelative(cwt.at);
|
||||
if (oldDist > 3) {
|
||||
for (cell *c: dcal) {
|
||||
if (c->land == laCamelot) {
|
||||
int dist = celldistAltRelative(c);
|
||||
if (-1 <= dist && dist <= 1 && hrand(10) == 0) {
|
||||
printf("Trying to teleport near the round table (%d to %d)\n", oldDist, dist);
|
||||
items[itOrbTeleport] += 1;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dcal[hrand(isize(dcal))];
|
||||
}
|
||||
|
||||
/* auto a3 = addHook(hooks_nextland, 100, [] (eLand l) {
|
||||
eLand l2;
|
||||
do { l2 = pick(laRuins, laTerracotta, laPrairie); } while(l2 == l);
|
||||
@ -76,33 +106,108 @@ void autoplay(int num_moves = 1000000000) {
|
||||
#endif
|
||||
//mainloop();
|
||||
}
|
||||
int i = hrand(cwt.at->type);
|
||||
cell *c2 = cwt.at->move(i);
|
||||
|
||||
/* if(gcount < 500) for(int i=1; i<isize(dcal); i++) {
|
||||
c2 = dcal[i];
|
||||
if(lcount >= 50 && !sameland(lland, c2->land) && !sameland(lland2, c2->land)) break;
|
||||
else if(lcount < 50 && c2->item && c2->item != itOrbSafety) break;
|
||||
} */
|
||||
items[hrand(ittypes)] = 1 << hrand(11);
|
||||
kills[hrand(motypes)] = 1 << hrand(11);
|
||||
|
||||
// Use a random cheat
|
||||
int croll = hrand(50);
|
||||
if (croll < 25) {
|
||||
eItem b = (eItem) hrand(ittypes);
|
||||
printf("Gain item: %s\n", iinf[b].name);
|
||||
items[b] = (1 << hrand(11)) - 1;
|
||||
items[itOrbYendor] &= 15;
|
||||
again:
|
||||
if(c2->cpdist > 1) {
|
||||
for(int j=0; j<c2->type; j++)
|
||||
if(c2->move(j) && c2->move(j)->cpdist < c2->cpdist) {
|
||||
c2 = c2->move(j);
|
||||
goto again;
|
||||
reduceOrbPowers(); // in particlar, cancel out slaying+weakness, since the combination may confuse shadow
|
||||
} else if (croll == 25) {
|
||||
printf("Gain kills\n");
|
||||
kills[hrand(motypes)] = (1 << hrand(11)) - 1;
|
||||
} else if (croll == 26) {
|
||||
printf("Princess soon\n");
|
||||
princess::saved = true;
|
||||
princess::everSaved = true;
|
||||
items[itSavedPrincess]++;
|
||||
items[itOrbLove] = 1;
|
||||
items[itOrbTime] = 0;
|
||||
} else if (croll == 27) {
|
||||
printf("Gain allies\n");
|
||||
forCellEx(cz, cwt.at)
|
||||
if (!cz->monst)
|
||||
cz->monst = pick(moMouse, moFriendlyGhost, moGolem, moTameBomberbird, moKnight);
|
||||
} else if (croll == 28) {
|
||||
printf("Place orbs with pickup effects\n");
|
||||
forCellEx(cz, cwt.at)
|
||||
if (!cz->item)
|
||||
cz->item = pick(itOrbLife, itOrbFriend, itOrbSpeed, itOrbShield, itOrbChaos, itOrbPurity);
|
||||
} else if (croll == 29) {
|
||||
printf("Place fun walls\n");
|
||||
forCellEx(cz, cwt.at)
|
||||
if (!cz->wall)
|
||||
cz->wall = pick(waExplosiveBarrel, waBigStatue, waThumperOff, waBonfireOff, waCloud, waMirror);
|
||||
} else if (croll == 30) {
|
||||
cell *ct = dcal[hrand(isize(dcal))];
|
||||
if (!isPlayerOn(ct) && !ct->monst && !ct->wall) {
|
||||
eWall hazard = pick(waRose, waFireTrap, waMineMine, waTrapdoor, waChasm, waCavewall);
|
||||
printf("Spam a hazard: %s\n", winf[hazard].name);
|
||||
ct->wall = hazard;
|
||||
}
|
||||
} else if (croll == 31 && !memory_saving_mode) {
|
||||
//printf("Saving memory\n");
|
||||
//memory_saving_mode = true;
|
||||
//save_memory();
|
||||
//memory_saving_mode = false;
|
||||
} else if (croll == 33) {
|
||||
cell *ct = dcal[hrand(isize(dcal))];
|
||||
if (!isPlayerOn(ct) && !ct->monst && !ct->wall) {
|
||||
printf("Spam some slime\n");
|
||||
ct->item = itNone;
|
||||
ct->wall = hrand(2) ? waFloorA : waFloorB;
|
||||
ct->monst = hrand(2) ? moSlime : moNone;
|
||||
}
|
||||
}
|
||||
|
||||
// don't show warning dialogs
|
||||
items[itWarning] = 1;
|
||||
|
||||
// Make a random move
|
||||
int roll = hrand(50);
|
||||
if (roll == 0) {
|
||||
// drop dead orb
|
||||
bool res = movepcto(MD_DROP, 1);
|
||||
printf("DROP: %d\n", res);
|
||||
} else if (roll < 5) {
|
||||
// skip turn
|
||||
bool res = movepcto(MD_WAIT, 1);
|
||||
printf("WAIT: %d\n", res);
|
||||
} else if (roll < 42) {
|
||||
// move to or attack a neighbor cell
|
||||
int i = hrand(cwt.at->type);
|
||||
cell *c2 = cwt.at->move(i);
|
||||
cwt.spin = 0;
|
||||
int d = neighborId(cwt.at, c2);
|
||||
if(d >= 0 && movepcto(d, 1, false))
|
||||
println(hlog, "OK");
|
||||
else {
|
||||
println(hlog, "NOK");
|
||||
if (d >= 0) {
|
||||
int subdir = (roll%2==0)?1:-1;
|
||||
string c2info = dnameof(c2->wall) + "; " + dnameof(c2->monst) + "; " + dnameof(c2->item);
|
||||
bool res = movepcto(d, subdir, false);
|
||||
printf("MOVE %d [%s] sub %d: %d\n", d, c2info.c_str(), subdir, res);
|
||||
if (!res && c2->monst) {
|
||||
printf("clearing the monster (%s)\n", minf[c2->monst].name);
|
||||
killMonster(c2, moNone);
|
||||
jumpTo(roKeyboard, c2, itNone, 0, moNone);
|
||||
}
|
||||
} else {
|
||||
printf("MOVE CONFUSED %d\n", d);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// try to use a ranged orb
|
||||
cell *ct = cellToTarget();
|
||||
eItem ti = targetRangedOrb(ct, roMouseForce);
|
||||
const char *tm = (ti == eItem(-1)) ? "orb cannot be used (see message log)" : iinf[ti].name;
|
||||
printf("TARGET %p: %s\n", (void*)ct, tm);
|
||||
}
|
||||
|
||||
if(false) if(turncount % 5000 == 0) {
|
||||
printf("cells travelled: %d\n", celldist(cwt.at));
|
||||
|
||||
@ -125,6 +230,10 @@ void autoplay(int num_moves = 1000000000) {
|
||||
cellcount = 0;
|
||||
activateSafety(laCrossroads);
|
||||
// landlist[hrand(isize(landlist))]);
|
||||
if (cellcount < 0) {
|
||||
//printf("How did cellcount become negative?\n");
|
||||
cellcount = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(cwt.at->land == laWestWall && cwt.at->landparam >= 30) {
|
||||
@ -132,6 +241,32 @@ void autoplay(int num_moves = 1000000000) {
|
||||
forCellEx(c2, cwt.at) c2->item = itOrbSafety;
|
||||
}
|
||||
|
||||
if(isIcyLand(cwt.at)) {
|
||||
float heat = HEAT(cwt.at);
|
||||
// Checking for extreme values as well as NaNs and infinities
|
||||
if (!(-1e10 < heat && heat < 1e10)) {
|
||||
printf("Heat is out of expected range\n");
|
||||
canmove = true;
|
||||
doAutoplay = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (cwt.at->land == laCamelot) {
|
||||
for(int i=0; i<isize(dcal); i++) {
|
||||
cell *c = dcal[i];
|
||||
if(c->land == laCamelot && celldistAltRelative(c) == 0 && c->wall != waRoundTable) {
|
||||
printf("The round table of camelot has been breached!\n");
|
||||
kills[moPlayer] = 0;
|
||||
canmove = true;
|
||||
doAutoplay = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(cwt.at->monst && !isMultitile(cwt.at->monst)) {
|
||||
printf("on a non-multitile monster: %s\n", minf[cwt.at->monst].name);
|
||||
}
|
||||
|
||||
for(int i=0; i<isize(dcal); i++) {
|
||||
cell *c = dcal[i];
|
||||
if(isChild(c, NULL)) {
|
||||
@ -143,6 +278,12 @@ void autoplay(int num_moves = 1000000000) {
|
||||
canmove = true;
|
||||
doAutoplay = false;
|
||||
}
|
||||
if(c->item == itBuggy || c->item == itBuggy2) {
|
||||
printf("buggy item found\n");
|
||||
kills[moPlayer] = 0;
|
||||
canmove = true;
|
||||
doAutoplay = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(buggyGeneration || isize(buggycells)) {
|
||||
|
4
game.cpp
4
game.cpp
@ -430,7 +430,7 @@ EX bool canPushThumperOn(movei mi, cell *player) {
|
||||
return
|
||||
passable(tgt, thumper, P_MIRROR) &&
|
||||
passable(tgt, player, P_MIRROR) &&
|
||||
!tgt->item;
|
||||
(!tgt->item || dice::on(thumper));
|
||||
}
|
||||
|
||||
EX void activateActiv(cell *c, bool msg) {
|
||||
@ -503,7 +503,7 @@ EX bool sameMonster(cell *c1, cell *c2) {
|
||||
EX eMonster haveMount() {
|
||||
for(cell *pc: player_positions()) {
|
||||
eMonster m = pc->monst;
|
||||
if(m) return m;
|
||||
if(isWorm(m)) return m;
|
||||
}
|
||||
return moNone;
|
||||
}
|
||||
|
@ -268,6 +268,7 @@ EX bool incompatible1(eLand l1, eLand l2) {
|
||||
if(l1 == laDeadCaves && l2 == laCaves) return true;
|
||||
if(l1 == laWarpSea && l2 == laKraken) return true;
|
||||
if(l1 == laPrairie && l2 == laCrossroads3) return true;
|
||||
if(l1 == laPrairie && l2 == laCrossroads4) return true;
|
||||
if(l1 == laWet && l2 == laDesert) return true;
|
||||
if(l1 == laFrog && l2 == laMotion) return true;
|
||||
if(isElemental(l1) && isElemental(l2)) return true;
|
||||
|
@ -41,7 +41,7 @@ EX void showOverview() {
|
||||
mouseovers += XLAT(" Hell: %1/%2", its(orbsUnlocked()), its(lands_for_hell()));
|
||||
}
|
||||
|
||||
bool pages;
|
||||
bool pages = false;
|
||||
|
||||
{
|
||||
dynamicval<int> ds(dual::state, dual::state ? 2 : 0);
|
||||
|
@ -659,7 +659,7 @@ EX void beastAttack(cell *c, bool player, bool targetdir) {
|
||||
if(c2->monst && c2->stuntime) {
|
||||
cellwalker bull (c, d);
|
||||
int subdir = determinizeBullPush(bull);
|
||||
auto mi = determinePush(bull, subdir, [c2] (movei mi) { return passable(mi.t, c2, P_BLOW); });
|
||||
auto mi = determinePush(bull, subdir, [c2] (movei mi) { return passable(mi.t, c2, P_BLOW) && !isPlayerOn(mi.t); });
|
||||
if(mi.proper())
|
||||
pushMonster(mi);
|
||||
}
|
||||
|
10
orbs.cpp
10
orbs.cpp
@ -115,7 +115,7 @@ EX void reduceOrbPowerAlways(eItem it) {
|
||||
EX void reverse_curse(eItem curse, eItem orb, bool cancel) {
|
||||
if(items[curse] && markOrb(itOrbPurity)) {
|
||||
items[orb] += items[curse];
|
||||
if(curse == itCurseWeakness) items[itOrbWinter] += items[curse];
|
||||
if(curse == itCurseWater) items[itOrbWinter] += items[curse];
|
||||
items[curse] = 0;
|
||||
}
|
||||
if(cancel && items[curse] && items[orb]) {
|
||||
@ -1211,6 +1211,7 @@ EX void apply_impact(cell *c) {
|
||||
if(markOrb(itOrbImpact))
|
||||
forCellEx(c1, c) {
|
||||
if(!c1->monst) continue;
|
||||
if(c1->monst == moMimic) continue;
|
||||
if(isMultitile(c1->monst)) continue;
|
||||
addMessage(XLAT("You stun %the1!", c1->monst));
|
||||
changes.ccell(c1);
|
||||
@ -1462,7 +1463,7 @@ EX eItem targetRangedOrb(cell *c, orbAction a) {
|
||||
}
|
||||
|
||||
// (5c) stun
|
||||
if(items[itOrbStunning] && c->monst && !isMultitile(c->monst) && c->stuntime < 3 && !shmup::on) {
|
||||
if(items[itOrbStunning] && c->monst && !isMultitile(c->monst) && c->monst != moMimic && c->stuntime < 3 && !shmup::on) {
|
||||
if(!isCheck(a)) stun_attack(c), apply_impact(c);
|
||||
return itOrbStunning;
|
||||
}
|
||||
@ -1481,9 +1482,12 @@ EX eItem targetRangedOrb(cell *c, orbAction a) {
|
||||
|
||||
if(isWeakCheck(a)) return itNone;
|
||||
|
||||
if(nowhereToBlow) {
|
||||
if(nowhereToBlow && isBlowableMonster(c->monst)) {
|
||||
addMessage(XLAT("Nowhere to blow %the1!", c->monst));
|
||||
}
|
||||
else if(nowhereToBlow) {
|
||||
addMessage(XLAT("Nowhere to blow %the1!", c->wall));
|
||||
}
|
||||
else if(jumpstate == 1 && jumpthru && jumpthru->monst) {
|
||||
addMessage(XLAT("Cannot jump through %the1!", jumpthru->monst));
|
||||
}
|
||||
|
10
pcmove.cpp
10
pcmove.cpp
@ -751,7 +751,7 @@ void pcmove::tell_why_cannot_attack() {
|
||||
addMessage(XLAT("You cannot attack Sandworms directly!"));
|
||||
else if(c2->monst == moHexSnake || c2->monst == moHexSnakeTail)
|
||||
addMessage(XLAT("You cannot attack Rock Snakes directly!"));
|
||||
else if(nonAdjacent(c2, cwt.at))
|
||||
else if(nonAdjacentPlayer(c2, cwt.at))
|
||||
addMessage(XLAT("You cannot attack diagonally!"));
|
||||
else if(thruVine(c2, cwt.at))
|
||||
addMessage(XLAT("You cannot attack through the Vine!"));
|
||||
@ -785,6 +785,12 @@ void pcmove::tell_why_cannot_attack() {
|
||||
addMessage(XLAT("You can only push this die if the highest number would be on the top!"));
|
||||
else if(c2->monst == moAngryDie)
|
||||
addMessage(XLAT("This die is really angry at you!"));
|
||||
else if((attackflags & AF_WEAK) && isIvy(c2))
|
||||
addMessage(XLAT("You are too weakened to attack %the1!", c2->monst));
|
||||
else if(isWorm(cwt.at->monst) && isWorm(c2->monst) && wormhead(cwt.at) == wormhead(c2) && cwt.at->monst != moTentacleGhost && c2->monst != moTentacleGhost)
|
||||
addMessage(XLAT("You cannot attack your own mount!"));
|
||||
else if(checkOrb(c2->monst, itOrbShield))
|
||||
addMessage(XLAT("A magical shield protects %the1!", c2->monst));
|
||||
else
|
||||
addMessage(XLAT("For some reason... cannot attack!"));
|
||||
}
|
||||
@ -929,7 +935,7 @@ bool pcmove::move_if_okay() {
|
||||
|
||||
void pcmove::tell_why_impassable() {
|
||||
cell*& c2 = mi.t;
|
||||
if(nonAdjacent(cwt.at,c2)) {
|
||||
if(nonAdjacentPlayer(cwt.at,c2)) {
|
||||
if(vmsg(miRESTRICTED)) addMessage(geosupport_football() < 2 ?
|
||||
XLAT("You cannot move between the cells without dots here!") :
|
||||
XLAT("You cannot move between the triangular cells here!")
|
||||
|
Loading…
Reference in New Issue
Block a user