Files
TheTree_mock/docs/DESIGN_DECISIONS.md
T

26 KiB
Raw Blame History

設計判断記録

本書はGAME_SPECIFICATION.mdで採用した重要判断と、その理由を記録する。過去案へ戻す場合は、影響範囲を確認して新しい判断を追記する。

D-001 地上/地下とFRONT/BACKを別軸にする

  • 状態: 採用
  • 判断: Y軸のゾーンと、奥行きの業務レイヤーを完全に分離する。
  • 理由: 旧文書では「表」が合法地上と客用空間の両方を指し、地下カジノが表施設なのか裏施設なのか判断できなかった。
  • 影響: 施設はzoneとlayerを必ず別フィールドで持つ。

D-002 主人公を従業員ユニットにしない

  • 状態: 採用
  • 判断: 主人公は一施設へ現場介入できる経営者として扱い、スタッフ枠を占有しない。
  • 理由: 神視点の間接操作と「主人公を同室配置」の記述が矛盾していたため。
  • 影響: 移動時間、個人行動ポイント、主人公能力値が必要になる。

D-003 標準速度の1日を現実12分にする

  • 状態: 採用
  • 判断: 現実30秒をゲーム内1時間とする。
  • 理由: 旧案の1日4分では、夕方ラッシュ、通知、シフト、関係イベントへ対応する時間が不足する。高速化はx2とx4で提供する。
  • 影響: 試作GameClockと操作UIを30秒/時間、x1/x2/x4へ同期済み。

D-004 通貨は一つ、違法性はHeatで表現する

  • 状態: 採用
  • 判断: 表金と裏金を分けない。
  • 理由: 二重残高と資金洗浄はUI負荷が高く、建築と動線の中心体験を薄める。違法収益の代償はHeatで十分に表現できる。
  • 影響: 違法サービスは収益と同時にHeatを発生させる。

D-005 風紀度と全館清潔度を廃止する

  • 状態: 採用
  • 判断: 風紀度をReputation、Heat、局所治安へ分け、清潔度はセル単位にする。
  • 理由: 一つの全体値が、客層、犯罪、衛生、監査を同時に動かしており原因が読めなかった。
  • 影響: レポートでは局所値の集計を表示するが、ゲーム判定は可能な限り現場値を使う。

D-006 破産結果を性別で分けない

  • 状態: 採用
  • 判断: 暴動、逃走、装備精算、契約化を性格、戦闘力、信用、ポリシーで決める。
  • 理由: 性別固定は客AIとして不自然で、プレイヤーが結果を予測・操作できない。
  • 影響: 性別は外見、好み、成人関係、妊娠可否など必要な箇所だけに用いる。

D-007 自由雇用者は売却できない

  • 状態: 採用
  • 判断: 契約移転の対象は、成人隷属契約など明示状態を持つユニットだけとする。
  • 理由: 旧文書内で一般従業員の売却可否が矛盾していた。
  • 影響: 雇用区分と契約状態をデータで明確に分ける。

D-008 愛の盾を好感度と別保存する

  • 状態: 採用
  • 判断: Shield MaxはAffectionから算出し、現在Shieldは別値として攻防に使う。
  • 理由: 好感度そのものを攻撃で減らすと、長期関係と短期防御の意味が混ざる。
  • 影響: Shieldは時間だけでは減らず、接触イベントでのみ損耗する。

D-009 重要ルートは閾値だけで確定させない

  • 状態: 採用
  • 判断: 50と80の境界では明示イベントとプレイヤーへの予告を要求する。
  • 理由: 見ていない場所の自動計算だけで取り返しのつかない結果になると、経営判断ではなく不意打ちになる。
  • 影響: 関係状態は数値とイベントフラグの両方を持つ。

D-010 決闘勝利で関係履歴を全消去しない

  • 状態: 採用
  • 判断: 勝利効果はRival Bond -20、Shield +30、接近禁止とする。
  • 理由: 一回の勝負で長期進行を0へ戻せると、日常の配置管理が無意味になる。
  • 影響: Rival Bond 80以上は通常決闘では解決できない。

