Esempio n. 1
0
        public static OthelloGame GetReflectedAcrossA1H8(OthelloGame game)
        {
            OthelloGame newGame = game.DeepCopy();

            for (int i = 0; i <= game.GetMovesMade(); i++)
            {
                for (int j = 0; j < BOARD_SIZE; j++)
                {
                    for (int k = 0; k < BOARD_SIZE; k++)
                    {
                        if (game.BoardHistory[i] != null)
                        {
                            newGame.BoardHistory[i][j, k] = game.BoardHistory[i][k, j];
                        }
                    }
                }
            }

            for (int i = 0; i < BOARD_SIZE; i++)
            {
                for (int j = 0; j < BOARD_SIZE; j++)
                {
                    newGame.Board[i, j] = game.Board[j, i];
                }
            }
            return(newGame);
        }
Esempio n. 2
0
        public static OthelloGame GetInverseGame(OthelloGame game)
        {
            OthelloGame newGame = game.DeepCopy();

            for (int i = 0; i <= game.GetMovesMade(); i++)
            {
                for (int j = 0; j < BOARD_SIZE; j++)
                {
                    for (int k = 0; k < BOARD_SIZE; k++)
                    {
                        if (game.BoardHistory[i] != null)
                        {
                            newGame.BoardHistory[i][j, k] = OpposingPlayer(game.BoardHistory[i][j, k]);
                        }
                    }
                }
            }

            for (int i = 0; i < BOARD_SIZE; i++)
            {
                for (int j = 0; j < BOARD_SIZE; j++)
                {
                    newGame.Board[i, j] = OpposingPlayer(game.Board[i, j]);
                }
            }
            return(newGame);
        }
Esempio n. 3
0
        private byte[] PredictBestMove(int depth, OthelloGame game, BoardStates player)
        {
            byte[]        bestMove = new byte[] { byte.MaxValue, byte.MaxValue };
            List <byte[]> moves    = game.GetPossiblePlayList();

            double bestScore = int.MinValue + 1;

            if (game.GetPieceCount(BoardStates.empty) > 58)//first two moves, don't compute
            {
                return(OpeningMove(player, game));
            }
            else if (moves.Count == 1) //don't compute if there is only 1 move
            {
                return(moves[0]);
            }

            foreach (byte[] move in moves)
            {
                OthelloGame testGame = game.DeepCopy();
                testGame.MakeMove(move);
                double thisScore = MinimaxAlphaBeta(testGame, depth - 1, double.MinValue, double.MaxValue, player);
                if (thisScore > bestScore)
                {
                    bestScore = thisScore;
                    bestMove  = move;
                }
            }
            return(bestMove);
        }
Esempio n. 4
0
        private double HeuristicEval(BoardStates player, OthelloGame game)
        {
            //Based of features of the board that humans have identified.
            //Hints of evaluation from any source I could find
            //idealy these could me optimized using a genetic algorithm,
            //but that is a different project


            const int searchableDepthOverride = 2; //override min-max in favor of complete evaluation
            const int endGame = 20;                //<20 moves is endgame
            const int midGame = 40;                // 20 moves in is midgame


            double value = 0;
            int    empty = game.GetPieceCount(BoardStates.empty);


            if (game.GameComplete)
            {
                return(CompleteEval(player, game));
            }
            else if (empty < searchableDepthOverride)
            {
                return(MinimaxAlphaBeta(game, searchableDepthOverride, int.MinValue, int.MaxValue, player));
            }

            value += coinDiffWeight * Math.Pow((game.GetPieceCount(player) - game.GetPieceCount(~player) + empty - coinDiffOffset), coinDiffPower);
            value += cornerDiffWeight * Math.Pow((game.GetCornerCount(player) - game.GetCornerCount(~player) + empty - cornerDiffOffset), cornerDiffPower);
            value += nearCornerDiffWeight * Math.Pow((game.GetAdjCornerCount(player) - game.GetAdjCornerCount(~player) + empty - nearCornerDiffOffset), nearCornerDiffPower);
            value += avalibleMoveDiffWeight * Math.Pow((game.GetPossiblePlayList(player).Count() - game.GetPossiblePlayList(~player).Count() + empty - avalibleMoveDiffOffset), avalibleMoveDiffPower);
            value += nonTurnableCoinDiffWeight * Math.Pow((game.GetSafePeiceCountEstimation(player) - game.GetSafePeiceCountEstimation(~player) + empty - nonTurnableCoinDiffOffset), nonTurnableCoinDiffPower);
            value += ControlledCornerDiffWeight * Math.Pow((game.GetControlledCorners(player) - game.GetControlledCorners(~player) + empty - ControlledCornerDiffOffset), ControlledCornerDiffPower);
            return(value);
        }
