Files
main_plugin_farm/src/farm_core/pests.py
T

70 lines
2.5 KiB
Python
Raw Normal View History

"""离线虫害时间结算;只投影状态,不读写数据库或使用随机数。"""
from dataclasses import replace
from .domain import Plot, integer
def season_duration(plot: Plot) -> int:
2026-10-26 11:34:00 +08:00
base = (plot.plant.growth_seconds if plot.harvest_count == 0
else plot.plant.regrowth_seconds)
2026-10-26 11:34:00 +08:00
return max(1, (base * (80 if plot.land_level >= 2 else 100) + 99) // 100)
def spawn_interval(plot: Plot) -> int:
"""至少留出两小时,每半个基础生长周期才发生一次虫害。"""
return max(7200, (season_duration(plot) + 1) // 2)
def start_growth(plot: Plot, now: int) -> Plot:
duration = season_duration(plot)
return advance_plot(replace(
plot, mature_at=integer(now + duration), pest_count=0, pest_spawned=0,
growth_remaining=integer(duration * 100), growth_updated_at=now,
next_pest_at=integer(now + spawn_interval(plot)), maturity_pests=0,
), now)
def _advance(remaining, cursor, pests, spawned, next_at, interval, now):
while remaining:
rate = 100 - pests * 5
finish = integer(cursor + (remaining + rate - 1) // rate)
if finish <= now and (next_at is None or finish <= next_at):
return 0, finish, pests, spawned, None, finish
end = min(now, next_at) if next_at is not None else now
remaining -= (end - cursor) * rate
cursor = end
if next_at is None or cursor < next_at:
break
pests += 1
spawned += 1
next_at = integer(next_at + interval) if spawned < 3 else None
if cursor == now:
break
return remaining, cursor, pests, spawned, next_at, None
def advance_plot(plot: Plot, now: int) -> Plot:
integer(now)
if (plot.plant is None or plot.withered
or plot.growth_remaining is None or not plot.growth_remaining):
return plot
if now < plot.growth_updated_at:
return plot
interval = spawn_interval(plot)
remaining, cursor, pests, spawned, next_at, finish = _advance(
plot.growth_remaining, plot.growth_updated_at, plot.pest_count,
plot.pest_spawned, plot.next_pest_at, interval, now,
)
if finish is None:
finish = _advance(
remaining, cursor, pests, spawned, next_at, interval,
integer(cursor + (remaining + 84) // 85),
)[-1]
return replace(
plot, mature_at=finish, pest_count=pests, pest_spawned=spawned,
growth_remaining=remaining, growth_updated_at=cursor,
next_pest_at=next_at,
maturity_pests=pests if remaining == 0 else 0,
)