[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:
parent
73e4712119
commit
a161988dbf
@ -103,7 +103,7 @@ def get_energy_cost(resource_type: ResourceType) -> int:
|
|||||||
return 10
|
return 10
|
||||||
energy_cost = abs(config.energy_cost)
|
energy_cost = abs(config.energy_cost)
|
||||||
avg_output = max(1, (config.min_output + config.max_output) / 2) if config.output_resource else 1
|
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
|
# Cached config values to avoid repeated lookups
|
||||||
|
|||||||
@ -438,6 +438,7 @@ class BDIAgentAI:
|
|||||||
return self._create_gather_fallback(target_resource, reason, goal, plan, bdi_info)
|
return self._create_gather_fallback(target_resource, reason, goal, plan, bdi_info)
|
||||||
|
|
||||||
# Calculate quantity to buy
|
# Calculate quantity to buy
|
||||||
|
# Use max(1, ...) to avoid division by zero
|
||||||
can_afford = self.agent.money // max(1, order.price_per_unit)
|
can_afford = self.agent.money // max(1, order.price_per_unit)
|
||||||
space = self.agent.inventory_space()
|
space = self.agent.inventory_space()
|
||||||
quantity = min(2, can_afford, space, order.quantity)
|
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
|
min_price = getattr(economy, 'min_price', 100) if economy else 100
|
||||||
|
|
||||||
energy_cost = get_energy_cost(resource_type)
|
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
|
# Apply trading skill
|
||||||
sell_modifier = get_trade_price_modifier(self.skills.trading, is_buying=False)
|
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)
|
signal = self.market.get_market_signal(resource_type)
|
||||||
|
|
||||||
if signal == "sell": # Scarcity
|
if signal == "sell": # Scarcity
|
||||||
price = int(fair_value * 1.3 * sell_modifier)
|
price = int(round(fair_value * 1.3 * sell_modifier))
|
||||||
elif signal == "hold":
|
elif signal == "hold":
|
||||||
price = int(fair_value * sell_modifier)
|
price = int(round(fair_value * sell_modifier))
|
||||||
else: # Surplus
|
else: # Surplus
|
||||||
cheapest = self.market.get_cheapest_order(resource_type)
|
cheapest = self.market.get_cheapest_order(resource_type)
|
||||||
if cheapest and cheapest.seller_id != self.agent.id:
|
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:
|
else:
|
||||||
price = int(fair_value * 0.8 * sell_modifier)
|
price = int(round(fair_value * 0.8 * sell_modifier))
|
||||||
|
|
||||||
return max(min_price, price)
|
return max(min_price, price)
|
||||||
|
|
||||||
|
|||||||
@ -296,7 +296,7 @@ def create_buy_action(resource_type: ResourceType) -> GOAPAction:
|
|||||||
|
|
||||||
def cost(state: WorldState) -> float:
|
def cost(state: WorldState) -> float:
|
||||||
# Trading cost is low (1 energy)
|
# 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)
|
# MILD profession effect for trading (everyone should be able to trade)
|
||||||
# Traders get a bonus, but non-traders shouldn't be heavily penalized
|
# Traders get a bonus, but non-traders shouldn't be heavily penalized
|
||||||
|
|||||||
@ -133,8 +133,8 @@ def _create_hunt() -> GOAPAction:
|
|||||||
|
|
||||||
def effects(state: WorldState) -> dict:
|
def effects(state: WorldState) -> dict:
|
||||||
# Account for success chance
|
# Account for success chance
|
||||||
effective_meat = int(expected * config.success_chance)
|
effective_meat = int(round(expected * config.success_chance))
|
||||||
effective_hide = int(1 * config.success_chance) # Average hide
|
effective_hide = int(round(1 * config.success_chance)) # Average hide
|
||||||
|
|
||||||
energy_spent = abs(config.energy_cost) / 50.0
|
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:
|
def effects(state: WorldState) -> dict:
|
||||||
# Estimate we'll get a reasonable price (around min_price from config)
|
# Estimate we'll get a reasonable price (around min_price from config)
|
||||||
# This is approximate - actual execution will get real prices
|
# 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)
|
current = getattr(state, count_name)
|
||||||
sell_qty = min(3, current - min_keep) # Sell up to 3, keep minimum
|
sell_qty = min(3, current - min_keep) # Sell up to 3, keep minimum
|
||||||
|
|||||||
@ -63,7 +63,7 @@ class Order:
|
|||||||
def apply_discount(self, percentage: float = 0.1) -> None:
|
def apply_discount(self, percentage: float = 0.1) -> None:
|
||||||
"""Apply a discount to the price."""
|
"""Apply a discount to the price."""
|
||||||
min_price = _get_min_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)
|
self.price_per_unit = max(min_price, self.price_per_unit - reduction)
|
||||||
|
|
||||||
def adjust_price(self, new_price: int, current_turn: int) -> bool:
|
def adjust_price(self, new_price: int, current_turn: int) -> bool:
|
||||||
@ -154,9 +154,9 @@ class OrderBook:
|
|||||||
DISCOUNT_RATE: float = 0.12
|
DISCOUNT_RATE: float = 0.12
|
||||||
|
|
||||||
# Supply/demand thresholds
|
# Supply/demand thresholds
|
||||||
LOW_SUPPLY_THRESHOLD: int = 3 # Less than this = scarcity
|
LOW_SUPPLY_THRESHOLD: int = 10 # Less than this = scarcity
|
||||||
HIGH_SUPPLY_THRESHOLD: int = 10 # More than this = surplus
|
HIGH_SUPPLY_THRESHOLD: int = 50 # More than this = surplus
|
||||||
DEMAND_DECAY: float = 0.95 # How fast demand score decays per turn
|
DEMAND_DECAY: float = 0.99 # How fast demand score decays per turn
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
"""Initialize price history and load config values."""
|
"""Initialize price history and load config values."""
|
||||||
@ -266,7 +266,8 @@ class OrderBook:
|
|||||||
total_cost = actual_quantity * order.price_per_unit
|
total_cost = actual_quantity * order.price_per_unit
|
||||||
if buyer_money < total_cost:
|
if buyer_money < total_cost:
|
||||||
# Try to buy what they can afford
|
# 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:
|
if actual_quantity <= 0:
|
||||||
return TradeResult(
|
return TradeResult(
|
||||||
success=False,
|
success=False,
|
||||||
@ -376,7 +377,7 @@ class OrderBook:
|
|||||||
# Use average sale price as reference if available
|
# Use average sale price as reference if available
|
||||||
reference_price = base_price
|
reference_price = base_price
|
||||||
if history.avg_sale_price > 0:
|
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
|
# Adjust based on supply/demand
|
||||||
if ratio < 0.7: # Scarcity - raise price
|
if ratio < 0.7: # Scarcity - raise price
|
||||||
@ -387,7 +388,7 @@ class OrderBook:
|
|||||||
else:
|
else:
|
||||||
price_multiplier = 1.0
|
price_multiplier = 1.0
|
||||||
|
|
||||||
suggested = int(reference_price * price_multiplier)
|
suggested = int(round(reference_price * price_multiplier))
|
||||||
return max(_get_min_price(), suggested)
|
return max(_get_min_price(), suggested)
|
||||||
|
|
||||||
def adjust_order_price(self, order_id: str, seller_id: str, new_price: int, current_turn: int) -> bool:
|
def adjust_order_price(self, order_id: str, seller_id: str, new_price: int, current_turn: int) -> bool:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user