Beispiel #1
0
 private float MinValue(DejarikChessDuD[] state, int turnDepth, bool secondMove, float alpha, float beta)
 {
     if (DejTree.CutOffTest(state, turnDepth))
     {
         return(DejTree.Eval(state));
     }
     else
     {
         float v = 420f;
         for (int i = 0; i < 25; i++)
         {
             if (state[i] != null && state[i].Owner == Enemy_Turn)
             {
                 for (int j = 0; j < 25; j++)
                 {
                     if (state[i].AllPossibleMoves()[j])
                     {
                         if (state[j] == null)
                         {
                             //We are "Moving" the piece to an empty sector.
                             DejarikChessDuD[] newState = Utilities.FakeMoveChessPiece(state, state[i], j);
                             if (secondMove)
                             {
                                 //This is the last move of the turn, next move is going to be ai
                                 v = Utilities.Min(v, MaxValue(newState, turnDepth + 1, false, alpha, beta));
                             }
                             else
                             {
                                 //next move is still the real person
                                 v = Utilities.Min(v, MinValue(newState, turnDepth, true, alpha, beta));
                             }
                         }
                         else
                         {
                             //We are "Attacking" another piece
                             int nextTurn = Enemy_Turn;
                             if (secondMove)
                             {
                                 nextTurn = Player_Turn;
                             }
                             DejarikChessDuD[] dudState = Utilities.Clone(state);
                             v = Utilities.Max(v, ChanceValue(dudState, i, j, turnDepth, secondMove, alpha, beta, nextTurn));
                         }
                         if (v <= alpha)
                         {
                             return(v);
                         }
                         if (v < beta)
                         {
                             beta = v;
                         }
                     }
                 }
             }
         }
         return(v);
     }
 }
Beispiel #2
0
    private float MaxValue(DejarikChessDuD[] state, int turnDepth, bool secondMove, float alpha, float beta)
    {
        float v = 0f;

        if (DejTree.CutOffTest(state, turnDepth)) //should be false until last move or a certain depth
        {
            v = DejTree.Eval(state);
        }
        else
        {
            v = -420f;
            for (int i = 0; i < 25; i++)
            {
                if (state[i] != null && state[i].Owner == Player_Turn && state[i].AllPossibleMoves() != null)
                {
                    for (int j = 0; j < 25; j++)
                    {
                        if (state[i].AllPossibleMoves()[j])
                        {
                            if (state[j] == null)
                            {
                                DejarikChessDuD[] newState = Utilities.FakeMoveChessPiece(state, state[i], j);
                                //We are "Moving" the piece to an empty sector.
                                if (secondMove)
                                {
                                    //This is the last move of the turn, next move is going to be enemy
                                    v = Utilities.Max(v, MinValue(newState, turnDepth + 1, false, alpha, beta));
                                }
                                else
                                {
                                    //next move is still ai, but is the last (second)
                                    v = Utilities.Max(v, MaxValue(newState, turnDepth, true, alpha, beta));
                                }
                            }
                            else
                            {
                                //We are "Attacking" another piece
                                //This is the last move of the turn, next move is going to be enemy
                                v = Utilities.Max(v, ChanceValue(state, i, j, turnDepth, secondMove, alpha, beta, Player_Turn));
                            }
                            if (v >= beta)
                            {
                                return(v);
                            }
                            if (v > alpha)
                            {
                                alpha = v;
                            }
                        }
                    }
                }
            }
        }
        return(v);
    }
