Skip to content

Case study / Multiplayer browser games

Testing multiplayer games from one browser

Short answerLocal bots use the existing game rules, including a 45-second night timer. That lets me inspect voting flows from a single screen.

I wanted to try voting flows in Word Imposter and Vampire Villagers without arranging other players first. Opening the room page was not enough: the games need participants to start, and some actions belong to a particular player's turn. I added a local simulator so I could reach those situations from my own screen.

The useful question was whether the game would accept the next action and present the resulting state. I did not need an opponent that could bluff convincingly. I chose simple rule-based bots with no LLM calls, keeping their decisions narrow enough to inspect.

Sending bots through the existing rules

Bots enter through the normal join operation. Their votes and night actions call the same game services that handle player actions. The simulator does not write a winning result or skip eligibility checks. Minimum player counts and valid targets remain responsibilities of the existing game rules.

In Word Imposter, consecutive bot turns advance until a human player needs to vote. In Vampire Villagers, the current role and phase determine whether a bot can cast a night vote, protect someone as the doctor, or investigate as the detective. The hunter's final shot also uses the existing action. Adding bots does not silently reconfigure the role counts.

  1. Room hostRequests bot actions in the local panel
  2. Server checkValidates environment, session and bot membership
  3. Existing game serviceApplies the normal action rules
  4. Player viewReturns state with other players' secrets removed
The simulator reuses the boundary between a player's action and the game's rules.

Automatic actions with manual phase control

Optional automatic mode runs eligible bot actions during the open room page's existing Livewire polling. I kept this within that request cycle instead of introducing a background worker. Closing the tab stops that activity. Starting the game and revealing voting results remain explicit host decisions; a separate 45-second game timer resolves the night.

Target selection is stable for the same eligible candidate set within a stage. That keeps a choice from changing arbitrarily during debugging; it does not make role allocation or an entire game deterministic. Completed actions are recorded separately so a repeated click or overlapping refresh does not submit the same bot action again.

Keeping local access on the server

Hiding the panel is insufficient. Each operation checks that the application is in a local or testing environment and that the session player is still the room's host. Bot identities come from a server-only registry scoped to that room. The browser cannot designate a human participant as a bot.

The existing presenters still determine what a player can see. Neither the simulation registry nor another player's secret role is added to public component state. A bot selects actions using the information its own role may receive, rather than gaining access to every hidden role.

This is a tool for inspecting game flow. It does not represent separate browser sessions, network delay or human bluffing.

A browser per bot would cover more client behavior, at the cost of managing those sessions. I chose service calls for this local workflow. Questions about disconnected clients or simultaneous behavior across different screens still require checks with real clients.

The public Word Imposter and Vampire Village pages let real players open a room. The bot panel is available only in local development.

Work together

Thinking about a similar project?

Tell me about your project