diff options
Diffstat (limited to 'Source/Randomizer.cpp')
-rw-r--r-- | Source/Randomizer.cpp | 106 |
1 files changed, 54 insertions, 52 deletions
diff --git a/Source/Randomizer.cpp b/Source/Randomizer.cpp index 8833078..3cc2712 100644 --- a/Source/Randomizer.cpp +++ b/Source/Randomizer.cpp | |||
@@ -1,16 +1,13 @@ | |||
1 | /* | 1 | /* |
2 | * BUGS: | 2 | * BUGS: |
3 | * Shipwreck vault is solved reversed? | 3 | * Shipwreck vault is solved reversed? -> Not reversed, just "half", you can normally solve orange. Seems to need pattern name. |
4 | * Swamp <-> symmetry has non-invisible background | 4 | * Tutorial sounds don't always play -> Unsure. Not controlled by pattern name. |
5 | * Tutorial sounds don't always play | ||
6 | * FEATURES: | 5 | * FEATURES: |
7 | * Clear "Randomized" button after short delay | ||
8 | * Randomize audio logs -- Hard, seem to be unloaded some times? | 6 | * Randomize audio logs -- Hard, seem to be unloaded some times? |
9 | * Swap sounds in jungle (along with panels) -- maybe impossible | 7 | * Swap sounds in jungle (along with panels) -- maybe impossible |
10 | * Make orange 7 (all of oranges?) hard. Like big = hard. | 8 | * Make orange 7 (all of oranges?) hard. Like big = hard. (See: HARD_MODE) |
11 | * Start the game if it isn't running? | 9 | * Start the game if it isn't running? |
12 | * Stop swapping colors in desert | 10 | * Stop swapping colors in desert |
13 | * Allow users to enter seed after randomly generating seed (aka detect user input in the text box) | ||
14 | */ | 11 | */ |
15 | #include "Memory.h" | 12 | #include "Memory.h" |
16 | #include "Randomizer.h" | 13 | #include "Randomizer.h" |
@@ -29,15 +26,21 @@ int find(const std::vector<T> &data, T search, size_t startIndex = 0) { | |||
29 | exit(-1); | 26 | exit(-1); |
30 | } | 27 | } |
31 | 28 | ||
32 | short Randomizer::Randomize(int seed) | 29 | bool Randomizer::GameIsRandomized() { |
33 | { | 30 | int currentFrame = _core.GetCurrentFrame(); |
34 | short metadata = _core.ReadMetadata(); | 31 | if (currentFrame >= _lastRandomizedFrame) { |
35 | if (metadata & 0x1) { | 32 | // Time went forwards, presumably we're still on the same save |
36 | // Already randomized -- exit. | 33 | _lastRandomizedFrame = currentFrame; |
37 | return metadata; | 34 | return true; |
38 | } | 35 | } |
39 | _core.WriteMetadata(metadata | 0x1); | 36 | // Otherwise, time has gone backwards, so assume new game |
40 | Random::SetSeed(seed); | 37 | return false; |
38 | } | ||
39 | |||
40 | void Randomizer::Randomize() | ||
41 | { | ||
42 | if (GameIsRandomized()) return; // Nice sanity check, but should be unnecessary (since Main checks anyways) | ||
43 | _lastRandomizedFrame = _core.GetCurrentFrame(); | ||
41 | 44 | ||
42 | // Content swaps -- must happen before squarePanels | 45 | // Content swaps -- must happen before squarePanels |
43 | _core.Randomize(upDownPanels, SWAP_LINES); | 46 | _core.Randomize(upDownPanels, SWAP_LINES); |
@@ -61,24 +64,23 @@ short Randomizer::Randomize(int seed) | |||
61 | RandomizeMountain(); | 64 | RandomizeMountain(); |
62 | // RandomizeChallenge(); | 65 | // RandomizeChallenge(); |
63 | // RandomizeAudioLogs(); | 66 | // RandomizeAudioLogs(); |
64 | return metadata; | ||
65 | } | 67 | } |
66 | 68 | ||
67 | void Randomizer::AdjustSpeed() { | 69 | void Randomizer::AdjustSpeed() { |
68 | // Desert Surface Final Control | 70 | // Desert Surface Final Control |
69 | _core._memory.WritePanelData<float>(0x09F95, OPEN_RATE, {0.04f}); // 4x | 71 | _core._memory->WritePanelData<float>(0x09F95, OPEN_RATE, {0.04f}); // 4x |
70 | // Swamp Sliding Bridge | 72 | // Swamp Sliding Bridge |
71 | _core._memory.WritePanelData<float>(0x0061A, OPEN_RATE, {0.1f}); // 4x | 73 | _core._memory->WritePanelData<float>(0x0061A, OPEN_RATE, {0.1f}); // 4x |
72 | // Mountain 2 Elevator | 74 | // Mountain 2 Elevator |
73 | _core._memory.WritePanelData<float>(0x09EEC, OPEN_RATE, {0.075f}); // 3x | 75 | _core._memory->WritePanelData<float>(0x09EEC, OPEN_RATE, {0.075f}); // 3x |
74 | } | 76 | } |
75 | 77 | ||
76 | void Randomizer::RandomizeTutorial() { | 78 | void Randomizer::RandomizeTutorial() { |
77 | // Disable tutorial cursor speed modifications (not working?) | 79 | // Disable tutorial cursor speed modifications (not working?) |
78 | _core._memory.WritePanelData<float>(0x00295, CURSOR_SPEED_SCALE, {1.0}); | 80 | _core._memory->WritePanelData<float>(0x00295, CURSOR_SPEED_SCALE, {1.0}); |
79 | _core._memory.WritePanelData<float>(0x0C373, CURSOR_SPEED_SCALE, {1.0}); | 81 | _core._memory->WritePanelData<float>(0x0C373, CURSOR_SPEED_SCALE, {1.0}); |
80 | _core._memory.WritePanelData<float>(0x00293, CURSOR_SPEED_SCALE, {1.0}); | 82 | _core._memory->WritePanelData<float>(0x00293, CURSOR_SPEED_SCALE, {1.0}); |
81 | _core._memory.WritePanelData<float>(0x002C2, CURSOR_SPEED_SCALE, {1.0}); | 83 | _core._memory->WritePanelData<float>(0x002C2, CURSOR_SPEED_SCALE, {1.0}); |
82 | } | 84 | } |
83 | 85 | ||
84 | void Randomizer::RandomizeSymmetry() { | 86 | void Randomizer::RandomizeSymmetry() { |
@@ -88,11 +90,11 @@ void Randomizer::RandomizeDesert() { | |||
88 | _core.Randomize(desertPanels, SWAP_LINES); | 90 | _core.Randomize(desertPanels, SWAP_LINES); |
89 | 91 | ||
90 | // Turn off desert surface 8 | 92 | // Turn off desert surface 8 |
91 | _core._memory.WritePanelData<float>(0x09F94, POWER, {0.0, 0.0}); | 93 | _core._memory->WritePanelData<float>(0x09F94, POWER, {0.0, 0.0}); |
92 | // Turn off desert flood final | 94 | // Turn off desert flood final |
93 | _core._memory.WritePanelData<float>(0x18076, POWER, {0.0, 0.0}); | 95 | _core._memory->WritePanelData<float>(0x18076, POWER, {0.0, 0.0}); |
94 | // Change desert floating target to desert flood final | 96 | // Change desert floating target to desert flood final |
95 | _core._memory.WritePanelData<int>(0x17ECA, TARGET, {0x18077}); | 97 | _core._memory->WritePanelData<int>(0x17ECA, TARGET, {0x18077}); |
96 | } | 98 | } |
97 | 99 | ||
98 | void Randomizer::RandomizeQuarry() { | 100 | void Randomizer::RandomizeQuarry() { |
@@ -100,14 +102,14 @@ void Randomizer::RandomizeQuarry() { | |||
100 | 102 | ||
101 | void Randomizer::RandomizeTreehouse() { | 103 | void Randomizer::RandomizeTreehouse() { |
102 | // Ensure that whatever pivot panels we have are flagged as "pivotable" | 104 | // Ensure that whatever pivot panels we have are flagged as "pivotable" |
103 | int panelFlags = _core._memory.ReadPanelData<int>(0x17DD1, STYLE_FLAGS, 1)[0]; | 105 | int panelFlags = _core._memory->ReadPanelData<int>(0x17DD1, STYLE_FLAGS, 1)[0]; |
104 | _core._memory.WritePanelData<int>(0x17DD1, STYLE_FLAGS, {panelFlags | 0x8000}); | 106 | _core._memory->WritePanelData<int>(0x17DD1, STYLE_FLAGS, {panelFlags | 0x8000}); |
105 | panelFlags = _core._memory.ReadPanelData<int>(0x17CE3, STYLE_FLAGS, 1)[0]; | 107 | panelFlags = _core._memory->ReadPanelData<int>(0x17CE3, STYLE_FLAGS, 1)[0]; |
106 | _core._memory.WritePanelData<int>(0x17CE3, STYLE_FLAGS, {panelFlags | 0x8000}); | 108 | _core._memory->WritePanelData<int>(0x17CE3, STYLE_FLAGS, {panelFlags | 0x8000}); |
107 | panelFlags = _core._memory.ReadPanelData<int>(0x17DB7, STYLE_FLAGS, 1)[0]; | 109 | panelFlags = _core._memory->ReadPanelData<int>(0x17DB7, STYLE_FLAGS, 1)[0]; |
108 | _core._memory.WritePanelData<int>(0x17DB7, STYLE_FLAGS, {panelFlags | 0x8000}); | 110 | _core._memory->WritePanelData<int>(0x17DB7, STYLE_FLAGS, {panelFlags | 0x8000}); |
109 | panelFlags = _core._memory.ReadPanelData<int>(0x17E52, STYLE_FLAGS, 1)[0]; | 111 | panelFlags = _core._memory->ReadPanelData<int>(0x17E52, STYLE_FLAGS, 1)[0]; |
110 | _core._memory.WritePanelData<int>(0x17E52, STYLE_FLAGS, {panelFlags | 0x8000}); | 112 | _core._memory->WritePanelData<int>(0x17E52, STYLE_FLAGS, {panelFlags | 0x8000}); |
111 | } | 113 | } |
112 | 114 | ||
113 | void Randomizer::RandomizeKeep() { | 115 | void Randomizer::RandomizeKeep() { |
@@ -115,11 +117,11 @@ void Randomizer::RandomizeKeep() { | |||
115 | 117 | ||
116 | void Randomizer::RandomizeShadows() { | 118 | void Randomizer::RandomizeShadows() { |
117 | // Distance-gate shadows laser to prevent sniping through the bars | 119 | // Distance-gate shadows laser to prevent sniping through the bars |
118 | _core._memory.WritePanelData<float>(0x19650, MAX_BROADCAST_DISTANCE, {2.5}); | 120 | _core._memory->WritePanelData<float>(0x19650, MAX_BROADCAST_DISTANCE, {2.5}); |
119 | // Change the shadows tutorial cable to only activate avoid | 121 | // Change the shadows tutorial cable to only activate avoid |
120 | _core._memory.WritePanelData<int>(0x319A8, CABLE_TARGET_2, {0}); | 122 | _core._memory->WritePanelData<int>(0x319A8, CABLE_TARGET_2, {0}); |
121 | // Change shadows avoid 8 to power shadows follow | 123 | // Change shadows avoid 8 to power shadows follow |
122 | _core._memory.WritePanelData<int>(0x1972F, TARGET, {0x1C34C}); | 124 | _core._memory->WritePanelData<int>(0x1972F, TARGET, {0x1C34C}); |
123 | 125 | ||
124 | std::vector<int> randomOrder(shadowsPanels.size(), 0); | 126 | std::vector<int> randomOrder(shadowsPanels.size(), 0); |
125 | std::iota(randomOrder.begin(), randomOrder.end(), 0); | 127 | std::iota(randomOrder.begin(), randomOrder.end(), 0); |
@@ -128,9 +130,9 @@ void Randomizer::RandomizeShadows() { | |||
128 | _core.RandomizeRange(randomOrder, SWAP_NONE, 16, 21); // Follow | 130 | _core.RandomizeRange(randomOrder, SWAP_NONE, 16, 21); // Follow |
129 | _core.ReassignTargets(shadowsPanels, randomOrder); | 131 | _core.ReassignTargets(shadowsPanels, randomOrder); |
130 | // Turn off original starting panel | 132 | // Turn off original starting panel |
131 | _core._memory.WritePanelData<float>(shadowsPanels[0], POWER, {0.0f, 0.0f}); | 133 | _core._memory->WritePanelData<float>(shadowsPanels[0], POWER, {0.0f, 0.0f}); |
132 | // Turn on new starting panel | 134 | // Turn on new starting panel |
133 | _core._memory.WritePanelData<float>(shadowsPanels[randomOrder[0]], POWER, {1.0f, 1.0f}); | 135 | _core._memory->WritePanelData<float>(shadowsPanels[randomOrder[0]], POWER, {1.0f, 1.0f}); |
134 | } | 136 | } |
135 | 137 | ||
136 | void Randomizer::RandomizeTown() { | 138 | void Randomizer::RandomizeTown() { |
@@ -167,7 +169,7 @@ void Randomizer::RandomizeJungle() { | |||
167 | 169 | ||
168 | void Randomizer::RandomizeSwamp() { | 170 | void Randomizer::RandomizeSwamp() { |
169 | // Distance-gate swamp snipe 1 to prevent RNG swamp snipe | 171 | // Distance-gate swamp snipe 1 to prevent RNG swamp snipe |
170 | _core._memory.WritePanelData<float>(0x17C05, MAX_BROADCAST_DISTANCE, {15.0}); | 172 | _core._memory->WritePanelData<float>(0x17C05, MAX_BROADCAST_DISTANCE, {15.0}); |
171 | } | 173 | } |
172 | 174 | ||
173 | void Randomizer::RandomizeMountain() { | 175 | void Randomizer::RandomizeMountain() { |
@@ -178,7 +180,7 @@ void Randomizer::RandomizeMountain() { | |||
178 | // Randomize final pillars order | 180 | // Randomize final pillars order |
179 | std::vector<int> targets = {pillars[0] + 1}; | 181 | std::vector<int> targets = {pillars[0] + 1}; |
180 | for (const int pillar : pillars) { | 182 | for (const int pillar : pillars) { |
181 | int target = _core._memory.ReadPanelData<int>(pillar, TARGET, 1)[0]; | 183 | int target = _core._memory->ReadPanelData<int>(pillar, TARGET, 1)[0]; |
182 | targets.push_back(target); | 184 | targets.push_back(target); |
183 | } | 185 | } |
184 | targets[5] = pillars[5] + 1; | 186 | targets[5] = pillars[5] + 1; |
@@ -189,27 +191,27 @@ void Randomizer::RandomizeMountain() { | |||
189 | _core.RandomizeRange(randomOrder, SWAP_NONE, 5, 9); // Right Pillars 1-4 | 191 | _core.RandomizeRange(randomOrder, SWAP_NONE, 5, 9); // Right Pillars 1-4 |
190 | _core.ReassignTargets(pillars, randomOrder, targets); | 192 | _core.ReassignTargets(pillars, randomOrder, targets); |
191 | // Turn off original starting panels | 193 | // Turn off original starting panels |
192 | _core._memory.WritePanelData<float>(pillars[0], POWER, {0.0f, 0.0f}); | 194 | _core._memory->WritePanelData<float>(pillars[0], POWER, {0.0f, 0.0f}); |
193 | _core._memory.WritePanelData<float>(pillars[5], POWER, {0.0f, 0.0f}); | 195 | _core._memory->WritePanelData<float>(pillars[5], POWER, {0.0f, 0.0f}); |
194 | // Turn on new starting panels | 196 | // Turn on new starting panels |
195 | _core._memory.WritePanelData<float>(pillars[randomOrder[0]], POWER, {1.0f, 1.0f}); | 197 | _core._memory->WritePanelData<float>(pillars[randomOrder[0]], POWER, {1.0f, 1.0f}); |
196 | _core._memory.WritePanelData<float>(pillars[randomOrder[5]], POWER, {1.0f, 1.0f}); | 198 | _core._memory->WritePanelData<float>(pillars[randomOrder[5]], POWER, {1.0f, 1.0f}); |
197 | 199 | ||
198 | // Read the target of keep front laser, and write it to keep back laser. | 200 | // Read the target of keep front laser, and write it to keep back laser. |
199 | std::vector<int> keepFrontLaserTarget = _core._memory.ReadPanelData<int>(0x0360E, TARGET, 1); | 201 | std::vector<int> keepFrontLaserTarget = _core._memory->ReadPanelData<int>(0x0360E, TARGET, 1); |
200 | _core._memory.WritePanelData<int>(0x03317, TARGET, keepFrontLaserTarget); | 202 | _core._memory->WritePanelData<int>(0x03317, TARGET, keepFrontLaserTarget); |
201 | } | 203 | } |
202 | 204 | ||
203 | void Randomizer::RandomizeChallenge() { | 205 | void Randomizer::RandomizeChallenge() { |
204 | std::vector<int> randomOrder(challengePanels.size(), 0); | 206 | std::vector<int> randomOrder(challengePanels.size(), 0); |
205 | std::iota(randomOrder.begin(), randomOrder.end(), 0); | 207 | std::iota(randomOrder.begin(), randomOrder.end(), 0); |
206 | _core.RandomizeRange(randomOrder, SWAP_NONE, 1, 9); // Easy maze - Triple 2 | 208 | _core.RandomizeRange(randomOrder, SWAP_NONE, 1, 9); // Easy maze - Triple 2 |
207 | std::vector<int> triple1Target = _core._memory.ReadPanelData<int>(0x00C80, TARGET, 1); | 209 | std::vector<int> triple1Target = _core._memory->ReadPanelData<int>(0x00C80, TARGET, 1); |
208 | _core._memory.WritePanelData<int>(0x00CA1, TARGET, triple1Target); | 210 | _core._memory->WritePanelData<int>(0x00CA1, TARGET, triple1Target); |
209 | _core._memory.WritePanelData<int>(0x00CB9, TARGET, triple1Target); | 211 | _core._memory->WritePanelData<int>(0x00CB9, TARGET, triple1Target); |
210 | std::vector<int> triple2Target = _core._memory.ReadPanelData<int>(0x00C22, TARGET, 1); | 212 | std::vector<int> triple2Target = _core._memory->ReadPanelData<int>(0x00C22, TARGET, 1); |
211 | _core._memory.WritePanelData<int>(0x00C59, TARGET, triple2Target); | 213 | _core._memory->WritePanelData<int>(0x00C59, TARGET, triple2Target); |
212 | _core._memory.WritePanelData<int>(0x00C68, TARGET, triple2Target); | 214 | _core._memory->WritePanelData<int>(0x00C68, TARGET, triple2Target); |
213 | _core.ReassignTargets(challengePanels, randomOrder); | 215 | _core.ReassignTargets(challengePanels, randomOrder); |
214 | } | 216 | } |
215 | 217 | ||