diff options
| -rw-r--r-- | lingo.cpp | 133 |
1 files changed, 86 insertions, 47 deletions
| diff --git a/lingo.cpp b/lingo.cpp index cd68814..077bc3c 100644 --- a/lingo.cpp +++ b/lingo.cpp | |||
| @@ -428,6 +428,22 @@ public: | |||
| 428 | 428 | ||
| 429 | private: | 429 | private: |
| 430 | 430 | ||
| 431 | bool isClueTrivial(Height height, Colour colour, const verbly::form& clue, const verbly::form& solution) const | ||
| 432 | { | ||
| 433 | if (height == kTop && colour == kWhite) | ||
| 434 | { | ||
| 435 | return !database_->forms((verbly::filter)clue && (verbly::word::synonyms %= solution)).all().empty(); | ||
| 436 | } else if (height == kBottom && colour == kWhite) | ||
| 437 | { | ||
| 438 | return !database_->forms((verbly::filter)clue && (verbly::form::pronunciations %= solution)).all().empty(); | ||
| 439 | } else if (height == kBottom && colour == kBlack) | ||
| 440 | { | ||
| 441 | return !database_->forms((verbly::filter)clue && (verbly::form::merographs %= solution)).all().empty() | ||
| 442 | || !database_->forms((verbly::filter)clue && (verbly::form::holographs %= solution)).all().empty(); | ||
| 443 | } | ||
| 444 | return false; | ||
| 445 | } | ||
| 446 | |||
| 431 | void generatePuzzle() | 447 | void generatePuzzle() |
| 432 | { | 448 | { |
| 433 | std::cout << "Generating puzzle..." << std::endl; | 449 | std::cout << "Generating puzzle..." << std::endl; |
| @@ -568,70 +584,93 @@ private: | |||
| 568 | } | 584 | } |
| 569 | 585 | ||
| 570 | verbly::form solution = database_->forms(forwardFilter).first(); | 586 | verbly::form solution = database_->forms(forwardFilter).first(); |
| 571 | verbly::filter admissible = cleanFilter && (verbly::form::proper == false); | ||
| 572 | 587 | ||
| 573 | std::cout << "Solution decided: " << solution.getText() << std::endl; | 588 | std::cout << "Solution decided: " << solution.getText() << std::endl; |
| 574 | 589 | ||
| 575 | std::ostringstream msg_stream; | 590 | bool made_puzzle = false; |
| 576 | for (int i=0; i<static_cast<int>(kHeightCount); i++) { | 591 | for (int i=0; i<10; i++) |
| 577 | Height height = static_cast<Height>(i); | 592 | { |
| 578 | std::optional<Colour>& colour = parts[i]; | 593 | verbly::filter admissible = cleanFilter && (verbly::form::proper == false) && (verbly::form::length == static_cast<int>(solution.getText().size())); |
| 579 | if (colour.has_value()) { | 594 | std::ostringstream msg_stream; |
| 580 | if (*colour == kOrange) | 595 | bool trivial = false; |
| 581 | { | 596 | for (int i=0; i<static_cast<int>(kHeightCount); i++) { |
| 582 | msg_stream << COLOUR_EMOTES[*colour] << " " << orange_clue << std::endl; | 597 | Height height = static_cast<Height>(i); |
| 583 | admissible &= (verbly::form::text == orange_solution); | 598 | std::optional<Colour>& colour = parts[i]; |
| 599 | if (colour.has_value()) { | ||
| 600 | if (*colour == kOrange) | ||
| 601 | { | ||
| 602 | msg_stream << COLOUR_EMOTES[*colour] << " " << orange_clue << std::endl; | ||
| 603 | admissible &= (verbly::form::text == orange_solution); | ||
| 604 | } else { | ||
| 605 | verbly::filter questionFilter = makeHintFilter(solution, height, *colour, kTowardQuestion); | ||
| 606 | verbly::form questionPart = database_->forms(questionFilter && cleanFilter && wordFilter).first(); | ||
| 607 | msg_stream << COLOUR_EMOTES[*colour] << " " << questionPart.getText() << std::endl; | ||
| 608 | |||
| 609 | if (isClueTrivial(height, *colour, questionPart, solution)) | ||
| 610 | { | ||
| 611 | trivial = true; | ||
| 612 | break; | ||
| 613 | } | ||
| 614 | |||
| 615 | admissible &= makeHintFilter(questionPart, height, *colour, kTowardSolution); | ||
| 616 | } | ||
| 584 | } else { | 617 | } else { |
| 585 | verbly::filter questionFilter = makeHintFilter(solution, height, *colour, kTowardQuestion); | 618 | msg_stream << NONE_EMOTE << std::endl; |
| 586 | verbly::form questionPart = database_->forms(questionFilter && cleanFilter && wordFilter).first(); | ||
| 587 | msg_stream << COLOUR_EMOTES[*colour] << " " << questionPart.getText() << std::endl; | ||
| 588 | |||
| 589 | admissible &= makeHintFilter(questionPart, height, *colour, kTowardSolution); | ||
| 590 | } | 619 | } |
| 591 | } else { | ||
| 592 | msg_stream << NONE_EMOTE << std::endl; | ||
| 593 | } | 620 | } |
| 594 | } | ||
| 595 | auto byspace = hatkirby::split<std::list<std::string>>(solution.getText(), " "); | ||
| 596 | std::list<std::string> lens; | ||
| 597 | for (const std::string& wordpart : byspace) | ||
| 598 | { | ||
| 599 | lens.push_back(std::to_string(wordpart.size())); | ||
| 600 | } | ||
| 601 | 621 | ||
| 602 | msg_stream << "(" << hatkirby::implode(std::begin(lens), std::end(lens), " ") << ")"; | 622 | if (trivial) |
| 603 | 623 | { | |
| 604 | std::string message_text = msg_stream.str(); | 624 | std::cout << "Puzzle is trivial." << std::endl; |
| 605 | std::cout << message_text << std::endl << std::endl << solution.getText() << std::endl; | 625 | continue; |
| 626 | } | ||
| 606 | 627 | ||
| 607 | std::vector<verbly::form> admissibleResults = database_->forms(admissible, {}, 10).all(); | 628 | auto byspace = hatkirby::split<std::list<std::string>>(solution.getText(), " "); |
| 608 | if (green_uses > 0 || (admissibleResults.size() <= (hints == 1 ? 2 : 5))) | 629 | std::list<std::string> lens; |
| 609 | { | 630 | for (const std::string& wordpart : byspace) |
| 610 | genpuzzle = std::make_unique<puzzle>(); | ||
| 611 | genpuzzle->message = message_text; | ||
| 612 | genpuzzle->solution = hatkirby::lowercase(solution.getText()); | ||
| 613 | while (genpuzzle->solution.find(" ") != std::string::npos) | ||
| 614 | { | 631 | { |
| 615 | genpuzzle->solution.erase(genpuzzle->solution.find(" "), 1); | 632 | lens.push_back(std::to_string(wordpart.size())); |
| 616 | } | 633 | } |
| 617 | 634 | ||
| 618 | if (green_uses > 0) | 635 | msg_stream << "(" << hatkirby::implode(std::begin(lens), std::end(lens), " ") << ")"; |
| 636 | |||
| 637 | std::string message_text = msg_stream.str(); | ||
| 638 | std::cout << message_text << std::endl << std::endl << solution.getText() << std::endl; | ||
| 639 | |||
| 640 | std::vector<verbly::form> admissibleResults = database_->forms(admissible, {}, 10).all(); | ||
| 641 | if (green_uses > 0 || (admissibleResults.size() <= (hints == 1 ? 2 : 5))) | ||
| 619 | { | 642 | { |
| 620 | verbly::notion notion = database_->notions( | 643 | genpuzzle = std::make_unique<puzzle>(); |
| 621 | (verbly::notion::numOfImages > 1) && solution).first(); | 644 | genpuzzle->message = message_text; |
| 622 | auto [image, extension] = imagenet_->getImageForNotion(notion.getId(), rng_); | 645 | genpuzzle->solution = hatkirby::lowercase(solution.getText()); |
| 623 | if (image.empty()) | 646 | while (genpuzzle->solution.find(" ") != std::string::npos) |
| 624 | { | 647 | { |
| 625 | throw std::runtime_error("Could not find image for green hint."); | 648 | genpuzzle->solution.erase(genpuzzle->solution.find(" "), 1); |
| 626 | } | 649 | } |
| 627 | 650 | ||
| 628 | genpuzzle->attachment_name = std::string("SPOILER_image.") + extension; | 651 | if (green_uses > 0) |
| 629 | genpuzzle->attachment_content = std::move(image); | 652 | { |
| 630 | } | 653 | verbly::notion notion = database_->notions( |
| 654 | (verbly::notion::numOfImages > 1) && solution).first(); | ||
| 655 | auto [image, extension] = imagenet_->getImageForNotion(notion.getId(), rng_); | ||
| 656 | if (image.empty()) | ||
| 657 | { | ||
| 658 | throw std::runtime_error("Could not find image for green hint."); | ||
| 659 | } | ||
| 631 | 660 | ||
| 661 | genpuzzle->attachment_name = std::string("SPOILER_image.") + extension; | ||
| 662 | genpuzzle->attachment_content = std::move(image); | ||
| 663 | } | ||
| 664 | |||
| 665 | made_puzzle = true; | ||
| 666 | break; | ||
| 667 | } else { | ||
| 668 | std::cout << "Too many (" << admissibleResults.size() << ") results." << std::endl; | ||
| 669 | } | ||
| 670 | } | ||
| 671 | if (made_puzzle) | ||
| 672 | { | ||
| 632 | break; | 673 | break; |
| 633 | } else { | ||
| 634 | std::cout << "Too many (" << admissibleResults.size() << ") results." << std::endl; | ||
| 635 | } | 674 | } |
| 636 | } catch (const std::exception& ex) { | 675 | } catch (const std::exception& ex) { |
| 637 | std::cout << ex.what() << std::endl; | 676 | std::cout << ex.what() << std::endl; |
