Personal projects

Reino do Ritmo

status in-development

Six shires, each with a style of music, where you collect notes, raise creatures that play along and open the next shire. Made for a seven-year-old child to play. The name is Portuguese for “Kingdom of Rhythm”.

The central decision

The game rule does not know Roblox. The core is pure Luau, without a line of game, workspace, Instance or task, and it is where economy, rarity rolls, offline income, streak and collection validation live. What runs inside Roblox is a thin layer that applies that core and draws the result.

The practical consequence is the same as in Onde está o Gato: most of the game is testable without opening Studio, with the suite running headless in milliseconds. The alternative would be opening the editor to check whether offline income respects the hour cap, which is slow enough that in practice nobody checks.

Keeping the core pure took three layers

It was the most interesting part of the project, and the one I would not have foreseen:

LayerWhat it catches
Linter configured with the language’s standard library, not Roblox’sgame, workspace, Instance, task
Guard in CIos.time, os.clock, tick, math.random — legitimate Luau, but it breaks determinism
The suite running outside Robloxeverything: a module that touches the runtime simply does not execute

The third is the one that proves it. The first two exist so the failure arrives early and points to the right place, instead of showing up as a red test with no explanation.

A trap that cost discovery: the linter does not cascade configuration by directory. Running it pointed at the core folder ignores the restricted configuration there and uses the root one, which loads the Roblox library and approves exactly what it should block. Only the explicit form catches it, and it is the one CI uses.

What crossed from stack to stack

This project is the translation of my .NET patterns into Luau: layered architecture with the dependency pointing inward, notification instead of exception, clock and randomness injected instead of accessed directly.

What did not cross is documented with the same honesty, because it is where translating a pattern usually turns into cargo cult: not everything that makes sense in an enterprise domain with relational persistence makes sense in a single-aggregate save. Identity, repository and domain event, for example, gain nothing here.

About the people in the game

Two NPCs are a tribute to real children, with first name and stylized appearance. Nothing that identifies anyone.

Pablo Mickael Quevedo Senior Software Engineer · Novo Hamburgo, Brazil