Jerhemy Waldon
Aria

Playing together with Aria, Part 1: Games

Tic Tac Toe with a persona that can say no. Invitations it accepts or declines from a play drive, a skill level from its personality, a game record so its reactions don't repeat, invitations of its own, and games as plug-ins: rules on the server, a board in the app.

Playing together with Aria, Part 1: Games

The talking picture was the most technically demanding feature. This one is the lightest, and maybe the best illustration of a theme that runs through the whole series: everything Aria does goes through its personality and the relationship, even a game of Tic Tac Toe.

Games are optional and off by default (GAMES_ENABLED). The first and only game so far is Tic Tac Toe, and that’s on purpose: the interesting part isn’t the game.

Inviting Aria to play

The game button next to the message box opens a picker: choose a game, then Send invitation or Cancel. No chat message is posted for it. The invitation shows above the message box until Aria answers, a moment later, on its own. If you write something first, its reply answers the invitation instead.

It can say no

Whether Aria accepts is its decision, made from a play drive:

play drive = 0.35 · playfulness + 0.20 · energy + 0.15 · spontaneity + 0.30 · affection
chance     = 0.35 + 0.60 · play drive

The chance is then lowered when something’s off between you: ×0.4 when the relationship is under strain, ×0.3 during an open conflict, and ×0.7 when the mood estimate reads you as low. A playful persona that’s fond of you usually says yes. When you seem down, it may rather talk. Then one roll decides, with the same logged dice as every other decision.

Either way, the answer comes in its own words. Yes starts the game (you move first). No comes with a reason.

This could easily have been “the persona always agrees to play”. Letting it decline is a small thing that makes the invitation feel like asking someone, not pressing a button.

Playing

While a game is on, the chat splits in two: the board on the left (larger), the conversation on the right. On narrow screens the board sits above the chat. You can keep talking while you play, and that’s most of the fun.

Aria never sees the board as an image. Every turn, its prompt describes the position in words (the board, the last move, whose turn it is), with an instruction never to write moves as text. Its moves are made on the board for it, at its skill level.

Skill from personality

How well Aria plays follows its personality:

skill = 0.55 + 0.30 · thoroughness + 0.20 · assertiveness − 0.15 · playfulness   (kept within 0.30–0.97)

At skill s, it plays its best move (a full negamax search, with ties broken at random) with probability s, and a random free cell otherwise. A thorough, self-assured persona is hard to beat. A very playful one plays looser and makes the occasional silly move. Tic Tac Toe is solved, so a perfect player would only ever draw or win, which isn’t much of a game.

A game of Tic Tac Toe beside the conversation

Reactions that don’t repeat

When a game ends, Aria reacts in a follow-on message a moment later. Given only the result, a model’s reactions repeat quickly: win, “Good game! Want to play again?”, lose, “Good game! Want to play again?”

So the reaction now gets context:

  • The game record: wins on both sides, draws and the current streak, across your finished games of that kind with this persona.
  • How this game went: who started, how many moves, the last move.
  • An angle for the reaction, picked by the dice from a list for that result.
  • Its own earlier lines after recent games, marked “don’t repeat these”.

A rematch is offered “not every time”. And the result leaves its prompt once you’ve moved on: after your first message it’s told not to bring the game up unless you do, and after your second the result is gone. That rule came from seeing it keep offering a rematch in a quick chat after the subject had changed. A context trace is how that one was found.

It invites you too

Now and then, Aria invites you itself, mostly when it’s playful and close:

  • only when no game is open, not within 12 hours of the last game, and not within a day of you saying no;
  • never under strain, during a conflict, or when you seem low;
  • with a small chance (0.01 + 0.12 · drive², twice that when it writes first, at most 0.3).

It invites the way it says anything else, in its own words, ending the message with a small marker that’s removed before you see it. The chat shows a card under the message: Play or Not now. While it waits for your answer, its prompt says so, so it doesn’t ask again.

Games as plug-ins

Tic Tac Toe is the first game, so it was built as the first plug-in, not as a special case:

  • On the server, a game is a class with a typed state (stored as JSON on the game session): the initial state, applying and validating a move (returning the next turn, the result, and the move in words), choosing the persona’s move at a skill level, and describing the position in words for the prompt. It’s registered with one line.
  • In the app, a game is a board component, registered under the same key.

Everything else is shared: the picker, the invitations, the panel, storage, events and the prompt sections. A new game touches nothing outside its own two files. Games aren’t copied when a persona is cloned, so a game in progress doesn’t continue in two places.

What I learned

  • Even a game goes through the relationship. A play drive, a mood check and a conflict penalty made one game of Tic Tac Toe feel like an interaction instead of a widget.
  • Give the model a record, not just a result. Reactions only stopped repeating once Aria could see the score, its own earlier lines, and an angle to take.
  • Describe state in words. A small model plays along fine with a board described in text. It never needs to draw one.
  • Build the first one as a plug-in. The second game will be two files.

In Part 2: stories told in parts, with choices, and roleplay scenes where Aria plays a part, or narrates the whole thing as a game master.