diff --git a/main.py b/main.py index dbeecbe..c0b7a75 100644 --- a/main.py +++ b/main.py @@ -15,7 +15,9 @@ from rich.text import Text crafting_recipes = { 'Industrial Synthesis': {'input': {'Coal': 4, 'Copper': 4}, 'output': {'Conductor': 10}, 'turns': 3}, - 'Manual Synthesis': {'input': {'Coal': 1, 'Copper': 1}, 'output': {'Conductor': 2}, 'turns': 2} + 'Manual Synthesis': {'input': {'Coal': 1, 'Copper': 1}, 'output': {'Conductor': 2}, 'turns': 2}, + 'Microchip Fabrication': {'input': {'Silicon': 2, 'Conductor': 1}, 'output': {'Microchips': 5}, 'turns': 4}, + 'Battery Production': {'input': {'Lithium': 3, 'Copper': 2}, 'output': {'Batteries': 4}, 'turns': 3} } @@ -37,6 +39,9 @@ def main(): # Game loop for turn in range(1, 27): console.print(f"\n--- Turn {turn} ---\n", style="grey50") + market.inflation_rate += market.inflation_change if market.inflation_growing else -market.inflation_change + market.inflation_rate = max(0.0001, min(market.inflation_rate, 0.05)) + market.gdp *= (1 + (market.inflation_rate / 20)) market.update_market() market.print_market_events() @@ -83,7 +88,10 @@ class Market: def __init__(self): self.current_turn = 0 self.companies = {} - self.products = {'Coal': 10.0, 'Copper': 15.0, 'Conductor': 20.0} + self.products = { + 'Coal': 10.0, 'Copper': 15.0, 'Conductor': 20.0, + 'Silicon': 12.0, 'Lithium': 18.0, 'Microchips': 30.0, 'Batteries': 25.0 + } self.starting_prices = self.products.copy() self.events = load_json('market_events.json')["events"] self.stock_ledger = {} @@ -102,16 +110,48 @@ class Market: def update_market(self): self.current_turn += 1 self.previous_prices = self.products.copy() - self.update_prices() + + # Update prices based on inflation and random fluctuations + for product in self.products: + inflation_adjustment = self.inflation_rate + random_fluctuation = random.uniform(-0.01, 0.01) # ±1% fluctuation + price_change_factor = 1 + inflation_adjustment + random_fluctuation + self.products[product] *= price_change_factor + + self.reset_trade_volumes() + + # Procedural generation of market trends + self.trend_factor = self.generate_market_trend() + + # Update economic indicators + self.update_economic_indicators() + + # Handle market events + self.handle_market_events() + + def update_prices(self): + min_prices = { + 'Coal': 0.01, 'Copper': 0.20, 'Conductor': 1.50, + 'Silicon': 0.50, 'Lithium': 0.50, 'Microchips': 2.00, 'Batteries': 5.00 + } + max_change = 0.1 + + for product in self.products: + inflation_adjustment = self.inflation_rate + random_fluctuation = random.uniform(-max_change, max_change) + price_change_factor = 1 + inflation_adjustment + random_fluctuation + + new_price = self.products[product] * price_change_factor + self.products[product] = max(min_prices[product], new_price) + self.reset_trade_volumes() self.trend_factor = self.generate_market_trend() self.update_economic_indicators() self.handle_market_events() - - def update_prices(self): - for product in self.products: - demand_factor = self.total_bought[product] - self.total_sold[product] - self.products[product] *= (1 + demand_factor * 0.05) + def calculate_price_change(self, product): + demand_factor = self.total_bought[product] - self.total_sold[product] + # Here you can define how strongly demand affects the price, e.g., 0.05 as in your original code + return demand_factor * 0.05 def reset_trade_volumes(self): self.total_bought = dict.fromkeys(self.total_bought, 0) @@ -184,8 +224,8 @@ class Market: console = Console() event_info = f"Last Market Event: {self.last_event_name}\n" economic_indicators = ( - f"Inflation Rate: {self.inflation_rate:.2f}%\n" - f"Unemployment Rate: {self.unemployment_rate:.2f}%\n" + f"Inflation Rate: {self.inflation_rate * 100:.2f}%\n" + f"Unemployment Rate: {self.unemployment_rate * 100:.2f}%\n" f"GDP: {self.gdp:.2f} €" ) @@ -315,10 +355,12 @@ class Company: _market (Market): Reference to the game's market. _debug (bool): Flag for enabling debug mode. """ + def __init__(self, player_id, competitors_ids, market=None, debug=False): self.player_id = player_id self.cash = 500.0 - self.inventory = {'Coal': 0, 'Copper': 0, 'Conductor': 0} + self.inventory = {'Coal': 0, 'Copper': 0, 'Conductor': 0, + 'Silicon': 0, 'Lithium': 0, 'Microchips': 0, 'Batteries': 0} self.crafting_queue = [] self.own_stock_ownership = {cid: 51 if cid == player_id else 0 for cid in [player_id] + competitors_ids} self.stock_holdings = {cid: 0 for cid in set([player_id] + competitors_ids + ["RationalAI", "RiskTakingAI"])} @@ -399,6 +441,9 @@ class Company: else: print("Insufficient inventory to complete sale.") + # Update market prices after trading + market.update_prices() # This call ensures prices are updated with constraints + def crafting_decision(self): """Displays crafting options and handles the user's crafting choice.""" print("\nCrafting Decision") @@ -452,14 +497,21 @@ class Company: def _sell_stock(self, company_id, amount, total_value, is_ai): """Handles the selling of stocks for the specified company.""" # Check if the seller has enough stocks to sell - if self._get_stock_ownership(company_id) < amount: + stock_ownership = self._get_stock_ownership(company_id) if not is_ai else self.own_stock_ownership[company_id] + if stock_ownership < amount: return "Not enough stocks to sell." # Update stock ownership if is_ai: - self.stock_holdings[company_id] -= amount # Decrease AI's stock holdings + if company_id == self.player_id: + # AI selling its own stock + self.own_stock_ownership[company_id] -= amount + else: + # AI selling other company's stock + self.stock_holdings[company_id] -= amount else: - self.own_stock_ownership[company_id] -= amount # Decrease player's own stock holdings + # Player selling stock + self.own_stock_ownership[company_id] -= amount self.cash += total_value # Add the proceeds to the seller's cash return f"Sold {amount} stocks of {company_id}." @@ -491,7 +543,8 @@ class Company: def make_decision(self, market, competitors): console = Console() - status_table = Table(title=f"\n[bold cyan]{self.player_id}'s Turn - Turn {market.current_turn}", box=box.ROUNDED) + status_table = Table(title=f"\n[bold cyan]{self.player_id}'s Turn - Turn {market.current_turn}", + box=box.ROUNDED) # Cash Row status_table.add_column("Category", style="bold cyan") @@ -635,6 +688,7 @@ class AICompany(Company): Methods provide the AI's logic for crafting, trading, stock transactions, and handling market events. """ + def __init__(self, player_id, competitors_ids, market, risk_tolerance): super().__init__(player_id, competitors_ids, market) self.risk_tolerance = risk_tolerance @@ -644,7 +698,7 @@ class AICompany(Company): def update_average_prices(self): """Updates the average prices of products in the market for AI decision-making purposes.""" self.average_prices = {product: (self.average_prices[product] * ( - self._market.current_turn - 1) + price) / self._market.current_turn + self._market.current_turn - 1) + price) / self._market.current_turn for product, price in self._market.products.items()} def make_decision(self, market, competitors): @@ -724,7 +778,8 @@ class AICompany(Company): """ Determines if the AI should craft products based on inventory and market conditions. """ - return all(self.inventory[product] >= qty for product, qty in crafting_recipes['Manual Synthesis']['input'].items()) + return all( + self.inventory[product] >= qty for product, qty in crafting_recipes['Manual Synthesis']['input'].items()) def should_sell_products(self, market): """ @@ -758,7 +813,7 @@ class AICompany(Company): def print_ai_actions(ai_competitors): - """Displays the actions history, current cash, and inventory of AI competitors.""" + """Displays the actions history, current cash, inventory, and stock information of AI competitors.""" console = Console() for ai in ai_competitors: panel_text = Text() @@ -770,7 +825,16 @@ def print_ai_actions(ai_competitors): # Append current cash and inventory to the text panel_text.append(f"\nCurrent Cash: {ai.cash:.2f} €\n", style="bold blue") - panel_text.append(f"Inventory: {inventory_text}", style="bold cyan") + panel_text.append(f"Inventory: {inventory_text}\n", style="bold cyan") + + # Display Shareholders and Investments + shareholders_text = ', '.join( + [f"{company}: {ownership} shares" for company, ownership in ai.own_stock_ownership.items()]) + investments_text = ', '.join( + [f"{company}: {holding} shares" for company, holding in ai.stock_holdings.items() if holding > 0]) + + panel_text.append(f"Shareholders: {shareholders_text}\n", style="bold green") + panel_text.append(f"Investments: {investments_text}", style="bold magenta") # Display in a panel console.print(Panel(panel_text, title=f"[bold]{ai.player_id}'s Status", border_style="grey50"))