Esempio n. 5
0
        public static OthelloGame GetHalfPiRotation(OthelloGame game)
        {
            OthelloGame newGame = game.DeepCopy();

            for (int i = 0; i <= game.GetMovesMade(); i++)
            {
                for (int j = 0; j < BOARD_SIZE; j++)
                {
                    for (int k = 0; k < BOARD_SIZE; k++)
                    {
                        if (game.BoardHistory[i] != null)
                        {
                            newGame.BoardHistory[i][j, k] = game.BoardHistory[i][BOARD_SIZE - k - 1, j];
                        }
                    }
                }
            }

            for (int i = 0; i < BOARD_SIZE; i++)
            {
                for (int j = 0; j < BOARD_SIZE; j++)
                {
                    newGame.Board[i, j] = game.Board[BOARD_SIZE - j - 1, i];
                }
            }
            return(newGame);
        }
Esempio n. 6
0
        public static BoardStates GetCurrentLeader(OthelloGame game)
        {
            BoardStates leader = BoardStates.empty;

            leader = game.GetPieceCount(BoardStates.white) > game.GetPieceCount(BoardStates.black)
                ? BoardStates.white : BoardStates.black;
            return(leader);
        }
Esempio n. 7
0
        public static void TestMinMax(OthelloGame _myGame, int minimaxDepth = 3)
        {
            const int testCount = 100;

            object wonGamesLock = new object();
            int    wonGames     = 0;
            object tieGamesLock = new object();
            int    tieGames     = 0;

            var stopwatch = Stopwatch.StartNew();

            //Parallel.For(0, testCount, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount },index =>
            //{
            for (int index = 0; index < testCount; index++)
            {//non-parallel for loop to debug
                BoardStates player = (index % 2 == 0) ? BoardStates.black : BoardStates.white;

                OthelloGame testGame     = new OthelloGame();
                MinMaxAgent othelloAgent = new MinMaxAgent(2);
                RandomAgent randAgent    = new RandomAgent();
                while (!testGame.GameComplete)
                {
                    if (testGame.WhosTurn == player)
                    {
                        testGame.MakeMove(othelloAgent.MakeMove(testGame, player));
                    }
                    else
                    {
                        testGame.MakeMove(randAgent.MakeMove(testGame, ~player));
                    }
                }
                if (testGame.GameComplete)//just gotta check
                {
                    if (testGame.FinalWinner == player)
                    {
                        lock (wonGamesLock) { wonGames++; }
                    }
                    else if (testGame.FinalWinner == BoardStates.empty)
                    {
                        lock (tieGamesLock) { tieGames++; }
                    }
                    Console.WriteLine("Finished Game " + index + ", " + testGame.FinalWinner.ToString()
                                      + " won " + testGame.GetPieceCount(testGame.FinalWinner) + " to "
                                      + testGame.GetPieceCount(OthelloGame.OpposingPlayer(testGame.FinalWinner)));;
                }
                else
                {
                    throw new Exception("MiniMax Testing didn't complete a game");
                }
            }

            //});
            stopwatch.Stop();
            Console.WriteLine("Won " + wonGames + " / " + testCount + " games, " + ((double)wonGames / testCount) * 100 + " %");
            Console.WriteLine("Tied " + tieGames + " / " + testCount + " games, " + ((double)tieGames / testCount) * 100 + " %");
            Console.WriteLine("Lost " + (testCount - wonGames - tieGames) + " / " + testCount + " games, " + ((double)(testCount - wonGames - tieGames) / testCount) * 100 + " %");
            Console.WriteLine("Elapsed time for games : {0}", stopwatch.Elapsed);
        }
