消化システム設計

概要

食べた物が蓄えになるまでの経路を決めるドキュメントです。口に入れた物は、かさとして腹を満たし、 栄養として体に残り、そこから体脂肪になります。何をどの物差しで数えるか、どの速さで動くかを扱います。 口にした物で体調を崩す道(6 節の菌と免疫)も、同じ経路の続きとしてここが持ちます。

境界は次のとおり。尽きたときに死ぬことは VitalsSystem.md 8 節(飢えは 死に方の 1 つ)、プロパティの契約と個体差の置き場所は Characters.md、 ステータスの見せ方は StatusArea.md が持ちます。

新設する文法はありません。 使うのは既存の仕組み——stages(段ごとの寄与)・transfer (tick 毎の輸送、GameElementDefinition.md 8.4.1節)——だけです。

1. 物差しを、数える単位ごとに分ける

この模型の要は、何をどの単位で数えるかです。 1 本の値で「かさ」と「エネルギー」を兼ねる ——腹が満ちる量をカロリーで数える——と、かさばるが軽い葉物と、小さいが重い脂が同じ数直線に 乗らないため、どちらかが必ず狂います。

物差し プロパティ 1 単位の意味
かさ(mL) satiety(満腹感) 胃に入っている物の体積
エネルギー(tick) carbohydrate・protein・lipid・body_fat 15 分ぶんの生命維持(1 日 = 96)
微量栄養(mg) vitamin ビタミン C 相当の体内量

食べ物は「かさ」と「中身」を別々に名乗ります。 ほとんどの食べ物では近い値になりますが、 別の数なので次が書けます。

2. 満腹感は、胃に入っているかさ

satiety は実体値です。食べたかさぶん増え、tick で減ります。max が胃の容量(1,500mL)で、 素の減りは一定(−16/tick)で、1 日に 1,536mL 減ります。

「これ以上食べられない」もここが持ちます。 段 full を置き、eat を not: {subject: agent, prop: satiety, in_stage_or_above: full} で塞ぎます。水分の full と not_thirsty の対称形です(LiquidContainerSystem.md 5節)。

段 下限 域
starving 0 危険
hungry 50 要注意
peckish 200 留意
fed 400 安全(1 食で届く)
full 900 安全。ここから上は食べられない

full を max ではなく 6 割に置くのは、あふれた分を捨てずに済ませるためです。 食料は個体の カードなので、入る分だけ食べて残すことはできません(GameElementDefinition.md 9.2 節。一部だけ使えるのは中身入りの容器だけ)。最大の食料は 550mL(焼いた タロイモ)なので、full の直前(899)で食べても 1,449 で収まり、1 mL も捨てません。

段は max の 80% で安全域を外れる規約(Characters.md)に従いません。 max は容量であって「これだけ満ちていてほしい」量ではないためです。1 食(512mL)で fed に届き、 そこから 8 時間かけて starving へ落ちます。

3. エネルギーは、栄養素ごとに 3 本

体内に残っているエネルギーを、糖質・たんぱく質・脂質の 3 本で持ちます。 在庫がある間は transfer で body_fat へ流れ続け、尽きれば body_fat が削られていきます(5 節)。

3 本に分けているのは、吸収の速さと欠乏したときに起きることが違うからです。器官(胃・腸)で 分けるのをやめたのは、器官には物差しが 1 つしか無く、栄養素の違いを表せないためです。

速さ 主な食材 尽きると
carbohydrate(糖質) 2/tick イモ・穀物・果実 固有の弊害は無い
protein(たんぱく質) 1/tick 肉・魚・甲殻類 筋が落ちる・傷が治らない(未実装。未決事項節)
lipid(脂質) 0.25/tick ヤシの果肉・脂の乗った肉 必須脂肪酸欠乏と、肉だけを食べ続けたときの毒性(7 節)

糖質に固有の欠乏症が無いのは、炭水化物が必須栄養素ではないためです。 体は糖新生でブドウ糖を 作れるので、肉と脂だけでも生きられます。糖質を残しているのは弊害のためではなく、栽培で安定して 大量に得られるという入手経路の違いと、吸収が速いことのためです。

lipid の速さだけは、1 日に要る量そのものです。 尽きた域に段を持つのはこの 1 本だけなので (7 節)、在庫を切らさずにいるには「速さ × 1 日」を運び入れなければなりません—— 1 日 24で、 1 日に燃やすエネルギー 96の 4 分の 1 にあたります。この割合が置いてある数で、現実の目安(脂から摂る分は総エネルギーの 2〜3 割)から採りました。残りの 2 本の速さは在庫が何 tick 保つかしか決めません(5 節)が、 ここだけは違う——速さを動かすと、fat_starved を抜ける値段が動きます。

