void Turn() { bool blackWin = board.HasConsecutiveNPiece(Status.StateEnum.black, 5); bool whiteWin = board.HasConsecutiveNPiece(Status.StateEnum.white, 5); if (blackWin && whiteWin) { OnGameOver(Status.StateEnum.empty); } else if (blackWin) { OnGameOver(Status.StateEnum.black); } else if (whiteWin) { OnGameOver(Status.StateEnum.white); } else if (!board.Content.Any(e => e.State == Status.StateEnum.empty)) { OnGameOver(Status.StateEnum.empty); } else if (curPlayer == Status.StateEnum.black) { curPlayer = Status.StateEnum.white; PlayerWhite.Active(); } else { curPlayer = Status.StateEnum.black; PlayerBlack.Active(); } }
void Next() { var prePri = CurrentPrimaryStage; var preSub = CurrentSubStage; int intPri = (int)CurrentPrimaryStage; int intSub = (int)CurrentSubStage; intSub = (intSub + 1) % Helper.EnumHelper.GetValues(typeof(SubProcedureEnum)).Length; if (intSub == 0) { intPri = (intPri + 1) % Helper.EnumHelper.GetValues(typeof(PlayerEnum)).Length; } CurrentPrimaryStage = (PlayerEnum)intPri; CurrentSubStage = (SubProcedureEnum)intSub; if (CurrentSubStage == SubProcedureEnum.Checking) { bool blackWin = board.HasConsecutiveNPiece(Status.StateEnum.black, 5); bool whiteWin = board.HasConsecutiveNPiece(Status.StateEnum.white, 5); if (blackWin && whiteWin) { OnGameOver(Status.StateEnum.empty); } else if (blackWin) { OnGameOver(Status.StateEnum.black); } else if (whiteWin) { OnGameOver(Status.StateEnum.white); } else if (!board.Content.Any(e => e.State == Status.StateEnum.empty)) { OnGameOver(Status.StateEnum.empty); } else { Next(); return; } } OnTurnChange(); if (CurrentSubStage == SubProcedureEnum.Rotation && IsCurrentPlayerHuman()) { OnRotateButtonSwitch(true); } if (CurrentSubStage == SubProcedureEnum.Placement) { if (!IsCurrentPlayerHuman()) { new Thread(new ThreadStart(GetCurrentPlayer().Active)).Start(); //GetCurrentPlayer().Active(); } else { Placeable = true; } } }
public static Action Minimax(PentagoBoard currentState, Status.StateEnum color, int depth, NodeSelecter sel, StateEvaluater eva) { Action bestAction = null; Placement curPlc = new Placement() { Player = color, }; Rotation curRtt = new Rotation(); for (int i = 0; i < currentState.TotalWidth; i++) { for (int j = 0; j < currentState.TotalHeight; j++) { if (currentState[i, j].State == Status.StateEnum.empty) { //curPlc = new Placement(); curPlc.X = i; curPlc.Y = j; curPlc.Do(currentState); for (int k = 0; k < currentState.Sections.Count; k++) { //curRtt = new Rotation(); curRtt.SectionNo = k; curRtt.Clockwise = true; curRtt.Do(currentState); if (depth <= 1 || currentState.IsFull(Status.StateEnum.empty) || currentState.HasConsecutiveNPiece(color, 5) || currentState.HasConsecutiveNPiece(GetOppoColor(color), 5)) { int value = eva(currentState, color); if (bestAction == null) { bestAction = new Action(curPlc, curRtt); bestAction.Value = value; } else if (sel(bestAction.Value, value) > 0) { bestAction.SetAction(curPlc, curRtt); bestAction.Value = value; } } else { var subAction = Minimax(currentState, GetOppoColor(color), depth - 1, sel, eva); if (bestAction == null) { bestAction = new Action(curPlc, curRtt); bestAction.Value = -subAction.Value; } else if (sel(bestAction.Value, -subAction.Value) > 0) { bestAction.SetAction(curPlc, curRtt); bestAction.Value = -subAction.Value; } } curRtt.RollBack(currentState); //if the board state remains the same after rotating clockwise, it will be the same after rotating counterclockwise //so the node can be eliminated if (!currentState.Sections[k].IsSameInBothDirection) { curRtt.Clockwise = false; curRtt.Do(currentState); if (depth == 1 || currentState.IsFull(Status.StateEnum.empty) || currentState.HasConsecutiveNPiece(color, 5) || currentState.HasConsecutiveNPiece(GetOppoColor(color), 5)) { int value = eva(currentState, color); if (bestAction == null) { bestAction = new Action(curPlc, curRtt); bestAction.Value = value; } else if (sel(bestAction.Value, value) > 0) { bestAction.SetAction(curPlc, curRtt); bestAction.Value = value; } } else { var subAction = Minimax(currentState, GetOppoColor(color), depth - 1, sel, eva); if (sel(bestAction.Value, -subAction.Value) > 0) { bestAction.SetAction(curPlc, curRtt); bestAction.Value = -subAction.Value; } } curRtt.RollBack(currentState); } } curPlc.RollBack(currentState); } } } return(bestAction); }
public static Action MinimaxLocal(PentagoBoard currentState, Status.StateEnum color, int depth, NodeSelecter sel, StateEvaluater eva) { Action bestAction = null; Placement curPlc = new Placement() { Player = color, }; Rotation curRtt = new Rotation(); var searchSpace = new bool[6, 6]; if (currentState.IsEmpty(Status.StateEnum.empty)) { for (int i = 0; i < currentState.TotalWidth; i++) { for (int j = 0; j < currentState.TotalHeight; j++) { searchSpace[i, j] = true; } } } else if (currentState.CountSteps(Status.StateEnum.empty) < 5) { for (int i = 0; i < currentState.TotalWidth; i++) { for (int j = 0; j < currentState.TotalHeight; j++) { if (currentState[i, j].State == GetOppoColor(color)) { for (int k = (i == 0) ? 0 : -1; k <= ((i == currentState.TotalWidth - 1) ? 0 : 1); k++) { for (int l = (j == 0) ? 0 : -1; l <= ((j == currentState.TotalHeight - 1) ? 0 : 1); l++) { if (!(k == 0 && l == 0) && !searchSpace[i + k, j + l] && currentState[i + k, j + l].State == Status.StateEnum.empty) { searchSpace[i + k, j + l] = true; } } } } } } } else { for (int i = 0; i < currentState.TotalWidth; i++) { for (int j = 0; j < currentState.TotalHeight; j++) { if (currentState[i, j].State != Status.StateEnum.empty) { for (int k = (i == 0) ? 0 : -1; k <= ((i == currentState.TotalWidth - 1) ? 0 : 1); k++) { for (int l = (j == 0) ? 0 : -1; l <= ((j == currentState.TotalHeight - 1) ? 0 : 1); l++) { if (!(k == 0 && l == 0) && !searchSpace[i + k, j + l] && currentState[i + k, j + l].State == Status.StateEnum.empty) { searchSpace[i + k, j + l] = true; } } } } } } } var nospace = searchSpace.Cast <bool>().All(e => !e); for (int i = 0; i < currentState.TotalWidth; i++) { for (int j = 0; j < currentState.TotalHeight; j++) { if (searchSpace[i, j]) { //curPlc = new Placement(); curPlc.X = i; curPlc.Y = j; curPlc.Do(currentState); for (int k = 0; k < currentState.Sections.Count; k++) { //curRtt = new Rotation(); curRtt.SectionNo = k; curRtt.Clockwise = true; curRtt.Do(currentState); if (depth <= 1 || currentState.IsFull(Status.StateEnum.empty) || currentState.HasConsecutiveNPiece(color, 5) || currentState.HasConsecutiveNPiece(GetOppoColor(color), 5)) { int value = eva(currentState, color); if (bestAction == null) { bestAction = new Action(curPlc, curRtt); bestAction.Value = value; } else if (sel(bestAction.Value, value) > 0) { bestAction.SetAction(curPlc, curRtt); bestAction.Value = value; } } else { var subAction = Minimax(currentState, GetOppoColor(color), depth - 1, sel, eva); if (bestAction == null) { bestAction = new Action(curPlc, curRtt); bestAction.Value = -subAction.Value; } else if (sel(bestAction.Value, -subAction.Value) > 0) { bestAction.SetAction(curPlc, curRtt); bestAction.Value = -subAction.Value; } } curRtt.RollBack(currentState); //if the board state remains the same after rotating clockwise, it will be the same after rotating counterclockwise //so the node can be eliminated if (!currentState.Sections[k].IsSameInBothDirection) { curRtt.Clockwise = false; curRtt.Do(currentState); if (depth == 1 || currentState.IsFull(Status.StateEnum.empty) || currentState.HasConsecutiveNPiece(color, 5) || currentState.HasConsecutiveNPiece(GetOppoColor(color), 5)) { int value = eva(currentState, color); if (bestAction == null) { bestAction = new Action(curPlc, curRtt); bestAction.Value = value; } else if (sel(bestAction.Value, value) > 0) { bestAction.SetAction(curPlc, curRtt); bestAction.Value = value; } } else { var subAction = Minimax(currentState, GetOppoColor(color), depth - 1, sel, eva); if (sel(bestAction.Value, -subAction.Value) > 0) { bestAction.SetAction(curPlc, curRtt); bestAction.Value = -subAction.Value; } } curRtt.RollBack(currentState); } } curPlc.RollBack(currentState); } } } return(bestAction); }
public override int Evaluate(object info) { if (Depth == maxDepth || currentState.IsFull(Status.StateEnum.empty)) { return(EvaluateCurrent(info)); //List<Status> consideringLine = new List<Status>(n); //for (int i = 0; i < currentState.TotalWidth; i++) // for (int j = 0; j < currentState.TotalHeight; j++) // { // //check for horizontal case // if (i + n <= currentState.TotalWidth) // { // consideringLine.Clear(); // for (int k = 0; k < n; k++) // consideringLine.Add(currentState[i + k, j]); // var value = GetValueForALine(consideringLine, player); // totalValue += value; // } // //check for vertical case // if (j + n <= currentState.TotalWidth) // { // consideringLine.Clear(); // for (int k = 0; k < n; k++) // consideringLine.Add(currentState[i, j + k]); // var value = GetValueForALine(consideringLine, player); // totalValue += value; // } // //check for diagonal case // if (i + n <= currentState.TotalWidth && j + n <= currentState.TotalWidth) // { // consideringLine.Clear(); // for (int k = 0; k < n; k++) // consideringLine.Add(currentState[i + k, j + k]); // var value = GetValueForALine(consideringLine, player); // totalValue += value; // } // if (i + n <= currentState.TotalWidth && j - n >= -1) // { // consideringLine.Clear(); // for (int k = 0; k < n; k++) // consideringLine.Add(currentState[i + k, j - k]); // var value = GetValueForALine(consideringLine, player); // totalValue += value; // } // } } else { bool win = currentState.HasConsecutiveNPiece(currentTurn, 5); bool lose = currentState.HasConsecutiveNPiece(NextTurn(), 5); if (win && lose) { this.Value = 0; return(this.Value); } if (win) { this.Value = 10000; return(this.Value); } if (lose) { this.Value = -10000; return(this.Value); } var children = this.Expand().Cast <PentagoNode>(); if (this.nodeType == NodeTypeEnum.MAX) { foreach (var child in children) { child.DoAction(); child.Evaluate(info); BestChild = (BestChild == null) ? child : ((BestChild.Value > child.Value) ? BestChild : child); child.Rollback(); } } else { foreach (var child in children) { child.DoAction(); child.Evaluate(info); BestChild = (BestChild == null) ? child : ((BestChild.Value < child.Value) ? BestChild : child); child.Rollback(); } } Value = BestChild.Value; return(BestChild.Value); } }