himeshi’s blog

Simutrans本体改造まわりのお話をつらつらと

OTRPの運営方針について

どうも、ひめしです。

OTRPの運営(?)方針について尋ねられることが多くなってきましたので、自分の思考の整理も兼ねてここに書き残しておきます。

OTRPの方針はその起源から来るものも多いので、OTRPの起源あたりからつらつらと書いていこうと思います。

【1/9更新】本家フォーラムへの投稿について文面を変更しました。standard統合を目指す予定のない機能は本家フォーラムに投稿する必要はなく、OTRPのみにプルリクエストできます。

 

OTRPのはじまり

もともとは「二車線パッチ」として道路での二車線走行機能を実現すべくパッチを本家フォーラムに投げ始めたのが始まりです。動作確認のために本家フォーラムに貼っていた実行ファイルを日本のユーザーにも紹介したのが始まりでした。

その後本家フォーラムで「二車線パッチ」について議論を重ねましたが、主に私のコーディング技術が未熟だったことが原因で本家統合の見通しが立たなくなりました。そのままプロジェクトは終わるところでしたが、二車線パッチをこよなく愛してくださる方々がいらっしゃいましたので、2017年11月に独立を宣言し、私家版Simutransとして専用配布ページをオープンしました。

二車線パッチ時代から開発を進めるにつれて要求仕様が膨らみ、本来の二車線走行以外の付随機能も載せるようになっていきました。本家統合を放棄し独立したことで、二車線走行関連機能以外も実装し搭載するようになっていきます。日本人プレイヤーが好む「乱開発フレンドリー」な機能をそれなりのスピードで実装していったことで、OTRPはおかげさまで日本を中心にユーザー規模が拡大しています。

 

OTRPの役割

OTRPは、いろいろな事情でSimutrans Standardに組み込めない機能を受け入れるエディションです。

ですので、standardに組み込まれて然るべき機能がOTRPのみに搭載されているという状態を私はあまり良しとしていません。本家で議論が止まってしまった、そもそもstandardにはふさわしくないなどといったパッチを受け入れるというのがOTRPの立ち位置だと私は考えています。

ただし現実は、standardに入りうるのにOTRPのみになっている機能も少なからずあります。これは単に私がきちんとstandardに持っていくのをサボっているだけですので、2019年はこれらの機能も少しずつ本家に持っていくことを計画しています。

 

「OTRPについての議論の場」について

近頃OTRPに興味をお持ちの方が増えた上に、OTRPにプルリクエストを投げてくださる方も増えようとしています。議論がすぐ流れてしまうTwitterではなく、OTRPのための議論の場が欲しいという声は理解できます。

しかし、先に述べたようにOTRPはstandardに組み込むことができない機能を受け入れる場ですので、OTRPの為の機能の議論をする場を設けることはあまり適切だと考えていません。作るべきなのは「standard系(extended向けではない)の本体議論をする場」です。これについてはTwitterなり日本語フォーラムなり本家フォーラムなり既存インフラがそれなりにあります。

なおpull requestを投げてくださる開発者様とのやり取りは、基本的にGitHub上で行うこととしています。Twitter上での議論でも構いません。

 

OTRPの開発原則

去年の夏にも同じ話は書きましたが、再掲しておきます。

  • アップデート時は常にsimutrans standard nightlyに追従する。あくまでもstandardの拡張版であり、本家でされた改良、バグ修正の恩恵をプレイヤーが確実に受け取れるようにする。アップデートで必ずnightlyに追従することで本家の変更をmergeすることが困難になるのを防ぐ。
  • 独自アドオンを要求する機能は搭載しない。standard用のアドオンがあればそれで完結する設計にする。ただでさえ64, 128, extended用のpakとフィールドが分かれているsimutransのアドオン界隈において、OTRP独自の規格を設けてもうまくいくはずがないからである。
  • セーブデータの互換性を確保する。いつ何時も、standardのセーブデータは必ずOTRPで読み込めるようにする。standardのセーブデータを読み込んだときは、OTRPで開いたときにはstandardと全く同じ挙動をするようにする。(つまりOTRPはただのstandardとしても使える。)OTRPのセーブデータもOTRP独自の機能まわりを犠牲にすればstandardで読み込む手段を提供する。
  • UIの互換性に配慮する。standardからOTRPに乗り換えてきた人にとって、OTRPの機能について何も知らなくてもstandardとして遊ぶ分には困らないようにする。プレイヤーはOTRPの機能について少しずつ探求することができる。(extendedは始める前にある程度extended独自のゲームシステムについての知識がないと不自由する傾向にある。)

