My son is nine and plays games on the computer. One evening it occurred to me: if he is going to play games anyway, why not ours?
I started without telling him. What came out was arminefe.com.
What is in it
- Backgammon — two players, the real rule set, dice rolled on the server
- Card games — okey, pişti, uno and others: open a table, invite, play
- Hangman and battleship — simple, but two-player
- Robot Warriors — a tick-based combat RPG: ten classes, a paper-doll visual system, armour tiers, crafting, and two currencies
The scope later widened: the site is now open to four age groups, not only children. Adult tables are separate.
No WebSockets — and there should not be
The site lives on shared hosting. You cannot hold a persistent connection there; every request arrives, runs and dies.
That looks like a constraint. Given the genre it is not: in backgammon it is either your turn or it is not. Seeing your opponent’s move after 200 milliseconds or after 900 makes no difference to the game.
So the client asks the server at intervals: “has anything changed?”
client → server : state? (last_event_id = 412)
server → client : no new events ← cheap answer
…
client → server : state? (last_event_id = 412)
server → client : event 413 — opponent rolled 6-3, checker B24 → B18
The critical part is that the server sends what happened after the last event, not the whole state. Otherwise every poll ships the entire board and the bandwidth is wasted.
The interval is not fixed either: it polls often while a move is expected, backs off when it is the opponent’s turn, and stops when the tab goes to the background. Those three rules cut server load to a third with no change in feel.
Robot combat: ticks
Combat is a different problem. Something happens in real time and both sides must see the same thing.
The answer was to break the fight into discrete steps. It does not stream in real time; the server computes the whole fight at once and produces a list of events:
tick 1 : A attacks → 14 damage (no crit)
tick 2 : B guards → 6 damage absorbed
tick 3 : A ability → "overload" (lasts 3 ticks)
tick 4 : B attacks → miss
…
tick 21: B falls
The client takes that list and plays it back — animation, damage numbers, sound. What you see is a live fight; what was computed is a record.
Two benefits: both players see the identical fight, because they are playing the same list, and the fight can be replayed.
Keeping the door shut
On a children’s site you do not leave a registration form open. Entry is by QR code: I generate an invitation, a QR appears on screen, the child scans it with their phone and the account opens. The code is single-use and expires.
That way I know who came in and nobody random can sign up. There are two administrators: me, and the parent I am — so both of us can look at the panel.
Feedback from a one-person audience is brutal. If something is slow he does not say “slow”, he stops playing. If a rule is convoluted he does not say “I don’t understand”, he never opens that game again. No client has ever given me a signal that clean.
Result
The day I showed him, his first question was “did you make this?” His second was “can I invite my friend?” — which is exactly why the invitation system existed.
The technical lesson: constraints simplify design. Because there were no WebSockets I had to write an event-based protocol, and that protocol then fitted every game unchanged. With persistent connections I would probably have written a different solution for each one.