├── .gitignore ├── COPYING ├── README.markdown ├── bin ├── 3x3.gamma ├── gnugo.sh └── libego.sh ├── cgos ├── cgos.configure.sh └── client │ └── cgosGtp.tcl ├── cmakeall ├── regression └── board_test.sh ├── source ├── .unused │ ├── distributed_twogtp │ │ ├── CMakeLists.txt │ │ ├── admin.cpp │ │ ├── admin.hpp │ │ ├── d2g-admin.cpp │ │ ├── d2g-worker.cpp │ │ ├── database.cpp │ │ ├── database.hpp │ │ ├── gtp_process.cpp │ │ ├── gtp_process.hpp │ │ ├── remi │ │ │ ├── CBAST.cpp │ │ │ ├── CBAST.h │ │ │ └── CMakeLists.txt │ │ ├── worker.cpp │ │ └── worker.hpp │ ├── experiments.cpp │ ├── fast_pool.hpp │ ├── model.hpp │ ├── sgf.cpp │ ├── sgf.hpp │ ├── sgf_gtp.cpp │ └── sgf_gtp.hpp ├── CMakeLists.txt ├── cmake │ └── modules │ │ ├── AddBoostCxxTest.cmake │ │ ├── EnsureBuildTypeIsChosen.cmake │ │ ├── EnsureOutOfSourceBuild.cmake │ │ ├── SetCxxFlags.cmake │ │ └── SetDefaultInstallationDirs.cmake ├── engine │ ├── CMakeLists.txt │ ├── all_hash3x3.hpp │ ├── engine.cpp │ ├── engine.hpp │ ├── mcts_gtp.hpp │ ├── mcts_tree.cpp │ ├── mcts_tree.hpp │ ├── mm.hpp │ ├── param.cpp │ ├── param.hpp │ ├── stat.hpp │ ├── time_control.cpp │ └── time_control.hpp ├── goboard │ ├── CMakeLists.txt │ ├── benchmark.cpp │ ├── benchmark.hpp │ ├── board.cpp │ ├── board.hpp │ ├── color.cpp │ ├── color.hpp │ ├── config.hpp │ ├── dir.hpp │ ├── ego.cpp │ ├── ego.hpp │ ├── gammas.hpp │ ├── hash.cpp │ ├── hash.hpp │ ├── move.cpp │ ├── move.hpp │ ├── player.cpp │ ├── player.hpp │ ├── playout_test.cpp │ ├── playout_test.hpp │ ├── sampler.hpp │ ├── vertex.cpp │ └── vertex.hpp ├── gtp │ ├── CMakeLists.txt │ ├── gtp.cpp │ ├── gtp.hpp │ ├── gtp_gogui.cpp │ ├── gtp_gogui.hpp │ ├── gtp_gogui_test.cpp │ └── gtp_test.cpp ├── gui │ ├── CMakeLists.txt │ ├── gui.cpp │ ├── gui.h │ ├── manager.cpp │ └── manager.h ├── libgamegui │ ├── CMakeLists.txt │ ├── Field.cpp │ ├── Field.h │ ├── GameScene.cpp │ ├── GameScene.h │ ├── Grid.cpp │ ├── Grid.h │ ├── HavannahGrid.cpp │ ├── HavannahGrid.h │ ├── HexGrid.cpp │ ├── HexGrid.h │ ├── HoGrid.cpp │ ├── HoGrid.h │ ├── ResizableView.cpp │ ├── ResizableView.h │ ├── Ruler.cpp │ ├── Ruler.h │ ├── SquareGrid.cpp │ ├── SquareGrid.h │ ├── YGrid.cpp │ ├── YGrid.h │ ├── images.qrc │ └── images │ │ ├── gogui-black-32x32.png │ │ ├── gogui-black.svg │ │ ├── gogui-white-32x32.png │ │ ├── gogui-white.svg │ │ └── wood.png ├── main │ ├── CMakeLists.txt │ ├── main.cpp │ └── mm_train.hpp ├── mm_preprocess_sgf.py └── utils │ ├── CMakeLists.txt │ ├── fast_random.cpp │ ├── fast_random.hpp │ ├── fast_stack.hpp │ ├── fast_timer.cpp │ ├── fast_timer.hpp │ ├── nat-inl.hpp │ ├── nat.hpp │ ├── test.cpp │ ├── test.hpp │ ├── to_string.hpp │ └── utils.hpp ├── twogtp ├── play.sh └── students │ ├── for_each_lab_comp.sh │ ├── list_workers.py │ ├── screen_worker.sh │ ├── server.py │ └── worker.py └── vs2010 ├── Go.sln ├── Go.suo ├── Go.vcxproj ├── Go.vcxproj.filters └── Go.vcxproj.user /.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | bin/engine 3 | bin/fuego-0.4 4 | bin/gnugo-3.8 5 | ipch 6 | vs2010/Go.sdf 7 | vs2010/Release 8 | vs2010/Debug 9 | bin/mogo-3 10 | log/* 11 | twogtp/2010-* 12 | *~ -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | Library of Effective GO routines 2 | ================================ 3 | 4 | This is a Library of Effective GO routines (libEGO), a high performance 5 | implementation of Go rules and most popular algorithms used in computer Go. 6 | 7 | 8 | Installation 9 | ------------ 10 | 11 | You will need: 12 | * git (version control system) 13 | * cmake (cross-platform, open-source build system) 14 | 15 | Checkout the source: 16 | 17 | git clone git://github.com/lukaszlew/libego.git 18 | 19 | Construct library and examples with your favorite compiler: 20 | 21 | ./cmakeall # do all the work 22 | 23 | Run GTP engine: 24 | 25 | ./bin/libego.sh # Same as ./bin/engine but loads pattern gammas from a file. 26 | ./bin/libego.sh gui # Experimental gui for making experiments :) 27 | 28 | You can connect engine to GoGui using first command. 29 | 30 | Thanks 31 | ------ 32 | 33 | My girlfriend for her endless support and patience. 34 | Benjamin Tauber for many hours of extreme programming. 35 | Jakub Pawlewicz for the idea of pseudo-liberties and find-union algorithms. 36 | Dave Hillis for the idea of mercy rule. 37 | Markus Enzenberger for his computer go bibliography and GoGui. 38 | Don Dailey for setting up CGOS server. 39 | Remi Coulom for supervising my work. 40 | And last but not least, a whole computer Go community for a 41 | stimulating mixture of cooperation and competition. 42 | 43 | Copyright 44 | --------- 45 | 46 | All files Copyright 2006 and onwards Łukasz Lew. 47 | 48 | All files in this package are under General Public License, 49 | which may be found in the file COPYING. 50 | 51 | Contact 52 | ------- 53 | 54 | Lukasz Lew 55 | -------------------------------------------------------------------------------- /bin/gnugo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | gnugo-3.8 \ 4 | --mode gtp \ 5 | --chinese-rules \ 6 | --capture-all-dead \ 7 | --positional-superko \ 8 | --level=0 9 | -------------------------------------------------------------------------------- /bin/libego.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | SCRIPT_DIR="$(readlink -f $(dirname "$0"))" 3 | 4 | "${SCRIPT_DIR}"/engine \ 5 | "LoadGammas ${SCRIPT_DIR}/3x3.gamma" \ 6 | "$1" \ 7 | \ 8 | gtp 9 | -------------------------------------------------------------------------------- /cgos/cgos.configure.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | THIS_DIR="$(readlink -f $(dirname "${0}"))" 4 | 5 | LOGIN="${1}" # you can hardcode login 6 | #LOGIN="MyBot-${1}" # or at least add some prefix 7 | PASSWORD="${2}" # yep, hardcode password as well 8 | GTP_CONFIG_FILE="${3}" 9 | 10 | usage () { 11 | echo "Usage: ${0} LOGIN PASSWORD GTP_CONFIG_FILE" 12 | exit 1 13 | } 14 | 15 | 16 | if test -z "${LOGIN}"; then 17 | usage 18 | fi 19 | 20 | if test -z "${PASSWORD}"; then 21 | usage 22 | fi 23 | 24 | if test -z "${GTP_CONFIG_FILE}"; then 25 | usage 26 | fi 27 | 28 | # Login's subdirectory and files 29 | 30 | LOGIN_DIR="${THIS_DIR}/${LOGIN}" 31 | 32 | CGOS_CONFIG_FILE="${LOGIN_DIR}/cgos.cfg" 33 | PLEASE_WAIT_FILE="${LOGIN_DIR}/please_wait_for_game_end" 34 | STARTSCRIPT_FILE="${LOGIN_DIR}/cgos.start.sh" 35 | STOPSCRIPT_FILE="${LOGIN_DIR}/cgos.stop.sh" 36 | KILLSCRIPT_FILE="${LOGIN_DIR}/cgos.kill.sh" 37 | CONFIGGTP_FILE="${LOGIN_DIR}/config.gtp" 38 | 39 | DATE=`date "+%FT%T"` 40 | LOG_FILE="${LOGIN_DIR}/${DATE}.log" 41 | 42 | # CGOS configuration setup 43 | 44 | CGOS_CONFIG=" 45 | %section server 46 | server cgos.boardspace.net 47 | port 6867 48 | 49 | %section player 50 | name ${LOGIN} 51 | password ${PASSWORD} 52 | invoke ${THIS_DIR}/../bin/engine \"gtpfile ${CONFIGGTP_FILE}\" gtp 53 | priority 10 54 | " 55 | 56 | # Magic scripts 57 | 58 | STARTSCRIPT=" 59 | ${THIS_DIR}/client/cgosGtp.tcl \\ 60 | -c \"${CGOS_CONFIG_FILE}\" \\ 61 | -k \"${PLEASE_WAIT_FILE}\" \\ 62 | | tee \"${LOG_FILE}\" && 63 | rm -f \"${PLEASE_WAIT_FILE}\" && 64 | echo \"CGOS session on login ${LOGIN} finished properly.\" 65 | " 66 | 67 | STOPSCRIPT="#!/bin/sh 68 | touch \"${PLEASE_WAIT_FILE}\" 69 | " 70 | 71 | KILLSCRIPT="#!/bin/sh 72 | pkill -f \"cgosGtp.tcl.*${LOGIN_DIR}\" 73 | rm -f \"${PLEASE_WAIT_FILE}\" 74 | " 75 | # Do the job 76 | 77 | mkdir -p "${LOGIN_DIR}" && 78 | cp "${GTP_CONFIG_FILE}" "${CONFIGGTP_FILE}" && 79 | echo "${CGOS_CONFIG}" > "${CGOS_CONFIG_FILE}" && 80 | echo "${STARTSCRIPT}" > "${STARTSCRIPT_FILE}" && 81 | echo "${STOPSCRIPT}" > "${STOPSCRIPT_FILE}" && 82 | echo "${KILLSCRIPT}" > "${KILLSCRIPT_FILE}" && 83 | chmod +x "${STARTSCRIPT_FILE}" && 84 | chmod +x "${STOPSCRIPT_FILE}" && 85 | chmod +x "${KILLSCRIPT_FILE}" 86 | 87 | 88 | -------------------------------------------------------------------------------- /cmakeall: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Defaults. 4 | 5 | SCRIPT_NAME="$(basename "$0")" 6 | SCRIPT_DIR="$(readlink -f $(dirname "$0"))" 7 | 8 | BUILD_TYPE="Release" 9 | INSTALL_PREFIX="${SCRIPT_DIR}" 10 | 11 | # Parse options. 12 | 13 | usage () { 14 | echo "Usage: ${SCRIPT_NAME} [Release | Debug] [install-prefix]" 15 | } 16 | 17 | if test $# -ge 1; then 18 | if test "$1" = "Release"; then 19 | BUILD_TYPE="Release" 20 | shift 21 | elif test "$1" = "Debug"; then 22 | BUILD_TYPE="Debug" 23 | shift 24 | else 25 | echo "Bad build type: \"$1\"" 26 | usage 27 | exit 1 28 | fi 29 | fi 30 | 31 | if test $# -ge 1; then 32 | INSTALL_PREFIX="$(readlink -f $1)" 33 | if test -z ${INSTALL_PREFIX}; then 34 | echo "Wrong install-prefix: \"$1\"" 35 | usage 36 | exit 1 37 | fi 38 | shift 39 | fi 40 | 41 | # Do the actual work. 42 | 43 | echo "Build type: $BUILD_TYPE" 44 | echo "Install prefix: $INSTALL_PREFIX" 45 | echo 46 | 47 | cd "${SCRIPT_DIR}" 48 | mkdir -p "build/${BUILD_TYPE}" 49 | cd "build/${BUILD_TYPE}" 50 | 51 | cmake -D "CMAKE_BUILD_TYPE=${BUILD_TYPE}" \ 52 | -D "CMAKE_INSTALL_PREFIX=${INSTALL_PREFIX}" \ 53 | "${SCRIPT_DIR}/source" \ 54 | $@ && 55 | 56 | make -j2 all install 57 | -------------------------------------------------------------------------------- /regression/board_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ROOT="$(readlink -f $(dirname "$0"))/.." 3 | 4 | if test $# -eq 0; then 5 | "${ROOT}/bin/engine" "board_test" 6 | elif test $# -eq 1; then 7 | "${ROOT}/bin/engine" "board_test 1" 2> "${ROOT}/regression/board_test.txt" 8 | else 9 | echo "fail" 10 | exit 1 11 | fi 12 | -------------------------------------------------------------------------------- /source/.unused/distributed_twogtp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set_cxx_flags (FALSE) 2 | 3 | # ----------------------------------------------------------------------------- 4 | # Qt 5 | 6 | find_package (Qt4) 7 | 8 | if (NOT QT_FOUND) 9 | message("\nWarning: Qt4 not found, d2g will not be build.\n") 10 | return() 11 | endif() 12 | 13 | set (QT_USE_QTSQL 1) 14 | set (QT_USE_QTNETWORK 1) 15 | set (QT_DONT_USE_QTGUI 1) 16 | include (${QT_USE_FILE}) 17 | 18 | include_directories (${QT_INCLUDE_DIRS}) 19 | link_directories (${QT_LIBRARY_DIRS}) 20 | 21 | # ----------------------------------------------------------------------------- 22 | # my libs 23 | 24 | # IMPROVE: utils should be imported automatically from libego 25 | include_directories (${libego_SOURCE_DIR}/utils) 26 | link_directories (${libego_BINARY_DIR}/utils) 27 | 28 | include_directories (${libego_SOURCE_DIR}/libego) 29 | link_directories (${libego_BINARY_DIR}/libego) 30 | 31 | include_directories (${libego_SOURCE_DIR}/libgtp) 32 | link_directories (${libego_BINARY_DIR}/libgtp) 33 | 34 | # ----------------------------------------------------------------------------- 35 | # Remi's BAST optimizer 36 | 37 | add_subdirectory (remi) 38 | include_directories (remi) 39 | link_directories (remi) 40 | 41 | 42 | # ----------------------------------------------------------------------------- 43 | # d2g-worker 44 | 45 | add_executable (d2g-worker 46 | d2g-worker.cpp database.cpp gtp_process.cpp worker.cpp) 47 | 48 | target_link_libraries (d2g-worker utils ego gtp remi ${QT_LIBRARIES}) 49 | install (TARGETS d2g-worker ${INSTALL_TARGETS_DEFAULT_ARGS}) 50 | 51 | # ----------------------------------------------------------------------------- 52 | # d2g-admin 53 | 54 | add_executable (d2g-admin 55 | d2g-admin.cpp database.cpp gtp_process.cpp admin.cpp) 56 | 57 | target_link_libraries (d2g-admin utils ego gtp remi ${QT_LIBRARIES}) 58 | install (TARGETS d2g-admin ${INSTALL_TARGETS_DEFAULT_ARGS}) 59 | 60 | -------------------------------------------------------------------------------- /source/.unused/distributed_twogtp/admin.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ADMIN_HPP_ 2 | #define ADMIN_HPP_ 3 | 4 | #include "database.hpp" 5 | #include "gtp.hpp" 6 | 7 | class Admin { 8 | public: 9 | Admin (Database& db); 10 | ~Admin (); 11 | void Run (); 12 | 13 | private: 14 | void CAddGameSetup (Gtp::Io& io); 15 | void CAddEngineSearchPath (Gtp::Io& io); 16 | 17 | void CSetEngineCommandLine (Gtp::Io& io); 18 | void CAddEngineConfigLine (Gtp::Io& io); 19 | void CAddEngine (Gtp::Io& io); 20 | 21 | 22 | void CSetExperimentDescription (Gtp::Io& io); 23 | void CSetExperimentEngine (Gtp::Io& io); 24 | void CAddExperimentParam (Gtp::Io& io); 25 | void CAddExperiment (Gtp::Io& io); 26 | 27 | void CCloseAllExperiments (Gtp::Io& io); 28 | 29 | void CAddParam (Gtp::Io& io); 30 | void SetPvBoth (); 31 | void CAddGames (Gtp::Io& io); 32 | void CLoopAddGames (Gtp::Io& io); 33 | 34 | bool AddEngine (QString name, QString config_file, QString command_line); 35 | 36 | void CExtractCsv (Gtp::Io& io); 37 | 38 | private: 39 | Database& db; 40 | 41 | QString config; 42 | QString command_line; 43 | 44 | QString first_engine; 45 | QString second_engine; 46 | 47 | ParamsValues pv_first, pv_second; 48 | 49 | QString experiment_description; 50 | QStringList experiment_params; 51 | 52 | int experiment_id; 53 | // (for_first_engine, param_name) -> list of values 54 | QMap , QList > params; 55 | }; 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /source/.unused/distributed_twogtp/d2g-admin.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "database.hpp" 6 | 7 | #include "admin.hpp" 8 | 9 | int main () { 10 | srand (time (0)); 11 | 12 | Database db; 13 | if (!db.ProcessSettingsFile (QDir::homePath() + "/.my.cnf") || !db.Connect ()) { 14 | return 1; 15 | } 16 | 17 | Admin admin (db); 18 | admin.Run (); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /source/.unused/distributed_twogtp/d2g-worker.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "database.hpp" 6 | 7 | #include "admin.hpp" 8 | #include "worker.hpp" 9 | 10 | void usage (const char* file) { 11 | qWarning () 12 | << "Usage: " << file << " [--worker | --admin]"; 13 | } 14 | 15 | int main (int argc, char** argv) { 16 | srand (time (0)); 17 | 18 | if (argc != 2) { 19 | usage (argv[0]); 20 | return 1; 21 | } 22 | 23 | Database db; 24 | if (!db.ProcessSettingsFile (QDir::homePath() + "/.my.cnf") || !db.Connect ()) { 25 | return 1; 26 | } 27 | 28 | if (QString (argv[1]) == "--admin") { 29 | Admin admin (db); 30 | admin.Run (); 31 | return 0; 32 | } 33 | 34 | if (QString (argv[1]) == "--worker") { 35 | Worker worker (db); 36 | worker.Run (); 37 | return 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /source/.unused/distributed_twogtp/database.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DATABASE_HPP_ 2 | #define DATABASE_HPP_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | typedef QList< QPair > ParamsValues; 10 | 11 | struct GameResult { 12 | int id; 13 | std::vector params; 14 | bool victory; // 1 = win 0 = loss 15 | std::string ToString() const; 16 | }; 17 | 18 | class Database { 19 | public: 20 | Database (); 21 | ~Database (); 22 | 23 | bool ProcessSettingsFile (QString file_name); 24 | bool Connect (); 25 | 26 | // for worker 27 | 28 | bool AddEngine (QString name, 29 | QString command_line, 30 | QVariant gtp_name, 31 | QVariant gtp_version, 32 | QString send_gtp_config); 33 | 34 | bool AddGameSetup (QString name, int board_size, float komi); 35 | 36 | int AddExperiment (QString game_setup_name, 37 | QString first_engine_name, 38 | QString second_engine_name, 39 | QString description, 40 | QStringList experiment_params); 41 | 42 | void CloseAllExperiments (); 43 | 44 | int AddGame (int experiment_id, bool first_is_black, 45 | const ParamsValues& pv_first); 46 | 47 | bool AddGameParam (int game_id, QString name, QString value); 48 | 49 | int GetUnclaimedGameCount (int experiment_id); 50 | 51 | QStringList GetParams (int experiment_id); 52 | 53 | QList GetNewGameResults (int expeiment_id, 54 | QString* last_finished_at, 55 | QStringList params); 56 | 57 | QString settings_file_name; 58 | QSqlDatabase db; 59 | }; 60 | 61 | 62 | class DbEngine { 63 | public: 64 | void Get (QSqlDatabase db, int player_id); 65 | 66 | int id; 67 | QString name; 68 | QString command_line; 69 | QString gtp_name; 70 | QString gtp_version; 71 | QString send_gtp_config; 72 | }; 73 | 74 | class DbGame { 75 | public: 76 | bool GetUnclaimed (QSqlDatabase db); 77 | void Finish (QSqlDatabase db, 78 | bool first_won, 79 | QVariant first_report, 80 | QVariant second_report, 81 | QString sgf); 82 | 83 | int id; 84 | QString rule_set; 85 | int board_size; 86 | float komi; 87 | bool first_is_black; 88 | 89 | DbEngine first; 90 | DbEngine second; 91 | QList > first_params; 92 | }; 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /source/.unused/distributed_twogtp/gtp_process.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "gtp_process.hpp" 9 | 10 | GtpProcess::GtpProcess () { 11 | } 12 | 13 | GtpProcess::~GtpProcess () { 14 | process.close(); 15 | } 16 | 17 | bool GtpProcess::Start (QString name_, 18 | QString command_line_, 19 | int timeout_ms) 20 | { 21 | name = name_; 22 | command_line = command_line_.trimmed(); 23 | 24 | process.start (command_line); 25 | if (!process.waitForStarted (timeout_ms)) { 26 | qDebug () << command_line << " failed to start"; 27 | return false; 28 | } 29 | 30 | if (!BasicCommandsOk ()) { 31 | return false; 32 | } 33 | 34 | return true; 35 | } 36 | 37 | 38 | bool GtpProcess::BasicCommandsOk () { 39 | QString response; 40 | return 41 | Command ("known_command genmove", &response) && response == "true" && 42 | Command ("known_command play", &response) && response == "true" && 43 | // because MoGo fails here 44 | //Command ("known_command boardsize", &response) && response == "true" && 45 | Command ("known_command clear_board", &response) && response == "true" && 46 | Command ("known_command komi", &response) && response == "true"; 47 | } 48 | 49 | 50 | bool GtpProcess::IsRunning () { 51 | return process.state () == QProcess::Running; 52 | } 53 | 54 | QString GtpProcess::Name () const { 55 | return name; 56 | } 57 | 58 | QString GtpProcess::CommandLine () const { 59 | return command_line; 60 | } 61 | 62 | 63 | bool GtpProcess::Command (QString command, QString* response, int timeout_ms) { 64 | if (command.trimmed() == "") return true; 65 | process.write (command.toAscii()); 66 | process.write ("\n"); 67 | 68 | // read chunk 69 | const QString sep = "\n\n"; 70 | 71 | QString chunk; 72 | while (!chunk.contains (sep)) { 73 | if (!process.waitForReadyRead (timeout_ms)) { 74 | qDebug() << "GtpProcess Command timeout on command: " << command; 75 | qDebug() << "Read so far: " << chunk; 76 | return false; 77 | } 78 | chunk += process.readAll(); 79 | } 80 | 81 | if (chunk.count (sep) != 1 || !chunk.endsWith (sep) || chunk[0] != '=') { 82 | CHECK (chunk[0] == '?'); 83 | qDebug() << "Command: " << command << " failed"; 84 | return false; 85 | } 86 | 87 | chunk[0] = ' '; 88 | if (response != NULL) *response = chunk.trimmed(); 89 | return true; 90 | } 91 | 92 | QVariant GtpProcess::TryCommand (QString command) { 93 | QString ret = ""; 94 | if (!Command (command, &ret)) { 95 | return QVariant(); 96 | } 97 | return ret; 98 | } 99 | 100 | bool GtpProcess::ClearBoard (uint board_size, float komi) { 101 | return 102 | Command ("boardsize " + QString::number (board_size), NULL) && 103 | Command ("komi " + QString::number (komi), NULL) && 104 | Command ("clear_board", NULL); 105 | } 106 | 107 | bool GtpProcess::Play (Move m) { 108 | return Command ("play " + QString::fromStdString(m.ToGtpString()), NULL); 109 | } 110 | 111 | bool GtpProcess::Genmove (Player pl, Vertex* v, int timeout_ms) { 112 | QString response; 113 | QString pl_str = pl.ToGtpString().c_str(); 114 | if (!Command ("genmove " + pl_str, &response, timeout_ms)) return false; 115 | *v = Vertex::OfGtpString (response.toStdString()); 116 | return true; 117 | } 118 | 119 | bool GtpProcess::Quit () { 120 | if (!Command ("quit", NULL)) return false; 121 | if (!process.waitForFinished (1000)) { 122 | process.close(); 123 | } 124 | return true; 125 | } 126 | -------------------------------------------------------------------------------- /source/.unused/distributed_twogtp/gtp_process.hpp: -------------------------------------------------------------------------------- 1 | #ifndef GTP_PROCESS_H_ 2 | #define GTP_PROCESS_H_ 3 | 4 | #include 5 | #include 6 | #include "player.hpp" 7 | #include "vertex.hpp" 8 | #include "move.hpp" 9 | 10 | 11 | class GtpProcess { 12 | public: 13 | GtpProcess (); 14 | ~GtpProcess (); 15 | 16 | bool Start (QString name, 17 | QString command_line, 18 | int timeout_ms = 60000); 19 | 20 | bool IsRunning (); 21 | 22 | QString Name () const; 23 | QString CommandLine () const; 24 | 25 | bool ClearBoard (uint board_size, float komi); 26 | bool Play (Move); 27 | bool Genmove (Player, Vertex*, int timeout_ms); 28 | bool Quit (); 29 | 30 | QVariant TryCommand (QString command); 31 | 32 | private: 33 | bool Command (QString command, QString* response, int timeout_ms = 60000); 34 | bool BasicCommandsOk (); 35 | 36 | private: 37 | QProcess process; 38 | QString name; 39 | QString command_line; 40 | }; 41 | 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /source/.unused/distributed_twogtp/remi/CBAST.cpp: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // CBAST.cpp 4 | // 5 | // Rémi Coulom 6 | // 7 | // April, 2009 8 | // 9 | ///////////////////////////////////////////////////////////////////////////// 10 | #include "CBAST.h" 11 | 12 | #include 13 | #include 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | // Constructor 17 | ///////////////////////////////////////////////////////////////////////////// 18 | CBAST::CBAST(int DimensionsInit, double ExplorationInit): 19 | area(DimensionsInit), 20 | Dimensions(DimensionsInit), 21 | Exploration(ExplorationInit), 22 | pnodeRoot(0) 23 | { 24 | OnReset(); 25 | } 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | // NextSample 29 | ///////////////////////////////////////////////////////////////////////////// 30 | const std::vector &CBAST::NextSample(int i) 31 | { 32 | CNode *pnode = pnodeRoot; 33 | area.Reset(); 34 | 35 | while (true) 36 | { 37 | if (pnode->outcome == CResults::Unknown) 38 | { 39 | pnode->outcome = CResults::InProgress; 40 | mInProgress[i] = pnode; 41 | const std::vector &v = area.vCenter; 42 | 43 | do 44 | { 45 | pnode->Games++; 46 | pnode = pnode->pnodeParent; 47 | } 48 | while (pnode); 49 | 50 | return v; 51 | } 52 | 53 | if (!pnode->tpnodeChild[0]) 54 | { 55 | pnode->CreateChildren(); 56 | pnode = area.Follow(*pnode, 1); 57 | continue; 58 | } 59 | 60 | double LogT = std::log(double(pnode->Games)) * 0.5; 61 | 62 | double v0 = pnode->tpnodeChild[0]->Victories + 1; 63 | double n0 = pnode->tpnodeChild[0]->Games + 1; 64 | double v1 = pnode->tpnodeChild[1]->Victories + 1; 65 | double n1 = pnode->tpnodeChild[1]->Games + 1; 66 | 67 | if (n1 * (v0 + Exploration * std::sqrt(LogT * n0)) > 68 | n0 * (v1 + Exploration * std::sqrt(LogT * n1))) 69 | pnode = area.Follow(*pnode, 0); 70 | else 71 | pnode = area.Follow(*pnode, 1); 72 | } 73 | } 74 | 75 | ///////////////////////////////////////////////////////////////////////////// 76 | // MaxParameter 77 | ///////////////////////////////////////////////////////////////////////////// 78 | bool CBAST::MaxParameter(std::vector &vMax) const 79 | { 80 | CNode *pnode = pnodeRoot; 81 | area.Reset(); 82 | 83 | while (pnode->Victories && 84 | pnode->tpnodeChild[0] && 85 | pnode->tpnodeChild[0]->Games && 86 | pnode->tpnodeChild[1]->Games && 87 | (pnode->tpnodeChild[0]->Victories + pnode->tpnodeChild[1]->Victories)) 88 | { 89 | int v0 = pnode->tpnodeChild[0]->Victories; 90 | int n0 = pnode->tpnodeChild[0]->Games; 91 | int v1 = pnode->tpnodeChild[1]->Victories; 92 | int n1 = pnode->tpnodeChild[1]->Games; 93 | 94 | if (v0 * n1 > v1 * n0) 95 | pnode = area.Follow(*pnode, 0); 96 | else 97 | pnode = area.Follow(*pnode, 1); 98 | } 99 | 100 | vMax = area.vCenter; 101 | 102 | return true; 103 | } 104 | 105 | ///////////////////////////////////////////////////////////////////////////// 106 | // OnOutcome 107 | ///////////////////////////////////////////////////////////////////////////// 108 | void CBAST::OnOutcome(CResults::Outcome outcome, int i) 109 | { 110 | std::map::iterator mi = mInProgress.find(i); 111 | assert(mi != mInProgress.end()); 112 | CNode *pnode = mi->second; 113 | assert(pnode->outcome == CResults::InProgress); 114 | mInProgress.erase(mi); 115 | 116 | pnode->outcome = outcome; 117 | 118 | if (outcome == CResults::Win) 119 | do 120 | { 121 | pnode->Victories++; 122 | pnode = pnode->pnodeParent; 123 | } 124 | while (pnode); 125 | } 126 | 127 | ///////////////////////////////////////////////////////////////////////////// 128 | // OnReset() 129 | ///////////////////////////////////////////////////////////////////////////// 130 | void CBAST::OnReset() 131 | { 132 | if (pnodeRoot) 133 | delete pnodeRoot; 134 | 135 | pnodeRoot = new CNode(); 136 | pnodeRoot->Depth = 0; 137 | pnodeRoot->pnodeParent = 0; 138 | pnodeRoot->outcome = CResults::InProgress; 139 | 140 | mInProgress.clear(); 141 | } 142 | 143 | ///////////////////////////////////////////////////////////////////////////// 144 | // CNode constructor 145 | ///////////////////////////////////////////////////////////////////////////// 146 | CBAST::CNode::CNode(): 147 | outcome(CResults::Unknown), 148 | Games(0), 149 | Victories(0) 150 | { 151 | tpnodeChild[0] = 0; 152 | tpnodeChild[1] = 0; 153 | } 154 | 155 | ///////////////////////////////////////////////////////////////////////////// 156 | // CNode destructor 157 | ///////////////////////////////////////////////////////////////////////////// 158 | CBAST::CNode::~CNode() 159 | { 160 | for (int i = 2; --i >= 0;) 161 | if (tpnodeChild[i]) 162 | delete tpnodeChild[i]; 163 | } 164 | 165 | ///////////////////////////////////////////////////////////////////////////// 166 | // Create node children 167 | ///////////////////////////////////////////////////////////////////////////// 168 | void CBAST::CNode::CreateChildren() 169 | { 170 | for (int i = 2; --i >= 0;) 171 | { 172 | CNode &node = *new CNode(); 173 | tpnodeChild[i] = &node; 174 | node.pnodeParent = this; 175 | node.Depth = Depth + 1; 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /source/.unused/distributed_twogtp/remi/CBAST.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // CBAST.h 4 | // 5 | // Rémi Coulom 6 | // 7 | // April, 2009 8 | // 9 | ///////////////////////////////////////////////////////////////////////////// 10 | #ifndef CBAST_Declared 11 | #define CBAST_Declared 12 | 13 | #include 14 | #include 15 | 16 | class CResults // results 17 | { 18 | public: //////////////////////////////////////////////////////////////////// 19 | enum Outcome {Loss = 0, Win = 1, Unknown = 2, InProgress = 3}; 20 | }; 21 | 22 | class CBAST 23 | { 24 | private: /////////////////////////////////////////////////////////////////// 25 | struct CNode // node 26 | { 27 | CNode *tpnodeChild[2]; 28 | CNode *pnodeParent; 29 | int Depth; 30 | 31 | CResults::Outcome outcome; 32 | 33 | int Games; 34 | int Victories; 35 | 36 | CNode(); 37 | ~CNode(); 38 | 39 | void CreateChildren(); 40 | }; 41 | 42 | private: /////////////////////////////////////////////////////////////////// 43 | mutable struct CArea 44 | { 45 | std::vector vCenter; 46 | std::vector vRadius; 47 | 48 | CArea(int n): vCenter(n), vRadius(n) {Reset();} 49 | 50 | void Reset() 51 | { 52 | for (int i = vCenter.size(); --i >= 0;) 53 | { 54 | vCenter[i] = 0.0; 55 | vRadius[i] = 1.0; 56 | } 57 | } 58 | 59 | CNode *Follow(const CNode &node, int i) 60 | { 61 | const int Dim = node.Depth % vCenter.size(); 62 | vRadius[Dim] *= 0.5; 63 | vCenter[Dim] += vRadius[Dim] * (2 * i - 1); 64 | return node.tpnodeChild[i]; 65 | } 66 | } area; 67 | 68 | private: /////////////////////////////////////////////////////////////////// 69 | const int Dimensions; 70 | const double Exploration; 71 | 72 | CNode *pnodeRoot; 73 | std::map mInProgress; 74 | 75 | public: //////////////////////////////////////////////////////////////////// 76 | CBAST(int DimensionsInit, double ExplorationInit = 1.0); 77 | 78 | const std::vector &NextSample(int i); 79 | bool MaxParameter(std::vector &vMax) const; 80 | void OnOutcome(CResults::Outcome outcome, int i); 81 | void OnReset(); 82 | }; 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /source/.unused/distributed_twogtp/remi/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set_cxx_flags (FALSE) 2 | 3 | add_library(remi CBAST.cpp) 4 | -------------------------------------------------------------------------------- /source/.unused/distributed_twogtp/worker.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "test.hpp" 6 | #include "full_board.hpp" 7 | #include "gtp_process.hpp" 8 | #include "database.hpp" 9 | 10 | #include "worker.hpp" 11 | 12 | Worker::Worker (Database& db) : db (db) 13 | { 14 | } 15 | 16 | 17 | Worker::~Worker () 18 | { 19 | } 20 | 21 | 22 | void Worker::Run () 23 | { 24 | while (true) { 25 | if (!GrabJob()) { 26 | qWarning() << "Waiting for job ..."; 27 | sleep (30); 28 | continue; 29 | } 30 | } 31 | } 32 | 33 | void StartPlayer (GtpProcess& p, DbGame& db_game, bool first) { 34 | DbEngine& db_player = first ? db_game.first : db_game.second; 35 | //QString& config = black ? db_game.black_gtp_config : db_game.white_gtp_config; 36 | 37 | qDebug() << "---------------------------------------------------------"; 38 | qDebug() << "STARTING " << (first ? "FIRST: " : "SECOND: "); 39 | qDebug() << db_player.name.toLatin1().data(); 40 | qDebug() << "command_line:" << db_player.command_line.trimmed().toLatin1().data(); 41 | 42 | CHECK (p.Start (db_player.name, db_player.command_line)); 43 | CHECK (p.TryCommand ("name").toString () == db_player.gtp_name); 44 | CHECK (p.TryCommand ("version").toString () == db_player.gtp_version); 45 | p.TryCommand ("go_rules " + db_game.rule_set); 46 | 47 | qDebug () << "engine.send_gtp_config:"; 48 | foreach (QString line, db_player.send_gtp_config.split ("\n")) { 49 | qDebug () << " " << line.toLatin1().data(); 50 | CHECK (!p.TryCommand (line).isNull()); 51 | } 52 | 53 | if (first) 54 | { 55 | CHECK (p.TryCommand ("known_command d2gtp-params") == "true"); 56 | QPair param; 57 | foreach (param, db_game.first_params) { 58 | QString cmd = "d2gtp-params " + param.first + " " + param.second; 59 | qDebug () << cmd.toLatin1().data(); 60 | CHECK (p.TryCommand (cmd) != QVariant()); 61 | } 62 | } 63 | 64 | CHECK (p.ClearBoard (db_game.board_size, db_game.komi)); 65 | } 66 | 67 | 68 | const int genmove_timeout_ms = 600000; 69 | 70 | bool Worker::GrabJob () 71 | { 72 | // claim job 73 | if (!db_game.GetUnclaimed (db.db)) return false; 74 | 75 | // do the work 76 | GtpProcess first; 77 | GtpProcess second; 78 | 79 | StartPlayer (first, db_game, true); 80 | StartPlayer (second, db_game, false); 81 | 82 | // TODO send seed 83 | 84 | board.Clear (); 85 | GtpProcess* act = &first; 86 | GtpProcess* other = &second; 87 | if (!db_game.first_is_black) qSwap (act, other); 88 | 89 | vector history; 90 | bool first_won; 91 | Player act_player = Player::Black(); 92 | bool by_resignation; 93 | 94 | while (true) { 95 | Vertex v; 96 | CHECK (act->Genmove (act_player, &v, genmove_timeout_ms)); 97 | 98 | if (v == Vertex::Invalid ()) { // resignation 99 | first_won = (other == &first); 100 | qDebug() << "Player " << act_player.ToGtpString().c_str() 101 | << " (" << act->Name() << ") resigned."; 102 | by_resignation = true; 103 | break; 104 | } 105 | 106 | Move move = Move (act_player, v); 107 | history.push_back (move); 108 | 109 | CHECK (board.Play (move)); 110 | 111 | qDebug() << board.GetBoard ().ToAsciiArt (move.GetVertex()).c_str() 112 | << move.ToGtpString().c_str() 113 | << " (" << act->Name().toLatin1().data() << ")\n"; 114 | 115 | CHECK (other->Play (move)); 116 | 117 | if (board.GetBoard().BothPlayerPass()) { 118 | Player winner = board.GetBoard().TrompTaylorWinner(); 119 | first_won = (winner == Player::Black ()) == db_game.first_is_black; 120 | qDebug() << "Both player pass. Winner is " 121 | << QString::fromStdString (winner.ToGtpString()) << endl; 122 | break; 123 | } 124 | 125 | act_player = act_player.Other (); 126 | qSwap (act, other); 127 | } 128 | 129 | qDebug () << (first_won ? "First" : "Second") << " player won. \n\n" ; 130 | 131 | // update finish 132 | QString sgf = ""; 133 | 134 | db_game.Finish (db.db, 135 | first_won, 136 | first.TryCommand ("game_report"), 137 | second.TryCommand ("game_report"), 138 | sgf); 139 | 140 | return true; 141 | } 142 | 143 | -------------------------------------------------------------------------------- /source/.unused/distributed_twogtp/worker.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WORKER_HPP_ 2 | #define WORKER_HPP_ 3 | 4 | #include "database.hpp" 5 | #include "full_board.hpp" 6 | 7 | class Worker { 8 | public: 9 | Worker (Database& db); 10 | ~Worker (); 11 | void Run (); 12 | 13 | private: 14 | bool ConnectDatabase (); 15 | bool GrabJob (); 16 | 17 | private: 18 | Database& db; 19 | DbGame db_game; 20 | FullBoard board; 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /source/.unused/experiments.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ 2 | * * 3 | * This file is part of Library of Effective GO routines - EGO library * 4 | * * 5 | * Copyright 2006 and onwards, Lukasz Lew * 6 | * * 7 | * EGO library is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 2 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | * EGO library is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 | * GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with EGO library; if not, write to the Free Software * 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, * 20 | * Boston, MA 02110-1301 USA * 21 | * * 22 | \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 23 | 24 | // ---------------------------------------------------------------------- 25 | 26 | class AafStats { 27 | public: 28 | Stat unconditional; 29 | NatMap given_move; 30 | 31 | AafStats () : given_move (Stat()) { 32 | } 33 | 34 | void reset (float prior = 1.0) { 35 | unconditional.reset (prior, 0.0); 36 | ForEachNat (Move, m) 37 | given_move [m].reset (prior, 0.0); 38 | } 39 | 40 | void update (Move* move_history, uint move_count, float score) { 41 | unconditional.update (score); 42 | rep (ii, move_count) 43 | given_move [move_history [ii]].update (score); 44 | } 45 | 46 | float norm_mean_given_move (const Move& m) { 47 | return given_move[m].mean () - unconditional.mean (); // ineffective in loop 48 | } 49 | }; 50 | 51 | // ---------------------------------------------------------------------- 52 | 53 | class AllAsFirst { 54 | public: 55 | FastRandom random; 56 | Board* board; 57 | AafStats aaf_stats; 58 | uint playout_no; 59 | float aaf_fraction; 60 | float influence_scale; 61 | float prior; 62 | bool progress_dots; 63 | 64 | public: 65 | AllAsFirst (Gtp::ReplWithGogui& gtp, Board& board_) 66 | : random (123), board (&board_) 67 | { 68 | playout_no = 50000; 69 | aaf_fraction = 0.5; 70 | influence_scale = 6.0; 71 | prior = 1.0; 72 | progress_dots = false; 73 | 74 | gtp.RegisterGfx ("AAF.move_value", "black", this, &AllAsFirst::CMoveValue); 75 | gtp.RegisterGfx ("AAF.move_value", "white", this, &AllAsFirst::CMoveValue); 76 | 77 | gtp.RegisterParam ("AAF.params", "prior", &prior); 78 | gtp.RegisterParam ("AAF.params", "aaf_fraction", &aaf_fraction); 79 | gtp.RegisterParam ("AAF.params", "influence_scale", &influence_scale); 80 | gtp.RegisterParam ("AAF.params", "playout_number", &playout_no); 81 | gtp.RegisterParam ("AAF.params", "20_progress_dots", &progress_dots); 82 | } 83 | 84 | void do_playout (const Board* base_board) { 85 | Board mc_board; 86 | mc_board.Load (*base_board); 87 | 88 | FastStack history; 89 | 90 | if (!DoLightPlayout (mc_board, random, history)) return; 91 | 92 | uint aaf_move_count = uint (float(history.Size())*aaf_fraction); 93 | float score = mc_board.PlayoutScore (); 94 | 95 | aaf_stats.update (history.Data(), aaf_move_count, score); 96 | } 97 | 98 | void CMoveValue (Gtp::Io& io) { 99 | Player player = io.Read (); 100 | io.CheckEmpty (); 101 | 102 | aaf_stats.reset (prior); 103 | rep (ii, playout_no) { 104 | if (progress_dots && (ii * 20) % playout_no == 0) cerr << "." << flush; 105 | do_playout (board); 106 | } 107 | if (progress_dots) cerr << endl; 108 | 109 | Gtp::GoguiGfx gfx; 110 | 111 | ForEachNat (Vertex, v) { 112 | if (board->ColorAt (v) == Color::Empty ()) { 113 | gfx.SetInfluence(v.ToGtpString (), 114 | aaf_stats.norm_mean_given_move (Move(player, v)) / 115 | influence_scale 116 | ); 117 | } 118 | } 119 | 120 | gfx.Report (io); 121 | } 122 | }; 123 | -------------------------------------------------------------------------------- /source/.unused/fast_pool.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #ifndef FAST_POOL_H_ 6 | #define FAST_POOL_H_ 7 | 8 | #include "utils.hpp" 9 | #include "fast_stack.hpp" 10 | 11 | template 12 | class FastPool { 13 | public: 14 | 15 | FastPool () { 16 | memory = new Elt[size]; 17 | free_elts = new FreeEltsStack; 18 | Reset (); 19 | } 20 | 21 | ~FastPool () { 22 | delete [] memory; 23 | delete free_elts; 24 | } 25 | 26 | void Reset() { 27 | free_elts->Clear(); // TODO tu skonczylem 28 | rep (i, size) { 29 | free_elts->Push (memory + i); 30 | } 31 | } 32 | 33 | Elt* Alloc () { 34 | return new (free_elts->PopTop ()) Elt; 35 | } 36 | 37 | void Free (Elt* elt) { 38 | elt-~Elt(); 39 | free_elts->Push (elt); 40 | } 41 | 42 | private: 43 | 44 | typedef FastStack FreeEltsStack; 45 | 46 | private: 47 | Elt* memory; 48 | FreeEltsStack* free_elts; 49 | }; 50 | 51 | // TODO make fast_pool-inl.h 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /source/.unused/sgf.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SGF_H_ 2 | #define SGF_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "vertex.hpp" 9 | #include "color.hpp" 10 | 11 | using namespace std; 12 | 13 | extern const string embedded_gtp_tag; 14 | 15 | class SgfNodeProperties { 16 | public: 17 | map > property_map; 18 | 19 | void add (string name, string value); 20 | string to_sgf_string (); 21 | string get_comment (); 22 | void set_comment (string comment); 23 | string get_embedded_gtp (); 24 | list get_vertices_to_play (Color color); 25 | list get_vertices_to_clear (); 26 | 27 | list get_vertices_to_play (Player pl); 28 | string get_single_property (string prop_name, string default_value = ""); 29 | uint get_board_size (); 30 | float get_komi (); 31 | }; 32 | 33 | 34 | class SgfNode { 35 | public: 36 | list children; 37 | SgfNodeProperties properties; 38 | 39 | SgfNode* add_child (); 40 | string to_sgf_string (bool print_braces = true); 41 | }; 42 | 43 | 44 | class SgfTree { 45 | SgfNode* root; 46 | 47 | public: 48 | 49 | SgfTree (); 50 | ~SgfTree (); 51 | bool parse_property_value (istream& in, string& prop_value); 52 | 53 | // constructor 54 | bool parse_sgf (istream& in); 55 | string to_sgf_string (); 56 | bool save_to_file (const string& file_name); 57 | bool load_from_file (const string& file_name); 58 | bool is_loaded (); 59 | SgfNode* game_node (); 60 | SgfNodeProperties& properties (); 61 | }; 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /source/.unused/sgf_gtp.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ 2 | * * 3 | * This file is part of Library of Effective GO routines - EGO library * 4 | * * 5 | * Copyright 2006 and onwards, Lukasz Lew * 6 | * * 7 | * EGO library is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 2 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | * EGO library is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 | * GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with EGO library; if not, write to the Free Software * 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, * 20 | * Boston, MA 02110-1301 USA * 21 | * * 22 | \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 23 | 24 | 25 | #include "sgf_gtp.hpp" 26 | 27 | #include "testing.hpp" 28 | 29 | // class gtp_sgf 30 | 31 | SgfGtp::SgfGtp (Gtp::Repl& _gtp, SgfTree& _sgf_tree, FullBoard& _base_board) : 32 | sgf_tree (_sgf_tree), gtp (_gtp), base_board (_base_board) 33 | { 34 | gtp.Register ("sgf.load", this, &SgfGtp::CLoad); 35 | gtp.Register ("sgf.save", this, &SgfGtp::CSave); 36 | gtp.Register ("sgf.gtp.exec", this, &SgfGtp::CGtpExec); 37 | } 38 | 39 | 40 | void SgfGtp::CLoad (Gtp::Io& io) { 41 | string file_name = io.Read (); 42 | io.CheckEmpty(); 43 | 44 | if (!sgf_tree.load_from_file(file_name)) { 45 | io.SetError ("file not found or invalid SGF: " + file_name); 46 | return; 47 | } 48 | } 49 | 50 | void SgfGtp::CSave (Gtp::Io& io) { 51 | string file_name = io.Read (); 52 | io.CheckEmpty(); 53 | if (!sgf_tree.save_to_file(file_name)) { 54 | io.SetError ("file cound not be created: " + file_name); 55 | return; 56 | } 57 | } 58 | 59 | void SgfGtp::CGtpExec (Gtp::Io& io) { 60 | io.CheckEmpty(); 61 | if (!sgf_tree.is_loaded ()) { 62 | io.SetError ("SGF file not loaded"); 63 | return; 64 | } 65 | 66 | if (sgf_tree.properties ().get_board_size () != board_size) { 67 | io.SetError ("invalid board size"); 68 | return; 69 | } 70 | 71 | FullBoard save_board; 72 | save_board.Load (&base_board); 73 | 74 | base_board.clear (); 75 | base_board.SetKomi (sgf_tree.properties ().get_komi ()); 76 | ostringstream response; 77 | exec_embedded_gtp_rec (sgf_tree.game_node (), response); 78 | 79 | base_board.Load (&save_board); 80 | 81 | io.out << response.str (); 82 | } 83 | 84 | // It goes through a whole sgf and executes GTP commends embedded in SGF comments. 85 | // if you put "@gtp" in comment, everything below is an embedded gtp command. 86 | 87 | void SgfGtp::exec_embedded_gtp_rec (SgfNode* current_node, ostream& response) { 88 | // update position 89 | list vertex_list; 90 | vertex_list = current_node->properties.get_vertices_to_play (Color::Empty ()); 91 | if (vertex_list.empty () == false) { 92 | response << "sgf.gtp.exec: AE property in SGF not implemented" << endl; 93 | return; 94 | } 95 | 96 | player_for_each (pl) { 97 | vertex_list = current_node->properties.get_vertices_to_play (pl); 98 | for (list::iterator vi = vertex_list.begin(); 99 | vi != vertex_list.end(); 100 | vi++) { 101 | if (base_board.try_play (pl, *vi) == false) { 102 | response << "sgf.gtp.exec: bad move in SGF: " << pl << " " << *vi << endl; 103 | return; 104 | } 105 | } 106 | } 107 | 108 | 109 | // process gtp 110 | istringstream embedded_gtp (current_node->properties.get_embedded_gtp ()); 111 | ostringstream embedded_response; 112 | gtp.Run (embedded_gtp, embedded_response); // TODO add command logging 113 | // TODO make gtp filter out double newlines 114 | current_node->properties.set_comment (embedded_response.str ()); 115 | 116 | // save board 117 | FullBoard node_board; 118 | node_board.Load (&base_board); 119 | 120 | // recursove call 121 | for (list::iterator child = current_node->children.begin(); 122 | child != current_node->children.end(); 123 | child++) { 124 | base_board.Load (&node_board); 125 | exec_embedded_gtp_rec (&(*child), response); 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /source/.unused/sgf_gtp.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SGF_GTP_H_ 2 | #define SGF_GTP_H_ 3 | 4 | #include "full_board.hpp" 5 | #include "sgf.hpp" 6 | #include "gtp.hpp" 7 | 8 | class SgfGtp { 9 | public: 10 | SgfGtp (Gtp::Repl& _gtp, SgfTree& _sgf_tree, FullBoard& _base_board); 11 | virtual ~SgfGtp () {} 12 | void exec_embedded_gtp_rec (SgfNode* current_node, ostream& response); 13 | 14 | private: 15 | void CLoad (Gtp::Io& io); 16 | void CSave (Gtp::Io& io); 17 | void CGtpExec (Gtp::Io& io); 18 | 19 | SgfTree& sgf_tree; 20 | Gtp::Repl& gtp; 21 | FullBoard& base_board; 22 | }; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /source/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project (libego) 3 | 4 | # Import some cmake modules. 5 | 6 | set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules) 7 | 8 | include (CheckCXXCompilerFlag) 9 | 10 | include (EnsureOutOfSourceBuild) 11 | include (EnsureBuildTypeIsChosen) 12 | # include (AddBoostCxxTest) 13 | include (SetDefaultInstallationDirs) 14 | include (SetCxxFlags) 15 | 16 | # Add subdirectories. 17 | 18 | add_subdirectory (utils) 19 | add_subdirectory (gtp) 20 | add_subdirectory (goboard) 21 | add_subdirectory (engine) 22 | add_subdirectory (main) 23 | # add_subdirectory (libgamegui) 24 | # add_subdirectory (gui) 25 | -------------------------------------------------------------------------------- /source/cmake/modules/AddBoostCxxTest.cmake: -------------------------------------------------------------------------------- 1 | enable_testing () 2 | 3 | find_package (Boost COMPONENTS unit_test_framework REQUIRED) 4 | 5 | add_custom_target (check ALL ${CMAKE_CTEST_COMMAND}) 6 | 7 | macro (add_boost_cxx_test name) 8 | link_directories ( ${Boost_LIBRARY_DIRS} ) 9 | include_directories ( ${Boost_INCLUDE_DIRS} ) 10 | 11 | add_executable (${name} ${name}.cpp) 12 | target_link_libraries (${name} ${Boost_LIBRARIES}) 13 | 14 | add_test (${name} ${name}) 15 | add_dependencies (check ${name}) 16 | endmacro (add_boost_cxx_test) 17 | -------------------------------------------------------------------------------- /source/cmake/modules/EnsureBuildTypeIsChosen.cmake: -------------------------------------------------------------------------------- 1 | if(NOT CMAKE_BUILD_TYPE OR NOT CMAKE_BUILD_TYPE MATCHES "Debug|Release") 2 | message( 3 | FATAL_ERROR 4 | "\nChoose the type of build, options are: Debug, Release." 5 | ) 6 | endif(NOT CMAKE_BUILD_TYPE OR NOT CMAKE_BUILD_TYPE MATCHES "Debug|Release") 7 | -------------------------------------------------------------------------------- /source/cmake/modules/EnsureOutOfSourceBuild.cmake: -------------------------------------------------------------------------------- 1 | if ("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}") 2 | message(FATAL_ERROR "Error: In-source builds are not allowed.") 3 | endif ("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}") 4 | -------------------------------------------------------------------------------- /source/cmake/modules/SetCxxFlags.cmake: -------------------------------------------------------------------------------- 1 | macro (set_cxx_flags strong_release_flags) 2 | if(CMAKE_COMPILER_IS_GNUCXX) 3 | 4 | CHECK_CXX_COMPILER_FLAG ("-march=native" GNUCXX_SUPPORTS_MARCH_NATIVE) 5 | CHECK_CXX_COMPILER_FLAG ("-march=i686" GNUCXX_SUPPORTS_MARCH_I686) 6 | 7 | # Set CMAKE_CXX_MARCH_FLAGS 8 | if (GNUCXX_SUPPORTS_MARCH_NATIVE) 9 | set (CMAKE_CXX_MARCH_FLAGS "-march=native") 10 | elseif (GNUCXX_SUPPORTS_MARCH_I686) 11 | set (CMAKE_CXX_MARCH_FLAGS "-march=i686") 12 | else () 13 | message ("Please upgrade your compiler") 14 | set (CMAKE_CXX_MARCH_FLAGS "") 15 | endif() 16 | 17 | set (CMAKE_CXX_FLAGS "-std=c++0x -ggdb3 -Wall -Wextra -Wswitch-enum -Wunused -fshow-column") 18 | 19 | set (STRONG "${strong_release_flags}") 20 | if (STRONG) 21 | set (CMAKE_CXX_FLAGS_RELEASE 22 | "-O3 -fomit-frame-pointer -frename-registers ${CMAKE_CXX_MARCH_FLAGS}") 23 | else() 24 | set (CMAKE_CXX_FLAGS_RELEASE "") 25 | endif() 26 | 27 | set (CMAKE_CXX_FLAGS_DEBUG "-fno-inline -DTESTING") 28 | 29 | else() 30 | 31 | message("${CMAKE_SYSTEM_NAME} detected.") 32 | message ("If it works/not works for you, let us know libego-devel@googlegroups.com") 33 | 34 | endif() 35 | 36 | endmacro (set_cxx_flags) 37 | -------------------------------------------------------------------------------- /source/cmake/modules/SetDefaultInstallationDirs.cmake: -------------------------------------------------------------------------------- 1 | set (INSTALL_TARGETS_DEFAULT_ARGS 2 | RUNTIME DESTINATION bin 3 | LIBRARY DESTINATION lib 4 | ARCHIVE DESTINATION lib) 5 | -------------------------------------------------------------------------------- /source/engine/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set_cxx_flags (TRUE) 2 | 3 | include_directories (${libego_SOURCE_DIR}/utils) 4 | include_directories (${libego_SOURCE_DIR}/goboard) 5 | include_directories (${libego_SOURCE_DIR}/gtp) 6 | 7 | add_library (ai time_control.cpp mcts_tree.cpp param.cpp engine.cpp) 8 | 9 | target_link_libraries (ai ego gtp) 10 | 11 | # install (TARGETS engine ${INSTALL_TARGETS_DEFAULT_ARGS}) 12 | -------------------------------------------------------------------------------- /source/engine/all_hash3x3.hpp: -------------------------------------------------------------------------------- 1 | 2 | struct All2051Hash3x3 { 3 | All2051Hash3x3 () : 4 | empty (), 5 | random(123), 6 | min_hash (Hash3x3::Any ()) 7 | { 8 | gtp.Register ("gen_all_pat", this, &All2051Hash3x3::GtpGenerate); 9 | } 10 | 11 | void GtpGenerate (Gtp::Io& io) { 12 | io.CheckEmpty (); 13 | Generate (5000); 14 | } 15 | 16 | void Generate (uint n) { 17 | NewHashAt (Vertex::OfGtpString("A1")); 18 | NewHashAt (Vertex::OfGtpString("A2")); 19 | NewHashAt (Vertex::OfGtpString("B2")); 20 | 21 | rep (ii, n) { 22 | board.Load (empty); 23 | while (!board.BothPlayerPass ()) { 24 | Player pl = board.ActPlayer (); 25 | Vertex v = board.RandomLightMove (pl, random); 26 | board.PlayLegal (pl, v); 27 | rep (ii, board.Hash3x3ChangedCount ()) { 28 | NewHashAt (board.Hash3x3Changed (ii)); 29 | } 30 | } 31 | } 32 | } 33 | 34 | 35 | void NewHashAt (Vertex v) { 36 | Hash3x3 hash = board.Hash3x3At (v); 37 | if (!hash.IsLegal (Player::Black())) return; 38 | if (min_hash[hash] != Hash3x3::Any()) return; 39 | 40 | Hash3x3 all[8]; 41 | 42 | hash.GetAll8Symmetries (all); 43 | 44 | rep (ii, 8) CHECK (min_hash [all [ii]] == Hash3x3::Any ()); 45 | rep (ii, 8) min_hash [all [ii]] = all [0]; 46 | 47 | unique.push_back (all [0]); 48 | //cerr << "New: " << unique.size() << " " << all [0].ToString() << endl; 49 | } 50 | 51 | const Board empty; 52 | Board board; 53 | FastRandom random; 54 | 55 | vector unique; 56 | NatMap min_hash; 57 | }; 58 | -------------------------------------------------------------------------------- /source/engine/engine.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #ifndef ENGINE_H_ 6 | #define ENGINE_H_ 7 | 8 | #include "to_string.hpp" 9 | #include "gtp_gogui.hpp" 10 | #include "ego.hpp" 11 | #include "time_control.hpp" 12 | #include "mcts_tree.hpp" 13 | 14 | class Engine { 15 | public: 16 | Engine (); 17 | 18 | bool Reset (uint board_size); 19 | void SetKomi (float komi); 20 | bool Play (Move move); 21 | Move Genmove (Player player); 22 | bool Undo (); 23 | 24 | void DoPlayoutMove (); 25 | 26 | const Board& GetBoard () const; 27 | 28 | // Playout functions 29 | Move ChooseBestMove (); 30 | void DoNPlayouts (uint n); 31 | void SyncRoot (); 32 | void PrepareToPlayout (); 33 | void DoOnePlayout (bool use_tree, bool update_tree); 34 | Move ChooseMctsMove (bool* tree_phase); 35 | void PlayMove (Move m); 36 | double Score (bool tree_phase); 37 | 38 | enum InfluenceType { 39 | NoInfluence, 40 | MctsN, 41 | MctsMean, 42 | RaveN, 43 | RaveMean, 44 | Bias, 45 | MctsPolicyMix, 46 | SamplerMoveProb, 47 | PatternGammas, 48 | CompleteGammas, 49 | PlayoutTerritory, 50 | MctsTerritory 51 | }; 52 | 53 | void GetInfluence (InfluenceType type, NatMap & influence); 54 | 55 | std::string GetStringForVertex (Vertex v); 56 | vector LastPlayout (); 57 | 58 | void EnsureAllLegalChildren (MctsNode* node, const Board& board, const Sampler& sampler); 59 | void RemoveIllegalChildren (MctsNode* node, const Board& board); 60 | 61 | private: 62 | void EstimateTerritory (NatMap& influence, bool use_tree); 63 | 64 | TimeControl time_control; 65 | Gammas gammas; 66 | 67 | FastRandom random; 68 | 69 | MctsNode root; 70 | Sampler sampler; 71 | 72 | Board base_board; 73 | MctsNode* base_node; 74 | 75 | Board playout_board; 76 | MctsNode* playout_node; 77 | 78 | vector playout_moves; 79 | MctsTrace trace; 80 | 81 | friend class MctsGtp; 82 | }; 83 | 84 | #endif /* ENGINE_H_ */ 85 | -------------------------------------------------------------------------------- /source/engine/mcts_tree.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MCTS_TREE_ 2 | #define MCTS_TREE_ 3 | 4 | #include 5 | #include "stat.hpp" 6 | #include "gtp.hpp" 7 | 8 | 9 | class MctsNode { 10 | public: 11 | typedef std::list ChildrenList; // TODO vector, allocator? 12 | 13 | // Initialization. 14 | 15 | explicit MctsNode (Player player, Vertex v, double bias); 16 | 17 | void Reset (); 18 | 19 | // Printing. 20 | 21 | string ToString() const; 22 | string GuiString() const; 23 | 24 | string RecToString (float min_visit, uint max_children) const; 25 | 26 | // Children operations. 27 | 28 | void AddChild (const MctsNode& node); 29 | 30 | void RemoveChild (MctsNode* child_ptr); 31 | 32 | bool ReadyToExpand () const; 33 | 34 | // Child finding. 35 | 36 | MctsNode* FindChild (Move m); 37 | 38 | const MctsNode& MostExploredChild (Player pl) const; 39 | 40 | MctsNode& BestRaveChild (Player pl); 41 | 42 | // Other. 43 | 44 | float SubjectiveMean() const; 45 | 46 | float SubjectiveRaveValue (Player pl, float log_val) const; 47 | 48 | public: 49 | 50 | Move GetMove () const; 51 | 52 | Player player; 53 | Vertex v; 54 | NatMap has_all_legal_children; 55 | 56 | Stat stat; 57 | Stat rave_stat; 58 | const double bias; 59 | 60 | void RecPrint (ostream& out, uint depth, float min_visit, uint max_children) const; 61 | 62 | ChildrenList children; 63 | }; 64 | 65 | // ----------------------------------------------------------------------------- 66 | 67 | struct MctsTrace { 68 | public: 69 | 70 | void Reset (MctsNode& node); 71 | void NewMove (Move m); 72 | void NewNode (MctsNode& node); 73 | void UpdateTraceRegular (float score); 74 | void UpdateTraceRave (float score); 75 | 76 | private: 77 | vector nodes; 78 | vector moves; 79 | }; 80 | 81 | // ----------------------------------------------------------------------------- 82 | 83 | struct Mcts { 84 | }; 85 | 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /source/engine/param.cpp: -------------------------------------------------------------------------------- 1 | #include "param.hpp" 2 | 3 | float Param::genmove_playouts = 20000; 4 | bool Param::use_local = false; 5 | 6 | bool Param::tree_use = true; 7 | uint Param::tree_max_moves = 200; 8 | float Param::tree_explore_coeff = 0.0; 9 | bool Param::tree_rave_update = true; 10 | bool Param::tree_rave_use = true; 11 | float Param::tree_stat_bias = 0.0; 12 | float Param::tree_rave_bias = 0.001; 13 | float Param::tree_progressive_bias = 100.0; 14 | float Param::tree_progressive_bias_prior = 1.0; 15 | float Param::tree_rave_update_fraction = 0.75; 16 | 17 | float Param::prior_update_count = 10.0; 18 | float Param::prior_mean = 1.0; 19 | 20 | float Param::mature_update_count = 10.0; 21 | 22 | float Param::resign_mean = -0.90; 23 | -------------------------------------------------------------------------------- /source/engine/param.hpp: -------------------------------------------------------------------------------- 1 | #ifndef GO_PARAM_H 2 | #define GO_PARAM_H 3 | 4 | #include "utils.hpp" 5 | 6 | class Param { 7 | public: 8 | static float genmove_playouts; 9 | static bool use_local; 10 | 11 | static bool tree_use; 12 | static uint tree_max_moves; 13 | static float tree_explore_coeff; 14 | static bool tree_rave_update; 15 | static bool tree_rave_use; 16 | static float tree_stat_bias; 17 | static float tree_rave_bias; 18 | static float tree_progressive_bias; 19 | static float tree_progressive_bias_prior; 20 | static float tree_rave_update_fraction; 21 | 22 | static float prior_update_count; 23 | static float prior_mean; 24 | 25 | static float mature_update_count; 26 | 27 | static float resign_mean; 28 | }; 29 | 30 | #endif /* GO_PARAM_H */ 31 | -------------------------------------------------------------------------------- /source/engine/stat.hpp: -------------------------------------------------------------------------------- 1 | #ifndef STAT_H_ 2 | #define STAT_H_ 3 | 4 | #include 5 | #include "param.hpp" 6 | #include "ego.hpp" 7 | 8 | class Stat { 9 | public: 10 | 11 | Stat () {} // NatMap needs it 12 | 13 | Stat (float prior_count, float prior_mean) { 14 | reset (prior_count, prior_mean); 15 | } 16 | 17 | // TODO better prior initialization 18 | void reset (float prior_count, float prior_mean) { 19 | sample_count = prior_count; 20 | sample_sum = prior_count * prior_mean; 21 | square_sample_sum = prior_count * prior_mean * prior_mean * 2.0; 22 | ucb = 1.0E20; 23 | } 24 | 25 | void update (float sample) { 26 | sample_count += 1.0; 27 | sample_sum += sample; 28 | square_sample_sum += sample * sample; 29 | } 30 | 31 | float update_count () const { 32 | return sample_count; 33 | } 34 | 35 | float mean () const { 36 | return sample_sum / sample_count; 37 | } 38 | 39 | float variance () const { 40 | // VX = E(X^2) - EX ^ 2 41 | float m = mean (); 42 | return square_sample_sum / sample_count - m * m; 43 | } 44 | 45 | float std_dev () const { 46 | return sqrt (variance ()); 47 | } 48 | 49 | float std_err () const { 50 | // TODO assert sample_count 51 | return sqrt (variance () / sample_count); 52 | } 53 | 54 | float precision (float bias = 0.0) const { 55 | return 1.0 / (variance() / update_count () + bias); 56 | } 57 | 58 | void UpdateUcb (Player pl, float explore_coeff) { 59 | ucb = pl.SubjectiveScore (mean()); 60 | ucb += explore_coeff / sqrt (update_count()); 61 | } 62 | 63 | float Ucb () { 64 | return ucb; 65 | } 66 | 67 | static float SlowMix (const Stat& stat1, float b1, const Stat& stat2, float b2) { 68 | return 69 | (stat1.precision(b1) * stat1.mean() + stat2.precision(b2) * stat2.mean()) / 70 | (stat1.precision(b1) + stat2.precision(b2)); 71 | } 72 | 73 | // Optimized SlowMix 74 | static float Mix (const Stat& stat1, float b1, const Stat& stat2, float b2) { 75 | 76 | float n1 = stat1.sample_count; 77 | float n2 = stat2.sample_count; 78 | 79 | float s1 = stat1.sample_sum; 80 | float s2 = stat2.sample_sum; 81 | 82 | float v1 = stat1.square_sample_sum; 83 | float v2 = stat2.square_sample_sum; 84 | 85 | float nn1 = n1 * n1; 86 | float nn2 = n2 * n2; 87 | 88 | float x1 = (v1 + b1*nn1) * n1 - s1 * s1; 89 | float x2 = (v2 + b2*nn2) * n2 - s2 * s2; 90 | 91 | float t1 = nn1 * x2; 92 | float t2 = nn2 * x1; 93 | 94 | float mix = (t1*s1 + t2*s2) / (t1*n1 + t2*n2); 95 | 96 | ASSERT (fabs(mix - SlowMix(stat1, b1, stat2 ,b2)) < 0.00001); 97 | return mix; 98 | } 99 | 100 | 101 | string to_string (float minimal_update_count = 0.0) const { 102 | if (sample_count < minimal_update_count) return " "; 103 | 104 | ostringstream out; 105 | char buf [100]; 106 | sprintf (buf, "%+3.3f(%5.0f)", mean(), update_count()); 107 | out << buf; 108 | return out.str (); 109 | } 110 | 111 | private: 112 | float sample_count; 113 | float sample_sum; 114 | float square_sample_sum; 115 | float ucb; 116 | }; 117 | 118 | // ----------------------------------------------------------------------------- 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /source/engine/time_control.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #include "time_control.hpp" 6 | #include "param.hpp" 7 | #include "gtp_gogui.hpp" 8 | 9 | extern Gtp::ReplWithGogui gtp; 10 | 11 | 12 | TimeControl::TimeControl () : 13 | time_left (0.0), 14 | time_stones (-1), 15 | playouts_per_second (10000) 16 | { 17 | gtp.Register ("time_left", this, &TimeControl::GtpTimeLeft); 18 | } 19 | 20 | uint TimeControl::PlayoutCount (Player player) { 21 | int playouts = Param::genmove_playouts; 22 | if (time_stones [player] == 0 && time_left [player] < 60.0) { 23 | playouts = min (playouts, 24 | int (time_left [player] / 30.0 * playouts_per_second)); 25 | playouts = max (playouts, 1000); 26 | } 27 | return playouts; 28 | } 29 | 30 | void TimeControl::GtpTimeLeft (Gtp::Io& io) { 31 | Player pl = io.Read (); 32 | float seconds = io.Read (); 33 | int stones = io.Read (); 34 | time_left [pl] = seconds; 35 | time_stones [pl] = stones; 36 | } 37 | -------------------------------------------------------------------------------- /source/engine/time_control.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #ifndef TIME_CONTROL_H 6 | #define TIME_CONTROL_H 7 | 8 | #include "utils.hpp" 9 | #include "player.hpp" 10 | #include "gtp_gogui.hpp" 11 | 12 | class TimeControl { 13 | public: 14 | TimeControl (); 15 | uint PlayoutCount (Player player); 16 | void GtpTimeLeft (Gtp::Io& io); 17 | 18 | NatMap time_left; 19 | NatMap time_stones; 20 | float playouts_per_second; 21 | }; 22 | 23 | #endif /* TIME_CONTROL_H */ 24 | -------------------------------------------------------------------------------- /source/goboard/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set_cxx_flags (TRUE) 2 | 3 | # Ensure BOARDSIZE is correct. 4 | 5 | # TODO make automatic configuration file. 6 | 7 | # if(NOT DEFINED BOARDSIZE OR NOT BOARDSIZE MATCHES [0-9]+) 8 | # set (BOARDSIZE 9) 9 | # endif() 10 | 11 | # add_definitions(-DBOARDSIZE=${BOARDSIZE}) 12 | # message("BOARDSIZE = ${BOARDSIZE}") 13 | 14 | # Targets 15 | 16 | include_directories (${libego_SOURCE_DIR}/utils) 17 | add_library(ego ego.cpp) 18 | target_link_libraries (ego utils) 19 | 20 | #TODO install includes as well 21 | #install (TARGETS ego ${INSTALL_TARGETS_DEFAULT_ARGS}) 22 | -------------------------------------------------------------------------------- /source/goboard/benchmark.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #include "benchmark.hpp" 6 | 7 | #include "fast_timer.hpp" 8 | #include "utils.hpp" 9 | 10 | namespace Benchmark { 11 | 12 | uint move_count = 0; 13 | Board empty_board; 14 | Board board; 15 | FastRandom random (123); 16 | Gammas gammas; 17 | Sampler sampler (board, gammas); 18 | 19 | void DoPlayouts (uint playout_cnt, NatMap* win_cnt) { 20 | rep (ii, playout_cnt) { 21 | 22 | board.Load (empty_board); 23 | sampler.NewPlayout (); 24 | 25 | while (!board.BothPlayerPass ()) { 26 | Player pl = board.ActPlayer (); 27 | Vertex v = sampler.SampleMove (random); 28 | //Vertex v = board.RandomLightMove (pl, random); 29 | board.PlayLegal (pl, v); 30 | sampler.MovePlayed (); 31 | } 32 | 33 | (*win_cnt) [board.PlayoutWinner ()] ++; 34 | move_count += board.MoveCount(); 35 | } 36 | } 37 | 38 | string Run (uint playout_cnt) { 39 | NatMap win_cnt (0); 40 | FastTimer fast_timer; 41 | 42 | fast_timer.Reset (); 43 | fast_timer.Start (); 44 | float seconds_begin = ProcessUserTime (); 45 | 46 | DoPlayouts (playout_cnt, &win_cnt); 47 | 48 | float seconds_end = ProcessUserTime (); 49 | fast_timer.Stop (); 50 | 51 | 52 | float seconds_total = seconds_end - seconds_begin; 53 | float cc_per_playout = fast_timer.Ticks () / double (playout_cnt); 54 | float cc_per_move = fast_timer.Ticks () / double (move_count); 55 | float playouts_finished = win_cnt [Player::Black ()] + win_cnt [Player::White ()]; 56 | 57 | ostringstream ret; 58 | ret << endl 59 | << playout_cnt << " playouts in " << seconds_total << " seconds" << endl 60 | << float (playout_cnt) / seconds_total / 1000.0 << " kpps" << endl 61 | << 1000000.0 / cc_per_playout << " kpps/GHz (clock independent)" << endl 62 | << cc_per_move << " CC/move (clock independent)" << endl 63 | << win_cnt [Player::Black ()] << "/" << win_cnt [Player::White ()] 64 | << " (black wins / white wins)" << endl 65 | << "AVG moves/playout = " << move_count / playouts_finished << endl; 66 | 67 | return ret.str(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /source/goboard/benchmark.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #ifndef BENCHMARK_H_ 6 | #define BENCHMARK_H_ 7 | 8 | #include 9 | 10 | #include "board.hpp" 11 | 12 | namespace Benchmark { 13 | string Run (uint playout_cnt); 14 | } 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /source/goboard/color.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #include "color.hpp" 6 | 7 | Color::Color () : Nat () { 8 | } 9 | 10 | Color::Color (uint raw) : Nat (raw) { 11 | } 12 | 13 | Color Color::Black() { 14 | return Color (0); 15 | } 16 | 17 | Color Color::White() { 18 | return Color (1); 19 | } 20 | 21 | Color Color::Empty() { 22 | return Color (2); 23 | } 24 | 25 | Color Color::OffBoard() { 26 | return Color (3); 27 | } 28 | 29 | Color Color::OfPlayer (Player pl) { 30 | return OfRaw (pl.GetRaw ()); 31 | } 32 | 33 | 34 | bool Color::IsPlayer () const { 35 | return GetRaw() <= 1; 36 | } 37 | 38 | bool Color::IsNotPlayer () const { 39 | return GetRaw() > 1; 40 | } 41 | 42 | Player Color::ToPlayer () const { 43 | return Player::OfRaw (GetRaw()); 44 | } 45 | 46 | char Color::ToShowboardChar () const { 47 | NatMap tab (' '); 48 | tab [Black()] = '#'; 49 | tab [White()] = 'O'; 50 | tab [Empty()] = '.'; 51 | tab [OffBoard()] = '$'; 52 | return tab [*this]; 53 | } 54 | -------------------------------------------------------------------------------- /source/goboard/color.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #ifndef COLOR_H_ 6 | #define COLOR_H_ 7 | 8 | #include "player.hpp" 9 | 10 | class Color : public Nat { 11 | public: 12 | 13 | // Constructors. 14 | 15 | explicit Color(); 16 | 17 | static Color Black(); 18 | static Color White(); 19 | static Color Empty(); 20 | static Color OffBoard(); 21 | 22 | static Color OfPlayer (Player pl); 23 | 24 | // Utilities. 25 | 26 | bool IsPlayer() const; 27 | bool IsNotPlayer() const; 28 | Player ToPlayer() const; 29 | char ToShowboardChar() const; 30 | 31 | // Other. 32 | 33 | static const uint kBound = 4; 34 | 35 | private: 36 | friend class Nat ; 37 | explicit Color (uint raw); 38 | }; 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /source/goboard/config.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #ifndef CONFIG_H_ 6 | #define CONFIG_H_ 7 | 8 | // TODO this have to be renamed to max_board_size 9 | // TODO better use of CMake 10 | 11 | const uint board_size = 9; 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /source/goboard/dir.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DIR_H_ 2 | #define DIR_H_ 3 | 4 | #include "nat.hpp" 5 | 6 | class Dir : public Nat { 7 | public: 8 | explicit Dir () : Nat () {}; 9 | 10 | static Dir N () { return OfRaw (0); } 11 | static Dir E () { return OfRaw (1); } 12 | static Dir S () { return OfRaw (2); } 13 | static Dir W () { return OfRaw (3); } 14 | static Dir NW () { return OfRaw (4); } 15 | static Dir NE () { return OfRaw (5); } 16 | static Dir SE () { return OfRaw (6); } 17 | static Dir SW () { return OfRaw (7); } 18 | 19 | bool IsSimple4 () const { return GetRaw() < 4; } 20 | 21 | Dir Opposite () { 22 | return OfRaw (((raw + 2) & 3) | (raw & 4)); 23 | } 24 | 25 | uint Proximity () { return GetRaw() < 4 ? 0 : 1; } // TODO direct >= 4 26 | 27 | static const uint kBound = 8; 28 | 29 | private: 30 | friend class Nat ; 31 | explicit Dir (uint raw) : Nat (raw) {}; 32 | }; 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /source/goboard/ego.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #include "ego.hpp" 6 | 7 | #include "fast_timer.cpp" 8 | #include "fast_random.cpp" 9 | 10 | #include "player.cpp" 11 | #include "color.cpp" 12 | #include "vertex.cpp" 13 | #include "move.cpp" 14 | 15 | #include "hash.cpp" 16 | #include "board.cpp" 17 | 18 | #include "benchmark.cpp" 19 | #include "playout_test.cpp" 20 | -------------------------------------------------------------------------------- /source/goboard/ego.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #ifndef EGO_H_ 6 | #define EGO_H_ 7 | 8 | #include "utils.hpp" 9 | #include "nat.hpp" 10 | 11 | #include "fast_timer.hpp" 12 | #include "fast_random.hpp" 13 | #include "fast_stack.hpp" 14 | 15 | #include "player.hpp" 16 | #include "color.hpp" 17 | #include "dir.hpp" 18 | #include "vertex.hpp" 19 | #include "move.hpp" 20 | 21 | #include "hash.hpp" 22 | #include "board.hpp" 23 | 24 | #include "gammas.hpp" 25 | #include "sampler.hpp" 26 | 27 | #include "benchmark.hpp" 28 | #include "playout_test.hpp" 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /source/goboard/gammas.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _GAMMAS_HPP 2 | #define _GAMMAS_HPP 3 | 4 | #include "hash.hpp" 5 | 6 | const double GammaskAccurancy = 1.0e-10; 7 | 8 | 9 | 10 | class Gammas { 11 | public: 12 | Gammas () { 13 | gammas = new Tab; 14 | ResetToUniform (); 15 | } 16 | 17 | ~Gammas () { 18 | delete gammas; 19 | } 20 | 21 | void ZeroAllGammas () { 22 | ForEachNat (Hash3x3, hash) { 23 | ForEachNat (Player, pl) { 24 | (*gammas) [hash] [pl] = 0.0; 25 | } 26 | } 27 | } 28 | 29 | 30 | void ResetToUniform () { 31 | ForEachNat (Hash3x3, hash) { 32 | ForEachNat (Player, pl) { 33 | (*gammas) [hash] [pl] = 34 | (hash.IsLegal (pl) && !hash.IsEyelike (pl)) 35 | ? 1.0 36 | : 0.0; 37 | } 38 | } 39 | } 40 | 41 | 42 | bool Read (istream& in) { 43 | uint raw_hash; 44 | double value; 45 | string c; 46 | 47 | ZeroAllGammas (); 48 | 49 | rep (ii, 2051) { 50 | in >> raw_hash >> c >> value; 51 | 52 | if (!in || c != ",") { 53 | ResetToUniform (); 54 | cerr << "Error at:" << ii << endl; 55 | return false; 56 | } 57 | 58 | Hash3x3 all[8]; 59 | Hash3x3::OfRaw (raw_hash).GetAll8Symmetries (all); 60 | rep (ii, 8) { 61 | Hash3x3 hash = all[ii]; 62 | CHECK (value > 0.0); 63 | CHECK (hash.IsLegal (Player::Black ())); 64 | CHECK (value > GammaskAccurancy * 100); 65 | 66 | // Note: We zero values of play-in-eye 67 | if (!hash.IsEyelike (Player::Black())) { 68 | (*gammas) [hash] [Player::Black()] = value; 69 | hash = hash.InvertColors (); 70 | (*gammas) [hash] [Player::White()] = value; 71 | } 72 | } 73 | } 74 | // check that nothing more can be read 75 | in >> raw_hash; 76 | if (in) { 77 | ResetToUniform (); 78 | return false; 79 | } 80 | return true; 81 | } 82 | 83 | 84 | double Get (Hash3x3 hash, Player pl) const { 85 | return (*gammas) [hash] [pl]; 86 | } 87 | 88 | private: 89 | 90 | typedef NatMap > Tab; 91 | Tab* gammas; 92 | }; 93 | 94 | #endif 95 | 96 | -------------------------------------------------------------------------------- /source/goboard/hash.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #include "hash.hpp" 6 | 7 | Hash::Hash () { 8 | } 9 | 10 | uint Hash::Index() const { 11 | return hash; 12 | } 13 | 14 | uint Hash::Lock() const { 15 | return hash >> 32; 16 | } 17 | 18 | void Hash::Randomize (FastRandom& fr) { 19 | hash = 20 | (uint64 (fr.GetNextUint ()) << (0*16)) ^ 21 | (uint64 (fr.GetNextUint ()) << (1*16)) ^ 22 | (uint64 (fr.GetNextUint ()) << (2*16)) ^ 23 | (uint64 (fr.GetNextUint ()) << (3*16)); 24 | } 25 | 26 | void Hash::SetZero () { 27 | hash = 0; 28 | } 29 | 30 | bool Hash::operator== (const Hash& other) const { 31 | return hash == other.hash; 32 | } 33 | 34 | void Hash::operator^= (const Hash& other) { 35 | hash ^= other.hash; 36 | } 37 | 38 | // ----------------------------------------------------------------------------- 39 | 40 | Zobrist::Zobrist () : hashes (Hash()) { 41 | FastRandom fr (123); 42 | ForEachNat (Player, pl) { 43 | ForEachNat (Vertex, v) { 44 | Move m = Move (pl, v); 45 | hashes [m].Randomize (fr); 46 | } 47 | } 48 | } 49 | 50 | Hash Zobrist::OfMove (Move m) const { 51 | return hashes [m]; 52 | } 53 | 54 | Hash Zobrist::OfPlayerVertex (Player pl, Vertex v) const { 55 | return hashes [Move (pl, v)]; 56 | } 57 | -------------------------------------------------------------------------------- /source/goboard/move.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #include "move.hpp" 6 | 7 | Move::Move (Player player, Vertex vertex) 8 | : Nat (player.GetRaw () | (vertex.GetRaw () << 1)) 9 | { 10 | ASSERT (player.IsValid()); 11 | ASSERT (vertex.IsValid()); 12 | } 13 | 14 | Move::Move (int raw) : Nat (raw) { 15 | } 16 | 17 | Move Move::OtherPlayer () const { 18 | return Move::OfRaw (GetRaw() ^ 0x1); 19 | }; 20 | 21 | Player Move::GetPlayer () const { 22 | return Player::OfRaw (GetRaw() & 0x1); 23 | } 24 | 25 | Vertex Move::GetVertex () const { 26 | return Vertex::OfRaw (GetRaw() >> 1) ; 27 | } 28 | 29 | string Move::ToGtpString () const { 30 | return 31 | GetPlayer().ToGtpString() + " " + 32 | GetVertex().ToGtpString(); 33 | } 34 | 35 | Move Move::OfGtpString (const std::string& s) { 36 | stringstream ss (s); 37 | return OfGtpStream (ss); 38 | } 39 | 40 | Move Move::OfGtpStream (istream& in) { 41 | Player pl = Player::OfGtpStream (in); 42 | Vertex v = Vertex::OfGtpStream (in); 43 | if (!in || pl == Player::Invalid() || v == Vertex::Invalid()) { 44 | in.setstate (ios_base::badbit); // TODO undo read? 45 | return Invalid(); 46 | } 47 | return Move (pl, v); 48 | } 49 | -------------------------------------------------------------------------------- /source/goboard/move.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #ifndef MOVE_H_ 6 | #define MOVE_H_ 7 | 8 | #include 9 | #include 10 | 11 | #include "player.hpp" 12 | #include "vertex.hpp" 13 | 14 | 15 | class Move : public Nat { 16 | public: 17 | 18 | // Constructors. 19 | 20 | Move () {} // TODO remove it 21 | Move (Player player, Vertex vertex); // Asserts valid player and vertex. 22 | static Move OfGtpString (const std::string& s); 23 | static Move OfGtpStream (std::istream& s); 24 | 25 | // Utilities. 26 | 27 | Player GetPlayer () const; 28 | Vertex GetVertex () const; 29 | Move OtherPlayer () const; 30 | std::string ToGtpString () const; 31 | 32 | // Other. 33 | 34 | const static uint kBound = Vertex::kBound << 1; 35 | 36 | private: 37 | friend class Nat ; 38 | explicit Move (int raw); 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /source/goboard/player.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #include "player.hpp" 6 | 7 | Player::Player () : Nat () { 8 | } 9 | 10 | Player::Player (uint raw) : Nat (raw) { 11 | } 12 | 13 | Player Player::Black () { 14 | return Player (0); 15 | } 16 | 17 | Player Player::White () { 18 | return Player (1); 19 | } 20 | 21 | Player Player::OfGtpStream (istream& in) { 22 | string s; 23 | in >> s; 24 | if (!in) return Invalid (); 25 | if (s == "b" || s == "B" || s == "Black" || s == "BLACK "|| s == "black") { 26 | return Black(); 27 | } 28 | if (s == "w" || s == "W" || s == "White" || s == "WHITE "|| s == "white") { 29 | return White(); 30 | } 31 | in.setstate (ios_base::badbit); // TODO undo read? 32 | return Invalid(); 33 | } 34 | 35 | Player Player::WinnerOfBoardScore (int score) { 36 | return Player::OfRaw (score <= 0); 37 | } 38 | 39 | Player Player::Other() const { 40 | return Player(GetRaw() ^ 1); 41 | } 42 | 43 | int Player::ToScore () const { 44 | return 1 - int(GetRaw() + GetRaw()) ; 45 | } 46 | 47 | string Player::ToGtpString () const { 48 | NatMap gtp_string (""); 49 | gtp_string [Black()] = "B"; 50 | gtp_string [White()] = "W"; 51 | return gtp_string [*this]; 52 | } 53 | 54 | float Player::SubjectiveScore (const float& score) const { 55 | NatMap tab (0.0); 56 | tab[Black()] = score; 57 | tab[White()] = - score; 58 | return tab [*this]; 59 | } 60 | -------------------------------------------------------------------------------- /source/goboard/player.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #ifndef PLAYER_H_ 6 | #define PLAYER_H_ 7 | 8 | #include 9 | #include 10 | #include "nat.hpp" 11 | 12 | class Player : public Nat { 13 | public: 14 | 15 | // Constructors. 16 | Player (); 17 | static Player Black (); 18 | static Player White (); 19 | static Player WinnerOfBoardScore (int score); 20 | static Player OfGtpStream (std::istream& s); 21 | 22 | // Utilities. 23 | 24 | Player Other() const; 25 | int ToScore () const; // ToScore (Black()) == 1, ToScore (White()) == -1 26 | std::string ToGtpString () const; 27 | 28 | float SubjectiveScore (const float& score) const; 29 | 30 | // Other. 31 | 32 | static const uint kBound = 2; 33 | 34 | private: 35 | friend class Nat ; 36 | explicit Player (uint raw); 37 | }; 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /source/goboard/playout_test.cpp: -------------------------------------------------------------------------------- 1 | #include "playout_test.hpp" 2 | 3 | void PlayoutTest (bool print_moves) { 4 | Board empty; 5 | Board board; 6 | FastRandom random (123); 7 | NatMap win_cnt (0); 8 | uint move_count = 0; 9 | uint move_count2 = 0; 10 | uint hash_changed_count = 0; 11 | Gammas gammas; 12 | Sampler sampler (board, gammas); 13 | uint n = 10000; 14 | if (board_size == 19) { 15 | n = 1000; 16 | } 17 | 18 | rep (ii, n) { 19 | board.Load (empty); 20 | sampler.NewPlayout (); 21 | 22 | // Plaout loop 23 | while (!board.BothPlayerPass ()) { 24 | move_count2 += 1; 25 | FastStack legals; // TODO pass 26 | Player pl = board.ActPlayer(); 27 | 28 | // legal moves 29 | rep (jj, board.EmptyVertexCount()) { 30 | Vertex v = board.EmptyVertex (jj); 31 | CHECK2 (board.KoVertex() == v || 32 | board.IsLegal (pl, v) == board.Hash3x3At(v).IsLegal(pl), { 33 | board.Dump1 (v); 34 | }); 35 | if (v != Vertex::Pass () && 36 | board.IsLegal (pl, v) && 37 | !board.IsEyelike (pl, v)) { 38 | legals.Push(v); 39 | } 40 | } 41 | 42 | // random move 43 | Vertex sampler_v = sampler.SampleMove(random); 44 | CHECK (board.IsLegal (pl, sampler_v)); 45 | 46 | 47 | CHECK2 (fabs (sampler.act_gamma_sum [pl] - legals.Size()) < 0.000001, { 48 | board.Dump1 (board.LastVertex()); 49 | WW (sampler.act_gamma_sum [pl]); 50 | WW (legals.Size()); 51 | WW (move_count2); 52 | }); 53 | 54 | Vertex v; 55 | uint random_idx = 999; 56 | if (legals.Size() == 0) { 57 | v = Vertex::Pass (); 58 | } else { 59 | random_idx = random.GetNextUint (legals.Size()); 60 | v = legals.Remove (random_idx); 61 | } 62 | 63 | // play_it 64 | board.PlayLegal (pl, v); 65 | sampler.MovePlayed (); 66 | 67 | hash_changed_count += board.Hash3x3ChangedCount (); 68 | 69 | if (print_moves && ii < 1000) { 70 | cerr << move_count2 << ":" 71 | << v.ToGtpString () << " " 72 | << "(" << random_idx << "/" << legals.Size () + 1 << ") " 73 | << board.Hash3x3ChangedCount () 74 | << endl; 75 | } 76 | } 77 | 78 | win_cnt [board.PlayoutWinner ()] ++; 79 | move_count += board.MoveCount(); 80 | } 81 | 82 | // Report and regression checks. 83 | cerr 84 | << "board_test ok: " 85 | << win_cnt [Player::Black ()] << "/" 86 | << win_cnt [Player::White ()] << " " 87 | << move_count << " " 88 | << hash_changed_count << " " 89 | << endl; 90 | 91 | if (board_size == 9) { 92 | CHECK (win_cnt [Player::Black()] == 4436); 93 | CHECK (win_cnt [Player::White()] == 5564); 94 | CHECK (move_count == move_count2); 95 | CHECK (move_count2 == 1109454); 96 | CHECK (hash_changed_count == 3702383); 97 | } else if (board_size == 19) { 98 | CHECK (win_cnt [Player::Black()] == 476); 99 | CHECK (win_cnt [Player::White()] == 524); 100 | CHECK (move_count == move_count2); 101 | CHECK (move_count2 == 454567); 102 | CHECK (hash_changed_count == 1689259); 103 | } else { 104 | CHECK (false); 105 | } 106 | } 107 | 108 | 109 | 110 | void SamplerPlayoutTest (bool print_moves) { 111 | Board empty; 112 | Board board; 113 | FastRandom random (123); 114 | NatMap win_cnt (0); 115 | uint move_count = 0; 116 | uint move_count2 = 0; 117 | uint hash_changed_count = 0; 118 | Gammas gammas; 119 | Sampler sampler (board, gammas); 120 | 121 | uint n = 10000; 122 | if (board_size == 19) n = 1000; 123 | 124 | rep (ii, n) { 125 | board.Load (empty); 126 | sampler.NewPlayout(); 127 | 128 | // Plaout loop 129 | while (!board.BothPlayerPass ()) { 130 | move_count2 += 1; 131 | Player pl = board.ActPlayer(); 132 | 133 | 134 | // random move 135 | Vertex v = sampler.SampleMove(random); 136 | CHECK (board.IsLegal (pl, v)); 137 | 138 | // play_it 139 | board.PlayLegal (pl, v); 140 | sampler.MovePlayed(); 141 | 142 | hash_changed_count += board.Hash3x3ChangedCount (); 143 | 144 | if (print_moves && ii < 1000) { 145 | cerr << move_count2 << ":" 146 | << v.ToGtpString () << " " 147 | << board.Hash3x3ChangedCount () 148 | << endl; 149 | } 150 | } 151 | 152 | win_cnt [board.PlayoutWinner ()] ++; 153 | move_count += board.MoveCount(); 154 | } 155 | 156 | // Report and regression checks. 157 | cerr 158 | << "sampler_test results: " 159 | << win_cnt [Player::Black ()] << " " 160 | << win_cnt [Player::White ()] << " " 161 | << move_count << " " 162 | << hash_changed_count << " " 163 | << endl; 164 | 165 | 166 | if (board_size == 9) { 167 | CHECK (win_cnt [Player::Black()] == 4587); 168 | CHECK (win_cnt [Player::White()] == 5413); 169 | CHECK (move_count == move_count2); 170 | CHECK (move_count2 == 1150865 ); 171 | CHECK (hash_changed_count == 3798115); 172 | } else if (board_size == 19) { 173 | CHECK(false); // TODO too lazy to update these. 174 | CHECK (win_cnt [Player::Black()] == 452); 175 | CHECK (win_cnt [Player::White()] == 548); 176 | CHECK (move_count == move_count2); 177 | CHECK (move_count2 == 455121); 178 | CHECK (hash_changed_count == 1692632); 179 | } else { 180 | CHECK (false); 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /source/goboard/playout_test.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _PLAYOUT_TEST_HPP 2 | #define _PLAYOUT_TEST_HPP 3 | 4 | void PlayoutTest (bool print_moves); 5 | void SamplerPlayoutTest (bool print_moves); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /source/goboard/vertex.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #include "to_string.hpp" 6 | 7 | #include "vertex.hpp" 8 | 9 | // ----------------------------------------------------------------------------- 10 | 11 | namespace Coord { 12 | const string col_tab = "ABCDEFGHJKLMNOPQRSTUVWXYZ"; 13 | 14 | bool IsOk (int coord) { 15 | return static_cast (coord) < board_size; 16 | } 17 | 18 | string RowToGtpString (uint row) { 19 | CHECK (row < board_size); 20 | return ToString (board_size - row); 21 | } 22 | 23 | string ColumnToGtpString (uint column) { 24 | CHECK (column < board_size); 25 | return ToString (col_tab [column]); 26 | } 27 | 28 | int RowOfGtpInt (int r) { 29 | return board_size - r; 30 | } 31 | 32 | int ColumnOfGtpChar (char c) { 33 | return col_tab.find (c); 34 | } 35 | } 36 | 37 | //-------------------------------------------------------------------------------- 38 | 39 | namespace { 40 | const static uint dNS = (board_size + 2); 41 | const static uint dWE = 1; 42 | } 43 | 44 | Vertex::Vertex (uint raw) : Nat (raw) { 45 | } 46 | 47 | Vertex Vertex::Pass() { 48 | return Vertex (kBound - 2); 49 | } 50 | 51 | Vertex Vertex::Any() { 52 | return Vertex (kBound - 1); 53 | } 54 | 55 | Vertex Vertex::OfCoords (int row, int column) { 56 | if (!Coord::IsOk (row) || !Coord::IsOk (column)) { 57 | return Vertex::Invalid(); 58 | } 59 | return Vertex::OfRaw ((row+1) * dNS + (column+1) * dWE); 60 | } 61 | 62 | Vertex Vertex::OfSgfString (const string& s) { 63 | if (s == "" || (s == "tt" && board_size <= 19)) return Pass(); 64 | if (s.size() != 2) return Invalid(); 65 | int col = s[0] - 'a'; 66 | int row = s[1] - 'a'; 67 | return Vertex::OfCoords (row, col); 68 | } 69 | 70 | Vertex Vertex::OfGtpString (const string& s) { 71 | if (s == "pass" || s == "PASS" || s == "Pass") return Pass(); 72 | 73 | istringstream parser (s); 74 | char c; 75 | int r; 76 | if (!(parser >> c >> r)) return Invalid(); 77 | 78 | if (c >= 'a' && c <= 'z') c = c - 'a' + 'A'; 79 | int row = Coord::RowOfGtpInt (r); 80 | int col = Coord::ColumnOfGtpChar (c); 81 | 82 | return Vertex::OfCoords (row, col); 83 | } 84 | 85 | Vertex Vertex::OfGtpStream (istream& in) { 86 | string s; 87 | in >> s; 88 | if (!in) return Invalid (); 89 | Vertex v = OfGtpString (s); 90 | if (v == Invalid()) in.setstate (ios_base::badbit); 91 | return v; 92 | } 93 | 94 | int Vertex::GetRow() const { 95 | return int (GetRaw() / dNS - 1); 96 | } 97 | 98 | int Vertex::GetColumn() const { 99 | return int (GetRaw() % dNS - 1); 100 | } 101 | 102 | bool Vertex::IsOnBoard() const { 103 | return Coord::IsOk (GetRow()) & Coord::IsOk (GetColumn()); 104 | } 105 | 106 | Vertex Vertex::N() const { return Vertex::OfRaw (GetRaw() - dNS); } 107 | Vertex Vertex::W() const { return Vertex::OfRaw (GetRaw() - dWE); } 108 | Vertex Vertex::E() const { return Vertex::OfRaw (GetRaw() + dWE); } 109 | Vertex Vertex::S() const { return Vertex::OfRaw (GetRaw() + dNS); } 110 | 111 | Vertex Vertex::NW() const { return N().W(); } 112 | Vertex Vertex::NE() const { return N().E(); } 113 | Vertex Vertex::SW() const { return S().W(); } 114 | Vertex Vertex::SE() const { return S().E(); } 115 | 116 | Vertex Vertex::Nbr(Dir d) const { 117 | ASSERT (IsOnBoard ()); 118 | const static uint delta_raw[8] = { // TODO NatMap when compiler allows 119 | -dNS, +dWE, +dNS, -dWE, 120 | -dNS-dWE, -dNS+dWE, +dNS+dWE, +dNS-dWE 121 | }; 122 | 123 | return OfRaw (GetRaw() + delta_raw[d.GetRaw()]); 124 | } 125 | 126 | 127 | string Vertex::ToGtpString() const { 128 | if (*this == Invalid()) return "invalid"; 129 | if (*this == Pass()) return "pass"; 130 | if (*this == Any()) return "any"; 131 | if (!IsOnBoard ()) return "off board"; 132 | 133 | return 134 | Coord::ColumnToGtpString (GetColumn()) + 135 | Coord::RowToGtpString (GetRow()); 136 | } 137 | -------------------------------------------------------------------------------- /source/goboard/vertex.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #ifndef VERTEX_H_ 6 | #define VERTEX_H_ 7 | 8 | #include 9 | #include 10 | #include "config.hpp" 11 | 12 | class Dir; 13 | 14 | namespace Coord { 15 | bool IsOk (int coord); 16 | 17 | std::string RowToGtpString (uint row); 18 | std::string ColumnToGtpString (uint column); 19 | int RowOfGtpInt (int r); 20 | int ColumnOfGtpChar (char c); 21 | } 22 | 23 | class Vertex : public Nat { 24 | public: 25 | 26 | // Constructors. 27 | 28 | explicit Vertex() {}; // TODO remove it 29 | 30 | static Vertex Pass(); 31 | static Vertex Any(); // NatMap doesn't work with Invalid 32 | 33 | static Vertex OfCoords (int row, int column); 34 | static Vertex OfGtpString (const std::string& s); 35 | static Vertex OfGtpStream (std::istream& in); 36 | static Vertex OfSgfString (const std::string& s); 37 | 38 | // Utilities. 39 | 40 | int GetRow() const; 41 | int GetColumn() const; 42 | 43 | // This can be achieved quicker by color_at lookup. 44 | bool IsOnBoard() const; 45 | 46 | Vertex N() const; 47 | Vertex W() const; 48 | Vertex E() const; 49 | Vertex S() const; 50 | 51 | Vertex NW() const; 52 | Vertex NE() const; 53 | Vertex SW() const; 54 | Vertex SE() const; 55 | 56 | Vertex Nbr(Dir d) const; 57 | 58 | std::string ToGtpString() const; 59 | 60 | // Other. 61 | 62 | static const uint kBound = (board_size + 2) * (board_size + 2) + 2; 63 | // board with guards + pass + any 64 | 65 | private: 66 | friend class Nat ; 67 | explicit Vertex (uint raw); 68 | }; 69 | 70 | #define for_each_8_nbr(center_v, nbr_v, block) { \ 71 | Vertex nbr_v; \ 72 | nbr_v = center_v.N (); block; \ 73 | nbr_v = center_v.W (); block; \ 74 | nbr_v = center_v.E (); block; \ 75 | nbr_v = center_v.S (); block; \ 76 | nbr_v = center_v.NW (); block; \ 77 | nbr_v = center_v.NE (); block; \ 78 | nbr_v = center_v.SW (); block; \ 79 | nbr_v = center_v.SE (); block; \ 80 | } 81 | 82 | // ----------------------------------------------------------------------------- 83 | #endif 84 | -------------------------------------------------------------------------------- /source/gtp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set_cxx_flags (FALSE) 2 | 3 | include_directories (${libego_SOURCE_DIR}/utils) 4 | 5 | add_library (gtp gtp.cpp gtp_gogui.cpp) 6 | 7 | # add_boost_cxx_test (gtp_test) 8 | # target_link_libraries (gtp_test gtp) 9 | 10 | # add_boost_cxx_test (gtp_gogui_test) 11 | # target_link_libraries (gtp_gogui_test gtp) 12 | 13 | 14 | #install (TARGETS gtp ${INSTALL_TARGETS_DEFAULT_ARGS}) 15 | # TODO: 16 | # make install optional 17 | # install headers 18 | # make cmake file for importing 19 | # install (EXPORT libgtp DESTINATION ?) 20 | # install (TARGETS gtp EXPORT libgtp ${INSTALL_TARGETS_DEFAULT_ARGS}) 21 | -------------------------------------------------------------------------------- /source/gtp/gtp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "gtp.hpp" 7 | 8 | namespace Gtp { 9 | 10 | Io::Io (const string& params_) : params (params_), success(true), quit_gtp (false) { 11 | } 12 | 13 | string Io::ReadLine () { 14 | in.clear(); 15 | string line; 16 | if (!getline (in, line)) { 17 | SetError ("Io::ReadLine failed, this should not happen."); 18 | throw Repl::Return(); 19 | } 20 | return line; 21 | } 22 | 23 | void Io::SetError (const string& message) { 24 | out.str (message); 25 | success = false; 26 | } 27 | 28 | void Io::CheckEmpty() { 29 | string s; 30 | in >> s; 31 | if (in) { 32 | SetError ("too many parameters"); 33 | throw Repl::Return(); 34 | } 35 | in.clear(); 36 | } 37 | 38 | bool Io::IsEmpty() { 39 | string s; 40 | std::streampos pos = in.tellg(); 41 | in >> s; 42 | bool ok = in; 43 | in.seekg(pos); 44 | in.clear(); 45 | return !ok; 46 | } 47 | 48 | void Io::PrepareIn () { 49 | in.clear(); 50 | in.str (params); 51 | } 52 | 53 | string Io::Report () const { 54 | string s = out.str (); 55 | while (s.size () > 0 && 56 | (s [s.size() - 1] == '\n' || 57 | s [s.size() - 1] == ' ' || 58 | s [s.size() - 1] == '\t')) 59 | { 60 | s.resize (s.size() - 1); 61 | } 62 | return s; 63 | } 64 | 65 | // ----------------------------------------------------------------------------- 66 | 67 | // IMPROVE: can't Static Aux be anonymous function 68 | 69 | void StaticAux(const string& ret, Io& io) { 70 | io.CheckEmpty (); 71 | io.out << ret; 72 | } 73 | 74 | Repl::Callback StaticCommand (const string& ret) { 75 | return std::bind(StaticAux, ret, _1); 76 | } 77 | 78 | // ----------------------------------------------------------------------------- 79 | 80 | Repl::Repl () { 81 | Register ("list_commands", this, &Repl::CListCommands); 82 | Register ("help", this, &Repl::CListCommands); 83 | Register ("known_command", this, &Repl::CKnownCommand); 84 | Register ("quit", this, &Repl::CQuit); 85 | Register ("gtpfile", this, &Repl::CGtpFile); 86 | } 87 | 88 | void Repl::Register (const string& name, Callback callback) { 89 | callbacks[name].push_back (callback); 90 | } 91 | 92 | void Repl::RegisterStatic (const string& name, const string& response) { 93 | Register (name, StaticCommand(response)); 94 | } 95 | 96 | void ParseLine (const string& line, int* id, string* command, string* rest) { 97 | stringstream ss; 98 | for (unsigned int ii = 0; ii != line.size (); ii += 1) { 99 | char c = line [ii]; 100 | if (false) {} 101 | else if (c == '\t') ss << ' '; 102 | else if (c == '\n') assert (false); 103 | else if (c <= 31 || c == 127) continue; 104 | else if (c == '#') break; // remove comments 105 | else ss << c; 106 | } 107 | *id = -1; 108 | *command = ""; 109 | *rest = ""; 110 | ss >> *id; 111 | if (!ss) { 112 | ss.clear (); 113 | ss.seekg (ios_base::beg); 114 | } 115 | ss >> *command; 116 | getline (ss, *rest); 117 | } 118 | 119 | Repl::Status Repl::RunOneCommand (const string& line, string* report) { 120 | int id; 121 | string command, params; 122 | 123 | ParseLine (line, &id, &command, ¶ms); 124 | 125 | Io io(params); 126 | 127 | *report = ""; 128 | if (command == "") return NoOp; 129 | 130 | if (IsCommand (command)) { 131 | // Callback call with optional fast return. 132 | list& cmd_list = callbacks [command]; 133 | for (list::iterator cmd = cmd_list.begin(); 134 | cmd != cmd_list.end(); 135 | ++cmd) 136 | { 137 | io.PrepareIn(); 138 | try { (*cmd) (io); } catch (Return) { } 139 | } 140 | } else { 141 | io.SetError ("unknown command: \"" + command + "\""); 142 | } 143 | 144 | *report = io.Report(); 145 | if (io.quit_gtp) return Quit; 146 | if (io.success) return Success; 147 | return Failure; 148 | } 149 | 150 | void Repl::Run (istream& in, ostream& out) { 151 | in.clear(); 152 | while (true) { 153 | string line, report; 154 | if (!getline (in, line)) { 155 | if (errno == EINTR) { 156 | errno = 0; 157 | in.clear(); 158 | continue; 159 | } 160 | break; 161 | } 162 | 163 | Status status = RunOneCommand (line, &report); 164 | if (status == NoOp) continue; 165 | 166 | out << (status == Failure ? "?" : "=") << " " 167 | << report 168 | << endl << endl; 169 | 170 | if (status == Quit) break; 171 | } 172 | } 173 | 174 | void Repl::CListCommands (Io& io) { 175 | io.CheckEmpty(); 176 | pair > p; 177 | for (map >::iterator cb = callbacks.begin(); 178 | cb != callbacks.end(); 179 | ++cb) 180 | { 181 | io.out << cb->first << endl; 182 | } 183 | } 184 | 185 | void Repl::CKnownCommand (Io& io) { 186 | io.out << boolalpha << IsCommand(io.Read ()); 187 | io.CheckEmpty(); 188 | } 189 | 190 | void Repl::CQuit (Io& io) { 191 | io.CheckEmpty(); 192 | io.out << "bye"; 193 | io.quit_gtp = true; 194 | } 195 | 196 | void Repl::CGtpFile (Io& io) { 197 | string file = io.Read (); 198 | io.CheckEmpty(); 199 | ifstream in (file.c_str()); 200 | if (!in) { 201 | io.SetError ("No such file: \"" + file + "\""); 202 | return; 203 | } 204 | Run (in, cerr); 205 | } 206 | 207 | bool Repl::IsCommand (const string& name) { 208 | return callbacks.find(name) != callbacks.end(); 209 | } 210 | 211 | namespace detail { 212 | 213 | #define Specialization(T) \ 214 | template<> T IoReadOfStream< T > (istream& in) { \ 215 | T t; \ 216 | in >> t; \ 217 | return t; \ 218 | } 219 | 220 | Specialization(bool); 221 | Specialization(char); 222 | Specialization(int); 223 | Specialization(unsigned int); 224 | Specialization(float); 225 | Specialization(double); 226 | Specialization(string); 227 | #undef Specialization 228 | 229 | } // namespace detail 230 | 231 | } // namespace Gtp 232 | -------------------------------------------------------------------------------- /source/gtp/gtp.hpp: -------------------------------------------------------------------------------- 1 | #ifndef GTP_H_ 2 | #define GTP_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace Gtp { 11 | 12 | using namespace std; 13 | using std::placeholders::_1; 14 | 15 | // ----------------------------------------------------------------------------- 16 | // Command communication interface. 17 | 18 | class Io { 19 | public: 20 | 21 | istringstream in; 22 | ostringstream out; 23 | 24 | // Repl Will print "? message" on the output 25 | void SetError (const string& message); 26 | 27 | // Reads and returns type T, throws syntax_error otherwise. 28 | template T Read (); 29 | 30 | // Reads and returns type T, returns default value in case of syntax error. 31 | template T Read (const T& default_value); 32 | 33 | // Reads and returns rest of the argument line. 34 | string ReadLine (); 35 | 36 | // Returns true is all that's left in in is whitespace. 37 | bool IsEmpty (); 38 | 39 | // Throws syntax_error if a non-whitespace is still in in 40 | void CheckEmpty (); 41 | 42 | private: 43 | friend class Repl; 44 | 45 | Io (const string& params); 46 | void PrepareIn (); 47 | string Report () const; 48 | 49 | private: 50 | const string& params; 51 | bool success; 52 | bool quit_gtp; 53 | }; 54 | 55 | 56 | // ----------------------------------------------------------------------------- 57 | // GTP read-eval-print-loop (repl) 58 | 59 | class Repl { 60 | public: 61 | typedef std::function< void(Io&) > Callback; 62 | 63 | Repl (); 64 | 65 | void Register (const string& name, Callback command); 66 | 67 | template 68 | void Register (const string& name, T* object, void(T::*member)(Io&)); 69 | 70 | void RegisterStatic (const string& name, const string& response); 71 | 72 | enum Status { 73 | Success, 74 | Failure, 75 | Quit, 76 | NoOp 77 | }; 78 | 79 | Status RunOneCommand (const string& line, string* report); 80 | 81 | void Run (istream&, ostream&); 82 | 83 | bool IsCommand (const string& name); 84 | 85 | private: 86 | // Exception that can be thrown by a command and will be caught by Repl::Run 87 | struct Return {}; 88 | 89 | friend class Io; 90 | 91 | // commands built-in into interpreter (registered during interpreter construction) 92 | void CListCommands (Io&); 93 | void CKnownCommand (Io&); 94 | void CQuit (Io&); 95 | void CGtpFile (Io&); 96 | 97 | private: 98 | map > callbacks; 99 | }; 100 | 101 | // Creates a callback that: 102 | // - without arguments prints value of given variable 103 | // - with one argument sets the given variable to this value using Io::Read. 104 | template 105 | Repl::Callback GetSetCallback (T* var); 106 | 107 | 108 | // ----------------------------------------------------------------------------- 109 | // implementation 110 | namespace detail { 111 | template T IoReadOfStream (istream& in) { return T::OfGtpStream (in); } 112 | #define Specialization(T) template<> T IoReadOfStream< T > (istream& in) 113 | Specialization(bool); 114 | Specialization(char); 115 | Specialization(int); 116 | Specialization(unsigned int); 117 | Specialization(float); 118 | Specialization(double); 119 | Specialization(string); 120 | #undef Specialization 121 | } 122 | 123 | 124 | template 125 | T Io::Read () { 126 | in.clear(); 127 | T t = detail::IoReadOfStream (in); 128 | if (in.fail()) { 129 | in.clear(); 130 | SetError ("syntax error"); 131 | throw Repl::Return(); 132 | } 133 | return t; 134 | } 135 | 136 | template 137 | T Io::Read (const T& default_value) { 138 | in.clear(); 139 | T t = detail::IoReadOfStream (in); 140 | if (in.fail()) { 141 | in.clear(); 142 | return default_value; 143 | } 144 | return t; 145 | } 146 | 147 | template 148 | void Repl::Register (const string& name, T* object, void(T::*member)(Io&)) { 149 | Register (name, std::bind(member, object, _1)); 150 | } 151 | 152 | 153 | namespace { 154 | template 155 | void GetSetCallbackAux (T* var, Io& io) { 156 | if (io.IsEmpty()) { 157 | io.out << *var; 158 | return; 159 | } 160 | // TODO handle quoted strings 161 | T tmp = io.Read(); 162 | io.CheckEmpty (); 163 | *var = tmp; 164 | } 165 | } 166 | 167 | template 168 | Repl::Callback GetSetCallback (T* var) { 169 | return bind(GetSetCallbackAux, var, _1); 170 | } 171 | 172 | // ----------------------------------------------------------------------------- 173 | 174 | } // namespace Gtp 175 | 176 | #endif // _GTP_H_ 177 | -------------------------------------------------------------------------------- /source/gtp/gtp_gogui.cpp: -------------------------------------------------------------------------------- 1 | #include "gtp_gogui.hpp" 2 | #include 3 | #include 4 | 5 | namespace Gtp { 6 | 7 | GoguiGfx::GoguiGfx () { 8 | } 9 | 10 | 11 | void GoguiGfx::SetInfluence (const string& vertex, float influence) { 12 | if (influence != 0.0 && ! qisnan (influence)) { 13 | ostringstream s; 14 | s << influence; 15 | gfx_output ["INFLUENCE"] += vertex + " " + s.str() + " "; 16 | } 17 | } 18 | 19 | void GoguiGfx::SetLabel (const string& vertex, const string& label) { 20 | if (label != "") { 21 | gfx_output ["LABEL"] += vertex + " \"" + label + "\" "; 22 | } 23 | } 24 | 25 | void GoguiGfx::SetSymbol (const string& vertex, GoguiGfx::Symbol s) { 26 | string key; 27 | switch (s) { 28 | case circle: key = "CIRCLE"; break; 29 | case triangle: key = "TRIANGLE"; break; 30 | case square: key = "SQUARE"; break; 31 | default: assert (false); 32 | } 33 | gfx_output [key] += vertex + " "; 34 | } 35 | 36 | void GoguiGfx::AddVariationMove (const string& player_and_vertex) { 37 | gfx_output ["VAR"] += player_and_vertex + " "; 38 | } 39 | 40 | void GoguiGfx::SetStatusBar (const string& status) { 41 | gfx_output ["STATUS"] += status + " "; 42 | } 43 | 44 | void GoguiGfx::Report (Io& io) { 45 | for (map ::iterator it = gfx_output.begin(); 46 | it != gfx_output.end(); 47 | ++it) 48 | { 49 | io.out << it->first << " " << it->second << endl; 50 | } 51 | } 52 | 53 | // ----------------------------------------------------------------------------- 54 | 55 | ReplWithGogui::ReplWithGogui () : Repl () { 56 | Register ("gogui_analyze_commands", this, &ReplWithGogui::CAnalyze); 57 | } 58 | 59 | void ReplWithGogui::RegisterGfx (const string& name, 60 | const string& params, 61 | Callback command) 62 | { 63 | string full_name = params == "" ? name : name + " " + params; 64 | analyze_list 65 | << "gfx/" << full_name << "/" << full_name << endl; 66 | if (!IsCommand (name)) { 67 | Register (name, command); 68 | } 69 | } 70 | 71 | void ReplWithGogui::CParam (const string& cmd_name, Io& io) { 72 | map& vars = params[cmd_name]; 73 | if (io.IsEmpty ()) { 74 | // print all vars and their values 75 | for (map ::iterator it = vars.begin(); 76 | it != vars.end(); 77 | ++it) 78 | { 79 | io.out << "[string] " << it->first << " "; 80 | it->second (io); 81 | io.out << endl; 82 | } 83 | } else { 84 | string var_name = io.Read (); 85 | if (vars.find (var_name) == vars.end ()) { 86 | io.SetError ("unknown variable: \"" + var_name + "\""); 87 | return; 88 | } 89 | vars[var_name] (io); 90 | } 91 | } 92 | 93 | void ReplWithGogui::CAnalyze (Io& io) { 94 | io.out << analyze_list.str (); 95 | } 96 | 97 | } // namespace Gtp 98 | -------------------------------------------------------------------------------- /source/gtp/gtp_gogui.hpp: -------------------------------------------------------------------------------- 1 | #ifndef GTP_GOGUI_H_ 2 | #define GTP_GOGUI_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "gtp.hpp" 8 | #include "utils.hpp" 9 | 10 | namespace Gtp { 11 | 12 | using namespace std; 13 | 14 | // ----------------------------------------------------------------------------- 15 | 16 | class GoguiGfx { 17 | public: 18 | GoguiGfx(); 19 | 20 | enum Symbol { circle, triangle, square }; 21 | 22 | void SetInfluence (const string& vertex, float influence); 23 | void SetLabel (const string& vertex, const string& label); 24 | void SetSymbol (const string& vertex, Symbol s); 25 | 26 | void AddVariationMove (const string& player_and_vertex); 27 | 28 | void SetStatusBar (const string& status); 29 | 30 | void Report (Io& io); 31 | 32 | private: 33 | map gfx_output; 34 | }; 35 | 36 | // ----------------------------------------------------------------------------- 37 | 38 | class ReplWithGogui : public Repl { 39 | public: 40 | ReplWithGogui (); 41 | 42 | void RegisterGfx (const string& name, const string& params, Callback command); 43 | 44 | template 45 | void RegisterGfx (const string& name, 46 | const string& params, 47 | T* object, 48 | void(T::*member)(Io&)); 49 | 50 | template 51 | void RegisterParam (const string& cmd_name, const string& param_name, T* param); 52 | 53 | private: 54 | void CAnalyze (Io&); 55 | void CParam (const string& cmd_name, Io& io); 56 | 57 | private: 58 | stringstream analyze_list; 59 | map > params; // params [cmd_name] [param_name] 60 | }; 61 | 62 | // ----------------------------------------------------------------------------- 63 | // internal 64 | 65 | template 66 | void ReplWithGogui::RegisterGfx (const string& name, 67 | const string& params, 68 | T* object, 69 | void(T::*member)(Io&)) 70 | { 71 | RegisterGfx (name, params, std::bind(member, object, _1)); 72 | } 73 | 74 | template 75 | void ReplWithGogui::RegisterParam (const string& cmd_name, 76 | const string& param_name, 77 | T* param) 78 | { 79 | params [cmd_name] [param_name] = GetSetCallback (param); 80 | if (IsCommand (cmd_name)) return; 81 | analyze_list << "param/" << cmd_name << "/" << cmd_name << endl; // NOTE: factor out 82 | Register (cmd_name, std::bind (&ReplWithGogui::CParam, this, cmd_name, _1)); 83 | } 84 | 85 | } // namespace Gtp 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /source/gtp/gtp_gogui_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define BOOST_TEST_MAIN 4 | #define BOOST_TEST_DYN_LINK // IMPROVE: why do I need this? 5 | #include 6 | 7 | #include "gtp.hpp" 8 | #include "gtp_gogui.hpp" 9 | 10 | using std::endl; 11 | using std::stringstream; 12 | using std::string; 13 | 14 | // ----------------------------------------------------------------------------- 15 | 16 | void DoGfx (Gtp::Io&) { 17 | } 18 | 19 | class DummyAnalyzeUser { 20 | public: 21 | void DoBlah (Gtp::Io&) { 22 | } 23 | }; 24 | 25 | // Environement of all unit tests. 26 | struct Fixture { 27 | stringstream in; 28 | stringstream out; 29 | stringstream expected_out; 30 | 31 | Gtp::ReplWithGogui gtp; 32 | DummyAnalyzeUser dau; 33 | 34 | int i; 35 | float f; 36 | string s; 37 | // TODO try custom type with << >> operators 38 | 39 | Fixture() 40 | : i(1), f(1.5), s("one_and_half") 41 | { 42 | out << endl; 43 | expected_out << endl; 44 | gtp.RegisterGfx ("do_gfx", "all", &DoGfx); 45 | gtp.RegisterGfx ("do_gfx", "half", &DoGfx); 46 | gtp.RegisterGfx ("do_gfx", "", &DoGfx); 47 | gtp.RegisterGfx ("do_blah", 48 | "", 49 | &dau, 50 | &DummyAnalyzeUser::DoBlah); 51 | gtp.RegisterParam ("test.params", "int", &i); 52 | gtp.RegisterParam ("test.params", "float", &f); 53 | gtp.RegisterParam ("test.params", "str", &s); 54 | gtp.RegisterParam ("test.params2", "same_str", &s); 55 | } 56 | }; 57 | 58 | // ----------------------------------------------------------------------------- 59 | 60 | BOOST_FIXTURE_TEST_SUITE( f, Fixture ) 61 | 62 | BOOST_AUTO_TEST_CASE (ListCommands) { 63 | in 64 | << "help" << endl 65 | ; 66 | 67 | expected_out 68 | << "= " 69 | << "do_blah" << endl 70 | << "do_gfx" << endl 71 | << "gogui_analyze_commands" << endl 72 | << "gtpfile" << endl 73 | << "help" << endl 74 | << "known_command" << endl 75 | << "list_commands" << endl 76 | << "quit" << endl 77 | << "test.params" << endl 78 | << "test.params2" << endl 79 | << endl 80 | ; 81 | 82 | gtp.Run(in, out); 83 | BOOST_CHECK_EQUAL (out.str(), expected_out.str()); 84 | } 85 | 86 | BOOST_AUTO_TEST_CASE (GoguiAnalyzeCommands) { 87 | in 88 | << "gogui_analyze_commands" << endl 89 | << "do_gfx" << endl 90 | << "do_blah" << endl 91 | ; 92 | expected_out 93 | << "= " 94 | << "gfx/do_gfx all/do_gfx all" << endl 95 | << "gfx/do_gfx half/do_gfx half" << endl 96 | << "gfx/do_gfx/do_gfx" << endl 97 | << "gfx/do_blah/do_blah" << endl 98 | << "param/test.params/test.params" << endl 99 | << "param/test.params2/test.params2" << endl 100 | << endl 101 | << "= " << endl 102 | << endl 103 | << "= " << endl 104 | << endl 105 | ; 106 | gtp.Run(in, out); 107 | BOOST_CHECK_EQUAL (out.str(), expected_out.str()); 108 | } 109 | 110 | BOOST_AUTO_TEST_CASE (GfxVariable1) { 111 | in 112 | << "test.params" << endl 113 | << "test.params2" << endl 114 | << "test.params x" << endl 115 | << "test.params float" << endl 116 | ; 117 | 118 | expected_out 119 | 120 | << "= " 121 | << "[string] float 1.5" << endl 122 | << "[string] int 1" << endl 123 | << "[string] str one_and_half" << endl 124 | << endl 125 | 126 | << "= " 127 | << "[string] same_str one_and_half" << endl 128 | << endl 129 | 130 | << "? unknown variable: \"x\"" << endl 131 | << endl 132 | 133 | << "= 1.5" << endl 134 | << endl 135 | ; 136 | gtp.Run(in, out); 137 | BOOST_CHECK_EQUAL (out.str(), expected_out.str()); 138 | } 139 | 140 | BOOST_AUTO_TEST_CASE (GfxVariable2) { 141 | in 142 | << "test.params float NotFloat" << endl 143 | << "test.params float 11.5 " << endl 144 | << "test.params float" << endl 145 | << "test.params str string_with_no_spaces" << endl 146 | << "test.params2 same_str" << endl 147 | ; 148 | 149 | expected_out 150 | 151 | << "? syntax error" << endl 152 | << endl 153 | 154 | << "= " << endl 155 | << endl 156 | 157 | << "= 11.5" << endl 158 | << endl 159 | 160 | << "= " << endl 161 | << endl 162 | 163 | << "= string_with_no_spaces" << endl 164 | << endl 165 | ; 166 | gtp.Run(in, out); 167 | BOOST_CHECK_EQUAL (out.str(), expected_out.str()); 168 | BOOST_CHECK_EQUAL (f, 11.5); 169 | BOOST_CHECK_EQUAL (s, "string_with_no_spaces"); 170 | } 171 | 172 | BOOST_AUTO_TEST_SUITE_END() 173 | -------------------------------------------------------------------------------- /source/gtp/gtp_test.cpp: -------------------------------------------------------------------------------- 1 | #define BOOST_TEST_MAIN 2 | #define BOOST_TEST_DYN_LINK // IMPROVE: why do I need this? 3 | #include 4 | #include 5 | #include 6 | 7 | #include "gtp.hpp" 8 | 9 | using std::endl; 10 | using std::stringstream; 11 | using std::string; 12 | using std::istream; 13 | 14 | // ----------------------------------------------------------------------------- 15 | 16 | // A simple command. 17 | void CAdd (Gtp::Io& io) { 18 | io.out << io.Read() + io.Read(11); 19 | io.CheckEmpty (); 20 | } 21 | 22 | // A simple command implemented as a method. 23 | class DummyGtpUser { 24 | public: 25 | DummyGtpUser (Gtp::Repl& gtp) { 26 | gtp.Register ("echo", this, &DummyGtpUser::CEcho); 27 | gtp.Register ("echo2", this, &DummyGtpUser::CEcho); 28 | gtp.Register ("echo2", this, &DummyGtpUser::CEcho); 29 | } 30 | 31 | private: 32 | void CEcho (Gtp::Io& io) { 33 | std::string s; 34 | std::getline(io.in, s); 35 | //boost::trim(s); 36 | io.out << s << endl; 37 | } 38 | }; 39 | 40 | // Environement of all unit tests. 41 | struct Fixture { 42 | stringstream in; 43 | stringstream out; 44 | stringstream expected_out; 45 | 46 | Gtp::Repl gtp; 47 | DummyGtpUser gtp_user; 48 | 49 | float f; 50 | int i; 51 | string s; 52 | 53 | Fixture() 54 | : gtp_user (gtp), f (1.5), i(-1), s("GTP rulez") 55 | { 56 | gtp.Register ("+", CAdd); 57 | gtp.RegisterStatic ("whoami", "Santa "); 58 | gtp.RegisterStatic ("whoami", "Claus ! "); 59 | gtp.RegisterStatic ("whoareyou", "Merry"); 60 | gtp.Register ("var_f", Gtp::GetSetCallback (&f)); 61 | gtp.Register ("var_i", Gtp::GetSetCallback (&i)); 62 | gtp.Register ("var_s", Gtp::GetSetCallback (&s)); 63 | } 64 | }; 65 | 66 | // ----------------------------------------------------------------------------- 67 | 68 | BOOST_FIXTURE_TEST_SUITE( f, Fixture ) 69 | 70 | BOOST_AUTO_TEST_CASE (BuiltInCommands) { 71 | in 72 | << "help" << endl 73 | << "list_commands # same as help" << endl 74 | << "list_commands badArgument" << endl 75 | << "known_command help" << endl 76 | << "known_command hlp" << endl 77 | << "quit # bye bye" << endl 78 | << "this won't be executed" << endl 79 | ; 80 | 81 | stringstream expected_help_msg; 82 | expected_help_msg 83 | << "= " 84 | << "+" << endl 85 | << "echo" << endl 86 | << "echo2" << endl 87 | << "gtpfile" << endl 88 | << "help" << endl 89 | << "known_command" << endl 90 | << "list_commands" << endl 91 | << "quit" << endl 92 | << "var_f" << endl 93 | << "var_i" << endl 94 | << "var_s" << endl 95 | << "whoami" << endl 96 | << "whoareyou" << endl 97 | << endl 98 | ; 99 | 100 | expected_out 101 | << expected_help_msg.str() 102 | << expected_help_msg.str() 103 | << "? too many parameters" << endl << endl 104 | << "= true" << endl << endl 105 | << "= false" << endl << endl 106 | << "= bye" << endl << endl 107 | ; 108 | 109 | gtp.Run(in, out); 110 | BOOST_CHECK_EQUAL (out.str(), expected_out.str()); 111 | } 112 | 113 | BOOST_AUTO_TEST_CASE (RegisteredCommands) { 114 | in 115 | // << "echo GTP was never so simple " << endl 116 | // << "echo2 print twice " << endl 117 | << "+ 1 2 " << endl 118 | << " + 1 2 3 " << endl 119 | << " + 11" << endl 120 | << " whoami " << endl 121 | << " whoami today " << endl 122 | << " whoareyou " << endl 123 | << " " << endl 124 | << " who are you " << endl 125 | ; 126 | expected_out 127 | // << "= GTP was never so simple" << endl << endl 128 | // << "= print twice" << endl << "print twice" << endl << endl 129 | << "= 3" << endl << endl 130 | << "? too many parameters" << endl << endl 131 | << "= 22" << endl << endl 132 | << "= Santa Claus !" << endl << endl 133 | << "? too many parameters" << endl << endl 134 | << "= Merry" << endl << endl 135 | << "? unknown command: \"who\"" << endl << endl 136 | ; 137 | 138 | gtp.Run(in, out); 139 | BOOST_CHECK_EQUAL (out.str(), expected_out.str()); 140 | } 141 | 142 | BOOST_AUTO_TEST_CASE (GetSetCommands) { 143 | in 144 | << "var_f" << endl 145 | << "var_i" << endl 146 | << "var_s" << endl 147 | << "var_f 123.25" << endl 148 | << "var_i 321" << endl 149 | << "var_s no_spaces" << endl 150 | << "var_f 123.a" << endl 151 | << "var_i 321.5" << endl 152 | ; 153 | expected_out 154 | << "= 1.5" << endl << endl 155 | << "= -1" << endl << endl 156 | << "= GTP rulez" << endl << endl 157 | << "= " << endl << endl 158 | << "= " << endl << endl 159 | << "= " << endl << endl 160 | << "? too many parameters" << endl << endl 161 | << "? too many parameters" << endl << endl 162 | ; 163 | gtp.Run(in, out); 164 | BOOST_CHECK_EQUAL (out.str(), expected_out.str()); 165 | BOOST_CHECK_EQUAL (f, 123.25); 166 | BOOST_CHECK_EQUAL (i, 321); 167 | BOOST_CHECK_EQUAL (s, "no_spaces"); 168 | } 169 | 170 | BOOST_AUTO_TEST_CASE (RunSingleCommand) { 171 | string response; 172 | // BOOST_CHECK_EQUAL (gtp.RunOneCommand ("echo \t out there ", &response), 173 | // Gtp::Repl::Success); 174 | // BOOST_CHECK_EQUAL (response, "out there"); 175 | BOOST_CHECK_EQUAL (gtp.RunOneCommand ("please", &response), 176 | Gtp::Repl::Failure); 177 | BOOST_CHECK_EQUAL (response, "unknown command: \"please\""); 178 | BOOST_CHECK_EQUAL (gtp.RunOneCommand ("quit", &response), Gtp::Repl::Quit); 179 | BOOST_CHECK_EQUAL (response, "bye"); 180 | BOOST_CHECK_EQUAL (gtp.RunOneCommand ("123 \t ", &response), Gtp::Repl::NoOp); 181 | BOOST_CHECK_EQUAL (response, ""); 182 | } 183 | 184 | // Private Default Constructor class 185 | class Pdc { 186 | public: 187 | int i; 188 | string s; 189 | 190 | static Pdc OfGtpStream (istream& in) { 191 | Pdc pdc; 192 | in >> pdc.i >> pdc.s; 193 | return pdc; 194 | } 195 | 196 | private: 197 | Pdc () {}; 198 | }; 199 | 200 | void CReadPdc (Gtp::Io& io) { 201 | Pdc pdc = io.Read (); 202 | io.out << pdc.s << " - " << pdc.i; 203 | } 204 | 205 | BOOST_AUTO_TEST_CASE (NoDefaultConstructorGtp) { 206 | gtp.Register ("read_pdc", CReadPdc); 207 | 208 | string response; 209 | 210 | BOOST_CHECK_EQUAL (gtp.RunOneCommand ("read_pdc 42 istheanswer", &response), 211 | Gtp::Repl::Success); 212 | BOOST_CHECK_EQUAL (response, "istheanswer - 42"); 213 | 214 | BOOST_CHECK_EQUAL (gtp.RunOneCommand ("read_pdc istheanswer 42", &response), 215 | Gtp::Repl::Failure); 216 | BOOST_CHECK_EQUAL (response, "syntax error"); 217 | } 218 | 219 | BOOST_AUTO_TEST_SUITE_END() 220 | -------------------------------------------------------------------------------- /source/gui/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(Qt4 REQUIRED) 2 | include (${QT_USE_FILE}) 3 | 4 | include_directories ( 5 | ${libego_SOURCE_DIR}/engine 6 | ${libego_SOURCE_DIR}/goboard 7 | ${libego_SOURCE_DIR}/utils 8 | ${libego_SOURCE_DIR}/gtp 9 | ${libego_SOURCE_DIR}/libgamegui 10 | ) 11 | 12 | add_definitions ( -Wall ) 13 | 14 | qt4_wrap_cpp (MOC_SRCS manager.h) 15 | add_library (gui gui.cpp manager.cpp ${MOC_SRCS}) 16 | -------------------------------------------------------------------------------- /source/gui/gui.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "gui.h" 4 | #include "engine.hpp" 5 | #include "manager.h" 6 | 7 | 8 | void RunGui (Engine& engine) { 9 | Q_INIT_RESOURCE(images); 10 | 11 | int argc = 1; 12 | char** argv = (char**)malloc(sizeof(char*)); 13 | argv[0] = (char*)malloc(6*sizeof(char)); 14 | strncpy (argv[0], "GoGui\0", 6); 15 | QApplication app (argc, argv); 16 | Gui::Manager gogui (engine); 17 | gogui.show(); 18 | app.exec(); 19 | } 20 | -------------------------------------------------------------------------------- /source/gui/gui.h: -------------------------------------------------------------------------------- 1 | #ifndef GO_GUI_H_ 2 | #define GO_GUI_H_ 3 | 4 | class Engine; 5 | 6 | void RunGui (Engine&); 7 | 8 | #endif /* GO_GUI_H_ */ 9 | -------------------------------------------------------------------------------- /source/gui/manager.h: -------------------------------------------------------------------------------- 1 | #ifndef MANAGER_H_ 2 | #define MANAGER_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | class GameScene; 16 | class QCheckBox; 17 | class Move; 18 | class Player; 19 | 20 | namespace Gui { 21 | 22 | class Manager : public QDialog { 23 | public: 24 | Manager (Engine& engine); 25 | 26 | 27 | public slots: 28 | void getInfluence (); 29 | void refreshBoard (); 30 | void sliderMoved (int value); 31 | void handleMousePress (int x, int y, Qt::MouseButtons buttons); 32 | void handleHooverEntered (int x, int y); 33 | void clearBoard (); 34 | void playMove (); 35 | void undoMove (); 36 | void playoutMove (); 37 | void showGammas (int); 38 | 39 | private: 40 | 41 | QRadioButton* radio_nul; 42 | QRadioButton* radio_mcts_n; 43 | QRadioButton* radio_mcts_m; 44 | QRadioButton* radio_rave_n; 45 | QRadioButton* radio_rave_m; 46 | QRadioButton* radio_bias; 47 | QRadioButton* radio_mix; 48 | QRadioButton* radio_samp_p; 49 | QRadioButton* radio_gamma; 50 | QRadioButton* radio_gamma2; 51 | QRadioButton* radio_terr; 52 | QRadioButton* radio_terr2; 53 | 54 | QSlider* slider1; 55 | QSlider* slider2; 56 | 57 | QLabel* statebar; 58 | 59 | GameScene* game_scene; 60 | NatMap influence; 61 | Engine::InfluenceType influence_type; 62 | 63 | Engine& engine; 64 | 65 | private: 66 | Q_OBJECT 67 | }; 68 | 69 | } // namespace 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /source/libgamegui/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set ( SRCS GameScene.cpp Field.cpp Grid.cpp ResizableView.cpp HexGrid.cpp SquareGrid.cpp Ruler.cpp YGrid.cpp HoGrid.cpp HavannahGrid.cpp ) 2 | set ( MOC_HDRS GameScene.h ResizableView.h ) 3 | set ( RCS images.qrc ) 4 | set ( UIS ) 5 | 6 | set ( BOOST_ROOT /usr/local/include/boost-1_39 ) 7 | set ( QT_USE_QTSVG TRUE ) 8 | 9 | add_definitions ( -Wall ) 10 | 11 | find_package(Qt4 REQUIRED) 12 | include ( ${QT_USE_FILE} ) 13 | qt4_add_resources ( RC_SRCS ${RCS} ) 14 | qt4_wrap_ui ( UI_HDRS ${UIS} ) 15 | qt4_wrap_cpp ( MOC_SRCS ${MOC_HDRS} ) 16 | 17 | include_directories ( ${CMAKE_BINARY_DIR} ${BOOST_ROOT} ) 18 | 19 | add_library(gamegui ${SRCS} ${RC_SRCS} ${UI_HDRS} ${MOC_SRCS} ) 20 | 21 | target_link_libraries(gamegui ${QT_LIBRARIES}) 22 | -------------------------------------------------------------------------------- /source/libgamegui/Field.h: -------------------------------------------------------------------------------- 1 | #ifndef FIELD_H 2 | #define FIELD_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class Field: public QGraphicsItemGroup 10 | { 11 | 12 | public: 13 | Field(const QPainterPath & path, QGraphicsItem *parent = 0); 14 | 15 | enum EStoneColor 16 | { 17 | StoneWhite, StoneBlack 18 | }; 19 | virtual QGraphicsItem* addStone(EStoneColor stoneColor); 20 | void removeStone(); 21 | 22 | virtual QGraphicsItem* addMark(); 23 | void removeMark(); 24 | 25 | virtual QGraphicsItem* addCircle(); 26 | void removeCircle(); 27 | 28 | virtual QGraphicsItem* addSquare(); 29 | void removeSquare(); 30 | 31 | virtual QGraphicsItem* addTriangle(); 32 | void removeTriangle(); 33 | 34 | virtual QGraphicsItem* addLabel(const QString& label); 35 | void removeLabel(); 36 | 37 | virtual void addBGMark(const QColor& c = QColor(32,32,32,32)); 38 | void removeBGMark(); 39 | 40 | virtual QPainterPath shape() const { 41 | return m_background->shape(); 42 | } 43 | 44 | virtual void clearField(); 45 | 46 | typedef boost::function mouse_callback_type; 47 | typedef boost::function wheel_callback_type; 48 | typedef boost::function hoover_callback_type; 49 | void setMousePressHandler(const mouse_callback_type& handler) { m_mousePressHandler = handler; } 50 | void setMouseDoubleClickHandler(const mouse_callback_type& handler) { m_mouseDoubleClickHandler = handler; } 51 | void setMouseReleaseHandler(const mouse_callback_type& handler) { m_mouseReleaseHandler = handler; } 52 | void setMouseWheelHandler(const wheel_callback_type& handler) { m_mouseWheelHandler = handler; } 53 | void setHooverEnterHandler(const hoover_callback_type& handler) { m_hooverEnterHandler = handler; } 54 | void setHooverLeaveHandler(const hoover_callback_type& handler) { m_hooverLeaveHandler = handler; } 55 | 56 | protected: 57 | virtual void mousePressEvent ( QGraphicsSceneMouseEvent * event ); 58 | virtual void mouseDoubleClickEvent ( QGraphicsSceneMouseEvent * event ); 59 | virtual void mouseReleaseEvent ( QGraphicsSceneMouseEvent * event ); 60 | virtual void wheelEvent ( QGraphicsSceneWheelEvent * event ); 61 | virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event ); 62 | virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ); 63 | 64 | virtual void removeItem(QGraphicsItem*& item); 65 | 66 | QAbstractGraphicsShapeItem *m_background; 67 | QGraphicsItem *m_stone; 68 | QGraphicsItem *m_mark; 69 | QGraphicsItem *m_circle; 70 | QGraphicsItem *m_square; 71 | QGraphicsItem *m_triangle; 72 | QGraphicsItem *m_label; 73 | boost::shared_ptr bgMark; 74 | 75 | mouse_callback_type m_mousePressHandler; 76 | mouse_callback_type m_mouseReleaseHandler; 77 | mouse_callback_type m_mouseDoubleClickHandler; 78 | wheel_callback_type m_mouseWheelHandler; 79 | hoover_callback_type m_hooverEnterHandler; 80 | hoover_callback_type m_hooverLeaveHandler; 81 | 82 | static const QString s_blackStoneFilename; 83 | static const QString s_whiteStoneFilename; 84 | 85 | static const qreal s_stoneAspectRatio; 86 | static const qreal s_shapeAspectRatio; 87 | 88 | static const QPen s_shapePen; 89 | 90 | static const qreal s_fieldZValue, s_stoneZValue, s_backgroundZValue, s_shapeZValue, s_labelZValue; 91 | }; 92 | 93 | #endif // FIELD_H 94 | -------------------------------------------------------------------------------- /source/libgamegui/GameScene.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARDSCENE_H_ 2 | #define BOARDSCENE_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class Field; 9 | class Grid; 10 | 11 | class GameScene: public QGraphicsScene 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | static GameScene *createHavannahScene(int size, QObject *parent = 0); 17 | static GameScene *createHexScene(int size, QObject *parent = 0); 18 | static GameScene *createHoScene(int size, QObject *parent = 0); 19 | static GameScene *createGoScene(int size, QObject *parent = 0); 20 | static GameScene *createYScene(int size, QObject *parent = 0); 21 | 22 | public: 23 | GameScene(Grid *grid, QObject *parent = 0); 24 | 25 | void clearBoard(); 26 | 27 | void addBlackStone(int x, int y); 28 | void addWhiteStone(int x, int y); 29 | void removeStone(int x, int y); 30 | 31 | void addMark(int x, int y); 32 | void removeMark(int x, int y); 33 | 34 | void addCircle(int x, int y); 35 | void removeCircle(int x, int y); 36 | 37 | void addSquare(int x, int y); 38 | void removeSquare(int x, int y); 39 | 40 | void addTriangle(int x, int y); 41 | void removeTriangle(int x, int y); 42 | 43 | void addLabel(int x, int y, const QString& label); 44 | void removeLabel(int x, int y); 45 | 46 | void addBGMark(int x, int y, const QColor& c = QColor(32,32,32,32)); 47 | void removeBGMark(int x, int y); 48 | 49 | static QString getFieldString(int x, int y); 50 | 51 | void handleMousePress(int x, int y, Qt::MouseButtons buttons); 52 | void handleMouseDoubleClick(int x, int y, Qt::MouseButtons buttons); 53 | void handleMouseRelease(int x, int y, Qt::MouseButtons buttons); 54 | void handleWheelMove(int x, int y, int delta); 55 | void handleHooverEnter(int x, int y); 56 | void handleHooverLeave(int x, int y); 57 | 58 | signals: 59 | void mousePressed(int x, int y, Qt::MouseButtons buttons); 60 | void mouseDoubleClicked(int x, int y, Qt::MouseButtons buttons); 61 | void mouseReleased(int x, int y, Qt::MouseButtons buttons); 62 | void mouseWheelMoved(int x, int y, int delta); 63 | void hooverEntered(int x, int y); 64 | void hooverLeft(int x, int y); 65 | 66 | protected: 67 | enum EShapeType 68 | { 69 | TypeBlackStone, 70 | TypeWhiteStone, 71 | TypeMark, 72 | TypeCircle, 73 | TypeSquare, 74 | TypeTriangle, 75 | TypeLabel, 76 | }; 77 | void addShape(int x, int y, EShapeType type, const QString& label = QString()); 78 | void removeShape(int x, int y, EShapeType type); 79 | 80 | QMutex m_mutex; 81 | Grid *m_grid; // not-null 82 | QGraphicsItem *m_ruler; 83 | typedef QMap map_type; 84 | map_type m_fields; 85 | }; 86 | 87 | #endif /* BOARDSCENE_H_ */ 88 | -------------------------------------------------------------------------------- /source/libgamegui/Grid.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Grid.h" 5 | #include "Field.h" 6 | 7 | const qreal Grid::s_gridZVlaue = 0.0; 8 | const qreal Grid::s_handicapSpotRadius = 3.0; 9 | 10 | Grid::Grid(int size, QGraphicsItem * parent) : 11 | QGraphicsItem(parent), m_size(size) 12 | { 13 | setZValue(s_gridZVlaue); 14 | } 15 | 16 | void Grid::drawHorizontalLines(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) const { 17 | QVector lines; 18 | for (int y = minimalYCoordinate(); y <= maximalYCoordinate(); y++) { 19 | bool started = false; 20 | int startX; 21 | for (int x = minimalXCoordinate(y); x <= maximalXCoordinate(y); x++) { 22 | if (!started && isValidCoordinate(x, y)) { 23 | started = true; 24 | startX = x; 25 | } 26 | if (started && !isValidCoordinate(x + 1, y)) { 27 | started = false; 28 | lines.push_back(QLineF(getFieldPosition(startX, y), getFieldPosition(x, y))); 29 | } 30 | } 31 | } 32 | painter->drawLines(lines); 33 | } 34 | 35 | void Grid::drawVerticalLines(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) const { 36 | QVector lines; 37 | for (int x = minimalXCoordinate(); x <= maximalXCoordinate(); x++) { 38 | bool started = false; 39 | int startY; 40 | for (int y = minimalYCoordinate(x); y <= maximalYCoordinate(x); y++) { 41 | if (!started && isValidCoordinate(x, y)) { 42 | started = true; 43 | startY = y; 44 | } 45 | if (started && !isValidCoordinate(x, y + 1)) { 46 | started = false; 47 | lines.push_back(QLineF(getFieldPosition(x, startY), getFieldPosition(x, y))); 48 | } 49 | } 50 | } 51 | painter->drawLines(lines); 52 | } 53 | 54 | void Grid::drawRightDiagonalLines(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) const { 55 | QVector lines; 56 | for (int sum = minimalXCoordinate() + minimalYCoordinate(); sum < maximalXCoordinate() + maximalYCoordinate(); sum++) { 57 | bool started = false; 58 | int startX; 59 | for (int x = minimalXCoordinate(); x <= maximalXCoordinate(); x++) { 60 | if (!started && isValidCoordinate(x, sum -x)) { 61 | started = true; 62 | startX = x; 63 | } 64 | if (started && !isValidCoordinate(x + 1, sum - x - 1)) { 65 | started = false; 66 | QPointF startPoint = getFieldPosition(startX, sum - startX); 67 | QPointF endPoint = getFieldPosition(x, sum - x); 68 | lines.push_back(QLineF(startPoint, endPoint)); 69 | } 70 | } 71 | } 72 | painter->drawLines(lines); 73 | } 74 | 75 | void Grid::drawLeftDiagonalLines(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) const { 76 | QVector lines; 77 | for (int diff = minimalYCoordinate() - maximalXCoordinate(); 78 | diff <= maximalYCoordinate() - minimalXCoordinate(); diff++) { 79 | bool started = false; 80 | int startX; 81 | for (int x = minimalXCoordinate(); x <= maximalXCoordinate(); x++) { 82 | if (!started && isValidCoordinate(x, x + diff)) { 83 | started = true; 84 | startX = x; 85 | } 86 | if (started && !isValidCoordinate(x + 1, x + 1 + diff)) { 87 | started = false; 88 | QPointF startPoint = getFieldPosition(startX, diff + startX); 89 | QPointF endPoint = getFieldPosition(x, x + diff); 90 | lines.push_back(QLineF(startPoint, endPoint)); 91 | } 92 | } 93 | } 94 | painter->drawLines(lines); 95 | } 96 | 97 | void Grid::drawHandicapSpots(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) const { 98 | painter->setBrush(Qt::black); 99 | QList > points = getHandicapCoordinates(); 100 | 101 | QPair point; 102 | foreach(point, points) 103 | { 104 | if (isValidCoordinate(point.first, point.second)) 105 | painter->drawEllipse(getFieldPosition(point.first, point.second), 106 | s_handicapSpotRadius , s_handicapSpotRadius); 107 | } 108 | } 109 | 110 | void Grid::drawFieldsShape(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) const { 111 | QTransform transform = painter->transform(); 112 | for (int x = minimalXCoordinate(); x <= maximalXCoordinate(); x++) { 113 | for (int y = minimalYCoordinate(x); y <= maximalYCoordinate(x); y++) { 114 | if (isValidCoordinate(x, y)) { 115 | painter->setTransform(transform); 116 | painter->translate(getFieldPosition(x, y)); 117 | painter->drawPath(getPath()); 118 | } 119 | } 120 | } 121 | } 122 | 123 | Field* Grid::createField(QGraphicsItem * parent) { 124 | return new Field(getPath(), parent); 125 | } 126 | 127 | bool Grid::isValidCoordinate(int x, int y) const { 128 | return (x >= minimalXCoordinate(y)) && (x <= maximalXCoordinate(y)) && 129 | (y >= minimalYCoordinate(x)) && (y <= maximalYCoordinate(x)); 130 | } 131 | -------------------------------------------------------------------------------- /source/libgamegui/Grid.h: -------------------------------------------------------------------------------- 1 | #ifndef GRID_H_ 2 | #define GRID_H_ 3 | 4 | #include 5 | 6 | #include 7 | 8 | class Field; 9 | class Ruler; 10 | 11 | class Grid: public QGraphicsItem 12 | { 13 | public: 14 | Grid(int size, QGraphicsItem * parent = 0); 15 | 16 | void drawHorizontalLines(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) const; 17 | void drawVerticalLines(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) const; 18 | void drawRightDiagonalLines(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) const; 19 | void drawLeftDiagonalLines(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) const; 20 | void drawHandicapSpots(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) const; 21 | void drawFieldsShape(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) const; 22 | 23 | virtual QList > getHandicapCoordinates() const = 0; 24 | 25 | virtual int minimalXCoordinate(int y) const = 0; 26 | virtual int maximalXCoordinate(int y) const = 0; 27 | 28 | virtual int minimalYCoordinate(int x) const = 0; 29 | virtual int maximalYCoordinate(int x) const = 0; 30 | 31 | virtual int minimalXCoordinate() const = 0; 32 | virtual int maximalXCoordinate() const = 0; 33 | 34 | virtual int minimalYCoordinate() const = 0; 35 | virtual int maximalYCoordinate() const = 0; 36 | 37 | virtual bool isValidCoordinate(int x, int y) const; 38 | 39 | virtual QPointF getFieldPosition(int x, int y) const = 0; 40 | 41 | virtual QPainterPath getPath() const = 0; 42 | virtual Ruler* createRuler() = 0; 43 | 44 | Field* createField(QGraphicsItem * parent = 0); 45 | 46 | virtual QPointF fieldSize() const = 0; 47 | 48 | protected: 49 | int m_size; 50 | static const qreal s_gridZVlaue; 51 | static const qreal s_handicapSpotRadius; 52 | }; 53 | 54 | #endif /* GRID_H_ */ 55 | -------------------------------------------------------------------------------- /source/libgamegui/HavannahGrid.cpp: -------------------------------------------------------------------------------- 1 | #include "HavannahGrid.h" 2 | 3 | #include "Ruler.h" 4 | 5 | const qreal HavannahGrid::s_width = 80; 6 | const qreal HavannahGrid::s_height = 40 * 1.73205; 7 | 8 | QRectF HavannahGrid::boundingRect() const { 9 | QPointF top = getFieldPosition(minimalXCoordinate(minimalYCoordinate()), minimalYCoordinate()); 10 | QPointF left = getFieldPosition(minimalXCoordinate(), maximalYCoordinate(minimalXCoordinate())); 11 | QPointF right = getFieldPosition(maximalXCoordinate(), minimalYCoordinate(maximalXCoordinate())); 12 | QPointF bottom = getFieldPosition(maximalXCoordinate(maximalYCoordinate()), maximalYCoordinate()); 13 | return QRectF(QPointF(left.x() , top.y()) - fieldSize() / 2, QPointF(right.x(), bottom.y()) + fieldSize() / 2); 14 | } 15 | 16 | void HavannahGrid::paint(QPainter *painter, const QStyleOptionGraphicsItem* style, QWidget* widget) { 17 | drawFieldsShape(painter, style, widget); 18 | } 19 | 20 | QList > HavannahGrid::getHandicapCoordinates() const { 21 | return QList >(); 22 | } 23 | 24 | int HavannahGrid::minimalXCoordinate(int y) const { 25 | int res = m_size / 2 + 2 - y; 26 | return (res < 1) ? 1 : res; 27 | } 28 | 29 | int HavannahGrid::maximalXCoordinate(int y) const { 30 | int res = m_size + m_size / 2 + 1 - y; 31 | return (res > m_size) ? m_size : res; 32 | } 33 | 34 | int HavannahGrid::minimalYCoordinate(int x) const { 35 | return minimalXCoordinate(x); 36 | } 37 | 38 | int HavannahGrid::maximalYCoordinate(int x) const { 39 | return maximalXCoordinate(x); 40 | } 41 | 42 | QPainterPath HavannahGrid::getPath() const { 43 | QPolygonF szesciokat(7); 44 | szesciokat[0] = QPointF(-s_width / 2, 0); 45 | szesciokat[1] = QPointF(-s_width / 4, -s_height / 2); 46 | szesciokat[2] = QPointF(s_width / 4, -s_height / 2); 47 | szesciokat[3] = QPointF(s_width / 2, 0); 48 | szesciokat[4] = QPointF(s_width / 4, s_height / 2); 49 | szesciokat[5] = QPointF(-s_width / 4, s_height / 2); 50 | szesciokat[6] = QPointF(-s_width / 2, 0); 51 | QPainterPath path; 52 | path.addPolygon(szesciokat); 53 | return path; 54 | } 55 | 56 | Ruler* HavannahGrid::createRuler() { 57 | return new Ruler(Ruler::LocateAfter | Ruler::TypeLetters, Ruler::LocateBefore, this); 58 | } 59 | 60 | QPointF HavannahGrid::getFieldPosition(int x, int y) const { 61 | return QPointF(0.75 * x * s_width, (0.5 * x + y) * s_height); 62 | } 63 | -------------------------------------------------------------------------------- /source/libgamegui/HavannahGrid.h: -------------------------------------------------------------------------------- 1 | #ifndef HAVANNAHGRID_H_ 2 | #define HAVANNAHGRID_H_ 3 | 4 | #include "Grid.h" 5 | 6 | class HavannahGrid : public Grid 7 | { 8 | public: 9 | HavannahGrid(int size, QGraphicsItem * parent = 0) : Grid(size, parent) {} 10 | 11 | virtual QRectF boundingRect() const; 12 | virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *style, QWidget *widget); 13 | 14 | virtual QList > getHandicapCoordinates() const; 15 | 16 | virtual int minimalXCoordinate(int y) const; 17 | virtual int maximalXCoordinate(int y) const; 18 | 19 | virtual int minimalYCoordinate(int x) const; 20 | virtual int maximalYCoordinate(int x) const; 21 | 22 | virtual int minimalXCoordinate() const { return 1; } 23 | virtual int maximalXCoordinate() const { return m_size; } 24 | 25 | virtual int minimalYCoordinate() const { return 1; } 26 | virtual int maximalYCoordinate() const { return m_size; } 27 | 28 | virtual QPainterPath getPath() const; 29 | virtual Ruler* createRuler(); 30 | 31 | virtual QPointF fieldSize() const { return QPointF(s_width, s_height); } 32 | 33 | protected: 34 | virtual QPointF getFieldPosition(int x, int y) const; 35 | 36 | static const qreal s_width, s_height; 37 | }; 38 | 39 | #endif /* HAVANNAHGRID_H_ */ 40 | -------------------------------------------------------------------------------- /source/libgamegui/HexGrid.cpp: -------------------------------------------------------------------------------- 1 | #include "HexGrid.h" 2 | 3 | #include "Ruler.h" 4 | 5 | const qreal HexGrid::s_width = 40 * 1.73205; 6 | const qreal HexGrid::s_height = 80; 7 | 8 | QRectF HexGrid::boundingRect() const { 9 | QPointF LL = getFieldPosition(minimalXCoordinate(), minimalYCoordinate(minimalXCoordinate())); 10 | QPointF LH = getFieldPosition(minimalXCoordinate(), maximalYCoordinate(minimalXCoordinate())); 11 | QPointF HL = getFieldPosition(maximalXCoordinate(), minimalYCoordinate(maximalXCoordinate())); 12 | QPointF HH = getFieldPosition(maximalXCoordinate(), maximalYCoordinate(maximalXCoordinate())); 13 | return QRectF(QPointF(LL.x(), HL.y()) - fieldSize() / 2, QPointF(HH.x(), LH.y()) + fieldSize() / 2); 14 | } 15 | 16 | void HexGrid::paint(QPainter *painter, const QStyleOptionGraphicsItem* style, QWidget* widget) { 17 | drawFieldsShape(painter, style, widget); 18 | } 19 | 20 | QList > HexGrid::getHandicapCoordinates() const { 21 | return QList >(); 22 | } 23 | 24 | QPainterPath HexGrid::getPath() const { 25 | QPolygonF szesciokat(7); 26 | szesciokat[0] = QPointF(0, -s_height / 2); 27 | szesciokat[1] = QPointF(s_width / 2, -s_height / 4); 28 | szesciokat[2] = QPointF(s_width / 2, s_height / 4); 29 | szesciokat[3] = QPointF(0, s_height / 2); 30 | szesciokat[4] = QPointF(-s_width / 2, s_height / 4); 31 | szesciokat[5] = QPointF(-s_width / 2, -s_height / 4); 32 | szesciokat[6] = QPointF(0, -s_height / 2); 33 | QPainterPath path; 34 | path.addPolygon(szesciokat); 35 | return path; 36 | } 37 | 38 | Ruler* HexGrid::createRuler() { 39 | return new Ruler(Ruler::LocateAfter | Ruler::LocateBefore | Ruler::TypeLetters, Ruler::LocateBefore | Ruler::LocateAfter, this); 40 | } 41 | 42 | QPointF HexGrid::getFieldPosition(int x, int y) const { 43 | return QPointF((x + 0.5 * y) * s_width, y * 0.75 * s_height); 44 | } 45 | -------------------------------------------------------------------------------- /source/libgamegui/HexGrid.h: -------------------------------------------------------------------------------- 1 | #ifndef HEXGRID_H_ 2 | #define HEXGRID_H_ 3 | 4 | #include "Grid.h" 5 | 6 | class HexGrid: public Grid 7 | { 8 | public: 9 | HexGrid(int size, QGraphicsItem * parent = 0) : Grid(size, parent) {} 10 | 11 | virtual QRectF boundingRect() const; 12 | virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *style, QWidget *widget); 13 | 14 | virtual QList > getHandicapCoordinates() const; 15 | 16 | virtual int minimalXCoordinate(int y) const { return 1; } 17 | virtual int maximalXCoordinate(int y) const { return m_size; } 18 | 19 | virtual int minimalYCoordinate(int x) const { return 1; } 20 | virtual int maximalYCoordinate(int x) const { return m_size; } 21 | 22 | virtual int minimalXCoordinate() const { return 1; } 23 | virtual int maximalXCoordinate() const { return m_size; } 24 | 25 | virtual int minimalYCoordinate() const { return 1; } 26 | virtual int maximalYCoordinate() const { return m_size; } 27 | 28 | virtual QPainterPath getPath() const; 29 | virtual Ruler* createRuler(); 30 | 31 | virtual QPointF fieldSize() const { return QPointF(s_width, s_height); } 32 | 33 | protected: 34 | virtual QPointF getFieldPosition(int x, int y) const; 35 | 36 | static const qreal s_width, s_height; 37 | }; 38 | 39 | #endif /* HEXGRID_H_ */ 40 | -------------------------------------------------------------------------------- /source/libgamegui/HoGrid.cpp: -------------------------------------------------------------------------------- 1 | #include "HoGrid.h" 2 | #include "Ruler.h" 3 | 4 | void HoGrid::paint(QPainter *painter, const QStyleOptionGraphicsItem* style, QWidget* widget) { 5 | drawVerticalLines(painter, style, widget); 6 | drawHorizontalLines(painter, style, widget); 7 | drawRightDiagonalLines(painter, style, widget); 8 | drawHandicapSpots(painter, style, widget); 9 | } 10 | 11 | QList > HoGrid::getHandicapCoordinates() const { 12 | QList > res; 13 | 14 | if (m_size > 4) { 15 | int diff = (m_size < 13) ? 2 : 3; 16 | int minXField = minimalXCoordinate() + diff; 17 | int maxXField = maximalXCoordinate() - diff; 18 | int minYField = minimalYCoordinate() + diff; 19 | int maxYField = maximalYCoordinate() - diff; 20 | 21 | 22 | res.push_back(QPair (minXField, minimalYCoordinate(minXField) + diff)); 23 | res.push_back(QPair (minXField, maximalYCoordinate(minXField) - diff)); 24 | res.push_back(QPair (maxXField, minimalYCoordinate(maxXField) + diff)); 25 | res.push_back(QPair (maxXField, maximalYCoordinate(maxXField) - diff)); 26 | res.push_back(QPair (minimalXCoordinate(minYField) + diff, minYField)); 27 | res.push_back(QPair (maximalXCoordinate(maxYField) - diff, maxYField)); 28 | res.push_back(QPair (minimalXCoordinate(minYField) + diff, maximalYCoordinate(maxXField) - diff)); 29 | } 30 | return res; 31 | } 32 | 33 | int HoGrid::minimalXCoordinate(int y) const { 34 | int res = m_size / 2 + 2 - y; 35 | return (res < 1) ? 1 : res; 36 | } 37 | 38 | int HoGrid::maximalXCoordinate(int y) const { 39 | int res = m_size + m_size / 2 + 1 - y; 40 | return (res > m_size) ? m_size : res; 41 | } 42 | 43 | int HoGrid::minimalYCoordinate(int x) const { 44 | return minimalXCoordinate(x); 45 | } 46 | 47 | int HoGrid::maximalYCoordinate(int x) const { 48 | return maximalXCoordinate(x); 49 | } 50 | 51 | Ruler* HoGrid::createRuler() { 52 | return new Ruler(Ruler::LocateAfter | Ruler::TypeLetters, Ruler::LocateBefore, this); 53 | } 54 | -------------------------------------------------------------------------------- /source/libgamegui/HoGrid.h: -------------------------------------------------------------------------------- 1 | #ifndef HOGRID_H_ 2 | #define HOGRID_H_ 3 | 4 | #include "HexGrid.h" 5 | 6 | class HoGrid: public HexGrid 7 | { 8 | public: 9 | HoGrid(int size, QGraphicsItem * parent = 0) : HexGrid(size, parent) {} 10 | 11 | virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *style, QWidget *widget); 12 | 13 | virtual QList > getHandicapCoordinates() const; 14 | 15 | virtual int minimalXCoordinate(int y) const; 16 | virtual int maximalXCoordinate(int y) const; 17 | 18 | virtual int minimalYCoordinate(int x) const; 19 | virtual int maximalYCoordinate(int x) const; 20 | 21 | virtual int minimalXCoordinate() const { return 1; } 22 | virtual int maximalXCoordinate() const { return m_size; } 23 | 24 | virtual int minimalYCoordinate() const { return 1; } 25 | virtual int maximalYCoordinate() const { return m_size; } 26 | 27 | 28 | virtual Ruler* createRuler(); 29 | }; 30 | 31 | #endif /* HOGRID_H_ */ 32 | -------------------------------------------------------------------------------- /source/libgamegui/ResizableView.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "ResizableView.h" 4 | 5 | ResizableView::ResizableView(QWidget *parent) : 6 | QGraphicsView(parent) 7 | { 8 | setResizeAnchor(QGraphicsView::AnchorViewCenter); 9 | setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 10 | setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 11 | } 12 | 13 | ResizableView::ResizableView(QGraphicsScene * scene, QWidget * parent) : 14 | QGraphicsView(scene, parent) 15 | { 16 | setResizeAnchor(QGraphicsView::AnchorViewCenter); 17 | setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 18 | setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 19 | } 20 | 21 | 22 | ResizableView::~ResizableView() 23 | { 24 | } 25 | 26 | void ResizableView::wheelEvent(QWheelEvent *event) 27 | { 28 | Q_UNUSED(event); 29 | ///* 30 | if (event->delta() > 0) 31 | scale(1.2, 1.2); 32 | else 33 | scale(1 / 1.2, 1 / 1.2); 34 | //*/ 35 | } 36 | 37 | void ResizableView::resizeEvent(QResizeEvent* event) 38 | { 39 | /* whole scene should be visible */ 40 | fitInView(scene()->sceneRect(), Qt::KeepAspectRatio); 41 | QGraphicsView::resizeEvent(event); 42 | } 43 | 44 | -------------------------------------------------------------------------------- /source/libgamegui/ResizableView.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARDVIEW_H_ 2 | #define BOARDVIEW_H_ 3 | 4 | #include 5 | 6 | class ResizableView: public QGraphicsView 7 | { 8 | Q_OBJECT 9 | 10 | public: 11 | ResizableView(QWidget *parent = 0); 12 | ResizableView(QGraphicsScene * scene, QWidget * parent = 0); 13 | ~ResizableView(); 14 | 15 | protected: 16 | void wheelEvent(QWheelEvent *event); 17 | virtual void resizeEvent(QResizeEvent * event); 18 | }; 19 | #endif /* BOARDVIEW_H_ */ 20 | -------------------------------------------------------------------------------- /source/libgamegui/Ruler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "Ruler.h" 4 | 5 | #include "Grid.h" 6 | 7 | const int Ruler::s_fontSize = 20; 8 | 9 | Ruler::Ruler(int verticalType, int horizontalType, Grid* grid) : 10 | QGraphicsItem(grid), m_grid(grid), m_verticalType(verticalType), m_horizontalType(horizontalType) { 11 | } 12 | 13 | QRectF Ruler::boundingRect() const { 14 | QPointF topLeft = m_grid->boundingRect().topLeft(); 15 | QPointF bottomRight = m_grid->boundingRect().bottomRight(); 16 | if (m_horizontalType & LocateBefore) 17 | topLeft -= QPointF(m_grid->fieldSize().x(), 0); 18 | if (m_horizontalType & LocateAfter) 19 | bottomRight += QPointF(m_grid->fieldSize().x(), 0); 20 | if (m_verticalType & LocateBefore) 21 | topLeft -= QPointF(0, m_grid->fieldSize().y()); 22 | if (m_verticalType & LocateAfter) 23 | bottomRight += QPointF(0, m_grid->fieldSize().y()); 24 | return QRectF(topLeft, bottomRight); 25 | } 26 | 27 | void Ruler::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { 28 | QFont font("Arial", s_fontSize); 29 | painter->setFont(font); 30 | 31 | if (m_horizontalType & LocateBefore) 32 | for (int y = m_grid->minimalYCoordinate(); y <= m_grid->maximalYCoordinate(); y++) { 33 | QRectF rect(m_grid->getFieldPosition(m_grid->minimalXCoordinate(y) - 1, y) - m_grid->fieldSize() / 2, 34 | QSizeF(m_grid->fieldSize().x() , m_grid->fieldSize().y() )); 35 | painter->drawText(rect, Qt::AlignHCenter | Qt::AlignVCenter, getCoordinateString(m_horizontalType, y)); 36 | } 37 | 38 | if (m_horizontalType & LocateAfter) 39 | for (int y = m_grid->minimalYCoordinate(); y <= m_grid->maximalYCoordinate(); y++) { 40 | QRectF rect(m_grid->getFieldPosition(m_grid->maximalXCoordinate(y) + 1, y) - m_grid->fieldSize() / 2, 41 | QSizeF(m_grid->fieldSize().x() , m_grid->fieldSize().y() )); 42 | painter->drawText(rect, Qt::AlignHCenter | Qt::AlignVCenter, getCoordinateString(m_horizontalType, y)); 43 | } 44 | 45 | if (m_verticalType & LocateBefore) 46 | for (int x = m_grid->minimalXCoordinate(); x <= m_grid->maximalXCoordinate(); x++) { 47 | QRectF rect(m_grid->getFieldPosition(x, m_grid->minimalYCoordinate(x) - 1) - m_grid->fieldSize() / 2, 48 | QSizeF(m_grid->fieldSize().x() , m_grid->fieldSize().y() )); 49 | painter->drawText(rect, Qt::AlignHCenter | Qt::AlignVCenter, getCoordinateString(m_verticalType, x)); 50 | } 51 | 52 | if (m_verticalType & LocateAfter) 53 | for (int x = m_grid->minimalXCoordinate(); x <= m_grid->maximalXCoordinate(); x++) { 54 | QRectF rect(m_grid->getFieldPosition(x, m_grid->maximalYCoordinate(x) + 1) - m_grid->fieldSize() / 2, 55 | QSizeF(m_grid->fieldSize().x() , m_grid->fieldSize().y() )); 56 | painter->drawText(rect, Qt::AlignHCenter | Qt::AlignVCenter, getCoordinateString(m_verticalType, x)); 57 | } 58 | } 59 | 60 | QString Ruler::getCoordinateString(int type, int coord) { 61 | if (type & TypeLetters) { 62 | return QString('A' - 1 + coord); 63 | } else { 64 | return QString::number(coord); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /source/libgamegui/Ruler.h: -------------------------------------------------------------------------------- 1 | #ifndef RULER_H_ 2 | #define RULER_H_ 3 | 4 | #include 5 | 6 | class Grid; 7 | 8 | class Ruler: public QGraphicsItem 9 | { 10 | public: 11 | enum ERulerType 12 | { 13 | LocateBefore = 0x1, 14 | LocateAfter = 0x2, 15 | TypeLetters = 0x4, 16 | }; 17 | 18 | Ruler(int verticalType, int horizontalType, Grid* /*not-null */ grid); 19 | 20 | virtual QRectF boundingRect() const; 21 | virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 22 | 23 | static QString getCoordinateString(int type, int coord); 24 | private: 25 | const Grid *m_grid; 26 | const int m_verticalType; 27 | const int m_horizontalType; 28 | 29 | static const int s_fontSize; 30 | }; 31 | 32 | #endif /* RULER_H_ */ 33 | -------------------------------------------------------------------------------- /source/libgamegui/SquareGrid.cpp: -------------------------------------------------------------------------------- 1 | #include "SquareGrid.h" 2 | #include "Ruler.h" 3 | 4 | const qreal SquareGrid::s_width = 40; 5 | const qreal SquareGrid::s_height = 40; 6 | 7 | QRectF SquareGrid::boundingRect() const { 8 | QPointF topLeft = getFieldPosition( 9 | (square_direction & ReverseX) ? maximalXCoordinate() : minimalXCoordinate() , 10 | (square_direction & ReverseY) ? maximalYCoordinate() : minimalYCoordinate() 11 | ) - fieldSize() / 2; 12 | QPointF bottomRight = getFieldPosition( 13 | (square_direction & ReverseX) ? minimalXCoordinate() : maximalXCoordinate(), 14 | (square_direction & ReverseY) ? minimalXCoordinate() : maximalYCoordinate() 15 | ) + fieldSize() / 2; 16 | return QRectF(topLeft, bottomRight); 17 | } 18 | 19 | void SquareGrid::paint(QPainter *painter, const QStyleOptionGraphicsItem* style, QWidget* widget) { 20 | drawVerticalLines(painter, style, widget); 21 | drawHorizontalLines(painter, style, widget); 22 | drawHandicapSpots(painter, style, widget); 23 | } 24 | 25 | QList > SquareGrid::getHandicapCoordinates() const { 26 | QList > res; 27 | 28 | if (m_size > 4) { 29 | int diff = (m_size < 13) ? 2 : 3; 30 | 31 | res.push_back(QPair (minimalXCoordinate() + diff, minimalYCoordinate() + diff)); 32 | res.push_back(QPair (minimalXCoordinate() + diff, maximalYCoordinate() - diff)); 33 | res.push_back(QPair (maximalXCoordinate() - diff, minimalYCoordinate() + diff)); 34 | res.push_back(QPair (maximalXCoordinate() - diff, maximalYCoordinate() - diff)); 35 | 36 | if (m_size & 1 && m_size > 8) { 37 | int middleXField = (minimalXCoordinate() + maximalXCoordinate()) / 2; 38 | int middleYField = (minimalYCoordinate() + maximalYCoordinate()) / 2; 39 | res.push_back(QPair (middleXField, minimalYCoordinate() + diff)); 40 | res.push_back(QPair (middleXField, maximalYCoordinate() - diff)); 41 | res.push_back(QPair (minimalXCoordinate() + diff, middleYField)); 42 | res.push_back(QPair (maximalXCoordinate() - diff, middleYField)); 43 | res.push_back(QPair (middleXField, middleYField)); 44 | } 45 | } 46 | return res; 47 | } 48 | 49 | QPointF SquareGrid::getFieldPosition(int x, int y) const { 50 | return QPointF(x * s_width, (maximalYCoordinate()-y) * s_height); 51 | } 52 | 53 | QPainterPath SquareGrid::getPath() const { 54 | QPainterPath path; 55 | path.addRect(-s_width / 2, -s_height / 2, s_width, s_height); 56 | return path; 57 | } 58 | 59 | Ruler* SquareGrid::createRuler() { 60 | return new Ruler(Ruler::LocateBefore | Ruler::LocateAfter | Ruler::TypeLetters, Ruler::LocateAfter 61 | | Ruler::LocateBefore, this); 62 | } 63 | -------------------------------------------------------------------------------- /source/libgamegui/SquareGrid.h: -------------------------------------------------------------------------------- 1 | #ifndef SQUAREGRID_H_ 2 | #define SQUAREGRID_H_ 3 | 4 | #include "Grid.h" 5 | 6 | class SquareGrid: public Grid 7 | { 8 | public: 9 | enum ESquareDirection 10 | { 11 | ReverseX = 0x1, 12 | ReverseY = 0x2 13 | }; 14 | SquareGrid(int size, int direction, QGraphicsItem * parent = 0) : 15 | Grid(size, parent), 16 | square_direction(direction) 17 | { 18 | } 19 | 20 | virtual QRectF boundingRect() const; 21 | virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *style, QWidget *widget); 22 | 23 | virtual QList > getHandicapCoordinates() const; 24 | 25 | virtual int minimalXCoordinate(int ) const { return 1; } 26 | virtual int maximalXCoordinate(int ) const { return m_size; } 27 | 28 | virtual int minimalYCoordinate(int ) const { return 1; } 29 | virtual int maximalYCoordinate(int ) const { return m_size; } 30 | 31 | virtual int minimalXCoordinate() const { return 1; } 32 | virtual int maximalXCoordinate() const { return m_size; } 33 | 34 | virtual int minimalYCoordinate() const { return 1; } 35 | virtual int maximalYCoordinate() const { return m_size; } 36 | 37 | virtual QPainterPath getPath() const; 38 | virtual Ruler* createRuler(); 39 | 40 | virtual QPointF fieldSize() const { return QPointF(s_width, s_height); } 41 | 42 | protected: 43 | virtual QPointF getFieldPosition(int x, int y) const; 44 | 45 | static const qreal s_width, s_height; 46 | 47 | int square_direction; 48 | }; 49 | 50 | #endif /* SQUAREGRID_H_ */ 51 | -------------------------------------------------------------------------------- /source/libgamegui/YGrid.cpp: -------------------------------------------------------------------------------- 1 | #include "YGrid.h" 2 | #include "Ruler.h" 3 | 4 | YGrid::YGrid(int size, QGraphicsItem * parent) : HexGrid(size, parent) {} 5 | 6 | QRectF YGrid::boundingRect() const { 7 | QPointF top = getFieldPosition(maximalXCoordinate(), minimalYCoordinate(maximalXCoordinate())); 8 | QPointF bottomLeft = getFieldPosition(minimalXCoordinate(maximalYCoordinate()), maximalYCoordinate()); 9 | QPointF bottomRight = getFieldPosition(maximalXCoordinate(maximalYCoordinate()), maximalYCoordinate()); 10 | return QRectF(QPointF(bottomLeft.x(), top.y()) - fieldSize() / 2, bottomRight + fieldSize() / 2); 11 | } 12 | 13 | void YGrid::paint(QPainter *painter, const QStyleOptionGraphicsItem *style, QWidget *widget) { 14 | drawFieldsShape(painter, style, widget); 15 | } 16 | 17 | Ruler* YGrid::createRuler() { 18 | return new Ruler( Ruler::LocateAfter | Ruler::TypeLetters, Ruler::LocateBefore, this); 19 | } 20 | -------------------------------------------------------------------------------- /source/libgamegui/YGrid.h: -------------------------------------------------------------------------------- 1 | #ifndef YGRID_H_ 2 | #define YGRID_H_ 3 | 4 | #include "HexGrid.h" 5 | 6 | class YGrid: public HexGrid 7 | { 8 | public: 9 | YGrid(int size, QGraphicsItem * parent = 0); 10 | 11 | virtual QRectF boundingRect() const; 12 | virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *style, QWidget *widget); 13 | 14 | virtual int minimalXCoordinate(int y) const { return m_size - y + 1; } 15 | virtual int maximalXCoordinate(int y) const { return m_size; } 16 | 17 | virtual int minimalYCoordinate(int x) const { return m_size - x + 1; } 18 | virtual int maximalYCoordinate(int x) const { return m_size; } 19 | 20 | virtual int minimalXCoordinate() const { return 1; } 21 | virtual int maximalXCoordinate() const { return m_size; } 22 | 23 | virtual int minimalYCoordinate() const { return 1; } 24 | virtual int maximalYCoordinate() const { return m_size; } 25 | 26 | Ruler* createRuler(); 27 | 28 | 29 | }; 30 | 31 | #endif /* YGRID_H_ */ 32 | -------------------------------------------------------------------------------- /source/libgamegui/images.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/gogui-black-32x32.png 4 | images/gogui-black.svg 5 | images/gogui-white-32x32.png 6 | images/gogui-white.svg 7 | images/wood.png 8 | 9 | 10 | -------------------------------------------------------------------------------- /source/libgamegui/images/gogui-black-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukaszlew/libego/9c50391a5b37cbf74b403a508a9b153cd7b32735/source/libgamegui/images/gogui-black-32x32.png -------------------------------------------------------------------------------- /source/libgamegui/images/gogui-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 22 | 24 | 27 | 31 | 35 | 36 | 47 | 48 | 66 | 68 | 69 | 71 | image/svg+xml 72 | 74 | 75 | 76 | 77 | 81 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /source/libgamegui/images/gogui-white-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukaszlew/libego/9c50391a5b37cbf74b403a508a9b153cd7b32735/source/libgamegui/images/gogui-white-32x32.png -------------------------------------------------------------------------------- /source/libgamegui/images/gogui-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 22 | 24 | 27 | 31 | 35 | 36 | 47 | 50 | 54 | 58 | 59 | 70 | 71 | 89 | 91 | 92 | 94 | image/svg+xml 95 | 97 | 98 | 99 | 100 | 104 | 117 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /source/libgamegui/images/wood.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukaszlew/libego/9c50391a5b37cbf74b403a508a9b153cd7b32735/source/libgamegui/images/wood.png -------------------------------------------------------------------------------- /source/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set_cxx_flags (FALSE) 2 | 3 | include_directories (${libego_SOURCE_DIR}/utils) 4 | include_directories (${libego_SOURCE_DIR}/goboard) 5 | include_directories (${libego_SOURCE_DIR}/gtp) 6 | include_directories (${libego_SOURCE_DIR}/engine) 7 | # include_directories (${libego_SOURCE_DIR}/libgamegui) 8 | # include_directories (${libego_SOURCE_DIR}/gui) 9 | 10 | add_executable (engine main.cpp) #TODO make mm_train separate executable 11 | # target_link_libraries (engine ai gui gamegui) 12 | target_link_libraries (engine ai) 13 | 14 | install (TARGETS engine ${INSTALL_TARGETS_DEFAULT_ARGS}) 15 | -------------------------------------------------------------------------------- /source/main/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #include "gtp_gogui.hpp" 6 | 7 | Gtp::ReplWithGogui gtp; 8 | //Gtp::Repl& gtp = gtp2; 9 | 10 | #include "engine.hpp" 11 | //#include "gui.h" 12 | #include "mcts_gtp.hpp" 13 | #include "mm_train.hpp" 14 | 15 | 16 | 17 | // TODO automatize through CMake (and add git SHA1) 18 | #ifndef VERSION 19 | #define VERSION unknown 20 | #endif 21 | 22 | void GtpBenchmark (Gtp::Io& io) { 23 | uint n = io.Read (100000); 24 | io.CheckEmpty (); 25 | io.out << Benchmark::Run (n); 26 | } 27 | 28 | void GtpBoardTest (Gtp::Io& io) { 29 | bool print_moves = io.Read (false); 30 | io.CheckEmpty (); 31 | PlayoutTest (print_moves); 32 | } 33 | 34 | void GtpSamplerTest (Gtp::Io& io) { 35 | bool print_moves = io.Read (false); 36 | io.CheckEmpty (); 37 | SamplerPlayoutTest (print_moves); 38 | } 39 | 40 | void GtpMmTest (Gtp::Io& io) { 41 | io.CheckEmpty (); 42 | Mm::Test (); 43 | } 44 | 45 | int main(int argc, char** argv) { 46 | // no buffering to work well with gogui 47 | setbuf (stdout, NULL); 48 | setbuf (stderr, NULL); 49 | //srand48 (123); 50 | 51 | gtp.RegisterStatic("name", "Libego"); 52 | gtp.RegisterStatic("version", STRING(VERSION)); 53 | gtp.RegisterStatic("protocol_version", "2"); 54 | gtp.Register ("benchmark", GtpBenchmark); 55 | gtp.Register ("board_test", GtpBoardTest); 56 | gtp.Register ("sampler_test", GtpSamplerTest); 57 | gtp.Register ("mm_test", GtpMmTest); 58 | 59 | Engine& engine = *(new Engine()); 60 | MctsGtp mcts_gtp (engine); 61 | 62 | reps (ii, 1, argc) { 63 | if (ii == argc-1 && string (argv[ii]) == "gtp") continue; 64 | string response; 65 | switch (gtp.RunOneCommand (argv[ii], &response)) { 66 | case Gtp::Repl::Success: 67 | cerr << response << endl; 68 | break; 69 | case Gtp::Repl::Failure: 70 | cerr << "Command: \"" << argv[ii] << "\" failed." << endl; 71 | return 1; 72 | case Gtp::Repl::NoOp: 73 | break; 74 | case Gtp::Repl::Quit: 75 | cerr << response << endl; 76 | return 0; 77 | } 78 | } 79 | 80 | if (argc == 1 || string(argv[argc-1]) == "gtp") { 81 | gtp.Run (cin, cout); 82 | } 83 | 84 | delete &engine; 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /source/main/mm_train.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "all_hash3x3.hpp" 3 | #include "mm.hpp" 4 | 5 | struct MmTrain { 6 | MmTrain () : 7 | random(123), 8 | pattern_level (uint(-1)) 9 | { 10 | gtp.Register ("mm_train", this, &MmTrain::GtpMmTrain); 11 | } 12 | 13 | void GtpMmTrain (Gtp::Io& io) { 14 | string file_name = io.Read (); 15 | string out_file_name = io.Read (); 16 | uint needed_moves = io.Read (); 17 | uint epochs = io.Read (); 18 | io.CheckEmpty(); 19 | 20 | ifstream file; 21 | ofstream out_file; 22 | 23 | file.open (file_name.c_str(), ifstream::in); 24 | if (!file.good()) { 25 | io.SetError ("Can't open in-file: " + file_name); 26 | return; 27 | } 28 | 29 | out_file.open (out_file_name.c_str(), ofstream::out); 30 | if (!out_file.good()) { 31 | io.SetError ("Can't open out-file: " + out_file_name); 32 | return; 33 | } 34 | 35 | cerr << "Initializing..." << endl << flush; 36 | Init (); 37 | cerr << "Reading game file..." << endl << flush; 38 | Read (file, needed_moves); 39 | file.close (); 40 | cerr << "Harvesting pattern data..." << endl << flush; 41 | Harvest(); 42 | cerr << "Learning..." << endl << flush; 43 | Learn (epochs); 44 | cerr << "Dumping..." << endl << flush; 45 | Dump (out_file); 46 | cerr << "Done." << endl << flush; 47 | out_file.close (); 48 | } 49 | 50 | void Read (istream& in, double needed_move_count) { 51 | uint game_no = 0; 52 | uint total_move_count = 0; 53 | 54 | string s; 55 | while (in >> s) { 56 | CHECK (s == "file"); 57 | games.resize (game_no + 1); 58 | files.resize (game_no + 1); 59 | 60 | getline (in, files[game_no]); 61 | CHECK (in); 62 | 63 | uint bs; 64 | CHECK (in >> bs); 65 | 66 | uint move_count; 67 | CHECK (in >> move_count); 68 | total_move_count += move_count; 69 | 70 | games [game_no].resize (move_count); 71 | rep (ii, move_count) { 72 | Move m = Move::OfGtpStream (in); 73 | CHECK (m.IsValid ()); 74 | games [game_no] [ii] = m; 75 | } 76 | if (bs == board_size) { 77 | game_no += 1; 78 | } 79 | } 80 | 81 | accept_prob = needed_move_count / total_move_count; 82 | WW (accept_prob); 83 | } 84 | 85 | void Init () { 86 | All2051Hash3x3 all2051; 87 | level_to_pattern.resize (2051); 88 | all2051.Generate (5000); 89 | CHECK (all2051.unique.size() == 2051); 90 | rep (level, 2051) { 91 | Hash3x3 all[8]; 92 | all2051.unique [level].GetAll8Symmetries (all); 93 | rep (ii, 8) { 94 | pattern_level [all [ii]] = level; 95 | } 96 | level_to_pattern [level] = all [0]; 97 | } 98 | } 99 | 100 | void Harvest () { 101 | rep (game_no, games.size()) { 102 | if (game_no % (games.size() / 50) == 0) { 103 | cerr << "." << flush; 104 | } 105 | const vector & moves = games[game_no]; 106 | board.Clear (); 107 | 108 | rep (move_no, moves.size()) { 109 | Move m = moves [move_no]; 110 | HarvestNewMatch (m); 111 | CHECK2 (board.IsLegal (m), { 112 | cerr 113 | << "Illegal move " << m.ToGtpString() 114 | << " nr " << move_no 115 | << " in file " << files[game_no] 116 | << endl; 117 | }); 118 | board.PlayLegal (m); 119 | } 120 | } 121 | cerr << endl; 122 | } 123 | 124 | void HarvestNewMatch (Move m) { 125 | if (random.NextDouble () > accept_prob) return; 126 | 127 | Player pl = m.GetPlayer (); 128 | 129 | Mm::Match& match = model.NewMatch(); 130 | 131 | rep (ii, board.EmptyVertexCount()) { 132 | Vertex v = board.EmptyVertex (ii); 133 | if (!board.IsLegal (pl, v)) continue; 134 | 135 | Hash3x3 hash = board.Hash3x3At (v); 136 | 137 | if (pl == Player::White ()) { 138 | hash = hash.InvertColors(); 139 | } 140 | 141 | CHECK (pattern_level [hash] != uint(-1)); 142 | 143 | Mm::Team& team = match.NewTeam(); 144 | team.SetFeatureLevel (Mm::kPatternFeature, pattern_level [hash]); 145 | 146 | if (v == m.GetVertex()) { 147 | match.SetWinnerLastTeam(); 148 | } 149 | } 150 | } 151 | 152 | void Learn (uint epochs) { 153 | WW(model.matches.size()); 154 | 155 | model.PreprocessData (); 156 | model.Train (epochs); 157 | } 158 | 159 | void Dump (ostream& out) { 160 | vector > sort_tab (2051); 161 | rep (level, 2051) { 162 | sort_tab [level].first = model.gammas.Get (Mm::kPatternFeature, level); 163 | sort_tab [level].second = level; 164 | } 165 | std::sort (sort_tab.begin(), sort_tab.end()); 166 | rep (level, 2051) { 167 | out 168 | << setw(7) << level_to_pattern [sort_tab [level].second].GetRaw() << ", " 169 | << sort_tab [level].first 170 | << endl; 171 | } 172 | } 173 | 174 | vector > games; 175 | vector files; 176 | double accept_prob; 177 | 178 | Board board; 179 | FastRandom random; 180 | Mm::BtModel model; 181 | 182 | NatMap pattern_level; 183 | vector level_to_pattern; 184 | }; 185 | 186 | MmTrain mm_train; 187 | -------------------------------------------------------------------------------- /source/mm_preprocess_sgf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import sys 4 | import re, os 5 | 6 | file = "" 7 | fail = False 8 | 9 | def toCoords (m): 10 | if (m in ("tt", "ti")): return "pass" 11 | rows = "ABCDEFGHJKLMNOPQRST" 12 | row = ord(m[0]) - ord('a') 13 | col = 19-ord(m[1]) + ord('a') 14 | if (row in range(19) and col in range(1,20)): 15 | return "%s%d" % (rows [row], col) 16 | else: 17 | global fail 18 | fail = True 19 | 20 | def doFile (name): 21 | global file, fail 22 | file = name 23 | fail = False 24 | 25 | f = open(name, 'rb').read() 26 | f = filter(lambda g: not g.isspace(), f) 27 | 28 | f = re.sub ('EV\[[^]]*\]', '', f) 29 | f = re.sub ('PW\[[^]]*\]', '', f) 30 | f = re.sub ('PB\[[^]]*\]', '', f) 31 | f = re.sub ('SO\[[^]]*\]', '', f) 32 | f = re.sub ('DT\[[^]]*\]', '', f) 33 | 34 | assert (f[0] == '(' and f[-1] == ')') 35 | f = f[1:-1] 36 | l = f.split (';'); 37 | 38 | assert (l[0] == "") 39 | 40 | header = l[1] 41 | moves = l[2:] 42 | 43 | size = re.search('SZ\\[([^]]*)\\]', header).group(1) 44 | 45 | ret_moves = [] 46 | 47 | 48 | handi = re.search('AB((\[..\])+)', header) 49 | if handi != None: 50 | hcs = handi.group(1).split("[") 51 | assert (hcs [0] == "") 52 | hcs = hcs[1:] 53 | handi_n = 0 54 | for hc in hcs: 55 | assert (len(hc) == 3) 56 | assert (hc[2] == ']') 57 | ret_moves.append ("B %s" % toCoords (hc[:2])) 58 | handi_n += 1 59 | xx = re.search('HA\[([1-9])\]', header) 60 | if xx != None: 61 | assert handi_n == int (xx.group(1)) 62 | 63 | 64 | 65 | for m in moves: 66 | if not len (m) in (3, 5): 67 | fail = True 68 | return (19, []) 69 | assert (m[0] in ('W', 'B')) 70 | assert (m[1] == '[') 71 | assert (m[-1] == ']') 72 | if (len(m) == 3): 73 | ret_moves.append ("%s pass" % (m[0])) 74 | else: 75 | ret_moves.append ("%s %s" % (m[0], toCoords (m[2:4]))) 76 | 77 | return (size, ret_moves) 78 | 79 | 80 | try: 81 | for root, _, files in os.walk(sys.argv[1], topdown=False): 82 | for name in files: 83 | (size, moves) = doFile ((os.path.join(root, name))) 84 | if (not fail): 85 | print "file", file 86 | print size, len(moves) 87 | print "\n".join (moves) 88 | print 89 | else: 90 | sys.stderr.write ("Bad file: ") 91 | sys.stderr.write (file) 92 | sys.stderr.write ("\n") 93 | except Exception, err: 94 | sys.stderr.write (file + "\n") 95 | raise err 96 | -------------------------------------------------------------------------------- /source/utils/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set_cxx_flags (FALSE) 2 | 3 | # find_package (Boost COMPONENTS date_time filesystem REQUIRED) 4 | # include_directories (${Boost_INCLUDE_DIRS}) 5 | # link_directories (${Boost_LIBRARY_DIRS}) 6 | 7 | add_library(utils test.cpp) 8 | # target_link_libraries (utils ${Boost_LIBRARIES}) 9 | -------------------------------------------------------------------------------- /source/utils/fast_random.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #include "fast_random.hpp" 6 | #include "cstdio" 7 | 8 | #ifdef __MINGW32__ 9 | #include 10 | #endif 11 | 12 | //tr1::minstd_rand0 mt; // this is eqivalent when #include 13 | 14 | FastRandom::FastRandom (uint seed) : seed (seed) { 15 | } 16 | 17 | FastRandom::FastRandom () : seed (TimeSeed()) { 18 | } 19 | 20 | void FastRandom::SetSeed (uint new_seed) { 21 | seed = new_seed; 22 | } 23 | 24 | uint FastRandom::GetSeed () { 25 | return seed; 26 | } 27 | 28 | uint FastRandom::GetNextUint () { // a number between 0 ... (uint(1)<<31) - 1 - 1 29 | uint hi, lo; 30 | lo = 16807 * (seed & 0xffff); 31 | hi = 16807 * (seed >> 16); 32 | lo += (hi & 0x7fff) << 16; 33 | lo += hi >> 15; 34 | seed = (lo & 0x7FFFFFFF) + (lo >> 31); 35 | return seed; 36 | } 37 | 38 | // n must be between 1 .. (1<<16) + 1 39 | uint FastRandom::GetNextUint (uint n) { // 0 .. n-1 40 | ASSERT (n > 0); 41 | ASSERT (n <= (1<<16)+1); 42 | return ((GetNextUint() & 0xffff) * n) >> 16; 43 | } 44 | 45 | double FastRandom::NextDouble () { 46 | const double inv_max_uint = 1.0 / double (uint(1) << 31); // TODO - 1 - 1 47 | return GetNextUint() * inv_max_uint; 48 | } 49 | 50 | double FastRandom::NextDouble (double scale) { 51 | const double inv_max_uint = 1.0 / double (uint(1) << 31); // TODO - 1 - 1 52 | uint s = GetNextUint(); 53 | double ret = double (s) * (inv_max_uint * scale); 54 | return ret; 55 | } 56 | 57 | /* 58 | // TODO move it to test 59 | void FastRandom::test () { 60 | uint start = GetNextUint (); 61 | 62 | uint n = 1; 63 | uint max = 0; 64 | uint sum = start; 65 | 66 | while (true) { 67 | uint r = GetNextUint (); 68 | if (r == start) break; 69 | n++; 70 | sum += r; 71 | if (max < r) max = r; 72 | } 73 | printf ("n = %d\n", n); 74 | printf ("max = %d\n", max); 75 | printf ("sum = %d\n", sum); 76 | } 77 | 78 | void FastRandom::test2 (uint k, uint n) { 79 | uint* bucket = new uint[k]; 80 | 81 | rep (ii, k) bucket [ii] = 0; 82 | rep (ii, n) { 83 | uint r = GetNextUint (k); 84 | ASSERT (r < k); 85 | bucket [r] ++; 86 | } 87 | rep (ii, k) printf ("%d\n", bucket [ii]); 88 | delete[] bucket; 89 | } 90 | */ 91 | -------------------------------------------------------------------------------- /source/utils/fast_random.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #ifndef FAST_RANDOM_ 6 | #define FAST_RANDOM_ 7 | 8 | #include "utils.hpp" 9 | 10 | class FastRandom { // Park - Miller "minimal standard" 11 | public: 12 | 13 | FastRandom (); 14 | FastRandom (uint seed); 15 | void SetSeed (uint seed); 16 | uint GetSeed (); 17 | 18 | uint GetNextUint (); 19 | uint GetNextUint (uint n); // n must be between 1 .. (1<<16) + 1 20 | 21 | double NextDouble (); 22 | double NextDouble (double scale); 23 | 24 | uint seed; 25 | }; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /source/utils/fast_stack.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #ifndef FAST_STACK_H_ 6 | #define FAST_STACK_H_ 7 | 8 | #include 9 | 10 | #include "utils.hpp" 11 | #include "fast_random.hpp" 12 | 13 | template class FastStack { 14 | public: 15 | FastStack () : size (0) { 16 | } 17 | 18 | void Clear () { 19 | size = 0; 20 | } 21 | 22 | bool IsEmpty () const { 23 | return size == 0; 24 | } 25 | 26 | bool IsFull () const { 27 | return size == max_size; 28 | } 29 | 30 | uint Size() const { 31 | return size; 32 | } 33 | 34 | uint Capacity () const { 35 | return max_size - size; 36 | } 37 | 38 | Elt* Data() { 39 | return tab; 40 | } 41 | 42 | const Elt* Data() const { 43 | return tab; 44 | } 45 | 46 | vector AsVector () { 47 | vector ret(size); 48 | rep (ii, size) ret[ii] = tab[ii]; 49 | return ret; 50 | } 51 | 52 | void Push (const Elt& elt) { 53 | tab [size++] = elt; 54 | Check (); 55 | } 56 | 57 | Elt& Top () { 58 | ASSERT (size > 0); 59 | return tab [size-1]; 60 | } 61 | 62 | Elt& NewTop() { 63 | size += 1; 64 | Check(); 65 | return Top(); 66 | } 67 | 68 | void Pop () { 69 | size--; 70 | Check (); 71 | } 72 | 73 | Elt Remove (uint idx) { 74 | Elt elt = tab [idx]; 75 | size--; 76 | tab [idx] = tab [size]; 77 | return elt; 78 | } 79 | 80 | Elt& PopTop () { 81 | size--; 82 | Check(); 83 | return tab [size]; 84 | } 85 | 86 | Elt& operator[] (uint i) { 87 | ASSERT (i < size); 88 | return tab [i]; 89 | } 90 | 91 | const Elt& operator[] (uint i) const { 92 | ASSERT (i < size); 93 | return tab [i]; 94 | } 95 | 96 | private: 97 | void Check () const { 98 | ASSERT (size <= max_size); 99 | } 100 | 101 | private: 102 | Elt tab [max_size]; 103 | uint size; 104 | }; 105 | 106 | // TODO add iterators 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /source/utils/fast_timer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | // TODO move such stuff to porting.h (or somwhere) 6 | #if defined(_MSC_VER) || defined(__MINGW32__) 7 | #include 8 | #else 9 | #include 10 | #include 11 | #endif 12 | 13 | #ifdef _MSC_VER 14 | #include 15 | #pragma intrinsic(__rdtsc) 16 | #endif 17 | 18 | #include 19 | #include 20 | 21 | #include "fast_timer.hpp" 22 | 23 | // ----------------------------------------------------------------------------- 24 | 25 | FastTimer::FastTimer () { 26 | Reset (); 27 | uint64 t1, t2; 28 | t1 = GetCcTime (); 29 | t2 = GetCcTime (); 30 | overhead = double (t2 - t1); 31 | } 32 | 33 | 34 | uint64 FastTimer::GetCcTime () { 35 | # ifdef _MSC_VER 36 | return __rdtsc(); 37 | # else 38 | if (sizeof(long) == 8) { 39 | uint64 a, d; 40 | asm volatile ("rdtsc\n\t" : "=a"(a), "=d"(d)); 41 | return (d << 32) | (a & 0xffffffff); 42 | } else { 43 | uint64 l; 44 | asm volatile ("rdtsc\n\t" : "=A"(l)); 45 | return l; 46 | } 47 | # endif //_MSC_VER 48 | } 49 | 50 | 51 | void FastTimer::Reset () { 52 | sample_cnt = 0; 53 | sample_sum = 0; 54 | } 55 | 56 | 57 | void FastTimer::Start () { 58 | start_time = GetCcTime (); 59 | } 60 | 61 | 62 | void FastTimer::Stop () { 63 | uint64 stop_time; 64 | stop_time = GetCcTime (); 65 | sample_cnt += 1.0; 66 | sample_sum += double (stop_time - start_time) - overhead; 67 | } 68 | 69 | 70 | double FastTimer::Ticks () { 71 | return sample_sum / sample_cnt; 72 | } 73 | 74 | 75 | string FastTimer::ToString (float unit) { 76 | ostringstream s; 77 | s.precision(15); 78 | s << "avg CC = " << Ticks () / unit << " (cnt = " << sample_cnt << ")"; 79 | return s.str (); 80 | } 81 | 82 | 83 | int TimeSeed () { 84 | FastTimer timer; 85 | return (int)timer.GetCcTime(); 86 | } 87 | 88 | 89 | float ProcessUserTime () { 90 | # ifndef WIN32 91 | 92 | rusage usage [1]; 93 | getrusage (RUSAGE_SELF, usage); 94 | return 95 | float(usage->ru_utime.tv_sec) + 96 | float(usage->ru_utime.tv_usec) / 1000000.0; 97 | 98 | # elif defined(_MSC_VER) || defined(__MINGW32__) 99 | 100 | union { FILETIME t; __int64 i64; } start, exit, kernel, user; 101 | if (GetProcessTimes(GetCurrentProcess(), &start.t, &exit.t, &kernel.t, &user.t)) { 102 | __int64 userMicro = user.i64 / 10U; //(*((__int64*) &user.t)) / 10U; 103 | return (float)((double)userMicro / 1000000.0f); 104 | } else { 105 | return 0; 106 | } 107 | 108 | # else 109 | 110 | return 0; 111 | 112 | # endif 113 | } 114 | 115 | // TODO use this to port rusage to windows/mingw 116 | // http://octave.sourceforge.net/doxygen/html/getrusage_8cc-source.html 117 | // http://stackoverflow.com/questions/771944/how-to-measure-user-time-used-by-process-on-windows 118 | // http://www.ginac.de/pipermail/ginac-list/2006-July/000861.html 119 | 120 | -------------------------------------------------------------------------------- /source/utils/fast_timer.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #ifndef FAST_TIMER_H_ 6 | #define FAST_TIMER_H_ 7 | 8 | #include 9 | 10 | class FastTimer { 11 | public: 12 | FastTimer (); 13 | void Reset(); 14 | void Start(); 15 | void Stop(); 16 | double Ticks(); 17 | std::string ToString (float unit = 1.0); 18 | 19 | public: 20 | static uint64 GetCcTime (); 21 | 22 | double sample_cnt; 23 | double sample_sum; 24 | uint64 start_time; 25 | double overhead; 26 | }; 27 | 28 | float ProcessUserTime (); 29 | int TimeSeed (); 30 | 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /source/utils/nat-inl.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #ifndef NAT_INL_H_ 6 | #define NAT_INL_H_ 7 | 8 | #include "test.hpp" 9 | #include 10 | #include 11 | 12 | 13 | template 14 | T Nat::OfRaw (uint raw) { 15 | ASSERT (raw < T::kBound); 16 | return T (raw); 17 | } 18 | 19 | template 20 | T Nat::Invalid() { 21 | return T (-1); 22 | } 23 | 24 | template 25 | Nat::Nat () : raw (-1) { 26 | } 27 | 28 | // Utils. 29 | 30 | template 31 | bool Nat::MoveNext() { 32 | if (raw+1 == T::kBound) { 33 | return false; 34 | } 35 | raw += 1; 36 | return true; 37 | } 38 | 39 | template 40 | uint Nat::GetRaw() const { 41 | return raw; 42 | } 43 | 44 | template 45 | bool Nat::IsValid() const { 46 | return *this != Invalid(); 47 | } 48 | 49 | template 50 | bool Nat::operator == (const Nat& other) const { 51 | return this->raw == other.raw; 52 | } 53 | 54 | template 55 | bool Nat::operator != (const Nat& other) const { 56 | return this->raw != other.raw; 57 | } 58 | 59 | template 60 | Nat::Nat (uint raw) : raw (raw) { 61 | ASSERT (raw < T::kBound || raw == static_cast (-1)); 62 | } 63 | 64 | // ----------------------------------------------------------------------------- 65 | 66 | template 67 | NatMap ::NatMap () { 68 | } 69 | 70 | template 71 | NatMap ::NatMap (const Elt& init) { 72 | SetAll (init); 73 | } 74 | 75 | template 76 | Elt& NatMap ::operator [] (Nat nat) { 77 | ASSERT (nat != Nat::Invalid()); 78 | return tab [nat.GetRaw()]; 79 | } 80 | 81 | template 82 | const Elt& NatMap ::operator [] (Nat nat) const { 83 | ASSERT (nat != Nat::Invalid()); 84 | return tab [nat.GetRaw()]; 85 | } 86 | 87 | template 88 | void NatMap ::SetAll (const Elt& elt) { 89 | ForEachNat (Nat, nat) { 90 | (*this)[nat] = elt; 91 | } 92 | } 93 | 94 | template 95 | void NatMap ::SetAllToZero () { 96 | memset (tab, '\0', sizeof (tab)); 97 | } 98 | 99 | template 100 | Elt NatMap ::Min () const { 101 | Elt min_all = 1E20; 102 | ForEachNat (Nat, nat) { 103 | Elt val = (*this) [nat]; 104 | if (qisnan (val)) continue; 105 | min_all = min (min_all, val); 106 | } 107 | return min_all; 108 | } 109 | 110 | template 111 | Elt NatMap ::Max () const { 112 | Elt max_all = -1E20; 113 | ForEachNat (Nat, nat) { 114 | Elt val = (*this) [nat]; 115 | if (qisnan (val)) continue; 116 | max_all = max (max_all, val); 117 | } 118 | return max_all; 119 | } 120 | 121 | template 122 | Elt NatMap ::Mean () const { 123 | double n = 0.0; 124 | Elt sum = 0.0; 125 | ForEachNat (Nat, nat) { 126 | Elt val = (*this) [nat]; 127 | if (qisnan (val)) continue; 128 | sum += val; 129 | n += 1; 130 | } 131 | if (n == 0.0) return nan(""); 132 | return sum / n; 133 | } 134 | 135 | 136 | template 137 | Elt NatMap ::StdDev () const { 138 | double n = 0.0; 139 | Elt sum2 = 0.0; 140 | ForEachNat (Nat, nat) { 141 | Elt val = (*this) [nat]; 142 | if (qisnan (val)) continue; 143 | sum2 += val * val; 144 | n += 1; 145 | } 146 | if (n == 0.0) return nan(""); 147 | double mean = Mean (); 148 | return sqrt (sum2 / n - mean * mean); 149 | } 150 | 151 | template 152 | void NatMap :: 153 | operator += (Elt val) { ForEachNat (Nat, nat) (*this) [nat] += val; } 154 | 155 | template 156 | void NatMap :: 157 | operator -= (Elt val) { ForEachNat (Nat, nat) (*this) [nat] -= val; } 158 | 159 | template 160 | void NatMap :: 161 | operator *= (Elt val) { ForEachNat (Nat, nat) (*this) [nat] *= val; } 162 | 163 | template 164 | void NatMap :: 165 | operator /= (Elt val) { ForEachNat (Nat, nat) (*this) [nat] /= val; } 166 | 167 | template 168 | void NatMap ::LogAll (double base) { 169 | double base_change = log (base); 170 | ForEachNat (Nat, nat) { 171 | (*this) [nat] = log ((*this) [nat]) / base_change; 172 | } 173 | } 174 | 175 | 176 | template 177 | void NatMap ::Scale (Elt min_val, Elt max_val) { 178 | Elt min_all = Min (); 179 | Elt max_all = Max (); 180 | 181 | std::cerr << "Scale: " << min_all << " .. " << max_all << endl; 182 | 183 | ForEachNat (Nat, nat) { 184 | Elt& elt = (*this) [nat]; 185 | elt = (elt - min_all) / (max_all - min_all); 186 | elt = elt * (max_val - min_val) + min_val; 187 | (*this) [nat] = elt; 188 | } 189 | } 190 | 191 | template 192 | void NatMap ::Dump () { 193 | ForEachNat (Nat, v) { 194 | if (v.IsOnBoard() || v == Nat::Pass ()) { 195 | cerr << v.ToGtpString() << " " << (*this) [v] << endl; 196 | } 197 | } 198 | } 199 | 200 | 201 | template 202 | void NatMap ::Load (const NatMap& other) { 203 | memcpy(this, &other, sizeof(NatMap)); 204 | } 205 | 206 | #endif 207 | -------------------------------------------------------------------------------- /source/utils/nat.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #ifndef NAT_H_ 6 | #define NAT_H_ 7 | 8 | #include "utils.hpp" 9 | 10 | // ----------------------------------------------------------------------------- 11 | // For a use case look in player.h 12 | 13 | template 14 | class Nat { 15 | public: 16 | // Constructors. 17 | 18 | Nat (); // TODO replace default constructor with Invalid. 19 | static T OfRaw (uint raw); 20 | static T Invalid(); 21 | 22 | // Utils. 23 | 24 | bool MoveNext(); 25 | uint GetRaw() const; 26 | bool IsValid() const; 27 | bool operator == (const Nat& other) const; 28 | bool operator != (const Nat& other) const; 29 | 30 | protected: 31 | explicit Nat (uint raw); 32 | uint raw; 33 | }; 34 | 35 | #define ForEachNat(T, var) for (T var = T::Invalid(); var.MoveNext(); ) 36 | 37 | // ----------------------------------------------------------------------------- 38 | // NatMap is an array that can be indexed by Nat 39 | 40 | template 41 | class NatMap { 42 | public: 43 | explicit NatMap (); 44 | explicit NatMap (const Elt& init); 45 | Elt& operator[] (Nat nat); 46 | const Elt& operator[] (Nat nat) const; 47 | void SetAll (const Elt& elt); 48 | void SetAllToZero (); // Assumes POD of Elt, uses memset 49 | void Load (const NatMap& other); 50 | 51 | Elt Min () const; 52 | Elt Max () const; 53 | Elt Mean () const; 54 | Elt StdDev () const; 55 | 56 | void operator += (Elt val); 57 | void operator -= (Elt val); 58 | void operator *= (Elt val); 59 | void operator /= (Elt val); 60 | void LogAll (double base); 61 | 62 | void Dump (); 63 | 64 | void Scale (Elt min_val, Elt max_val); 65 | 66 | private: 67 | Elt tab [Nat::kBound]; 68 | }; 69 | 70 | // ----------------------------------------------------------------------------- 71 | 72 | template 73 | class NatSet { 74 | public: 75 | 76 | explicit NatSet () : mark (0), act_mark (1) { } 77 | 78 | void Clear () { act_mark += 1; } 79 | 80 | bool IsMarked (Nat n) const { return mark [n] == act_mark; } 81 | void Mark (Nat n) { mark [n] = act_mark; } 82 | 83 | private: 84 | NatMap mark; 85 | uint act_mark; 86 | }; 87 | 88 | // ----------------------------------------------------------------------------- 89 | 90 | #include "nat-inl.hpp" 91 | 92 | #endif // NAT_H_ 93 | -------------------------------------------------------------------------------- /source/utils/test.cpp: -------------------------------------------------------------------------------- 1 | #ifdef NDEBUG 2 | #undef NDEBUG 3 | #endif 4 | 5 | #include 6 | #include 7 | #include "test.hpp" 8 | 9 | // TODO replace __assert_fail with a backtrace and core dump 10 | // http://stackoverflow.com/questions/18265/ 11 | 12 | void TestFail (const char* msg, const char* file, int line, const char* pf) { 13 | fprintf (stderr, "ASSERT FAIL: %s %s %d %s\n", msg, file, line, pf ); 14 | fflush (stderr); 15 | exit(1); 16 | } 17 | -------------------------------------------------------------------------------- /source/utils/test.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_H_ 2 | #define TEST_H_ 3 | 4 | #include 5 | 6 | void TestFail (const char* msg, const char* file, int line, const char* pf); 7 | 8 | // TODO ifndef DEBUG 9 | 10 | // On default there should be one global kCheckAsserts == false 11 | // During debugging it might be convinient to define local variable 12 | // with the same name to change behaviour of subset of ASSERTS. 13 | 14 | // ASSERT's arument should have no side effects. 15 | // CHECK might be used safely with side effects. 16 | // ASSERT2 and CHECK2 take as a second argument block of code that 17 | // will be executed in case of failure. 18 | // It might be convinient to use WW in this blocks. 19 | 20 | #if 1 21 | const bool kCheckAsserts = false; 22 | #else 23 | const bool kCheckAsserts = true; 24 | #endif 25 | 26 | // debugging macros 27 | 28 | #define STRING__(x) #x 29 | #define STRING(x) STRING__(x) 30 | 31 | // Debug print to track code execution. 32 | // Funny to use: Just write QQ(a) to have letter a printed when it is executed. 33 | #define QQ(x) cerr << #x << flush; 34 | 35 | // Convinient macro for printing value of expression. 36 | #define WW(x) cerr << #x << " = " << x << endl << flush; 37 | 38 | // Automatic progam failure with report. 39 | #ifdef _MSC_VER 40 | #define FAIL(msg) (TestFail (msg, __FILE__, __LINE__, __FUNCSIG__), exit(0)) 41 | #else 42 | #define FAIL(msg) (TestFail (msg, __FILE__, __LINE__, __PRETTY_FUNCTION__), exit(0)) 43 | #endif 44 | 45 | // Always evaluate condition and always assert true. 46 | #define CHECK2(expr, block) { if (!(expr)) { block; FAIL (#expr); } } 47 | 48 | #define CHECK(expr) CHECK2(expr, {}) 49 | 50 | // Evalueate and assert only if kCheckAsserts == true 51 | #define ASSERT2(expr, block) { if (kCheckAsserts) { CHECK2 (expr, block) } } 52 | 53 | #define ASSERT(expr) ASSERT2(expr, {}) 54 | 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /source/utils/to_string.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TO_STRING_H_ 2 | #define TO_STRING_H_ 3 | 4 | #include 5 | #include 6 | 7 | template 8 | std::string ToString(const T& val) { 9 | std::ostringstream s; 10 | s << val; 11 | return s.str(); 12 | } 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /source/utils/utils.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2006 and onwards, Lukasz Lew 3 | // 4 | 5 | #ifndef UTILS_H_ 6 | #define UTILS_H_ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | typedef unsigned int uint; 13 | typedef unsigned long long uint64; 14 | 15 | using namespace std; 16 | 17 | //TODO rename to ignore 18 | #define unused(p) (void)(p) 19 | 20 | #define rep(i,n) for (uint i = 0; i != (uint)(n); i++) 21 | #define reps(i,s,n) for (int i = (s); i < int(n); i++) 22 | 23 | // performance macros 24 | 25 | template bool qisnan(T x) { 26 | T t = x; 27 | return t != x; 28 | } 29 | 30 | const double qnan = numeric_limits::quiet_NaN(); 31 | 32 | #ifdef _MSC_VER 33 | 34 | // put more of them in various places of source to force almost flat 35 | // source in Visual C++ (no function calls except remove_chain) 36 | 37 | #define no_inline __declspec(noinline) 38 | #define flatten 39 | #define all_inline __forceinline 40 | 41 | #else 42 | 43 | #define no_inline __attribute__((noinline)) 44 | #define flatten __attribute__((flatten)) 45 | #define all_inline __attribute__((always_inline)) 46 | 47 | #endif //_MSC_VER 48 | 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /twogtp/play.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | SCRIPT_DIR="$(readlink -f $(dirname "$0"))" 4 | 5 | if test $# -ne 2; then 6 | echo "Usage: $0 GAME_NO PROC_NO" 7 | exit 1 8 | fi 9 | 10 | BLACK="${SCRIPT_DIR}/../bin/libego.sh" 11 | WHITE="${SCRIPT_DIR}/../bin/gnugo.sh" 12 | GAME_NO="$1" 13 | PROC_NO="$2" 14 | 15 | DIR="${SCRIPT_DIR}/$(date +%F/%T)" 16 | 17 | mkdir -p "${DIR}" 18 | cd "${DIR}" 19 | 20 | echo "Results will be in $DIR" 21 | echo -n "Starting processes: " 22 | 23 | for i in `seq ${PROC_NO}`; do 24 | echo -n "$i " 25 | gogui-twogtp \ 26 | -auto \ 27 | -size 9 \ 28 | -komi 6.5 \ 29 | -alternate \ 30 | -referee "${GNUGO}" \ 31 | -games "${GAME_NO}" \ 32 | -black "${BLACK}" \ 33 | -white "${WHITE}" \ 34 | -sgffile "p${i}" \ 35 | -verbose \ 36 | 2> "p${i}.log" & 37 | done 38 | 39 | echo 40 | echo "Waiting to finish ..." 41 | wait 42 | 43 | cat p*.dat > "all.dat" 44 | gogui-twogtp -analyze "all.dat" 45 | 46 | echo "Starting browser ..." 47 | 48 | firefox "all.html" & 49 | -------------------------------------------------------------------------------- /twogtp/students/for_each_lab_comp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | colors="red pink orange brown yellow khaki cyan green violet blue crimson" 4 | 5 | for c in $colors; do 6 | for i in `seq -w 0 16`; do 7 | echo $c$i `ssh "$c$i" $@` & 8 | sleep 0.1 9 | done 10 | done 11 | -------------------------------------------------------------------------------- /twogtp/students/list_workers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import xmlrpclib, time, sys, subprocess, os, re, sys, socket, multiprocessing 4 | 5 | address = "students.mimuw.edu.pl", 7553 6 | proxy = xmlrpclib.ServerProxy("http://%s:%d/" % address) 7 | print proxy.list_workers () 8 | -------------------------------------------------------------------------------- /twogtp/students/screen_worker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | screen -dm python ~/libego/twogtp/students/worker.py 3 | -------------------------------------------------------------------------------- /twogtp/students/server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import xmlrpclib 4 | from SimpleXMLRPCServer import SimpleXMLRPCServer 5 | import random, os, datetime, sys, traceback, math 6 | 7 | 8 | start_time = datetime.datetime.now() 9 | log_dir = "/home/dokstud/lew/logi/%s" % start_time.isoformat() 10 | 11 | report_file = "report.csv" 12 | 13 | params_sampler = { 14 | "progressive_bias" : lambda: random.uniform (60.0, 120), 15 | "progressive_bias_prior" : lambda: random.uniform (0, 40), 16 | "proxy_1_bonus" : lambda: random.uniform (0, 30), 17 | "proxy_2_bonus" : lambda: random.uniform (0, 20), 18 | } 19 | 20 | params_names = params_sampler.keys () #csv header 21 | 22 | csv_header = ", ".join (params_names) + ", first_is_black, first_win, sgf_file" 23 | 24 | params_of_series = [] 25 | games_per_series = 2 26 | 27 | gnugo = \ 28 | "'/home/dokstud/lew/.bin/gnugo-3.8 --mode gtp --chinese-rules" \ 29 | " --capture-all-dead --positional-superko --level=0'" 30 | 31 | libego = \ 32 | "'/home/dokstud/lew/libego/bin/engine" \ 33 | " \"LoadGammas /home/dokstud/lew/libego/bin/3x3.gamma\"" \ 34 | " %s gtp'" 35 | 36 | gtp_set_command = "set" 37 | 38 | # TODO seed, cputime 39 | workers = {} 40 | idle_workers = {} 41 | 42 | def gen_params (): 43 | return dict (((p, params_sampler [p] ()) for p in params_names)) 44 | 45 | 46 | def params_to_gtp (params): 47 | gtp = "" 48 | for param_name in params_names: 49 | gtp += '"%s %s %f" ' % (gtp_set_command, param_name, params[param_name]) 50 | return gtp 51 | 52 | 53 | def format_report_line (series_id, first_is_black, first_win, sgf): 54 | params = params_of_series [series_id] 55 | csv_line = ", ".join ((str(params [param_name]) for param_name in params_names)) 56 | # scv_line, oh yeah :) 57 | return csv_line + (', %d, %d, "%s"' % (first_is_black, first_win, sgf)) 58 | 59 | 60 | def report_idling (worker_id): 61 | idle_workers [worker_id] = datetime.datetime.now() 62 | if (worker_id in workers): 63 | print "Warning! Idling worker on worker list." 64 | return 0 65 | 66 | 67 | def get_game_setup (worker_id): 68 | if (worker_id in workers): 69 | print "Warning! Worker already on worker list." 70 | if (worker_id in idle_workers): 71 | idle_workers.pop (worker_id) 72 | workers [worker_id] = datetime.datetime.now() 73 | 74 | global series_id 75 | params = gen_params () 76 | series_id = len (params_of_series) 77 | params_of_series.append (params) 78 | ret = (log_dir, 79 | series_id, 80 | games_per_series, 81 | libego % params_to_gtp (params), 82 | gnugo 83 | ) 84 | return ret 85 | 86 | 87 | def report_game_result (worker_id, clog_dir, series_id, result_list): 88 | # error handling 89 | if (not worker_id in workers): 90 | print "Old report from ", worker_id 91 | if (clog_dir == log_dir): 92 | print "Warning! but the same experiment dir!" 93 | return 0; 94 | if clog_dir != log_dir: 95 | print "Warning! in pool, but wrong dir!!" 96 | return 0 97 | 98 | worker_start = workers.pop (worker_id) 99 | f = open (report_file, "a") 100 | # TODO check for result length 101 | for (first_is_black, first_win, sgf) in result_list: 102 | print (first_is_black, first_win, sgf) 103 | f.write ("%s\n" % format_report_line (series_id, first_is_black, first_win, sgf)) 104 | f.close () 105 | return 0 106 | 107 | 108 | def list_workers (): 109 | s = "ACTIVE:\n" 110 | t_now = datetime.datetime.now() 111 | for w in workers: 112 | d = t_now - workers[w] 113 | mark = " *" if d.seconds > 60 else "" 114 | s += "%s %s %s\n" % (w, str(d), mark) 115 | s += "IDLE:\n" 116 | for w in idle_workers: 117 | d = t_now - idle_workers[w] 118 | mark = " *" if d.seconds > 60 else "" 119 | s += "%s %s %s\n" % (w, str(d), mark) 120 | return s 121 | 122 | os.makedirs (log_dir) 123 | os.chdir (log_dir) 124 | 125 | address = "students.mimuw.edu.pl", 7553 126 | server = SimpleXMLRPCServer (address) 127 | 128 | server.register_function (get_game_setup, "get_game_setup") 129 | server.register_function (report_game_result, "report_game_result") 130 | server.register_function (list_workers, "list_workers") 131 | server.register_function (report_idling, "report_idling") 132 | 133 | print "Listening on port %d..." % address[1] 134 | 135 | f = open (report_file, "a") 136 | f.write ("%s\n" % csv_header) 137 | f.close () 138 | 139 | server.serve_forever() 140 | -------------------------------------------------------------------------------- /twogtp/students/worker.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import xmlrpclib, time, sys, subprocess, os, re, sys, socket, multiprocessing 4 | 5 | 6 | def exec_cmd (cmd): 7 | process = subprocess.Popen (cmd, 8 | stdout = subprocess.PIPE, 9 | stderr = subprocess.STDOUT, 10 | shell = True) 11 | return process.communicate () [0] 12 | 13 | def do_one_series (proxy, worker_id): 14 | try: 15 | task = proxy.get_game_setup (worker_id) 16 | except socket.error, e: 17 | print "No server, waiting" 18 | time.sleep (5) 19 | return 20 | 21 | (log_dir, series_id, game_count, first, second) = task 22 | if series_id == -1: 23 | print "No more tasks, exiting." 24 | sys.exit (1) 25 | 26 | print "New task. Series %d, %d games." %(series_id, game_count) 27 | print "First : ", first 28 | print "Second: ", second 29 | 30 | os.chdir (log_dir) 31 | 32 | sgf_prefix = "game-%d" % series_id 33 | gnugo = \ 34 | "'/home/dokstud/lew/.bin/gnugo-3.8 --mode gtp --chinese-rules --capture-all-dead" \ 35 | " --positional-superko --level=0'" 36 | args = [ 37 | "/home/dokstud/lew/.bin/gogui-twogtp", 38 | "-auto", 39 | "-size", "9", 40 | "-komi", "6.5", 41 | "-alternate", 42 | "-referee", gnugo, 43 | "-games", "%d" % game_count, 44 | "-black", first, 45 | "-white", second, 46 | "-sgffile", sgf_prefix, 47 | # "-verbose", 48 | ] 49 | 50 | cmd = " ".join (args) 51 | print exec_cmd (cmd) 52 | 53 | result_list = [] 54 | for game_no in range (game_count): 55 | file_name = sgf_prefix + "-" + str (game_no) + ".sgf" 56 | sgf_file = open (file_name, "r") 57 | sgf = sgf_file.read () 58 | sgf_file.close () 59 | winner_letter = re.search (r'RE\[([^]]*)\]', sgf).group(1) [0] 60 | assert (winner_letter in 'BW') 61 | first_is_black = (game_no % 2 == 0) 62 | black_win = 1 if winner_letter == 'B' else 0 63 | first_win = first_is_black == black_win 64 | result = (first_is_black, first_win, file_name) 65 | print "%10s | Winner: %s | First is %s" % (file_name, 66 | winner_letter, 67 | "black" if game_no % 2 == 0 else "white" 68 | ) 69 | result_list.append (result) 70 | 71 | print "Results: ", result_list, "\n" 72 | try: 73 | proxy.report_game_result (worker_id, log_dir, series_id, result_list) 74 | except socket.error, e: 75 | return 76 | 77 | 78 | def main (): 79 | ps_cmd = 'pgrep "^python .*worker.py" -lf' 80 | ps_out = exec_cmd (ps_cmd).splitlines () 81 | print ps_out 82 | if len (ps_out) > multiprocessing.cpu_count (): 83 | print "More workers than processes, exiting ..." 84 | sys.exit (1) 85 | 86 | address = "students.mimuw.edu.pl", 7553 87 | proxy = xmlrpclib.ServerProxy("http://%s:%d/" % address) 88 | worker_id = "%s.%d" % (os.uname() [1], os.getpid()) 89 | 90 | while True: 91 | users = [u for u in exec_cmd ("users").strip().split () if u != "lew"] 92 | if len (users) > 0: 93 | print len (users), " users on host: ", users 94 | print "Waiting ..." 95 | try: 96 | proxy.report_idling (worker_id) 97 | except socket.error, e: 98 | print "No server, waiting" 99 | time.sleep (10) 100 | continue 101 | do_one_series (proxy, worker_id) 102 | 103 | main () 104 | -------------------------------------------------------------------------------- /vs2010/Go.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Go", "Go.vcxproj", "{2E104903-BA2D-6299-6E16-814494E3CAC2}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {2E104903-BA2D-6299-6E16-814494E3CAC2}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {2E104903-BA2D-6299-6E16-814494E3CAC2}.Debug|Win32.Build.0 = Debug|Win32 14 | {2E104903-BA2D-6299-6E16-814494E3CAC2}.Release|Win32.ActiveCfg = Release|Win32 15 | {2E104903-BA2D-6299-6E16-814494E3CAC2}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /vs2010/Go.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukaszlew/libego/9c50391a5b37cbf74b403a508a9b153cd7b32735/vs2010/Go.suo -------------------------------------------------------------------------------- /vs2010/Go.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | Win32Proj 26 | 27 | 28 | 29 | Application 30 | true 31 | 32 | 33 | Application 34 | false 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | true 48 | $(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include;..\source\engine;..\source\gtp;..\source\goboard;..\source\utils 49 | 50 | 51 | true 52 | $(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include;..\source\engine;..\source\gtp;..\source\goboard;..\source\utils 53 | 54 | 55 | 56 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 57 | MultiThreadedDebugDLL 58 | Level3 59 | ProgramDatabase 60 | Disabled 61 | 62 | 63 | MachineX86 64 | true 65 | Console 66 | 67 | 68 | 69 | 70 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 71 | MultiThreadedDLL 72 | Level3 73 | ProgramDatabase 74 | Full 75 | true 76 | AnySuitable 77 | true 78 | Speed 79 | true 80 | false 81 | StreamingSIMDExtensions2 82 | Fast 83 | 4Bytes 84 | true 85 | false 86 | true 87 | true 88 | 89 | 90 | MachineX86 91 | true 92 | Console 93 | true 94 | true 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /vs2010/Go.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | -------------------------------------------------------------------------------- /vs2010/Go.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | --------------------------------------------------------------------------------