jevsnes.git / third-party / c / patches / 0016-hc-routines-already-done-in-open-mode.patch
0016-hc-routines-already-done-in-open-mode.patch56 lines · 2.9 KB · raw
1diff --git a/third-party/c/zbanks-alttp/ap_plan.c b/third-party/c/zbanks-alttp/ap_plan.c
2index 03f78390..a1b2c3e5 100644
3--- a/third-party/c/zbanks-alttp/ap_plan.c
4+++ b/third-party/c/zbanks-alttp/ap_plan.c
5@@ -911,6 +911,51 @@
6         //score += 1000;
7         break;
8     case GOAL_SCRIPT:
9+        // Carried patch (jev): every "HC " script exists only to progress
10+        // the castle rescue sequence (a guard's key, the miniboss guarding
11+        // Zelda's cell) - but the open-mode preset (zbanks::rando::PRESET)
12+        // sets sram_progress2's zelda_at_sanctuary bit (0x04) from frame 0,
13+        // so that sequence is already done before the bot ever moves. With
14+        // no gate, Jev was offered "HC kill guard for key" as a live
15+        // routine at 70% and the bot walked there, entered, and turned
16+        // around - the routine has nothing left to do. Evidence:
17+        // ../../research/zbanks-alttp.md, "Hyrule Castle routines are
18+        // already done in open mode".
19+        if (strncmp(goal->node->script->name, "HC ", 3) == 0 && (*ap_ram.sram_progress2 & 0x04)) {
20+            return GOAL_SCORE_UNSATISFIABLE;
21+        }
22+        // Carried patch (jev): general completion check for every routine,
23+        // not only the castle's - a routine's own screen already knows
24+        // whether its reward is claimed, the same way GOAL_CHEST's own
25+        // scoring reads sram_room_state. Jev picked "Blind's House Block
26+        // Puzzle" at 79% (frame 41857) with the room's own chests already
27+        // open: the routine has nothing left to solve. If a script's screen
28+        // has at least one chest node and every one of them already shows
29+        // its opened bit, the whole routine is complete - a puzzle with no
30+        // chest on its screen (AgTower's statues/curtain, the Kak well
31+        // jump) is untouched by this check, since has_chest stays false.
32+        // Evidence: ../../research/zbanks-alttp.md, "Never re-offer a
33+        // routine whose reward is already claimed".
34+        {
35+            bool has_chest = false;
36+            bool all_open = true;
37+            for (struct ap_node * n = goal->node->screen->node_list->next;
38+                 n != goal->node->screen->node_list; n = n->next) {
39+                if (n->type != NODE_CHEST) {
40+                    continue;
41+                }
42+                has_chest = true;
43+                assert(goal->node->screen->dungeon_room != (uint16_t) -1);
44+                uint16_t room_state = ap_ram.sram_room_state[goal->node->screen->dungeon_room];
45+                if (!(room_state & (1 << (n->tile_attr - 0x58 + 4)))) {
46+                    all_open = false;
47+                    break;
48+                }
49+            }
50+            if (has_chest && all_open) {
51+                return GOAL_SCORE_COMPLETE;
52+            }
53+        }
54         break;
55     case GOAL_EXPLORE:
56         //if (goal->node->screen->name[0] != 'H') {