Created Move#fromSAN, moved implementation from Board

This commit is contained in:
Kai S. K. Engelbart 2019-11-19 06:30:53 +01:00
parent 4dfd218440
commit 6cb0da80d7
Signed by: kske
GPG Key ID: 8BEB13EC5DF7EF13
2 changed files with 97 additions and 79 deletions

View File

@ -6,8 +6,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import dev.kske.chess.board.Piece.Color; import dev.kske.chess.board.Piece.Color;
@ -98,83 +96,7 @@ public class Board {
* @param sanMove The move to execute in SAN (Standard Algebraic Notation) * @param sanMove The move to execute in SAN (Standard Algebraic Notation)
*/ */
public void move(String sanMove) { public void move(String sanMove) {
Map<String, Pattern> patterns = new HashMap<>(); move(Move.fromSAN(sanMove, this));
patterns.put("pieceMove",
Pattern.compile(
"^(?<pieceType>[NBRQK])(?:(?<fromFile>[a-h])|(?<fromRank>[1-8])|(?<fromSquare>[a-h][1-8]))?x?(?<toSquare>[a-h][1-8])(?:\\+{0,2}|\\#)$"));
patterns.put("pawnCapture",
Pattern.compile("^(?<fromFile>[a-h])(?<fromRank>[1-8])?x(?<toSquare>[a-h][1-8])(?<promotedTo>[NBRQ])?(?:\\+{0,2}|\\#)?$"));
patterns.put("pawnPush", Pattern.compile("^(?<toSquare>[a-h][1-8])(?<promotedTo>[NBRQ])?(?:\\+{0,2}|\\#)$"));
patterns.put("castling", Pattern.compile("^(?<queenside>O-O-O)|(?<kingside>O-O)(?:\\+{0,2}|\\#)?$"));
patterns.forEach((patternName, pattern) -> {
Matcher m = pattern.matcher(sanMove);
if (m.find()) {
Position pos = null, dest = null;
Move move = null;
switch (patternName) {
case "pieceMove":
dest = Position.fromLAN(m.group("toSquare"));
if (m.group("fromSquare") != null) pos = Position.fromLAN(m.group("fromSquare"));
else {
Class<? extends Piece> pieceClass = Piece.fromFirstChar(m.group("pieceType").charAt(0));
char file;
int rank;
if (m.group("fromFile") != null) {
file = m.group("fromFile").charAt(0);
rank = get(pieceClass, file);
pos = Position.fromLAN(String.format("%c%d", file, rank));
} else if (m.group("fromRank") != null) {
rank = Integer.parseInt(m.group("fromRank").substring(0, 1));
file = get(pieceClass, rank);
pos = Position.fromLAN(String.format("%c%d", file, rank));
} else pos = get(pieceClass, dest);
}
move = new Move(pos, dest);
break;
case "pawnCapture":
char file = m.group("fromFile").charAt(0);
int rank = m.group("fromRank") == null ? get(Pawn.class, file) : Integer.parseInt(m.group("fromRank"));
dest = Position.fromLAN(m.group("toSquare"));
pos = Position.fromLAN(String.format("%c%d", file, rank));
if (m.group("promotedTo") != null) {
try {
move = new PawnPromotion(pos, dest, Piece.fromFirstChar(m.group("promotedTo").charAt(0)));
} catch (NoSuchMethodException | SecurityException | IllegalArgumentException e) {
e.printStackTrace();
}
} else move = new Move(pos, dest);
break;
case "pawnPush":
dest = Position.fromLAN(m.group("toSquare"));
int step = log.getActiveColor() == Color.WHITE ? 1 : -1;
// One step forward
if (boardArr[dest.x][dest.y + step] != null) pos = new Position(dest.x, dest.y + step);
// Double step forward
else pos = new Position(dest.x, dest.y + 2 * step);
if (m.group("promotedTo") != null) {
try {
move = new PawnPromotion(pos, dest, Piece.fromFirstChar(m.group("promotedTo").charAt(0)));
} catch (NoSuchMethodException | SecurityException | IllegalArgumentException e) {
e.printStackTrace();
}
} else move = new Move(pos, dest);
break;
case "castling":
pos = new Position(4, log.getActiveColor() == Color.WHITE ? 7 : 0);
dest = new Position(m.group("kingside") != null ? 6 : 2, pos.y);
move = new Castling(pos, dest);
break;
}
move(move);
return;
}
});
} }
/** /**

View File

@ -1,6 +1,12 @@
package dev.kske.chess.board; package dev.kske.chess.board;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import dev.kske.chess.board.Piece.Color;
/** /**
* Project: <strong>Chess</strong><br> * Project: <strong>Chess</strong><br>
@ -53,6 +59,96 @@ public class Move {
public String toLAN() { return getPos().toLAN() + getDest().toLAN(); } public String toLAN() { return getPos().toLAN() + getDest().toLAN(); }
/**
* 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
*/
public static Move fromSAN(String sanMove, Board board) {
Map<String, Pattern> patterns = new HashMap<>();
patterns.put("pieceMove",
Pattern.compile(
"^(?<pieceType>[NBRQK])(?:(?<fromFile>[a-h])|(?<fromRank>[1-8])|(?<fromSquare>[a-h][1-8]))?x?(?<toSquare>[a-h][1-8])(?:\\+{0,2}|\\#)$"));
patterns.put("pawnCapture",
Pattern.compile("^(?<fromFile>[a-h])(?<fromRank>[1-8])?x(?<toSquare>[a-h][1-8])(?<promotedTo>[NBRQ])?(?:\\+{0,2}|\\#)?$"));
patterns.put("pawnPush", Pattern.compile("^(?<toSquare>[a-h][1-8])(?<promotedTo>[NBRQ])?(?:\\+{0,2}|\\#)$"));
patterns.put("castling", Pattern.compile("^(?<queenside>O-O-O)|(?<kingside>O-O)(?:\\+{0,2}|\\#)?$"));
for (Map.Entry<String, Pattern> entry : patterns.entrySet()) {
Matcher m = entry.getValue().matcher(sanMove);
if (m.find()) {
Position pos = null, dest = null;
Move move = null;
switch (entry.getKey()) {
case "pieceMove":
dest = Position.fromLAN(m.group("toSquare"));
if (m.group("fromSquare") != null) pos = Position.fromLAN(m.group("fromSquare"));
else {
Class<? extends Piece> pieceClass = Piece.fromFirstChar(m.group("pieceType").charAt(0));
char file;
int rank;
if (m.group("fromFile") != null) {
file = m.group("fromFile").charAt(0);
rank = board.get(pieceClass, file);
pos = Position.fromLAN(String.format("%c%d", file, rank));
} else if (m.group("fromRank") != null) {
rank = Integer.parseInt(m.group("fromRank").substring(0, 1));
file = board.get(pieceClass, rank);
pos = Position.fromLAN(String.format("%c%d", file, rank));
} else pos = board.get(pieceClass, dest);
}
move = new Move(pos, dest);
break;
case "pawnCapture":
char file = m.group("fromFile").charAt(0);
int rank = m.group("fromRank") == null ? board.get(Pawn.class, file) : Integer.parseInt(m.group("fromRank"));
dest = Position.fromLAN(m.group("toSquare"));
pos = Position.fromLAN(String.format("%c%d", file, rank));
if (m.group("promotedTo") != null) {
try {
move = new PawnPromotion(pos, dest, Piece.fromFirstChar(m.group("promotedTo").charAt(0)));
} catch (NoSuchMethodException | SecurityException | IllegalArgumentException e) {
e.printStackTrace();
}
} else move = new Move(pos, dest);
break;
case "pawnPush":
dest = Position.fromLAN(m.group("toSquare"));
int step = board.getLog().getActiveColor() == Color.WHITE ? 1 : -1;
// One step forward
if (board.getBoardArr()[dest.x][dest.y + step] != null) pos = new Position(dest.x, dest.y + step);
// Double step forward
else pos = new Position(dest.x, dest.y + 2 * step);
if (m.group("promotedTo") != null) {
try {
move = new PawnPromotion(pos, dest, Piece.fromFirstChar(m.group("promotedTo").charAt(0)));
} catch (NoSuchMethodException | SecurityException | IllegalArgumentException e) {
e.printStackTrace();
}
} else move = new Move(pos, dest);
break;
case "castling":
pos = new Position(4, board.getLog().getActiveColor() == Color.WHITE ? 7 : 0);
dest = new Position(m.group("kingside") != null ? 6 : 2, pos.y);
move = new Castling(pos, dest);
break;
}
return move;
}
}
return null;
}
public String toSAN(Board board) { return null; }
public boolean isHorizontal() { return getyDist() == 0; } public boolean isHorizontal() { return getyDist() == 0; }
public boolean isVertical() { return getxDist() == 0; } public boolean isVertical() { return getxDist() == 0; }