Example #1
0
        private void MakeMove(move_t m)
        {
            // start move log output
            string move = (this.Turn == Player.WHITE) ? "W" : "B";

            move += ":\t";

            // piece
            switch (this.Board.Grid[m.from.number][m.from.letter].piece)
            {
            case Piece.PAWN:
                move += "P";
                break;

            case Piece.ROOK:
                move += "R";
                break;

            case Piece.KNIGHT:
                move += "k";
                break;

            case Piece.BISHOP:
                move += "B";
                break;

            case Piece.QUEEN:
                move += "Q";
                break;

            case Piece.KING:
                move += "K";
                break;
            }

            // kill
            if (this.Board.Grid[m.to.number][m.to.letter].piece != Piece.NONE || LegalMoveSet.isEnPassant(this.Board, m))
            {
                move += "x";
            }

            // letter
            switch (m.to.letter)
            {
            case 0: move += "a"; break;

            case 1: move += "b"; break;

            case 2: move += "c"; break;

            case 3: move += "d"; break;

            case 4: move += "e"; break;

            case 5: move += "f"; break;

            case 6: move += "g"; break;

            case 7: move += "h"; break;
            }

            // number
            move += (m.to.number + 1).ToString();

            // update board / make actual move
            this.Board = LegalMoveSet.move(this.Board, m);

            // if that move put someone in check
            if (LegalMoveSet.isCheck(this.Board, (Turn == Player.WHITE) ? Player.BLACK : Player.WHITE))
            {
                move += "+";
            }

            // show log
            this.m_UI.LogMove(move + "\n");
        }
Example #2
0
        public List <position_t> Select(position_t pos)
        {
            // has previously selected something
            if (this.Board.Grid[this.Selection.number][this.Selection.letter].piece != Piece.NONE &&
                this.Turn == this.Board.Grid[this.Selection.number][this.Selection.letter].player &&
                (this.m_nPlayers == 2 ||
                 this.Turn == Player.WHITE))
            {
                // get previous selections moves and determine if we chose a legal one by clicking
                List <position_t> moves = LegalMoveSet.getLegalMove(this.Board, this.Selection);
                foreach (position_t move in moves)
                {
                    if (move.Equals(pos))
                    {
                        // we selected a legal move so update the board
                        MakeMove(new move_t(this.Selection, pos));

                        // If piece that was just moved is a king and it moved anyhthing other than 1 square, it was
                        // a castling move, so we need to move the rook
                        if (this.Board.Grid[pos.number][pos.letter].piece == Piece.KING && Math.Abs(pos.letter - this.Selection.letter) == 2)
                        {
                            int row = (this.Turn == Player.WHITE) ? 0 : 7;

                            // Left rook
                            if (pos.letter < 4)
                            {
                                LegalMoveSet.move(this.Board, new move_t(new position_t(0, row), new position_t(3, row)));
                            }
                            // right rook
                            else
                            {
                                LegalMoveSet.move(this.Board, new move_t(new position_t(7, row), new position_t(5, row)));
                            }
                        }

                        // finish move
                        switchPlayer();
                        if (detectCheckmate())
                        {
                            return(new List <position_t>());
                        }

                        if (this.m_nPlayers == 1)         // start ai
                        {
                            new Thread(AISelect).Start(); // thread turn
                        }
                        return(new List <position_t>());
                    }
                }
            }

            // first click, let's show possible moves
            if (this.Board.Grid[pos.number][pos.letter].player == this.Turn && (this.m_nPlayers == 2 || this.Turn == Player.WHITE))
            {
                List <position_t> moves = LegalMoveSet.getLegalMove(this.Board, pos);
                this.Selection = pos;
                return(moves);
            }

            // reset
            this.Selection = new position_t();
            return(new List <position_t>());
        }
