1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
|
/* BUGS:
* Quarry colors are broken (specfically boathouse row 2 is translating wrong)
* Desert flood exit isn't off properly
* FEATURES:
* Randomize audio logs
* Randomize lasers
* Tackle remaining areas (Treehouse, Keep, Shadows, Town, Monastery, Jungle, Bunker, Swamp)
* Compile panel lists in a more reasonable way
* Separate panels out by "square", which can probably be anywhere
* List of panels which can be valid "Burn" (aka desert) substitutes: Prevent (or limit) panel counting
*/
#include "Memory.h"
#include "WitnessRandomizer.h"
#include <string>
#include <iostream>
int main(int argc, char** argv)
{
WitnessRandomizer randomizer = WitnessRandomizer();
//*
if (argc == 2) {
srand(atoi(argv[1])); // Seed with RNG from command line
}
std::vector<int> tutorialPanels = {
// 0x0A3B5, // Back Left
0x0A3B2, // Back Right
0x00295, // Center Left
0x00293, // Front Center
0x002C2, // Front Left
0x0C335, // Pillar
0x0C373, // Patio floor
};
randomizer.Randomize(tutorialPanels, SWAP_TARGETS);
std::vector<int> symmetryPanels = {
// 0x3C12B, // Glass Factory Discard
0x01A54, // Glass Factory Entry
0x00086, // Glass Factory Vertical Symmetry 1
0x00087, // Glass Factory Vertical Symmetry 2
0x00059, // Glass Factory Vertical Symmetry 3
0x00062, // Glass Factory Vertical Symmetry 4
0x0005C, // Glass Factory Vertical Symmetry 5
// 0x17CC8, // Glass Factory Summon Boat
0x0008D, // Glass Factory Rotational Symmetry 1
0x00081, // Glass Factory Rotational Symmetry 2
0x00083, // Glass Factory Rotational Symmetry 3
0x00084, // Glass Factory Melting 1
0x00082, // Glass Factory Melting 2
0x0343A, // Glass Factory Melting 3
0x000B0, // Symmetry Island Door 1
0x00022, // Symmetry Island Black Dots 1
0x00023, // Symmetry Island Black Dots 2
0x00024, // Symmetry Island Black Dots 3
0x00025, // Symmetry Island Black Dots 4
0x00026, // Symmetry Island Black Dots 5
0x0007C, // Symmetry Island Colored Dots 1
0x0007E, // Symmetry Island Colored Dots 2
0x00075, // Symmetry Island Colored Dots 3
0x00073, // Symmetry Island Colored Dots 4
0x00077, // Symmetry Island Colored Dots 5
0x00079, // Symmetry Island Colored Dots 6
0x00065, // Symmetry Island Fading Lines 1
0x0006D, // Symmetry Island Fading Lines 2
0x00072, // Symmetry Island Fading Lines 3
0x0006F, // Symmetry Island Fading Lines 4
0x00070, // Symmetry Island Fading Lines 5
0x00071, // Symmetry Island Fading Lines 6
0x00076, // Symmetry Island Fading Lines 7
// 0x009B8, // Symmetry Island Transparent 1 // Too mean for right now
// 0x003E8, // Symmetry Island Transparent 2 // Too mean for right now
// 0x00A15, // Symmetry Island Transparent 3 // Too mean for right now
// 0x00B53, // Symmetry Island Transparent 4 // Too mean for right now
// 0x00B8D, // Symmetry Island Transparent 5 // Too mean for right now
// 0x1C349, // Symmetry Island Door 2 - Collision fails here, sadly
0x00A52, // Symmetry Island Laser Yellow 1
0x00A57, // Symmetry Island Laser Yellow 2
0x00A5B, // Symmetry Island Laser Yellow 3
0x00A61, // Symmetry Island Laser Blue 1
0x00A64, // Symmetry Island Laser Blue 2
0x00A68, // Symmetry Island Laser Blue 3
// 0x0360D, // Symmetry Island Laser
};
randomizer.Randomize(symmetryPanels, SWAP_PATHWAYS | SWAP_COLORS);
std::vector<int> desertPanels = {
// 0x17CE7, // Desert Discard
// 0x0CC7B, // Desert Vault
// 0x0339E, // Desert Vault Box
0x00698, // Desert Surface 1
0x0048F, // Desert Surface 2
0x09F92, // Desert Surface 3
// 0x09FA0, // Desert Surface 3 Control
0x0A036, // Desert Surface 4
0x09DA6, // Desert Surface 5
0x0A049, // Desert Surface 6
0x0A053, // Desert Surface 7
0x09F94, // Desert Surface 8
// 0x09F86, // Desert Surface 8 Control
// 0x0C339, // Desert Surface Door
// 0x09FAA, // Desert Lightswitch
0x00422, // Desert Light 1
0x006E3, // Desert Light 2
// 0x0A02D, // Desert Light 3
0x00C72, // Desert Pond 1
0x0129D, // Desert Pond 2
0x008BB, // Desert Pond 3
0x0078D, // Desert Pond 4
0x18313, // Desert Pond 5
// 0x0A249, // Desert Pond Exit Door
// 0x1C2DF, // Desert Flood Control Lower Far Left
// 0x1831E, // Desert Flood Control Lower Far Right
// 0x1C260, // Desert Flood Control Lower Near Left
// 0x1831C, // Desert Flood Control Lower Near Right
// 0x1C2F3, // Desert Flood Control Raise Far Left
// 0x1831D, // Desert Flood Control Raise Far Right
// 0x1C2B1, // Desert Flood Control Raise Near Left
// 0x1831B, // Desert Flood Control Raise Near Right
0x04D18, // Desert Flood 1
0x01205, // Desert Flood 2
0x181AB, // Desert Flood 3
0x0117A, // Desert Flood 4
0x17ECA, // Desert Flood 5
// 0x18076, // Desert Flood Exit
// 0x0A15C, // Desert Final Left Convex
// 0x09FFF, // Desert Final Left Concave
// 0x0A15F, // Desert Final Near
// 0x17C31, // Desert Final Transparent
0x012D7, // Desert Final Far
// 0x0A015, // Desert Final Far Control
// 0x03608, // Desert Laser
};
randomizer.Randomize(desertPanels, SWAP_PATHWAYS);
std::vector<int> quarryPanels = {
0x01E5A, // Mill Entry Door Left
0x01E59, // Mill Entry Door Right
// 0x03678, // Mill Lower Ramp Contol
0x00E0C, // Mill Lower Row 1
0x01489, // Mill Lower Row 2
0x0148A, // Mill Lower Row 3
0x014D9, // Mill Lower Row 4
0x014E7, // Mill Lower Row 5
0x014E8, // Mill Lower Row 6
// 0x03679, // Mill Lower Lift Control
0x00557, // Mill Upper Row 1
0x005F1, // Mill Upper Row 2
0x00620, // Mill Upper Row 3
0x009F5, // Mill Upper Row 4
0x0146C, // Mill Upper Row 5
0x3C12D, // Mill Upper Row 6
0x03686, // Mill Upper Row 7
0x014E9, // Mill Upper Row 8
0x0367C, // Mill Control Room 1
// 0x03675, // Mill Upper Lift Control
// 0x03676, // Mill Upper Ramp Control
0x3C125, // Mill Control Room 2
// 0x275ED, // Mill EP Door
// 0x17CAC, // Mill Stairs Shortcut Door
0x03677, // Mill Stairs Control
// 0x17CF0, // Mill Discard
// 0x17CC4, // Mill Elevator Control
0x021D5, // Boathouse Ramp Activation Shapers
0x034D4, // Boathouse Ramp Activation Stars
// 0x03852, // Boathouse Ramp Angle Control
0x021B3, // Boathouse Erasers and Shapers 1
0x021B4, // Boathouse Erasers and Shapers 2
0x021B0, // Boathouse Erasers and Shapers 3
0x021AF, // Boathouse Erasers and Shapers 4
0x021AE, // Boathouse Erasers and Shapers 5
// 0x17CA6, // Boathouse Summon Boat
// 0x03858, // Boathouse Ramp Position Control
// 0x38663, // Boathouse Shortcut
0x021B5, // Boathouse Erasers and Stars 1
0x021B6, // Boathouse Erasers and Stars 2
0x021B7, // Boathouse Erasers and Stars 3
0x021BB, // Boathouse Erasers and Stars 4
0x09DB5, // Boathouse Erasers and Stars 5
0x09DB1, // Boathouse Erasers and Stars 6
0x3C124, // Boathouse Erasers and Stars 7
0x09DB3, // Boathouse Erasers Shapers and Stars 1
0x09DB4, // Boathouse Erasers Shapers and Stars 2
0x0A3CB, // Boathouse Erasers Shapers and Stars 3
0x0A3CC, // Boathouse Erasers Shapers and Stars 4
0x0A3D0, // Boathouse Erasers Shapers and Stars 5
// 0x275FA, // Boathouse Hook Control
0x09E57, // Quarry Entry Gate 1
0x17C09, // Quarry Entry Gate 2
// 0x03612, // Quarry Laser
};
randomizer.Randomize(quarryPanels, SWAP_PATHWAYS | SWAP_COLORS);
/*/
int MILL_L_1 = 0xE0C;
int MILL_U_1 = 0x557;
int QUARRY_E_1 = 0x9E57;
int QUARRY_E_2 = 0x17C09;
int MILL_E_1 = 0x1E5A;
randomizer.SwapPanels(QUARRY_E_2, MILL_E_1, SWAP_PATHWAYS | SWAP_COLORS);
//*/
}
WitnessRandomizer::WitnessRandomizer() : _memory(Memory("witness64_d3d11.exe"))
{
// Turn off desert flood final
_memory.WriteData<float>({0x5B28C0, 0x18, 0x18076*8, 0x2A8}, {0.0f});
// Change desert floating target to desert flood final
_memory.WriteData<int>({0x5B28C0, 0x18, 0x17ECA*8, 0x2BC}, {0x18077});
}
void WitnessRandomizer::Randomize(std::vector<int> panels, int flags) {
for (size_t i=panels.size() - 1; i > 1; i--) {
int target = rand() % i;
if (i != target) {
std::cout << "Swapping panels " << std::hex << panels[i] << " and " << std::hex << panels[target] << std::endl;
SwapPanels(panels[i], panels[target], flags);
std::swap(panels[i], panels[target]); // Panel indices in the array
}
}
}
void WitnessRandomizer::SwapPanels(int panel1, int panel2, int flags) {
std::map<int, int> offsets;
if (flags & SWAP_TARGETS) {
offsets[0x2BC] = sizeof(int);
}
if (flags & SWAP_PATHWAYS) {
offsets[0x3B8] = sizeof(int); // num_dots
offsets[0x3BC] = sizeof(int); // num_connections
offsets[0x3C8] = sizeof(void*); // *dot_positions
offsets[0x3D0] = sizeof(void*); // *dot_flags
offsets[0x3D8] = sizeof(void*); // *dot_connection_a
offsets[0x3E0] = sizeof(void*); // *dot_connection_b
offsets[0x440] = sizeof(void*); // *reflection_data
offsets[0x448] = sizeof(int); // grid_size_x
offsets[0x44C] = sizeof(int); // grid_size_y
offsets[0x450] = sizeof(int); // style_flags // This is required to not ignore dots
offsets[0x4B0] = sizeof(void*); // *panel_target
offsets[0x4D8] = sizeof(void*); // *specular_texture
offsets[0x420] = sizeof(void*); // *decorations
offsets[0x428] = sizeof(void*); // *decoration_flags
offsets[0x438] = sizeof(int); // num_decorations
offsets[0x45C] = sizeof(int); // sequence_len
offsets[0x460] = sizeof(void*); // *sequence
offsets[0x468] = sizeof(int); // dot_sequence_len
offsets[0x470] = sizeof(void*); // *dot_sequence
offsets[0x478] = sizeof(int); // dot_sequence_len_reflection
offsets[0x480] = sizeof(void*); // *dot_sequence_reflection
offsets[0x3A4] = sizeof(float); // path_width_scale
offsets[0x3A8] = sizeof(float); // startpoint_scale
// TODO: Try using is_cylinder to swap into tutorial pillar. If it fails, discard.
// Probably not: Extra back distance
// SwapPanelData(panels[i], panels[target], 0x2FC, 125); // is_cylinder through max_connections
}
if (flags & SWAP_STYLE) {
// 340 - pattern_scale
// 288 - flash_mode
}
if (flags & SWAP_COLORS) {
offsets[0xC8] = 16; // path_color
offsets[0xD8] = 16; // reflection_path_color
// offsets[0xE8] = 16; // deprecated_finished_path_color
offsets[0xF8] = 16; // dot_color
offsets[0x108] = 16; // active_color
offsets[0x118] = 16; // background_region_color
offsets[0x128] = 16; // success_color_a
offsets[0x138] = 16; // success_color_b
offsets[0x148] = 16; // strobe_color_a
offsets[0x158] = 16; // strobe_color_b
offsets[0x168] = 16; // error_color
// offsets[0x178] = 16; // video_status_color
offsets[0x188] = 16; // pattern_point_color
offsets[0x198] = 16; // pattern_point_color_a
offsets[0x1A8] = 16; // pattern_point_color_b
offsets[0x1B8] = 16; // symbol_a
offsets[0x1C8] = 16; // symbol_b
offsets[0x1D8] = 16; // symbol_c
offsets[0x1E8] = 16; // symbol_d
offsets[0x1F8] = 16; // symbol_e
offsets[0x208] = sizeof(int); // push_symbol_colors
offsets[0x20C] = 16; // outer_background
offsets[0x21C] = sizeof(int); // outer_background_mode
offsets[0x4A8] = sizeof(void*); // *colored_regions
}
if (flags & SWAP_TRACED) {
offsets[0x230] = 16; // traced_edges
}
for (auto const& [offset, size] : offsets) {
SwapPanelData(panel1, panel2, offset, size);
}
}
void WitnessRandomizer::SwapPanelData(int panel1, int panel2, int finalOffset, int dataSize) {
// Currently wired for old version
std::vector<int> panel1Offset = {0x5B28C0, 0x18, panel1*8, finalOffset};
std::vector<int> panel2Offset = {0x5B28C0, 0x18, panel2*8, finalOffset};
std::vector<byte> panel1Data = _memory.ReadData<byte>(panel1Offset, dataSize);
std::vector<byte> panel2Data = _memory.ReadData<byte>(panel2Offset, dataSize);
bool failed = _memory.WriteData<byte>(panel2Offset, panel1Data);
if (failed) {
_memory.WriteData<byte>(panel2Offset, panel1Data);
}
failed = _memory.WriteData<byte>(panel1Offset, panel2Data);
if (failed) {
_memory.WriteData<byte>(panel1Offset, panel2Data);
}
}
|