shingoushori's dialy

音信号処理を専ら研究していた元博士後期課程の学生によるメモ

YouTube はじめました

YouTube はじめました

www.youtube.com

とりあえず、素敵な交通シミュレーション Simutrans の本体改造、
人工地盤プレイについてあげてみています

www.youtube.com

GitHub はじめました

GitHub はじめました

github.com

とりあえず、素敵な交通シミュレーション Simutrans の本体改造をやってみています

FrontPage - Simutrans日本語化・解説

最近Webブラウザのタブに居続けたナイスURL

s0sem0y.hatenablog.com

s0sem0y.hatenablog.com

tech-blog.abeja.asia

blog.brainpad.co.jp

qiita.com

qiita.com

dsas.blog.klab.org

www.speechandhearing.net

www.slideshare.net

speakerdeck.com

ajaxsoundstudio.com

Mido - MIDI Objects for Python — Mido 1.2.8 documentation

aidiary.hatenablog.com

qiita.com

yukara-13.hatenablog.com

qiita.com

PythonでSimutransのマップに天空の市道の格子点にバス停を追加してみた

フリーの交通?シミュレーション
Simutrans(http://japanese.simutrans.com)が, 素晴らしい.

それでもって私は人工地盤っぽいことをやっています。
Simutransで人工地盤してみる - shingoushori's dialy
大規模な都市開発をさっさとやるべく、Pythonでセーブデータをいじっています

先日、↓道路の格子を特定階層に構築するのをやりました。
PythonでSimutransのマップに天空の市道の碁盤の目を追加してみた - shingoushori's dialy
今回は、その道路の格子点にバス停を追加してみました。

↓こんな感じです↓

恐ろしいことに、道路とバス停の方向が別にあっていなくてもバス停を置けそうです。セーブデータをいじる限りは
交差点や曲がり角でも、まぁ、置けそうです。恐ろしや
shingoushori on Twitter: "セーブデータをいじっていたところ、バス停の道路を交差点にできた、一応 #simutrans https://t.co/OxuT7w6V3c"
プレイしていくうちに、エラーが出そうで怖いです
いやその前に、特定の向きのバス停を特定の方向に接続されている道路に追加したところセーブデータの読み込みに失敗することもありました
それが、何度もPythonスクリプトを走らせていたら安定してきたような、とても不安です
ですから、交差点や曲がり角には、やはり置くべ機ではないでしょう
↓私ならば、こんな感じでバス停の向きに道路の向きを揃えてしまいます↓
PythonでSimutransの特定の行と列の格子点にある特定の種類の道路の接続方向を揃えてみた - shingoushori's dialy



とりあえず、成功することもあるんだ ぐらいのメモです

バス停の追加では、これまでとの大きな違いがありました
1つ新規で追加するときにセーブデータ上で追加する箇所が2箇所でした
・各座標のところにpakを登録
・一意なバス停番号付きでバス停情報?を追加
後者はなくても大丈夫かも?全くもって、よくわかりません


↓サンプルコードです。
↓※絶対に元のデータを上書きしないでください。
↓※データや設定が破壊されても、責任は一切負えません。
↓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 = 'testout_elv_road.sve'
filename_out = 'testresult.sve'

# 格子状に道路を敷く
def structline_create_constF(root, N_x, N_y, pitch_x, pitch_y, target_h, target_way):
  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 % 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)
      print str(count_x) + " " + str(count_y) + " " + str(connect_arg)
      
      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 = str(target_h) #'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 = target_way #'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

# バス停を格子点に作る
def create_haltestelle_structline_constF(root, N_x, N_y, pitch_x, pitch_y, target_h):
  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 % pitch_x == 0) and (count_y % pitch_y == 0):
      create_haltestelle(root, N_x, N_y, count_x, count_y, target_h, '('+str(count_x)+','+str(count_y)+')')
      #create_haltestelle(root, N_x, N_y, count_x, count_y, target_h, str(count_x))
    count_p = count_p + 1

