#ifndef GENERATE_H_0582FCEA #define GENERATE_H_0582FCEA #include #include #include #include #include #include #include "Panel.h" #include "PuzzleSymbols.h" #include "Random.h" typedef std::set Shape; // The main class for generating puzzles. class Generate { public: Generate() { _width = _height = 0; _areaTotal = _genTotal = _totalPuzzles = _areaPuzzles = _stoneTypes = 0; _fullGaps = _bisect = _allowNonMatch = false; _panel = NULL; _parity = -1; colorblind = false; _seed = Random::rand(); arrowColor = backgroundColor = successColor = {0, 0, 0, 0}; resetConfig(); } enum Config { // See configinfo.txt for explanations of config flags. None = 0, FullGaps = 0x1, StartEdgeOnly = 0x2, DisableWrite = 0x4, PreserveStructure = 0x8, MakeStonesUnsolvable = 0x10, SmallShapes = 0x20, DisconnectShapes = 0x40, ResetColors = 0x80, DisableCancelShapes = 0x100, RequireCancelShapes = 0x200, BigShapes = 0x400, SplitShapes = 0x800, RequireCombineShapes = 0x1000, TreehouseLayout = 0x2000, TreehouseColors = 0x4000, AlternateColors = 0x8000, WriteColors = 0x10000, Write2Color = 0x20000, FixBackground = 0x40000, CombineErasers = 0x80000, LongPath = 0x100000, ShortPath = 0x200000, EnableFlash = 0x400000, DecorationsOnly = 0x800000, FalseParity = 0x1000000, DisableDotIntersection = 0x2000000, WriteDotColor = 0x4000000, WriteDotColor2 = 0x8000000, LongestPath = 0x10000000, WriteInvisible = 0x20000000, DisableReset = 0x40000000, MountainFloorH = 0x80000000 }; void generate(int width, int height, PuzzleSymbols symbols); /*void generateMaze(int id); void generateMaze(int id, int numStarts, int numExits);*/ void initPanel(); void setPath(const std::set& path) { customPath = path; for (Point p : path) setSymbol(IntersectionFlags::PATH, p.first, p.second); } void setObstructions(const std::vector& walls) { _obstructions = {walls}; } void setObstructions(const std::vector>& walls) { _obstructions = walls; } void setSymbol(Decoration::Shape symbol, int x, int y); void setSymbol(IntersectionFlags symbol, int x, int y) { setSymbol(static_cast(symbol), x, y); } void setGridSize(int width, int height); void setSymmetry(Panel::Symmetry symmetry); void write(int id); void setFlag(Config option) { _config |= option; }; void setFlagOnce(Config option) { _config |= option; _oneTimeAdd |= option; }; bool hasFlag(Config option) { return _config & option; }; void removeFlag(Config option) { _config &= ~option; }; void removeFlagOnce(Config option) { _config &= ~option; _oneTimeRemove |= option; }; void resetConfig(); void seed(long seed) { Random::seed(seed); _seed = Random::rand(); } float pathWidth; // Controls how thick the line is on the puzzle std::vector hitPoints; // The generated path will be forced to hit // these points in order std::set openPos; // Custom set of points that can have symbols placed on std::set blockPos; // Point that must be left open std::set customPath; Color arrowColor, backgroundColor, successColor; // For the arrow puzzles private: int get_symbol_type(int flags) { return flags & 0x700; } void set_path(Point pos); Point get_sym_point(Point pos) { return _panel->get_sym_point(pos); } int get_parity(Point pos) { return (pos.first / 2 + pos.second / 2) % 2; } void clear(); void resetVars(); void init_treehouse_layout(); template T pick_random(const std::vector& vec) { return vec[Random::rand() % vec.size()]; } template T pick_random(const std::set& set) { auto it = set.begin(); std::advance(it, Random::rand() % set.size()); return *it; } template T pop_random(const std::vector& vec) { int i = Random::rand() % vec.size(); T item = vec[i]; vec.erase(vec.begin() + i); return item; } template T pop_random(const std::set& set) { T item = pick_random(set); set.erase(item); return item; } bool on_edge(Point p) { return (p.first == 0 || p.first + 1 == _panel->width() || p.second == 0 || p.second + 1 == _panel->height()); } bool off_edge(Point p) { return (p.first < 0 || p.first >= _panel->width() || p.second < 0 || p.second >= _panel->height()); } static std::vector _DIRECTIONS1, _8DIRECTIONS1, _DIRECTIONS2, _8DIRECTIONS2, _SHAPEDIRECTIONS, _DISCONNECT; // bool generate_maze(int id, int numStarts, int numExits); bool generateInternal(int width, int height, PuzzleSymbols symbols); bool place_all_symbols(PuzzleSymbols& symbols); bool generate_path(PuzzleSymbols& symbols); bool generate_path_length(int minLength, int maxLength); bool generate_path_length(int minLength) { return generate_path_length(minLength, 10000); }; bool generate_path_regions(int minRegions); bool generate_longest_path(); bool generate_special_path(); void erase_path(); Point adjust_point(Point pos); std::set get_region(Point pos); std::vector get_symbols_in_region(Point pos); std::vector get_symbols_in_region(const std::set& region); bool place_start(int amount); bool place_exit(int amount); bool can_place_gap(Point pos); bool place_gaps(int amount); bool can_place_dot(Point pos, bool intersectionOnly); bool place_dots(int amount, Decoration::Color color, bool intersectionOnly); bool can_place_stone(const std::set& region, int color); bool place_stones(int color, int amount); Shape generate_shape(std::set& region, std::set& bufferRegion, Point pos, int maxSize); Shape generate_shape(std::set& region, Point pos, int maxSize) { std::set buffer; return generate_shape(region, buffer, pos, maxSize); } int make_shape_symbol(Shape shape, bool rotated, bool negative, int rotation, int depth); int make_shape_symbol(const Shape& shape, bool rotated, bool negative) { return make_shape_symbol(shape, rotated, negative, -1, 0); } bool place_shapes(const std::vector& colors, const std::vector& negativeColors, int amount, int numRotated, int numNegative); int count_color(const std::set& region, int color); bool place_stars(int color, int amount); bool has_star(const std::set& region, int color); bool checkStarZigzag(); bool place_triangles(int color, int amount, int targetCount); int count_sides(Point pos); bool place_arrows(int color, int amount, int targetCount); int count_crossings(Point pos, Point dir); bool place_erasers(const std::vector& colors, const std::vector& eraseSymbols); bool combine_shapes(std::vector& shapes); bool hasSymbolOrPath(const Point& pos) { return hasSymbolOrPath(pos.first, pos.second); } bool hasSymbolOrPath(int x, int y); std::unique_ptr _panel; std::vector> _custom_grid; int _width, _height; Panel::Symmetry _symmetry; std::set _starts, _exits; std::set _gridpos, _openpos; std::set _path, _path1, _path2; bool _fullGaps, _bisect; int _stoneTypes; int _config; int _oneTimeAdd, _oneTimeRemove; long _seed; std::vector _splitPoints; bool _allowNonMatch; // Used for multi-generator int _parity; std::vector> _obstructions; bool colorblind; int _areaTotal, _genTotal, _areaPuzzles, _totalPuzzles; std::wstring _areaName; void set(int x, int y, int val) { _panel->set(x, y, val); } void set(const Point& pos, int val) { _panel->set(pos.first, pos.second, val); } int get(int x, int y) { return _panel->get(x, y); } int get(const Point& pos) { return _panel->get(pos.first, pos.second); } // std::vector> _panelData; // std::vector> _drawnPath; friend class PuzzleList; friend class Special; }; #endif /* end of include guard: GENERATE_H_0582FCEA */