D-011 ヒロイン一人の離脱を即時ゲームオーバーにしない

  • 状態: 採用
  • 判断: 離脱は経営能力と物語分岐の損失として扱う。
  • 理由: 20~30時間の経営ゲームで一人の自動進行が全セーブを終わらせると、実験的な経営を妨げる。
  • 影響: ゲームオーバーは経営破綻、世界樹喪失、明示された最終章へ限定する。

D-012 CorruptionとRival Bondを独立させる

  • 状態: 採用
  • 判断: 禁忌への適応と、特定ライバルへの関係を別軸にする。
  • 理由: 地下勤務を選ぶだけで自動的にNTRへ進むと、地下経営と純愛維持を両立できない。
  • 影響: 高Corruptionかつ高Affectionの忠誠型サブ分岐を許可する。

D-013 全登場人物の成人条件をデータで保証する

  • 状態: 採用
  • 判断: 成人向け行為、成人労働、契約取引に関わる人物は成人確認済みフラグを必須とする。
  • 理由: 世代システムと成人向け要素を同一作品で扱うため、境界を実装上も曖昧にしない必要がある。
  • 影響: 未成年期は非性的な人口データのみ。成人化は明示的な時間経過後に行う。

D-014 MVPは14日間の垂直スライスにする

  • 状態: 採用
  • 判断: Rank 1~3、ヒロイン1人、ライバル1人、100客を対象とする。
  • 理由: 全仕様を薄く作るより、本作固有の二層動線と関係リスクが面白いかを先に検証する。
  • 影響: 世代、大規模戦争、7人分のシナリオはMVP後に実装する。

D-015 成人向けルートを設定で無効化可能にする

  • 状態: 採用
  • 判断: NTR、強制性の強い展開、妊娠などを個別設定する。
  • 理由: プレイヤーの嗜好差が大きく、望まないルートを避ける管理負担をゲーム難易度に含めるべきではない。
  • 影響: 無効化時の代替イベントを必ず用意し、進行不能にしない。

D-016 1ゲーム分の固定TickとCommand Queueを採用する

  • 状態: 採用
  • 判断: Simulationの状態変更は1ゲーム分の固定Tick境界で、順序付けしたCommandを通して行う。
  • 理由: 画面更新速度や入力TimingによってAI、収支、イベント結果が変わると、再現TestとSave復旧が成立しない。
  • 影響: UIは状態を直接変更せずCommandを発行し、同一Tick内の処理順を固定する。

D-017 人物移動はSoft Collisionにする

  • 状態: 採用
  • 判断: 通路Cellを一人だけが占有するHard Reservationではなく、密度を移動Costと速度へ反映する。
  • 理由: 多人数が狭い縦動線へ集中する本作では、Hard Reservationは相互待ちと永久停止を起こしやすい。
  • 影響: 混雑は視覚と効率低下で表現し、施設入口、座席、昇降機だけ明示Slotを予約する。

D-018 在庫・料金・Service開始を原子的に処理する

  • 状態: 採用
  • 判断: 在庫Reservation、料金決済、Service Slot確保、状態遷移を一つのTransactionで確定する。
  • 理由: 途中失敗時にItemだけ消える、料金だけ取る、座席だけ埋まる不整合を防ぐため。
  • 影響: 取消は履歴削除ではなく、Reservation解除と逆取引で表現する。

D-019 SaveはSnapshot方式を採用する

  • 状態: 採用
  • 判断: 全状態Snapshotと短い診断Journalを保存し、完全なEvent Sourcingは採用しない。
  • 理由: 任意時点再生より、通常のSave容量、Load速度、Migrationの理解しやすさを優先する。
  • 影響: 決定性確認用のCommand ReplayはTest機能として持つが、製品Saveの復元方式にはしない。

D-020 RNGをSystem別Streamへ分離する

  • 状態: 採用
  • 判断: 客判断、Event、行政、戦闘、生成を別の決定的RNG Streamで処理する。
  • 理由: 無関係な客が一人増えただけで監査や重要Eventの乱数結果まで変わる連鎖を避けるため。
  • 影響: Seedだけでなく各StreamのStateとCounterをSaveする。

D-021 監査は監査官の巡回と視認で判定する

  • 状態: 採用
  • 判断: 監査発生後の発見は全館一括抽選ではなく、監査官の移動、視線、帳簿、証言、既知証拠で判定する。
  • 理由: FRONT/BACK動線と隠蔽設計を監査対策へ接続し、処罰の理由をプレイヤーが追跡できるようにする。
  • 影響: 監査官はPathServiceを使い、証拠ごとに発見元と位置を保存する。