要するにOTRPがstandardの完全上位互換として使えるようにするということです。今のところRibi-Arrow以外についてはこの原則を守って開発しているつもりです。

 

OTRP統合の依頼について

OTRPに統合してほしい機能がある場合は、teamhimeh/simutransのOTRPブランチにプルリクエストしてください。先に上げた「OTRPの開発原則」に反することがない限りは、基本的に受け入れる用意があります。

ただし、standardに統合する予定のある機能に関しては、まず一度本家に投げることをお願いしています。これは専らメンテナンス上の都合によるもので、ある単一機能について本家リポジトリとOTRPリポジトリとで不必要な差分が生じることを防ぐための措置です。

ある機能についてstandard統合を目指すのか、OTRP専用に提供するかは開発者の自由です。standardに統合させる予定のない機能については最初からOTRPにプルリクしていただいて結構です。また、開発した機能をさっさと日本のユーザーに届けたいのであれば、本家フォーラムへの投稿とOTRPへのプルリクを同時にしていただいてもかまいません。皆さまのプルリクエストを心よりお待ちしております。

なお、OTRPはリリースごとに原則として本家リポジトリに追従しますので、standardに統合されればその機能は必ずOTRPユーザーにも届きます。

standardベースで開発するかOTRPベースで開発するか

OTRP固有の機能に密接に結びついた内容でない限りは、standardベースのコードで開発することをオススメします。standardとOTRPのコード差分はそこまで大きくないので、standardベースで開発したブランチをOTRPベースのブランチにmergeしてもあまりconflictしないはずです。

セーブデータの読み書きはstandardとOTRPでバージョン管理が異なるので注意してください。もしわからなければstandard向けのままプルリクしていただいてもかまいません。

 

機能の実装依頼について

私への機能の実装依頼はどのような形でしていただいてもかまいません。ですが、実装するかどうかは私の心の琴線に触れたかどうか次第です。

多くの皆さまにとってあまり現実的な話ではないことは承知しておりますが、ある機能がSimutransに載るための最速ルートは自分で実装してしまうことです。一人でも多くの方がこのルートを取れるように、私はこれまでパッチゼミをしたり本体開発本を書いたりとそれなりに活動してきたつもりです。

それはさておき、皆さまのご意見やご要望をいただくことは私のSimutrans本体開発活動の原動力の一つです。皆さまの声すべてにお応えすることはなかなか難しいですが、今後もぜひご意見ご要望をお寄せいただき本体開発を(コードを書かずとも)一緒に楽しんでいただければなと思います。

 

2019年の本体開発活動について

昨年はずいぶんたくさん実装をした覚えがありますが、今年はCities: Skylinesに手を出そうかななどと考えているので開発ペースは落ちると思います。

現時点で私がやりたいと思っている主なトピックは以下のとおりです。

  • 増解結
  • 範囲建設系ツールをOTRPからstandardに持っていく

それでは今年もよろしくお願いいたします。

C95日本シムトラ学会大盛況のお礼とBOOTH通販開始のお知らせ

どうも、ひめしです。

C95の2日目で出展しました「日本シムトラ学会」では大変多くの皆さまにおこしいただき、新刊もたくさんご購入いただきました。おかげさまで出品した7品のうち自由町を除く全てが完売(自由町も終了時点で在庫僅少)しました。ありがとうございました。

 今回私はコミケ初参加(サークル参加はおろか一般参加も経験無し)でした。右も左も分からない私を準備段階から支えてくださり、当日も巧みなトークでたくさん人集めをしていただいたMARKさん、ポスター作りをお手伝いいただき会計作業をがんばってくださったふぃすたむさん、そして、私が今回頒布した本体開発本の作成に多大なサポートを頂いたshingoushoriさんに、今一度お礼を申し上げたく思います。

 

