Note for Players: This document is technical documentation for developers. If you want to learn how to play Barony, see PLAYER_GUIDE.md instead.
Completion Date: February 11, 2026
Version: 1.0.0
All 7 major features have been successfully implemented and tested. See CHANGELOG.md for detailed feature list.
- ✅ Army Movement & Pathfinding - Complete with Manhattan distance pathfinding
- ✅ Army Management & Composition - Split/merge mechanics fully functional
- ✅ Territory Control & Village Mechanics - Ownership system with persistent villages
- ✅ Castle Capture & Win Conditions - 3-tick capture timer with game over state
- ✅ Basic AI Opponent - Rule-based AI with priority decision-making
- ✅ Enhanced UI & User Experience - Mouse controls, tooltips, HUD panels, game log
- ✅ Ruler Decision System (CK-Lite) - Policy-based strategic layer with stat mechanics
- ✅ Core Loop: Complete game from start to victory/defeat ✓
- ✅ Engagement: Games last 5-15 minutes with meaningful decisions ✓
- ✅ Strategic Depth: Ruler policies create 10-15% variance in outcomes ✓
- ✅ Polish: UI is clear, controls are responsive, no major bugs ✓
- ✅ AI: AI opponent provides reasonable challenge (~30-40% win rate) ✓
- ✅ Stability: Zero crashes during extended playtesting ✓
- ✅ Decision Impact: Policy effects visible within 10 ticks ✓
- Backend: Comprehensive unit and integration tests (all passing)
- Web Client: Model tests (all passing)
- CI Pipeline: All tests passing with 100% success rate
Transform the current technical prototype into an engaging single-player strategy game where players command armies, capture territory, and compete against AI opponents for control of the map.
The prototype initially supported:
- ✅ 10x10 grid with CASTLE, VILLAGE, and EMPTY tiles
- ✅ Two armies (Player 1 and Player 2)
- ✅ Instant army teleportation via REST command
- ✅ Villages generate 1 soldier per tick when occupied
- ✅ Combat via mutual soldier reduction when armies share location
- ✅ Basic rendering (colored tiles + circles for armies)
- ✅ REST API (GET /state, POST /tick, POST /command)
Current: Armies teleport instantly to any position via REST command
MVP: Armies move 1 tile per tick toward a destination
- Pathfinding: Implement A* or simple Manhattan distance pathfinding
- Movement Queue: Armies remember their destination and move each tick
- Movement Visualization: Players see armies traveling across the grid
- Movement Blocking: Armies cannot move through impassable terrain (optional for MVP)
- Add
Army.destinationXandArmy.destinationYfields - Add
Army.isMoving()method - Modify
GameService.tick()to process movement for all armies - Update
Commandto accept destination coordinates - Add movement validation (can't move through enemy castles, optional)
- Smooth interpolation between grid positions (optional for v1, can defer to v2)
- Visual indicator showing army destination (selection box or path preview)
- Backend: Add destination fields to Army model
- Backend: Implement pathfinding algorithm (Manhattan distance for MVP)
- Backend: Add movement processing in tick() method
- Backend: Update command validation for movement
- Backend: Add unit tests for movement mechanics (8-10 tests)
- Web Client: Add visual feedback for army destination
- Web Client: Test movement commands and rendering
- Documentation: Update README with movement mechanics
Current: Army size is a single integer (soldier count)
MVP: Armies show size and can be split into multiple armies
- Army Display: Show soldier count directly on army visualization
- Army Splitting: Split an army into two armies at the same location
- Army Merging: Automatically merge friendly armies at the same location
- Minimum Army Size: Require at least 1 soldier per army (can't split to 0)
- Add
POST /commandsupport for SPLIT command - Add
Command.splitAmountfield (how many soldiers to split off) - Implement
GameService.splitArmy(armyId, soldierCount) - Implement automatic merging in
tick()for co-located friendly armies - Update combat to handle multiple armies per player per location
- Display soldier count as text label over army circles
- Add keyboard shortcut for split command (e.g.,
Skey) - Add UI prompt for split amount (console input for MVP, can be UI later)
- Show multiple armies at same location (offset circles or stack indicator)
- Backend: Add SPLIT command type to Command enum
- Backend: Implement splitArmy() in GameService
- Backend: Implement automatic army merging
- Backend: Add unit tests for splitting/merging (6-8 tests)
- Web Client: Display soldier count on armies
- Web Client: Add split command input handling
- Web Client: Render multiple armies at same location
- Web Client: Add unit tests for army display
- Documentation: Update README with army management
Current: Villages generate soldiers only when occupied (any army present)
MVP: Villages generate soldiers only for the owning player
- Village Ownership: Villages belong to the player whose army occupies them
- Persistent Ownership: Villages retain ownership until captured by enemy
- Visual Ownership: Color-code villages (blue=player 1, red=player 2, brown=neutral)
- Income Display: Show total soldier production per tick in UI
- Add
Tile.ownerIdfield (0=neutral, 1=player1, 2=player2) - Modify village soldier generation to check tile ownership
- Add village capture logic when enemy army occupies village
- Add
GameState.getPlayerIncome(playerId)method
- Color villages based on ownership (blue/red tint on brown base)
- Display territory statistics (castles owned, villages owned, income/tick)
- Add visual feedback when capturing a village
- Backend: Add ownerId to Tile model
- Backend: Implement village capture logic in tick()
- Backend: Update soldier generation to respect ownership
- Backend: Add getPlayerIncome() calculation
- Backend: Add unit tests for ownership and capture (6-8 tests)
- Web Client: Update tile rendering for ownership colors
- Web Client: Display territory statistics panel
- Web Client: Add unit tests for rendering
- Documentation: Update README with territory mechanics
Current: No win/loss conditions
MVP: Win by capturing all enemy castles, lose by losing all castles
- Castle Ownership: Castles belong to players (castles start owned)
- Castle Capture: Occupy enemy castle for N ticks to capture it (N=3 for MVP)
- Win Condition: Player wins when they own all castles
- Loss Condition: Player loses when they have no castles remaining
- Game Over State: Display win/loss message and prevent further actions
- Add
Tile.ownerIdfor castles (extend from village ownership) - Add
Tile.occupationTickscounter for capture progress - Add
GameState.checkWinCondition()method - Add
GameState.gameOverandGameState.winnerIdfields - Prevent commands when game is over
- Color castles based on ownership (gray with blue/red outline)
- Show capture progress bar over contested castles
- Display win/loss overlay with "Play Again" option (restart via new /reset endpoint)
- Add sound effects for capture/victory (optional)
- Backend: Add ownerId to castle tiles (initialization in GameService)
- Backend: Add occupationTicks to Tile model
- Backend: Implement castle capture logic in tick()
- Backend: Add checkWinCondition() and game over state
- Backend: Add POST /reset endpoint to restart game
- Backend: Add unit tests for castle capture and win conditions (8-10 tests)
- Web Client: Render castle ownership colors
- Web Client: Display capture progress
- Web Client: Show win/loss overlay
- Web Client: Add reset functionality
- Web Client: Add unit tests
- Documentation: Update README with victory conditions
Current: Player 2 armies exist but require manual control
MVP: Simple AI that controls Player 2 armies
- AI Strategy: Simple rule-based AI (no machine learning)
- AI Goals:
- Capture neutral villages (priority: nearest)
- Attack enemy villages (if superior force)
- Defend owned villages (if under threat)
- Attack enemy castles (if overwhelming force)
- AI Execution: AI makes decisions during each tick
- AI Difficulty: Single difficulty level (balanced for MVP)
- Add
GameService.executeAI()method called during tick() - Implement AI decision logic:
- Scan for targets (villages, castles, enemy armies)
- Calculate threat levels and opportunity scores
- Issue movement commands for AI armies
- Implement army splitting for multi-front strategy
- Add AI army spawning at player 2's castle
- Visual indicator that AI is "thinking" (optional)
- Distinguish AI actions in game log (optional, can defer)
- Backend: Implement executeAI() in GameService
- Backend: Add target evaluation logic
- Backend: Add AI command generation
- Backend: Add AI army spawning/management
- Backend: Add unit tests for AI decision-making (8-10 tests)
- Backend: Balance AI difficulty through testing
- Documentation: Update README with AI description
Current: Minimal rendering with keyboard-only controls
MVP: Improved visualization and mouse-based interaction
- Mouse Controls:
- Click army to select it
- Click destination to move selected army
- Right-click to deselect
- Visual Feedback:
- Highlight selected army (glowing effect or border)
- Show movement range/destination preview
- Display hover tooltips (tile type, army size, ownership)
- HUD Elements:
- Top bar: Tick count, player income, army count
- Side panel: Selected army details
- Bottom bar: Game status messages
- Game Log: Recent events (army moved, village captured, combat occurred)
- Implement mouse input handling (GLFW mouse callbacks)
- Add army selection state and rendering
- Implement tooltip system with position tracking
- Add HUD rendering using text rendering or simple shapes
- Add game log with scrolling message list
- No changes required (all UI-side)
- Web Client: Add mouse input handling
- Web Client: Implement army selection
- Web Client: Add tooltip system
- Web Client: Create HUD panel rendering
- Web Client: Implement game log
- Web Client: Add unit tests for UI interactions
- Documentation: Update README with controls and UI
Current: Game focuses purely on military and territorial control
MVP: Add lightweight policy-based ruler decisions with delayed, indirect consequences
- Single Ruler Layer: Player embodies a single ruler making policy decisions for their realm
- Policy-Based Decisions: Choose from periodic policy options (every 10-20 ticks)
- Indirect Effects: Decisions affect game mechanics, not narrative:
- Village population growth/decline rates
- Village stability (affects soldier generation efficiency)
- Army morale (affects combat effectiveness)
- Army loyalty (affects desertion risk)
- Delayed Consequences: Policy effects take 5-10 ticks to manifest
- System-Driven Outcomes: No dialogue, quests, or story events
- CK-Lite Scope: Explicitly excludes:
- Dynasties, succession, or family management
- Diplomacy, negotiations, or character relationships
- Events with narrative text or choices
- Character skills, traits, or development
Policy Categories:
-
Economic Policies (affects village income and stability)
- Heavy Taxation: +20% income, -10% stability
- Balanced Budget: No change to income or stability
- Infrastructure Investment: -10% income, +10% stability
-
Military Policies (affects army morale and loyalty)
- Aggressive Training: +10% morale, -5% loyalty
- Standard Service: No change to morale or loyalty
- Veteran Benefits: -10% morale, +10% loyalty
-
Population Policies (affects village population growth)
- Growth Focus: +15% population growth, -5% stability
- Stable Population: No change
- Quality Over Quantity: -10% population growth, +10% stability
Decision Interface:
- Every 15 ticks, player is prompted with a policy choice
- UI shows current policy in each category
- UI displays current realm statistics:
- Average village stability (%)
- Average army morale (%)
- Average army loyalty (%)
- Total population across all owned villages
- Policy changes apply to all owned villages/armies
Mechanical Effects:
Village Stability:
- Base soldier generation: 1 per tick at 100% stability
- Modified generation:
base * (stability / 100) - Example: 70% stability = 0.7 soldiers/tick (rounded)
- Stability recovers slowly over time toward 100% (2% per tick)
Army Morale:
- Base combat strength: 1 soldier kills 1 enemy soldier
- Modified combat:
strength * (morale / 100) - Example: 120% morale = 1.2x combat effectiveness
- Morale decays slowly over time toward 100% (1% per tick)
Army Loyalty:
- Base desertion: 0% per tick
- Modified desertion:
(100 - loyalty) / 20% per tick - Example: 80% loyalty = 1% desertion per tick
- Loyalty recovers slowly over time toward 100% (2% per tick)
Population Growth:
- Affects maximum soldiers that can be generated at villages
- Villages have population cap (e.g., 50 soldiers)
- Growth policies modify this cap over time
- Higher population = more soldier generation potential
- Add
RulerDecisionmodel with policy types and effects - Add policy state to
GameState(current policy in each category) - Add
Village.stability,Village.populationfields - Add
Army.morale,Army.loyaltyfields - Implement policy effect calculation in
GameService.tick() - Add
POST /api/decisionendpoint to change policies - Add
GET /api/ruler-statsendpoint for realm statistics - Implement gradual stat recovery/decay logic
- Add policy selection UI (radio buttons or dropdown for each category)
- Display current policies in HUD (top-right corner)
- Show realm statistics panel (stability, morale, loyalty, population)
- Add visual indicators for villages/armies affected by low stats:
- Unstable villages: yellow tint
- Low morale armies: dimmed color
- Disloyal armies: orange outline
- Add policy change confirmation with preview of effects
- Show tick countdown until next policy decision is available
- Backend: Create RulerDecision model and policy types
- Backend: Add stability/morale/loyalty/population fields to models
- Backend: Implement policy effect calculations in tick()
- Backend: Add decision and stats endpoints
- Backend: Add unit tests for policy effects (10-12 tests)
- Backend: Balance policy effects through playtesting
- Web Client: Create policy selection UI
- Web Client: Display realm statistics panel
- Web Client: Add visual indicators for affected entities
- Web Client: Test policy changes and effect visualization
- Documentation: Update README with ruler decision mechanics
- Documentation: Document policy types and effects
- Army movement & pathfinding
- Territory control & ownership
- Enhanced army visualization
Milestone: Armies move realistically and villages have ownership
- Army management (split/merge)
- Castle capture mechanics
- Win/loss conditions
Milestone: Complete game loop with victory conditions
- Basic AI opponent
- Enhanced UI & mouse controls
- Ruler decision system (CK-lite layer)
- Polish and balancing
Milestone: Full MVP with AI opponent, strategic depth via ruler decisions, and polished UI
POST /command/move - Move army to destination (queued movement)
POST /command/split - Split army into two armies
POST /reset - Reset game state to initial conditions
GET /stats - Get player statistics (income, territories, etc.)
POST /api/decision - Change ruler policy (requires policy type and choice)
GET /api/ruler-stats - Get realm statistics (stability, morale, loyalty, population)// Army.java additions
private int destinationX;
private int destinationY;
private boolean isMoving;
private int morale; // 0-200, default 100, affects combat effectiveness
private int loyalty; // 0-100, default 100, affects desertion rate
// Tile.java additions (for villages)
private int ownerId; // 0=neutral, 1=player1, 2=player2
private int occupationTicks; // For castle capture
private int stability; // 0-100, default 100, affects soldier generation
private int population; // Current population, affects generation capacity
// GameState.java additions
private boolean gameOver;
private int winnerId;
private int ticksPerMove; // Config: tiles per tick
private Map<String, String> rulerPolicies; // Maps policy category to current choice
private int policyDecisionCooldown; // Ticks until next policy change allowed
// New RulerDecision.java
class RulerDecision {
enum PolicyCategory { ECONOMIC, MILITARY, POPULATION }
enum EconomicPolicy { HEAVY_TAXATION, BALANCED_BUDGET, INFRASTRUCTURE_INVESTMENT }
enum MilitaryPolicy { AGGRESSIVE_TRAINING, STANDARD_SERVICE, VETERAN_BENEFITS }
enum PopulationPolicy { GROWTH_FOCUS, STABLE_POPULATION, QUALITY_OVER_QUANTITY }
PolicyCategory category;
Object policyChoice; // One of the policy enums
Map<String, Integer> effects; // Maps stat names to percentage modifiers
}
// New PlayerStats.java
class PlayerStats {
int playerId;
int castlesOwned;
int villagesOwned;
int totalIncome;
int totalArmySize;
}
// New RulerStats.java
class RulerStats {
int playerId;
double averageStability; // Average across all owned villages
double averageMorale; // Average across all armies
double averageLoyalty; // Average across all armies
int totalPopulation; // Sum of all village populations
Map<String, String> currentPolicies; // Current policy in each category
int ticksUntilNextDecision;
}- Mouse event handling (click, hover)
- Keyboard shortcuts (S=split, R=reset, Space=tick)
- Input state management- Text rendering for labels and HUD
- Tooltip system with position tracking
- Multi-layer rendering (tiles, armies, UI)
- Selection highlighting effects- Backend: Target 80% code coverage for new features
- Web Client: Test all user input handling and state management
- End-to-end game scenarios (capture village, win game)
- AI behavior validation
- Multi-army interactions
- Balance testing: AI difficulty, soldier generation rates, ruler policy effects
- UX testing: Controls feel responsive, UI is clear, policy decisions are intuitive
- Performance testing: 60 FPS with 20+ armies
- Strategy testing: Verify multiple viable policy combinations
An MVP is successful when:
- ✅ Core Loop: Player can play a complete game from start to victory/defeat
- ✅ Engagement: Games last 5-15 minutes with meaningful decisions
- ✅ Strategic Depth: Ruler policies create observable gameplay differences (10-15% variance in outcomes)
- ✅ Polish: UI is clear, controls are responsive, no major bugs
- ✅ AI: AI opponent provides reasonable challenge (wins ~30-40% vs new players)
- ✅ Stability: Zero crashes during 30-minute playtest session
- ✅ Decision Impact: Player can correlate policy choices with visible stat changes within 10 ticks
These features are explicitly NOT in MVP:
Core Gameplay:
- ❌ Multiple unit types (knights, archers, etc.)
- ❌ Terrain effects (mountains, rivers, forests)
- ❌ Fog of war / limited visibility
- ❌ Resource system beyond soldier generation
- ❌ Technology/research tree
- ❌ Multiplayer or networked gameplay
- ❌ Save/load game functionality
- ❌ Advanced AI with multiple difficulty levels
- ❌ Sound effects and music
- ❌ Animations and particle effects
- ❌ Modding support
- ❌ Localization / multiple languages
Ruler/Character Systems (CK-Lite Boundaries):
- ❌ Dynasties, family trees, or succession mechanics
- ❌ Character development (skills, traits, education)
- ❌ Diplomacy system (alliances, treaties, negotiations)
- ❌ Relationship/opinion system between characters
- ❌ Narrative events with story text or branching choices
- ❌ Council members, advisors, or court management
- ❌ Marriage, children, or inheritance
- ❌ Character portraits, appearance, or customization
- ❌ Multiple playable rulers or realm switching
- ❌ Assassination, intrigue, or espionage mechanics
- ❌ Religion, culture, or ideological systems
- ❌ Feasts, tournaments, or social events
- Backend Development: ~70-90 hours (includes ruler decision system)
- Web Client Development: ~50-70 hours (includes policy UI and stat displays)
- Testing & Polish: ~25-35 hours
- Documentation: ~10-15 hours
Total: ~155-210 hours (5-7 weeks for solo developer, 3-4 weeks for small team)
✅ MVP Complete! All 7 major features have been successfully implemented and tested.
Post-MVP Development:
- See ROADMAP.md for post-MVP feature roadmap (v1.1 through v3.0)
- Review community feedback and prioritize v1.1 features
- Begin implementation of polish and quality-of-life enhancements
- This MVP focuses on fun over scope - better to have 7 polished features than 15 half-baked ones
- Each feature should be fully tested before moving to the next
- Regular playtesting (every 2-3 features) helps identify balance issues early
- Consider streaming development or sharing builds for community feedback
- Ruler decisions add strategic depth without narrative complexity - the system should feel like managing mechanics, not role-playing a character
- Policy effects should be balanced so no single strategy dominates - encourage experimentation and adaptation