diff --git a/src/dev/kske/chess/board/Castling.java b/src/dev/kske/chess/board/Castling.java index e631a24..9f973ad 100644 --- a/src/dev/kske/chess/board/Castling.java +++ b/src/dev/kske/chess/board/Castling.java @@ -4,7 +4,7 @@ package dev.kske.chess.board; * Project: Chess
* File: Castling.java
* Created: 2 Nov 2019
- * + * * @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"; + } } diff --git a/src/dev/kske/chess/board/Move.java b/src/dev/kske/chess/board/Move.java index 6196cdf..d3841c8 100644 --- a/src/dev/kske/chess/board/Move.java +++ b/src/dev/kske/chess/board/Move.java @@ -12,7 +12,7 @@ import dev.kske.chess.board.Piece.Color; * Project: Chess
* File: Move.java
* Created: 02.07.2019
- * + * * @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; } diff --git a/src/dev/kske/chess/board/Pawn.java b/src/dev/kske/chess/board/Pawn.java index 18e275e..7b44b0a 100644 --- a/src/dev/kske/chess/board/Pawn.java +++ b/src/dev/kske/chess/board/Pawn.java @@ -7,7 +7,7 @@ import java.util.List; * Project: Chess
* File: Pawn.java
* Created: 01.07.2019
- * + * * @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); diff --git a/src/dev/kske/chess/board/PawnPromotion.java b/src/dev/kske/chess/board/PawnPromotion.java index 91ddaac..2c78750 100644 --- a/src/dev/kske/chess/board/PawnPromotion.java +++ b/src/dev/kske/chess/board/PawnPromotion.java @@ -10,27 +10,29 @@ import dev.kske.chess.board.Piece.Color; * Project: Chess
* File: PawnPromotion.java
* Created: 2 Nov 2019
- * + * * @since Chess v0.5-alpha * @author Kai S. K. Engelbart */ public class PawnPromotion extends Move { - private final Class promotionPieceClass; private final Constructor promotionPieceConstructor; + private final char promotionPieceChar; - public PawnPromotion(Position pos, Position dest, Class promotionPieceClass) throws NoSuchMethodException, SecurityException { + public PawnPromotion(Position pos, Position dest, Class 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 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); } } diff --git a/src/dev/kske/chess/ui/MainWindow.java b/src/dev/kske/chess/ui/MainWindow.java index 1fe3960..3dc54b5 100644 --- a/src/dev/kske/chess/ui/MainWindow.java +++ b/src/dev/kske/chess/ui/MainWindow.java @@ -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,