Esempio n. 8
0
        public OthelloGame DeepCopy()
        {
            //return ObjectCopier.Clone<OthelloGame>(this);
            OthelloGame game = (OthelloGame)this.MemberwiseClone();

            game.Board        = GetBoardCopy(this.Board);
            game.BoardHistory = GetBoardHistoryCopy(this.BoardHistory);
            return(game);
        }
Esempio n. 9
0
        public static List <OthelloGame> ReadAllGames3(string path)
        {//Parallel ForEach for files & games, all at once, outdated
            List <OthelloGame> gameRepo = new List <OthelloGame>();
            List <string>      files    = GetFiles(path);

            object      gameTransferLock = new object();
            List <Task> gameTransferTask = new List <Task>();

            Parallel.ForEach(files, new ParallelOptions {
                MaxDegreeOfParallelism = Environment.ProcessorCount
            }, (file) =>                                                                                                   //For each file, read games
            {
                object fileGameLock             = new object();
                List <OthelloGame> fileGameRepo = new List <OthelloGame>();

                var stopwatch         = System.Diagnostics.Stopwatch.StartNew();
                List <ThorGame> games = FileIO.ReadThorFile(file);

                //Parallel.ForEach(games, (tgame) => //for each game, transfer to OthelloGame
                //{
                foreach (ThorGame tgame in games)
                {
                    OthelloGame oGame;

                    try
                    {
                        oGame = new OthelloGame(tgame);
                        lock (fileGameLock)
                        {
                            fileGameRepo = fileGameRepo.Concat(OthelloGame.GetAllGameRotations(oGame)).ToList();
                        }
                    }
                    catch (Exception)
                    {
                        System.Diagnostics.Debug.WriteLine("failed a THOR->OthelloGame Transformation");
                    }
                }

                //});


                lock (gameTransferLock)
                {
                    gameRepo = gameRepo.Concat(fileGameRepo).ToList();
                }
                if (8 * games.Count != fileGameRepo.Count)
                {
                    Console.WriteLine("Games have been lost, " + fileGameRepo.Count + " / " + (8 * games.Count) + " games  transferred : " + ((double)fileGameRepo.Count / (8 * games.Count)) + " %");
                }


                stopwatch.Stop();
                Console.WriteLine("Elapsed time for transferring " + file + " info= {0}", stopwatch.Elapsed);
            });
            return(gameRepo);
        }
Esempio n. 10
0
 private static int CompleteEval(BoardStates player, OthelloGame game)
 {
     if (game.FinalWinner == player)
     {
         return(int.MaxValue);
     }
     else
     {
         return(int.MinValue);
     }
 }
Esempio n. 11
0
        public static List <OthelloGame> ReadAllGames(string path)
        {//Task per game in a given File, tackles one file at a time
            List <OthelloGame> gameRepo = new List <OthelloGame>();
            List <string>      files    = GetFiles(path);

            object gameTransferLock = new object();

            foreach (var file in files) //For each file, read games
            {
                object             fileGameLock     = new object();
                List <OthelloGame> fileGameRepo     = new List <OthelloGame>();
                List <Task>        fileTransferTask = new List <Task>();

                var             stopwatch = System.Diagnostics.Stopwatch.StartNew();
                List <ThorGame> games     = FileIO.ReadThorFile(file);

                foreach (ThorGame tgame in games) //for each game, transfer to OthelloGame
                {
                    OthelloGame oGame;

                    fileTransferTask.Add(Task.Run(() =>
                    {
                        try
                        {
                            oGame = new OthelloGame(tgame);
                            lock (fileGameLock)
                            {
                                fileGameRepo = fileGameRepo.Concat(OthelloGame.GetAllGameRotations(oGame)).ToList();
                            }
                        }
                        catch (Exception)
                        {
                            System.Diagnostics.Debug.WriteLine("failed a THOR->OthelloGame Transformation");
                        }
                    }));
                }
                Task.WaitAll(fileTransferTask.ToArray());
                foreach (Task t in fileTransferTask)
                {
                    t.Dispose();
                }
                gameRepo = gameRepo.Concat(fileGameRepo).ToList();

                if (8 * games.Count != fileGameRepo.Count)
                {
                    Console.WriteLine("Games have been lost, " + fileGameRepo.Count + " / " + (8 * games.Count) + " games  transferred : " + ((double)fileGameRepo.Count / (8 * games.Count)) + " %");
                }


                stopwatch.Stop();
                Console.WriteLine("Elapsed time for transferring " + file + " info= {0}", stopwatch.Elapsed);
            }
            return(gameRepo);
        }
