summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Source/Panels.h37
-rw-r--r--Source/Randomizer.cpp58
-rw-r--r--Source/Randomizer.h4
-rw-r--r--Source/RandomizerCore.cpp9
-rw-r--r--enc_temp_folder/39556c61ea71e3139a19e47cd4dbe2/RandomizerCore.cpp119
5 files changed, 189 insertions, 38 deletions
diff --git a/Source/Panels.h b/Source/Panels.h index b3a7791..2187d57 100644 --- a/Source/Panels.h +++ b/Source/Panels.h
@@ -34,10 +34,8 @@ std::vector<int> leftRightPanels = {
34 34
35// These panels are very tall (aka not square) and can't take symmetry panels on them. 35// These panels are very tall (aka not square) and can't take symmetry panels on them.
36std::vector<int> tallUpDownPanels = { 36std::vector<int> tallUpDownPanels = {
37 0x335AB, // UTM In Elevator Control
38 0x3369D, // UTM Lower Elevator Control
39 0x335AC, // UTM Upper Elevator Control
40 0x09EEB, // Mountain 2 Elevator 37 0x09EEB, // Mountain 2 Elevator
38 0x17CC4, // Mill Elevator Control
41}; 39};
42 40
43// Note: Some of these (non-controls) are duplicated elsewhere 41// Note: Some of these (non-controls) are duplicated elsewhere
@@ -57,6 +55,9 @@ std::vector<int> upDownPanels = {
57 55
58 0x0A3B5, // Tutorial Back Left 56 0x0A3B5, // Tutorial Back Left
59 0x17CC4, // Mill Elevator Control 57 0x17CC4, // Mill Elevator Control
58// 0x335AB, // UTM In Elevator Control
59// 0x3369D, // UTM Lower Elevator Control
60// 0x335AC, // UTM Upper Elevator Control
60}; 61};
61 62
62// Note: Some of these (non-controls) are duplicated elsewhere 63// Note: Some of these (non-controls) are duplicated elsewhere
@@ -81,9 +82,33 @@ std::vector<int> pillars = {
81 0x09E56, // Mountain 3 Right Pillar 2 82 0x09E56, // Mountain 3 Right Pillar 2
82 0x09E5A, // Mountain 3 Right Pillar 3 83 0x09E5A, // Mountain 3 Right Pillar 3
83 0x33961, // Mountain 3 Right Pillar 4 84 0x33961, // Mountain 3 Right Pillar 4
84 0x09DD5, // UTM Challenge Pillar 85// 0x09DD5, // UTM Challenge Pillar
85// 0x1C31A, // Challenge Left Pillar 86};
86// 0x1C319, // Challenge Right Pillar 87
88std::vector<int> challengePanels = {
89 0x0A332, // Challenge Record Start
90 0x0088E, // Challenge Easy Maze
91 0x00BAF, // Challenge Hard Maze
92 0x00BF3, // Challenge Stones Maze
93 0x00C09, // Challenge Pedestal
94 0x0051F, // Challenge Column Bottom Left
95 0x00524, // Challenge Column Top Right
96 0x00CDB, // Challenge Column Top Left
97 0x00CD4, // Challenge Column Far Panel
98 0x00C80, // Challenge Triple 1 Left
99// 0x00CA1, // Challenge Triple 1 Center
100// 0x00CB9, // Challenge Triple 1 Right
101 0x00C22, // Challenge Triple 2 Left
102// 0x00C59, // Challenge Triple 2 Center
103// 0x00C68, // Challenge Triple 2 Right
104// 0x04CB3, // Challenge Left Timer
105// 0x04CB5, // Challenge Middle Timer
106// 0x04CB6, // Challenge Right Timer
107 0x034EC, // Challenge Triangle
108 0x034F4, // Challenge Triangle
109 0x1C31A, // Challenge Left Pillar
110 0x1C319, // Challenge Right Pillar
111// 0x0356B, // Challenge Vault Box
87}; 112};
88 113
89std::vector<int> mountainMultipanel = { 114std::vector<int> mountainMultipanel = {
diff --git a/Source/Randomizer.cpp b/Source/Randomizer.cpp index 8c4297d..6729ae7 100644 --- a/Source/Randomizer.cpp +++ b/Source/Randomizer.cpp
@@ -1,18 +1,15 @@
1/* 1/*
2 * TODO: Split out main() logic into another file, and move into separate functions for easier testing. Then write tests.
3 * BUGS: 2 * BUGS:
4 * Shipwreck vault fails, possibly because of dot_reflection? Sometimes? 3 * Shipwreck vault is solved reversed?
5 * Some panels are impossible casually: (idc, I think) 4 * Extra_back_distance to make pillar swaps work
6 ** Town Stars, Invisible dots 5 * Verify UTM perspective?
7 * FEATURES: 6 * FEATURES:
8 * SWAP_TARGETS should still require the full panel sequence (and have ways to prevent softlocks?) 7 * Challenge randomization
9 ** Do: Challenge
10 * Randomize audio logs 8 * Randomize audio logs
11 * Swap sounds in jungle (along with panels) -- maybe impossible 9 * Swap sounds in jungle (along with panels) -- maybe impossible
12 * Make orange 7 (all of oranges?) hard. Like big = hard. 10 * Make orange 7 (all of oranges?) hard. Like big = hard.
13 * Start the game if it isn't running? 11 * Start the game if it isn't running?
14 * UI for the randomizer :( 12 * Increase odds of mountain oranges garbage on other panels? [setting]
15 * Increase odds of mountain oranges garbage on other panels?
16*/ 13*/
17#include "Memory.h" 14#include "Memory.h"
18#include "Randomizer.h" 15#include "Randomizer.h"
@@ -34,11 +31,11 @@ int find(const std::vector<T> &data, T search, size_t startIndex = 0) {
34void Randomizer::Randomize() 31void Randomizer::Randomize()
35{ 32{
36 // Content swaps -- must happen before squarePanels 33 // Content swaps -- must happen before squarePanels
37 _core.Randomize(tallUpDownPanels, SWAP_LINES|SWAP_LINES); 34 _core.Randomize(tallUpDownPanels, SWAP_LINES);
38 _core.Randomize(upDownPanels, SWAP_LINES|SWAP_LINES); 35 _core.Randomize(upDownPanels, SWAP_LINES);
39 _core.Randomize(leftForwardRightPanels, SWAP_LINES|SWAP_LINES); 36 _core.Randomize(leftForwardRightPanels, SWAP_LINES);
40 37
41 _core.Randomize(squarePanels, SWAP_LINES|SWAP_LINES); 38 _core.Randomize(squarePanels, SWAP_LINES);
42 39
43 // Individual area modifications 40 // Individual area modifications
44 RandomizeTutorial(); 41 RandomizeTutorial();
@@ -54,6 +51,7 @@ void Randomizer::Randomize()
54 RandomizeJungle(); 51 RandomizeJungle();
55 RandomizeSwamp(); 52 RandomizeSwamp();
56 RandomizeMountain(); 53 RandomizeMountain();
54 // RandomizeChallenge();
57} 55}
58 56
59void Randomizer::RandomizeTutorial() { 57void Randomizer::RandomizeTutorial() {
@@ -68,7 +66,7 @@ void Randomizer::RandomizeSymmetry() {
68} 66}
69 67
70void Randomizer::RandomizeDesert() { 68void Randomizer::RandomizeDesert() {
71 _core.Randomize(desertPanels, SWAP_LINES|SWAP_LINES); 69 _core.Randomize(desertPanels, SWAP_LINES);
72 70
73 // Turn off desert surface 8 71 // Turn off desert surface 8
74 _core.WritePanelData<float>(0x09F94, POWER, {0.0, 0.0}); 72 _core.WritePanelData<float>(0x09F94, POWER, {0.0, 0.0});
@@ -83,10 +81,14 @@ void Randomizer::RandomizeQuarry() {
83 81
84void Randomizer::RandomizeTreehouse() { 82void Randomizer::RandomizeTreehouse() {
85 // Ensure that whatever pivot panels we have are flagged as "pivotable" 83 // Ensure that whatever pivot panels we have are flagged as "pivotable"
86 _core.WritePanelData<int>(0x17DD1, STYLE_FLAGS, {0x8000}); 84 int panelFlags = _core.ReadPanelData<int>(0x17DD1, STYLE_FLAGS, 1)[0];
87 _core.WritePanelData<int>(0x17CE3, STYLE_FLAGS, {0x8000}); 85 _core.WritePanelData<int>(0x17DD1, STYLE_FLAGS, {panelFlags | 0x8000});
88 _core.WritePanelData<int>(0x17DB7, STYLE_FLAGS, {0x8000}); 86 panelFlags = _core.ReadPanelData<int>(0x17CE3, STYLE_FLAGS, 1)[0];
89 _core.WritePanelData<int>(0x17E52, STYLE_FLAGS, {0x8000}); 87 _core.WritePanelData<int>(0x17CE3, STYLE_FLAGS, {panelFlags | 0x8000});
88 panelFlags = _core.ReadPanelData<int>(0x17DB7, STYLE_FLAGS, 1)[0];
89 _core.WritePanelData<int>(0x17DB7, STYLE_FLAGS, {panelFlags | 0x8000});
90 panelFlags = _core.ReadPanelData<int>(0x17E52, STYLE_FLAGS, 1)[0];
91 _core.WritePanelData<int>(0x17E52, STYLE_FLAGS, {panelFlags | 0x8000});
90} 92}
91 93
92void Randomizer::RandomizeKeep() { 94void Randomizer::RandomizeKeep() {
@@ -138,11 +140,9 @@ void Randomizer::RandomizeBunker() {
138void Randomizer::RandomizeJungle() { 140void Randomizer::RandomizeJungle() {
139 std::vector<int> randomOrder(junglePanels.size(), 0); 141 std::vector<int> randomOrder(junglePanels.size(), 0);
140 std::iota(randomOrder.begin(), randomOrder.end(), 0); 142 std::iota(randomOrder.begin(), randomOrder.end(), 0);
141 // Randomize Waves 2-7
142 // Waves 1 cannot be randomized, since no other panel can start on 143 // Waves 1 cannot be randomized, since no other panel can start on
143 _core.RandomizeRange(randomOrder, SWAP_NONE, 1, 7); 144 _core.RandomizeRange(randomOrder, SWAP_NONE, 1, 7); // Waves 2-7
144 // Randomize Pitches 1-6 onto themselves 145 _core.RandomizeRange(randomOrder, SWAP_NONE, 8, 13); // Pitches 1-6
145 _core.RandomizeRange(randomOrder, SWAP_NONE, 8, 13);
146 _core.ReassignTargets(junglePanels, randomOrder); 146 _core.ReassignTargets(junglePanels, randomOrder);
147} 147}
148 148
@@ -153,9 +153,23 @@ void Randomizer::RandomizeSwamp() {
153 153
154void Randomizer::RandomizeMountain() { 154void Randomizer::RandomizeMountain() {
155 _core.Randomize(lasers, SWAP_TARGETS); 155 _core.Randomize(lasers, SWAP_TARGETS);
156 _core.Randomize(pillars, SWAP_LINES|SWAP_LINES); 156 _core.Randomize(pillars, SWAP_LINES);
157 _core.Randomize(mountainMultipanel, SWAP_LINES);
157 158
158 // Read the target of keep front laser, and write it to keep back laser. 159 // Read the target of keep front laser, and write it to keep back laser.
159 std::vector<int> keepFrontLaserTarget = _core.ReadPanelData<int>(0x0360E, TARGET, 1); 160 std::vector<int> keepFrontLaserTarget = _core.ReadPanelData<int>(0x0360E, TARGET, 1);
160 _core.WritePanelData<int>(0x03317, TARGET, keepFrontLaserTarget); 161 _core.WritePanelData<int>(0x03317, TARGET, keepFrontLaserTarget);
162}
163
164void Randomizer::RandomizeChallenge() {
165 std::vector<int> randomOrder(challengePanels.size(), 0);
166 std::iota(randomOrder.begin(), randomOrder.end(), 0);
167 _core.RandomizeRange(randomOrder, SWAP_NONE, 1, 11); // Easy maze - Triple 2
168 std::vector<int> triple1Target = _core.ReadPanelData<int>(0x00C80, TARGET, 1);
169 _core.WritePanelData<int>(0x00CA1, TARGET, triple1Target);
170 _core.WritePanelData<int>(0x00CB9, TARGET, triple1Target);
171 std::vector<int> triple2Target = _core.ReadPanelData<int>(0x00C22, TARGET, 1);
172 _core.WritePanelData<int>(0x00C59, TARGET, triple2Target);
173 _core.WritePanelData<int>(0x00C68, TARGET, triple2Target);
174 _core.ReassignTargets(challengePanels, randomOrder);
161} \ No newline at end of file 175} \ No newline at end of file
diff --git a/Source/Randomizer.h b/Source/Randomizer.h index 861f5a2..82ea924 100644 --- a/Source/Randomizer.h +++ b/Source/Randomizer.h
@@ -6,7 +6,6 @@ public:
6 void Randomize(); 6 void Randomize();
7 7
8private: 8private:
9 RandomizerCore _core;
10 void RandomizeTutorial(); 9 void RandomizeTutorial();
11 void RandomizeSymmetry(); 10 void RandomizeSymmetry();
12 void RandomizeDesert(); 11 void RandomizeDesert();
@@ -20,4 +19,7 @@ private:
20 void RandomizeJungle(); 19 void RandomizeJungle();
21 void RandomizeSwamp(); 20 void RandomizeSwamp();
22 void RandomizeMountain(); 21 void RandomizeMountain();
22 void RandomizeChallenge();
23
24 RandomizerCore _core;
23}; 25};
diff --git a/Source/RandomizerCore.cpp b/Source/RandomizerCore.cpp index ef0e6e6..d8d8014 100644 --- a/Source/RandomizerCore.cpp +++ b/Source/RandomizerCore.cpp
@@ -105,15 +105,6 @@ void RandomizerCore::ReassignTargets(const std::vector<int>& panels, const std::
105 for (size_t i=0; i<order.size() - 1; i++) { 105 for (size_t i=0; i<order.size() - 1; i++) {
106 // Set the target of order[i] to order[i+1], using the "real" target as determined above. 106 // Set the target of order[i] to order[i+1], using the "real" target as determined above.
107 const int panelTarget = targetToActivatePanel[order[i+1]]; 107 const int panelTarget = targetToActivatePanel[order[i+1]];
108
109 std::stringstream message;
110 message << "i=" << i;
111 message << " order[i]=" << order[i];
112 message << " order[i+1]=" << order[i+1];
113 message << " panels[order[i]]=0x" << std::hex << panels[order[i]];
114 message << " panels[order[i+1]]=0x" << std::hex << panels[order[i+1]];
115 message << " panelTarget=0x" << std::hex << panelTarget << std::endl;
116 OutputDebugStringA(message.str().c_str());
117 WritePanelData<int>(panels[order[i]], TARGET, {panelTarget}); 108 WritePanelData<int>(panels[order[i]], TARGET, {panelTarget});
118 } 109 }
119} 110}
diff --git a/enc_temp_folder/39556c61ea71e3139a19e47cd4dbe2/RandomizerCore.cpp b/enc_temp_folder/39556c61ea71e3139a19e47cd4dbe2/RandomizerCore.cpp new file mode 100644 index 0000000..ef0e6e6 --- /dev/null +++ b/enc_temp_folder/39556c61ea71e3139a19e47cd4dbe2/RandomizerCore.cpp
@@ -0,0 +1,119 @@
1#include "RandomizerCore.h"
2#include "Memory.h"
3#include <sstream>
4
5void RandomizerCore::Randomize(std::vector<int>& panels, int flags) {
6 return RandomizeRange(panels, flags, 0, panels.size());
7}
8
9// Range is [start, end)
10void RandomizerCore::RandomizeRange(std::vector<int> &panels, int flags, size_t startIndex, size_t endIndex) {
11 if (panels.size() == 0) return;
12 if (startIndex >= endIndex) return;
13 if (endIndex >= panels.size()) endIndex = panels.size();
14 for (size_t i = endIndex-1; i > startIndex; i--) {
15 const size_t target = rand() % (i - startIndex) + startIndex;
16 if (i != target) {
17 // std::cout << "Swapping panels " << std::hex << panels[i] << " and " << std::hex << panels[target] << std::endl;
18 SwapPanels(panels[i], panels[target], flags);
19 std::swap(panels[i], panels[target]); // Panel indices in the array
20 }
21 }
22}
23
24void RandomizerCore::SwapPanels(int panel1, int panel2, int flags) {
25 std::map<int, int> offsets;
26
27 if (flags & SWAP_TARGETS) {
28 offsets[TARGET] = sizeof(int);
29 }
30 if (flags & SWAP_LINES) {
31 offsets[PATH_COLOR] = 16;
32 offsets[REFLECTION_PATH_COLOR] = 16;
33 offsets[DOT_COLOR] = 16;
34 offsets[ACTIVE_COLOR] = 16;
35 offsets[BACKGROUND_REGION_COLOR] = 16;
36 offsets[SUCCESS_COLOR_A] = 16;
37 offsets[SUCCESS_COLOR_B] = 16;
38 offsets[STROBE_COLOR_A] = 16;
39 offsets[STROBE_COLOR_B] = 16;
40 offsets[ERROR_COLOR] = 16;
41 offsets[PATTERN_POINT_COLOR] = 16;
42 offsets[PATTERN_POINT_COLOR_A] = 16;
43 offsets[PATTERN_POINT_COLOR_B] = 16;
44 offsets[SYMBOL_A] = 16;
45 offsets[SYMBOL_B] = 16;
46 offsets[SYMBOL_C] = 16;
47 offsets[SYMBOL_D] = 16;
48 offsets[SYMBOL_E] = 16;
49 offsets[PUSH_SYMBOL_COLORS] = sizeof(int);
50 offsets[OUTER_BACKGROUND] = 16;
51 offsets[OUTER_BACKGROUND_MODE] = sizeof(int);
52 offsets[TRACED_EDGES] = 16;
53 offsets[AUDIO_PREFIX] = sizeof(void*);
54// offsets[IS_CYLINDER] = sizeof(int);
55// offsets[CYLINDER_Z0] = sizeof(float);
56// offsets[CYLINDER_Z1] = sizeof(float);
57// offsets[CYLINDER_RADIUS] = sizeof(float);
58 offsets[SPECULAR_ADD] = sizeof(float);
59 offsets[SPECULAR_POWER] = sizeof(int);
60 offsets[PATH_WIDTH_SCALE] = sizeof(float);
61 offsets[STARTPOINT_SCALE] = sizeof(float);
62 offsets[NUM_DOTS] = sizeof(int);
63 offsets[NUM_CONNECTIONS] = sizeof(int);
64 offsets[DOT_POSITIONS] = sizeof(void*);
65 offsets[DOT_FLAGS] = sizeof(void*);
66 offsets[DOT_CONNECTION_A] = sizeof(void*);
67 offsets[DOT_CONNECTION_B] = sizeof(void*);
68 offsets[DECORATIONS] = sizeof(void*);
69 offsets[DECORATION_FLAGS] = sizeof(void*);
70 offsets[DECORATION_COLORS] = sizeof(void*);
71 offsets[NUM_DECORATIONS] = sizeof(int);
72 offsets[REFLECTION_DATA] = sizeof(void*);
73 offsets[GRID_SIZE_X] = sizeof(int);
74 offsets[GRID_SIZE_Y] = sizeof(int);
75 offsets[STYLE_FLAGS] = sizeof(int);
76 offsets[SEQUENCE_LEN] = sizeof(int);
77 offsets[SEQUENCE] = sizeof(void*);
78 offsets[DOT_SEQUENCE_LEN] = sizeof(int);
79 offsets[DOT_SEQUENCE] = sizeof(void*);
80 offsets[DOT_SEQUENCE_LEN_REFLECTION] = sizeof(int);
81 offsets[DOT_SEQUENCE_REFLECTION] = sizeof(void*);
82 offsets[NUM_COLORED_REGIONS] = sizeof(int);
83 offsets[COLORED_REGIONS] = sizeof(void*);
84 offsets[PANEL_TARGET] = sizeof(void*);
85 offsets[SPECULAR_TEXTURE] = sizeof(void*);
86 }
87
88 for (auto const& [offset, size] : offsets) {
89 std::vector<byte> panel1data = ReadPanelData<byte>(panel1, offset, size);
90 std::vector<byte> panel2data = ReadPanelData<byte>(panel2, offset, size);
91 WritePanelData<byte>(panel2, offset, panel1data);
92 WritePanelData<byte>(panel1, offset, panel2data);
93 }
94}
95
96void RandomizerCore::ReassignTargets(const std::vector<int>& panels, const std::vector<int>& order) {
97 // This list is offset by 1, so the target of the Nth panel is in position N (aka the N+1th element)
98 // The first panel may not have a wire to power it, so we use the panel ID itself.
99 std::vector<int> targetToActivatePanel = {panels[0] + 1};
100 for (const int panel : panels) {
101 int target = ReadPanelData<int>(panel, TARGET, 1)[0];
102 targetToActivatePanel.push_back(target);
103 }
104
105 for (size_t i=0; i<order.size() - 1; i++) {
106 // Set the target of order[i] to order[i+1], using the "real" target as determined above.
107 const int panelTarget = targetToActivatePanel[order[i+1]];
108
109 std::stringstream message;
110 message << "i=" << i;
111 message << " order[i]=" << order[i];
112 message << " order[i+1]=" << order[i+1];
113 message << " panels[order[i]]=0x" << std::hex << panels[order[i]];
114 message << " panels[order[i+1]]=0x" << std::hex << panels[order[i+1]];
115 message << " panelTarget=0x" << std::hex << panelTarget << std::endl;
116 OutputDebugStringA(message.str().c_str());
117 WritePanelData<int>(panels[order[i]], TARGET, {panelTarget});
118 }
119}