夏コミ(C96)出展について

今回大盛況に終わった日本シムトラ学会ですが、私が次の夏コミでサークルを主催する予定は今のところありません。

個人的にはシムトラ同人誌頒布の機会は年一回くらいがちょうどいいのかなと思っています。シムトラ学会も2017年は3回もありましたが2018年は一回でしたので、まぁそのぐらいの頻度がちょうどいいのでしょう。とか言って年一回の申込みで落選してしまったらorzなのですが。

申込書は会場で購入し手元にありますので、シムトラ関連でC96に出展したいという方には喜んでお譲りします。ご興味をお持ちの方はtwitter @himeshi_hobに連絡をお願いします。

 

『Simutransの本体開発』の再販について

今回弊サークルで出品しました新刊のうち、ひめし著『Simutransの本体開発』と、ふぃすたむさん著『Simutrans-Extended 信号保安システム入門』は午前中に完売してしまい、午後にブースにいらっしゃった皆さまに頒布することができませんでした。そこで、『Simutransの本体開発』についてはBOOTHにて通販することとしました。

himeshi.booth.pm

本自体の価格はコミケと同じ1000円ですが、送料が上乗せされることをご容赦ください。手元の在庫がゼロなのと、年末年始で印刷所が休みなので、発送開始は2019年1月14日を予定しています。

なお、この通販に関しては2019年1月中のみ実施予定です。2月アタマには一旦店じまいする予定ですので、ご希望の方はお早めにご注文ください。

2018年版 みんなが欲しいアドオン・機能

どうも、ひめしです。おかげさまでSimutrans Advent Calendar 2018は大盛況のうちに幕を閉じることができました。記事を投稿してくださった皆さま、お読みいただいた皆さま、ありがとうございます。

adventar.org

 

今年で二回目のアドベントカレンダーですが、実はこんな企画をやっていました。

【アドオンをリクエストしようキャンペーン】
エントリーされた皆さま、記事の中に「今自分が欲しいアドオン」を書いてみましょう! 

というわけで、皆さまからいただいたアドオンリクエストを以下に列挙します。特記なき場合は主にpak128無印のアドオン需要です。

車両

建築物

  • 奥行きの長さが半分の箱積み
  • 中小規模の駅舎
  • 市内建築の公園、博物館、文化施設など
  • 「緑」な公園アドオン
  • コンテナホーム・ホッパ・フォークリフト・トラックヤードなどの貨物駅セット
  • 果樹園(田んぼや茶畑以外に農地が欲しい)
  • 商店街のアーケード
  • 温泉宿
  • 繁華街歓楽街のにぎやかなビル

軌道や架線

  • 架線柱2マスおき設置に対応したwayobj
  • diagonalで道路を2つ並べたときに真ん中を埋めるアドオン(中央分離帯やダミーの車線など)
  • SIS新幹線軌道の新描画位置対応版
  • OTRPで使いやすい大交差点対応道路信号(pak64系だと釘ニさんのアドオンが良い例です。)

本体の機能

  • 路線ごとの営業最高速度
  • 路線ごとに運賃n倍プッシュ(ルート検索でも考慮)
  • groundobjで雨を降らせる(雨雲がかかってるところを薄暗くするなど)
  • 土土地の上げ下げを,レールとかでCtrlと組み合わせるときれいな直線が引ける,適な機能

 

アドオン職人の皆さん、仕事の時間ですよ!

 

【1/1追記】

peing.net

ここにリストアップされたアドオンについて質問箱に配布先を書いてくださった方がいらっしゃいました。

『Simutransの本体開発』を書いて

この記事はSimutrans Advent Calendar 24日目の記事として書かれたものです。

adventar.org

私、ひめしはこの度Simutrans本体開発初の教科書『Simutransの本体開発』を執筆し、頒布させていただいております。環境構築から始まり、シムトラ本体開発の基礎知識の解説、そして本体改造の実践演習と、ゼロからある程度本体改造を楽しめるようになるまで一通りカバーしたつもりです。

 12月8日にはありす様主催のSimutrans学会in京都にて初回頒布をさせていただきました。おかげさまで売上部数22部を記録し、増刷をさせていただくまでになりました。ご購入いただきました皆さま、ありがとうございます。次回の頒布は冬コミ二日目です。ぜひいらしてください。 