Example #3
0
        private static int mimaab(ChessBoard board, Player turn, int depth, int alpha, int beta)
        {
            // base case, at maximum depth return board fitness
            if (depth >= DEPTH)
            {
                return(board.fitness(MAX));
            }
            else
            {
                List <ChessBoard> boards = new List <ChessBoard>();

                // get available moves / board states from moves for the current player
                foreach (position_t pos in board.Pieces[turn])
                {
                    if (STOP)
                    {
                        return(-1);      // interupts
                    }
                    List <position_t> moves = LegalMoveSet.getLegalMove(board, pos);
                    foreach (position_t move in moves)
                    {
                        if (STOP)
                        {
                            return(-1);      // interupts
                        }
                        ChessBoard b2 = LegalMoveSet.move(board, new move_t(pos, move));
                        boards.Add(b2);
                    }
                }

                int a = alpha, b = beta;
                if (turn != MAX) // minimize
                {
                    foreach (ChessBoard b2 in boards)
                    {
                        if (STOP)
                        {
                            return(-1);      // interupt
                        }
                        b = Math.Min(b, mimaab(b2, (turn == Player.WHITE) ? Player.BLACK : Player.WHITE, depth + 1, a, b));
                        if (a >= b)
                        {
                            return(a);
                        }
                    }
                    return(b);
                }
                else // maximize
                {
                    foreach (ChessBoard b2 in boards)
                    {
                        if (STOP)
                        {
                            return(-1);      // interupt
                        }
                        a = Math.Max(a, mimaab(b2, (turn == Player.WHITE) ? Player.BLACK : Player.WHITE, depth + 1, a, b));
                        if (a >= b)
                        {
                            return(b);
                        }
                    }
                    return(a);
                }
            }
        }
Example #4
0
        public static move_t MiniMaxAB(ChessBoard board, Player turn)
        {
            RUNNING = true;  // we've started running
            STOP    = false; // no interupt command sent
            MAX     = turn;  // who is maximizing

            // gather all possible moves
            Dictionary <position_t, List <position_t> > moves = LegalMoveSet.getPlayerMoves(board, turn);

            // because we're threading safely store best result from each thread
            int[]    bestresults = new int[moves.Count];
            move_t[] bestmoves   = new move_t[moves.Count];

            // thread the generation of each move
            Parallel.ForEach(moves, (movelist, state, index) =>
            {
                if (STOP) // interupt
                {
                    state.Stop();
                    return;
                }

                // initialize thread best
                bestresults[index] = int.MinValue;
                bestmoves[index]   = new move_t(new position_t(-1, -1), new position_t(-1, -1));

                // for each move for the current piece(thread)
                foreach (position_t move in movelist.Value)
                {
                    if (STOP) // interupt
                    {
                        state.Stop();
                        return;
                    }

                    // make initial move and start recursion
                    ChessBoard b2 = LegalMoveSet.move(board, new move_t(movelist.Key, move));
                    int result    = mimaab(b2, (turn == Player.WHITE) ? Player.BLACK : Player.WHITE, 1, Int32.MinValue, Int32.MaxValue);

                    // if result is better or best hasn't been set yet
                    if (bestresults[index] < result || (bestmoves[index].to.Equals(new position_t(-1, -1)) && bestresults[index] == int.MinValue))
                    {
                        bestresults[index]    = result;
                        bestmoves[index].from = movelist.Key;
                        bestmoves[index].to   = move;
                    }
                }
            });

            // interupted
            if (STOP)
            {
                return(new move_t(new position_t(-1, -1), new position_t(-1, -1)));
            }

            // find the best of the thread results
            int    best = int.MinValue;
            move_t m    = new move_t(new position_t(-1, -1), new position_t(-1, -1));

            for (int i = 0; i < bestmoves.Length; i++)
            {
                if (best < bestresults[i] || (m.to.Equals(new position_t(-1, -1)) && !bestmoves[i].to.Equals(new position_t(-1, -1))))
                {
                    best = bestresults[i];
                    m    = bestmoves[i];
                }
            }
            return(m);
        }
