on
Project Aegis Dev Log: Building a Tower Defense Game with 100% AI-Generated Code
A dev log of Project Aegis — a mid-core mobile tower defense game built entirely by AI. Zero manual Unity clicks, zero hand-written lines of code. 42,000+ lines of C#, 589 passing tests, 8 milestones in ~20 hours.
This is the dev log for Project Aegis — a feasibility test to answer one question: Can you build a real, architecturally sound Unity game with 100% AI-generated code and zero manual interaction with the Unity Editor?
The answer, after ~20 hours of wall-clock time: yes, you can.
Not a single click was made in Unity3D. Not a single line of code was written by hand. Every C# file, every prefab, every ScriptableObject, every UXML layout, every scene modification — all generated by Claude through Claude Code and MCP for Unity.
I won’t explain the full workflow here — I covered that in detail in my previous post Beyond Vibe-Coding. This post is the practical dev log: what happened milestone by milestone, what I learned, and where things broke.
The Game
Project Aegis is a mid-core mobile strategy game blending merge mechanics with tower defense. Players build and merge structures on a grid-based fortress, recruit heroes and troops, erect towers, and defend against escalating enemy waves. The tech stack is not messing around:
- Unity 6 with URP
- DOTS/Entities/Burst for the battle simulation (200+ entities at 60 FPS)
- VContainer for dependency injection
- R3 for reactive state, MessagePipe for pub/sub
- UI Toolkit (UXML/USS) for all UI — critical because it’s plain text that AI can read and write
- 4 assembly definitions enforcing clean layered architecture (SharedLogic, Core, BattleSim, Presentation)
The architecture follows SOLID principles, interfaces everywhere, proper DI, and every service testable in isolation. This isn’t a toy project.
The Numbers
| Metric | Value |
|---|---|
| Total wall-clock time | ~20-22 hours |
| Final C# files | 328 |
| Final lines of C# | 42,628 |
| Test methods (all passing) | 589 |
| Compile errors | 0 |
| Manual Unity clicks | 0 |
| Lines of code written by hand | 0 |
| Manual non-code actions | 1 (creating a .env file with API keys) |
Milestone 1 — Grid & Building Placement
The foundation milestone established the entire project architecture and the core build mechanic. An 8x8 grid system with cell occupancy tracking, a scrollable build menu populated from a BuildingCatalog ScriptableObject, and building placement supporting varying footprints (1x1 to 2x2) with collision detection and visual placement previews. A basic gold economy with a ReactiveProperty<int>-backed EconomyService gates purchases. Camera controls support pinch-to-zoom and drag-to-pan via the new Input System. Building selection provides visual feedback through outline highlighting.
Architecturally, this milestone set the patterns everything else would follow: a pure C# SharedLogic layer with zero Unity dependencies (grid model, building data, economy rules), a Core layer with service interfaces and implementations behind VContainer DI, and a Presentation layer with thin MonoBehaviour views. 14 interfaces were defined — IGridService, IBuildingService, IEconomyService, IInputService, ICameraService, among others — each with a corresponding stub for testing. 8 assembly definitions enforce the layer boundaries at compile time. A BuildingFactory handles prefab instantiation through Addressables.
Result: 66 C# files, 5,117 lines, 14 interfaces, 7 services + 7 stubs, 4 controllers, 3 views, 1 factory, 11 MonoBehaviours, 5 ScriptableObject classes, 8 assembly definitions. Zero compile errors. Zero bugs.
What I learned: Getting the architecture right in Milestone 1 is everything. The ADRs (Architecture Decision Records) and the CLAUDE.md file gave Claude enough context to make correct architectural choices from the start. The decision to use VContainer’s LifetimeScope hierarchy, R3’s ReactiveProperty for observable state, and MessagePipe for decoupled pub/sub events — all established here — meant every subsequent milestone could build on solid foundations without rework.
Milestone 2 — Merge System
The core merge mechanic: two adjacent same-type/same-tier buildings combine into a higher-tier version. A MergeRecipeCatalog ScriptableObject drives all merge rules — no hardcoded recipes. The MergeService in SharedLogic handles recipe validation and adjacency detection, including correct handling of multi-cell footprints (a 2x2 building’s adjacency set is different from a 1x1). A MergeController orchestrates the UI flow: tap a building, see valid merge partners highlighted, confirm the merge, watch the old buildings get destroyed and the new tier spawned in place.
Technically interesting: the adjacency detection algorithm walks all occupied cells of both buildings and checks for shared edges, not just origin-cell proximity. This means a 2x2 Barracks next to a 1x1 Barracks correctly detects as mergeable regardless of which cell is adjacent. Tier-based visual distinction uses material swapping driven by tier data in the catalog — Claude created 9 materials and 8 prefabs for the tier variants, all correctly referenced in the ScriptableObject asset.
Result: 1 new interface, 2 services, 2 controllers, 2 MonoBehaviours, 1 ScriptableObject, 3 SharedLogic classes, 5 test files (36 test methods), 18 new asset files. Two bugs surfaced post-implementation — quickly fixed by providing logs and a bug description.
What I learned: The data-driven approach (ScriptableObject catalogs for everything) pays off immediately. Merge recipes, tier stats, visual properties — all tunable without touching code. Also: providing Claude with console output and a clear bug description is remarkably effective for quick fixes. The cycle is fast: describe symptom, provide logs, Claude traces through the service interfaces to the cause, fix deployed.
Milestone 3 — Combat Foundation (First Playable)
This was the big one — standing up an entire DOTS/ECS battle simulation layer from scratch. The architecture splits cleanly: a FlowFieldModel in SharedLogic computes pathfinding grids (cost field, integration field, flow field) that enemies follow to navigate around buildings. The ECS layer lives in the BattleSim assembly and runs 7 Burst-compiled systems: EnemySpawnSystem, EnemyMovementSystem (reads flow field directions), TowerTargetingSystem (nearest-enemy acquisition with range checks), ProjectileMovementSystem, DamageSystem, DeathSystem, and CombatSyncSystem (bridges ECS entity state to MonoBehaviour views via hybrid rendering).
11 ECS components were created — EnemyTag, Health, MoveSpeed, FlowFieldPosition, TowerData, ProjectileData, DamageOnHit, among others. All systems are ISystem implementations with [BurstCompile] attributes and use SystemAPI.Query for entity iteration — no managed allocations on the hot path.
The Presentation layer has an EnemySpawnService that instantiates pooled enemy GameObjects and an EnemyView MonoBehaviour that syncs transform position from the ECS entity each frame. A CombatBridge service mediates between the MonoBehaviour world and the ECS world, handling entity creation/destruction and state queries. Win/lose conditions check if all waves are cleared or if enemies reach the fortress.
Result: 51 new C# files, 4,616 lines, 11 ECS components, 7 ECS systems, 1 interface, 1 service, 2 controllers, 2 views, 2 factories, 9 MonoBehaviours, 4 ScriptableObject classes, 7 test files (56 test methods). Several bugs surfaced post-implementation, and some design changes were made during implementation (enemies spawn on top, move to bottom). ~3 hours wall-clock time.
What I learned: ECS is where Claude struggles most. The DOTS API is less represented in training data, and Burst constraints (no managed types, no allocations in [BurstCompile] methods, NativeArray instead of List<T>) create subtle compilation issues. But it got there. The flow field pathfinding — a non-trivial algorithm involving Dijkstra’s integration pass and gradient descent for direction vectors — was implemented correctly in SharedLogic as pure C#, which made it unit-testable without entering Play mode. Also: UnityMCP became noticeably slow during this milestone and was a genuine bottleneck.
Milestone 4 — Hero and Unit Combat
This milestone added the player’s fighting force. Barracks buildings now produce melee troops through a TroopSpawnService that creates ECS entities with TroopTag, UnitAttack, UnitHealth, and MoveSpeed components. A RallyPointController lets the player set a rally position on the battlefield — troops move to it and auto-engage nearby enemies via a TroopCombatSystem that handles target acquisition, attack cooldowns, and damage application.
A player-controllable hero was introduced with a HeroController (plain C# per ADR-007) handling tap-to-move input, a HeroMovementSystem in ECS for pathfinding, and a HeroAbilitySystem for cooldown-based abilities. The hero gets a dedicated HUD panel built in UI Toolkit (UXML/USS) showing HP, ability cooldowns, and portrait. Enemy retaliation was added via a RetaliationSystem so enemies fight back against troops and the hero instead of just walking politely to their death.
New ECS components: TroopTag, HeroTag, AbilityCooldown, AttackTarget, RetaliationTarget, and more — 14 in total. New systems: TroopMovementSystem, TroopCombatSystem, HeroMovementSystem, HeroAbilitySystem, RetaliationSystem, UnitDeathSystem, HeroSquadSystem.
Result: 45 new files, ~3,675 lines, 14 ECS components, 7 systems, 4 controllers, 3 views, 2 factories, 8 test files (39 tests). 174/174 tests passing. ~1.5 hours + 30 minutes for missed features.
What I learned: Claude silently dropped hero abilities and unit auto-engagement from the implementation. No error, no mention — it just didn’t do them. This is the “missing features without explanation” failure mode. The plan document is your safety net: always diff the implementation against the plan. After explicitly telling Claude to plan these back in, the implementation went smoothly.
I also experimented with giving each phase to a dedicated sub-agent with its own context. It didn’t work well — agents request confirmation for every tiny action and don’t retain approvals, making it extremely tedious. Back to single-agent sequential execution.
Milestone 5 — Economy and Game Time
This milestone restructured how time flows in the game and built out the wave economy. The central piece is a GameTimeService implementing a dual-tick game loop: ILogicTickable for game state updates that pause when the game is paused, and IVisualTickable for visual updates (animations, particles) that always run. A speed toggle switches between 1x and 2x by scaling Time.timeScale while the visual tick remains unaffected.
The ContinuousWaveService manages a 10-wave progression with distinct preparation/combat phases — enemies escalate in count, speed, and health per wave, all driven by a WaveCatalog ScriptableObject. A GoldMineService provides passive income across 3 building tiers, ticking on the logic clock and publishing ResourceChanged messages via MessagePipe. The EconomyService was extended to support multiple income sources (kill rewards, wave completion bonuses, passive income) all flowing through R3’s ReactiveProperty<int> so the UI updates reactively.
The cross-cutting change: all existing Update() and LateUpdate() methods across 22 files were migrated to the new ILogicTickable/IVisualTickable interfaces, registered with VContainer, and driven by the central GameTimeService. This means every controller and service that needs per-frame logic now declares which tick type it needs.
Result: 13 new files, ~1,542 lines, 4 interfaces, 2 services, 1 ScriptableObject class, 1 controller, 3 test files (35 methods), 22 modified C# files + 5 assets. 207/207 tests passing. ~1.5 hours.
What I learned: Cross-cutting refactors are where this workflow truly shines. Migrating every Update method to a new tick interface across 22 files is tedious manual work but trivial for Claude — it understands the pattern, finds all call sites, and applies it consistently. After implementation, NullReferenceExceptions and missing DI registrations surfaced when pressing Play. I told Claude to use UnityMCP to press Play and fix all exceptions — it ran through several fix-test iterations automatically until clean. This pattern became the unity-quality-gate skill.
Milestone 6 — Full Game Loop, Tutorial, UI
This milestone wired everything into a complete game experience. A GameFlowController (plain C# per ADR-007) orchestrates the full lifecycle: startup initialization, wave progression, victory/defeat detection, and game reset. A PauseController toggles GameTimeService.IsPaused and shows a pause overlay. Wave announcements use a banner system with USS-driven fade-in/fade-out animations and a wave progress bar that fills reactively via R3 binding to wave completion percentage.
The game-over popup shows Victory or Defeat with session stats (waves survived, enemies killed, buildings built) and a Play Again button that resets all services through the DI container. A TutorialOverlayController implements a non-blocking 3-step tutorial with PlayerPrefs persistence (later migrated to the unified save system in Milestone 7) — it highlights UI elements with dimmed overlays and instructional text, advancing on player actions.
All UI was built entirely in UI Toolkit: UXML for layout structure, USS for styling and animations. The GameHUD.uxml file defines the full HUD hierarchy (resource bar, wave info, speed toggle, hero panel, build button) and Claude reads/writes it as plain text — no Unity Inspector interaction needed.
Result: 8 new files, ~1,530 lines, 5 controllers, 1 popup, 2 new messages, 2 test files (12 methods), 15 modified C# files. 219/219 tests passing. 30 minutes total.
What I learned: This was the fastest milestone — 30 minutes for a complete UI layer and game flow. UI Toolkit was the key enabler. UXML and USS are plain text that Claude reads, writes, and modifies directly. No clicking through Unity’s Inspector. This is probably the single biggest enabler for zero-manual-interaction development. If you’re doing AI-assisted Unity development and still using uGUI, switch to UI Toolkit. One issue surfaced only during manual playtesting (grid not resetting on replay) — caught and fixed in the same session.
Milestone 7 — Local Saves and Analytics
The persistence system uses a JsonSaveService implementing ISaveService with Newtonsoft.Json serialization. The design uses a dirty-flag pattern: services mark themselves dirty when state changes, and AutoSaveController triggers serialization only when needed — at wave completion, app background (OnApplicationPause), and app quit. File I/O is atomic: write to a temp file, then File.Move to the target path, with a .bak backup that the recovery logic falls back to if the primary file is corrupted.
Save state is composed from multiple ISaveable implementations — GridSaveData, EconomySaveData, WaveSaveData, TutorialSaveData — each responsible for serializing/deserializing its own domain. This keeps the save system decoupled from game logic: each service knows how to save itself, and the JsonSaveService just orchestrates the collection and persistence.
Analytics follows a domain-split handler pattern: CombatAnalyticsHandler, EconomyAnalyticsHandler, WaveAnalyticsHandler, and SessionAnalyticsHandler — all implementing a common interface and registered with VContainer. Each handler subscribes to relevant MessagePipe events and translates them into analytics calls through the IAnalyticsService abstraction. Claude found, downloaded, and integrated the GameAnalytics SDK, resolved its dependencies, and wired it as the concrete IAnalyticsService implementation.
Result: 19 new files, ~3,030 lines, 2 services, 1 controller, 1 new interface + 3 extended, 5 DTOs, 4 analytics handlers, 6 test files (48 methods), 15 modified C# files. 277/277 tests passing. ~2-2.5 hours.
What I learned: Claude can handle third-party SDK integration surprisingly well. The only manual action in the entire project: I created the .env file with the API secret key myself, for security reasons. The domain-split analytics pattern was particularly clean — Claude actually suggested a single monolithic handler initially, and I steered it toward the split pattern. A good example of the developer’s architectural judgment complementing the AI’s implementation speed.
Testing revealed incomplete save state (unit positioning, wave timers weren’t persisted) — my fault, not Claude’s. It wasn’t in the plan. Lesson: your save system is only as complete as your specification.
Intermediate Milestone 1 — Major Refactoring
A foundational ECS refactoring to prepare for the gameplay expansion. The codebase had accumulated 12 per-type ECS components — TroopAttack, TroopHealth, HeroAttack, HeroHealth, EnemyAttack, EnemyHealth, TroopTarget, HeroTarget, EnemyTarget, and so on. These were consolidated into 3 unified generic components: UnitAttack, UnitHealth, and UnitTarget, plus a new EnemyResourceDrop component. Every system that queried the old components was migrated to use the unified versions with entity-tag-based filtering (EnemyTag, TroopTag, HeroTag) instead of separate component types.
New SharedLogic types were added (GridConstants for the expanded 12x12 grid, BuildingFlags for capability bitmasking), ADR-007 was updated to codify the plain-C#-controller rule, and both the GDD and MVP plan documents were refreshed.
Result: 93 files changed, 8 created, 12 deleted, 41 modified. 851 C# lines added, 452 removed (+399 net). 15 test files touched. 298/298 tests passing. ~1 hour.
What I learned: I was genuinely surprised how smoothly a foundational refactoring went. Renaming and consolidating ECS components touches everything — systems, queries, entity creation, tests. The quality gate verified the game starts, runs for 5 seconds, and stops without errors. Gameplay still worked despite extensive internal changes. This is where the layered architecture and comprehensive test suite really pay off — Claude can make sweeping changes with confidence because the 298 tests catch regressions immediately.
Intermediate Milestones 2-11 — Massive Gameplay Expansion
This was the largest block of work — 10 milestones executed over ~6 hours, each with its own plan-review-implement cycle. Here’s what was built:
Squad System (MS 2-4): A full SquadManager and SquadService with formation layout (units arrange in configurable patterns around a leader), leader promotion (if the leader dies, the highest-health unit takes over), and squad-level combat where the squad moves as a unit but individual members engage independently. New ECS systems: SquadMovementSystem, SquadCombatSystem, FormationSystem. A HeroSquadService syncs the hero’s rally point with their assigned squad.
Gate & Fortress Breach (MS 5): A GateView MonoBehaviour on a destructible gate building, a GateBreachSystem in ECS that detects when enemies reach the gate and applies siege damage, and a FortressBreachSystem for the final breach condition. Gate HP is displayed in the HUD via R3 binding.
Multi-Resource Economy (MS 6-7): The single-gold economy was replaced with a ResourceService supporting multiple ResourceType values (Gold, Wood, Steel, Food). A ResourceIncomeService handles per-tick income from production buildings. ResourceCost structs define multi-resource costs for building and merging. The entire UI was updated to display all resource types.
Military Production (MS 7): A MilitaryProductionController manages queued troop production from military buildings (Barracks, Archery Range, Knights Camp) with build times, queue limits, and resource costs. Production state persists across save/load.
Merge Pattern Detection (MS 8): PatternDetector and MergePattern types enable advanced merge recipes that check spatial arrangements — not just adjacency, but specific relative positions of buildings.
Building Movement (MS 9): Players can pick up and relocate existing buildings. The BuildingMovementController handles the drag interaction, validates the new position against occupancy, and animates the move.
New Building Types (MS 10-11): Farm, Archery Range, Gate, Knights Camp, Steel Mill, Wood Cutter — each with unique icons, prefabs, catalog entries, and production behaviors. 6 new building types with 57 prefabs total, all created and correctly referenced through UnityMCP.
Difficulty Scaling: A DifficultyScalingService adjusts enemy stats (health, speed, damage, count) per wave based on configurable curves in a ScriptableObject. A HUD element shows the current difficulty tier.
Save/Load Extension: Persistence was extended to cover squads, gate state, military production queues, continuous wave progress, and hero squad assignments.
Result: 485 files changed. 98 C# files created, 14 deleted, 104 modified. 18,709 C# lines added, 1,692 removed. 55 test files touched (31 new), 7,628 test lines added. 57 prefabs created automatically (and referenced correctly). 228 asset/meta/prefab files changed. 521/521 tests passing. ~6 hours.
What I learned: This was the phase that truly stress-tested the workflow. 485 files changed, 18k+ lines added, 57 prefabs auto-created and correctly referenced — all without a single Unity click. There were a couple of gameplay bugs afterwards but no runtime exceptions at all. The key was treating each intermediate milestone as its own mini-project with its own plan-review-implement cycle.
The adversarial Planner/Challenger debate skill was born from this phase. I had jumped too quickly from a vague high-level overview to detailed plans, and the implementation gaps showed. The debate pits a Planner agent against a Challenger agent for up to 5 rounds of structured critique — it adds 20-30 minutes to planning but the plans survive implementation far better.
Milestone 8 — Juice!
The polish milestone — making the game feel good. The architecture centers on a FeedbackService that listens to game events via MessagePipe (enemy killed, merge completed, wave cleared, ability cast) and dispatches multi-channel feedback through specialized services:
VfxService: Spawns pooled particle effects at world positions. Coin bursts on kill, sparkle effects on merge, impact effects on projectile hits — all defined in aFeedbackCatalogScriptableObject with per-effect configuration (prefab, duration, scale).ScreenShakeService: Cinemachine Impulse-based camera shake with configurable amplitude, frequency, and decay curves per event type. Heavy shake on merge, light shake on hits, dramatic shake on fortress breach.DamageNumberService: Floating damage numbers that spawn at hit positions, animate upward with randomized spread, and fade out. Uses object pooling to avoid GC pressure.BuiltInTweenService(671 lines): A custom tweening system to avoid external DOTween dependencies. Supports scale punches, position lerps, color fades, and easing curves — enough for UI animations and world-space feedback without pulling in a third-party library.
On the ECS side, a new KnockbackImpulse component and KnockbackSystem apply physics-based knockback to enemies on hit — the impulse decays over time and blends with the flow field movement.
The Presentation layer received broad visual polish: EnemyView, HeroView, TroopView, and UnitView all got hit-flash animations (white material flash on damage), death sequences, and idle wobbles. UI elements — build menu, building selection, merge highlights, resource display, wave announcements, game-over popup — all received animated transitions via the tween service. The resource counter animates to its new value instead of snapping. Wave announcements slide in with scale overshoot and fade out.
Result: 155 files changed, 35 C# files created, 3 deleted, 31 modified. 5,559 lines added, 1,294 removed. 14 new test files, 2,279 test lines added. 589/589 tests passing. ~1.5 hours.
What I learned: This was the milestone I was most curious about — “juice” is inherently subjective and hard to specify in a plan document. But Claude did remarkably well. The key was being specific in the plan about what events trigger what feedback rather than describing the desired feel. “When EnemyKilledMessage fires, spawn coin burst VFX at entity position, apply screen shake (amplitude 0.3, duration 0.2s), and show damage number” is actionable. “Make kills feel impactful” is not.
All the callbacks and triggers are wired correctly. You can see tiny animations, UI reacting to world events, screen shake on impacts. It doesn’t look like a AAA game, but the infrastructure for juice is comprehensive. A couple of minor bugs visible on close inspection, nothing serious.
42,628 lines of C# across 328 files — all generated by Claude, zero written by hand.
What I Learned — The Practical Takeaways
After 309 sessions and 2,360 messages over 20 days, here’s what I’d tell someone attempting something similar:
1. Architecture is your force multiplier
SOLID principles, interfaces everywhere, small focused files, assembly definitions enforcing layer boundaries — these aren’t academic exercises. They’re what make AI-assisted development work. Claude can follow execution paths in a well-structured codebase. In monolithic classes, it gets lost chasing things it thinks could be the problem.
2. UI Toolkit over uGUI, always
For AI-assisted development, this is non-negotiable. UXML and USS are plain text. Claude reads and writes them directly. No Inspector clicking needed. This was probably the single biggest enabler for zero-manual-interaction development.
3. Context management is the #1 skill
One phase per session. Clear context between phases. Always reference the plan document so Claude knows exactly what it should do — and what it should NOT do. When context windows get full, Claude starts hallucinating problems and initiating unrequested refactorings. This happens far more with Sonnet than Opus, which is why I exclusively use Opus for implementation.
4. Plans are your safety net
Claude silently dropped features in Milestone 4. No error, no mention. The only way I caught it was by diffing the implementation against the plan. Always review completeness, not just correctness.
5. Quality gates are non-negotiable
The unity-quality-gate skill — which verifies compilation, runs all tests, enters Play mode, checks for runtime exceptions, stops Play mode, and verifies clean shutdown — emerged from Milestone 5 debugging and became a standard part of every implementation. Automate your verification.
6. The “just press Play and fix” loop works
Telling Claude to use UnityMCP to press Play, read the console, fix all errors, and repeat until clean is surprisingly effective. It typically takes 2-4 iterations to go from “implementation done” to “actually running without exceptions.”
7. Opus over Sonnet for implementation
The reduced hallucination rate and better scope discipline justify the higher cost many times over. Sonnet’s speed advantage evaporates when you have to redo work because it went off-script.
Where Things Go Wrong
This isn’t all smooth sailing. The real friction points:
- Scope overreach: Claude sometimes implements Phase 3 when you asked for Phase 1 only, or refactors surrounding code while fixing a bug. Opus does this far less than Sonnet.
- Silent feature drops: Features get quietly omitted from implementation without any mention.
- Surface-level bug fixes: Claude frequently fixes the symptom, not the root cause. The insights report confirms this: “Incomplete first-pass fixes requiring multiple iterations” was a top friction category.
- Context rot: When work packages are too large, Claude starts hallucinating. The discipline of one-phase-per-session is non-negotiable.
- Dependence: After working this way for weeks, my reaction to an HTTP 500 from Anthropic was “let’s take a break and wait” rather than switching to manual development. That’s genuinely unsettling. Keep your hands-on craft sharp.
What’s Next
The project is ongoing. The expansion plan has detailed phases covering more combat systems, economy depth, and polish. The full expansion will roughly triple the codebase.
I’m also continuing to refine the workflow itself — the adversarial planning debate, the phased implementation commands, the quality gates. The step from “developer types commands sequentially” to “agent chains run a full pipeline autonomously” is architecturally small, even if the trust and safety questions around it are not.
If you’re interested in the workflow, check out the Beyond Vibe-Coding post for the full breakdown, or grab the Claude Code workflow skills from the marketplace.
This post was written with the help of Claude Code. The game was built entirely by it.