; RVSのサブモジュール
; BRDの集計や判定などを行う
*SUB_Define
numalias SUB_TOWARD_ENUMSTART,0
numalias SUB_TOWARD_UP,0
numalias SUB_TOWARD_RIGHTUP,1
numalias SUB_TOWARD_RIGHT,2
numalias SUB_TOWARD_RIGHTDOWN,3
numalias SUB_TOWARD_DOWN,4
numalias SUB_TOWARD_LEFTDOWN,5
numalias SUB_TOWARD_LEFT,6
numalias SUB_TOWARD_LEFTUP,7
numalias SUB_TOWARD_ENUMEND,7

numalias SUB_NOTREVERSIBLE,0
numalias SUB_REVERSIBLE,1

defsub SubInit
defsub SubIsExistStone
defsub SubIsExistNeighber
defsub SubIsExistReversibles
defsub SubIsExistReversibleCell
defsub SubReverseStone
defsub subCheckReversibleAllWards

numalias SUB_VARNUM_EXTERNAL,400
numalias SUB_Loop,SUB_VARNUM_EXTERNAL
numalias SUB_Return,SUB_VARNUM_EXTERNAL+1
numalias SUB_PosX,SUB_VARNUM_EXTERNAL+2
numalias SUB_PosY,SUB_VARNUM_EXTERNAL+3
numalias SUB_Color,SUB_VARNUM_EXTERNAL+4
numalias SUB_ReverseColor,SUB_VARNUM_EXTERNAL+5
numalias SUB_PosX2,SUB_VARNUM_EXTERNAL+6
numalias SUB_PosY2,SUB_VARNUM_EXTERNAL+7
numalias SUB_Count,SUB_VARNUM_EXTERNAL+8

numalias SUB_VARNUM_INTERNAL,410
numalias SUB_Arg1,SUB_VARNUM_INTERNAL
numalias SUB_Arg2,SUB_VARNUM_INTERNAL+1
numalias SUB_Arg3,SUB_VARNUM_INTERNAL+2
numalias SUB_Arg4,SUB_VARNUM_INTERNAL+3
numalias SUB_Arg5,SUB_VARNUM_INTERNAL+4
numalias SUB_Arg6,SUB_VARNUM_INTERNAL+5
numalias SUB_Arg7,SUB_VARNUM_INTERNAL+6
numalias SUB_Arg8,SUB_VARNUM_INTERNAL+7
numalias SUB_Arg9,SUB_VARNUM_INTERNAL+8
numalias SUB_Tmp,SUB_VARNUM_INTERNAL+9

; 方向の状態 方向 X差分、Y差分、X終端、Y終端、反転可否
numalias SUB_Towards,4
dim ?SUB_Towards[SUB_TOWARD_ENUMEND][4]
return

*SubInit
movl ?SUB_Towards[SUB_TOWARD_UP],0,-1,0,0,SUB_NOTREVERSIBLE
movl ?SUB_Towards[SUB_TOWARD_RIGHTUP],1,-1,7,0,SUB_NOTREVERSIBLE
movl ?SUB_Towards[SUB_TOWARD_RIGHT],1,0,7,0,SUB_NOTREVERSIBLE
movl ?SUB_Towards[SUB_TOWARD_RIGHTDOWN],1,1,7,7,SUB_NOTREVERSIBLE
movl ?SUB_Towards[SUB_TOWARD_DOWN],0,1,0,7,SUB_NOTREVERSIBLE
movl ?SUB_Towards[SUB_TOWARD_LEFTDOWN],-1,1,0,7,SUB_NOTREVERSIBLE
movl ?SUB_Towards[SUB_TOWARD_LEFT],-1,0,0,0,SUB_NOTREVERSIBLE
movl ?SUB_Towards[SUB_TOWARD_LEFTUP],-1,-1,0,0,SUB_NOTREVERSIBLE
return

; Xが返ってきたらアボート
*SubIsExistStone
getparam i%SUB_Return,%SUB_PosX,%SUB_PosY
BrdIsExistStone %%SUB_Return,%SUB_PosX,%SUB_PosY
return

*SubIsExistNeighber
getparam i%SUB_Return,%SUB_PosX,%SUB_PosY
mov %%SUB_Return,0
for %SUB_Loop=SUB_TOWARD_ENUMSTART to SUB_TOWARD_ENUMEND
	BrdIsExistStone %SUB_Tmp,%SUB_PosX+?SUB_Towards[%SUB_Loop][0],%SUB_PosY+?SUB_Towards[%SUB_Loop][1]
	if %SUB_Tmp=1 mov %%SUB_Return,1:break
next
return

; 反転可能な方向が一つでもあればOK
; 時計回りにチェックしているが、特に意味は無い
*SubIsExistReversibles
getparam i%SUB_Return,%SUB_Color,%SUB_PosX,%SUB_PosY
subCheckReversibleAllWards %%SUB_Return,%SUB_Color,%SUB_PosX,%SUB_PosY
return

