summary refs log tree commit diff stats
path: root/data/maps/the_congruent/rooms/Flipped Magenta Room.txtpb
blob: db33a80bbff1d483a94c32c1b2e4a1c54aaaa942 (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
name: "Flipped Magenta Room"
display_name: "Flipped Magenta Room"
panels {
  name: "LOOK"
  path: "Panels/Side Up 1/panel_1"
  clue: "look"
  answer: "cook"
  symbols: "sparkles"
}
panels {
  name: "SLOW"
  path: "Panels/Side Up 1/panel_2"
  clue: "slow"
  answer: "show"
  symbols: "sparkles"
}
panels {
  name: "RULE"
  path: "Panels/Side Up 1/panel_3"
  clue: "rule"
  answer: "rude"
  symbols: "sparkles"
}
panels {
  name: "MALE"
  path: "Panels/Side Up 1/panel_4"
  clue: "male"
  answer: "mace"
  symbols: "sparkles"
}
panels {
  name: "LAST"
  path: "Panels/Side Up 1/panel_5"
  clue: "last"
  answer: "fast"
  symbols: "sparkles"
}
panels {
  name: "LATE"
  path: "Panels/Side Up 1/panel_6"
  clue: "late"
  answer: "date"
  symbols: "sparkles"
}
panels {
  name: "LEFT"
  path: "Panels/Side Up 1/panel_7"
  clue: "left"
  answer: "heft"
  symbols: "sparkles"
}
panels {
  name: "LIST"
  path: "Panels/Side Up 1/panel_8"
  clue: "list"
  answer: "fist"
  symbols: "sparkles"
}
panels {
  name: "LUST"
  path: "Panels/Side Up 1/panel_9"
  clue: "lust"
  answer: "gust"
  symbols: "sparkles"
}
panels {
  name: "LAND"
  path: "Panels/Side Up 1/panel_10"
  clue: "land"
  answer: "sand"
  symbols: "sparkles"
}
r: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
#ifndef GENERATE_H_0582FCEA
#define GENERATE_H_0582FCEA

#include <stdlib.h>
#include <time.h>

#include <algorithm>
#include <memory>
#include <set>
#include <string>

#include "Panel.h"
#include "PuzzleSymbols.h"
#include "Random.h"

typedef std::set<Point> 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,
    RegularStartEnd = 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<Point>& path) {
    customPath = path;
    for (Point p : path) setSymbol(IntersectionFlags::PATH, p.first, p.second);
  }
  void setObstructions(const std::vector<Point>& walls) {
    _obstructions = {walls};
  }
  void setObstructions(const std::vector<std::vector<Point>>& walls) {
    _obstructions = walls;
  }
  void setSymbol(Decoration::Shape symbol, int x, int y);
  void setSymbol(IntersectionFlags symbol, int x, int y) {
    setSymbol(static_cast<Decoration::Shape>(symbol), x, y);
  }
  void setGridSize(int width, int height);
  void setSymmetry(Panel::Symmetry symmetry);
  std::string AsCode();
  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<Point> hitPoints;  // The generated path will be forced to hit
                                 // these points in order
  std::set<Point>
      openPos;  // Custom set of points that can have symbols placed on
  std::set<Point> blockPos;  // Point that must be left open
  std::set<Point> customPath;
  Color arrowColor, backgroundColor, successColor;  // For the arrow puzzles

  bool place_gaps(int amount);

 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 <class T>
  T pick_random(const std::vector<T>& vec) {
    return vec[Random::rand() % vec.size()];
  }
  template <class T>
  T pick_random(const std::set<T>& set) {
    auto it = set.begin();
    std::advance(it, Random::rand() % set.size());
    return *it;
  }
  template <class T>
  T pop_random(const std::vector<T>& vec) {
    int i = Random::rand() % vec.size();
    T item = vec[i];
    vec.erase(vec.begin() + i);
    return item;
  }
  template <class T>
  T pop_random(const std::set<T>& 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<Point> _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<Point> get_region(Point pos);
  std::vector<int> get_symbols_in_region(Point pos);
  std::vector<int> get_symbols_in_region(const std::set<Point>& region);
  bool place_start(int amount);
  bool place_exit(int amount);
  bool can_place_gap(Point pos);

  bool can_place_dot(Point pos, bool intersectionOnly);
  bool place_dots(int amount, int color, bool intersectionOnly);
  bool can_place_stone(const std::set<Point>& region, int color);
  bool place_stones(int color, int amount);
  Shape generate_shape(std::set<Point>& region, std::set<Point>& bufferRegion,
                       Point pos, int maxSize);
  Shape generate_shape(std::set<Point>& region, Point pos, int maxSize) {
    std::set<Point> 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<int>& colors,
                    const std::vector<int>& negativeColors, int amount,
                    int numRotated, int numNegative);
  int count_color(const std::set<Point>& region, int color);
  bool place_stars(int color, int amount);
  bool has_star(const std::set<Point>& 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<int>& colors,
                     const std::vector<int>& eraseSymbols);
  bool combine_shapes(std::vector<Shape>& shapes);

  bool hasSymbolOrPath(const Point& pos) {
    return hasSymbolOrPath(pos.first, pos.second);
  }
  bool hasSymbolOrPath(int x, int y);

  std::unique_ptr<Panel> _panel;
  std::vector<std::vector<int>> _custom_grid;
  int _width, _height;
  Panel::Symmetry _symmetry;
  std::set<Point> _starts, _exits;
  std::set<Point> _gridpos, _openpos;
  std::set<Point> _path, _path1, _path2;
  bool _fullGaps, _bisect;
  int _stoneTypes;
  int _config;
  int _oneTimeAdd, _oneTimeRemove;
  long _seed;
  std::vector<Point> _splitPoints;
  bool _allowNonMatch;  // Used for multi-generator
  int _parity;
  std::vector<std::vector<Point>> _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<std::vector<int>> _panelData;
  //  std::vector<std::vector<bool>> _drawnPath;

  friend class PuzzleList;
  friend class Special;
};

#endif /* end of include guard: GENERATE_H_0582FCEA */