// board_size <size> GTPResponse boardsize(unsigned int size) { if (size != BOARDSIZE) { return GTPResponse(GTP_FAILURE, "unacceptable size # " + intToString(BOARDSIZE) + " only"); } else { return GTPResponse(GTP_SUCCESS, ""); } }
GTPResponse GTP::gtp_play(vecstr args){ if(args.size() != 2) return GTPResponse(false, "Wrong number of arguments"); switch(tolower(args[0][0])){ case 'w': return play(args[1], Side::P1); case 'b': return play(args[1], Side::P2); default: return GTPResponse(false, "Invalid player selection"); } }
GTPResponse HavannahGTP::gtp_dists(vecstr args){ Board board = game.getboard(); LBDists dists(&board); int side = 0; if(args.size() >= 1){ switch(tolower(args[0][0])){ case 'w': side = 1; break; case 'b': side = 2; break; default: return GTPResponse(false, "Invalid player selection"); } } int size = board.get_size(); int size_d = board.get_size_d(); string s = "\n"; s += string(size + 3, ' '); for(int i = 0; i < size; i++) s += " " + to_str(i+1); s += "\n"; string white = "O", black = "@"; if(colorboard){ string esc = "\033", reset = esc + "[0m"; white = esc + "[1;33m" + "@" + reset; //yellow black = esc + "[1;34m" + "@" + reset; //blue } for(int y = 0; y < size_d; y++){ s += string(abs(size-1 - y) + 2, ' '); s += char('A' + y); for(int x = board.linestart(y); x < board.lineend(y); x++){ int p = board.get(x, y); s += ' '; if(p == 0){ int d = (side ? dists.get(Move(x, y), side) : dists.get(Move(x, y))); if(d < 10) s += to_str(d); else s += '.'; }else if(p == 1){ s += white; }else if(p == 2){ s += black; } } if(y < size-1) s += " " + to_str(1 + size + y); s += '\n'; } return GTPResponse(true, s); }
GTPResponse HavannahGTP::gtp_play(vecstr args){ if(args.size() != 2) return GTPResponse(false, "Wrong number of arguments"); char toplay = 0; switch(tolower(args[0][0])){ case 'w': toplay = 1; break; case 'b': toplay = 2; break; default: return GTPResponse(false, "Invalid player selection"); } return play(args[1], toplay); }
// play GTPResponse play(int stone_colour, GoMove position) { if (stone_colour == s.getNextToPlay()) { if (s.isValidMove(position)) { s.makeMove(position); ai_interface.notifyPlayHasBeenMade(position); return GTPResponse(GTP_SUCCESS, ""); } else { return GTPResponse(GTP_FAILURE, "illegal move"); } } else { return GTPResponse(GTP_FAILURE, "Consecutive moves of the same color are not supported."); } }
GTPResponse HavannahGTP::gtp_swap(vecstr args){ if(args.size() == 0) return GTPResponse(false, "Wrong number of arguments"); log("swap " + implode(args, " ")); if(args.size() >= 1) allow_swap = from_str<bool>(args[0]); string ret = ""; if(allow_swap) ret += "Swap on"; else ret += "Swap off"; return GTPResponse(true, ret); }
GTPResponse HavannahGTP::gtp_extended(vecstr args){ if(args.size() >= 1) genmoveextended = from_str<bool>(args[0]); else genmoveextended = !genmoveextended; return GTPResponse(true, "extended " + to_str(genmoveextended)); }
GTPResponse GTP::gtp_clearboard(vecstr args){ hist.clear(); set_board(); time_control.new_game(); return GTPResponse(true); }
GTPResponse GTP::gtp_print(vecstr args){ Board board = *hist; for(auto arg : args) if (!board.move(arg)) break; return GTPResponse(true, "\n" + board.to_s(colorboard)); }
GTPResponse GTP::gtp_colorboard(vecstr args){ if(args.size() >= 1) colorboard = from_str<int>(args[0]); else colorboard = !colorboard; return GTPResponse(true, "Color " + to_str(colorboard)); }
GTPResponse GTP::gtp_verbose(vecstr args){ if(args.size() >= 1) verbose = from_str<int>(args[0]); else verbose = !verbose; return GTPResponse(true, "Verbose " + to_str(verbose)); }
GTPResponse HavannahGTP::gtp_history(vecstr args){ string ret; vector<Move> hist = game.get_hist(); for(unsigned int i = 0; i < hist.size(); i++) ret += move_str(hist[i]) + " "; return GTPResponse(true, ret); }
// final_score GTPResponse final_score() { ScoredGame sg = s.scoreGame(); std::ostringstream oss; if (sg.black_score > sg.white_score) { oss << "B+" << (sg.black_score - sg.white_score); } else if (sg.white_score > sg.black_score) { oss << "W+" << (sg.white_score - sg.black_score); } else { oss << "0"; // draw is represented by a zero } /* for (unsigned int y = BOARDSIZE - 1; y < BOARDSIZE; y--) { oss << "\n# "; for (unsigned int x = 0; x < BOARDSIZE; x++) { if (sg.owned_by[x][y] == WHITE) oss << "W "; else if (sg.owned_by[x][y] == BLACK) oss << "B "; else oss << "_ "; } } */ return GTPResponse(GTP_SUCCESS, oss.str()); }
GTPResponse HavannahGTP::gtp_boardsize(vecstr args){ if(args.size() != 1) return GTPResponse(false, "Current board size: " + to_str(game.getsize())); log("boardsize " + args[0]); int size = from_str<int>(args[0]); if(size < 3 || size > 10) return GTPResponse(false, "Size " + to_str(size) + " is out of range."); game = HavannahGame(size); set_board(); time_remain = time.game; return GTPResponse(true); }
// time_settings GTPResponse time_settings(int main_time, int byo_yomi_time, int byo_yomi_stones) { // TODO: implement this prooperly white_time_left = main_time; black_time_left = main_time; return GTPResponse(GTP_SUCCESS, ""); }
// clear_board GTPResponse clear_board() { float old_komi = s.getKomi(); s = GoState::newGame(SUPERKO_POSITIONAL); s.setKomi(old_komi); ai_interface.resetToNewState(s); return GTPResponse(GTP_SUCCESS, ""); }
GTPResponse HavannahGTP::gtp_debug(vecstr args){ string str = "\n"; str += "Board size: " + to_str(game.getboard().get_size()) + "\n"; str += "Board cells: " + to_str(game.getboard().numcells()) + "\n"; str += "Board vec: " + to_str(game.getboard().vecsize()) + "\n"; str += "Board mem: " + to_str(game.getboard().memsize()) + "\n"; return GTPResponse(true, str); }
GTPResponse HavannahGTP::gtp_clearboard(vecstr args){ game.clear(); set_board(); time_remain = time.game; log("clear_board"); return GTPResponse(true); }
GTPResponse GTP::play(const std::string & pos, Side toplay){ if(toplay != hist->toplay()) return GTPResponse(false, "It is the other player's turn!"); if(hist->won() >= Outcome::DRAW) return GTPResponse(false, "The game is already over."); Move m(pos); if(!hist->valid_move(m)) return GTPResponse(false, "Invalid move"); move(m); if(verbose >= 2) logerr("Placement: " + m.to_s() + ", outcome: " + hist->won().to_s() + "\n" + hist->to_s(colorboard)); return GTPResponse(true); }
GTPResponse GTP::gtp_load_sgf(vecstr args){ if(args.size() == 0) return GTPResponse(true, "load_sgf <filename>"); std::ifstream infile(args[0].c_str()); if(!infile) { return GTPResponse(false, "Error opening file " + args[0] + " for reading"); } SGFParser<Move> sgf(infile); if(sgf.game() != Board::name){ infile.close(); return GTPResponse(false, "File is for the wrong game: " + sgf.game()); } int size = sgf.size(); if(size != hist->get_size()){ if(hist.len() == 0){ hist = History(size); set_board(); time_control.new_game(); }else{ infile.close(); return GTPResponse(false, "File has the wrong boardsize to match the existing game"); } } Side s = Side::P1; while(sgf.next_node()){ Move m = sgf.move(); move(m); // push the game forward s = ~s; } if(sgf.has_children()) agent->load_sgf(sgf); assert(sgf.done_child()); infile.close(); return true; }
// genmove GTPResponse genmove(int stone_colour, bool verbose = false) { if (stone_colour == s.getNextToPlay()) { time_t start = time(NULL); GoMove move = GoMove::none(); std::string ai_type = args.get("ai", ""); int time_left = (stone_colour == BLACK) ? black_time_left : white_time_left; if (ai_type == "simulate") { RNG rng; PatternMatcher p; GoStateAnalyser gsa(s, rng, p); move = gsa.selectMoveForSimulation_Mogo<true>(); } else { move = ai_interface.selectMove(time_left, verbose); std::cerr << "Performing update (tree cull after move play)\n"; ai_interface.notifyPlayHasBeenMade(move); } if (!move.isResign()) { s.makeMove(move); } time_t end = time(NULL); time_left -= (end - start); // estimate time used in case we don't have time_left if (time_left < 0) { time_left = 0; } std::cerr << "Spent approx " << (end - start) << " secs thinking\n"; (stone_colour == BLACK ? black_time_left : white_time_left) = time_left; std::cerr << boardToString(s) << "\n"; return GTPResponse(GTP_SUCCESS, moveToString(move)); } else { return GTPResponse(GTP_FAILURE, "Consecutive moves of the same color are not supported."); } }
// time_left GTPResponse time_left(int colour, int time, int stones) { // TODO: implement stones (byo-yomi) correctly if (colour == WHITE) { white_time_left = time; } else if (colour == BLACK) { black_time_left = time; } return GTPResponse(GTP_SUCCESS, ""); }
GTPResponse GTP::gtp_undo(vecstr args){ int num = (args.size() >= 1 ? from_str<int>(args[0]) : 1); while(num--){ hist.undo(); } set_board(false); if(verbose >= 2) logerr(hist->to_s(colorboard) + "\n"); return GTPResponse(true); }
GTPResponse HavannahGTP::play(const string & pos, int toplay){ if(toplay != game.toplay()) return GTPResponse(false, "It is the other player's turn!"); if(game.getboard().won() >= 0) return GTPResponse(false, "The game is already over."); Move m = parse_move(pos); if(!game.valid(m)) return GTPResponse(false, "Invalid move"); move(m); log(string("play ") + (toplay == 1 ? 'w' : 'b') + ' ' + move_str(m, false)); if(verbose >= 2) logerr("Placement: " + move_str(m) + ", outcome: " + game.getboard().won_str() + "\n" + game.getboard().to_s(colorboard)); return GTPResponse(true); }
GTPResponse GTP::gtp_save_sgf(vecstr args){ int limit = -1; if(args.size() == 0) return GTPResponse(true, "save_sgf <filename> [work limit]"); std::ifstream infile(args[0].c_str()); if(infile) { infile.close(); return GTPResponse(false, "File " + args[0] + " already exists"); } std::ofstream outfile(args[0].c_str()); if(!outfile) return GTPResponse(false, "Opening file " + args[0] + " for writing failed"); if(args.size() > 1) limit = from_str<unsigned int>(args[1]); SGFPrinter<Move> sgf(outfile); sgf.game(Board::name); sgf.program(gtp_name(vecstr()).response, gtp_version(vecstr()).response); sgf.size(hist->get_size()); sgf.end_root(); Side s = Side::P1; for(auto m : hist){ sgf.move(s, m); s = ~s; } agent->gen_sgf(sgf, limit); sgf.end(); outfile.close(); return true; }
GTPResponse HavannahGTP::gtp_undo(vecstr args){ int num = 1; if(args.size() >= 1) num = from_str<int>(args[0]); while(num--){ game.undo(); log("undo"); } set_board(false); if(verbose >= 2) logerr(game.getboard().to_s(colorboard) + "\n"); return GTPResponse(true); }
GTPResponse HavannahGTP::gtp_patterns(vecstr args){ bool symmetric = true; bool invert = true; string ret; Board board = game.getboard(); for(Board::MoveIterator move = board.moveit(); !move.done(); ++move){ ret += move->to_s() + " "; unsigned int p = board.pattern(*move); if(symmetric) p = board.pattern_symmetry(p); if(invert && board.toplay() == 2) p = board.pattern_invert(p); ret += to_str(p); ret += "\n"; } return GTPResponse(true, ret); }
GTPResponse GTP::gtp_history(vecstr args){ std::string ret; for(auto m : hist) ret += m.to_s() + " "; return GTPResponse(true, ret); }
GTPResponse GTP::gtp_all_legal(vecstr args){ std::string ret; for(MoveIterator move(*hist); !move.done(); ++move) ret += move->to_s() + " "; return GTPResponse(true, ret); }
GTPResponse GTP::gtp_state(vecstr args){ return GTPResponse(true, hist->state()); }