about summary refs log tree commit diff stats
path: root/WitnessRandomizer/WitnessRandomizer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WitnessRandomizer/WitnessRandomizer.cpp')
-rw-r--r--WitnessRandomizer/WitnessRandomizer.cpp175
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
24template <class T>
25int 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
21int main(int argc, char** argv) 32int 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
73WitnessRandomizer::WitnessRandomizer() : _memory("witness64_d3d11.exe") 88WitnessRandomizer::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
88void WitnessRandomizer::Randomize(std::vector<int> panels, int flags) { 114void WitnessRandomizer::Randomize(std::vector<int> &panels, int flags) {
115 return RandomizeRange(panels, flags, 0, panels.size());
116}
117
118// Range is [start, end)
119void 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/*
217void 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
230void 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
183void WitnessRandomizer::SwapPanelData(int panel1, int panel2, int finalOffset, int dataSize) { 246void 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
258void WitnessRandomizer::TurnOn(int panel) {
259 _memory.WriteData<float>({0x5B28C0, 0x18, panel*8, 0x2A8}, {1.0f, 1.0f});
260}
261
262void WitnessRandomizer::TurnOff(int panel) {
263 _memory.WriteData<float>({0x5B28C0, 0x18, panel*8, 0x2A8}, {0.0f, 0.0f});
264}