Example #1
0
        public Move getBestMove(Desk desk, GameRules rules)
        {
            movesInspected = 0;
            int       topMoveScore     = int.MinValue;
            int       currentScore     = 0;
            short     currentPlayer    = desk.getCurrentPlayer();
            short     oppositePlayer   = rules.getOppositePlayer(currentPlayer);
            bool      maximizingPlayer = false;
            ArrayList topMoves         = new ArrayList();

            //check game end - both players have some fields and at least one can move
            if (rules.isGameEnd(desk))
            {
                return(null);
            }

            ArrayList possiblePlayerMoves = rules.getPossibleMoves(desk, currentPlayer);

            if (possiblePlayerMoves.Count == 0)        //no possible moves for current player, switch to another player
            {
                possiblePlayerMoves = rules.getPossibleMoves(desk, oppositePlayer);
                oppositePlayer      = currentPlayer;
                maximizingPlayer    = !maximizingPlayer;
            }

            //loop possible moves
            foreach (Move move in possiblePlayerMoves)
            {
                //try the move and run minimax
                desk.makeMove(move);
                currentScore = minimax(desk, rules, depthMax, oppositePlayer, maximizingPlayer);
                desk.undoMove(move);

                if (currentScore > topMoveScore)     //new top move found
                {
                    topMoveScore = currentScore;
                    topMoves.Clear();
                    topMoves.Add(move);
                }
                else if (currentScore == topMoveScore)    //more moves with same value found
                {
                    topMoves.Add(move);
                }
            }

            if (!randomMoveSelection)
            {
                return((Move)topMoves[0]);
            }

            //pick randomly one of the top moves
            Random r = new Random();

            return((Move)topMoves[r.Next(0, topMoves.Count)]);
        }
Example #2
0
        private void undoMove(Move move, bool refreshDesk = true)
        {
            bool setAIButtons = false;

            stopPlayers(refreshDesk, setAIButtons);

            int  movesDoneCount = movesDone.Count;
            bool autorunAI      = false;

            if (movesDoneCount <= 0)
            {
                throw new Exception("No moves to undo.");
            }
            addGameNotice("move undo");
            movesDone.RemoveAt(movesDoneCount - 1);
            movesUndone.Add(move);
            boardUnmakeMove(move);
            decrementGameSteps();
            if (movesDone.Count == 0)
            {
                clearMovesHistorySelectedIndex();
            }
            else
            {
                setMovesHistorySelectedIndex(movesUndone.Count - 1);
            }
            desk.undoMove(move);
            desk.setCurrentPlayer((short)desk.getPieceOwnership(move.getFrom()[0], move.getFrom()[1]));
            updatePlayerPiecesCnt(rules.getOppositePlayer(desk.getCurrentPlayer()));
            if (isComputerOnTurn())
            {
                aiButtonsEnableContinue();
            }
            else
            {
                aiButtonsDisable();
            }
            if (!gameRunning)
            {
                reactivateFinishedGame();
            }
            setActivePlayer(desk.getCurrentPlayer(), autorunAI, refreshDesk);
        }
