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);
        }
Exemple #5
0
        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);
            }
        }