/* * Quackle -- Crossword game artificial intelligence and analysis tool * Copyright (C) 2005-2019 Jason Katz-Brown, John O'Laughlin, and John Fultz. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef QUACKLE_ENDGAME_H #define QUACKLE_ENDGAME_H #include #include #include #include "alphabetparameters.h" #include "game.h" namespace Quackle { struct EndgameMove { EndgameMove(const Move &_move) : move(_move), optimistic(0), pessimistic(0), estimated(0), outplay(false) { } Move move; double optimistic; double pessimistic; double estimated; bool outplay; }; class EndgameMoveList : public vector { public: static bool optimisticComparator(const EndgameMove &move1, const EndgameMove &move2); }; class Endgame { public: // constructs a new endgame solver Endgame(); ~Endgame(); // Find the best move in this position. Also initializes the // move list, rack, resets numbers, and closes logfile. void setPosition(const GamePosition &position); // get access to the position that starts each playahead of the // endgame; use to rechange rack or scores etcetera GamePosition ¤tPosition(); const GamePosition ¤tPosition() const; void setDispatch(ComputerDispatch *dispatch); // If logfile is an empty string, logging is disabled. // If logfile is the same logfile as currently set, nothing // happens. If it is different, old logfile is closed if it // was open. If append is false, this destroys file contents // already in logfile. void setLogfile(const string &logfile, bool append = true); string logfile() const; // append message to logfile if one is open void logMessage(const UVString &message); bool isLogging() const; void closeLogfile(); // Set moves to include in solution. void setIncludedMoves(const MoveList &moves); // include only currently included moves that are within // equityThreshold points below the best play and cap at // maxNumberOfMoves // void pruneTo(double equityThreshold, int maxNumberOfMoves); // return a list of moves, sorted by estimated equity MoveList moves(unsigned int nmoves); // return the move list const EndgameMoveList &endgameMoves() const; // Return the best move Move solve(int nestedness); void reallyPlayOut(Move &move, int nestedness); double disappoint(EndgameMove &hope, double bestPessimistic); protected: void writeLogHeader(); void writeLogFooter(); UVOFStream m_logfileStream; string m_logfile; bool m_logfileIsOpen; bool m_hasHeader; UVString m_xmlIndent; Game m_originalGame; Game m_endgameGame; ComputerDispatch *m_dispatch; EndgameMoveList m_endgameMoves; int m_nestedDisappointPlayNumber; int m_subnestedDisappointPlayNumber; int m_unnestedDisappointPlayNumber; int m_nestedInitialPlayNumber; int m_subnestedInitialPlayNumber; int m_unnestedInitialPlayNumber; }; inline GamePosition &Endgame::currentPosition() { return m_originalGame.currentPosition(); } inline const GamePosition &Endgame::currentPosition() const { return m_originalGame.currentPosition(); } inline string Endgame::logfile() const { return m_logfile; } inline bool Endgame::isLogging() const { return m_logfileIsOpen; } inline const EndgameMoveList &Endgame::endgameMoves() const { return m_endgameMoves; } } UVOStream& operator<<(UVOStream& o, const Quackle::EndgameMove &move); UVOStream& operator<<(UVOStream& o, const Quackle::EndgameMoveList &move); #endif