Beispiel #3
0
 void ThreadedWork()
 {
     try
     {
         _threadRunning = true;
         bool workDone = false;
         for (int i = 0; i < 25; i++)
         {
             int[] adiacents = BoardManager.AdiacentSectors(i);
             for (int j = 0; j < adiacents.Length; j++)
             {
                 if (adiacents[j] < 0 || adiacents[j] > 24)
                 {
                     Debug.Log("AdiacentSectors fail: sector " + i + " has adiacent " + adiacents[j]);
                 }
             }
         }
         // This pattern lets us interrupt the work at a safe point if neeeded.
         int   turnDepth = 0;
         float oldv      = -1000f;
         float v         = -1000f;
         float alpha     = -1000f;
         float beta      = 1000f;
         if (waitingForPush)
         {
             int[] possiblePushSectors = BoardManager.AdiacentSectors(pushedPiece.CurrentSector);
             fromSector = pushedPiece.CurrentSector;
             int found       = 0;
             int sectorFound = -1;
             for (int i = 0; i < possiblePushSectors.Length; i++)
             {
                 if (realState[possiblePushSectors[i]] == null)
                 {
                     found++;
                     sectorFound = possiblePushSectors[i];
                 }
             }
             if (found == 1)
             {
                 toSector = sectorFound;
             }
             else
             {
                 for (int i = 0; _threadRunning && i < possiblePushSectors.Length; i++)
                 {
                     if (realState[possiblePushSectors[i]] == null)
                     {
                         //we can move the piece into sector "i"
                         DejarikChessDuD[] newState = Utilities.FakeMoveChessPiece(realState, realState[pushedPiece.CurrentSector], possiblePushSectors[i]);
                         if (originalTurn == Player_Turn)
                         {
                             //next action is taken by AI
                             v = Utilities.Max(v, MaxValue(newState, turnDepth, secondMove, alpha, beta));
                         }
                         else
                         {
                             //next action is taken by a Real Person (tm)
                             v = Utilities.Max(v, MinValue(newState, turnDepth, secondMove, alpha, beta));
                         }
                         if (oldv != v)
                         {
                             toSector = possiblePushSectors[i];
                         }
                         if (v >= beta)
                         {
                             workDone = true;
                             break;
                         }
                         if (v > alpha)
                         {
                             alpha = v;
                         }
                         oldv = v;
                     }
                 }
             }
             workDone = true;
         }
         else
         {
             if (DejTree.CutOffTest(realState, turnDepth)) //should be false until last move or a certain depth
             {
                 v = DejTree.Eval(realState);
             }
             else
             {
                 int i = 0;
                 for (i = 0; _threadRunning && i < 25; i++)
                 {
                     if (realState[i] != null && realState[i].Owner == Player_Turn)
                     {
                         //Debug.Log("Starting to evaluate actions available for piece" + state[i].Name);
                         if (realState[i].AllPossibleMoves() == null)
                         {
                             // Debug.Log("Possible moves for " + state[i].Name + " are null");
                             continue;
                         }
                         int j = 0;
                         for (j = 0; _threadRunning && j < 25; j++)
                         {
                             bool possibleMove = realState[i].AllPossibleMoves()[j];
                             if (possibleMove)
                             {
                                 if (realState[j] == null)
                                 {
                                     //We are "Moving" the piece to an empty sector.
                                     DejarikChessDuD[] newState = Utilities.FakeMoveChessPiece(realState, realState[i], j);
                                     if (secondMove)
                                     {
                                         //This is the last move of the turn, next move is going to be enemy
                                         v = Utilities.Max(v, MinValue(newState, turnDepth + 1, false, alpha, beta));
                                     }
                                     else
                                     {
                                         //next move is still ai, but is the last (second)
                                         v = Utilities.Max(v, MaxValue(newState, turnDepth, true, alpha, beta));
                                     }
                                 }
                                 else
                                 {
                                     //We are "Attacking" another piece
                                     //This is the last move of the turn, next move is going to be enemy
                                     int nextTurn = Player_Turn;
                                     if (secondMove)
                                     {
                                         nextTurn = Enemy_Turn;
                                     }
                                     DejarikChessDuD[] dudState = Utilities.Clone(realState);
                                     v = Utilities.Max(v, ChanceValue(dudState, i, j, turnDepth, secondMove, alpha, beta, nextTurn));
                                 }
                                 if (oldv != v)
                                 {
                                     fromSector = i;
                                     toSector   = j;
                                 }
                                 if (v >= beta)
                                 {
                                     //return v;
                                     //break out of both cycles and move on
                                     workDone = true;
                                     break;
                                 }
                                 if (v > alpha)
                                 {
                                     alpha = v;
                                 }
                                 oldv = v;
                             }
                             // Debug.Log("Finished to evaluate action " + j + " for piece" + state[i].Name);
                         }
                         //Debug.Log("Finished to evaluate actions available for piece" + state[i].Name);
                         if (workDone)
                         {
                             break;
                         }
                     }
                 }
             }
         }
         workDone       = true;
         _threadRunning = false;
     }
     catch (System.Exception e)
     {
         System.Console.WriteLine(e.Message);
     }
 }
