Added variations in Log, added LogTest
This commit is contained in:
parent
7258e96b1a
commit
1723c44524
@ -5,7 +5,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import dev.kske.chess.board.Log.LoggedMove;
|
||||
import dev.kske.chess.board.Log.MoveNode;
|
||||
import dev.kske.chess.board.Piece.Color;
|
||||
import dev.kske.chess.board.Piece.Type;
|
||||
|
||||
@ -163,9 +163,9 @@ public class Board implements Cloneable {
|
||||
* Reverts the last move.
|
||||
*/
|
||||
public void revert() {
|
||||
LoggedMove loggedMove = log.getLast();
|
||||
Move move = loggedMove.move;
|
||||
Piece capturedPiece = loggedMove.capturedPiece;
|
||||
MoveNode moveNode = log.getLast();
|
||||
Move move = moveNode.move;
|
||||
Piece capturedPiece = moveNode.capturedPiece;
|
||||
|
||||
switch (move.type) {
|
||||
case PAWN_PROMOTION:
|
||||
@ -509,7 +509,7 @@ public class Board implements Cloneable {
|
||||
if (castlingSb.length() == 0) sb.append("-");
|
||||
sb.append(castlingSb);
|
||||
|
||||
final LoggedMove lastMove = log.getLast();
|
||||
final MoveNode lastMove = log.getLast();
|
||||
|
||||
// En passant availability
|
||||
sb.append(" " + (lastMove == null || lastMove.enPassant == null ? "-" : lastMove.enPassant.toSAN()));
|
||||
|
@ -1,7 +1,7 @@
|
||||
package dev.kske.chess.board;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import dev.kske.chess.board.Piece.Color;
|
||||
|
||||
@ -13,27 +13,30 @@ import dev.kske.chess.board.Piece.Color;
|
||||
*/
|
||||
public class Log implements Cloneable {
|
||||
|
||||
private List<LoggedMove> moves;
|
||||
private MoveNode root, current;
|
||||
|
||||
private Position enPassant;
|
||||
private Color activeColor;
|
||||
private int fullmoveCounter, halfmoveClock;
|
||||
|
||||
public Log() {
|
||||
moves = new ArrayList<>();
|
||||
reset();
|
||||
}
|
||||
|
||||
// TODO: Adjust to variations
|
||||
@Override
|
||||
public Object clone() {
|
||||
Log log = null;
|
||||
try {
|
||||
log = (Log) super.clone();
|
||||
if (!isEmpty()) {
|
||||
log.current = (MoveNode) current.clone();
|
||||
if (current == root) log.root = log.current;
|
||||
else log.root = (MoveNode) root.clone();
|
||||
}
|
||||
} catch (CloneNotSupportedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
log.moves = new ArrayList<>();
|
||||
log.moves.addAll(this.moves);
|
||||
return log;
|
||||
}
|
||||
|
||||
@ -50,13 +53,16 @@ public class Log implements Cloneable {
|
||||
if (pawnMove || capturedPiece != null) halfmoveClock = 0;
|
||||
else++halfmoveClock;
|
||||
activeColor = activeColor.opposite();
|
||||
moves.add(new LoggedMove(move, capturedPiece, enPassant, activeColor, fullmoveCounter, halfmoveClock));
|
||||
}
|
||||
final MoveNode leaf = new MoveNode(move, capturedPiece, enPassant, activeColor, fullmoveCounter, halfmoveClock);
|
||||
|
||||
/**
|
||||
* @return the last logged move, or {@code null} if there is none
|
||||
*/
|
||||
public LoggedMove getLast() { return moves.isEmpty() ? null : moves.get(moves.size() - 1); }
|
||||
if (isEmpty()) {
|
||||
root = leaf;
|
||||
current = leaf;
|
||||
} else {
|
||||
current.addVariation(leaf);
|
||||
current = leaf;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removed the last move from the log and adjusts its state to the previous
|
||||
@ -64,36 +70,45 @@ public class Log implements Cloneable {
|
||||
*/
|
||||
public void removeLast() {
|
||||
if (!isEmpty()) {
|
||||
moves.remove(moves.size() - 1);
|
||||
if (current.parent == null) {
|
||||
current = null;
|
||||
root = null;
|
||||
} else {
|
||||
current = current.parent;
|
||||
if (!isEmpty()) {
|
||||
LoggedMove last = moves.get(moves.size() - 1);
|
||||
activeColor = last.activeColor;
|
||||
enPassant = last.enPassant;
|
||||
fullmoveCounter = last.fullmoveCounter;
|
||||
halfmoveClock = last.halfmoveClock;
|
||||
activeColor = current.activeColor;
|
||||
enPassant = current.enPassant;
|
||||
fullmoveCounter = current.fullmoveCounter;
|
||||
halfmoveClock = current.halfmoveClock;
|
||||
} else reset();
|
||||
}
|
||||
} else reset();
|
||||
}
|
||||
|
||||
public boolean isEmpty() { return moves.isEmpty(); }
|
||||
public boolean isEmpty() { return root == null; }
|
||||
|
||||
/**
|
||||
* Reverts the log to its initial state corresponding to the default board
|
||||
* position.
|
||||
*/
|
||||
public void reset() {
|
||||
moves.clear();
|
||||
root = null;
|
||||
current = null;
|
||||
enPassant = null;
|
||||
activeColor = Color.WHITE;
|
||||
fullmoveCounter = 1;
|
||||
halfmoveClock = 0;
|
||||
}
|
||||
|
||||
public List<LoggedMove> getLoggedMoves() { return moves; }
|
||||
/**
|
||||
* @return The first logged move, or {@code null} if there is none
|
||||
*/
|
||||
public MoveNode getRoot() { return root; }
|
||||
|
||||
public List<LoggedMove> getMoves() { return moves; }
|
||||
|
||||
public void setMoves(List<LoggedMove> moves) { this.moves = moves; }
|
||||
/**
|
||||
* @return the last logged move, or {@code null} if there is none
|
||||
*/
|
||||
public MoveNode getLast() { return current; }
|
||||
|
||||
public Position getEnPassant() { return enPassant; }
|
||||
|
||||
@ -111,7 +126,7 @@ public class Log implements Cloneable {
|
||||
|
||||
public void setHalfmoveClock(int halfmoveClock) { this.halfmoveClock = halfmoveClock; }
|
||||
|
||||
public static class LoggedMove {
|
||||
public static class MoveNode {
|
||||
|
||||
public final Move move;
|
||||
public final Piece capturedPiece;
|
||||
@ -119,7 +134,10 @@ public class Log implements Cloneable {
|
||||
public final Color activeColor;
|
||||
public final int fullmoveCounter, halfmoveClock;
|
||||
|
||||
public LoggedMove(Move move, Piece capturedPiece, Position enPassant, Color activeColor, int fullmoveCounter,
|
||||
private MoveNode parent;
|
||||
private Set<MoveNode> variations = new HashSet<>();
|
||||
|
||||
public MoveNode(Move move, Piece capturedPiece, Position enPassant, Color activeColor, int fullmoveCounter,
|
||||
int halfmoveClock) {
|
||||
this.move = move;
|
||||
this.capturedPiece = capturedPiece;
|
||||
@ -128,5 +146,17 @@ public class Log implements Cloneable {
|
||||
this.fullmoveCounter = fullmoveCounter;
|
||||
this.halfmoveClock = halfmoveClock;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object clone() throws CloneNotSupportedException {
|
||||
return super.clone();
|
||||
}
|
||||
|
||||
public void addVariation(MoveNode variation) {
|
||||
if (!variations.contains(variation)) {
|
||||
variations.add(variation);
|
||||
variation.parent = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package dev.kske.chess.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@ -13,7 +14,7 @@ import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
|
||||
import dev.kske.chess.board.Log;
|
||||
import dev.kske.chess.board.Log.LoggedMove;
|
||||
import dev.kske.chess.board.Log.MoveNode;
|
||||
import dev.kske.chess.event.Event;
|
||||
import dev.kske.chess.event.EventBus;
|
||||
import dev.kske.chess.event.MoveEvent;
|
||||
@ -56,7 +57,7 @@ public class LogPanel extends JPanel implements Subscribable {
|
||||
public void handle(Event<?> event) {
|
||||
if (log == null) return;
|
||||
|
||||
final List<LoggedMove> moves = log.getLoggedMoves();
|
||||
final List<MoveNode> moves = /* log.getLoggedMoves() */ new ArrayList<>();
|
||||
String[][] data = new String[moves.size() / 2 + moves.size() % 2][2];
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
data[i][0] = moves.get(i * 2).move.toSAN();
|
||||
|
159
test/dev/kske/chess/board/LogTest.java
Normal file
159
test/dev/kske/chess/board/LogTest.java
Normal file
@ -0,0 +1,159 @@
|
||||
package dev.kske.chess.board;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import dev.kske.chess.board.Piece.Color;
|
||||
|
||||
/**
|
||||
* Project: <strong>Chess</strong><br>
|
||||
* File: <strong>LogTest.java</strong><br>
|
||||
* Created: <strong>13 Sep 2019</strong><br>
|
||||
* Author: <strong>Kai S. K. Engelbart</strong>
|
||||
*/
|
||||
class LogTest {
|
||||
|
||||
Log log = new Log();
|
||||
|
||||
/**
|
||||
* Test method for {@link dev.kske.chess.board.Log#Log()}.
|
||||
*/
|
||||
@Test
|
||||
void testLog() {
|
||||
assertTrue(log.isEmpty());
|
||||
assertNull(log.getLast());
|
||||
assertNull(log.getRoot());
|
||||
assertEquals(log.getActiveColor(), Color.WHITE);
|
||||
assertNull(log.getEnPassant());
|
||||
assertEquals(log.getFullmoveCounter(), 1);
|
||||
assertEquals(log.getHalfmoveClock(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link dev.kske.chess.board.Log#clone()}.
|
||||
*/
|
||||
@Test
|
||||
void testClone() {
|
||||
Log other = (Log) log.clone();
|
||||
log.setActiveColor(Color.WHITE);
|
||||
other.setActiveColor(Color.BLACK);
|
||||
assertNotEquals(other.getActiveColor(), log.getActiveColor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link dev.kske.chess.board.Log#add(dev.kske.chess.board.Move, dev.kske.chess.board.Piece, boolean)}.
|
||||
*/
|
||||
@Test
|
||||
void testAdd() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link dev.kske.chess.board.Log#removeLast()}.
|
||||
*/
|
||||
@Test
|
||||
void testRemoveLast() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link dev.kske.chess.board.Log#isEmpty()}.
|
||||
*/
|
||||
@Test
|
||||
void testIsEmpty() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link dev.kske.chess.board.Log#reset()}.
|
||||
*/
|
||||
@Test
|
||||
void testReset() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link dev.kske.chess.board.Log#getRoot()}.
|
||||
*/
|
||||
@Test
|
||||
void testGetRoot() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link dev.kske.chess.board.Log#getLast()}.
|
||||
*/
|
||||
@Test
|
||||
void testGetLast() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link dev.kske.chess.board.Log#getEnPassant()}.
|
||||
*/
|
||||
@Test
|
||||
void testGetEnPassant() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link dev.kske.chess.board.Log#setEnPassant(dev.kske.chess.board.Position)}.
|
||||
*/
|
||||
@Test
|
||||
void testSetEnPassant() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link dev.kske.chess.board.Log#getActiveColor()}.
|
||||
*/
|
||||
@Test
|
||||
void testGetActiveColor() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link dev.kske.chess.board.Log#setActiveColor(dev.kske.chess.board.Piece.Color)}.
|
||||
*/
|
||||
@Test
|
||||
void testSetActiveColor() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link dev.kske.chess.board.Log#getFullmoveCounter()}.
|
||||
*/
|
||||
@Test
|
||||
void testGetFullmoveCounter() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link dev.kske.chess.board.Log#setFullmoveCounter(int)}.
|
||||
*/
|
||||
@Test
|
||||
void testSetFullmoveCounter() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link dev.kske.chess.board.Log#getHalfmoveClock()}.
|
||||
*/
|
||||
@Test
|
||||
void testGetHalfmoveClock() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link dev.kske.chess.board.Log#setHalfmoveClock(int)}.
|
||||
*/
|
||||
@Test
|
||||
void testSetHalfmoveClock() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user