max は 3 本とも 120。食べ溜めはできません——満杯の在庫へ足した分は捨てられます。

4. ビタミンは、エネルギーとは別の物差し

vitamin は mg(ビタミン C 相当)で持ちます。エネルギーの在庫にはしません——葉物はエネルギーを ほとんど持たないので、エネルギーとして数えると常に 0 に張り付き、「食べていない」と区別が付かなく なるためです。

ヒトのプールは飽和で約 1,500mg、300mg を割ると壊血病が出ます。代謝回転は 1 日およそ 48mg なので、 max 1,500・−0.5/tick。空心菜 1 束(83mg)は、1 日の回転を越えて運びます。

壊血病は、この値の一番下の段そのものです。 怪我のカードにはしません——身体の外から負ったものだけを 怪我にし、内側で起きている不調はその原因となる値の段が持ちます (DesignPrinciples.md)。後から入る空腹・脱水・寝不足の弊害も、 同じ形でそれぞれの段が持ちます。

段の境目は現実の量で置きます。壊血病に落ちるのは 300mg を割ったときで、残りの段は そこから 1 日の回転の何日ぶん上にあるかで置いています。

段 下限 域 備考
scurvy 0 危険 壊血病。古傷が開き、歯が抜ける
deficient 300 要注意 —
waning 600 留意 —
replete 1,200 安全 max の 80%(Characters.md)

scurvy の段が pain を 60 押し上げます(刺し傷・牙の傷と並ぶ、この島で最も重い段)。modify なので可逆——段を抜けた瞬間に痛みは引きます。手当てに当たるのは葉物を食べることで、放置した分だけ 支払う量が増えます: 割った直後なら空心菜 1 束(83mg)で戻せますが、0 まで落とすと 4 束要ります。

痛みだけでは済みません——この段は immunity も押し下げます(押す量は 6.2 節)。vitamin 自身は 致命的域を持ちませんが、菌源のある暮らしで壊血病を抱えれば、菌が上限へ暴走して血が削られます (Voyage.md 3.9.3 節が航海でその筋書きを通します)。

開始時の 900mg から葉物を絶てば 12.5 日目に落ちます。 status タグを持つので、落ちるより前から残りがステータスエリアのバーに出ます (StatusArea.md)。

脂質の欠乏とたんぱく質過多も、同じ形で書きます(7 節)。どちらも死に方を増やしません ——削るのは既にある水と蓄えで、終わり方は脱水と餓死のままです。 たんぱく質の欠乏(筋が落ちる)だけは、削る先がまだ決まっていません(未決事項節)。

5. 体脂肪は、3 本から届いた分が積み上がる

body_fat の単位はエネルギーと同じ tick です。3 本からの transfer で増え、段ごとの基礎代謝で 減ります(太っているほど速い=食べ過ぎても際限なく太らない平衡点)。

糖質だけで暮らすと、ちょうど釣り合います——糖質は 2/tick 流れますが、在庫が半分の時間しか 続かないため、1 日 3 食のイモが基礎代謝 1/tick と釣り合う勘定です。3 本とも在庫が あるときは 3 本の速さを足した速さで流れるので、食べた直後は身になるのが速く、尽きれば止まります。 流れる総量は速さによらず変わらない(transfer は保存する)ので、速さが決めるのは timing だけです ——段を持つ lipid を除いて(3 節)。あちらは在庫が尽きた域そのものに寄与があるので、 速さが「切らさずにいるのに要る量」になります。

6. 食中毒は、抽選ではなく全身の菌量で決まる

生の物を口にすると菌が体へ入り、免疫が菌の増える速さを上回っていれば消え、下回っていれば増えて 症状が出ます。 悪いことが起きるかを毎回の抽選では決めません (DesignPrinciples.md「悪いことが起きるかは、毎回の抽選ではなく 蓄積する値で決める」)——抽選では、同じ判断を何度重ねても回どうしが繋がらず、当たった回を運としてしか 説明できないためです。腹を空かせたまま食べた日と、寝ずに食べた日は、同じ 1 つの値の上で足し合わさります。

持つのは次のとおりです。どちらも身体の仕組みなので個体差を持たせず、player_character trait が配ります。

