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 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);
}
}
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,