rich
This commit is contained in:
parent
f88d46221a
commit
4add18930d
282
main.py
282
main.py
@ -1,5 +1,10 @@
|
|||||||
import random
|
|
||||||
import json
|
import json
|
||||||
|
import random
|
||||||
|
|
||||||
|
from rich.console import Console
|
||||||
|
from rich.table import Table
|
||||||
|
from rich.prompt import Prompt
|
||||||
|
from rich import box
|
||||||
|
|
||||||
crafting_recipes = {
|
crafting_recipes = {
|
||||||
'recipe1': {'input': {'A': 4, 'B': 4}, 'output': {'C': 10}, 'turns': 3},
|
'recipe1': {'input': {'A': 4, 'B': 4}, 'output': {'C': 10}, 'turns': 3},
|
||||||
@ -20,17 +25,17 @@ class Market:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.current_turn = 0
|
self.current_turn = 0
|
||||||
self.companies = {}
|
self.companies = {}
|
||||||
self.products = {'A': 10, 'B': 15, 'C': 20}
|
self.products = {'A': 10.0, 'B': 15.0, 'C': 20.0}
|
||||||
self.events = load_json('market_events.json')["events"]
|
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.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,
|
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)}
|
"decrease": lambda x: max(1, x - 3.0)}
|
||||||
self.stock_ledger = {} # Initialize the stock ledger
|
self.stock_ledger = {} # Initialize the stock ledger
|
||||||
|
|
||||||
# Economic indicators
|
# Economic indicators
|
||||||
self.inflation_rate = 0.02 # Example starting inflation rate (2%)
|
self.inflation_rate = 0.02 # Example starting inflation rate (2%)
|
||||||
self.unemployment_rate = 0.05 # Example starting unemployment rate (5%)
|
self.unemployment_rate = 0.05 # Example starting unemployment rate (5%)
|
||||||
self.gdp = 10000 # Example starting GDP value
|
self.gdp = 500000 # Example starting GDP value
|
||||||
|
|
||||||
def update_stock_ledger(self, company_id, owner_id, amount):
|
def update_stock_ledger(self, company_id, owner_id, amount):
|
||||||
key = (company_id, owner_id)
|
key = (company_id, owner_id)
|
||||||
@ -41,20 +46,42 @@ class Market:
|
|||||||
|
|
||||||
def get_stock_price(self, company_id):
|
def get_stock_price(self, company_id):
|
||||||
company_value = self.companies[company_id].get_value(self)
|
company_value = self.companies[company_id].get_value(self)
|
||||||
return company_value / 100
|
return round(company_value / 100.0, 2)
|
||||||
|
|
||||||
def update_market(self):
|
def update_market(self):
|
||||||
self.current_turn += 1
|
self.current_turn += 1
|
||||||
trend_adjustment = random.choice([2, -2, 0])
|
trend_adjustment = random.choice([2, -2, 0])
|
||||||
|
|
||||||
|
# Adjust prices based on inflation
|
||||||
self.products = self.adjust_prices(trend_adjustment)
|
self.products = self.adjust_prices(trend_adjustment)
|
||||||
|
|
||||||
event = random.choices(self.events, weights=[e["probability"] for e in self.events])[0]
|
event = random.choices(self.events, weights=[e["probability"] for e in self.events])[0]
|
||||||
if event["effect"] in ["new_competitor", "exit_competitor"]:
|
if event["effect"] in ["new_competitor", "exit_competitor"]:
|
||||||
self.handle_competitor_event(event["effect"])
|
self.handle_competitor_event(event["effect"])
|
||||||
else:
|
else:
|
||||||
self.products = {k: self.event_effects[event["effect"]](v) for k, v in self.products.items()}
|
self.products = {k: self.event_effects[event["effect"]](v) for k, v in self.products.items()}
|
||||||
print(f"Market Event: {event['name']}")
|
|
||||||
self.update_economic_indicators() # Update economic indicators each turn
|
self.update_economic_indicators() # Update economic indicators each turn
|
||||||
|
|
||||||
|
def adjust_prices(self):
|
||||||
|
# Apply inflation more subtly and cumulatively
|
||||||
|
for product, price in self.products.items():
|
||||||
|
# Apply inflation
|
||||||
|
inflation_adjustment = price * self.inflation_rate
|
||||||
|
new_price = price + inflation_adjustment
|
||||||
|
|
||||||
|
# Apply a very small random fluctuation for additional realism
|
||||||
|
fluctuation = random.uniform(-0.03, 0.03) # Slightly smaller range
|
||||||
|
new_price += fluctuation
|
||||||
|
|
||||||
|
# Ensure the price doesn't fall below a reasonable minimum (e.g., 1)
|
||||||
|
new_price = max(1, new_price)
|
||||||
|
|
||||||
|
# Update the price with rounding off to 2 decimal places
|
||||||
|
self.products[product] = round(new_price, 2)
|
||||||
|
|
||||||
|
return self.products
|
||||||
|
|
||||||
def handle_competitor_event(self, effect):
|
def handle_competitor_event(self, effect):
|
||||||
adjustment = random.randint(1, 3)
|
adjustment = random.randint(1, 3)
|
||||||
self.products = {k: max(1, v - adjustment) if effect == "new_competitor" else v + adjustment for k, v in
|
self.products = {k: max(1, v - adjustment) if effect == "new_competitor" else v + adjustment for k, v in
|
||||||
@ -78,7 +105,8 @@ class Market:
|
|||||||
final_score = company.get_value(self)
|
final_score = company.get_value(self)
|
||||||
|
|
||||||
# Determine the majority owner
|
# Determine the majority owner
|
||||||
majority_owner = max(company.own_stock_ownership, key=lambda owner: (company.own_stock_ownership[owner], 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]
|
majority_percentage = company.own_stock_ownership[majority_owner]
|
||||||
|
|
||||||
# Check if the majority owner owns 51% or more
|
# Check if the majority owner owns 51% or more
|
||||||
@ -111,21 +139,49 @@ class Market:
|
|||||||
class Company:
|
class Company:
|
||||||
def __init__(self, player_id, competitors_ids):
|
def __init__(self, player_id, competitors_ids):
|
||||||
self.player_id = player_id
|
self.player_id = player_id
|
||||||
self.cash = 100
|
self.cash = 500.0
|
||||||
self.inventory = {'A': 0, 'B': 0, 'C': 0}
|
self.inventory = {'A': 0, 'B': 0, 'C': 0}
|
||||||
self.crafting_queue = []
|
self.crafting_queue = []
|
||||||
# Initialize own stock ownership with player and competitors
|
|
||||||
self.own_stock_ownership = {self.player_id: 51} # Majority stock owned by the player
|
|
||||||
for cid in competitors_ids:
|
|
||||||
self.own_stock_ownership[cid] = 0
|
|
||||||
|
|
||||||
# Initialize other stock holdings
|
# Initialize stock ownership in the player's company
|
||||||
|
self.own_stock_ownership = {player_id: 51} # Player owns 51 shares of their company
|
||||||
|
for cid in competitors_ids:
|
||||||
|
self.own_stock_ownership[cid] = 0 # Competitors initially own no shares
|
||||||
|
|
||||||
|
# Initialize stock holdings in other companies
|
||||||
all_companies = competitors_ids + [player_id]
|
all_companies = competitors_ids + [player_id]
|
||||||
self.other_stock_holdings = {cid: 0 for cid in all_companies}
|
self.other_stock_holdings = {cid: 0 for cid in all_companies} # Player owns no shares in other companies initially
|
||||||
|
|
||||||
|
self.total_shares = 100 # Total shares per company
|
||||||
|
|
||||||
def get_value(self, market):
|
def get_value(self, market):
|
||||||
return self.cash + sum(self.inventory[product] * price for product, price in market.products.items())
|
return self.cash + sum(self.inventory[product] * price for product, price in market.products.items())
|
||||||
|
|
||||||
|
def trade_product(self, market, product, quantity, buying):
|
||||||
|
total_cost = round(market.products[product] * quantity, 2)
|
||||||
|
print("\nProduct Trading Decision")
|
||||||
|
products = list(market.products.keys())
|
||||||
|
print("\nAvailable Products:")
|
||||||
|
for idx, product in enumerate(products, 1):
|
||||||
|
print(f" {idx}: {product}")
|
||||||
|
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)
|
||||||
|
|
||||||
|
trade_type = self.get_user_choice(2, "Choose trade type (1: Buy, 2: Sell): ")
|
||||||
|
self.trade_product(market, product, quantity, buying=trade_type == 1)
|
||||||
|
|
||||||
|
def crafting_decision(self):
|
||||||
|
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):
|
def trade_product(self, market, product, quantity, buying):
|
||||||
total_cost = market.products[product] * quantity
|
total_cost = market.products[product] * quantity
|
||||||
if buying:
|
if buying:
|
||||||
@ -157,7 +213,7 @@ class Company:
|
|||||||
self.crafting_queue = [order for order in self.crafting_queue if order not in completed_orders]
|
self.crafting_queue = [order for order in self.crafting_queue if order not in completed_orders]
|
||||||
|
|
||||||
def trade_stock(self, action, market, company_id, amount):
|
def trade_stock(self, action, market, company_id, amount):
|
||||||
if company_id not in market.companies:
|
if company_id not in market.companies and company_id != self.player_id:
|
||||||
print("Company not found in the market.")
|
print("Company not found in the market.")
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -165,75 +221,169 @@ class Company:
|
|||||||
total_value = stock_price * amount
|
total_value = stock_price * amount
|
||||||
|
|
||||||
if action == 'buy':
|
if action == 'buy':
|
||||||
|
if company_id == self.player_id:
|
||||||
|
# Calculate available shares in the player's company
|
||||||
|
available_shares = self.total_shares - sum(self.own_stock_ownership.values()) + \
|
||||||
|
self.own_stock_ownership[self.player_id]
|
||||||
|
else:
|
||||||
|
# Calculate available shares in an AI company
|
||||||
|
available_shares = self.total_shares - self.other_stock_holdings[company_id]
|
||||||
|
|
||||||
|
if amount > available_shares:
|
||||||
|
print(f"Not enough available shares to buy. Available: {available_shares}")
|
||||||
|
return
|
||||||
|
|
||||||
if self.cash < total_value:
|
if self.cash < total_value:
|
||||||
print("Insufficient funds to buy stocks.")
|
print("Insufficient funds to buy stocks.")
|
||||||
return
|
return
|
||||||
|
|
||||||
self.cash -= total_value
|
self.cash -= total_value
|
||||||
self.other_stock_holdings[company_id] += amount
|
if company_id == self.player_id:
|
||||||
market.companies[company_id].own_stock_ownership[self.player_id] += amount
|
# Buying shares of the player's own company
|
||||||
|
self.own_stock_ownership[self.player_id] += amount
|
||||||
|
else:
|
||||||
|
# Buying shares of an AI company
|
||||||
|
self.other_stock_holdings[company_id] += amount
|
||||||
|
|
||||||
print(f"Bought {amount} stocks of {company_id}.")
|
print(f"Bought {amount} stocks of {company_id}.")
|
||||||
|
|
||||||
elif action == 'sell':
|
elif action == 'sell':
|
||||||
if self.other_stock_holdings[company_id] < amount:
|
if company_id == self.player_id:
|
||||||
print("Not enough stocks to sell.")
|
# Selling shares of the player's own company
|
||||||
return
|
if self.own_stock_ownership[self.player_id] < amount:
|
||||||
|
print("Not enough stocks to sell.")
|
||||||
|
return
|
||||||
|
self.own_stock_ownership[self.player_id] -= amount
|
||||||
|
else:
|
||||||
|
# Selling shares of an AI company
|
||||||
|
if self.other_stock_holdings.get(company_id, 0) < amount:
|
||||||
|
print("Not enough stocks to sell.")
|
||||||
|
return
|
||||||
|
self.other_stock_holdings[company_id] -= amount
|
||||||
|
|
||||||
self.cash += total_value
|
self.cash += total_value
|
||||||
self.other_stock_holdings[company_id] -= amount
|
|
||||||
market.companies[company_id].own_stock_ownership[self.player_id] -= amount
|
|
||||||
print(f"Sold {amount} stocks of {company_id}.")
|
print(f"Sold {amount} stocks of {company_id}.")
|
||||||
|
|
||||||
def make_decision(self, market, competitors):
|
def make_decision(self, market, competitors):
|
||||||
print(f"\n{self.player_id}'s Turn - Turn {market.current_turn}")
|
console = Console()
|
||||||
print(f"Cash: {self.cash}")
|
|
||||||
print(f"Inventory: {self.inventory}")
|
|
||||||
print(f"Market Prices: {market.products}")
|
|
||||||
print(f"Own Stock Ownership: {self.own_stock_ownership}")
|
|
||||||
print(f"Stock Holdings in Other Companies: {self.other_stock_holdings}")
|
|
||||||
|
|
||||||
while True:
|
# Enhanced table for player's status with Euro symbol
|
||||||
action = input("Choose an action (1: Trade Products, 2: Craft, 3: Trade Stocks, 4: Skip Turn): ")
|
status_table = Table(title=f"[bold green]{self.player_id}'s Turn - Turn {market.current_turn}", box=box.ROUNDED)
|
||||||
|
|
||||||
if action == '1':
|
status_table.add_column("Category", justify="left", style="bold cyan")
|
||||||
self.trade_products_decision(market)
|
status_table.add_column("Details", justify="left")
|
||||||
elif action == '2':
|
|
||||||
self.crafting_decision()
|
# Use colors to highlight key data
|
||||||
elif action == '3':
|
status_table.add_row("Cash", f"[bold yellow]{self.cash:.2f} €")
|
||||||
stock_action = input("Choose stock action (1: Buy, 2: Sell): ")
|
status_table.add_row("Inventory", ', '.join(
|
||||||
if stock_action == '1':
|
[f"[bold magenta]{item}: {quantity}" for item, quantity in self.inventory.items()]))
|
||||||
self.trade_stocks_decision('buy', market, competitors)
|
status_table.add_row("Market Prices", ', '.join(
|
||||||
elif stock_action == '2':
|
[f"[bold blue]{product}: {price:.2f} €" for product, price in market.products.items()]))
|
||||||
self.trade_stocks_decision('sell', market, competitors)
|
|
||||||
elif action == '4':
|
# Display shareholders and investments with color coding
|
||||||
break # Skip turn
|
shareholders = ', '.join(
|
||||||
else:
|
[f"[bold]{company}[/]: {ownership} shares" for company, ownership in self.own_stock_ownership.items()])
|
||||||
print("Invalid choice. Please enter a valid option.")
|
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 menu with clear choices
|
||||||
|
actions = {
|
||||||
|
"1": "Trade Products",
|
||||||
|
"2": "Craft",
|
||||||
|
"3": "Trade Stocks",
|
||||||
|
"4": "Skip Turn"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Display the choices to the player in an intuitive way
|
||||||
|
choices_display = "\n".join([f"{key}: {value}" for key, value in actions.items()])
|
||||||
|
console.print(f"Available Actions:\n{choices_display}", style="bold")
|
||||||
|
|
||||||
|
# Prompt for action choice
|
||||||
|
action_choice = Prompt.ask("Choose your action", choices=list(actions.keys()), default="4")
|
||||||
|
|
||||||
|
# Perform the selected action
|
||||||
|
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):
|
||||||
|
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)
|
||||||
|
|
||||||
|
trade_type = self.get_user_choice(2, "Choose trade type (1: Buy, 2: Sell): ")
|
||||||
|
self.trade_product(market, product, quantity, buying=trade_type == 1)
|
||||||
|
|
||||||
def trade_stocks_decision(self, action, market, competitors):
|
def trade_stocks_decision(self, action, market, competitors):
|
||||||
print("Stock Trading Decision")
|
print("\nStock Trading Decision")
|
||||||
|
|
||||||
# Common logic for displaying stock information
|
|
||||||
if action == 'buy':
|
if action == 'buy':
|
||||||
print("Available companies to buy stocks from:")
|
print("Available companies to buy stocks from:")
|
||||||
elif action == 'sell':
|
elif action == 'sell':
|
||||||
print("Your stock holdings:")
|
print("Your stock holdings:")
|
||||||
|
|
||||||
for competitor in competitors:
|
# Include the player's company in the list
|
||||||
stock_info = f"{competitor.player_id}: Current stock price - {market.get_stock_price(competitor.player_id)}"
|
companies = competitors + [self] # Assuming 'self' represents the player's company
|
||||||
if action == 'sell' and self.other_stock_holdings[competitor.player_id] > 0:
|
|
||||||
stock_info += f", Owned: {self.other_stock_holdings[competitor.player_id]}"
|
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)
|
print(stock_info)
|
||||||
|
|
||||||
company_id = input("Enter the company ID to trade stocks: ")
|
company_choice = self.get_user_choice(len(companies), "Enter the company number to trade stocks: ")
|
||||||
if company_id not in market.companies:
|
company_id = companies[company_choice - 1].player_id
|
||||||
print("Invalid company ID.")
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
amount = self.get_valid_input("Enter the amount of stocks to trade: ", int, "Stock amount must be positive.",
|
||||||
amount = int(input("Enter the amount of stocks to trade: "))
|
lambda x: x > 0)
|
||||||
if amount <= 0:
|
self.trade_stock(action, market, company_id, amount)
|
||||||
raise ValueError("Stock amount must be positive.")
|
|
||||||
self.trade_stock(action, market, company_id, amount)
|
@staticmethod
|
||||||
except ValueError as e:
|
def get_user_choice(num_options, prompt):
|
||||||
print(f"Invalid amount: {e}")
|
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):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
value = input_type(input(prompt))
|
||||||
|
if not validation_func(value):
|
||||||
|
raise ValueError
|
||||||
|
return value
|
||||||
|
except ValueError:
|
||||||
|
print(error_message)
|
||||||
|
|
||||||
|
|
||||||
class AICompany(Company):
|
class AICompany(Company):
|
||||||
@ -263,12 +413,14 @@ class AICompany(Company):
|
|||||||
break
|
break
|
||||||
elif action == 'buy':
|
elif action == 'buy':
|
||||||
for product, price in market.products.items():
|
for product, price in market.products.items():
|
||||||
if price < self.average_prices[product] * 0.9:
|
if price > 0: # Check to avoid division by zero
|
||||||
quantity = self.cash // price
|
quantity = self.cash // price
|
||||||
if quantity > 0:
|
if quantity > 0:
|
||||||
self.trade_product(market, product, quantity, True)
|
self.trade_product(market, product, quantity, True)
|
||||||
self.last_action = f"Bought {quantity} of {product}"
|
self.last_action = f"Bought {quantity} of {product}"
|
||||||
break
|
break
|
||||||
|
else:
|
||||||
|
print(f"Price for {product} is currently zero, skipping.")
|
||||||
|
|
||||||
def perform_stock_action(self, market, action):
|
def perform_stock_action(self, market, action):
|
||||||
company_id, amount = self.select_stock_action(market, action)
|
company_id, amount = self.select_stock_action(market, action)
|
||||||
@ -357,7 +509,7 @@ def main():
|
|||||||
market.companies = {"Player": player, "Rational AI": ai_competitors[0], "Risk-Taking AI": ai_competitors[1]}
|
market.companies = {"Player": player, "Rational AI": ai_competitors[0], "Risk-Taking AI": ai_competitors[1]}
|
||||||
|
|
||||||
for turn in range(10):
|
for turn in range(10):
|
||||||
print(f"\n--- Turn {turn + 1} ---")
|
print(f"\n---\n")
|
||||||
market.update_market()
|
market.update_market()
|
||||||
player.update_crafting()
|
player.update_crafting()
|
||||||
player.make_decision(market, ai_competitors)
|
player.make_decision(market, ai_competitors)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user