プロパティ 単位 意味
pathogen log₁₀ CFU(0〜9) 全身に居る菌の量
immunity 単位なし(20〜100) それを抑え込む力

6.1 菌は対数で持つ

対数目盛では指数増殖が定数の add になります。 明るさを EV で持っているのと同じ形 (IlluminationSystem.md 1 節)で、「細菌が自分で自分を押し上げる」を 近似せずに書けます。増える速さは定数 1 つ(+0.15/tick)で、log₁₀2 ≒ 0.30 が 1 回の倍加なので、 倍加時間は log₁₀2 をこの速さで割った長さです。

add の量に参照や積は書きません。 あの表現力はエンジン専用に取ってあるので (src/domain/PassiveAmount.ts の ProductAmount)、増える速さも減る速さも、すべて段ごとの定数です。

落とし穴は 0 の意味です。 log₁₀ 0 は「菌ゼロ」ではなく「菌 1 個」なので、増殖の passives を無条件に 置くと感染していない体でも菌が増えます。菌が居ることになる段(latent 以上)に居る間だけ増やす、 という条件 1 つでそこを塞ぎます。増え始める値は latent の min(0.1)で、条件はその段を名指す ので、段を足しても増え始める値は動きません。

段 下限 域 何が起きるか
sterile 0 安全 菌が居ない。増殖もしない
latent 0.1 安全 潜伏期。増えているが症状は出ない
feverish 5 要注意 発熱。hydration を -1/tick
septicemic 7 危険 敗血症。hydration を -2/tick、blood を -40/tick

死に方は増えません(VitalsSystem.md 8 節)。上の 2 段が削るのは既にある水と血で、 終わり方は脱水と失血のままです。対症療法が効く道(熱で余計に要る水は飲めば追いつく)と効かない道 (漏れ出た血は戻らない)を同時に持ちます(VitalsSystem.md 8.1 節)。

削るのはここだけです。 菌を入れた側は押し上げるところまでしかしません——口から入る生肉(下の 「1 食で入る量」)も、膿んだ傷(InjurySystem.md 6.3 節)も、宛先はこの 1 つの値で、 そこから先の症状と死に方を知りません。

潜伏期は画面に出ません。 下 2 段が alert を持たないので、安全域の行はステータスエリアに現れず (StatusArea.md 2 節)、発症したら出るが既存の規約のまま成り立ちます。

合流は過大に見ます。 対数上の足し算は線形では掛け算なので、続けて食べた分を実際より重く見ますが、 向き(続けて食べるほど危ない)は正しいので直しません(DesignPrinciples.md 「模型のずれは、罰の向きが正しければ許容する」)。

1 食で入る量は、食べ物の側が名乗ります。 量は +3——生の食肉の表面菌数(10³ CFU/g の桁)から置いた 仮の値です。焼けば菌は死ぬので、焼いた先(roasted_meat)は名乗りません。火を通す価値が、「身になる量が 増える」と「菌が入らない」になります。

名乗るのは、焼いた先を持つ食べ物(丸焼きの鎖、FireSystem.md 7.2 節)のうち、 生でも食べられる物です。どちらも cooking_progress の on_max で決まります——焼いた先を持つとは 自分の on_max が別の物を生むこと、生であるとはどの物の on_max からも生まれないこと、つまり鎖の 先頭に居ることです。焼いて生まれた物には既に火が通っているので、焦げる手前の焼けた肉(roasted_meat)は 生ではありません。いまこの両方を満たすのは 1 つで、生肉(raw_meat)です。

火を通す手段の無い食べ物へは掛けません——避ける手の無い罰になり、対価の形になりません。生で食べる 葉物(water_spinach)が菌を名乗らないのはこの線によるもので、あちらで危ないのは植物ではなく育った水の ほう(寄生虫)です。数え上げが増えたときはここも直します(見張るのは tests/world-codex/digestion.test.ts)。

6.2 免疫は、段ごとの定数で菌を引く

要点は、閾値が 2 つの定数の大小 1 つに畳まれていることです。 除去が増殖(+0.15)を上回れば菌は 0 へ 着地して止まり、下回れば上限へ暴走します。免疫の段と菌の段を掛け合わせた表は要りません。

段 下限 引く量 増殖(+0.15)との差
failing 20 -0.05 暴走する
weakened 25 -0.10 ゆっくり暴走する
robust 40 -0.20 着地する。健康な体(素の 60)はここ
primed 70 -0.30 速く着地する

生活からの寄与は modify(可逆)で、宣言は原因の段の側が持ちます(壊血病が pain を押し上げるのと 同じ形、4 節)。押す量の順位は現実の効き目の順です。

