From a161988dbfe14b41183047a94aceff188a38a76b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=BD=D0=B5=D1=81=D0=B0=D1=80=D0=B5=D0=B2=20=D0=9C?= =?UTF-8?q?=D0=B0=D0=BA=D1=81=D0=B8=D0=BC?= Date: Fri, 30 Jan 2026 18:42:35 +0300 Subject: [PATCH] [upd] Refine energy cost calculations and enhance price adjustments in market and BDI agent logic. Implement rounding for improved accuracy in financial computations and adjust supply/demand thresholds for better market dynamics. --- backend/core/ai.py | 2 +- backend/core/bdi/bdi_agent.py | 13 ++++++++----- backend/core/goap/action.py | 2 +- backend/core/goap/actions.py | 6 +++--- backend/core/market.py | 15 ++++++++------- 5 files changed, 21 insertions(+), 17 deletions(-) diff --git a/backend/core/ai.py b/backend/core/ai.py index 08667be..26cb077 100644 --- a/backend/core/ai.py +++ b/backend/core/ai.py @@ -103,7 +103,7 @@ def get_energy_cost(resource_type: ResourceType) -> int: return 10 energy_cost = abs(config.energy_cost) avg_output = max(1, (config.min_output + config.max_output) / 2) if config.output_resource else 1 - return int(energy_cost / avg_output) + return int(round(energy_cost / avg_output)) # Cached config values to avoid repeated lookups diff --git a/backend/core/bdi/bdi_agent.py b/backend/core/bdi/bdi_agent.py index df52bd1..9af39f8 100644 --- a/backend/core/bdi/bdi_agent.py +++ b/backend/core/bdi/bdi_agent.py @@ -438,6 +438,7 @@ class BDIAgentAI: return self._create_gather_fallback(target_resource, reason, goal, plan, bdi_info) # Calculate quantity to buy + # Use max(1, ...) to avoid division by zero can_afford = self.agent.money // max(1, order.price_per_unit) space = self.agent.inventory_space() quantity = min(2, can_afford, space, order.quantity) @@ -540,7 +541,7 @@ class BDIAgentAI: min_price = getattr(economy, 'min_price', 100) if economy else 100 energy_cost = get_energy_cost(resource_type) - fair_value = max(min_price, int(energy_cost * energy_to_money_ratio)) + fair_value = max(min_price, int(round(energy_cost * energy_to_money_ratio))) # Apply trading skill sell_modifier = get_trade_price_modifier(self.skills.trading, is_buying=False) @@ -549,15 +550,17 @@ class BDIAgentAI: signal = self.market.get_market_signal(resource_type) if signal == "sell": # Scarcity - price = int(fair_value * 1.3 * sell_modifier) + price = int(round(fair_value * 1.3 * sell_modifier)) elif signal == "hold": - price = int(fair_value * sell_modifier) + price = int(round(fair_value * sell_modifier)) else: # Surplus cheapest = self.market.get_cheapest_order(resource_type) if cheapest and cheapest.seller_id != self.agent.id: - price = max(min_price, cheapest.price_per_unit - 1) + # Undercut, but respect floor (80% of fair value or min_price) + floor_price = max(min_price, int(round(fair_value * 0.8))) + price = max(floor_price, cheapest.price_per_unit - 1) else: - price = int(fair_value * 0.8 * sell_modifier) + price = int(round(fair_value * 0.8 * sell_modifier)) return max(min_price, price) diff --git a/backend/core/goap/action.py b/backend/core/goap/action.py index 9b58bcd..982ab44 100644 --- a/backend/core/goap/action.py +++ b/backend/core/goap/action.py @@ -296,7 +296,7 @@ def create_buy_action(resource_type: ResourceType) -> GOAPAction: def cost(state: WorldState) -> float: # Trading cost is low (1 energy) - base_cost = 0.5 + base_cost = 0.2 # MILD profession effect for trading (everyone should be able to trade) # Traders get a bonus, but non-traders shouldn't be heavily penalized diff --git a/backend/core/goap/actions.py b/backend/core/goap/actions.py index e734f0e..22b4b29 100644 --- a/backend/core/goap/actions.py +++ b/backend/core/goap/actions.py @@ -133,8 +133,8 @@ def _create_hunt() -> GOAPAction: def effects(state: WorldState) -> dict: # Account for success chance - effective_meat = int(expected * config.success_chance) - effective_hide = int(1 * config.success_chance) # Average hide + effective_meat = int(round(expected * config.success_chance)) + effective_hide = int(round(1 * config.success_chance)) # Average hide energy_spent = abs(config.energy_cost) / 50.0 @@ -295,7 +295,7 @@ def _create_sell_action(resource_type: ResourceType, min_keep: int = 1) -> GOAPA def effects(state: WorldState) -> dict: # Estimate we'll get a reasonable price (around min_price from config) # This is approximate - actual execution will get real prices - estimated_price = 100 # Base estimate (min_price from config) + estimated_price = 150 # Better estimate than min_price (fair value) current = getattr(state, count_name) sell_qty = min(3, current - min_keep) # Sell up to 3, keep minimum diff --git a/backend/core/market.py b/backend/core/market.py index ba27c96..d434567 100644 --- a/backend/core/market.py +++ b/backend/core/market.py @@ -63,7 +63,7 @@ class Order: def apply_discount(self, percentage: float = 0.1) -> None: """Apply a discount to the price.""" min_price = _get_min_price() - reduction = max(1, int(self.price_per_unit * percentage)) + reduction = max(1, int(round(self.price_per_unit * percentage))) self.price_per_unit = max(min_price, self.price_per_unit - reduction) def adjust_price(self, new_price: int, current_turn: int) -> bool: @@ -154,9 +154,9 @@ class OrderBook: DISCOUNT_RATE: float = 0.12 # Supply/demand thresholds - LOW_SUPPLY_THRESHOLD: int = 3 # Less than this = scarcity - HIGH_SUPPLY_THRESHOLD: int = 10 # More than this = surplus - DEMAND_DECAY: float = 0.95 # How fast demand score decays per turn + LOW_SUPPLY_THRESHOLD: int = 10 # Less than this = scarcity + HIGH_SUPPLY_THRESHOLD: int = 50 # More than this = surplus + DEMAND_DECAY: float = 0.99 # How fast demand score decays per turn def __post_init__(self): """Initialize price history and load config values.""" @@ -266,7 +266,8 @@ class OrderBook: total_cost = actual_quantity * order.price_per_unit if buyer_money < total_cost: # Try to buy what they can afford - actual_quantity = buyer_money // order.price_per_unit + # Use max(1, ...) to avoid division by zero, though price is min 100 + actual_quantity = buyer_money // max(1, order.price_per_unit) if actual_quantity <= 0: return TradeResult( success=False, @@ -376,7 +377,7 @@ class OrderBook: # Use average sale price as reference if available reference_price = base_price if history.avg_sale_price > 0: - reference_price = int((base_price + history.avg_sale_price) / 2) + reference_price = int(round((base_price + history.avg_sale_price) / 2)) # Adjust based on supply/demand if ratio < 0.7: # Scarcity - raise price @@ -387,7 +388,7 @@ class OrderBook: else: price_multiplier = 1.0 - suggested = int(reference_price * price_multiplier) + suggested = int(round(reference_price * price_multiplier)) return max(_get_min_price(), suggested) def adjust_order_price(self, order_id: str, seller_id: str, new_price: int, current_turn: int) -> bool: