public override AIDecision RequestMove(AiGameInformation gameInformation) { var moves = gameInformation.GameTree.PrimaryMoveTimeline.ToList(); if (moves.Any() && moves.Last().Kind == MoveKind.Pass) { return(AIDecision.MakeMove(Move.Pass(gameInformation.AIColor), "You passed, too!")); } JokerGame currentGame = new JokerGame(gameInformation.GameInfo.BoardSize.Height, gameInformation.GameInfo.BoardSize.Width, null, null); foreach (Move move in gameInformation.GameTree.PrimaryMoveTimeline) { currentGame.moves.AddLast(new JokerMove(move.WhoMoves == StoneColor.Black ? 'B' : 'W', new JokerPoint(move.Coordinates.X, move.Coordinates.Y))); } currentGame.board = JokerExtensionMethods.OurBoardToJokerBoard(GetLastNodeOrEmptyBoard(gameInformation.GameTree).BoardState, gameInformation.GameInfo.BoardSize); JokerPoint point = new AlphaBetaPlayer(gameInformation.AIColor == StoneColor.Black ? 'B' : 'W').betterPlanMove(currentGame, this.TreeDepth); return(AIDecision.MakeMove(Move.PlaceStone(gameInformation.AIColor, new Position(point.x, point.y)), "I chose using the minimax algorithm and heuristics.")); }
private void FixHistory(AiGameInformation aiGameInformation) { // Initialize if not yet. if (!this._initialized) { Initialize(aiGameInformation); this._initialized = true; } // Fix history. var trueHistory = aiGameInformation.GameTree.PrimaryMoveTimeline.ToList(); for (int i = 0; i < trueHistory.Count; i++) { if (this._history.Count == i) { var trueMove = trueHistory[i]; this._history.Add(trueMove); string moveDescription = trueMove.Coordinates.ToIgsCoordinates(); if (trueMove.Kind == MoveKind.Pass) { moveDescription = "PASS"; } SendCommand("play " + (trueMove.WhoMoves == StoneColor.Black ? "B" : "W") + " " + moveDescription); } } }
public AIDecision RequestMove(Fuego fuego, AiGameInformation gameInformation) { var action = FuegoAction.ThatReturnsAiDecision(() => TrueRequestMove(fuego, gameInformation)); EnqueueAction(action); return(action.GetAiDecisionResult()); }
/// <summary> /// Requests a move from Fuego /// <para> /// This is called ASYNCHRONOUSLY by the AI agent. /// </para> /// </summary> /// <param name="gameInformation">Information about the requested move and the game</param> /// <returns>Decision</returns> public override AIDecision RequestMove(AiGameInformation gameInformation) { OldFuegoAction action = new FuegoSpace.OldFuegoAction(this, () => TrueRequestMove(gameInformation)); EnqueueAction(action); return(action.GetAiDecisionResult()); }
public async Task <IEnumerable <Position> > GetIsolatedDeadPositions(Fuego fuego, GameController gameController) { var action = FuegoAction.ThatReturnsGtpResponse(() => { var information = new AiGameInformation(gameController.Info, StoneColor.Black, gameController.Players.Black, gameController.GameTree); TrueInitialize(information); FixHistory(information); // Set the player's strength if (_lastMaxGames != fuego.MaxGames) { SendCommand("uct_param_player max_games " + fuego.MaxGames); _lastMaxGames = fuego.MaxGames; } var result = SendCommand("final_status_list dead"); return(result); }); EnqueueAction(action); var response = await action.GetGtpResponseAsync(); var positions = response.Text.Split(new[] { ' ', '\n' }, StringSplitOptions.RemoveEmptyEntries); var mark = new List <Position>(); foreach (string position in positions) { mark.Add(Position.FromIgsCoordinates(position)); } return(mark); }
private void FixHistory(AiGameInformation aiGameInformation) { // Fix history. var trueHistory = aiGameInformation.GameTree.PrimaryTimeline.ToList(); for (int i = 0; i < trueHistory.Count; i++) { if (this._history.Count == i) { var trueNode = trueHistory[i]; foreach (var pos in trueNode.AddBlack) { SendCommand("play B " + pos.ToIgsCoordinates()); } foreach (var pos in trueNode.AddWhite) { SendCommand("play W " + pos.ToIgsCoordinates()); } if (trueNode.Move != null && trueNode.Move.Kind != MoveKind.None) { var trueMove = trueNode.Move; this._history.Add(trueMove); string moveDescription = trueMove.Coordinates.ToIgsCoordinates(); if (trueMove.Kind == MoveKind.Pass) { moveDescription = "PASS"; } SendCommand("play " + (trueMove.WhoMoves == StoneColor.Black ? "B" : "W") + " " + moveDescription); } } } }
public void MovePerformed(AiGameInformation aiGameInformation) { var action = new FuegoAction(() => { FixHistory(aiGameInformation); }); EnqueueAction(action); }
/// <summary> /// Schedules the initialization of Fuego for a game. /// </summary> public void Initialize(AiGameInformation gameInformation) { var init = new FuegoAction(() => { TrueInitialize(gameInformation); }); EnqueueAction(init); }
public override AIDecision RequestMove(AiGameInformation gameInformation) { if (_brokenDueToInvalidLaunch) { return(AIDecision.Resign( "Fuego already plays in another game. Fuego may only play in one game at a time.")); } RequireInitialization(gameInformation); return(FuegoSingleton.Instance.RequestMove(this, gameInformation)); }
public override AIDecision RequestMove(AiGameInformation gameInformation) { RandomPlayer internalPlayer = new RandomPlayer(gameInformation.AIColor == StoneColor.Black ? 'B' : 'W'); char[,] board = JokerExtensionMethods.OurBoardToJokerBoard(GetLastNodeOrEmptyBoard(gameInformation.GameTree).BoardState, gameInformation.GameInfo.BoardSize); JokerPoint point = internalPlayer.makeMove(board, gameInformation.GameInfo.BoardSize.Width, gameInformation.GameInfo.BoardSize.Height); return(AIDecision.MakeMove(Move.PlaceStone(gameInformation.AIColor, new Position(point.x, point.y)), "I chose at random.")); }
private void Initialize(AiGameInformation gameInformation) { this._engine = AISystems.FuegoBuilder.CreateEngine(gameInformation.GameInfo.BoardSize.Width); // Board size SendCommand("boardsize " + gameInformation.GameInfo.BoardSize.Width); // Rules switch (gameInformation.GameInfo.RulesetType) { case RulesetType.AGA: case RulesetType.Chinese: SendCommand("go_rules chinese"); SendCommand("go_param_rules japanese_scoring 0"); break; case RulesetType.Japanese: SendCommand("go_rules japanese"); SendCommand("go_param_rules japanese_scoring 1"); break; } SendCommand("komi " + gameInformation.GameInfo.Komi.ToString(CultureInfo.InvariantCulture)); // Strength SendCommand("uct_param_player ponder " + (this.Ponder ? "1" : "0")); if (this.MaxGames > 0) { SendCommand("uct_param_player max_games " + this.MaxGames); } if (!this.AllowResign) { SendCommand("uct_param_player resign_threshold 0"); } // TODO (future work) Petr: on IGS, make it so two passes don't end a game // Time settings string timeSettings = gameInformation.AiPlayer.Clock.GetGtpInitializationCommand(); if (timeSettings != null) { SendCommand(timeSettings); } // Regardless of time controls, we are never willing to wait more than 15 seconds. SendCommand("go_param timelimit 15"); // Print beginning info Note("Komi set to " + SendCommand("get_komi").Text); DebuggingNote("Random seed is " + SendCommand("get_random_seed").Text); SendCommand("go_param_rules"); }
public AIDecision GetIsolatedHint(Fuego fuego, AiGameInformation gameInformation) { var action = FuegoAction.ThatReturnsAiDecision(() => { TrueInitialize(gameInformation); return(TrueRequestMove(fuego, gameInformation)); }); EnqueueAction(action); return(action.GetAiDecisionResult()); }
/// <summary> /// Taking effect only once per game, this method initializes the <see cref="FuegoSingleton"/> by setting the correct /// game rule parameters (such as chinese vs. japanese). /// This is only used by <see cref="MovePerformed(Move, GameTree, GamePlayer, GameInfo)"/> and <see cref="RequestMove(AiGameInformation)"/> which are only used when this is an actual player in a game. /// </summary> /// <param name="aiGameInformation">The ai game information.</param> private void RequireInitialization(AiGameInformation aiGameInformation) { if (!_initialized) { _initialized = true; if (_isPrimaryPlayer) { FuegoSingleton.Instance.Initialize(aiGameInformation); } } }
public AIDecision GetHint(Fuego fuego, AiGameInformation gameInformation) { var action = FuegoAction.ThatReturnsAiDecision(() => { var result = TrueRequestMove(fuego, gameInformation); UndoOneMove(); return(result); }); EnqueueAction(action); return(action.GetAiDecisionResult()); }
/// <summary> /// Gets a hint from the AI. /// <para> /// This is called ASYNCHRONOUSLY by the assistant. /// </para> /// </summary> /// <param name="gameInformation"></param> /// <returns></returns> public override AIDecision GetHint(AiGameInformation gameInformation) { var action = new OldFuegoAction(this, () => { var result = TrueRequestMove(gameInformation); UndoOneMove(); return(result); }); EnqueueAction(action); return(action.GetAiDecisionResult()); }
public override AIDecision GetHint(AiGameInformation gameInformation) { if (FuegoSingleton.Instance.CurrentGame == null) { return(FuegoSingleton.Instance.GetIsolatedHint(this, gameInformation)); } else { if (FuegoSingleton.Instance.CurrentGame.Info.Equals(gameInformation.GameInfo)) { return(FuegoSingleton.Instance.GetHint(this, gameInformation)); } else { // Fuego is playing elsewhere, we cannot get hints. return(null); } } }
/// <summary> /// Initializes Fuego for a game, by setting board size, rules and time control. /// </summary> /// <param name="gameInformation">The game information.</param> private void TrueInitialize(AiGameInformation gameInformation) { // Clear locals _history = new List <Move>(); _storedNotes = new List <string>(); // Board size SendCommand("boardsize " + gameInformation.GameInfo.BoardSize.Width); // Rules switch (gameInformation.GameInfo.RulesetType) { case RulesetType.AGA: case RulesetType.Chinese: SendCommand("go_rules chinese"); SendCommand("go_param_rules japanese_scoring 0"); break; case RulesetType.Japanese: SendCommand("go_rules japanese"); SendCommand("go_param_rules japanese_scoring 1"); break; } // Komi SendCommand("komi " + gameInformation.GameInfo.Komi.ToString(CultureInfo.InvariantCulture)); // Time settings string timeSettings = gameInformation.AiPlayer.Clock.GetGtpInitializationCommand(); if (timeSettings != null) { SendCommand(timeSettings); } // Regardless of time controls, we are never willing to wait more than 15 seconds. SendCommand("go_param timelimit 15"); // Print beginning info Debug.WriteLine("AI: Komi set to " + SendCommand("get_komi").Text); Debug.WriteLine("AI: Random seed is " + SendCommand("get_random_seed").Text); }
public override AIDecision RequestMove(AiGameInformation preMoveInformation) { var moves = preMoveInformation.GameTree.PrimaryMoveTimeline.ToList(); if (moves.Any() && moves.Last().Kind == MoveKind.Pass) { return(AIDecision.MakeMove(Move.Pass(preMoveInformation.AIColor), "You passed, too!")); } GameBoard createdBoard = GameBoard.CreateBoardFromGameTree(preMoveInformation.GameInfo, preMoveInformation.GameTree); MoveResult[,] moveResults = Ruleset.Create( preMoveInformation.GameInfo.RulesetType, preMoveInformation.GameInfo.BoardSize, CountingType.Area).GetMoveResult(GetLastNodeOrEmptyBoard(preMoveInformation.GameTree)); List <Position> possibleIntersections = new List <Position>(); for (int x = 0; x < preMoveInformation.GameInfo.BoardSize.Width; x++) { for (int y = 0; y < preMoveInformation.GameInfo.BoardSize.Height; y++) { if (moveResults[x, y] == MoveResult.Legal) { possibleIntersections.Add(new Position(x, y)); } } } if (possibleIntersections.Count == 0) { // TODO (future): The AI should probably pass, not resign. return(AIDecision.Resign("There are no more moves left to do.")); } Position chosen = possibleIntersections[Randomizer.Next(possibleIntersections.Count)]; return(AIDecision.MakeMove(Move.PlaceStone(preMoveInformation.AIColor, chosen), "I chose at random.")); }
public override AIDecision RequestMove(AiGameInformation gameInformation) { DateTime whenEndWaiting = DateTime.Now.AddSeconds(2); while (DateTime.Now < whenEndWaiting) { // Active waiting. } if (gameInformation.Node == null) { return(AIDecision.MakeMove(Move.PlaceStone(gameInformation.AIColor, new Position(0, 0)), "The board is empty so I'll just play at A1.")); } for (int y = 0; y < gameInformation.GameInfo.BoardSize.Height; y++) { for (int x = 0; x < gameInformation.GameInfo.BoardSize.Width; x++) { if (gameInformation.Node.BoardState[x, y] == StoneColor.None) { return(AIDecision.MakeMove(Move.PlaceStone(gameInformation.AIColor, new Position(x, y)), "I always place stones in the first point that's unoccupied.")); } } } return(AIDecision.MakeMove(Move.Pass(gameInformation.AIColor), "Board is full. This should never happen.")); }
private AIDecision TrueRequestMove(AiGameInformation gameInformation) { FixHistory(gameInformation); // Move for what color? string movecolor = gameInformation.AIColor == StoneColor.Black ? "B" : "W"; // Update remaining time var timeLeftArguments = gameInformation.AiPlayer.Clock.GetGtpTimeLeftCommandArguments(); if (timeLeftArguments != null) { int secondsRemaining = timeLeftArguments.NumberOfSecondsRemaining; secondsRemaining = Math.Max(secondsRemaining - 2, 0); // let's give the AI less time to ensure it does its move on time SendCommand("time_left " + movecolor + " " + secondsRemaining + " " + timeLeftArguments.NumberOfStonesRemaining); } // Generate the next move string result = SendCommand("genmove " + movecolor).Text; if (result == "resign") { var resignDecision = AIDecision.Resign("Resigned because of low win chance."); resignDecision.AiNotes = this._storedNotes; this._storedNotes.Clear(); return(resignDecision); } var move = result == "PASS" ? Move.Pass(gameInformation.AIColor) : Move.PlaceStone(gameInformation.AIColor, Position.FromIgsCoordinates(result)); // Change history this._history.Add(move); // Get win percentage string commandResult = SendCommand("uct_value_black").Text; float value = float.Parse(commandResult, CultureInfo.InvariantCulture); if (gameInformation.AIColor == StoneColor.White) { value = 1 - value; } string winChanceNote = (Math.Abs(value) < OldFuego.ComparisonTolerance) || (Math.Abs(value - 1) < OldFuego.ComparisonTolerance) ? "Reading from opening book." : "Win chance (" + gameInformation.AIColor + "): " + 100 * value + "%"; Note(winChanceNote); var moveDecision = AIDecision.MakeMove( move, winChanceNote); moveDecision.AiNotes = this._storedNotes.ToList(); // copy // Prepare the way this._storedNotes.Clear(); // Return result return(moveDecision); }
public void MovePerformed(Move move, AiGameInformation aiGameInformation) { Program.MovePerformed(move, aiGameInformation.GameTree, aiGameInformation.AiPlayer, aiGameInformation.GameInfo); }
/// <summary> /// Requests a move from the AI /// </summary> /// <param name="gameInformation">Move request info</param> /// <returns>AI decision</returns> public override AIDecision RequestMove(AiGameInformation gameInformation) { return(AIDecision.Resign("I could have won but I decided to let you win.")); }
private AIDecision TrueRequestMove(Fuego fuego, AiGameInformation gameInformation) { FixHistory(gameInformation); // Set whether a player can resign bool allowResign = fuego.AllowResign && gameInformation.GameInfo.NumberOfHandicapStones == 0; if (allowResign != this._lastAllowResign) { this._lastAllowResign = allowResign; if (!allowResign) { SendCommand("uct_param_player resign_threshold 0"); } } // Set whether a player can ponder if (!_ponderSet) { SendCommand("uct_param_player ponder " + (fuego.Ponder ? "1" : "0")); _ponderSet = true; } // Set the player's strength if (_lastMaxGames != fuego.MaxGames) { SendCommand("uct_param_player max_games " + fuego.MaxGames); _lastMaxGames = fuego.MaxGames; } // Move for what color? string movecolor = gameInformation.AIColor == StoneColor.Black ? "B" : "W"; // Update remaining time var timeLeftArguments = gameInformation.AiPlayer.Clock.GetGtpTimeLeftCommandArguments(); if (timeLeftArguments != null) { int secondsRemaining = timeLeftArguments.NumberOfSecondsRemaining; secondsRemaining = Math.Max(secondsRemaining - 2, 0); // let's give the AI less time to ensure it does its move on time SendCommand("time_left " + movecolor + " " + secondsRemaining + " " + timeLeftArguments.NumberOfStonesRemaining); } // Generate the next move string result = SendCommand("genmove " + movecolor).Text; if (result == "resign") { var resignDecision = AIDecision.Resign("Resigned because of low win chance."); resignDecision.AiNotes = this._storedNotes; this._storedNotes.Clear(); return(resignDecision); } var move = result == "PASS" ? Move.Pass(gameInformation.AIColor) : Move.PlaceStone(gameInformation.AIColor, Position.FromIgsCoordinates(result)); // Change history this._history.Add(move); // Get win percentage string commandResult = SendCommand("uct_value_black").Text; float value = float.Parse(commandResult, CultureInfo.InvariantCulture); if (gameInformation.AIColor == StoneColor.White) { value = 1 - value; } string winChanceNote = (Math.Abs(value) < ComparisonTolerance) || (Math.Abs(value - 1) < ComparisonTolerance) ? "Reading from opening book." : "Win chance (" + gameInformation.AIColor + "): " + 100 * value + "%"; Debug.WriteLine(winChanceNote); var moveDecision = AIDecision.MakeMove( move, winChanceNote); moveDecision.AiNotes = this._storedNotes.ToList(); // copy // Prepare the way this._storedNotes.Clear(); // Return result return(moveDecision); }