summary refs log tree commit diff stats
path: root/Source/Puzzle.h
blob: 94cb4b0f0e13c1f644d999c48ee81a9f0099475a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#pragma once
#include <memory>
#include <vector>

class Memory;

enum Type {
    Stone =      0x100,
    Square = Stone, // @Deprecated
    Star =       0x200,
    Poly =       0x400,
    Eraser =     0x500,
    Nega = Eraser, // @Deprecated
    Triangle =   0x600,
    RPoly =     0x1000, // @Cleanup!
    Ylop =      0x2000,
};

enum Color {
    Black =     0x1,
    White =     0x2,
    Gray =      0x3,
    Purple =    0x4,
    Green =     0x5,
    Cyan =      0x6,
    Pink =      0x7,
    Yellow =    0x8,
    Blue =      0x9,
    Orange =    0xA,
};

struct Decoration {
    Type type;
    Color color;
    int polyshape = 0;
    // For triangles only
    int count = 0;
};

struct Cell {
    inline static Cell Undefined() {
        Cell c;
        c.undefined = true;
        return c;
    }
    bool undefined = false;

    bool start = false;
    enum class Dir {NONE, LEFT, RIGHT, UP, DOWN};
    Dir end = Dir::NONE;
    std::shared_ptr<Decoration> decoration = nullptr;
    enum class Dot {NONE, BLACK, BLUE, YELLOW, INVISIBLE};
    Dot dot = Dot::NONE;
    enum class Gap {NONE, BREAK, FULL};
    Gap gap = Gap::NONE;

    // Line color
    enum class Color {NONE, BLACK, BLUE, YELLOW};
    Color color = Color::NONE;
};

struct Negation {};
struct Pos {int x; int y;};

#include <cassert> // TODO: Move this + impl to cpp
class Puzzle {
public:
    int16_t height;
    int16_t width;
    bool hasDecorations = false;

    enum class Symmetry {NONE, X, Y, XY};
    Symmetry sym = Symmetry::NONE;
    bool pillar = false;

    bool valid;
    std::vector<Negation> negations;
    std::vector<Pos> invalidElements;

    inline Cell GetCell(int x, int y) const {
        x = Mod(x);
        if (!SafeCell(x, y)) return Cell::Undefined();
        return grid[x][y];
    }
    inline Cell::Color GetLine(int x, int y) const {
        return grid[x][y].color;
    }
    inline void NewGrid(int newWidth, int newHeight) {
        if (newWidth == 0) {
            assert(false);
            newWidth = width;
            newHeight = height;
        } else {
            // @Cleanup! This should be in the ctor...
            width = 2*newWidth + 1;
            height = 2*newHeight + 1;
        }
        grid.clear();
        grid.resize(width);
        for (int x=0; x<width; x++) grid[x].resize(height);
    }

    // @TODO:
    Pos GetSymmetricalPos(int x, int y);

// private:
    std::vector<std::vector<Cell>> grid;

private:
    inline int Mod(int x) const {
        if (!pillar) return x;
        return (x + width * height * 2) % width;
    }

    inline bool SafeCell(int x, int y) const {
        if (x < 0 || x >= width) return false;
        if (y < 0 || y >= height) return false;
        return true;
    }
};

class PuzzleSerializer {
public:
    PuzzleSerializer(const std::shared_ptr<Memory>& memory);
    Puzzle ReadPuzzle(int id);
    void WritePuzzle(const Puzzle& p, int id);

private:
    // @Bug: Blue and orange are swapped?
    enum Flags {
        IS_ENDPOINT =            0x1,
        IS_STARTPOINT =          0x2,
        IS_FULL_GAP =            0x8,
        HAS_DOT =               0x20,
        DOT_IS_BLUE =          0x100,
        DOT_IS_ORANGE =        0x200,
        DOT_IS_INVISIBLE =    0x1000,
        HAS_ONE_CONN =       0x100000,
        HAS_VERTI_CONN =    0x200000,
        HAS_HORIZ_CONN =    0x400000,
    };

    void ReadIntersections(Puzzle& p, int id);
    void ReadDecorations(Puzzle& p, int id);
    void WriteIntersections(const Puzzle& p, int id);
    void WriteDecorations(const Puzzle& p, int id);

    std::tuple<int, int> loc_to_xy(const Puzzle& p, int location) const;
    int xy_to_loc(const Puzzle& p, int x, int y) const;
    // Decoration location
    std::tuple<int, int> dloc_to_xy(const Puzzle& p, int location) const;
    int xy_to_dloc(const Puzzle& p, int x, int y) const;
    Cell::Dot FlagsToDot(int flags) const;
    // Iterate connection lists for another location which is connected to us; return that other location.
    int FindConnection(int i, const std::vector<int>& connections_a, const std::vector<int>& connections_b) const;

    std::shared_ptr<Memory> _memory;
};