D-022 日次の金融締めを00:00、朝の運用境界を06:00に分ける

  • 状態: D-031により廃止
  • 判断: 売上・原価・賃金・維持費・未払金の日次締めとDaySummary確定は日付境界の00:00に行う。06:00はシフト交代、個人AP回復、監査抽選、朝Event、その後のAutosaveだけを行う。
  • 理由: 日付と財務期間の境界を一致させ、同じ売上や費用がどの日に属するかを一意にする。同時に、06:00の人物・監査処理と保存を重い金融処理から分離する。
  • 影響: 23:59から00:00で保留Service確定、Ledger照合、未払判定、DaySummaryをこの順で行う。05:59から06:00のTestは財務締めを再実行しないことも検証する。

D-023 世界樹Rankは1段階ずつ原子的に昇格する

  • 状態: 採用
  • 判断: Rankは条件を満たした次段階へだけ上げる。World拡張、Path再構築、GameState、進行履歴を一つの原子的境界として扱う。
  • 理由: デバッグ用の直接Rank指定を製品Commandへ残すと、解禁条件を飛ばせるだけでなく、Map Boundsだけが先に広がる部分適用を起こし得るため。
  • 影響: 累計Faithと累計客を現在値から分離し、昇格Requestを冪等化する。Rollback不能時は自動再試行せず隔離し、保存復旧を要求する。

D-024 客の欲求を6軸へ統一し、安全・交流を文脈へ分離する

  • 状態: 採用
  • 判断: 永続する客欲求はHunger、Sleep、Hygiene、Medical、Leisure、Intimacyの6種だけとする。安全は危険評価と強制行動、交流は好み・同行者・接客・関係Eventの文脈として扱う。
  • 理由: ゲーム仕様の6欲求と実装の旧5欲求が不一致で、Safetyの不安値が負傷・病気、Socialの孤独値が成人向けIntimacyと混同され得た。原因と解決施設が異なる値を同じ軸へ載せると、客の選択理由とバランス調整が読めなくなる。
  • 影響: GuestService SnapshotをVersion 2へ上げる。Version 1だけはrest→sleep、fun→leisure、social→intimacy、safety→medical、hygiene=0として原子的に移行する。旧名は通常の生成・更新・候補入力では拒否し、Intimacyの時間帯Contextは成人確認済みDefinitionに限定する。

D-025 境界施設は配置anchorでZoneを判定する

  • 状態: 採用
  • 判断: BOUNDARY施設は配置anchorをy = 0へ固定し、Footprintが地上側へ広がることを許可する。ただし地下側へのはみ出しは拒否する。ABOVE_GROUND/UNDERGROUND施設は全占有Cellを指定Zone内へ固定する。
  • 理由: 仕様上の受付はFRONT/境界かつ4×2であり、全Cellをy = 0へ要求すると正規データの施設が原理的に建設不能になる。一方、地下施設の一部だけを未掘削地上へ逃がす配置は許可できない。
  • 影響: Placement Previewと建設確定は同じZone規則を使い、地下CellにはZoneとは別に全Cell掘削済み条件を適用する。

D-026 人物配置リスクPreviewは読み取り専用にする

  • 状態: 採用
  • 判断: 配置確定前の接触時間、Shield攻撃候補、発火可能Event、Route Lock警告、回避案は、既存状態と提案Shiftから生成する純粋なPreviewとして計算する。Previewだけで関係値やLockを変更しない。
  • 理由: 画面を開いた順序や候補の比較回数で関係進行が変わると、配置判断の再現性が失われる。Route Lockは取り返しのつかない境界なので、予測結果から暗黙確定してはならない。
  • 影響: 接触区間は半開区間のunionで二重計上を防ぎ、同一actor・同一shift IDの提案だけを置換する。Content Filterは表示だけを変え、risk、cost、cooldown、Lockの機械的結果は変えない。

