Inspiration
It started when I went back to visit my grandparents and ended up playing Reversi with my much younger cousins — and beat them without holding back. If I go easy, I get scolded for it, but I also have my pride, so I didn't want to just let them win either. Winning that easily against kids that much younger, though, felt kind of unfair. That's when I thought, "this game could use some element of luck, so the outcome isn't decided by skill gap alone." When it came to turning that idea into something concrete, another idea popped into my head: "what if the board itself could rotate?" Combining those two thoughts became the seed for this project — Reversi where random lanes on the board rotate mid-game, keeping the outcome uncertain no matter the skill gap.
What it does
Kaiten Reversi takes the classic game of Reversi (Othello) and adds a twist: the board itself moves. Every time a piece is placed, there's a 30% chance that one of the four outer lanes on the board randomly rotates one step. The only warning is a brief flash on the lane about to move — you never know which one it'll be. A position you carefully built up can suddenly get shuffled, so the outcome stays uncertain right up to the end, even when there's a big skill gap between players.
There are two ways to play:
Offline mode — two players share one device, with lanes rotating automatically and randomly as pieces are placed, just as described above. Online mode — two players on separate devices play over the internet, matched with a simple room code and synced in near real-time.
How we built it
Our stack is Expo (SDK 57) + React Native + Expo Router, in TypeScript. The game logic (placing pieces, flipping them, rotating lanes, judging the winner) is implemented as a fully separate logic layer, decoupled from the UI. Anything that uses randomness is also pluggable from the outside, so tests can verify outcomes deterministically.
For offline play, we built the flow — place a piece → 30% chance check → a blinking warning animation on the lane about to move → the actual rotation → turn resolution — as a state machine. While the blink is playing, the board update itself shows immediately, but the turn indicator is deliberately held back until the rotation finishes, so the game feels like "the next turn doesn't start until the rotation is done."
For online play, we used Firebase Realtime Database with anonymous auth, and adopted a "host-authoritative" model. One device (the first player) does all the actual game computation and writes the results to the server; the other device (the second player) does no computation at all and acts purely as a display client, sending its own moves as "proposals" to the server. This design sidesteps the classic problem of both devices consuming randomness separately and ending up out of sync. It also let us wrap the existing offline game logic almost as-is for the host side, so the new work for online play was mostly limited to the server communication layer.
We also iterated on the board UI: a brief highlight flash on the most recently placed piece before it fades back, a color pass on the board, and making the rotation-warning blink cover the pieces as well as the tiles so it's easier to notice. By having the game state carry "the position of the last move" as part of its own data, these visual improvements propagated to online play automatically, with no extra code needed there.
Ad display is also integrated. Throughout development, we kept a running set of design notes for every feature — writing down the goal, the decisions made, alternatives we considered, and anything we deliberately left open — before touching code.
Challenges we ran into
The biggest technical wall came from two quirks of the realtime database we used for online sync. One: writing an empty value causes that field to disappear entirely, which broke our check for whether the other player had joined — it always evaluated as "not joined" even after they had. The other: a data structure as sparse as a game board risked getting corrupted when synced directly, which we fixed by serializing the entire game state to a string before syncing it. That fix turned out to have a nice side effect later — it meant our board UI improvements could reach online play for free, without touching the sync code again.
Another persistent issue: board rotation can, in theory, leave the next player with no legal moves, or make a "pass" decision stale because it was computed before a rotation changed the board underneath it. We judged that properly solving this wasn't worth the complexity within our hackathon timeline, and deliberately left it unresolved for now.
On the visual side, the rotation warning blink was only affecting the tile background, not the piece sitting on top of it — simply a matter of draw order, which we fixed by reordering the layers.
Accomplishments that we're proud of
What we're most proud of is that one small twist turned a classic game like Reversi into something that's genuinely fun to play. Coming back to it and playing it ourselves over and over, we could really feel how much a single tension — the possibility that a lane might rotate at any moment — changes the whole texture of staring at the board. The idea that started this project, keeping the outcome uncertain even across a big skill gap, wasn't just a nice thought on paper; seeing it actually work as something playable was a more satisfying discovery than we expected.
The other thing we're proud of is getting this all the way to a finished, working product within the hackathon's tight timeline. We didn't stop at local, same-device play — we pushed through and built online play too, letting two people on opposite sides of the world face off in real time, without cutting corners along the way.
What we learned
On the product side, the biggest lesson was how much a single small rule change can transform the quality of an experience. Rotating lanes didn't take much code to implement, but once we actually played with it, the tension of staring at the board became something completely different. Evaluating an idea on paper and evaluating it after actually building something playable turned out to be two very different things.
On the technical side, the hardest part was getting AdMob working in production. Even though the implementation itself was supposedly done, no ads were showing up, and it took us a while to figure out why. It turned out we were missing the setup for app-ads.txt — a file that has to live on your website, separate from the app's own code. We didn't even know it existed, and once we did, the setup itself wasn't easy to follow either. Struggling through it and actually getting ads to display, even if it's a small, unglamorous win, felt like real progress toward monetization.
What's next for kaiten-reversi
Our first priority is reaching more players by expanding platform support — right now we're iOS-focused, with the web build kept as a dev-only tool, and we want to properly bring both Android and web up to the same level.
Next, we want to let players control the "luck" itself. The rotation chance and lane-selection logic are currently fixed, and turning these into adjustable settings would let players dial in how much randomness offsets a skill gap, tuning the game to fit whoever they're playing against.
Above all, we want to keep expanding the core idea of "a board that moves." Rotating lanes was just our first twist on Reversi, and we see it as a starting point for building out even more depth and variety in the gameplay itself.
CPU opponents aren't part of our near-term plan — we'd rather focus first on deepening platform reach and gameplay around human-vs-human play.
Log in or sign up for Devpost to join the conversation.