chain jump
This commit is contained in:
parent
8affa353da
commit
729384fb62
@ -5,6 +5,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -33,12 +34,11 @@ public class GameBoardTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testSurrender() {
|
void testSurrender() {
|
||||||
final var hiWhite = holdingIdentityResolver.getByUsername(whitePlayerName);
|
final var hiWhite = holdingIdentityResolver.getByUsername(whitePlayerName);
|
||||||
final var hiBlack = holdingIdentityResolver.getByUsername(blackPlayerName);
|
final var hiBlack = holdingIdentityResolver.getByUsername(blackPlayerName);
|
||||||
final String message = "GameBoard SURRENDER test";
|
|
||||||
|
|
||||||
final GameState game = cordaClient.gameProposalCreate(
|
final GameState game = cordaClient.gameProposalCreate(
|
||||||
hiWhite, hiBlack, Stone.Color.BLACK, message);
|
hiWhite, hiBlack, Stone.Color.BLACK, "GameBoard SURRENDER test");
|
||||||
|
|
||||||
System.out.println("Game UUID " +game.uuid());
|
System.out.println("Game UUID " +game.uuid());
|
||||||
|
|
||||||
@ -70,12 +70,11 @@ public class GameBoardTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testMove() {
|
void testMove() {
|
||||||
final var hiWhite = holdingIdentityResolver.getByUsername(whitePlayerName);
|
final var hiWhite = holdingIdentityResolver.getByUsername(whitePlayerName);
|
||||||
final var hiBlack = holdingIdentityResolver.getByUsername(blackPlayerName);
|
final var hiBlack = holdingIdentityResolver.getByUsername(blackPlayerName);
|
||||||
final String message = "GameBoard MOVE test";
|
|
||||||
|
|
||||||
final GameState game = cordaClient.gameProposalCreate(
|
final GameState game = cordaClient.gameProposalCreate(
|
||||||
hiWhite, hiBlack, Stone.Color.BLACK, message);
|
hiWhite, hiBlack, Stone.Color.BLACK, "GameBoard MOVE test");
|
||||||
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());
|
||||||
@ -126,6 +125,44 @@ public class GameBoardTests {
|
|||||||
assertThat(m3.moveNumber() == 3);
|
assertThat(m3.moveNumber() == 3);
|
||||||
assertThat(m3.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT);
|
assertThat(m3.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT);
|
||||||
|
|
||||||
|
final var m4 = cordaClient.gameBoardMove(hiBlack, game.uuid(), move(8, 15),
|
||||||
|
"Choose one of two possible mandatory jumps");
|
||||||
|
assertThat(m4.moveNumber() == 4);
|
||||||
|
assertThat(m4.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT);
|
||||||
|
|
||||||
|
final var m5 = cordaClient.gameBoardMove(hiWhite, game.uuid(), move(26, 22), null);
|
||||||
|
assertThat(m5.moveNumber() == 5);
|
||||||
|
assertThat(m5.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT);
|
||||||
|
|
||||||
|
final var m6 = cordaClient.gameBoardMove(hiBlack, game.uuid(), move(4, 8), null);
|
||||||
|
assertThat(m6.moveNumber() == 6);
|
||||||
|
assertThat(m6.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT);
|
||||||
|
|
||||||
|
final var m7 = cordaClient.gameBoardMove(hiWhite, game.uuid(), move(23, 18),
|
||||||
|
"A move that ends in mandatory capture on a next turn for me");
|
||||||
|
assertThat(m7.moveNumber() == 7);
|
||||||
|
assertThat(m7.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT);
|
||||||
|
|
||||||
|
final var m8 = cordaClient.gameBoardMove(hiBlack, game.uuid(), move(9, 14),
|
||||||
|
"Moard mandatory capture on a next turn for opponent");
|
||||||
|
assertThat(m8.moveNumber() == 8);
|
||||||
|
assertThat(m8.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT);
|
||||||
|
|
||||||
|
final var m9 = cordaClient.gameBoardMove(hiWhite, game.uuid(), move(18, 11),
|
||||||
|
"First part of a mandatory jump");
|
||||||
|
assertThat(m9.moveNumber() == 9);
|
||||||
|
assertThat(m9.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_YOU);
|
||||||
|
|
||||||
|
assertThatThrownBy(() -> {
|
||||||
|
cordaClient.gameBoardMove(hiWhite, game.uuid(), move(22, 17),
|
||||||
|
"An attempt to ignore mandatory capture");
|
||||||
|
});
|
||||||
|
|
||||||
|
final var m10 = cordaClient.gameBoardMove(hiWhite, game.uuid(), move(11, 4),
|
||||||
|
"Second part of a mandatory jump into a king row");
|
||||||
|
assertThat(m10.board().get(4)).isEqualTo(WHITE_KING);
|
||||||
|
assertThat(m10.moveNumber() == 9);
|
||||||
|
assertThat(m10.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayList<Integer> move(int from, int to) {
|
ArrayList<Integer> move(int from, int to) {
|
||||||
|
@ -31,6 +31,10 @@ public class Move {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Stone.Color apply(Map<Integer, Stone> board, Stone.Color expectedMoveColor) {
|
private Stone.Color apply(Map<Integer, Stone> board, Stone.Color expectedMoveColor) {
|
||||||
|
final Set<Move> mandatoryJumps = getMandatoryJumps(board, expectedMoveColor);
|
||||||
|
if (mandatoryJumps.size() != 0 && !mandatoryJumps.contains(this))
|
||||||
|
throw new Exception("A mandatory opponent's stone capture must be performed");
|
||||||
|
|
||||||
Stone movingStone = board.remove(from);
|
Stone movingStone = board.remove(from);
|
||||||
if (movingStone == null)
|
if (movingStone == null)
|
||||||
throw new Exception("An empty starting tile");
|
throw new Exception("An empty starting tile");
|
||||||
@ -42,10 +46,6 @@ public class Move {
|
|||||||
if (!allMoves.contains(this))
|
if (!allMoves.contains(this))
|
||||||
throw new Exception("Prohibited move");
|
throw new Exception("Prohibited move");
|
||||||
|
|
||||||
final Set<Move> mandatoryJumps = getMandatoryJumps(board, expectedMoveColor);
|
|
||||||
if (mandatoryJumps.size() != 0 && !mandatoryJumps.contains(this))
|
|
||||||
throw new Exception("A mandatory opponent's stone capture must be performed");
|
|
||||||
|
|
||||||
movingStone = movingStone.promoteIfPossible(to);
|
movingStone = movingStone.promoteIfPossible(to);
|
||||||
if (board.put(to, movingStone) != null)
|
if (board.put(to, movingStone) != null)
|
||||||
throw new Exception("An occupied finishing tile");
|
throw new Exception("An occupied finishing tile");
|
||||||
@ -54,15 +54,35 @@ public class Move {
|
|||||||
final Stone jumpOver = board.remove(this.jumpOver);
|
final Stone jumpOver = board.remove(this.jumpOver);
|
||||||
if (jumpOver == null || jumpOver.getColor() != expectedMoveColor.opposite())
|
if (jumpOver == null || jumpOver.getColor() != expectedMoveColor.opposite())
|
||||||
throw new Exception("Must jump over an opponent's stone");
|
throw new Exception("Must jump over an opponent's stone");
|
||||||
|
|
||||||
|
final Set<Move> chainJumps = movingStone.getJumps(this.to);
|
||||||
|
chainJumps.removeIf(move -> !move.canJump(board, expectedMoveColor));
|
||||||
|
if (chainJumps.size() != 0)
|
||||||
|
return expectedMoveColor; // player must continue his turn
|
||||||
}
|
}
|
||||||
|
|
||||||
return expectedMoveColor.opposite();
|
return expectedMoveColor.opposite(); // player has finished his turn
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isJump() {
|
boolean isJump() {
|
||||||
return this.jumpOver != null;
|
return this.jumpOver != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean canJump(Map<Integer, Stone> board, Stone.Color color) {
|
||||||
|
final Stone jumpStone = board.get(this.from);
|
||||||
|
if (jumpStone == null || jumpStone.getColor() != color)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
final Stone jumpOverStone = board.get(this.jumpOver);
|
||||||
|
if (jumpOverStone == null || jumpOverStone.getColor() != color.opposite())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (board.get(this.to) != null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static Integer intersection(Set<Integer> a, Set<Integer> b) {
|
static Integer intersection(Set<Integer> a, Set<Integer> b) {
|
||||||
Set<Integer> intersection = new HashSet<Integer>(a);
|
Set<Integer> intersection = new HashSet<Integer>(a);
|
||||||
|
|
||||||
@ -151,26 +171,20 @@ public class Move {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<Move> getMandatoryJumps(Map<Integer, Stone> board, Stone.Color color) {
|
static Set<Move> getMandatoryJumps(Map<Integer, Stone> board, Stone.Color color) {
|
||||||
Set<Move> res = new HashSet<Move>();
|
Set<Move> res = new HashSet<Move>();
|
||||||
|
|
||||||
for (Map.Entry<Integer, Stone> entry : board.entrySet()) {
|
for (Map.Entry<Integer, Stone> entry : board.entrySet()) {
|
||||||
final Integer from = entry.getKey();
|
final Integer from = entry.getKey();
|
||||||
final Stone stone = entry.getValue();
|
final Stone stone = entry.getValue();
|
||||||
|
|
||||||
if (stone.getColor() != color)
|
if (stone.getColor() != color)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
final Stone.Color opponentsColor = color.opposite();
|
final Set<Move> jumps = stone.getJumps(from);
|
||||||
final Set<Move> allJumps = stone.getJumps(from);
|
jumps.removeIf( move -> !move.canJump(board, color));
|
||||||
|
|
||||||
allJumps.removeIf( j -> {
|
res.addAll(jumps);
|
||||||
if (board.get(j.to) != null)
|
|
||||||
return true; // must be an empty jumpTo tile
|
|
||||||
final Stone jumpOverStone = board.get(j.jumpOver);
|
|
||||||
return jumpOverStone == null || jumpOverStone.getColor() != opponentsColor;
|
|
||||||
});
|
|
||||||
|
|
||||||
res.addAll(allJumps);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
Loading…
Reference in New Issue
Block a user