shingoushori's dialy

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

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()