package chess.play; import java.util.List; import java.util.Scanner; import chess.board.ArrayBoard; import chess.board.ArrayMove; import chess.bots.LazySearcher; import chess.bots.SimpleSearcher; import chess.game.SimpleEvaluator; import cse332.chess.interfaces.Searcher; // @author Caitlin Schaefer (ceschae@uw.edu) // 7/30/18 // CSE 332 - Summer 2018 // // A local "bot vs. bot" chess program so // two students can compete their bots against // each other. Both students should run this program // and follow instructions on entering moves one by // one. Bots will recommend all moves, but the students // have to enter each move into the other computer. public class LocalBvB { public static final String STARTING_POSITION = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; private ArrayBoard board; private boolean playerGoesFirst; private Searcher bot; private Scanner console; private String winner; public static void main(String[] args) { LocalBvB game = new LocalBvB(); game.play(); } public LocalBvB() { intro(); } // Plays the game through the console. The human player contributes moves, // and the bot makes a move response, repeat until win condition. public void play() { this.board = ArrayBoard.FACTORY.create().init(STARTING_POSITION); System.out.print("is player playing as black (1) or white (2)? "); String line = this.console.nextLine(); Scanner input = new Scanner(line); int turn = input.nextInt(); turn--; // sets black to 0, white to 1 if (turn == 0) { this.playerGoesFirst = true; } // otherwise autoset to false // Change "LazySearcher" here to make the bot harder setupPlayer(new LazySearcher(), 3, 3); while (this.board.generateMoves().size() > 0 && this.board.allPiecesOfColor(this.playerGoesFirst? turn % 2 : (turn - 1) % 2).hasNext()) { printCurrentBoard(turn); ArrayMove move; if (turn % 2 == 0) { // player goes on even turns move = getPlayerMove(); } else { // bot goes on odd turns move = this.bot.getBestMove(board, 1000, 1000); printBotMove(move); } this.board.applyMove(move); if (this.board.inCheck()) { System.out.println("WARNING: IN CHECK"); } turn++; } printCurrentBoard(turn); if (this.playerGoesFirst && turn % 2 == 1 || !this.playerGoesFirst && turn % 2 == 0) { System.out.println("you won!"); } else { System.out.println("bot won!"); } } // Takes in a Searcher, with a set depth and cutoff, and constructs // a bot for the user to play against. public void setupPlayer(Searcher searcher, int depth, int cutoff) { searcher.setDepth(depth); searcher.setCutoff(cutoff); searcher.setEvaluator(new SimpleEvaluator()); this.bot = searcher; } // Prints the intro to the console. public void intro() { System.out.println("Welcome to the Board vs. Board (BvB) chess program!"); System.out.println("Two chess bots play against each other using humans to enter"); System.out.println(" moves for them. A player enters a move, then the computer"); System.out.println(" recommends the next move to insert into the other computer,"); System.out.println(" so on until there's a win condition."); System.out.println(); System.out.println("Players enter moves in the form of (starting position) (ending position)"); System.out.println(" like so:"); System.out.println("next move? a2 b3"); System.out.println(); System.out.println("If you want to promote a pawn, you would do this by appending Q, R, B, or N"); System.out.println(" like so:"); System.out.println("next move? b7 b8 Q"); System.out.println(); System.out.println("Then the computer will print the current state of the board, and"); System.out.println(" print the next move to make:"); System.out.println("bot chooses move: h4 g3"); System.out.println(); this.console = new Scanner(System.in); } // Given which turn it is, prints the current board state to the console. public void printCurrentBoard(int turn) { System.out.printf("turn %3d: \n" + board.toString() + "\n", playerGoesFirst ? turn : turn - 1); } // Given a move, prints the current bot move to the console. public void printBotMove(ArrayMove move) { if (move != null) { System.out.print("bot chooses move: " + move.toString().substring(0, 2) + " " + move.toString().substring(2, 4)); if (move.toString().contains("=")) { System.out.println("raw move: " + move.toString()); System.out.println(" " + move.toString().charAt(5)); } else { System.out.println(); } } } // Takes in the player move from the console, including some // error checking, and returns the ArrayMove result (guaranteed // to be a valid move) public ArrayMove getPlayerMove() { String botInput = getBotInput(); ArrayMove move = validMove(botInput); while (move == null) { System.out.println("that's not a valid move!"); botInput = getBotInput(); if (botInput != null) { move = validMove(botInput); } } return move; } // Given String input, verifies that the move is valid. // Returns the move if valid string, returns null otherwise. public ArrayMove validMove(String input) { if (!ArrayBoard.onboard(ArrayBoard.indexOfSquare(input))) { return null; } else { ArrayMove move = this.board.createMoveFromString(input); if (!this.board.isLegalMove(move)) { return null; } else { return move; } } } // Takes in the string representation from the console, // verifies the format is valid, and returns a string // representation. public String getBotInput() { System.out.print("next move? "); String line = this.console.nextLine(); Scanner input = new Scanner(line); String start = input.next(); if (start.length() != 2) { input.close(); return null; } if (!input.hasNext()) { input.close(); return null; } String end = input.next(); if (end.length() != 2) { input.close(); return null; } if (input.hasNext()) { // handles promotions end += input.next(); if (end.length() != 3) { input.close(); return null; } } input.close(); return start + end; } }