Improved PGN parsing, added PGN file loading
This commit is contained in:
parent
02a4b3ee32
commit
84158c2dac
@ -154,8 +154,6 @@ public class Board {
|
|||||||
// Move the rook
|
// Move the rook
|
||||||
Move rookMove = move.dest.x == 6 ? new Move(7, move.pos.y, 5, move.pos.y) // Kingside
|
Move rookMove = move.dest.x == 6 ? new Move(7, move.pos.y, 5, move.pos.y) // Kingside
|
||||||
: new Move(0, move.pos.y, 3, move.pos.y); // Queenside
|
: new Move(0, move.pos.y, 3, move.pos.y); // Queenside
|
||||||
|
|
||||||
// Move the rook
|
|
||||||
setDest(rookMove, getPos(rookMove));
|
setDest(rookMove, getPos(rookMove));
|
||||||
setPos(rookMove, null);
|
setPos(rookMove, null);
|
||||||
|
|
||||||
@ -193,18 +191,22 @@ public class Board {
|
|||||||
Map<String, Pattern> patterns = new HashMap<>();
|
Map<String, Pattern> patterns = new HashMap<>();
|
||||||
patterns.put("pieceMove",
|
patterns.put("pieceMove",
|
||||||
Pattern.compile(
|
Pattern.compile(
|
||||||
"^(?<pieceType>[NBRQK])(?:(?<fromFile>[a-h])|(?<fromRank>[1-8])|(?<fromSquare>[a-h][1-8]))?x?(?<toSquare>[a-h][1-8])$"));
|
"^(?<pieceType>[NBRQK])(?:(?<fromFile>[a-h])|(?<fromRank>[1-8])|(?<fromSquare>[a-h][1-8]))?x?(?<toSquare>[a-h][1-8])(?:\\+{0,2}|\\#)$"));
|
||||||
patterns.put("pawnCapture",
|
patterns.put("pawnCapture",
|
||||||
Pattern
|
Pattern
|
||||||
.compile("^(?<fromFile>[a-h])(?<fromRank>[1-8])?x(?<toSquare>[a-h][1-8])(?<promotedTo>[NBRQK])?$"));
|
.compile(
|
||||||
patterns.put("pawnPush", Pattern.compile("^(?<toSquare>[a-h][1-8])(?<promotedTo>[NBRQK])?$"));
|
"^(?<fromFile>[a-h])(?<fromRank>[1-8])?x(?<toSquare>[a-h][1-8])(?<promotedTo>[NBRQK])?(?:\\+{0,2}|\\#)?$"));
|
||||||
|
patterns.put("pawnPush", Pattern.compile("^(?<toSquare>[a-h][1-8])(?<promotedTo>[NBRQK])?(?:\\+{0,2}|\\#)$"));
|
||||||
|
patterns.put("castling", Pattern.compile("^(?<queenside>O-O-O)|(?<kingside>O-O)(?:\\+{0,2}|\\#)?$"));
|
||||||
|
|
||||||
patterns.forEach((patternName, pattern) -> {
|
patterns.forEach((patternName, pattern) -> {
|
||||||
Matcher m = pattern.matcher(sanMove);
|
Matcher m = pattern.matcher(sanMove);
|
||||||
if (m.find()) {
|
if (m.find()) {
|
||||||
Position pos = null, dest = Position.fromLAN(m.group("toSquare"));
|
Position pos = null, dest = null;
|
||||||
|
Move.Type moveType = Move.Type.NORMAL;
|
||||||
switch (patternName) {
|
switch (patternName) {
|
||||||
case "pieceMove":
|
case "pieceMove":
|
||||||
|
dest = Position.fromLAN(m.group("toSquare"));
|
||||||
if (m.group("fromSquare") != null) pos = Position.fromLAN(m.group("fromSquare"));
|
if (m.group("fromSquare") != null) pos = Position.fromLAN(m.group("fromSquare"));
|
||||||
else {
|
else {
|
||||||
Type type = Type.fromFirstChar(m.group("pieceType").charAt(0));
|
Type type = Type.fromFirstChar(m.group("pieceType").charAt(0));
|
||||||
@ -222,12 +224,14 @@ public class Board {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "pawnCapture":
|
case "pawnCapture":
|
||||||
|
dest = Position.fromLAN(m.group("toSquare"));
|
||||||
char file = m.group("fromFile").charAt(0);
|
char file = m.group("fromFile").charAt(0);
|
||||||
int rank = m.group("fromRank") == null ? get(Type.PAWN, file)
|
int rank = m.group("fromRank") == null ? get(Type.PAWN, file)
|
||||||
: Integer.parseInt(m.group("fromRank"));
|
: Integer.parseInt(m.group("fromRank"));
|
||||||
pos = Position.fromLAN(String.format("%c%d", file, rank));
|
pos = Position.fromLAN(String.format("%c%d", file, rank));
|
||||||
break;
|
break;
|
||||||
case "pawnPush":
|
case "pawnPush":
|
||||||
|
dest = Position.fromLAN(m.group("toSquare"));
|
||||||
// TODO: Pawn promotion
|
// TODO: Pawn promotion
|
||||||
int step = log.getActiveColor() == Color.WHITE ? 1 : -1;
|
int step = log.getActiveColor() == Color.WHITE ? 1 : -1;
|
||||||
|
|
||||||
@ -236,8 +240,13 @@ public class Board {
|
|||||||
// Double step forward
|
// Double step forward
|
||||||
else pos = new Position(dest.x, dest.y + 2 * step);
|
else pos = new Position(dest.x, dest.y + 2 * step);
|
||||||
break;
|
break;
|
||||||
|
case "castling":
|
||||||
|
pos = new Position(4, log.getActiveColor() == Color.WHITE ? 7 : 0);
|
||||||
|
dest = new Position(m.group("kingside") != null ? 6 : 2, pos.y);
|
||||||
|
moveType = Move.Type.CASTLING;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
move(new Move(pos, dest));
|
move(new Move(pos, dest, moveType));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -36,8 +36,8 @@ public class Game {
|
|||||||
init(boardPane, whiteName, blackName);
|
init(boardPane, whiteName, blackName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Game(BoardPane boardPane, String whiteName, String blackName, String fen) {
|
public Game(BoardPane boardPane, String whiteName, String blackName, Board board) {
|
||||||
board = new Board(fen);
|
this.board = board;
|
||||||
init(boardPane, whiteName, blackName);
|
init(boardPane, whiteName, blackName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,12 +18,14 @@ public class PGNDatabase {
|
|||||||
|
|
||||||
private final List<PGNGame> games = new ArrayList<>();
|
private final List<PGNGame> games = new ArrayList<>();
|
||||||
|
|
||||||
public void load(File pgnFile) {
|
public void load(File pgnFile) throws FileNotFoundException, ChessException {
|
||||||
try (Scanner sc = new Scanner(pgnFile)) {
|
try (Scanner sc = new Scanner(pgnFile)) {
|
||||||
while (sc.hasNext())
|
while (sc.hasNext())
|
||||||
games.add(PGNGame.parse(sc));
|
games.add(PGNGame.parse(sc));
|
||||||
} catch (FileNotFoundException | ChessException e) {
|
} catch (FileNotFoundException | ChessException e) {
|
||||||
e.printStackTrace();
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<PGNGame> getGames() { return games; }
|
||||||
}
|
}
|
||||||
|
@ -25,17 +25,15 @@ public class PGNGame {
|
|||||||
|
|
||||||
MatchResult matchResult;
|
MatchResult matchResult;
|
||||||
Pattern tagPairPattern = Pattern.compile("\\[(\\w+) \"(.*)\"]"),
|
Pattern tagPairPattern = Pattern.compile("\\[(\\w+) \"(.*)\"]"),
|
||||||
movePattern = Pattern.compile("\\d+\\. (\\S+)\\s(\\S+)"),
|
movePattern = Pattern.compile("\\d+\\.\\s+(?:(?:(\\S+)\\s+(\\S+))|(?:O-O-O)|(?:O-O))(?:\\+{0,2}|\\#)"),
|
||||||
nagPattern = Pattern.compile("(\\$\\d{1,3})*"),
|
nagPattern = Pattern.compile("(\\$\\d{1,3})*"),
|
||||||
terminationMarkerPattern = Pattern.compile("1-0|0-1|1\\/2-1\\/2|\\*");
|
terminationMarkerPattern = Pattern.compile("1-0|0-1|1\\/2-1\\/2|\\*");
|
||||||
|
|
||||||
// Parse tag pairs
|
// Parse tag pairs
|
||||||
while (true) {
|
while (sc.findInLine(tagPairPattern) != null) {
|
||||||
if (sc.findInLine(tagPairPattern) != null) {
|
|
||||||
matchResult = sc.match();
|
matchResult = sc.match();
|
||||||
if (matchResult.groupCount() == 2) game.setTag(matchResult.group(0), matchResult.group(1));
|
if (matchResult.groupCount() == 2) game.setTag(matchResult.group(1), matchResult.group(2));
|
||||||
else break;
|
else break;
|
||||||
} else break;
|
|
||||||
sc.nextLine();
|
sc.nextLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,19 +44,19 @@ public class PGNGame {
|
|||||||
|
|
||||||
// TODO: Parse RAV (Recursive Annotation Variation)
|
// TODO: Parse RAV (Recursive Annotation Variation)
|
||||||
|
|
||||||
sc.findWithinHorizon(movePattern, 20);
|
if (sc.findWithinHorizon(movePattern, 20) != null) {
|
||||||
matchResult = sc.match();
|
matchResult = sc.match();
|
||||||
if (matchResult.groupCount() > 0) for (int i = 1; i < matchResult.groupCount() + 1; i++) {
|
if (matchResult.groupCount() > 0) for (int i = 1; i < matchResult.groupCount() + 1; i++) {
|
||||||
game.board.move(matchResult.group(i));
|
game.board.move(matchResult.group(i));
|
||||||
System.out.println(game.board.toFEN());
|
System.out.println(game.getBoard().getLog().getLast().move.toLAN() + ": " + game.board.toFEN());
|
||||||
}
|
}
|
||||||
else break;
|
else break;
|
||||||
|
} else break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse game termination marker
|
// Parse game termination marker
|
||||||
if (sc.hasNext(terminationMarkerPattern)) {
|
if (sc.findWithinHorizon(terminationMarkerPattern, 20) == null)
|
||||||
sc.next(terminationMarkerPattern);
|
System.err.println("Termination marker expected");
|
||||||
} else throw new ChessException("Game termination marker expected");
|
|
||||||
|
|
||||||
return game;
|
return game;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import java.io.FileReader;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import dev.kske.chess.board.Board;
|
||||||
import dev.kske.chess.game.Game;
|
import dev.kske.chess.game.Game;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,7 +38,7 @@ public class FENDropTarget extends DropTargetAdapter {
|
|||||||
final GamePane gamePane = mainWindow.addGamePane();
|
final GamePane gamePane = mainWindow.addGamePane();
|
||||||
final String fen = br.readLine();
|
final String fen = br.readLine();
|
||||||
DialogUtil.showGameConfigurationDialog((whiteName, blackName) -> {
|
DialogUtil.showGameConfigurationDialog((whiteName, blackName) -> {
|
||||||
final Game game = new Game(gamePane.getBoardPane(), whiteName, blackName, fen);
|
final Game game = new Game(gamePane.getBoardPane(), whiteName, blackName, new Board(fen));
|
||||||
gamePane.setGame(game);
|
gamePane.setGame(game);
|
||||||
game.start();
|
game.start();
|
||||||
});
|
});
|
||||||
|
@ -3,7 +3,6 @@ package dev.kske.chess.ui;
|
|||||||
import java.awt.GridBagConstraints;
|
import java.awt.GridBagConstraints;
|
||||||
import java.awt.GridBagLayout;
|
import java.awt.GridBagLayout;
|
||||||
import java.awt.GridLayout;
|
import java.awt.GridLayout;
|
||||||
import java.awt.Insets;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -70,7 +69,6 @@ public class GamePane extends JComponent {
|
|||||||
toolPanel.add(btnSwapColors);
|
toolPanel.add(btnSwapColors);
|
||||||
|
|
||||||
GridBagConstraints gbc_toolPanel = new GridBagConstraints();
|
GridBagConstraints gbc_toolPanel = new GridBagConstraints();
|
||||||
gbc_toolPanel.insets = new Insets(0, 0, 5, 5);
|
|
||||||
gbc_toolPanel.anchor = GridBagConstraints.NORTH;
|
gbc_toolPanel.anchor = GridBagConstraints.NORTH;
|
||||||
gbc_toolPanel.fill = GridBagConstraints.HORIZONTAL;
|
gbc_toolPanel.fill = GridBagConstraints.HORIZONTAL;
|
||||||
gbc_toolPanel.gridx = 0;
|
gbc_toolPanel.gridx = 0;
|
||||||
@ -80,7 +78,6 @@ public class GamePane extends JComponent {
|
|||||||
|
|
||||||
moveSelectionPanel = new JPanel();
|
moveSelectionPanel = new JPanel();
|
||||||
GridBagConstraints gbc_moveSelectionPanel = new GridBagConstraints();
|
GridBagConstraints gbc_moveSelectionPanel = new GridBagConstraints();
|
||||||
gbc_moveSelectionPanel.insets = new Insets(0, 0, 5, 0);
|
|
||||||
gbc_moveSelectionPanel.fill = GridBagConstraints.BOTH;
|
gbc_moveSelectionPanel.fill = GridBagConstraints.BOTH;
|
||||||
gbc_moveSelectionPanel.gridx = 2;
|
gbc_moveSelectionPanel.gridx = 2;
|
||||||
gbc_moveSelectionPanel.gridy = 0;
|
gbc_moveSelectionPanel.gridy = 0;
|
||||||
@ -103,7 +100,6 @@ public class GamePane extends JComponent {
|
|||||||
moveSelectionPanel.add(btnLast);
|
moveSelectionPanel.add(btnLast);
|
||||||
boardPane = new BoardPane();
|
boardPane = new BoardPane();
|
||||||
GridBagConstraints gbc_boardPane = new GridBagConstraints();
|
GridBagConstraints gbc_boardPane = new GridBagConstraints();
|
||||||
gbc_boardPane.insets = new Insets(0, 0, 5, 5);
|
|
||||||
gbc_boardPane.fill = GridBagConstraints.BOTH;
|
gbc_boardPane.fill = GridBagConstraints.BOTH;
|
||||||
gbc_boardPane.gridx = 0;
|
gbc_boardPane.gridx = 0;
|
||||||
gbc_boardPane.gridy = 1;
|
gbc_boardPane.gridy = 1;
|
||||||
@ -111,7 +107,6 @@ public class GamePane extends JComponent {
|
|||||||
|
|
||||||
JPanel numberPanel = new JPanel(new GridLayout(8, 1));
|
JPanel numberPanel = new JPanel(new GridLayout(8, 1));
|
||||||
GridBagConstraints gbc_numberPanel = new GridBagConstraints();
|
GridBagConstraints gbc_numberPanel = new GridBagConstraints();
|
||||||
gbc_numberPanel.insets = new Insets(0, 0, 5, 5);
|
|
||||||
gbc_numberPanel.anchor = GridBagConstraints.WEST;
|
gbc_numberPanel.anchor = GridBagConstraints.WEST;
|
||||||
gbc_numberPanel.fill = GridBagConstraints.VERTICAL;
|
gbc_numberPanel.fill = GridBagConstraints.VERTICAL;
|
||||||
gbc_numberPanel.gridx = 1;
|
gbc_numberPanel.gridx = 1;
|
||||||
@ -120,7 +115,6 @@ public class GamePane extends JComponent {
|
|||||||
|
|
||||||
JPanel letterPanel = new JPanel(new GridLayout(1, 8));
|
JPanel letterPanel = new JPanel(new GridLayout(1, 8));
|
||||||
GridBagConstraints gbc_letterPanel = new GridBagConstraints();
|
GridBagConstraints gbc_letterPanel = new GridBagConstraints();
|
||||||
gbc_letterPanel.insets = new Insets(0, 0, 0, 5);
|
|
||||||
gbc_letterPanel.anchor = GridBagConstraints.NORTH;
|
gbc_letterPanel.anchor = GridBagConstraints.NORTH;
|
||||||
gbc_letterPanel.fill = GridBagConstraints.HORIZONTAL;
|
gbc_letterPanel.fill = GridBagConstraints.HORIZONTAL;
|
||||||
gbc_letterPanel.gridx = 0;
|
gbc_letterPanel.gridx = 0;
|
||||||
@ -137,7 +131,6 @@ public class GamePane extends JComponent {
|
|||||||
|
|
||||||
JScrollPane scrollPane = new JScrollPane();
|
JScrollPane scrollPane = new JScrollPane();
|
||||||
GridBagConstraints gbc_scrollPane = new GridBagConstraints();
|
GridBagConstraints gbc_scrollPane = new GridBagConstraints();
|
||||||
gbc_scrollPane.insets = new Insets(0, 0, 5, 0);
|
|
||||||
gbc_scrollPane.fill = GridBagConstraints.BOTH;
|
gbc_scrollPane.fill = GridBagConstraints.BOTH;
|
||||||
gbc_scrollPane.gridx = 2;
|
gbc_scrollPane.gridx = 2;
|
||||||
gbc_scrollPane.gridy = 1;
|
gbc_scrollPane.gridy = 1;
|
||||||
|
@ -2,16 +2,19 @@ package dev.kske.chess.ui;
|
|||||||
|
|
||||||
import java.awt.Toolkit;
|
import java.awt.Toolkit;
|
||||||
import java.awt.datatransfer.StringSelection;
|
import java.awt.datatransfer.StringSelection;
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
|
||||||
|
import javax.swing.JComboBox;
|
||||||
import javax.swing.JMenu;
|
import javax.swing.JMenu;
|
||||||
import javax.swing.JMenuBar;
|
import javax.swing.JMenuBar;
|
||||||
import javax.swing.JMenuItem;
|
import javax.swing.JMenuItem;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
|
|
||||||
|
import dev.kske.chess.board.Board;
|
||||||
import dev.kske.chess.game.Game;
|
import dev.kske.chess.game.Game;
|
||||||
|
import dev.kske.chess.pgn.PGNDatabase;
|
||||||
|
import dev.kske.chess.pgn.PGNGame;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project: <strong>Chess</strong><br>
|
* Project: <strong>Chess</strong><br>
|
||||||
@ -47,20 +50,20 @@ public class MenuBar extends JMenuBar {
|
|||||||
|
|
||||||
JMenuItem loadFileMenu = new JMenuItem("Load game file");
|
JMenuItem loadFileMenu = new JMenuItem("Load game file");
|
||||||
loadFileMenu.addActionListener((evt) -> DialogUtil.showFileSelectionDialog(mainWindow, (file) -> {
|
loadFileMenu.addActionListener((evt) -> DialogUtil.showFileSelectionDialog(mainWindow, (file) -> {
|
||||||
|
final String name = file.getName().substring(0, file.getName().lastIndexOf('.'));
|
||||||
final String extension = file.getName().substring(file.getName().lastIndexOf('.')).toLowerCase();
|
final String extension = file.getName().substring(file.getName().lastIndexOf('.')).toLowerCase();
|
||||||
switch (extension) {
|
switch (extension) {
|
||||||
case ".fen":
|
case ".fen":
|
||||||
try {
|
try {
|
||||||
final GamePane gamePane = mainWindow
|
final GamePane gamePane = mainWindow.addGamePane(name);
|
||||||
.addGamePane(file.getName().substring(0, file.getName().lastIndexOf('.')));
|
|
||||||
final String fen = new String(Files.readAllBytes(file.toPath()),
|
final String fen = new String(Files.readAllBytes(file.toPath()),
|
||||||
StandardCharsets.UTF_8);
|
StandardCharsets.UTF_8);
|
||||||
DialogUtil.showGameConfigurationDialog((whiteName, blackName) -> {
|
DialogUtil.showGameConfigurationDialog((whiteName, blackName) -> {
|
||||||
final Game game = new Game(gamePane.getBoardPane(), whiteName, blackName, fen);
|
final Game game = new Game(gamePane.getBoardPane(), whiteName, blackName, new Board(fen));
|
||||||
gamePane.setGame(game);
|
gamePane.setGame(game);
|
||||||
game.start();
|
game.start();
|
||||||
});
|
});
|
||||||
} catch (IOException e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
JOptionPane.showMessageDialog(mainWindow,
|
JOptionPane.showMessageDialog(mainWindow,
|
||||||
"Failed to load the file " + file.getName() + ": " + e.toString(),
|
"Failed to load the file " + file.getName() + ": " + e.toString(),
|
||||||
@ -69,7 +72,35 @@ public class MenuBar extends JMenuBar {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ".pgn":
|
case ".pgn":
|
||||||
// TODO: Load board from PGN
|
try {
|
||||||
|
final GamePane gamePane = mainWindow.addGamePane(name);
|
||||||
|
PGNDatabase pgnDB = new PGNDatabase();
|
||||||
|
pgnDB.load(file);
|
||||||
|
if (pgnDB.getGames().size() > 0) {
|
||||||
|
String[] gameNames = new String[pgnDB.getGames().size()];
|
||||||
|
for (int i = 0; i < gameNames.length; i++) {
|
||||||
|
final PGNGame game = pgnDB.getGames().get(i);
|
||||||
|
gameNames[i] = String.format("%s vs %s: %s",
|
||||||
|
game.getTag("White"),
|
||||||
|
game.getTag("Black"),
|
||||||
|
game.getTag("Result"));
|
||||||
|
}
|
||||||
|
JComboBox<String> comboBox = new JComboBox<>(gameNames);
|
||||||
|
JOptionPane
|
||||||
|
.showMessageDialog(mainWindow, comboBox, "Select a game", JOptionPane.QUESTION_MESSAGE);
|
||||||
|
DialogUtil.showGameConfigurationDialog((whiteName, blackName) -> {
|
||||||
|
final Game game = new Game(gamePane.getBoardPane(), whiteName, blackName,
|
||||||
|
pgnDB.getGames().get(comboBox.getSelectedIndex()).getBoard());
|
||||||
|
game.start();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
JOptionPane.showMessageDialog(mainWindow,
|
||||||
|
"Failed to load the file " + file.getName() + ": " + e.toString(),
|
||||||
|
"File loading error",
|
||||||
|
JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
JOptionPane.showMessageDialog(mainWindow,
|
JOptionPane.showMessageDialog(mainWindow,
|
||||||
@ -119,7 +150,7 @@ public class MenuBar extends JMenuBar {
|
|||||||
final GamePane gamePane = mainWindow.addGamePane();
|
final GamePane gamePane = mainWindow.addGamePane();
|
||||||
final String fen = JOptionPane.showInputDialog("Enter a FEN string: ");
|
final String fen = JOptionPane.showInputDialog("Enter a FEN string: ");
|
||||||
DialogUtil.showGameConfigurationDialog((whiteName, blackName) -> {
|
DialogUtil.showGameConfigurationDialog((whiteName, blackName) -> {
|
||||||
final Game game = new Game(gamePane.getBoardPane(), whiteName, blackName, fen);
|
final Game game = new Game(gamePane.getBoardPane(), whiteName, blackName, new Board(fen));
|
||||||
gamePane.setGame(game);
|
gamePane.setGame(game);
|
||||||
game.start();
|
game.start();
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user