オプションrng: Rng非公開 読み取り専用change読み取り専用codex読み取り専用effective実効値(8.3節)の読み取りの区切り。世界の状態ではなく計算の途中を区切るものなので、使うのも いつ区切るかを決めるのもPropertyValueだけ。
非公開 読み取り専用gain非公開 読み取り専用gains今、1つの操作を実行している最中か(withInteractionGains)。ここに居る間の書き込みだけを 溜める。undefinedなら溜めない=操作の外で回ったtickや、rangeイベントから走る効果は入らない。
非公開 読み取り専用inside今、時間の経過(runTick)の中か。ここでの実体値への書き込みは、操作が直に増やしたものでは ない(PropertyGain)——値を動かしているのは経過そのもので、輸送も端のクランプも同じ。 その中で始まった別の操作は自分の稼ぎを持つので、withInteractionGainsが降ろす。
非公開next次に配るinstanceId。1から始まるのはNO_INSTANCEを空けておくため。 worldも例外ではなく
ここから受け取る(createWorld)。
一意であることまでは、ここだけでは保証しない——番号を直に名乗ってWorldObjectを組む道が
残っている(試験の足場)。予約値を名乗らないことだけは、WorldObjectのコンストラクタが
どの道でも守る。
読み取り専用rngpick(10節)の重み付き抽選に使う乱数源。テストで決定的に振る舞わせられるよう、コンストラクタで差し替え可能。
非公開 読み取り専用running今効いている、操作が宣言した持続効果(11.7節)と、その宣言元、そしてその操作の関係が用意した
文脈。durationを進めている間だけ並ぶ。経過中のtickで、そのぶんだけを操作の稼ぎとして拾う
ための控え(countTickMovementAsGain)であり、宣言元がbecomeしたときに登録を張り直す先でもある
(setInteractionPassivesRegistered)。
文脈を憶えるのは、役の解決先が宣言元の今の参加から決まらないから(11.5節)。宣言元が経過中に 別の関係へも加わると、そちらが役を解く関係になる(WorldObject.participation)ので、辿り直しでは この操作の役に戻れない。
1つではなく積む。 経過中のtickは手番を配り、その手番も操作なのでここへ乗る(入れ子)。 内側だけを持つと、外側のぶんは登録されたまま辿れなくなる。
非公開seam実行中のまとまりの深さ(runToSeam)。0へ戻ったところが操作の切れ目。
非公開 読み取り専用signal非公開 読み取り専用subject今どのオブジェクトの効果を適用しているか(withSubject)。記録する変化の主体になる。
非公開taking待っていた手番を起こしている最中か。この間に挙がった待ちは受け取らない(takeWaitingTurns)。
非公開 読み取り専用tick今のtickで動いたぶんが操作の稼ぎになるプロパティ(countTickMovementAsGain)。tickを回す手前で、 その操作が宣言した持続効果(11.7節)が対象を名乗って並べる。持つのは指し先(gainTargetKey)で、 プロパティそのものではない——名乗ってから動くまでの間にbecomeが挟まりうる。
非公開 読み取り専用tick観測口と、今の適用の文脈。どれも「bodyの実行中だけ差し替わる値」(Scoped)なので、 挿して抜くところは各メソッドに書かない——戻し忘れる余地が無いことは、Scopedが1箇所で保証する。
非公開waiting時間の中では起こせず、操作の切れ目を待っている手番(trigger: tick、11.1節)。時間を要する
手番は、配られたその場では起こせない——手番を配るのは時間を進めている最中で、そのとき動作主は
時間を進めている操作にまだ就いている(GameElementDefinition.md 11.5節の不変条件)。
非公開world非公開worldこのセッションのworld(createWorld)。生成していなければundefined——時間の概念を持たないセッション。
ゲーム内時間をamount分だけ進める。tick境界(World.minutesUntilTick)を跨ぐたびに、その境界まで 時計を進めてtick()を1回実行する。
呼び出しを刻んでも結果は変わらない(次の境界までを時計から読み直すため)。UI層はこれを利用して、 一括で進めた経過をあとから刻んで見せる。
これ自身も1つのまとまりとして囲う(runToSeam)。操作の中から呼ばれたぶんは入れ子になるので 切れ目にならず、操作の外で時間が動いた場合だけ、進め終えたところが切れ目になる。
今効いている、操作が宣言した持続効果(11.7節)が持つ影響の辺を書き出す
(Windows.md 8.4節)。登録と同じく、辿れるのはここだけ
(setInteractionPassivesRegistered)。役も同じく憶えた文脈が答える
(runningInteractionPassives)。
効いているものを、視点で絞らずまるごと書き出す。 どの辺がその視点に届くかを決めるのは
書き込み先(PropertyInfluences)——辺の両端のどちらでもない物には1件も当たらない——なので、
ここで手前から絞ると、同じ判定を2箇所が持つことになる。加わっている操作だけに絞ることも
できない:対象に書けるのは役だけではなく(self・parent・ancestorも書ける、11.7節)、
その相手はその操作に加わっていない。
このtickで指し先が動いたぶんを、今の操作の稼ぎとして数える(PropertyPassiveEffectが、積分の 手前で自分の対象を名乗る)。名乗れるのは今の操作が宣言した持続効果(11.7節)だけ。
受け取るのは指し先で、プロパティ値ではない。 名乗る時点でその物がまだ持っていなくてよい ——このtickの積分の途中でbecomeが走れば、新しい型にしか無いプロパティはそこで生える(9.9.1節)。
指定したObjectDefの新しいWorldObjectを生成する(spawn、9.4節)。まだどこにも配置されていないため、呼び出し側がmoveToSlotOrRejectionで配置する。
worldインスタンスを生成し、このセッションのworldとして結び付けて返す。時計を持つworldを得る唯一の道 ——WorldObjectの生成にはセッションが要る(初期値のロールにrngを使う)のに、World付きのセッションは そのworldインスタンスを要る、という相互依存を、生成と結び付けを同じ1手にして断つ。
生成は一度だけ。2回目は、既にそのworldで動き出したオブジェクトが居るはずなので拒む。
時間を要する手番を、操作の切れ目まで待たせる(Action.takeTurn)。
同じ物の同じ手番は1つしか待たせない。 限界に居る間は毎tick同じ手番が挙がるが、起こすのは 切れ目に1度でよい。
待ちを起こしている最中に挙がったものは、手番の別を問わず落とす(理由はtakeWaitingTurns)。
非公開gatherbodyの実行中に物が出入りするたび、その1件ずつをonChangeへ流す(WorldChange参照)。
これは「何が起きたか」だけを運ぶ。 起きた結果どう見えるかは、そのtick境界の世界を読み直す側 (PlayScene.runAndRecord)の仕事で、両方が要る——ログだけでは絵にならず、絵だけでは誰がやったか分からない。
bodyの実行中に操作が直に増やした値を、操作1回ぶんまとめてonGainsへ流す(PropertyGain参照)。
1件ずつではなく1回ぶんをまとめて流す。 同じ値へ複数回書く効果があり(胃へ足したぶんが 溢れて戻る)、途中の書き込みを個別に流すと、受け取る側が足し合わせ直すことになる。
bodyの実行中に告げられた出来事を、その1件ずつをonSignalへ流す(WorldSignal参照)。どの告げ方で 宣言されたものも、この1つの口を通る。
物の出入りとは別の観測口にする。 出入りは世界の形が変わったことで、こちらは形が変わらない ままの出来事なので、同じログに混ぜると受け取る側が毎回どちらかを選り分けることになる。
bodyの実行中にtickが回るたび、その直後にonTickを呼ぶ。呼ばれた時点で世界はそのtick境界の時刻に 居るので、UI層は「その瞬間の世界」を読み取れる(時間経過の再現、PlayScene参照)。
実体値への書き込み1件を溜める(PropertyValue.addからのみ呼ぶ)。操作を実行している間 (withInteractionGains)の、時間の経過の外での書き込みだけを数える。
形を変えない出来事1件を観測口へ流す(SignalEffectからのみ呼ぶ)。誰の身に起きたかは効果が 指した対象で、物の出入りの主体(今適用中の効果、runAndRecordChange)とは別に決まる——殴って外した 出来事は、殴った側ではなく殴られた側の上のことになる。
このtickで実体値が動いたぶんを溜める(PropertyValue.tickからのみ呼ぶ)。時間の経過の中で 起きるのに操作の稼ぎになる唯一のものなので、recordGainとは別の口で受ける。
受け取るのは、その値へ同じtickに入るaddをまとめ、端のクランプまで済ませた後の正味。
数え先かどうかは名乗り(countTickMovementAsGain)が決めるが、数える量は宣言した量ではなく
動いた量で、荷や痛みが同じtickで削ったぶんはそこから引かれている。
物の出入り1件を観測口へ流す(WorldObjectの配置の関門からのみ呼ぶ)。主体は今適用中の効果から 決まるので、呼び出し側は渡さない——「誰の仕業か」を各関門が覚えて回す形にすると、増えた関門が 渡し忘れる。
観測していなければ何もしない。世界に出入りが無い呼び出し(未配置のまま消えた物)も流さない。
非公開run1 tick分の世界の進行。値の積分(WorldObject.tick)のあとに、時間が起こす操作を配る
(trigger: tick、WorldObject.runTickActions)——動物が動くのは時間が経ったからで、
そのtickの値が出そろった後になる(HuntingSystem.md 5.2節)。
観測口(observeTicks)へ知らせるのは両方を終えてから。「そのtick境界の世界」には、 動物がしたことも含まれている。
bodyを、抜けたところを操作の切れ目にする1つのまとまりとして走らせる(ActionSystem.md 2節)。 時間の中では起こせなかった手番(deferTurn)を、抜けたところで起こす。
まとまりを名乗るのは、操作を実行として張る側(InteractionRelation.whileActing)
——操作(actions/combinations・製作の1工程・枠へ入れる)はどれもそこを通るので、操作を書く側が
囲いを覚えておく必要は無い。操作でないのに囲うのは操作の外で起きる時間の進行
(advanceWorldTime)で、待たせた手番を無関係な次の操作まで持ち越さないため。
入れ子の内側では起こさない——外側のまとまりがまだ続いていて、動作主はそちらに就いたままだから (GameElementDefinition.md 11.5節)。
declarerが宣言元になっている、経過中の操作の持続効果(11.7節)の登録を、対象を問わずまとめて 外す/載せ直す。
この登録を辿れるのはここだけ。 宣言しているのは物ではなく操作で、効いている間そのdefを 持っているのはこのセッションなので、物のdefからは見つからない。
載る先は宣言元とは限らない(役を対象にできる、11.5節)ので、誰の型が変わったときに呼ぶかを 決めるのは呼ぶ側(WorldObject.setInteractionPassivesOfParticipantsRegistered)。
非公開take待っていた手番を、宣言の順に起こす。要件(14節)は起こす時点で引き直されるので、待っている間に 限界を抜けた手番はそこで落ちる。
起こしている最中に挙がった待ちは、手番の別を問わず落とす(deferTurn)。起こした手番自身も 時間を進めるので、その間にまた同じ手番が挙がることも(一度の強制では限界を抜けられなかった場合)、 別の値が尽きて違う手番が挙がることもある。どちらもここで受け取ると切れ目から抜けられないので、 次に時間が動いたときの待ちとして拾い直す。
操作が宣言した持続効果(11.7節)が効いている間としてbodyを実行する。登録はその一式が持ち (InteractionPassiveEffects.setAllRegistered)、こちらは効いている間のぶんを積んで持つ。
contextはその操作の関係が用意した文脈(InteractionRelation.contextFor)。役はここから解く
——理由はrunningInteractionPassives。
bodyを「sourceが宣言した操作1回」として囲う(InteractionDefが、実行のはじめから終わりまでを 囲う)。ここに居る間に操作が増やした値だけがobserveGainsへ流れる——経過中のtickが動かした値は 入らず(insideTick)、その操作が宣言した持続効果が動かしたぶんだけが入る(recordTickMovement)。
溜めたぶんは抜けるときに流す。入れ子になる——経過中のtickが配った手番(動物の1手)は その中で実行され、自分の稼ぎを自分の溜め場へ持つ。
bodyの実行中に起きた変化の主体をsubjectにする(WorldObject.applyActiveEffectが囲う)。
入れ子は内側が勝つ。効果の適用中に別のオブジェクトのrangeイベントが走れば、そこで起きた変化は そのオブジェクトのものになる(治りきった怪我が自分を消すのは、殴った側の仕業ではない)。
1セッション分の実行時状態。WorldCodexはロード後不変な定義の集合であり続けるため、instance IDの発行という 可変な状態はここに持たせる。スロット移動はWorldObject.moveToSlotOrRejectionが自分自身の責務として行うため、ここでは 仲介しない。
観測口(observe)はどれも同じ約束を持つ。*
分かれているのは運ぶものが違うからで、何を運ぶかは各メソッドが言う。