Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

39 hex2p implementieren #61

Merged
merged 13 commits into from
Jan 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions src/main/java/jchess/common/BaseChessGame.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import dx.schema.types.MarkerType;
import dx.schema.types.PieceType;
import jchess.common.components.MarkerComponent;
import jchess.common.components.PieceComponent;
import jchess.common.components.PieceIdentifier;
import jchess.common.components.TileComponent;
import jchess.common.events.BoardClickedEvent;
import jchess.common.events.BoardInitializedEvent;
Expand Down Expand Up @@ -73,6 +75,8 @@ public void revertState() {

protected abstract Entity getEntityAtPosition(int x, int y);

protected abstract int getDirectionFromOwnerId(int ownerId);

protected void onBoardClicked(int x, int y) {
Entity clickedEntity = getEntityAtPosition(x, y);
if (clickedEntity == null) {
Expand All @@ -90,7 +94,11 @@ protected void onBoardClicked(int x, int y) {
if (clickedMarker.onMarkerClicked != null) {
clickedMarker.onMarkerClicked.run();
}
} else if (clickedEntity.piece != null) {
eventManager.getEvent(RenderEvent.class).fire(null);
return;
}

if (clickedEntity.piece != null) {
long startTime = System.currentTimeMillis();

// show the tiles this piece can move to
Expand All @@ -100,7 +108,9 @@ protected void onBoardClicked(int x, int y) {

long endTime = System.currentTimeMillis();
logger.info("Computing valid moves with kingCheck took {} ms", endTime - startTime);
} else if (clickedEntity.tile != null) {
}

if (clickedEntity.tile != null) {
// show which pieces can move to the selected tile
for (Entity attacker : clickedEntity.tile.attackingPieces) {
createMoveFromMarker(attacker);
Expand Down Expand Up @@ -212,6 +222,20 @@ protected MateResult computeMateResult() {
}
}

protected void placePiece(Entity tile, int ownerId, int direction, PieceStore.IPieceDefinitionProvider pieceProvider) {
PieceStore.PieceDefinition pieceDefinition = pieceProvider.getPieceDefinition();
PieceIdentifier pieceIdentifier = new PieceIdentifier(
pieceProvider.getPieceType(),
pieceDefinition.shortName(),
ownerId,
direction
);

PieceComponent pieceComp = new PieceComponent(this, pieceIdentifier, pieceDefinition.baseMoves());
pieceComp.addSpecialMoves(pieceDefinition.specialRules());
tile.piece = pieceComp;
}

@Override
public void start() {
generateBoard();
Expand Down Expand Up @@ -241,6 +265,18 @@ public int getActivePlayerId() {
return activePlayerId;
}

@Override
public void createPiece(Entity targetTile, PieceType pieceType, int ownerId) {
PieceStore.IPieceDefinitionProvider pieceProvider = pieceStore.getPiece(pieceType);
if (pieceProvider == null) {
logger.error("unable to place piece with pieceType '" + pieceType + "'. PieceType does not exist.");
return;
}

int direction = getDirectionFromOwnerId(ownerId);
placePiece(targetTile, ownerId, direction, pieceProvider);
}

@Override
public int getNumPlayers() {
return numPlayers;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import jchess.ecs.Entity;
import jchess.el.CompiledTileExpression;
import jchess.el.v2.ExpressionCompiler;

import java.util.Set;
import java.util.stream.Stream;

Expand Down
10 changes: 10 additions & 0 deletions src/main/java/jchess/gamemode/GameModeStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import dx.schema.types.LayoutId;
import jchess.common.IChessGame;
import jchess.gamemode.hex2p.Hex2pPieceLayouts;
import jchess.gamemode.hex2p.Hex2pPieces;
import jchess.gamemode.hex2p.Hex2PlayerGame;
import jchess.gamemode.hex3p.Hex3PlayerGame;
import jchess.gamemode.hex3p.Hex3pPieceLayouts;
import jchess.gamemode.hex3p.Hex3pPieces;
Expand All @@ -25,6 +28,13 @@ public class GameModeStore {
));
}

for (Hex2pPieceLayouts pieceLayout : Hex2pPieceLayouts.values()) {
gameModeProviders.put(LayoutId.HEX_2_P.name() + "." + pieceLayout.name(), new GameModeProvider(
Hex2PlayerGame::new, LayoutId.HEX_2_P, "2 Player Hexagonal Chess - " + pieceLayout.name(), 2,
new PieceStore(Hex2pPieces.values()), pieceLayout
));
}

for (Square2pPieceLayouts pieceLayout : Square2pPieceLayouts.values()) {
gameModeProviders.put(LayoutId.SQUARE_2_P.name() + "." + pieceLayout.name(), new GameModeProvider(
Square2PlayerGame::new, LayoutId.SQUARE_2_P, "2 Player Classic Chess - " + pieceLayout.name(), 2,
Expand Down
100 changes: 100 additions & 0 deletions src/main/java/jchess/gamemode/hex2p/Hex2PlayerGame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package jchess.gamemode.hex2p;

import dx.schema.types.Vector2I;
import jchess.common.BaseChessGame;
import jchess.common.components.TileComponent;
import jchess.ecs.Entity;
import jchess.gamemode.IPieceLayoutProvider;
import jchess.gamemode.PieceStore;

import java.awt.Point;
import java.util.Arrays;
import java.util.Objects;

public class Hex2PlayerGame extends BaseChessGame {

private static final int numTilesHorizontal = 6 + 5;

private static final int numTilesVertical = 21;

private final Entity[][] tiles = new Entity[numTilesVertical][numTilesHorizontal];

public Hex2PlayerGame(PieceStore pieceStore, IPieceLayoutProvider layoutProvider) {
super(2, pieceStore, layoutProvider);
}

@Override
public dx.schema.types.Entity applyPerspective(dx.schema.types.Entity tile, int playerIndex) {
if (playerIndex < 0 || playerIndex > 1) {
throw new IllegalArgumentException("playerIndex must be 0 or 1, but was " + playerIndex);
}
if (playerIndex == 0) return tile;
if (tile == null || tile.getTile() == null || tile.getTile().getDisplayPos() == null) return tile;

Vector2I displayPos = tile.getTile().getDisplayPos();
displayPos.setX(numTilesHorizontal - displayPos.getX());
displayPos.setY(numTilesVertical - displayPos.getY());
return tile;
}

@Override
protected Entity getEntityAtPosition(int x, int y) {
if (x < 0 || x >= numTilesHorizontal) return null;
if (y < 0 || y >= numTilesVertical) return null;

return tiles[y][x];
}

@Override
protected int getDirectionFromOwnerId(int ownerId) {
return ownerId == 0 ? 0 : 180;
}

@Override
protected void generateBoard() {
for (int y = 0; y < numTilesVertical; y++) {
Entity[] tileRow = tiles[y];
final int x0;
final int x1;

if (y < 5) { // top part
x0 = 5 - y;
x1 = x0 + 2 * (y + 1);
} else if (y < 16) { // middle part
x0 = (y % 2 == 0) ? 1 : 0;
x1 = numTilesHorizontal;
} else { // bottom part
x0 = y - 15;
x1 = x0 + (6 - x0) * 2;
}

for (int x = x0; x < x1; x += 2) {
tileRow[x] = entityManager.createEntity();
tileRow[x].tile = new TileComponent(new Point(x, y), y % 3);
}
}

// second pass: generate neighbors
Arrays.stream(tiles).flatMap(Arrays::stream)
.filter(Objects::nonNull)
.forEach(entity -> {
TileComponent tile = entity.tile;
assert tile != null;
int x = tile.position.x;
int y = tile.position.y;
tile.neighborsByDirection.put(0, getEntityAtPosition(x, y - 2));
tile.neighborsByDirection.put(30, getEntityAtPosition(x + 1, y - 3));
tile.neighborsByDirection.put(60, getEntityAtPosition(x + 1, y - 1));
tile.neighborsByDirection.put(90, getEntityAtPosition(x + 2, y));
tile.neighborsByDirection.put(120, getEntityAtPosition(x + 1, y + 1));
tile.neighborsByDirection.put(150, getEntityAtPosition(x + 1, y + 3));
tile.neighborsByDirection.put(180, getEntityAtPosition(x, y + 2));
tile.neighborsByDirection.put(210, getEntityAtPosition(x - 1, y + 3));
tile.neighborsByDirection.put(240, getEntityAtPosition(x - 1, y + 1));
tile.neighborsByDirection.put(270, getEntityAtPosition(x - 2, y));
tile.neighborsByDirection.put(300, getEntityAtPosition(x - 1, y - 1));
tile.neighborsByDirection.put(330, getEntityAtPosition(x - 1, y - 3));
});
}

}
149 changes: 149 additions & 0 deletions src/main/java/jchess/gamemode/hex2p/Hex2pPieceLayouts.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package jchess.gamemode.hex2p;

import jchess.common.IChessGame;
import jchess.ecs.Entity;
import jchess.gamemode.IPieceLayoutProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.function.BiFunction;

public enum Hex2pPieceLayouts implements IPieceLayoutProvider {
Standard((game, tileProvider) -> populateStandardBoard(new BoardController(game, tileProvider))),
Custom((game, tileProvider) -> populateCustomBoard(new BoardController(game, tileProvider))),
;

private static final int PLAYER_LIGHT = 0;
private static final int PLAYER_DARK = 1;

private static final Logger logger = LoggerFactory.getLogger(Hex2pPieceLayouts.class);

public final IPieceLayoutProvider layoutProvider;

Hex2pPieceLayouts(IPieceLayoutProvider layoutProvider) {
this.layoutProvider = layoutProvider;
}

@Override
public void placePieces(IChessGame game, BiFunction<Integer, Integer, Entity> tileProvider) {
layoutProvider.placePieces(game, tileProvider);
}

private static void populateStandardBoard(BoardController boardController) {
// place kings
boardController.placeKing(6, 19, PLAYER_LIGHT);
boardController.placeKing(6, 1, PLAYER_DARK);

// place queens
boardController.placeQueen(4, 19, PLAYER_LIGHT);
boardController.placeQueen(4, 1, PLAYER_DARK);


// place bishops
for (int i = 0; i <= 4; i+=2) {
boardController.placeBishop(5, i, PLAYER_DARK);
boardController.placeBishop(5, 20 - i, PLAYER_LIGHT);
}

// place knights
for (int x : new int[]{3, 7}) {
boardController.placeKnight(x,18, PLAYER_LIGHT);
boardController.placeKnight(x,2, PLAYER_DARK);
}

// place rooks
for (int x : new int[] {2, 8}) {
boardController.placeRook(x,17, PLAYER_LIGHT);
boardController.placeRook(x,3, PLAYER_DARK);
}


// place pawns
for (int i = 0; i < 5; i++) {
for (int x : new int[] {1+i, 9-i}) {
boardController.placePawn(x, 16 - i, PLAYER_LIGHT);
boardController.placePawn(x, 4 + i, PLAYER_DARK);
}
}
}

private static void populateCustomBoard(BoardController boardController) {
populateStandardBoard(boardController);

boardController.placeArcher(4,15, PLAYER_LIGHT);
boardController.placeArcher(6,15, PLAYER_LIGHT);
boardController.placeArcher(4,5, PLAYER_DARK);
boardController.placeArcher(6,5, PLAYER_DARK);

boardController.placePegasus(5,14, PLAYER_LIGHT);
boardController.placePegasus(5,6, PLAYER_DARK);

boardController.placeSkrull(3,16, PLAYER_LIGHT);
boardController.placeSkrull(7,16, PLAYER_LIGHT);
boardController.placeSkrull(3,4, PLAYER_DARK);
boardController.placeSkrull(7,4, PLAYER_DARK);

boardController.placeCatapult(4,17, PLAYER_LIGHT);
boardController.placeCatapult(6,17, PLAYER_LIGHT);
boardController.placeCatapult(4,3, PLAYER_DARK);
boardController.placeCatapult(6,3, PLAYER_DARK);

}

@SuppressWarnings("SameParameterValue")
private record BoardController(IChessGame game, BiFunction<Integer, Integer, Entity> tileProvider) {

private Entity getEntityAtPosition(int x, int y) {
return tileProvider.apply(x, y);
}

private void placeRook(int x, int y, int playerColor) {
placePiece(x, y, playerColor, Hex2pPieces.Rook);
}

private void placeKnight(int x, int y, int playerColor) {
placePiece(x, y, playerColor, Hex2pPieces.Knight);
}

private void placeBishop(int x, int y, int playerColor) {
placePiece(x, y, playerColor, Hex2pPieces.Bishop);
}

private void placeQueen(int x, int y, int playerColor) {
placePiece(x, y, playerColor, Hex2pPieces.Queen);
}

private void placeKing(int x, int y, int playerColor) {
placePiece(x, y, playerColor, Hex2pPieces.King);
}

private void placePawn(int x, int y, int playerColor) {
placePiece(x, y, playerColor, Hex2pPieces.Pawn);
}

private void placeArcher(int x, int y, int playerColor) {
placePiece(x, y, playerColor, Hex2pPieces.Archer);
}

private void placePegasus(int x, int y, int playerColor) {
placePiece(x, y, playerColor, Hex2pPieces.Pegasus);
}

private void placeSkrull(int x, int y, int playerColor) {
placePiece(x, y, playerColor, Hex2pPieces.Skrull);
}

private void placeCatapult(int x, int y, int playerColor) {
placePiece(x, y, playerColor, Hex2pPieces.Catapult);
}

private void placePiece(int x, int y, int playerColor, Hex2pPieces piece) {
Entity tile = getEntityAtPosition(x, y);
if (tile == null) {
logger.error("cannot place piece on tile ({}, {}). No tile found.", x, y);
return;
}
game.createPiece(tile, piece.getPieceType(), playerColor);
}
}
}
Loading
Loading