604 lines
26 KiB
Python
604 lines
26 KiB
Python
"""
|
|
A simple business simulation game with a focus on market dynamics, crafting and trading.
|
|
|
|
Key features:
|
|
- Market simulation: Manage dynamic product prices, economic factors and random events.
|
|
- Business management: Allows players to craft products, trade and manage inventory.
|
|
- AI Competitors: Includes RationalAI and RiskTakingAI, each with unique strategies.
|
|
- Crafting System: Allows the creation of products using specific recipes.
|
|
- Stock Market: Facilitates stock trading for players and AI, affecting financial strategies.
|
|
- Turn-based gameplay: Includes crafting, trading and stock decisions per turn.
|
|
|
|
Goals:
|
|
- Engage players in strategic economic decisions in a compact, interactive format.
|
|
- Utilises a 'rich' library for enhanced console performance and interaction.
|
|
|
|
How to play:
|
|
1. Start the game by running the main function.
|
|
2. Decide on crafting, trading and stock transactions.
|
|
3. Compete against the AI with different strategies.
|
|
4. Play through a set number of rounds, resulting in a final score.
|
|
|
|
Note: Requires 'rich' and 'json' libraries for functionality.
|
|
"""
|
|
|
|
import json
|
|
import random
|
|
|
|
from rich.console import Console
|
|
from rich.table import Table
|
|
from rich.prompt import Prompt
|
|
from rich import box
|
|
|
|
from rich.panel import Panel
|
|
from rich.text import Text
|
|
|
|
crafting_recipes = {
|
|
'recipe1': {'input': {'A': 4, 'B': 4}, 'output': {'C': 10}, 'turns': 3},
|
|
'recipe2': {'input': {'A': 1, 'B': 1}, 'output': {'C': 2}, 'turns': 2}
|
|
}
|
|
|
|
|
|
def load_json(filename):
|
|
"""Loads JSON data from a file."""
|
|
try:
|
|
with open(filename) as file:
|
|
return json.load(file)
|
|
except FileNotFoundError:
|
|
print(f"Error: The file {filename} was not found.")
|
|
exit(1)
|
|
|
|
|
|
class Market:
|
|
"""Manages market dynamics, including companies, products, stock transactions, and economic indicators."""
|
|
|
|
def __init__(self):
|
|
self.current_turn = 0
|
|
self.companies = {}
|
|
self.products = {'A': 10.0, 'B': 15.0, 'C': 20.0}
|
|
self.events = load_json('market_events.json')["events"]
|
|
self.adjust_prices = lambda adjustment: {k: max(1, v + adjustment) for k, v in self.products.items()}
|
|
self.event_effects = {"double": lambda x: x * 2, "halve": lambda x: x / 2, "increase": lambda x: x + 3.0,
|
|
"decrease": lambda x: max(1, x - 3.0)}
|
|
self.stock_ledger = {}
|
|
|
|
# Economic indicators
|
|
self.inflation_rate = 0.02 # Example starting inflation rate (2%)
|
|
self.unemployment_rate = 0.05 # Example starting unemployment rate (5%)
|
|
self.gdp = 500000 # Example starting GDP value
|
|
|
|
def update_stock_ledger(self, company_id, owner_id, amount):
|
|
"""Updates the ledger with the given stock transaction details."""
|
|
key = (company_id, owner_id)
|
|
self.stock_ledger[key] = self.stock_ledger.get(key, 0) + amount
|
|
|
|
def get_stock_ownership(self, company_id, owner_id):
|
|
"""Retrieves stock ownership details for a specified company and owner."""
|
|
return self.stock_ledger.get((company_id, owner_id), 0)
|
|
|
|
def get_stock_price(self, company_id):
|
|
"""Returns the current stock price of the specified company."""
|
|
company = self.companies[company_id]
|
|
company_value = company.value # No argument passed
|
|
return round(company_value / 100.0, 2)
|
|
|
|
def update_market(self):
|
|
"""Applies market events, adjusts prices, and updates economic indicators for the current turn."""
|
|
self.current_turn += 1
|
|
trend_adjustment = random.choice([2, -2, 0])
|
|
|
|
self.products = self.adjust_prices(trend_adjustment)
|
|
|
|
event = random.choices(self.events, weights=[e["probability"] for e in self.events])[0]
|
|
if event["effect"] in ["new_competitor", "exit_competitor"]:
|
|
self.handle_competitor_event(event["effect"])
|
|
else:
|
|
self.products = {k: self.event_effects[event["effect"]](v) for k, v in self.products.items()}
|
|
|
|
self.update_economic_indicators()
|
|
|
|
def adjust_prices(self):
|
|
"""Adjusts market product prices based on inflation and other factors."""
|
|
for product, price in self.products.items():
|
|
inflation_adjustment = price * self.inflation_rate
|
|
new_price = price + inflation_adjustment
|
|
|
|
# small random fluctuation for realism
|
|
fluctuation = random.uniform(-0.03, 0.03)
|
|
new_price += fluctuation
|
|
|
|
new_price = max(1.5, new_price)
|
|
self.products[product] = round(new_price, 2)
|
|
|
|
return self.products
|
|
|
|
def handle_competitor_event(self, effect):
|
|
"""Handles market changes due to new or exiting competitors."""
|
|
adjustment = float(random.randint(1, 3))
|
|
self.products = {k: max(1.0, v - adjustment) if effect == "new_competitor" else v + adjustment for k, v in
|
|
self.products.items()}
|
|
|
|
def update_economic_indicators(self):
|
|
"""Updates market's economic indicators like inflation and unemployment rates."""
|
|
# Update the inflation rate based on market conditions
|
|
self.inflation_rate += random.uniform(-0.01, 0.01) # Random fluctuation
|
|
self.inflation_rate = max(0.5, self.inflation_rate) # Ensure non-negative
|
|
|
|
# Update the unemployment rate
|
|
self.unemployment_rate += random.uniform(-0.005, 0.005) # Random fluctuation
|
|
self.unemployment_rate = min(max(self.unemployment_rate, 0), 1) # Bound between 0 and 1
|
|
|
|
# Update GDP based on market performance
|
|
self.gdp += self.gdp * (random.uniform(-0.01, 0.03) + self.inflation_rate)
|
|
|
|
def calculate_final_scores(self):
|
|
"""Calculates and returns final scores based on company values and stock ownership."""
|
|
final_scores = {}
|
|
for company_id, company in self.companies.items():
|
|
# Use the 'value' property instead of the 'get_value' method
|
|
final_score = company.value
|
|
|
|
# Determine the majority owner
|
|
majority_owner = max(company.own_stock_ownership,
|
|
key=lambda owner: (company.own_stock_ownership[owner], owner))
|
|
majority_percentage = company.own_stock_ownership[majority_owner]
|
|
|
|
# Check if the majority owner owns 51% or more
|
|
is_major_owner = majority_percentage >= 51
|
|
|
|
# Initialize or update the score
|
|
if company_id not in final_scores:
|
|
final_scores[company_id] = {'score': 0, 'note': '', 'majority_owner': majority_owner}
|
|
|
|
# Distribute scores
|
|
for owner_id, percentage in company.own_stock_ownership.items():
|
|
if percentage > 20:
|
|
score_transfer = final_score * (percentage / 100)
|
|
if owner_id not in final_scores:
|
|
final_scores[owner_id] = {'score': 0, 'note': '', 'majority_owner': ''}
|
|
final_scores[owner_id]['score'] += score_transfer
|
|
|
|
# If no one owns 51% or more, assign the remainder to the company itself
|
|
if not is_major_owner:
|
|
remaining_score = final_score - sum(
|
|
final_scores.get(owner, {'score': 0})['score'] for owner in company.own_stock_ownership)
|
|
final_scores[company_id]['score'] += remaining_score
|
|
|
|
return final_scores
|
|
|
|
|
|
class Company:
|
|
"""Represents a company within the market, managing finances, inventory, and stock transactions."""
|
|
def __init__(self, player_id, competitors_ids, market=None):
|
|
self.player_id = player_id
|
|
self.cash = 500.0
|
|
self.inventory = {'A': 0, 'B': 0, 'C': 0}
|
|
self.crafting_queue = []
|
|
self.own_stock_ownership = {cid: 51 if cid == player_id else 0 for cid in [player_id] + competitors_ids}
|
|
|
|
all_company_ids = set([player_id] + competitors_ids + ["RationalAI", "RiskTakingAI"])
|
|
self.other_stock_holdings = {cid: 0 for cid in all_company_ids}
|
|
|
|
self.total_shares = 100
|
|
self._market = market
|
|
|
|
@property
|
|
def value(self):
|
|
"""Calculates the total value of the company, combining cash and the market value of its inventory."""
|
|
return self.cash + sum(self.inventory[product] * price for product, price in self._market.products.items())
|
|
|
|
def crafting_decision(self):
|
|
"""Displays crafting options and handles the user's crafting choice."""
|
|
print("\nCrafting Decision")
|
|
recipe_keys = list(crafting_recipes.keys())
|
|
print("\nAvailable Recipes:")
|
|
for idx, recipe in enumerate(recipe_keys, 1):
|
|
print(f" {idx}: {recipe}")
|
|
recipe_choice = self.get_user_choice(len(recipe_keys), "Choose a recipe to craft: ")
|
|
self.craft_product(recipe_keys[recipe_choice - 1])
|
|
|
|
def trade_product(self, market, product, quantity, buying=True):
|
|
"""Executes a product trade transaction based on the specified parameters."""
|
|
total_cost = market.products[product] * quantity
|
|
if buying and self.cash >= total_cost:
|
|
self.cash -= total_cost
|
|
self.inventory[product] += quantity
|
|
elif not buying and self.inventory[product] >= quantity:
|
|
self.cash += total_cost
|
|
self.inventory[product] -= quantity
|
|
|
|
def craft_product(self, recipe_key):
|
|
"""Processes crafting of a product based on the chosen recipe."""
|
|
recipe = crafting_recipes[recipe_key]
|
|
if all(self.inventory[product] >= quantity for product, quantity in recipe['input'].items()):
|
|
self.crafting_queue.append({'recipe': recipe, 'turns_remaining': recipe['turns']})
|
|
for product, quantity in recipe['input'].items():
|
|
self.inventory[product] -= quantity
|
|
print("Crafting order placed.")
|
|
else:
|
|
print("Not enough resources to craft.")
|
|
|
|
def update_crafting(self):
|
|
"""Updates the crafting queue, completing orders as their turns conclude."""
|
|
for order in self.crafting_queue[:]:
|
|
order['turns_remaining'] -= 1
|
|
if order['turns_remaining'] == 0:
|
|
for product, quantity in order['recipe']['output'].items():
|
|
self.inventory[product] += quantity
|
|
self.crafting_queue.remove(order)
|
|
|
|
def trade_stock(self, action, market, company_id, amount, is_ai=False):
|
|
"""Executes a stock trade action, buying or selling as specified."""
|
|
if company_id not in market.companies and company_id != self.player_id:
|
|
return "Company not found in the market."
|
|
|
|
stock_price = market.get_stock_price(company_id)
|
|
total_value = stock_price * amount
|
|
|
|
if action == 'buy':
|
|
return self._buy_stock(company_id, amount, total_value, is_ai)
|
|
elif action == 'sell':
|
|
return self._sell_stock(company_id, amount, total_value, is_ai)
|
|
else:
|
|
return "Invalid stock action."
|
|
|
|
def _buy_stock(self, company_id, amount, total_value, is_ai):
|
|
"""Handles the buying of stocks for the specified company."""
|
|
available_shares = self._calculate_available_shares(company_id)
|
|
if amount > available_shares:
|
|
return f"Not enough available shares to buy. Available: {available_shares}"
|
|
|
|
if self.cash < total_value:
|
|
return "Insufficient funds to buy stocks."
|
|
|
|
self._update_stock_ownership(company_id, amount, total_value, buying=True)
|
|
message = f"Bought {amount} stocks of {company_id}."
|
|
if is_ai:
|
|
self.last_action = message
|
|
else:
|
|
print(message)
|
|
return message
|
|
|
|
def _sell_stock(self, company_id, amount, total_value, is_ai):
|
|
"""Handles the selling of stocks for the specified company."""
|
|
if self._get_stock_ownership(company_id) < amount:
|
|
return "Not enough stocks to sell."
|
|
|
|
self._update_stock_ownership(company_id, amount, total_value, buying=False)
|
|
message = f"Sold {amount} stocks of {company_id}."
|
|
if is_ai:
|
|
self.last_action = message
|
|
else:
|
|
print(message)
|
|
return message
|
|
|
|
def _calculate_available_shares(self, company_id):
|
|
"""Calculates the number of available shares for a given company."""
|
|
if company_id == self.player_id:
|
|
return self.total_shares - sum(self.own_stock_ownership.values()) + self.own_stock_ownership[self.player_id]
|
|
else:
|
|
return self.total_shares - self.other_stock_holdings.get(company_id, 0)
|
|
|
|
def _get_stock_ownership(self, company_id):
|
|
"""Retrieves the stock ownership amount for a given company."""
|
|
if company_id == self.player_id:
|
|
return self.own_stock_ownership[self.player_id]
|
|
return self.other_stock_holdings.get(company_id, 0)
|
|
|
|
def _update_stock_ownership(self, company_id, amount, total_value, buying):
|
|
"""Updates the stock ownership details after a buy or sell action."""
|
|
if company_id == self.player_id:
|
|
if buying:
|
|
self.own_stock_ownership[self.player_id] += amount
|
|
else:
|
|
self.own_stock_ownership[self.player_id] -= amount
|
|
else:
|
|
if buying:
|
|
self.other_stock_holdings[company_id] += amount
|
|
else:
|
|
self.other_stock_holdings[company_id] -= amount
|
|
self.cash += -total_value if buying else total_value
|
|
|
|
def make_decision(self, market, competitors):
|
|
"""Presents decision options to the user and processes the chosen action."""
|
|
console = Console()
|
|
status_table = Table(title=f"[bold green]{self.player_id}'s Turn - Turn {market.current_turn}", box=box.ROUNDED)
|
|
status_table.add_column("Category", style="bold cyan")
|
|
status_table.add_column("Details")
|
|
status_table.add_row("Cash", f"[bold yellow]{self.cash:.2f} €")
|
|
status_table.add_row("Inventory", ', '.join(
|
|
[f"[bold magenta]{item}: {quantity}" for item, quantity in self.inventory.items()]))
|
|
status_table.add_row("Market Prices", ', '.join(
|
|
[f"[bold blue]{product}: {price:.2f} €" for product, price in market.products.items()]))
|
|
shareholders = ', '.join(
|
|
[f"[bold]{company}[/]: {ownership} shares" for company, ownership in self.own_stock_ownership.items()])
|
|
status_table.add_row("Your Shareholders", shareholders)
|
|
investments = ', '.join(
|
|
[f"[bold]{company}[/]: {holding} shares" for company, holding in self.other_stock_holdings.items() if
|
|
holding > 0])
|
|
status_table.add_row("Your Investments", investments)
|
|
console.print(status_table)
|
|
actions = {
|
|
"1": "Trade Products",
|
|
"2": "Craft",
|
|
"3": "Trade Stocks",
|
|
"4": "Skip Turn"
|
|
}
|
|
|
|
choices_display = "\n".join([f"{key}: {value}" for key, value in actions.items()])
|
|
console.print(f"Available Actions:\n{choices_display}", style="bold")
|
|
action_choice = Prompt.ask("Choose your action", choices=list(actions.keys()), default="4")
|
|
selected_action = actions.get(action_choice, None)
|
|
|
|
if selected_action == "Trade Products":
|
|
self.trade_products_decision(market)
|
|
elif selected_action == "Craft":
|
|
self.crafting_decision()
|
|
elif selected_action == "Trade Stocks":
|
|
stock_actions = ["Buy", "Sell"]
|
|
stock_action_choice = Prompt.ask("Choose stock action", choices=stock_actions, default=stock_actions[0])
|
|
self.trade_stocks_decision(stock_action_choice.lower(), market, competitors)
|
|
elif selected_action == "Skip Turn":
|
|
pass # Skip turn
|
|
else:
|
|
console.print("[bold red]Invalid choice. Please enter a valid option.")
|
|
|
|
def trade_products_decision(self, market):
|
|
"""Handles the decision-making process for trading products."""
|
|
print("\nProduct Trading Decision")
|
|
products = list(market.products.keys())
|
|
print("\nAvailable Products:")
|
|
for idx, product in enumerate(products, 1):
|
|
print(f" {idx}: {product} - Price: {market.products[product]},00 €")
|
|
product_choice = self.get_user_choice(len(products), "Choose a product to trade: ")
|
|
product = products[product_choice - 1]
|
|
|
|
quantity = self.get_valid_input("Enter the quantity to trade: ", int, "Quantity must be positive.",
|
|
lambda x: x > 0)
|
|
|
|
self.get_user_choice(2, "Choose trade type (1: Buy, 2: Sell): ")
|
|
self.trade_product(market, product, quantity)
|
|
|
|
def trade_stocks_decision(self, action, market, competitors):
|
|
"""Facilitates the decision-making process for stock trading actions."""
|
|
print("\nStock Trading Decision")
|
|
if action == 'buy':
|
|
print("Available companies to buy stocks from:")
|
|
elif action == 'sell':
|
|
print("Your stock holdings:")
|
|
|
|
companies = competitors + [self]
|
|
|
|
for idx, company in enumerate(companies, 1):
|
|
company_id = company.player_id
|
|
stock_info = f" {idx}: {company_id} - Current stock price: {market.get_stock_price(company_id)}"
|
|
if action == 'sell' and self.other_stock_holdings.get(company_id, 0) > 0:
|
|
stock_info += f", Owned: {self.other_stock_holdings[company_id]}"
|
|
print(stock_info)
|
|
|
|
company_choice = self.get_user_choice(len(companies), "Enter the company number to trade stocks: ")
|
|
company_id = companies[company_choice - 1].player_id
|
|
|
|
amount = self.get_valid_input("Enter the amount of stocks to trade: ", int, "Stock amount must be positive.",
|
|
lambda x: x > 0)
|
|
self.trade_stock(action, market, company_id, amount)
|
|
|
|
@staticmethod
|
|
def get_user_choice(num_options, prompt):
|
|
"""Prompts the user for a choice and validates the input."""
|
|
choice = 0
|
|
while choice < 1 or choice > num_options:
|
|
try:
|
|
choice = int(input(prompt))
|
|
if choice < 1 or choice > num_options:
|
|
raise ValueError
|
|
except ValueError:
|
|
print(f"Please enter a number between 1 and {num_options}.")
|
|
return choice
|
|
|
|
@staticmethod
|
|
def get_valid_input(prompt, input_type, error_message, validation_func=lambda x: True):
|
|
"""Requests and validates user input based on specified criteria."""
|
|
while True:
|
|
try:
|
|
value = input_type(input(prompt))
|
|
if not validation_func(value):
|
|
raise ValueError
|
|
return value
|
|
except ValueError:
|
|
print(error_message)
|
|
|
|
def is_market_boom(self):
|
|
"""Checks if the market is booming."""
|
|
return all(price > 20 for price in self._market.products.values())
|
|
|
|
|
|
class AICompany(Company):
|
|
"""Represents an AI-driven company with automated trading, crafting, and stock actions."""
|
|
def __init__(self, player_id, competitors_ids, market):
|
|
super().__init__(player_id, competitors_ids, market)
|
|
self.last_action = "None"
|
|
self.average_prices = {product: market.products[product] for product in market.products}
|
|
|
|
def update_average_prices(self):
|
|
"""Updates the average prices of products based on the current market turn."""
|
|
turn = self._market.current_turn
|
|
for product, price in self._market.products.items():
|
|
self.average_prices[product] = (self.average_prices[product] * (turn - 1) + price) / turn
|
|
|
|
def choose_best_crafting_option(self):
|
|
"""Selects the most viable crafting option based on current inventory."""
|
|
return next((recipe_key for recipe_key, recipe in crafting_recipes.items()
|
|
if all(self.inventory[prod] >= qty for prod, qty in recipe['input'].items())), None)
|
|
|
|
def perform_trade_action(self, action):
|
|
"""Performs a trade action, either buying or selling, based on the specified action."""
|
|
if action == 'sell':
|
|
self.sell_inventory_items()
|
|
elif action == 'buy':
|
|
self.buy_inventory_items()
|
|
|
|
def sell_inventory_items(self):
|
|
"""Executes the selling of inventory items."""
|
|
for product, quantity in self.inventory.items():
|
|
if quantity > 0:
|
|
self.trade_product(self._market, product, quantity, buying=False)
|
|
self.last_action = f"Sold {quantity} of {product}"
|
|
break
|
|
|
|
def buy_inventory_items(self):
|
|
"""Executes the buying of inventory items based on current market prices."""
|
|
for product, price in self._market.products.items():
|
|
if price > 0:
|
|
quantity = int(self.cash // price)
|
|
if quantity > 0:
|
|
self.trade_product(self._market, product, quantity)
|
|
self.last_action = f"Bought {quantity} of {product}"
|
|
break
|
|
|
|
def perform_stock_action(self, action):
|
|
"""Performs a stock action, buying or selling, based on a selected strategy."""
|
|
company_id, amount = self.select_stock_action(action)
|
|
if company_id:
|
|
self.trade_stock(action, self._market, company_id, amount, is_ai=True)
|
|
|
|
def select_stock_action(self, action):
|
|
"""Selects a stock action to perform, either buying or selling."""
|
|
if action == 'buy':
|
|
return self.select_stock_to_buy()
|
|
elif action == 'sell':
|
|
return self.select_stock_to_sell()
|
|
return None, 0
|
|
|
|
def select_stock_to_buy(self):
|
|
"""Chooses a company's stock to buy based on market conditions."""
|
|
company_id = random.choice(list(self._market.companies.keys()))
|
|
amount = random.randint(1, 10)
|
|
return company_id, amount
|
|
|
|
def select_stock_to_sell(self):
|
|
"""Chooses a company's stock to sell from the AI's holdings."""
|
|
owned_stocks = [(comp_id, amount) for comp_id, amount in self.other_stock_holdings.items() if amount > 0]
|
|
if owned_stocks:
|
|
company_id, _ = random.choice(owned_stocks)
|
|
amount = random.randint(1, self.other_stock_holdings[company_id])
|
|
return company_id, amount
|
|
return None, 0
|
|
|
|
def attempt_crafting(self):
|
|
"""Attempts to craft an item based on the best available crafting option."""
|
|
recipe_key = self.choose_best_crafting_option()
|
|
if recipe_key:
|
|
self.craft_product(recipe_key)
|
|
self.last_action = f"Started crafting {recipe_key}"
|
|
|
|
|
|
class RationalAI(AICompany):
|
|
"""AI strategy focused on rational and market-condition-based decisions."""
|
|
def __init__(self, player_id, competitors_ids, market):
|
|
super().__init__(player_id, competitors_ids, market)
|
|
|
|
def make_decision(self, market, competitors):
|
|
"""Makes a market decision based on current market conditions and AI strategy."""
|
|
if self.should_craft():
|
|
self.attempt_crafting()
|
|
elif self.is_market_boom() or market.current_turn > 7:
|
|
self.perform_trade_action('sell')
|
|
else:
|
|
self.perform_trade_action('buy')
|
|
self.perform_stock_action(random.choice(['buy', 'sell']))
|
|
|
|
def should_craft(self):
|
|
"""Determines if crafting is a rational choice based on market conditions."""
|
|
return random.choice([True, False]) if self.is_market_boom() else self._market.current_turn <= 7
|
|
|
|
|
|
class RiskTakingAI(AICompany):
|
|
"""AI strategy focused on high-risk, high-reward decisions in the market."""
|
|
def __init__(self, player_id, competitors_ids, market):
|
|
super().__init__(player_id, competitors_ids, market)
|
|
|
|
def make_decision(self, market, competitors):
|
|
"""Makes bold market decisions based on a high-risk approach."""
|
|
if random.choice([True, False]):
|
|
self.perform_trade_action('buy')
|
|
elif self.should_craft():
|
|
self.attempt_crafting()
|
|
else:
|
|
self.perform_trade_action('sell')
|
|
self.perform_stock_action(random.choice(['buy', 'sell']))
|
|
|
|
def should_craft(self):
|
|
"""Determines if crafting is a suitable choice, leaning towards riskier decisions."""
|
|
return random.choice([True, False]) if self.is_market_boom() else self._market.current_turn <= 7
|
|
|
|
|
|
def print_ai_actions(ai_competitors):
|
|
"""Displays the last actions taken by AI competitors in a styled console format."""
|
|
console = Console()
|
|
for ai in ai_competitors:
|
|
action_text = Text()
|
|
|
|
if "Bought" in ai.last_action or "Sold" in ai.last_action:
|
|
action_color = "green" if "Bought" in ai.last_action else "red"
|
|
action_text.append(ai.last_action, style=f"bold {action_color}")
|
|
elif "Crafting" in ai.last_action:
|
|
action_text.append(ai.last_action, style="bold blue")
|
|
else:
|
|
action_text.append(ai.last_action, style="bold")
|
|
|
|
console.print(
|
|
Panel(action_text, title=f"[bold]{ai.player_id}'s Action", border_style="bright_yellow"))
|
|
|
|
|
|
def main():
|
|
"""
|
|
Simulates a 10-turn market game between the player and two AI competitors.
|
|
"""
|
|
|
|
competitors_ids = ["Player", "RationalAI", "RiskTakingAI"]
|
|
market = Market()
|
|
player = Company("Player", [company_type for company_type in competitors_ids if company_type != "Player"], market)
|
|
|
|
other_competitors = set(competitors_ids) - {"RationalAI", "RiskTakingAI"}
|
|
ai_competitors = [
|
|
RationalAI("RationalAI", list(other_competitors), market),
|
|
RiskTakingAI("RiskTakingAI", list(other_competitors), market),
|
|
]
|
|
|
|
market.companies = {"Player": player, "RationalAI": ai_competitors[0], "RiskTakingAI": ai_competitors[1]}
|
|
|
|
for turn in range(10):
|
|
print(f"\n---\n")
|
|
market.update_market()
|
|
player.update_crafting()
|
|
player.make_decision(market, ai_competitors)
|
|
print(f"\n---\n")
|
|
|
|
for ai in ai_competitors:
|
|
ai.make_decision(market, ai_competitors)
|
|
ai.update_crafting()
|
|
|
|
print_ai_actions(ai_competitors)
|
|
|
|
print(f"\n---\n")
|
|
final_scores = market.calculate_final_scores()
|
|
|
|
console = Console()
|
|
score_table = Table(header_style="bold magenta", box=box.DOUBLE_EDGE)
|
|
score_table.add_column("Company", style="bold cyan")
|
|
score_table.add_column("Final Score", justify="right", style="bold yellow")
|
|
score_table.add_column("Majority Owner", style="bold green")
|
|
score_table.add_column("Ownership Percentage", justify="right", style="dim")
|
|
sorted_scores = sorted(final_scores.items(), key=lambda item: item[1]['score'], reverse=True)
|
|
|
|
for company_id, data in sorted_scores:
|
|
ownership_percentage = f"{data['score'] / market.companies[company_id].value * 100:.2f}%"
|
|
score_table.add_row(company_id, f"{data['score']:.0f}", data['majority_owner'], ownership_percentage)
|
|
|
|
console.print(score_table)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|