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 | } | ||
