@Override public void chooseMove() { long startTime = System.nanoTime(); Move bestMove = null; double bestScore = 0; // We need to initialize alpha and beta -infinity and + infinity respectively. double alpha = Double.NEGATIVE_INFINITY; double beta = Double.POSITIVE_INFINITY; int maxDepth; for (maxDepth = 1; (System.nanoTime() - startTime) <= maxTime; maxDepth++) { List<Move> legalMoves = GameState2P.getLegalMoves(state, index); bestScore = 0; for (Move m : legalMoves) { // If we run out time we break out. if ((System.nanoTime() - startTime) >= maxTime) { break; } GameState2P next = m.doMove(state); double score = getMinScoreAlphaBeta(next, maxDepth, alpha, beta); if (bestMove == null || score >= bestScore) { bestMove = m; bestScore = score; } } } System.out.println("Depth: " + maxDepth + " trans score: " + bestScore); GameState2P newState = bestMove.doMove(state); game.doMove(index, newState); }
/* * Consider all possible moves by our opponent */ private double getMinScoreAlphaBeta( final GameState2P state, int depth, double alpha, double beta) { double res = Double.POSITIVE_INFINITY; double score; // We try to get the current opponent state from the transposition table. TranspositionEntry entry = minTable.getEntryFromGameState(state); // Get the opponent's moves. final List<Move> opponentMoves = GameState2P.getLegalMoves(state, indexOpponent); // Check if current opp state existed before in table and that the depth is less than the depth // stored in the entry. We need to check the states as well, as it is possible that two state // has the same hashcode. // Then return the previous best minimax score for this state. if (null != entry && state.equals(entry.getGameState2P()) && depth <= entry.getDepth()) { res = entry.getMinimax(); } if (depth == 0 || state.isGameOver()) { res = state.evaluateState(index); } else { Comparator<Move> comparator = new Comparator<Move>() { @Override public int compare(Move move1, Move move2) { // Check if the current opponent moves exist in the transposition table. If it doesn't // set minimax // to positive infinity, in order words the worst result for the opponent. int lhs = (null != minTable.getEntryFromGameState(move1.doMove(state))) ? (int) minTable.getEntryFromGameState(move1.doMove(state)).getMinimax() : (int) Double.POSITIVE_INFINITY; int rhs = (null != minTable.getEntryFromGameState(move2.doMove(state))) ? (int) minTable.getEntryFromGameState(move2.doMove(state)).getMinimax() : (int) Double.POSITIVE_INFINITY; // If right is lower swap. if (lhs > rhs) { return 1; } else if (lhs == rhs) { return 0; } else { return -1; } } }; // For the minimax score we need to sort the opponent's moves by their scores lowest first, in // order to optimise // the search. Collections.sort(opponentMoves, comparator); // The opponent will go through their moves and try to get the best minimax score for them. // Once a promising child move is found store it with the minimax value in the transposition // table. for (Move move : opponentMoves) { GameState2P next = move.doMove(state); score = getMaxScoreAlphaBeta(next, depth - 1, alpha, beta); res = Math.min(res, score); beta = Math.min(beta, score); if (beta <= alpha) { // minTable.addEntry(next, res, depth); break; } } } return res; }
@Override public void doMove( String s, Table table, WhitePlayer whitePlayer, BlackPlayer blackPlayer, ArrayList<SaveState> saveStateArrayList, SaveState previousState, TextArea status) throws IOException, Mate, CheckIsOpen, CastlingDone, ChangePawn { // BufferedReader reader=new BufferedReader(new InputStreamReader(System.in)); while (!s.equals("exit")) { saveStateArrayList.add(new SaveState(table, whitePlayer, blackPlayer)); previousState = saveStateArrayList.get(saveStateArrayList.size() - 1); boolean nextToBlack = false; System.out.println("White player moves: " + s); // s = reader.readLine(); try { new WhiteMove(s).move(table, whitePlayer, blackPlayer); Cell myKingCell = table.getOpponentKingCell( WHITE, whitePlayer.getChessItemsMap(), blackPlayer.getChessItemsMap(), table); // is Check to my king? if (Move.isInAllItemsOfAvailableCellListBlack( myKingCell, blackPlayer.getChessItemsMap(), table)) { System.out.println("Black player will Announce you Check and Mate"); // Undo Last Move previousState.undoHere(table, whitePlayer, blackPlayer); // Undo Last Move table.toString(); throw new CheckIsOpen(); } // table.toString(); nextToBlack = true; } catch (PlayerSameChessItem playerSameChessItem) { System.out.println("Source & Target are the same"); } catch (EmptySourceCell emptySourceCell) { System.out.println("Source Cell is empty"); } catch (InvalidSource invalidSource) { System.out.println("Source is invalid"); } catch (NoCell noCell) { } catch (InvalidMoveString invalidMoveString) { System.out.println("String is invalid"); } catch (InvalidMove invalidMove) { } catch (NoAvailableCells noAvailableCells) { System.out.println("No Available Cells"); } /*catch (Check check) { }*/ if (nextToBlack) { // is Check or not? Cell kingCell = table.getOpponentKingCell( BLACK, whitePlayer.getChessItemsMap(), blackPlayer.getChessItemsMap(), table); if (Move.isInAllItemsOfAvailableCellListWhite( kingCell, whitePlayer.getChessItemsMap(), table)) { try { throw new Check(); } catch (Check check) { System.out.println("Check to Black Army"); // is Mate or not? ArrayList<BlackTestMove> blackTestMoves = new ArrayList<>(); saveStateArrayList.add(new SaveState(table, whitePlayer, blackPlayer)); previousState = saveStateArrayList.get(saveStateArrayList.size() - 1); for (SortedMap.Entry<String, ChessItem> item : blackPlayer.getChessItemsMap().entrySet()) { if (item.getValue() instanceof BlackKing) { try { for (Cell cell : new BlackKingMoves(table.getCellByString(item.getKey()), table, true) .getMoves()) { blackTestMoves.add( new BlackTestMove( item.getValue().toString(), item.getKey(), cell.toString())); } } catch (NoAvailableCells noAvailableCells) { } } if (item.getValue() instanceof BlackQueen) { try { for (Cell cell : new BlackQueenMoves(table.getCellByString(item.getKey()), table).getMoves()) { blackTestMoves.add( new BlackTestMove( item.getValue().toString(), item.getKey(), cell.toString())); } } catch (NoAvailableCells noAvailableCells) { } } if (item.getValue() instanceof BlackBishop) { try { for (Cell cell : new BlackBishopMoves(table.getCellByString(item.getKey()), table) .getMoves()) { blackTestMoves.add( new BlackTestMove( item.getValue().toString(), item.getKey(), cell.toString())); } } catch (NoAvailableCells noAvailableCells) { } } if (item.getValue() instanceof BlackKnight) { try { for (Cell cell : new BlackKnightMoves(table.getCellByString(item.getKey()), table) .getMoves()) { blackTestMoves.add( new BlackTestMove( item.getValue().toString(), item.getKey(), cell.toString())); } } catch (NoAvailableCells noAvailableCells) { } } if (item.getValue() instanceof BlackPawn) { try { for (Cell cell : new BlackPawnMoves(table.getCellByString(item.getKey()), table).getMoves()) { blackTestMoves.add( new BlackTestMove( item.getValue().toString(), item.getKey(), cell.toString())); } } catch (NoAvailableCells noAvailableCells) { } } if (item.getValue() instanceof BlackRook) { try { for (Cell cell : new BlackRookMoves(table.getCellByString(item.getKey()), table).getMoves()) { blackTestMoves.add( new BlackTestMove( item.getValue().toString(), item.getKey(), cell.toString())); } } catch (NoAvailableCells noAvailableCells) { } } } ArrayList<BlackTestMove> availableMoves = new ArrayList<>(); try { if (blackTestMoves.size() > 0) { for (BlackTestMove move : blackTestMoves) { if (move.getChessItem().equals(Black.KING)) { new BlackMove(move.getSource(), move.getDestination()) .move(table, whitePlayer, blackPlayer); if (!(Move.isInAllItemsOfAvailableCellListWhite( table.getCellByString(move.getDestination()), whitePlayer.getChessItemsMap(), table))) { availableMoves.add(move); } previousState.undoHere(table, whitePlayer, blackPlayer); } else { new BlackMove(move.getSource(), move.getDestination()) .move(table, whitePlayer, blackPlayer); if (!(Move.isInAllItemsOfAvailableCellListWhite( kingCell, whitePlayer.getChessItemsMap(), table))) { availableMoves.add(move); } previousState.undoHere(table, whitePlayer, blackPlayer); } } if (availableMoves.size() == 0) { throw new Mate(BLACK); } else { status.appendText("Available moves for black player are:\n"); System.out.println("Available moves for black player are:"); for (BlackTestMove move : availableMoves) { status.appendText(move.toString() + "\n"); System.out.println(move.toString()); } } } } catch (NoAvailableCells noAvailableCells) { } catch (NoCell noCell) { } catch (InvalidMove invalidMove) { } catch (PlayerSameChessItem playerSameChessItem) { } catch (EmptySourceCell emptySourceCell) { } catch (InvalidSource invalidSource) { } } } saveState = new SaveState(table, whitePlayer, blackPlayer); table.toString(); break; } } }