さて、本自体はシムトラ本体開発の教科書として閉じた形にしたかったので、あまり余計なことは書きませんでした。(ページ数が増えて価格が上昇するのを避けたかったというのもありますが。)この記事では、本にまつわる与太話をつらつらと書いていきたいと思います。

 

本を書き始めた動機

本のあとがきのところには「去年のパッチゼミで教科書が必要と感じた」とか書きましたが、実際のところこの本を執筆したのは完全に院試勉強の現実逃避ですorz

院試(大学院修士課程の入学試験のこと)は8月末でしたので7月アタマぐらいから院試のための勉強を始めたのですが、いかんせん身が入りませんでした。院試が終われば卒論の中間発表なるものを提出することになっていましたので、「気分転換にTeXの練習でもするか」とおもむろにTeXのセットアップを始めたわけです。

このときふざけて本体開発本の序論的なものを書いてみたのですが、そこでスイッチが入ってしまいアレヨアレヨと筆が進み始めてしまいました。

 とはいえこのときはただ現実逃避のために本を書いていたので、どこで頒布するとかいう話はとくに考えていませんでした。ちょうどこの時期にC94(夏コミ)があったのですが、それもあって「次の冬コミに出せ」というお声をいただくようになります。

コミケ出展どころかコミケに行ったことさえない私は躊躇していましたが、MARKさんからトドメの一言が。

 そしてついに退路を自ら断ってしまったわけです(

 ありすさんによるシムトラ京都学会のアナウンスもあったので、京都学会に間に合うように執筆をするということがこの時決まりました。

 

 全然別の話になりますが、本体開発本を書いたのは私がいつSimutransの活動から離れても良いようにしたいからという理由もあります。私がSimutransを始めてから8年が経ちましたが、この間にずいぶんと界隈の人が入れ替わりました。あれだけ精力的に動画を上げていたうp主さんが、あれだけすばらしいアドオンを量産していた作者さんが突然失踪することはごく当たり前に起こることです。

アドオンであれ本体改造であれ、作者が引退すると、その制作物は程度の差はあれど使えなくなっていきます。緩急坂の導入によって古い軌道系アドオンは事実上使えなくなりました。本体のパッチの場合、本家のコードの変化に追従させないと、パッチを統合することさえすぐに困難になります。アドオンやパッチが継続的に使えるようにするには、「誰か」がメンテナンスを担う必要があります。この点で、アドオンや本体パッチの製作技術を次の世代に伝えることは重要なのです。

技術を次の世代に伝えることの重要性を私が痛感した一つのできごとは、俗にいうSISショックです。SISプロジェクトの構成メンバーの方々がいろいろな事情によりアドオン制作の第一線から引退され、多くのアドオンが「死に絶えた」というべき状況になりました。SISの後継を担うアドオンは私が知る限り未だ登場していません。作者が引退すると制作物が死を迎えるというのはあまりにも悲しいと私は思うのです。

アドオン制作の場合、その制作プロセスの全てをオープンにすることはあまり一般的ではなく、オープンにしようとしても簡単ではありません(それでも最近はAdvent Calendarなどを通じてアドオン制作ノウハウを公開する方が増えており、大変喜ばしいことです)。しかし、本体開発の場合はソースコードが成果物であり、原典です。ソースコードを読み、その意味を理解し、コードを書くことでアルゴリズムを表現する術を得れば、誰でも思うように開発をすることができます。ですから、『Simutransの本体開発』では、ソースコードの読み方を解説し、実践演習を通じてコードの書き方も習得できるようにしたのです。

私はまだ学生の身分です。いつSimutransの世界からバッタリ消えることになるかは自分でもわかりません。しかし、作ったものは当分そこに残ります。このとき、本体開発を嗜む日本人が少しでもいれば、メンテナンスがされなくなり死に絶えていく運命にある遺産を蘇らせることができるわけです。未来のSimutrans本体開発を担う人の育成に、今回執筆した本が少しでも役立つことができればとても嬉しいです。

 

書くペースとか

8月上旬から書きあげた本ですが、ページ数だけで言えば8月の終わりには8割以上紙を埋めていました。あとから知ったのですが、最初に一気にかきあげると本は完成にこぎつけやすいそうです(要出典)。9・10月はほぼ筆を進めず、11月に残りの2割を書きつつ、既に書いた部分の修正を重ねていきました。

書く内容に困ることはありませんでした。2017年にやった本体パッチゼミの内容をそのまま本に書き下すだけだったからです。(もちろん本の内容はパッチゼミよりも大幅に充実させました。)

特に技術書的なモノの場合、本を誰かに添削してもらうというのは大変有効だと思います。今回の本ではshingoushoriさんに文体・内容の両面から添削をしていただきました。

 

これから本を書く人へ

これからシムトラ系同人誌を書こうとする人にむけていくつか書き残しておこうと思います。

本を書き始めるときにまず最初にすべきことは、頒布イベントへの申込みです。というのも、コミケなどの大型イベントになるとイベントの3〜6ヶ月前というかなり早い段階で参加申し込みが締め切られます。シムトラ系だと主たるイベントはやはりコミケ、ということになると思いますので、本を書くなら12・1月中に決断すべきです。

イベントに申し込むとやる気に満ち溢れると思います。そのまま全体の8割ぐらいはページを埋めてしまいましょう。締切ドリブンな書き方は締切直前の時期に忙しくなってしまうとアウトなので、スタートダッシュでほぼ全部埋めてあとは修正をするだけという状態にまでしてしまうのが良いと思います。それでも締切直前は慌ただしくなるものですが。

本を有償で頒布する場合、気をつけなければならないことは権利関係です。これについてはMARKさん(自由町というシムトラ入門本を執筆なさっています)が12/8のシムトラ学会でわかりやすく説明されていました。一度は確認してアタマに入れておいたほうが良いと思います。(下の動画の5:30あたりから権利関係の話がはじまります。)

www.youtube.com

 

おわりに

『Simutransの本体開発』の次回の頒布はC95(冬コミ)二日目(日曜日)東ホールT-06b「日本シムトラ学会」にて行います。頒布価格は一冊1000円です。新刊5品、既刊2品の計7品を用意してお待ちしております。ぜひおこしください。

 

ネット通販はコミケ頒布であまった分だけやります。コミケで売り切れる可能性も無くはないです。入手したい方はコミケ来場をオススメします。どうしても入手したい方でコミケ来場が物理的に困難な場合はひめしにご連絡ください。

 京都学会で本をお買い上げいただいた方へ、このたびは本をご購入いただきありがとうございました。本体開発とどのように関わるかは各人の自由ですし、本をどのように扱うかもまた各人の自由です。しかし、せっかく本を手にとっていただいたので、ただ文章を眺めるだけではなく、ぜひ演習をこなして本体開発を習得していただけると著者として大変嬉しいです。

 

ほしいアドオン

アドベントカレンダーのキャンペーンでほしいアドオンを挙げようというのをやっておりますので私も書いておきます。私が欲しいのは基本的にpak128無印版のアドオンです。

車両系... TOQ2000・6000系(Qシートも)、都営浅草線5500系、シティーカーアドオン(バラエティ豊かな日本車をたくさん走らせたい)

インフラ系... SIS新幹線軌道の新描画位置対応版、OTRPで使いやすい大交差点対応道路信号(pak64系だと釘ニさんのアドオンが良い例です。)

Simutrans本体2018年総まとめ

どうも、ひめしです。

先日12/8に開催されましたシムトラ学会in京都でお話した内容のスライドを公開します。(イベントのハッシュタグは #シムトラ学会4 です。)2018年にあったSimutrans本体の機能追加を総ざらいする内容です。(extendedは除いています。)

speakerdeck.com

後日ありすさんから発表の動画が上げられるとのことですので、そちらもよろしくおねがいします。

 

【12/15追記】

学会の動画が上げられましたので貼っておきます。

www.youtube.com

なぜ振り分け信号の手前で列車は減速するのか

どうも、ひめしです。コードを書く気にも本を書く気にもなれないので記事を書きます(

Simutrans standardには振り分け信号というものが用意されています。あいている適当なホームを見つけて入線する信号ですが、デフォで設定した経路以外に入線するときはきまって信号手前で減速します。これはなぜなのでしょうか?

これを理解するにはsync()とsync_step()の説明が必要です。

simutransは車両、建物、道路などといったすべてのオブジェクトに対して定義されたsync()とsync_step()という二種類の関数を延々と呼び続けることでシミュレーションを実現します。「すべての」オブジェクトかどうかはあやしいですが。鉄道車両が一番わかり易いので以降は鉄道車両を題材に説明します。

鉄道車両の場合、毎フレーム画面を描画するたびに車両の位置や速度が変化していきます。したがって毎フレームごとにこれらを再計算しなければなりません。画面を描画するたびに(正確には画面を描画する前に呼ばれる)行うシミュレーション処理は基本的にsync_step()にかかれています。convoi_tに定義されたsync_stepの冒頭は以下のような感じです。編成のstateごとに定められた処理を行っています。(コードの中身を読む必要はありません。)

sync_result convoi_t::sync_step(uint32 delta_t)
{
	// still have to wait before next action?
	wait_lock -= delta_t;
	if(wait_lock > 0) {
		return SYNC_OK;
	}
	wait_lock = 0;

	switch(state) {
		case INITIAL:
			// in depot, should not be in sync list, remove
			return SYNC_REMOVE;

		case EDIT_SCHEDULE:
		case ROUTING_1:
		case DUMMY4:
		case DUMMY5:
		case NO_ROUTE:

ところで位置の更新や速度の計算は比較的少ない計算量で終えることができますが、ルート探索などは処理が重いので1描画フレームの時間内に処理を完結させることが困難なことがあります。マップ内に10000編成いるならば、描画する間に10000編成分のsync_step()を回し終わらねばならないわけです。

そこで、「処理量は大きいけど急を要さない(1フレームの間に処理を完了させる必要がない)」処理を回す関数としてstep()が用意されています。実際、convoi_t::step()を見ると、主に

  • ルート探索
  • 停車状態での発車判定・発車処理
  • 貨客の積み下ろし

が行われていることがわかります。これらの処理はいずれも車両が停止している間に行われています。車両が停止しているならば画面が動かない限り再描画の必要はなく、位置や速度といった描画に直接関わるパラメータが変化することもないのでテキトーに処理をはじめてテキトーなタイミングで終わればよいのです。

さて、Simutransは少なくともstandardでは描画まわりはマルチスレッド化されているものの、シミュレーション部は未だ完全なシングルスレッドです。シングルスレッドのプログラムですから処理は定められた順番に逐次行われていくのですが、sync()とsync_step()はどのように呼び分けられるのでしょうか?

実際のCPU時間の使われ方を簡単な図にすると、下のようなものになります。

f:id:himeshi:20181017000428p:plain
step()とsync_step()の呼ばれかた
基本的にはsync_step()・step()両方とも、クロックを持つ外部オブジェクトから定期的に呼ばれています。もう少し具体的に言うと、呼び出し間隔が決められていて、前回の呼び出し時間から定められた時間経過すると、関数が呼び出されるチャンスが与えられるという仕組みです。
例えば描画レートが30fpsの場合、sync_step()の最後の呼び出しから1/30秒たつと(実際にはちょっと違いますが)sync_step()を呼び出すことが可能になり、sync_step()が呼ばれます。その結果図のようにsync_step()が概ね定間隔で呼ばれます。
さて、CPUがあいていればsync_step()が適切なタイミングで呼ばれますが、もし大きな実行時間を要するstep()が実行中だとsync_step()を呼び出すタイミングが遅くなってしまいます。これでは画面描画が遅くなりカクつく原因になります。そこで、step()の中では時折interrupt_check()を呼び出して、sync_step()を呼び出すことになっています。ソースコードを覗いたことがある人なら INT_CHECK という文字列に見覚えがあるのではないでしょうか?simintr.hにこのマクロは定義されており、INT_CHECKを踏むと、interrupt_check()を呼び、sync_step()を呼ぶ必要があるタイミングであるかチェックするのです。下のコードはdataobj/route.ccの一部で、INT_CHECKがコードに挿入されている例です。引数の文字列はデバッグ用途のものです。

// memory in static list ...
if(  nodes == NULL  ) {
	MAX_STEP = welt->get_settings().get_max_route_steps();
	nodes = new ANode[MAX_STEP];
}

INT_CHECK("route 347");

// we clear it here probably twice: does not hurt ...
route.clear();

このようにしてsimutransはsync_step()をできるだけ等間隔に呼びつつ、その合間に処理量の大きい処理を行っています。さて、振り分け信号の減速問題に話を戻すことにしましょう。

列車が動いているときの処理は基本的にsync_step()で行っています。列車が進めば次の閉塞に進入可能か判断する必要があります。rail_vehicle_t::is_signal_clear()がその関数ですが、この関数はsync_step()内で呼ばれます。ですので、振り分け信号を目の前にしたときの処理もsync_step()が行うことになります。
ところで、振り分け信号はまず予め指定した座標に入線できるかチェックします。もしこの時点で進入許可が出れば、列車はそのまま進行すればいいのでsync_step()内で処理は完結します。
ところがここで入線できないということになると、空きホームを探さねばなりません。空きホームを探すのは探索処理にあたり、sync_step()ではなくstep()内で行うことになっています。step()は処理の完了時間が予測できないので、列車が走行中に行う処理を記述することはできません。そこで空きホームを探す探索処理を行うために、列車を一度停止させてstep()を回す必要があるのです。
というわけで厳密には列車は一度停止しているのですが、その停止は一瞬なので見かけ上はただ減速してるように見えます。これが振り分け信号の手前で列車が減速する理由です。

なお先ほどのお話には大きく2つのツッコミどころがあります。

  • 振り分け信号の探索処理は探索空間がさほど大きくないので実はsync_step()内で行っても大丈夫なのではないか?なぜstep()内で行う必要があるのか
  • 列車が走行中に行う処理をstep()にやらせることは本当に不可能なのか?

このあたりの話はマルチスレッド化にも深く関わるところでまた大きなトピックになりますので、別の機会に解説することにしましょう。
とりあえず今回はここまでにします。お読みいただきありがとうございました。

続・アドオンの減色について

前回はアドオンの減色のしくみについて解説したので、今回はなぜ減色がされているのか、今後減色が解消される見込みはあるのかなどについて考えたいと思います。
himeshi.hateblo.jp


アドオン減色について語るには、まずSimutransの描画処理まわりをおさらいする必要があります。
Simutransに限らず大半のGUIプログラムは、描画処理を何らかのライブラリに任せる形で行っています。言い換えると、描画ライブラリと呼ばれるプログラムに対して描画命令をすることで画面が描画されるということです。Simutransは描画ライブラリとしてallegro、GDI、OpenGLSDL、SDL2をサポートしています。今回は描画ライブラリをSDL2として話を進めることにします。
なお描画ライブラリの命令は描画ライブラリごとに異なるので、simsys.hが描画命令を共通化する役割を持っています。SDL2の場合の実装ファイルはsimsys_s2.ccです。

描画手順は各ライブラリごとに若干異なりますが、概ね次の手順で行われます。まずSimutransは描画するピクセルデータを描画バッファと呼ばれる変数に格納します。描画バッファにピクセルデータを格納し終えたらライブラリの画面更新命令を呼びます。これで、描画バッファに格納されたピクセルデータが画面に反映されるのです。
Simutransの描画処理は、地面を描き、線路を描き、車両を描き・・・と続いていきます。地面画像の上に線路画像や車両画像が塗り重ねられていき、最終的にすべて塗り重ねた結果を描画ライブラリに渡しています。よってピクセルを塗り重ねていく処理はSimutrans自身が行うことになります。塗り重ねの処理はdisplay/simgraph16.ccにかかれています。なおsimgraph0.ccGUIを起動しないサーバーモード用の処理であり、描画処理を行いません。

simgraph16.ccの386行目で、描画バッファ変数は次のように宣言されています。

/*
 * Output framebuffer
 */
static PIXVAL* textur = NULL;

PIXVAL型の実体はuint16です。この時点で、画像の塗り重ね処理自体が16bit整数で行われていることがわかります。減色されたアドオン画像を256階調RGBに復元しているわけではないのです。ちなみに画像のアルファ値はライブラリに渡されるのではなく、simutrans自身が重ね塗りをするときに吸収しています。

さて、描画処理自体が16bit(内訳はRGBそれぞれ5bitずつで本当は15bit)で行われていることがわかりましたが、32bitで扱うのとくらべてどのような違いがあるのでしょうか?大きな違いは主に2つです。

  • 描画処理のパフォーマンスに差が出る
  • アドオンpakファイルサイズが2倍になる

32bit化するとアドオンサイズが2倍になるのは良いと思います。1ピクセルにつき従来は16bitで表現されていたものが32bitで表現されますからね。
描画処理のパフォーマンスに差が出るというのは、まずピクセル計算に必要なメモリが倍になります。それに伴ってメモリとCPUのデータやりとりも2倍になります。ひめしはあまりグラフィックに詳しくないのでこれがどのレベルまでパフォーマンスに影響を与えるかはよくわかりません。
ともかく、色を32bitで扱うようにするとストレージや処理系の負担になることは事実です。が、近年のコンピュターのパフォーマンスを考えればそろそろ32bit化をしても良い気はしてきます。実は32bit化の足かせになるのはここではありません。Simutransの描画系が16bitから32bitに移行するに当たって困難なのは次の二点です。

  • 実装量が膨大であること
  • アドオンの互換性を担保しなければならないこと

画像描画まわりのコードは膨大です。新しく32bitでの描画をサポートしようとすれば、最低限display/simgraph.hで宣言されている関数をすべて実装しなければなりません。simgraph.hは宣言ファイルですが、このファイルだけで381行あります。16bit色描画を実装したsimgraph16.ccは5336行あります。
実装するのはsimgraphまわりだけではありません。makeobjでpng画像をコンパイルする過程もそうですし、なによりGDIやSDLといった各ライブラリとのインターフェースも32bit色表現に対応させる必要があります。すべての描画ライブラリできちんと動作することを担保せねばなりません。
ちなみに現行Simutransがアルファ対応をするときに32bit化せず16bit空間でゴリ押したのは実装量低減とパフォーマンスの問題とされています。(ソース:
https://forum.simutrans.com/index.php/topic,15314.0.html

アドオンの互換性も大きな課題です。Simutransにはプレイヤーカラーや発光色といった特殊色があります。16bit色環境ではこれらは特殊色として専用の値を割り当てていましたが、32bit色環境でも似た処理を採用するのが望ましいでしょう。するとARGB各成分それぞれフルに8bitを割り当てるわけには行きません。おそらくALPHA成分は5bitにするといった策が現実的になると考えられます。
32bit色環境は間違いなくパフォーマンス面で悪影響をもたらすので、オプションとして提供されるのが望ましいでしょう。すると、アドオンは16bit環境と32bit環境の双方をサポートする必要が出てきます。16bit色環境実行時のパフォーマンスが落ちては元も子もないので、32bit色でコンパイルされたアドオンを16bit色環境でスムーズに表示できるよう工夫が必要です。16bit画像をpakに含めてしまうのは一つの策ですが、明らかにファイルサイズが無駄に大きくなります。32bit色表現で、16bit色環境実行時にスムーズに読み出せるbit配置に工夫するのが良い作戦かと思います。


だらだらと書きましたが、要点はこんな感じです。

  • 減色ナシ化はパフォーマンスが悪化する。それを受け入れれば可能。(ただしアルファチャンネルは若干のビット落ちがあるかも)
  • 本体を減色ナシに対応させるのであれば、減色版本体も同時に提供する必要。
  • 実装はかなり大変。
  • アドオンの互換性をどうするか(減色環境での軽量動作をどう担保するか)の検討が必要

アドオン製作者の皆さんはどうお考えでしょうか?