//return Agent's decision public ActionFunction NextMove(Board state, int p) { ActionFunction bestAction = new ActionFunction(); player_num = p; root = new Node(p); board = state; Stopwatch sw = new Stopwatch(); try { sw.Start(); do { current_depth++; bestAction = AlphaBeta.Search(board, root); } while (sw.ElapsedMilliseconds / 1000 < 5 && current_depth < MAX_DEPTH); sw.Stop(); sw.Reset(); current_depth = 0; } catch (Exception ex) { Console.WriteLine(ex.ToString()); } return(bestAction); }
public Node(ActionFunction move, ActionFunction undoMove, int player) { Move = move; Undo = undoMove; Player = player; Children = new List<Node>(); }
private IEnumerator AITurn(int playerNum) /// AI Controls { MessageText.text = ""; //move or choose wall playerStatus[playerNum].currentTurn = true; playersTurnText.text = "Player " + (playerNum + 1) + "'s Turn!"; Assets.Scripts.ActionFunction action = MyAgent.NextMove(MainBoard, playerNum); // <- currently has an issue if (action.function == null) { Debug.LogError("Agent action is null. Something is wrong. Agent just skip his move"); yield break; } if (action.function.Method.Name == "MovePawn") { RenderPawnPosition(action.player, action.x, action.y); } else if (action.function.Method.Name == "PlaceHorizontalWall") { RenderWall(action.x, action.y, true); } else if (action.function.Method.Name == "PlaceVerticalWall") { RenderWall(action.x, action.y, false); } else { Debug.LogError("Agent returning a non-supported action"); } MainBoard.ExecuteFunction(action); UpdateWallRemTxt(); //Update UI anyway because it doesn't matter yield return(null); }
private static ValueAndAction MinValue(Board board, Node node, ref int alpha, ref int beta, int depth) { if (Agent.CutOff(depth)) { node.Value = Agent.Evaluate(node); if (node.Value != 0) { UnityEngine.Debug.Log(node.ToString() + " at depth= " + depth + " has value = " + node.Value); } return(new ValueAndAction(node.Value, node.Move)); } int tempVal = int.MaxValue; ActionFunction tempAction = new ActionFunction(); Agent.GenerateSuccessors(node); foreach (Node child in node.Children) { board.ExecuteFunction(child.Move); var retValAction = MaxValue(board, child, ref alpha, ref beta, depth + 1); board.ExecuteFunction(child.Undo); if (retValAction.value < tempVal) { tempVal = retValAction.value; tempAction = child.Move; if (retValAction.value <= alpha) { retValAction.action = child.Move; return(retValAction); } beta = Math.Min(beta, retValAction.value); } } return(new ValueAndAction(tempVal, tempAction)); }
public void ExecuteFunction(ActionFunction actionFunction) { Action action = actionFunction.function; action.Invoke(this, actionFunction.player, actionFunction.x, actionFunction.y); }
public static void GenerateSuccessors(Node node) { //Player 1 prioritizes moving up -> left or right -> Wall -> Down (tentative Move Ordering) PlayerInfo[] playerStatus = board.playerStatus; int p = node.Player; int nextPlayer = (p + 1) % 2; ActionFunction undo = new ActionFunction(Board.UndoMovePawn, p, playerStatus[p].x, playerStatus[p].y); #region Player 1's Successors if (node.Player == PLAYER1) //first check in all if statemtents is the players position in relation to moving { //Move up if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x - 1, playerStatus[p].y)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x - 1, playerStatus[p].y), undo, nextPlayer)); } else { // going up jumping over 1 player directly if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x - 2, playerStatus[p].y)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x - 2, playerStatus[p].y), undo, nextPlayer)); } // going Up by 1 and Right by 1 if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x - 1, playerStatus[p].y + 1)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x - 1, playerStatus[p].y + 1), undo, nextPlayer)); } //going Left by 1 AND Up by 1 if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x - 1, playerStatus[p].y - 1)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x - 1, playerStatus[p].y - 1), undo, nextPlayer)); } } //Move Left if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x, playerStatus[p].y - 1)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x, playerStatus[p].y - 1), undo, nextPlayer)); } // going Left jumping over 1 player directly else if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x, playerStatus[p].y - 2)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x, playerStatus[p].y - 2), undo, nextPlayer)); } //Move Right if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x, playerStatus[p].y + 1)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x, playerStatus[p].y + 1), undo, nextPlayer)); } //going Right by jumping over 1 player directly else if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x, playerStatus[p].y + 2)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x, playerStatus[p].y + 2), undo, nextPlayer)); } //Move Down // going down by 1 (checks on location and for walls) if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x + 1, playerStatus[p].y)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x + 1, playerStatus[p].y), undo, nextPlayer)); } else { // going down jumping over 1 player directly if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x + 2, playerStatus[p].y)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x + 2, playerStatus[p].y), undo, nextPlayer)); } // going Down by 1 AND to the Left by 1 if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x + 1, playerStatus[p].y - 1)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x + 1, playerStatus[p].y - 1), undo, nextPlayer)); } // going Right by 1 AND Down by 1 if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x - 1, playerStatus[p].y + 1)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x - 1, playerStatus[p].y + 1), undo, nextPlayer)); } } } #endregion #region Player 2's Successors else { //Player 2 prioritizes moving down -> left or right -> Wall -> Up (tentative Move Ordering) //Move Down // going down by 1 (checks on location and for walls) if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x + 1, playerStatus[p].y)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x + 1, playerStatus[p].y), undo, nextPlayer)); } else { // going down jumping over 1 player directly if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x + 2, playerStatus[p].y)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x + 2, playerStatus[p].y), undo, nextPlayer)); } // going Down by 1 AND to the Left by 1 if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x + 1, playerStatus[p].y - 1)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x + 1, playerStatus[p].y - 1), undo, nextPlayer)); } // going Right by 1 AND Down by 1 if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x + 1, playerStatus[p].y + 1)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x + 1, playerStatus[p].y + 1), undo, nextPlayer)); } } //Move Left // if (playerStatus[p].y - 1 >= 0) // { if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x, playerStatus[p].y - 1)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x, playerStatus[p].y - 1), undo, nextPlayer)); } // going Left jumping over 1 player directly else if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x, playerStatus[p].y - 2)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x, playerStatus[p].y - 2), undo, nextPlayer)); } //} //Move Right if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x, playerStatus[p].y + 1)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x, playerStatus[p].y + 1), undo, nextPlayer)); } //going Right jumping over 1 player directly else if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x, playerStatus[p].y + 2)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x, playerStatus[p].y + 2), undo, nextPlayer)); } //Move up if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x - 1, playerStatus[p].y)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x - 1, playerStatus[p].y), undo, nextPlayer)); } else { // going up jumping over 1 player directly if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x - 2, playerStatus[p].y)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x - 2, playerStatus[p].y), undo, nextPlayer)); } // going Up by 1 and Right by 1 if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x - 1, playerStatus[p].y + 1)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x - 1, playerStatus[p].y + 1), undo, nextPlayer)); } //going Left by 1 AND Up by 1 if (board.IsPawnMoveLegal(playerStatus[p].x, playerStatus[p].y, playerStatus[p].x - 1, playerStatus[p].y - 1)) { node.Children.Add(new Node(new ActionFunction(Board.MovePawn, p, playerStatus[p].x - 1, playerStatus[p].y - 1), undo, nextPlayer)); } } } #endregion #region Wall Generation (for both players) taking too long if (playerStatus[p].wallsLeft == 0) // player has no wall left { return; } ActionFunction undoWall; for (int x = 0; x < Board.BOARD_SIZE - 1; x++) { for (int y = 0; y < Board.BOARD_SIZE - 1; y++) { //Horizontal Wall if (board.CheckWallH(x, y)) { undoWall = new ActionFunction(Board.UndoPlaceHorizontalWall, p, x, y); node.Children.Add(new Node(new ActionFunction(Board.PlaceHorizontalWall, p, x, y), undoWall, nextPlayer)); } //Vertical Wall if (board.CheckWallV(x, y)) { undoWall = new ActionFunction(Board.UndoPlaceVerticalWall, p, x, y); node.Children.Add(new Node(new ActionFunction(Board.PlaceVerticalWall, p, x, y), undoWall, nextPlayer)); } } } #endregion }
public ValueAndAction(int val, ActionFunction act) { value = val; action = act; }