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 }