Turnforge
C++ turn-based tactics with deterministic enemy AI

Watch the gameplay
A 66-second scripted replay of one complete match from the default map and stats. It uses the normal input controller to show invalid movement, BFS, enemy intentions, Guard, combat and victory. The silent 720p/30 FPS video is rendered offline; its frame rate is separate from live game performance and it does not represent human playtesting.
- Movement and rejected wall clicks preserve the documented turn rules.
- Guard changes the forecast and reduces an actual enemy hit from 2 HP to 1 HP.
- Four attacks finish the match in round 6 with 3 HP remaining.
My contribution
A portfolio project developed with AI assistance across C++ implementation, UI, verification tooling and generated character artwork. The public source and reports document the implemented behavior, engineering choices and remaining validation work.
Engineering decisions
- Keep gameplay rules independent of raylib so they can be tested without opening a graphics window.
- Use BFS on the small uniform-cost grid and derive occupancy from living units.
- Reuse the real enemy-turn implementation on a copied state for an accurate, read-only forecast.
- Finish one offline arena and a reproducible Windows package before expanding the feature set.
Testing & evidence
- The rule suite passes 24 scenarios and 352 checks in Release and Debug, including preview immutability, actual-turn agreement, Guard and lethal-hit cancellation.
- A separate seeded suite passes 500 sessions, 64,433 actions and 1,126,045 checks. It is correctness coverage, not a player win-rate study.
- Recording QA passes 20 command-line/asset cases and the input/render verifier; the demo is fully decoded and checked as 1,980 video frames.
- The Windows ZIP runs after extraction outside the source tree with PATH restricted to Windows system directories.
Current limitations & next steps
One fixed map, one player and two melee enemies; no audio, saving or networking. Live performance is not established by the offline video: hidden-window runs varied from about 39 to 58 FPS and the 60 FPS target has not been met consistently. Human input/playtesting, visible-window benchmarking and broader balance remain pending.
The problem it solves
A small offline tactical game built with C++17 and raylib. A knight faces a pursuing goblin and a flanking bandit on an 8×8 arena. BFS validates movement around walls and living units, while a read-only simulation forecasts enemy movement and HP loss before End Turn. The core is independent of rendering and covered by rule, stress, input and package checks.
How it works
A standalone C++ rules model drives the raylib presentation. Enemy previews reuse the live AI on a copied match state, so movement, occupancy, damage and action order stay consistent with actual turns.
- 01
Mouse / keyboard → validated move, attack or Guard
- 02
Game state → BFS, occupancy and ordered enemy turns
- 03
Copied game state → read-only next-turn forecast
- 04
Model + forecast → raylib sprites, animation and HUD
An 8×8 grid, living-unit occupancy, orthogonal BFS, action budgets and immediate win/loss transitions.
Goblin pursues directly; bandit prefers another attack side within a two-step detour budget and falls back to direct pursuit when alone.
A copied enemy turn predicts movement and HP loss without changing the live game; sprites animate the resulting model state.
CTest rules and seeded stress checks, replayed input events, render captures and a self-contained Windows ZIP.
Catat Uang
Offline-first Flutter finance app with a Go synchronization API