# バス停を作る
def create_haltestelle(root, N_x, N_y, target_x, target_y, target_h, target_str):
  
  # get バス停の数
  n_haltestelleNum = 0
  while (root[n_haltestelleNum].tag != 'haltestelle_t'):
    n_haltestelleNum = n_haltestelleNum + 1
  n_haltestelleNum = n_haltestelleNum - 1
  haltestelleNum = int(root[n_haltestelleNum].text)
  #print str(haltestelleNum)
  
  # バス停
  haltestelleNum = haltestelleNum + 1
  root[n_haltestelleNum].text = str(haltestelleNum)
  subelem_1 = ET.Element('haltestelle_t')
  subelem_2 = ET.SubElement(subelem_1, 'i16')
  subelem_2.text = str(haltestelleNum) # 番号
  subelem_2 = ET.SubElement(subelem_1, 'i32')
  subelem_2.text = str(1) # owner
  subelem_2 = ET.SubElement(subelem_1, 'koord3d')
  subelem_3 = ET.SubElement(subelem_2, 'i16')
  subelem_3.text = str(target_x) # 座標 x
  subelem_3 = ET.SubElement(subelem_2, 'i16')
  subelem_3.text = str(target_y) # 座標 y
  subelem_3 = ET.SubElement(subelem_2, 'i8')
  subelem_3.text = str(target_h) # 標高 y
  subelem_2 = ET.SubElement(subelem_1, 'koord3d')
  subelem_3 = ET.SubElement(subelem_2, 'i16')
  subelem_3.text = str(-1) # 
  subelem_3 = ET.SubElement(subelem_2, 'i16')
  subelem_3.text = str(-1) # 
  subelem_3 = ET.SubElement(subelem_2, 'i8')
  subelem_3.text = str(-1) # 
  subelem_2 = ET.SubElement(subelem_1, 'CDATA')
  subelem_2.text = '' # 
  n_i64 = 0
  for n_i64 in range(96):
    subelem_2 = ET.SubElement(subelem_1, 'i64')
    subelem_2.text = str(0) # 
  root.insert(n_haltestelleNum + 1, subelem_1)
  
  subelem_0 = ET.Element('id')
  subelem_0.text = '7' # 
  subelem_1 = ET.Element('gebaeude_t')
  subelem_2 = ET.SubElement(subelem_1, 'obj_t')
  subelem_3 = ET.SubElement(subelem_2, 'i8')
  subelem_3.text = '0' #
  subelem_3 = ET.SubElement(subelem_2, 'i8')
  subelem_3.text = '0' # 
  subelem_3 = ET.SubElement(subelem_2, 'i8')
  subelem_3.text = '1' # owner?
  subelem_2 = ET.SubElement(subelem_1, 'CDATA')
  subelem_2.text = 'wa-road-busstop-3' # 
  subelem_2 = ET.SubElement(subelem_1, 'i16')
  subelem_2.text = '0' # 向き 0 : 南北, 1 : 東西
  subelem_2 = ET.SubElement(subelem_1, 'i32')
  subelem_2.text = '0' # 向き?  揃える必要あり?
  subelem_2 = ET.SubElement(subelem_1, 'i32')
  subelem_2.text = '-1' # 
  
  
  target_p = target_x + target_y * N_x
  count_p = 0
  count_x = 0
  count_y = 0
  planquadrat_iter = root.iter('planquadrat_t')
  target_planquadrat = list(planquadrat_iter)[target_p]
  # マーカー
  #target_planquadrat[1][3].text='('+ str(target_x) +','+ str(target_y) +')'
  
  grund_iter = target_planquadrat.iter('grund_t')
  for grund in grund_iter:
    if (grund[0].text == str(target_h)):
      # 狙いの高度のgrundを発見
      if (grund[5].text == str(1)):
        # 道路あり
        grund[3].text = target_str # CDATA
        grund[8].text = str(int(grund[8].text)+1)
        grund.insert(9, subelem_0)
        grund.insert(10, subelem_1)



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)


pitch_x = 4
pitch_y = 4
target_h = 10 
target_way = 'city_road' 
structline_create_constF(root, N_x, N_y, pitch_x, pitch_y, target_h, target_way)

target_h = 5
structline_create_constF(root, N_x, N_y, pitch_x, pitch_y, target_h, target_way)
create_haltestelle_structline_constF(root, N_x, N_y, pitch_x, pitch_y, target_h)

pitch_x = 5
pitch_y = 5
target_h = -1 
structline_create_constF(root, N_x, N_y, pitch_x, pitch_y, target_h, target_way)
create_haltestelle_structline_constF(root, N_x, N_y, pitch_x, pitch_y, target_h)


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)は, 素晴らしい.

セーブデータをxmlにできるので、乱開発したい気持ちとPythonの練習を高ぶらせられて幸せです.
今回は、乱開発のために市街を広げさせて交通需要を増やすための布石です.
それなりにちゃんと地上に道路を敷きます.

前回、天空に市道を敷いてみました.
しかし、地上は市街化しませんでした.
PythonでSimutransのマップに天空の市道の碁盤の目を追加してみた - shingoushori's dialy
従って、面倒だけれども、地上に道路を敷きます...

