diff options
Diffstat (limited to 'ext/wittle_generator/Generate.h')
| -rw-r--r-- | ext/wittle_generator/Generate.h | 248 | 
1 files changed, 248 insertions, 0 deletions
| diff --git a/ext/wittle_generator/Generate.h b/ext/wittle_generator/Generate.h new file mode 100644 index 0000000..c28a47d --- /dev/null +++ b/ext/wittle_generator/Generate.h | |||
| @@ -0,0 +1,248 @@ | |||
| 1 | #ifndef GENERATE_H_0582FCEA | ||
| 2 | #define GENERATE_H_0582FCEA | ||
| 3 | |||
| 4 | #include <stdlib.h> | ||
| 5 | #include <time.h> | ||
| 6 | |||
| 7 | #include <algorithm> | ||
| 8 | #include <memory> | ||
| 9 | #include <set> | ||
| 10 | #include <string> | ||
| 11 | |||
| 12 | #include "Panel.h" | ||
| 13 | #include "PuzzleSymbols.h" | ||
| 14 | #include "Random.h" | ||
| 15 | |||
| 16 | typedef std::set<Point> Shape; | ||
| 17 | |||
| 18 | // The main class for generating puzzles. | ||
| 19 | class Generate { | ||
| 20 | public: | ||
| 21 | Generate() { | ||
| 22 | _width = _height = 0; | ||
| 23 | _areaTotal = _genTotal = _totalPuzzles = _areaPuzzles = _stoneTypes = 0; | ||
| 24 | _fullGaps = _bisect = _allowNonMatch = false; | ||
| 25 | _panel = NULL; | ||
| 26 | _parity = -1; | ||
| 27 | colorblind = false; | ||
| 28 | _seed = Random::rand(); | ||
| 29 | arrowColor = backgroundColor = successColor = {0, 0, 0, 0}; | ||
| 30 | resetConfig(); | ||
| 31 | } | ||
| 32 | enum Config { // See configinfo.txt for explanations of config flags. | ||
| 33 | None = 0, | ||
| 34 | FullGaps = 0x1, | ||
| 35 | StartEdgeOnly = 0x2, | ||
| 36 | DisableWrite = 0x4, | ||
| 37 | PreserveStructure = 0x8, | ||
| 38 | MakeStonesUnsolvable = 0x10, | ||
| 39 | SmallShapes = 0x20, | ||
| 40 | DisconnectShapes = 0x40, | ||
| 41 | ResetColors = 0x80, | ||
| 42 | DisableCancelShapes = 0x100, | ||
| 43 | RequireCancelShapes = 0x200, | ||
| 44 | BigShapes = 0x400, | ||
| 45 | SplitShapes = 0x800, | ||
| 46 | RequireCombineShapes = 0x1000, | ||
| 47 | TreehouseLayout = 0x2000, | ||
| 48 | TreehouseColors = 0x4000, | ||
| 49 | AlternateColors = 0x8000, | ||
| 50 | WriteColors = 0x10000, | ||
| 51 | Write2Color = 0x20000, | ||
| 52 | FixBackground = 0x40000, | ||
| 53 | CombineErasers = 0x80000, | ||
| 54 | LongPath = 0x100000, | ||
| 55 | ShortPath = 0x200000, | ||
| 56 | EnableFlash = 0x400000, | ||
| 57 | DecorationsOnly = 0x800000, | ||
| 58 | FalseParity = 0x1000000, | ||
| 59 | DisableDotIntersection = 0x2000000, | ||
| 60 | WriteDotColor = 0x4000000, | ||
| 61 | WriteDotColor2 = 0x8000000, | ||
| 62 | LongestPath = 0x10000000, | ||
| 63 | WriteInvisible = 0x20000000, | ||
| 64 | DisableReset = 0x40000000, | ||
| 65 | MountainFloorH = 0x80000000 | ||
| 66 | }; | ||
| 67 | |||
| 68 | void generate(int width, int height, PuzzleSymbols symbols); | ||
| 69 | |||
| 70 | /*void generateMaze(int id); | ||
| 71 | void generateMaze(int id, int numStarts, int numExits);*/ | ||
| 72 | void initPanel(); | ||
| 73 | void setPath(const std::set<Point>& path) { | ||
| 74 | customPath = path; | ||
| 75 | for (Point p : path) setSymbol(IntersectionFlags::PATH, p.first, p.second); | ||
| 76 | } | ||
| 77 | void setObstructions(const std::vector<Point>& walls) { | ||
| 78 | _obstructions = {walls}; | ||
| 79 | } | ||
| 80 | void setObstructions(const std::vector<std::vector<Point>>& walls) { | ||
| 81 | _obstructions = walls; | ||
| 82 | } | ||
| 83 | void setSymbol(Decoration::Shape symbol, int x, int y); | ||
| 84 | void setSymbol(IntersectionFlags symbol, int x, int y) { | ||
| 85 | setSymbol(static_cast<Decoration::Shape>(symbol), x, y); | ||
| 86 | } | ||
| 87 | void setGridSize(int width, int height); | ||
| 88 | void setSymmetry(Panel::Symmetry symmetry); | ||
| 89 | void write(int id); | ||
| 90 | void setFlag(Config option) { _config |= option; }; | ||
| 91 | void setFlagOnce(Config option) { | ||
| 92 | _config |= option; | ||
| 93 | _oneTimeAdd |= option; | ||
| 94 | }; | ||
| 95 | bool hasFlag(Config option) { return _config & option; }; | ||
| 96 | void removeFlag(Config option) { _config &= ~option; }; | ||
| 97 | void removeFlagOnce(Config option) { | ||
| 98 | _config &= ~option; | ||
| 99 | _oneTimeRemove |= option; | ||
| 100 | }; | ||
| 101 | void resetConfig(); | ||
| 102 | void seed(long seed) { | ||
| 103 | Random::seed(seed); | ||
| 104 | _seed = Random::rand(); | ||
| 105 | } | ||
| 106 | |||
| 107 | float pathWidth; // Controls how thick the line is on the puzzle | ||
| 108 | std::vector<Point> hitPoints; // The generated path will be forced to hit | ||
| 109 | // these points in order | ||
| 110 | std::set<Point> | ||
| 111 | openPos; // Custom set of points that can have symbols placed on | ||
| 112 | std::set<Point> blockPos; // Point that must be left open | ||
| 113 | std::set<Point> customPath; | ||
| 114 | Color arrowColor, backgroundColor, successColor; // For the arrow puzzles | ||
| 115 | |||
| 116 | private: | ||
| 117 | int get_symbol_type(int flags) { return flags & 0x700; } | ||
| 118 | void set_path(Point pos); | ||
| 119 | Point get_sym_point(Point pos) { return _panel->get_sym_point(pos); } | ||
| 120 | int get_parity(Point pos) { return (pos.first / 2 + pos.second / 2) % 2; } | ||
| 121 | void clear(); | ||
| 122 | void resetVars(); | ||
| 123 | void init_treehouse_layout(); | ||
| 124 | template <class T> | ||
| 125 | T pick_random(const std::vector<T>& vec) { | ||
| 126 | return vec[Random::rand() % vec.size()]; | ||
| 127 | } | ||
| 128 | template <class T> | ||
| 129 | T pick_random(const std::set<T>& set) { | ||
| 130 | auto it = set.begin(); | ||
| 131 | std::advance(it, Random::rand() % set.size()); | ||
| 132 | return *it; | ||
| 133 | } | ||
| 134 | template <class T> | ||
| 135 | T pop_random(const std::vector<T>& vec) { | ||
| 136 | int i = Random::rand() % vec.size(); | ||
| 137 | T item = vec[i]; | ||
| 138 | vec.erase(vec.begin() + i); | ||
| 139 | return item; | ||
| 140 | } | ||
| 141 | template <class T> | ||
| 142 | T pop_random(const std::set<T>& set) { | ||
| 143 | T item = pick_random(set); | ||
| 144 | set.erase(item); | ||
| 145 | return item; | ||
| 146 | } | ||
| 147 | bool on_edge(Point p) { | ||
| 148 | return (p.first == 0 || p.first + 1 == _panel->width() || p.second == 0 || | ||
| 149 | p.second + 1 == _panel->height()); | ||
| 150 | } | ||
| 151 | bool off_edge(Point p) { | ||
| 152 | return (p.first < 0 || p.first >= _panel->width() || p.second < 0 || | ||
| 153 | p.second >= _panel->height()); | ||
| 154 | } | ||
| 155 | static std::vector<Point> _DIRECTIONS1, _8DIRECTIONS1, _DIRECTIONS2, | ||
| 156 | _8DIRECTIONS2, _SHAPEDIRECTIONS, _DISCONNECT; | ||
| 157 | // bool generate_maze(int id, int numStarts, int numExits); | ||
| 158 | bool generateInternal(int width, int height, PuzzleSymbols symbols); | ||
| 159 | bool place_all_symbols(PuzzleSymbols& symbols); | ||
| 160 | bool generate_path(PuzzleSymbols& symbols); | ||
| 161 | bool generate_path_length(int minLength, int maxLength); | ||
| 162 | bool generate_path_length(int minLength) { | ||
| 163 | return generate_path_length(minLength, 10000); | ||
| 164 | }; | ||
| 165 | bool generate_path_regions(int minRegions); | ||
| 166 | bool generate_longest_path(); | ||
| 167 | bool generate_special_path(); | ||
| 168 | void erase_path(); | ||
| 169 | Point adjust_point(Point pos); | ||
| 170 | std::set<Point> get_region(Point pos); | ||
| 171 | std::vector<int> get_symbols_in_region(Point pos); | ||
| 172 | std::vector<int> get_symbols_in_region(const std::set<Point>& region); | ||
| 173 | bool place_start(int amount); | ||
| 174 | bool place_exit(int amount); | ||
| 175 | bool can_place_gap(Point pos); | ||
| 176 | bool place_gaps(int amount); | ||
| 177 | bool can_place_dot(Point pos, bool intersectionOnly); | ||
| 178 | bool place_dots(int amount, Decoration::Color color, bool intersectionOnly); | ||
| 179 | bool can_place_stone(const std::set<Point>& region, int color); | ||
| 180 | bool place_stones(int color, int amount); | ||
| 181 | Shape generate_shape(std::set<Point>& region, std::set<Point>& bufferRegion, | ||
| 182 | Point pos, int maxSize); | ||
| 183 | Shape generate_shape(std::set<Point>& region, Point pos, int maxSize) { | ||
| 184 | std::set<Point> buffer; | ||
| 185 | return generate_shape(region, buffer, pos, maxSize); | ||
| 186 | } | ||
| 187 | int make_shape_symbol(Shape shape, bool rotated, bool negative, int rotation, | ||
| 188 | int depth); | ||
| 189 | int make_shape_symbol(const Shape& shape, bool rotated, bool negative) { | ||
| 190 | return make_shape_symbol(shape, rotated, negative, -1, 0); | ||
| 191 | } | ||
| 192 | bool place_shapes(const std::vector<int>& colors, | ||
| 193 | const std::vector<int>& negativeColors, int amount, | ||
| 194 | int numRotated, int numNegative); | ||
| 195 | int count_color(const std::set<Point>& region, int color); | ||
| 196 | bool place_stars(int color, int amount); | ||
| 197 | bool has_star(const std::set<Point>& region, int color); | ||
| 198 | bool checkStarZigzag(); | ||
| 199 | bool place_triangles(int color, int amount, int targetCount); | ||
| 200 | int count_sides(Point pos); | ||
| 201 | bool place_arrows(int color, int amount, int targetCount); | ||
| 202 | int count_crossings(Point pos, Point dir); | ||
| 203 | bool place_erasers(const std::vector<int>& colors, | ||
| 204 | const std::vector<int>& eraseSymbols); | ||
| 205 | bool combine_shapes(std::vector<Shape>& shapes); | ||
| 206 | |||
| 207 | bool hasSymbolOrPath(const Point& pos) { | ||
| 208 | return hasSymbolOrPath(pos.first, pos.second); | ||
| 209 | } | ||
| 210 | bool hasSymbolOrPath(int x, int y); | ||
| 211 | |||
| 212 | std::unique_ptr<Panel> _panel; | ||
| 213 | std::vector<std::vector<int>> _custom_grid; | ||
| 214 | int _width, _height; | ||
| 215 | Panel::Symmetry _symmetry; | ||
| 216 | std::set<Point> _starts, _exits; | ||
| 217 | std::set<Point> _gridpos, _openpos; | ||
| 218 | std::set<Point> _path, _path1, _path2; | ||
| 219 | bool _fullGaps, _bisect; | ||
| 220 | int _stoneTypes; | ||
| 221 | int _config; | ||
| 222 | int _oneTimeAdd, _oneTimeRemove; | ||
| 223 | long _seed; | ||
| 224 | std::vector<Point> _splitPoints; | ||
| 225 | bool _allowNonMatch; // Used for multi-generator | ||
| 226 | int _parity; | ||
| 227 | std::vector<std::vector<Point>> _obstructions; | ||
| 228 | bool colorblind; | ||
| 229 | |||
| 230 | int _areaTotal, _genTotal, _areaPuzzles, _totalPuzzles; | ||
| 231 | std::wstring _areaName; | ||
| 232 | |||
| 233 | void set(int x, int y, int val) { _panel->set(x, y, val); } | ||
| 234 | void set(const Point& pos, int val) { | ||
| 235 | _panel->set(pos.first, pos.second, val); | ||
| 236 | } | ||
| 237 | |||
| 238 | int get(int x, int y) { return _panel->get(x, y); } | ||
| 239 | int get(const Point& pos) { return _panel->get(pos.first, pos.second); } | ||
| 240 | |||
| 241 | // std::vector<std::vector<int>> _panelData; | ||
| 242 | // std::vector<std::vector<bool>> _drawnPath; | ||
| 243 | |||
| 244 | friend class PuzzleList; | ||
| 245 | friend class Special; | ||
| 246 | }; | ||
| 247 | |||
| 248 | #endif /* end of include guard: GENERATE_H_0582FCEA */ | ||