D-027 採用費と運営費戻しを日次分類で明示する

  • 状態: 採用
  • 判断: 契約時の採用費は日給と分離して運営費へ計上し、運営費の戻しは同期間費用の相殺として扱う。相殺超過だけをexpense recovery収益へ振り替える。
  • 理由: 採用費を賃金へ入れるとStaffの日次発生額と二重計上になり、運営費戻しを客向け返金へ入れると符号が逆になる。どちらもunknown categoryのままでは正常な雇用後の日次締めが停止する。
  • 影響: STAFF_SIGNING_COST→cost_of_goods、OPERATING_REFUND→cost_of_goods相殺を固定し、相殺超過はanomaly付きでrevenueへ入れる。それ以外の未知categoryはfail-closedを維持する。

D-028 通路施設は副占有からPathへ投影し、未完成の垂直Topologyを推測しない

  • 状態: 採用
  • 判断: 客用通路と業務用通路は主要施設占有と共存するROUTE subslotとして実Pathへ投影する。従業員ドアは職員権限付きFRONT↔BACK Connectorにする。昇降機は、同階隣接Edgeを安全に抑制する垂直Topologyが完成するまで明示的に無変更拒否する。
  • 理由: 通路proxyを主要占有だけで完成扱いにすると、地図には存在しても移動不能になる。一方、現在の平面Graphへ昇降機Connectorだけを足すと、通常隣接Edgeが待ち時間や停止状態を迂回し、運行規則が無効になる。
  • 影響: 建設完成・撤去はProjectorを通してSpatial、Path、Connectorを一つの原子的境界として更新する。未対応昇降機はUNSUPPORTED_VERTICAL_TOPOLOGYを返し、どの依存状態も変更しない。

次の実装契約(未実装):

  • PathServiceの通常WALK Edgeは同じyのx±1だけとし、yが変わる移動は明示Connectorだけに限定する。実A*、到達不能理由の診断探索、復旧地点検索に同じ規則を適用し、別階への暗黙テレポート候補を作らない。
  • 客用/業務用昇降機は回転0度に固定し、同じx・同じFRONT/BACK内のorigin → origin + (0, 1, 0)を双方向ELEVATOR Connectorにする。全FootprintはROUTEとして各階から乗降点へ到達可能にする。
  • 客用はFRONT、容量4、待機8、1階10分、一般利用。業務用はBACK、容量8、待機16、1階5分、staff権限とする。停止・停電中も通常WALKで迂回できてはならない。
  • 待機列、現在階、CabinState、運行状態はPathService所有の可変値とし、ProjectorはID、端点、権限、容量、所要時間など不変部分だけを照合する。乗車中または待機中の撤去は無変更拒否する。
  • 保存意味が変わるため、Path v4、Projector v2、Runtime v7として明示移行する。v6に存在し得る未投影の完成昇降機は、v7移行時に安定IDで投影し、片側だけ生成された状態を許可しない。
  • maintenance Mana 5/6を実Consumerへ登録し、Brownout/OUTAGEをConnector運行状態へ同期する。完成・撤去・停電・Save復元はConstruction、World、Spatial、Path、Mana、通知を一つのrollback境界で検証する。

D-029 境界PauseはTickのhard stopとして扱う

  • 状態: 採用
  • 判断: catch-up中の境界失敗、rollback隔離、日次照合待ち、破綻がPauseを要求したら、同一Frameの残りTickと次の時刻加算を止める。境界分までClockが進んだ失敗は、その分の後続段階だけを再開時に1回実行する。
  • 理由: Pause flagだけを立てて既に算出したTick数を走らせると、Coordinatorの保留分とClockがずれ、保存不能になる。Clockを巻き戻すと、先に確定したCommandと通知の時刻が過去へ取り残される。
  • 影響: running中のCommandは到達予定分をeffective minuteとしてClock加算前に確定する。速度変更と手動stepはhard stopを解除せず、再開は専用の確認境界を通す。

D-030 複数DomainEventは履歴確定後に一括配信する

  • 状態: 採用
  • 判断: Transactionが生成したDomainEventは全件を先に検証・履歴Commitし、その後で固定順にSubscriberへ配る。配信中の再入EventはBatch末尾へ送る。
  • 理由: 1件ずつ検証と通知を交互に行うと、後続ID衝突時に先行通知だけが外へ残り、状態rollback後の再試行で二重通知になる。
  • 影響: UIと不可逆な外部処理はService固有signalではなくCommit済みDomainEventまたはTick Snapshotを使う。Batch拒否は履歴・通知とも無変更となる。

