shingoushori's dialy

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

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マス幅の高架を敷設します.
・平坦化をスルーする条件: すでに高架で道路か線路が敷設されているところ
 せっかく坂道にすると決めたマスなので、残しておきます

... PythonXMLパーサが、今の所は肌に合いません ...
... 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()