# Movement-Based Combat System Implementation ## Overview Implemented a complete grid-based combat system with movement, positioning, and range-based attacks. The system transforms static combat into dynamic spatial warfare where agents must move into range before attacking. --- ## Phase 1: Data Model Extensions ✅ ### 1.1 Weapon.cs - **Added**: `WeaponType` enum (Melee, Ranged, Magic) - **Added**: `_range` field (int, default 1 for melee) - **Impact**: Weapons now declare their combat class and effective range ### 1.2 Monster.cs - **Added**: `MonsterSize` enum (Small, Medium, Large) - **Added**: `_size` field (default Medium) - **Mapping**: - Small: 4 creatures per square - Medium: 1 creature per square (1x1) - Large: 1 creature in 4x4 squares - **Impact**: Monsters occupy different amounts of grid space ### 1.3 CharacterStats.cs - **Added**: `GetMovementRange()` method - **Formula**: Speed / 2 (minimum 1 square per turn) - **Impact**: Speed stat now determines both initiative and movement capability ### 1.4 Combatant.cs - **Added**: `GridPosition` property (Vector2Int) - **Added**: `Size` property (MonsterSize) - **Added Methods**: - `DistanceTo(Combatant)` - Manhattan distance - `IsAdjacentTo(Combatant)` - 1 square away check - `CanReachTarget(Combatant, Weapon)` - Range validation - `GetFootprintSize()` - Grid size based on monster size - `GetCreaturesPerSquare()` - Stacking limit --- ## Phase 2: Combat Infrastructure ✅ ### 2.1 CombatAction.cs (NEW) ```csharp public enum ActionType { Move, Attack, UseItem, Defend, Pass } public class CombatAction ``` - Represents turn decisions - Holds actor, action type, targets (combatant/position/item) - Flexible constructors for different action types - Used by CombatResolver to make combat determinate ### 2.2 MovementValidator.cs (NEW) Static utility class for all combat rules: - `CanAttack()` - Range validation (melee adjacency, ranged within range) - `CanMoveTo()` - Movement validation (in bounds, speed limit, grid valid) - `IsAdjacentTo()` - Melee range check (1 square away) - `ManhattanDistance()` - Distance calculation - `GetDirectionTowards()` - Direction for pathfinding - `GetNextPositionTowards()` - Single step toward target ### 2.3 CombatGrid.cs (NEW) Core spatial management system: **Constructor**: `CombatGrid(Vector2Int gridSize, float cellSize)` - Default: 11x7 grid - Tracks all occupancy per cell **Key Methods**: - `PlaceAllCombatants()` - Agents left side, monsters right side - `IsPositionValid()` - Respects grid bounds and size rules - `TryMoveCombatant()` - Atomic move with validation - `GetReachablePositions()` - BFS pathfinding within movement range - `PlaceCombatant()` - Place individual combatant - `RemoveCombatant()` - Remove from grid (on death) - `GridToWorldPosition()` / `WorldToGridPosition()` - Coordinate conversion **Occupancy Rules**: - Large (4x4): Cannot share any space - Medium (1x1): Needs empty cell - Small: Up to 4 per square (stacking) --- ## Phase 3: Event System Extensions ✅ ### 3.1 CombatEvent.cs **New Event Kinds**: - `MovementStart` - Actor begins moving - `MovementComplete` - Actor finishes moving - `OutOfRange` - Attack failed (ranged/magic out of range) - `TooFarForMelee` - Attack failed (not adjacent) - `TargetUnreachable` - Movement failed **New Event Fields**: - `SourcePosition` (Vector2Int) - Where movement started - `TargetPosition` (Vector2Int) - Destination or target location - `MovementDistance` (int) - Squares moved --- ## Phase 4: Combat Resolver Refactor ✅ ### 4.1 Core Flow Changes **Old**: Pick target → Attack every turn **New**: 1. **InitializeGrid()** - Create 11x7 grid, place all combatants 2. **SelectActions()** - Each combatant decides Move/Attack/UseItem 3. **ExecuteActions()** - Process decisions in order ### 4.2 New Methods #### `InitializeGrid()` - Creates CombatGrid with 11x7 cells - Places combatants (agents left, monsters right) #### `SelectActions()` - Agents check health, use potions if <20% HP - Pick random enemy target - **Decision logic**: - If target in weapon range → Attack action - If out of range → Move action (toward target) - If no weapon or can't move → Pass action #### `ExecuteActions()` - Processes all actions in turn order - Dispatches to specific executors #### `ExecuteMovement()` - Updates grid position - Emits MovementStart, MovementComplete events - Records source, destination, distance in events #### `ExecuteAttack()` - **Validates range BEFORE attacking** - Melee: Must be adjacent (distance = 1) - Ranged/Magic: Must be ≤ weapon.Range - Emits OutOfRange/TooFarForMelee if validation fails - Only calls TakeSwing() if valid #### `ExecuteUseItem()` - Agents can use consumables during their turn - Immediate health restoration ### 4.3 Combat Flow ``` Round starts ├─ SelectActions (all actors decide) │ └─ Pick target │ ├─ In range? → Attack │ └─ Out of range? → Move ├─ ExecuteActions (process decisions) │ ├─ Movement (all moves for round) │ ├─ Attacks (validated against actual positions) │ └─ Items (consumables used) └─ Check win conditions ``` --- ## Phase 5: BattleArenaView Animation ✅ ### 5.1 Slot Class Enhancement - **Added**: `CurrentGridPos` - Tracks position on grid ### 5.2 PlaceCombatants() Refactor - **Old**: Hard-coded team layout - **New**: Uses grid positions from Combatant objects - Respects actual CombatGrid placement ### 5.3 CreateSlot() Size Scaling ```csharp Small: 0.4f scale (smaller creatures) Medium: 0.58f scale (default, human-sized) Large: 1.2f scale (larger creatures) ``` ### 5.4 Replay() Event Handling **New Event Handlers**: - `MovementStart` - Brief pause (0.2s) - `MovementComplete` → `Movement()` animation - `OutOfRange` / `TooFarForMelee` → `RangeFailure()` animation - `HealthPotionUsed` → `HealPotion()` animation ### 5.5 New Animation Methods #### `Movement(CombatEvent e)` - Animates combatant from source to target position - Updates CurrentGridPos - Smooth glide over 0.6 beats #### `RangeFailure(int combatantId)` - Visual feedback: brief shake effect - 3 cycles of left-right motion - Indicates attack couldn't connect #### `HealPotion(CombatEvent e)` - Green color flash - Green floating text (+amount) - Updates displayed health - 0.6s total animation ### 5.6 Position Tracking Updates - **Strike()**: Uses actual grid positions from events - **ApplyFinalState()**: Uses final combatant GridPosition - **DrawNameplates()**: Uses Transform.position (dynamic) - **AddFloater()**: Uses Transform.position (dynamic) --- ## Architecture Integration 🔗 ``` BattleArenaView (Animation) ↑ │ replays events with positions │ CombatResolver (Logic) ├─ InitializeGrid() → CombatGrid ├─ SelectActions() → CombatAction[] ├─ ExecuteActions() │ ├─ ExecuteMovement() → uses MovementValidator │ ├─ ExecuteAttack() → uses MovementValidator │ └─ ExecuteUseItem() │ └─ Emits CombatEvent[] (with positions) ├─ MovementStart ├─ MovementComplete ├─ OutOfRange ├─ TooFarForMelee ├─ TargetUnreachable ├─ Hit/Miss └─ Death CombatGrid (Spatial State) ├─ PlaceAllCombatants() ├─ IsPositionValid() ├─ TryMoveCombatant() └─ GetReachablePositions() MovementValidator (Rules) ├─ CanAttack() ├─ CanMoveTo() ├─ IsAdjacentTo() └─ ManhattanDistance() Weapon (Type/Range) ├─ WeaponType enum └─ Range property Monster (Size) └─ MonsterSize enum Combatant (Positioning) ├─ GridPosition ├─ Size ├─ DistanceTo() ├─ CanReachTarget() └─ GetFootprintSize() ``` --- ## What This Enables ✨ ✅ **Spatial Combat** - No more "attack from anywhere" ✅ **Melee vs Ranged** - Different weapons have different reach ✅ **Speed-Based Movement** - Faster = more squares per turn ✅ **Smart AI** - Agents automatically move into range ✅ **Monster Sizes** - Large/Medium/Small occupy different space ✅ **Grid Stacking** - Small creatures can stack (4 per square) ✅ **Replayable Events** - All movement recorded for animation ✅ **Extensible** - Easy to add Defend, Flee, abilities, etc. --- ## Compatibility Notes ⚠️ ### Backwards Compatibility - Existing weapons default to `Melee` with `Range=1` if not specified - Existing monsters default to `MonsterSize.Medium` - Agents default to `MonsterSize.Medium` - CombatResolver interface unchanged (still takes combatants, returns BattleResult) - CombatDirector calls unchanged ### Testing Recommendations 1. Test melee combat (agent must be adjacent to monster) 2. Test ranged combat (agent moves into range, then attacks) 3. Test monster sizes: - Small creatures stacking - Large creatures blocking movement - Medium creatures standard behavior 4. Test grid boundaries (combatants can't move off grid) 5. Test multiple combatants (ensure pathfinding avoids allies) 6. Test movement range calculation (Speed/2) 7. Test speed stat affecting both initiative and movement --- ## Future Enhancements 1. **Defend Action** - Reduce incoming damage this turn 2. **Ranged Abilities** - Spells with area of effect 3. **Terrain Effects** - Obstacles, difficult terrain 4. **Crowd Control** - Stuns, roots, slows 5. **Smart Pathfinding** - Avoid allies, seek advantage 6. **Flanking Mechanics** - Bonuses for surrounding enemy 7. **Line of Sight** - Visibility-based targeting 8. **Formations** - Coordinated group movement --- ## Performance Considerations - CombatGrid uses Dictionary for O(1) occupancy lookup - BFS pathfinding is O(n) where n = grid cells (77 for 11x7) - Movement validation is O(1) per cell - All spatial queries happen once per turn - No per-frame updates (resolved completely before animation) --- ## Files Modified/Created ### Modified - `Weapon.cs` - Added WeaponType, Range - `Monster.cs` - Added MonsterSize - `CharacterStats.cs` - Added GetMovementRange() - `Combatant.cs` - Added positioning and range methods - `CombatEvent.cs` - Added movement event kinds, position fields - `CombatResolver.cs` - Complete refactor with grid system - `BattleArenaView.cs` - Updated animation, position tracking ### Created - `CombatAction.cs` - Action type system - `CombatGrid.cs` - Spatial grid management - `MovementValidator.cs` - Rule validation system **Total**: 7 modified, 3 new = 10 files changed --- ## Testing Checklist - [ ] Project compiles without errors - [ ] Basic fight resolves (agents vs monsters) - [ ] Melee attacks require adjacency - [ ] Ranged attacks work at range - [ ] Agents move into range automatically - [ ] Movement distance respects Speed stat - [ ] Large monsters block space - [ ] Small monsters stack (4 per square) - [ ] Health potions heal and show animation - [ ] Out of range attacks emit proper events - [ ] Movement animation plays correctly - [ ] Grid placement looks balanced - [ ] Final positions are accurate - [ ] Arena playback matches log-only mode