Beispiel #4
0
    //This is the main Coroutine, executing every "coroutineInterval" instead of every frame
    private IEnumerator MainCoroutine()
    {
        //Build a minmax tree for imperfect, adversarial, stochastic alpha-beta search.
        //Every max/min node is separated by a chance node.
        //Some chance nodes have only 1 child, with probability==1 (deterministic movements)
        //Every turn contains two moves.

        //Wait for board to initialize
        while (!board.initialized)
        {
            yield return(new WaitForSeconds(2 * coroutineInterval));
        }
        DejarikChessPiece[] currentRealState = new DejarikChessPiece[25];
        DejarikChessDuD[]   state            = new DejarikChessDuD[25];
        float v          = -2000f;
        float oldv       = v;
        int   fromSector = -1;
        int   toSector   = -1;

        while (!board.gameEnded)
        {
            //version 1: we wait for our turn to calculate everything.
            while (board.currentTurn != this.Player_Turn)
            {
                yield return(new WaitForSeconds(5 * coroutineInterval));
            }
            Debug.Log("Starting search");
            //We get the current state of the game
            for (int i = 0; i < 25; i++)
            {
                currentRealState[i] = board.getPieceInSector(i);
                if (board.getPieceInSector(i) != null)
                {
                    state[i] = new DejarikChessDuD(currentRealState[i].Name, currentRealState[i].Attack, currentRealState[i].Defense, currentRealState[i].Movement,
                                                   currentRealState[i].CurrentSector, currentRealState[i].Owner, currentRealState[i].pieceType, currentRealState[i].AllPossibleMoves());
                }
                else
                {
                    state[i] = null;
                }
            }
            //Simulating first move at level 0
            float alpha      = -1000f;
            float beta       = 1000f;
            int   turnDepth  = 0;
            bool  vFound     = false;
            bool  secondMove = (board.actionsLeft == 1);
            if (board.waitingForPush)
            {
                int[] possiblePushSectors = BoardManager.AdiacentSectors(board.pushed.CurrentSector);
                fromSector = board.pushed.CurrentSector;
                for (int i = 0; i < possiblePushSectors.Length; i++)
                {
                    if (state[i] == null)
                    {
                        //we can move the piece into sector "i"
                        DejarikChessDuD[] newState = Utilities.FakeMoveChessPiece(state, state[board.pushed.CurrentSector], i);
                        if ((board.originalTurn == Player_Turn && !secondMove) || (board.originalTurn == Enemy_Turn && secondMove))
                        {
                            //next action is taken by AI
                            v = Utilities.Max(v, MaxValue(newState, turnDepth, secondMove, alpha, beta));
                        }
                        else
                        {
                            //next action is taken by a Real Person (tm)
                            v = Utilities.Max(v, MinValue(newState, turnDepth, secondMove, alpha, beta));
                        }
                        if (oldv != v)
                        {
                            toSector = i;
                        }
                        if (v >= beta)
                        {
                            break;
                        }
                        if (v > alpha)
                        {
                            alpha = v;
                        }
                        oldv = v;
                    }
                }
            }
            else
            {
                if (DejTree.CutOffTest(state, turnDepth)) //should be false until last move or a certain depth
                {
                    v = DejTree.Eval(state);
                }
                else
                {
                    v = -420f;
                    int i = 0;
                    for (i = 0; i < 25; i++)
                    {
                        if (state[i] != null && state[i].Owner == Player_Turn)
                        {
                            Debug.Log("Starting to evaluate actions available for piece" + state[i].Name);
                            if (state[i].AllPossibleMoves() == null)
                            {
                                Debug.Log("Possible moves for " + state[i].Name + " are null");
                                continue;
                            }
                            int j = 0;
                            for (j = 0; j < 25; j++)
                            {
                                if (state[i].AllPossibleMoves()[j])
                                {
                                    if (state[j] == null)
                                    {
                                        //We are "Moving" the piece to an empty sector.
                                        DejarikChessDuD[] newState = Utilities.FakeMoveChessPiece(state, state[i], j);
                                        if (secondMove)
                                        {
                                            //This is the last move of the turn, next move is going to be enemy
                                            v = Utilities.Max(v, MinValue(newState, turnDepth + 1, false, alpha, beta));
                                        }
                                        else
                                        {
                                            //next move is still ai, but is the last (second)
                                            v = Utilities.Max(v, MaxValue(newState, turnDepth, true, alpha, beta));
                                        }
                                    }
                                    else
                                    {
                                        //We are "Attacking" another piece
                                        //This is the last move of the turn, next move is going to be enemy
                                        v = Utilities.Max(v, ChanceValue(state, i, j, turnDepth, secondMove, alpha, beta, Player_Turn));
                                    }
                                    if (oldv != v)
                                    {
                                        fromSector = i;
                                        toSector   = j;
                                    }
                                    if (v >= beta)
                                    {
                                        //return v;
                                        //break out of both cycles and move on
                                        vFound = true;
                                        break;
                                    }
                                    if (v > alpha)
                                    {
                                        alpha = v;
                                    }
                                    oldv = v;
                                    Debug.Log("Finished to evaluate action " + j + " for piece" + state[i].Name);
                                }
                                yield return(new WaitForSeconds(coroutineInterval));
                            }
                            //I need to return control to Unity
                            Debug.Log("Finished to evaluate actions available for piece" + state[i].Name);
                            yield return(new WaitForSeconds(coroutineInterval));

                            if (vFound)
                            {
                                break;
                            }
                        }
                    }
                }
            }
            // the action of the node with value v
            selectedChessPiece = currentRealState[fromSector];
            if (currentRealState[toSector] == null)
            {
                if (board.waitingForPush)
                {
                    PushChessPiece(toSector);
                }
                else
                {
                    MoveChessPiece(toSector);
                }
            }
            else
            {
                //attack
                AttackChessPiece(toSector);
            }
        }
    }