package dev.kske.chess.game; import java.util.HashMap; import java.util.Map; import javax.swing.JOptionPane; import dev.kske.chess.board.Board; import dev.kske.chess.board.GameState; import dev.kske.chess.board.Move; import dev.kske.chess.board.Piece.Color; import dev.kske.chess.event.EventBus; import dev.kske.chess.event.MoveEvent; import dev.kske.chess.game.ai.AIPlayer; import dev.kske.chess.ui.BoardComponent; import dev.kske.chess.ui.BoardPane; import dev.kske.chess.ui.EngineUtil; import dev.kske.chess.ui.EngineUtil.EngineInfo; import dev.kske.chess.ui.OverlayComponent; /** * Project: Chess
* File: Game.java
* Created: 06.07.2019
* Author: Kai S. K. Engelbart */ public class Game { private Map players = new HashMap<>(); private Board board; private OverlayComponent overlayComponent; private BoardComponent boardComponent; public Game(BoardPane boardPane, String whiteName, String blackName) { board = new Board(); init(boardPane, whiteName, blackName); } public Game(BoardPane boardPane, String whiteName, String blackName, String fen) { board = new Board(fen); init(boardPane, whiteName, blackName); } private void init(BoardPane boardPane, String whiteName, String blackName) { // Initialize / synchronize UI overlayComponent = boardPane.getOverlayComponent(); boardComponent = boardPane.getBoardComponent(); boardComponent.setBoard(board); // Initialize players players.put(Color.WHITE, getPlayer(whiteName, Color.WHITE)); players.put(Color.BLACK, getPlayer(blackName, Color.BLACK)); // Initialize the game variable in each player players.values().forEach(player -> player.setGame(this)); } private Player getPlayer(String name, Color color) { switch (name) { case "Natural Player": return new NaturalPlayer(color, overlayComponent); case "AI Player": return new AIPlayer(color, 4, -10); default: for (EngineInfo info : EngineUtil.getEngineInfos()) if (info.name.equals(name)) return new UCIPlayer(color, info.path); System.err.println("Invalid player name: " + name); return null; } } public void onMove(Player player, Move move) { if (board.getPos(move).getColor() == player.color && board.attemptMove(move)) { // Redraw boardComponent.repaint(); overlayComponent.displayArrow(move); // Run garbage collection System.gc(); System.out.printf("%s: %s%n", player.color, move); System.out.println("FEN: " + board.toFEN()); EventBus.getInstance().dispatch(new MoveEvent(move)); GameState eventType = board.getGameEventType(board.getDest(move).getColor().opposite()); switch (eventType) { case CHECKMATE: case STALEMATE: String result = String.format("%s in %s!%n", player.color.opposite(), eventType); System.out.print(result); JOptionPane.showMessageDialog(boardComponent, result); break; case CHECK: System.out.printf("%s in check!%n", player.color.opposite()); default: players.get(board.getLog().getActiveColor()).requestMove(); } } else player.requestMove(); } public void start() { players.get(board.getLog().getActiveColor()).requestMove(); } public void reset() { players.values().forEach(Player::cancelMove); board.initDefaultPositions(); boardComponent.repaint(); overlayComponent.clearDots(); overlayComponent.clearArrow(); } /** * Stops the game by disconnecting its players form the UI. */ public void stop() { players.values().forEach(Player::disconnect); } /** * Assigns the players their opposite colors. */ public void swapColors() { players.values().forEach(Player::cancelMove); Player white = players.get(Color.WHITE); Player black = players.get(Color.BLACK); white.setColor(Color.BLACK); black.setColor(Color.WHITE); players.put(Color.WHITE, black); players.put(Color.BLACK, white); players.get(board.getLog().getActiveColor()).requestMove(); } /** * @return The board on which this game's moves are made */ public Board getBoard() { return board; } /** * @return The players participating in this game */ public Map getPlayers() { return players; } }