食料がマイナスの間、木材で建つはずの道路まで作れなかった。条件式一つの話
一度落ちると、自力では戻れなかった。
日本進化シミュレーション第15回 / 全16回目次
「AI自動開発について、ある程度開発が進むと慢性的に資源が足りませんとなるようですが、こちらは正しい挙動ですか」
という質問をもらった。
僕には、正しい挙動のはずがないと分かっていた。
とはいえ「資源が足りない」という表示自体は、資源が本当に足りていない時にも普通に出るメッセージなので、まずは実際に自動開発を長時間回して、何が起きているのかを自分の目で確かめることにした。
再現させてみたら、意外なものまで巻き込まれていた
数百回ぶんのターンを連続で回すと、ある街で食料がマイナスになった。
そこから先、その街は道路すら1本も敷けなくなっていた。
道路は木材1で建つ。食料は要らない。
なのに、食料と何の関係もない道路の建設まで、毎回「資源が足りません」ではじかれていた。
食料だけ、意図的にマイナスを許していた
コードを読むと、食料だけ特別扱いになっていた。
食料が尽きると飢饉のような表現として幸福度が下がる仕組みがあり、そのために食料は-20までマイナスを許容する作りになっている。
木材や石材、資金は、計算の最後に0未満にならないよう切り捨てられる。
食料だけ、その切り捨てが抜けていて、マイナスのまま次のターンへ持ち越されていた。
ここまでは、意図した仕様だった。
「コストが0なら常に賄える」はずが、そうなっていなかった
問題は、購入できるかどうかを判定する関数の書き方だった。
「必要な食料が指定されていなければ0として扱い、保有量がその0以上ならOK」という、一見自然な比較になっていた。
ところが保有量そのものがマイナスだと、この比較が壊れる。
0以上必要なところ、手元の食料がマイナス20なら、マイナス20は0以上ではない。
食料を1つも必要としない道路の購入まで、判定上は「足りていない」ことにされてしまっていた。
一度落ちると、自力では戻れない
さらに悪いことに、この状態から抜け出す手段も塞がれていた。
食料を回復させるには農地を建てる必要があるが、農地の建設にも当然この判定を通る。
食料が要らない建設まで全部止まっているので、農地も例外なく止まる。
一度マイナスに落ちたら最後、何をやっても資源が動かなくなる。
慢性的な資源不足に見えていたのは、実際には特定の街が完全に停止していただけだった。
直し方は、条件を一段追加するだけ
return (!c.wood || resources.wood >= c.wood) && (!c.stone || resources.stone >= c.stone) && (!c.food || resources.food >= c.food) && (!c.gold || resources.gold >= c.gold);コストが指定されていない資源については、保有量がマイナスであっても常に賄えるとみなす。
たった1行のロジックの見直しで直った。
「ある資源だけマイナスを許す」設計は、他を巻き込みやすい
この一件で分かったのは、特定の資源だけ特別な挙動を持たせると、その資源と関係ないはずの処理にまで影響が漏れやすいということだった。
食料の飢饉表現自体は、ゲームとして必要な仕様だと思う。
ただ、その特別扱いを追加するときに、判定ロジック側への影響までは考えが及んでいなかった。
今後、同じように「ある資源だけ特殊な状態を許す」仕組みを足すときは、その資源に依存していないはずの他の処理を、道連れにしていないか必ず見直すようにしている。
※運営者が個人で書いているnoteです。