diff options
| author | jbzdarkid <jbzdarkid@gmail.com> | 2019-11-18 09:41:22 -0800 |
|---|---|---|
| committer | jbzdarkid <jbzdarkid@gmail.com> | 2019-11-18 09:41:22 -0800 |
| commit | c282663a96ae9704a59c55c9300dbc8c49e0ef39 (patch) | |
| tree | 071a26b8e58b8aac4d347c6a8200a4b01663abe1 | |
| parent | bff40e55c9c55fbc8439bb225d1937b2d805e629 (diff) | |
| download | witness-tutorializer-c282663a96ae9704a59c55c9300dbc8c49e0ef39.tar.gz witness-tutorializer-c282663a96ae9704a59c55c9300dbc8c49e0ef39.tar.bz2 witness-tutorializer-c282663a96ae9704a59c55c9300dbc8c49e0ef39.zip | |
Add sanity checks for overwriting buffers
| -rw-r--r-- | Source/Puzzle.h | 4 | ||||
| -rw-r--r-- | Source/PuzzleSerializer.cpp | 15 | ||||
| -rw-r--r-- | Source/Randomizer2.cpp | 20 | ||||
| -rw-r--r-- | Source/Randomizer2Core.cpp | 30 | ||||
| -rw-r--r-- | Source/Randomizer2Core.h | 3 |
5 files changed, 37 insertions, 35 deletions
| diff --git a/Source/Puzzle.h b/Source/Puzzle.h index 962874e..1e00ef4 100644 --- a/Source/Puzzle.h +++ b/Source/Puzzle.h | |||
| @@ -65,8 +65,8 @@ struct Pos {int x; int y;}; | |||
| 65 | 65 | ||
| 66 | class Puzzle { | 66 | class Puzzle { |
| 67 | public: | 67 | public: |
| 68 | int16_t height = 0; | 68 | int height = 0; |
| 69 | int16_t width = 0; | 69 | int width = 0; |
| 70 | bool hasDecorations = false; | 70 | bool hasDecorations = false; |
| 71 | 71 | ||
| 72 | enum class Symmetry {NONE, X, Y, XY}; | 72 | enum class Symmetry {NONE, X, Y, XY}; |
| diff --git a/Source/PuzzleSerializer.cpp b/Source/PuzzleSerializer.cpp index c1e93a5..e845578 100644 --- a/Source/PuzzleSerializer.cpp +++ b/Source/PuzzleSerializer.cpp | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | #include "PuzzleSerializer.h" | 1 | #include "PuzzleSerializer.h" |
| 2 | #include "Memory.h" | 2 | #include "Memory.h" |
| 3 | #include <cassert> | ||
| 3 | 4 | ||
| 4 | #pragma warning (disable:26451) | 5 | #pragma warning (disable:26451) |
| 5 | #pragma warning (disable:26812) | 6 | #pragma warning (disable:26812) |
| @@ -47,6 +48,16 @@ void PuzzleSerializer::WritePuzzle(const Puzzle& p, int id) { | |||
| 47 | WriteDecorations(p, id); | 48 | WriteDecorations(p, id); |
| 48 | WriteSequence(p, id); | 49 | WriteSequence(p, id); |
| 49 | 50 | ||
| 51 | #ifndef NDEBUG | ||
| 52 | int maxDots = _memory->ReadEntityData<int>(id, NUM_DOTS, 1)[0]; | ||
| 53 | assert(_intersectionFlags.size() <= maxDots); | ||
| 54 | assert(_intersectionLocations.size() <= maxDots*2); | ||
| 55 | |||
| 56 | int maxConnections = _memory->ReadEntityData<int>(id, NUM_CONNECTIONS, 1)[0]; | ||
| 57 | assert(_connectionsA.size() <= maxConnections); | ||
| 58 | assert(_connectionsB.size() <= maxConnections); | ||
| 59 | #endif | ||
| 60 | |||
| 50 | _memory->WriteEntityData<int>(id, GRID_SIZE_X, {(p.width + 1)/2}); | 61 | _memory->WriteEntityData<int>(id, GRID_SIZE_X, {(p.width + 1)/2}); |
| 51 | _memory->WriteEntityData<int>(id, GRID_SIZE_Y, {(p.height + 1)/2}); | 62 | _memory->WriteEntityData<int>(id, GRID_SIZE_Y, {(p.height + 1)/2}); |
| 52 | _memory->WriteEntityData<int>(id, NUM_DOTS, {static_cast<int>(_intersectionFlags.size())}); | 63 | _memory->WriteEntityData<int>(id, NUM_DOTS, {static_cast<int>(_intersectionFlags.size())}); |
| @@ -376,6 +387,10 @@ void PuzzleSerializer::WriteDecorations(const Puzzle& p, int id) { | |||
| 376 | } | 387 | } |
| 377 | } | 388 | } |
| 378 | 389 | ||
| 390 | #ifndef NDEBUG | ||
| 391 | int maxDecorations = _memory->ReadEntityData<int>(id, NUM_DECORATIONS, 1)[0]; | ||
| 392 | assert(decorations.size() < maxDecorations); | ||
| 393 | #endif | ||
| 379 | _memory->WriteEntityData<int>(id, NUM_DECORATIONS, {static_cast<int>(decorations.size())}); | 394 | _memory->WriteEntityData<int>(id, NUM_DECORATIONS, {static_cast<int>(decorations.size())}); |
| 380 | _memory->WriteArray<int>(id, DECORATIONS, decorations); | 395 | _memory->WriteArray<int>(id, DECORATIONS, decorations); |
| 381 | } | 396 | } |
| diff --git a/Source/Randomizer2.cpp b/Source/Randomizer2.cpp index 7a50c7b..c28795a 100644 --- a/Source/Randomizer2.cpp +++ b/Source/Randomizer2.cpp | |||
| @@ -14,7 +14,7 @@ Randomizer2::Randomizer2(const std::shared_ptr<Memory>& memory) : _memory(memory | |||
| 14 | 14 | ||
| 15 | void Randomizer2::Randomize() { | 15 | void Randomizer2::Randomize() { |
| 16 | RandomizeTutorial(); | 16 | RandomizeTutorial(); |
| 17 | RandomizeKeep(); | 17 | // RandomizeKeep(); |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | void Randomizer2::RandomizeTutorial() { | 20 | void Randomizer2::RandomizeTutorial() { |
| @@ -24,7 +24,7 @@ void Randomizer2::RandomizeTutorial() { | |||
| 24 | p.grid[0][8].start = true; | 24 | p.grid[0][8].start = true; |
| 25 | p.grid[8][0].end = Cell::Dir::UP; | 25 | p.grid[8][0].end = Cell::Dir::UP; |
| 26 | 26 | ||
| 27 | for (Pos pos : Randomizer2Core::CutEdges(p, 14)) { | 27 | for (Pos pos : Randomizer2Core::CutEdges(p, 14, true)) { |
| 28 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 28 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
| 29 | } | 29 | } |
| 30 | _serializer.WritePuzzle(p, 0x293); | 30 | _serializer.WritePuzzle(p, 0x293); |
| @@ -32,7 +32,7 @@ void Randomizer2::RandomizeTutorial() { | |||
| 32 | 32 | ||
| 33 | { | 33 | { |
| 34 | Puzzle p; | 34 | Puzzle p; |
| 35 | p.NewGrid(7, 7); | 35 | p.NewGrid(6, 6); |
| 36 | 36 | ||
| 37 | switch (Random::RandInt(1, 4)) { | 37 | switch (Random::RandInt(1, 4)) { |
| 38 | case 1: | 38 | case 1: |
| @@ -60,7 +60,7 @@ void Randomizer2::RandomizeTutorial() { | |||
| 60 | break; | 60 | break; |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | for (Pos pos : Randomizer2Core::CutEdges(p, 35)) { | 63 | for (Pos pos : Randomizer2Core::CutEdges(p, 35, true)) { |
| 64 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 64 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| @@ -88,7 +88,7 @@ void Randomizer2::RandomizeKeep() { | |||
| 88 | p.grid[4][8].start = true; | 88 | p.grid[4][8].start = true; |
| 89 | p.grid[6][0].end = Cell::Dir::UP; | 89 | p.grid[6][0].end = Cell::Dir::UP; |
| 90 | 90 | ||
| 91 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges2(p, 5); | 91 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges(p, 5, false); |
| 92 | Puzzle copy = p; | 92 | Puzzle copy = p; |
| 93 | std::vector<int> gates = {0x00344, 0x00488, 0x00489, 0x00495, 0x00496}; | 93 | std::vector<int> gates = {0x00344, 0x00488, 0x00489, 0x00495, 0x00496}; |
| 94 | for (int i=0; i<gates.size(); i++) { | 94 | for (int i=0; i<gates.size(); i++) { |
| @@ -118,7 +118,7 @@ void Randomizer2::RandomizeKeep() { | |||
| 118 | p.grid[0][8].start = true; | 118 | p.grid[0][8].start = true; |
| 119 | p.grid[8][0].end = Cell::Dir::RIGHT; | 119 | p.grid[8][0].end = Cell::Dir::RIGHT; |
| 120 | 120 | ||
| 121 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges2(p, 7); | 121 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges(p, 7, false); |
| 122 | for (Pos pos : cutEdges) { | 122 | for (Pos pos : cutEdges) { |
| 123 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 123 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
| 124 | } | 124 | } |
| @@ -133,7 +133,7 @@ void Randomizer2::RandomizeKeep() { | |||
| 133 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 133 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
| 134 | } | 134 | } |
| 135 | // Cut to 6 of 9 additional edges | 135 | // Cut to 6 of 9 additional edges |
| 136 | for (Pos pos : Randomizer2Core::CutEdges2(q, 6)) { | 136 | for (Pos pos : Randomizer2Core::CutEdges(q, 6, false)) { |
| 137 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 137 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
| 138 | } | 138 | } |
| 139 | _serializer.WritePuzzle(q, 0x19DC); | 139 | _serializer.WritePuzzle(q, 0x19DC); |
| @@ -158,7 +158,7 @@ void Randomizer2::RandomizeKeep() { | |||
| 158 | 158 | ||
| 159 | std::vector<int> pebbleMarkers = {0x034a9, 0x034b1, 0x034be, 0x034c4}; | 159 | std::vector<int> pebbleMarkers = {0x034a9, 0x034b1, 0x034be, 0x034c4}; |
| 160 | 160 | ||
| 161 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges2(p, 7); | 161 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges(p, 7, false); |
| 162 | for (Pos pos : cutEdges) { | 162 | for (Pos pos : cutEdges) { |
| 163 | p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; | 163 | p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; |
| 164 | } | 164 | } |
| @@ -187,7 +187,7 @@ void Randomizer2::RandomizeKeep() { | |||
| 187 | p.grid[0][8].start = true; | 187 | p.grid[0][8].start = true; |
| 188 | p.grid[4][0].end = Cell::Dir::UP; | 188 | p.grid[4][0].end = Cell::Dir::UP; |
| 189 | 189 | ||
| 190 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges2(p, 2); | 190 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges(p, 2, false); |
| 191 | for (Pos pos : cutEdges) { | 191 | for (Pos pos : cutEdges) { |
| 192 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 192 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
| 193 | } | 193 | } |
| @@ -201,7 +201,7 @@ void Randomizer2::RandomizeKeep() { | |||
| 201 | for (Pos pos : cutEdges) { | 201 | for (Pos pos : cutEdges) { |
| 202 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 202 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
| 203 | } | 203 | } |
| 204 | for (Pos pos : Randomizer2Core::CutEdges2(q, 7)) { | 204 | for (Pos pos : Randomizer2Core::CutEdges(q, 7, false)) { |
| 205 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 205 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
| 206 | } | 206 | } |
| 207 | _serializer.WritePuzzle(q, 0x1A0F); | 207 | _serializer.WritePuzzle(q, 0x1A0F); |
| diff --git a/Source/Randomizer2Core.cpp b/Source/Randomizer2Core.cpp index 8bd5765..0310ae2 100644 --- a/Source/Randomizer2Core.cpp +++ b/Source/Randomizer2Core.cpp | |||
| @@ -6,31 +6,19 @@ | |||
| 6 | #include <iostream> | 6 | #include <iostream> |
| 7 | #include <cassert> | 7 | #include <cassert> |
| 8 | 8 | ||
| 9 | // @Cutnpaste | 9 | std::vector<Pos> Randomizer2Core::CutEdges(const Puzzle& p, size_t numEdges, bool allowEdges) { |
| 10 | std::vector<Pos> Randomizer2Core::CutEdges(const Puzzle& p, size_t numEdges) { | ||
| 11 | std::vector<Pos> edges; | 10 | std::vector<Pos> edges; |
| 12 | for (int x=0; x<p.width; x++) { | 11 | int xMin = allowEdges ? 0 : 1; |
| 13 | for (int y=0; y<p.height; y++) { | 12 | int xMax = allowEdges ? p.width : p.width-1; |
| 14 | if (x%2 == y%2) continue; | 13 | int yMin = allowEdges ? 0 : 1; |
| 15 | if (p.grid[x][y].gap != Cell::Gap::NONE) continue; | 14 | int yMax = allowEdges ? p.height : p.height-1; |
| 16 | 15 | ||
| 17 | // If the puzzle already has a sequence, don't cut along it. | 16 | for (int x=xMin; x<xMax; x++) { |
| 18 | bool inSequence = false; | 17 | for (int y=yMin; y<yMax; y++) { |
| 19 | for (Pos pos : p.sequence) inSequence |= (pos.x == x && pos.y == y); | ||
| 20 | if (inSequence) continue; | ||
| 21 | edges.emplace_back(Pos{x, y}); | ||
| 22 | } | ||
| 23 | } | ||
| 24 | return CutEdgesInternal(p, edges, numEdges); | ||
| 25 | } | ||
| 26 | |||
| 27 | std::vector<Pos> Randomizer2Core::CutEdges2(const Puzzle& p, size_t numEdges) { | ||
| 28 | std::vector<Pos> edges; | ||
| 29 | // Note the iterator bounds; we skip the outer edges. | ||
| 30 | for (int x=1; x<p.width-1; x++) { | ||
| 31 | for (int y=1; y<p.height-1; y++) { | ||
| 32 | if (x%2 == y%2) continue; | 18 | if (x%2 == y%2) continue; |
| 33 | if (p.grid[x][y].gap != Cell::Gap::NONE) continue; | 19 | if (p.grid[x][y].gap != Cell::Gap::NONE) continue; |
| 20 | if (p.grid[x][y].start) continue; | ||
| 21 | if (p.grid[x][y].end != Cell::Dir::NONE) continue; | ||
| 34 | 22 | ||
| 35 | // If the puzzle already has a sequence, don't cut along it. | 23 | // If the puzzle already has a sequence, don't cut along it. |
| 36 | bool inSequence = false; | 24 | bool inSequence = false; |
| diff --git a/Source/Randomizer2Core.h b/Source/Randomizer2Core.h index 63ba6a8..443f893 100644 --- a/Source/Randomizer2Core.h +++ b/Source/Randomizer2Core.h | |||
| @@ -7,8 +7,7 @@ class Puzzle; | |||
| 7 | class Randomizer2Core { | 7 | class Randomizer2Core { |
| 8 | public: | 8 | public: |
| 9 | // CAUTION: Does not actually cut edges, just returns a list of suggested cuts. | 9 | // CAUTION: Does not actually cut edges, just returns a list of suggested cuts. |
| 10 | static std::vector<Pos> CutEdges(const Puzzle& p, size_t numEdges); | 10 | static std::vector<Pos> CutEdges(const Puzzle& p, size_t numEdges, bool allowEdges); |
| 11 | static std::vector<Pos> CutEdges2(const Puzzle& p, size_t numEdges); | ||
| 12 | 11 | ||
| 13 | private: | 12 | private: |
| 14 | static std::vector<Pos> CutEdgesInternal(const Puzzle& p, std::vector<Pos>& edges, size_t numEdges); | 13 | static std::vector<Pos> CutEdgesInternal(const Puzzle& p, std::vector<Pos>& edges, size_t numEdges); |
