Files
Code_of_Conquest/docs/PHASE4_COMBAT_IMPLEMENTATION.md
2025-11-28 10:43:58 -06:00

29 KiB
Raw Blame History

Phase 4: Combat & Progression Systems - Implementation Plan

Status: In Progress - Week 2 Complete, Week 3 Next Timeline: 4-5 weeks Last Updated: November 27, 2025 Document Version: 1.3


Completion Summary

Week 1: Combat Backend - COMPLETE

Task Description Status Tests
1.1 Verify Combat Data Models Complete -
1.2 Implement Combat Service Complete 25 tests
1.3 Implement Damage Calculator Complete 39 tests
1.4 Implement Effect Processor Complete -
1.5 Implement Combat Actions Complete -
1.6 Combat API Endpoints Complete 19 tests
1.7 Manual API Testing ⏭️ Skipped -

Files Created:

  • /api/app/models/enemy.py - EnemyTemplate, LootEntry dataclasses
  • /api/app/services/enemy_loader.py - YAML-based enemy loading
  • /api/app/services/combat_service.py - Combat orchestration service
  • /api/app/services/damage_calculator.py - Damage formula calculations
  • /api/app/api/combat.py - REST API endpoints
  • /api/app/data/enemies/*.yaml - 6 sample enemy definitions
  • /api/tests/test_damage_calculator.py - 39 tests
  • /api/tests/test_enemy_loader.py - 25 tests
  • /api/tests/test_combat_service.py - 25 tests
  • /api/tests/test_combat_api.py - 19 tests

Total Tests: 108 passing

Week 2: Inventory & Equipment - COMPLETE

Task Description Status Tests
2.1 Item Data Models (Affixes) Complete 24 tests
2.2 Item Data Files (YAML) Complete -
2.2.1 Item Generator Service Complete 35 tests
2.3 Inventory Service Complete 24 tests
2.4 Inventory API Endpoints Complete 25 tests
2.5 Character Stats Calculation Complete 17 tests
2.6 Equipment-Combat Integration Complete 140 tests
2.7 Combat Loot Integration Complete 59 tests

Files Created/Modified:

  • /api/app/models/items.py - Item with affix support, spell_power field
  • /api/app/models/affixes.py - Affix, BaseItemTemplate dataclasses
  • /api/app/models/stats.py - spell_power_bonus, updated damage formula
  • /api/app/models/combat.py - Combatant weapon properties
  • /api/app/services/item_generator.py - Procedural item generation
  • /api/app/services/inventory_service.py - Equipment management
  • /api/app/services/damage_calculator.py - Refactored to use stats properties
  • /api/app/services/combat_service.py - Equipment integration
  • /api/app/api/inventory.py - REST API endpoints

Total Tests (Week 2): 324+ passing


Overview

This phase implements the core combat and progression systems for Code of Conquest, enabling turn-based tactical combat, inventory management, equipment, skill trees, and the NPC shop. This is a prerequisite for the story progression and quest systems.

Key Deliverables:

  • Turn-based combat system (API + UI)
  • Inventory & equipment management
  • Skill tree visualization and unlocking
  • XP and leveling system
  • NPC shop

Phase Structure

Sub-Phase Duration Focus
Phase 4A 2-3 weeks Combat Foundation
Phase 4B 1-2 weeks Skill Trees & Leveling
Phase 4C 3-4 days NPC Shop

Total Estimated Time: 4-5 weeks (~140-175 hours)


Phase 4A: Combat Foundation (Weeks 1-3)

Week 1: Combat Backend & Data Models COMPLETE

Task 1.1: Verify Combat Data Models COMPLETE

Files: /api/app/models/combat.py, effects.py, abilities.py, stats.py

Verified: Combatant, CombatEncounter dataclasses, effect types (BUFF, DEBUFF, DOT, HOT, STUN, SHIELD), stacking logic, YAML ability loading, serialization methods.


Task 1.2: Implement Combat Service COMPLETE

File: /api/app/services/combat_service.py

Implemented: CombatService class with initiate_combat(), process_action(), initiative rolling, turn management, death checking, combat end detection.


Task 1.3: Implement Damage Calculator COMPLETE

File: /api/app/services/damage_calculator.py

Implemented: calculate_physical_damage(), calculate_magical_damage(), apply_damage() with shield absorption. Physical formula: weapon.damage + (STR/2) - defense. 39 unit tests.


Task 1.4: Implement Effect Processor COMPLETE

File: /api/app/models/effects.py

Implemented: tick() method for DOT/HOT damage/healing, duration tracking, stat modifiers via get_effective_stats().


Task 1.5: Implement Combat Actions COMPLETE

File: /api/app/services/combat_service.py

Implemented: _execute_attack(), _execute_spell(), _execute_item(), _execute_defend() with mana costs, cooldowns, effect application.


Task 1.6: Combat API Endpoints COMPLETE

File: /api/app/api/combat.py

Endpoints:

  • POST /api/v1/combat/start - Initiate combat
  • POST /api/v1/combat/<combat_id>/action - Take action
  • GET /api/v1/combat/<combat_id>/state - Get state
  • POST /api/v1/combat/<combat_id>/flee - Attempt flee
  • POST /api/v1/combat/<combat_id>/enemy-turn - Enemy AI
  • GET /api/v1/combat/enemies - List templates (public)
  • GET /api/v1/combat/enemies/<id> - Enemy details (public)

19 integration tests passing.


Task 1.7: Manual API Testing ⏭️ SKIPPED

Covered by 108 comprehensive automated tests.


Week 2: Inventory & Equipment System COMPLETE

Task 2.1: Item Data Models COMPLETE

Files: /api/app/models/items.py, affixes.py, enums.py

Implemented: Item dataclass with affix support (applied_affixes, base_template_id, generated_name, is_generated), Affix model (PREFIX/SUFFIX types, MINOR/MAJOR/LEGENDARY tiers), BaseItemTemplate for procedural generation. 24 tests.


Task 2.2: Item Data Files COMPLETE

Directory: /api/app/data/

Created:

  • base_items/weapons.yaml - 13 weapon templates
  • base_items/armor.yaml - 12 armor templates (cloth/leather/chain/plate)
  • affixes/prefixes.yaml - 18 prefixes (elemental, material, quality, legendary)
  • affixes/suffixes.yaml - 11 suffixes (stat bonuses, animal totems, legendary)
  • items/consumables/potions.yaml - Health/mana potions (small/medium/large)

Task 2.2.1: Item Generator Service COMPLETE

Files: /api/app/services/item_generator.py, affix_loader.py, base_item_loader.py

Implemented Diablo-style procedural generation:

  • Affix distribution: COMMON/UNCOMMON (0), RARE (1), EPIC (2), LEGENDARY (3)
  • Name generation: "Flaming Dagger of Strength"
  • Tier weights by rarity (RARE: 80% MINOR, EPIC: 70% MAJOR, LEGENDARY: 50% LEGENDARY)
  • Luck-influenced rarity rolling

35 tests.


Task 2.3: Implement Inventory Service COMPLETE

File: /api/app/services/inventory_service.py

Implemented: add_item(), remove_item(), equip_item(), unequip_item(), use_consumable(), use_consumable_in_combat(). Full object storage for generated items. Validation for slots, levels, item types. 24 tests.


Task 2.4: Inventory API Endpoints COMPLETE

File: /api/app/api/inventory.py

Endpoints:

  • GET /api/v1/characters/<id>/inventory - Get inventory + equipped
  • POST /api/v1/characters/<id>/inventory/equip - Equip item
  • POST /api/v1/characters/<id>/inventory/unequip - Unequip item
  • POST /api/v1/characters/<id>/inventory/use - Use consumable
  • DELETE /api/v1/characters/<id>/inventory/<item_id> - Drop item

25 tests.


Task 2.5: Update Character Stats Calculation COMPLETE

Files: /api/app/models/stats.py, character.py

Added damage_bonus, defense_bonus, resistance_bonus fields to Stats. Updated get_effective_stats() to populate from equipped weapon/armor. 17 tests.


Task 2.6: Equipment-Combat Integration COMPLETE

Files: stats.py, items.py, character.py, combat.py, combat_service.py, damage_calculator.py

Key changes:

  • Damage scaling: int(STR * 0.75) + damage_bonus (was STR // 2)
  • Added spell_power system for magical weapons
  • Combatant weapon properties (crit_chance, crit_multiplier, elemental support)
  • DamageCalculator uses stats.damage directly (removed weapon_damage param)

140 tests.


Task 2.7: Combat Loot Integration COMPLETE

Files: combat_loot_service.py, static_item_loader.py, app/models/enemy.py

Implemented hybrid loot system:

  • Static drops (consumables, materials) via StaticItemLoader
  • Procedural drops (equipment) via ItemGenerator
  • Difficulty bonuses: EASY +0%, MEDIUM +5%, HARD +15%, BOSS +30%
  • Enemy variants: goblin_scout, goblin_warrior, goblin_chieftain

59 tests.


Week 3: Combat UI

Task 3.1: Create Combat Template COMPLETE

Objective: Build HTMX-powered combat interface

File: /public_web/templates/game/combat.html

Layout:

┌─────────────────────────────────────────────────────────────┐
│                        COMBAT ENCOUNTER                      │
├───────────────┬─────────────────────────┬───────────────────┤
│               │                         │                   │
│  YOUR         │   COMBAT LOG            │  TURN ORDER       │
│  CHARACTER    │                         │  ───────────      │
│  ─────────    │   Goblin attacks you    │  1. Aragorn ✓     │
│  HP: ████ 80  │   for 12 damage!        │  2. Goblin        │
│  MP: ███  60  │                         │  3. Orc           │
│               │   You attack Goblin     │                   │
│  ENEMY        │   for 18 damage!        │  ACTIVE EFFECTS   │
│  ─────────    │   CRITICAL HIT!         │  ───────────      │
│  Goblin       │                         │  🛡️ Defending     │
│  HP: ██   12  │   Goblin is stunned!    │  (1 turn)         │
│               │                         │                   │
│               │   ─────────────────     │                   │
│               │   ACTION BUTTONS        │                   │
│               │   ─────────────────     │                   │
│               │   [Attack] [Spell]      │                   │
│               │   [Item]   [Defend]     │                   │
│               │                         │                   │
└───────────────┴─────────────────────────┴───────────────────┘

Implementation:

{% extends "base.html" %}

{% block title %}Combat - Code of Conquest{% endblock %}

{% block extra_head %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/combat.css') }}">
{% endblock %}

{% block content %}
<div class="combat-container">
    <h1 class="combat-title">⚔️ COMBAT ENCOUNTER</h1>

    <div class="combat-grid">
        {# Left Panel - Combatants #}
        <aside class="combat-panel combat-combatants">
            <div class="combatant-card player-card">
                <h3>{{ character.name }}</h3>
                <div class="hp-bar">
                    <div class="hp-fill" style="width: {{ (character.current_hp / character.stats.max_hp * 100)|int }}%"></div>
                    <span class="hp-text">HP: {{ character.current_hp }} / {{ character.stats.max_hp }}</span>
                </div>
                <div class="mp-bar">
                    <div class="mp-fill" style="width: {{ (character.current_mp / character.stats.max_mp * 100)|int }}%"></div>
                    <span class="mp-text">MP: {{ character.current_mp }} / {{ character.stats.max_mp }}</span>
                </div>
            </div>

            <div class="vs-divider">VS</div>

            {% for enemy in enemies %}
            <div class="combatant-card enemy-card" id="enemy-{{ loop.index0 }}">
                <h3>{{ enemy.name }}</h3>
                <div class="hp-bar">
                    <div class="hp-fill enemy" style="width: {{ (enemy.current_hp / enemy.stats.max_hp * 100)|int }}%"></div>
                    <span class="hp-text">HP: {{ enemy.current_hp }} / {{ enemy.stats.max_hp }}</span>
                </div>
                {% if enemy.current_hp > 0 %}
                <button class="btn btn-target" onclick="selectTarget('{{ enemy.combatant_id }}')">
                    Target
                </button>
                {% else %}
                <span class="defeated-badge">DEFEATED</span>
                {% endif %}
            </div>
            {% endfor %}
        </aside>

        {# Middle Panel - Combat Log & Actions #}
        <section class="combat-panel combat-main">
            <div class="combat-log" id="combat-log">
                <h3>Combat Log</h3>
                <div class="log-entries">
                    {% for entry in combat_log[-10:] %}
                    <div class="log-entry">{{ entry }}</div>
                    {% endfor %}
                </div>
            </div>

            <div class="combat-actions" id="combat-actions">
                <h3>Your Turn</h3>
                <div class="action-buttons">
                    <button class="btn btn-action btn-attack"
                            hx-post="/combat/{{ combat_id }}/action"
                            hx-vals='{"action_type": "attack", "ability_id": "basic_attack", "target_id": ""}'
                            hx-target="#combat-container"
                            hx-swap="outerHTML">
                        ⚔️ Attack
                    </button>

                    <button class="btn btn-action btn-spell"
                            onclick="openSpellMenu()">
                        ✨ Cast Spell
                    </button>

                    <button class="btn btn-action btn-item"
                            onclick="openItemMenu()">
                        🎒 Use Item
                    </button>

                    <button class="btn btn-action btn-defend"
                            hx-post="/combat/{{ combat_id }}/action"
                            hx-vals='{"action_type": "defend"}'
                            hx-target="#combat-container"
                            hx-swap="outerHTML">
                        🛡️ Defend
                    </button>
                </div>
            </div>
        </section>

        {# Right Panel - Turn Order & Effects #}
        <aside class="combat-panel combat-sidebar">
            <div class="turn-order">
                <h3>Turn Order</h3>
                <ol>
                    {% for combatant_id in turn_order %}
                    <li class="{% if loop.index0 == current_turn_index %}active-turn{% endif %}">
                        {{ get_combatant_name(combatant_id) }}
                        {% if loop.index0 == current_turn_index %}✓{% endif %}
                    </li>
                    {% endfor %}
                </ol>
            </div>

            <div class="active-effects">
                <h3>Active Effects</h3>
                {% for effect in character.active_effects %}
                <div class="effect-badge {{ effect.effect_type }}">
                    {{ effect.name }} ({{ effect.duration }})
                </div>
                {% endfor %}
            </div>
        </aside>
    </div>
</div>

{# Modal Container #}
<div id="modal-container"></div>
{% endblock %}

{% block scripts %}
<script>
let selectedTargetId = null;

function selectTarget(targetId) {
    selectedTargetId = targetId;

    // Update UI to show selected target
    document.querySelectorAll('.btn-target').forEach(btn => {
        btn.classList.remove('selected');
    });
    event.target.classList.add('selected');
}

function openSpellMenu() {
    // TODO: Open modal with spell selection
}

function openItemMenu() {
    // TODO: Open modal with item selection
}

// Auto-scroll combat log to bottom
const logDiv = document.querySelector('.log-entries');
if (logDiv) {
    logDiv.scrollTop = logDiv.scrollHeight;
}
</script>
{% endblock %}

Also create /public_web/static/css/combat.css

Acceptance Criteria:

  • 3-column layout works
  • Combat log displays messages
  • HP/MP bars update dynamically
  • Action buttons trigger HTMX requests
  • Turn order displays correctly
  • Active effects shown

Task 3.2: Combat HTMX Integration COMPLETE

Objective: Wire combat UI to API via HTMX

File: /public_web/app/views/game_views.py

Implementation:

"""
Combat Views

Routes for combat UI.
"""

from flask import Blueprint, render_template, request, g, redirect, url_for

from app.services.api_client import APIClient, APIError
from app.utils.auth import require_auth
from app.utils.logging import get_logger

logger = get_logger(__file__)

combat_bp = Blueprint('combat', __name__)


@combat_bp.route('/<combat_id>')
@require_auth
def combat_view(combat_id: str):
    """Display combat interface."""
    api_client = APIClient()

    try:
        # Get combat state
        response = api_client.get(f'/combat/{combat_id}/state')
        combat_state = response['result']

        return render_template(
            'game/combat.html',
            combat_id=combat_id,
            combat_state=combat_state,
            turn_order=combat_state['turn_order'],
            current_turn_index=combat_state['current_turn_index'],
            combat_log=combat_state['combat_log'],
            character=combat_state['combatants'][0],  # Player is first
            enemies=combat_state['combatants'][1:]     # Rest are enemies
        )

    except APIError as e:
        logger.error(f"Failed to load combat {combat_id}: {e}")
        return redirect(url_for('game.play'))


@combat_bp.route('/<combat_id>/action', methods=['POST'])
@require_auth
def combat_action(combat_id: str):
    """Process combat action (HTMX endpoint)."""
    api_client = APIClient()

    action_data = {
        'action_type': request.form.get('action_type'),
        'ability_id': request.form.get('ability_id'),
        'target_id': request.form.get('target_id'),
        'item_id': request.form.get('item_id')
    }

    try:
        # Submit action to API
        response = api_client.post(f'/combat/{combat_id}/action', json=action_data)
        result = response['result']

        # Check if combat ended
        if result['combat_state']['status'] in ['victory', 'defeat']:
            return redirect(url_for('combat.combat_results', combat_id=combat_id))

        # Re-render combat view with updated state
        return render_template(
            'game/combat.html',
            combat_id=combat_id,
            combat_state=result['combat_state'],
            turn_order=result['combat_state']['turn_order'],
            current_turn_index=result['combat_state']['current_turn_index'],
            combat_log=result['combat_state']['combat_log'],
            character=result['combat_state']['combatants'][0],
            enemies=result['combat_state']['combatants'][1:]
        )

    except APIError as e:
        logger.error(f"Combat action failed: {e}")
        return render_template('partials/error.html', error=str(e))


@combat_bp.route('/<combat_id>/results')
@require_auth
def combat_results(combat_id: str):
    """Display combat results (victory/defeat)."""
    api_client = APIClient()

    try:
        response = api_client.get(f'/combat/{combat_id}/results')
        results = response['result']

        return render_template(
            'game/combat_results.html',
            victory=results['victory'],
            xp_gained=results['xp_gained'],
            gold_gained=results['gold_gained'],
            loot=results['loot']
        )

    except APIError as e:
        logger.error(f"Failed to load combat results: {e}")
        return redirect(url_for('game.play'))

Register blueprint in /public_web/app/__init__.py:

from app.views.combat import combat_bp
app.register_blueprint(combat_bp, url_prefix='/combat')

Acceptance Criteria:

  • Combat view loads from API
  • Action buttons submit to API
  • Combat state updates dynamically
  • Combat results shown at end
  • Errors handled gracefully

Task 3.3: Inventory UI COMPLETE

Objective: Add inventory accordion to character panel

File: /public_web/templates/game/partials/character_panel.html

Add Inventory Section:

{# Existing character panel code #}

{# Add Inventory Accordion #}
<div class="panel-accordion" data-accordion="inventory">
    <button class="panel-accordion-header" onclick="togglePanelAccordion(this)">
        <span>Inventory <span class="count">({{ character.inventory|length }}/{{ inventory_max }})</span></span>
        <span class="accordion-icon"></span>
    </button>
    <div class="panel-accordion-content">
        <div class="inventory-grid">
            {% for item in inventory %}
            <div class="inventory-item {{ item.rarity }}"
                 hx-get="/inventory/{{ character.character_id }}/item/{{ item.item_id }}"
                 hx-target="#modal-container"
                 hx-swap="innerHTML">
                <img src="{{ item.icon_url or '/static/img/items/default.png' }}" alt="{{ item.name }}">
                <span class="item-name">{{ item.name }}</span>
            </div>
            {% endfor %}
        </div>
    </div>
</div>

{# Equipment Section #}
<div class="panel-accordion" data-accordion="equipment">
    <button class="panel-accordion-header" onclick="togglePanelAccordion(this)">
        <span>Equipment</span>
        <span class="accordion-icon"></span>
    </button>
    <div class="panel-accordion-content">
        <div class="equipment-slots">
            <div class="equipment-slot">
                <label>Weapon:</label>
                {% if character.equipped.weapon %}
                <span class="equipped-item">{{ get_item_name(character.equipped.weapon) }}</span>
                <button class="btn-small"
                        hx-post="/inventory/{{ character.character_id }}/unequip"
                        hx-vals='{"slot": "weapon"}'
                        hx-target="#character-panel"
                        hx-swap="outerHTML">
                    Unequip
                </button>
                {% else %}
                <span class="empty-slot">Empty</span>
                {% endif %}
            </div>

            <div class="equipment-slot">
                <label>Helmet:</label>
                {# Similar for helmet, chest, boots, etc. #}
            </div>
        </div>
    </div>
</div>

Create /public_web/templates/game/partials/item_modal.html:

<div class="modal-overlay" onclick="closeModal()">
    <div class="modal-content" onclick="event.stopPropagation()">
        <div class="modal-header">
            <h2 class="item-name {{ item.rarity }}">{{ item.name }}</h2>
            <button class="modal-close" onclick="closeModal()">×</button>
        </div>

        <div class="modal-body">
            <p class="item-description">{{ item.description }}</p>

            <div class="item-stats">
                {% if item.item_type == 'weapon' %}
                <p><strong>Damage:</strong> {{ item.damage }}</p>
                <p><strong>Crit Chance:</strong> {{ (item.crit_chance * 100)|int }}%</p>
                {% elif item.item_type == 'armor' %}
                <p><strong>Defense:</strong> {{ item.defense }}</p>
                <p><strong>Resistance:</strong> {{ item.resistance }}</p>
                {% elif item.item_type == 'consumable' %}
                <p><strong>HP Restore:</strong> {{ item.hp_restore }}</p>
                <p><strong>MP Restore:</strong> {{ item.mp_restore }}</p>
                {% endif %}
            </div>

            <p class="item-value">Value: {{ item.value }} gold</p>
        </div>

        <div class="modal-footer">
            {% if item.item_type == 'weapon' %}
            <button class="btn btn-primary"
                    hx-post="/inventory/{{ character_id }}/equip"
                    hx-vals='{"item_id": "{{ item.item_id }}", "slot": "weapon"}'
                    hx-target="#character-panel"
                    hx-swap="outerHTML">
                Equip Weapon
            </button>
            {% elif item.item_type == 'consumable' %}
            <button class="btn btn-primary"
                    hx-post="/inventory/{{ character_id }}/use"
                    hx-vals='{"item_id": "{{ item.item_id }}"}'
                    hx-target="#character-panel"
                    hx-swap="outerHTML">
                Use Item
            </button>
            {% endif %}

            <button class="btn btn-secondary" onclick="closeModal()">Cancel</button>
        </div>
    </div>
</div>

Acceptance Criteria:

  • Inventory displays in character panel
  • Click item shows modal with details
  • Equip/unequip works via HTMX
  • Use consumable works
  • Equipment slots show equipped items

Task 3.4: Combat Testing & Polish COMPLETE

Objective: Playtest combat and fix bugs

Testing Checklist:

  • Start combat from story session

  • Turn order correct

  • Attack deals damage

  • Critical hits work

  • Effects apply and tick correctly

  • Defend action works

  • Victory awards XP/gold/loot

  • Defeat handling works

  • Combat log readable

  • HP/MP bars update

  • Multiple enemies work - would like to update to allow the player to select which enemy to attack

  • Combat state persists (refresh page)

  • Spells consume mana - unable to test

  • Items can be used in combat - unable to test

Bug Fixes & Polish:

  • Fix any calculation errors
  • Improve combat log messages
  • Add visual feedback (animations, highlights)
  • Improve mobile responsiveness
  • Add loading states

Acceptance Criteria:

  • Combat flows smoothly start to finish
  • No critical bugs
  • UX feels responsive and clear
  • Ready for real gameplay

Phase 4B: Skill Trees & Leveling (Week 4)

See /PHASE4b.md

Phase 4C: NPC Shop (Days 15-18)

See /PHASE4c.md

Success Criteria - Phase 4 Complete

Combat System

  • Turn-based combat works end-to-end
  • Damage calculations correct (physical, magical, critical)
  • Effects process correctly (DOT, HOT, buffs, debuffs, shields, stun)
  • Combat UI functional and responsive
  • Victory awards XP, gold, loot
  • Combat state persists

Inventory System

  • Inventory displays in UI
  • Equip/unequip items works
  • Consumables can be used
  • Equipment affects character stats
  • Item YAML data loaded correctly

Skill Trees

  • Visual skill tree UI works
  • Prerequisites enforced
  • Unlock skills with skill points
  • Respec functionality works
  • Stat bonuses apply immediately

Leveling

  • XP awarded after combat
  • Level up triggers at threshold
  • Skill points granted on level up
  • Level up modal shown
  • Character stats increase

NPC Shop

  • Shop inventory displays
  • Purchase validation works
  • Items added to inventory
  • Gold deducted correctly
  • Transactions logged

Next Steps After Phase 4

Once Phase 4 is complete, you'll have a fully playable combat game with progression. The next logical phases are:

Phase 5: Story Progression & Quests (Original Phase 4 from roadmap)

  • AI-driven story progression
  • Action prompts (button-based gameplay)
  • Quest system (YAML-driven, context-aware)
  • Full gameplay loop: Explore → Combat → Quests → Level Up

Phase 6: Multiplayer Sessions

  • Invite-based co-op
  • Time-limited sessions
  • AI-generated campaigns

Phase 7: Marketplace & Economy

  • Player-to-player trading
  • Auction system
  • Economy balancing

Appendix: Testing Strategy

Manual Testing Checklist

Combat:

  • Start combat from story
  • Turn order correct
  • Attack deals damage
  • Spells work
  • Items usable in combat
  • Defend action
  • Victory conditions
  • Defeat handling

Inventory:

  • Add items
  • Remove items
  • Equip weapons
  • Equip armor
  • Use consumables
  • Inventory UI updates

Skills:

  • View skill trees
  • Unlock skills
  • Prerequisites enforced
  • Stat bonuses apply
  • Respec works

Shop:

  • Browse inventory
  • Purchase items
  • Insufficient gold handling
  • Transaction logging

Document Maintenance

Update this document as you complete tasks:

  • Mark tasks complete with
  • Add notes about implementation decisions
  • Update time estimates based on actual progress
  • Document any blockers or challenges

Good luck with Phase 4 implementation! 🚀