Make it so the player can only check the network once per turn.



import random
import sys
import time
from colorama import Fore, Style, init

# Initialize colorama with automatic reset and stripping for unsupported environments
init(autoreset=True, strip=True)

# ASCII Art Title
TITLE = f"""
{Fore.CYAN}  __  __    _    ____  _  _______ _____ 
 |  \/  |  / \  |  _ \| |/ / ____|_   _|
 | |\/| | / _ \ | |_) | ' /|  _|   | |  
 | |  | |/ ___ \|  _ <| . \| |___  | |  
 |_|  |_/_/   \_\_| \_\_|\_\_____| |_|  
                                        
{Style.RESET_ALL}
"""

# Welcome Text without the '=' lines, with yellow coloring
WELCOME_TEXT = f"""{Fore.YELLOW}Welcome to the Text-Based Trading Game!
Your goal is to accumulate as much wealth as possible within a set number of turns.
Explore a variety of goods, manage your cargo capacity, and navigate the dynamic market.
Be mindful of your relationships with towns—they play a crucial role in your success.{Style.RESET_ALL}"""

# HELP Text with detailed rules and trading categories
HELP_TEXT = f"""
{Fore.GREEN}Game Rules and Instructions:{Style.RESET_ALL}

1. {Fore.YELLOW}Objective:{Style.RESET_ALL}
   Accumulate as much wealth as possible within the allotted number of turns.

2. {Fore.YELLOW}Commands:{Style.RESET_ALL}
   - {Fore.CYAN}BUY:{Style.RESET_ALL} Purchase goods from the market.
   - {Fore.CYAN}SELL:{Style.RESET_ALL} Sell goods from your inventory.
   - {Fore.CYAN}TRAVEL:{Style.RESET_ALL} Move to a different town.
   - {Fore.CYAN}STATUS:{Style.RESET_ALL} View your current status, inventory, and relationships.
   - {Fore.CYAN}UPGRADE:{Style.RESET_ALL} Upgrade your cargo capacity.
   - {Fore.CYAN}NETWORK:{Style.RESET_ALL} Get rumors and information about other towns.
   - {Fore.CYAN}HELP:{Style.RESET_ALL} View the game rules and trading categories.
   - {Fore.CYAN}EXIT:{Style.RESET_ALL} Exit the game.

3. {Fore.YELLOW}Goods Categories and Their Impact on Relationships:{Style.RESET_ALL}
   - {Fore.CYAN}Supportive Goods:{Style.RESET_ALL} Food, Herbs, Cloth
     - Buying large quantities improves {Fore.CYAN}Reputation{Style.RESET_ALL}.
   - {Fore.CYAN}Strategic Goods:{Style.RESET_ALL} Gold, Gems, Iron
     - Buying significant amounts improves {Fore.CYAN}Trade Relations{Style.RESET_ALL}.
   - {Fore.CYAN}Luxury Goods:{Style.RESET_ALL} Silk, Wine
     - Buying these increases {Fore.CYAN}Favor{Style.RESET_ALL}.

4. {Fore.YELLOW}Trading Tips:{Style.RESET_ALL}
   - Buying in bulk may grant discounts.
   - Over-buying or over-selling can affect your relationships with towns.
   - Relationships affect prices and trading conditions.

5. {Fore.YELLOW}Relationships with Towns:{Style.RESET_ALL}
   - {Fore.CYAN}Trade:{Style.RESET_ALL} Reflects your trading history with the town.
   - {Fore.CYAN}Reputation:{Style.RESET_ALL} Represents your overall standing and trustworthiness.
   - {Fore.CYAN}Favor:{Style.RESET_ALL} Indicates personal favor and goodwill from the town.

6. {Fore.YELLOW}Events:{Style.RESET_ALL}
   - Random events may occur, impacting markets and relationships.
   - Your global reputation can influence the likelihood of events.

7. {Fore.YELLOW}Turn Mechanics:{Style.RESET_ALL}
   - Actions like {Fore.CYAN}BUY, SELL, TRAVEL,{Style.RESET_ALL} and {Fore.CYAN}UPGRADE{Style.RESET_ALL} consume a turn.
   - Viewing {Fore.CYAN}STATUS, NETWORK,{Style.RESET_ALL} or {Fore.CYAN}HELP{Style.RESET_ALL} does not consume a turn.

{Style.RESET_ALL}
"""

# Print methods for different speeds
def fast_print(text):
    for char in text:
        print(char, end="", flush=True)
        time.sleep(0.0005)
    print()

def medium_print(text):
    for char in text:
        print(char, end="", flush=True)
        time.sleep(0.005)  # Medium typing speed
    print()

def slow_print(text):
    for char in text:
        print(char, end="", flush=True)
        time.sleep(0.02)  # Slow typing speed
    print()

def get_relationship_status(average_score):
    """Converts a numerical relationship score into a descriptive status."""
    if average_score >= 80:
        return "Ally"
    elif average_score >= 50:
        return "Friendly"
    elif average_score >= -20:
        return "Neutral"
    elif average_score >= -60:
        return "Hostile"
    else:
        return "Enemy"

# Goods and their base prices, weights, base supply, and base demand
GOODS = {
    "Spices": {"base_price": 100, "weight": 5, "base_supply": 300, "base_demand": 300},
    "Gems": {"base_price": 500, "weight": 10, "base_supply": 150, "base_demand": 200},
    "Food": {"base_price": 50, "weight": 3, "base_supply": 400, "base_demand": 400},
    "Silk": {"base_price": 200, "weight": 4, "base_supply": 150, "base_demand": 200},
    "Iron": {"base_price": 150, "weight": 15, "base_supply": 200, "base_demand": 250},
    "Wine": {"base_price": 120, "weight": 6, "base_supply": 200, "base_demand": 250},
    "Tea": {"base_price": 80, "weight": 2, "base_supply": 300, "base_demand": 300},
    "Herbs": {"base_price": 60, "weight": 3, "base_supply": 350, "base_demand": 300},
    "Cloth": {"base_price": 180, "weight": 8, "base_supply": 100, "base_demand": 150},
    "Gold": {"base_price": 1000, "weight": 25, "base_supply": 80, "base_demand": 100},
}

# Combined list of all goods for inventory and selection
ALL_GOODS = GOODS.copy()

# Expanded list of Towns
TOWNS = [
    "Amberville", "Brightstone", "Crimsonburg", "Dusktown",
    "Sunset City", "Northport", "Riverside", "Hilltop",
    "Lakeside", "Oakwood", "Stormhaven", "Fairview"
]

# List of possible random events
GLOBAL_EVENTS = [
    "Economic boom affecting all markets.",
    "Global trade embargo reducing supply worldwide.",
    "Pandemic affecting demand for certain goods globally.",
    "Technological advancements altering trade dynamics.",
    "Global inflation increasing prices across the board.",
    "Global recession decreasing purchasing power.",
]

LOCAL_EVENTS = [
    "Thieves attacked your caravan and stole some goods!",
    "A storm ruined your goods during travel.",
    "A festival in town increased demand for certain goods.",
    "Disease outbreak decreased the demand for food.",
    "New trade routes discovered, affecting supply.",
    "Pirates disrupted trade in the seas.",
    "Economic boom in Crimsonburg raised prices.",
    "Market crash in Brightstone lowered prices.",
    "Government imposed a tax on trade.",
    "Discovery of a rare gem deposit increased gem supply.",
    "Locusts devastated the food supplies in Dusktown.",
    "Artisans in Amberville created new uses for spices, increasing their demand.",
    "Floods in Riverside increased the supply of iron.",
    "Harvest season in Lakeside boosted the demand for food.",
    "Gold rush in Hilltop increased the supply and demand for gold.",
    "Silk shortage in Sunset City raised silk prices.",
    "Herbal harvest in Oakwood decreased the supply of herbs.",
    "Tea festival in Fairview increased the demand for tea.",
    "Ironworks expansion in Northport increased the supply of iron.",
    "Wine tasting event in Stormhaven boosted wine prices.",
    "Cloth market crash in Fairview lowered cloth prices.",
    "Bandit attack in Oakwood stole some of your goods.",
    "Natural disaster in Dusktown affecting multiple goods.",
    "Town marketplace upgrade in Riverside lowered base prices for certain goods.",
]

