diff options
| -rw-r--r-- | App/App.vcxproj | 1 | ||||
| -rw-r--r-- | Source/Randomizer.cpp | 270 | ||||
| -rw-r--r-- | Source/Randomizer.h | 16 | ||||
| -rw-r--r-- | Source/RandomizerCore.cpp | 139 | ||||
| -rw-r--r-- | Source/RandomizerCore.h | 14 | ||||
| -rw-r--r-- | Test/Temp.cpp | 14 | ||||
| -rw-r--r-- | Test/Test.vcxproj | 1 |
7 files changed, 231 insertions, 224 deletions
| diff --git a/App/App.vcxproj b/App/App.vcxproj index e9bc419..e5d0f94 100644 --- a/App/App.vcxproj +++ b/App/App.vcxproj | |||
| @@ -156,7 +156,6 @@ | |||
| 156 | </Link> | 156 | </Link> |
| 157 | </ItemDefinitionGroup> | 157 | </ItemDefinitionGroup> |
| 158 | <ItemGroup> | 158 | <ItemGroup> |
| 159 | <ClInclude Include="Resource.h" /> | ||
| 160 | <ClInclude Include="Version.h" /> | 159 | <ClInclude Include="Version.h" /> |
| 161 | </ItemGroup> | 160 | </ItemGroup> |
| 162 | <ItemGroup> | 161 | <ItemGroup> |
| diff --git a/Source/Randomizer.cpp b/Source/Randomizer.cpp index 3cc2712..aaddf21 100644 --- a/Source/Randomizer.cpp +++ b/Source/Randomizer.cpp | |||
| @@ -3,11 +3,12 @@ | |||
| 3 | * Shipwreck vault is solved reversed? -> Not reversed, just "half", you can normally solve orange. Seems to need pattern name. | 3 | * Shipwreck vault is solved reversed? -> Not reversed, just "half", you can normally solve orange. Seems to need pattern name. |
| 4 | * Tutorial sounds don't always play -> Unsure. Not controlled by pattern name. | 4 | * Tutorial sounds don't always play -> Unsure. Not controlled by pattern name. |
| 5 | * FEATURES: | 5 | * FEATURES: |
| 6 | * Start the game if it isn't running? | ||
| 7 | * Stop swapping colors in desert | ||
| 8 | * Look into valid panel swaps for keep walk-ons. | ||
| 6 | * Randomize audio logs -- Hard, seem to be unloaded some times? | 9 | * Randomize audio logs -- Hard, seem to be unloaded some times? |
| 7 | * Swap sounds in jungle (along with panels) -- maybe impossible | 10 | * Swap sounds in jungle (along with panels) -- maybe impossible |
| 8 | * Make orange 7 (all of oranges?) hard. Like big = hard. (See: HARD_MODE) | 11 | * Make orange 7 (all of oranges?) hard. Like big = hard. (See: HARD_MODE) |
| 9 | * Start the game if it isn't running? | ||
| 10 | * Stop swapping colors in desert | ||
| 11 | */ | 12 | */ |
| 12 | #include "Memory.h" | 13 | #include "Memory.h" |
| 13 | #include "Randomizer.h" | 14 | #include "Randomizer.h" |
| @@ -27,7 +28,7 @@ int find(const std::vector<T> &data, T search, size_t startIndex = 0) { | |||
| 27 | } | 28 | } |
| 28 | 29 | ||
| 29 | bool Randomizer::GameIsRandomized() { | 30 | bool Randomizer::GameIsRandomized() { |
| 30 | int currentFrame = _core.GetCurrentFrame(); | 31 | int currentFrame = GetCurrentFrame(); |
| 31 | if (currentFrame >= _lastRandomizedFrame) { | 32 | if (currentFrame >= _lastRandomizedFrame) { |
| 32 | // Time went forwards, presumably we're still on the same save | 33 | // Time went forwards, presumably we're still on the same save |
| 33 | _lastRandomizedFrame = currentFrame; | 34 | _lastRandomizedFrame = currentFrame; |
| @@ -40,13 +41,13 @@ bool Randomizer::GameIsRandomized() { | |||
| 40 | void Randomizer::Randomize() | 41 | void Randomizer::Randomize() |
| 41 | { | 42 | { |
| 42 | if (GameIsRandomized()) return; // Nice sanity check, but should be unnecessary (since Main checks anyways) | 43 | if (GameIsRandomized()) return; // Nice sanity check, but should be unnecessary (since Main checks anyways) |
| 43 | _lastRandomizedFrame = _core.GetCurrentFrame(); | 44 | _lastRandomizedFrame = GetCurrentFrame(); |
| 44 | 45 | ||
| 45 | // Content swaps -- must happen before squarePanels | 46 | // Content swaps -- must happen before squarePanels |
| 46 | _core.Randomize(upDownPanels, SWAP_LINES); | 47 | Randomize(upDownPanels, SWAP_LINES); |
| 47 | _core.Randomize(leftForwardRightPanels, SWAP_LINES); | 48 | Randomize(leftForwardRightPanels, SWAP_LINES); |
| 48 | 49 | ||
| 49 | _core.Randomize(squarePanels, SWAP_LINES); | 50 | Randomize(squarePanels, SWAP_LINES); |
| 50 | 51 | ||
| 51 | // Individual area modifications | 52 | // Individual area modifications |
| 52 | RandomizeTutorial(); | 53 | RandomizeTutorial(); |
| @@ -68,33 +69,33 @@ void Randomizer::Randomize() | |||
| 68 | 69 | ||
| 69 | void Randomizer::AdjustSpeed() { | 70 | void Randomizer::AdjustSpeed() { |
| 70 | // Desert Surface Final Control | 71 | // Desert Surface Final Control |
| 71 | _core._memory->WritePanelData<float>(0x09F95, OPEN_RATE, {0.04f}); // 4x | 72 | _memory->WritePanelData<float>(0x09F95, OPEN_RATE, {0.04f}); // 4x |
| 72 | // Swamp Sliding Bridge | 73 | // Swamp Sliding Bridge |
| 73 | _core._memory->WritePanelData<float>(0x0061A, OPEN_RATE, {0.1f}); // 4x | 74 | _memory->WritePanelData<float>(0x0061A, OPEN_RATE, {0.1f}); // 4x |
| 74 | // Mountain 2 Elevator | 75 | // Mountain 2 Elevator |
| 75 | _core._memory->WritePanelData<float>(0x09EEC, OPEN_RATE, {0.075f}); // 3x | 76 | _memory->WritePanelData<float>(0x09EEC, OPEN_RATE, {0.075f}); // 3x |
| 76 | } | 77 | } |
| 77 | 78 | ||
| 78 | void Randomizer::RandomizeTutorial() { | 79 | void Randomizer::RandomizeTutorial() { |
| 79 | // Disable tutorial cursor speed modifications (not working?) | 80 | // Disable tutorial cursor speed modifications (not working?) |
| 80 | _core._memory->WritePanelData<float>(0x00295, CURSOR_SPEED_SCALE, {1.0}); | 81 | _memory->WritePanelData<float>(0x00295, CURSOR_SPEED_SCALE, {1.0}); |
| 81 | _core._memory->WritePanelData<float>(0x0C373, CURSOR_SPEED_SCALE, {1.0}); | 82 | _memory->WritePanelData<float>(0x0C373, CURSOR_SPEED_SCALE, {1.0}); |
| 82 | _core._memory->WritePanelData<float>(0x00293, CURSOR_SPEED_SCALE, {1.0}); | 83 | _memory->WritePanelData<float>(0x00293, CURSOR_SPEED_SCALE, {1.0}); |
| 83 | _core._memory->WritePanelData<float>(0x002C2, CURSOR_SPEED_SCALE, {1.0}); | 84 | _memory->WritePanelData<float>(0x002C2, CURSOR_SPEED_SCALE, {1.0}); |
| 84 | } | 85 | } |
| 85 | 86 | ||
| 86 | void Randomizer::RandomizeSymmetry() { | 87 | void Randomizer::RandomizeSymmetry() { |
| 87 | } | 88 | } |
| 88 | 89 | ||
| 89 | void Randomizer::RandomizeDesert() { | 90 | void Randomizer::RandomizeDesert() { |
| 90 | _core.Randomize(desertPanels, SWAP_LINES); | 91 | Randomize(desertPanels, SWAP_LINES); |
| 91 | 92 | ||
| 92 | // Turn off desert surface 8 | 93 | // Turn off desert surface 8 |
| 93 | _core._memory->WritePanelData<float>(0x09F94, POWER, {0.0, 0.0}); | 94 | _memory->WritePanelData<float>(0x09F94, POWER, {0.0, 0.0}); |
| 94 | // Turn off desert flood final | 95 | // Turn off desert flood final |
| 95 | _core._memory->WritePanelData<float>(0x18076, POWER, {0.0, 0.0}); | 96 | _memory->WritePanelData<float>(0x18076, POWER, {0.0, 0.0}); |
| 96 | // Change desert floating target to desert flood final | 97 | // Change desert floating target to desert flood final |
| 97 | _core._memory->WritePanelData<int>(0x17ECA, TARGET, {0x18077}); | 98 | _memory->WritePanelData<int>(0x17ECA, TARGET, {0x18077}); |
| 98 | } | 99 | } |
| 99 | 100 | ||
| 100 | void Randomizer::RandomizeQuarry() { | 101 | void Randomizer::RandomizeQuarry() { |
| @@ -102,14 +103,14 @@ void Randomizer::RandomizeQuarry() { | |||
| 102 | 103 | ||
| 103 | void Randomizer::RandomizeTreehouse() { | 104 | void Randomizer::RandomizeTreehouse() { |
| 104 | // Ensure that whatever pivot panels we have are flagged as "pivotable" | 105 | // Ensure that whatever pivot panels we have are flagged as "pivotable" |
| 105 | int panelFlags = _core._memory->ReadPanelData<int>(0x17DD1, STYLE_FLAGS, 1)[0]; | 106 | int panelFlags = _memory->ReadPanelData<int>(0x17DD1, STYLE_FLAGS, 1)[0]; |
| 106 | _core._memory->WritePanelData<int>(0x17DD1, STYLE_FLAGS, {panelFlags | 0x8000}); | 107 | _memory->WritePanelData<int>(0x17DD1, STYLE_FLAGS, {panelFlags | 0x8000}); |
| 107 | panelFlags = _core._memory->ReadPanelData<int>(0x17CE3, STYLE_FLAGS, 1)[0]; | 108 | panelFlags = _memory->ReadPanelData<int>(0x17CE3, STYLE_FLAGS, 1)[0]; |
| 108 | _core._memory->WritePanelData<int>(0x17CE3, STYLE_FLAGS, {panelFlags | 0x8000}); | 109 | _memory->WritePanelData<int>(0x17CE3, STYLE_FLAGS, {panelFlags | 0x8000}); |
| 109 | panelFlags = _core._memory->ReadPanelData<int>(0x17DB7, STYLE_FLAGS, 1)[0]; | 110 | panelFlags = _memory->ReadPanelData<int>(0x17DB7, STYLE_FLAGS, 1)[0]; |
| 110 | _core._memory->WritePanelData<int>(0x17DB7, STYLE_FLAGS, {panelFlags | 0x8000}); | 111 | _memory->WritePanelData<int>(0x17DB7, STYLE_FLAGS, {panelFlags | 0x8000}); |
| 111 | panelFlags = _core._memory->ReadPanelData<int>(0x17E52, STYLE_FLAGS, 1)[0]; | 112 | panelFlags = _memory->ReadPanelData<int>(0x17E52, STYLE_FLAGS, 1)[0]; |
| 112 | _core._memory->WritePanelData<int>(0x17E52, STYLE_FLAGS, {panelFlags | 0x8000}); | 113 | _memory->WritePanelData<int>(0x17E52, STYLE_FLAGS, {panelFlags | 0x8000}); |
| 113 | } | 114 | } |
| 114 | 115 | ||
| 115 | void Randomizer::RandomizeKeep() { | 116 | void Randomizer::RandomizeKeep() { |
| @@ -117,22 +118,22 @@ void Randomizer::RandomizeKeep() { | |||
| 117 | 118 | ||
| 118 | void Randomizer::RandomizeShadows() { | 119 | void Randomizer::RandomizeShadows() { |
| 119 | // Distance-gate shadows laser to prevent sniping through the bars | 120 | // Distance-gate shadows laser to prevent sniping through the bars |
| 120 | _core._memory->WritePanelData<float>(0x19650, MAX_BROADCAST_DISTANCE, {2.5}); | 121 | _memory->WritePanelData<float>(0x19650, MAX_BROADCAST_DISTANCE, {2.5}); |
| 121 | // Change the shadows tutorial cable to only activate avoid | 122 | // Change the shadows tutorial cable to only activate avoid |
| 122 | _core._memory->WritePanelData<int>(0x319A8, CABLE_TARGET_2, {0}); | 123 | _memory->WritePanelData<int>(0x319A8, CABLE_TARGET_2, {0}); |
| 123 | // Change shadows avoid 8 to power shadows follow | 124 | // Change shadows avoid 8 to power shadows follow |
| 124 | _core._memory->WritePanelData<int>(0x1972F, TARGET, {0x1C34C}); | 125 | _memory->WritePanelData<int>(0x1972F, TARGET, {0x1C34C}); |
| 125 | 126 | ||
| 126 | std::vector<int> randomOrder(shadowsPanels.size(), 0); | 127 | std::vector<int> randomOrder(shadowsPanels.size(), 0); |
| 127 | std::iota(randomOrder.begin(), randomOrder.end(), 0); | 128 | std::iota(randomOrder.begin(), randomOrder.end(), 0); |
| 128 | _core.RandomizeRange(randomOrder, SWAP_NONE, 0, 8); // Tutorial | 129 | RandomizeRange(randomOrder, SWAP_NONE, 0, 8); // Tutorial |
| 129 | _core.RandomizeRange(randomOrder, SWAP_NONE, 8, 16); // Avoid | 130 | RandomizeRange(randomOrder, SWAP_NONE, 8, 16); // Avoid |
| 130 | _core.RandomizeRange(randomOrder, SWAP_NONE, 16, 21); // Follow | 131 | RandomizeRange(randomOrder, SWAP_NONE, 16, 21); // Follow |
| 131 | _core.ReassignTargets(shadowsPanels, randomOrder); | 132 | ReassignTargets(shadowsPanels, randomOrder); |
| 132 | // Turn off original starting panel | 133 | // Turn off original starting panel |
| 133 | _core._memory->WritePanelData<float>(shadowsPanels[0], POWER, {0.0f, 0.0f}); | 134 | _memory->WritePanelData<float>(shadowsPanels[0], POWER, {0.0f, 0.0f}); |
| 134 | // Turn on new starting panel | 135 | // Turn on new starting panel |
| 135 | _core._memory->WritePanelData<float>(shadowsPanels[randomOrder[0]], POWER, {1.0f, 1.0f}); | 136 | _memory->WritePanelData<float>(shadowsPanels[randomOrder[0]], POWER, {1.0f, 1.0f}); |
| 136 | } | 137 | } |
| 137 | 138 | ||
| 138 | void Randomizer::RandomizeTown() { | 139 | void Randomizer::RandomizeTown() { |
| @@ -141,8 +142,8 @@ void Randomizer::RandomizeTown() { | |||
| 141 | void Randomizer::RandomizeMonastery() { | 142 | void Randomizer::RandomizeMonastery() { |
| 142 | std::vector<int> randomOrder(monasteryPanels.size(), 0); | 143 | std::vector<int> randomOrder(monasteryPanels.size(), 0); |
| 143 | std::iota(randomOrder.begin(), randomOrder.end(), 0); | 144 | std::iota(randomOrder.begin(), randomOrder.end(), 0); |
| 144 | _core.RandomizeRange(randomOrder, SWAP_NONE, 3, 9); // Outer 2 & 3, Inner 1-4 | 145 | RandomizeRange(randomOrder, SWAP_NONE, 3, 9); // Outer 2 & 3, Inner 1-4 |
| 145 | _core.ReassignTargets(monasteryPanels, randomOrder); | 146 | ReassignTargets(monasteryPanels, randomOrder); |
| 146 | } | 147 | } |
| 147 | 148 | ||
| 148 | void Randomizer::RandomizeBunker() { | 149 | void Randomizer::RandomizeBunker() { |
| @@ -151,73 +152,208 @@ void Randomizer::RandomizeBunker() { | |||
| 151 | // Randomize Tutorial 2-Advanced Tutorial 4 + Glass 1 | 152 | // Randomize Tutorial 2-Advanced Tutorial 4 + Glass 1 |
| 152 | // Tutorial 1 cannot be randomized, since no other panel can start on | 153 | // Tutorial 1 cannot be randomized, since no other panel can start on |
| 153 | // Glass 1 will become door + glass 1, due to the targetting system | 154 | // Glass 1 will become door + glass 1, due to the targetting system |
| 154 | _core.RandomizeRange(randomOrder, SWAP_NONE, 1, 10); | 155 | RandomizeRange(randomOrder, SWAP_NONE, 1, 10); |
| 155 | // Randomize Glass 1-3 into everything after the door/glass 1 | 156 | // Randomize Glass 1-3 into everything after the door/glass 1 |
| 156 | const size_t glass1Index = find(randomOrder, 9); | 157 | const size_t glass1Index = find(randomOrder, 9); |
| 157 | _core.RandomizeRange(randomOrder, SWAP_NONE, glass1Index + 1, 12); | 158 | RandomizeRange(randomOrder, SWAP_NONE, glass1Index + 1, 12); |
| 158 | _core.ReassignTargets(bunkerPanels, randomOrder); | 159 | ReassignTargets(bunkerPanels, randomOrder); |
| 159 | } | 160 | } |
| 160 | 161 | ||
| 161 | void Randomizer::RandomizeJungle() { | 162 | void Randomizer::RandomizeJungle() { |
| 162 | std::vector<int> randomOrder(junglePanels.size(), 0); | 163 | std::vector<int> randomOrder(junglePanels.size(), 0); |
| 163 | std::iota(randomOrder.begin(), randomOrder.end(), 0); | 164 | std::iota(randomOrder.begin(), randomOrder.end(), 0); |
| 164 | // Waves 1 cannot be randomized, since no other panel can start on | 165 | // Waves 1 cannot be randomized, since no other panel can start on |
| 165 | _core.RandomizeRange(randomOrder, SWAP_NONE, 1, 7); // Waves 2-7 | 166 | RandomizeRange(randomOrder, SWAP_NONE, 1, 7); // Waves 2-7 |
| 166 | _core.RandomizeRange(randomOrder, SWAP_NONE, 8, 13); // Pitches 1-6 | 167 | RandomizeRange(randomOrder, SWAP_NONE, 8, 13); // Pitches 1-6 |
| 167 | _core.ReassignTargets(junglePanels, randomOrder); | 168 | ReassignTargets(junglePanels, randomOrder); |
| 168 | } | 169 | } |
| 169 | 170 | ||
| 170 | void Randomizer::RandomizeSwamp() { | 171 | void Randomizer::RandomizeSwamp() { |
| 171 | // Distance-gate swamp snipe 1 to prevent RNG swamp snipe | 172 | // Distance-gate swamp snipe 1 to prevent RNG swamp snipe |
| 172 | _core._memory->WritePanelData<float>(0x17C05, MAX_BROADCAST_DISTANCE, {15.0}); | 173 | _memory->WritePanelData<float>(0x17C05, MAX_BROADCAST_DISTANCE, {15.0}); |
| 173 | } | 174 | } |
| 174 | 175 | ||
| 175 | void Randomizer::RandomizeMountain() { | 176 | void Randomizer::RandomizeMountain() { |
| 176 | // Randomize lasers & some of mountain | 177 | // Randomize lasers & some of mountain |
| 177 | _core.Randomize(lasers, SWAP_TARGETS); | 178 | Randomize(lasers, SWAP_TARGETS); |
| 178 | _core.Randomize(mountainMultipanel, SWAP_LINES); | 179 | Randomize(mountainMultipanel, SWAP_LINES); |
| 179 | 180 | ||
| 180 | // Randomize final pillars order | 181 | // Randomize final pillars order |
| 181 | std::vector<int> targets = {pillars[0] + 1}; | 182 | std::vector<int> targets = {pillars[0] + 1}; |
| 182 | for (const int pillar : pillars) { | 183 | for (const int pillar : pillars) { |
| 183 | int target = _core._memory->ReadPanelData<int>(pillar, TARGET, 1)[0]; | 184 | int target = _memory->ReadPanelData<int>(pillar, TARGET, 1)[0]; |
| 184 | targets.push_back(target); | 185 | targets.push_back(target); |
| 185 | } | 186 | } |
| 186 | targets[5] = pillars[5] + 1; | 187 | targets[5] = pillars[5] + 1; |
| 187 | 188 | ||
| 188 | std::vector<int> randomOrder(pillars.size(), 0); | 189 | std::vector<int> randomOrder(pillars.size(), 0); |
| 189 | std::iota(randomOrder.begin(), randomOrder.end(), 0); | 190 | std::iota(randomOrder.begin(), randomOrder.end(), 0); |
| 190 | _core.RandomizeRange(randomOrder, SWAP_NONE, 0, 4); // Left Pillars 1-4 | 191 | RandomizeRange(randomOrder, SWAP_NONE, 0, 4); // Left Pillars 1-4 |
| 191 | _core.RandomizeRange(randomOrder, SWAP_NONE, 5, 9); // Right Pillars 1-4 | 192 | RandomizeRange(randomOrder, SWAP_NONE, 5, 9); // Right Pillars 1-4 |
| 192 | _core.ReassignTargets(pillars, randomOrder, targets); | 193 | ReassignTargets(pillars, randomOrder, targets); |
| 193 | // Turn off original starting panels | 194 | // Turn off original starting panels |
| 194 | _core._memory->WritePanelData<float>(pillars[0], POWER, {0.0f, 0.0f}); | 195 | _memory->WritePanelData<float>(pillars[0], POWER, {0.0f, 0.0f}); |
| 195 | _core._memory->WritePanelData<float>(pillars[5], POWER, {0.0f, 0.0f}); | 196 | _memory->WritePanelData<float>(pillars[5], POWER, {0.0f, 0.0f}); |
| 196 | // Turn on new starting panels | 197 | // Turn on new starting panels |
| 197 | _core._memory->WritePanelData<float>(pillars[randomOrder[0]], POWER, {1.0f, 1.0f}); | 198 | _memory->WritePanelData<float>(pillars[randomOrder[0]], POWER, {1.0f, 1.0f}); |
| 198 | _core._memory->WritePanelData<float>(pillars[randomOrder[5]], POWER, {1.0f, 1.0f}); | 199 | _memory->WritePanelData<float>(pillars[randomOrder[5]], POWER, {1.0f, 1.0f}); |
| 199 | 200 | ||
| 200 | // Read the target of keep front laser, and write it to keep back laser. | 201 | // Read the target of keep front laser, and write it to keep back laser. |
| 201 | std::vector<int> keepFrontLaserTarget = _core._memory->ReadPanelData<int>(0x0360E, TARGET, 1); | 202 | std::vector<int> keepFrontLaserTarget = _memory->ReadPanelData<int>(0x0360E, TARGET, 1); |
| 202 | _core._memory->WritePanelData<int>(0x03317, TARGET, keepFrontLaserTarget); | 203 | _memory->WritePanelData<int>(0x03317, TARGET, keepFrontLaserTarget); |
| 203 | } | 204 | } |
| 204 | 205 | ||
| 205 | void Randomizer::RandomizeChallenge() { | 206 | void Randomizer::RandomizeChallenge() { |
| 206 | std::vector<int> randomOrder(challengePanels.size(), 0); | 207 | std::vector<int> randomOrder(challengePanels.size(), 0); |
| 207 | std::iota(randomOrder.begin(), randomOrder.end(), 0); | 208 | std::iota(randomOrder.begin(), randomOrder.end(), 0); |
| 208 | _core.RandomizeRange(randomOrder, SWAP_NONE, 1, 9); // Easy maze - Triple 2 | 209 | RandomizeRange(randomOrder, SWAP_NONE, 1, 9); // Easy maze - Triple 2 |
| 209 | std::vector<int> triple1Target = _core._memory->ReadPanelData<int>(0x00C80, TARGET, 1); | 210 | std::vector<int> triple1Target = _memory->ReadPanelData<int>(0x00C80, TARGET, 1); |
| 210 | _core._memory->WritePanelData<int>(0x00CA1, TARGET, triple1Target); | 211 | _memory->WritePanelData<int>(0x00CA1, TARGET, triple1Target); |
| 211 | _core._memory->WritePanelData<int>(0x00CB9, TARGET, triple1Target); | 212 | _memory->WritePanelData<int>(0x00CB9, TARGET, triple1Target); |
| 212 | std::vector<int> triple2Target = _core._memory->ReadPanelData<int>(0x00C22, TARGET, 1); | 213 | std::vector<int> triple2Target = _memory->ReadPanelData<int>(0x00C22, TARGET, 1); |
| 213 | _core._memory->WritePanelData<int>(0x00C59, TARGET, triple2Target); | 214 | _memory->WritePanelData<int>(0x00C59, TARGET, triple2Target); |
| 214 | _core._memory->WritePanelData<int>(0x00C68, TARGET, triple2Target); | 215 | _memory->WritePanelData<int>(0x00C68, TARGET, triple2Target); |
| 215 | _core.ReassignTargets(challengePanels, randomOrder); | 216 | ReassignTargets(challengePanels, randomOrder); |
| 216 | } | 217 | } |
| 217 | 218 | ||
| 218 | void Randomizer::RandomizeAudioLogs() { | 219 | void Randomizer::RandomizeAudioLogs() { |
| 219 | std::vector<int> randomOrder(audiologs.size(), 0); | 220 | std::vector<int> randomOrder(audiologs.size(), 0); |
| 220 | std::iota(randomOrder.begin(), randomOrder.end(), 0); | 221 | std::iota(randomOrder.begin(), randomOrder.end(), 0); |
| 221 | _core.Randomize(randomOrder, SWAP_NONE); | 222 | Randomize(randomOrder, SWAP_NONE); |
| 222 | _core.ReassignNames(audiologs, randomOrder); | 223 | ReassignNames(audiologs, randomOrder); |
| 223 | } \ No newline at end of file | 224 | } |
| 225 | |||
| 226 | void Randomizer::Randomize(std::vector<int>& panels, int flags) { | ||
| 227 | return RandomizeRange(panels, flags, 0, panels.size()); | ||
| 228 | } | ||
| 229 | |||
| 230 | // Range is [start, end) | ||
| 231 | void Randomizer::RandomizeRange(std::vector<int> &panels, int flags, size_t startIndex, size_t endIndex) { | ||
| 232 | if (panels.size() == 0) return; | ||
| 233 | if (startIndex >= endIndex) return; | ||
| 234 | if (endIndex >= panels.size()) endIndex = panels.size(); | ||
| 235 | for (size_t i = endIndex-1; i > startIndex; i--) { | ||
| 236 | const size_t target = Random::RandInt(startIndex, i); | ||
| 237 | if (i != target) { | ||
| 238 | // std::cout << "Swapping panels " << std::hex << panels[i] << " and " << std::hex << panels[target] << std::endl; | ||
| 239 | SwapPanels(panels[i], panels[target], flags); | ||
| 240 | std::swap(panels[i], panels[target]); // Panel indices in the array | ||
| 241 | } | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 245 | void Randomizer::SwapPanels(int panel1, int panel2, int flags) { | ||
| 246 | std::map<int, int> offsets; | ||
| 247 | |||
| 248 | if (flags & SWAP_TARGETS) { | ||
| 249 | offsets[TARGET] = sizeof(int); | ||
| 250 | } | ||
| 251 | if (flags & SWAP_AUDIO_NAMES) { | ||
| 252 | offsets[AUDIO_LOG_NAME] = sizeof(void*); | ||
| 253 | } | ||
| 254 | if (flags & SWAP_LINES) { | ||
| 255 | offsets[PATH_COLOR] = 16; | ||
| 256 | offsets[REFLECTION_PATH_COLOR] = 16; | ||
| 257 | offsets[DOT_COLOR] = 16; | ||
| 258 | offsets[ACTIVE_COLOR] = 16; | ||
| 259 | offsets[BACKGROUND_REGION_COLOR] = 12; // Not copying alpha to preserve transparency. | ||
| 260 | offsets[SUCCESS_COLOR_A] = 16; | ||
| 261 | offsets[SUCCESS_COLOR_B] = 16; | ||
| 262 | offsets[STROBE_COLOR_A] = 16; | ||
| 263 | offsets[STROBE_COLOR_B] = 16; | ||
| 264 | offsets[ERROR_COLOR] = 16; | ||
| 265 | offsets[PATTERN_POINT_COLOR] = 16; | ||
| 266 | offsets[PATTERN_POINT_COLOR_A] = 16; | ||
| 267 | offsets[PATTERN_POINT_COLOR_B] = 16; | ||
| 268 | offsets[SYMBOL_A] = 16; | ||
| 269 | offsets[SYMBOL_B] = 16; | ||
| 270 | offsets[SYMBOL_C] = 16; | ||
| 271 | offsets[SYMBOL_D] = 16; | ||
| 272 | offsets[SYMBOL_E] = 16; | ||
| 273 | offsets[PUSH_SYMBOL_COLORS] = sizeof(int); | ||
| 274 | offsets[OUTER_BACKGROUND] = 16; | ||
| 275 | offsets[OUTER_BACKGROUND_MODE] = sizeof(int); | ||
| 276 | offsets[TRACED_EDGES] = 16; | ||
| 277 | offsets[AUDIO_PREFIX] = sizeof(void*); | ||
| 278 | // offsets[IS_CYLINDER] = sizeof(int); | ||
| 279 | // offsets[CYLINDER_Z0] = sizeof(float); | ||
| 280 | // offsets[CYLINDER_Z1] = sizeof(float); | ||
| 281 | // offsets[CYLINDER_RADIUS] = sizeof(float); | ||
| 282 | offsets[SPECULAR_ADD] = sizeof(float); | ||
| 283 | offsets[SPECULAR_POWER] = sizeof(int); | ||
| 284 | offsets[PATH_WIDTH_SCALE] = sizeof(float); | ||
| 285 | offsets[STARTPOINT_SCALE] = sizeof(float); | ||
| 286 | offsets[NUM_DOTS] = sizeof(int); | ||
| 287 | offsets[NUM_CONNECTIONS] = sizeof(int); | ||
| 288 | offsets[DOT_POSITIONS] = sizeof(void*); | ||
| 289 | offsets[DOT_FLAGS] = sizeof(void*); | ||
| 290 | offsets[DOT_CONNECTION_A] = sizeof(void*); | ||
| 291 | offsets[DOT_CONNECTION_B] = sizeof(void*); | ||
| 292 | offsets[DECORATIONS] = sizeof(void*); | ||
| 293 | offsets[DECORATION_FLAGS] = sizeof(void*); | ||
| 294 | offsets[DECORATION_COLORS] = sizeof(void*); | ||
| 295 | offsets[NUM_DECORATIONS] = sizeof(int); | ||
| 296 | offsets[REFLECTION_DATA] = sizeof(void*); | ||
| 297 | offsets[GRID_SIZE_X] = sizeof(int); | ||
| 298 | offsets[GRID_SIZE_Y] = sizeof(int); | ||
| 299 | offsets[STYLE_FLAGS] = sizeof(int); | ||
| 300 | offsets[SEQUENCE_LEN] = sizeof(int); | ||
| 301 | offsets[SEQUENCE] = sizeof(void*); | ||
| 302 | offsets[DOT_SEQUENCE_LEN] = sizeof(int); | ||
| 303 | offsets[DOT_SEQUENCE] = sizeof(void*); | ||
| 304 | offsets[DOT_SEQUENCE_LEN_REFLECTION] = sizeof(int); | ||
| 305 | offsets[DOT_SEQUENCE_REFLECTION] = sizeof(void*); | ||
| 306 | offsets[NUM_COLORED_REGIONS] = sizeof(int); | ||
| 307 | offsets[COLORED_REGIONS] = sizeof(void*); | ||
| 308 | offsets[PANEL_TARGET] = sizeof(void*); | ||
| 309 | offsets[SPECULAR_TEXTURE] = sizeof(void*); | ||
| 310 | } | ||
| 311 | |||
| 312 | for (auto const& [offset, size] : offsets) { | ||
| 313 | std::vector<byte> panel1data = _memory->ReadPanelData<byte>(panel1, offset, size); | ||
| 314 | std::vector<byte> panel2data = _memory->ReadPanelData<byte>(panel2, offset, size); | ||
| 315 | _memory->WritePanelData<byte>(panel2, offset, panel1data); | ||
| 316 | _memory->WritePanelData<byte>(panel1, offset, panel2data); | ||
| 317 | } | ||
| 318 | } | ||
| 319 | |||
| 320 | void Randomizer::ReassignTargets(const std::vector<int>& panels, const std::vector<int>& order, std::vector<int> targets) { | ||
| 321 | if (targets.empty()) { | ||
| 322 | // This list is offset by 1, so the target of the Nth panel is in position N (aka the N+1th element) | ||
| 323 | // The first panel may not have a wire to power it, so we use the panel ID itself. | ||
| 324 | targets = {panels[0] + 1}; | ||
| 325 | for (const int panel : panels) { | ||
| 326 | int target = _memory->ReadPanelData<int>(panel, TARGET, 1)[0]; | ||
| 327 | targets.push_back(target); | ||
| 328 | } | ||
| 329 | } | ||
| 330 | |||
| 331 | for (size_t i=0; i<order.size() - 1; i++) { | ||
| 332 | // Set the target of order[i] to order[i+1], using the "real" target as determined above. | ||
| 333 | const int panelTarget = targets[order[i+1]]; | ||
| 334 | _memory->WritePanelData<int>(panels[order[i]], TARGET, {panelTarget}); | ||
| 335 | } | ||
| 336 | } | ||
| 337 | |||
| 338 | void Randomizer::ReassignNames(const std::vector<int>& panels, const std::vector<int>& order) { | ||
| 339 | std::vector<int64_t> names; | ||
| 340 | for (const int panel : panels) { | ||
| 341 | names.push_back(_memory->ReadPanelData<int64_t>(panel, AUDIO_LOG_NAME, 1)[0]); | ||
| 342 | } | ||
| 343 | |||
| 344 | for (int i=0; i<panels.size(); i++) { | ||
| 345 | _memory->WritePanelData<int64_t>(panels[i], AUDIO_LOG_NAME, {names[order[i]]}); | ||
| 346 | } | ||
| 347 | } | ||
| 348 | |||
| 349 | short Randomizer::ReadMetadata() { | ||
| 350 | return _memory->ReadData<short>({GLOBALS + METADATA}, 1)[0]; | ||
| 351 | } | ||
| 352 | |||
| 353 | void Randomizer::WriteMetadata(short metadata) { | ||
| 354 | return _memory->WriteData<short>({GLOBALS + METADATA}, {metadata}); | ||
| 355 | } | ||
| 356 | |||
| 357 | int Randomizer::GetCurrentFrame() { | ||
| 358 | return _memory->ReadData<int>({SCRIPT_FRAMES}, 1)[0]; | ||
| 359 | } | ||
| diff --git a/Source/Randomizer.h b/Source/Randomizer.h index ea05975..c9603ac 100644 --- a/Source/Randomizer.h +++ b/Source/Randomizer.h | |||
| @@ -8,7 +8,7 @@ public: | |||
| 8 | 8 | ||
| 9 | void AdjustSpeed(); | 9 | void AdjustSpeed(); |
| 10 | 10 | ||
| 11 | void ClearOffsets() {_core.ClearOffsets();} | 11 | void ClearOffsets() {_memory->ClearOffsets();} |
| 12 | 12 | ||
| 13 | private: | 13 | private: |
| 14 | 14 | ||
| @@ -29,5 +29,17 @@ private: | |||
| 29 | void RandomizeChallenge(); | 29 | void RandomizeChallenge(); |
| 30 | void RandomizeAudioLogs(); | 30 | void RandomizeAudioLogs(); |
| 31 | 31 | ||
| 32 | RandomizerCore _core; | 32 | void Randomize(std::vector<int>& panels, int flags); |
| 33 | void RandomizeRange(std::vector<int> &panels, int flags, size_t startIndex, size_t endIndex); | ||
| 34 | void SwapPanels(int panel1, int panel2, int flags); | ||
| 35 | void ReassignTargets(const std::vector<int>& panels, const std::vector<int>& order, std::vector<int> targets = {}); | ||
| 36 | void ReassignNames(const std::vector<int>& panels, const std::vector<int>& order); | ||
| 37 | |||
| 38 | short ReadMetadata(); | ||
| 39 | void WriteMetadata(short metadata); | ||
| 40 | int GetCurrentFrame(); | ||
| 41 | |||
| 42 | std::shared_ptr<Memory> _memory = std::make_shared<Memory>("witness64_d3d11.exe"); | ||
| 43 | |||
| 44 | friend class SwapTests_Shipwreck_Test; | ||
| 33 | }; | 45 | }; |
| diff --git a/Source/RandomizerCore.cpp b/Source/RandomizerCore.cpp index f00dacd..e69de29 100644 --- a/Source/RandomizerCore.cpp +++ b/Source/RandomizerCore.cpp | |||
| @@ -1,139 +0,0 @@ | |||
| 1 | #include "RandomizerCore.h" | ||
| 2 | #include "Memory.h" | ||
| 3 | #include "Random.h" | ||
| 4 | #include <sstream> | ||
| 5 | |||
| 6 | void RandomizerCore::Randomize(std::vector<int>& panels, int flags) { | ||
| 7 | return RandomizeRange(panels, flags, 0, panels.size()); | ||
| 8 | } | ||
| 9 | |||
| 10 | // Range is [start, end) | ||
| 11 | void RandomizerCore::RandomizeRange(std::vector<int> &panels, int flags, size_t startIndex, size_t endIndex) { | ||
| 12 | if (panels.size() == 0) return; | ||
| 13 | if (startIndex >= endIndex) return; | ||
| 14 | if (endIndex >= panels.size()) endIndex = panels.size(); | ||
| 15 | for (size_t i = endIndex-1; i > startIndex; i--) { | ||
| 16 | const size_t target = Random::RandInt(startIndex, i); | ||
| 17 | if (i != target) { | ||
| 18 | // std::cout << "Swapping panels " << std::hex << panels[i] << " and " << std::hex << panels[target] << std::endl; | ||
| 19 | SwapPanels(panels[i], panels[target], flags); | ||
| 20 | std::swap(panels[i], panels[target]); // Panel indices in the array | ||
| 21 | } | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | void RandomizerCore::SwapPanels(int panel1, int panel2, int flags) { | ||
| 26 | std::map<int, int> offsets; | ||
| 27 | |||
| 28 | if (flags & SWAP_TARGETS) { | ||
| 29 | offsets[TARGET] = sizeof(int); | ||
| 30 | } | ||
| 31 | if (flags & SWAP_AUDIO_NAMES) { | ||
| 32 | offsets[AUDIO_LOG_NAME] = sizeof(void*); | ||
| 33 | } | ||
| 34 | if (flags & SWAP_LINES) { | ||
| 35 | offsets[PATH_COLOR] = 16; | ||
| 36 | offsets[REFLECTION_PATH_COLOR] = 16; | ||
| 37 | offsets[DOT_COLOR] = 16; | ||
| 38 | offsets[ACTIVE_COLOR] = 16; | ||
| 39 | offsets[BACKGROUND_REGION_COLOR] = 12; // Not copying alpha to preserve transparency. | ||
| 40 | offsets[SUCCESS_COLOR_A] = 16; | ||
| 41 | offsets[SUCCESS_COLOR_B] = 16; | ||
| 42 | offsets[STROBE_COLOR_A] = 16; | ||
| 43 | offsets[STROBE_COLOR_B] = 16; | ||
| 44 | offsets[ERROR_COLOR] = 16; | ||
| 45 | offsets[PATTERN_POINT_COLOR] = 16; | ||
| 46 | offsets[PATTERN_POINT_COLOR_A] = 16; | ||
| 47 | offsets[PATTERN_POINT_COLOR_B] = 16; | ||
| 48 | offsets[SYMBOL_A] = 16; | ||
| 49 | offsets[SYMBOL_B] = 16; | ||
| 50 | offsets[SYMBOL_C] = 16; | ||
| 51 | offsets[SYMBOL_D] = 16; | ||
| 52 | offsets[SYMBOL_E] = 16; | ||
| 53 | offsets[PUSH_SYMBOL_COLORS] = sizeof(int); | ||
| 54 | offsets[OUTER_BACKGROUND] = 16; | ||
| 55 | offsets[OUTER_BACKGROUND_MODE] = sizeof(int); | ||
| 56 | offsets[TRACED_EDGES] = 16; | ||
| 57 | offsets[AUDIO_PREFIX] = sizeof(void*); | ||
| 58 | // offsets[IS_CYLINDER] = sizeof(int); | ||
| 59 | // offsets[CYLINDER_Z0] = sizeof(float); | ||
| 60 | // offsets[CYLINDER_Z1] = sizeof(float); | ||
| 61 | // offsets[CYLINDER_RADIUS] = sizeof(float); | ||
| 62 | offsets[SPECULAR_ADD] = sizeof(float); | ||
| 63 | offsets[SPECULAR_POWER] = sizeof(int); | ||
| 64 | offsets[PATH_WIDTH_SCALE] = sizeof(float); | ||
| 65 | offsets[STARTPOINT_SCALE] = sizeof(float); | ||
| 66 | offsets[NUM_DOTS] = sizeof(int); | ||
| 67 | offsets[NUM_CONNECTIONS] = sizeof(int); | ||
| 68 | offsets[DOT_POSITIONS] = sizeof(void*); | ||
| 69 | offsets[DOT_FLAGS] = sizeof(void*); | ||
| 70 | offsets[DOT_CONNECTION_A] = sizeof(void*); | ||
| 71 | offsets[DOT_CONNECTION_B] = sizeof(void*); | ||
| 72 | offsets[DECORATIONS] = sizeof(void*); | ||
| 73 | offsets[DECORATION_FLAGS] = sizeof(void*); | ||
| 74 | offsets[DECORATION_COLORS] = sizeof(void*); | ||
| 75 | offsets[NUM_DECORATIONS] = sizeof(int); | ||
| 76 | offsets[REFLECTION_DATA] = sizeof(void*); | ||
| 77 | offsets[GRID_SIZE_X] = sizeof(int); | ||
| 78 | offsets[GRID_SIZE_Y] = sizeof(int); | ||
| 79 | offsets[STYLE_FLAGS] = sizeof(int); | ||
| 80 | offsets[SEQUENCE_LEN] = sizeof(int); | ||
| 81 | offsets[SEQUENCE] = sizeof(void*); | ||
| 82 | offsets[DOT_SEQUENCE_LEN] = sizeof(int); | ||
| 83 | offsets[DOT_SEQUENCE] = sizeof(void*); | ||
| 84 | offsets[DOT_SEQUENCE_LEN_REFLECTION] = sizeof(int); | ||
| 85 | offsets[DOT_SEQUENCE_REFLECTION] = sizeof(void*); | ||
| 86 | offsets[NUM_COLORED_REGIONS] = sizeof(int); | ||
| 87 | offsets[COLORED_REGIONS] = sizeof(void*); | ||
| 88 | offsets[PANEL_TARGET] = sizeof(void*); | ||
| 89 | offsets[SPECULAR_TEXTURE] = sizeof(void*); | ||
| 90 | } | ||
| 91 | |||
| 92 | for (auto const& [offset, size] : offsets) { | ||
| 93 | std::vector<byte> panel1data = _memory->ReadPanelData<byte>(panel1, offset, size); | ||
| 94 | std::vector<byte> panel2data = _memory->ReadPanelData<byte>(panel2, offset, size); | ||
| 95 | _memory->WritePanelData<byte>(panel2, offset, panel1data); | ||
| 96 | _memory->WritePanelData<byte>(panel1, offset, panel2data); | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | void RandomizerCore::ReassignTargets(const std::vector<int>& panels, const std::vector<int>& order, std::vector<int> targets) { | ||
| 101 | if (targets.empty()) { | ||
| 102 | // This list is offset by 1, so the target of the Nth panel is in position N (aka the N+1th element) | ||
| 103 | // The first panel may not have a wire to power it, so we use the panel ID itself. | ||
| 104 | targets = {panels[0] + 1}; | ||
| 105 | for (const int panel : panels) { | ||
| 106 | int target = _memory->ReadPanelData<int>(panel, TARGET, 1)[0]; | ||
| 107 | targets.push_back(target); | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | for (size_t i=0; i<order.size() - 1; i++) { | ||
| 112 | // Set the target of order[i] to order[i+1], using the "real" target as determined above. | ||
| 113 | const int panelTarget = targets[order[i+1]]; | ||
| 114 | _memory->WritePanelData<int>(panels[order[i]], TARGET, {panelTarget}); | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | void RandomizerCore::ReassignNames(const std::vector<int>& panels, const std::vector<int>& order) { | ||
| 119 | std::vector<int64_t> names; | ||
| 120 | for (const int panel : panels) { | ||
| 121 | names.push_back(_memory->ReadPanelData<int64_t>(panel, AUDIO_LOG_NAME, 1)[0]); | ||
| 122 | } | ||
| 123 | |||
| 124 | for (int i=0; i<panels.size(); i++) { | ||
| 125 | _memory->WritePanelData<int64_t>(panels[i], AUDIO_LOG_NAME, {names[order[i]]}); | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | short RandomizerCore::ReadMetadata() { | ||
| 130 | return _memory->ReadData<short>({GLOBALS + METADATA}, 1)[0]; | ||
| 131 | } | ||
| 132 | |||
| 133 | void RandomizerCore::WriteMetadata(short metadata) { | ||
| 134 | return _memory->WriteData<short>({GLOBALS + METADATA}, {metadata}); | ||
| 135 | } | ||
| 136 | |||
| 137 | int RandomizerCore::GetCurrentFrame() { | ||
| 138 | return _memory->ReadData<int>({SCRIPT_FRAMES}, 1)[0]; | ||
| 139 | } | ||
| diff --git a/Source/RandomizerCore.h b/Source/RandomizerCore.h index 7555de2..89560b6 100644 --- a/Source/RandomizerCore.h +++ b/Source/RandomizerCore.h | |||
| @@ -10,20 +10,6 @@ __declspec(selectany) int SWAP_AUDIO_NAMES = 0x4; | |||
| 10 | class RandomizerCore | 10 | class RandomizerCore |
| 11 | { | 11 | { |
| 12 | public: | 12 | public: |
| 13 | void Randomize(std::vector<int>& panels, int flags); | ||
| 14 | void RandomizeRange(std::vector<int> &panels, int flags, size_t startIndex, size_t endIndex); | ||
| 15 | void SwapPanels(int panel1, int panel2, int flags); | ||
| 16 | void ReassignTargets(const std::vector<int>& panels, const std::vector<int>& order, std::vector<int> targets = {}); | ||
| 17 | void ReassignNames(const std::vector<int>& panels, const std::vector<int>& order); | ||
| 18 | |||
| 19 | short ReadMetadata(); | ||
| 20 | void WriteMetadata(short metadata); | ||
| 21 | int GetCurrentFrame(); | ||
| 22 | |||
| 23 | void ClearOffsets() {_memory->ClearOffsets();} | ||
| 24 | |||
| 25 | // private: | ||
| 26 | std::shared_ptr<Memory> _memory = std::make_shared<Memory>("witness64_d3d11.exe"); | ||
| 27 | }; | 13 | }; |
| 28 | 14 | ||
| 29 | #if GLOBALS == 0x5B28C0 | 15 | #if GLOBALS == 0x5B28C0 |
| diff --git a/Test/Temp.cpp b/Test/Temp.cpp new file mode 100644 index 0000000..3d589c1 --- /dev/null +++ b/Test/Temp.cpp | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | #include "gtest/gtest.h" | ||
| 2 | #include "Randomizer.h" | ||
| 3 | |||
| 4 | GTEST_TEST(SwapTests, Shipwreck) { | ||
| 5 | Randomizer randomizer; | ||
| 6 | int shipwreck = 0xAFB; | ||
| 7 | int thEntry = 0x288C; | ||
| 8 | int si1 = 0x00000022; | ||
| 9 | int bu1 = 0x6; | ||
| 10 | int td1 = 0x5D; | ||
| 11 | |||
| 12 | randomizer.SwapPanels(si1, td1, SWAP_LINES); | ||
| 13 | |||
| 14 | } | ||
| diff --git a/Test/Test.vcxproj b/Test/Test.vcxproj index 15843f3..75e22a9 100644 --- a/Test/Test.vcxproj +++ b/Test/Test.vcxproj | |||
| @@ -35,7 +35,6 @@ | |||
| 35 | <ItemGroup> | 35 | <ItemGroup> |
| 36 | <ClCompile Include="Temp.cpp" /> | 36 | <ClCompile Include="Temp.cpp" /> |
| 37 | <ClCompile Include="RandomTests.cpp" /> | 37 | <ClCompile Include="RandomTests.cpp" /> |
| 38 | <ClCompile Include="Swap.cpp" /> | ||
| 39 | </ItemGroup> | 38 | </ItemGroup> |
| 40 | <ItemGroup> | 39 | <ItemGroup> |
| 41 | <ProjectReference Include="..\Source\Source.vcxproj"> | 40 | <ProjectReference Include="..\Source\Source.vcxproj"> |
