[Simutrans] cityrules.tabで都市の発展を制御する
Simutransには様々な機能がありますが、本記事では取り上げられることが意外と少ないcityrules.tabを見ていきたいと思います。
cityrules.tabはSimutransにいくつかある設定ファイルのひとつで、都市の発展に関する設定を担当しています。通り一遍の解説は設定ファイル/cityrules.tab - Simutrans日本語化・解説に譲り、本記事では市道・建物の生成ルールを詳しく取り上げます。
cityrules.tabを編集することで、都市が発展する際に市道・建物がどのように建設されるかを制御することができます。先行研究として、シムトランス観光局 - Simutrans Tourism - 碁盤の目状の町並み作りに挑戦があります。
以下、SimutransはすべてStandardです。
cityrules.tabを試してみる
手始めに、いくつかのcityrules.tabで発展の様子を観察してみることにします。準備として、適当にマップを生成します。
そしてチートツール「都市の人口を増やす」を連打します。まずはpak64デフォルトのcityrules.tabでやってみましょう。
今度は前記シムトランス観光局から発展ルールをお借りして、同じことをやってみます。
このように、発展ルールを調整することにより、都市の発展を制御することができます。
pak.nipponは独自のcityrules.tabを持っているので、これも試してみます。
cityrules.tabでできること
それではcityrules.tabを編集するとどんなことができるのでしょうか。実験的にいくつか発展ルールを作ってみました。
建物を作らない
cityrules.tabに発展ルールをひとつも記述しないと、人口を増やしても建物が生えなくなります。
まあ、無職者と浮浪者が増えるのですが…。このあたりの挙動は、市域内の道路を全撤去した場合の挙動と似ています。「モニュメントは市道で周囲を囲んで建設される」という仕様があるので、ちょっとだけ市道が増えているのがわかります。
碁盤目都市
建物は生やすけれど新たな市道を作らない、というのも当然可能です。この場合そのままでは既存の幹線道路に沿って市域が拡大してしまうので、あらかじめ道路網を整備しておくようなプレイスタイルに有効でしょう。特に、デフォルトのままでは、いわゆる碁盤目都市は2×2格子以外にするのが難しかったところをうまいことやれるようになります。
4×4格子でやってみます。まずはデフォルトのcityrules.tabから。
格子の中に市道ができたり、市道ができなかった格子は内部が埋められずに残ってしまったりして、うまいこといきません。
次に4×4格子に適するような発展ルールを作ってやってみます。
市内建築物を綺麗に生やすことができました。モニュメントが生えたせいで市道が建設されているところがありますが、これはcityrules.tabではどうしようもないので仕方ありません。
同じ4×4格子でも、格子を邪魔しない程度に市道を生やすルールも可能です。少し小さめの碁盤を用意して試してみます。
そして人口を増やします。
このように碁盤の中は余計な道路が生えすぎず、しかし碁盤の外へ枠を越えて発展していきます。碁盤の中でちょっと道路ができているのはモニュメントが生えると周りに影響してしまうのが理由です。さすがに碁盤の外に無から4×4格子を生成するのは無理ですが、許容できる程度の生え方にはなったかなと思います。最初の碁盤を「田」ではなく「井」の字型にするとまた違うかもしれません。
格子を維持しつつ道路を生やす発展ルールは、マップ内に碁盤の計画都市とそれ以外の都市を共存させることを目論んで書きました。そこで、碁盤を引かなくてもちゃんと道路が生えて都市が広がってくれることを試してみます。
うまくいっています。
ただ、このルールは4×4碁盤の内外の調和が取れるように直線を多めにしつつ、4×4格子の中に市道ができないように分岐を少なくしたので、道路が平行なまま接続せず何マスも続いてしまうというケースがちらほら見られます。今の例では右上あたりにその傾向が出ているのがわかります。
初期生成都市
新しいマップを作ったときに生成される都市も、内部的には人口を増やすツールと似たような処理をしているっぽく、ということはcityrules.tabで制御できます。
たとえば先のルールで新しいマップを生成してみます。
新しいマップを作るときにこのルールにするのはあまり適当とは思えない感もありますが、ルールが適用されているのは確認できると思います。マップ生成時とそれ以降の開発とでcityrules.tabを使い分けることは可能なので、マップ生成に最適化したcityrules.tabを作るとよい感じになるかもしれません。
cityrules.tabの書き方
「ぼくのかんがえたさいきょうの発展を達成するためにはどんなcityrules.tabを書けばよいか」解説マニュアルが存在しないので試みに書いてみます。対象読者としてはsimuconf.tabなどのSimutransの何らかの設定ファイルを多少弄ったことある以上の人を想定しています。また、前記日本語wikiの該当ページもあわせて参照するとよいです。
準備1:設定項目を理解する
cityrules.tabの発展ルールのセクションは次のようになっています。
house_1 = ... Hn. sss
house_1.chance = -2
house_2 = ... .nH sss
house_2.chance = -2
road_1 = .H. SnS .sS
road_1.chance = 8
road_2 = .H. .n. SsS
road_2.chance = 4
house_1
とhouse_1.chance
の2行で1組の設定で、これを何個も並べていくことになります。house
の他にroad
もあり、書き方は同じです。house
が建物の生え方、road
が市道の生え方に関する設定です。
house_1
の方は、記号・アルファベットをたくさん並べます。この並んでいる文字は、1文字が1タイルに対応していて、全体で正方形の領域を表現しています。正方形のサイズは3×3・5×5・7×7のどれかでなければいけません。
house_1 = ... Hn. sss
# これは、正方形の領域
# ...
# Hn.
# sss
# に対応する
Simutransの設定ファイルは1行1項目が基本なので、正方形をスライスして1行に並べて書きます。
各文字の意味はデフォルトのcityrules.tabのコメントや日本語wikiに書いてあります。書き抜いてくると次のようになります。
S |
道路ではない |
s |
道路 |
n |
裸地(何もない素の地面) |
H |
建物(house)ではない |
h |
建物 |
T |
停留所(stop)ではない |
t |
停留所 |
U |
allowed slope for roads |
u |
forbidden slope for roads |
. |
なんでもよい |
house_1.chance
の方は整数で、その組の「重み」を指定します。日本語wikiには「この規則が適用される確率を表します」と書いてあります。同じことです。数値が大きい方が「軽い」「確率が低い」「選ばれにくい」です。
準備2:動きを理解する
さて、都市が発展するときには、次のような動作をします(これは日本語wikiの「アルゴリズム」を噛み砕いたものです)。
- 建物・道路を生やす候補となるタイルを選ぶ。
- 今選んだ候補タイルを中心とする正方形の領域を考える。その正方形と、cityrules.tabの発展ルールの正方形とを比べてみて、一致するルールだけを残す。
- 残ったルールを
house
とroad
に分ける。 house
とroad
のそれぞれについて、残ったルールの“chance
”に対応する「重み」をぜんぶ足す。「重み」の和が充分大きければ、そのタイルに建物あるいは道路ができる(TRPGが分かる方は、「重み」の和がステータス値で、そこにSimutransがダイスを振っていくと考えれば近いです(ほんまかいな))。
(とても大雑把な表現をしたので、正確なアルゴリズムについては日本語wikiやソースコードをあたってください。)
目標ルールをcityrules.tabに落とし込む
やることは「準備2」を逆算することなのですが、慣れていないとなかなか難しい。しかしながら、自分のやっていることを他人にできるようにマニュアルとして書くのも難しい。。。一言でまとめると「ひたすら試行錯誤する」になってしまう。
- 「あり得そうなシナリオ」をいくつか用意する。具体的には、初期生成された都市にあり得そうな配置を何パターンか選ぶことになる。計画都市を対象にするなら碁盤目も。紙やパソコンに書きつけておくとよい。
- 各シナリオについて、「こういうふうに道路が生えたら嬉しい」「ここには道路は生えて欲しくない」というような事例を作る。
- 「こういうふうに道路が生えたら嬉しい」を実現できるようなルールを書く。その上で、そのルールで「ここには道路は生えて欲しくない」が発生しうるかどうかよーく考えてみる。
- 「ここには道路が生えて欲しくない」が発生しなさそうなルールを採用して、cityrules.tabに書く。
- そのルール群で「都市の人口を増やす」を試してみる。
- 生えて欲しくない道路や建物ができてしまったら、その原因となったルールがどれか考えてみる。それらしきルールがあれば、それをどうにか改良する。
- よさげになるまで繰り返す。
ね、簡単でしょ?
ちなみに、建物と道路では、道路の方が小さな違いがクリティカルになることが多くて難しいように感じました。
もっといい方法があるよという方はぜひご紹介ください(というか、私自身数時間試したに過ぎないのですよね…)。Advent Calendarがなくてもブログは書いていいのよ(チラッ
cityrules.tabの限界
cityrules.tabを弄らないのと弄るのとでは見える景色が結構違うのではないかな、と思うのですが、しかしcityrules.tabを弄ってもできないこともあります。
最も大きいのは、「マップ全体通して同じcityrules.tabが適用される」ということで、都市ごとに異なるルールを適用したりできないので、現実のゲームプレイでは柔軟性に欠けると言わざるを得ないかもしれません。また、ルールの記述法が「物足りない」というか、目標とするルールを素直に表現することができず、妥協した書き方をした上で変な所が出なくなるまで試行錯誤する、みたいなことを私の場合はしていて、これは大きな課題だと思います。
cityrules.tabを書いての所感
- デフォルトのcityrules.tabは3×3ルールのみで書かれていて(5×5・7×7はあとから追加されたためと見られる)、5×5・7×7ルールを活用すればよりbetterなルールをデフォルトで提供することもできるのではないかと思ったりします(思うだけ)。
- cityrules.tabの表現力として、“OR”が簡単でないことが特徴だと感じました。すなわち、「タイルAとタイルBの両方に道路がある ではない 場合」を表現しようとすると、「タイルAに道路がない OR タイルBに道路がない」が必要になるのですが、これを1つのルールとして書く方法は存在しないので、「タイルAには道路があるがタイルBには道路がない」と「タイルAには道路がないがタイルBには道路がある」の2つを書いてあと
chance
値を上手い具合に調整するとか諦めるとかするしかなく、結構な制約になります。 chance
値は日本語wikiの説明によれば線形ではないのでかなり扱いづらいです。しかも、上の説明では「重みの和」と書きましたが、実際には日本語wikiの説明によればルールごとに確率試行を繰り返すので、とても直観的ではありません。
これからのこと
こんなこといいな、できたらいいな、ふしぎなパッチがかなえてくれる(
- cityrules.tab編集補助ツール。これには2段階あって、第1段階としてとりあえず正方形で書いたものを1行にして連番を付けてくれるというだけのものなら簡単に作ることができます。第2段階としては、複数のルールの「重みの和」を具体的に求めることができるようにするとか、“OR”を書いたらそれを複数のルールにばらして記述してもらえるとか、より踏み込んだ記述支援が考えられます。
- ソースコードを読んでcityrules.tabの挙動を精緻に理解することができれば、より「よい」ルールの書き方を見出すことができるかもしれません。
- 本体改造してcityrules.tabの挙動を弄ってみよう!
配布
途中のスクリーンショットを撮るのに使ったcityrules.tabは近日中に配布する予定です(準備が間に合いませんでしたごめんなさい)。