Esempio n. 12
0
        private static byte[] OpeningMove(BoardStates player, OthelloGame game)
        {//avoid computation for first move - only one symmetric option
         //randomly select perpendicular or diagonal for second move - parallel
         //has been shown to be much worse
         //SPECIFIC TO 8x8 BOARDS
            byte[][] firstMoves = new byte[4][] {
                new byte[] { 2, 3 },
                new byte[] { 3, 2 },
                new byte[] { 4, 5 },
                new byte[] { 5, 4 }
            };

            if (game.GetPieceCount(BoardStates.empty) == 60)
            {
                Random rndGen = new Random();
                int    rand   = (int)Math.Ceiling(rndGen.NextDouble() * 4);
                switch (rand)
                {
                case 1:
                    return(firstMoves[0]);

                case 2:
                    return(firstMoves[1]);

                case 3:
                    return(firstMoves[2]);

                case 4:
                    return(firstMoves[3]);

                default:
                    throw new Exception("OpeningMove has faulted with random number generation");
                }
            }
            if (game.GetPieceCount(BoardStates.empty) == 59)
            {
                List <byte[]> moves  = game.GetPossiblePlayList();
                Random        rndGen = new Random();
                byte          rand   = (byte)Math.Ceiling(rndGen.NextDouble() * 2);
                switch (rand)
                {
                case 1:     //diagonal
                    return(moves[0]);

                case 2:     //perpendicular
                    return(moves[0]);

                default:
                    throw new Exception("Opening move has faulted with random number generation");
                }
            }
            return(new byte[] { byte.MaxValue, byte.MaxValue });
        }
Esempio n. 13
0
        public static List <OthelloGame> ReadAllGames2(string path)
        {//Thread per File, tackles all at once, outdated
            List <OthelloGame> gameRepo         = new List <OthelloGame>();
            List <Thread>      fileIOThreadList = new List <Thread>();


            List <string> files = GetFiles(path);

            foreach (var file in files)
            {
                fileIOThreadList.Add(new Thread(() =>
                {
                    List <OthelloGame> fileGameRepo = new List <OthelloGame>();
                    var stopwatch         = System.Diagnostics.Stopwatch.StartNew();
                    List <ThorGame> games = ReadThorFile(file);

                    foreach (ThorGame tgame in games)
                    {
                        OthelloGame oGame;
                        try
                        {
                            oGame        = new OthelloGame(tgame);
                            fileGameRepo = fileGameRepo.Concat(OthelloGame.GetAllGameRotations(oGame)).ToList();
                        }
                        catch (Exception)
                        {
                            System.Diagnostics.Debug.WriteLine("failed a THOR->OthelloGame Transformation");
                        }
                    }

                    gameRepo = gameRepo.Concat(fileGameRepo).ToList();
                    stopwatch.Stop();
                    Console.WriteLine("Elapsed time for transferring " + file + " info= {0}", stopwatch.Elapsed);
                }));
            }
            foreach (Thread t in fileIOThreadList)
            {
                t.Start();
            }
            foreach (Thread t in fileIOThreadList)
            {
                t.Join();
            }
            return(gameRepo);
        }
