diff --git a/src/dev/kske/chess/game/Game.java b/src/dev/kske/chess/game/Game.java
new file mode 100644
index 0000000..80fad76
--- /dev/null
+++ b/src/dev/kske/chess/game/Game.java
@@ -0,0 +1,41 @@
+package dev.kske.chess.game;
+
+import java.util.Map;
+
+import dev.kske.chess.board.Board;
+import dev.kske.chess.board.Move;
+import dev.kske.chess.board.Piece.Color;
+
+/**
+ * Project: Chess
+ * File: Game.java
+ * Created: 06.07.2019
+ * Author: Kai S. K. Engelbart
+ */
+public class Game {
+
+ private Map players;
+ private Board board;
+
+ public Game(Map players, Board board) {
+ this.players = players;
+ this.board = board;
+
+ // Initialize the game variable in each player
+ players.values().forEach(player -> player.setGame(this));
+ }
+
+ public void start() {
+ players.get(Color.WHITE).requestMove();
+ }
+
+ public void onMove(Player player, Move move) {
+ if (board.getPos(move).getColor() == player.color && board.attemptMove(move)) {
+ System.out.printf("%s: %s%n", player.color, move);
+ players.get(player.color.opposite()).requestMove();
+ } else {
+ System.out.printf("%s: Illegal move!%n", player.getColor());
+ player.requestMove();
+ }
+ }
+}
diff --git a/src/dev/kske/chess/game/NaturalPlayer.java b/src/dev/kske/chess/game/NaturalPlayer.java
new file mode 100644
index 0000000..b30225d
--- /dev/null
+++ b/src/dev/kske/chess/game/NaturalPlayer.java
@@ -0,0 +1,56 @@
+package dev.kske.chess.game;
+
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import dev.kske.chess.board.Board;
+import dev.kske.chess.board.Move;
+import dev.kske.chess.board.Piece.Color;
+import dev.kske.chess.board.Position;
+import dev.kske.chess.ui.BoardPanel;
+
+/**
+ * Project: Chess
+ * File: NaturalPlayer.java
+ * Created: 06.07.2019
+ * Author: Kai S. K. Engelbart
+ */
+public class NaturalPlayer extends Player {
+
+ private boolean moveRequested;
+
+ public NaturalPlayer(Board board, Color color, BoardPanel boardPanel) {
+ super(board, color);
+ moveRequested = false;
+ boardPanel.addMouseListener(new MouseAdapter() {
+
+ private Position pos;
+
+ @Override
+ public void mousePressed(MouseEvent evt) {
+ if (!moveRequested) return;
+ if (pos == null) {
+ pos = new Position(evt.getPoint().x / boardPanel.getTileSize(),
+ evt.getPoint().y / boardPanel.getTileSize());
+
+ if (board.get(pos) != null && board.get(pos).getColor() == color)
+ boardPanel.displayMoves(board.getMoves(pos));
+ else pos = null;
+ } else {
+ Position dest = new Position(evt.getPoint().x / boardPanel.getTileSize(),
+ evt.getPoint().y / boardPanel.getTileSize());
+
+ boardPanel.clearDisplayMoves();
+ moveRequested = false;
+ game.onMove(NaturalPlayer.this, new Move(pos, dest));
+ pos = null;
+ }
+ }
+ });
+ }
+
+ @Override
+ public void requestMove() {
+ moveRequested = true;
+ }
+}
diff --git a/src/dev/kske/chess/game/Player.java b/src/dev/kske/chess/game/Player.java
new file mode 100644
index 0000000..fd34dde
--- /dev/null
+++ b/src/dev/kske/chess/game/Player.java
@@ -0,0 +1,36 @@
+package dev.kske.chess.game;
+
+import dev.kske.chess.board.Board;
+import dev.kske.chess.board.Piece.Color;
+
+/**
+ * Project: Chess
+ * File: Player.java
+ * Created: 06.07.2019
+ * Author: Kai S. K. Engelbart
+ */
+public abstract class Player {
+
+ protected Game game;
+ protected Board board;
+ protected Color color;
+
+ public Player(Board board, Color color) {
+ this.board = board;
+ this.color = color;
+ }
+
+ public abstract void requestMove();
+
+ public Game getGame() { return game; }
+
+ public void setGame(Game game) { this.game = game; }
+
+ public Board getBoard() { return board; }
+
+ public void setBoard(Board board) { this.board = board; }
+
+ public Color getColor() { return color; }
+
+ public void setColor(Color color) { this.color = color; }
+}
diff --git a/src/dev/kske/chess/ui/BoardPanel.java b/src/dev/kske/chess/ui/BoardPanel.java
index d5e4269..a068ce5 100644
--- a/src/dev/kske/chess/ui/BoardPanel.java
+++ b/src/dev/kske/chess/ui/BoardPanel.java
@@ -5,8 +5,6 @@ import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
@@ -15,7 +13,6 @@ import javax.swing.JPanel;
import dev.kske.chess.board.Board;
import dev.kske.chess.board.Move;
-import dev.kske.chess.board.Position;
import dev.kske.chess.event.GameEvent;
import dev.kske.chess.event.GameEventListener;
@@ -61,33 +58,6 @@ public class BoardPanel extends JPanel implements GameEventListener {
});
setSize(getPreferredSize());
-
- // Add a mouse adapter for testing piece movement
- addMouseListener(new MouseAdapter() {
-
- private Position pos;
-
- @Override
- public void mousePressed(MouseEvent evt) {
- if (pos == null) {
- pos = new Position(evt.getPoint().x / tileSize, evt.getPoint().y / tileSize);
-
- if (board.get(pos) != null) {
- displayMoves.clear();
- displayMoves.addAll(board.getMoves(pos));
- repaint();
- }
- } else {
- Position dest = new Position(evt.getPoint().x / tileSize, evt.getPoint().y / tileSize);
-
- if (board.attemptMove(new Move(pos, dest))) {
- displayMoves.clear();
- repaint();
- }
- pos = null;
- }
- }
- });
}
@Override
@@ -133,7 +103,26 @@ public class BoardPanel extends JPanel implements GameEventListener {
}
/**
- * Reverts the board to its initial state
+ * Displays move destinations on the board.
+ *
+ * @param moves The moves to display
+ */
+ public void displayMoves(List moves) {
+ displayMoves.clear();
+ displayMoves.addAll(moves);
+ repaint();
+ }
+
+ /**
+ * Clears all display moves.
+ */
+ public void clearDisplayMoves() {
+ displayMoves.clear();
+ repaint();
+ }
+
+ /**
+ * Reverts the board to its initial state.
*/
public void reset() {
board.initializeDefaultPositions();
@@ -149,6 +138,8 @@ public class BoardPanel extends JPanel implements GameEventListener {
@Override
public Dimension getPreferredSize() { return new Dimension(480, 480); }
+ public int getTileSize() { return tileSize; }
+
public Board getBoard() { return board; }
public void setBoard(Board board) {
diff --git a/src/dev/kske/chess/ui/GameModeDialog.java b/src/dev/kske/chess/ui/GameModeDialog.java
new file mode 100644
index 0000000..5461767
--- /dev/null
+++ b/src/dev/kske/chess/ui/GameModeDialog.java
@@ -0,0 +1,49 @@
+package dev.kske.chess.ui;
+
+import java.awt.FlowLayout;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+
+import dev.kske.chess.board.Piece.Color;
+import dev.kske.chess.game.Game;
+import dev.kske.chess.game.NaturalPlayer;
+import dev.kske.chess.game.Player;
+
+/**
+ * Project: Chess
+ * File: GameModeDialog.java
+ * Created: 06.07.2019
+ * Author: Kai S. K. Engelbart
+ */
+public class GameModeDialog extends JDialog {
+
+ private static final long serialVersionUID = 5470026233924735607L;
+
+ /**
+ * Create the dialog.
+ */
+ public GameModeDialog(BoardPanel boardPanel) {
+ super();
+ setModal(true);
+ setTitle("Game Mode Selection");
+ setBounds(100, 100, 231, 99);
+ setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+ getContentPane().setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
+
+ JButton btnNatural = new JButton("Game against natural opponent");
+ btnNatural.addActionListener((evt) -> {
+ Map players = new HashMap<>();
+ players.put(Color.WHITE, new NaturalPlayer(boardPanel.getBoard(), Color.WHITE, boardPanel));
+ players.put(Color.BLACK, new NaturalPlayer(boardPanel.getBoard(), Color.BLACK, boardPanel));
+ new Game(players, boardPanel.getBoard()).start();
+ dispose();
+ });
+ getContentPane().add(btnNatural);
+
+ JButton btnAI = new JButton("Game against AI");
+ getContentPane().add(btnAI);
+ }
+}
diff --git a/src/dev/kske/chess/ui/MainWindow.java b/src/dev/kske/chess/ui/MainWindow.java
index 33c7574..8784f42 100644
--- a/src/dev/kske/chess/ui/MainWindow.java
+++ b/src/dev/kske/chess/ui/MainWindow.java
@@ -64,5 +64,8 @@ public class MainWindow {
btnRestart.addActionListener((evt) -> boardPanel.reset());
toolPanel.add(btnRestart);
mframe.pack();
+
+ // Display dialog for game mode selection
+ new GameModeDialog(boardPanel).setVisible(true);
}
}