feat(battleship): add full placement/battle phases + metadata support + action-based moves

- Added Battleship Fleet definition (carrier, battleship, cruiser, submarine, destroyer)
- Implemented action-based MovePayload (`action: "place" | "shoot"`)
- Added placement and shot validation (ValidatePlacementMove, ValidateShotMove)
- Added ApplyPlacement and ApplyShot with correct ship placement + hit/miss logic
- Added pX_placed, pX_ready tracking and phase switching (placement → battle)
- Added Metadata field to MatchState (for phase/ready tracking)
- Updated MatchInit to initialize placement phase and readiness flags
- Updated MatchLoop to enforce turn order only during battle phase
- Added debug logging for state broadcasts
- Fixed protobuf dependency marking as indirect
This commit is contained in:
2025-12-03 21:00:38 +05:30
parent 10c7933aca
commit 0562d1e0c9
4 changed files with 165 additions and 10 deletions

View File

@@ -128,7 +128,11 @@ func (m *GenericMatch) MatchInit(
Turn: 0,
Winner: -1,
GameOver: false,
Metadata: map[string]interface{}{},
}
state.Metadata["phase"] = "placement"
state.Metadata["p0_ready"] = false
state.Metadata["p1_ready"] = false
label := fmt.Sprintf("%s:%s", m.GameName, m.Mode)
@@ -312,7 +316,8 @@ func (m *GenericMatch) MatchLoop(
// Turn enforcement — keep this here for turn-based games. If you want per-game control,
// move this check into the game's ApplyMove implementation or toggle via config.
if playerIdx != s.Turn {
phase := s.Metadata["phase"]
if phase == "battle" && playerIdx != s.Turn {
logger.Warn("Move rejected: not player's turn (idx=%d turn=%d)", playerIdx, s.Turn)
continue
}
@@ -338,6 +343,7 @@ func (m *GenericMatch) MatchLoop(
if changed {
if data, err := json.Marshal(s); err == nil {
logger.Info("Broadcasting state update (op=%d): %v", OpState, data)
if err := dispatcher.BroadcastMessage(OpState, data, nil, nil, true); err != nil {
logger.Error("BroadcastMessage failed: %v", err)
}