diff options
Diffstat (limited to 'lingo.cpp')
-rw-r--r-- | lingo.cpp | 70 |
1 files changed, 63 insertions, 7 deletions
diff --git a/lingo.cpp b/lingo.cpp index c2f36af..12471d1 100644 --- a/lingo.cpp +++ b/lingo.cpp | |||
@@ -37,6 +37,7 @@ enum Colour { | |||
37 | kBrown, | 37 | kBrown, |
38 | kYellow, | 38 | kYellow, |
39 | kGreen, | 39 | kGreen, |
40 | kOrange, | ||
40 | kColourCount | 41 | kColourCount |
41 | }; | 42 | }; |
42 | 43 | ||
@@ -48,7 +49,8 @@ const std::string COLOUR_EMOJIS[kColourCount] = { | |||
48 | "🟪", | 49 | "🟪", |
49 | "🟫", | 50 | "🟫", |
50 | "🟨", | 51 | "🟨", |
51 | "🟩" | 52 | "🟩", |
53 | "🟧", | ||
52 | }; | 54 | }; |
53 | 55 | ||
54 | const std::string NONE_EMOTE = "<:xx:1047267830535557180>"; | 56 | const std::string NONE_EMOTE = "<:xx:1047267830535557180>"; |
@@ -61,7 +63,8 @@ const std::string COLOUR_EMOTES[kColourCount] = { | |||
61 | "<:pr:1047262146926489691>", | 63 | "<:pr:1047262146926489691>", |
62 | "<:bn:1047262139187998790>", | 64 | "<:bn:1047262139187998790>", |
63 | "<:yw:1047262152781737986>", | 65 | "<:yw:1047262152781737986>", |
64 | "<:gn:1047262141914304633>" | 66 | "<:gn:1047262141914304633>", |
67 | "<:or:1047262144934182983>", | ||
65 | }; | 68 | }; |
66 | 69 | ||
67 | enum FilterDirection { | 70 | enum FilterDirection { |
@@ -272,6 +275,33 @@ verbly::filter makeHintFilter(verbly::filter subfilter, Height height, Colour co | |||
272 | return {}; | 275 | return {}; |
273 | } | 276 | } |
274 | 277 | ||
278 | class wanderlust { | ||
279 | public: | ||
280 | explicit wanderlust(const std::string& filename) | ||
281 | { | ||
282 | std::ifstream file(filename); | ||
283 | std::string line; | ||
284 | while (std::getline(file, line)) | ||
285 | { | ||
286 | std::string line2; | ||
287 | if (!std::getline(file, line2)) | ||
288 | { | ||
289 | throw std::invalid_argument("Wanderlust file is malformed."); | ||
290 | } | ||
291 | |||
292 | puzzles_.emplace_back(line, line2); | ||
293 | } | ||
294 | } | ||
295 | |||
296 | std::tuple<std::string, std::string> getPuzzle(std::mt19937& rng) const | ||
297 | { | ||
298 | return puzzles_.at(std::uniform_int_distribution<int>(0, puzzles_.size()-1)(rng)); | ||
299 | } | ||
300 | |||
301 | private: | ||
302 | std::vector<std::tuple<std::string, std::string>> puzzles_; | ||
303 | }; | ||
304 | |||
275 | class lingo { | 305 | class lingo { |
276 | public: | 306 | public: |
277 | lingo(std::mt19937& rng) : rng_(rng) {} | 307 | lingo(std::mt19937& rng) : rng_(rng) {} |
@@ -380,6 +410,7 @@ public: | |||
380 | 410 | ||
381 | database_ = std::make_unique<verbly::database>(config["verbly_datafile"].as<std::string>()); | 411 | database_ = std::make_unique<verbly::database>(config["verbly_datafile"].as<std::string>()); |
382 | imagenet_ = std::make_unique<imagenet>(config["imagenet"].as<std::string>()); | 412 | imagenet_ = std::make_unique<imagenet>(config["imagenet"].as<std::string>()); |
413 | wanderlust_ = std::make_unique<wanderlust>(config["wanderlust"].as<std::string>()); | ||
383 | 414 | ||
384 | scoreboard_endpoint_ = config["scoreboard_endpoint"].as<std::string>(); | 415 | scoreboard_endpoint_ = config["scoreboard_endpoint"].as<std::string>(); |
385 | scoreboard_secret_code_ = config["scoreboard_secret_code"].as<std::string>(); | 416 | scoreboard_secret_code_ = config["scoreboard_secret_code"].as<std::string>(); |
@@ -407,6 +438,7 @@ private: | |||
407 | {kMiddle, kBlue}, | 438 | {kMiddle, kBlue}, |
408 | {kMiddle, kPurple}, | 439 | {kMiddle, kPurple}, |
409 | {kMiddle, kGreen}, | 440 | {kMiddle, kGreen}, |
441 | {kMiddle, kOrange}, | ||
410 | {kBottom, kWhite}, | 442 | {kBottom, kWhite}, |
411 | {kBottom, kBlack}, | 443 | {kBottom, kBlack}, |
412 | {kBottom, kRed}, | 444 | {kBottom, kRed}, |
@@ -447,6 +479,7 @@ private: | |||
447 | int expensive_uses = 0; | 479 | int expensive_uses = 0; |
448 | int moderate_uses = 0; | 480 | int moderate_uses = 0; |
449 | int green_uses = 0; | 481 | int green_uses = 0; |
482 | int orange_uses = 0; | ||
450 | std::array<std::optional<Colour>, kHeightCount> parts; | 483 | std::array<std::optional<Colour>, kHeightCount> parts; |
451 | for (int height = 0; height < static_cast<int>(kHeightCount); height++) { | 484 | for (int height = 0; height < static_cast<int>(kHeightCount); height++) { |
452 | if (std::bernoulli_distribution(0.5)(rng_)) { | 485 | if (std::bernoulli_distribution(0.5)(rng_)) { |
@@ -472,6 +505,10 @@ private: | |||
472 | { | 505 | { |
473 | green_uses++; | 506 | green_uses++; |
474 | } | 507 | } |
508 | if (colour == kOrange) | ||
509 | { | ||
510 | orange_uses++; | ||
511 | } | ||
475 | 512 | ||
476 | std::cout << COLOUR_EMOJIS[colour]; | 513 | std::cout << COLOUR_EMOJIS[colour]; |
477 | } else { | 514 | } else { |
@@ -503,6 +540,13 @@ private: | |||
503 | continue; | 540 | continue; |
504 | } | 541 | } |
505 | 542 | ||
543 | std::string orange_clue; | ||
544 | std::string orange_solution; | ||
545 | if (orange_uses > 0) | ||
546 | { | ||
547 | std::tie(orange_clue, orange_solution) = wanderlust_->getPuzzle(rng_); | ||
548 | } | ||
549 | |||
506 | verbly::filter forwardFilter = cleanFilter && wordFilter; | 550 | verbly::filter forwardFilter = cleanFilter && wordFilter; |
507 | for (int i=0; i<static_cast<int>(kHeightCount); i++) { | 551 | for (int i=0; i<static_cast<int>(kHeightCount); i++) { |
508 | Height height = static_cast<Height>(i); | 552 | Height height = static_cast<Height>(i); |
@@ -510,7 +554,12 @@ private: | |||
510 | if (!colour.has_value()) { | 554 | if (!colour.has_value()) { |
511 | continue; | 555 | continue; |
512 | } | 556 | } |
513 | forwardFilter &= makeHintFilter(wordFilter, height, *colour, kTowardSolution); | 557 | if (*colour == kOrange) |
558 | { | ||
559 | forwardFilter &= (verbly::form::text == orange_solution); | ||
560 | } else { | ||
561 | forwardFilter &= makeHintFilter(wordFilter, height, *colour, kTowardSolution); | ||
562 | } | ||
514 | } | 563 | } |
515 | 564 | ||
516 | verbly::form solution = database_->forms(forwardFilter).first(); | 565 | verbly::form solution = database_->forms(forwardFilter).first(); |
@@ -523,11 +572,17 @@ private: | |||
523 | Height height = static_cast<Height>(i); | 572 | Height height = static_cast<Height>(i); |
524 | std::optional<Colour>& colour = parts[i]; | 573 | std::optional<Colour>& colour = parts[i]; |
525 | if (colour.has_value()) { | 574 | if (colour.has_value()) { |
526 | verbly::filter questionFilter = makeHintFilter(solution, height, *colour, kTowardQuestion); | 575 | if (*colour == kOrange) |
527 | verbly::form questionPart = database_->forms(questionFilter && cleanFilter && wordFilter).first(); | 576 | { |
528 | msg_stream << COLOUR_EMOTES[*colour] << " " << questionPart.getText() << std::endl; | 577 | msg_stream << COLOUR_EMOTES[*colour] << " " << orange_clue << std::endl; |
578 | admissible &= (verbly::form::text == orange_solution); | ||
579 | } else { | ||
580 | verbly::filter questionFilter = makeHintFilter(solution, height, *colour, kTowardQuestion); | ||
581 | verbly::form questionPart = database_->forms(questionFilter && cleanFilter && wordFilter).first(); | ||
582 | msg_stream << COLOUR_EMOTES[*colour] << " " << questionPart.getText() << std::endl; | ||
529 | 583 | ||
530 | admissible &= makeHintFilter(questionPart, height, *colour, kTowardSolution); | 584 | admissible &= makeHintFilter(questionPart, height, *colour, kTowardSolution); |
585 | } | ||
531 | } else { | 586 | } else { |
532 | msg_stream << NONE_EMOTE << std::endl; | 587 | msg_stream << NONE_EMOTE << std::endl; |
533 | } | 588 | } |
@@ -596,6 +651,7 @@ private: | |||
596 | std::mutex answers_mutex_; | 651 | std::mutex answers_mutex_; |
597 | std::string scoreboard_endpoint_; | 652 | std::string scoreboard_endpoint_; |
598 | std::string scoreboard_secret_code_; | 653 | std::string scoreboard_secret_code_; |
654 | std::unique_ptr<wanderlust> wanderlust_; | ||
599 | }; | 655 | }; |
600 | 656 | ||
601 | int main(int argc, char** argv) | 657 | int main(int argc, char** argv) |