*sub_PushCheckCellProc
xyloopct %SUB_PosX2,%SUB_PosY2
BrdGetStone %SUB_Tmp,%SUB_PosX2,%SUB_PosY2
if %SUB_Tmp=X xyloopbreak:return
if %SUB_Tmp=N xyloopbreak:return
BrdPushCheckCell %SUB_Tmp
return

; 反転可能な空きセルがあるかどうか
; ヒットセルが反転不可能な場合のみ呼ばれる
*SubIsExistReversibleCell
getparam i%SUB_Return,%SUB_Color
mov %%SUB_Return,0
; 全セルを調べる
for %SUB_PosY=0 to 7
	for %SUB_PosX=0 to 7
		; 空きセルでなければ調べる意味なし
		BrdIsExistStone %SUB_Tmp,%SUB_PosX,%SUB_PosY
		if %SUB_Tmp=0 subCheckReversibleAllWards %%SUB_Return,%SUB_Color,%SUB_PosX,%SUB_PosY
		if %%SUB_Return=1:break
	next
	if %%SUB_Return=1:break
next
return

; ひっくり返す
*SubReverseStone
getparam %SUB_Color,%SUB_PosX,%SUB_PosY
BrdGetReverseColor %SUB_ReverseColor,%SUB_Color
; 各方向で反転可能かどうかを調べる
for %SUB_Loop=SUB_TOWARD_ENUMSTART to SUB_TOWARD_ENUMEND
	BrdClearCheckCell
	; 各方向のセル内容を列として登録する
	xyloop *sub_PushCheckCellProc,%SUB_PosX+?SUB_Towards[%SUB_Loop][0],%SUB_PosY+?SUB_Towards[%SUB_Loop][1],?SUB_Towards[%SUB_Loop][2],?SUB_Towards[%SUB_Loop][3],?SUB_Towards[%SUB_Loop][0],?SUB_Towards[%SUB_Loop][1]
	; 反転数が1以上なら反転可能を登録する
	BrdCheckReverse %SUB_Count,%SUB_Color,%SUB_ReverseColor
	if %SUB_Count>0 mov ?SUB_Towards[%SUB_Loop][4],SUB_REVERSIBLE:skip 2
	mov ?SUB_Towards[%SUB_Loop][4],SUB_NOTREVERSIBLE
next
; 反転する
for %SUB_Loop=SUB_TOWARD_ENUMSTART to SUB_TOWARD_ENUMEND
	if ?SUB_Towards[%SUB_Loop][4]=SUB_REVERSIBLE xyloop *sub_ReverseProc,%SUB_PosX+?SUB_Towards[%SUB_Loop][0],%SUB_PosY+?SUB_Towards[%SUB_Loop][1],?SUB_Towards[%SUB_Loop][2],?SUB_Towards[%SUB_Loop][3],?SUB_Towards[%SUB_Loop][0],?SUB_Towards[%SUB_Loop][1]
next
return

*sub_ReverseProc
xyloopct %SUB_PosX2,%SUB_PosY2
BrdGetStone %SUB_Tmp,%SUB_PosX2,%SUB_PosY2
if %SUB_Tmp=%SUB_ReverseColor BrdReverseStone %SUB_Color,%SUB_PosX2,%SUB_PosY2:return
; 反対色以外はブレーク
xyloopbreak
return

; どこか一つでも存在した場合は1を返す
*subCheckReversibleAllWards
getparam i%SUB_Arg1,%SUB_Arg2,%SUB_Arg3,%SUB_Arg4
mov %%SUB_Arg1,0
BrdGetReverseColor %SUB_Arg5,%SUB_Arg2
; 各方向で反転可能かどうかを調べる
; Arg1 - Arg5 は不変なので注意
for %SUB_Loop=SUB_TOWARD_ENUMSTART to SUB_TOWARD_ENUMEND
	; 各方向のセル内容を列として探索する
	mov %SUB_Count,0:mov %SUB_Arg9,0
	xyloop *sub_CheckReversibleAWProc,%SUB_Arg3+?SUB_Towards[%SUB_Loop][0],%SUB_Arg4+?SUB_Towards[%SUB_Loop][1],?SUB_Towards[%SUB_Loop][2],?SUB_Towards[%SUB_Loop][3],?SUB_Towards[%SUB_Loop][0],?SUB_Towards[%SUB_Loop][1]
	; 反転数が1以上なら反転可能を返す
	if %SUB_Count>0 mov %%SUB_Arg1,1:break
next
return

*sub_CheckReversibleAWProc
xyloopct %SUB_Arg6,%SUB_Arg7
BrdGetStone %SUB_Arg8,%SUB_Arg6,%SUB_Arg7
;if %SUB_Arg3=7 & %SUB_Arg4=5 tracexy %SUB_Arg6,%SUB_Arg7
; 連続する反対色の数をチェック
if %SUB_Arg8=%SUB_Arg5 inc %SUB_Arg9:return
; 同色かつ反対色の連続があればOK
if %SUB_Arg8=%SUB_Arg2 & %SUB_Arg9>0 mov %SUB_Count,%SUB_Arg9:xyloopbreak:return
; それ以外はNGでブレーク
mov %SUB_Arg9,0
xyloopbreak
return