Example #3
0
        public ArrayList getPossibleJumps(Desk desk, int x, int y, short currentPlayer)
        {
            ArrayList possibleJumps = new ArrayList();
            ArrayList jumpsFound    = new ArrayList();
            Move      newMove;

            int[,] fields = desk.getFields();
            int xIncrement = 0;
            int yIncrement = 0;

            int[] targetCoords;
            short opposite_player = getOppositePlayer(currentPlayer);

            //loop all possible diretions for jump
            for (int i = 0; i < directionsJump.Length; i++)
            {
                if (directionsJump[i] == GameVar.DIR_UP_LEFT)
                {
                    xIncrement = -1;
                    yIncrement = 1;
                }
                else if (directionsJump[i] == GameVar.DIR_UP)
                {
                    xIncrement = 0;
                    yIncrement = 1;
                }
                else if (directionsJump[i] == GameVar.DIR_UP_RIGHT)
                {
                    xIncrement = 1;
                    yIncrement = 1;
                }
                else if (directionsJump[i] == GameVar.DIR_RIGHT)
                {
                    xIncrement = 1;
                    yIncrement = 0;
                }
                else if (directionsJump[i] == GameVar.DIR_LEFT)
                {
                    xIncrement = -1;
                    yIncrement = 0;
                }
                else if (directionsJump[i] == GameVar.DIR_DOWN_LEFT)
                {
                    xIncrement = -1;
                    yIncrement = -1;
                }
                else if (directionsJump[i] == GameVar.DIR_DOWN)
                {
                    xIncrement = 0;
                    yIncrement = -1;
                }
                else if (directionsJump[i] == GameVar.DIR_DOWN_RIGHT)
                {
                    xIncrement = 1;
                    yIncrement = -1;
                }

                //get target coords of possible jump
                targetCoords = canJump(fields, x, y, xIncrement, yIncrement, currentPlayer);
                if (targetCoords == null)      //no jump possible
                {
                    continue;
                }
                int targetCoordsX = targetCoords[0];
                int targetCoordsY = targetCoords[1];

                //create new (master) move, make it on desk and inspect again from new position - in case multiple jump
                newMove = new Move(x, y, targetCoordsX, targetCoordsY);
                newMove.addRemoveField(targetCoordsX - xIncrement, targetCoordsY - yIncrement);
                desk.makeMove(newMove);
                jumpsFound = getPossibleJumps(desk, targetCoordsX, targetCoordsY, currentPlayer);
                desk.undoMove(newMove);

                //multiple jump found
                if (jumpsFound.Count > 0)
                {
                    foreach (Move jump in jumpsFound)      //loop multiple jump fractals, add for master jump
                    {
                        jump.addOverField(jump.getFrom()[0], jump.getFrom()[1]);
                        jump.addRemoveField(jump.getFrom()[0] - xIncrement, jump.getFrom()[1] - yIncrement);
                        jump.setFrom(x, y);
                        possibleJumps.Add(jump);
                    }
                }
                else
                {
                    possibleJumps.Add(newMove);       //no (more) multijumps, add master jump to results
                }
            }
            return(possibleJumps);
        }
Example #4
0
        private int minimax(Desk desk, GameRules rules, int depth, short currentPlayer, bool maximizingPlayer)
        {
            movesInspected++;
            short oppositePlayer = rules.getOppositePlayer(currentPlayer);

            if (rules.isGameEnd(desk))      //check game end - both players have some fields and at least one can move
            {
                short nextPlayer = rules.getNextPlayer(desk);
                if (desk.getPlayerFields(GameVar.PLAYER_WHITE).Count != 0 && desk.getPlayerFields(GameVar.PLAYER_BLACK).Count != 0 && nextPlayer == -1)
                {
                    return(0);       //draw, neither of players can move
                }
                if (maximizingPlayer)
                {
                    return(int.MinValue + depthMax - depth);
                }
                return(int.MaxValue - depthMax + depth);
            }

            if (depth == 0)     //check depth level, return eval of current position
            {
                if (maximizingPlayer)
                {
                    return(-rules.getGameEvaluation(desk, oppositePlayer));
                }
                return(rules.getGameEvaluation(desk, oppositePlayer));
            }

            //get new possible moves, make the moves and call recursively minmax
            ArrayList possibleMoves = rules.getPossibleMoves(desk, currentPlayer);
            int       bestVal       = 0;
            int       currentVal    = 0;

            //current player has no possible moves, play "nothing" and call minimax
            if (possibleMoves.Count == 0)
            {
                if (maximizingPlayer)
                {
                    bestVal    = int.MinValue;
                    currentVal = minimax(desk, rules, depth, oppositePlayer, false);
                    bestVal    = Math.Max(bestVal, currentVal);
                }
                else
                {
                    bestVal    = int.MaxValue;
                    currentVal = minimax(desk, rules, depth, oppositePlayer, true);
                    bestVal    = Math.Min(bestVal, currentVal);
                }
                return(bestVal);
            }

            if (maximizingPlayer)      //current player's best move, looking for the highest rating move
            {
                bestVal = int.MinValue;
                foreach (Move move in possibleMoves)
                {
                    desk.makeMove(move);
                    currentVal = minimax(desk, rules, depth - 1, oppositePlayer, false);
                    desk.undoMove(move);
                    bestVal = Math.Max(bestVal, currentVal);
                }
            }
            else                  //opposite player's best move - the worst move for current player, looking for the lowest rating move
            {
                bestVal = int.MaxValue;
                foreach (Move move in possibleMoves)
                {
                    desk.makeMove(move);
                    currentVal = minimax(desk, rules, depth - 1, oppositePlayer, true);
                    desk.undoMove(move);
                    bestVal = Math.Min(bestVal, currentVal);
                }
            }
            return(bestVal);
        }