Working on SAN serialization of moves
+ SAN generation for castling moves + Appending promotion piece symbol in pawn promotion SAN + Asking the user to view a generated PGN file
This commit is contained in:
		| @@ -4,7 +4,7 @@ package dev.kske.chess.board; | ||||
|  * Project: <strong>Chess</strong><br> | ||||
|  * File: <strong>Castling.java</strong><br> | ||||
|  * Created: <strong>2 Nov 2019</strong><br> | ||||
|  *  | ||||
|  * | ||||
|  * @since Chess v0.5-alpha | ||||
|  * @author Kai S. K. Engelbart | ||||
|  */ | ||||
| @@ -32,4 +32,13 @@ public class Castling extends Move { | ||||
| 		super.revert(board, capturedPiece); | ||||
| 		rookMove.revert(board, null); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return {@code O-O-O} for a queenside castling or {@code O-O} for a kingside | ||||
| 	 *         castling | ||||
| 	 */ | ||||
| 	@Override | ||||
| 	public String toSAN(Board board) { | ||||
| 		return rookMove.pos.x == 0 ? "O-O-O" : "O-O"; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -12,7 +12,7 @@ import dev.kske.chess.board.Piece.Color; | ||||
|  * Project: <strong>Chess</strong><br> | ||||
|  * File: <strong>Move.java</strong><br> | ||||
|  * Created: <strong>02.07.2019</strong><br> | ||||
|  *  | ||||
|  * | ||||
|  * @since Chess v0.1-alpha | ||||
|  * @author Kai S. K. Engelbart | ||||
|  */ | ||||
| @@ -50,7 +50,7 @@ public class Move { | ||||
| 		if (move.length() == 5) { | ||||
| 			try { | ||||
| 				return new PawnPromotion(pos, dest, Piece.fromFirstChar(move.charAt(4))); | ||||
| 			} catch (NoSuchMethodException | SecurityException | IllegalArgumentException e) { | ||||
| 			} catch (Exception e) { | ||||
| 				e.printStackTrace(); | ||||
| 				return null; | ||||
| 			} | ||||
| @@ -62,7 +62,7 @@ public class Move { | ||||
| 	/** | ||||
| 	 * Converts a move string from standard algebraic notation to a {@link Move} | ||||
| 	 * object. | ||||
| 	 *  | ||||
| 	 * | ||||
| 	 * @param sanMove the move string to convert from | ||||
| 	 * @param board   the board on which the move has to be executed | ||||
| 	 * @return the converted {@link Move} object | ||||
| @@ -112,7 +112,7 @@ public class Move { | ||||
| 						if (m.group("promotedTo") != null) { | ||||
| 							try { | ||||
| 								move = new PawnPromotion(pos, dest, Piece.fromFirstChar(m.group("promotedTo").charAt(0))); | ||||
| 							} catch (NoSuchMethodException | SecurityException | IllegalArgumentException e) { | ||||
| 							} catch (Exception e) { | ||||
| 								e.printStackTrace(); | ||||
| 							} | ||||
| 						} else move = new Move(pos, dest); | ||||
| @@ -130,7 +130,7 @@ public class Move { | ||||
| 						if (m.group("promotedTo") != null) { | ||||
| 							try { | ||||
| 								move = new PawnPromotion(pos, dest, Piece.fromFirstChar(m.group("promotedTo").charAt(0))); | ||||
| 							} catch (NoSuchMethodException | SecurityException | IllegalArgumentException e) { | ||||
| 							} catch (Exception e) { | ||||
| 								e.printStackTrace(); | ||||
| 							} | ||||
| 						} else move = new Move(pos, dest); | ||||
| @@ -147,7 +147,27 @@ public class Move { | ||||
| 		return null; | ||||
| 	} | ||||
|  | ||||
| 	public String toSAN(Board board) { return null; } | ||||
| 	public String toSAN(Board board) { | ||||
| 		final Piece		piece	= board.get(pos); | ||||
| 		StringBuilder	sb		= new StringBuilder(8); | ||||
|  | ||||
| 		// Piece symbol | ||||
| 		if(!(piece instanceof Pawn)) | ||||
| 			sb.append(Character.toUpperCase(piece.firstChar())); | ||||
|  | ||||
| 		// Position | ||||
| 		// TODO: Deconstruct position into optional file or rank | ||||
| 		// TODO: Omit if the move is a pawn push | ||||
| 		sb.append(pos.toLAN()); | ||||
|  | ||||
| 		// Capture indicator | ||||
| 		if (board.get(dest) != null) sb.append('x'); | ||||
|  | ||||
| 		// Destination | ||||
| 		sb.append(dest.toLAN()); | ||||
|  | ||||
| 		return sb.toString(); | ||||
| 	} | ||||
|  | ||||
| 	public boolean isHorizontal() { return getyDist() == 0; } | ||||
|  | ||||
|   | ||||
| @@ -7,7 +7,7 @@ import java.util.List; | ||||
|  * Project: <strong>Chess</strong><br> | ||||
|  * File: <strong>Pawn.java</strong><br> | ||||
|  * Created: <strong>01.07.2019</strong><br> | ||||
|  *  | ||||
|  * | ||||
|  * @since Chess v0.1-alpha | ||||
|  * @author Kai S. K. Engelbart | ||||
|  */ | ||||
| @@ -74,7 +74,7 @@ public class Pawn extends Piece { | ||||
| 					moves.add(new PawnPromotion(pos, dest, Rook.class)); | ||||
| 					moves.add(new PawnPromotion(pos, dest, Knight.class)); | ||||
| 					moves.add(new PawnPromotion(pos, dest, Bishop.class)); | ||||
| 				} catch (NoSuchMethodException | SecurityException | IllegalArgumentException e) { | ||||
| 				} catch (Exception e) { | ||||
| 					e.printStackTrace(); | ||||
| 				} | ||||
| 			} else moves.add(move); | ||||
|   | ||||
| @@ -10,27 +10,29 @@ import dev.kske.chess.board.Piece.Color; | ||||
|  * Project: <strong>Chess</strong><br> | ||||
|  * File: <strong>PawnPromotion.java</strong><br> | ||||
|  * Created: <strong>2 Nov 2019</strong><br> | ||||
|  *  | ||||
|  * | ||||
|  * @since Chess v0.5-alpha | ||||
|  * @author Kai S. K. Engelbart | ||||
|  */ | ||||
| public class PawnPromotion extends Move { | ||||
|  | ||||
| 	private final Class<? extends Piece>		promotionPieceClass; | ||||
| 	private final Constructor<? extends Piece>	promotionPieceConstructor; | ||||
| 	private final char							promotionPieceChar; | ||||
|  | ||||
| 	public PawnPromotion(Position pos, Position dest, Class<? extends Piece> promotionPieceClass) throws NoSuchMethodException, SecurityException { | ||||
| 	public PawnPromotion(Position pos, Position dest, Class<? extends Piece> promotionPieceClass) | ||||
| 			throws ReflectiveOperationException, RuntimeException { | ||||
| 		super(pos, dest); | ||||
| 		this.promotionPieceClass = promotionPieceClass; | ||||
|  | ||||
| 		// Cache piece constructor | ||||
| 		promotionPieceConstructor = promotionPieceClass.getDeclaredConstructor(Color.class, Board.class); | ||||
| 		promotionPieceConstructor.setAccessible(true); | ||||
|  | ||||
| 		// Get piece char | ||||
| 		promotionPieceChar = (char) promotionPieceClass.getMethod("firstChar").invoke(promotionPieceConstructor.newInstance(null, null)); | ||||
| 	} | ||||
|  | ||||
| 	public PawnPromotion(int xPos, int yPos, int xDest, int yDest, Class<? extends Piece> promotionPiece) | ||||
| 			throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, | ||||
| 			InstantiationException { | ||||
| 			throws ReflectiveOperationException, RuntimeException { | ||||
| 		this(new Position(xPos, yPos), new Position(xDest, yDest), promotionPiece); | ||||
| 	} | ||||
|  | ||||
| @@ -51,22 +53,19 @@ public class PawnPromotion extends Move { | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public String toLAN() { | ||||
| 		char promotionPieceChar = '-'; | ||||
| 		try { | ||||
| 			promotionPieceChar = (char) promotionPieceClass.getMethod("firstChar").invoke(promotionPieceConstructor.newInstance(null, null)); | ||||
| 		} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException | ||||
| 				| InstantiationException e) { | ||||
| 			e.printStackTrace(); | ||||
| 		} | ||||
| 		return pos.toLAN() + dest.toLAN() + promotionPieceChar; | ||||
| 	public String toLAN() { return pos.toLAN() + dest.toLAN() + promotionPieceChar; } | ||||
|  | ||||
| 	@Override | ||||
| 	public String toSAN(Board board) { | ||||
| 		String san = super.toSAN(board); | ||||
| 		return san + Character.toUpperCase(promotionPieceChar); | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public int hashCode() { | ||||
| 		final int	prime	= 31; | ||||
| 		int			result	= super.hashCode(); | ||||
| 		result = prime * result + Objects.hash(promotionPieceClass); | ||||
| 		result = prime * result + Objects.hash(promotionPieceChar, promotionPieceConstructor); | ||||
| 		return result; | ||||
| 	} | ||||
|  | ||||
| @@ -74,8 +73,8 @@ public class PawnPromotion extends Move { | ||||
| 	public boolean equals(Object obj) { | ||||
| 		if (this == obj) return true; | ||||
| 		if (!super.equals(obj)) return false; | ||||
| 		if (getClass() != obj.getClass()) return false; | ||||
| 		if (!(obj instanceof PawnPromotion)) return false; | ||||
| 		PawnPromotion other = (PawnPromotion) obj; | ||||
| 		return Objects.equals(promotionPieceClass, other.promotionPieceClass); | ||||
| 		return promotionPieceChar == other.promotionPieceChar && Objects.equals(promotionPieceConstructor, other.promotionPieceConstructor); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| package dev.kske.chess.ui; | ||||
|  | ||||
| import java.awt.Desktop; | ||||
| import java.awt.EventQueue; | ||||
| import java.awt.Toolkit; | ||||
| import java.awt.dnd.DropTarget; | ||||
| @@ -168,7 +169,6 @@ public class MainWindow extends JFrame { | ||||
|  | ||||
| 	public void saveFile(File file) { | ||||
| 		final int		dotIndex	= file.getName().lastIndexOf('.'); | ||||
| 		final String	name		= file.getName().substring(0, dotIndex); | ||||
| 		final String	extension	= file.getName().substring(dotIndex).toLowerCase(); | ||||
|  | ||||
| 		if (extension.equals(".pgn")) try { | ||||
| @@ -178,6 +178,12 @@ public class MainWindow extends JFrame { | ||||
| 			PGNDatabase pgnDB = new PGNDatabase(); | ||||
| 			pgnDB.getGames().add(pgnGame); | ||||
| 			pgnDB.save(file); | ||||
|  | ||||
| 			if (JOptionPane.showConfirmDialog(this, | ||||
| 					"Game export finished. Do you want to view the created file?", | ||||
| 					"Game export finished", | ||||
| 					JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) | ||||
| 				Desktop.getDesktop().open(file); | ||||
| 		} catch (IOException e) { | ||||
| 			e.printStackTrace(); | ||||
| 			JOptionPane.showMessageDialog(this, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user