From f4193c32e9a32fb620f8d65a33528d8af9747c13 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Sun, 4 Jul 2021 14:17:21 -0700 Subject: [PATCH 01/23] Only show chasm trails in special modes --- celldrawer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/celldrawer.cpp b/celldrawer.cpp index adb058a4..0e8bef9e 100644 --- a/celldrawer.cpp +++ b/celldrawer.cpp @@ -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); From 5ee3ebd1f766920a82e925bacd63e0aa227e0f3c Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Mon, 5 Jul 2021 02:39:18 -0700 Subject: [PATCH 02/23] Orb of Air can no longer push sharks --- content.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content.cpp b/content.cpp index 1ddc4148..62da9e22 100644 --- a/content.cpp +++ b/content.cpp @@ -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 ) @@ -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, From a79c442469b694190bd59d6871a45480762343fc Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Mon, 5 Jul 2021 03:12:56 -0700 Subject: [PATCH 03/23] Fix 'nowhere to blow' message for happy dice --- orbs.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/orbs.cpp b/orbs.cpp index c1f60d3e..d6a85916 100644 --- a/orbs.cpp +++ b/orbs.cpp @@ -1481,9 +1481,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)); } From db5a9baac2d19dddcddd2b39886f6d4f15781b38 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Mon, 5 Jul 2021 05:25:59 -0700 Subject: [PATCH 04/23] Dice can now be pushed onto items --- game.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game.cpp b/game.cpp index 29e9a4d3..c9ecda59 100644 --- a/game.cpp +++ b/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) { From 306066fa4eadb4fd0d2e4574ddbf06b4ee0b6bc4 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Thu, 8 Jul 2021 01:32:11 -0700 Subject: [PATCH 05/23] Filtering the Overview now hides page buttons reliably --- menus.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menus.cpp b/menus.cpp index 4bf3d5fb..71343a83 100644 --- a/menus.cpp +++ b/menus.cpp @@ -41,7 +41,7 @@ EX void showOverview() { mouseovers += XLAT(" Hell: %1/%2", its(orbsUnlocked()), its(lands_for_hell())); } - bool pages; + bool pages = false; { dynamicval ds(dual::state, dual::state ? 2 : 0); From 7baa1ca932dc01c20eb7297f7dd293a6f26a6ba1 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Fri, 9 Jul 2021 20:00:25 -0700 Subject: [PATCH 06/23] Curse of Weakness no longer allows pushing parts of multitile monsters --- attack.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/attack.cpp b/attack.cpp index b64876ca..26d34134 100644 --- a/attack.cpp +++ b/attack.cpp @@ -1050,6 +1050,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); } From 7f28389e66eba5f4fcdcd043aa902c682e837485 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Fri, 9 Jul 2021 20:28:24 -0700 Subject: [PATCH 07/23] Orb of shield/shell no longer bypasses 'kraken will destroy boat' warning --- checkmove.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/checkmove.cpp b/checkmove.cpp index b38d45fb..4ab247e5 100644 --- a/checkmove.cpp +++ b/checkmove.cpp @@ -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++; } @@ -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(who == moPlayer && res && (markOrb2(itOrbShield) || markOrb2(itOrbShell)) && !eaten) - res = 0; - - if(who == moPlayer && res && markOrb2(itOrbDomination) && c->monst) - res = 0; + 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; } From c5f867da91814fd1e3a140353a4892d89a3460a1 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Fri, 9 Jul 2021 20:33:38 -0700 Subject: [PATCH 08/23] Fix checkmate check when standing on an Orb of Speed --- checkmove.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checkmove.cpp b/checkmove.cpp index b38d45fb..01e08f8f 100644 --- a/checkmove.cpp +++ b/checkmove.cpp @@ -119,7 +119,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) { From 45b6317e69d676889abb200bc5e4cdf978be6e10 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Fri, 9 Jul 2021 20:51:07 -0700 Subject: [PATCH 09/23] Fix crash after using Orb of Domination --- complex.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/complex.cpp b/complex.cpp index f04399d6..fb004bb3 100644 --- a/complex.cpp +++ b/complex.cpp @@ -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; @@ -3467,6 +3467,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 +3511,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); From 15f90f194e5a28668c0abbaad27726c1684d6eef Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Fri, 9 Jul 2021 21:20:30 -0700 Subject: [PATCH 10/23] Kraken Tentacle attacks now obey Warp restrictions --- complex.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/complex.cpp b/complex.cpp index f04399d6..b488dc77 100644 --- a/complex.cpp +++ b/complex.cpp @@ -2977,6 +2977,7 @@ EX namespace kraken { for(int i=0; imonst == 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); From 9d522cfe6fb796adcae3a36d8bc38c50dfa25b65 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Fri, 9 Jul 2021 21:30:13 -0700 Subject: [PATCH 11/23] Irradiated Field: bull generation no longer breaks ivy --- complex2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/complex2.cpp b/complex2.cpp index df1920e2..0ed33216 100644 --- a/complex2.cpp +++ b/complex2.cpp @@ -320,7 +320,7 @@ array 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; }}, From e544826a94ae7223b981752dfadeb1b28ea17401 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Fri, 9 Jul 2021 21:33:25 -0700 Subject: [PATCH 12/23] Fix crash when talking to a Knight in the Temple of Cthulhu --- complex2.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/complex2.cpp b/complex2.cpp index df1920e2..746f6dff 100644 --- a/complex2.cpp +++ b/complex2.cpp @@ -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)); From 4fe57cf5342ae90c8883e5e7baa258394855ea79 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Fri, 9 Jul 2021 21:35:38 -0700 Subject: [PATCH 13/23] Fix several Friendly Ivy interactions --- content.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content.cpp b/content.cpp index 1ddc4148..cc0be67f 100644 --- a/content.cpp +++ b/content.cpp @@ -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." From 0530c1dc690b6e4c671a1cc23f3646b07ef683f0 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Fri, 9 Jul 2021 21:43:30 -0700 Subject: [PATCH 14/23] haveMount: check specifically for worm-type monsters --- game.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game.cpp b/game.cpp index 29e9a4d3..819638d6 100644 --- a/game.cpp +++ b/game.cpp @@ -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; } From e31740c4c7079ce326b0e26242cbc80a1bb6a332 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Fri, 9 Jul 2021 21:46:59 -0700 Subject: [PATCH 15/23] Prairie no longer appears on Crossroads IV --- landlock.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/landlock.cpp b/landlock.cpp index db9a044a..690a635c 100644 --- a/landlock.cpp +++ b/landlock.cpp @@ -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; From 002c354a5181dfdfee7a6124f8881a31e89f93c2 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Fri, 9 Jul 2021 21:52:09 -0700 Subject: [PATCH 16/23] Raging Bull can no longer push Princess onto player's cell --- monstermove.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monstermove.cpp b/monstermove.cpp index b19480b8..7cb0702d 100644 --- a/monstermove.cpp +++ b/monstermove.cpp @@ -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); } From ef5a870a78a53a4cdd74008358bc75086318f0d0 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Fri, 9 Jul 2021 22:50:17 -0700 Subject: [PATCH 17/23] Orbs no longer stun Mimics --- orbs.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/orbs.cpp b/orbs.cpp index c1f60d3e..28b4e118 100644 --- a/orbs.cpp +++ b/orbs.cpp @@ -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; } From 71088e9a1c8c9a94f78ecc9308de8961d90b39a1 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Fri, 9 Jul 2021 23:10:44 -0700 Subject: [PATCH 18/23] Add missing 'cannot attack' messages --- pcmove.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pcmove.cpp b/pcmove.cpp index e15a1d42..fb2c8f17 100644 --- a/pcmove.cpp +++ b/pcmove.cpp @@ -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!")); } From 252abda9ca6df0bdf707f4153a03dae66dac0f0c Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Fri, 9 Jul 2021 23:29:13 -0700 Subject: [PATCH 19/23] Autoplay improvements --- devmods/autoplay.cpp | 181 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 161 insertions(+), 20 deletions(-) diff --git a/devmods/autoplay.cpp b/devmods/autoplay.cpp index 2aeced11..8bee4c1c 100644 --- a/devmods/autoplay.cpp +++ b/devmods/autoplay.cpp @@ -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= 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); - items[itOrbYendor] &= 15; - again: - if(c2->cpdist > 1) { - for(int j=0; jtype; j++) - if(c2->move(j) && c2->move(j)->cpdist < c2->cpdist) { - c2 = c2->move(j); - goto again; - } + + // 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; + 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; } - cwt.spin = 0; - int d = neighborId(cwt.at, c2); - if(d >= 0 && movepcto(d, 1, false)) - println(hlog, "OK"); - else { - println(hlog, "NOK"); - killMonster(c2, moNone); - jumpTo(roKeyboard, c2, itNone, 0, moNone); + } 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) { + 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); + } + } 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; iland == 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; iitem == itBuggy || c->item == itBuggy2) { + printf("buggy item found\n"); + kills[moPlayer] = 0; + canmove = true; + doAutoplay = false; + } } if(buggyGeneration || isize(buggycells)) { From 5e3af36fe7a971ed2736a20b9530988625534ff3 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Sat, 10 Jul 2021 00:34:37 -0700 Subject: [PATCH 20/23] Command line help: add line breaks --- commandline.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/commandline.cpp b/commandline.cpp index ec90b7f8..c801ba87 100644 --- a/commandline.cpp +++ b/commandline.cpp @@ -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; From c67f9b72afc938df09bc02fee906f274b269c9b1 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Sat, 10 Jul 2021 02:32:13 -0700 Subject: [PATCH 21/23] Cave transformation is fairer to players --- attack.cpp | 3 ++- complex.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/attack.cpp b/attack.cpp index 26d34134..a51300bd 100644 --- a/attack.cpp +++ b/attack.cpp @@ -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; } } diff --git a/complex.cpp b/complex.cpp index 7648bc58..7db92443 100644 --- a/complex.cpp +++ b/complex.cpp @@ -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--; From 1f64daa03ffd5bd48efc69cd280a8426c1f07263 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Sat, 10 Jul 2021 02:50:29 -0700 Subject: [PATCH 22/23] Reversing the Curse of Water now gives bonus Orb of Winter --- orbs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/orbs.cpp b/orbs.cpp index 2e489cc6..c97cf394 100644 --- a/orbs.cpp +++ b/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]) { From 2b0af749036b17a661d0dfa24e7662f5e5c05546 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Sat, 10 Jul 2021 03:53:42 -0700 Subject: [PATCH 23/23] Fix some messages when using Orb of the Warp --- pcmove.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pcmove.cpp b/pcmove.cpp index fb2c8f17..dd3e052b 100644 --- a/pcmove.cpp +++ b/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!")); @@ -935,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!")