§
------------------------------------------------
MIP 技術情報

				Jul 23, 2012
				 for MIP-003
				    wackdone
------------------------------------------------

ここでは、現状の MIP の実装の一部について簡単な説明と課題の列挙を行ないます。

--------------------
= NO_LOAD_BEYOND_DEPOT
--------------------
駅での積載判定 (RouteCostが触っている部分と同じ) に判定条件を追加しています。

== オリジナルの積載判定ループ
駅に到着した乗物は、そのスケジュールに沿って各行き先駅への貨物の積載処理が行われます。

{{{
  for (今の駅から先の各スケジュール項目を順番に) {
    if (この項目は今の駅) {
      break;  // もう一度この駅に来るのだから、これより先の駅行きは積まない
    }
      :
    この項目への積み込み処理
      :
  }
}}}


== NO_LOAD_BEYOND_DEPOT での追加内容
この判定にもう一つ条件を加えて以下のようにしました。

{{{
  for (今の駅から先の各スケジュール項目を順番に) {
    // NO_LOAD_BEYOND_DEPOTでこれを追加
    if (この項目は車庫行き) {
      break;  // 車庫に入った後に行く停車駅は見ない
    }

    if (この項目は今の駅) {
      break;  // もう一度この駅に来るのだから、これより先の停車駅は見ない
    }
      :
    この項目への積み込み処理
      :
  }
}}}

----------
== 課題1: 判定の位置
----------
「今の駅との比較」より前に入れているのは非効率です。
(一般に、車庫行きは一時的な現象であり、定常的な現象である「今の駅をまた通る」より
 発生頻度が低いため)

ですが、「今の駅」の判定より後にすると、RRC のパッチと衝突を起こしてしまいます。
(つまらない話ですが) このため、現状とりあえずはこの位置に挿入しています。

----------
== 課題2: 「わざと車庫行き」との折り合いの悪さ
----------
「わざと車庫行きにして積荷を捨てる」テクニックが使えなくなるのは、一部の
プレーヤーには不都合かと思います。
上で説明した判定を殺すだけなので、動作の切り替えはたいしたことないのですが、
車庫行きスケジュールについてのプレーヤーの真意をどのように拾うかが課題です。

全体設定にするというのは避けたい、かといって乗物の側にあまりステートを
持たせるのも管理が面倒になる、と板挟み。


--------------------
= SMART_GO_HOME_DEPOT
--------------------

----------
== オリジナルSimutransの動作とその不満点
----------
オリジナルのSimutransの「車庫へ」 (go home) は、以下のような仕組みになっていました。
オリジナルでボタンが押されると:
  (1) 行き先の車庫を決定: 乗物の現在位置から最も近いものを探す
    FOREACH (マップ内の全ての車庫) {
      乗物の現在位置とその車庫の距離をルートに沿って測る
      これまでより近かったらこの車庫を記録
    }
    この段階で記録に残った車庫が最短であり、この車庫へ行く
    (この段階で記録が無いということは、乗物の辿り着ける車庫が無いということ。)

  (2) 車庫へ行く項目をスケジュールに追加
    スケジュール上の現在の行き先項目のところに、車庫へ行く項目を挿入

オリジナルでは、(1)と(2)それぞれに使いにくさがありました。
(あくまで私のプレー経験上での話です。)

(1)の不満点
  マップ内の全ての車庫を検索するため、車庫の数が多いマップでは検索に時間がかかる。
  特に多数の地域路線などが存在するような大規模開発を行っている場合、
  マップ内のほとんどの車庫は乗物にとって接続外であるため、これらを走査する意味がない。

(2)の不満点
  ボタンを押したその場で向かおうとしてしまうので、編成組替えや運行整理などの目的で
  車庫へ向かわせる場合、押すタイミングに気をつかう。
  (現在の他の乗物の運行を妨げないように、またこの乗物の利益を損わないように)
  また車庫から運用に戻る場合も、そのままではボタンを押した時点の行き先へ
  戻ろうとしてしまうため、スケジュールを開いて行き先を再調整しなければならない。

