Inspiration
Our inspiration comes from classic Japanese grid-partitioning logic puzzles like Shikaku (Rectangles). Puzzles of this family are fundamentally tiling problems where players divide a grid of size \( W \times H \) into rect-linear regions. We wanted to elevate this concept into a modern, daily social experience for Reddit, introducing customizable shape and orientation constraints—where clues aren't just numbers, but visual rules (squares, horizontal/vertical rectangles) that guide partition boundaries.
What it does
Regionix is a spatial logic puzzle played inside Reddit.
- Solve: Divide the grid so that every cell is covered by exactly one region, and each region contains exactly one seed clue matching its constraint (e.g., a square region of size 4, a vertical rectangle of any size, or a horizontal region of size 6).
- Autosave & Persistence: Refreshes or app exits do not lose progress; state and timer values are cached in
localStorageto resume seamlessly. - Auto-Submit: The game automatically registers completion the second you find a valid configuration.
- Level Creator: Design custom logic puzzles, run an automated backtrack solver to verify if they have a unique solution, and publish them as playtestable posts to your subreddit.
- Daily Leaderboard & Streaks: Play date-seeded challenges daily to climb the standings and earn diamond rewards.
How we built it
Regionix is built on a modern web application stack:
- Frontend: Built with React 19, Vite, and Tailwind CSS 4 for reactive gameplay rendering and micro-animations.
- Backend: Serverless endpoints powered by Hono running inside Reddit's secure Node v22 (Devvit) runtime environment.
- Database & Cache: Devvit Redis for global leaderboard scores, streaks, and user profile data.
- Validation & Solvers: Developed a custom backtracking constraint propagation search algorithm in TypeScript to validate uniqueness and solve grids instantly in the Level Creator.
📐 The Scoring System
The final score uses a decaying mathematical multiplier based on elapsed time, penalty weights, and logins:
$$ \text{Score} = B \cdot \left( \frac{1}{1 + \alpha \cdot T} \right) - (\beta \cdot H) - (\gamma \cdot U) + (\delta \cdot S_{\text{streak}}) $$
Where:
- \( B \) is the base grid difficulty score: \( B = 100 \times (\text{Seeds Count}) \)
- \( T \) is the solve time in seconds.
- \( \alpha = 0.005 \) is the time decay coefficient.
- \( H \) is hints used (penalty \( \beta = 50 \)).
- \( U \) is undos used (penalty \( \gamma = 5 \)).
- \( S_{\text{streak}} \) is the active daily streak bonus (reward \( \delta = 20 \)).
Challenges we faced
- Accumulative Gesture Resizing: Standard swipe gestures usually shrink regions on backtrack. We solved this by using the bounding box union of coordinates swiped over, ensuring regions only grow during drags, and shrink to \( 1 \times 1 \) only when explicitly clicked.
- Iframe Webview Sandboxing: Standard browser prompts like
window.confirmorwindow.alertcrashed inside Reddit's iframe sandboxes. We eliminated all modal prompt dependencies, converting theResetaction into an instantaneous action. - Timer Synchronization: Ensuring timers kept ticking accurately across browser restarts or page refreshes required writing persistent, state-restored event hooks.
- Sorted Set Emulator Discrepancies: Redis client emulators in local Devvit playtesting have compatibility quirks with reverse ranking filters. We overcame this by fetching raw indexes (
redis.zRange(key, 0, -1)) and computing the leaderboard rankings in-memory.
What we learned
We mastered writing high-performance pathfinding and constraint solvers in TypeScript, implementing state serialization inside sandboxed WebView lifecycles, and designing visual color palettes that adapt seamlessly between dark (cyberpunk) and light (minimalist nordic) styles.
Built With
- algorithms
- algorithms.io
- backtracking
- canvas
- css3
- datastructures
- devvit
- hono
- html5
- javascript
- json
- node.js
- react
- redis
- rest-api
- serverless
- tailwind-css
- typescript
- vite
Log in or sign up for Devpost to join the conversation.