summary refs log tree commit diff stats
path: root/generator.h
diff options
context:
space:
mode:
Diffstat (limited to 'generator.h')
-rw-r--r--generator.h277
1 files changed, 0 insertions, 277 deletions
diff --git a/generator.h b/generator.h deleted file mode 100644 index d0333a6..0000000 --- a/generator.h +++ /dev/null
@@ -1,277 +0,0 @@
1#ifndef GENERATOR_H_811386CE
2#define GENERATOR_H_811386CE
3
4#include <string>
5#include <random>
6#include <map>
7#include <tuple>
8#include <memory>
9#include <verbly.h>
10#include <hkutil/string.h>
11
12enum Height {
13 kTop,
14 kMiddle,
15 kBottom,
16 kHeightCount
17};
18
19enum Colour {
20 kWhite,
21 kBlack,
22 kRed,
23 kBlue,
24 kPurple,
25 kBrown,
26 kYellow,
27 kGreen,
28 kOrange,
29 kColourCount
30};
31
32enum FilterDirection {
33 kTowardSolution,
34 kTowardQuestion
35};
36
37enum PalindromeQuery {
38 kPalindromeUnspecified,
39 kForcePalindrome,
40 kRejectPalindrome
41};
42
43struct GenerateOptions {
44 bool obscure_hint = false;
45 int max_answer_len = 0;
46 int max_hint_len = 0;
47 int exact_len = 0;
48 int max_len_diff = -1; // supported by single, double, paired, cohinted
49 bool multiword = false;
50 bool save_for_later = false;
51 bool reuse_solution = false; // supported by single, double, and stack
52 std::string unique_pool; // supported by single, double, and stack
53 PalindromeQuery palindrome = kPalindromeUnspecified; // only important for middle black. supported by single and paired
54 std::string copy_to; // supported by single and paired
55 std::string copy_to2; // supported by paired
56 std::string copy_hidden; // supported by single mid white
57 bool force_two_words = false;
58 bool must_be_broad = false; // the solution must also be gettable by bottom white/red/blue. supported by single and double
59 bool allow_top_expansion = false; // this disables the triviality check that top puzzles can't also apply to middle
60};
61
62class Wanderlust {
63public:
64 Wanderlust(const std::string& words_filename, const std::string& puzzles_filename) {
65 std::ifstream words_file(words_filename);
66 std::string line;
67 while (std::getline(words_file, line)) {
68 words_.push_back(line);
69 }
70
71 std::ifstream puzzles_file(puzzles_filename);
72 while (std::getline(puzzles_file, line)) {
73 std::string line2;
74 if (!std::getline(puzzles_file, line2)) {
75 throw std::invalid_argument("Wanderlust file is malformed.");
76 }
77
78 puzzles_.emplace_back(line, line2);
79 }
80 }
81
82 std::tuple<std::string, std::string> GetPuzzle(std::mt19937& rng) const {
83 return puzzles_.at(std::uniform_int_distribution<int>(0, puzzles_.size()-1)(rng));
84 }
85
86 const std::string& GetWord(std::mt19937& rng) const {
87 return words_.at(std::uniform_int_distribution<int>(0, words_.size()-1)(rng));
88 }
89
90private:
91 std::vector<std::tuple<std::string, std::string>> puzzles_;
92 std::vector<std::string> words_;
93};
94
95class CrossTower {
96public:
97 explicit CrossTower(std::string filename) {
98 std::ifstream file(filename);
99 std::string line;
100 while (std::getline(file, line)) {
101 sets_.push_back(hatkirby::split<std::vector<std::string>>(line, " "));
102 }
103 }
104
105 std::vector<std::vector<std::string>> GetPuzzleSet(std::mt19937& rng) const {
106 std::vector<std::vector<std::string>> result = sets_;
107 std::shuffle(result.begin(), result.end(), rng);
108 result.resize(4);
109
110 for (std::vector<std::string>& set : result) {
111 std::shuffle(set.begin(), set.end(), rng);
112 }
113
114 return result;
115 }
116
117private:
118 std::vector<std::vector<std::string>> sets_;
119};
120
121class Paintings {
122public:
123 explicit Paintings(std::string filename) {
124 std::ifstream file(filename);
125 std::string line;
126 while (std::getline(file, line)) {
127 auto parts = hatkirby::split<std::vector<std::string>>(line, ",");
128 paintings_.emplace_back(parts[0], parts[1], std::atoi(parts[2].c_str()));
129 }
130 }
131
132 const std::tuple<std::string, std::string, int>& GetPainting(std::mt19937& rng) const {
133 return paintings_.at(std::uniform_int_distribution<int>(0, paintings_.size()-1)(rng));
134 }
135
136private:
137 std::vector<std::tuple<std::string, std::string, int>> paintings_;
138};
139
140class Generator {
141public:
142
143 explicit Generator(unsigned int seed) : seed_(seed), rng_(seed) {
144 database_ = std::make_unique<verbly::database>("/Users/hatkirby/Dropbox/Programming/verbly-datafiles/d1.3_lingo7");
145 wanderlust_ = std::make_unique<Wanderlust>("../wanderlust_words.txt", "../wanderlust_puzzles.txt");
146 cross_tower_ = std::make_unique<CrossTower>("../cross_tower.txt");
147 paintings_ = std::make_unique<Paintings>("../paintings.txt");
148 }
149
150 // Querying
151 bool IsPanelRandomized(const std::string& name) const {
152 return panels_.count(name);
153 }
154
155 const std::tuple<std::string, std::string>& GetPanel(const std::string& name) const {
156 return panels_.at(name);
157 }
158
159 bool IsNodeRandomized(const std::string& name) const {
160 return replace_nodes_.count(name);
161 }
162
163 const std::tuple<std::string, int>& GetNode(const std::string& name) const {
164 return replace_nodes_.at(name);
165 }
166
167 const std::vector<std::tuple<std::string, std::string>>& GetResources() const {
168 return resources_;
169 }
170
171 // Sets the panel's question and answer to static values.
172 void GenerateStaticPanel(std::string name, std::string question, std::string answer = "");
173
174 // Generates a one-block puzzle with the given height and colour.
175 void GenerateSinglePanel(std::string name, Height height, Colour colour, GenerateOptions options = {});
176
177 // Generates a one-block puzzle with the given height and colour, where there is a panel on two faces of the block.
178 // Both puzzles will have the same answer.
179 void GenerateDoublePanel(std::string name1, std::string name2, Height height, Colour colour, GenerateOptions options = {});
180
181 // Generates two puzzles with the same hint but different answers.
182 void GenerateCohintedPanels(std::string name1, std::string name2, Height height, Colour colour, GenerateOptions options = {});
183
184 // Generates two panels at once, where the question for one is the answer to the other.
185 // Colour must be white, black, or yellow.
186 // Middle white is a special case; the puzzles will be antonyms of one another.
187 void GeneratePairedPanels(std::string name1, std::string name2, Height height, Colour colour, GenerateOptions options = {});
188
189 // Generates a vertical stack of panels that all have the same answer.
190 // If a name is left blank, that height will be ignored.
191 void GeneratePanelStack(std::string top_name, Colour top_colour, std::string middle_name, Colour middle_colour, std::string bottom_name, Colour bottom_colour, GenerateOptions options = {});
192
193 // Generate an orange puzzle, with a number for the hint.
194 void GenerateOrangeNumberPanel(std::string name);
195
196 // Generate an orange puzzle, with a word for the hint.
197 void GenerateOrangeWordPanel(std::string name);
198
199 // Generate an orange puzzle, with an addition problem for the hint.
200 void GenerateOrangeAdditionPanel(std::string name);
201
202 // Generates the ONE ROAD MANY TURNS panel by combining the solutions to four other panels.
203 void GenerateOneRoadManyTurns(std::string order_name, std::string part1_name, std::string part2_name, std::string part3_name, std::string part4_name);
204
205 // Generates a hybrid puzzle where the solution is two words and each word is provided by a different colour/height puzzle.
206 void GenerateComboPanel(std::string name, Height left_height, Colour left_colour, Height right_height, Colour right_colour, GenerateOptions options = {});
207
208 // Generates the cross tower sets-of-four puzzles.
209 void GenerateCrossTower(
210 std::string north_tower_name,
211 std::string south_tower_name,
212 std::string east_tower_name,
213 std::string west_tower_name,
214 std::string north_lookout_name,
215 std::string south_lookout_name,
216 std::string east_lookout_name,
217 std::string west_lookout_name,
218 std::string north_other_name1,
219 std::string north_other_name2,
220 std::string north_other_name3,
221 std::string south_other_name1,
222 std::string south_other_name2,
223 std::string south_other_name3,
224 std::string east_other_name1,
225 std::string east_other_name2,
226 std::string east_other_name3,
227 std::string west_other_name1,
228 std::string west_other_name2,
229 std::string west_other_name3);
230
231 // Generate a painting/panel pair.
232 void GeneratePaintingPuzzle(std::string panel_name, std::string painting_name);
233
234private:
235
236 verbly::filter MakeHintFilter(verbly::filter subfilter, Height height, Colour colour, FilterDirection filter_direction) const;
237
238 bool GenerateSinglePanelImpl(std::string name, Height height, Colour colour, GenerateOptions options);
239
240 bool GenerateDoublePanelImpl(std::string name1, std::string name2, Height height, Colour colour, GenerateOptions options);
241
242 bool GenerateCohintedPanelsImpl(std::string name1, std::string name2, Height height, Colour colour, GenerateOptions options);
243
244 bool GeneratePairedPanelsImpl(std::string name1, std::string name2, Height height, Colour colour, GenerateOptions options);
245
246 bool GeneratePanelStackImpl(std::string top_name, Colour top_colour, std::string middle_name, Colour middle_colour, std::string bottom_name, Colour bottom_colour, GenerateOptions options);
247
248 bool GenerateComboPanelImpl(std::string name, Height left_height, Colour left_colour, Height right_height, Colour right_colour, GenerateOptions options);
249
250 void SavePanel(std::string name, std::string question, std::string answer, GenerateOptions options = {});
251
252 verbly::filter GetWordFilter(FilterDirection direction, GenerateOptions options) const;
253
254 bool IsClueTrivial(Height height, Colour colour, const verbly::form& clue, const verbly::form& solution, GenerateOptions options = {}) const;
255
256 unsigned int seed_;
257 std::mt19937 rng_;
258 std::unique_ptr<verbly::database> database_;
259 std::unique_ptr<Wanderlust> wanderlust_;
260 std::unique_ptr<CrossTower> cross_tower_;
261 std::unique_ptr<Paintings> paintings_;
262
263 // name, question, answer
264 std::map<std::string, std::tuple<std::string, std::string>> panels_;
265
266 // name, resource_path, resource_id (0 if needs import)
267 std::map<std::string, std::tuple<std::string, int>> replace_nodes_;
268
269 // path, type
270 std::vector<std::tuple<std::string, std::string>> resources_;
271
272 std::vector<std::string> reusable_;
273 std::map<std::string, std::set<std::string>> pools_;
274 std::set<std::string> used_paintings_;
275};
276
277#endif /* end of include guard: GENERATOR_H_811386CE */