----------
== SMART_GO_HOME_DEPOT での変更内容  
----------
SMART_GO_HOME_DEPOTではそれぞれを以下のように変更しました。
  (1a) 所属車庫の認識と参照
    乗物が出庫する時点で、その車庫とスケジュール上の位置を記憶しておきます。
    (出庫した車庫の記憶は、すでにSimutransオリジナルで行われていますが、
     あまり有効に使われていません)
    「所属車庫へ」を押されたら、車庫探索を行わずにこの車庫へ行こうとします

  (1b) 最寄り車庫の探索の効率化
    最終的に全車庫を走査しますが、その前に一定距離 d 内にある車庫だけを
    対象にした探索を行います。(距離はマンハッタン距離です)
    1回目の走査: 乗物の位置から d 未満の距離にある車庫だけを対象
    これで見つからなかったら
    2回目の走査: 乗物の位置から d 以上の距離にある車庫を対象
    とします。

    この「一定距離 d」は経験的な手法などにより求まるべきですが
    現在は良い関数が見つからないため、「マップの広さの1/4」にしています。
    例えば 256x256 のマップであれば、 d = 64+64 = 128 となり、
    マンハッタン距離で 128 の範囲内にある車庫が優先して検証されます。

  (2) 車庫行きスケジュールの挿入位置: 所属車庫を出庫した時点の情報を参照
    上の(1a)に示されたように、出庫の段階で次に向かうスケジュール項目を
    記憶しています。「車庫行き」のエントリはこの位置の手前に挿入されます。

    例えば 5番目のスケジュール項目から運行を開始したのであれば、
    5番目の位置に「車庫行き」が挿入され、4番目の駅を出てから車庫にむかいます。
    出庫の時は、5番目の「車庫行き」が削除されていますので、
    元の5番目のスケジュールから運行が再開されます。

    なお出庫後の運行再開が 0番目 (スケジュールの先頭) から行われていた場合には、
    「車庫行き」エントリはスケジュールの末尾に追加されます。

----------
== 検討課題1: ボタンの置き方と見え方
----------
機能でわければ「所属車庫へ」と「最寄車庫へ」は別のボタンにした方が良いでしょう。
またウィンドウを見ただけで「今、所属車庫へ向う予定が入っているのかどうか」が
わかりにくいのも問題だと思われます。

ですが今のところは、オリジナルの画面レイアウトを壊さないよう、一つのボタンに
複数の機能を持たせてしまっています。
pak128であればボタン列の上にスペースがあるのでボタンを追加もできるでしょうが、
pak(64)の場合はこの余地が無いため、乗物情報ウィンドウが広がることになってしまいます。

----------
== 検討課題2: 挿入位置と運行再開点の選択
----------
営業から回送へ切り替えてのスムーズな車庫の入出庫を考えると、
現状の仕組みでは上手くない面があります。

始点や終点に引き上げ線のあるスケジュールでは、まあまあ上手く動きます。
  (所属車庫はこのあたり。運行開始は[0]から)
  [0] 始点駅
  [1] 途中駅
  [2] 終点駅
  [3] 途中駅
  [4] 始点駅
  [5] 引き上げ線
ここで、「所属車庫へ」を押すと、スケジュールの末尾に車庫行きが追加され、
  [0] 始点駅
  [1] 途中駅
  [2] 終点駅
  [3] 途中駅
  [4] 始点駅
  [5] 引き上げ線
  [6] 所属車庫
となります。始点駅に戻ってきて降車扱いを終えると、引き上げ線に行ってから
所属車庫に入り、次の出庫では[0]始点駅から営業運転が再開されます。
(ここでも本当は、所属車庫から引き上げ線に一度入れたいかもしれない)

では、引き上げ線などの設備が無いスケジュールで考えます。
  (所属車庫はこのあたり。運行開始は[0]から)
  [0] 始点駅
  [1] 途中駅
  [2] 終点駅
  [3] 途中駅
というスケジュールを組んで、[0]始点から運行を開始したとします。
「所属車庫へ」ボタンを押すと、スケジュールの末尾に車庫行きが追加され、
  [0] 始点駅
  [1] 途中駅
  [2] 終点駅
  [3] 途中駅
  [4] 所属車庫
というスケジュールになってしまいます。始点駅での客扱いが行われないまま
車庫へ直行してしまいます。

(所属車庫の位置が変わっても問題はだいたい同じです)

また環状線の場合はどうでしょうか。
  (所属車庫はこのあたり。運行開始は[0]から)
  [0] A駅
  [1] B駅
  [2] C駅
  [3] D駅
「所属車庫へ」ボタンを押すと、
  [0] A駅
  [1] B駅
  [2] C駅
  [3] D駅
  [4] 所属車庫
となり、D駅の扱いを終えてから入庫、出庫後はA駅から営業開始です。
これで都合の良い場合もあるでしょうが、都合の悪い場合もあるでしょう。
(車庫近くの駅の重要度や線型などによる)
山手線で言えば、向きは同じで、
  大崎止まりで入庫して、出庫後は品川から営業開始
になっている感じです。

本当は、
  「前回の運行開始位置の次に車庫行きを挿入、
    出庫後はまた運行開始位置に戻るところから再開」
とした方が全ての状況でだいたい上手くいくのですが、オリジナルSimutransの
仕組みとの兼ね合いでまだ実現しきれていません。
