右折左折の判定

囲み判定のアルゴリズム説明はアイデアノートから書き起こしたため、魔力ラインの方向を元に
転回値を計算する書き方になっていました。
V1.14(応募締切バージョン)の実際のスクリプトでは、魔力ラインの方向だけでなく、転回値も
プレーヤー移動時に計算し、魔力ラインのオブジェクト情報へ継承させています。
魔力ラインで囲ったとき、その場所のマップ値からのオブジェクト情報を見れば、プレーヤーの
転回値との差が分かりますので、そこからループの内側が左右どちらなのかを判定できます。
ということで、プレーヤーが方向を変えた時にどのように転回値を計算しているか解説。


スクリプトでは、転回値は右に曲がったら-1、左に曲がったら+1として加減しています。
デバッグでなんだかんだとやっているうちに、ノートとは逆の値で落ち着いてしまった)
dup後の変数で言うと、オブジェクト管理テーブル上での転回値はeer、方向はeevで持っています。
プレーヤーのキー入力判定は、プレーヤーの移動カウンタが0の場合のみ行われます。
(移動カウンタ=0は、移動完了時もしくは停止状態なのでマップのマス目ぴったりの位置。)
まず、キー入力判定前に c0=eev,eep で現在の方向と位置を退避。
方向の値は、←:0、↑:1、→:2、↓:3 です。(getkeyの矢印キーに対する順序と同じ並び)
その後、キー判定によって新しい方向とプレーヤー画像が決まります。
eevに方向の値が格納されたところで、

	eer+((eev-c0+4)\4-2)*(eev!c0)

としてeerに対して加減しています。(V1.14)
上の式の (eev-c0+4)\4-2 部分、eev決定処理の前後に対して値をテーブル化してみると、

後\前 ←:0 ↑:1 →:2 ↓:3
←:0 −2 −1
↑:1 −1 −2
→:2 −1 −2
↓:3 −1 −2

のようになります。
変化前後の対応を見ると、右折:-1、左折:1、反転:0、変化がない場合は直進:-2 となっています。
直進で-2というのが不都合なため、これに(eev!c0)を掛けることで0にマスクしています。

で、このマスク処理は無駄な感じがしていたのですが、その後V1.21にてようやく改善に成功。

	eer+((eev^1)+c0)\4-1

結構頭をひねりました。これで16Bytesの削減になっています。
上と同様にテーブル化してみると、

後\前 ←:0 ↑:1 →:2 ↓:3
←:0 −1
↑:1 −1
→:2 −1
↓:3 −1

右折:-1、左折:1、反転:2、直進:0 となり、直進がそのままでOKになりました。
反転については、プレーヤー反転時に魔力ラインを引き始めたときには転回値の差が2に
なるものの、囲むまでに必ず3以上の変化がありますので、そのままでも影響はありません。
(魔力ラインがすでに引かれている場合は、反転で魔力ラインのリセットが掛かります。)


あと、eevに新しい方向が格納された際、以下のような処理も行っています。

  c1+du(eev)   ; (duは-1,-21,1,21 の配列)
  if( map(c1)>=0 ) { eeq=8,c1 } ; (プレーヤーの位置=c1、移動カウンタ=8) 

先ほど退避の際にc0=eev,eepしたので、c1に現在位置を保持した状態。
方向eevからマップ上の移動量を求めてc1に加算し、移動先として新しい位置を求めます。
その場所が壁でなければ、位置と移動カウンタを更新して移動開始、という流れ。