押し下げるもの 量 どの段
壊血病 -40 vitamin の scurvy
空腹 -20 satiety の starving
ビタミン不足 -15 vitamin の deficient
寝不足 -15 wakefulness の overtired(キャラクタごとのファイル)
気の塞ぎ -10 happiness の miserable

ビタミンだけが 2 段で押し、量も最も重いのは、壊血病の創傷治癒不全が現実で最も確立しているからです。 vitamin の段は既に「古傷が開き、歯が抜ける」と書いており(4 節)、同じ現象を菌の側から見たものに あたります。体温は入れません——寒冷曝露そのものが感染を増やすという裏付けは弱いためです。 過剰側にボーナスも出しません——ビタミンを多く摂れば感染に強くなる、は現実で否定されています。

段の境目は「いくつ重なったか」で置きます。 素の 60 から、押し下げが 1 つまでなら robust に留まり (壊血病を除けばいちばん重い空腹の -20 でちょうど 40)、2 つ重なると weakened、3 つ重なるか壊血病 1 つで failing へ落ちます。こう置かないと、いちばん軽い -10 でも段が落ちて、重い順に並べた意味が消えます。

range.min(20)は、押し下げが重なっても残る守りの底です。 全部重ねても(-85)ここより下へは 行きません。素の 60(value)とは別の数で、こちらは「何も抱えていない体の高さ」、20 は「どこまで 落ちても残る高さ」です。

上がるのは感染している間だけ(+0.25/tick)。これが「感染が免疫を上げる」(獲得免疫)と 「免疫が反応するまでの時間差」の両方で、別の仕組みは作りません——潜伏期は、免疫が段を 1 つ上げるのに 要る tick 数そのものです——weakened の下端 25 から robust の 40 まで 60 tick。 引き戻すのはいちばん上の段だけ(-0.05/tick)なので、罹って治った体は素の 60 より高い所(70 の少し下)で 止まります。それが獲得免疫で、素のままでは段を落とす押し下げでも、少し深いものまでなら段を保てる余力になります。

獣も同じ物差しで pathogen を持ちます(animals.yaml の beast)。ただし immunity は固定値で、 生活では上下しません——上の表で押し下げを宣言している段は、どれも人しか持たない値のものだからです (獣の飢えは body_fat が受け持ちますが、そちらは人でも免疫を押しません)。動かないので段は 1 つで、人の 健康時と同じ高さに置いてあります。野生の獣の免疫が実際どの程度かは分からないので、これは仮決めです。

症状の出方は 1 点だけ人と違います——熱と敗血症が削る水は、渇きと同じゲート(catch の枠に居る間)の 中でしか引きません。獣の水分はもともと閉じ込められている間しか動かない値なので(TrapSystem.md 5.4 節)、ゲートの外から削ると「飲めない状況に置いたのは誰か」の言い分けが崩れ、島中の獣が熱で渇いて いくことになります。血のほうは無条件で、こちらは野生でも失われます。

6.3 傷んだ物の吐き下しは、その場で決着する抽選のまま

腐敗だけは eat の末尾の pick が引きます。 上の菌量へは移しません—— DesignPrinciples.md「体内で増える菌は、抽選ではなく蓄積と免疫で表す」節が、 その場で決着する抽選(腐った物の吐き下し・獣の反撃)はこの基準の外だと決めているためです。腐った物を 口にした報いはその場で終わり、次の食事へ持ち越しません。

仕組みの側でも、いまは書けません。 eat の add の量はリテラルなので傷んだ段と腐った段の差を 書けず、段の passives には set が無いので、「吐く」(腹が空になる)が書けない——移すには食べ物の 側が菌量を実体値として溜める形(perishable の作り直し)が要ります。

傷み具合は durability の残りの割合で刻みます。腐る速さは分類で違いますが、durability は種類に よらず 960 から始まるので、同じ境目が全部の食べ物で同じ「残り」を指します。

段 下限(durability) spoilage
sound 480 0(当たらない)
stale 240 25
rotten 0 100

引くのは eat の末尾の pick(GameElementDefinition.md 10 節)で、重みは 無事 100 : 吐く spoilage : 下す spoilage。spoilage は上の段が modify で押し上げる食べ物側の 値(sound では 0)で、当たるかどうかを決める数を 1 つに集めたものです。吐くと下すは同じ重みなので、 当たった回の半分ずつになります。

