help
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
package chess;
|
package chess;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
// An actor is an entity capable of making descisions on the board.
|
// An actor is an entity capable of making descisions on the board.
|
||||||
abstract class Actor {
|
abstract class Actor {
|
||||||
Util.Col col; // The color the Actor is acting as.
|
Util.Col col; // The color the Actor is acting as.
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ class Board {
|
|||||||
Util.scale, Util.scale, OutlineMode.SOLID,
|
Util.scale, Util.scale, OutlineMode.SOLID,
|
||||||
new Color(0, 150, 200, 150)
|
new Color(0, 150, 200, 150)
|
||||||
);
|
);
|
||||||
|
else if (info == Info.PROMOTION)
|
||||||
|
infoImage = new RectangleImage(
|
||||||
|
Util.scale, Util.scale, OutlineMode.SOLID,
|
||||||
|
new Color(200, 50, 200, 150)
|
||||||
|
);
|
||||||
|
|
||||||
scene.placeImageXY(
|
scene.placeImageXY(
|
||||||
new OverlayImage(
|
new OverlayImage(
|
||||||
@@ -64,6 +69,22 @@ class Board {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for a pawn eligible for promotion.
|
||||||
|
boolean isPawnPromotionPosition(Coord coord, Piece piece) {
|
||||||
|
if (piece == null || piece.type != PieceType.PAWN) return false;
|
||||||
|
|
||||||
|
boolean isPromotionPosition =
|
||||||
|
(piece.col == Util.Col.WHITE && coord.y == 0) ||
|
||||||
|
(piece.col == Util.Col.BLACK && coord.y == 7);
|
||||||
|
|
||||||
|
return isPromotionPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display promotion dialog.
|
||||||
|
void displayPromotionOptions(Coord coord) {
|
||||||
|
this.info.put(coord, Info.PROMOTION);
|
||||||
|
}
|
||||||
|
|
||||||
WorldImage drawPiece(Piece piece) {
|
WorldImage drawPiece(Piece piece) {
|
||||||
return (piece == null) ? new EmptyImage() : piece.draw();
|
return (piece == null) ? new EmptyImage() : piece.draw();
|
||||||
}
|
}
|
||||||
@@ -105,6 +126,15 @@ class Board {
|
|||||||
|
|
||||||
this.drop(targ);
|
this.drop(targ);
|
||||||
this.set(dest, piece);
|
this.set(dest, piece);
|
||||||
|
|
||||||
|
// Check if a pawn needs promotion.
|
||||||
|
if (piece.type == PieceType.PAWN &&
|
||||||
|
isPawnPromotionPosition(dest, piece)) {
|
||||||
|
// Hold turn til promotion complete.
|
||||||
|
this.game.setAwaitingPromotion(dest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.game.changeActive();
|
this.game.changeActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,6 +145,31 @@ class Board {
|
|||||||
return piece.moves(coord, this);
|
return piece.moves(coord, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Promote pawn to type.
|
||||||
|
void promotePawn(Coord pawnPos, PieceType promotionType) {
|
||||||
|
Piece pawn = this.get(pawnPos);
|
||||||
|
if (pawn == null || pawn.type != PieceType.PAWN) return;
|
||||||
|
|
||||||
|
Util.Col color = pawn.col;
|
||||||
|
Piece newPiece = null;
|
||||||
|
|
||||||
|
switch (promotionType) {
|
||||||
|
case QUEEN: newPiece = new Queen(color); break;
|
||||||
|
case ROOK: newPiece = new Rook(color); break;
|
||||||
|
case BISHOP: newPiece = new Bishop(color); break;
|
||||||
|
case KNIGHT: newPiece = new Knight(color); break;
|
||||||
|
default: newPiece = new Queen(color); // Default queen because best.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace pawn with new piece.
|
||||||
|
this.set(pawnPos, newPiece);
|
||||||
|
|
||||||
|
// Clear promotion indicator.
|
||||||
|
this.info.remove(pawnPos);
|
||||||
|
|
||||||
|
this.game.promotionComplete();
|
||||||
|
}
|
||||||
|
|
||||||
// Is the selected space free? (either nothing there, or an enemy piece).
|
// Is the selected space free? (either nothing there, or an enemy piece).
|
||||||
boolean isFree(Coord coord, Util.Col col) {
|
boolean isFree(Coord coord, Util.Col col) {
|
||||||
return this.get(coord) == null || this.get(coord).col != col;
|
return this.get(coord) == null || this.get(coord).col != col;
|
||||||
@@ -234,7 +289,7 @@ class Board {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Information layered over the board.
|
// Information layered over the board.
|
||||||
enum Info { CANMOVE, WARN, SELECTED }
|
enum Info { CANMOVE, WARN, SELECTED, PROMOTION }
|
||||||
|
|
||||||
// Measured from top left.
|
// Measured from top left.
|
||||||
class Coord {
|
class Coord {
|
||||||
|
|||||||
+70
-15
@@ -11,6 +11,8 @@ class Game extends World {
|
|||||||
WorldScene scene;
|
WorldScene scene;
|
||||||
Actor activeActor;
|
Actor activeActor;
|
||||||
Actor winner;
|
Actor winner;
|
||||||
|
Coord awaitingPromotion; // Tracks pawn awaiting promotion.
|
||||||
|
boolean promotionMode; // Whether game is in special promotion mode.
|
||||||
|
|
||||||
Game(Actor white, Actor black, Board board) {
|
Game(Actor white, Actor black, Board board) {
|
||||||
this.white = white;
|
this.white = white;
|
||||||
@@ -18,6 +20,8 @@ class Game extends World {
|
|||||||
this.board = board;
|
this.board = board;
|
||||||
this.activeActor = this.white;
|
this.activeActor = this.white;
|
||||||
this.winner = null;
|
this.winner = null;
|
||||||
|
this.awaitingPromotion = null;
|
||||||
|
this.promotionMode = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Game() {
|
Game() {
|
||||||
@@ -26,6 +30,8 @@ class Game extends World {
|
|||||||
this.black = new Player(Util.Col.BLACK, this.board);
|
this.black = new Player(Util.Col.BLACK, this.board);
|
||||||
this.activeActor = this.white;
|
this.activeActor = this.white;
|
||||||
this.winner = null;
|
this.winner = null;
|
||||||
|
this.awaitingPromotion = null;
|
||||||
|
this.promotionMode = false;
|
||||||
|
|
||||||
this.setup();
|
this.setup();
|
||||||
}
|
}
|
||||||
@@ -53,14 +59,30 @@ class Game extends World {
|
|||||||
Util.scale * 4, 3 * Util.scale
|
Util.scale * 4, 3 * Util.scale
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.scene.placeImageXY(
|
if (this.promotionMode) {
|
||||||
new TextImage(
|
this.scene.placeImageXY(
|
||||||
(this.activeActor.equals(this.white) ? "white" : "black") +
|
new TextImage(
|
||||||
"'s turn",
|
"PROMOTE: [Q]ueen; [R]ook; [B]ishop; "
|
||||||
Util.scale / 2, Color.red
|
+ "K[N]ight",
|
||||||
),
|
Util.scale / 3, Color.magenta
|
||||||
Util.scale * 2, 3 * Util.scale
|
),
|
||||||
);
|
Util.scale * 4, 3 * Util.scale
|
||||||
|
);
|
||||||
|
|
||||||
|
// Highlight pawn being promoted.
|
||||||
|
if (this.awaitingPromotion != null) {
|
||||||
|
this.board.displayPromotionOptions(this.awaitingPromotion);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.scene.placeImageXY(
|
||||||
|
new TextImage(
|
||||||
|
(this.activeActor.equals(this.white) ? "white" : "black"
|
||||||
|
) + "'s turn",
|
||||||
|
Util.scale / 2, Color.red
|
||||||
|
),
|
||||||
|
Util.scale * 2, 3 * Util.scale
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,12 +161,16 @@ class Game extends World {
|
|||||||
|
|
||||||
public void onMouseClicked(Posn posn) {
|
public void onMouseClicked(Posn posn) {
|
||||||
// Process clicks if game not over.
|
// Process clicks if game not over.
|
||||||
if (this.winner == null) this.activeActor.click(this.where(posn));
|
if (this.winner == null && !this.promotionMode)
|
||||||
|
this.activeActor.click(this.where(posn));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onKeyEvent(String key) {
|
public void onKeyEvent(String key) {
|
||||||
// Process keys if game is not over.
|
// Process keys if game is not over.
|
||||||
if (this.winner == null) this.activeActor.key(key);
|
if (this.winner == null) {
|
||||||
|
if (this.promotionMode) handlePromotionKey(key);
|
||||||
|
else this.activeActor.key(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeActive() {
|
void changeActive() {
|
||||||
@@ -152,12 +178,41 @@ class Game extends World {
|
|||||||
else this.activeActor = this.white;
|
else this.activeActor = this.white;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setWinner(Actor winner) {
|
// Enter promotion mode.
|
||||||
this.winner = winner;
|
void setAwaitingPromotion(Coord pawnPos) {
|
||||||
System.out.println(
|
this.awaitingPromotion = pawnPos;
|
||||||
(winner.equals(this.white) ? "WHITE" : "BLACK") + " WINS!"
|
this.promotionMode = true;
|
||||||
);
|
this.board.displayPromotionOptions(pawnPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Promotion selection key.
|
||||||
|
void handlePromotionKey(String key) {
|
||||||
|
if (this.awaitingPromotion == null) return;
|
||||||
|
|
||||||
|
PieceType promotionType = null;
|
||||||
|
|
||||||
|
switch (key.toLowerCase()) {
|
||||||
|
case "q": promotionType = PieceType.QUEEN; break;
|
||||||
|
case "r": promotionType = PieceType.ROOK; break;
|
||||||
|
case "b": promotionType = PieceType.BISHOP; break;
|
||||||
|
case "n":
|
||||||
|
promotionType = PieceType.KNIGHT;
|
||||||
|
break; // N for knight because K already taken for vim keys :P.
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (promotionType != null)
|
||||||
|
this.board.promotePawn(this.awaitingPromotion, promotionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when promotion is complete.
|
||||||
|
void promotionComplete() {
|
||||||
|
this.awaitingPromotion = null;
|
||||||
|
this.promotionMode = false;
|
||||||
|
this.changeActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setWinner(Actor winner) { this.winner = winner; }
|
||||||
|
|
||||||
boolean isGameOver() { return this.winner != null; }
|
boolean isGameOver() { return this.winner != null; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,12 @@ class Pawn extends Piece {
|
|||||||
|
|
||||||
return moves;
|
return moves;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if pawn in promotion position.
|
||||||
|
boolean canPromote(Coord coord) {
|
||||||
|
return (this.col == Util.Col.WHITE && coord.y == 0) ||
|
||||||
|
(this.col == Util.Col.BLACK && coord.y == Util.boardW - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Rook extends Piece {
|
class Rook extends Piece {
|
||||||
@@ -121,12 +127,6 @@ class Bishop extends Piece {
|
|||||||
|
|
||||||
ArrayList<Coord> moves(Coord coord, Board board) {
|
ArrayList<Coord> moves(Coord coord, Board board) {
|
||||||
ArrayList<Coord> moves = new ArrayList<Coord>();
|
ArrayList<Coord> moves = new ArrayList<Coord>();
|
||||||
/*
|
|
||||||
for (int i = -7; i < 8; i++) {
|
|
||||||
if (i == 0) continue; // Can't move to own position.
|
|
||||||
moves.add(new Coord(coord.x + i, coord.y + i));
|
|
||||||
moves.add(new Coord(coord.x + i, coord.y - i));
|
|
||||||
}*/
|
|
||||||
ArrayList<Coord> ne = board.getLineDiagNE(coord, this.col);
|
ArrayList<Coord> ne = board.getLineDiagNE(coord, this.col);
|
||||||
ArrayList<Coord> nw = board.getLineDiagNW(coord, this.col);
|
ArrayList<Coord> nw = board.getLineDiagNW(coord, this.col);
|
||||||
ArrayList<Coord> se = board.getLineDiagSE(coord, this.col);
|
ArrayList<Coord> se = board.getLineDiagSE(coord, this.col);
|
||||||
|
|||||||
@@ -2,11 +2,15 @@ package chess;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
// A human-controlled Actor."
|
// A human-controlled Actor.
|
||||||
class Player extends Actor {
|
class Player extends Actor {
|
||||||
Coord selected; // The currently selected piece.
|
Coord selected; // The currently selected piece.
|
||||||
|
Coord promotionPending; // Tracks if in a promotion.
|
||||||
|
|
||||||
Player(Util.Col col, Board board) { super(col, board); }
|
Player(Util.Col col, Board board) {
|
||||||
|
super(col, board);
|
||||||
|
this.promotionPending = null;
|
||||||
|
}
|
||||||
|
|
||||||
void click(Coord coord) {
|
void click(Coord coord) {
|
||||||
Piece piece = this.board.get(coord);
|
Piece piece = this.board.get(coord);
|
||||||
@@ -34,6 +38,17 @@ class Player extends Actor {
|
|||||||
System.out.println(
|
System.out.println(
|
||||||
"clicked on moveable space with something selected"
|
"clicked on moveable space with something selected"
|
||||||
);
|
);
|
||||||
|
// Check if this is a pawn that'll be promoted.
|
||||||
|
Piece movingPiece = this.board.get(this.selected);
|
||||||
|
boolean isPawnPromotion = false;
|
||||||
|
|
||||||
|
if (movingPiece != null && movingPiece.type == PieceType.PAWN) {
|
||||||
|
isPawnPromotion =
|
||||||
|
(movingPiece.col == Util.Col.WHITE && coord.y % 7 == 0
|
||||||
|
); // Check if on end of board; modulo is nice here.
|
||||||
|
if (isPawnPromotion) this.promotionPending = coord;
|
||||||
|
}
|
||||||
|
|
||||||
this.board.move(this.selected, coord);
|
this.board.move(this.selected, coord);
|
||||||
this.board.unselect(this.selected);
|
this.board.unselect(this.selected);
|
||||||
this.board.undisplayMoves(moves);
|
this.board.undisplayMoves(moves);
|
||||||
@@ -58,9 +73,16 @@ class Player extends Actor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void key(String key) {
|
void key(String key) {
|
||||||
|
// Not my problem.
|
||||||
|
if (this.promotionPending != null) return;
|
||||||
|
|
||||||
if (this.selected == null) return;
|
if (this.selected == null) return;
|
||||||
|
|
||||||
this.board.undisplayMoves(this.board.getMoves(this.selected));
|
this.board.undisplayMoves(this.board.getMoves(this.selected));
|
||||||
this.board.unselect(this.selected);
|
this.board.unselect(this.selected);
|
||||||
this.selected = null;
|
this.selected = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Call when promotion complete.
|
||||||
|
void clearPromotionPending() { this.promotionPending = null; }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user