Simutrans Advent Calender 2022 21日目 ~The Programable Dat~
Simutrans Advent Calender 2022 8日目に続いて21日目も担当させて頂くことになりました、当日ギリギリに書いているのでかなり乱雑な内容ですがご容赦
記事の一覧については以下のリンクからどうぞ
「pakに必要なものを3つあげよ」
この質問をされた時に何を3つ挙げるでしょうか? 今日の記事における模範解答としては以下の3つです
- dat(pakの性能定義)
- png(pakの外観)
- makeobj(pak化)
どれもpakには必要な物です、諸元を定めるdat・外観を定めるpng・この2つをまとめてpakとして構成するmakeobj、最悪pngがなくてもアドオンとして定義出来るケース*1もありますがdatがないことには始まらないと思います。
これらを効率的に作るテクニックが今回のアドカレの17日目にM_Kasumiさんが公開した記事においてdat・png共に効率化するツールと手法として紹介されていますが、あえて別アプローチと言う形で今回は書いてみたいと思います。
なぜRuby(とLinuxやら)を使うのか
理由は至極明快です、開発環境としてある程度整っているのがLinux環境上だっただけです。Windows環境でもそれなりに整えることは出来ると思いますが、既に開発関係はLinux上にある程度構築しており、どのマシンからでもSSH経由で作業が出来る強みがあります。
既にアドオンの構成ファイル(datもしくはpng)が更新された場合に自動でmakeobjを走らせるスクリプトがあるなど、切っても切り離せなくなりました。
そんなLinux環境*2で部分的に動くdatを書くための言語として開発中である「Radgrid(仮称)」について少しお話させていただきます。
Radgridについては以下のリポジトリからソースコード等をダウンロードなりすることが出来ますので、気が向いたら覗いてみてください。処理がガサツなコードまみれですが。
github.com
datの言語化とは?
端的には「一定の言語規則に基づいて書いたらdatが出力される」という風にだけ覚えていてください、実際はフォーマットがガチガチだったりするので自由度的にはKasumiさんのよりはあるかないか位だと思います。内部でガチガチなRubyの処理コードを書けるので記法やテクニックをわかっていたら効率よく書けるかもしれない、そんなレベルです。
サンプルコード
# coding: utf-8 #common obj "builDing" name "YIC-Mk_EX-/platform-1f_1" copyright "wa / M.Kousaka" #DratBuilding.group "station" #group "station" dims 1,1,16 type "stop" enables "pax" level 3 waytype "track" _image "platform-f_fence" cursor 5 icon 4 offset 2,0 _snow 1 #infos(['info','construction','ground']) infos(['ground']) frontImage{ siz = 0..@dim_t.to_i - 1 y_pos = 0 y_pos.to_i siz.each do |pos| line = "FrontImage[#{pos}][0][0][0][0][0]=#{@image}" if pos.to_i < 8 if pos.to_i == 0 || (pos.to_i % 2) == 0 puts line.to_s + ".#{y_pos}.#{@offset_x}" else puts line.to_s + ".#{y_pos}.#{@offset_x + 1}" y_pos += 1 end else if pos.to_i == 0 || (pos.to_i % 2) == 0 puts line.to_s + ".#{y_pos}.#{@offset_x - 2}" else puts line.to_s + ".#{y_pos}.#{(@offset_x - 2)+ 1}" y_pos += 1 end end if pos.to_i == 7 puts "\n" y_pos = 0 end end puts "\n" if @snow == 1 # 降雪画像がある場合のみ追加処理 siz.each do |pos| line = "FrontImage[#{pos}][0][0][0][0][1]=#{@image}" if pos.to_i < 8 if pos.to_i == 0 || (pos.to_i % 2) == 0 puts line.to_s + ".#{y_pos}.#{@offset_x}" else puts line.to_s + ".#{y_pos}.#{@offset_x + 1}" y_pos += 1 end else if pos.to_i == 0 || (pos.to_i % 2) == 0 puts line.to_s + ".#{y_pos}.#{@offset_x - 2}" else puts line.to_s + ".#{y_pos}.#{(@offset_x - 2)+ 1}" y_pos += 1 end end if pos.to_i == 7 puts "\n" y_pos = 4 end end end } backImage{ siz = 0..@dim_t.to_i - 1 y_pos = 0 y_pos.to_i siz.each do |pos| line = "BackImage[#{pos}][0][0][0][0][0]=#{@image}" if pos.to_i < 8 if pos.to_i == 0 || (pos.to_i % 2) == 0 puts line.to_s + ".#{y_pos}.#{@offset_x}" else puts line.to_s + ".#{y_pos}.#{@offset_x + 1}" y_pos += 1 end else if pos.to_i == 0 || (pos.to_i % 2) == 0 puts line.to_s + ".#{y_pos}.#{@offset_x - 2}" else puts line.to_s + ".#{y_pos}.#{(@offset_x - 2)+ 1}" y_pos += 1 end end if pos.to_i == 7 puts "\n" y_pos = 4 end end puts "\n" if @snow == 1 # 降雪画像がある場合のみ追加処理 y_pos = 4 siz.each do |pos| line = "BackImage[#{pos}][0][0][0][0][1]=#{@image}" if pos.to_i < 8 if pos.to_i == 0 || (pos.to_i % 2) == 0 puts line.to_s + ".#{y_pos}.#{@offset_x}" else puts line.to_s + ".#{y_pos}.#{@offset_x + 1}" y_pos += 1 end else if pos.to_i == 0 || (pos.to_i % 2) == 0 puts line.to_s + ".#{y_pos}.#{@offset_x - 2}" else puts line.to_s + ".#{y_pos}.#{(@offset_x - 2)+ 1}" y_pos += 1 end end if pos.to_i == 7 puts "\n" y_pos = 4 end end end }
ソース: radgrid/sample_plathome.rdg at master · Myagami/radgrid · GitHub
言わなくてもわかります、明らかに汚いコードというのは自他ともに認めざるを得ません。
これはpak.nippon向けに制作している「YIC_Platform_Extends」というプラットホームのニッチな拡張アドオンの1ファイルをradgird向けに書き直したものになります
ぱっと見で「これはdatの劣化コピーじゃないか?」と思われるかもしれませんが、それがおそらく正解です。
思想としては「既存のdatを一部手直しすればRadgrid側で読み込める」という所があります、それだけでなく同一画像を使用する前提として設計しているので画像指定を1箇所でして、内部的にはそこから参照したり、今のところ画像指定部分では生のRubyのソースコードを書けるようにして柔軟性(要検証)をもたせたりしています。
建物についてはかなり複雑なコードになりつつありますが、車両についてはかなりシンプルな構成になっている…とは思います
obj "vehicle" name "JRH DC_Kiha_130" copyright "555" waytype "track" _group "diesel" #engine_type "diesel" #smoke "Diesel" engine_smoke freight "Passagiere" speed "110" gear "140" payload "100" cost "1800000" weight "28" power "186" length "6" RunningCost "110" sound "2" year_month([1988,10],[2003,3])
車両アドオンのソースについては都合により日本語化Wikiに投稿されている555さんの「[Emu][Dmu]JR北海道車両セット」よりキハ130系のdatをサンプルコードに変換して作成しております、こっちのほうが結構シンプルに書ける要素が多いとは思います。
intro_year/monthとretire_year/monthを1つの行でまとめて書いて「これは1988年10月から登場して、2003年の3月には引退するな」という直感的なメソッドになっていたり、車両のタイプを指定したら付随する要素を自動的に指定したりと細かいところは手が入っていても、車両アドオン(特に電車や特急等)で必要な「連結設定が破綻していないか*3」といった重要な要素がまだ実装しきれていません。とりあえず気動車1両ならシンプルなテストが出来るので…*4
まだまだ荒削りな言語について雑な紹介という形で21日目の記事とさせていただきました、今後なにか更新したりしていたらシムトランス交流会議なる所にこっそり書いているかもしれません。
参加についてはこの記事をご参照ください
シムトランス交流会議 参加者募集! - Simutrans Addon Portal
最後に
余談①
8日目の記事のタイトルは「そのマップを離さない」、今日の記事のタイトルは「The Programable Dat」、そして記事で出した言語名は「Radgrid」
仕込んできた答え合わせと行きましょう
- そのマップを離さない
bushiroad-music.com
楽曲:君の手を離さない、厳密には「君の手を離さない ~BOUQUET Ver.~」が正解です
- The Programable Dat
assaultlily-pj.com
舞台名: The Fateful Gift
- Radgrid
ヴァルキリーの一柱
『アサルトリリィ』に登場する「一柳隊」の正式名。
余談②
言語名としてRadgridを付けた話とその由来については先に上げましたが、最初はdratという明らかに適当につけた名前でしたが英和翻訳を掛けたら明らかに和訳結果が色々と申し訳なくなったので仮案として「Radgrid」か「Eir(エイル)」で悩んだ末に「Radgridのほうがかっこいいじゃん」ということで決定、なおEirについてもまぁ…そういうことです。
詳しい話はこの動画に一切を丸投げします