Esempio n. 14
0
        public static List <OthelloGame> GetAllGameRotations(OthelloGame game)
        {
            List <OthelloGame> gameList = new List <OthelloGame>();

            gameList.Add(game);
            gameList.Add(GetReflectedAcrossA1H8(game));
            gameList.Add(GetReflectedAcrossA8H1(game));
            gameList.Add(GetPiRotation(game));

            OthelloGame invGame = GetHalfPiRotation(GetInverseGame(game));

            gameList.Add(invGame);
            gameList.Add(GetReflectedAcrossA1H8(game));
            gameList.Add(GetReflectedAcrossA8H1(game));
            gameList.Add(GetPiRotation(game));

            return(gameList);
        }
Esempio n. 15
0
        private double MinimaxAlphaBeta(OthelloGame board, int depth, double a, double b, BoardStates player)// bool isMaxPlayer)
        {
            // The heart of our AI. Minimax algorithm with alpha-beta pruning to speed up computation.
            // Higher search depths = greater difficulty.
            //from oliverzh200/reversi https://github.com/oliverzh2000/reversi

            if (depth == 0 || board.GameComplete)
            {
                return(HeuristicEval(player, board));
            }
            double        bestScore  = double.MinValue;
            List <byte[]> validMoves = board.GetPossiblePlayList();

            if (validMoves.Count > 0)
            {
                foreach (byte[] move in validMoves)
                {
                    OthelloGame childBoard = board.DeepCopy();
                    childBoard.MakeMove(move);
                    double nodeScore = MinimaxAlphaBeta(childBoard, depth - 1, a, b, player);

                    bestScore = Math.Max(bestScore, nodeScore);
                    a         = Math.Max(bestScore, a);

                    if (b <= a) //Prune
                    {
                        break;
                    }
                }
            }
            else
            {
                return(MinimaxAlphaBeta(board, depth, a, b, player));
            }
            return(bestScore);
        }
Esempio n. 16
0
        private byte[] PredictBestMove(int depth, OthelloGame game, BoardStates player)
        {
            byte[]        bestMove = new byte[] { byte.MaxValue, byte.MaxValue };
            List <byte[]> moves    = game.GetPossiblePlayList();

            double bestScore = int.MinValue + 1;

            foreach (byte[] move in moves)
            {
                OthelloGame testGame = game.DeepCopy();
                testGame.MakeMove(move);
                double thisScore = MinimaxAlphaBeta(testGame, depth - 1, double.MinValue, double.MaxValue, player);
                if (thisScore > bestScore)
                {
                    bestScore = thisScore;
                    bestMove  = move;
                }
            }
            if ((bestMove[0] == byte.MaxValue || bestMove[1] == byte.MaxValue) && moves.Count > 0)
            {//All moves are valued at -inf, return one of em
                return(moves[0]);
            }
            return(bestMove);
        }
Esempio n. 17
0
 public byte[] MakeMove(int searchDepth, OthelloGame game, BoardStates player)
 {
     return(PredictBestMove(searchDepth, game, player));
 }
Esempio n. 18
0
 public override byte[] MakeMove(OthelloGame game, BoardStates player)
 {
     return(PredictBestMove(SEARCH_DEPTH, game, player));
 }
Esempio n. 19
0
 public override double EvaluateBoard(OthelloGame game, BoardStates player)
 {
     throw new NotImplementedException();
 }
Esempio n. 20
0
 /// <summary>
 /// Returns Agent's move of choice
 /// </summary>
 /// <param name="game"></param>
 /// <param name="player"></param>
 /// <returns>Location of choice move</returns>
 public abstract byte[] MakeMove(OthelloGame game, BoardStates player);
Esempio n. 21
0
        public static OthelloGame GetPiRotation(OthelloGame game)
        {
            OthelloGame newGame = GetHalfPiRotation(GetHalfPiRotation(game));

            return(game);
        }