Code Farm economy rebalance: market saturation, infrastructure/defense/cosmetics, mastery track, secondary leaderboards, admin eras, underdog bonus and weekly contracts
Every purchase/upgrade path (new and pre-existing) is now race-safe against concurrent requests via atomic conditional SQL updates. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import random
|
||||
|
||||
from .. import economy
|
||||
from .common import GameError, _lvl, conditional_update_farm
|
||||
from .farm import ensure_farm, get_farm
|
||||
|
||||
|
||||
INFRA_COLUMN = {i.key: f"infra_{i.key}" for i in economy.INFRASTRUCTURE}
|
||||
|
||||
|
||||
def buy_infrastructure(user: dict, key: str) -> dict:
|
||||
infra = economy.infra_for(key)
|
||||
if not infra:
|
||||
raise GameError("Unknown infrastructure.")
|
||||
farm = ensure_farm(user["uid"])
|
||||
column = INFRA_COLUMN[infra.key]
|
||||
rows = conditional_update_farm(
|
||||
farm["uid"],
|
||||
set_clause=f"coins = coins - :cost, {column} = 1",
|
||||
where_clause=(
|
||||
f"COALESCE({column}, 0) = 0 AND coins >= :cost "
|
||||
f"AND COALESCE(prestige, 0) >= :min_prestige"
|
||||
),
|
||||
params={"cost": infra.cost, "min_prestige": infra.min_prestige},
|
||||
)
|
||||
if rows == 0:
|
||||
farm = get_farm(user["uid"])
|
||||
if _lvl(farm, column):
|
||||
raise GameError("You already own that infrastructure.")
|
||||
if _lvl(farm, "prestige") < infra.min_prestige:
|
||||
raise GameError(f"{infra.name} requires prestige {infra.min_prestige}.")
|
||||
raise GameError("Not enough coins for that infrastructure.")
|
||||
return {"key": infra.key, "spent": infra.cost}
|
||||
|
||||
|
||||
def owns_infrastructure(farm: dict, key: str) -> bool:
|
||||
column = INFRA_COLUMN.get(key)
|
||||
return bool(column and _lvl(farm, column))
|
||||
|
||||
|
||||
def roll_canary(coins_gain: int, plant_cost: int) -> int:
|
||||
roll = random.random()
|
||||
if roll < economy.CANARY_DOUBLE_CHANCE:
|
||||
return coins_gain * 2
|
||||
if roll < economy.CANARY_DOUBLE_CHANCE + economy.CANARY_FAIL_CHANCE:
|
||||
return min(coins_gain, plant_cost)
|
||||
return coins_gain
|
||||
Reference in New Issue
Block a user