D-031 営業日と日次決算の境界を06:00に統合する

  • 状態: 採用
  • 判断: 暦日は00:00に更新する一方、宿の営業日は06:00から翌日05:59までとする。日次決算は翌06:00に行い、その後に昼番開始、個人AP回復、監査抽選、朝Event、Autosaveを処理する。
  • 理由: 夜間の宿泊、酒場、地下営業を途中の00:00で分断せず、一続きの夜営業として同じDaySummaryへ含める。朝昼営業と夜営業の交代時に会計と運営判断をまとめる方が、宿の経営感覚と一致する。
  • 影響: DaySummaryの期間はDay N 06:00 <= minute < Day N+1 06:00となる。05:59から06:00の境界では財務締めを最初に一度だけ確定し、失敗時は昼番開始以降を保留する。旧D-022は廃止する。

D-032 通常UIの配属は継続計画と勤務実績を分けて保存する

  • 状態: 採用(2026-09-09。通常開業の単日受入・保存復元を確認。3営業日を含むP1全体は未合格)
  • 判断: 通常UIから行う施設配属と勤務帯変更は、従業員ごとの DAY/NIGHT 継続計画 work_assignments として保存する。計画から以後の日次出勤に必要な具体的Shiftを決定的に生成し、毎朝プレイヤーが同じ配属をやり直す必要をなくす。未配属は施設IDを空にした明示計画として扱う。
  • 理由: 雇用時や単日Shiftの一度きりの指定だけでは翌営業日の出勤が途切れる。一方、再配属で既存Shiftの施設を直接書き換えると、過去の勤務時間と日次給与の施設別配賦まで新しい配属先へ移り、決算と保存再開の整合が崩れる。
  • 勤務履歴: 配属変更時に、進行中Shiftは変更時刻で区切って旧施設・既勤務区間を保持する。過去のShiftは書き換えない。未開始の旧予定は取消し、新しい計画の有効区間を別Shiftとして作る。日付をまたぐ夜勤も同じ区間規則を使い、実績時間を重複計上しない。
  • 操作境界: UIは set_staff_work_assignment Commandを送り、Runtimeで施設、役割、定員、到達経路、勤務変更可能状態を検証してから確定する。変更後の将来予定に旧単日Overrideが残って以前の配属へ戻ることを防ぐ。作業中など変更を受け付けられない場合は、理由を表示して状態を維持する。
  • 保存互換: StaffService Snapshotをversion 4とし、継続計画を保存する。旧version 3の保存は計画なしで読み込み、既存の人物・単日Shift・給与履歴を保持する。旧保存の最終勤務先を推測して全員へ繰返し予定を付与しない。読み込み後に通常UIで配属を指定した人物から、新しい継続計画を使う。
  • 影響: 翌日出勤、再配属、夜勤の日付跨ぎ、未配属、作業中拒否、途中Save復元を受入へ含める。施設別給与は保存した実勤務区間を根拠とし、現在の計画だけから過去分を再分類しない。
  • 今回の範囲外: 施設価格、受付の直接収入、宿泊料金の決済・売上記帳タイミングは改定しない。開業ガイドと帳簿は現在のサービス・台帳・06:00決算を読み取って表示する。これらと仕様正本の照合・変更はPLAY-04/PLAY-05で別に判断する。

