第5部:内部の仕組みと仕様
FreeTrainは、時間、経済、人口動態が数式に基づいて相互に影響し合うシミュレーションエンジンを搭載しています。本章では、ソースコード調査に基づいた詳細な内部の仕組みと計算式について解説します。プラグイン作成時のパラメータ調整の参考にしてください。
5.1 時間と季節の管理
時間の進み方
ゲーム内の時間は Clock クラスによって管理されています。
- 基本単位: 内部処理は「分」単位で行われます。
- 現実時間との比率: 標準のゲーム速度(「普通」設定、タイマー間隔 100ms)において、100ms ごとにゲーム内時間が 2 分進みます。
- ゲーム内 1分 = 現実 50ms(0.05秒)
- ゲーム内 10分 = 現実 0.5秒
- ゲーム内 1日 = 現実 72秒
- ゲーム内 1か月 (30日) = 現実 36分
- 昼夜の切り替え:
- 6:00: 昼モードへ切り替え(朝)
- 18:00: 夜モードへ切り替え(夕)
このタイミングで
PictureManager.reset()が呼ばれ、夜景対応スプライトの再描画が行われます。
季節
3ヶ月ごとに季節が切り替わります。
- 春: 3月〜5月
- 夏: 6月〜8月
- 秋: 9月〜11月
- 冬: 12月〜2月
5.2 会計システム
プレイヤーの資産は AccountManager クラスによって管理されます。
資産と資金
- 開始資金: ゲーム開始時の手許資金は、デフォルトで150億円に設定されています。
- 手許資金: 建設や車両購入に使用できる現金です。
- 利息の不在: 現金に対して自動的に利息が付くロジックはありません。銀行預金や株式運用が必要です。
- 倒産判定: 手許資金がマイナスになると「倒産」と判定されます。
車両の資産価値と売却
車両(編成)を売却する際の返金額は、購入価格と経過年数に基づいて算出されます。
売却価格 = 購入価格 / (経過年数 + 2)- 購入直後:価格の 1/2 (50%)
- 1年経過:価格の 1/3 (約33%) 購入した瞬間に価値が半分になるため、注意が必要です。
建設・撤去コストの詳細
鉄道施設の費用は、基本単価に以下の式で算出される倍率を掛けたものになります。
| 施設 | 建設基本単価 | 撤去基本単価 |
|---|---|---|
| 通常線路 (1ボクセル) | 6,000,000 | 2,000,000 |
| 勾配線路 (1基) | 40,000,000 | 8,000,000 |
建設費用の計算式
建設費用 = 建設基本単価 × 高さ・深さ倍率
- 地上(高架):
地表からの高さ + 1- 地表なら1倍、高架1段なら2倍となります。
- 地下:
地表からの深さ × 2- 地下1階なら2倍、地下2階なら4倍となり、高架よりも割高に設定されています。
撤去費用の計算式
撤去費用 = 撤去基本単価 × ( |現在の高さ - 水面高さ| + 1 )
- 水面高さ (waterLevel): マップ全体の基準となる海抜(通常は0)です。撤去費用は地表からの高さではなく、この水面からの絶対的な距離に応じて高くなります。
運行・運賃の計算式
- 走行費用: 列車が4ボクセル移動するごとに以下の費用が徴収されます。
走行費用 = ( 車両数 × 20 + 乗客数 / 20 ) × 2000 - 運賃収入: 乗客が駅で降車した際、以下の式で算出される収益が発生します。
運賃収入 = 降車人数 × 基礎運賃 × 移動距離(ボクセル) × 2- 基礎運賃: plugin.xml の
<fare>タグで指定された値(デフォルト 400)。 - 移動距離: 乗車駅と降車駅の座標間の距離(マンハッタン距離)。
- ※この「× 2」という係数や
fareの基準値は、ゲーム内での1日の収益が現実の鉄道経営のおよそ3倍の効率になるようバランス調整された結果の数値です。
- 基礎運賃: plugin.xml の
5.3 地価システム
FreeTrainの経済シミュレーションの中核は、熱伝導方程式を応用した地価モデルです。ソースコードに基づく仕様は以下の通りです。
基本メカニズム
地価は「熱(Value)」の発生、伝導、拡散によって計算されます。
- 価値の発生 (Add Q): 駅や道路などの施設が活性化すると、そのボクセルに「熱(Q)」が加算されます。
q[x,y] += deltaQ
- 熱伝導 (Conduction): 熱は、周囲のボクセルへ「伝導率(Rho)」に応じて広がります。
- 舗装道路:
0.999(非常に熱を伝えやすい) - 未舗装道路:
0.8995 - 更地:
0.80 - 山:
0.40 - 海(水面下):
0.03(ほとんど熱を伝えない)
道路網がつながっていると地価が上がりやすく、山や海が障壁となって発展が止まるのはこのパラメータによるものです。
- 舗装道路:
- 時間減衰 (Diffusion): 熱は時間とともに「蒸発(拡散)」して失われます。
DIFF = 0.99(毎ステップ1%ずつ減少)- 更新頻度: ゲーム内時間で10時間ごとに再計算されます。
地価の算出式
最終的な「地価(Land Price)」は、蓄積された熱量 Q から以下の式で算出されます。
LandPrice = (int)(Math.Pow( Q, 0.3 ) * 10)
熱量 Q の0.3乗に比例するため、ある程度までは急激に上がりますが、高くなりすぎると伸び悩みます。
5.4 建物と収益
子会社の財務諸表計算
子会社(プレイヤー所有の建物)の利益、売上、経費は、建物の新築時価格(StructurePrice)と現在の地価(LandPrice)に基づいて、以下の対数関数モデルに従って計算されます。
- 利益の算出:
まず、その土地が生み出しうる最大利益
maxProfit(L)を求めます。maxProfit(L) = 0.01 × (L + 1) × log(L + 1)実際の利益は、建物価格
Tと地価Lのバランスで決まります。- 建物価格が地価以上のとき (T >= L):
Profit = maxProfitPrime(T) / 2 × (L - T) + maxProfit(T) - 建物価格が地価未満のとき (T < L):
Profit = maxProfitPrime(T) × 2 × (L - T) + maxProfit(T)
※maxProfitPrime(T)はmaxProfitの導関数0.01 × (1 + log(T + 1))です。
地価が高いほど利益が出やすく、また地価に見合った(安すぎない)建物を建てることで利益が最大化されます。
- 建物価格が地価以上のとき (T >= L):
- 経費と売上:
経費 = profit(StructurePrice, 0) + LandPrice売上 = 経費 + 利益
建物価格(時価)の算出
子会社の売買時に使用される「評価額」は、土地の価値と収益性が反映された「時価」として算出されます。
時価 = 新築時の建物価格 + 土地価格 + (過去1年間の利益 × 10)
- 土地価格: 建物が占有する全ボクセルの地価の合計。
- 利益の10倍: その建物が今後生み出すと期待される利益の合計。
このため、地価が上昇した場所や、乗客が多く利益が出ている建物を売却すると、建設時よりも大きな利益(キャピタルゲイン)を得ることができます。
自動発展
コンピュータによる自動発展は、駅の活性度に基づいた「発展エネルギー」の蓄積と、地価に応じた多段階のシミュレーションによって行われます。
開発のトリガー:エネルギーと試行回数
各駅は内部的に「発展エネルギー (
strength)」を持っており、以下のルールで変動します。- エネルギーの蓄積:
ScoreImported(降車客数) + ScoreExported(乗車客数) × 0.1- 降車客の影響が非常に大きく設定されています。乗客が降りる駅ほど、周囲が活性化します。
- エネルギーの拡散: 毎日、蓄積されたエネルギーに拡散係数(0.2)が掛けられ、翌日のベースとなります。
- 開発の試行: 列車の発着回数 (
ScoreTrains) がそのまま、その日の開発チャンス(最大試行回数)となります。
- エネルギーの蓄積:
開発地点の選定
開発が行われる場所は駅周辺からランダムに選ばれますが、その探索範囲は周辺の地価に比例して拡大します。
- 探索範囲(半径)の計算式:
半径 = 10 + (地価 × 0.1)- 地価が低い地域では半径10ボクセルですが、地価が上がるにつれてより遠く(地価100なら半径20ボクセル)まで開発が波及します。
- 制限: 水面下、マップ外、およびプレイヤー所有物件は対象外となります。
- 探索範囲(半径)の計算式:
建物の選定と建設・建て替えルール
開発地点が決まると、その場所の地価に見合った建物が候補の中から自動的に選ばれます。
- 選定基準: その地点の地価に対し、以下の価格帯の建物が選ばれます。
- 最小価格:
現在の地価 × 1.0 - 最大価格:
Max( 地価 + 15, 地価 × 1.2 ) - ※V2では、上記の計算結果をさらに10,000倍した価格が判定基準となります。
- 最小価格:
- 新規建設 (更地の場合): 対象地点が更地である場合、上記の条件に合致する建物があれば「工事現場」が配置されます。
- 建て替え判定 (既存物件がある場合): 既に建物がある場所でも、都市の発展(地価の上昇)に伴い、以下の条件を満たしたときのみ建て替えが行われます。
- 条件: 現在の建物の価格が、上昇した地価の2.5倍を下回った場合。
- この係数により、地価が少し上がった程度で建物が頻繁に入れ替わるのを防いでいます。
- プレイヤー物件の保護: プレイヤーが建設した建物 (
isOwned) は、コンピュータによる自動発展(撤去・建て替え)の対象から完全に除外されます。
- 選定基準: その地点の地価に対し、以下の価格帯の建物が選ばれます。
建設プロセス
FreeTrainでは、建物は一瞬で完成するのではなく、建設プロセスが可視化されます。
- 工事現場: 建設が決定すると、まず「工事現場」のエンティティが配置され、クレーンなどの専用グラフィックが表示されます。
- 完成: 一定時間が経過すると、工事現場が実際の建物へと置き換わります。
- 土地造成: 建物だけでなく、畑や駐車場などの地表オブジェクト(
LandBuilder)も、2x2から6x6などの可変サイズで自動的に配置されます。
特定の建物を自動発展の対象から外したい場合(特殊な建物など)、plugin.xmlに <computerCannotBuild /> タグを記述することで、CPUによる建設を禁止できます。
発展パラメータのチューニング指針
「発展パラメータ調整」ダイアログでの設定は、プレイスタイルに合わせて調整してください。
- 早く発展させたい場合:
tbAddedQScale(地価上昇補正係数)を上げる:駅や道路の影響がより早く地価に反映されます。tbReplacePriceFactor(建て替え価格係数)を下げる:古い建物がすぐに新しいビルに建て替わるようになります(デフォルト 2.5)。
- 開発のしがい(戦略性)を高めたい場合:
tbQAlpha(地価伝導率)を下げる:道路沿いに地価が広がるスピードが遅くなり、無計画な道路網では発展しにくくなります。tbBaseRho(標準地価伝播密度)を下げる:更地への地価の波及を抑え、駅の重要性を高めます。tbQDiffuse(1-地価発散率)を下げる:地価が冷めやすくなり、列車の運行を止めるとすぐに街が衰退する、シビアな運営を楽しめます。
5.5 人口動態
FreeTrainにおける「人口」とは、単なる居住者数だけでなく、その建物が生み出す「交通需要(乗客)」の定義でもあります。
乗客発生のメカニズム
建物に設定された「基礎人口base」に対して、人口クラスごとの「係数」を掛けることで乗客数が計算されます。
- 駅の集客範囲: 駅は周囲のボクセルから人口を吸い上げます。
- 通常施設: 半径 10ボクセル
- 広域施設: 半径 20ボクセル
スタジアムや空港などの巨大な構造物、あるいは C# でSpecialStationListenerインターフェースを実装した施設は、通常の2倍の広域から乗客を集めることができます。
- 乗車: 建物から出て、駅へ向かう人の流れです。
- 降車: 駅から降りて、建物へ向かう人の流れです。
建物の人口制限(地価によるキャップ)
計算された「建物の人口(駅を利用したい人)」は、その土地の地価によって上限が制限されます。
建物の人口 = Math.Min( 計算上の人口, 地価 * 建物体積(XYZ) + 10 )
地価が低い土地に巨大なビルを建てても、利用者は頭打ちになります。発展していない地域(地価50程度)では、1x1x1の建物から最大60人しか発生しません。
駅の利用人口と消費乗客数
各駅は、接続された建物から発生する人口を合計した「駅利用人口」を持っています。 ここから実際に列車に乗車した人数は「消費乗客数」として記録され、駅利用人口から差し引かれます。
- 消費乗客数: 実際に列車に乗って出かけた人数。
- 時間減衰: 消費乗客数は、出かけた人が戻ってくることを表現するため、毎時 0.8倍に減衰(回復)します。
乗客数の計算式
FreeTrain EX Av V2では、駅の乗客数は以下の式で決定されます。
乗客数 = min( 乗車希望者, 列車の詰め込み乗客上限 )
乗車希望者 = (駅利用人口 - 消費乗客数) * 0.3 * (amenity / 100)
- 乗車希望者: 駅にいる待機客のうち、一度に乗車できるのは最大30%です。
- 魅力係数 (
amenity): 列車の魅力(標準100)がそのままパーセンテージとして掛かります。- 魅力120の特急なら、30% * 1.2 = 36% の客を乗せられます。
- 魅力90の古い車両なら、30% * 0.9 = 27% しか乗せられません。
詰め込み乗客上限の計算
定員 (capacity) を超えて、どれだけ寿司詰めになれるかの限界値です。
FreeTrain EX Avでは、「着席定員 (seatedcapacity)」の設定値を用いて以下のように計算されます。
詰め込み乗客上限 = 着席定員 + (定員 - 着席定員) * 2
- 座席には1人しか座れませんが、立席スペース(定員 - 着席定員)には定員の2倍まで詰め込めると仮定しています。
- 例: 定員150人、着席50人の通勤電車の場合
- 立席定員 = 100人
- 上限 = 50 + (100 * 2) = 250人 (乗車率約167%)
人口クラス一覧
ソースコード (FreeTrain.Contributions.Population) に基づく全人口クラスの解説です。
プラグインのplugin.xmlに記述する際は、名前空間 freetrain.contributions.population. を接頭辞として付加してください(例: freetrain.contributions.population.ResidentialPopulation)。
1. 住居・宿泊系
| クラス名 | 説明 | 特徴 |
|---|---|---|
| ResidentialPopulation | 住宅 | 朝に「乗車(通勤)」が集中し、夕方~夜に「降車(帰宅)」が集中します。最も基本的なパターンです。 |
| BusinessInnPopulation | ビジネスホテル | 夕方~夜にチェックイン(降車)し、翌朝にチェックアウト(乗車)します。住宅とは逆のパターンを持ちます。 |
| LeisureHotelPopulation | リゾートホテル | ビジネスホテルと似ていますが、休日の利用率が高く設定されています。 |
2. 業務・産業系
| クラス名 | 説明 | 特徴 |
|---|---|---|
| OfficePopulation | オフィス | 平日の朝に「降車(出勤)」が集中し、夕方に「乗車(退勤)」します。休日は活動が低下します。 |
| IndustrialPopulation | 工場 | オフィスと似ていますが、シフト勤務などを想定し、夜間や早朝にも一定の流動があります。 |
| AgriculturalPopulation | 農業 | 農地などに使用されます。乗客流動は極めて少なく、季節や天候による変動要素(内部ロジック的には微小)が含まれます。 |
| SchoolPopulation | 学校 | 平日の朝に強い「降車(登校)」があり、夕方の早い時間に「乗車(下校)」が発生します。休日は休みとなります。 |
3. 商業・娯楽系
| クラス名 | 説明 | 特徴 |
|---|---|---|
| CommercialPopulation | 商業ビル | デパートや大規模店舗など。昼前から夕方にかけて継続的に「降車(来店)」と「乗車(帰宅)」が発生します。休日の方が流動が多くなります。 |
| ShopperPopulation | 小売店 | コンビニや小規模店舗向け。Commercialよりも短時間の利用客を想定しており、回転率が高いパターンです。 |
| RestaurantPopulation | レストラン | 昼食時(12時前後)と夕食時(18時~21時)にピークを持つ、二山型の流動パターンです。 |
| BarPopulation | 居酒屋・バー | 夜間(18時以降)に特化した流動を持ちます。深夜帯にも乗客が発生します。 |
| LeisureLandPopulation | レジャー施設 | 遊園地など。休日の朝~昼に「降車」が集中し、夕方~夜に「乗車」が集中します。滞在時間が長い設定です。 |
4. 特殊・ロジック系
これらは単体で特定のパターンを持つのではなく、計算ロジック自体を拡張するクラスです。
| クラス名 | 説明 | 特徴 |
|---|---|---|
| CombinationPopulation | 複合人口 | 複数の人口クラスを組み合わせて1つの建物に持たせることができます。例えば「住宅(Residential)と店舗(Shopper)の両方の特性」を併せ持つ建物などを表現する際に使用します。 |
| MultiplierPopulation | 倍率変更 | 既存の人口クラスをラップし、その発生率を特定倍率(例:1.5倍)にします。基本パターンは変えずに、交通量だけを増やしたい場合に使います。 |
| PersistentPopulation | 永続・固定 | 常に一定の人口がいるとみなされますが、乗降客の流動(トラフィック)は発生させません。人口統計上の数字だけを増やしたい、あるいは乗客を発生させない建物(変電所、車庫など)に使用されることがあります。 |
| ConstantPopulation | 定数 | 時間帯に関係なく、常に一定の乗客流動を発生させます。 |
| HourlyPopulation | 時間指定 | 24時間それぞれの乗車率・降車率をXMLで直接1時間ごとに定義できる上級者向けクラスです。独自の生活パターンを作りたい場合に使用します。 |
| HourlyWeeklyPopulation | 曜日別時間指定 | HourlyPopulation の拡張版で、平日と休日それぞれについて24時間のパターンを個別に定義できます。 |
時間帯別分布データの詳細
ResidentialPopulation(住宅)における、時間ごとの乗客発生率の定義です。
数値はすべて基礎人口に対するパーセンテージ (%) です。
| 時刻 | 平日:乗車(外出) [%] |
平日:降車(帰宅) [%] |
休日:乗車 [%] |
休日:降車 [%] |
|---|---|---|---|---|
| 0:00 | 10 | 20 | 10 | 20 |
| 1:00 | 5 | 10 | 5 | 10 |
| 2:00 | 5 | 5 | 5 | 5 |
| 3:00 | 5 | 5 | 5 | 5 |
| 4:00 | 5 | 5 | 5 | 5 |
| 5:00 | 5 | 5 | 5 | 5 |
| 6:00 | 40 | 5 | 20 | 5 |
| 7:00 | 100 | 10 | 50 | 10 |
| 8:00 | 80 | 10 | 40 | 10 |
| 9:00 | 80 | 10 | 40 | 10 |
| 10:00 | 60 | 20 | 50 | 20 |
| 11:00 | 40 | 20 | 40 | 30 |
| 12:00 | 40 | 30 | 40 | 40 |
| 13:00 | 30 | 30 | 30 | 30 |
| 14:00 | 30 | 30 | 30 | 30 |
| 15:00 | 40 | 40 | 40 | 40 |
| 16:00 | 40 | 50 | 40 | 50 |
| 17:00 | 30 | 60 | 30 | 60 |
| 18:00 | 30 | 70 | 30 | 70 |
| 19:00 | 25 | 90 | 25 | 100 |
| 20:00 | 25 | 100 | 25 | 80 |
| 21:00 | 20 | 80 | 20 | 60 |
| 22:00 | 20 | 60 | 20 | 50 |
| 23:00 | 15 | 50 | 15 | 40 |
住宅以外の各クラス(オフィス、店舗、学校等)の詳細な乗客発生率・下車誘引率の数値については、EX Av Wikiを参照してください。
- 乗客計算率%(V2案):各クラスの時間帯別の乗車発生率。
- 下車誘引率%(V2案):各クラスの時間帯別の降車発生率。
5.6 金融プラグイン仕様
標準の銀行プラグイン (Bank プラグイン) は、利息を伴う資金運用を提供します。
ローンの利息
銀行から資金を借り入れた場合、負債に対して利息が発生します。
- 日次計算: 利息は毎日、分単位の精度で計算されています。
- 利率: プラグインの設定や借入時の条件によって決定されます。
- 計算式:
利息 = 元金 × 年利 × 経過時間(分) / 1年間の総分数 - 返済: 返済時には、元金に加えて、それまでに累積した未払利息を合算して支払う必要があります。
定期預金の利息 (FixedDeposit.cs)
銀行への預金に対しても利息が発生し、プレイヤーの収益となります。
- 預け入れ期間に応じて利息が計算され、満期時または解約時に手許資金に払い戻されます。
株式市場 (Stock Market)
Economy.cs が市場全体をシミュレートしています。
- 更新頻度: 1日4回(6時間ごと)に大きな更新 (
MajorUpdate) があり、企業の決算などが反映されます。 - トレンド: 景気動向 (
BusinessTrend) はサイン波のような周期性を持ちつつ、ランダム要素 (RandomEx正規分布近似) によって変動します。
