### Core Engine - Updated `GameRules.ApplyMove` to return `(changed, gameOver, winnerIdx, keepTurn)` - Added keepTurn handling in `MatchLoop` to support Battleship mode B (classic rules) - Removed old single-board handling from MatchState and MatchInit - Cleaned go.mod by marking protobuf dependency as indirect ### Battleship - Implemented board-based state tracking using MatchState.Boards: - `p0_ships`, `p0_shots`, `p1_ships`, `p1_shots` - Removed legacy metadata-based ship/shot board encoding - Rewrote ValidateMove to use structured boards - Rewrote ApplyMove for classic Battleship rules (mode B): - Hits allow the attacker to keep their turn - Miss switches turn - Destroyed ship sections marked `X` - Improved CheckGameOver using structured boards ### TicTacToe - Updated ApplyMove signature to match new interface - Ensured TicTacToe always returns `keepTurn = false` - Updated code paths to use MatchState.Boards instead of Board ### Summary This commit completes the migration from a single-board architecture to a multi-board architecture across the engine, TicTacToe, and Battleship, enabling support for more complex games and multiple modes such as Battleship Mode B.
51 lines
1.7 KiB
Go
51 lines
1.7 KiB
Go
package games
|
|
|
|
import "localrepo/plugins/structs"
|
|
|
|
// MovePayload is the decoded payload sent from clients.
|
|
// It is intentionally untyped (map[string]interface{}) so each game
|
|
// can define its own move structure (e.g., row/col, coordinate, action type, etc.)
|
|
type MovePayload struct {
|
|
Data map[string]interface{} `json:"data"`
|
|
}
|
|
|
|
// GameRules defines a generic interface for match logic.
|
|
//
|
|
// Each game (TicTacToe, Battleship, Chess, etc.) must implement this interface.
|
|
// The Nakama match handler delegates all game-specific behavior to these methods.
|
|
type GameRules interface {
|
|
// Number of players needed to start.
|
|
MaxPlayers() int
|
|
|
|
// Assign symbols/colors/pieces at start.
|
|
AssignPlayerSymbols(players []*structs.Player)
|
|
|
|
// Apply a move.
|
|
// Returns: (changed, gameOver, winnerIndex)
|
|
ApplyMove(
|
|
state *structs.MatchState,
|
|
playerIdx int,
|
|
payload MovePayload,
|
|
) (changed bool, gameOver bool, winnerIdx int, keepTurn bool)
|
|
|
|
// If a player leaves, who wins?
|
|
// Return:
|
|
// >=0 → winner index
|
|
// -1 → draw
|
|
// -2 → invalid
|
|
ForfeitWinner(state *structs.MatchState, leaverIndex int) int
|
|
|
|
// InitBoards initializes all the boards required for the game.
|
|
//
|
|
// This is called AFTER all players have joined the match.
|
|
//
|
|
// Examples:
|
|
// - TicTacToe → 1 board shared by both players: {"tictactoe": 3x3}
|
|
// - Battleship → 2 boards per player:
|
|
// {"p0_ships":10x10, "p0_shots":10x10, "p1_ships":..., "p1_shots":...}
|
|
//
|
|
// The returned map is stored in MatchState.Boards.
|
|
InitBoards(players []*structs.Player, cfg GameConfiguration) map[string]*structs.Board
|
|
|
|
}
|