package bibliothek.chess.model; import javax.swing.Icon; import bibliothek.chess.util.Utils; import bibliothek.util.container.Single; /** * A figure is a part of a chess-board. Every figure has a {@link Behavior} that * describes how it can move and attack. Each figure has also an {@link Icon} * and belongs to a {@link Player}. * @author Benjamin Sigg */ public final class Figure { /** * Describes what kind of figure an instance of {@link Figure} is. * @author Benjamin Sigg */ public static enum Type{ /** most important figure of all */ KING( "King", "k", new King() ), /** most dangerous figure */ QUEEN( "Queen", "q", new Queen() ), /** can move only diagonal */ BISHOP( "Bishop", "b", new Bishop() ), /** can jump over other figures */ KNIGHT( "Knight", "n", new Knight() ), /** can move only horizontal and vertical*/ ROCK( "Rock", "r", new Rock() ), /** very slow figure */ PAWN( "Pawn", "p", new Pawn() ); /** The human readable name of this type */ private String name; /** A small version of {@link #name} */ private String sign; /** Describes how figures of this type behave */ private Behavior behavior; private Type( String name, String sign, Behavior behavior ){ this.name = name; this.sign = sign; this.behavior = behavior; } /** * Gets the name of this type. * @return A string that can be read by humans. */ public String getName() { return name; } /** * Gets the sign of this type. * @return A unique, small name */ public String getSign() { return sign; } /** * Gets the behavior of figures of this type. * @return The unique behavior */ public Behavior getBehavior() { return behavior; } } /** An {@link Icon} of size 16x16 */ private Icon smallIcon; /** An {@link Icon} of size 48x48 */ private Icon bigIcon; /** The board on which this figure stands */ private Board board; /** The player to which this figure belongs */ private Player player; /** The row in which this figure stands */ private int row; /** The column in which this figure stands */ private int column; /** * The type of this figure, describing how this figure looks like, and how * it can be used by a player. */ private Type type; /** Behavior describing how this figure can be moved by the player. */ private Behavior behavior; /** whether this figure has already been moved or not */ private boolean moved = false; /** whether this figure has been moved exactly once */ private boolean justMoved = false; /** * Creates a new figure. * @param board the board on which the figure will stand * @param player the owner of the figure * @param type what kind of figure * @param row the initial position (row-coordinate) * @param column the initial position (column-coordinate) */ public Figure( Board board, Player player, Type type, int row, int column ){ this( board, player, type, row, column, true ); } /** * Creates a new figure. * @param board the board on which the figure will stand * @param player the owner of the figure * @param type what kind of figure * @param row the initial position (row-coordinate) * @param column the initial position (column-coordinate) * @param icons whether the figure should create icons or not. Not creating * icons is faster, however the figure can't be displayed without icons. */ private Figure( Board board, Player player, Type type, int row, int column, boolean icons ){ this.board = board; this.player = player; this.type = type; if( icons ){ this.smallIcon = Utils.getChessIcon( type.getSign(), player, 16 ); this.bigIcon = Utils.getChessIcon( type.getSign(), player, 48 ); } this.row = row; this.column = column; this.behavior = type.getBehavior(); } /** * Gets the name of this figure. * @return the name, a string readable by a human * @see Type#name() */ public String getName(){ return type.getName(); } /** * Tells what kind of figure this figure is. * @return the type */ public Type getType() { return type; } /** * Gets the board on which this figure stands. * @return the board */ public Board getBoard() { return board; } /** * Gets the owner of this figure. * @return the player which can move this figure */ public Player getPlayer(){ return player; } /** * Gets a small icon for this figure. * @return an icon of size 16x16 */ public Icon getSmallIcon(){ return smallIcon; } /** * Gets a big icon for this figure. * @return an icon of size 48x48 */ public Icon getBigIcon(){ return bigIcon; } /** * Gets the row in which this figure stands currently * @return the row */ public int getRow() { return row; } /** * Gets the column in which this figure stands currently. * @return the column */ public int getColumn() { return column; } /** * Tells whether this figure has been moved at least once or not. * @return <code>true</code> if the figure has been moved */ public boolean isMoved() { return moved; } /** * Tells whether this figure has been moved exactly once or not * @return <code>true</code> if this figure has been moved exactly once * and only in the last stroke. */ public boolean isJustMoved() { return justMoved; } /** * Cleans the just moved flag and sets it to <code>false</code>. */ public void cleanJustMoved(){ justMoved = false; } /** * Changes the location of this figure. This might have influence on other * figures on the {@link #getBoard() board}, according to the rules of * chess. The behavior is unspecified for coordinates which are not * reachable by the rules of the game. * @param row the new row * @param column the new column */ public void setLocation( int row, int column ){ behavior.moving( board, this, row, column ); justMoved = !moved; moved = true; this.row = row; this.column = column; } /** * Creates a copy of this figure using the new board * @param board the new board * @return the new figure */ public Figure copy( Board board ){ Figure figure = new Figure( board, player, type, row, column, false ); figure.moved = moved; figure.justMoved = justMoved; return figure; } /** * Tells whether this figure can move to at least one other cell or not. * @return <code>true</code> if the figure can be moved. */ public boolean moveable(){ final Single<Boolean> result = new Single<Boolean>( false ); reachable( new Board.CellVisitor(){ public boolean visit( int r, int c, Figure figure ) { result.setA( true ); return false; } }); return result.getA(); } /** * Visits all cells which can be reached within the next legal move. * @param visitor the visitor */ public void reachable( Board.CellVisitor visitor ){ behavior.reachable( board, this, visitor ); } /** * Visits all cells which can be attacked within the next legal move. * @param visitor the visitor */ public void attackable( Board.CellVisitor visitor ){ behavior.attackable( board, this, visitor ); } @Override public String toString() { return player + " " + getName(); } }