AI improved
This commit is contained in:
parent
5ff9f68404
commit
4677ed637e
280
main.py
280
main.py
@ -1,24 +1,6 @@
|
|||||||
"""
|
"""
|
||||||
A simple business simulation game with a focus on market dynamics, crafting and trading.
|
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.
|
Note: Requires 'rich' and 'json' libraries for functionality.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -32,12 +14,13 @@ from rich.panel import Panel
|
|||||||
from rich.text import Text
|
from rich.text import Text
|
||||||
|
|
||||||
crafting_recipes = {
|
crafting_recipes = {
|
||||||
'recipe1': {'input': {'A': 4, 'B': 4}, 'output': {'C': 10}, 'turns': 3},
|
'Industrial Synthesis': {'input': {'Coal': 4, 'Copper': 4}, 'output': {'Conductor': 10}, 'turns': 3},
|
||||||
'recipe2': {'input': {'A': 1, 'B': 1}, 'output': {'C': 2}, 'turns': 2}
|
'Manual Synthesis': {'input': {'Coal': 1, 'Copper': 1}, 'output': {'Conductor': 2}, 'turns': 2}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
"""Initializes the game environment, runs the game loop."""
|
||||||
console = Console()
|
console = Console()
|
||||||
competitors_ids = ["Player", "RationalAI", "RiskTakingAI"]
|
competitors_ids = ["Player", "RationalAI", "RiskTakingAI"]
|
||||||
market = Market()
|
market = Market()
|
||||||
@ -52,7 +35,7 @@ def main():
|
|||||||
market.companies = {company.player_id: company for company in ai_competitors + [player]}
|
market.companies = {company.player_id: company for company in ai_competitors + [player]}
|
||||||
|
|
||||||
# Game loop
|
# Game loop
|
||||||
for turn in range(1, 11):
|
for turn in range(1, 27):
|
||||||
console.print(f"\n--- Turn {turn} ---\n", style="grey50")
|
console.print(f"\n--- Turn {turn} ---\n", style="grey50")
|
||||||
market.update_market()
|
market.update_market()
|
||||||
|
|
||||||
@ -67,6 +50,7 @@ def main():
|
|||||||
|
|
||||||
|
|
||||||
def load_json(filename):
|
def load_json(filename):
|
||||||
|
"""Loads and returns data from a JSON file specified by the filename."""
|
||||||
try:
|
try:
|
||||||
with open(filename) as file:
|
with open(filename) as file:
|
||||||
return json.load(file)
|
return json.load(file)
|
||||||
@ -76,41 +60,88 @@ def load_json(filename):
|
|||||||
|
|
||||||
|
|
||||||
class Market:
|
class Market:
|
||||||
|
"""
|
||||||
|
Represents the game's market, managing product prices, stock ledger, and economic indicators.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
current_turn (int): Counter for the game turn.
|
||||||
|
companies (dict): Stores company objects with their IDs.
|
||||||
|
products (dict): Current prices of products.
|
||||||
|
starting_prices (dict): Initial prices of products for comparison.
|
||||||
|
events (list): Potential market events affecting prices.
|
||||||
|
adjust_prices (function): Adjusts product prices based on trends.
|
||||||
|
event_effects (dict): Effects of market events on prices.
|
||||||
|
stock_ledger (dict): Tracks stock ownership.
|
||||||
|
inflation_rate (float): Inflation rate.
|
||||||
|
unemployment_rate (float): Unemployment rate.
|
||||||
|
gdp (float): Gross Domestic Product value.
|
||||||
|
|
||||||
|
The market is updated every turn.
|
||||||
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.current_turn = 0
|
self.current_turn = 0
|
||||||
self.companies = {}
|
self.companies = {}
|
||||||
self.products = {'A': 10.0, 'B': 15.0, 'C': 20.0}
|
self.products = {'Coal': 10.0, 'Copper': 15.0, 'Conductor': 20.0}
|
||||||
self.starting_prices = self.products.copy()
|
self.starting_prices = self.products.copy()
|
||||||
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.event_effects = {"double": lambda x: x * 2, "halve": lambda x: x / 2, "increase": lambda x: x + 3.0,
|
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)}
|
"decrease": lambda x: max(1, x - 3.0)}
|
||||||
self.stock_ledger = {}
|
self.stock_ledger = {}
|
||||||
self.inflation_rate = 0.02
|
self.inflation_rate = 0.05
|
||||||
self.unemployment_rate = 0.05
|
self.unemployment_rate = 0.05
|
||||||
self.gdp = 500000
|
self.gdp = 500000
|
||||||
|
self.trade_volume = 0
|
||||||
|
self.total_bought = {'Coal': 0, 'Copper': 0, 'Conductor': 0}
|
||||||
|
self.total_sold = {'Coal': 0, 'Copper': 0, 'Conductor': 0}
|
||||||
|
self.previous_prices = self.products.copy()
|
||||||
|
|
||||||
def update_stock_ledger(self, company_id, owner_id, amount):
|
def update_stock_ledger(self, company_id, owner_id, amount):
|
||||||
|
"""Updates the stock ledger for a given company and owner based on the transaction amount."""
|
||||||
self.stock_ledger[company_id, owner_id] = self.stock_ledger.get((company_id, owner_id), 0) + amount
|
self.stock_ledger[company_id, owner_id] = self.stock_ledger.get((company_id, owner_id), 0) + amount
|
||||||
|
|
||||||
def get_stock_ownership(self, company_id, owner_id):
|
def get_stock_ownership(self, company_id, owner_id):
|
||||||
|
"""Returns the number of stocks owned by a given owner for a specified company."""
|
||||||
return self.stock_ledger.get((company_id, owner_id), 0)
|
return self.stock_ledger.get((company_id, owner_id), 0)
|
||||||
|
|
||||||
def get_stock_price(self, company_id):
|
def get_stock_price(self, company_id):
|
||||||
|
"""Calculates and returns the current stock price for a specified company."""
|
||||||
return round(self.companies[company_id].value / 100.0, 2)
|
return round(self.companies[company_id].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])
|
self.previous_prices = self.products.copy()
|
||||||
self.products = self.adjust_prices(trend_adjustment)
|
# Adjust prices based on demand
|
||||||
|
for product in self.products.keys():
|
||||||
|
demand_factor = self.total_bought[product] - self.total_sold[product]
|
||||||
|
self.products[product] *= (1 + demand_factor * 0.05)
|
||||||
|
self.reset_trade_volumes()
|
||||||
|
|
||||||
|
# Update GDP
|
||||||
|
self.gdp += self.trade_volume * 0.1 # Example formula
|
||||||
|
self.trade_volume = 0
|
||||||
|
|
||||||
|
# Update inflation rate
|
||||||
|
self.inflation_rate += (self.gdp / 500000 - 1) * 0.05 # Example adjustment
|
||||||
|
|
||||||
|
# Handle market events
|
||||||
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()}
|
||||||
|
|
||||||
self.update_economic_indicators()
|
self.update_economic_indicators()
|
||||||
|
|
||||||
|
def reset_trade_volumes(self):
|
||||||
|
for product in self.total_bought.keys():
|
||||||
|
self.total_bought[product] = 0
|
||||||
|
self.total_sold[product] = 0
|
||||||
|
|
||||||
|
def record_trade(self, value):
|
||||||
|
self.trade_volume += value
|
||||||
|
|
||||||
def adjust_prices(self):
|
def adjust_prices(self):
|
||||||
|
"""Adjusts product prices in the market based on inflation and random fluctuations."""
|
||||||
for product, price in self.products.items():
|
for product, price in self.products.items():
|
||||||
inflation_adjustment = price * self.inflation_rate
|
inflation_adjustment = price * self.inflation_rate
|
||||||
fluctuation = random.uniform(-0.03, 0.03)
|
fluctuation = random.uniform(-0.03, 0.03)
|
||||||
@ -118,16 +149,19 @@ class Market:
|
|||||||
return self.products
|
return self.products
|
||||||
|
|
||||||
def handle_competitor_event(self, effect):
|
def handle_competitor_event(self, effect):
|
||||||
|
"""Handles market events related to competitors, adjusting product prices accordingly."""
|
||||||
adjustment = float(random.randint(1, 3))
|
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 = {k: max(1.0, v - adjustment) if effect == "new_competitor" else v + adjustment for k, v in
|
||||||
self.products.items()}
|
self.products.items()}
|
||||||
|
|
||||||
def update_economic_indicators(self):
|
def update_economic_indicators(self):
|
||||||
|
"""Updates key economic indicators like inflation and unemployment rates."""
|
||||||
self.inflation_rate = max(0.5, self.inflation_rate + random.uniform(-0.01, 0.01))
|
self.inflation_rate = max(0.5, self.inflation_rate + random.uniform(-0.01, 0.01))
|
||||||
self.unemployment_rate = min(max(self.unemployment_rate + random.uniform(-0.005, 0.005), 0), 1)
|
self.unemployment_rate = min(max(self.unemployment_rate + random.uniform(-0.005, 0.005), 0), 1)
|
||||||
self.gdp += self.gdp * (random.uniform(-0.01, 0.03) + self.inflation_rate)
|
self.gdp += self.gdp * (random.uniform(-0.01, 0.03) + self.inflation_rate)
|
||||||
|
|
||||||
def calculate_final_scores(self):
|
def calculate_final_scores(self):
|
||||||
|
"""Calculates and returns final scores for each company based on value and stock ownership."""
|
||||||
final_scores = {}
|
final_scores = {}
|
||||||
for company_id, company in self.companies.items():
|
for company_id, company in self.companies.items():
|
||||||
final_score = company.value
|
final_score = company.value
|
||||||
@ -149,12 +183,24 @@ class Market:
|
|||||||
|
|
||||||
|
|
||||||
class Company:
|
class Company:
|
||||||
"""Represents a company within the market, managing finances, inventory, and stock transactions."""
|
"""
|
||||||
|
Base class for a company in the game, handling inventory, stock, and financial transactions.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
player_id (str): Unique identifier for the company.
|
||||||
|
cash (float): Available cash for transactions.
|
||||||
|
inventory (dict): Current inventory of products.
|
||||||
|
crafting_queue (list): Queue of products being crafted.
|
||||||
|
own_stock_ownership (dict): Ownership percentage of own stocks.
|
||||||
|
stock_holdings (dict): Holdings of other companies' stocks.
|
||||||
|
total_shares (int): Total shares available in the 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):
|
def __init__(self, player_id, competitors_ids, market=None, debug=False):
|
||||||
self.player_id = player_id
|
self.player_id = player_id
|
||||||
self.cash = 500.0
|
self.cash = 500.0
|
||||||
self.inventory = {'A': 0, 'B': 0, 'C': 0}
|
self.inventory = {'Coal': 0, 'Copper': 0, 'Conductor': 0}
|
||||||
self.crafting_queue = []
|
self.crafting_queue = []
|
||||||
self.own_stock_ownership = {cid: 51 if cid == player_id else 0 for cid in [player_id] + competitors_ids}
|
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"])}
|
self.stock_holdings = {cid: 0 for cid in set([player_id] + competitors_ids + ["RationalAI", "RiskTakingAI"])}
|
||||||
@ -216,14 +262,24 @@ class Company:
|
|||||||
print(f"Crafting queue after update: {self.crafting_queue}")
|
print(f"Crafting queue after update: {self.crafting_queue}")
|
||||||
|
|
||||||
def trade_product(self, market, product, quantity, buying=True):
|
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
|
total_cost = market.products[product] * quantity
|
||||||
if buying and self.cash >= total_cost:
|
|
||||||
|
if buying:
|
||||||
|
if self.cash >= total_cost:
|
||||||
self.cash -= total_cost
|
self.cash -= total_cost
|
||||||
self.inventory[product] += quantity
|
self.inventory[product] += quantity
|
||||||
elif not buying and self.inventory[product] >= quantity:
|
market.total_bought[product] += quantity # Record the purchase in the market
|
||||||
|
market.record_trade(total_cost) # Update the market's trade volume
|
||||||
|
else:
|
||||||
|
print("Insufficient funds to complete purchase.")
|
||||||
|
else:
|
||||||
|
if self.inventory[product] >= quantity:
|
||||||
self.cash += total_cost
|
self.cash += total_cost
|
||||||
self.inventory[product] -= quantity
|
self.inventory[product] -= quantity
|
||||||
|
market.total_sold[product] += quantity # Record the sale in the market
|
||||||
|
market.record_trade(total_cost) # Update the market's trade volume
|
||||||
|
else:
|
||||||
|
print("Insufficient inventory to complete sale.")
|
||||||
|
|
||||||
def crafting_decision(self):
|
def crafting_decision(self):
|
||||||
"""Displays crafting options and handles the user's crafting choice."""
|
"""Displays crafting options and handles the user's crafting choice."""
|
||||||
@ -252,7 +308,7 @@ class Company:
|
|||||||
|
|
||||||
def _buy_stock(self, company_id, amount, total_value, is_ai):
|
def _buy_stock(self, company_id, amount, total_value, is_ai):
|
||||||
"""Handles the buying of stocks for the specified company."""
|
"""Handles the buying of stocks for the specified company."""
|
||||||
available_shares = self._calculate_available_shares(company_id)
|
available_shares = self._calculate_available_shares()
|
||||||
if amount > available_shares:
|
if amount > available_shares:
|
||||||
return f"Not enough available shares to buy. Available: {available_shares}"
|
return f"Not enough available shares to buy. Available: {available_shares}"
|
||||||
|
|
||||||
@ -260,10 +316,17 @@ class Company:
|
|||||||
return "Insufficient funds to buy stocks."
|
return "Insufficient funds to buy stocks."
|
||||||
|
|
||||||
# Update stock ownership
|
# Update stock ownership
|
||||||
if is_ai:
|
if company_id == self.player_id:
|
||||||
self.stock_holdings[company_id] += amount # Increase AI's stock holdings
|
# Buying own company's stock
|
||||||
|
self.own_stock_ownership[self.player_id] += amount
|
||||||
else:
|
else:
|
||||||
self.own_stock_ownership[company_id] += amount # Increase player's own stock holdings
|
# Buying another company's stock
|
||||||
|
if is_ai:
|
||||||
|
# For AI
|
||||||
|
self.stock_holdings[company_id] += amount
|
||||||
|
else:
|
||||||
|
# For player
|
||||||
|
self.stock_holdings[company_id] += amount
|
||||||
|
|
||||||
self.cash -= total_value # Deduct the cost from the buyer's cash
|
self.cash -= total_value # Deduct the cost from the buyer's cash
|
||||||
return f"Bought {amount} stocks of {company_id}."
|
return f"Bought {amount} stocks of {company_id}."
|
||||||
@ -283,7 +346,7 @@ class Company:
|
|||||||
self.cash += total_value # Add the proceeds to the seller's cash
|
self.cash += total_value # Add the proceeds to the seller's cash
|
||||||
return f"Sold {amount} stocks of {company_id}."
|
return f"Sold {amount} stocks of {company_id}."
|
||||||
|
|
||||||
def _calculate_available_shares(self, company_id):
|
def _calculate_available_shares(self):
|
||||||
"""Calculates the number of available shares for a given company."""
|
"""Calculates the number of available shares for a given company."""
|
||||||
total_owned = sum(self.stock_holdings.values()) + sum(self.own_stock_ownership.values())
|
total_owned = sum(self.stock_holdings.values()) + sum(self.own_stock_ownership.values())
|
||||||
return self.total_shares - total_owned
|
return self.total_shares - total_owned
|
||||||
@ -309,33 +372,54 @@ class Company:
|
|||||||
self.cash += -total_value if buying else total_value
|
self.cash += -total_value if buying else total_value
|
||||||
|
|
||||||
def make_decision(self, market, competitors):
|
def make_decision(self, market, competitors):
|
||||||
"""Presents decision options to the user and processes the chosen action."""
|
|
||||||
console = Console()
|
console = Console()
|
||||||
status_table = Table(title=f"[bold cyan]{self.player_id}'s Turn - Turn {market.current_turn}", box=box.ROUNDED)
|
status_table = Table(title=f"[bold cyan]{self.player_id}'s Turn - Turn {market.current_turn}", box=box.ROUNDED)
|
||||||
|
|
||||||
|
# Cash Row
|
||||||
status_table.add_column("Category", style="bold cyan")
|
status_table.add_column("Category", style="bold cyan")
|
||||||
status_table.add_column("Details")
|
status_table.add_column("Details")
|
||||||
status_table.add_row("Cash", f"[bold blue]{self.cash:.2f} €")
|
status_table.add_row("Cash", f"[bold blue]{self.cash:.2f} €")
|
||||||
status_table.add_row("Inventory", ', '.join(
|
|
||||||
[f"[bold]{item}: {quantity}" for item, quantity in self.inventory.items()]))
|
# Inventory Row
|
||||||
status_table.add_row("Market Prices", ', '.join(
|
inventory_display = ', '.join([f"[bold]{item}: {quantity}" for item, quantity in self.inventory.items()])
|
||||||
[f"[bold blue]{product}: {price:.2f} €" for product, price in market.products.items()]))
|
status_table.add_row("Inventory", inventory_display)
|
||||||
|
|
||||||
|
# Market Prices Row with Color Coding and Emojis
|
||||||
|
price_info = []
|
||||||
|
for product, price in market.products.items():
|
||||||
|
price_change = price - market.previous_prices.get(product, price)
|
||||||
|
if price_change > 0:
|
||||||
|
price_info.append(f"[green]{product}: {price:.2f} € :arrow_up_small:") # Green color and up emoji
|
||||||
|
elif price_change < 0:
|
||||||
|
price_info.append(f"[red]{product}: {price:.2f} € :arrow_down_small:") # Red color and down emoji
|
||||||
|
else:
|
||||||
|
price_info.append(f"{product}: {price:.2f} €") # Default color (no change)
|
||||||
|
status_table.add_row("Market Prices", ', '.join(price_info))
|
||||||
|
|
||||||
|
# Shareholders Row
|
||||||
shareholders = ', '.join(
|
shareholders = ', '.join(
|
||||||
[f"[bold]{company}[/]: {ownership} shares" for company, ownership in self.own_stock_ownership.items()])
|
[f"[bold]{company}[/]: {ownership} shares" for company, ownership in self.own_stock_ownership.items()])
|
||||||
status_table.add_row("Your Shareholders", shareholders)
|
status_table.add_row("Your Shareholders", shareholders)
|
||||||
|
|
||||||
|
# Investments Row
|
||||||
investments = ', '.join(
|
investments = ', '.join(
|
||||||
[f"[bold]{company}[/]: {holding} shares" for company, holding in self.stock_holdings.items() if
|
[f"[bold]{company}[/]: {holding} shares" for company, holding in self.stock_holdings.items() if
|
||||||
holding > 0])
|
holding > 0])
|
||||||
status_table.add_row("Your Investments", investments)
|
status_table.add_row("Your Investments", investments)
|
||||||
|
|
||||||
console.print(status_table)
|
console.print(status_table)
|
||||||
|
|
||||||
|
# Action Choices
|
||||||
actions = {
|
actions = {
|
||||||
"1": "Trade Products",
|
"1": "Trade Products",
|
||||||
"2": "Craft",
|
"2": "Craft",
|
||||||
"3": "Trade Stocks",
|
"3": "Trade Stocks",
|
||||||
"4": "Skip Turn"
|
"4": "Skip Turn"
|
||||||
}
|
}
|
||||||
|
|
||||||
choices_display = "\n".join([f"{key}: {value}" for key, value in actions.items()])
|
choices_display = "\n".join([f"{key}: {value}" for key, value in actions.items()])
|
||||||
console.print(f"Available Actions:\n{choices_display}", style="bold")
|
console.print(f"Available Actions:\n{choices_display}", style="bold")
|
||||||
|
|
||||||
|
# Action Selection
|
||||||
action_choice = Prompt.ask("Choose your action", default="4")
|
action_choice = Prompt.ask("Choose your action", default="4")
|
||||||
selected_action = actions.get(action_choice, None)
|
selected_action = actions.get(action_choice, None)
|
||||||
|
|
||||||
@ -422,11 +506,17 @@ class Company:
|
|||||||
return all(price > 20 for price in self._market.products.values())
|
return all(price > 20 for price in self._market.products.values())
|
||||||
|
|
||||||
|
|
||||||
def is_market_bust(market):
|
|
||||||
return all(price < 0.75 * market.starting_prices[product] for product, price in market.products.items())
|
|
||||||
|
|
||||||
|
|
||||||
class AICompany(Company):
|
class AICompany(Company):
|
||||||
|
"""
|
||||||
|
AI Company. Inherits from the Company class and adds AI-specific decision-making based on risk tolerance.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
risk_tolerance (float): A value representing the AI's willingness to take risks, influencing its decisions.
|
||||||
|
actions_history (list): Records the history of actions taken by the AI.
|
||||||
|
average_prices (dict): Tracks the average market prices of products for strategic decision-making.
|
||||||
|
|
||||||
|
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):
|
def __init__(self, player_id, competitors_ids, market, risk_tolerance):
|
||||||
super().__init__(player_id, competitors_ids, market)
|
super().__init__(player_id, competitors_ids, market)
|
||||||
self.risk_tolerance = risk_tolerance
|
self.risk_tolerance = risk_tolerance
|
||||||
@ -434,70 +524,119 @@ class AICompany(Company):
|
|||||||
self.average_prices = {product: market.products[product] for product in market.products}
|
self.average_prices = {product: market.products[product] for product in market.products}
|
||||||
|
|
||||||
def update_average_prices(self):
|
def update_average_prices(self):
|
||||||
self.average_prices = {product: (self.average_prices[product] * (self._market.current_turn - 1) + price) / self._market.current_turn
|
"""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
|
||||||
for product, price in self._market.products.items()}
|
for product, price in self._market.products.items()}
|
||||||
|
|
||||||
def make_decision(self, market, competitors):
|
def make_decision(self, market, competitors):
|
||||||
if self.risk_tolerance > 0.5: # High-Risk AI
|
if self.risk_tolerance > 0.5: # High-Risk AI
|
||||||
self.high_risk_decision(market, competitors)
|
self.high_risk_decision(market)
|
||||||
else: # Low-Risk AI
|
else: # Low-Risk AI
|
||||||
self.low_risk_decision(market, competitors)
|
self.low_risk_decision(market)
|
||||||
|
|
||||||
def low_risk_decision(self, market, competitors):
|
def low_risk_decision(self, market):
|
||||||
|
"""
|
||||||
|
Defines the decision-making process for a low-risk AI player.
|
||||||
|
"""
|
||||||
if market.current_turn == 1:
|
if market.current_turn == 1:
|
||||||
self.buy_product('A', self.cash / 3)
|
self.buy_product('Coal', self.cash / 3)
|
||||||
elif market.current_turn == 2:
|
elif market.current_turn == 2:
|
||||||
self.buy_product('B', min(self.inventory['A'], self.cash / market.products['B']))
|
self.buy_product('Copper', min(self.inventory['Coal'], self.cash / market.products['Copper']))
|
||||||
elif market.current_turn >= 3:
|
elif market.current_turn >= 3:
|
||||||
self.buy_and_craft(market)
|
self.buy_and_craft()
|
||||||
|
|
||||||
def high_risk_decision(self, market, competitors):
|
def high_risk_decision(self, market):
|
||||||
|
"""
|
||||||
|
Defines the decision-making process for a high-risk AI player.
|
||||||
|
"""
|
||||||
if market.current_turn == 1:
|
if market.current_turn == 1:
|
||||||
self.sell_own_shares(market)
|
self.sell_own_shares(market)
|
||||||
self.buy_product('A', self.cash / 2)
|
self.buy_product('Coal', self.cash / 2)
|
||||||
self.buy_product('B', self.cash)
|
self.buy_product('Copper', self.cash)
|
||||||
else:
|
else:
|
||||||
if self.should_craft(market):
|
if self.should_craft():
|
||||||
self.buy_and_craft(market)
|
self.buy_and_craft()
|
||||||
if self.should_sell_products(market):
|
if self.should_sell_products(market):
|
||||||
self.sell_high_value_products(market)
|
self.sell_high_value_products(market)
|
||||||
|
if market.current_turn > 6:
|
||||||
|
self.buy_stocks_strategy()
|
||||||
|
|
||||||
def buy_product(self, product, budget):
|
def buy_product(self, product, budget):
|
||||||
|
"""
|
||||||
|
Buys a specific quantity of a product for the AI company.
|
||||||
|
"""
|
||||||
quantity = int(budget // self._market.products[product])
|
quantity = int(budget // self._market.products[product])
|
||||||
if quantity > 0:
|
if quantity > 0:
|
||||||
self.trade_product(self._market, product, quantity)
|
self.trade_product(self._market, product, quantity)
|
||||||
action = f"Bought {quantity} of {product}"
|
action = f"Bought {quantity} of {product}"
|
||||||
self.actions_history.append(action)
|
self.actions_history.append(action)
|
||||||
|
|
||||||
|
def buy_stocks_strategy(self):
|
||||||
|
own_stock_left = 100 - self.own_stock_ownership[self.player_id]
|
||||||
|
if own_stock_left > 0:
|
||||||
|
stock_price = self._market.get_stock_price(self.player_id)
|
||||||
|
amount_to_buy = min(own_stock_left, int(self.cash / stock_price))
|
||||||
|
if amount_to_buy > 0:
|
||||||
|
action = f"{self.player_id} is buying its own stock. Amount to buy: {amount_to_buy}"
|
||||||
|
self.actions_history.append(action)
|
||||||
|
self.trade_stock('buy', self._market, self.player_id, amount_to_buy, is_ai=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
for company_id in self.stock_holdings:
|
||||||
|
if company_id != self.player_id:
|
||||||
|
stock_price = self._market.get_stock_price(company_id)
|
||||||
|
if stock_price <= self.cash:
|
||||||
|
amount_to_buy = int(self.cash / stock_price)
|
||||||
|
print(f"{self.player_id} is buying {company_id}'s stock. Amount to buy: {amount_to_buy}")
|
||||||
|
self.trade_stock('buy', self._market, company_id, amount_to_buy, is_ai=True)
|
||||||
|
return
|
||||||
|
|
||||||
def sell_own_shares(self, market):
|
def sell_own_shares(self, market):
|
||||||
|
"""
|
||||||
|
Sells a portion of the AI company's own shares.
|
||||||
|
"""
|
||||||
amount_to_sell = int(self.own_stock_ownership[self.player_id] * 0.25) # Sell 25% of own shares
|
amount_to_sell = int(self.own_stock_ownership[self.player_id] * 0.25) # Sell 25% of own shares
|
||||||
if amount_to_sell > 0:
|
if amount_to_sell > 0:
|
||||||
self.trade_stock('sell', market, self.player_id, amount_to_sell, is_ai=True)
|
self.trade_stock('sell', market, self.player_id, amount_to_sell, is_ai=True)
|
||||||
action = f"Sold {amount_to_sell} of own shares"
|
action = f"Sold {amount_to_sell} of own shares"
|
||||||
self.actions_history.append(action)
|
self.actions_history.append(action)
|
||||||
|
|
||||||
def should_craft(self, market):
|
def should_craft(self):
|
||||||
return all(self.inventory[product] >= qty for product, qty in crafting_recipes['recipe2']['input'].items())
|
"""
|
||||||
|
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())
|
||||||
|
|
||||||
def should_sell_products(self, market):
|
def should_sell_products(self, market):
|
||||||
return any(market.products[product] >= 2 * self.average_prices[product] for product in self.inventory if self.inventory[product] > 0)
|
"""
|
||||||
|
Decides if the AI should sell products based on market prices.
|
||||||
|
"""
|
||||||
|
return any(market.products[product] >= 2 * self.average_prices[product] for product in self.inventory if
|
||||||
|
self.inventory[product] > 0)
|
||||||
|
|
||||||
def sell_high_value_products(self, market):
|
def sell_high_value_products(self, market):
|
||||||
|
"""
|
||||||
|
Decides if the AI should sell products based on market prices.
|
||||||
|
"""
|
||||||
for product, quantity in self.inventory.items():
|
for product, quantity in self.inventory.items():
|
||||||
if quantity > 0 and market.products[product] >= 2 * self.average_prices[product]:
|
if quantity > 0 and market.products[product] >= 2 * self.average_prices[product]:
|
||||||
self.trade_product(market, product, quantity, buying=False)
|
self.trade_product(market, product, quantity, buying=False)
|
||||||
action = f"Sold high value products"
|
action = f"Sold high value products"
|
||||||
self.actions_history.append(action)
|
self.actions_history.append(action)
|
||||||
|
|
||||||
def buy_and_craft(self, market):
|
def buy_and_craft(self):
|
||||||
chosen_recipe = crafting_recipes['recipe2']
|
"""
|
||||||
|
Executes buying of resources and crafting of products for the AI.
|
||||||
|
"""
|
||||||
|
chosen_recipe = crafting_recipes['Manual Synthesis']
|
||||||
if all(self.inventory[product] >= qty for product, qty in chosen_recipe['input'].items()):
|
if all(self.inventory[product] >= qty for product, qty in chosen_recipe['input'].items()):
|
||||||
self.craft_product('recipe2')
|
self.craft_product('Manual Synthesis')
|
||||||
print(f"Crafting using recipe2")
|
print(f"Crafting using Manual Synthesis")
|
||||||
action = "Crafted products using recipe2"
|
action = "Crafted products using Manual Synthesis"
|
||||||
self.actions_history.append(action)
|
self.actions_history.append(action)
|
||||||
else:
|
else:
|
||||||
print("Not enough resources to craft using recipe2")
|
print("Not enough resources to craft using Manual Synthesis")
|
||||||
|
|
||||||
|
|
||||||
def print_ai_actions(ai_competitors):
|
def print_ai_actions(ai_competitors):
|
||||||
@ -509,17 +648,16 @@ def print_ai_actions(ai_competitors):
|
|||||||
|
|
||||||
# List all actions
|
# List all actions
|
||||||
for idx, action in enumerate(ai.actions_history, 1):
|
for idx, action in enumerate(ai.actions_history, 1):
|
||||||
panel_text.append(f"{idx}. Action: {action}\n", style="bold cyan")
|
panel_text.append(f"{idx}. Action: {action}\n", style="grey50")
|
||||||
|
|
||||||
# Append current cash and inventory to the text
|
# Append current cash and inventory to the text
|
||||||
panel_text.append(f"\nCurrent Cash: {ai.cash:.2f} €\n", style="bold yellow")
|
panel_text.append(f"\nCurrent Cash: {ai.cash:.2f} €\n", style="bold blue")
|
||||||
panel_text.append(f"Inventory: {inventory_text}", style="bold magenta")
|
panel_text.append(f"Inventory: {inventory_text}", style="bold cyan")
|
||||||
|
|
||||||
# Display in a panel
|
# Display in a panel
|
||||||
console.print(Panel(panel_text, title=f"[bold]{ai.player_id}'s Status", border_style="grey50"))
|
console.print(Panel(panel_text, title=f"[bold]{ai.player_id}'s Status", border_style="grey50"))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def display_final_scores(console, final_scores, market):
|
def display_final_scores(console, final_scores, market):
|
||||||
"""Displays the final scores in a styled table."""
|
"""Displays the final scores in a styled table."""
|
||||||
score_table = Table(header_style="bold cyan", box=box.DOUBLE_EDGE)
|
score_table = Table(header_style="bold cyan", box=box.DOUBLE_EDGE)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user