Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7cba7ac1dd | |||
| c83a360fec | |||
| 2631791330 | |||
| 497820db05 | |||
| 88c9431bf0 | |||
| 5a53a14933 | |||
| f7f66ec5db | |||
| d85b3d21ee | |||
| 382383d38b |
Binary file not shown.
Binary file not shown.
@@ -114,8 +114,11 @@ public class CasinoGameUI extends Application {
|
|||||||
Parent root = fxmlLoader.load();
|
Parent root = fxmlLoader.load();
|
||||||
CasinoGameController controller = fxmlLoader.getController();
|
CasinoGameController controller = fxmlLoader.getController();
|
||||||
|
|
||||||
int gameId = 1; // TODO echte gameId einsetzen
|
if (lobbyId <= 0) {
|
||||||
GameClient gameClient = new GameClient(clientService, gameId);
|
throw new IllegalStateException("CasinoGameUI: lobbyId must be set before start()");
|
||||||
|
}
|
||||||
|
|
||||||
|
GameClient gameClient = new GameClient(clientService, lobbyId);
|
||||||
GameService gameService = new GameService(gameClient);
|
GameService gameService = new GameService(gameClient);
|
||||||
controller.setGameService(gameService);
|
controller.setGameService(gameService);
|
||||||
|
|
||||||
|
|||||||
+26
-1
@@ -1,6 +1,7 @@
|
|||||||
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.get_game_state;
|
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.get_game_state;
|
||||||
|
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.app.checks.UserLoggedInCheck;
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.checks.UserLoggedInCheck;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.state.GamePhase;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby.Lobby;
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby.Lobby;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby.LobbyId;
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby.LobbyId;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby.LobbyManager;
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby.LobbyManager;
|
||||||
@@ -31,8 +32,10 @@ public class GetGameStateHandler extends CommandHandler<GetGameStateRequest> {
|
|||||||
String username = resolveUsername(request);
|
String username = resolveUsername(request);
|
||||||
|
|
||||||
Lobby lobby;
|
Lobby lobby;
|
||||||
|
LobbyId lobbyId;
|
||||||
if (gameId != null) {
|
if (gameId != null) {
|
||||||
lobby = lobbyManager.getLobby(LobbyId.of(gameId));
|
lobbyId = LobbyId.of(gameId);
|
||||||
|
lobby = lobbyManager.getLobby(lobbyId);
|
||||||
if (lobby == null) {
|
if (lobby == null) {
|
||||||
responseDispatcher.dispatch(
|
responseDispatcher.dispatch(
|
||||||
new ErrorResponse(
|
new ErrorResponse(
|
||||||
@@ -59,6 +62,7 @@ public class GetGameStateHandler extends CommandHandler<GetGameStateRequest> {
|
|||||||
request.getContext(), "NOT_IN_LOBBY", "User not in a lobby"));
|
request.getContext(), "NOT_IN_LOBBY", "User not in a lobby"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
lobbyId = lobby.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
var game = lobby.getGameController();
|
var game = lobby.getGameController();
|
||||||
@@ -69,9 +73,30 @@ public class GetGameStateHandler extends CommandHandler<GetGameStateRequest> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (game.getState().getPhase() == GamePhase.FINISHED) {
|
||||||
|
cleanupLobby(lobby, lobbyId);
|
||||||
|
}
|
||||||
|
|
||||||
responseDispatcher.dispatch(new GetGameStateResponse(request.getContext(), game, username));
|
responseDispatcher.dispatch(new GetGameStateResponse(request.getContext(), game, username));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleans up a lobby by removing all players and resetting the game controller. This is called
|
||||||
|
* when the game reaches FINISHED phase.
|
||||||
|
*/
|
||||||
|
private void cleanupLobby(Lobby lobby, LobbyId lobbyId) {
|
||||||
|
try {
|
||||||
|
// Remove all players from the lobby
|
||||||
|
for (String playerName : lobby.getPlayerNames()) {
|
||||||
|
lobbyManager.removePlayer(playerName);
|
||||||
|
}
|
||||||
|
// Reset the game controller so the lobby returns to CREATED state
|
||||||
|
lobby.initGame(null);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
// Log silently to avoid disrupting game state response
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private String resolveUsername(GetGameStateRequest request) {
|
private String resolveUsername(GetGameStateRequest request) {
|
||||||
String username = request.getUsername();
|
String username = request.getUsername();
|
||||||
if (username != null && !username.isBlank()) {
|
if (username != null && !username.isBlank()) {
|
||||||
|
|||||||
+27
-1
@@ -6,6 +6,7 @@ import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.deck.Rank;
|
|||||||
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.deck.Suit;
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.deck.Suit;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.player.Player;
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.player.Player;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.player.PlayerId;
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.player.PlayerId;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.state.GamePhase;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.state.GameState;
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.state.GameState;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.RequestContext;
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.RequestContext;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.SuccessResponse;
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.SuccessResponse;
|
||||||
@@ -33,11 +34,13 @@ public class GetGameStateResponse extends SuccessResponse {
|
|||||||
super(
|
super(
|
||||||
context,
|
context,
|
||||||
buildBody(
|
buildBody(
|
||||||
|
game,
|
||||||
Objects.requireNonNull(game, "game must not be null").getState(),
|
Objects.requireNonNull(game, "game must not be null").getState(),
|
||||||
requestingUsername));
|
requestingUsername));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ResponseBody buildBody(GameState state, String requestingUsername) {
|
private static ResponseBody buildBody(
|
||||||
|
GameController game, GameState state, String requestingUsername) {
|
||||||
Objects.requireNonNull(state, "state must not be null");
|
Objects.requireNonNull(state, "state must not be null");
|
||||||
|
|
||||||
ResponseBodyBuilder builder = ResponseBody.builder();
|
ResponseBodyBuilder builder = ResponseBody.builder();
|
||||||
@@ -47,6 +50,7 @@ public class GetGameStateResponse extends SuccessResponse {
|
|||||||
builder.param("CURRENT_BET", computeGlobalCurrentBet(state));
|
builder.param("CURRENT_BET", computeGlobalCurrentBet(state));
|
||||||
builder.param("DEALER", state.getDealerIndex());
|
builder.param("DEALER", state.getDealerIndex());
|
||||||
builder.param("ACTIVE_PLAYER", state.getCurrentPlayerIndex());
|
builder.param("ACTIVE_PLAYER", state.getCurrentPlayerIndex());
|
||||||
|
builder.param("WINNER", computeWinnerIndex(state, game));
|
||||||
|
|
||||||
appendCommunityCards(builder, state);
|
appendCommunityCards(builder, state);
|
||||||
|
|
||||||
@@ -55,6 +59,28 @@ public class GetGameStateResponse extends SuccessResponse {
|
|||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int computeWinnerIndex(GameState state, GameController game) {
|
||||||
|
GamePhase phase = state.getPhase();
|
||||||
|
if (phase != GamePhase.SHOWDOWN && phase != GamePhase.FINISHED) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerId winnerId = game.determineWinner();
|
||||||
|
if (winnerId == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
for (Player p : state.getPlayers()) {
|
||||||
|
if (p != null && winnerId.equals(p.getId())) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
private static int computeGlobalCurrentBet(GameState state) {
|
private static int computeGlobalCurrentBet(GameState state) {
|
||||||
int globalCurrentBet = 0;
|
int globalCurrentBet = 0;
|
||||||
for (Player p : state.getPlayers()) {
|
for (Player p : state.getPlayers()) {
|
||||||
|
|||||||
@@ -254,4 +254,12 @@ public class GameController {
|
|||||||
|
|
||||||
return bestPlayer;
|
return bestPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ends the current game by setting the phase to FINISHED. This should be called when the
|
||||||
|
* showdown is complete and a winner has been determined.
|
||||||
|
*/
|
||||||
|
public void endGame() {
|
||||||
|
engine.getState().setPhase(GamePhase.FINISHED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-2
@@ -49,6 +49,11 @@ public class RoundManager {
|
|||||||
state.setPhase(GamePhase.PREFLOP);
|
state.setPhase(GamePhase.PREFLOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state.countNonFoldedPlayers() == 1) {
|
||||||
|
state.setPhase(GamePhase.FINISHED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isBettingRoundFinished(state)) {
|
if (isBettingRoundFinished(state)) {
|
||||||
advancePhase(state);
|
advancePhase(state);
|
||||||
}
|
}
|
||||||
@@ -81,8 +86,9 @@ public class RoundManager {
|
|||||||
case FLOP -> dealTurn(state);
|
case FLOP -> dealTurn(state);
|
||||||
case TURN -> dealRiver(state);
|
case TURN -> dealRiver(state);
|
||||||
case RIVER -> showdown(state);
|
case RIVER -> showdown(state);
|
||||||
case SHOWDOWN -> {
|
case SHOWDOWN -> state.setPhase(GamePhase.FINISHED);
|
||||||
/* nothing */
|
case FINISHED -> {
|
||||||
|
/* game is over */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-14
@@ -11,18 +11,14 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The GameState class encapsulates the entire state of a poker game at any
|
* The GameState class encapsulates the entire state of a poker game at any given moment.
|
||||||
* given moment.
|
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>Important invariants this implementation maintains:
|
||||||
* Important invariants this implementation maintains:
|
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@code playerOrder} defines the stable seating/turn order.
|
* <li>{@code playerOrder} defines the stable seating/turn order.
|
||||||
* <li>{@code currentBets} always contains an entry for every player in
|
* <li>{@code currentBets} always contains an entry for every player in {@code playerOrder}.
|
||||||
* {@code playerOrder}.
|
* <li>{@code holeCards} maps every player to a mutable list; if not present, it is created on
|
||||||
* <li>{@code holeCards} maps every player to a mutable list; if not present, it
|
|
||||||
* is created on
|
|
||||||
* demand.
|
* demand.
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@@ -188,8 +184,7 @@ public class GameState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset bets to 0 for ALL players (do not clear the map). Also resets table
|
* Reset bets to 0 for ALL players (do not clear the map). Also resets table current bet to 0.
|
||||||
* current bet to 0.
|
|
||||||
*/
|
*/
|
||||||
public void resetBets() {
|
public void resetBets() {
|
||||||
for (PlayerId id : playerOrder) {
|
for (PlayerId id : playerOrder) {
|
||||||
@@ -232,8 +227,7 @@ public class GameState {
|
|||||||
// Cards
|
// Cards
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gives (overwrites) the two hole cards for the given player. Ensures stable
|
* Gives (overwrites) the two hole cards for the given player. Ensures stable list identity
|
||||||
* list identity
|
|
||||||
* (important if other code holds references).
|
* (important if other code holds references).
|
||||||
*/
|
*/
|
||||||
public void giveHoleCards(PlayerId playerId, Card c1, Card c2) {
|
public void giveHoleCards(PlayerId playerId, Card c1, Card c2) {
|
||||||
@@ -293,8 +287,7 @@ public class GameState {
|
|||||||
/**
|
/**
|
||||||
* Starts a new hand by resetting the game state for the next round of poker.
|
* Starts a new hand by resetting the game state for the next round of poker.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>This:
|
||||||
* This:
|
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>sets {@code phase=PREFLOP}
|
* <li>sets {@code phase=PREFLOP}
|
||||||
@@ -336,4 +329,19 @@ public class GameState {
|
|||||||
public boolean isFolded(PlayerId playerId) {
|
public boolean isFolded(PlayerId playerId) {
|
||||||
return getPlayer(playerId).isFolded();
|
return getPlayer(playerId).isFolded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counts the number of players who have not folded.
|
||||||
|
*
|
||||||
|
* @return The number of non-folded players
|
||||||
|
*/
|
||||||
|
public int countNonFoldedPlayers() {
|
||||||
|
int count = 0;
|
||||||
|
for (Player p : players.values()) {
|
||||||
|
if (p != null && !p.isFolded()) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user