feat(lobby): enter the game immediately and wait for the opponent inside it
CI / changes (pull_request) Successful in 1s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 14s
CI / ui (pull_request) Successful in 45s
CI / gate (pull_request) Successful in 1s
CI / deploy (pull_request) Successful in 1m4s
CI / changes (pull_request) Successful in 1s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 14s
CI / ui (pull_request) Successful in 45s
CI / gate (pull_request) Successful in 1s
CI / deploy (pull_request) Successful in 1m4s
Quick auto-match no longer waits on a separate screen: Enqueue opens a real game seating the caller with an empty opponent seat (new game status 'open') and the player enters it at once. A second human searching the same variant+rule joins that open game; otherwise a background reaper seats a robot after a 90s + random 0-90s wait, pushing a new in-app opponent_joined event that fills the opponent card and re-enables resign and chat in place. Matchmaking state is now the open games in the database (the in-memory pool, lobby.poll and lobby.cancel are gone), serialised by a per-bucket advisory lock. While a game is open the starter may move on their turn, but resign, chat and nudge are refused; the lobby and opponent card show "searching for opponent". Schema edited in the baseline (no prod data): 'open' status, nullable game_players.account_id for the empty seat, and a games.open_deadline_at stamp; jet code regenerated.
This commit is contained in:
+11
-6
@@ -41,8 +41,9 @@ language, not whichever bot the player signed in through last. Guests are sessio
|
||||
(auto-match only; no friends, stats or history); an abandoned guest that never
|
||||
joined a game and has been idle past the retention window is garbage-collected. While the app is open the client
|
||||
keeps a live stream and receives in-app updates in real time — the opponent's move,
|
||||
your turn, chat, nudges and a found match. Each update lands as the event itself, applied in place
|
||||
with no reload, so the board refreshes seamlessly and a found or invited game opens instantly. When the app is **closed**, the chosen
|
||||
your turn, chat, nudges and an opponent joining a game you are waiting in. Each update lands as the
|
||||
event itself, applied in place with no reload, so the board refreshes seamlessly and an invited game
|
||||
opens instantly. When the app is **closed**, the chosen
|
||||
out-of-app events (your turn, game over, nudge, a found match, an invitation or friend
|
||||
request) arrive as a **Telegram notification** instead — unless the player keeps
|
||||
notifications in the app only (a profile setting, **on by default**). The "your turn"
|
||||
@@ -84,8 +85,12 @@ unrestricted). Variants are shown by their **display name** — both Scrabble va
|
||||
"Scrabble"/"Скрэббл" and Erudit reads "Erudite"/"Эрудит" (by the interface language), and
|
||||
the same name titles the in-game screen. This gates only **starting** a new game — both auto-match and a friend
|
||||
invitation — so a player still sees and plays existing games of any language. Auto-match
|
||||
(always 2 players) joins a per-variant pool and is paired with the next waiting human;
|
||||
after 10 s with no human the robot substitutes. For Russian games (auto-match or friend
|
||||
(always 2 players) drops you **straight into the game and you wait inside it**: if it is your turn you
|
||||
can already move, otherwise you watch your tiles. While no opponent has joined, the opponent card (and
|
||||
the game's row in the lobby) reads **"searching for opponent"**, and resign, chat and nudge are
|
||||
unavailable. Another player searching the same variant and rule joins your game; failing that, a robot
|
||||
takes the empty seat after **1.5–3 minutes**, so a game always starts — and the New Game screen notes
|
||||
you can close the app while you wait and come back later. For Russian games (auto-match or friend
|
||||
invitation), New Game also offers **"Multiple words per turn"** (default **off**): off plays
|
||||
the simplified **single-word rule** — only the word laid along the player's line must be a
|
||||
real word, and any incidental perpendicular words are ignored and not scored — while on is
|
||||
@@ -121,8 +126,8 @@ the opponent's turn**, but that draft is position-only — the score preview and
|
||||
stay available only on the player's own turn.
|
||||
|
||||
### Robot opponent
|
||||
When auto-match finds no human within ten seconds, a robot opponent takes the empty
|
||||
seat so the game starts without waiting. It is meant to feel like a person: it
|
||||
When auto-match finds no human within the wait window (1.5–3 minutes), a robot opponent
|
||||
takes the empty seat of the game you are already waiting in. It is meant to feel like a person: it
|
||||
decides once per game whether to play to win (about 40% of the time, so the human
|
||||
wins most games), aims for a close score rather than crushing or throwing the game,
|
||||
and plays at a human pace — short thinking times for most moves, the occasional long
|
||||
|
||||
Reference in New Issue
Block a user