[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.

This commit is contained in:
Снесарев Максим 2026-01-30 18:42:35 +03:00
parent 73e4712119
commit a161988dbf
5 changed files with 21 additions and 17 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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: