From cebfd065c029788f3d6a8cc33b9401a708052335 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Wed, 15 Feb 2023 10:04:06 -0500 Subject: Did a buncha work --- generator.h | 230 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 generator.h (limited to 'generator.h') diff --git a/generator.h b/generator.h new file mode 100644 index 0000000..1381cd3 --- /dev/null +++ b/generator.h @@ -0,0 +1,230 @@ +#ifndef GENERATOR_H_811386CE +#define GENERATOR_H_811386CE + +#include +#include +#include +#include +#include +#include +#include + +enum Height { + kTop, + kMiddle, + kBottom, + kHeightCount +}; + +enum Colour { + kWhite, + kBlack, + kRed, + kBlue, + kPurple, + kBrown, + kYellow, + kGreen, + kOrange, + kColourCount +}; + +enum FilterDirection { + kTowardSolution, + kTowardQuestion +}; + +enum PalindromeQuery { + kPalindromeUnspecified, + kForcePalindrome, + kRejectPalindrome +}; + +struct GenerateOptions { + bool obscure_hint = false; + int max_answer_len = 0; + int max_hint_len = 0; + int exact_len = 0; + bool multiword = false; + bool save_for_later = false; + bool reuse_solution = false; // supported by single, double, and stack + std::string unique_pool; // supported by single, double, and stack + PalindromeQuery palindrome = kPalindromeUnspecified; // only important for middle black. supported by single and paired + std::string copy_to; // supported by single and paired + std::string copy_to2; // supported by paired + bool force_two_words = false; +}; + +class Wanderlust { +public: + Wanderlust(const std::string& words_filename, const std::string& puzzles_filename) { + std::ifstream words_file(words_filename); + std::string line; + while (std::getline(words_file, line)) { + words_.push_back(line); + } + + std::ifstream puzzles_file(puzzles_filename); + while (std::getline(puzzles_file, line)) { + std::string line2; + if (!std::getline(puzzles_file, line2)) { + throw std::invalid_argument("Wanderlust file is malformed."); + } + + puzzles_.emplace_back(line, line2); + } + } + + std::tuple GetPuzzle(std::mt19937& rng) const { + return puzzles_.at(std::uniform_int_distribution(0, puzzles_.size()-1)(rng)); + } + + const std::string& GetWord(std::mt19937& rng) const { + return words_.at(std::uniform_int_distribution(0, words_.size()-1)(rng)); + } + +private: + std::vector> puzzles_; + std::vector words_; +}; + +class CrossTower { +public: + explicit CrossTower(std::string filename) { + std::ifstream file(filename); + std::string line; + while (std::getline(file, line)) { + sets_.push_back(hatkirby::split>(line, " ")); + } + } + + std::vector> GetPuzzleSet(std::mt19937& rng) const { + std::vector> result = sets_; + std::shuffle(result.begin(), result.end(), rng); + result.resize(4); + + for (std::vector& set : result) { + std::shuffle(set.begin(), set.end(), rng); + } + + return result; + } + +private: + std::vector> sets_; +}; + +class Generator { +public: + + explicit Generator(unsigned int seed) : seed_(seed), rng_(seed) { + database_ = std::make_unique("/Users/hatkirby/Dropbox/Programming/verbly-datafiles/d1.3_lingo7"); + wanderlust_ = std::make_unique("../wanderlust_words.txt", "../wanderlust_puzzles.txt"); + cross_tower_ = std::make_unique("../cross_tower.txt"); + } + + // Querying + bool IsPanelRandomized(const std::string& name) const { + return panels_.count(name); + } + + const std::tuple& GetPanel(const std::string& name) const { + return panels_.at(name); + } + + // Sets the panel's question and answer to static values. + void GenerateStaticPanel(std::string name, std::string question, std::string answer = ""); + + // Generates a one-block puzzle with the given height and colour. + void GenerateSinglePanel(std::string name, Height height, Colour colour, GenerateOptions options = {}); + + // Generates a one-block puzzle with the given height and colour, where there is a panel on two faces of the block. + // Both puzzles will have the same answer. + void GenerateDoublePanel(std::string name1, std::string name2, Height height, Colour colour, GenerateOptions options = {}); + + // Generates two puzzles with the same hint but different answers. + void GenerateCohintedPanels(std::string name1, std::string name2, Height height, Colour colour, GenerateOptions options = {}); + + // Generates two panels at once, where the question for one is the answer to the other. + // Colour must be white, black, or yellow. + // Middle white is a special case; the puzzles will be antonyms of one another. + void GeneratePairedPanels(std::string name1, std::string name2, Height height, Colour colour, GenerateOptions options = {}); + + // Generates a vertical stack of panels that all have the same answer. + // If a name is left blank, that height will be ignored. + 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 = {}); + + // Generate an orange puzzle, with a number for the hint. + void GenerateOrangeNumberPanel(std::string name); + + // Generate an orange puzzle, with a word for the hint. + void GenerateOrangeWordPanel(std::string name); + + // Generate an orange puzzle, with an addition problem for the hint. + void GenerateOrangeAdditionPanel(std::string name); + + // Generates the ONE ROAD MANY TURNS panel by combining the solutions to four other panels. + void GenerateOneRoadManyTurns(std::string order_name, std::string part1_name, std::string part2_name, std::string part3_name, std::string part4_name); + + // Generates a hybrid puzzle where the solution is two words and each word is provided by a different colour/height puzzle. + void GenerateComboPanel(std::string name, Height left_height, Colour left_colour, Height right_height, Colour right_colour, GenerateOptions options = {}); + + // Generates the cross tower sets-of-four puzzles. + void GenerateCrossTower( + std::string north_tower_name, + std::string south_tower_name, + std::string east_tower_name, + std::string west_tower_name, + std::string north_lookout_name, + std::string south_lookout_name, + std::string east_lookout_name, + std::string west_lookout_name, + std::string north_other_name1, + std::string north_other_name2, + std::string north_other_name3, + std::string south_other_name1, + std::string south_other_name2, + std::string south_other_name3, + std::string east_other_name1, + std::string east_other_name2, + std::string east_other_name3, + std::string west_other_name1, + std::string west_other_name2, + std::string west_other_name3); + +private: + + verbly::filter MakeHintFilter(verbly::filter subfilter, Height height, Colour colour, FilterDirection filter_direction); + + bool GenerateSinglePanelImpl(std::string name, Height height, Colour colour, GenerateOptions options); + + bool GenerateDoublePanelImpl(std::string name1, std::string name2, Height height, Colour colour, GenerateOptions options); + + bool GenerateCohintedPanelsImpl(std::string name1, std::string name2, Height height, Colour colour, GenerateOptions options); + + bool GeneratePairedPanelsImpl(std::string name1, std::string name2, Height height, Colour colour, GenerateOptions options); + + 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); + + bool GenerateComboPanelImpl(std::string name, Height left_height, Colour left_colour, Height right_height, Colour right_colour, GenerateOptions options); + + void SavePanel(std::string name, std::string question, std::string answer, GenerateOptions options = {}); + + verbly::filter GetWordFilter(FilterDirection direction, GenerateOptions options) const; + + bool IsClueTrivial(Height height, Colour colour, const verbly::form& clue, const verbly::form& solution) const; + + unsigned int seed_; + std::mt19937 rng_; + std::unique_ptr database_; + std::unique_ptr wanderlust_; + std::unique_ptr cross_tower_; + + // name, question, answer + std::map> panels_; + + std::vector reusable_; + std::map> pools_; +}; + +#endif /* end of include guard: GENERATOR_H_811386CE */ -- cgit 1.4.1