# Player relationships with towns
RELATIONSHIP_BASE = 0  # Neutral
RELATIONSHIP_MAX = 100
RELATIONSHIP_MIN = -100

# Difficulty settings
DIFFICULTIES = {
    "EASY": {
        "event_chance": 0.12,
        "ai_aggressiveness": 0.7,
        "starting_money": 4000,
        "starting_cargo": 350,
        "turns": 50
    },
    "MEDIUM": {
        "event_chance": 0.2,
        "ai_aggressiveness": 1.0,
        "starting_money": 2500,
        "starting_cargo": 200,
        "turns": 35
    },
    "HARD": {
        "event_chance": 0.3,
        "ai_aggressiveness": 1.5,
        "starting_money": 1800,
        "starting_cargo": 150,
        "turns": 25
    }
}

class AITrader:
    """Represents an AI trader that interacts with the market each turn."""
    def __init__(self, trader_id, aggressiveness=1.0):
        self.trader_id = trader_id
        self.name = f"Trader_{trader_id}"
        self.aggressiveness = aggressiveness  # Determines transaction sizes and frequency

    def perform_action(self, market):
        """AI trader performs buy or sell actions based on strategy."""
        # Determine number of actions based on aggressiveness
        num_actions = random.randint(1, 3) if self.aggressiveness > 1.0 else random.randint(1, 2)
        for _ in range(num_actions):
            # Decide action based on aggressiveness
            action = random.choices(["BUY", "SELL"], weights=[self.aggressiveness, 1.0])[0]
            
            # Choose a good to buy or sell
            # Bias against interacting heavily with Gold and Gems
            goods_choices = list(ALL_GOODS.keys())
            goods_prob = []
            for good in goods_choices:
                if good in ["Gold", "Gems"]:
                    # Reduce interaction probability with high-impact goods
                    goods_prob.append(0.2)
                else:
                    goods_prob.append(0.8 / (len(goods_choices) - 2))  # Adjust weights accordingly
            good = random.choices(goods_choices, weights=goods_prob, k=1)[0]
            
            # Determine quantity based on aggressiveness
            quantity = random.randint(1, max(1, int(10 * self.aggressiveness)))  # Reduced max quantity
            if action == "BUY":
                # AI trader buys goods: decrease supply, increase demand
                if market.supply.get(good, 0) >= quantity:
                    market.supply[good] -= quantity
                    market.demand[good] += quantity * 0.5  # Reduced impact
            elif action == "SELL":
                # AI trader sells goods: increase supply, decrease demand
                market.supply[good] = market.supply.get(good, 0) + quantity
                market.demand[good] = market.demand.get(good, 0) - quantity * 0.5  # Reduced impact
                if market.demand.get(good, 0) < 50:  # Prevent demand from going too low
                    market.demand[good] = 50

class Player:
    """Represents the player with money, inventory, and cargo capacity."""
    def __init__(self, starting_money, starting_cargo):
        self.money = starting_money
        self.inventory = {good: 0 for good in GOODS}
        self.location = random.choice(TOWNS)
        self.turns = 0
        self.max_cargo = starting_cargo
        self.current_cargo = 0
        self.cargo_upgrades = 0
        # Initialize relationships with multiple aspects
        self.relationships = {town: {
            "Trade": RELATIONSHIP_BASE,
            "Reputation": RELATIONSHIP_BASE,
            "Favor": RELATIONSHIP_BASE
        } for town in TOWNS}
        self.event_log = []  # To track key events per turn
        self.reputation = 0  # Global reputation

    def modify_relationship(self, town, aspect, amount):
        """Modifies a specific aspect of the relationship with a town."""
        variation = random.randint(-1, 1)  # Reduced randomness for predictability
        adjusted_amount = amount + variation
        # Clamp the relationship aspect within defined limits
        new_score = self.relationships[town][aspect] + adjusted_amount
        new_score = max(RELATIONSHIP_MIN, min(new_score, RELATIONSHIP_MAX))
        self.relationships[town][aspect] = new_score
        # Notify the player about the change
        if adjusted_amount > 0:
            slow_print(f"[{town} - {aspect}] Improved by {adjusted_amount} points!")
        elif adjusted_amount < 0:
            slow_print(f"[{town} - {aspect}] Worsened by {-adjusted_amount} points!")

    def get_overall_relationship_status(self, town):
        """Determines the overall relationship status based on individual aspects."""
        aspects = self.relationships[town]
        # Calculate average of all aspects
        average = sum(aspects.values()) / len(aspects)
        return get_relationship_status(average)

    def status(self):
        """Displays the player's current status with detailed relationship aspects."""
        slow_print(f"\n{Fore.GREEN}Player Status:{Style.RESET_ALL}")
        fast_print(f"Location: {self.location}")
        fast_print(f"Money: ${self.money}")
        fast_print(f"Cargo: {self.current_cargo}/{self.max_cargo} units used")
        fast_print("Inventory:")
        for good, qty in self.inventory.items():
            if qty > 0:
                fast_print(f"  {good}: {qty}")
        # Display relationships with detailed aspects
        fast_print("\nRelationships:")
        for town, aspects in self.relationships.items():
            overall_status = self.get_overall_relationship_status(town)
            relationship_info = ', '.join([
                f"{Fore.CYAN}{aspect}: {score}{Style.RESET_ALL}" for aspect, score in aspects.items()
            ])
            if overall_status in ["Ally", "Friendly"]:
                status_color = Fore.GREEN
            elif overall_status in ["Hostile", "Enemy"]:
                status_color = Fore.RED
            else:
                status_color = Fore.YELLOW
            fast_print(f"  {town}: {relationship_info} | Overall: {status_color}{overall_status}{Style.RESET_ALL}")
        print()

    def status_short(self):
        """Displays the player's current status without relationship aspects."""
        slow_print(f"\n{Fore.GREEN}Player Status:{Style.RESET_ALL}")
        fast_print(f"Location: {self.location}")
        fast_print(f"Money: ${self.money}")
        fast_print(f"Cargo: {self.current_cargo}/{self.max_cargo} units used")
        fast_print("Inventory:")
        for good, qty in self.inventory.items():
            if qty > 0:
                fast_print(f"  {good}: {qty}")   
        print()

    def add_cargo(self, good, quantity):
        """Attempts to add cargo to the player's inventory."""
        # Determine weight based on whether the good is regular
        if good in GOODS:
            weight = GOODS[good]["weight"]
        else:
            weight = 5  # Default weight
        total_weight = weight * quantity
        if self.current_cargo + total_weight > self.max_cargo:
            return False, total_weight
        self.current_cargo += total_weight
        if good not in self.inventory:
            self.inventory[good] = 0
        self.inventory[good] += quantity
        return True, total_weight

    def remove_cargo(self, good, quantity):
        """Removes cargo from the player's inventory."""
        if good not in self.inventory:
            return
        # Determine weight based on whether the good is regular
        if good in GOODS:
            weight = GOODS[good]["weight"]
        else:
            weight = 5  # Default weight
        total_weight = weight * quantity
        self.inventory[good] -= quantity
        self.current_cargo -= total_weight
        if self.inventory[good] < 0:
            self.inventory[good] = 0
        if self.current_cargo < 0:
            self.current_cargo = 0

    def upgrade_cargo(self):
        """Allows the player to upgrade cargo capacity."""
        upgrade_cost = 500 + (self.cargo_upgrades * 200)
        upgrade_amount = 50
        if self.money < upgrade_cost:
            slow_print("Insufficient funds to upgrade cargo capacity.")
            return False  # Indicate that no upgrade was made
        confirm = input(f"Upgrade cargo capacity by {upgrade_amount} for ${upgrade_cost}? (Y/N): ").strip().upper()
        if confirm == 'Y':
            self.money -= upgrade_cost
            self.max_cargo += upgrade_amount
            self.cargo_upgrades += 1
            slow_print(f"Cargo capacity increased by {upgrade_amount}. New capacity: {self.max_cargo}")
            self.event_log.append(f"Upgraded cargo capacity by {upgrade_amount} for ${upgrade_cost}.")
            return True  # Indicate that upgrade was successful
        elif confirm == 'N':
            slow_print("Upgrade canceled.")
            return False
        else:
            slow_print("ERROR: Invalid Input")
            return False

