feat: honest AI opponent in quick game
CI / changes (pull_request) Successful in 3s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 14s
CI / ui (pull_request) Successful in 49s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m12s
CI / changes (pull_request) Successful in 3s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 14s
CI / ui (pull_request) Successful in 49s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m12s
New Game's quick game gains an explicit opponent selector — 🤖 AI (default) or 👤 Random player. AI starts a game seated with a pooled robot that joins and moves at once: no per-move timeout (a 7-day inactivity loss reusing the turn-timeout sweeper), chat/nudge disabled, no statistics, the opponent shown as 🤖 everywhere. The random path (disguised robot) is unchanged. Driven by one game flag (games.vs_ai), set only on AI-started games so the disguised path is never revealed; Matchmaker.StartVsAI seats the robot directly (no open pool); the robot replies event-driven via the game service's after-commit/after-create hook. Wire: vs_ai on EnqueueRequest + GameView.
This commit is contained in:
@@ -22,6 +22,9 @@ type GameMatcher interface {
|
||||
AttachRobot(ctx context.Context, gameID, robotID uuid.UUID) (game.Game, bool, error)
|
||||
ExpiredOpen(ctx context.Context, now time.Time) ([]game.OpenGame, error)
|
||||
InitialState(ctx context.Context, gameID, accountID uuid.UUID) (notify.PlayerState, error)
|
||||
// Create seats the given accounts in an active game at once; the AI-match path uses
|
||||
// it to start a game already seated with a robot (no open/wait phase).
|
||||
Create(ctx context.Context, params game.CreateParams) (game.Game, error)
|
||||
}
|
||||
|
||||
// Matchmaker turns an auto-match enqueue into a real game the player enters at once:
|
||||
@@ -96,6 +99,29 @@ func (m *Matchmaker) Enqueue(ctx context.Context, accountID uuid.UUID, variant e
|
||||
return EnqueueResult{Matched: joined, Game: g}, nil
|
||||
}
|
||||
|
||||
// StartVsAI creates an honest-AI game for accountID against a pooled robot, returning
|
||||
// the game the player enters at once. Unlike Enqueue it never opens or waits: it picks
|
||||
// a robot for the variant, seats the human and the robot in a random order (seat 0
|
||||
// moves first), and creates an active game flagged vs_ai. The flag makes the robot
|
||||
// reply immediately and suppresses chat, nudge and statistics; the robot's first move
|
||||
// (when it is seated first) follows on the game service's fast-move trigger.
|
||||
func (m *Matchmaker) StartVsAI(ctx context.Context, accountID uuid.UUID, variant engine.Variant, multipleWords bool) (EnqueueResult, error) {
|
||||
robotID, err := m.robots.Pick(variant)
|
||||
if err != nil {
|
||||
return EnqueueResult{}, err
|
||||
}
|
||||
params := aiMatchParams(variant, multipleWords)
|
||||
params.Seats = []uuid.UUID{accountID, robotID}
|
||||
if rand.IntN(2) == 1 {
|
||||
params.Seats = []uuid.UUID{robotID, accountID}
|
||||
}
|
||||
g, err := m.games.Create(ctx, params)
|
||||
if err != nil {
|
||||
return EnqueueResult{}, err
|
||||
}
|
||||
return EnqueueResult{Matched: true, Game: g}, nil
|
||||
}
|
||||
|
||||
// RunReaper substitutes a robot for any open game past its wait window, scanning every
|
||||
// interval until ctx is cancelled. It is started once from main.
|
||||
func (m *Matchmaker) RunReaper(ctx context.Context, interval time.Duration) {
|
||||
@@ -191,3 +217,17 @@ func autoMatchParams(variant engine.Variant, multipleWords bool) game.CreatePara
|
||||
MultipleWordsPerTurn: multipleWords,
|
||||
}
|
||||
}
|
||||
|
||||
// aiMatchParams builds the create parameters for an honest-AI two-player game: the
|
||||
// same casual auto-match defaults plus the vs_ai flag. The 7-day inactivity clock is
|
||||
// applied by the game service for vs_ai games, so TurnTimeout is left zero; the caller
|
||||
// fills Seats with the human and the picked robot.
|
||||
func aiMatchParams(variant engine.Variant, multipleWords bool) game.CreateParams {
|
||||
return game.CreateParams{
|
||||
Variant: variant,
|
||||
HintsAllowed: autoMatchHintsAllowed,
|
||||
HintsPerPlayer: autoMatchHintsPerPlayer,
|
||||
MultipleWordsPerTurn: multipleWords,
|
||||
VsAI: true,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user