PythonでSimutransのマップに天空の市道の碁盤の目を追加してみた
Simutrans(http://japanese.simutrans.com)は, 素晴らしい.
それでもって私は人工地盤っぽいことをやっています。
Simutransで人工地盤してみる - shingoushori's dialy
これまで、Pythonでセーブデータをあれこれし
地形をいじったり、交差部分の接続方向をいじったりして来ました
今回は、いよいよ道路を敷いてみました
... city_road でもいけました ... 高架の道路じゃなくても宙に浮くんですね
天空の市道 (接続方向の計算ミスった) #simutrans pic.twitter.com/qRdh4gTTZJ
— shingoushori (@shingoushori) 2017年9月16日
<経緯>
地形の坂とか、各街の標高や山の標高を考慮しながら敷設していくのは、
楽しいけれども、一向に眺めて楽しいところまでたどり着けなかったのです ...
さらに、気になったのがデータ容量と景観
地平から全山頂より超えるところまで足場を組み上げると..
その階層の分だけ、おそらくデータ容量がほぼ線形で増えます
街も足場で埋め尽くされて見えないし ...
... 足場は後から消せるのですね Simutrans アプリ上でも
だから、消せばいいわけですけれども さらに手間ですね
ミスも多いだろうし
... そういった事情を一気にクリアすべく、
もういっそ高い階層にセーブデータ上で流し込んでやろうということです<メモ>
しかし、上空に 市道を敷いても、その近辺に民家が経つことはなかったと思います 残念
↓サンプルコードです。
↓※絶対に元のデータを上書きしないでください。
↓※データや設定が破壊されても、責任は一切負えません。
↓version=0.120.4, 自作改造パック pak.japan_custom 用になっていますが ... 適宜正しい値になっていないと、面白いくらい開けないデータになります、多分
↓私はそれで苦戦しました
↓さらに、文字コードとかあれこれ読み込みが繊細です。
# -*- coding: utf-8 -*- import sys reload(sys) sys.setdefaultencoding('utf-8') import xml.etree.ElementTree as ET filename_in = 'test_in.sve' filename_out = 'test_out.sve' f = open(filename_in) data1 = f.read() # ファイル終端まで全て読んだデータを返す f.close() data2 = data1.replace("<![CDATA[","<CDATA>") data2 = data2.replace("]]>","</CDATA>") root = ET.fromstring(unicode(data2.encode('utf-8'))) # マップのサイズを取得 N_x = int(root[0][0].text) N_y = int(root[0][13].text) count_p = 0 count_x = 0 count_y = 0 pitch_x = 4 pitch_y = 4 for planquadrat in root.iter('planquadrat_t'): count_x = count_p % N_x count_y = count_p / N_x if (count_x % pitch_x == 0) or (count_y % pitch_y == 0): count_ch = len(planquadrat.getchildren()) # 接続方向 # 1:toN, 2:toE, 4:toS, 8:toW connect_arg = 0 if (count_x % pitch_x == 0): connect_arg = connect_arg + 1 + 4 if (count_y % pitch_y == 0): connect_arg = connect_arg + 2 + 8 if (count_x == 0): connect_arg = connect_arg & (15 - 8) if (count_x == N_x-1): connect_arg = connect_arg & (15 - 2) if (count_y == 0): connect_arg = connect_arg & (15 - 1) if (count_y == N_x-1): connect_arg = connect_arg & (15 - 4) elem_1 = ET.Element('id') elem_1.text = '6' elem_2 = ET.Element('grund_t') subelem_1 = ET.SubElement(elem_2, 'i8') subelem_1.text = '10' # 高度 subelem_1 = ET.SubElement(elem_2, 'i8') subelem_1.text = '-6' # subelem_1 = ET.SubElement(elem_2, 'i8') subelem_1.text = '4' # subelem_1 = ET.SubElement(elem_2, 'CDATA') subelem_1.text = '' # subelem_1 = ET.SubElement(elem_2, 'i8') subelem_1.text = '0' # subelem_1 = ET.SubElement(elem_2, 'id') subelem_1.text = '1' # subelem_1 = ET.SubElement(elem_2, 'strasse_t') subelem_2 = ET.SubElement(subelem_1, 'weg_t') subelem_3 = ET.SubElement(subelem_2, 'i8') subelem_3.text = '15' # owner? subelem_3 = ET.SubElement(subelem_2, 'i8') subelem_3.text = str(connect_arg) # 接続方向 subelem_3 = ET.SubElement(subelem_2, 'i16') subelem_3.text = '0' # 速度 (ロード時 pakの情報に上書き) subelem_3 = ET.SubElement(subelem_2, 'i8') subelem_3.text = '0' # subelem_3 = ET.SubElement(subelem_2, 'i32') subelem_3.text = '0' # subelem_3 = ET.SubElement(subelem_2, 'i32') subelem_3.text = '0' # subelem_3 = ET.SubElement(subelem_2, 'i32') subelem_3.text = '0' # subelem_3 = ET.SubElement(subelem_2, 'i32') subelem_3.text = '0' # subelem_2 = ET.SubElement(subelem_1, 'CDATA') subelem_2.text = 'city_road' subelem_1 = ET.SubElement(elem_2, 'id') subelem_1.text = '-1' # subelem_1 = ET.SubElement(elem_2, 'i8') subelem_1.text = '0' # planquadrat.insert(count_ch-1, elem_1) planquadrat.insert(count_ch, elem_2) count_p = count_p + 1 data3 = ET.tostring(root, encoding="utf-8") data4 = "<?xml version=\"1.0\"?>\n" + data3 data4 = data4.replace("<CDATA>","<![CDATA[") data4 = data4.replace("</CDATA>","]]>") data4 = data4.replace("<CDATA />","<![CDATA[]]>") data4 = data4.replace("<Simutrans pak=\"pak.japan_custom\" version=\"0.120.4\">","<Simutrans version=\"0.120.4\" pak=\"pak.japan_custom\">") f = open(filename_out,'w') # 書き込みモードで開く f.write(data4) # 引数の文字列をファイルに書き込む f.close()
PythonでSimutransの線路と道路の持ち主を変えてみた
Simutrans(http://japanese.simutrans.com)は, 素晴らしい.
プレイヤー会社を経営するわけですが、公共事業があってインフラとか地形いじりとかはそっちに任せられちゃうあたり、プレイしやすいのです!
しかし、プレイヤー会社と公共事業の切り替えはこんがらがります ...
... というわけで、とりあえず線路と道路を公共事業に譲渡しちゃおう、というのをやってみました
市道以外も、市道のように公共物でないオレンジ色の何かにできた 公共事業が2タイプある、というわけではないのだ、おそらく #simutrans pic.twitter.com/nY52LtSY7g
— shingoushori (@shingoushori) 2017年9月12日
公共事業にも2タイプあることを初めて意識した #simutrans pic.twitter.com/CrHxn4Khog
— shingoushori (@shingoushori) 2017年9月11日
とりあえず、
0 : プレイヤー会社, 1 : 公共事業, 15 : ?
です!
1 が灰色の公共事業、15が・・・? オレンジ色です
マルチプレイだと 最大15 つまり数字では 14まで
0~15 で 4 bit となっていると
市道や民家など、公共事業にも入れられないものの掃き溜めなのでしょう
...すると、公共事業じゃない市道 ... というのは
一体、どういうことなのでしょう? 一般的なのでしょうか
そして、Simutransの市道化 とは一体 ...
さておき、じゃあいっそのこと、全部 公共事業...じゃない何かオレンジ色の法人に譲渡してしまってはどうか ...
どうせ市道に勝手に譲渡させられるんなら、人口基盤のノリの高架だって譲渡してもいいでしょう!
...ということでやってみましたが ...
線路と道路だけでは...維持費が微妙に残りました おそらく、信号とかバス停とかです
その上、通行料がはいりません ... ただ、お金が減るだけ
道路と線路を 公共事業にやってもらっていたが、あまりの赤字に耐えきれずに 謎のオレンジ色法人に譲渡させてみた、Pythonでガリガリッと ... しかし 公共事業にまだ残っていて(駅に信号?)、地味に維持費が ... 作戦失敗 #simutrans pic.twitter.com/YDrIKAneGk
— shingoushori (@shingoushori) 2017年9月14日
ということで、
大人しく上述通りの
~ プレイヤー会社 の道路を 公共事業 に譲渡 ~ をやります
市道が 1 : 公共事業 じゃないので、ちゃんと 0 : プレイヤー会社 のものだけを選ぶ必要があるのです
↓サンプルコードです。
↓※絶対に元のデータを上書きしないでください。
↓※データや設定が破壊されても、責任は一切負えません。
↓version=0.120.4, 自作改造パック pak.japan_custom 用になっていますが ... 適宜正しい値になっていないと、面白いくらい開けないデータになります、多分
↓私はそれで苦戦しました
↓さらに、文字コードとかあれこれ読み込みが繊細です。
# -*- coding: utf-8 -*- import sys reload(sys) sys.setdefaultencoding('utf-8') import xml.etree.ElementTree as ET filename_in = 'test_in.sve' filename_out = 'test_out.sve' f = open(filename_in) data1 = f.read() # ファイル終端まで全て読んだデータを返す f.close() data2 = data1.replace("<![CDATA[","<CDATA>") data2 = data2.replace("]]>","</CDATA>") root = ET.fromstring(unicode(data2.encode('utf-8'))) # マップのサイズを取得 N_x = int(root[0][0].text) N_y = int(root[0][13].text) count_p = 0 count_x = 0 count_y = 0 for planquadrat in root.iter('planquadrat_t'): count_x = count_p % N_x count_y = count_p / N_x planquadrat_iter = planquadrat.iter('grund_t') for grund in planquadrat_iter: # strasse_t : 道路 grund_iter = grund.iter('strasse_t') for strasse in grund_iter: for weg in strasse.iter('weg_t'): if (int(weg[0].text) == 0): weg[0].text = str(1) # 0 : プレイヤー会社, 1 : 公共事業, 15 : ? print str(count_x) + " , " + str(count_y) + " , " + grund[0].text + " strasse_t" # schiene_t : 線路 grund_iter = grund.iter('schiene_t') for schiene in grund_iter: for weg in schiene.iter('weg_t'): if (int(weg[0].text) == 0): weg[0].text = str(1) # 0 : プレイヤー会社, 1 : 公共事業, 15 : ? print str(count_x) + " , " + str(count_y) + " , " + grund[0].text + " schiene_t" count_p = count_p + 1 data3 = ET.tostring(root, encoding="utf-8") count_p = count_p + 1 data3 = ET.tostring(root, encoding="utf-8") data4 = "<?xml version=\"1.0\"?>\n" + data3 data4 = data4.replace("<CDATA>","<![CDATA[") data4 = data4.replace("</CDATA>","]]>") data4 = data4.replace("<CDATA />","<![CDATA[]]>") data4 = data4.replace("<Simutrans pak=\"pak.japan_custom\" version=\"0.120.4\">","<Simutrans version=\"0.120.4\" pak=\"pak.japan_custom\">") f = open(filename_out,'w') # 書き込みモードで開く f.write(data4) # 引数の文字列をファイルに書き込む f.close()
PythonでSimutransの街の座標をずらしてみた
Simutrans(http://japanese.simutrans.com)は, 素晴らしい.
"日本の役場セット" ( アドオン/建物2 - Simutrans日本語化・解説 ) には, ニヤニヤしてしまいます.
しかし, 一段階大きい庁舎に変わる時に, 別のところに移る & 元の場所が適当な市内建築に置き換わる.
...(略)... というわけで, とりあえずその界隈に改めて,
元々の庁舎と同じ建物をランドマークとして建てられるようにしよう ... というのを、前回やりました
Simutransで, "日本の役場セット"をランドマークとして遺せるように魔改造してみた - shingoushori's dialy
その後、あれこれセーブデータとにらめっこしていたところ、単に1つの街に複数の庁舎を建てるだけなら、魔改造したpakを用意する必要はないことがわかりました
セーブデータのみをいじって検討した結果 ・1つの街に複数の庁舎→どれでも街の窓が開く→どれでも街全部消える ・街の座標?を最初の庁舎から移動→街を消去した時に移動後の座標のマーカーのみが消える ができた #Simutrans pic.twitter.com/17GApaVDJG
— shingoushori (@shingoushori) 2017年9月3日
さらに、新庁舎が建った時、元々の庁舎を削除させないだけなら、街の座標を元々の庁舎の座標からずらすだけで良いことがわかりました
人口を増やして行ったところ、元の庁舎たちが残ったままで新庁舎が建った ということは、必要なのは街の座標?を庁舎から外すことだけなのかもしれない pic.twitter.com/n3wIbNEPzO
— shingoushori (@shingoushori) 2017年9月3日
ずらし方は完全に探れてはいません
とりあえず多分庁舎の北西の角が街の座標なので
そこから北西方向に1マスずつずらしてみました
さて、ここで今回眉間にシワが寄り頭を掻きむしったのが、
1つの街に関する情報の取得です
これまで扱ってきたような、特定のtagの木にまとまっていません
仕方がないので、セーブデータを見比べて傾向を捉えた怪しい探り方をしています
実に危うい
↓サンプルコードです。
↓※絶対に元のデータを上書きしないでください。
↓※データや設定が破壊されても、責任は一切負えません。
↓version=0.120.4, 自作改造パック pak.japan_custom 用になっていますが ... 適宜正しい値になっていないと、面白いくらい開けないデータになります、多分
↓私はそれで苦戦しました
↓さらに、文字コードとかあれこれ読み込みが繊細です。
# -*- coding: utf-8 -*- import sys reload(sys) sys.setdefaultencoding('utf-8') import xml.etree.ElementTree as ET filename_in = 'test_in.sve' filename_out = 'test_out.sve' f = open(filename_in) data1 = f.read() # ファイル終端まで全て読んだデータを返す f.close() data2 = data1.replace("<![CDATA[","<CDATA>") data2 = data2.replace("]]>","</CDATA>") root = ET.fromstring(unicode(data2.encode('utf-8'))) # マップのサイズを取得 N_x = int(root[0][0].text) N_y = int(root[0][13].text) print str(N_x) + " " + str(N_y) root_iter = root.iter() while True: try: i = root_iter.next() if (i.tag == 'planquadrat_t'): break if (i.tag == 'CDATA'): j = root_iter.next() if (j.tag == 'koord'): print(i.text + " " + j[0].text + " " + j[1].text) j_x = int(j[0].text) j_y = int(j[1].text) if (j_x == 0) : j_x = 2 # 元庁舎のx方向の幅の最大値が 2だとする else : j_x = j_x - 1 if (j_y == 0) : j_y = 2 # 元庁舎のy方向の幅の最大値が 2だとする else : j_y = j_y - 1 j[0].text = str(j_x) j[1].text = str(j_y) print(" -> " + j[0].text + " " + j[1].text) except StopIteration: break data3 = ET.tostring(root, encoding="utf-8") data4 = "<?xml version=\"1.0\"?>\n" + data3 data4 = data4.replace("<CDATA>","<![CDATA[") data4 = data4.replace("</CDATA>","]]>") data4 = data4.replace("<CDATA />","<![CDATA[]]>") data4 = data4.replace("<Simutrans pak=\"pak.japan_custom\" version=\"0.120.4\">","<Simutrans version=\"0.120.4\" pak=\"pak.japan_custom\">") f = open(filename_out,'w') # 書き込みモードで開く f.write(data4) # 引数の文字列をファイルに書き込む f.close()
Simutransで, "日本の役場セット"をランドマークとして遺せるように魔改造してみた
Simutrans(http://japanese.simutrans.com)は, 素晴らしい.
"日本の役場セット" ( アドオン/建物2 - Simutrans日本語化・解説 ) には, ニヤニヤしてしまいます.
しかし, 一段階大きい庁舎に変わる時に, 別のところに移る & 元の場所が適当な市内建築に置き換わる.
ここで, 置き換わった市内建築がしょんぼりなのだ.
その界隈は元々は役場があった訳で, 都心である. そこが急に 1マスずつに細々とした建物になるのである.
... というわけで, とりあえずその界隈に改めて,
元々の庁舎と同じ建物をランドマークとして建てられるようにしよう と思ったのです.
↓ 実験中 ... ↓
気がついたら役場が都庁になって大移転する時期になっていた 実に迷惑なのだが コントロールがむずいので、せめて旧庁舎をランドマークとして遺せるように魔改造してみている ... #Simutrans pic.twitter.com/81aMtvk4EN
— shingoushori (@shingoushori) 2017年9月2日
"日本の役場セット" ( アドオン/建物2 - Simutrans日本語化・解説 ) は,
アドインの元データが見つからなかったので, バイナリをいじってしまいます.
↓ 前回バイナリをいじった時の記事はこちら ↓
<無理やり直し手法>
バイナリエディタで, 該当箇所を書き換える.
筆者はmacがメインでして,
バイナリエディタには 0xED ( http://www.suavetech.com/0xed/0xed.html ) を使いました.
[核心部]
・0すたーとの16進数で 00050 byte の 05 を 01 に変更する
[必要な修正] : 名前を変える
・TEXT ... の後ろの文字列
その前 に 00 を挟んだ xx が文字列長+1
例えば 02_CITY では 08
そんな感じでとりあえずなんとかできました
うまくいかないと Simutrans 自体の起動ができなくなるので,
魔改造対象のアドイン, 追加するpak, 追加するセーブデータ のバックアップは
マメに取っておくべきです. 恐ろしや
PythonでSimutransの特定の行と列の格子点にある特定の種類の道路の接続方向を揃えてみた
素敵な交通シミュレーション Simutrans で、
↓人工地盤っぽい感じで格子状に道路+線路を張り巡らしたいのです、私は
Simutransで人工地盤してみる - shingoushori's dialy
...タイトルが長くなりました
やりたいことは、↓こんな感じです
人工地盤で格子を築いた上に駅(バス停)を設置する座標なら格子点 地形を吸収すべく柱だらけの層で吸収 ... そこに待合室(まるでコインロッカー)的に1つ目を設置 ... 格子点自体は道路,線路層では交差点だが、下層は別の話 そして向きを揃えれば、いい感じ #Simutrans pic.twitter.com/gRCAcjGE7Q
— shingoushori (@shingoushori) 2017年8月31日
輝く都市!成長する都市!そして、崩れ落ちる新しき建築物したいですね!
揃えるのは大変なので、Pythonしちゃいます
手でやるのは本当に大変 手が滑ってめちゃくちゃな方向に接続されると崩れ落ちます、本当に!
今回のポイント ... サンプルの制限事項です
・"MOD_Slab_Skelton_Piller_Road_ELV" : これが 特定の種類の道路 の名前です なお、これは自作の道路です
・道路の"接続方向" のみしか確認していません "制限付き接続方向"については上書きしたつもりではいません
・特定の行と列の格子点 のつもりでしたが、書き換えミスで、特定の行と列 全部を書き換えています ... まぁ、こちらの方が更なる開発ができますね!
・揃える接続方向は 5 = 1(toN)+4(toS) です
[追記]
やはり、乱暴でした
"接続方向"の先に接続対象が存在しないところが大量にできてしまいます
すると、その接続方向に従って存在しない接続対象に行こうとするものがある時、Segmentation fault: 11 で落ちるようです
たとえそれが、車両でなく 歩行者, 乗降客であっても
ですので、このサンプルコードで実に危険です ... ...
↓サンプルコードです。
↓※絶対に元のデータを上書きしないでください。
↓※データや設定が破壊されても、責任は一切負えません。
↓version=0.120.4, 自作改造パック pak.japan_custom 用になっていますが ... 適宜正しい値になっていないと、面白いくらい開けないデータになります、多分
↓私はそれで苦戦しました
↓さらに、文字コードとかあれこれ読み込みが繊細です。
# -*- coding: utf-8 -*- import sys reload(sys) sys.setdefaultencoding('utf-8') import xml.etree.ElementTree as ET filename_in = 'test_in.sve' filename_out = 'test_out.sve' f = open(filename_in) data1 = f.read() # ファイル終端まで全て読んだデータを返す f.close() data2 = data1.replace("<![CDATA[","<CDATA>") data2 = data2.replace("]]>","</CDATA>") root = ET.fromstring(unicode(data2.encode('utf-8'))) # マップのサイズを取得 N_x = int(root[0][0].text) N_y = int(root[0][13].text) count_p = 0 count_x = 0 count_y = 0 for planquadrat in root.iter('planquadrat_t'): count_x = count_p % N_x count_y = count_p / N_x if (count_x % 5 == 0) or (count_x % 40 == 19) or (count_x % 40 == 21) \ or (count_y % 5 == 0) or (count_y % 40 == 19) or (count_y % 40 == 21): planquadrat_iter = planquadrat.iter('strasse_t') for strasse in planquadrat_iter: isTarget = False for elem in strasse.iter('CDATA'): if elem.text == "MOD_Slab_Skelton_Piller_Road_ELV": isTarget = True print str(count_x) + " , " + str(count_y) else: isTarget = False if isTarget: for weg in strasse.iter('weg_t'): weg[1].text = str(1+4) # 1:toN, 2:toE, 4:toS, 8:toW count_p = count_p + 1 data3 = ET.tostring(root, encoding="utf-8") data4 = "<?xml version=\"1.0\"?>\n" + data3 data4 = data4.replace("<CDATA>","<![CDATA[") data4 = data4.replace("</CDATA>","]]>") data4 = data4.replace("<CDATA />","<![CDATA[]]>") data4 = data4.replace("<Simutrans pak=\"pak.japan_custom\" version=\"0.120.4\">","<Simutrans version=\"0.120.4\" pak=\"pak.japan_custom\">") f = open(filename_out,'w') # 書き込みモードで開く f.write(data4) # 引数の文字列をファイルに書き込む f.close()
PythonでSimutransの特定の行と列の海底のレベルを水面まで持ち上げてみた
素敵な交通シミュレーション Simutrans で、
↓人工地盤っぽい感じで格子状に道路+線路を張り巡らしたいのです、私は
Simutransで人工地盤してみる - shingoushori's dialy
... 今回は、特定の行と列の海底のレベルを持ち上げてみました
高架を通すにも、海底のレベルが水面と同じじゃないと建てられないのです
自由に分岐したいので、橋では物足りないのです
今回入っている箇所を見つけた値は以下の3つ
・地面タイルの気候
・陸地の標高
・陸地の ... 水面のレベル ?
こんな感じになりました
Pythonによる、海を渡る高架橋のための海底の盛り土を検討中 湖の中が逆に深くなってしまった ... #Simutrans pic.twitter.com/qYySMZpOxE
— shingoushori (@shingoushori) 2017年8月29日
湖の水面のレベルに合わせた盛り土に成功 #Simutrans pic.twitter.com/1NkAOwWgaE
— shingoushori (@shingoushori) 2017年8月29日
↓サンプルコードです。
↓※絶対に元のデータを上書きしないでください。
↓※データや設定が破壊されても、責任は一切負えません。
↓version=0.120.4, 自作改造パック pak.japan_custom 用になっていますが ... 適宜正しい値になっていないと、面白いくらい開けないデータになります、多分
↓私はそれで苦戦しました
↓さらに、文字コードとかあれこれ読み込みが繊細です。
# -*- coding: utf-8 -*- import sys reload(sys) sys.setdefaultencoding('utf-8') import xml.etree.ElementTree as ET filename_in = 'test_in.sve' filename_out = 'test_out.sve' f = open(filename_in) data1 = f.read() # ファイル終端まで全て読んだデータを返す f.close() data2 = data1.replace("<![CDATA[","<CDATA>") data2 = data2.replace("]]>","</CDATA>") root = ET.fromstring(unicode(data2.encode('utf-8'))) # マップのサイズを取得 N_x = int(root[0][0].text) N_y = int(root[0][13].text) count_p = 0 count_x = 0 count_y = 0 for planquadrat in root.iter('planquadrat_t'): count_x = count_p % N_x count_y = count_p / N_x if (count_x % 5 == 0) or (count_y % 5 == 0) \ or (count_x % 40 == 19) or (count_x % 40 == 21) \ or (count_y % 40 == 19) or (count_y % 40 == 21): if planquadrat[0].text == "2": # "1" : 地中海性気候 ?, "2" : 海 n_grund = 0 planquadrat_iter = planquadrat.iter('grund_t') for grund in planquadrat_iter: if n_grund == 0: grund[0].text = grund[1].text # grund[0].text : 標高 ? # grund[1].text : 海面のレベル ? n_grund = n_grund + 1 count_p = count_p + 1 data3 = ET.tostring(root, encoding="utf-8") data4 = "<?xml version=\"1.0\"?>\n" + data3 data4 = data4.replace("<CDATA>","<![CDATA[") data4 = data4.replace("</CDATA>","]]>") data4 = data4.replace("<CDATA />","<![CDATA[]]>") data4 = data4.replace("<Simutrans pak=\"pak.japan_custom\" version=\"0.120.4\">","<Simutrans version=\"0.120.4\" pak=\"pak.japan_custom\">") f = open(filename_out,'w') # 書き込みモードで開く f.write(data4) # 引数の文字列をファイルに書き込む f.close()
PythonでSimutransの特定の行と列を平坦化してみた
素敵な交通シミュレーション Simutrans で、
↓人工地盤っぽい感じで格子状に道路+線路を張り巡らしたいのです、私は
Simutransで人工地盤してみる - shingoushori's dialy
... そこで今回は、セーブデータをいじり、特定の行と列を一気に平坦化してみました.
道路を敷設するにも、敷設できない方向の坂が付いていると、一旦平坦化しないといけないので、とりあえずpythonで簡略化しちゃいます.
(セーブデータは、xml ファイルで書き出し読み込みしています. )
・特定の行と列 1: 0+5*k (k={0,1,2,...}) 番目
駅の範囲が 2マス設定のままなので、道路は5マスおきです. 頑張れ、バス!
・特定の行と列 1: 20+40*k±1 (k={0,1,2,...}) 番目
幹線として、3マス幅の高架を敷設します.
・平坦化をスルーする条件: すでに高架で道路か線路が敷設されているところ
せっかく坂道にすると決めたマスなので、残しておきます
... PythonのXMLパーサが、今の所は肌に合いません ...
... Simutrans のセーブデータの仕様との相性もあるんでしょうが ...
↓サンプルコードです。
↓※絶対に元のデータを上書きしないでください。
↓※データや設定が破壊されても、責任は一切負えません。
↓version=0.120.4, 自作改造パック pak.japan_custom 用になっていますが ... 適宜正しい値になっていないと、面白いくらい開けないデータになります、多分
↓私はそれで苦戦しました
↓さらに、文字コードとかあれこれ読み込みが繊細です。
# -*- coding: utf-8 -*- import sys reload(sys) sys.setdefaultencoding('utf-8') import xml.etree.ElementTree as ET filename_in = 'test_in.sve' filename_out = 'test_out.sve' f = open(filename_in) data1 = f.read() # ファイル終端まで全て読んだデータを返す f.close() data2 = data1.replace("<![CDATA[","<CDATA>") data2 = data2.replace("]]>","</CDATA>") root = ET.fromstring(unicode(data2.encode('utf-8'))) # マップのサイズを取得 N_x = int(root[0][0].text) N_y = int(root[0][13].text) count_p = 0 count_x = 0 count_y = 0 for planquadrat in root.iter('planquadrat_t'): count_x = count_p % N_x count_y = count_p / N_x if (count_x % 5 == 0) or (count_y % 5 == 0) \ or (count_x % 40 == 19) or (count_x % 40 == 21) \ or (count_y % 40 == 19) or (count_y % 40 == 21): N_strasse = 0 # 道路 N_schiene = 0 # 線路 planquadrat_iter = planquadrat.iter('grund_t') planquadrat_iter.next() # 地上(?)はスルー for grund in planquadrat_iter: for elem in grund.iter('strasse_t'): N_strasse = N_strasse + 1 for elem in grund.iter('schiene_t'): N_schiene = N_schiene + 1 for grund in planquadrat.iter('grund_t'): if (N_strasse == 0) and (N_schiene == 0): grund_iter = grund.iter() elemdist = 0 for elem in grund_iter: if elemdist == 5: elem.text = "0" # 平坦化 elemdist = elemdist + 1 count_p = count_p + 1 data3 = ET.tostring(root, encoding="utf-8") data4 = "<?xml version=\"1.0\"?>\n" + data3 data4 = data4.replace("<CDATA>","<![CDATA[") data4 = data4.replace("</CDATA>","]]>") data4 = data4.replace("<CDATA />","<![CDATA[]]>") data4 = data4.replace("<Simutrans pak=\"pak.japan_custom\" version=\"0.120.4\">","<Simutrans version=\"0.120.4\" pak=\"pak.japan_custom\">") f = open(filename_out,'w') # 書き込みモードで開く f.write(data4) # 引数の文字列をファイルに書き込む f.close()