class Market:
    """Represents the market of a specific town."""
    PRICE_FLOOR = 10
    PRICE_CEILING = 2000

    def __init__(self, town, player):
        self.town = town
        self.player = player
        # Initialize supply and demand per good with increased random variations
        self.supply = {}
        self.demand = {}
        for good, info in GOODS.items():
            supply_variation = random.uniform(0.6, 1.4)  # Increased range from 0.6-1.4
            demand_variation = random.uniform(0.6, 1.4)  # Increased range from 0.6-1.4
            self.supply[good] = info["base_supply"] * supply_variation
            self.demand[good] = info["base_demand"] * demand_variation
        self.prices = {}
        self.generate_prices()
        # Initialize AI traders for the town
        self.ai_traders = [AITrader(trader_id=i+1, aggressiveness=random.uniform(0.7, 1.5)) for i in range(10)]  # 10 AI traders per town

    def generate_prices(self):
            """Calculates current prices based on supply, demand, and relationship with the player."""
            relation_modifier = self.get_relationship_modifier(self.town)
            for good, info in GOODS.items():
                # Calculate price based on demand and supply with increased elasticity
                if self.supply.get(good, 0) == 0:
                    price_multiplier = 2  # High price if no supply
                else:
                    ratio = self.demand.get(good, 0) / self.supply.get(good, 0)
                    elasticity = random.uniform(0.7, 1.3)  # Adjusted elasticity range
                    price_multiplier = ratio * elasticity
                new_price = int(GOODS[good]["base_price"] * price_multiplier * relation_modifier)
                new_price = max(self.PRICE_FLOOR, min(new_price, self.PRICE_CEILING))
                self.prices[good] = new_price

    def get_relationship_modifier(self, town):
        """Determines price modifiers based on multiple relationship aspects."""
        aspects = self.player.relationships[town]
        trade = aspects["Trade"]
        reputation = aspects["Reputation"]
        favor = aspects["Favor"]

        # Calculate individual modifiers
        if trade >= 80:
            trade_modifier = 0.75  # 25% discount for buying, 25% bonus for selling
        elif trade >= 50:
            trade_modifier = 0.85  # 15% discount
        elif trade >= -20:
            trade_modifier = 1.00  # Neutral
        elif trade >= -60:
            trade_modifier = 1.20  # 20% price increase
        else:
            trade_modifier = 1.40  # 40% price increase

        if reputation >= 70:
            reputation_modifier = 0.90  # 10% discount
        elif reputation >= 40:
            reputation_modifier = 0.95  # 5% discount
        else:
            reputation_modifier = 1.00  # Neutral

        if favor >= 60:
            favor_modifier = 0.95  # 5% discount
        else:
            favor_modifier = 1.00  # Neutral

        # Combine modifiers by averaging
        overall_modifier = (trade_modifier + reputation_modifier + favor_modifier) / 3
        return overall_modifier

    def display_prices(self):
        """Displays the current prices, supply, and demand for all goods in the market."""
        slow_print(f"\n{Fore.GREEN}Market Overview in {self.town}:{Style.RESET_ALL}")
        for good, price in self.prices.items():
            supply = int(self.supply.get(good, 0))
            demand = int(self.demand.get(good, 0))
            fast_print(f"{Fore.YELLOW}{good}: ${price} (Supply: {supply}, Demand: {demand}){Style.RESET_ALL}")
        print()

    def process_ai_traders(self):
        """Processes all AI traders' actions for the market."""
        for trader in self.ai_traders:
            trader.perform_action(self)
        # After AI traders have acted, regenerate prices
        self.generate_prices()

