| import json |
| import random |
| from dataclasses import dataclass, field, asdict |
|
|
| @dataclass |
| class ConflictEvent: |
| id: str |
| title: str |
| story: str |
| primary_disruption: dict |
| decisions_required: list[str] |
| resource_budget: dict |
| difficulty: int |
|
|
| TEMPLATES = [ |
| |
| ConflictEvent( |
| id="d1_gym", |
| title="The Slump", |
| story="You haven't seen the inside of a gym in ten days. Your energy is flagging and your favorite jeans feel tight.", |
| primary_disruption={"physical_health.fitness": -15.0}, |
| decisions_required=["Wake up early for a run", "Join a weekend boot camp", "Ignore it and rest"], |
| resource_budget={"time": 4.0, "money": 0.0, "energy": 20.0}, |
| difficulty=1 |
| ), |
| ConflictEvent( |
| id="d1_bill", |
| title="Forgotten Invoice", |
| story="A late notice arrived for your electricity bill. It's not a lot, but the late fee is annoying.", |
| primary_disruption={"finances.liquidity": -20.0}, |
| decisions_required=["Pay it now", "Call to dispute the fee", "Set up autopay for next time"], |
| resource_budget={"time": 1.0, "money": 100.0, "energy": 5.0}, |
| difficulty=1 |
| ), |
| ConflictEvent( |
| id="d1_argument", |
| title="Heated Group Chat", |
| story="A minor political disagreement in the group chat turned personal. Everyone is being quiet now.", |
| primary_disruption={"relationships.social": -20.0}, |
| decisions_required=["Apologize to the group", "Message the friend privately", "Mute the chat for a week"], |
| resource_budget={"time": 2.0, "money": 30.0, "energy": 15.0}, |
| difficulty=1 |
| ), |
|
|
| |
| ConflictEvent( |
| id="d2_project", |
| title="The Surge", |
| story="Your boss just walked by and dropped a 'small favor' on your desk. It looks like it'll take ten hours.", |
| primary_disruption={"career.workload": 25.0, "time.free_hours_per_week": -20.0}, |
| decisions_required=["Work late all week", "Delegate parts to a junior", "Refuse the assignment"], |
| resource_budget={"time": 10.0, "money": 0.0, "energy": 40.0}, |
| difficulty=2 |
| ), |
| ConflictEvent( |
| id="d2_car", |
| title="Check Engine Light", |
| story="Your car started making a rhythmic thumping sound on the highway. The mechanic says the repair isn't cheap.", |
| primary_disruption={"finances.liquidity": -30.0, "time.commute_burden": 25.0}, |
| decisions_required=["Repair it immediately", "Take the bus for a week", "Borrow a car from a friend"], |
| resource_budget={"time": 5.0, "money": 500.0, "energy": 10.0}, |
| difficulty=2 |
| ), |
| ConflictEvent( |
| id="d2_neglect", |
| title="Cold Dinner", |
| story="Your partner mentions they feel like 'roommates' lately. You realize you haven't had a real conversation in weeks.", |
| primary_disruption={"relationships.romantic": -25.0, "mental_wellbeing.stress_level": 20.0}, |
| decisions_required=["Plan a surprise date", "Have a long talk tonight", "Buy a thoughtful gift"], |
| resource_budget={"time": 6.0, "money": 150.0, "energy": 30.0}, |
| difficulty=2 |
| ), |
|
|
| |
| ConflictEvent( |
| id="d3_interview", |
| title="The Opportunity", |
| story="An old contact reached out for a dream job interview. You need to prep while keeping your current job afloat.", |
| primary_disruption={"career.workload": 20.0, "time.free_hours_per_week": -15.0, "mental_wellbeing.stress_level": 20.0}, |
| decisions_required=["Intensive weekend prep", "Fake a sick day to interview", "Turn it down to stay stable"], |
| resource_budget={"time": 12.0, "money": 50.0, "energy": 50.0}, |
| difficulty=3 |
| ), |
| ConflictEvent( |
| id="d3_family", |
| title="Family SOS", |
| story="Your sibling is going through a rough patch and needs help moving out and some financial support.", |
| primary_disruption={"relationships.family": 20.0, "time.free_hours_per_week": -25.0, "finances.liquidity": -20.0}, |
| decisions_required=["Spend the weekend helping", "Send them money but stay home", "Help them find other movers"], |
| resource_budget={"time": 15.0, "money": 400.0, "energy": 60.0}, |
| difficulty=3 |
| ), |
| ConflictEvent( |
| id="d3_health", |
| title="The Warning Sign", |
| story="You had a fainting spell at the office. Tests are expensive, and doctors say you need immediate change.", |
| primary_disruption={"physical_health.energy": -30.0, "mental_wellbeing.stress_level": 30.0, "finances.liquidity": -40.0}, |
| decisions_required=["Take a week of medical leave", "Consult a high-end specialist", "Change diet and sleep habits"], |
| resource_budget={"time": 20.0, "money": 800.0, "energy": 5.0}, |
| difficulty=3 |
| ), |
|
|
| |
| ConflictEvent( |
| id="d4_review", |
| title="Judgment Day", |
| story="A major performance review is in three days. Rumors of layoffs are circulating and the atmosphere is tense.", |
| primary_disruption={"career.workload": 30.0, "mental_wellbeing.stress_level": 25.0, "relationships.romantic": -15.0, "time.free_hours_per_week": -20.0}, |
| decisions_required=["Pull all-nighters to prove worth", "Start networking for new roles", "Draft a defensive report"], |
| resource_budget={"time": 18.0, "money": 0.0, "energy": 80.0}, |
| difficulty=4 |
| ), |
| ConflictEvent( |
| id="d4_move", |
| title="The Big Relocation", |
| story="You've decided to move across the country for growth. The logistics are a nightmare and friends are sad to see you go.", |
| primary_disruption={"finances.liquidity": -50.0, "relationships.social": -30.0, "career.growth_trajectory": 20.0, "time.admin_overhead": 30.0}, |
| decisions_required=["Hire full-service movers", "Host a series of farewell dinners", "DIY pack everything"], |
| resource_budget={"time": 30.0, "money": 1500.0, "energy": 100.0}, |
| difficulty=4 |
| ), |
| ConflictEvent( |
| id="d4_audit", |
| title="Tax Audit", |
| story="The IRS has flagged your last three years of returns. You need to dig through thousands of documents while paying a CPA.", |
| primary_disruption={"finances.long_term_health": -20.0, "mental_wellbeing.stress_level": 30.0, "time.admin_overhead": 40.0, "finances.liquidity": -15.0}, |
| decisions_required=["Spend nights scanning receipts", "Hire a tax lawyer", "Try to settle immediately"], |
| resource_budget={"time": 25.0, "money": 1000.0, "energy": 40.0}, |
| difficulty=4 |
| ), |
|
|
| |
| ConflictEvent( |
| id="d5_friday", |
| title="Friday 6PM", |
| story="Your flight just got cancelled. Your card declined trying to rebook. Your boss moved Monday deadline to Sunday.", |
| primary_disruption={"career.workload": 35.0, "finances.liquidity": -40.0, "mental_wellbeing.stress_level": 30.0, "time.free_hours_per_week": -25.0}, |
| decisions_required=["Book a bus and work on it", "Call boss to negotiate", "Crash at a nearby friend's"], |
| resource_budget={"time": 10.0, "money": 500.0, "energy": 60.0}, |
| difficulty=5 |
| ), |
| ConflictEvent( |
| id="d5_storm", |
| title="The Perfect Storm", |
| story="Your firm lost its biggest client, your partner moved out, and your car got towed—all on the same Tuesday.", |
| primary_disruption={"career.stability": -30.0, "relationships.romantic": -25.0, "finances.debt_pressure": 35.0, "physical_health.energy": -25.0}, |
| decisions_required=["Find an emergency side hustle", "Beg partner for a second chance", "Take a mental health day"], |
| resource_budget={"time": 8.0, "money": 200.0, "energy": 20.0}, |
| difficulty=5 |
| ), |
| ConflictEvent( |
| id="d5_burnout", |
| title="The Total Collapse", |
| story="You can't get out of bed. Your body has quit, your motivation is gone, and work emails are piling into the hundreds.", |
| primary_disruption={"mental_wellbeing.motivation": -40.0, "physical_health.sleep_quality": -30.0, "career.satisfaction": -35.0, "relationships.family": -20.0}, |
| decisions_required=["Request indefinite medical leave", "Disconnect all electronics", "Let it all burn and sleep"], |
| resource_budget={"time": 40.0, "money": 2000.0, "energy": 0.0}, |
| difficulty=5 |
| ), |
|
|
| |
| ConflictEvent( |
| id="d1_flat_tyre", |
| title="Flat Tyre", |
| story="Your bike tyre went flat halfway to work. You're going to be late to a team standup.", |
| primary_disruption={"time.commute_burden": 20.0, "mental_wellbeing.stress_level": 10.0}, |
| decisions_required=["Call a cab", "Lock the bike and walk", "Ask to dial into the standup"], |
| resource_budget={"time": 2.0, "money": 30.0, "energy": 15.0}, |
| difficulty=1 |
| ), |
| ConflictEvent( |
| id="d2_train_delay", |
| title="Train Delay", |
| story="Your morning train is delayed 90 minutes due to a signal failure. You have a 9 AM client meeting.", |
| primary_disruption={"time.commute_burden": 30.0, "career.workload": 15.0, "mental_wellbeing.stress_level": 15.0}, |
| decisions_required=["Dial in remotely", "Take a rideshare", "Reschedule the meeting"], |
| resource_budget={"time": 3.0, "money": 80.0, "energy": 20.0}, |
| difficulty=2 |
| ), |
| ConflictEvent( |
| id="d3_car_breakdown", |
| title="Breakdown on the Highway", |
| story="Your car engine seized on the freeway during rush hour. Tow + rental = $400 minimum.", |
| primary_disruption={"finances.liquidity": -35.0, "time.commute_burden": 40.0, "mental_wellbeing.stress_level": 20.0}, |
| decisions_required=["Rent a replacement car", "Rideshare all week", "Borrow from a friend"], |
| resource_budget={"time": 6.0, "money": 500.0, "energy": 30.0}, |
| difficulty=3 |
| ), |
| ConflictEvent( |
| id="d4_rideshare_surge", |
| title="Surge Pricing Nightmare", |
| story="A major event cancelled all transit. Rideshares are 9x surge. You're presenting in 2 hours.", |
| primary_disruption={"finances.liquidity": -50.0, "mental_wellbeing.stress_level": 30.0, "time.free_hours_per_week": -10.0}, |
| decisions_required=["Pay the surge", "Organise a carpool", "Present remotely"], |
| resource_budget={"time": 4.0, "money": 200.0, "energy": 40.0}, |
| difficulty=4 |
| ), |
| ConflictEvent( |
| id="d5_transit_strike", |
| title="City-Wide Transit Strike", |
| story="All buses, trains, and rideshares are on indefinite strike. Your car is in the shop.", |
| primary_disruption={"time.commute_burden": 50.0, "finances.liquidity": -30.0, "career.workload": 20.0, "mental_wellbeing.stress_level": 25.0}, |
| decisions_required=["Negotiate remote work for the week", "Rent an e-bike/scooter", "Crash at a colleague's place"], |
| resource_budget={"time": 15.0, "money": 400.0, "energy": 50.0}, |
| difficulty=5 |
| ), |
| ] |
|
|
| def generate_conflict(difficulty: int = None) -> ConflictEvent: |
| if difficulty: |
| pool = [t for t in TEMPLATES if t.difficulty == difficulty] |
| else: |
| pool = TEMPLATES |
| return random.choice(pool) |
|
|
| def escalate_conflict(conflict: ConflictEvent) -> ConflictEvent: |
| new_disruption = {k: v * 1.4 for k, v in conflict.primary_disruption.items()} |
| new_budget = {k: v * 0.7 for k, v in conflict.resource_budget.items()} |
| new_difficulty = min(5, conflict.difficulty + 1) |
| |
| return ConflictEvent( |
| id=f"{conflict.id}_escalated", |
| title=f"ESCALATED: {conflict.title}", |
| story=f"Current situation just got much worse. {conflict.story}", |
| primary_disruption=new_disruption, |
| decisions_required=conflict.decisions_required, |
| resource_budget=new_budget, |
| difficulty=new_difficulty |
| ) |
|
|
| def adaptive_escalate(conflict: ConflictEvent, agent_history: list) -> tuple: |
| """Decide whether to escalate, ease, or hold based on past performance. |
| |
| Args: |
| conflict: Current conflict event. |
| agent_history: List of (conflict_id, reward) tuples from past episodes. |
| |
| Returns: |
| (new_conflict, reason): Updated conflict and a human-readable reason string. |
| """ |
| |
| from collections import defaultdict |
| by_type = defaultdict(list) |
| for cid, reward in agent_history: |
| base_id = cid.replace("_escalated", "") |
| by_type[base_id].append(reward) |
| |
| base_id = conflict.id.replace("_escalated", "") |
| past = by_type.get(base_id, []) |
| |
| if len(past) >= 3: |
| avg = sum(past) / len(past) |
| if avg > 0.7: |
| |
| escalated = escalate_conflict(conflict) |
| return escalated, f"Agent averaged {avg:.2f} on {base_id} ({len(past)} runs) — escalating" |
| elif avg < 0.4: |
| |
| new_diff = max(1, conflict.difficulty - 1) |
| eased = generate_conflict(difficulty=new_diff) |
| return eased, f"Agent averaged {avg:.2f} on {base_id} ({len(past)} runs) — easing to difficulty {new_diff}" |
| |
| |
| return conflict, "insufficient history — holding" |
|
|
| def save_templates(): |
| import os |
| data_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "data", "conflicts.json") |
| with open(data_path, 'w') as f: |
| json.dump([asdict(t) for t in TEMPLATES], f, indent=4) |
| print(f"Saved 15 templates to {data_path}") |
|
|
| def main(): |
| save_templates() |
| print("\n--- GENERATED CONFLICT SAMPLES ---") |
| for d in range(1, 6): |
| c = generate_conflict(d) |
| print(f"\n[DIFFICULTY {d}] {c.title}") |
| print(f"Story: {c.story}") |
| print(f"Primary Disruption: {c.primary_disruption}") |
| print(f"Resource Budget: {c.resource_budget}") |
|
|
| if __name__ == "__main__": |
| main() |
|
|
| from core.task import Task, Route, ExoEvent, Milestone |
|
|
| class TaskGenerator: |
| def generate(self, domain: str = None, difficulty: int = None) -> Task: |
| diff = difficulty or 3 |
| if domain == "transport_crisis": |
| return self.generate_transport_crisis(diff) |
| elif domain == "flight_crisis": |
| return self.generate_flight_crisis(diff) |
| elif domain == "code_merge_crisis": |
| return self.generate_code_merge_crisis(diff) |
| elif domain == "career": |
| return self.generate_career(diff) |
| elif domain == "finances": |
| return self.generate_finances(diff) |
| elif domain == "relationships": |
| return self.generate_relationships(diff) |
| elif domain == "physical_health": |
| return self.generate_physical_health(diff) |
| elif domain == "mental_wellbeing": |
| return self.generate_mental_wellbeing(diff) |
| elif domain == "time": |
| return self.generate_time(diff) |
| else: |
| return self.generate_transport_crisis(diff) |
|
|
| |
| def generate_transport_crisis(self, difficulty: int) -> Task: |
| """Randomly choose one of 5 real-world transport disruption modes.""" |
| return random.choice([ |
| self.generate_flight_crisis, |
| self.generate_train_delay, |
| self.generate_car_breakdown, |
| self.generate_rideshare_surge, |
| self.generate_transit_strike, |
| ])(difficulty) |
|
|
| def generate_train_delay(self, difficulty: int) -> Task: |
| routes = [ |
| Route(id="dial_in", name="Dial In Remotely", description="Join the meeting via video call from the station.", required_action_types=["communicate"], preconditions={}, consequences={"meeting_attended": True}, closes_routes=["rideshare"], milestones_unlocked=["m1"], final_reward=2.0), |
| Route(id="rideshare", name="Take a Rideshare", description="Pay for a cab/rideshare and make it there in time.", required_action_types=["spend", "communicate"], preconditions={}, consequences={"arrived_on_time": True}, closes_routes=["dial_in"], milestones_unlocked=["m2"], final_reward=2.5), |
| Route(id="reschedule", name="Reschedule the Meeting", description="Negotiate a new meeting time with all parties.", required_action_types=["communicate"], preconditions={}, consequences={"meeting_rescheduled": True}, closes_routes=[], milestones_unlocked=["m3"], final_reward=1.5), |
| ] |
| milestones = [ |
| Milestone(id="m1", description="Meeting attended on time remotely.", condition_key="meeting_attended", condition_value=True, reward=1.0), |
| Milestone(id="m2", description="Made it to the office despite the delay.", condition_key="arrived_on_time", condition_value=True, reward=1.5), |
| Milestone(id="m3", description="Meeting rescheduled without relationship cost.", condition_key="meeting_rescheduled", condition_value=True, reward=0.8), |
| ] |
| events = [ |
| ExoEvent(step=2, probability=0.8, id="delay_extended", description="Train delay extended by another 45 minutes.", world_mutation={}, hidden_state_mutation={}, closes_routes=[]), |
| ExoEvent(step=4, probability=0.6, id="rideshare_surge", description="Rideshares now showing 3x surge pricing.", world_mutation={}, hidden_state_mutation={}, closes_routes=[]), |
| ] |
| return Task( |
| id="train_delay_task", domain="transport_crisis", goal="Navigate Train Delay Crisis", |
| constraints={"budget_max": 150, "deadline_step": 8}, |
| hidden_state={"platform_reassigned": False}, |
| mutable_world={"time.commute_burden": 30.0, "mental_wellbeing.stress_level": 15.0}, |
| visible_world={"time.commute_burden": 30.0, "mental_wellbeing.stress_level": 15.0}, |
| success_conditions=[{"key": "meeting_attended", "value": True}, {"key": "arrived_on_time", "value": True}, {"key": "meeting_rescheduled", "value": True}], |
| failure_conditions=[{"key": "finances.liquidity", "value": 10.0, "op": "lt"}], |
| event_schedule=events, viable_routes=routes, milestones=milestones, |
| horizon=12 + difficulty * 2, difficulty=difficulty, |
| domain_metadata={"story": "Signal failure has brought the entire line to a halt.", "transport_mode": "train"} |
| ) |
|
|
| def generate_car_breakdown(self, difficulty: int) -> Task: |
| routes = [ |
| Route(id="rent_car", name="Rent a Replacement Car", description="Call a rental agency and get mobile again.", required_action_types=["spend", "communicate"], preconditions={}, consequences={"mobile": True}, closes_routes=[], milestones_unlocked=["m1"], final_reward=2.5), |
| Route(id="rideshare_week", name="Rideshare for the Week", description="Use rideshares until the car is repaired.", required_action_types=["spend"], preconditions={}, consequences={"transport_sorted": True}, closes_routes=["rent_car"], milestones_unlocked=["m2"], final_reward=1.5), |
| Route(id="borrow_car", name="Borrow a Friend's Car", description="Call around and borrow a vehicle.", required_action_types=["communicate"], preconditions={}, consequences={"borrowed": True}, closes_routes=[], milestones_unlocked=["m3"], final_reward=2.0), |
| ] |
| milestones = [ |
| Milestone(id="m1", description="Replacement vehicle secured.", condition_key="mobile", condition_value=True, reward=1.5), |
| Milestone(id="m2", description="Transport plan for the week sorted.", condition_key="transport_sorted", condition_value=True, reward=1.0), |
| Milestone(id="m3", description="Vehicle borrowed without relationship cost.", condition_key="borrowed", condition_value=True, reward=1.2), |
| ] |
| events = [ |
| ExoEvent(step=2, probability=1.0, id="repair_estimate", description="Mechanic confirms repair takes 3–5 days, not 1.", world_mutation={}, hidden_state_mutation={}, closes_routes=[]), |
| ExoEvent(step=5, probability=0.7, id="rental_shortage", description="Rental agencies report no compact cars available.", world_mutation={}, hidden_state_mutation={}, closes_routes=["rent_car"]), |
| ] |
| return Task( |
| id="car_breakdown_task", domain="transport_crisis", goal="Recover from Car Breakdown", |
| constraints={"budget_max": 500, "deadline_step": 10}, |
| hidden_state={"tow_dispatched": False}, |
| mutable_world={"finances.liquidity": -35.0, "time.commute_burden": 40.0}, |
| visible_world={"finances.liquidity": -35.0, "time.commute_burden": 40.0}, |
| success_conditions=[{"key": "mobile", "value": True}, {"key": "transport_sorted", "value": True}, {"key": "borrowed", "value": True}], |
| failure_conditions=[{"key": "finances.liquidity", "value": 0.0, "op": "le"}], |
| event_schedule=events, viable_routes=routes, milestones=milestones, |
| horizon=14 + difficulty * 2, difficulty=difficulty, |
| domain_metadata={"story": "Engine seized on the highway. Car is in the shop for days.", "transport_mode": "car"} |
| ) |
|
|
| def generate_rideshare_surge(self, difficulty: int) -> Task: |
| routes = [ |
| Route(id="pay_surge", name="Pay the Surge Price", description="Absorb the cost and get there on time.", required_action_types=["spend"], preconditions={}, consequences={"arrived": True}, closes_routes=["remote"], milestones_unlocked=["m1"], final_reward=2.0), |
| Route(id="carpool", name="Organise a Carpool", description="Find colleagues or strangers going the same way.", required_action_types=["communicate", "negotiate"], preconditions={}, consequences={"carpooled": True}, closes_routes=[], milestones_unlocked=["m2"], final_reward=3.0), |
| Route(id="remote", name="Present Remotely", description="Negotiate to dial in instead of attending in person.", required_action_types=["communicate"], preconditions={}, consequences={"remote_approved": True}, closes_routes=["pay_surge"], milestones_unlocked=["m3"], final_reward=1.5), |
| ] |
| milestones = [ |
| Milestone(id="m1", description="Arrived at venue on time.", condition_key="arrived", condition_value=True, reward=1.5), |
| Milestone(id="m2", description="Carpool arranged — zero cost.", condition_key="carpooled", condition_value=True, reward=2.0), |
| Milestone(id="m3", description="Remote attendance approved.", condition_key="remote_approved", condition_value=True, reward=1.0), |
| ] |
| events = [ |
| ExoEvent(step=1, probability=1.0, id="surge_spike", description="Surge jumped to 12x. All buses cancelled.", world_mutation={}, hidden_state_mutation={}, closes_routes=[]), |
| ExoEvent(step=3, probability=0.9, id="meeting_reminder", description="Organiser sends a 30-minute warning.", world_mutation={}, hidden_state_mutation={}, closes_routes=[]), |
| ] |
| return Task( |
| id="rideshare_surge_task", domain="transport_crisis", goal="Get to the Presentation on Time", |
| constraints={"budget_max": 200, "deadline_step": 6}, |
| hidden_state={}, |
| mutable_world={"finances.liquidity": -50.0, "mental_wellbeing.stress_level": 30.0}, |
| visible_world={"finances.liquidity": -50.0, "mental_wellbeing.stress_level": 30.0}, |
| success_conditions=[{"key": "arrived", "value": True}, {"key": "carpooled", "value": True}, {"key": "remote_approved", "value": True}], |
| failure_conditions=[], |
| event_schedule=events, viable_routes=routes, milestones=milestones, |
| horizon=8 + difficulty * 2, difficulty=difficulty, |
| domain_metadata={"story": "A major city event caused city-wide rideshare surge on your big presentation day.", "transport_mode": "rideshare"} |
| ) |
|
|
| def generate_transit_strike(self, difficulty: int) -> Task: |
| routes = [ |
| Route(id="wfh_negotiate", name="Negotiate Full Remote Week", description="Get manager approval to WFH for the strike duration.", required_action_types=["communicate", "negotiate"], preconditions={}, consequences={"wfh_approved": True}, closes_routes=[], milestones_unlocked=["m1"], final_reward=3.0), |
| Route(id="micromobility", name="Rent E-Bike / Scooter", description="Use micro-mobility for the week.", required_action_types=["spend"], preconditions={}, consequences={"transport_secured": True}, closes_routes=[], milestones_unlocked=["m2"], final_reward=2.0), |
| Route(id="colleague_crash",name="Crash at a Colleague's Place", description="Stay near the office temporarily.", required_action_types=["communicate"], preconditions={}, consequences={"accommodation_sorted": True}, closes_routes=[], milestones_unlocked=["m3"], final_reward=1.5), |
| ] |
| milestones = [ |
| Milestone(id="m1", description="WFH approved for the strike period.", condition_key="wfh_approved", condition_value=True, reward=2.0), |
| Milestone(id="m2", description="Micro-mobility solution in place.", condition_key="transport_secured", condition_value=True, reward=1.0), |
| Milestone(id="m3", description="Temporary accommodation sorted.", condition_key="accommodation_sorted",condition_value=True, reward=0.8), |
| ] |
| events = [ |
| ExoEvent(step=2, probability=0.9, id="strike_extended", description="Union announces the strike could last 2 weeks.", world_mutation={}, hidden_state_mutation={}, closes_routes=[]), |
| ExoEvent(step=5, probability=0.7, id="scooter_shortage", description="E-bike rental companies sold out in your area.", world_mutation={}, hidden_state_mutation={}, closes_routes=["micromobility"]), |
| ] |
| return Task( |
| id="transit_strike_task", domain="transport_crisis", goal="Survive City-Wide Transit Strike", |
| constraints={"budget_max": 400, "deadline_step": 14}, |
| hidden_state={}, |
| mutable_world={"time.commute_burden": 50.0, "mental_wellbeing.stress_level": 25.0}, |
| visible_world={"time.commute_burden": 50.0, "mental_wellbeing.stress_level": 25.0}, |
| success_conditions=[{"key": "wfh_approved", "value": True}, {"key": "transport_secured", "value": True}, {"key": "accommodation_sorted", "value": True}], |
| failure_conditions=[], |
| event_schedule=events, viable_routes=routes, milestones=milestones, |
| horizon=18 + difficulty * 2, difficulty=difficulty, |
| domain_metadata={"story": "All public transport workers walked off the job. The city is gridlocked.", "transport_mode": "transit_strike"} |
| ) |
|
|
| def generate_flight_crisis(self, difficulty: int) -> Task: |
| routes = [ |
| Route(id="rebook_premium", name="Rebook Premium Option", description="Call agent and rebook on premium ticket", required_action_types=["communicate", "spend"], preconditions={}, consequences={"flight_rebooked": True}, closes_routes=["wait_lounge"], milestones_unlocked=["m1"], final_reward=2.5), |
| Route(id="wait_lounge", name="Accept Delay & Work", description="Stay at airport lounge and work on laptop", required_action_types=["rest", "delegate"], preconditions={}, consequences={"caught_up": True}, closes_routes=["rebook_premium"], milestones_unlocked=["m2"], final_reward=1.8), |
| ] |
| milestones = [ |
| Milestone(id="m1", description="Successfully rebooked flight before deadline", condition_key="flight_rebooked", condition_value=True, reward=1.0), |
| Milestone(id="m2", description="Caught up with all emergency slack messages", condition_key="caught_up", condition_value=True, reward=0.8), |
| ] |
| events = [ |
| ExoEvent(step=2, probability=1.0, id="price_surge", description="Ticket prices sharply increased by $300.", world_mutation={}, hidden_state_mutation={}, closes_routes=[]), |
| ExoEvent(step=4, probability=1.0, id="lounge_full", description="The airport lounge is now at maximum capacity.", world_mutation={}, hidden_state_mutation={}, closes_routes=["wait_lounge"]), |
| ] |
| return Task( |
| id="flight_crisis_task", domain="flight_crisis", goal="Survive Airport Cancellation", |
| constraints={"budget_max": 800, "deadline_step": 10}, |
| hidden_state={"lounge_capacity": 100}, |
| mutable_world={"mental_wellbeing.stress_level": 25.0, "time.free_hours_per_week": -10.0}, |
| visible_world={"mental_wellbeing.stress_level": 25.0, "time.free_hours_per_week": -10.0}, |
| success_conditions=[{"key": "flight_rebooked", "value": True}, {"key": "caught_up", "value": True}], |
| failure_conditions=[], |
| event_schedule=events, viable_routes=routes, milestones=milestones, |
| horizon=15 + difficulty * 2, difficulty=difficulty, domain_metadata={"story": "A major storm grounded commercial flights."} |
| ) |
|
|
| def generate_code_merge_crisis(self, difficulty: int) -> Task: |
| routes = [ |
| Route(id="revert_commit", name="Revert Commit", description="Quickly revert the broken merge to unblock the team.", required_action_types=["delegate", "communicate"], preconditions={}, consequences={"pipeline_unblocked": True}, closes_routes=["hotfix"], milestones_unlocked=["unblocked"], final_reward=1.5), |
| Route(id="hotfix", name="Patch Forward", description="Find the logic error and push a hotfix.", required_action_types=["communicate", "spend"], preconditions={}, consequences={"bug_resolved": True}, closes_routes=["revert_commit"], milestones_unlocked=["fixed"], final_reward=3.0), |
| ] |
| milestones = [ |
| Milestone(id="unblocked", description="CI pipeline is green again", condition_key="pipeline_unblocked", condition_value=True, reward=1.0), |
| Milestone(id="fixed", description="Bug resolved without losing features", condition_key="bug_resolved", condition_value=True, reward=2.0), |
| ] |
| events = [ |
| ExoEvent(step=3, probability=0.8, id="cto_ping", description="CTO asks for an ETA on the fix.", world_mutation={}, hidden_state_mutation={}, closes_routes=[]), |
| ] |
| return Task( |
| id="code_merge_task", domain="code_merge_crisis", goal="Resolve Production Outage", |
| constraints={"budget_max": 1000, "deadline_step": 8}, |
| hidden_state={}, |
| mutable_world={"career.stability": -20.0, "mental_wellbeing.stress_level": 30.0}, |
| visible_world={"career.stability": -20.0, "mental_wellbeing.stress_level": 30.0}, |
| success_conditions=[{"key": "pipeline_unblocked", "value": True}, {"key": "bug_resolved", "value": True}], |
| failure_conditions=[], |
| event_schedule=events, viable_routes=routes, milestones=milestones, |
| horizon=10 + difficulty * 2, difficulty=difficulty, domain_metadata={"story": "A botched merge just took down the staging environment."} |
| ) |
|
|
| def generate_career(self, difficulty: int) -> Task: |
| routes = [ |
| Route(id="r1", name="Negotiate Workload", description="Discuss with manager to reduce workload.", required_action_types=["communicate"], preconditions={}, consequences={"workload_reduced": True}, closes_routes=["r2"], milestones_unlocked=["m1"], final_reward=2.0), |
| Route(id="r2", name="Find New Job", description="Start applying for new roles.", required_action_types=["spend", "communicate"], preconditions={}, consequences={"job_found": True}, closes_routes=["r1", "r3"], milestones_unlocked=["m2"], final_reward=3.0), |
| Route(id="r3", name="Delegate to Team", description="Push tasks to junior colleagues.", required_action_types=["delegate"], preconditions={}, consequences={"team_delegated": True}, closes_routes=["r2"], milestones_unlocked=["m3"], final_reward=1.5), |
| ] |
| milestones = [ |
| Milestone(id="m1", description="Manager agreed to reduce tasks.", condition_key="workload_reduced", condition_value=True, reward=1.0), |
| Milestone(id="m2", description="Interview secured.", condition_key="job_found", condition_value=True, reward=1.5), |
| Milestone(id="m3", description="Tasks successfully delegated.", condition_key="team_delegated", condition_value=True, reward=0.8), |
| ] |
| events = [ |
| ExoEvent(step=3, probability=0.7, id="boss_asks", description="Boss asks for progress on current tasks.", world_mutation={}, hidden_state_mutation={}, closes_routes=[]) |
| ] |
| return Task( |
| id="career_crisis", domain="career", goal="Manage Career Overload", constraints={"budget_max": 500, "deadline_step": 12}, |
| hidden_state={}, |
| mutable_world={"career.workload": 30.0, "time.free_hours_per_week": -20.0}, |
| visible_world={"career.workload": 30.0, "time.free_hours_per_week": -20.0}, |
| success_conditions=[{"key": "workload_reduced", "value": True}, {"key": "job_found", "value": True}, {"key": "team_delegated", "value": True}], |
| failure_conditions=[], event_schedule=events, viable_routes=routes, milestones=milestones, horizon=15 + difficulty * 2, difficulty=difficulty, domain_metadata={"story": "Severe workload is threatening your career stability."} |
| ) |
|
|
| def generate_finances(self, difficulty: int) -> Task: |
| routes = [ |
| Route(id="r1", name="Emergency Fund", description="Dip into savings.", required_action_types=["spend"], preconditions={}, consequences={"used_emergency": True}, closes_routes=[], milestones_unlocked=["m1"], final_reward=1.0), |
| Route(id="r2", name="Negotiate Payment Plan", description="Call the creditor to delay payments.", required_action_types=["communicate"], preconditions={}, consequences={"payment_plan": True}, closes_routes=["r1"], milestones_unlocked=["m2"], final_reward=2.5), |
| Route(id="r3", name="Sell Asset", description="Liquidate an asset for quick cash.", required_action_types=["communicate", "spend"], preconditions={}, consequences={"asset_sold": True}, closes_routes=["r2"], milestones_unlocked=["m3"], final_reward=1.5), |
| ] |
| milestones = [ |
| Milestone(id="m1", description="Emergency fund accessed.", condition_key="used_emergency", condition_value=True, reward=0.5), |
| Milestone(id="m2", description="Favorable payment plan negotiated.", condition_key="payment_plan", condition_value=True, reward=1.0), |
| Milestone(id="m3", description="Asset successfully sold.", condition_key="asset_sold", condition_value=True, reward=0.8), |
| ] |
| events = [ |
| ExoEvent(step=2, probability=0.9, id="late_fee", description="A late fee was applied to the balance.", world_mutation={}, hidden_state_mutation={}, closes_routes=[]) |
| ] |
| return Task( |
| id="finance_crisis", domain="finances", goal="Resolve Financial Pressure", constraints={"budget_max": 1000, "deadline_step": 10}, |
| hidden_state={}, |
| mutable_world={"finances.liquidity": -40.0, "finances.debt_pressure": 20.0}, |
| visible_world={"finances.liquidity": -40.0, "finances.debt_pressure": 20.0}, |
| success_conditions=[{"key": "used_emergency", "value": True}, {"key": "payment_plan", "value": True}, {"key": "asset_sold", "value": True}], |
| failure_conditions=[], event_schedule=events, viable_routes=routes, milestones=milestones, horizon=15 + difficulty * 2, difficulty=difficulty, domain_metadata={"story": "An unexpected expense has caused financial strain."} |
| ) |
|
|
| def generate_relationships(self, difficulty: int) -> Task: |
| routes = [ |
| Route(id="r1", name="Couples Therapy", description="Book a session with a therapist.", required_action_types=["spend", "communicate"], preconditions={}, consequences={"therapy_scheduled": True}, closes_routes=["r3"], milestones_unlocked=["m1"], final_reward=3.0), |
| Route(id="r2", name="Honest Conversation", description="Sit down and talk through issues.", required_action_types=["communicate"], preconditions={}, consequences={"had_conversation": True}, closes_routes=[], milestones_unlocked=["m2"], final_reward=2.0), |
| Route(id="r3", name="Give Space", description="Take some time apart.", required_action_types=["rest"], preconditions={}, consequences={"giving_space": True}, closes_routes=["r1", "r2"], milestones_unlocked=["m3"], final_reward=1.0), |
| ] |
| milestones = [ |
| Milestone(id="m1", description="Therapy session completed.", condition_key="therapy_scheduled", condition_value=True, reward=1.5), |
| Milestone(id="m2", description="A productive conversation occurred.", condition_key="had_conversation", condition_value=True, reward=1.0), |
| Milestone(id="m3", description="Space given without escalation.", condition_key="giving_space", condition_value=True, reward=0.5), |
| ] |
| events = [ |
| ExoEvent(step=4, probability=0.6, id="partner_escalates", description="Partner sends an emotional text msg.", world_mutation={}, hidden_state_mutation={}, closes_routes=[]) |
| ] |
| return Task( |
| id="relationship_crisis", domain="relationships", goal="Repair Relationship Friction", constraints={"budget_max": 800, "deadline_step": 14}, |
| hidden_state={}, |
| mutable_world={"relationships.romantic": -30.0, "mental_wellbeing.stress_level": 20.0}, |
| visible_world={"relationships.romantic": -30.0, "mental_wellbeing.stress_level": 20.0}, |
| success_conditions=[{"key": "therapy_scheduled", "value": True}, {"key": "had_conversation", "value": True}, {"key": "giving_space", "value": True}], |
| failure_conditions=[], event_schedule=events, viable_routes=routes, milestones=milestones, horizon=15 + difficulty * 2, difficulty=difficulty, domain_metadata={"story": "Growing distance and recent conflicts demand attention."} |
| ) |
|
|
| def generate_physical_health(self, difficulty: int) -> Task: |
| routes = [ |
| Route(id="r1", name="Medical Leave", description="Request time off to recover.", required_action_types=["communicate", "rest"], preconditions={}, consequences={"on_leave": True}, closes_routes=[], milestones_unlocked=["m1"], final_reward=2.5), |
| Route(id="r2", name="See Specialist", description="Pay for a top-tier medical consultation.", required_action_types=["spend", "communicate"], preconditions={}, consequences={"saw_doctor": True}, closes_routes=[], milestones_unlocked=["m2"], final_reward=2.0), |
| Route(id="r3", name="Lifestyle Change", description="Commit to better diet and sleep.", required_action_types=["rest"], preconditions={}, consequences={"lifestyle_changed": True}, closes_routes=["r1"], milestones_unlocked=["m3"], final_reward=1.5), |
| ] |
| milestones = [ |
| Milestone(id="m1", description="Leave approved.", condition_key="on_leave", condition_value=True, reward=1.0), |
| Milestone(id="m2", description="Clear diagnosis received.", condition_key="saw_doctor", condition_value=True, reward=1.0), |
| Milestone(id="m3", description="First week of new habits complete.", condition_key="lifestyle_changed", condition_value=True, reward=0.5), |
| ] |
| events = [ |
| ExoEvent(step=3, probability=0.8, id="doctor_call", description="The clinic calls with test results.", world_mutation={}, hidden_state_mutation={}, closes_routes=[]) |
| ] |
| return Task( |
| id="health_crisis", domain="physical_health", goal="Address Health Warning", constraints={"budget_max": 1500, "deadline_step": 15}, |
| hidden_state={}, |
| mutable_world={"physical_health.energy": -30.0, "mental_wellbeing.stress_level": 30.0}, |
| visible_world={"physical_health.energy": -30.0, "mental_wellbeing.stress_level": 30.0}, |
| success_conditions=[{"key": "on_leave", "value": True}, {"key": "saw_doctor", "value": True}, {"key": "lifestyle_changed", "value": True}], |
| failure_conditions=[], event_schedule=events, viable_routes=routes, milestones=milestones, horizon=15 + difficulty * 2, difficulty=difficulty, domain_metadata={"story": "Physical symptoms are becoming impossible to ignore."} |
| ) |
|
|
| def generate_mental_wellbeing(self, difficulty: int) -> Task: |
| routes = [ |
| Route(id="r1", name="Professional Therapy", description="Start regular therapy sessions.", required_action_types=["spend", "communicate"], preconditions={}, consequences={"therapy_started": True}, closes_routes=[], milestones_unlocked=["m1"], final_reward=3.0), |
| Route(id="r2", name="Disconnect", description="Take a full digital detox break.", required_action_types=["rest"], preconditions={}, consequences={"disconnected": True}, closes_routes=["r3"], milestones_unlocked=["m2"], final_reward=1.5), |
| Route(id="r3", name="Medication Evaluation", description="See a psychiatrist for options.", required_action_types=["spend"], preconditions={}, consequences={"medication_taken": True}, closes_routes=["r2"], milestones_unlocked=["m3"], final_reward=2.0), |
| ] |
| milestones = [ |
| Milestone(id="m1", description="Meaningful breakthrough in therapy.", condition_key="therapy_started", condition_value=True, reward=1.5), |
| Milestone(id="m2", description="Successfully unplugged for 48 hours.", condition_key="disconnected", condition_value=True, reward=0.8), |
| Milestone(id="m3", description="Prescription acquired.", condition_key="medication_taken", condition_value=True, reward=1.0), |
| ] |
| events = [ |
| ExoEvent(step=2, probability=0.5, id="panic_attack", description="A sudden wave of severe anxiety hits.", world_mutation={}, hidden_state_mutation={}, closes_routes=[]) |
| ] |
| return Task( |
| id="mental_crisis", domain="mental_wellbeing", goal="Avert Total Burnout", constraints={"budget_max": 600, "deadline_step": 12}, |
| hidden_state={}, |
| mutable_world={"mental_wellbeing.motivation": -35.0, "mental_wellbeing.stress_level": 40.0}, |
| visible_world={"mental_wellbeing.motivation": -35.0, "mental_wellbeing.stress_level": 40.0}, |
| success_conditions=[{"key": "therapy_started", "value": True}, {"key": "disconnected", "value": True}, {"key": "medication_taken", "value": True}], |
| failure_conditions=[], event_schedule=events, viable_routes=routes, milestones=milestones, horizon=15 + difficulty * 2, difficulty=difficulty, domain_metadata={"story": "Complete exhaustion and loss of motivation."} |
| ) |
|
|
| def generate_time(self, difficulty: int) -> Task: |
| routes = [ |
| Route(id="r1", name="Reprioritize", description="Restructure calendar and say 'no'.", required_action_types=["communicate"], preconditions={}, consequences={"priorities_reset": True}, closes_routes=[], milestones_unlocked=["m1"], final_reward=2.0), |
| Route(id="r2", name="Delegate", description="Pay someone or ask for help with chores.", required_action_types=["spend", "delegate"], preconditions={}, consequences={"tasks_delegated": True}, closes_routes=[], milestones_unlocked=["m2"], final_reward=1.5), |
| Route(id="r3", name="Cancel Commitments", description="Drop out of major upcoming events.", required_action_types=["communicate"], preconditions={}, consequences={"commitments_cancelled": True}, closes_routes=["r1"], milestones_unlocked=["m3"], final_reward=1.0), |
| ] |
| milestones = [ |
| Milestone(id="m1", description="Calendar cleared of non-essentials.", condition_key="priorities_reset", condition_value=True, reward=1.0), |
| Milestone(id="m2", description="Help secured for daily tasks.", condition_key="tasks_delegated", condition_value=True, reward=0.8), |
| Milestone(id="m3", description="Social obligations cancelled.", condition_key="commitments_cancelled", condition_value=True, reward=0.5), |
| ] |
| events = [ |
| ExoEvent(step=3, probability=0.9, id="new_request", description="A friend asks for an 'urgent' favor.", world_mutation={}, hidden_state_mutation={}, closes_routes=[]) |
| ] |
| return Task( |
| id="time_crisis", domain="time", goal="Regain Time Control", constraints={"budget_max": 300, "deadline_step": 10}, |
| hidden_state={}, |
| mutable_world={"time.free_hours_per_week": -25.0, "time.admin_overhead": 20.0}, |
| visible_world={"time.free_hours_per_week": -25.0, "time.admin_overhead": 20.0}, |
| success_conditions=[{"key": "priorities_reset", "value": True}, {"key": "tasks_delegated", "value": True}, {"key": "commitments_cancelled", "value": True}], |
| failure_conditions=[], event_schedule=events, viable_routes=routes, milestones=milestones, horizon=15 + difficulty * 2, difficulty=difficulty, domain_metadata={"story": "You are double-booked and drowning in obligations."} |
| ) |
|
|