■ 🕑 1. Trails In Sky Combat Emu - Procedural
│ #!/usr/bin/env python3
│ """
│ Trails in the Sky - Procedural Combat Timeline Engine with Persistent Event Labels
│ """
│ import os
│ import sys
│ import time
│ import random
│
│ # === EVENT TYPES ===
│ TYPE_CHARACTER = 0 # Player character taking action
│ TYPE_ENEMY = 1 # Enemy AI taking action
│ TYPE_SPELL_RESOLVE = 2 # Spell resolves after cast delay
│ TYPE_STATUS_EXPIRE = 4 # Status effect ends
│ TYPE_PLAYER_INPUT = 5 # Wait for player input before proceeding
│
│ # === STATUS EFFECTS COLORS ===
│ STATUS_COLORS = {
│ "Casting": "\033[37m", # Light grey / off-white
│ "Poisoned": "\033[95m", # Purple
│ "Burning": "\033[91m", # Red
│ "Slowed": "\033[94m", # Blue
│ "Haste": "\033[92m", # Green
│ "Muted": "\033[93m", # Yellow
│ "Dead": "\033[90m" # Gray
│ }
│ RESET_COLOR = "\033[0m"
│
│ # === LABEL POOL (1-9,a-z,A-Z) ===
│ label_pool = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
│ label_counter = 0
│
│ def get_label():
│ """Get next label in the cyclic pool"""
│ global label_counter
│ label = label_pool[label_counter % len(label_pool)]
│ label_counter += 1
│ return label
│
│ # === DATA STRUCTURES ===
│ def create_character(name, hp, ep, cp, atk, defense, speed, mov, is_player=False):
│ """Create a new character dictionary with persistent label"""
│ return {
│ 'name': name,
│ 'hp': hp,
│ 'max_hp': hp,
│ 'ep': ep,
│ 'cp': cp,
│ 'atk': atk,
│ 'defense': defense,
│ 'speed': speed,
│ 'mov': mov,
│ 'is_player': is_player,
│ 'alive': True,
│ 'status_effects': [],
│ 'next_action_time': 0,
│ 'orbment': [4, 2, 0, 1, 1, 0, 0], # Fire, Water, Earth, Wind, Time, Space, Mirage
│ 'label': get_label()
│ }
│
│ def create_spell_resolve_event(caster_id, target_id, spell_name, resolve_time):
│ """Create a spell resolve event with persistent label"""
│ return {
│ 'name': f"{spell_name} ({caster_id}→{target_id})",
│ 'next_action_time': resolve_time,
│ 'caster_id': caster_id,
│ 'target_id': target_id,
│ 'spell_name': spell_name,
│ 'type': TYPE_SPELL_RESOLVE,
│ 'label': get_label()
│ }
│
│ def create_status_expire_event(target_id, effect_name, expire_time):
│ """Create a status expiration event with persistent label"""
│ return {
│ 'name': f"{effect_name} expires",
│ 'next_action_time': expire_time,
│ 'target_id': target_id,
│ 'effect_name': effect_name,
│ 'type': TYPE_STATUS_EXPIRE,
│ 'label': get_label()
│ }
│
│ # === UTILITY FUNCTIONS ===
│ def get_terminal_size():
│ try:
│ return os.get_terminal_size()
│ except:
│ return type('obj', (object,), {'columns': 80, 'lines': 24})
│
│ def clear_screen():
│ os.system('cls' if os.name == 'nt' else 'clear')
│
│ def format_time(time_val):
│ return f"{time_val:08d}"
│
│ def is_valid_participant(p):
│ """Check if participant should be displayed on timeline"""
│ if isinstance(p, dict):
│ if p.get('type') == TYPE_STATUS_EXPIRE:
│ return p['next_action_time'] > global_time
│ return p.get('alive', True) or p.get('type') in [TYPE_SPELL_RESOLVE]
│ return False
│
│ def get_status_color_for(event):
│ """Determine color based on spell name, status expiration, or character status"""
│ if isinstance(event, dict):
│ # Spell Resolve: check spell name
│ if event.get('type') == TYPE_SPELL_RESOLVE:
│ if event['spell_name'] == "Burn":
│ return STATUS_COLORS["Burning"]
│ elif event['spell_name'] == "Poison":
│ return STATUS_COLORS["Poisoned"]
│ elif event['spell_name'] == "Heal":
│ return STATUS_COLORS["Haste"]
│
│ # Status Expire: use the status name
│ elif event.get('type') == TYPE_STATUS_EXPIRE:
│ effect_name = event.get('effect_name', '')
│ return STATUS_COLORS.get(effect_name, "")
│
│ # Character: check their status effects
│ elif 'status_effects' in event:
│ for se in event['status_effects']:
│ if se['name'] in STATUS_COLORS:
│ return STATUS_COLORS[se['name']]
│ return ""
│
│ # === STATUS EFFECTS ===
│ def apply_status_effect(target, effect_name, duration, on_apply=None, on_tick=None, on_expire=None):
│ """Apply a status effect to a target character"""
│ existing = None
│ for se in target['status_effects']:
│ if se['name'] == effect_name:
│ existing = se
│ break
│ if existing:
│ if existing['duration'] > 0:
│ existing['duration'] = max(existing['duration'], duration)
│ return
│ # Add the effect to the target's status list
│ new_effect = {
│ 'name': effect_name,
│ 'duration': duration,
│ 'on_apply': on_apply,
│ 'on_tick': on_tick,
│ 'on_expire': on_expire
│ }
│ target['status_effects'].append(new_effect)
│ # Call apply function if it exists
│ if new_effect['on_apply']:
│ new_effect['on_apply'](target)
│ # Create expiration event
│ if new_effect['duration'] > 0:
│ expire_event = create_status_expire_event(
│ id(target),
│ effect_name,
│ global_time + new_effect['duration']
│ )
│ participants.append(expire_event)
│
│ def tick_status_effects(characters, global_time):
│ """Tick all active status effects"""
│ for char in characters:
│ if not char['alive']:
│ continue
│ for effect in list(char['status_effects']):
│ effect['duration'] -= 1
│ if effect['on_tick']:
│ effect['on_tick'](char)
│ if effect['duration'] <= 0:
│ if effect['on_expire']:
│ effect['on_expire'](char)
│ char['status_effects'].remove(effect)
│
│ # === SPELL SYSTEM ===
│ def cast_burn_spell(caster, target, resolve_time):
│ message = f"{caster['name']} casts Burn on {target['name']}!"
│ print(message.rjust(31))
│ damage = int(caster['atk'] * 1.5)
│ target['hp'] = max(0, target['hp'] - damage)
│ if target['hp'] == 0:
│ print(f"{target['name']} collapses!")
│ target['alive'] = False
│
│ # Remove Casting status
│ caster['status_effects'] = [se for se in caster['status_effects'] if se['name'] != 'Casting']
│
│ # Apply burn effect (30 AT duration)
│ apply_status_effect(
│ target,
│ "Burning",
│ 30,
│ on_apply=lambda t: print(f"{t['name']} catches fire!"),
│ on_tick=lambda t: t.update({'hp': max(0, t['hp'] - 1)}),
│ on_expire=lambda t: print(f"{t['name']} is no longer burning.")
│ )
│
│ def cast_poison_spell(caster, target, resolve_time):
│ print(f"{caster['name']} casts Poison on {target['name']}!")
│ damage = int(caster['atk'] * 1.5)
│ target['hp'] = max(0, target['hp'] - damage)
│ if target['hp'] == 0:
│ print(f"{target['name']} collapses!")
│ target['alive'] = False
│
│ # Remove Casting status
│ caster['status_effects'] = [se for se in caster['status_effects'] if se['name'] != 'Casting']
│
│ # Apply poison effect (20 AT duration)
│ apply_status_effect(
│ target,
│ "Poisoned",
│ 20,
│ on_apply=lambda t: print(f"{t['name']} is poisoned!"),
│ on_tick=lambda t: t.update({'hp': max(0, t['hp'] - 1)}),
│ on_expire=lambda t: print(f"{t['name']} is no longer poisoned.")
│ )
│
│ def cast_heal_spell(caster, target, resolve_time):
│ print(f"{caster['name']} casts Heal on {target['name']}!")
│ target['hp'] = min(target['max_hp'], target['hp'] + 50)
│ print(f"{target['name']} healed to {target['hp']}/{target['max_hp']}")
│
│ # Remove Casting status
│ caster['status_effects'] = [se for se in caster['status_effects'] if se['name'] != 'Casting']
│
│ # === COMBAT ACTIONS ===
│ def handle_player_turn(actor, enemies, participants, global_time):
│ """Handle a player's turn"""
│ print(f"\n{actor['name']}'s Turn:")
│ print("A: Attack | B: Cast Burn | P: Cast Poison | H: Heal | R: Run")
│ choice = input("Choose action: ").strip().lower()
│
│ targets = [e for e in enemies if e['alive']]
│ if not targets:
│ print("No enemies alive.")
│ return
│
│ if choice == 'a':
│ target = select_target_from_list(targets)
│ if target:
│ print(f"{
│
├─■ 🕑 2.
│ Hm can't post screenshot? Well
│
│ 'no OOP' version
│
│ maybe easier to understand than OOP version.
│
│
│
└─■ 🕑 3.
There are Emus in Trails in the Sky? I've seen many bird type monsters but never anything like an emu.