症状 何が起きるか どう書くか
吐く 腹が空になり、少し前に食べた分まで失う satiety を set で 0、3 本を add で -40 ずつ
下痢 食べた物が身にならない+脱水 3 本を add で -40 ずつ、hydration をさらに -48

pick は add より後ろに置きます——腹に収めてから吐くので、順が逆だと吐いた後に食べたことに なります(同 9.7 節)。下痢は「行き先が無いまま減らす」ので、transfer ではなく add で書きます。 吸収率を下げたい場合は、transfer の to_amount を amount より小さくしても同じことが表せます。

死に方はここでも増えません。 下痢の脱水は、既にある渇きの死に方へ流れます (VitalsSystem.md 8 節)。

段と spoilage は foods.yaml の perishable が配るので腐る物すべてが持ち、引く pick は 食べられる物すべての eat に書いてあります。例外は焦げた塊(charred_lump)だけで、 水も栄養素も残らない炭は腐らないので spoilage を持ちません。

7. 食の偏りは、水と蓄えを削って既存の死に方へ流す【確定】

脂が尽きたまま肉ばかり食べ続けると死にます。 ただし死に方は増えません——削るのは既にある hydration と body_fat で、終わり方は脱水と餓死のままです (VitalsSystem.md 8 節・8.2 節)。

引き金は 1 つの段です。 lipid の一番下の段(fat_starved、脂の在庫が尽きた域)が、壊血病 (4 節)とまったく同じ形で寄与を持ちます。違うのは、寄与の中身が痛みだけではないことです。持つのは 水を余計に削る(余ったたんぱく質は尿素として捨てるしかなく、その排泄に水が要る)・ たんぱく質を余計に削る(捨てられる分は身にならない=食べても蓄えが増えない)・痛みを押し上げる (必須脂肪酸の欠乏で肌が荒れ、傷が治らない)です。

出どころ: #656(食べ方の偏りで死ぬ道)

8. 脂が尽きた段が持つ寄与

7 節の寄与を数とゲートへ落としたもので、覆すのに人間の判断は要りません。

寄与 何を表すか ゲート
hydration を -1/tick 余計に削る 余ったたんぱく質は尿素として捨てるしかなく、その排泄に水が要る protein の在庫があるとき
protein を -2/tick 余計に削る 捨てられる分は身にならない。食べても蓄えが増えない 同上
pain を 30 押し上げる 必須脂肪酸の欠乏(肌が荒れ、傷が治らない) 無し(脂が尽きている間ずっと)

水の削りは -1/tick が -2/tick になる形で、水分の保ちがちょうど半分になります。倍より重くは しません——読みやすい形が崩れるうえ、抜けるのに払うのは下のとおり果肉 1 つなので、払うほうを 選ばせるのにこれ以上は要りません。

抜けるのに払うのは、ヤシの果肉 1 つで 1 日ぶんです。 1 日に要るのは 24(3 節)で、果肉 1 つが 運ぶのは 26。壊血病に対する葉物と同じ形で、1 つ食べれば 1 日ぶんを越えて運ぶので、要るのは 値段ではなく忘れないことのほうです。放置した分だけ支払う量が増えることもありません——lipid は 0 で止まり、段を抜けるのに要るのは常に 1 だけで、壊血病(4 節)のように底まで戻す必要がありません。

この段は、いちばん安い暮らし方の既定ではありません。 最小の献立がその 1 日ぶんを運んでいる ことは、次節の表が持ちます。

9. 1 日ぶんの値は、島が 1 日に返す量と釣り合っている

満腹・ビタミン・エネルギーの減る速さは、今のままとします。 島が 1 日に返す量が出たので、 突き合わせられます(stats/balance.yaml の daily_minimum と daily_minimum_menu。読み方は BalanceStats.md)。

1 日を賄う最小労働は 549 分 (島じゅうを渡り歩ける前提。移動時間は数えていません)で、うち 360 分は眠るぶんなので、 採って食べるのに払うのは 189 分です。 これが ContentSkeleton.md 8 節の自由時間 891 分を出している引き算の相手で、1 周回の日数の 見積もりはこの値の上に立っています——速さを動かせば、そちらが動きます。

賄うもの 献立 1 日
水 湧き水から汲んだ水 9.33杯 50 分
満腹・蓄え 生肉 3.07切れ 85 分
満腹・蓄え 焼いた芋 0.14個 6 分
脂 ヤシの果肉 0.45個 35 分
ビタミン 空心菜 0.47束 15 分

未決事項・今後の検討課題