Example #5
0
        private static List <position_t> Pawn(ChessBoard board, position_t pos, bool verify_check = true)
        {
            List <position_t> moves = new List <position_t>();

            piece_t p = board.Grid[pos.number][pos.letter];

            if (p.piece == Piece.NONE)
            {
                return(moves);
            }

            // gather relative moves
            List <position_t> relative = new List <position_t>();

            relative.Add(new position_t(-1, 1 * ((p.player == Player.BLACK) ? -1 : 1)));
            relative.Add(new position_t(0, 1 * ((p.player == Player.BLACK) ? -1 : 1)));
            relative.Add(new position_t(0, 2 * ((p.player == Player.BLACK) ? -1 : 1)));
            relative.Add(new position_t(1, 1 * ((p.player == Player.BLACK) ? -1 : 1)));

            // iterate moves
            foreach (position_t move in relative)
            {
                position_t moved = new position_t(move.letter + pos.letter, move.number + pos.number);

                // bounds check
                if (moved.letter < 0 || moved.letter > 7 || moved.number < 0 || moved.number > 7)
                {
                    continue;
                }

                // double forward move
                if (moved.letter == pos.letter && board.Grid[moved.number][moved.letter].piece == Piece.NONE && Math.Abs(moved.number - pos.number) == 2)
                {
                    // check the first step
                    int  step        = -((moved.number - pos.number) / (Math.Abs(moved.number - pos.number)));
                    bool hasnt_moved = pos.number == ((p.player == Player.BLACK) ? 6 : 1);
                    if (board.Grid[moved.number + step][moved.letter].piece == Piece.NONE && hasnt_moved)
                    {
                        moves.Add(moved);
                    }
                }
                // if it's not blocked we can move forward
                else if (moved.letter == pos.letter && board.Grid[moved.number][moved.letter].piece == Piece.NONE)
                {
                    moves.Add(moved);
                }
                // angled attack
                else if (moved.letter != pos.letter && board.Grid[moved.number][moved.letter].piece != Piece.NONE && board.Grid[moved.number][moved.letter].player != p.player)
                {
                    moves.Add(moved);
                }
                // en passant
                else if (isEnPassant(board, new move_t(pos, moved)))
                {
                    moves.Add(moved);
                }
            }

            if (verify_check)// make sure each move doesn't put us in check
            {
                for (int i = moves.Count - 1; i >= 0; i--)
                {
                    ChessBoard b2 = LegalMoveSet.move(board, new move_t(pos, moves[i]));
                    if (isCheck(b2, p.player))
                    {
                        moves.RemoveAt(i);
                    }
                }
            }
            return(moves);
        }
Example #6
0
        private static List <position_t> King(ChessBoard board, position_t pos, bool verify_check = true)
        {
            List <position_t> moves = new List <position_t>();

            piece_t p = board.Grid[pos.number][pos.letter];

            if (p.piece == Piece.NONE)
            {
                return(moves);
            }

            // collect all relative moves possible
            List <position_t> relative = new List <position_t>();

            relative.Add(new position_t(-1, 1));
            relative.Add(new position_t(0, 1));
            relative.Add(new position_t(1, 1));

            relative.Add(new position_t(-1, 0));
            relative.Add(new position_t(1, 0));

            relative.Add(new position_t(-1, -1));
            relative.Add(new position_t(0, -1));
            relative.Add(new position_t(1, -1));

            // Iterate moves
            foreach (position_t move in relative)
            {
                position_t moved = new position_t(move.letter + pos.letter, move.number + pos.number);

                // bound check
                if (moved.letter < 0 || moved.letter > 7 || moved.number < 0 || moved.number > 7)
                {
                    continue;
                }

                // if it's not blocked we can move
                if (board.Grid[moved.number][moved.letter].piece == Piece.NONE || board.Grid[moved.number][moved.letter].player != p.player)
                {
                    if (verify_check) // make sure we don't put ourselves in check
                    {
                        ChessBoard b2 = LegalMoveSet.move(board, new move_t(pos, moved));
                        if (!isCheck(b2, p.player))
                        {
                            moves.Add(moved);
                        }
                    }
                    else
                    {
                        moves.Add(moved);
                    }
                }
            }

            // Castling

            /* A king can only castle if:
             * king has not moved
             * rook has not moved
             * king is not in check
             * king does not end up in check
             * king does not pass through any other peieces
             * king does not pass through any squares under attack
             * king knows secret handshake
             */
            if (verify_check)
            {
                if (!isCheck(board, p.player) &&
                    p.lastPosition.Equals(new position_t(-1, -1)))
                {
                    bool castleRight = allowCastle(board, p.player, pos, true);
                    bool castleLeft  = allowCastle(board, p.player, pos, false);

                    if (castleRight)
                    {
                        moves.Add(new position_t(6, pos.number));
                    }
                    if (castleLeft)
                    {
                        moves.Add(new position_t(2, pos.number));
                    }
                }
            }

            return(moves);
        }