class Game:
    """Represents the main game loop and logic."""

    def __init__(self):
        # Difficulty selection will be done in start()
        self.player = None
        self.difficulty = None
        self.turns_total = 0
        self.markets = {}
        self.current_market = None
        self.current_event = None
        # Define decay rates to return supply and demand towards base values
        self.supply_decay_rate = 0.03  # Reduced decay rate for slower stabilization
        self.demand_decay_rate = 0.03  # Reduced decay rate for slower stabilization
        self.turn_counter = 1
        self.game_over = False
        self.key_events = []  # To track key events for summary

    def choose_difficulty(self):
        """Allows the player to choose a difficulty level."""
        fast_print("\nChoose Difficulty Level:")
        for idx, level in enumerate(DIFFICULTIES.keys(), 1):
            fast_print(f"{idx}. {level.capitalize()}")
        while True:
            choice = input(f"Enter the number corresponding to your choice (1-{len(DIFFICULTIES)}): ").strip()
            if choice.isdigit() and 1 <= int(choice) <= len(DIFFICULTIES):
                selected = list(DIFFICULTIES.keys())[int(choice)-1]
                fast_print(f"Selected {selected.capitalize()} difficulty.\n")
                return selected
            else:
                fast_print("Invalid choice. Please try again.")

    def start(self):
        """Starts the game by displaying the title and welcome message."""
        fast_print(TITLE)
        # Print the '=' lines separately in yellow without extra line breaks
        fast_print(f"""{Fore.YELLOW}{'='*60}{Style.RESET_ALL}""")
        medium_print(WELCOME_TEXT)
        fast_print(f"""{Fore.YELLOW}{'='*60}{Style.RESET_ALL}""")
        # Now choose difficulty
        self.difficulty = self.choose_difficulty()
        # Initialize player and markets after difficulty is chosen
        self.player = Player(
            starting_money=DIFFICULTIES[self.difficulty]["starting_money"],
            starting_cargo=DIFFICULTIES[self.difficulty]["starting_cargo"]
        )
        self.turns_total = DIFFICULTIES[self.difficulty]["turns"]
        self.markets = {town: Market(town, self.player) for town in TOWNS}
        self.current_market = self.markets[self.player.location]
        input("Press Enter to start your trading adventure...")
        self.game_loop()

    def game_loop(self):
        """Main game loop that runs until the player runs out of turns or exits."""
        while self.turn_counter <= self.turns_total and not self.game_over:
            medium_print(f"\n--- Turn {self.turn_counter}/{self.turns_total} ---")
            # Display player status (excluding relationships)
            self.player.status_short()
            # Display prices for the current market
            self.current_market.display_prices()
            command = input("Enter command (BUY/SELL/TRAVEL/STATUS/UPGRADE/NETWORK/HELP/EXIT): ").strip().upper()
            if command == "STATUS":
                self.player.status()
                continue  # Do not advance the turn
            elif command == "NETWORK":
                self.check_network()
                continue  # Do not advance the turn
            elif command == "HELP":
                print(f"{Fore.YELLOW}{'='*60}{Style.RESET_ALL}")
                fast_print(HELP_TEXT)
                print(f"{Fore.YELLOW}{'='*60}{Style.RESET_ALL}")
                continue  # Do not advance the turn
            elif command == "EXIT":
                slow_print("Thank you for playing!")
                self.end_game()
            elif command in ["BUY", "SELL", "TRAVEL", "UPGRADE"]:
                # Process commands that consume a turn
                if command == "BUY":
                    self.buy()
                elif command == "SELL":
                    self.sell()
                elif command == "TRAVEL":
                    self.travel()
                elif command == "UPGRADE":
                    upgraded = self.player.upgrade_cargo()
                    if not upgraded:
                        continue  # If upgrade did not happen, do not advance the turn
                # At this point, a turn has passed
                # Process AI traders and events
                self.apply_decay()
                # Process AI traders for all markets
                for market in self.markets.values():
                    market.process_ai_traders()
                # Trigger event before displaying prices
                self.trigger_event()
                # Regenerate prices after events
                self.current_market.generate_prices()
                self.turn_counter += 1
            else:
                slow_print("ERROR: Invalid Input")
                continue  # Do not advance the turn
        self.end_game()

    def check_network(self):
        """Provides rumors about the status of other towns in the merchant network."""
        medium_print(f"\n{Fore.GREEN}Merchant Network Rumors:{Style.RESET_ALL}")
        for town, market in self.markets.items():
            #if town == self.player.location:
            #    continue  # Skip current location
            status = self.player.get_overall_relationship_status(town)
            rumor = self.generate_rumor(town, market, status)
            if status in ["Ally", "Friendly"]:
                color = Fore.CYAN
            elif status in ["Hostile", "Enemy"]:
                color = Fore.RED
            else:
                color = Fore.YELLOW
            fast_print(f"{color}{town}:{Style.RESET_ALL}")
            fast_print(f" {rumor}")
        print()

    def generate_rumor(self, town, market, status):
        """Generates a rumor based on the town's market and relationship status."""
        # Base rumor based on relationship
        if status == "Ally":
            base_rumor = f"{Fore.BLUE}is thriving and their trade is booming.{Style.RESET_ALL}"
        elif status == "Friendly":
            base_rumor = f"{Fore.GREEN}is experiencing steady trade.{Style.RESET_ALL}"
        elif status == "Neutral":
            base_rumor = f"{Fore.YELLOW}has a balanced market with no major changes.{Style.RESET_ALL}"
        elif status == "Hostile":
            base_rumor = f"{Fore.RED}is facing some challenges, causing minor disruptions in trade.{Style.RESET_ALL}"
        else:  # Enemy
            base_rumor = f"{Fore.RED}is in turmoil, significantly affecting their market and relations.{Style.RESET_ALL}"

        # Select multiple goods to include in the rumor
        affected_goods = random.sample(list(ALL_GOODS.keys()), k=random.randint(1, 3))  # Affect 1 to 3 goods

        goods_rumors = []
        for good in affected_goods:
            supply = market.supply.get(good, 0)
            demand = market.demand.get(good, 0)
            good_colored = f"{Fore.CYAN}{good}{Style.RESET_ALL}"
            if demand > supply * 1.5:
                # High demand pushing prices up
                rumor_text = f"high demand for {good_colored} is pushing prices up"
                rumor_colored = f"{Fore.RED}{rumor_text}{Style.RESET_ALL}"
                goods_rumors.append(rumor_colored)
            elif demand < supply * 0.5:
                # Excess supply lowering prices
                rumor_text = f"excess supply of {good_colored} is lowering prices"
                rumor_colored = f"{Fore.GREEN}{rumor_text}{Style.RESET_ALL}"
                goods_rumors.append(rumor_colored)
            else:
                # Stable demand and supply
                rumor_text = f"stable demand and supply for {good_colored}"
                rumor_colored = f"{Fore.YELLOW}{rumor_text}{Style.RESET_ALL}"
                goods_rumors.append(rumor_colored)

        goods_rumor = "; ".join(goods_rumors)
        rumor = f"{base_rumor} Additionally, there's {goods_rumor}."
        return rumor

    def buy(self):
        """Handles the buying process for the player."""
        good = self.choose_good("buy")
        if not good:
            return

        price = self.current_market.prices.get(good, GOODS.get(good, {}).get("base_price", 100))
        # Calculate max affordable based on money
        max_affordable_quantity = self.player.money // price
        # Calculate max based on cargo
        if good in GOODS:
            good_weight = GOODS[good]["weight"]
        else:
            good_weight = 5  # Default weight
        available_cargo_space = self.player.max_cargo - self.player.current_cargo
        max_cargo_quantity = available_cargo_space // good_weight
        # Calculate max based on supply
        max_supply = int(self.current_market.supply.get(good, 0))

        max_quantity = min(max_affordable_quantity, max_cargo_quantity, max_supply)

        if max_quantity <= 0:
            slow_print("You cannot buy any units of this good due to insufficient funds, cargo space, or supply.")
            return

        # Encourage bulk buying with discounts
        discount = 0
        discounted_price = price
        if max_quantity >= 20:
            discount = 0.10  # 10% discount for buying 20 or more units
            discounted_price = int(price * (1 - discount))
            fast_print(f"Bulk purchase discount applied! Price per unit: ${discounted_price} (Original: ${price})")
        elif max_quantity >= 10:
            discount = 0.05  # 5% discount for buying 10 or more units
            discounted_price = int(price * (1 - discount))
            fast_print(f"Bulk purchase discount applied! Price per unit: ${discounted_price} (Original: ${price})")

        fast_print(f"You can afford up to {max_quantity} units based on your constraints.")
        quantity_input = input(f"Enter the quantity of {good} to buy (max {max_quantity}): ").strip()
        if not quantity_input.isdigit() or int(quantity_input) <= 0 or int(quantity_input) > max_quantity:
            slow_print("ERROR: Invalid Input. Transaction canceled.")
            return

        quantity = int(quantity_input)
        cost = discounted_price * quantity

        success, added_weight = self.player.add_cargo(good, quantity)
        if not success:
            slow_print(f"Cannot buy {quantity} {good}. Exceeds cargo capacity.")
            return

        # Update player and market
        self.player.money -= cost
        self.current_market.supply[good] -= quantity
        self.current_market.demand[good] += quantity * 0.4  # Increased impact
        slow_print(f"Bought {quantity} {good} for ${cost}.")
        fast_print(f"Cargo Updated: {self.player.current_cargo}/{self.player.max_cargo} units used.")
        self.player.event_log.append(f"Turn {self.turn_counter}: Bought {quantity} {good} for ${cost}.")
        self.key_events.append(f"Turn {self.turn_counter}: Bought {quantity} {good} for ${cost}.")

        # Define which aspect to modify based on the type of good
        supportive_goods = ["Food", "Herbs", "Cloth"]
        strategic_goods = ["Gold", "Gems", "Iron"]
        luxury_goods = ["Silk", "Wine"]

        relationship_change_trade = 0
        relationship_change_reputation = 0
        relationship_change_favor = 0

        if quantity >= max_quantity * 0.5:
            if good in supportive_goods:
                relationship_change_reputation = 15  # Improved Reputation
                self.player.event_log.append(f"Turn {self.turn_counter}: Bought large quantity of {good}, improved Reputation.")
                self.key_events.append(f"Turn {self.turn_counter}: Bought large quantity of {good}, improved Reputation.")
            elif good in strategic_goods:
                relationship_change_trade = 12  # Improved Trade Relations
                self.player.event_log.append(f"Turn {self.turn_counter}: Bought significant amount of {good}, improved Trade Relations.")
                self.key_events.append(f"Turn {self.turn_counter}: Bought significant amount of {good}, improved Trade Relations.")
            elif good in luxury_goods:
                relationship_change_favor = 8  # Increased Favor
                self.player.event_log.append(f"Turn {self.turn_counter}: Bought luxury good {good}, increased Favor.")
                self.key_events.append(f"Turn {self.turn_counter}: Bought luxury good {good}, increased Favor.")
        elif quantity >= max_quantity * 0.3:
            # Aggressive buying affects multiple aspects negatively
            relationship_change_trade = -10
            relationship_change_reputation = -8
            relationship_change_favor = -5
            self.player.event_log.append(f"Turn {self.turn_counter}: Aggressively bought {quantity} {good}, strained relationships.")
            self.key_events.append(f"Turn {self.turn_counter}: Aggressively bought {quantity} {good}, strained relationships.")

        # Apply relationship changes
        if relationship_change_trade != 0:
            self.player.modify_relationship(self.player.location, "Trade", relationship_change_trade)
        if relationship_change_reputation != 0:
            self.player.modify_relationship(self.player.location, "Reputation", relationship_change_reputation)
        if relationship_change_favor != 0:
            self.player.modify_relationship(self.player.location, "Favor", relationship_change_favor)

    def sell(self):
        """Handles the selling process for the player."""
        good = self.choose_good("sell")
        if not good:
            return
        if self.player.inventory.get(good, 0) == 0:
            fast_print(f"You have no {good} to sell.")
            return

        max_sell_quantity = int(self.player.inventory.get(good, 0))

        fast_print(f"You can sell up to {max_sell_quantity} units based on your inventory.")
        quantity_input = input(f"Enter the quantity of {good} to sell (max {max_sell_quantity}): ").strip()
        if not quantity_input.isdigit() or int(quantity_input) <= 0 or int(quantity_input) > max_sell_quantity:
            slow_print("ERROR: Invalid Input. Transaction canceled.")
            return

        quantity = int(quantity_input)
        price = self.current_market.prices.get(good, GOODS.get(good, {}).get("base_price", 100))
        revenue = price * quantity

        # Risky Selling: If selling more than a threshold, relationships may decrease
        risky_threshold = max_sell_quantity * 0.9  # Increased threshold to 90% of inventory
        relationship_decrement_trade = 7  # Reduced impact
        relationship_decrement_reputation = 5
        relationship_decrement_favor = 3

        if quantity > risky_threshold:
            risk = random.random()
            if risk < 0.4:  # 40% chance of negative impact
                self.player.modify_relationship(self.player.location, "Trade", -relationship_decrement_trade)
                self.player.modify_relationship(self.player.location, "Reputation", -relationship_decrement_reputation)
                self.player.modify_relationship(self.player.location, "Favor", -relationship_decrement_favor)
                slow_print(f"Over-selling {good} has slightly upset the local merchants.")
                self.player.event_log.append(f"Turn {self.turn_counter}: Over-sold {good}, strained relationships.")
                self.key_events.append(f"Turn {self.turn_counter}: Over-sold {good}, strained relationships.")

        # Update player and market
        self.player.money += revenue
        self.player.remove_cargo(good, quantity)
        self.current_market.supply[good] += quantity
        self.current_market.demand[good] -= quantity * 0.4  # Increased impact
        slow_print(f"Sold {quantity} {good} for ${revenue}.")
        fast_print(f"Cargo Updated: {self.player.current_cargo}/{self.player.max_cargo} units used.")
        self.player.event_log.append(f"Turn {self.turn_counter}: Sold {quantity} {good} for ${revenue}.")
        self.key_events.append(f"Turn {self.turn_counter}: Sold {quantity} {good} for ${revenue}.")

        # Define which aspect to modify based on the type of good
        needed_goods = ["Gems", "Iron", "Gold"]
        desired_goods = ["Food", "Herbs", "Cloth"]
        luxury_goods = ["Silk", "Wine"]

        relationship_change_trade = 0
        relationship_change_reputation = 0
        relationship_change_favor = 0

        if good in needed_goods and quantity >= max_sell_quantity * 0.5:
            relationship_change_trade = 15  # Improved Trade Relations
            self.player.event_log.append(f"Turn {self.turn_counter}: Sold large quantity of {good}, improved Trade Relations.")
            self.key_events.append(f"Turn {self.turn_counter}: Sold large quantity of {good}, improved Trade Relations.")
        elif good in desired_goods and quantity >= max_sell_quantity * 0.4:
            relationship_change_reputation = 10  # Improved Reputation
            self.player.event_log.append(f"Turn {self.turn_counter}: Sold significant amount of {good}, improved Reputation.")
            self.key_events.append(f"Turn {self.turn_counter}: Sold significant amount of {good}, improved Reputation.")
        elif good in luxury_goods and quantity >= max_sell_quantity * 0.3:
            relationship_change_favor = 8  # Increased Favor
            self.player.event_log.append(f"Turn {self.turn_counter}: Sold luxury good {good}, increased Favor.")
            self.key_events.append(f"Turn {self.turn_counter}: Sold luxury good {good}, increased Favor.")

        # Apply relationship changes
        if relationship_change_trade != 0:
            self.player.modify_relationship(self.player.location, "Trade", relationship_change_trade)
        if relationship_change_reputation != 0:
            self.player.modify_relationship(self.player.location, "Reputation", relationship_change_reputation)
        if relationship_change_favor != 0:
            self.player.modify_relationship(self.player.location, "Favor", relationship_change_favor)

    def travel(self):
        """Handles the travel process for the player to move between towns."""
        available_towns = [town for town in TOWNS if town != self.player.location]
        slow_print("\nAvailable towns to travel to:")
        for idx, town in enumerate(available_towns, 1):
            fast_print(f"{idx}. {town}")
        choice = input(f"Enter the number of the town you want to travel to (1-{len(available_towns)}): ").strip()
        if not choice.isdigit() or not (1 <= int(choice) <= len(available_towns)):
            slow_print("ERROR: Invalid Input. Travel canceled.")
            return
        new_location = available_towns[int(choice) - 1]
        self.player.location = new_location
        self.current_market = self.markets[new_location]
        slow_print(f"Traveled to {new_location}.")
        self.player.event_log.append(f"Turn {self.turn_counter}: Traveled to {new_location}.")
        self.key_events.append(f"Turn {self.turn_counter}: Traveled to {new_location}.")

        # Impact relationships by choosing to travel frequently without significant trades
        # Penalty affects all aspects slightly
        travel_penalty_chance = 0.3  # 30% chance to slightly reduce relationships
        if random.random() < travel_penalty_chance:  # 30% chance to slightly reduce relationships
            penalty_trade = -3
            penalty_reputation = -2
            penalty_favor = -1
            self.player.modify_relationship(new_location, "Trade", penalty_trade)
            self.player.modify_relationship(new_location, "Reputation", penalty_reputation)
            self.player.modify_relationship(new_location, "Favor", penalty_favor)
            slow_print(f"Frequent traveling has slightly strained your relationships with {new_location}.")
            self.player.event_log.append(f"Turn {self.turn_counter}: Frequent traveling strained relationships with {new_location}.")
            self.key_events.append(f"Turn {self.turn_counter}: Frequent traveling strained relationships with {new_location}.")

    def choose_good(self, action):
        """Prompts the player to choose a good to buy or sell."""
        fast_print("Available goods:")
        all_goods = list(ALL_GOODS.keys())
        for idx, good in enumerate(all_goods, 1):
            fast_print(f"{idx}. {good}")
        choice = input(f"Enter the number of the good to {action}: ").strip()
        if not choice.isdigit() or not (1 <= int(choice) <= len(all_goods)):
            slow_print("ERROR: Invalid Input. Operation canceled.")
            return None
        return all_goods[int(choice) - 1]

    def trigger_event(self):
        """Randomly triggers a global or local event based on difficulty settings."""
        event_chance = DIFFICULTIES[self.difficulty]["event_chance"]
        # Reduce event chance based on reputation
        reputation_factor = 1 - (self.player.reputation / 200)  # Adjust as needed
        reputation_factor = max(0.5, reputation_factor)  # Ensure at least 50% of base chance
        adjusted_event_chance = event_chance * reputation_factor
        if random.random() < adjusted_event_chance:
            event_type = random.choice(["GLOBAL", "LOCAL"])
            if event_type == "GLOBAL":
                event = random.choice(GLOBAL_EVENTS)
                slow_print(f"\n{Fore.RED}Global Event: {event}{Style.RESET_ALL}")
                self.apply_event(event, global_event=True)
                self.key_events.append(f"Turn {self.turn_counter}: Global Event - {event}")
            else:
                event = random.choice(LOCAL_EVENTS)
                slow_print(f"\n{Fore.RED}Local Event: {event}{Style.RESET_ALL}")
                self.apply_event(event, global_event=False)
                self.key_events.append(f"Turn {self.turn_counter}: Local Event - {event}")

    def apply_event(self, event, global_event=False):
        """Applies the effects of a triggered event to the game."""
        # Handle events based on their descriptions
        # Modify specific relationship aspects based on event
        if "extra goods" in event.lower():
            # Example player-specific positive event
            good = random.choice(list(ALL_GOODS.keys()))
            quantity = random.randint(5, 15)
            # Check if adding these goods exceeds cargo capacity
            added_weight = GOODS[good]["weight"] * quantity
            if self.player.current_cargo + added_weight <= self.player.max_cargo:
                self.player.inventory[good] += quantity
                self.player.current_cargo += added_weight
                self.player.money += 100  # Bonus money
                slow_print(f"You found extra {quantity} units of {good} and gained $100!")
                # Modify multiple relationship aspects positively
                self.player.modify_relationship(self.player.location, "Trade", 5)
                self.player.modify_relationship(self.player.location, "Reputation", 5)
                self.player.modify_relationship(self.player.location, "Favor", 5)
                self.player.event_log.append(f"Turn {self.turn_counter}: Found extra {quantity} {good} and gained $100.")
                self.key_events.append(f"Turn {self.turn_counter}: Found extra {quantity} {good} and gained $100.")
                self.player.reputation += 5
            else:
                slow_print(f"You found extra {quantity} units of {good}, but don't have enough cargo space to carry them.")
            return

        if "tax" in event.lower():
            tax_amount = 100  # Increased impact
            self.player.money = max(0, self.player.money - tax_amount)
            slow_print(f"The government imposed a tax on your trade. You lost ${tax_amount}.")
            # Tax affects Trade and Reputation negatively
            self.player.modify_relationship(self.player.location, "Trade", -10)
            self.player.modify_relationship(self.player.location, "Reputation", -5)
            self.player.event_log.append(f"Turn {self.turn_counter}: Imposed tax of ${tax_amount}.")
            self.key_events.append(f"Turn {self.turn_counter}: Imposed tax of ${tax_amount}.")
            self.player.reputation -= 10
            return

        if "economic boom" in event.lower():
            affected_good = "Gems"
            price_boost = int(GOODS[affected_good]["base_price"] * 0.4)
            self.current_market.demand[affected_good] += 100  # Increased impact
            self.current_market.prices[affected_good] += price_boost
            slow_print(f"An economic boom raised the demand and price of {affected_good} by ${price_boost}.")
            # Improve Trade Relations due to economic boom
            self.player.modify_relationship(self.player.location, "Trade", 10)
            self.player.modify_relationship(self.player.location, "Reputation", 5)
            self.player.reputation += 15
            return
        elif "market crash" in event.lower():
            affected_good = "Spices"
            price_drop = int(GOODS[affected_good]["base_price"] * 0.35)
            self.current_market.demand[affected_good] = max(50, self.current_market.demand.get(affected_good, 0) - 150)  # Increased impact
            self.current_market.prices[affected_good] = max(Market.PRICE_FLOOR, self.current_market.prices.get(affected_good, 0) - price_drop)
            slow_print(f"A market crash decreased the demand and price of {affected_good} by ${price_drop}.")
            # Decrease Trade Relations and Reputation
            self.player.modify_relationship(self.player.location, "Trade", -10)
            self.player.modify_relationship(self.player.location, "Reputation", -5)
            self.player.reputation -= 15
            return
        elif "thieves" in event.lower() or "bandit" in event.lower():
            affected_good = random.choice(list(ALL_GOODS.keys()))
            stolen_qty = random.randint(5, 15)  # Increased impact
            actual_stolen = min(stolen_qty, self.player.inventory.get(affected_good, 0))
            self.player.inventory[affected_good] -= actual_stolen
            self.player.remove_cargo(affected_good, actual_stolen)
            # Partial impact on market
            self.current_market.supply[affected_good] = self.current_market.supply.get(affected_good, 0) + actual_stolen * 0.3  # Increased impact
            self.current_market.demand[affected_good] = self.current_market.demand.get(affected_good, 0) - actual_stolen * 0.3  # Increased impact
            slow_print(f"Bandits stole {actual_stolen} units of {affected_good} from your cargo!")
            # Decrease Trade Relations, Reputation, and Favor
            self.player.modify_relationship(self.player.location, "Trade", -12)
            self.player.modify_relationship(self.player.location, "Reputation", -8)
            self.player.modify_relationship(self.player.location, "Favor", -5)
            self.player.event_log.append(f"Turn {self.turn_counter}: Bandits stole {actual_stolen} {affected_good}.")
            self.key_events.append(f"Turn {self.turn_counter}: Bandits stole {actual_stolen} {affected_good}.")
            self.player.reputation -= 20
            return
        elif "storm" in event.lower() or "natural disaster" in event.lower():
            damaged_good = random.choice(list(ALL_GOODS.keys()))
            damaged_qty = random.randint(5, 15)  # Increased impact
            actual_damaged = min(damaged_qty, self.player.inventory.get(damaged_good, 0))
            self.player.inventory[damaged_good] -= actual_damaged
            self.player.remove_cargo(damaged_good, actual_damaged)
            # Partial impact on market
            self.current_market.supply[damaged_good] = self.current_market.supply.get(damaged_good, 0) + actual_damaged * 0.2  # Increased impact
            self.current_market.demand[damaged_good] = self.current_market.demand.get(damaged_good, 0) - actual_damaged * 0.2  # Increased impact
            slow_print(f"A storm damaged {actual_damaged} units of {damaged_good} in your cargo.")
            # Decrease Trade Relations, Reputation, and Favor
            self.player.modify_relationship(self.player.location, "Trade", -5)
            self.player.modify_relationship(self.player.location, "Reputation", -3)
            self.player.modify_relationship(self.player.location, "Favor", -2)
            self.player.event_log.append(f"Turn {self.turn_counter}: Storm damaged {actual_damaged} {damaged_good}.")
            self.key_events.append(f"Turn {self.turn_counter}: Storm damaged {actual_damaged} {damaged_good}.")
            self.player.reputation -= 10
            return
        elif "festival" in event.lower():
            affected_good = random.choice(["Spices", "Wine", "Cloth"])
            price_boost = int(GOODS[affected_good]["base_price"] * 0.3)
            self.current_market.demand[affected_good] += 80  # Increased impact
            self.current_market.prices[affected_good] += price_boost
            slow_print(f"The festival increased the demand for {affected_good}, boosting its price by ${price_boost}.")
            # Improve Reputation and Favor during festivals
            self.player.modify_relationship(self.player.location, "Reputation", 10)
            self.player.modify_relationship(self.player.location, "Favor", 10)
            self.player.event_log.append(f"Turn {self.turn_counter}: Festival boosted {affected_good} prices.")
            self.key_events.append(f"Turn {self.turn_counter}: Festival boosted {affected_good} prices.")
            self.player.reputation += 10
            return
        elif "disease" in event.lower():
            affected_good = "Food"
            price_drop = int(GOODS[affected_good]["base_price"] * 0.25)  # Increased impact
            self.current_market.demand[affected_good] = max(50, self.current_market.demand.get(affected_good, 0) - 120)  # Increased impact
            self.current_market.prices[affected_good] = max(Market.PRICE_FLOOR, self.current_market.prices.get(affected_good, 0) - price_drop)
            slow_print(f"A disease outbreak decreased the demand for {affected_good}, lowering its price by ${price_drop}.")
            # Decrease Trade Relations and Reputation
            self.player.modify_relationship(self.player.location, "Trade", -10)
            self.player.modify_relationship(self.player.location, "Reputation", -5)
            self.player.reputation -= 15
            return
        elif "trade routes" in event.lower():
            affected_good = random.choice(list(ALL_GOODS.keys()))
            supply_change = random.randint(-40, 40)  # Increased impact
            self.current_market.supply[affected_good] = max(10, self.current_market.supply.get(affected_good, 0) + supply_change)
            slow_print(f"New trade routes have altered the supply of {affected_good}, changing its supply by {supply_change} units.")
            # Minor impact on relationships
            if supply_change < 0:
                self.player.modify_relationship(self.player.location, "Trade", -5)
                self.player.modify_relationship(self.player.location, "Reputation", -2)
                self.player.modify_relationship(self.player.location, "Favor", -1)
                self.player.event_log.append(f"Turn {self.turn_counter}: Trade routes negatively affected {affected_good} supply.")
                self.key_events.append(f"Turn {self.turn_counter}: Trade routes negatively affected {affected_good} supply.")
                self.player.reputation -= 5
            return
        elif "pirates" in event.lower():
            affected_good = random.choice(list(ALL_GOODS.keys()))
            price_drop = int(GOODS[affected_good]["base_price"] * 0.35)  # Increased impact
            self.current_market.demand[affected_good] = max(50, self.current_market.demand.get(affected_good, 0) - 70)  # Increased impact
            self.current_market.prices[affected_good] = max(Market.PRICE_FLOOR, self.current_market.prices.get(affected_good, 0) - price_drop)
            slow_print(f"Pirates disrupted trade, decreasing the demand and price of {affected_good} by ${price_drop}.")
            # Decrease Trade Relations, Reputation, and Favor
            self.player.modify_relationship(self.player.location, "Trade", -10)
            self.player.modify_relationship(self.player.location, "Reputation", -5)
            self.player.modify_relationship(self.player.location, "Favor", -2)
            self.player.event_log.append(f"Turn {self.turn_counter}: Pirates disrupted trade, decreased {affected_good} price.")
            self.key_events.append(f"Turn {self.turn_counter}: Pirates disrupted trade, decreased {affected_good} price.")
            self.player.reputation -= 15
            return
        elif "rare gem" in event.lower():
            affected_good = "Gems"
            supply_increase = 70  # Increased impact
            self.current_market.supply[affected_good] = max(10, self.current_market.supply.get(affected_good, 0) + supply_increase)
            self.current_market.demand[affected_good] = max(50, self.current_market.demand.get(affected_good, 0) - 40)  # Increased impact
            slow_print(f"Discovery of a rare gem deposit increased the supply of {affected_good}, lowering its price.")
            # Improve Trade Relations and Reputation
            self.player.modify_relationship(self.player.location, "Trade", 10)
            self.player.modify_relationship(self.player.location, "Reputation", 5)
            self.player.event_log.append(f"Turn {self.turn_counter}: Discovered rare gem deposit, affected {affected_good}.")
            self.key_events.append(f"Turn {self.turn_counter}: Discovered rare gem deposit, affected {affected_good}.")
            self.player.reputation += 10
            return
        elif "locusts" in event.lower():
            affected_good = "Food"
            damage = random.randint(10, 20)  # Increased impact
            actual_damaged = min(damage, self.player.inventory.get(affected_good, 0))
            self.player.inventory[affected_good] -= actual_damaged
            self.player.remove_cargo(affected_good, actual_damaged)
            # Partial impact on market
            self.current_market.supply[affected_good] = self.current_market.supply.get(affected_good, 0) + actual_damaged * 0.3  # Increased impact
            self.current_market.demand[affected_good] = self.current_market.demand.get(affected_good, 0) - actual_damaged * 0.3  # Increased impact
            slow_print(f"Locusts devastated your food supplies, destroying {actual_damaged} units of {affected_good}.")
            # Decrease Trade Relations, Reputation, and Favor
            self.player.modify_relationship(self.player.location, "Trade", -8)
            self.player.modify_relationship(self.player.location, "Reputation", -5)
            self.player.modify_relationship(self.player.location, "Favor", -3)
            self.player.event_log.append(f"Turn {self.turn_counter}: Locusts destroyed {actual_damaged} {affected_good}.")
            self.key_events.append(f"Turn {self.turn_counter}: Locusts destroyed {actual_damaged} {affected_good}.")
            self.player.reputation -= 10
            return
        elif "artisans" in event.lower():
            affected_good = "Spices"
            price_boost = int(GOODS[affected_good]["base_price"] * 0.35)  # Increased impact
            self.current_market.demand[affected_good] += 60  # Increased impact
            self.current_market.prices[affected_good] += price_boost
            slow_print(f"Artisans in {self.player.location} created new uses for {affected_good}, increasing its demand and price by ${price_boost}.")
            # Improve Reputation and Favor
            self.player.modify_relationship(self.player.location, "Reputation", 10)
            self.player.modify_relationship(self.player.location, "Favor", 10)
            self.player.event_log.append(f"Turn {self.turn_counter}: Artisans boosted {affected_good} demand.")
            self.key_events.append(f"Turn {self.turn_counter}: Artisans boosted {affected_good} demand.")
            self.player.reputation += 20
            return
        elif "global economic boom" in event.lower():
            for market in self.markets.values():
                affected_good = "Gold"
                price_boost = int(GOODS[affected_good]["base_price"] * 0.3)  # Increased impact
                market.demand[affected_good] += 50  # Increased impact
                market.prices[affected_good] = min(int(market.prices.get(affected_good, 0) * 1.3), Market.PRICE_CEILING)
            slow_print("A global economic boom has increased the demand and prices for Gold across all markets.")
            # Improve Trade Relations and Reputation globally
            for town in TOWNS:
                self.player.modify_relationship(town, "Trade", 10)
                self.player.modify_relationship(town, "Reputation", 5)
            self.player.reputation += 20
            return
        elif "global recession" in event.lower() or "economic recession" in event.lower():
            for market in self.markets.values():
                affected_good = "Food"
                price_drop = int(GOODS[affected_good]["base_price"] * 0.25)  # Increased impact
                market.demand[affected_good] = max(50, market.demand.get(affected_good, 0) - 80)  # Increased impact
                market.prices[affected_good] = max(Market.PRICE_FLOOR, market.prices.get(affected_good, 0) - price_drop)
            slow_print("A global recession has decreased the demand and prices for Food across all markets.")
            # Decrease Trade Relations and Reputation globally
            for town in TOWNS:
                self.player.modify_relationship(town, "Trade", -10)
                self.player.modify_relationship(town, "Reputation", -5)
            self.player.reputation -= 20
            return

    def apply_decay(self):
        """Applies decay to supply and demand in all markets to move towards base values."""
        for good, info in GOODS.items():
            for market in self.markets.values():
                # Supply decay towards base_supply
                if market.supply.get(good, 0) < info["base_supply"]:
                    market.supply[good] += info["base_supply"] * self.supply_decay_rate
                    if market.supply[good] > info["base_supply"]:
                        market.supply[good] = info["base_supply"]
                elif market.supply.get(good, 0) > info["base_supply"]:
                    market.supply[good] -= info["base_supply"] * self.supply_decay_rate
                    if market.supply[good] < info["base_supply"]:
                        market.supply[good] = info["base_supply"]

                # Demand decay towards base_demand
                if market.demand.get(good, 0) < info["base_demand"]:
                    market.demand[good] += info["base_demand"] * self.demand_decay_rate
                    if market.demand[good] > info["base_demand"]:
                        market.demand[good] = info["base_demand"]
                elif market.demand.get(good, 0) > info["base_demand"]:
                    market.demand[good] -= info["base_demand"] * self.demand_decay_rate
                    if market.demand[good] < info["base_demand"]:
                        market.demand[good] = info["base_demand"]

                # Additional decay for Gold's value to prevent hoarding
                if good == "Gold":
                    market.prices["Gold"] = max(Market.PRICE_FLOOR, int(market.prices["Gold"] * 0.99))  # 1% depreciation per turn

    def end_game(self):
        """Displays the final game results and concludes the game."""
        slow_print("\nGame Over!")
        fast_print(f"Final Money: ${self.player.money}")
        total_goods = sum(self.player.inventory.values())
        fast_print(f"Total Goods: {total_goods}")
        net_worth = self.player.money + sum(
            self.player.inventory.get(good, 0) * self.current_market.prices.get(good, 0) for good in ALL_GOODS
        )
        fast_print(f"Net Worth: ${net_worth}")

        # Calculate overall relationship scores
        total_trade = sum([self.player.relationships[town]["Trade"] for town in TOWNS])
        total_reputation = sum([self.player.relationships[town]["Reputation"] for town in TOWNS])
        total_favor = sum([self.player.relationships[town]["Favor"] for town in TOWNS])

        average_trade = total_trade / len(TOWNS)
        average_reputation = total_reputation / len(TOWNS)
        average_favor = total_favor / len(TOWNS)

        # Calculate liquidity vs stock ratio
        total_stock_value = sum(
            self.player.inventory.get(good, 0) * self.current_market.prices.get(good, 0) for good in ALL_GOODS
        )
        if total_stock_value == 0:
            liquidity_ratio = 5  # Assign maximum if no stock
        else:
            liquidity_ratio = self.player.money / total_stock_value
            liquidity_ratio = min(liquidity_ratio, 5)  # Cap at 5 for scoring

        # Calculate scores for each category
        net_worth_score = self.calculate_net_worth_score(net_worth)
        trade_score = self.calculate_trade_score(average_trade)
        reputation_score = self.calculate_reputation_score(average_reputation)
        favor_score = self.calculate_favor_score(average_favor)
        liquidity_score = self.calculate_liquidity_score(liquidity_ratio)

        total_score = net_worth_score + trade_score + reputation_score + favor_score + liquidity_score

        # Determine final rating based on total_score
        rating = self.determine_rating(total_score)

        rating_messages = {
            "Legendary": "Incredible! You became an unmatched trading legend with stellar relationships and unmatched liquidity.",
            "Great": "Congratulations! You became a legendary trader with excellent relationships and strong liquidity.",
            "Excellent": "Outstanding! You achieved impressive wealth and maintained excellent relationships.",
            "Good": "Well done! You made a substantial profit and maintained good relationships.",
            "Decent": "Good job! You made a respectable profit and kept decent relations.",
            "Neutral": "You had a balanced trading journey with both successes and challenges.",
            "Poor": "You struggled to make a significant profit and had poor relationships.",
            "Bad": "You struggled to make a profit and had poor relationships.",
            "Terrible": "Better luck next time. Your trading skills and relationships need significant improvement."
        }

        slow_print(f"Final Rating: {Fore.CYAN}{rating}{Style.RESET_ALL}")
        slow_print(rating_messages.get(rating, ""))

        # Display key events summary
        slow_print("\nSummary of Your Journey:")
        for event in self.key_events[:50]:  # Limit to first 50 for readability
            fast_print(event)
        if len(self.key_events) > 50:
            fast_print("...")

        # Provide more detailed summaries based on performance metrics
        if rating in ["Legendary", "Great", "Excellent"]:
            slow_print("\nYou excelled in trading, made strategic decisions, and built strong alliances with the towns.")
        elif rating in ["Good", "Decent", "Neutral"]:
            slow_print("\nYou had a successful trading journey with some notable achievements and maintained balanced relations.")
        elif rating in ["Poor", "Bad", "Terrible"]:
            slow_print("\nYour trading endeavors faced challenges, resulting in limited profits and strained relationships.")

        slow_print("\nThank you for playing the Text-Based Trading Game!")
        sys.exit()

    def calculate_net_worth_score(self, net_worth):
        """Assigns a score based on net worth."""
        if net_worth >= 40000:
            return 5
        elif net_worth >= 30000:
            return 4
        elif net_worth >= 20000:
            return 3
        elif net_worth >= 15000:
            return 2
        elif net_worth >= 10000:
            return 1
        else:
            return 0

    def calculate_trade_score(self, average_trade):
        """Assigns a score based on average Trade Relations."""
        if average_trade >= 80:
            return 5
        elif average_trade >= 60:
            return 4
        elif average_trade >= 40:
            return 3
        elif average_trade >= 20:
            return 2
        elif average_trade >= 0:
            return 1
        else:
            return 0

    def calculate_reputation_score(self, average_reputation):
        """Assigns a score based on average Reputation."""
        if average_reputation >= 80:
            return 5
        elif average_reputation >= 60:
            return 4
        elif average_reputation >= 40:
            return 3
        elif average_reputation >= 20:
            return 2
        elif average_reputation >= 0:
            return 1
        else:
            return 0

    def calculate_favor_score(self, average_favor):
        """Assigns a score based on average Favor."""
        if average_favor >= 80:
            return 5
        elif average_favor >= 60:
            return 4
        elif average_favor >= 40:
            return 3
        elif average_favor >= 20:
            return 2
        elif average_favor >= 0:
            return 1
        else:
            return 0

    def calculate_liquidity_score(self, liquidity_ratio):
        """Assigns a score based on liquidity_ratio."""
        if liquidity_ratio >= 4:
            return 4
        elif liquidity_ratio >= 3:
            return 3
        elif liquidity_ratio >= 2:
            return 2
        elif liquidity_ratio >= 1:
            return 1
        else:
            return 0

    def determine_rating(self, total_score):
        """Determines the final rating based on total_score."""
        # Adjust thresholds based on the new scoring system
        if total_score >= 20:
            return "Legendary"
        elif total_score >= 16:
            return "Great"
        elif total_score >= 12:
            return "Excellent"
        elif total_score >= 9:
            return "Good"
        elif total_score >= 7:
            return "Decent"
        elif total_score >= 5:
            return "Neutral"
        elif total_score >= 3:
            return "Poor"
        elif total_score >= 1:
            return "Bad"
        else:
            return "Terrible"

# Main execution block with error handling
if __name__ == "__main__":
    try:
        game_instance = Game()
        game_instance.start()
    except Exception as e:
        print(f"\n{Fore.RED}An unexpected error occurred: {e}{Style.RESET_ALL}")
        sys.exit(1)