diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/deck/Card.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/deck/Card.java new file mode 100644 index 0000000..5663da6 --- /dev/null +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/deck/Card.java @@ -0,0 +1,53 @@ +package ch.unibas.dmi.dbis.cs108.casono.server.domain.game.deck; + +/** + * The Card class represents a single playing card in a standard deck of cards. + * Each card has a suit (Hearts, Diamonds, Clubs, Spades) and a rank (2-10, + * Jack, Queen, King, Ace). + * This class provides methods to retrieve the suit and rank of the card, as + * well as a string representation of the card. + */ +public class Card { + + private Suit suit; + private Rank rank; + + /** + * Constructs a Card with the specified suit and rank. + * + * @param suit The suit of the card (Hearts, Diamonds, Clubs, Spades). + * @param rank The rank of the card (2-10, Jack, Queen, King, Ace). + */ + public Card(Suit suit, Rank rank) { + this.suit = suit; + this.rank = rank; + } + + /** + * Retrieves the suit of the card. + * + * @return The suit of the card. + */ + public Suit getSuit() { + return suit; + } + + /** + * Retrieves the rank of the card. + * + * @return The rank of the card. + */ + public Rank getRank() { + return rank; + } + + /** + * Returns a string representation of the card, combining its rank and suit. + * + * @return A string representation of the card (e.g., "Ace of Spades"). + */ + @Override + public String toString() { + return rank + " of " + suit; + } +} diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/deck/Deck.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/deck/Deck.java new file mode 100644 index 0000000..6a2cf95 --- /dev/null +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/deck/Deck.java @@ -0,0 +1,66 @@ +package ch.unibas.dmi.dbis.cs108.casono.server.domain.game.deck; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * The Deck class represents a standard deck of playing cards. It provides + * functionality to create a full deck of 52 cards, shuffle the deck, and draw + * cards from it. The deck is initialized with all combinations of suits and + * ranks, and can be manipulated through its methods. + */ +public class Deck { + + private List cards; + + /** + * Constructs a new Deck object and initializes it with a standard set of 52 + * playing cards. The deck is created by iterating through all suits and ranks, + * creating a Card object for each combination, and adding it to the list of + * cards. + */ + public Deck() { + + cards = new ArrayList<>(); + + for (Suit suit : Suit.values()) { + for (Rank rank : Rank.values()) { + cards.add(new Card(suit, rank)); + } + } + } + + /** + * Shuffles the deck of cards using the Collections.shuffle method, which + * randomly permutes the list of cards. This method can be called to randomize + * the order of the cards in the deck before drawing. + */ + public void shuffle() { + Collections.shuffle(cards); + } + + /** + * Draws and removes the last card in the list, which represents the top of the deck. + * This method removes and returns the last card in the list of cards, which + * represents the top of the deck. If the deck is empty, this method will throw an + * IndexOutOfBoundsException. + * + * @return The Card object that was drawn from the deck. + */ + public Card draw() { + return cards.remove(cards.size() - 1); + } + + /** + * Retrieves the current list of cards in the deck. This method returns a new + * LinkedList containing the cards, which allows for safe manipulation of the + * returned list without affecting the internal state of the deck. + * + * @return A List of Card objects currently in the deck. + */ + public void setCards(List cards) { + this.cards = new LinkedList<>(cards); + } +} diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/deck/Rank.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/deck/Rank.java new file mode 100644 index 0000000..b50b0d4 --- /dev/null +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/deck/Rank.java @@ -0,0 +1,22 @@ +package ch.unibas.dmi.dbis.cs108.casono.server.domain.game.deck; + +/** + * The Rank enumeration represents the rank of a playing card in a standard + * deck of cards. It includes the ranks from Two to Ace, which are used to + * determine the value of the card in various card games, including poker. + */ +public enum Rank { + TWO, + THREE, + FOUR, + FIVE, + SIX, + SEVEN, + EIGHT, + NINE, + TEN, + JACK, + QUEEN, + KING, + ACE +} diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/deck/Suit.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/deck/Suit.java new file mode 100644 index 0000000..eb38b70 --- /dev/null +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/deck/Suit.java @@ -0,0 +1,14 @@ +package ch.unibas.dmi.dbis.cs108.casono.server.domain.game.deck; + +/** + * The Suit enumeration represents the four suits of a standard deck of playing + * cards: Hearts, Diamonds, Clubs, and Spades. Each suit is used to categorize + * the cards and can have different values in various card games, including + * poker. + */ +public enum Suit { + HEARTS, + DIAMONDS, + CLUBS, + SPADES +} diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/player/Player.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/player/Player.java new file mode 100644 index 0000000..65a501f --- /dev/null +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/player/Player.java @@ -0,0 +1,154 @@ +package ch.unibas.dmi.dbis.cs108.casono.server.domain.game.player; + +import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.deck.Card; +import java.util.ArrayList; +import java.util.List; + +/** + * The Player class represents a participant in the poker game. It holds + * information about the player's identity, chip count, status, and hand of + * cards. The class provides methods for managing the player's chips, hand, and + * status during the game. + */ +public class Player { + + private PlayerId id; + private int chips; + private PlayerStatus status; + private boolean folded = false; + + private List hand = new ArrayList<>(); + + /** + * Constructs a Player with the specified ID and initial chip count. The + * player's status is set to ACTIVE by default. + * + * @param id The unique identifier for the player. + * @param chips The initial number of chips the player has. + */ + public Player(PlayerId id, int chips) { + this.id = id; + this.chips = chips; + this.status = PlayerStatus.ACTIVE; + } + + /** + * Checks if the player is all-in, meaning they have no chips left to bet. + * + * @return true if the player is all-in, false otherwise. + */ + public boolean isAllIn() { + return chips == 0; + } + + /** + * Retrieves the unique identifier of the player. + * + * @return The player's ID. + */ + public PlayerId getId() { + return id; + } + + /** + * Returns the display name of the player. + * Currently identical to the player ID. + * + * @return The player's name. + */ + public String getName() { + return id.value(); + } + + /** + * Retrieves the current chip count of the player. + * + * @return The number of chips the player has. + */ + public int getChips() { + return chips; + } + + /** + * Removes a specified amount of chips from the player's total. If the amount + * exceeds the player's current chips, it sets the chip count to zero. + * + * @param amount The number of chips to remove from the player. + */ + public void removeChips(int amount) { + chips -= amount; + if (chips < 0) { + chips = 0; + } + } + + /** + * Adds a specified amount of chips to the player's total. + * + * @param amount The number of chips to add to the player. + */ + public void addChips(int amount) { + chips += amount; + } + + /** + * Sets the player's status to the specified value. + * + * @param status The new status for the player. + */ + public void setStatus(PlayerStatus status) { + this.status = status; + } + + /** + * Retrieves the current status of the player. + * + * @return The player's status. + */ + public PlayerStatus getStatus() { + return status; + } + + /** + * Retrieves the player's current hand of cards. + * + * @return A list of Card objects representing the player's hand. + */ + public List getHand() { + return hand; + } + + /** + * Adds a card to the player's hand. + * + * @param card The Card object to be added to the player's hand. + */ + public void giveCard(Card card) { + hand.add(card); + } + + /** + * Clears the player's hand of cards, removing all cards from the hand. + */ + public void clearHand() { + hand.clear(); + } + + /** + * Checks if the player has folded in the current round. + * + * @return true if the player has folded, false otherwise. + */ + public boolean isFolded() { + return folded; + } + + /** + * Sets the player's folded status to the specified value. + * + * @param folded The new folded status for the player. + */ + public void setFolded(boolean folded) { + this.folded = folded; + } +} diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/player/PlayerId.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/player/PlayerId.java new file mode 100644 index 0000000..6471fc3 --- /dev/null +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/player/PlayerId.java @@ -0,0 +1,74 @@ +package ch.unibas.dmi.dbis.cs108.casono.server.domain.game.player; + +import java.util.Objects; + +/** + * PlayerId is a value object that represents the unique identifier of a player + * in the game. It encapsulates a string value and provides validation to ensure + * that it is not null. The PlayerId class also includes a factory method for + * creating instances and overrides the toString method for easy representation. + */ +public record PlayerId(String value) { + + /** + * Constructs a PlayerId with the specified value. The constructor validates + * that the value is not null. + * + * @param value the string value representing the player's unique identifier + * @throws NullPointerException if the value is null + */ + public PlayerId { + Objects.requireNonNull(value, "PlayerId cannot be null"); + } + + /** + * Factory method to create a PlayerId instance from a string value. + * + * @param value the string value representing the player's unique identifier + * @return a new PlayerId instance with the specified value + */ + public static PlayerId of(String value) { + return new PlayerId(value); + } + + /** + * Returns the string representation of the PlayerId, which is the encapsulated + * value. + * + * @return the string value of the PlayerId + */ + @Override + public String toString() { + return value; + } + + /** + * Compares this PlayerId with another object for equality. + * + * @param o the object to compare to + * @return true if this PlayerId is equal to the given object, false otherwise + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + + PlayerId playerId = (PlayerId) o; + return Objects.equals(value, playerId.value); + } + + /** + * Returns the hash code for this PlayerId. + * + * @return the hash code of the PlayerId + */ + @Override + public int hashCode() { + return Objects.hash(value); + } +} diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/player/PlayerStatus.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/player/PlayerStatus.java new file mode 100644 index 0000000..e3884c1 --- /dev/null +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/player/PlayerStatus.java @@ -0,0 +1,14 @@ +package ch.unibas.dmi.dbis.cs108.casono.server.domain.game.player; + +/** + * The PlayerStatus enumeration represents the various states a player can be in + * during a poker game. It helps to track the player's current status, such as + * whether they are actively participating in the hand, have folded, are all-in, + * or have been eliminated from the game. + */ +public enum PlayerStatus { + ACTIVE, + FOLDED, + ALL_IN, + OUT +} diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/state/BettingState.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/state/BettingState.java new file mode 100644 index 0000000..d6ad7cc --- /dev/null +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/state/BettingState.java @@ -0,0 +1,19 @@ +package ch.unibas.dmi.dbis.cs108.casono.server.domain.game.state; + +import java.util.HashMap; +import java.util.Map; + +/** + * Represents the betting state of the current hand, including the pot size, + * the current highest bet, and the individual bets made by each player. + * It keeps track of the total pot, the current bet amount, and the bets made + * by each player. This class is essential for managing the betting rounds and + * ensuring that all players' bets are accounted for during the game. + */ +public class BettingState { + + private int pot; + private int currentBet; + + private Map playerBets = new HashMap<>(); +} diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/state/GamePhase.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/state/GamePhase.java new file mode 100644 index 0000000..8ed9307 --- /dev/null +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/state/GamePhase.java @@ -0,0 +1,18 @@ +package ch.unibas.dmi.dbis.cs108.casono.server.domain.game.state; + +/** + * The GamePhase enumeration represents the different phases of a poker game. + * Each phase corresponds to a specific stage in the game, such as waiting for + * players, dealing cards, and determining the winner. This enumeration is + * essential for managing the flow of the game and ensuring that actions are + * performed at the appropriate times. + */ +public enum GamePhase { + WAITING, + PREFLOP, + FLOP, + TURN, + RIVER, + SHOWDOWN, + FINISHED +} diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/state/GameState.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/state/GameState.java new file mode 100644 index 0000000..0375a2d --- /dev/null +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/state/GameState.java @@ -0,0 +1,510 @@ +package ch.unibas.dmi.dbis.cs108.casono.server.domain.game.state; + +import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.deck.Card; +import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.deck.Deck; +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 java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * The GameState class encapsulates the entire state of a poker game at any + * given + * moment. It maintains information about the players, the pot, the current + * phase of the game, the dealer position, and the cards in play. This class is + * central to managing the flow of the game and ensuring that all actions and + * decisions are based on an accurate representation of the current game state. + */ +public class GameState { + + private Map players = new HashMap<>(); + + private List playerOrder = new ArrayList<>(); + + private Pot pot = new Pot(); + + private TableState tableState = new TableState(); + + private int currentPlayerIndex; + + private boolean handActive; + + private boolean allowOutOfTurn; + + private GamePhase phase; + + private int dealerIndex; + + private Map currentBets = new HashMap<>(); + + private Map playerBetCommitments = new HashMap<>(); + + private Map> holeCards = new HashMap<>(); + + private List communityCards = new ArrayList<>(); + + // private final Set foldedPlayers = new HashSet<>(); + + private Deck deck; + + // Getter + + /** + * Returns the list of players currently in the game. + * + * @return A list of Player objects representing the players in the game. + */ + public Collection getPlayers() { + return players.values(); + } + + /** + * Returns the current player whose turn it is to act. + * + * @return The Player object representing the current player. + */ + public Player getCurrentPlayer() { + PlayerId id = playerOrder.get(currentPlayerIndex); + return players.get(id); + } + + /** + * Returns the index of the current player in the players list. + * + * @return An integer representing the index of the current player. + */ + public int getCurrentPlayerIndex() { + return currentPlayerIndex; + } + + /** + * Indicates whether a hand is currently active in the game. + * + * @return true if a hand is active, false otherwise. + */ + public boolean isHandActive() { + return handActive; + } + + /** + * Returns the current phase of the game (e.g., PREFLOP, FLOP, TURN, RIVER). + * + * @return The GamePhase enum value representing the current phase of the game. + */ + public GamePhase getPhase() { + return phase; + } + + /** + * Returns the current state of the table, including player statuses and + * positions. + * + * @return A TableState object representing the current state of the table. + */ + public TableState getTableState() { + return tableState; + } + + /** + * Returns the current pot, which contains the total amount of chips bet by + * players in the current hand. + * + * @return A Pot object representing the current pot. + */ + public Pot getPot() { + return pot; + } + + /** + * Returns the current deck of cards being used in the game. + * + * @return A Deck object representing the current deck of cards. + */ + public Deck getDeck() { + return deck; + } + + /** + * Returns the list of community cards currently on the table. + * + * @return A list of Card objects representing the community cards. + */ + public List getCommunityCards() { + return communityCards; + } + + /** + * Returns the hole cards for a specific player based on their ID. + * + * @param playerId The ID of the player whose hole cards are being requested. + * @return A list of Card objects representing the player's hole cards, or an + * empty list if the player has no hole cards. + */ + public List getHoleCards(PlayerId playerId) { + return holeCards.getOrDefault(playerId, new ArrayList<>()); + } + + /** + * Returns the index of the dealer in the players list. + * + * @return An integer representing the index of the dealer. + */ + public int getDealerIndex() { + return dealerIndex; + } + + /** + * Returns a map of player IDs to their current hole cards. + * + * @return A map where the key is the player ID and the value is a list of + * Card objects representing the player's hole cards. + */ + public Map> getPlayerCards() { + return holeCards; + } + + /** + * Returns the number of players currently in the game. + * + * @return An integer representing the number of players in the game. + */ + public int getPlayerCount() { + return players.size(); + } + + // SETTER + + /** + * Sets the index of the current player in the players list. + * + * @param index An integer representing the index of the current player. + */ + public void setCurrentPlayerIndex(int index) { + this.currentPlayerIndex = index; + } + + /** + * Sets whether a hand is currently active in the game. + * + * @param handActive A boolean value indicating whether a hand is active. + */ + public void setHandActive(boolean handActive) { + this.handActive = handActive; + } + + /** + * Sets the current phase of the game. + * + * @param phase The GamePhase enum value representing the new phase of the game. + */ + public void setPhase(GamePhase phase) { + this.phase = phase; + } + + /** + * Sets the index of the dealer in the players list. + * + * @param dealerIndex An integer representing the index of the dealer. + */ + public void setDealerIndex(int dealerIndex) { + this.dealerIndex = dealerIndex; + } + + /** + * Sets the current deck of cards being used in the game. + * + * @param deck A Deck object representing the new deck of cards to be used in + * the game. + */ + public void setDeck(Deck deck) { + this.deck = deck; + } + + /** + * Adds a player to the game with the specified ID and initial chip count. This + * method creates a new Player object, adds it to the list of players, and + * initializes the player's current bet and bet commitment in the game state. + * + * @param id The ID of the player to add. + * @param chips The initial number of chips the player has. + */ + public void addPlayer(PlayerId id, int chips) { + + Player player = new Player(id, chips); + + players.put(id, player); + playerOrder.add(id); + + currentBets.put(id, 0); + playerBetCommitments.put(id, 0); + } + + // BETTING LOGIC + + /** + * Retrieves the current bet amount for a specific player based on their ID. + * + * @param playerId The ID of the player whose current bet is being requested. + * @return An integer representing the current bet amount for the specified + * player, or 0 if the player has not placed any bets. + */ + public int getCurrentBet(PlayerId playerId) { + return currentBets.getOrDefault(playerId, 0); + } + + /** + * Sets the current bet amount for a specific player based on their ID. This + * method updates the currentBets map with the new bet amount for the specified + * player. + * + * @param playerId The ID of the player whose current bet is being set. + * @param amount The new bet amount to be set for the specified player. + */ + public void setCurrentBet(PlayerId playerId, int amount) { + currentBets.put(playerId, amount); + } + + /** + * Resets the current bets for all players by clearing the currentBets map. This + * method is typically called at the start of a new hand to ensure that all + * players' bets are reset to zero. + */ + public void resetBets() { + currentBets.clear(); + } + + /** + * Adds a specified amount to the pot. This method updates the total amount in + * the pot by adding the given amount to it. + * + * @param amount The amount of chips to be added to the pot. + */ + public void addToPot(int amount) { + pot.add(amount); + } + + /** + * Returns whether out-of-turn actions are allowed in the game. Out-of-turn + * actions refer to players being able to act when it is not their turn, which + * can be a feature in some poker variants or game modes. + * + * @return true if out-of-turn actions are allowed, false otherwise. + */ + public boolean isAllowOutOfTurn() { + return allowOutOfTurn; + } + + /** + * Sets whether out-of-turn actions are allowed in the game. This method updates + * the allowOutOfTurn flag, which determines if players can act when it is not + * their turn. + * + * @param allowOutOfTurn A boolean value indicating whether out-of-turn actions + * should be allowed in the game. + */ + public void setAllowOutOfTurn(boolean allowOutOfTurn) { + this.allowOutOfTurn = allowOutOfTurn; + } + + // PLAYER HELPERS + + /** + * Retrieves a player from the game based on their ID. This method searches the + * list of players for a player with the specified ID and returns it. If no + * player with the given ID is found, a RuntimeException is thrown. + * + * @param id The ID of the player to retrieve. + * @return The Player object corresponding to the specified ID. + * @throws RuntimeException if no player with the given ID is found in the game. + */ + public Player getPlayer(PlayerId id) { + Player player = players.get(id); + + if (player == null) { + throw new RuntimeException("Player not found: " + id); + } + + return player; + } + + // BET COMMITMENTS + + /** + * Retrieves the current bet commitment for a specific player based on their ID. + * A bet commitment represents the total amount a player has committed to the + * pot in the current hand, including all bets, raises, and calls they have + * made. + * + * @param playerId The ID of the player whose current bet commitment is being + * requested. + * @return An integer representing the current bet commitment for the specified + * player, or 0 if the player has not made any bet commitments. + */ + public int getCurrentBetCommitment(PlayerId playerId) { + return playerBetCommitments.getOrDefault(playerId, 0); + } + + /** + * Sets the current bet commitment for a specific player based on their ID. This + * method updates the playerBetCommitments map with the new bet commitment + * amount for the specified player. + * + * @param playerId The ID of the player whose current bet commitment is being + * set. + * @param amount The new bet commitment amount to be set for the specified + * player. + */ + public void setCurrentBetCommitment(PlayerId playerId, int amount) { + playerBetCommitments.put(playerId, amount); + } + + // CARDS + + /** + * Gives hole cards to a specific player based on their ID. This method takes + * two Card objects representing the player's hole cards and adds them to the + * holeCards map under the player's ID. + * + * @param playerId The ID of the player to whom the hole cards are being given. + * @param c1 The first Card object representing one of the player's hole + * cards. + * @param c2 The second Card object representing the other hole card for + * the player. + */ + public void giveHoleCards(PlayerId playerId, Card c1, Card c2) { + + List cards = new ArrayList<>(); + cards.add(c1); + cards.add(c2); + + holeCards.put(playerId, cards); + } + + /** + * Adds a community card to the game state. This method takes a Card object + * representing a community card and adds it to the list of community cards on + * the table. + * + * @param card The Card object representing the community card to be added to + * the + * game state. + */ + public void addCommunityCard(Card card) { + communityCards.add(card); + } + + /** + * Resets the community cards by clearing the list of community cards. This + * method is typically called at the start of a new hand to ensure that all + * community cards from the previous hand are removed from the game state. + */ + public void resetCommunityCards() { + communityCards.clear(); + } + + // TURN MANAGEMENT + + /** + * Advances the turn to the next player in the players list. This method updates + * the currentPlayerIndex by incrementing it and wrapping around to the start of + * the list if necessary, ensuring that the turn order is maintained correctly + * throughout the game. + */ + public void nextPlayer() { + int start = currentPlayerIndex; + + do { + currentPlayerIndex = (currentPlayerIndex + 1) % playerOrder.size(); + + Player p = getCurrentPlayer(); + + if (!p.isFolded() && !p.isAllIn()) { + return; + } + + } while (currentPlayerIndex != start); + } + + // Dealer Rotation + + /** + * Rotates the dealer position to the next player in the players list. This + * method updates the dealerIndex by incrementing it and wrapping around to the + * start of the list if necessary, ensuring that the dealer position rotates + * correctly after each hand. + */ + public void rotateDealer() { + dealerIndex = (dealerIndex + 1) % playerOrder.size(); + } + + /** + * Retrieves the current dealer based on the dealerIndex. This method returns + * the Player object corresponding to the current dealer position in the players + * list. + * + * @return The Player object representing the current dealer. + */ + public Player getDealer() { + PlayerId id = playerOrder.get(dealerIndex); + return players.get(id); + } + + // HAND RESET + + /** + * Starts a new hand by resetting the game state for the next round of poker. + * This + * method sets the handActive flag to true, resets the game phase to PREFLOP, + * clears the pot, resets all player bets and bet commitments, clears the + * community cards, and initializes a new shuffled deck of cards for the new + * hand. + */ + public void startNewHand() { + + handActive = true; + phase = GamePhase.PREFLOP; + + pot = new Pot(); + + resetBets(); + playerBetCommitments.clear(); + + resetCommunityCards(); + holeCards.clear(); + + for (Player player : players.values()) { + player.setFolded(false); + } + + deck = new Deck(); + deck.shuffle(); + + currentPlayerIndex = (dealerIndex + 1) % playerOrder.size(); + } + + /** + * Folds a player in the current hand. This method adds the specified player's ID + * to the set of folded players, indicating that the player has folded and is + * no longer active in the current hand. + * + * @param playerId The ID of the player who is folding. + */ + public void foldPlayer(PlayerId playerId) { + getPlayer(playerId).setFolded(true); + } + + /** + * Checks if a specific player has folded in the current hand. This method + * checks if the specified player's ID is present in the set of folded players, + * indicating that the player has folded. + * + * @param playerId The ID of the player to check for folding status. + * @return true if the player has folded, false otherwise. + */ + public boolean isFolded(PlayerId playerId) { + return getPlayer(playerId).isFolded(); + } +} diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/state/Pot.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/state/Pot.java new file mode 100644 index 0000000..3f09f47 --- /dev/null +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/state/Pot.java @@ -0,0 +1,46 @@ +package ch.unibas.dmi.dbis.cs108.casono.server.domain.game.state; + +/** + * The Pot class represents the total amount of chips that players have bet in a + * poker game. It provides methods to add chips to the pot, retrieve the + * current amount, and reset the pot for a new round. This class is essential + * for managing the betting aspect of the game and ensuring that the pot is + * accurately maintained throughout the game. + */ +public class Pot { + + // Disabled because it caused the port to be set to 0 + // private int total; + private int amount = 0; + + /** + * Adds the specified amount of chips to the pot. + * + * @param chips The number of chips to add to the pot. + */ + public void add(int chips) { + amount += chips; + } + + /** + * Retrieves the current amount of chips in the pot. + * + * @return The current amount of chips in the pot. + */ + public int getAmount() { + return amount; + } + + // Disabled because it caused the port to be set to 0 + // public int getTotal() { + // return total; + // } + + /** + * Resets the pot to zero, typically used at the end of a round or when + * starting a new game. + */ + public void reset() { + amount = 0; + } +} diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/state/TableState.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/state/TableState.java new file mode 100644 index 0000000..3d953c3 --- /dev/null +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/state/TableState.java @@ -0,0 +1,158 @@ +package ch.unibas.dmi.dbis.cs108.casono.server.domain.game.state; + +/** + * The TableState class represents the current state of the poker table during a + * game. It keeps track of the current bet, the last raise size, the minimum + * raise amount, and the big blind. Additionally, it manages the betting status, + * including whether betting is currently open and if it can be reopened after + * being closed. The class also tracks the last aggressor's ID to determine who + * made the most recent aggressive action (like a raise) in the betting round. + */ +public class TableState { + + private int currentBet; + private int lastRaiseSize; + private int minRaise; + private int bigBlind; + + private boolean bettingOpen; + private boolean canReopenBetting; + + private String lastAggressorId; + + /** + * Retrieves the current bet amount for the table. This value represents the + * highest bet that has been placed in the current betting round and is used to + * determine how much players need to call or raise to stay in the hand. + * + * @return The current bet amount for the table. + */ + public int getCurrentBet() { + return currentBet; + } + + /** + * Sets the current bet amount for the table. This method is typically called + * when a player places a bet or raises, updating the current bet to reflect + * the new amount. + * + * @param currentBet The new current bet amount to set for the table. + */ + public void setCurrentBet(int currentBet) { + this.currentBet = currentBet; + } + + /** + * Returns the big blind amount. The big blind serves as a baseline + * for betting and is often used to determine the minimum bet or raise. + * + * @return The big blind amount. + */ + public int getBigBlind() { + return bigBlind; + } + + /** + * Sets the big blind amount for the game. The big blind is a forced bet that + * players must post before the cards are dealt, and it serves as a baseline for + * betting in the game. + * + * @param bigBlind The amount to set as the big blind for the game. + */ + public void setBigBlind(int bigBlind) { + this.bigBlind = bigBlind; + } + + /** + * Retrieves the minimum raise amount for the current betting round. The + * minimum raise is typically determined by the size of the last raise or the + * big blind, ensuring that players must raise by at least a certain amount. + * + * @return The minimum raise amount for the current betting round. + */ + public int getMinRaise() { + return minRaise; + } + + /** + * Sets the minimum raise amount for the current betting round. This method is + * typically called after a raise is made, updating the minimum raise to ensure + * that subsequent raises meet the required amount. + * + * @param minRaise The new minimum raise amount to set for the current betting + * round. + */ + public void setMinRaise(int minRaise) { + this.minRaise = minRaise; + } + + /** + * Checks if betting is currently open at the table. This status indicates + * whether players are allowed to place bets or raises during the current + * betting round. + * + * @return true if betting is open, false otherwise. + */ + public boolean isBettingOpen() { + return bettingOpen; + } + + /** + * Sets the betting status for the table. This method can be used to open or + * close betting during a betting round, controlling whether players can place + * bets or raises. + * + * @param bettingOpen The new betting status to set for the table (true for + * open, false for closed). + */ + public void setBettingOpen(boolean bettingOpen) { + this.bettingOpen = bettingOpen; + } + + /** + * Checks if betting can be reopened after being closed. This status allows for + * scenarios where betting may be temporarily closed (e.g., after a raise) but + * can be reopened to allow other players to respond. + * + * @return true if betting can be reopened, false otherwise. + */ + public boolean canReopenBetting() { + return canReopenBetting; + } + + /** + * Sets whether betting can be reopened after being closed. This method is + * typically called after a raise is made, allowing for the possibility of + * reopening betting to let other players respond to the raise. + * + * @param canReopenBetting The new status indicating whether betting can be + * reopened (true or false). + */ + public void setCanReopenBetting(boolean canReopenBetting) { + this.canReopenBetting = canReopenBetting; + } + + /** + * Retrieves the ID of the last aggressor in the current betting round. The + * last aggressor is the player who made the most recent aggressive action (like + * a raise) and is important for determining the flow of betting and who may + * have the opportunity to respond. + * + * @return The ID of the last aggressor in the current betting round. + */ + public String getLastAggressorId() { + return lastAggressorId; + } + + /** + * Sets the ID of the last aggressor in the current betting round. This method + * is typically called after a player makes an aggressive action (like a raise), + * updating the last aggressor ID to reflect the most recent aggressive action. + * + * @param lastAggressorId The new ID of the last aggressor to set for the + * current betting round. + */ + public void setLastAggressorId(String lastAggressorId) { + this.lastAggressorId = lastAggressorId; + } +}