D-033 P1の厨房供給は既存レシピを維持して通常操作へ接続する

  • 状態: 採用(2026-09-09。供給・製造のP1調整値。3営業日を含む通常プレイの受入は別途検証する)
  • 判断: 既存の ingredient/raw_food 4個から ingredient/basic_meal 4個を15稼働分で作るレシピを維持する。厨房の継続生産計画は客や客財布を要求せず、入力予約、製造進捗、完成時消費と出力を独立して扱う。無人、停電、到達不能、休業時は進捗と予約を保持し、材料の期限切れはバッチ失敗として予約を解放する。出力容量が足りなければ材料を消費せず待つ。
  • 調整値: 食材は1個3G・重量1・期限1,440分、基本料理は重量1・完成後期限720分。保管容量は倉庫100、厨房40、食堂24の重量とし、施設の接客定員とは分ける。厨房への食材補給目標は8個、完成料理の目標は既定8個・上限16個(4個単位)とする。これらは SupplyCatalog に明記した暫定値であり、価格バランスの合格を意味しない。
  • 人員データ: 倉庫の必要役割を既存雇用候補の porter に合わせる。食堂は既存の cook/server を維持して attendant を追加し、接客係Iris/Junoも配属できるようにする。候補に存在しない役割だけを要求して厨房と食堂の同時営業を阻む状態を解消する。
  • 保存と撤去: 生産計画、進行中バッチ、予約ID、進捗と時刻を保存し、復元済みInventoryの所有者・品目・数量・依頼者・用途・期限と照合する。有効な生産計画または進行中バッチがある厨房は解体対象にできない。停止済みかつバッチがない計画は解体成功後に削除する。
  • 仕様差: 正本の「料理ポイント+食器在庫」、食器・清掃用消耗品の購入と消費、廃棄物回収の通常操作は後続の仕様調整へ残す。今回の基本料理を料理ポイントへ暗黙に読み替えない。食堂の現行15分/35Gと正本45分/25G、受付の直接収入、宿泊決済時刻、倉庫のRank解禁条件も、この供給接続では改定しない。

D-034: 通常営業の価格・休業操作とv1照合処理の軽量化

  • 日付: 2026-09-09。承認済みPLAY-05の実装。
  • 価格: 奉仕60%/安価80%/標準100%/高価150%/ぼったくり250%。Gは整数、0.5Gを切り上げる。UI、客の候補評価、Runtimeの新規見積は同じ規則を使う。受付済み・サービス中の価格と方針は受付時のコピーを維持し、後から変更しない。
  • 基準値: 新設受付を無料・20分、一般客室を120G、大衆食堂を25G・45分へ正本§7.6に合わせる。受付を同じ客が何度も訪れて直接売上を増やす動作を解消し、自然な候補ではチェックインを1回までにする。厨房・倉庫等は既存の無料設定を維持する。
  • 保存互換: Runtime v7とDigest v1は維持する。価格・開閉は既存Policyへ格納する。既存保存の非受付施設は保存された基準価格・時間を引き継ぐ。受付では保存された施設の基準価格が20Gでも新規見積は0Gにする。旧受付で受付済みの20G見積、過去の台帳、サービス中の時間は遡及修正しない。旧施設を現行基準へ一括変更する移行は今回行わない。
  • 営業: business_openは既存operator_openへ反映する。休業は新規受付を止め、待機客の予約・在庫を返して再判断させる。開始済みサービスは既存の完了処理を続ける。全グループの所有参照・遷移上限を事前確認し、休業による退列では忍耐を消費しない。厨房・物流の既存開閉判定も同じoperator_openを参照する。配車後でも積込時に荷元を再確認し、休業なら未積込の予約を解いて再試行する。積込済みの貨物は納品先が営業中なら配送を完了できる。休業だけで雇用や給与は止めない。
  • 満足: 既存のサービス品質による満足サンプルへ価格補正(+10,+5,0,-5,-20)を追加する。P1では期待品質を共通50とし、品質が20以上上回ると負の補正を半減する。-2.5は-3へ丸める。品質への反応度quality_sensitivityを期待品質と取り違えない。客別期待品質、待ち時間・好み等を含む正本§8.5の全式、宿泊前払いと追加精算は後続へ残す。
  • 表示: 営業パネルの当日費用は当該施設をsourceとする運営費の記帳で、給与配賦を含む確定利益ではない。給与配賦・施設別利益は06:00の帳簿で確認する。需要は客の予算とUtilityへ実反映するが、予測人数を算出していない段階で架空の人数予測を表示しない。
  • 性能: Snapshotの履歴・項目・検証頻度を減らさず、Digest呼出しの中だけで同じ辞書キー構成の符号化と順序を再利用する。String/StringNameを分け、上限を設ける。値や可変コンテナの出力をキャッシュしない。旧v1実装をテスト参照として残し、全対応型・衝突・変更・深さ・拒否条件のバイト一致を検証する。測定の約2倍はDigest単体であり、実ゲームのfps改善率ではない。
  • 検証記録: P1営業設定。P1全体・初見30分・昇降機・Windows性能の完成判定とは分ける。