feat: 加天气 / 谷仓 / 建筑三套系统,收获改为入库 + 择时卖出
动手前先修掉了两处「死机制」,新增的三个系统各自激活一个: * 天气:小麦 2 天成熟、初始水分 2、每天只掉 1 点,等于永远不需要浇水。 现在水分消耗由天气决定(晴 1 / 多云 0 / 干旱 2,雨天反补 3),而 `state.forecast` 把明天的天气提前告诉你——「今晚浇不浇」成了能算的决策。 5 种天气、权重合计 100、同种不连出;暴风雨会毁未熟作物,温室免疫。 * 谷仓:市场波动原本纯装饰(收获当场按市价变现,没有择时空间)。现在收获与 收取只进 `state.inventory`,靠新增的 `sell` 换金币,价格波动才真正参与决策。 仓满时 `_store()` 抛 `granary_full` 且不改状态,作物原样留在地里。 * 建筑:新增 `build`,买的是「以后不用天天手动做」——水井自动浇干地、 喂食器自动喂食(只吃库存饲料,绝不自动花钱)、温室、谷仓扩容。 每天在 `advance_day` 里先于生长执行,同类越造越贵(×1.6)。 存档升到 `SAVE_VERSION=2`,配 `MIN_SAVE_VERSION=1` 向后兼容,旧档缺的新字段 一律走默认值,不作废玩家手里的档。`advance_day(weather=...)` 是留给测试的 确定性入口。 顺带修两个真 bug: * `daemon.py` 三处 `makedirs(os.path.dirname(path))`:`--pid-file pid.txt` 这种只给文件名的用法会让 dirname 变成空串,启动阶段直接崩。抽出 `ensure_parent_dir()` 兜底。 * `RemoteFarm.snapshot()` 是本地缓存,非实时客户端轮询会一直读到旧数据, 看起来像服务器卡死。补 docstring 指明要自己调 `refresh()`。 质量门禁:ruff format/check 全绿、pyright 0 错误、503 项测试 OK(skip 35)、 bench 无回归(brief 19.5µs / snapshot 48.5µs / POST full=1 400µs)。 另起真实服务器(--tick 3 + 预置存档)跑了 38 项端到端验收,全过。
This commit is contained in:
1 parent
a92c29ead2
commit
cf24cb43f1
21 files changed
+1349
-112
No files matched your search
+27
-7
@@ -104,6 +104,10 @@ class ServerHandle:
|
||||
# 数据源是 FarmEngine.brief_source()(**不是**完整快照),加字段时两处一起改。
|
||||
BRIEF_KEYS = (
|
||||
"day",
|
||||
"weather",
|
||||
"weather_name",
|
||||
"forecast",
|
||||
"forecast_name",
|
||||
"gold",
|
||||
"level",
|
||||
"exp",
|
||||
@@ -116,6 +120,10 @@ BRIEF_KEYS = (
|
||||
"next_plot_price",
|
||||
"animal_count",
|
||||
"max_animals",
|
||||
"storage_used",
|
||||
"granary_capacity",
|
||||
"granary_free",
|
||||
"building_count",
|
||||
"net_worth",
|
||||
"goal_index",
|
||||
"seconds_to_tick",
|
||||
@@ -150,16 +158,26 @@ def rules_text() -> str:
|
||||
f"每天开始时行动点恢复为 {config.START_AP} 点,作物生长、牲畜产出、市场价格都在此刻结算。\n"
|
||||
f"2. 行动点:播种/浇水/喂食各消耗 1 点,收获与收取产出免费。行动点用完只能等第二天——"
|
||||
"时间只能自然流动,没有任何「手动推进一天」的接口,别白费请求。\n"
|
||||
f"3. 水分:作物每天消耗 1 点水分(上限 {config.WATER_CAPACITY}),水分为 0 时停止生长。"
|
||||
f"播种时自带 {config.PLANT_INITIAL_MOISTURE} 点水分。\n"
|
||||
f"4. 收获:成熟后 harvest 获得金币与经验,有 {config.LUCKY_CHANCE:.0%} 概率丰收翻倍。\n"
|
||||
f"3. 天气与水分:每天随机一种天气(晴/多云/雨/干旱/暴风雨)。作物每天按天气蒸发"
|
||||
f" 0~2 点水分(上限 {config.WATER_CAPACITY}),水分为 0 时停止生长;"
|
||||
f"播种自带 {config.PLANT_INITIAL_MOISTURE} 点。雨天与暴风雨会自动补满水分,"
|
||||
"暴风雨还可能毁掉未成熟的作物(温室可免疫)。state.forecast 是明天的预报——"
|
||||
"提前一天浇水就能避免断水停长。\n"
|
||||
"4. 收获与谷仓:harvest / collect 的产出**先进谷仓,不直接换钱**,再用 sell "
|
||||
"按当时的市价卖出。仓容 = 基础 "
|
||||
f"{config.GRANARY_BASE} + 等级成长 + 谷仓建筑,装不下时收获会被拒绝"
|
||||
"(granary_full),先卖货或者建谷仓。\n"
|
||||
"5. 牲畜:每天必须喂食才会累计产出周期;连续 3 天未进食会永久离开农场。\n"
|
||||
f"6. 市场:作物与畜产品价格每天在基础价 ±{config.PRICE_VOLATILITY:.0%} 内波动,"
|
||||
"高价卖出收益更高。\n"
|
||||
f"6. 市场:作物与畜产品价格每天在基础价 ±{config.PRICE_VOLATILITY:.0%} 内波动。"
|
||||
'有了谷仓之后,"什么时候卖"才真正影响收益:囤到高位再 sell。\n'
|
||||
f"7. 土地:初始 {config.BASE_PLOTS} 块,每升 1 级多 {config.PLOTS_PER_LEVEL} 块,"
|
||||
f"上限 {config.MAX_PLOTS} 块;购地价格每次递增。\n"
|
||||
"8. 目标:把净资产(金币 + 土地 + 牲畜 + 库存 + 地里作物)做到 10000 金币。\n"
|
||||
"9. 多人:每个 farm 是一个独立牧场,用 ?farm=名字 区分,互不影响;"
|
||||
"8. 建筑:build 建造 granary / well / feeder / greenhouse。谷仓加仓容、"
|
||||
"水井每天自动浇 1 块干透的地、喂食器每天自动喂 1 只牲畜(只吃库存饲料,"
|
||||
"不会替你花钱)、温室免疫暴风雨且水分蒸发减半。同类建筑越造越贵。\n"
|
||||
f"9. 目标:把净资产(金币 + 土地 + 牲畜 + 饲料 + 地里作物 + **谷仓存货**)"
|
||||
f"做到 {config.GOALS[-1][0]} 金币。\n"
|
||||
"10. 多人:每个 farm 是一个独立牧场,用 ?farm=名字 区分,互不影响;"
|
||||
"排行榜见 GET /api/world。\n"
|
||||
"\n推荐决策循环(AI 最短路径):\n"
|
||||
" GET /api/actions?farm=me → 拿到当前所有**合法**动作(含开销与理由)\n"
|
||||
@@ -379,6 +397,8 @@ def _register_meta_routes(app: FastAPI, svc: _Services) -> None:
|
||||
"actions": actions_mod.describe_actions(),
|
||||
"crops": config.CROPS,
|
||||
"animals": config.ANIMALS,
|
||||
"buildings": config.BUILDINGS,
|
||||
"weather": config.WEATHER,
|
||||
"endpoints": {
|
||||
"state": "GET /api/state?farm=NAME",
|
||||
"catalog": "GET /api/catalog?farm=NAME",
|
||||
|
||||
Reference in new issue
Block a user