How It Works

Real-time multiplayer Guess Who with a hybrid AI verification engine — deterministic lookups for facts, local VLM for vibes.

Game Flow

1Enter your name and get matched with another player via FIFO matchmaking.
2Both players see 24 randomly selected characters and secretly pick one as their identity.
3Take turns asking yes/no questions or guessing the opponent's character.
4Questions are evaluated against the opponent's secret character — factual traits resolve instantly, subjective ones go through the AI.
5Eliminate characters from your board based on answers. Your opponent sees eliminations in real time.
6Correctly guess the opponent's character to win!

Hybrid Verification Engine

When you ask a question, the system decides how to answer it:

Question: "Do they have brown hair?" │ ▼ ┌──────────────────────────────┐ │ Check character attributes │ │ (DB key/value lookup) │ └──────────────┬───────────────┘ │ Match found? ──YES──▶ Instant verdict │ NO │ ▼ ┌──────────────────────────────┐ │ Send to VLM (Ollama) │ │ image + attributes + question│ └──────────────┬───────────────┘ │ ▼ Yes / No / Inconclusive

Factual questions (hair color, glasses, hat) resolve instantly from the database.

Subjective questions ("looks friendly", "seems athletic") get evaluated by the AI model looking at the character's image and metadata.

If the model can't decide, you get Inconclusive — the round still completes normally.

Tech Stack

BackendScala 3 + ZIO
HTTP / WebSocketZIO-HTTP + Tapir
FrontendSvelteKit + TypeScript
DatabasePostgreSQL + Skunk
AI ModelOllama (qwen2.5vl:3b)
Proxy / TLSCaddy (auto HTTPS)

Architecture

┌──────────┐ WebSocket ┌──────────────┐ │ Browser │◀───────────▶│ ZIO-HTTP │ └──────────┘ │ (Game Loop) │ └──────┬───────┘ │ ┌────────────┼────────────┐ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │PostgreSQL │ │ Ollama │ │ Caddy │ │(chars, │ │ (VLM) │ │(TLS + │ │ history) │ │ │ │ static) │ └──────────┘ └──────────┘ └──────────┘

WebSocket Protocol

Tagged-union message protocol over WebSocket:

Client → Server

  • SelectCharacter — pick your secret character
  • SubmitQuestion — ask a yes/no question
  • GuessCharacter — guess opponent's character
  • EliminateCharacter — flip a card

Server → Client

  • GameStart — match found, 24 characters
  • TurnStart — whose turn it is
  • RoundResult — Yes / No / Inconclusive
  • GuessResult — correct or wrong
  • GameOver — winner + Elo delta
Play Now