diff options
| -rw-r--r-- | Source/Panels.h | 87 | ||||
| -rw-r--r-- | Source/Randomizer.cpp | 286 | ||||
| -rw-r--r-- | Source/Randomizer.h | 168 | ||||
| -rw-r--r-- | Source/RandomizerCore.cpp | 119 | ||||
| -rw-r--r-- | Source/RandomizerCore.h | 155 |
5 files changed, 428 insertions, 387 deletions
| diff --git a/Source/Panels.h b/Source/Panels.h index e070005..b3a7791 100644 --- a/Source/Panels.h +++ b/Source/Panels.h | |||
| @@ -17,50 +17,6 @@ std::vector<int> lasers = { | |||
| 17 | 0x19650, // Shadows | 17 | 0x19650, // Shadows |
| 18 | }; | 18 | }; |
| 19 | 19 | ||
| 20 | // Note: Some of these (non-desert) are duplicated elsewhere | ||
| 21 | std::vector<int> burnablePanels = { | ||
| 22 | 0x17D9C, // Treehouse Yellow 7 | ||
| 23 | 0x17DC2, // Treehouse Yellow 8 | ||
| 24 | 0x17DC4, // Treehouse Yellow 9 | ||
| 25 | 0x00999, // Swamp Discontinuous 1 | ||
| 26 | 0x0099D, // Swamp Discontinuous 2 | ||
| 27 | 0x009A0, // Swamp Discontinuous 3 | ||
| 28 | 0x009A1, // Swamp Discontinuous 4 | ||
| 29 | 0x00007, // Swamp Rotation Tutorial 1 | ||
| 30 | 0x00008, // Swamp Rotation Tutorial 2 | ||
| 31 | 0x00009, // Swamp Rotation Tutorial 3 | ||
| 32 | 0x0000A, // Swamp Rotation Tutorial 4 | ||
| 33 | 0x28AC7, // Town Blue 1 | ||
| 34 | 0x28AC8, // Town Blue 2 | ||
| 35 | 0x28ACA, // Town Blue 3 | ||
| 36 | 0x28ACB, // Town Blue 4 | ||
| 37 | 0x28ACC, // Town Blue 5 | ||
| 38 | 0x17CF0, // Mill Discard | ||
| 39 | |||
| 40 | 0x00698, // Desert Surface 1 | ||
| 41 | 0x0048F, // Desert Surface 2 | ||
| 42 | 0x09F92, // Desert Surface 3 | ||
| 43 | 0x0A036, // Desert Surface 4 | ||
| 44 | 0x09DA6, // Desert Surface 5 | ||
| 45 | 0x0A049, // Desert Surface 6 | ||
| 46 | 0x0A053, // Desert Surface 7 | ||
| 47 | 0x09F94, // Desert Surface 8 | ||
| 48 | 0x00422, // Desert Light 1 | ||
| 49 | 0x006E3, // Desert Light 2 | ||
| 50 | 0x0A02D, // Desert Light 3 | ||
| 51 | 0x00C72, // Desert Pond 1 | ||
| 52 | 0x0129D, // Desert Pond 2 | ||
| 53 | 0x008BB, // Desert Pond 3 | ||
| 54 | 0x0078D, // Desert Pond 4 | ||
| 55 | 0x18313, // Desert Pond 5 | ||
| 56 | 0x04D18, // Desert Flood 1 | ||
| 57 | 0x01205, // Desert Flood 2 | ||
| 58 | 0x181AB, // Desert Flood 3 | ||
| 59 | 0x0117A, // Desert Flood 4 | ||
| 60 | 0x17ECA, // Desert Flood 5 | ||
| 61 | 0x012D7, // Desert Final Far | ||
| 62 | }; | ||
| 63 | |||
| 64 | // Note: Some of these (non-controls) are duplicated elsewhere | 20 | // Note: Some of these (non-controls) are duplicated elsewhere |
| 65 | // TODO: Gave up | 21 | // TODO: Gave up |
| 66 | std::vector<int> leftRightPanels = { | 22 | std::vector<int> leftRightPanels = { |
| @@ -105,10 +61,10 @@ std::vector<int> upDownPanels = { | |||
| 105 | 61 | ||
| 106 | // Note: Some of these (non-controls) are duplicated elsewhere | 62 | // Note: Some of these (non-controls) are duplicated elsewhere |
| 107 | std::vector<int> leftForwardRightPanels = { | 63 | std::vector<int> leftForwardRightPanels = { |
| 108 | // 0x00075, // Symmetry Island Colored Dots 3 | 64 | 0x00075, // Symmetry Island Colored Dots 3 |
| 109 | // 0x288EA, // UTM Perspective 1 | 65 | 0x288EA, // UTM Perspective 1 |
| 110 | // 0x288FC, // UTM Perspective 2 | 66 | 0x288FC, // UTM Perspective 2 |
| 111 | // 0x289E7, // UTM Perspective 3 | 67 | 0x289E7, // UTM Perspective 3 |
| 112 | 68 | ||
| 113 | 0x17DD1, // Treehouse Left Orange 9 | 69 | 0x17DD1, // Treehouse Left Orange 9 |
| 114 | 0x17CE3, // Treehouse Right Orange 4 | 70 | 0x17CE3, // Treehouse Right Orange 4 |
| @@ -458,6 +414,35 @@ std::vector<int> squarePanels = { | |||
| 458 | 0x09E85, // Tunnels Town Shortcut | 414 | 0x09E85, // Tunnels Town Shortcut |
| 459 | }; | 415 | }; |
| 460 | 416 | ||
| 417 | std::vector<int> desertPanels = { | ||
| 418 | 0x00698, // Desert Surface 1 | ||
| 419 | 0x0048F, // Desert Surface 2 | ||
| 420 | 0x09F92, // Desert Surface 3 | ||
| 421 | 0x0A036, // Desert Surface 4 | ||
| 422 | 0x09DA6, // Desert Surface 5 | ||
| 423 | 0x0A049, // Desert Surface 6 | ||
| 424 | 0x0A053, // Desert Surface 7 | ||
| 425 | 0x09F94, // Desert Surface 8 | ||
| 426 | 0x00422, // Desert Light 1 | ||
| 427 | 0x006E3, // Desert Light 2 | ||
| 428 | 0x0A02D, // Desert Light 3 | ||
| 429 | 0x00C72, // Desert Pond 1 | ||
| 430 | 0x0129D, // Desert Pond 2 | ||
| 431 | 0x008BB, // Desert Pond 3 | ||
| 432 | 0x0078D, // Desert Pond 4 | ||
| 433 | 0x18313, // Desert Pond 5 | ||
| 434 | 0x04D18, // Desert Flood 1 | ||
| 435 | 0x01205, // Desert Flood 2 | ||
| 436 | 0x181AB, // Desert Flood 3 | ||
| 437 | 0x0117A, // Desert Flood 4 | ||
| 438 | 0x17ECA, // Desert Flood 5 | ||
| 439 | // 0x18076, // Desert Flood Exit | ||
| 440 | // 0x0A15C, // Desert Final Left Convex | ||
| 441 | // 0x09FFF, // Desert Final Left Concave | ||
| 442 | // 0x0A15F, // Desert Final Near | ||
| 443 | 0x012D7, // Desert Final Far | ||
| 444 | }; | ||
| 445 | |||
| 461 | std::vector<int> shadowsPanels = { | 446 | std::vector<int> shadowsPanels = { |
| 462 | 0x198B5, // Shadows Tutorial 1 | 447 | 0x198B5, // Shadows Tutorial 1 |
| 463 | 0x198BD, // Shadows Tutorial 2 | 448 | 0x198BD, // Shadows Tutorial 2 |
| @@ -485,8 +470,8 @@ std::vector<int> shadowsPanels = { | |||
| 485 | 470 | ||
| 486 | std::vector<int> monasteryPanels = { | 471 | std::vector<int> monasteryPanels = { |
| 487 | 0x00B10, // Monastery Left Door | 472 | 0x00B10, // Monastery Left Door |
| 488 | 0x00290, // Monastery Exterior 1 | ||
| 489 | 0x00C92, // Monastery Right Door | 473 | 0x00C92, // Monastery Right Door |
| 474 | 0x00290, // Monastery Exterior 1 | ||
| 490 | 0x00038, // Monastery Exterior 2 | 475 | 0x00038, // Monastery Exterior 2 |
| 491 | 0x00037, // Monastery Exterior 3 | 476 | 0x00037, // Monastery Exterior 3 |
| 492 | // 0x09D9B, // Monastery Bonsai | 477 | // 0x09D9B, // Monastery Bonsai |
| @@ -616,10 +601,6 @@ std::vector<int> nothingPanels = { | |||
| 616 | 0x0C335, // Tutorial Pillar | 601 | 0x0C335, // Tutorial Pillar |
| 617 | 0x0C373, // Tutorial Patio floor | 602 | 0x0C373, // Tutorial Patio floor |
| 618 | 0x1C349, // Symmetry Island Door 2 - Collision fails here, sadly | 603 | 0x1C349, // Symmetry Island Door 2 - Collision fails here, sadly |
| 619 | 0x18076, // Desert Flood Exit - I am doing something with this -- but it's a very unique panel. | ||
| 620 | 0x0A15C, // Desert Final Left Convex | ||
| 621 | 0x09FFF, // Desert Final Left Concave | ||
| 622 | 0x0A15F, // Desert Final Near | ||
| 623 | 0x033EA, // Keep Yellow Pressure Plates | 604 | 0x033EA, // Keep Yellow Pressure Plates |
| 624 | 0x0A3A8, // Keep Yellow Reset | 605 | 0x0A3A8, // Keep Yellow Reset |
| 625 | 0x01BE9, // Keep Purple Pressure Plates | 606 | 0x01BE9, // Keep Purple Pressure Plates |
| diff --git a/Source/Randomizer.cpp b/Source/Randomizer.cpp index b8462e5..8c4297d 100644 --- a/Source/Randomizer.cpp +++ b/Source/Randomizer.cpp | |||
| @@ -2,15 +2,10 @@ | |||
| 2 | * TODO: Split out main() logic into another file, and move into separate functions for easier testing. Then write tests. | 2 | * TODO: Split out main() logic into another file, and move into separate functions for easier testing. Then write tests. |
| 3 | * BUGS: | 3 | * BUGS: |
| 4 | * Shipwreck vault fails, possibly because of dot_reflection? Sometimes? | 4 | * Shipwreck vault fails, possibly because of dot_reflection? Sometimes? |
| 5 | * Treehouse pivots *should* work, but I need to not copy style_flags. | ||
| 6 | This seems to cause crashes when pivots appear elsewhere in the world. | ||
| 7 | * Some panels are impossible casually: (idc, I think) | 5 | * Some panels are impossible casually: (idc, I think) |
| 8 | ** Town Stars, Invisible dots | 6 | ** Town Stars, Invisible dots |
| 9 | * Something is wrong with jungle re: softlocks | ||
| 10 | * FEATURES: | 7 | * FEATURES: |
| 11 | * SWAP_TARGETS should still require the full panel sequence (and have ways to prevent softlocks?) | 8 | * SWAP_TARGETS should still require the full panel sequence (and have ways to prevent softlocks?) |
| 12 | ** Think about: Jungle | ||
| 13 | ** Hard: Monastery | ||
| 14 | ** Do: Challenge | 9 | ** Do: Challenge |
| 15 | * Randomize audio logs | 10 | * Randomize audio logs |
| 16 | * Swap sounds in jungle (along with panels) -- maybe impossible | 11 | * Swap sounds in jungle (along with panels) -- maybe impossible |
| @@ -28,212 +23,139 @@ | |||
| 28 | #include <chrono> | 23 | #include <chrono> |
| 29 | 24 | ||
| 30 | template <class T> | 25 | template <class T> |
| 31 | size_t find(const std::vector<T> &data, T search, size_t startIndex = 0) { | 26 | int find(const std::vector<T> &data, T search, size_t startIndex = 0) { |
| 32 | for (size_t i=startIndex ; i<data.size(); i++) { | 27 | for (size_t i=startIndex ; i<data.size(); i++) { |
| 33 | if (data[i] == search) return i; | 28 | if (data[i] == search) return static_cast<int>(i); |
| 34 | } | 29 | } |
| 35 | std::cout << "Couldn't find " << search << " in data!" << std::endl; | 30 | std::cout << "Couldn't find " << search << " in data!" << std::endl; |
| 36 | exit(-1); | 31 | exit(-1); |
| 37 | } | 32 | } |
| 38 | 33 | ||
| 39 | void Randomizer::Randomize(int seed) | 34 | void Randomizer::Randomize() |
| 40 | { | 35 | { |
| 41 | // Content swaps -- must happen before squarePanels | 36 | // Content swaps -- must happen before squarePanels |
| 42 | Randomize(tallUpDownPanels, SWAP_LINES | SWAP_STYLE); | 37 | _core.Randomize(tallUpDownPanels, SWAP_LINES|SWAP_LINES); |
| 43 | Randomize(upDownPanels, SWAP_LINES | SWAP_STYLE); | 38 | _core.Randomize(upDownPanels, SWAP_LINES|SWAP_LINES); |
| 44 | Randomize(leftForwardRightPanels, SWAP_LINES); | 39 | _core.Randomize(leftForwardRightPanels, SWAP_LINES|SWAP_LINES); |
| 45 | 40 | ||
| 46 | Randomize(squarePanels, SWAP_LINES | SWAP_STYLE); | 41 | _core.Randomize(squarePanels, SWAP_LINES|SWAP_LINES); |
| 47 | 42 | ||
| 48 | // Frame swaps -- must happen after squarePanels | 43 | // Individual area modifications |
| 49 | Randomize(burnablePanels, SWAP_LINES | SWAP_STYLE); | 44 | RandomizeTutorial(); |
| 45 | RandomizeSymmetry(); | ||
| 46 | RandomizeDesert(); | ||
| 47 | RandomizeQuarry(); | ||
| 48 | RandomizeTreehouse(); | ||
| 49 | RandomizeKeep(); | ||
| 50 | RandomizeShadows(); | ||
| 51 | RandomizeTown(); | ||
| 52 | RandomizeMonastery(); | ||
| 53 | RandomizeBunker(); | ||
| 54 | RandomizeJungle(); | ||
| 55 | RandomizeSwamp(); | ||
| 56 | RandomizeMountain(); | ||
| 57 | } | ||
| 50 | 58 | ||
| 51 | // Target swaps, can happen whenever | 59 | void Randomizer::RandomizeTutorial() { |
| 52 | Randomize(lasers, SWAP_TARGETS); | 60 | // Disable tutorial cursor speed modifications (not working?) |
| 53 | // Read the target of keep front laser, and write it to keep back laser. | 61 | _core.WritePanelData<float>(0x00295, CURSOR_SPEED_SCALE, {1.0}); |
| 54 | std::vector<int> keepFrontLaserTarget = ReadPanelData<int>(0x0360E, TARGET, 1); | 62 | _core.WritePanelData<float>(0x0C373, CURSOR_SPEED_SCALE, {1.0}); |
| 55 | WritePanelData<int>(0x03317, TARGET, keepFrontLaserTarget); | 63 | _core.WritePanelData<float>(0x00293, CURSOR_SPEED_SCALE, {1.0}); |
| 64 | _core.WritePanelData<float>(0x002C2, CURSOR_SPEED_SCALE, {1.0}); | ||
| 65 | } | ||
| 56 | 66 | ||
| 57 | std::vector<int> randomOrder; | 67 | void Randomizer::RandomizeSymmetry() { |
| 68 | } | ||
| 58 | 69 | ||
| 59 | /* Jungle | 70 | void Randomizer::RandomizeDesert() { |
| 60 | randomOrder = std::vector(junglePanels.size(), 0); | 71 | _core.Randomize(desertPanels, SWAP_LINES|SWAP_LINES); |
| 61 | std::iota(randomOrder.begin(), randomOrder.end(), 0); | ||
| 62 | // Randomize Waves 2-7 | ||
| 63 | // Waves 1 cannot be randomized, since no other panel can start on | ||
| 64 | randomizer.RandomizeRange(randomOrder, SWAP_NONE, 1, 7); | ||
| 65 | // Randomize Pitches 1-6 onto themselves | ||
| 66 | randomizer.RandomizeRange(randomOrder, SWAP_NONE, 7, 13); | ||
| 67 | randomizer.ReassignTargets(junglePanels, randomOrder); | ||
| 68 | */ | ||
| 69 | 72 | ||
| 70 | /* Bunker */ | 73 | // Turn off desert surface 8 |
| 71 | randomOrder = std::vector(bunkerPanels.size(), 0); | 74 | _core.WritePanelData<float>(0x09F94, POWER, {0.0, 0.0}); |
| 72 | std::iota(randomOrder.begin(), randomOrder.end(), 0); | 75 | // Turn off desert flood final |
| 73 | // Randomize Tutorial 2-Advanced Tutorial 4 + Glass 1 | 76 | _core.WritePanelData<float>(0x18076, POWER, {0.0, 0.0}); |
| 74 | // Tutorial 1 cannot be randomized, since no other panel can start on | 77 | // Change desert floating target to desert flood final |
| 75 | // Glass 1 will become door + glass 1, due to the targetting system | 78 | _core.WritePanelData<int>(0x17ECA, TARGET, {0x18077}); |
| 76 | RandomizeRange(randomOrder, SWAP_NONE, 1, 10); | 79 | } |
| 77 | // Randomize Glass 1-3 into everything after the door | ||
| 78 | const size_t glassDoorIndex = find(randomOrder, 9) + 1; | ||
| 79 | RandomizeRange(randomOrder, SWAP_NONE, glassDoorIndex, 12); | ||
| 80 | ReassignTargets(bunkerPanels, randomOrder); | ||
| 81 | |||
| 82 | /* Shadows */ | ||
| 83 | randomOrder = std::vector(shadowsPanels.size(), 0); | ||
| 84 | std::iota(randomOrder.begin(), randomOrder.end(), 0); | ||
| 85 | RandomizeRange(randomOrder, SWAP_NONE, 0, 8); // Tutorial | ||
| 86 | RandomizeRange(randomOrder, SWAP_NONE, 8, 16); // Avoid | ||
| 87 | RandomizeRange(randomOrder, SWAP_NONE, 16, 21); // Follow | ||
| 88 | ReassignTargets(shadowsPanels, randomOrder); | ||
| 89 | // Turn off original starting panel | ||
| 90 | WritePanelData<float>(shadowsPanels[0], POWER, {0.0f, 0.0f}); | ||
| 91 | // Turn on new starting panel | ||
| 92 | WritePanelData<float>(shadowsPanels[randomOrder[0]], POWER, {1.0f, 1.0f}); | ||
| 93 | 80 | ||
| 94 | /* Monastery | 81 | void Randomizer::RandomizeQuarry() { |
| 95 | randomOrder = std::vector(monasteryPanels.size(), 0); | 82 | } |
| 96 | std::iota(randomOrder.begin(), randomOrder.end(), 0); | ||
| 97 | randomizer.RandomizeRange(randomOrder, SWAP_NONE, 2, 6); // outer 2 & 3, inner 1 | ||
| 98 | // Once outer 3 and right door are solved, inner 2-4 are accessible | ||
| 99 | int innerPanelsIndex = max(find(randomOrder, 2), find(randomOrder, 4)); | ||
| 100 | randomizer.RandomizeRange(randomOrder, SWAP_NONE, innerPanelsIndex, 9); // Inner 2-4 | ||
| 101 | 83 | ||
| 102 | randomizer.ReassignTargets(monasteryPanels, randomOrder); | 84 | void Randomizer::RandomizeTreehouse() { |
| 103 | */ | 85 | // Ensure that whatever pivot panels we have are flagged as "pivotable" |
| 86 | _core.WritePanelData<int>(0x17DD1, STYLE_FLAGS, {0x8000}); | ||
| 87 | _core.WritePanelData<int>(0x17CE3, STYLE_FLAGS, {0x8000}); | ||
| 88 | _core.WritePanelData<int>(0x17DB7, STYLE_FLAGS, {0x8000}); | ||
| 89 | _core.WritePanelData<int>(0x17E52, STYLE_FLAGS, {0x8000}); | ||
| 104 | } | 90 | } |
| 105 | 91 | ||
| 106 | Randomizer::Randomizer() | 92 | void Randomizer::RandomizeKeep() { |
| 107 | { | 93 | } |
| 108 | // Turn off desert surface 8 | ||
| 109 | WritePanelData<float>(0x09F94, POWER, {0.0, 0.0}); | ||
| 110 | // Turn off desert flood final | ||
| 111 | WritePanelData<float>(0x18076, POWER, {0.0, 0.0}); | ||
| 112 | // Change desert floating target to desert flood final | ||
| 113 | WritePanelData<int>(0x17ECA, TARGET, {0x18077}); | ||
| 114 | 94 | ||
| 95 | void Randomizer::RandomizeShadows() { | ||
| 115 | // Distance-gate shadows laser to prevent sniping through the bars | 96 | // Distance-gate shadows laser to prevent sniping through the bars |
| 116 | WritePanelData<float>(0x19650, MAX_BROADCAST_DISTANCE, {2.5}); | 97 | _core.WritePanelData<float>(0x19650, MAX_BROADCAST_DISTANCE, {2.5}); |
| 117 | // Change the shadows tutorial cable to only activate avoid | 98 | // Change the shadows tutorial cable to only activate avoid |
| 118 | WritePanelData<int>(0x319A8, CABLE_TARGET_2, {0}); | 99 | _core.WritePanelData<int>(0x319A8, CABLE_TARGET_2, {0}); |
| 119 | // Change shadows avoid 8 to power shadows follow | 100 | // Change shadows avoid 8 to power shadows follow |
| 120 | WritePanelData<int>(0x1972F, TARGET, {0x1C34C}); | 101 | _core.WritePanelData<int>(0x1972F, TARGET, {0x1C34C}); |
| 121 | |||
| 122 | // Distance-gate swamp snipe 1 to prevent RNG swamp snipe | ||
| 123 | WritePanelData<float>(0x17C05, MAX_BROADCAST_DISTANCE, {5.0}); | ||
| 124 | 102 | ||
| 125 | // Disable tutorial cursor speed modifications (not working?) | 103 | std::vector<int> randomOrder(shadowsPanels.size(), 0); |
| 126 | WritePanelData<float>(0x00295, CURSOR_SPEED_SCALE, {1.0}); | 104 | std::iota(randomOrder.begin(), randomOrder.end(), 0); |
| 127 | WritePanelData<float>(0x0C373, CURSOR_SPEED_SCALE, {1.0}); | 105 | _core.RandomizeRange(randomOrder, SWAP_NONE, 0, 8); // Tutorial |
| 128 | WritePanelData<float>(0x00293, CURSOR_SPEED_SCALE, {1.0}); | 106 | _core.RandomizeRange(randomOrder, SWAP_NONE, 8, 16); // Avoid |
| 129 | WritePanelData<float>(0x002C2, CURSOR_SPEED_SCALE, {1.0}); | 107 | _core.RandomizeRange(randomOrder, SWAP_NONE, 16, 21); // Follow |
| 108 | _core.ReassignTargets(shadowsPanels, randomOrder); | ||
| 109 | // Turn off original starting panel | ||
| 110 | _core.WritePanelData<float>(shadowsPanels[0], POWER, {0.0f, 0.0f}); | ||
| 111 | // Turn on new starting panel | ||
| 112 | _core.WritePanelData<float>(shadowsPanels[randomOrder[0]], POWER, {1.0f, 1.0f}); | ||
| 130 | } | 113 | } |
| 131 | 114 | ||
| 132 | void Randomizer::Randomize(std::vector<int>& panels, int flags) { | 115 | void Randomizer::RandomizeTown() { |
| 133 | return RandomizeRange(panels, flags, 0, panels.size()); | ||
| 134 | } | 116 | } |
| 135 | 117 | ||
| 136 | // Range is [start, end) | 118 | void Randomizer::RandomizeMonastery() { |
| 137 | void Randomizer::RandomizeRange(std::vector<int> &panels, int flags, size_t startIndex, size_t endIndex) { | 119 | std::vector<int> randomOrder(monasteryPanels.size(), 0); |
| 138 | if (panels.size() == 0) return; | 120 | std::iota(randomOrder.begin(), randomOrder.end(), 0); |
| 139 | if (startIndex >= endIndex) return; | 121 | _core.RandomizeRange(randomOrder, SWAP_NONE, 3, 9); // Outer 2 & 3, Inner 1-4 |
| 140 | if (endIndex >= panels.size()) endIndex = panels.size(); | 122 | _core.ReassignTargets(monasteryPanels, randomOrder); |
| 141 | for (size_t i = endIndex-1; i > startIndex+1; i--) { | ||
| 142 | const size_t target = rand() % (i - startIndex) + startIndex; | ||
| 143 | if (i != target) { | ||
| 144 | // std::cout << "Swapping panels " << std::hex << panels[i] << " and " << std::hex << panels[target] << std::endl; | ||
| 145 | SwapPanels(panels[i], panels[target], flags); | ||
| 146 | std::swap(panels[i], panels[target]); // Panel indices in the array | ||
| 147 | } | ||
| 148 | } | ||
| 149 | } | 123 | } |
| 150 | 124 | ||
| 151 | void Randomizer::SwapPanels(int panel1, int panel2, int flags) { | 125 | void Randomizer::RandomizeBunker() { |
| 152 | std::map<int, int> offsets; | 126 | std::vector<int> randomOrder(bunkerPanels.size(), 0); |
| 127 | std::iota(randomOrder.begin(), randomOrder.end(), 0); | ||
| 128 | // Randomize Tutorial 2-Advanced Tutorial 4 + Glass 1 | ||
| 129 | // Tutorial 1 cannot be randomized, since no other panel can start on | ||
| 130 | // Glass 1 will become door + glass 1, due to the targetting system | ||
| 131 | _core.RandomizeRange(randomOrder, SWAP_NONE, 1, 10); | ||
| 132 | // Randomize Glass 1-3 into everything after the door/glass 1 | ||
| 133 | const size_t glass1Index = find(randomOrder, 9); | ||
| 134 | _core.RandomizeRange(randomOrder, SWAP_NONE, glass1Index + 1, 12); | ||
| 135 | _core.ReassignTargets(bunkerPanels, randomOrder); | ||
| 136 | } | ||
| 153 | 137 | ||
| 154 | if (flags & SWAP_TARGETS) { | 138 | void Randomizer::RandomizeJungle() { |
| 155 | offsets[TARGET] = sizeof(int); | 139 | std::vector<int> randomOrder(junglePanels.size(), 0); |
| 156 | } | 140 | std::iota(randomOrder.begin(), randomOrder.end(), 0); |
| 157 | if (flags & SWAP_STYLE) { | 141 | // Randomize Waves 2-7 |
| 158 | offsets[STYLE_FLAGS] = sizeof(int); | 142 | // Waves 1 cannot be randomized, since no other panel can start on |
| 159 | } | 143 | _core.RandomizeRange(randomOrder, SWAP_NONE, 1, 7); |
| 160 | if (flags & SWAP_LINES) { | 144 | // Randomize Pitches 1-6 onto themselves |
| 161 | offsets[PATH_COLOR] = 16; | 145 | _core.RandomizeRange(randomOrder, SWAP_NONE, 8, 13); |
| 162 | offsets[REFLECTION_PATH_COLOR] = 16; | 146 | _core.ReassignTargets(junglePanels, randomOrder); |
| 163 | offsets[DOT_COLOR] = 16; | 147 | } |
| 164 | offsets[ACTIVE_COLOR] = 16; | ||
| 165 | offsets[BACKGROUND_REGION_COLOR] = 16; | ||
| 166 | offsets[SUCCESS_COLOR_A] = 16; | ||
| 167 | offsets[SUCCESS_COLOR_B] = 16; | ||
| 168 | offsets[STROBE_COLOR_A] = 16; | ||
| 169 | offsets[STROBE_COLOR_B] = 16; | ||
| 170 | offsets[ERROR_COLOR] = 16; | ||
| 171 | offsets[PATTERN_POINT_COLOR] = 16; | ||
| 172 | offsets[PATTERN_POINT_COLOR_A] = 16; | ||
| 173 | offsets[PATTERN_POINT_COLOR_B] = 16; | ||
| 174 | offsets[SYMBOL_A] = 16; | ||
| 175 | offsets[SYMBOL_B] = 16; | ||
| 176 | offsets[SYMBOL_C] = 16; | ||
| 177 | offsets[SYMBOL_D] = 16; | ||
| 178 | offsets[SYMBOL_E] = 16; | ||
| 179 | offsets[PUSH_SYMBOL_COLORS] = sizeof(int); | ||
| 180 | offsets[OUTER_BACKGROUND] = 16; | ||
| 181 | offsets[OUTER_BACKGROUND_MODE] = sizeof(int); | ||
| 182 | offsets[TRACED_EDGES] = 16; | ||
| 183 | offsets[AUDIO_PREFIX] = sizeof(void*); | ||
| 184 | // offsets[IS_CYLINDER] = sizeof(int); | ||
| 185 | // offsets[CYLINDER_Z0] = sizeof(float); | ||
| 186 | // offsets[CYLINDER_Z1] = sizeof(float); | ||
| 187 | // offsets[CYLINDER_RADIUS] = sizeof(float); | ||
| 188 | offsets[SPECULAR_ADD] = sizeof(float); | ||
| 189 | offsets[SPECULAR_POWER] = sizeof(int); | ||
| 190 | offsets[PATH_WIDTH_SCALE] = sizeof(float); | ||
| 191 | offsets[STARTPOINT_SCALE] = sizeof(float); | ||
| 192 | offsets[NUM_DOTS] = sizeof(int); | ||
| 193 | offsets[NUM_CONNECTIONS] = sizeof(int); | ||
| 194 | offsets[DOT_POSITIONS] = sizeof(void*); | ||
| 195 | offsets[DOT_FLAGS] = sizeof(void*); | ||
| 196 | offsets[DOT_CONNECTION_A] = sizeof(void*); | ||
| 197 | offsets[DOT_CONNECTION_B] = sizeof(void*); | ||
| 198 | offsets[DECORATIONS] = sizeof(void*); | ||
| 199 | offsets[DECORATION_FLAGS] = sizeof(void*); | ||
| 200 | offsets[DECORATION_COLORS] = sizeof(void*); | ||
| 201 | offsets[NUM_DECORATIONS] = sizeof(int); | ||
| 202 | offsets[REFLECTION_DATA] = sizeof(void*); | ||
| 203 | offsets[GRID_SIZE_X] = sizeof(int); | ||
| 204 | offsets[GRID_SIZE_Y] = sizeof(int); | ||
| 205 | offsets[SEQUENCE_LEN] = sizeof(int); | ||
| 206 | offsets[SEQUENCE] = sizeof(void*); | ||
| 207 | offsets[DOT_SEQUENCE_LEN] = sizeof(int); | ||
| 208 | offsets[DOT_SEQUENCE] = sizeof(void*); | ||
| 209 | offsets[DOT_SEQUENCE_LEN_REFLECTION] = sizeof(int); | ||
| 210 | offsets[DOT_SEQUENCE_REFLECTION] = sizeof(void*); | ||
| 211 | offsets[NUM_COLORED_REGIONS] = sizeof(int); | ||
| 212 | offsets[COLORED_REGIONS] = sizeof(void*); | ||
| 213 | offsets[PANEL_TARGET] = sizeof(void*); | ||
| 214 | offsets[SPECULAR_TEXTURE] = sizeof(void*); | ||
| 215 | } | ||
| 216 | 148 | ||
| 217 | for (auto const& [offset, size] : offsets) { | 149 | void Randomizer::RandomizeSwamp() { |
| 218 | std::vector<byte> panel1data = ReadPanelData<byte>(panel1, offset, size); | 150 | // Distance-gate swamp snipe 1 to prevent RNG swamp snipe |
| 219 | std::vector<byte> panel2data = ReadPanelData<byte>(panel2, offset, size); | 151 | _core.WritePanelData<float>(0x17C05, MAX_BROADCAST_DISTANCE, {15.0}); |
| 220 | WritePanelData<byte>(panel2, offset, panel1data); | ||
| 221 | WritePanelData<byte>(panel1, offset, panel2data); | ||
| 222 | } | ||
| 223 | } | 152 | } |
| 224 | 153 | ||
| 225 | void Randomizer::ReassignTargets(const std::vector<int>& panels, const std::vector<int>& order) { | 154 | void Randomizer::RandomizeMountain() { |
| 226 | // This list is offset by 1, so the target of the Nth panel is in position N (aka the N+1th element) | 155 | _core.Randomize(lasers, SWAP_TARGETS); |
| 227 | // The first panel may not have a wire to power it, so we use the panel ID itself. | 156 | _core.Randomize(pillars, SWAP_LINES|SWAP_LINES); |
| 228 | std::vector<int> targetToActivatePanel = {panels[0] + 1}; | ||
| 229 | for (const int panel : panels) { | ||
| 230 | int target = ReadPanelData<int>(panel, TARGET, 1)[0]; | ||
| 231 | targetToActivatePanel.push_back(target); | ||
| 232 | } | ||
| 233 | 157 | ||
| 234 | for (size_t i=0; i<order.size() - 1; i++) { | 158 | // Read the target of keep front laser, and write it to keep back laser. |
| 235 | // Set the target of order[i] to order[i+1], using the "real" target as determined above. | 159 | std::vector<int> keepFrontLaserTarget = _core.ReadPanelData<int>(0x0360E, TARGET, 1); |
| 236 | const int panelTarget = targetToActivatePanel[order[i+1]]; | 160 | _core.WritePanelData<int>(0x03317, TARGET, keepFrontLaserTarget); |
| 237 | WritePanelData<int>(panels[order[i]], TARGET, {panelTarget}); | 161 | } \ No newline at end of file |
| 238 | } | ||
| 239 | } | ||
| diff --git a/Source/Randomizer.h b/Source/Randomizer.h index 6615e31..861f5a2 100644 --- a/Source/Randomizer.h +++ b/Source/Randomizer.h | |||
| @@ -1,159 +1,23 @@ | |||
| 1 | #pragma once | 1 | #pragma once |
| 2 | #include "Memory.h" | 2 | #include "RandomizerCore.h" |
| 3 | |||
| 4 | // #define GLOBALS 0x5B28C0 | ||
| 5 | #define GLOBALS 0x62A080 | ||
| 6 | |||
| 7 | __declspec(selectany) int SWAP_NONE = 0x0; | ||
| 8 | __declspec(selectany) int SWAP_TARGETS = 0x1; | ||
| 9 | __declspec(selectany) int SWAP_LINES = 0x2; | ||
| 10 | __declspec(selectany) int SWAP_STYLE = 0x4; | ||
| 11 | 3 | ||
| 12 | class Randomizer { | 4 | class Randomizer { |
| 13 | public: | 5 | public: |
| 14 | Randomizer(); | 6 | void Randomize(); |
| 15 | |||
| 16 | void Randomize(int seed); | ||
| 17 | |||
| 18 | void Randomize(std::vector<int>& panels, int flags); | ||
| 19 | void RandomizeRange(std::vector<int> &panels, int flags, size_t startIndex, size_t endIndex); | ||
| 20 | void SwapPanels(int panel1, int panel2, int flags); | ||
| 21 | void ReassignTargets(const std::vector<int>& panels, const std::vector<int>& order); | ||
| 22 | |||
| 23 | template <class T> | ||
| 24 | std::vector<T> ReadPanelData(int panel, int offset, size_t size) { | ||
| 25 | return _memory.ReadData<T>({GLOBALS, 0x18, panel*8, offset}, size); | ||
| 26 | } | ||
| 27 | |||
| 28 | template <class T> | ||
| 29 | void WritePanelData(int panel, int offset, const std::vector<T>& data) { | ||
| 30 | _memory.WriteData<T>({GLOBALS, 0x18, panel*8, offset}, data); | ||
| 31 | } | ||
| 32 | 7 | ||
| 33 | private: | 8 | private: |
| 34 | Memory _memory = Memory("witness64_d3d11.exe"); | 9 | RandomizerCore _core; |
| 10 | void RandomizeTutorial(); | ||
| 11 | void RandomizeSymmetry(); | ||
| 12 | void RandomizeDesert(); | ||
| 13 | void RandomizeQuarry(); | ||
| 14 | void RandomizeTreehouse(); | ||
| 15 | void RandomizeKeep(); | ||
| 16 | void RandomizeShadows(); | ||
| 17 | void RandomizeTown(); | ||
| 18 | void RandomizeMonastery(); | ||
| 19 | void RandomizeBunker(); | ||
| 20 | void RandomizeJungle(); | ||
| 21 | void RandomizeSwamp(); | ||
| 22 | void RandomizeMountain(); | ||
| 35 | }; | 23 | }; |
| 36 | |||
| 37 | #if GLOBALS == 0x5B28C0 | ||
| 38 | #define PATH_COLOR 0xC8 | ||
| 39 | #define REFLECTION_PATH_COLOR 0xD8 | ||
| 40 | #define DOT_COLOR 0xF8 | ||
| 41 | #define ACTIVE_COLOR 0x108 | ||
| 42 | #define BACKGROUND_REGION_COLOR 0x118 | ||
| 43 | #define SUCCESS_COLOR_A 0x128 | ||
| 44 | #define SUCCESS_COLOR_B 0x138 | ||
| 45 | #define STROBE_COLOR_A 0x148 | ||
| 46 | #define STROBE_COLOR_B 0x158 | ||
| 47 | #define ERROR_COLOR 0x168 | ||
| 48 | #define PATTERN_POINT_COLOR 0x188 | ||
| 49 | #define PATTERN_POINT_COLOR_A 0x198 | ||
| 50 | #define PATTERN_POINT_COLOR_B 0x1A8 | ||
| 51 | #define SYMBOL_A 0x1B8 | ||
| 52 | #define SYMBOL_B 0x1C8 | ||
| 53 | #define SYMBOL_C 0x1D8 | ||
| 54 | #define SYMBOL_D 0x1E8 | ||
| 55 | #define SYMBOL_E 0x1F8 | ||
| 56 | #define PUSH_SYMBOL_COLORS 0x208 | ||
| 57 | #define OUTER_BACKGROUND 0x20C | ||
| 58 | #define OUTER_BACKGROUND_MODE 0x21C | ||
| 59 | #define TRACED_EDGES 0x230 | ||
| 60 | #define AUDIO_PREFIX 0x278 | ||
| 61 | #define POWER 0x2A8 | ||
| 62 | #define TARGET 0x2BC | ||
| 63 | #define IS_CYLINDER 0x2FC | ||
| 64 | #define CYLINDER_Z0 0x300 | ||
| 65 | #define CYLINDER_Z1 0x304 | ||
| 66 | #define CYLINDER_RADIUS 0x308 | ||
| 67 | #define CURSOR_SPEED_SCALE 0x358 | ||
| 68 | #define SPECULAR_ADD 0x398 | ||
| 69 | #define SPECULAR_POWER 0x39C | ||
| 70 | #define PATH_WIDTH_SCALE 0x3A4 | ||
| 71 | #define STARTPOINT_SCALE 0x3A8 | ||
| 72 | #define NUM_DOTS 0x3B8 | ||
| 73 | #define NUM_CONNECTIONS 0x3BC | ||
| 74 | #define MAX_BROADCAST_DISTANCE 0x3C0 | ||
| 75 | #define DOT_POSITIONS 0x3C8 | ||
| 76 | #define DOT_FLAGS 0x3D0 | ||
| 77 | #define DOT_CONNECTION_A 0x3D8 | ||
| 78 | #define DOT_CONNECTION_B 0x3E0 | ||
| 79 | #define DECORATIONS 0x420 | ||
| 80 | #define DECORATION_FLAGS 0x428 | ||
| 81 | #define DECORATION_COLORS 0x430 | ||
| 82 | #define NUM_DECORATIONS 0x438 | ||
| 83 | #define REFLECTION_DATA 0x440 | ||
| 84 | #define GRID_SIZE_X 0x448 | ||
| 85 | #define GRID_SIZE_Y 0x44C | ||
| 86 | #define STYLE_FLAGS 0x450 | ||
| 87 | #define SEQUENCE_LEN 0x45C | ||
| 88 | #define SEQUENCE 0x460 | ||
| 89 | #define DOT_SEQUENCE_LEN 0x468 | ||
| 90 | #define DOT_SEQUENCE 0x470 | ||
| 91 | #define DOT_SEQUENCE_LEN_REFLECTION 0x478 | ||
| 92 | #define DOT_SEQUENCE_REFLECTION 0x480 | ||
| 93 | #define NUM_COLORED_REGIONS 0x4A0 | ||
| 94 | #define COLORED_REGIONS 0x4A8 | ||
| 95 | #define PANEL_TARGET 0x4B0 | ||
| 96 | #define SPECULAR_TEXTURE 0x4D8 | ||
| 97 | #define CABLE_TARGET_2 0xD8 | ||
| 98 | #elif GLOBALS == 0x62A080 | ||
| 99 | #define PATH_COLOR 0xC0 | ||
| 100 | #define REFLECTION_PATH_COLOR 0xD0 | ||
| 101 | #define DOT_COLOR 0xF0 | ||
| 102 | #define ACTIVE_COLOR 0x100 | ||
| 103 | #define BACKGROUND_REGION_COLOR 0x110 | ||
| 104 | #define SUCCESS_COLOR_A 0x120 | ||
| 105 | #define SUCCESS_COLOR_B 0x130 | ||
| 106 | #define STROBE_COLOR_A 0x140 | ||
| 107 | #define STROBE_COLOR_B 0x150 | ||
| 108 | #define ERROR_COLOR 0x160 | ||
| 109 | #define PATTERN_POINT_COLOR 0x180 | ||
| 110 | #define PATTERN_POINT_COLOR_A 0x190 | ||
| 111 | #define PATTERN_POINT_COLOR_B 0x1A0 | ||
| 112 | #define SYMBOL_A 0x1B0 | ||
| 113 | #define SYMBOL_B 0x1C0 | ||
| 114 | #define SYMBOL_C 0x1D0 | ||
| 115 | #define SYMBOL_D 0x1E0 | ||
| 116 | #define SYMBOL_E 0x1F0 | ||
| 117 | #define PUSH_SYMBOL_COLORS 0x200 | ||
| 118 | #define OUTER_BACKGROUND 0x204 | ||
| 119 | #define OUTER_BACKGROUND_MODE 0x214 | ||
| 120 | #define TRACED_EDGES 0x228 | ||
| 121 | #define AUDIO_PREFIX 0x270 | ||
| 122 | #define POWER 0x2A0 | ||
| 123 | #define TARGET 0x2B4 | ||
| 124 | #define IS_CYLINDER 0x2F4 | ||
| 125 | #define CYLINDER_Z0 0x2F8 | ||
| 126 | #define CYLINDER_Z1 0x2FC | ||
| 127 | #define CYLINDER_RADIUS 0x300 | ||
| 128 | #define CURSOR_SPEED_SCALE 0x350 | ||
| 129 | #define SPECULAR_ADD 0x38C | ||
| 130 | #define SPECULAR_POWER 0x390 | ||
| 131 | #define PATH_WIDTH_SCALE 0x39C | ||
| 132 | #define STARTPOINT_SCALE 0x3A0 | ||
| 133 | #define NUM_DOTS 0x3B4 | ||
| 134 | #define NUM_CONNECTIONS 0x3B8 | ||
| 135 | #define MAX_BROADCAST_DISTANCE 0x3BC | ||
| 136 | #define DOT_POSITIONS 0x3C0 | ||
| 137 | #define DOT_FLAGS 0x3C8 | ||
| 138 | #define DOT_CONNECTION_A 0x3D0 | ||
| 139 | #define DOT_CONNECTION_B 0x3D8 | ||
| 140 | #define DECORATIONS 0x418 | ||
| 141 | #define DECORATION_FLAGS 0x420 | ||
| 142 | #define DECORATION_COLORS 0x428 | ||
| 143 | #define NUM_DECORATIONS 0x430 | ||
| 144 | #define REFLECTION_DATA 0x438 | ||
| 145 | #define GRID_SIZE_X 0x440 | ||
| 146 | #define GRID_SIZE_Y 0x444 | ||
| 147 | #define STYLE_FLAGS 0x448 | ||
| 148 | #define SEQUENCE_LEN 0x454 | ||
| 149 | #define SEQUENCE 0x458 | ||
| 150 | #define DOT_SEQUENCE_LEN 0x460 | ||
| 151 | #define DOT_SEQUENCE 0x468 | ||
| 152 | #define DOT_SEQUENCE_LEN_REFLECTION 0x470 | ||
| 153 | #define DOT_SEQUENCE_REFLECTION 0x478 | ||
| 154 | #define NUM_COLORED_REGIONS 0x498 | ||
| 155 | #define COLORED_REGIONS 0x4A0 | ||
| 156 | #define PANEL_TARGET 0x4A8 | ||
| 157 | #define SPECULAR_TEXTURE 0x4D0 | ||
| 158 | #define CABLE_TARGET_2 0xD0 | ||
| 159 | #endif \ No newline at end of file | ||
| diff --git a/Source/RandomizerCore.cpp b/Source/RandomizerCore.cpp new file mode 100644 index 0000000..ef0e6e6 --- /dev/null +++ b/Source/RandomizerCore.cpp | |||
| @@ -0,0 +1,119 @@ | |||
| 1 | #include "RandomizerCore.h" | ||
| 2 | #include "Memory.h" | ||
| 3 | #include <sstream> | ||
| 4 | |||
| 5 | void RandomizerCore::Randomize(std::vector<int>& panels, int flags) { | ||
| 6 | return RandomizeRange(panels, flags, 0, panels.size()); | ||
| 7 | } | ||
| 8 | |||
| 9 | // Range is [start, end) | ||
| 10 | void 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 | |||
| 24 | void 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 | |||
| 96 | void 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 | } | ||
| diff --git a/Source/RandomizerCore.h b/Source/RandomizerCore.h new file mode 100644 index 0000000..4002611 --- /dev/null +++ b/Source/RandomizerCore.h | |||
| @@ -0,0 +1,155 @@ | |||
| 1 | #pragma once | ||
| 2 | #include "Memory.h" | ||
| 3 | |||
| 4 | // #define GLOBALS 0x5B28C0 | ||
| 5 | #define GLOBALS 0x62A080 | ||
| 6 | |||
| 7 | __declspec(selectany) int SWAP_NONE = 0x0; | ||
| 8 | __declspec(selectany) int SWAP_TARGETS = 0x1; | ||
| 9 | __declspec(selectany) int SWAP_LINES = 0x2; | ||
| 10 | |||
| 11 | class RandomizerCore | ||
| 12 | { | ||
| 13 | public: | ||
| 14 | void Randomize(std::vector<int>& panels, int flags); | ||
| 15 | void RandomizeRange(std::vector<int> &panels, int flags, size_t startIndex, size_t endIndex); | ||
| 16 | void SwapPanels(int panel1, int panel2, int flags); | ||
| 17 | void ReassignTargets(const std::vector<int>& panels, const std::vector<int>& order); | ||
| 18 | |||
| 19 | template <class T> | ||
| 20 | std::vector<T> ReadPanelData(int panel, int offset, size_t size) { | ||
| 21 | return _memory.ReadData<T>({GLOBALS, 0x18, panel*8, offset}, size); | ||
| 22 | } | ||
| 23 | |||
| 24 | template <class T> | ||
| 25 | void WritePanelData(int panel, int offset, const std::vector<T>& data) { | ||
| 26 | _memory.WriteData<T>({GLOBALS, 0x18, panel*8, offset}, data); | ||
| 27 | } | ||
| 28 | |||
| 29 | private: | ||
| 30 | Memory _memory = Memory("witness64_d3d11.exe"); | ||
| 31 | }; | ||
| 32 | |||
| 33 | #if GLOBALS == 0x5B28C0 | ||
| 34 | #define PATH_COLOR 0xC8 | ||
| 35 | #define REFLECTION_PATH_COLOR 0xD8 | ||
| 36 | #define DOT_COLOR 0xF8 | ||
| 37 | #define ACTIVE_COLOR 0x108 | ||
| 38 | #define BACKGROUND_REGION_COLOR 0x118 | ||
| 39 | #define SUCCESS_COLOR_A 0x128 | ||
| 40 | #define SUCCESS_COLOR_B 0x138 | ||
| 41 | #define STROBE_COLOR_A 0x148 | ||
| 42 | #define STROBE_COLOR_B 0x158 | ||
| 43 | #define ERROR_COLOR 0x168 | ||
| 44 | #define PATTERN_POINT_COLOR 0x188 | ||
| 45 | #define PATTERN_POINT_COLOR_A 0x198 | ||
| 46 | #define PATTERN_POINT_COLOR_B 0x1A8 | ||
| 47 | #define SYMBOL_A 0x1B8 | ||
| 48 | #define SYMBOL_B 0x1C8 | ||
| 49 | #define SYMBOL_C 0x1D8 | ||
| 50 | #define SYMBOL_D 0x1E8 | ||
| 51 | #define SYMBOL_E 0x1F8 | ||
| 52 | #define PUSH_SYMBOL_COLORS 0x208 | ||
| 53 | #define OUTER_BACKGROUND 0x20C | ||
| 54 | #define OUTER_BACKGROUND_MODE 0x21C | ||
| 55 | #define TRACED_EDGES 0x230 | ||
| 56 | #define AUDIO_PREFIX 0x278 | ||
| 57 | #define POWER 0x2A8 | ||
| 58 | #define TARGET 0x2BC | ||
| 59 | #define IS_CYLINDER 0x2FC | ||
| 60 | #define CYLINDER_Z0 0x300 | ||
| 61 | #define CYLINDER_Z1 0x304 | ||
| 62 | #define CYLINDER_RADIUS 0x308 | ||
| 63 | #define CURSOR_SPEED_SCALE 0x358 | ||
| 64 | #define SPECULAR_ADD 0x398 | ||
| 65 | #define SPECULAR_POWER 0x39C | ||
| 66 | #define PATH_WIDTH_SCALE 0x3A4 | ||
| 67 | #define STARTPOINT_SCALE 0x3A8 | ||
| 68 | #define NUM_DOTS 0x3B8 | ||
| 69 | #define NUM_CONNECTIONS 0x3BC | ||
| 70 | #define MAX_BROADCAST_DISTANCE 0x3C0 | ||
| 71 | #define DOT_POSITIONS 0x3C8 | ||
| 72 | #define DOT_FLAGS 0x3D0 | ||
| 73 | #define DOT_CONNECTION_A 0x3D8 | ||
| 74 | #define DOT_CONNECTION_B 0x3E0 | ||
| 75 | #define DECORATIONS 0x420 | ||
| 76 | #define DECORATION_FLAGS 0x428 | ||
| 77 | #define DECORATION_COLORS 0x430 | ||
| 78 | #define NUM_DECORATIONS 0x438 | ||
| 79 | #define REFLECTION_DATA 0x440 | ||
| 80 | #define GRID_SIZE_X 0x448 | ||
| 81 | #define GRID_SIZE_Y 0x44C | ||
| 82 | #define STYLE_FLAGS 0x450 | ||
| 83 | #define SEQUENCE_LEN 0x45C | ||
| 84 | #define SEQUENCE 0x460 | ||
| 85 | #define DOT_SEQUENCE_LEN 0x468 | ||
| 86 | #define DOT_SEQUENCE 0x470 | ||
| 87 | #define DOT_SEQUENCE_LEN_REFLECTION 0x478 | ||
| 88 | #define DOT_SEQUENCE_REFLECTION 0x480 | ||
| 89 | #define NUM_COLORED_REGIONS 0x4A0 | ||
| 90 | #define COLORED_REGIONS 0x4A8 | ||
| 91 | #define PANEL_TARGET 0x4B0 | ||
| 92 | #define SPECULAR_TEXTURE 0x4D8 | ||
| 93 | #define CABLE_TARGET_2 0xD8 | ||
| 94 | #elif GLOBALS == 0x62A080 | ||
| 95 | #define PATH_COLOR 0xC0 | ||
| 96 | #define REFLECTION_PATH_COLOR 0xD0 | ||
| 97 | #define DOT_COLOR 0xF0 | ||
| 98 | #define ACTIVE_COLOR 0x100 | ||
| 99 | #define BACKGROUND_REGION_COLOR 0x110 | ||
| 100 | #define SUCCESS_COLOR_A 0x120 | ||
| 101 | #define SUCCESS_COLOR_B 0x130 | ||
| 102 | #define STROBE_COLOR_A 0x140 | ||
| 103 | #define STROBE_COLOR_B 0x150 | ||
| 104 | #define ERROR_COLOR 0x160 | ||
| 105 | #define PATTERN_POINT_COLOR 0x180 | ||
| 106 | #define PATTERN_POINT_COLOR_A 0x190 | ||
| 107 | #define PATTERN_POINT_COLOR_B 0x1A0 | ||
| 108 | #define SYMBOL_A 0x1B0 | ||
| 109 | #define SYMBOL_B 0x1C0 | ||
| 110 | #define SYMBOL_C 0x1D0 | ||
| 111 | #define SYMBOL_D 0x1E0 | ||
| 112 | #define SYMBOL_E 0x1F0 | ||
| 113 | #define PUSH_SYMBOL_COLORS 0x200 | ||
| 114 | #define OUTER_BACKGROUND 0x204 | ||
| 115 | #define OUTER_BACKGROUND_MODE 0x214 | ||
| 116 | #define TRACED_EDGES 0x228 | ||
| 117 | #define AUDIO_PREFIX 0x270 | ||
| 118 | #define POWER 0x2A0 | ||
| 119 | #define TARGET 0x2B4 | ||
| 120 | #define IS_CYLINDER 0x2F4 | ||
| 121 | #define CYLINDER_Z0 0x2F8 | ||
| 122 | #define CYLINDER_Z1 0x2FC | ||
| 123 | #define CYLINDER_RADIUS 0x300 | ||
| 124 | #define CURSOR_SPEED_SCALE 0x350 | ||
| 125 | #define SPECULAR_ADD 0x38C | ||
| 126 | #define SPECULAR_POWER 0x390 | ||
| 127 | #define PATH_WIDTH_SCALE 0x39C | ||
| 128 | #define STARTPOINT_SCALE 0x3A0 | ||
| 129 | #define NUM_DOTS 0x3B4 | ||
| 130 | #define NUM_CONNECTIONS 0x3B8 | ||
| 131 | #define MAX_BROADCAST_DISTANCE 0x3BC | ||
| 132 | #define DOT_POSITIONS 0x3C0 | ||
| 133 | #define DOT_FLAGS 0x3C8 | ||
| 134 | #define DOT_CONNECTION_A 0x3D0 | ||
| 135 | #define DOT_CONNECTION_B 0x3D8 | ||
| 136 | #define DECORATIONS 0x418 | ||
| 137 | #define DECORATION_FLAGS 0x420 | ||
| 138 | #define DECORATION_COLORS 0x428 | ||
| 139 | #define NUM_DECORATIONS 0x430 | ||
| 140 | #define REFLECTION_DATA 0x438 | ||
| 141 | #define GRID_SIZE_X 0x440 | ||
| 142 | #define GRID_SIZE_Y 0x444 | ||
| 143 | #define STYLE_FLAGS 0x448 | ||
| 144 | #define SEQUENCE_LEN 0x454 | ||
| 145 | #define SEQUENCE 0x458 | ||
| 146 | #define DOT_SEQUENCE_LEN 0x460 | ||
| 147 | #define DOT_SEQUENCE 0x468 | ||
| 148 | #define DOT_SEQUENCE_LEN_REFLECTION 0x470 | ||
| 149 | #define DOT_SEQUENCE_REFLECTION 0x478 | ||
| 150 | #define NUM_COLORED_REGIONS 0x498 | ||
| 151 | #define COLORED_REGIONS 0x4A0 | ||
| 152 | #define PANEL_TARGET 0x4A8 | ||
| 153 | #define SPECULAR_TEXTURE 0x4D0 | ||
| 154 | #define CABLE_TARGET_2 0xD0 | ||
| 155 | #endif \ No newline at end of file | ||
