public void RegisterWin(IGameAgent player) { ++gameAmount; if (player != null) { ++playerToWinAmounts[player]; ++playerToLosAmounts[player.opponent]; } else { ++drawAmount; } if (gameAmount % 1000 == 999) { string s = string.Empty; List <IGameAgent> gameAgents = new List <IGameAgent>(playerToWinAmounts.Keys); foreach (IGameAgent gameAgent in gameAgents) { s += $"{gameAgent.GetName()}: wins: {playerToWinAmounts[gameAgent]} - losses: {playerToLosAmounts[gameAgent]}\n"; playerToWinAmounts[gameAgent] = 0; playerToLosAmounts[gameAgent] = 0; } Debug.Log($"{s}Draws: {drawAmount}\n"); drawAmount = 0; } }
protected float GetScore(Board board, IGameAgent gameAgent, float alpha = float.MinValue, float beta = float.MaxValue, int depth = int.MaxValue) { Game.State gameState = game.GetState(board, gameAgent); if (gameState != Game.State.playing || depth == 0) { return(game.GetScore(board, gameAgent, gameState)); } else { float score = float.MinValue; List <Position> possibleMoves = game.GetPossibleMoves(board, gameAgent); for (int i = 0; i < possibleMoves.Count; ++i) { Board newBoard = new Board(board, gameAgent, possibleMoves[i]); if (i == 0) { score = -GetScore(newBoard, gameAgent.opponent, -beta, -alpha, depth - 1); } else { score = -GetScore(newBoard, gameAgent.opponent, -alpha - 1, -alpha, depth - 1); } if (alpha < score && score < beta) { score = -GetScore(newBoard, gameAgent.opponent, -beta, -score, depth - 1); } alpha = Mathf.Max(alpha, score); if (beta <= alpha) { break; } } return(alpha); } }
public Position BestNodeSearch(Board board, IGameAgent gameAgent, float alpha = float.MinValue, float beta = float.MaxValue, int depth = int.MaxValue) { List <Position> possibleMoves = game.GetPossibleMoves(game.board, this); Position bestMove = possibleMoves.GetRandom(); int subtreeCount = possibleMoves.Count; int betterMovesAmount = 0; do { float testValue = Guess(alpha, beta, subtreeCount); betterMovesAmount = 0; for (int i = 0; i < possibleMoves.Count; ++i) { float moveValue = -TTNegaMaxAlphaBeta(new Board(game.board, this, possibleMoves[i]), opponent, -testValue, -testValue + 1); if (testValue <= moveValue) { ++betterMovesAmount; bestMove = possibleMoves[i]; } } if (betterMovesAmount == 0) { beta = testValue; } else { subtreeCount = betterMovesAmount; alpha = testValue; } }while (2 < beta - alpha && betterMovesAmount != 1); return(bestMove); }
protected void NextMove() { if (isTrainingGame) { activeGameAgent = activeGameAgent.opponent; switch (activeGameAgent.GetPlayer()) { case GameAgent.Player.agent: activeGameAgent.RequestMove(); break; case GameAgent.Player.human: //wait for input break; case GameAgent.Player.random: DoMove(GetPossibleMoves(board, activeGameAgent).GetRandom()); break; } } else { StartCoroutine(NextMoveCoroutine()); } }
protected IEnumerator Begin() { if (randomStartingPlayer) { /* randomize players */ int playerIndex0 = Random.Range(0, players.Length); players.Swap(0, playerIndex0); int playerIndex1 = Random.Range(0, players.Length); while (playerIndex0 == playerIndex1) { playerIndex1 = Random.Range(0, players.Length); } players.Swap(1, playerIndex1); } yield return(new WaitUntil(() => players[0].isReady && players[1].isReady)); board.Clear(); userInterface?.Clear(); activeGameAgent = players[0]; players[0].id = -1; players[1].id = +1; players[0].opponent = players[1]; players[1].opponent = players[0]; players[0].HandleOnGameBegin(); players[1].HandleOnGameBegin(); NextMove(); }
protected void UndoMove() { Position position = moves[board.moveIndex]; board.SetState(position, 0); --board.moveIndex; userInterface?.UndoMove(position); activeGameAgent = activeGameAgent.opponent; }
private void StopAndRemoveAgent(IGameAgent agent) { foreach (var agentItem in mGameAgentList) { if (agent == agentItem) { agent.Stop(); mGameAgentList.Remove(agent); break; } } }
public override float GetReward(Game.State gameState, Board board, IGameAgent gameAgent) { switch (gameState) { case Game.State.win: return(+(1 - (board.moveIndex - 4) / 5f)); case Game.State.draw: return(0.1f); case Game.State.loss: return(-(1 - (board.moveIndex - 4) / 5f)); default: return(0); } }
public override float GetReward(Game.State gameState, Board board, IGameAgent gameAgent) { switch (gameState) { case Game.State.win: return(1 - 0.5f * board.moveIndex / 9.0f); case Game.State.draw: return(0.01f); case Game.State.loss: return(-1 + 0.5f * board.moveIndex / 9.0f); default: return(0); } }
protected float GetScore(Board board, IGameAgent gameAgent, int depth = int.MaxValue) { Game.State gameState = game.GetState(board, gameAgent); if (gameState != Game.State.playing || depth == 0) { return(game.GetScore(board, gameAgent, gameState)); } else { float score = float.MinValue; List <Position> possibleMoves = game.GetPossibleMoves(board, gameAgent); for (int i = 0; i < possibleMoves.Count; ++i) { score = Mathf.Max(score, -GetScore(new Board(board, gameAgent, possibleMoves[i]), gameAgent.opponent, depth - 1)); } return(score); } }
private IGameAgent CreateGameAgent(SGameRoomItem item) { IGameAgent agent = null; switch (item.HostType) { case enGameHostType.IPC: { break; } case enGameHostType.Scene: { string strPrefix = item.GameNameID.ToString(); if (strPrefix.Length > 6) { strPrefix = strPrefix.Substring(0, 6); } int prefix = int.Parse(strPrefix); if (mGameAssemblies.ContainsKey(prefix)) { var impl = mGameAssemblies[prefix]; var obj = Activator.CreateInstance(impl); agent = obj as IGameAgent; } else { throw new NotImplementedException("no implemented found by gameid:" + item.GameNameID); } break; } case enGameHostType.Socket: { break; } } return(agent); }
protected float GetScore(Board board, IGameAgent gameAgent, float alpha = float.MinValue, float beta = float.MaxValue, int depth = int.MaxValue) { if (cache.ContainsKey(board.GetBitMask(gameAgent.id).bits)) { if (cache[board.GetBitMask(gameAgent.id).bits].ContainsKey(board.GetBitMask(-gameAgent.id).bits)) { return(cache[board.GetBitMask(gameAgent.id).bits][board.GetBitMask(-gameAgent.id).bits]); } } else { cache.Add(board.GetBitMask(gameAgent.id).bits, new Dictionary <ulong, float>()); } float score = float.MinValue;; Game.State gameState = game.GetState(board, gameAgent); if (gameState != Game.State.playing || depth == 0) { score = game.GetScore(board, gameAgent, gameState); } else { List <Position> possibleMoves = game.GetPossibleMoves(board, gameAgent); for (int i = 0; i < possibleMoves.Count; ++i) { score = Mathf.Max(score, -GetScore(new Board(board, gameAgent, possibleMoves[i]), gameAgent.opponent, -beta, -alpha, depth - 1)); beta = Mathf.Max(score, beta); if (beta <= alpha) { break; } } } if (depth != 0) //don't cache a heuristic score { cache[board.GetBitMask(gameAgent.id).bits].Add(board.GetBitMask(-gameAgent.id).bits, score); } return(score); }
protected float GetScore(Board board, IGameAgent gameAgent, float alpha = float.MinValue, float beta = float.MaxValue, int depth = int.MaxValue) { Game.State gameState = game.GetState(board, gameAgent); if (gameState != Game.State.playing || depth == 0) { return(game.GetScore(board, gameAgent, gameState)); } else { float score = float.MinValue; List <Position> possibleMoves = game.GetPossibleMoves(board, gameAgent); //--- Killer heuristic --- for (int i = 0; i < possibleMoves.Count; ++i) { if (killers.Contains(possibleMoves[i])) { Position move = possibleMoves[i]; possibleMoves.RemoveAt(i); possibleMoves.Insert(0, move); } } //------------------------- for (int i = 0; i < possibleMoves.Count; ++i) { score = Mathf.Max(score, -GetScore(new Board(board, gameAgent, possibleMoves[i]), gameAgent.opponent, -beta, -alpha, depth - 1)); beta = Mathf.Max(score, beta); if (beta <= alpha) { //--- Killer heuristic --- killers.Enqueue(possibleMoves[i]); if (2 < killers.Count) { killers.Dequeue(); } //------------------------- break; } } return(score); } }
protected IEnumerator NextMoveCoroutine() { activeGameAgent = activeGameAgent.opponent; yield return(new WaitForSeconds(0.1f)); switch (activeGameAgent.GetPlayer()) { case GameAgent.Player.agent: activeGameAgent.RequestMove(); break; case GameAgent.Player.human: //wait for input break; case GameAgent.Player.random: DoMove(GetPossibleMoves(board, activeGameAgent).GetRandom()); break; } yield break; }
protected float GetScore(Board board, IGameAgent gameAgent, int depth = int.MaxValue) { float guess = GuessScore(board, gameAgent); float lowerBound = float.MinValue; float upperBound = float.MaxValue; while (lowerBound < upperBound) { float beta = Mathf.Max(guess, lowerBound + 1); guess = TTNegaMaxAlphaBeta(board, gameAgent, beta - 1, beta, depth); if (guess < beta) { upperBound = guess; } else { lowerBound = guess; } } return(guess); }
public SudokuSocketMiddleware(IGameAgent gameAgent, RequestDelegate next) { _gameAgent = gameAgent ?? throw new ArgumentNullException(nameof(gameAgent)); _next = next ?? throw new ArgumentNullException(nameof(next)); }
public float GetReward(Game.State gameState, Board board, IGameAgent gameAgent) { Debug.LogError("AlgorithmAgent.GetReward(...): this function should not be used"); return 0; }
public override float GuessScore(Board board, IGameAgent gameAgent) { return(+1 - board.moveIndex / 10f); }
public abstract float GetReward(Game.State gameState, Board board, IGameAgent gameAgent);
public abstract float GuessScore(Board board, IGameAgent gameAgent);
public abstract float GetScore(Board board, IGameAgent gameAgent, State gameState);
public abstract State GetState(Board board, IGameAgent gameAgent);
public abstract List <Position> GetPossibleMoves(Board board, IGameAgent gameAgent);