diff options
Diffstat (limited to 'WitnessRandomizer/WitnessRandomizer.cpp')
-rw-r--r-- | WitnessRandomizer/WitnessRandomizer.cpp | 175 |
1 files changed, 123 insertions, 52 deletions
diff --git a/WitnessRandomizer/WitnessRandomizer.cpp b/WitnessRandomizer/WitnessRandomizer.cpp index 2a06ee2..70e4fb2 100644 --- a/WitnessRandomizer/WitnessRandomizer.cpp +++ b/WitnessRandomizer/WitnessRandomizer.cpp | |||
@@ -1,22 +1,33 @@ | |||
1 | /* | 1 | /* |
2 | * BUGS: | ||
3 | * 3-way in treehouse not working :( | ||
4 | * Mountain orange is copying movement data :( | ||
5 | * Treehouse panels are not copying color? | ||
2 | * FEATURES: | 6 | * FEATURES: |
3 | * SWAP_TARGETS should still require the full panel sequence (and have ways to prevent softlocks?) | 7 | * SWAP_TARGETS should still require the full panel sequence (and have ways to prevent softlocks?) |
4 | ** Jungle(?), Bunker, Monastery, Challenge(!), Shadows | 8 | ** Think about: Jungle |
9 | ** Hard: Monastery | ||
10 | ** Do: Challenge | ||
5 | * Randomize audio logs | 11 | * Randomize audio logs |
6 | * List of panels which split left/right (for left/right controls) | ||
7 | * List of panels which split up/down (for up/down controls) | ||
8 | * Swap sounds in jungle (along with panels) -- maybe impossible | 12 | * Swap sounds in jungle (along with panels) -- maybe impossible |
9 | * Make orange 7 (all of oranges?) hard. Like big = hard. | 13 | * Make orange 7 (all of oranges?) hard. Like big = hard. |
10 | * Kill panel slowdown in tutorial | 14 | * Kill panel slowdown in tutorial |
11 | * Fix desert elevator (laser rando) / Add keep? | 15 | * Fix desert elevator (laser rando) / Add keep? |
12 | * TRY: | ||
13 | * Swap treehouse pivots | ||
14 | */ | 16 | */ |
15 | #include "Memory.h" | 17 | #include "Memory.h" |
16 | #include "WitnessRandomizer.h" | 18 | #include "WitnessRandomizer.h" |
17 | #include "Panels.h" | 19 | #include "Panels.h" |
18 | #include <string> | 20 | #include <string> |
19 | #include <iostream> | 21 | #include <iostream> |
22 | #include <numeric> | ||
23 | |||
24 | template <class T> | ||
25 | int find(const std::vector<T> &data, T search, int startIndex = 0) { | ||
26 | for (int i=startIndex ; i<data.size(); i++) { | ||
27 | if (data[i] == search) return i; | ||
28 | } | ||
29 | return -1; | ||
30 | } | ||
20 | 31 | ||
21 | int main(int argc, char** argv) | 32 | int main(int argc, char** argv) |
22 | { | 33 | { |
@@ -24,60 +35,75 @@ int main(int argc, char** argv) | |||
24 | 35 | ||
25 | if (argc == 2) { | 36 | if (argc == 2) { |
26 | srand(atoi(argv[1])); // Seed with RNG from command line | 37 | srand(atoi(argv[1])); // Seed with RNG from command line |
38 | } else { | ||
39 | int seed = rand() % 1 << 16; | ||
40 | std::cout << "Selected seed:" << seed << std::endl; | ||
41 | srand(seed); | ||
27 | } | 42 | } |
28 | 43 | ||
29 | //* | 44 | |
30 | randomizer.Randomize(lasers, SWAP_TARGETS); | 45 | // Content swaps -- must happen before squarePanels |
31 | 46 | randomizer.Randomize(upDownPanels, SWAP_LINES | SWAP_STYLE); | |
32 | randomizer.Randomize(squarePanels, SWAP_LINES | SWAP_STYLE); | 47 | randomizer.Randomize(leftForwardRightPanels, SWAP_LINES | SWAP_STYLE); |
33 | randomizer.Randomize(burnablePanels, SWAP_LINES | SWAP_STYLE); | 48 | |
34 | 49 | randomizer.Randomize(squarePanels, SWAP_LINES | SWAP_STYLE); | |
35 | 50 | ||
36 | // randomizer.Randomize(monasteryPanels, SWAP_TARGETS); | 51 | // Frame swaps -- must happen after squarePanels |
37 | // randomizer.Randomize(shadowsPanels, SWAP_TARGETS); | 52 | randomizer.Randomize(burnablePanels, SWAP_LINES | SWAP_STYLE); |
38 | // randomizer.Randomize(bunkerPanels, SWAP_TARGETS); | 53 | |
39 | 54 | ||
40 | // randomizer.Randomize(junglePanels, SWAP_LINES | SWAP_STYLE); | 55 | // Target swaps, can happen whenever |
41 | // randomizer.Randomize(mountainMultipanel, SWAP_LINES | SWAP_STYLE); | 56 | randomizer.Randomize(lasers, SWAP_TARGETS); |
42 | // randomizer.Randomize(pillars, SWAP_LINES | SWAP_STYLE | SWAP_BACK_DISTANCE); | 57 | |
43 | 58 | std::vector<int> randomOrder = std::vector(junglePanels.size(), 0); | |
44 | /*/ | 59 | std::iota(randomOrder.begin(), randomOrder.end(), 0); |
45 | int BOATH_3_1 = 0x21B5; | 60 | // Randomize Waves 2-7 |
46 | int MILL_L_1 = 0xE0C; | 61 | // Waves 1 cannot be randomized, since no other panel can start on |
47 | int MILL_U_1 = 0x557; | 62 | randomizer.RandomizeRange(randomOrder, SWAP_NONE, 1, 7); |
48 | int QUARRY_E_1 = 0x9E57; | 63 | // Randomize Pitches 1-6 onto themselves |
49 | int QUARRY_E_2 = 0x17C09; | 64 | randomizer.RandomizeRange(randomOrder, SWAP_NONE, 7, 13); |
50 | int MILL_E_1 = 0x1E5A; | 65 | randomizer.ReassignTargets(junglePanels, randomOrder); |
51 | int BUNKER_G_1 = 0xA010; | 66 | |
52 | int BUNKER_T_1 = 0x9F7D; | 67 | randomOrder = std::vector(bunkerPanels.size(), 0); |
53 | int TUT_PILLAR = 0xC335; | 68 | std::iota(randomOrder.begin(), randomOrder.end(), 0); |
54 | int TUT_F_C = 0x293; | 69 | // Randomize Tutorial 2-Advanced Tutorial 4 + Glass 1 |
55 | int PILLAR_L_1 = 0x383D; | 70 | // Tutorial 1 cannot be randomized, since no other panel can start on |
56 | int PILLAR_L_4 = 0x339BB; | 71 | // Glass 1 will become door + glass 1, due to the targetting system |
57 | int PILLAR_C = 0x9DD5; | 72 | randomizer.RandomizeRange(randomOrder, SWAP_NONE, 1, 10); |
58 | int PILLAR_C_L = 0x1C31A; | 73 | // Randomize Glass 1-3 into everything after the door |
59 | int DESERT_1 = 0x00698; | 74 | int glassDoorIndex = find(randomOrder, 9) + 1; |
60 | int DESERT_L_2 = 0x006E3; | 75 | randomizer.RandomizeRange(randomOrder, SWAP_NONE, glassDoorIndex, 12); |
61 | int TOWN_S_1 = 0x28AC7; | 76 | randomizer.ReassignTargets(bunkerPanels, randomOrder); |
62 | 77 | ||
63 | 78 | randomOrder = std::vector(shadowsPanels.size(), 0); | |
64 | //randomizer.SwapPanels(PILLAR_L_1, PILLAR_C_L, SWAP_LINES | SWAP_STYLE | SWAP_BACK_DISTANCE); | 79 | std::iota(randomOrder.begin(), randomOrder.end(), 0); |
65 | //randomizer.SwapPanelData(PILLAR_L_1, PILLAR_C_L, 0x200, 0x50); | 80 | randomizer.RandomizeRange(randomOrder, SWAP_NONE, 0, 8); // Tutorial |
66 | // Turn on the panel | 81 | randomizer.RandomizeRange(randomOrder, SWAP_NONE, 8, 16); // Avoid |
67 | //randomizer._memory.WriteData<float>({0x5B28C0, 0x18, PILLAR_L_1*8, 0x2A8}, {1.0f, 1.0f}); | 82 | randomizer.RandomizeRange(randomOrder, SWAP_NONE, 16, 21); // Follow |
68 | 83 | randomizer.ReassignTargets(shadowsPanels, randomOrder); | |
69 | // randomizer.SwapPanels(PILLAR_L_1, PILLAR_C_L, SWAP_LINES | SWAP_STYLE | SWAP_BACK_DISTANCE); | 84 | randomizer.TurnOff(shadowsPanels[0]); |
70 | //*/ | 85 | randomizer.TurnOn(shadowsPanels[randomOrder[0]]); |
71 | } | 86 | } |
72 | 87 | ||
73 | WitnessRandomizer::WitnessRandomizer() : _memory("witness64_d3d11.exe") | 88 | WitnessRandomizer::WitnessRandomizer() : _memory("witness64_d3d11.exe") |
74 | { | 89 | { |
75 | // Turn off desert flood final | 90 | // Turn off desert flood final |
76 | _memory.WriteData<float>({0x5B28C0, 0x18, 0x18076*8, 0x2A8}, {0.0f, 0.0f}); | 91 | TurnOff(0x18076); |
77 | // Change desert floating target to desert flood final | 92 | // Change desert floating target to desert flood final |
78 | _memory.WriteData<int>({0x5B28C0, 0x18, 0x17ECA*8, 0x2BC}, {0x18077}); | 93 | _memory.WriteData<int>({0x5B28C0, 0x18, 0x17ECA*8, 0x2BC}, {0x18077}); |
79 | // Distance-gate shadows laser to prevent sniping through the bars | 94 | // Distance-gate shadows laser to prevent sniping through the bars |
80 | _memory.WriteData<float>({0x5B28C0, 0x18, 0x19650*8, 0x3C0}, {2.0f}); | 95 | _memory.WriteData<float>({0x5B28C0, 0x18, 0x19650*8, 0x3C0}, {2.5f}); |
96 | // Change the shadows tutorial cable to only activate avoid | ||
97 | _memory.WriteData<int>({0x5B28C0, 0x18, 0x319A8*8, 0xD8}, {0}); | ||
98 | // Change shadows avoid 8 to power shadows follow | ||
99 | _memory.WriteData<int>({0x5B28C0, 0x18, 0x1972F*8, 0x2BC}, {0x1C34C}); | ||
100 | // Disable tutorial cursor speed modifications | ||
101 | _memory.WriteData<float>({0x5B28C0, 0x18, 0x00295*8, 0x358}, {1.0}); | ||
102 | _memory.WriteData<float>({0x5B28C0, 0x18, 0x0C373*8, 0x358}, {1.0}); | ||
103 | _memory.WriteData<float>({0x5B28C0, 0x18, 0x00293*8, 0x358}, {1.0}); | ||
104 | _memory.WriteData<float>({0x5B28C0, 0x18, 0x002C2*8, 0x358}, {1.0}); | ||
105 | |||
106 | |||
81 | 107 | ||
82 | // Explicitly set back-off distance for the challenge entry & final 2 pillars | 108 | // Explicitly set back-off distance for the challenge entry & final 2 pillars |
83 | // _memory.WriteData<float>({0x5B28C0, 0x18, 0x9DD5*8, 0x22C}, {2.5f}); | 109 | // _memory.WriteData<float>({0x5B28C0, 0x18, 0x9DD5*8, 0x22C}, {2.5f}); |
@@ -85,10 +111,17 @@ WitnessRandomizer::WitnessRandomizer() : _memory("witness64_d3d11.exe") | |||
85 | // _memory.WriteData<float>({0x5B28C0, 0x18, 0x1C319*8, 0x22C}, {3.0f}); | 111 | // _memory.WriteData<float>({0x5B28C0, 0x18, 0x1C319*8, 0x22C}, {3.0f}); |
86 | } | 112 | } |
87 | 113 | ||
88 | void WitnessRandomizer::Randomize(std::vector<int> panels, int flags) { | 114 | void WitnessRandomizer::Randomize(std::vector<int> &panels, int flags) { |
115 | return RandomizeRange(panels, flags, 0, panels.size()); | ||
116 | } | ||
117 | |||
118 | // Range is [start, end) | ||
119 | void WitnessRandomizer::RandomizeRange(std::vector<int> &panels, int flags, size_t startIndex, size_t endIndex) { | ||
89 | if (panels.size() == 0) return; | 120 | if (panels.size() == 0) return; |
90 | for (size_t i=panels.size() - 1; i > 1; i--) { | 121 | if (startIndex >= endIndex) return; |
91 | int target = rand() % i; | 122 | if (endIndex >= panels.size()) endIndex = panels.size(); |
123 | for (size_t i = endIndex-1; i > startIndex+1; i--) { | ||
124 | size_t target = rand() % (i - startIndex) + startIndex; | ||
92 | if (i != target) { | 125 | if (i != target) { |
93 | // std::cout << "Swapping panels " << std::hex << panels[i] << " and " << std::hex << panels[target] << std::endl; | 126 | // std::cout << "Swapping panels " << std::hex << panels[i] << " and " << std::hex << panels[target] << std::endl; |
94 | SwapPanels(panels[i], panels[target], flags); | 127 | SwapPanels(panels[i], panels[target], flags); |
@@ -180,6 +213,36 @@ void WitnessRandomizer::SwapPanels(int panel1, int panel2, int flags) { | |||
180 | } | 213 | } |
181 | } | 214 | } |
182 | 215 | ||
216 | /* | ||
217 | void WitnessRandomizer::SwapTargetList(const std::vector<int>& initialOrder, const std::vector<int>& randomizedOrder) { | ||
218 | std::vector<std::vector<int>> randomizedTargets; | ||
219 | for (int panel : randomizedOrder) { | ||
220 | randomizedTargets.push_back(_memory.ReadData<int>({0x5B28C0, 0x18, panel*8, 0x2BC}, 1)); | ||
221 | } | ||
222 | for (int i=0; i<initialOrder.size(); i++) { | ||
223 | int panel = initialOrder[i]; | ||
224 | std::vector<int> target = randomizedTargets[i]; | ||
225 | _memory.WriteData<int>({0x5B28C0, 0x18, panel*8, 0x2BC}, target); | ||
226 | } | ||
227 | } | ||
228 | */ | ||
229 | |||
230 | void WitnessRandomizer::ReassignTargets(const std::vector<int>& panels, const std::vector<int>& order) { | ||
231 | std::vector<int> targetToActivatePanel = {panels[0] + 1}; | ||
232 | for (int panel : panels) { | ||
233 | int target = _memory.ReadData<int>({0x5B28C0, 0x18, panel*8, 0x2BC}, 1)[0]; | ||
234 | targetToActivatePanel.push_back(target); | ||
235 | } | ||
236 | |||
237 | for (int i=0; i<order.size() - 1; i++) { | ||
238 | // order[i+1] is the target panel | ||
239 | // order[i+1] - 1 is the (real) panel before the target panel | ||
240 | // targets[order[i+1] - 1] is the (real) target which will activate the target panel | ||
241 | int panelTarget = targetToActivatePanel[order[i+1]]; | ||
242 | _memory.WriteData<int>({0x5B28C0, 0x18, panels[order[i]]*8, 0x2BC}, {panelTarget}); | ||
243 | } | ||
244 | } | ||
245 | |||
183 | void WitnessRandomizer::SwapPanelData(int panel1, int panel2, int finalOffset, int dataSize) { | 246 | void WitnessRandomizer::SwapPanelData(int panel1, int panel2, int finalOffset, int dataSize) { |
184 | // Currently wired for old version | 247 | // Currently wired for old version |
185 | std::vector<int> panel1Offset = {0x5B28C0, 0x18, panel1*8, finalOffset}; | 248 | std::vector<int> panel1Offset = {0x5B28C0, 0x18, panel1*8, finalOffset}; |
@@ -191,3 +254,11 @@ void WitnessRandomizer::SwapPanelData(int panel1, int panel2, int finalOffset, i | |||
191 | _memory.WriteData<byte>(panel2Offset, panel1Data); | 254 | _memory.WriteData<byte>(panel2Offset, panel1Data); |
192 | _memory.WriteData<byte>(panel1Offset, panel2Data); | 255 | _memory.WriteData<byte>(panel1Offset, panel2Data); |
193 | } | 256 | } |
257 | |||
258 | void WitnessRandomizer::TurnOn(int panel) { | ||
259 | _memory.WriteData<float>({0x5B28C0, 0x18, panel*8, 0x2A8}, {1.0f, 1.0f}); | ||
260 | } | ||
261 | |||
262 | void WitnessRandomizer::TurnOff(int panel) { | ||
263 | _memory.WriteData<float>({0x5B28C0, 0x18, panel*8, 0x2A8}, {0.0f, 0.0f}); | ||
264 | } | ||