"""
Calibrated Monte Carlo simulation test for Level Progression in FreeExile.
Conditions:
  - 1000 players per cohort or across diverse play styles
  - 90 days season
  - 5 hours/day
  - 15 maps/hour (4 min/map) -> 75 maps/day -> 6,750 maps per season
  - Death rates tested: 0.0%, 0.1%, 0.5%, 1.0%, 2.0% per map
  - Tiered Death Penalty:
      Levels 1-60: 0%
      Levels 61-80: 5%
      Levels 81-89: 10%
      Levels 90-99: 15%
      Level 99->100: 25% (floor at 0% of current level, no de-leveling)
"""

import sys
import os
import random

sys.path.insert(0, os.path.dirname(__file__))
from scratch_curve_explorer import generate_curve

def run_calibrated_simulation():
    delta_exp = generate_curve()
    
    # 75 maps/day * 90 days = 6750 maps
    # Calibrate maps required per bracket for deathless player:
    # Levels 1-60 (Campaign): ~600 maps (8 days)
    # Levels 61-80 (T1-T10 White/Yellow Maps): ~1200 maps (16 days)
    # Levels 81-90 (T11-T13 Early Red Maps): ~1200 maps (16 days)
    # Levels 90-99 (T14-T16 Late Red Maps): ~1875 maps (25 days)
    # Level 99->100 (Hardcore Soft-Wall): ~1500 maps (20 days)
    # Total for 100% deathless = 6375 maps = 85.0 days!
    
    bracket_maps = {
        '1-60': 600,
        '61-80': 1200,
        '81-90': 1200,
        '90-99': 1875,
        '99-100': 1500,
    }
    
    cohorts = [0.000, 0.0005, 0.001, 0.005, 0.010, 0.020]
    num_players = 200
    days = 90
    maps_per_day = 75
    
    print("\n" + "="*80)
    print(f"MONTE CARLO LEVEL PROGRESSION SIMULATION (90 Days, 5 hrs/day, 75 maps/day)")
    print("="*80)
    
    for p_death in cohorts:
        reached_100_count = 0
        days_to_100 = []
        final_levels = []
        
        for player in range(num_players):
            level = 1
            current_xp = 0
            reached_100_day = None
            
            for day in range(1, days + 1):
                if level >= 100:
                    break
                for m in range(maps_per_day):
                    if level >= 100:
                        if reached_100_day is None:
                            reached_100_day = day
                        break
                        
                    req_xp = delta_exp[level]
                    if level < 60:
                        map_xp = req_xp / (bracket_maps['1-60'] / 59)
                    elif level < 80:
                        map_xp = req_xp / (bracket_maps['61-80'] / 20)
                    elif level < 90:
                        map_xp = req_xp / (bracket_maps['81-90'] / 10)
                    elif level < 99:
                        map_xp = req_xp / (bracket_maps['90-99'] / 9)
                    else: # level 99 -> 100
                        map_xp = req_xp / bracket_maps['99-100']
                        
                    # Check death
                    if random.random() < p_death:
                        if level <= 60:
                            pct = 0.0
                        elif level <= 80:
                            pct = 0.05
                        elif level <= 89:
                            pct = 0.10
                        elif level < 99:
                            pct = 0.15
                        else:
                            pct = 0.25
                        current_xp = max(0, current_xp - req_xp * pct)
                    else:
                        current_xp += map_xp
                        while level < 100 and current_xp >= delta_exp[level]:
                            current_xp -= delta_exp[level]
                            level += 1
                            if level == 100:
                                if reached_100_day is None:
                                    reached_100_day = day
                                break
                                
            final_progress = level + (current_xp / delta_exp[min(level, 99)] if level < 100 else 0)
            final_levels.append(final_progress)
            if level >= 100:
                reached_100_count += 1
                days_to_100.append(reached_100_day)
                
        avg_final = sum(final_levels) / len(final_levels)
        pct_100 = (reached_100_count / num_players) * 100
        avg_days = f"{sum(days_to_100) / len(days_to_100):.1f} days" if days_to_100 else "N/A"
        min_days = f"{min(days_to_100)} days" if days_to_100 else "N/A"
        
        print(f"Cohort p_death={p_death*100:5.2f}% | Reach Lv100: {reached_100_count:3d}/{num_players} ({pct_100:5.1f}%) | Avg Level: {avg_final:6.2f} | Avg Completion: {avg_days} (Fastest: {min_days})")

if __name__ == '__main__':
    random.seed(42)
    run_calibrated_simulation()
