2016/03/09
■ [変愚蛮怒/スポイラー] build_tunnel2()関数処理の流れ(変愚蛮怒 Ver2.1.5)
(昨日の記事もろとも図解しないと)ダメだ、やっぱ。やはり、そのうちに。
- 始点から終点までの距離を整数を(ニュートン・ラプソン法で)得る。
- 始点から終点までの距離がcutoff値より大きい場合以下の処理を行う。
- 以下の式で始点x1,y1から終点x2,y2までの間に中間地点x3,y3を作成する。
- dx = (x2 - x1) / 2, dy = (y2 - y1) / 2
- changex = (randint0(abs(dy) + 2) * 2 - abs(dy) - 1) / 2
- changey = (randint0(abs(dx) + 2) * 2 - abs(dx) - 1) / 2
- x3 = x1 + dx + changex, y3 = y1 + dy + changey
- 以上の式で、得られる中間地点の範囲は概ね、「始点と終点を端点としたマップと並行な長方形」をその中点を中心に90度回転させた形になる。abs(dx)=abs(dy)ならば、始点と終点を対称点に持ったマップと並行な正方形になるし、abs(dx)=0か、abs(dy)=0ならば始点と終点を中点として垂直線に伸びた範囲を持つ。
- 定められた中間地点x3,y3がマップ範囲外になってしまう場合、単純に始点と終点の中点に取り直す。
- 得られたx3,y3中間地点にCAVE_SOLID属性がついていた場合、以下の処理を行う。
- 中間地点を50回に渡り、xy各座標を-1~1の範囲でマップ外にはみ出ないよう、CAVE_SOLID属性を持たない地点が得られるまでシフトしていく。
- 途中でCAVE_SOLID属性を持たない地点が得られたか、どうしても得られなかった場合もやむなく、そこで中間地点を確定する。
- 確定した中間地点がCAVE_FLOOR属性を持つならば以下のように処理を進める。
- 始点から中間地点までの指定でbuild_tunnel2()を再帰実行する。これが失敗したら、自身の関数はfalseを返し、グローバル変数firsesuccedeフラグをfalseにする。成功した場合以下のように続ける。
- 中間地点にCAVE_ROOM属性がついているか5%の確率で中間地点から終点までの範囲でbuild_tunnel2()を再帰実行し、その成否フラグを得る。それが返す成否には関係なくいずれにせよ、グローバル変数firsesuccedeフラグをtrueにする。
- そうでなければ成否フラグをfalseにして、現在の中間地点にドアを生成する。ドア生成数が最大の200に達していた場合、自身の関数はfalseを後で返す。
- 始点から中間地点までの指定でbuild_tunnel2()を再帰実行する。これが失敗したら、自身の関数はfalseを返し、グローバル変数firsesuccedeフラグをfalseにする。成功した場合以下のように続ける。
- 確定した中間地点がCAVE_FLOOR属性を持たないならば以下のように処理を進める。
- 始点から中間地点までの指定でbuild_tunnel2()を再帰実行する。これが失敗したら、自身の関数はfalseを後で返すこととし、グローバル変数firsesuccedeフラグをfalseにする。成功した場合以下のように続ける。
- 中間地点から終点までの範囲でbuild_tunnel2()を再帰実行し、その成否フラグを得る。それが返す成否には関係なくいずれにせよ、グローバル変数firsesuccedeフラグをtrueにする。
- 始点から中間地点までの指定でbuild_tunnel2()を再帰実行する。これが失敗したら、自身の関数はfalseを後で返すこととし、グローバル変数firsesuccedeフラグをfalseにする。成功した場合以下のように続ける。
- 以上までの処理で、この時点でfirsesuccedeフラグがtrueならば、set_tunnel()関数で周囲のマスのCAVE_*フラグを整理する。
- この時点で確定した自身の成否フラグを関数の帰り値として返す。
- 以下の式で始点x1,y1から終点x2,y2までの間に中間地点x3,y3を作成する。
- そもそも距離がcutoff値以下ならばshort_seg_hack()関数を通じて、単純に接続する。
以上で、build_tunnel2()の流れは判明。set_tunnel()とshort_seg_hack()についてはまた後日とする。