日をまたぐ長さのレポートの読み方
数値は stats/durations.yaml にあります。
tests/diagnostics/durationStatsReport.test.ts が、定義(src/assets/world-codex/*.yaml)だけから
計算したものです。日数を決める値——怪我の severity・食べ物の durability・season_remaining・
道具の durability とそれらを動かす passives——を変更したら再生成します。
npm run stats:durations
この文書は手書きで、再生成しても書き換わりません。 持つのは読み方——何を測ったか、どこに線を 引いたか、何を数えていないか——だけです。数値そのものは1行も書きません(書けば、再生成した YAMLとずれます)。
YAMLの節
unit は、そのレコードの測定値の単位です。件数(durations・tool_wears)は単位を持ちません。
| 節 | 中身 |
|---|---|
meta |
日の列に載せる下限、数えた長さの数、最長と最短、使うたびに減る値の数 |
durations |
日をまたぐ長さの、長い順の1本の列。種類では分けない |
tool_wear |
使うたびに減る値が尽きるまでの回数 |
この表とYAMLが食い違うと npm test が赤くなります。 表に挙げた節がYAMLに在って空でないことと、
表に無い節がYAMLに無いことの両方を、生成元のテストが見ます。
なぜ1本の列なのか
この表が答えたいのは逆転です——骨折より擦り傷のほうが治りが遅い、塩漬けの肉が生肉より早く
傷む、といった並びの狂い。逆転は種類をまたいで起こるので、怪我の表・食べ物の表・季節の表と
分けると見えません。同じ列に並んでいることが検査そのものなので、durations は種類で分けず、
days の降順だけで並べます。
日数の列が分かれているのは、長さを振らせるものが2つあり、それぞれ別の軸だからです。days を
基準に、shortest_days は条件つきの軸を、longest_days はロールの軸を、それぞれ反対の端まで
振ったものです。
| 列 | 何が振れた場合か |
|---|---|
days |
基準。条件つきの増減が最も遅く端へ届く組み合わせで、ロールは短いほうに出た場合 |
shortest_days |
条件つきが最も速く端へ届く組み合わせの場合(days 以下) |
longest_days |
ロールが長いほうに出た場合(days 以上) |
「条件つきが全部重なった場合」ではありません。 条件つきの増減は端へ近づける側とは限らず、
遠ざける側にもなります(傷の膿み具合は、宿主の免疫が高いほど遅く上がる、
InjurySystem.md 6.2 節)。重なった数ではなく、届く速さで採ります。
shortest_days が別の列なのは、条件つきの増減(GameElementDefinition.md 8.2節)がどれも同時に
成立するとは限らないためです。同時に成立しうる組み合わせ(下の「計測方法」)をすべて並べた
うえで、days はその端へ最も遅く届くもの、shortest_days は最も速く届くものになります。
longest_days が別の列なのは、生成時に1回引く初期値(同6.2節、value: {min, max})が条件つきとは
無関係に長さを振らせるためです。骨折の severity は折れ方をここで1回引くので、条件つきを1つも
持たないまま2つの長さを持ちます。2つの軸を1つの幅へ畳むと、条件が重なったのか重く出たのかが
読めなくなります。 値が戻って繰り返す周期(repeats)では、次の発火までは戻った量ぶんなので
ロールは長さを変えず、longest_days は days と等しくなります。
逆転を読むときは日数の列をすべて見ます——生肉と塩漬けの肉は days では順当でも shortest_days では
近づき、下端しか見ない読み方は「上端でだけ起こる逆転」を見落とします。
計測方法
数え方の線は src/analysis/durations.ts の冒頭が持ちます。長さはすべて「tick毎に動く値が range の
端へ届くまで」(src/analysis/rangeCycles.ts)で、それを日へ直したものです。
- 1日に満たない長さは数えません。 乾き・飢え・疲れ・調理・火の燃えは1日の中で何度も回るもので、
日で読む長さとは尺度が違います(
DesignPrinciples.md「長くかかるものだけ、現実の4分の1へ縮める」)。同じ列に混ぜると、日をまたぐ長さの逆転が 1日未満の行に埋もれます。ただし同じ値が日をまたいで尽きるところは数えます——渇きで倒れるまで・ 蓄えた脂肪が尽きるまでは日で読む長さで、怪我の治りと並べる意味があります。 - 隣の物に押されて初めて進むものは数えません。 炉が焼く・刺さった傷が血を奪うといった増減は、 置いておくだけでは起こりません。これを寿命として数えると、火にかけていない肉まで勝手に 焼け落ちることになります。
- 繰り返すものも一度きりのものも同じ列に置きます(
repeats)。季節は端で値が戻って次の季節へ 移り、怪我は端で消えますが、どちらも「その長さのあいだ続く」ことに変わりはありません。 - 条件つきの増減は、同時に成立しうる組み合わせだけを1つの場合として数えます。 問いは「合算する
か」ではなく「どの組み合わせが同時に成立しうるか」です——同じ気温を
ltとgteで見ている 寒さと暖かさのように、書かれた条件そのものが重なりを禁じているものは別々の場合になります。 重ならないと言い切れない組み合わせは重なるものとして数えるので、罠の耐久は地面での減りと獲物を 抱えている間の減りが同時に効く場合を持ちます(src/analysis/conditionCases.ts)。 - どちらの端へ向かうかは、端のイベントごとに見ます。 上下どちらへも動きうる値では、下端の イベントは下がる場合だけを、上端のイベントは上がる場合だけを見ます。
- 段で切り替わる増減は数えません。 段ごとに速さが変わるものは、1つの長さでは言い表せません
(
src/analysis/rangeCycles.ts)。 - 長さの起点は
rangeの下端ではなく、宣言された初期値(value)です。 両者が同じ食べ物では 差が出ませんが、キャラクタの値では出ます——満たされた状態からの長さを知りたいなら、maxとvalueの差のぶんだけ短く出ていることになります。 - 初期値が幅で宣言されているものは、両端から数えます。 生成時に1回引くロール(
value: {min, max}) は、向かう端によってどちらが遠いかが裏返る——下端へ向かうなら重く出たほうが、上端へ向かうなら 軽く出たほうが遠い。近いほうがdays、遠いほうがlongest_daysです。宣言の下端を一律に基準と すると、上端へ向かう値では幅の長い側がdaysに入り、短い側がどこにも出なくなります。 - 実際に起きるかは数えません。 生肉が保つ日数は誰も食べなかった場合の長さで、その前に 食べられる確率は見ません。
使うたびに減る値を、日の列に置かない理由
斧は振ったときだけ、槍は突いたときだけ削れるので、その削れ方から「何日で壊れるか」を出すには 振り続けた場合と置くほかありません。それは経過時間ではなく労働時間で、食べ物が腐るまでの日数と 同じ軸に置くと在りもしない逆転が見えます(斧のほうが肉より早く壊れる、のように)。
そこで tool_wear は回数で出し、1回に払う時間(labor_minutes)を添えます。日の列と突き合わせ
たいときは、両者を掛けたものが「他に何もせず使い続けた場合」の下限になります。
同じ道具でも使い方ごとに行が分かれます(step・owner)——斧は木を伐るのと獲物を殴るのとで
1回の削れ方が違い、壊れるまでの回数もそこで変わるためです。
同じ道具が両方の列に出ます。 屋外で朽ちる速さ(DurabilitySystem.md
2節)と、振るたびに欠ける量は独立した増減なので、石斧は日の列にも回数の列にも並びます——どちらが
先に来るかは使い方が決めるので、片方を落とすと、残ったほうが寿命そのものに見えます。
このレポートは判定を出さない
逆転が見つかっても、ここでは直しません。どちらを動かすかは、並びを読んでから決めます。
値そのものの妥当性(骨折の長さがこれでよいか)は、この表ではなく
InjurySystem.md をはじめとする仕様書が持つ判断です。