Compare commits

..

No commits in common. "7d26dca7522a449f7add1c608d14a29ccc29c821" and "1f2ff242e4f11a7aecc6e763263f6748323cc2b8" have entirely different histories.

18 changed files with 192 additions and 617 deletions

View File

@ -18,7 +18,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import djmil.cordacheckers.cordaclient.dao.GameState; import djmil.cordacheckers.cordaclient.dao.GameState;
import djmil.cordacheckers.cordaclient.dao.HoldingIdentity; import djmil.cordacheckers.cordaclient.dao.HoldingIdentity;
import djmil.cordacheckers.cordaclient.dao.Stone; import djmil.cordacheckers.cordaclient.dao.Piece;
import djmil.cordacheckers.cordaclient.dao.Rank; import djmil.cordacheckers.cordaclient.dao.Rank;
import djmil.cordacheckers.cordaclient.dao.VirtualNode; import djmil.cordacheckers.cordaclient.dao.VirtualNode;
import djmil.cordacheckers.cordaclient.dao.VirtualNodeList; import djmil.cordacheckers.cordaclient.dao.VirtualNodeList;
@ -95,7 +95,7 @@ public class CordaClient {
.getResponce(requestBody); .getResponce(requestBody);
} }
public GameState gameProposalCreate(HoldingIdentity issuer, HoldingIdentity acquier, Stone.Color acquierColor, public GameState gameProposalCreate(HoldingIdentity issuer, HoldingIdentity acquier, Piece.Color acquierColor,
String message String message
) { ) {
final RequestBody requestBody = new RequestBody( final RequestBody requestBody = new RequestBody(

View File

@ -7,9 +7,9 @@ import java.util.UUID;
public record GameState( public record GameState(
Status status, Status status,
String opponentName, String opponentName,
Stone.Color opponentColor, Piece.Color opponentColor,
Map<Integer, Stone> board, Map<Integer, Piece> board,
Integer moveNumber, Integer moveNumber,
List<Integer> previousMove, List<Integer> previousMove,

View File

@ -1,6 +1,6 @@
package djmil.cordacheckers.cordaclient.dao; package djmil.cordacheckers.cordaclient.dao;
public class Stone { public class Piece {
public enum Type { public enum Type {
MAN, MAN,
@ -19,12 +19,12 @@ public class Stone {
Color color; Color color;
Type type; Type type;
public Stone() { public Piece() {
this.color = null; this.color = null;
this.type = null; this.type = null;
} }
public Stone(Color color, Type type) { public Piece(Color color, Type type) {
this.color = color; this.color = color;
this.type = type; this.type = type;
} }
@ -50,7 +50,7 @@ public class Stone {
return false; return false;
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
Stone other = (Stone) obj; Piece other = (Piece) obj;
if (color != other.color) if (color != other.color)
return false; return false;
if (type != other.type) if (type != other.type)

View File

@ -1,10 +1,10 @@
package djmil.cordacheckers.cordaclient.dao.flow.arguments; package djmil.cordacheckers.cordaclient.dao.flow.arguments;
import djmil.cordacheckers.cordaclient.dao.Stone; import djmil.cordacheckers.cordaclient.dao.Piece;
public record ReqGameProposalCreate( public record ReqGameProposalCreate(
String opponentName, String opponentName,
Stone.Color opponentColor, Piece.Color opponentColor,
String message String message
) { ) {

View File

@ -19,7 +19,7 @@ import com.fasterxml.jackson.databind.JsonMappingException;
import djmil.cordacheckers.cordaclient.CordaClient; import djmil.cordacheckers.cordaclient.CordaClient;
import djmil.cordacheckers.cordaclient.dao.GameState; import djmil.cordacheckers.cordaclient.dao.GameState;
import djmil.cordacheckers.cordaclient.dao.HoldingIdentity; import djmil.cordacheckers.cordaclient.dao.HoldingIdentity;
import djmil.cordacheckers.cordaclient.dao.Stone; import djmil.cordacheckers.cordaclient.dao.Piece;
import djmil.cordacheckers.cordaclient.dao.flow.arguments.ReqGameProposalCreate; import djmil.cordacheckers.cordaclient.dao.flow.arguments.ReqGameProposalCreate;
import djmil.cordacheckers.user.HoldingIdentityResolver; import djmil.cordacheckers.user.HoldingIdentityResolver;
import djmil.cordacheckers.user.User; import djmil.cordacheckers.user.User;
@ -59,7 +59,7 @@ public class GameProposalController {
final HoldingIdentity gpSender = sender.getHoldingIdentity(); final HoldingIdentity gpSender = sender.getHoldingIdentity();
// TODO: throw execption with custom type // TODO: throw execption with custom type
final HoldingIdentity gpReceiver = holdingIdentityResolver.getByUsername(gpRequest.opponentName()); final HoldingIdentity gpReceiver = holdingIdentityResolver.getByUsername(gpRequest.opponentName());
final Stone.Color gpReceiverColor = gpRequest.opponentColor(); final Piece.Color gpReceiverColor = gpRequest.opponentColor();
// TODO handle expectionns here // TODO handle expectionns here
GameState gameStateView = cordaClient.gameProposalCreate( GameState gameStateView = cordaClient.gameProposalCreate(

View File

@ -1,215 +0,0 @@
package djmil.cordacheckers;
import static java.lang.Math.abs;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;
import org.junit.platform.commons.annotation.Testable;
@Testable
public class CheckersMoveTest {
public final static Map<Integer, List<Integer>> adjacentCell = Map.ofEntries(
Map.entry(1, Arrays.asList(5, 6, 10)),
Map.entry(2, Arrays.asList(6, 7, 9, 11)),
Map.entry(3, Arrays.asList(7, 8, 10, 12)),
Map.entry(4, Arrays.asList(8, 11)),
Map.entry(5, Arrays.asList(1, 9, 14, 9, 11)),
Map.entry(6, Arrays.asList(1, 2, 9, 10, 13, 15)),
Map.entry(7, Arrays.asList(2, 3, 10, 11, 14, 16)),
Map.entry(8, Arrays.asList(3, 4, 11, 12, 15)),
Map.entry(9, Arrays.asList(2, 5, 6, 13, 14, 18)),
Map.entry(10, Arrays.asList(1, 3, 6, 7, 14, 15, 17, 19)),
Map.entry(11, Arrays.asList(2, 4, 7, 8, 15, 16, 18, 20)),
Map.entry(12, Arrays.asList(3, 8, 16, 19)),
Map.entry(13, Arrays.asList(6, 9, 17, 22)),
Map.entry(14, Arrays.asList(5, 7, 9, 10, 17, 18, 21, 23)),
Map.entry(15, Arrays.asList(6, 8, 10, 11, 18, 19, 22, 24)),
Map.entry(16, Arrays.asList(7, 11, 12, 19, 20, 23)),
Map.entry(17, Arrays.asList(10, 13, 14, 21, 22, 26)),
Map.entry(18, Arrays.asList(9, 11, 14, 15, 22, 23, 25, 27)),
Map.entry(19, Arrays.asList(10, 12, 15, 16, 23, 24)),
Map.entry(20, Arrays.asList(11, 16, 24, 27)),
Map.entry(21, Arrays.asList(14, 17, 25, 30)),
Map.entry(22, Arrays.asList(13, 15, 17, 18, 25, 26, 29, 31)),
Map.entry(23, Arrays.asList(14, 16, 18, 19, 26, 27, 30, 32)),
Map.entry(24, Arrays.asList(15, 19, 20, 27, 28, 31)),
Map.entry(25, Arrays.asList(18, 21, 22, 29, 30)),
Map.entry(26, Arrays.asList(17, 19, 22, 23, 30, 31)),
Map.entry(27, Arrays.asList(18, 20, 23, 24, 31, 32)),
Map.entry(28, Arrays.asList(19, 24, 32)),
Map.entry(29, Arrays.asList(22, 25)),
Map.entry(30, Arrays.asList(21, 23, 25, 26)),
Map.entry(31, Arrays.asList(22, 24, 26, 27)),
Map.entry(32, Arrays.asList(23, 27, 28))
);
public static class Jump {
final public int jump;
final public int step;
Jump(int jump, int step) {
this.jump = jump;
this.step = step;
}
static Set<Jump> intersect(Set<Integer> jumps, Set<Integer> steps) {
Set<Jump> res = new HashSet<Jump>();
for (Integer jump :jumps) {
var jumpSteps = getKingSteps(jump);
jumpSteps.retainAll(steps);
if (jumpSteps.size() == 1)
res.add(new Jump(jump, jumpSteps.iterator().next()));
}
return res;
}
@Override
public String toString() {
return "[jump=" + jump + ", step=" + step + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + jump;
result = prime * result + step;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Jump other = (Jump) obj;
if (jump != other.jump)
return false;
if (step != other.step)
return false;
return true;
}
}
public static Set<Integer> getBlackSteps(Integer idx) {
return adjacentCell.get(idx).stream()
.filter(cur -> cur > idx && cur - idx <= 5)
.collect(Collectors.toSet());
}
public static Set<Integer> getWhiteSteps(Integer idx) {
return adjacentCell.get(idx).stream()
.filter(cur -> cur < idx && idx - cur <= 5)
.collect(Collectors.toSet());
}
public static Set<Integer> getKingSteps(Integer idx) {
return adjacentCell.get(idx).stream()
.filter(cur -> abs(idx - cur) <= 5)
.collect(Collectors.toSet());
}
public static Set<Jump> getBlackJumps(Integer idx) {
final var allSteps = getBlackSteps(idx);
final var allJumps = adjacentCell.get(idx).stream()
.filter(cur -> cur > idx && cur - idx > 5)
.collect(Collectors.toSet());
return Jump.intersect(allJumps, allSteps);
}
public static Set<Jump> getWhiteJumps(Integer idx) {
final var allSteps = getWhiteSteps(idx);
final var allJumps = adjacentCell.get(idx).stream()
.filter(cur -> idx > cur && idx - cur > 5)
.collect(Collectors.toSet());
return Jump.intersect(allJumps, allSteps);
}
public static Set<Jump> getKingJumps(Integer idx) {
final var allSteps = getKingSteps(idx);
final var allJumps = adjacentCell.get(idx).stream()
.filter(cur -> abs(idx - cur) > 5)
.collect(Collectors.toSet());
return Jump.intersect(allJumps, allSteps);
}
@Test
void blackStepTest() {
assertThat(getBlackSteps(1)).containsAll(Arrays.asList(5, 6));
assertThat(getBlackSteps(4)).containsAll(Arrays.asList(8));
assertThat(getBlackSteps(18)).containsAll(Arrays.asList(22, 23));
assertThat(getBlackSteps(21)).containsAll(Arrays.asList(25));
}
@Test
void whiteStepTest() {
assertThat(getWhiteSteps(29)).containsAll(Arrays.asList(25));
assertThat(getWhiteSteps(28)).containsAll(Arrays.asList(24));
assertThat(getWhiteSteps(14)).containsAll(Arrays.asList(9, 10));
assertThat(getWhiteSteps(8)).containsAll(Arrays.asList(3, 4));
}
@Test
void kingStepTest() {
assertThat(getKingSteps(29)).containsAll(Arrays.asList(25));
assertThat(getKingSteps(31)).containsAll(Arrays.asList(26, 27));
assertThat(getKingSteps(20)).containsAll(Arrays.asList(16, 24));
assertThat(getKingSteps(13)).containsAll(Arrays.asList(9, 17));
assertThat(getKingSteps(2)).containsAll(Arrays.asList(6, 7));
assertThat(getKingSteps(15)).containsAll(Arrays.asList(10, 11, 18, 19));
}
@Test
void blackJumpTest() {
assertThat(getBlackJumps(4)).containsAll(
Arrays.asList(new Jump(11, 8)));
assertThat(getBlackJumps(16)).containsAll(
Arrays.asList(new Jump(23, 19)));
assertThat(getBlackJumps(15)).containsAll(
Arrays.asList(new Jump(22, 18), new Jump(24, 19)));
assertThat(getBlackJumps(28)).isEmpty();
}
@Test
void whiteJumpTest() {
assertThat(getWhiteJumps(30)).containsAll(
Arrays.asList(new Jump(21, 25), new Jump(23, 26)));
assertThat(getWhiteJumps(17)).containsAll(
Arrays.asList(new Jump(10, 14)));
assertThat(getWhiteJumps(7)).isEmpty();
assertThat(getWhiteJumps(9)).containsAll(
Arrays.asList(new Jump(2, 6)));
}
@Test
void kingJumpTest() {
assertThat(getKingJumps(11)).containsAll(
Arrays.asList(new Jump(2, 7), new Jump(4, 8), new Jump(18, 15),new Jump(20, 16)));
assertThat(getKingJumps(17)).containsAll(
Arrays.asList(new Jump(10, 14), new Jump(26, 22)));
assertThat(getKingJumps(32)).containsAll(
Arrays.asList(new Jump(23, 27)));
}
}

View File

@ -12,7 +12,7 @@ import org.springframework.boot.test.context.SpringBootTest;
import djmil.cordacheckers.cordaclient.dao.GameState; import djmil.cordacheckers.cordaclient.dao.GameState;
import djmil.cordacheckers.cordaclient.dao.GameState.Status; import djmil.cordacheckers.cordaclient.dao.GameState.Status;
import djmil.cordacheckers.cordaclient.dao.Stone; import djmil.cordacheckers.cordaclient.dao.Piece;
import djmil.cordacheckers.user.HoldingIdentityResolver; import djmil.cordacheckers.user.HoldingIdentityResolver;
@SpringBootTest @SpringBootTest
@ -26,10 +26,10 @@ public class GameBoardTests {
final String whitePlayerName = "alice"; final String whitePlayerName = "alice";
final String blackPlayerName = "bob"; final String blackPlayerName = "bob";
final static Stone WHITE_MAN = new Stone(Stone.Color.WHITE, Stone.Type.MAN); final static Piece WHITE_MAN = new Piece(Piece.Color.WHITE, Piece.Type.MAN);
final static Stone WHITE_KING = new Stone(Stone.Color.WHITE, Stone.Type.KING); final static Piece WHITE_KING = new Piece(Piece.Color.WHITE, Piece.Type.KING);
final static Stone BLACK_MAN = new Stone(Stone.Color.BLACK, Stone.Type.MAN); final static Piece BLACK_MAN = new Piece(Piece.Color.BLACK, Piece.Type.MAN);
final static Stone BLACK_KING = new Stone(Stone.Color.BLACK, Stone.Type.KING); final static Piece BLACK_KING = new Piece(Piece.Color.BLACK, Piece.Type.KING);
@Test @Test
void testSurrender() { void testSurrender() {
@ -38,14 +38,14 @@ public class GameBoardTests {
final String message = "GameBoard SURRENDER test"; final String message = "GameBoard SURRENDER test";
final GameState game = cordaClient.gameProposalCreate( final GameState game = cordaClient.gameProposalCreate(
hiWhite, hiBlack, Stone.Color.BLACK, message); hiWhite, hiBlack, Piece.Color.BLACK, message);
System.out.println("Game UUID " +game.uuid()); System.out.println("Game UUID " +game.uuid());
final GameState acceptedGameBlackView = cordaClient.gameProposalAccept( final GameState acceptedGameBlackView = cordaClient.gameProposalAccept(
hiBlack, game.uuid()); hiBlack, game.uuid());
assertThat(acceptedGameBlackView.opponentColor()).isEqualByComparingTo(Stone.Color.WHITE); assertThat(acceptedGameBlackView.opponentColor()).isEqualByComparingTo(Piece.Color.WHITE);
assertThat(acceptedGameBlackView.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT); assertThat(acceptedGameBlackView.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT);
assertThatThrownBy(() -> { // Black can not surrender, since it is opponent's turn assertThatThrownBy(() -> { // Black can not surrender, since it is opponent's turn
@ -57,14 +57,14 @@ public class GameBoardTests {
hiWhite, game.uuid()); hiWhite, game.uuid());
assertThat(surrendererGameView.opponentName()).isEqualToIgnoringCase(blackPlayerName); assertThat(surrendererGameView.opponentName()).isEqualToIgnoringCase(blackPlayerName);
assertThat(surrendererGameView.opponentColor()).isEqualByComparingTo(Stone.Color.BLACK); assertThat(surrendererGameView.opponentColor()).isEqualByComparingTo(Piece.Color.BLACK);
assertThat(surrendererGameView.status()).isEqualByComparingTo(Status.GAME_RESULT_YOU_LOOSE); assertThat(surrendererGameView.status()).isEqualByComparingTo(Status.GAME_RESULT_YOU_LOOSE);
final GameState winnerGameView = cordaClient.gameStateGet( final GameState winnerGameView = cordaClient.gameStateGet(
hiBlack, game.uuid()); hiBlack, game.uuid());
assertThat(winnerGameView.opponentName()).isEqualToIgnoringCase(whitePlayerName); assertThat(winnerGameView.opponentName()).isEqualToIgnoringCase(whitePlayerName);
assertThat(winnerGameView.opponentColor()).isEqualByComparingTo(Stone.Color.WHITE); assertThat(winnerGameView.opponentColor()).isEqualByComparingTo(Piece.Color.WHITE);
assertThat(winnerGameView.status()).isEqualByComparingTo(Status.GAME_RESULT_YOU_WON); assertThat(winnerGameView.status()).isEqualByComparingTo(Status.GAME_RESULT_YOU_WON);
} }
@ -75,7 +75,7 @@ public class GameBoardTests {
final String message = "GameBoard MOVE test"; final String message = "GameBoard MOVE test";
final GameState game = cordaClient.gameProposalCreate( final GameState game = cordaClient.gameProposalCreate(
hiWhite, hiBlack, Stone.Color.BLACK, message); hiWhite, hiBlack, Piece.Color.BLACK, message);
System.out.println("Game UUID " +game.uuid()); System.out.println("Game UUID " +game.uuid());
final var m0 = cordaClient.gameProposalAccept(hiBlack, game.uuid()); final var m0 = cordaClient.gameProposalAccept(hiBlack, game.uuid());
@ -95,21 +95,7 @@ public class GameBoardTests {
assertThat(m0.board().get(18)).isNull(); assertThat(m0.board().get(18)).isNull();
assertThat(m1.board().get(22)).isNull(); assertThat(m1.board().get(22)).isNull();
assertThat(m1.board().get(18)).isEqualTo(WHITE_MAN); assertThat(m1.board().get(18)).isEqualTo(WHITE_MAN);
assertThat(m1.moveNumber() == 1);
assertThat(m1.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT); assertThat(m1.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT);
assertThatThrownBy(() -> {
cordaClient.gameBoardMove(hiBlack, game.uuid(), move(12, 13),
"Prohibitted move shall be rejected");
});
final var m2 = cordaClient.gameBoardMove(hiBlack, game.uuid(), move(11, 15), null);
assertThat(m1.board().get(11)).isEqualTo(BLACK_MAN);
assertThat(m1.board().get(15)).isNull();
assertThat(m2.board().get(11)).isNull();
assertThat(m2.board().get(15)).isEqualTo(BLACK_MAN);
assertThat(m2.moveNumber() == 2);
assertThat(m2.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT);
} }
ArrayList<Integer> move(int from, int to) { ArrayList<Integer> move(int from, int to) {

View File

@ -10,7 +10,7 @@ import org.springframework.boot.test.context.SpringBootTest;
import djmil.cordacheckers.cordaclient.dao.GameState; import djmil.cordacheckers.cordaclient.dao.GameState;
import djmil.cordacheckers.cordaclient.dao.GameState.Status; import djmil.cordacheckers.cordaclient.dao.GameState.Status;
import djmil.cordacheckers.cordaclient.dao.Stone; import djmil.cordacheckers.cordaclient.dao.Piece;
import djmil.cordacheckers.user.HoldingIdentityResolver; import djmil.cordacheckers.user.HoldingIdentityResolver;
@SpringBootTest @SpringBootTest
@ -23,7 +23,7 @@ public class GameProposalTests {
final String issuer = "alice"; final String issuer = "alice";
final String acquier = "bob"; final String acquier = "bob";
final Stone.Color acquierColor = Stone.Color.WHITE; final Piece.Color acquierColor = Piece.Color.WHITE;
@Test @Test
void testCreate() { void testCreate() {

View File

@ -8,7 +8,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import djmil.cordacheckers.cordaclient.dao.GameState; import djmil.cordacheckers.cordaclient.dao.GameState;
import djmil.cordacheckers.cordaclient.dao.Stone; import djmil.cordacheckers.cordaclient.dao.Piece;
import djmil.cordacheckers.user.HoldingIdentityResolver; import djmil.cordacheckers.user.HoldingIdentityResolver;
@SpringBootTest @SpringBootTest
@ -21,7 +21,7 @@ public class GameStateTests {
final String issuer = "alice"; final String issuer = "alice";
final String acquier = "bob"; final String acquier = "bob";
final Stone.Color acquierColor = Stone.Color.WHITE; final Piece.Color acquierColor = Piece.Color.WHITE;
@Test @Test
void testList() { void testList() {

View File

@ -9,7 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import djmil.cordacheckers.cordaclient.dao.GameState; import djmil.cordacheckers.cordaclient.dao.GameState;
import djmil.cordacheckers.cordaclient.dao.Stone; import djmil.cordacheckers.cordaclient.dao.Piece;
import djmil.cordacheckers.cordaclient.dao.Rank; import djmil.cordacheckers.cordaclient.dao.Rank;
import djmil.cordacheckers.user.HoldingIdentityResolver; import djmil.cordacheckers.user.HoldingIdentityResolver;
@ -32,7 +32,7 @@ public class RankingTests {
final var hiLooser = holdingIdentityResolver.getByUsername("Bob"); final var hiLooser = holdingIdentityResolver.getByUsername("Bob");
final GameState game = cordaClient.gameProposalCreate( final GameState game = cordaClient.gameProposalCreate(
hiWinner, hiLooser, Stone.Color.WHITE, "GameBoard GLOBAL_RANKING test"); hiWinner, hiLooser, Piece.Color.WHITE, "GameBoard GLOBAL_RANKING test");
cordaClient.gameProposalAccept(hiLooser, game.uuid()); cordaClient.gameProposalAccept(hiLooser, game.uuid());
cordaClient.gameBoardSurrender(hiLooser, game.uuid()); cordaClient.gameBoardSurrender(hiLooser, game.uuid());

View File

@ -1,194 +0,0 @@
package djmil.cordacheckers.checkers;
import static java.lang.Math.abs;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class Move {
final public Integer from;
final public Integer to;
final public Integer jumpOver;
public Move(int from, int to) {
this.from = from;
this.to = to;
Set<Integer> fromSteps = getSteps(from);
if (fromSteps.contains(to))
this.jumpOver = null;
else
this.jumpOver = intersection(fromSteps, getSteps(to));
}
public static Stone.Color apply(List<Integer> moves, Map<Integer, Stone> board, Stone.Color moveColor) {
Move move = new Move(moves.get(0), moves.get(1));
return move.apply(board, moveColor);
}
private Stone.Color apply(Map<Integer, Stone> board, Stone.Color expectedMoveColor) {
Stone movingStone = board.remove(from);
if (movingStone == null)
throw new Exception("An empty starting tile");
if (movingStone.getColor() != expectedMoveColor)
throw new Exception("Only " +expectedMoveColor.name() +" color is expected to move");
final Set<Move> allMoves = movingStone.getMoves(from);
if (!allMoves.contains(this))
throw new Exception("Prohibited move");
// TODO: check for mandatory captures
movingStone = movingStone.promoteIfPossible(to);
if (board.put(to, movingStone) != null)
throw new Exception("An occupied finishing tile");
if (isJump()) {
final Stone jumpOver = board.remove(this.jumpOver);
if (jumpOver == null || jumpOver.getColor() != expectedMoveColor.opposite())
throw new Exception("Must jump over an opponent's stone");
}
return expectedMoveColor.opposite();
}
public boolean isJump() {
return this.jumpOver != null;
}
static Integer intersection(Set<Integer> a, Set<Integer> b) {
Set<Integer> intersection = new HashSet<Integer>(a);
intersection.retainAll(b);
if (intersection.size() != 1)
// A legit move is characterized by single intersection point
throw new Exception("Prohibited move");
return intersection.iterator().next();
}
static Set<Integer> getSteps(Integer idx) {
return adjacentCell.get(idx).stream()
.filter(cur -> abs(idx - cur) <= 5)
.collect(Collectors.toSet());
}
static Set<Integer> getJumps(Integer idx) {
return adjacentCell.get(idx).stream()
.filter(cur -> abs(idx - cur) > 5)
.collect(Collectors.toSet());
}
static Set<Integer> getBlackSteps(Integer idx) {
return adjacentCell.get(idx).stream()
.filter(cur -> cur > idx && cur - idx <= 5)
.collect(Collectors.toSet());
}
static Set<Integer> getWhiteSteps(Integer idx) {
return adjacentCell.get(idx).stream()
.filter(cur -> cur < idx && idx - cur <= 5)
.collect(Collectors.toSet());
}
static Set<Integer> getBlackJumps(Integer idx) {
return adjacentCell.get(idx).stream()
.filter(cur -> cur > idx && cur - idx > 5)
.collect(Collectors.toSet());
}
static Set<Integer> getWhiteJumps(Integer idx) {
return adjacentCell.get(idx).stream()
.filter(cur -> cur < idx && idx - cur > 5)
.collect(Collectors.toSet());
}
final static Map<Integer, List<Integer>> adjacentCell = Map.ofEntries(
Map.entry(1, Arrays.asList(5, 6, 10)),
Map.entry(2, Arrays.asList(6, 7, 9, 11)),
Map.entry(3, Arrays.asList(7, 8, 10, 12)),
Map.entry(4, Arrays.asList(8, 11)),
Map.entry(5, Arrays.asList(1, 9, 14, 9, 11)),
Map.entry(6, Arrays.asList(1, 2, 9, 10, 13, 15)),
Map.entry(7, Arrays.asList(2, 3, 10, 11, 14, 16)),
Map.entry(8, Arrays.asList(3, 4, 11, 12, 15)),
Map.entry(9, Arrays.asList(2, 5, 6, 13, 14, 18)),
Map.entry(10, Arrays.asList(1, 3, 6, 7, 14, 15, 17, 19)),
Map.entry(11, Arrays.asList(2, 4, 7, 8, 15, 16, 18, 20)),
Map.entry(12, Arrays.asList(3, 8, 16, 19)),
Map.entry(13, Arrays.asList(6, 9, 17, 22)),
Map.entry(14, Arrays.asList(5, 7, 9, 10, 17, 18, 21, 23)),
Map.entry(15, Arrays.asList(6, 8, 10, 11, 18, 19, 22, 24)),
Map.entry(16, Arrays.asList(7, 11, 12, 19, 20, 23)),
Map.entry(17, Arrays.asList(10, 13, 14, 21, 22, 26)),
Map.entry(18, Arrays.asList(9, 11, 14, 15, 22, 23, 25, 27)),
Map.entry(19, Arrays.asList(10, 12, 15, 16, 23, 24)),
Map.entry(20, Arrays.asList(11, 16, 24, 27)),
Map.entry(21, Arrays.asList(14, 17, 25, 30)),
Map.entry(22, Arrays.asList(13, 15, 17, 18, 25, 26, 29, 31)),
Map.entry(23, Arrays.asList(14, 16, 18, 19, 26, 27, 30, 32)),
Map.entry(24, Arrays.asList(15, 19, 20, 27, 28, 31)),
Map.entry(25, Arrays.asList(18, 21, 22, 29, 30)),
Map.entry(26, Arrays.asList(17, 19, 22, 23, 30, 31)),
Map.entry(27, Arrays.asList(18, 20, 23, 24, 31, 32)),
Map.entry(28, Arrays.asList(19, 24, 32)),
Map.entry(29, Arrays.asList(22, 25)),
Map.entry(30, Arrays.asList(21, 23, 25, 26)),
Map.entry(31, Arrays.asList(22, 24, 26, 27)),
Map.entry(32, Arrays.asList(23, 27, 28))
);
public static class Exception extends RuntimeException {
public Exception(String message) {
super(message);
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((from == null) ? 0 : from.hashCode());
result = prime * result + ((to == null) ? 0 : to.hashCode());
result = prime * result + ((jumpOver == null) ? 0 : jumpOver.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Move other = (Move) obj;
if (from == null) {
if (other.from != null)
return false;
} else if (!from.equals(other.from))
return false;
if (to == null) {
if (other.to != null)
return false;
} else if (!to.equals(other.to))
return false;
if (jumpOver == null) {
if (other.jumpOver != null)
return false;
} else if (!jumpOver.equals(other.jumpOver))
return false;
return true;
}
@Override
public String toString() {
return "[from=" + from + ", to=" + to + ", jumpOver=" + jumpOver + "]";
}
}

View File

@ -1,112 +0,0 @@
package djmil.cordacheckers.checkers;
import java.util.HashSet;
import java.util.Set;
import net.corda.v5.base.annotations.ConstructorForDeserialization;
import net.corda.v5.base.annotations.CordaSerializable;
@CordaSerializable
public class Stone {
@CordaSerializable
public enum Type {
MAN,
KING;
}
@CordaSerializable
public enum Color {
WHITE,
BLACK;
public Color opposite() {
switch (this) {
case WHITE:
return BLACK;
case BLACK:
return WHITE;
}
throw new RuntimeException("Unknown Color");
}
}
private final Color color;
private final Type type;
@ConstructorForDeserialization
public Stone(Color color, Type type) {
this.color = color;
this.type = type;
}
public Color getColor() {
return color;
}
public Type getType() {
return type;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Stone other = (Stone) obj;
if (color != other.color)
return false;
if (type != other.type)
return false;
return true;
}
public Set<Move> getJumps(Integer from) {
Set<Integer> jumps;
if (type == Type.KING)
jumps = Move.getJumps(from);
else if (color == Color.BLACK)
jumps = Move.getBlackJumps(from);
else
jumps = Move.getWhiteJumps(from);
Set<Move> res = new HashSet<>();
for (Integer jump : jumps)
res.add(new Move(from, jump));
return res;
}
public Set<Move> getMoves(Integer from) {
Set<Integer> steps;
if (type == Type.KING)
steps = Move.getSteps(from);
else if (color == Color.BLACK)
steps = Move.getBlackSteps(from);
else
steps = Move.getWhiteSteps(from);
Set<Move> moves = getJumps(from); // <<--- Steps + Jumps
for (Integer step : steps) {
moves.add(new Move(from, step));
}
return moves;
}
public Stone promoteIfPossible(Integer to) {
if ((color == Color.WHITE && to >= 1 && to <= 4) ||
(color == Color.BLACK && to >= 29 && to <= 32))
return new Stone(color, Type.KING);
else
return this;
}
}

View File

@ -3,16 +3,35 @@ package djmil.cordacheckers.contracts;
import static djmil.cordacheckers.contracts.GameCommand.requireThat; import static djmil.cordacheckers.contracts.GameCommand.requireThat;
import static djmil.cordacheckers.contracts.UtxoLedgerTransactionUtil.getSingleCommand; import static djmil.cordacheckers.contracts.UtxoLedgerTransactionUtil.getSingleCommand;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import djmil.cordacheckers.checkers.Stone; import djmil.cordacheckers.states.Piece;
import djmil.cordacheckers.states.Piece.Color;
import net.corda.v5.ledger.utxo.transaction.UtxoLedgerTransaction; import net.corda.v5.ledger.utxo.transaction.UtxoLedgerTransaction;
public class GameBoardContract implements net.corda.v5.ledger.utxo.Contract { public class GameBoardContract implements net.corda.v5.ledger.utxo.Contract {
public static class MoveResult {
final public Map<Integer, Piece> board;
final public Piece.Color moveColor;
public MoveResult(Map<Integer, Piece> board, Color moveColor) {
this.board = board;
this.moveColor = moveColor;
}
public static class Exception extends RuntimeException {
public Exception(String message) {
super(message);
}
}
}
private final static Logger log = LoggerFactory.getLogger(GameBoardContract.class); private final static Logger log = LoggerFactory.getLogger(GameBoardContract.class);
@Override @Override
@ -40,33 +59,60 @@ public class GameBoardContract implements net.corda.v5.ledger.utxo.Contract {
} }
} }
public final static Map<Integer, Stone> initialBoard = Map.ofEntries( public static MoveResult applyMove(List<Integer> move, Map<Integer, Piece> board, Piece.Color moveColor) {
// Inspired by Checkers notation rules: https://www.bobnewell.net/nucleus/checkers.php final int mFrom = move.get(0);
Map.entry( 1, new Stone(Stone.Color.BLACK, Stone.Type.MAN)), final int mTo = move.get(1);
Map.entry( 2, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry( 3, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry( 4, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry( 5, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry( 6, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry( 7, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry( 8, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry( 9, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry(10, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry(11, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry(12, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry(21, new Stone(Stone.Color.WHITE, Stone.Type.MAN)), final Piece piece = board.get(mFrom);
Map.entry(22, new Stone(Stone.Color.WHITE, Stone.Type.MAN)), if (piece == null)
Map.entry(23, new Stone(Stone.Color.WHITE, Stone.Type.MAN)), throw new MoveResult.Exception("An empty starting tile");
Map.entry(24, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
Map.entry(25, new Stone(Stone.Color.WHITE, Stone.Type.MAN)), if (piece.getColor() != moveColor)
Map.entry(26, new Stone(Stone.Color.WHITE, Stone.Type.MAN)), throw new MoveResult.Exception("Can not move opponent's piece");
Map.entry(27, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
Map.entry(28, new Stone(Stone.Color.WHITE, Stone.Type.MAN)), if (board.get(mTo) != null)
Map.entry(29, new Stone(Stone.Color.WHITE, Stone.Type.MAN)), throw new MoveResult.Exception("An occupied finishing tile");
Map.entry(30, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
Map.entry(31, new Stone(Stone.Color.WHITE, Stone.Type.MAN)), final Map<Integer, Piece> newBoard = new LinkedHashMap<Integer, Piece>(board);
Map.entry(32, new Stone(Stone.Color.WHITE, Stone.Type.MAN)) newBoard.remove(mFrom);
newBoard.put(mTo, piece);
return new GameBoardContract.MoveResult(newBoard, moveColor.opposite());
}
final static Piece WHITE_MAN = new Piece(Piece.Color.WHITE, Piece.Type.MAN);
final static Piece WHITE_KING = new Piece(Piece.Color.WHITE, Piece.Type.KING);
final static Piece BLACK_MAN = new Piece(Piece.Color.BLACK, Piece.Type.MAN);
final static Piece BLACK_KING = new Piece(Piece.Color.BLACK, Piece.Type.KING);
public final static Map<Integer, Piece> initialBoard = Map.ofEntries(
// Inspired by Checkers notation rules: https://www.bobnewell.net/nucleus/checkers.php
Map.entry( 1, BLACK_MAN),
Map.entry( 2, BLACK_MAN),
Map.entry( 3, BLACK_MAN),
Map.entry( 4, BLACK_MAN),
Map.entry( 5, BLACK_MAN),
Map.entry( 6, BLACK_MAN),
Map.entry( 7, BLACK_MAN),
Map.entry( 8, BLACK_MAN),
Map.entry( 9, BLACK_MAN),
Map.entry(10, BLACK_MAN),
Map.entry(11, BLACK_MAN),
Map.entry(12, BLACK_MAN),
Map.entry(21, WHITE_MAN),
Map.entry(22, WHITE_MAN),
Map.entry(23, WHITE_MAN),
Map.entry(24, WHITE_MAN),
Map.entry(25, WHITE_MAN),
Map.entry(26, WHITE_MAN),
Map.entry(27, WHITE_MAN),
Map.entry(28, WHITE_MAN),
Map.entry(29, WHITE_MAN),
Map.entry(30, WHITE_MAN),
Map.entry(31, WHITE_MAN),
Map.entry(32, WHITE_MAN)
); );
} }

View File

@ -6,25 +6,25 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import djmil.cordacheckers.checkers.Move;
import djmil.cordacheckers.checkers.Stone;
import djmil.cordacheckers.contracts.GameBoardContract; import djmil.cordacheckers.contracts.GameBoardContract;
import djmil.cordacheckers.contracts.GameBoardContract.MoveResult;
import djmil.cordacheckers.states.Piece.Color;
import net.corda.v5.base.annotations.ConstructorForDeserialization; import net.corda.v5.base.annotations.ConstructorForDeserialization;
import net.corda.v5.base.types.MemberX500Name; import net.corda.v5.base.types.MemberX500Name;
import net.corda.v5.ledger.utxo.BelongsToContract; import net.corda.v5.ledger.utxo.BelongsToContract;
@BelongsToContract(GameBoardContract.class) @BelongsToContract(GameBoardContract.class)
public class GameBoardState extends GameState { public class GameBoardState extends GameState {
private final Stone.Color moveColor; private final Piece.Color moveColor;
private final Integer moveNumber; private final Integer moveNumber;
private final Map<Integer, Stone> board; private final Map<Integer, Piece> board;
public GameBoardState(GameProposalState gameProposalState) { public GameBoardState(GameProposalState gameProposalState) {
super(gameProposalState.whitePlayer, gameProposalState.blackPlayer, super(gameProposalState.whitePlayer, gameProposalState.blackPlayer,
gameProposalState.gameUuid, gameProposalState.message, gameProposalState.participants); gameProposalState.gameUuid, gameProposalState.message, gameProposalState.participants);
this.board = new LinkedHashMap<Integer, Stone>(GameBoardContract.initialBoard); this.board = new LinkedHashMap<Integer, Piece>(GameBoardContract.initialBoard);
this.moveColor = Stone.Color.WHITE; this.moveColor = Piece.Color.WHITE;
this.moveNumber = 0; this.moveNumber = 0;
} }
@ -32,8 +32,9 @@ public class GameBoardState extends GameState {
super(currentGameBoardState.whitePlayer, currentGameBoardState.blackPlayer, currentGameBoardState.gameUuid, super(currentGameBoardState.whitePlayer, currentGameBoardState.blackPlayer, currentGameBoardState.gameUuid,
message, currentGameBoardState.participants); message, currentGameBoardState.participants);
this.board = new LinkedHashMap<Integer, Stone>(currentGameBoardState.getBoard()); final MoveResult moveResult = GameBoardContract.applyMove(move, currentGameBoardState.getBoard(), currentGameBoardState.getMoveColor());
this.moveColor = Move.apply(move, this.board, currentGameBoardState.getMoveColor()); this.moveColor = moveResult.moveColor;
this.board = moveResult.board;
this.moveNumber = (currentGameBoardState.moveColor == this.moveColor) this.moveNumber = (currentGameBoardState.moveColor == this.moveColor)
? currentGameBoardState.getMoveNumber() // current player has not finished his move jet ? currentGameBoardState.getMoveNumber() // current player has not finished his move jet
@ -42,7 +43,7 @@ public class GameBoardState extends GameState {
@ConstructorForDeserialization @ConstructorForDeserialization
public GameBoardState(MemberX500Name whitePlayer, MemberX500Name blackPlayer, public GameBoardState(MemberX500Name whitePlayer, MemberX500Name blackPlayer,
Stone.Color moveColor, Integer moveNumber, Map<Integer, Stone> board, String message, Color moveColor, Integer moveNumber, Map<Integer, Piece> board, String message,
UUID gameUuid, List<PublicKey> participants) { UUID gameUuid, List<PublicKey> participants) {
super(whitePlayer, blackPlayer, gameUuid, message, participants); super(whitePlayer, blackPlayer, gameUuid, message, participants);
@ -51,7 +52,7 @@ public class GameBoardState extends GameState {
this.board = board; this.board = board;
} }
public Stone.Color getMoveColor() { public Piece.Color getMoveColor() {
return moveColor; return moveColor;
} }
@ -60,10 +61,10 @@ public class GameBoardState extends GameState {
} }
public MemberX500Name getActivePlayerName() { public MemberX500Name getActivePlayerName() {
return moveColor == Stone.Color.WHITE ? whitePlayer : blackPlayer; return moveColor == Piece.Color.WHITE ? whitePlayer : blackPlayer;
} }
public Map<Integer, Stone> getBoard() { public Map<Integer, Piece> getBoard() {
return board; return board;
} }

View File

@ -5,7 +5,6 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import djmil.cordacheckers.checkers.Stone;
import net.corda.v5.base.annotations.CordaSerializable; import net.corda.v5.base.annotations.CordaSerializable;
import net.corda.v5.base.types.MemberX500Name; import net.corda.v5.base.types.MemberX500Name;
import net.corda.v5.ledger.utxo.ContractState; import net.corda.v5.ledger.utxo.ContractState;
@ -68,11 +67,11 @@ public abstract class GameState implements ContractState {
throw new NotInvolved(playerName, this.getClass(), gameUuid); throw new NotInvolved(playerName, this.getClass(), gameUuid);
} }
public Stone.Color getOpponentColor(MemberX500Name playerName) throws NotInvolved { public Piece.Color getOpponentColor(MemberX500Name playerName) throws NotInvolved {
if (playerName.compareTo(whitePlayer) == 0) if (playerName.compareTo(whitePlayer) == 0)
return Stone.Color.BLACK; return Piece.Color.BLACK;
if (playerName.compareTo(blackPlayer) == 0) if (playerName.compareTo(blackPlayer) == 0)
return Stone.Color.WHITE; return Piece.Color.WHITE;
throw new NotInvolved(playerName, this.getClass(), gameUuid); throw new NotInvolved(playerName, this.getClass(), gameUuid);
} }

View File

@ -0,0 +1,64 @@
package djmil.cordacheckers.states;
import net.corda.v5.base.annotations.ConstructorForDeserialization;
import net.corda.v5.base.annotations.CordaSerializable;
@CordaSerializable
public class Piece {
@CordaSerializable
public enum Type {
MAN,
KING;
}
@CordaSerializable
public enum Color {
WHITE,
BLACK;
public Color opposite() {
switch (this) {
case WHITE:
return BLACK;
case BLACK:
return WHITE;
}
throw new RuntimeException("Unknown Color");
}
}
private final Color color;
private final Type type;
@ConstructorForDeserialization
public Piece(Color color, Type type) {
this.color = color;
this.type = type;
}
public Color getColor() {
return color;
}
public Type getType() {
return type;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Piece other = (Piece) obj;
if (color != other.color)
return false;
if (type != other.type)
return false;
return true;
}
}

View File

@ -10,13 +10,13 @@ import java.util.UUID;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import djmil.cordacheckers.checkers.Stone;
import djmil.cordacheckers.contracts.GameCommand; import djmil.cordacheckers.contracts.GameCommand;
import djmil.cordacheckers.gamestate.CommitSubFlow; import djmil.cordacheckers.gamestate.CommitSubFlow;
import djmil.cordacheckers.gamestate.FlowResponce; import djmil.cordacheckers.gamestate.FlowResponce;
import djmil.cordacheckers.gamestate.View; import djmil.cordacheckers.gamestate.View;
import djmil.cordacheckers.gamestate.ViewBuilder; import djmil.cordacheckers.gamestate.ViewBuilder;
import djmil.cordacheckers.states.GameProposalState; import djmil.cordacheckers.states.GameProposalState;
import djmil.cordacheckers.states.Piece;
import net.corda.v5.application.flows.ClientRequestBody; import net.corda.v5.application.flows.ClientRequestBody;
import net.corda.v5.application.flows.ClientStartableFlow; import net.corda.v5.application.flows.ClientStartableFlow;
import net.corda.v5.application.flows.CordaInject; import net.corda.v5.application.flows.CordaInject;
@ -88,10 +88,10 @@ public class CreateFlow implements ClientStartableFlow{
private GameProposalState buildGameProposalStateFrom(ClientRequestBody requestBody) { private GameProposalState buildGameProposalStateFrom(ClientRequestBody requestBody) {
final CreateFlowArgs args = requestBody.getRequestBodyAs(jsonMarshallingService, CreateFlowArgs.class); final CreateFlowArgs args = requestBody.getRequestBodyAs(jsonMarshallingService, CreateFlowArgs.class);
final Stone.Color opponentColor = Stone.Color.valueOf(args.opponentColor); final Piece.Color opponentColor = Piece.Color.valueOf(args.opponentColor);
if (opponentColor == null) { if (opponentColor == null) {
throw new RuntimeException("Allowed values for opponentColor are: " throw new RuntimeException("Allowed values for opponentColor are: "
+ Stone.Color.WHITE.name() +", " + Stone.Color.BLACK.name() + Piece.Color.WHITE.name() +", " + Piece.Color.BLACK.name()
+ ". Actual value was: " + args.opponentColor); + ". Actual value was: " + args.opponentColor);
} }
@ -101,8 +101,8 @@ public class CreateFlow implements ClientStartableFlow{
"MemberLookup can't find opponentName specified in flow arguments: " + args.opponentName "MemberLookup can't find opponentName specified in flow arguments: " + args.opponentName
); );
final MemberInfo whitePlayerInfo = opponentColor == Stone.Color.WHITE ? opponentInfo : myInfo; final MemberInfo whitePlayerInfo = opponentColor == Piece.Color.WHITE ? opponentInfo : myInfo;
final MemberInfo blackPlayerInfo = opponentColor == Stone.Color.BLACK ? opponentInfo : myInfo; final MemberInfo blackPlayerInfo = opponentColor == Piece.Color.BLACK ? opponentInfo : myInfo;
return new GameProposalState( return new GameProposalState(
whitePlayerInfo.getName(), whitePlayerInfo.getName(),

View File

@ -4,10 +4,10 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import djmil.cordacheckers.checkers.Stone;
import djmil.cordacheckers.states.GameBoardState; import djmil.cordacheckers.states.GameBoardState;
import djmil.cordacheckers.states.GameProposalState; import djmil.cordacheckers.states.GameProposalState;
import djmil.cordacheckers.states.GameResultState; import djmil.cordacheckers.states.GameResultState;
import djmil.cordacheckers.states.Piece;
import net.corda.v5.base.types.MemberX500Name; import net.corda.v5.base.types.MemberX500Name;
// GameBoard from the player's point of view // GameBoard from the player's point of view
@ -27,9 +27,9 @@ public class View {
public final Status status; public final Status status;
public final String opponentName; public final String opponentName;
public final Stone.Color opponentColor; public final Piece.Color opponentColor;
public final Map<Integer, Stone> board; public final Map<Integer, Piece> board;
public final Integer moveNumber; public final Integer moveNumber;
public final List<Integer> previousMove; public final List<Integer> previousMove;