地上に道路を敷く上で今回考慮した面倒な要素を列挙します
・木 -> 削除
・役場 -> 残す
・その他建物 -> 残す
・坂 -> 残す
・坂道 -> 東西, 南北 方向は、その方向に敷設
     ただし, 格子の方向に双方に限る
     格子点が 東西, 南北 方向であれば敷設

さあ、それでもとりあえず残るのが 隣接する市道との接続
接続していないと、大方繋がらないまま市道化されてしまいました.
これを解決しようにも、現行のPythonxmlパーサで 1次元でイテレータを回しているやり方だと、接続方向について検索するのが厳しいです ...
先は長い ...


↓サンプルコードです。
↓※絶対に元のデータを上書きしないでください。
↓※データや設定が破壊されても、責任は一切負えません。
↓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 = 3
pitch_y = 3
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):
    if (planquadrat[1][5].text == '-1') and (planquadrat[0].text == '1'):
      # 道路なし
      # 
      # 建物なし
      
      if ((planquadrat[1][4].text == '0') \
       or ((planquadrat[1][4].text == '28') and (((count_x % pitch_x != 0) and (count_y % pitch_y == 0)) or ((count_x % pitch_x == 0) and (count_y % pitch_y == 0))) ) \
       or ((planquadrat[1][4].text == '36') and (((count_x % pitch_x == 0) and (count_y % pitch_y != 0)) or ((count_x % pitch_x == 0) and (count_y % pitch_y == 0))) ) ):
        # 0 : 平地
        # 28 : 東西
        # 36 : 南北
        
        # 木などを除去
        count_ch = len(list(planquadrat[1]))
        for num in range(count_ch, 6, -1):
          planquadrat[1].remove(planquadrat[1][num-1])
        # 補正
        subelem_1 = ET.SubElement(planquadrat[1], 'id')
        subelem_1.text = '-1' # 
        subelem_1 = ET.SubElement(planquadrat[1], 'i8')
        subelem_1.text = '0' # 
        
        # 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)
        
        planquadrat[1][5].text ='1'
        subelem_1 = ET.Element('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 = 'dirt_road' #'city_road' 
        planquadrat[1].insert(6, subelem_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(http://japanese.simutrans.com)は, 素晴らしい.

それでもって私は人工地盤っぽいことをやっています。
Simutransで人工地盤してみる - shingoushori's dialy

これまで、Pythonでセーブデータをあれこれし
地形をいじったり、交差部分の接続方向をいじったりして来ました
今回は、いよいよ道路を敷いてみました

... city_road でもいけました ... 高架の道路じゃなくても宙に浮くんですね

<経緯>
地形の坂とか、各街の標高や山の標高を考慮しながら敷設していくのは、
楽しいけれども、一向に眺めて楽しいところまでたどり着けなかったのです ...

さらに、気になったのがデータ容量と景観
地平から全山頂より超えるところまで足場を組み上げると..
その階層の分だけ、おそらくデータ容量がほぼ線形で増えます
街も足場で埋め尽くされて見えないし ...
... 足場は後から消せるのですね 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)は, 素晴らしい.

プレイヤー会社を経営するわけですが、公共事業があってインフラとか地形いじりとかはそっちに任せられちゃうあたり、プレイしやすいのです!

しかし、プレイヤー会社と公共事業の切り替えはこんがらがります ...
... というわけで、とりあえず線路と道路を公共事業に譲渡しちゃおう、というのをやってみました



とりあえず、
0 : プレイヤー会社, 1 : 公共事業, 15 : ?
です!
1 が灰色の公共事業、15が・・・? オレンジ色です

マルチプレイだと 最大15 つまり数字では 14まで
0~15 で 4 bit となっていると
市道や民家など、公共事業にも入れられないものの掃き溜めなのでしょう

...すると、公共事業じゃない市道 ... というのは
一体、どういうことなのでしょう? 一般的なのでしょうか
そして、Simutransの市道化 とは一体 ...

さておき、じゃあいっそのこと、全部 公共事業...じゃない何かオレンジ色の法人に譲渡してしまってはどうか ...
どうせ市道に勝手に譲渡させられるんなら、人口基盤のノリの高架だって譲渡してもいいでしょう!
...ということでやってみましたが ...
線路と道路だけでは...維持費が微妙に残りました おそらく、信号とかバス停とかです
その上、通行料がはいりません ... ただ、お金が減るだけ

ということで、
大人しく上述通りの
 ~ プレイヤー会社 の道路を 公共事業 に譲渡 ~ をやります
市道が 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()