How the ddpoker Table Design System Handles Seating Arrangements
The ddpoker table design system splits concerns between visual styling managed by TableDesign and seat logic handled by PokerTable, which uses a fixed 10-seat array with offset calculations to center the local player at display seat five.
The open-source ddpoker project implements a robust architecture that separates aesthetic table configuration from player positioning mechanics. While the TableDesign class manages gradient backgrounds and persisted color profiles, the PokerTable class orchestrates seating arrangements through array-based storage and mathematical seat translation. This design ensures consistent visual theming while supporting dynamic player assignment and dealer button rotation across the 10-seat layout.
Architectural Separation of Concerns
The system divides table design into two distinct domains that operate independently. Understanding this separation is critical for modifying either the visual presentation or seating logic without affecting the other.
Visual Appearance is handled by TableDesign, a BaseProfile subclass that stores top and bottom gradient colors as java.awt.Color fields (colorTop_ and colorBottom_). These profiles serialize to HTML color strings (#RRGGBBAA) and persist in the tables/ directory, loaded at runtime via TableDesignManager.
Seat Management is implemented in PokerTable, the core model that maintains a fixed array of PokerPlayer objects, tracks the dealer button position, and provides utilities to map logical table seats to display positions in the UI.
Visual Profile Management
The TableDesign class focuses exclusively on aesthetic configuration, leaving seat allocation to other components.
Color values are serialized through read() and write() methods that convert between Java Color objects and HTML hex strings. The TableDesignManager.getDefaultProfile() method retrieves the most recently used profile or falls back to a built-in "Green" theme, supplying it to the UI layer at PokerGameboard lines 149-151.
Source: code/poker/src/main/java/com/donohoedigital/games/poker/TableDesign.java — color handling at lines 69-73 and profile I/O at lines 61-71.
Seat Storage and Assignment
The PokerTable class in code/poker/src/main/java/com/donohoedigital/games/poker/PokerTable.java implements the seating arrangement logic using a fixed-size array structure.
Fixed Array Structure
Player positions are stored in a 10-element array defined by PokerConstants.SEATS, where empty positions contain null:
PokerPlayer players_[] = new PokerPlayer[PokerConstants.SEATS]; // PokerTable.java L69-70
Adding Players
Random assignment uses addPlayer(PokerPlayer p), which locates a random empty slot and delegates to setPlayer():
public void addPlayer(PokerPlayer p) { … setPlayer(p, i); } // PokerTable.java L75-86
Targeted assignment uses setPlayer(p, nSeat), which validates seat availability, updates the array, and fires a TYPE_PLAYER_ADDED event:
public void setPlayer(PokerPlayer p, int nSeat) { … } // PokerTable.java L32-53
Occupancy queries support UI decision-making through getNumOccupiedSeats() (lines 112-119) and getNumOpenSeats() (lines 100-107), allowing interfaces to determine available actions like rebuys or add-ons.
Dealer Button Management
The dealer position (nButton_) is stored as a seat index within the PokerTable state. Helper methods manage button rotation around occupied seats:
moveButton()advances to the next occupied seatsetButtonRandom()places the button randomlysetButtonHighCard()assigns based on high card logic
The setButton(int n) method updates the internal index and fires TYPE_BUTTON_MOVED events:
public void setButton(int n) { … firePokerTableEvent(...); } // PokerTable.java L33-42
Display Seat Translation
To ensure the local human player always appears at seat 5 (index 4) in the UI, PokerTable implements offset calculations that rotate the logical seat numbers without altering the underlying array.
Offset Calculation
The getSeatOffset() method computes the rotation needed to center the local player:
public int getSeatOffset() { … return 4 - nSeat; } // PokerTable.java L62-80
Seat Mapping Methods
Two complementary methods handle the translation between internal logic and display:
getDisplaySeat(int nSeat)adds the offset and wraps using modulo arithmetic (lines 85-96)getTableSeat(int nDisplaySeat)subtracts the offset to convert display positions back to logical indices (lines 99-110)
This allows the UI to call table.getDisplaySeat(logicalSeat) for each player, ensuring consistent positioning regardless of which seat the local player occupies.
Practical Implementation
Creating a Table and Seating Players
// Create a new table (number 1) attached to a game instance
PokerTable table = new PokerTable(myGame, 1);
// Create two PokerPlayer instances (could be human or AI)
PokerPlayer alice = new PokerPlayer(...);
PokerPlayer bob = new PokerPlayer(...);
// Seat them in random open seats
table.addPlayer(alice);
table.addPlayer(bob);
// Query occupied seats – should be 2
int occupied = table.getNumOccupiedSeats(); // returns 2
Relevant source: PokerTable constructor L73-78, addPlayer L75-86, getNumOccupiedSeats L112-119.
Mapping Logical Seats to UI Positions
int logicalSeat = 0; // first seat in the array
int uiSeat = table.getDisplaySeat(logicalSeat);
// uiSeat will be 4 (seat 5) if the local human is at seat 0,
// otherwise it will be rotated so the human stays centered.
Relevant source: getSeatOffset() L62-80, getDisplaySeat() L85-96.
Rotating the Dealer Button
int next = table.getNextSeatAfterButton(); // finds next occupied seat after current button
table.setButton(next); // updates nButton_ and fires TYPE_BUTTON_MOVED
Relevant source: getNextSeatAfterButton() L124-126, setButton() L33-42.
Summary
- Separation of concerns:
TableDesignhandles visual styling (colors/gradients) whilePokerTablemanages seating arrangements and player positioning. - Fixed array storage: Seats are stored in a 10-element
PokerPlayerarray withnullindicating empty positions. - Flexible assignment: The system supports both random seating via
addPlayer()and specific seat targeting viasetPlayer(). - Dealer rotation: The dealer button tracks as a seat index with methods to advance randomly or to the next occupied seat.
- UI centering: Offset calculations in
getDisplaySeat()ensure the local player always renders at position 5 regardless of logical seat assignment.
Frequently Asked Questions
Where is the seat data stored in ddpoker?
Seat occupancy data is stored in the players_ array within PokerTable.java (lines 69-70), defined as new PokerPlayer[PokerConstants.SEATS] with a fixed length of 10. Empty seats contain null values, and the array index directly corresponds to the logical seat number (0-9).
How does ddpoker ensure the local player always appears in the center?
The getSeatOffset() method calculates a rotation value (4 - nSeat) that shifts all display positions so the local human player occupies index 4 (display seat 5). When the UI renders players, it calls getDisplaySeat() to translate internal array indices to rotated display positions, maintaining visual consistency across different seating positions.
Can players choose specific seats or are they randomly assigned?
The system supports both approaches. addPlayer() assigns players to random empty seats, while setPlayer(PokerPlayer p, int nSeat) allows direct seat selection by specifying the target index. The latter validates that the seat is empty before assignment and fires appropriate events for UI updates.
What is the relationship between TableDesign and PokerTable?
TableDesign and PokerTable operate independently. TableDesign (managed by TableDesignManager) only affects visual appearance through color profiles stored in the tables/ directory, while PokerTable contains all seating arrangement logic, player positioning, and dealer button management. The UI (PokerGameboard) consumes both: it applies the visual profile for rendering aesthetics and queries PokerTable for player positions.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →