#apply
#include "../_include.txt"
#include "../../define/_vector2.txt"


cev[CEV_PANKU_MAN] .name("mg_パンツ食うマン") {

    def {
        NUM_OF_VAR = 80
        NUM_OF_STR = 0
        NUM_OF_PIC = 32

        BASE_LAYER = 6

        PATH_BACK   = "pm\bg"
        PATH_COVER  = "cm\da"
        PATH_ILLUST = "pm\il"
        PATH_CHARA  = "pm\ch"
        PATH_WARP   = "pm\wa"
        PATH_COUNT  = "pm\co"
        PATH_REMAIN = "pm\li"
        PATH_BAR    = "pm\ba"
        PATH_POWER  = "pm\ca"
        PATH_PANTY  = "pm\pt"
        PATH_STAGE  = "pm\st0"

        PIC_HEAD    = 2
        PIC_BACK    = 3
        PIC_MAP     = 4
        PIC_REMAIN  = 5
        PIC_POWER   = 6
        PIC_SCORE   = 7//+0_+7
        PIC_HISCORE = 15//+0_+7
        PIC_WARP    = 23
        PIC_ENEMY   = 24//+0_+2
        PIC_PLAYER  = 27
        PIC_PANTY   = 28
        PIC_ILLUST  = 29
        PIC_COVER   = 30
        PIC_BAR     = 31

        //実績
        ACHIEVE_CLEAR = 3 * 3

        //更新フラグ
        TR_BIT_SCORE   = 1 << 0
        TR_BIT_HISCORE = 1 << 1
        TR_BIT_MYCHARA = 1 << 2
        TR_BIT_WARP    = 1 << 3
        TR_BIT_ENEMY   = 1 << 4
        TR_BIT_POWER   = 1 << 5
        TR_BIT_REMAIN  = 1 << 6

        //向き
        DIR_UP = 0
        DIR_RIGHT
        DIR_DOWN
        DIR_LEFT

        //判定用のカラー(argb)
        COLOR_NONE  = 0x00000000
        COLOR_WALL  = 0xff52cd00
        COLOR_DOT   = 0xfff6ffff
        COLOR_POWER = 0xffffb418

        //消去に使うマップタイル
        TILESET_ID = 1
        TILE_ID_NONE = 161

        //スコア
        SCORE_MAX    = 999999
        SCORE_DOT    = 1
        SCORE_POWER  = 10
        SCORE_CLEAR  = 50
        SCORE_PANTY  = 200
        SCORE_EXTEND = 2000

        //状態
        SCENE_STATE_NORMAL = 0
        SCENE_STATE_WARP
        SCENE_STATE_RETURN
        SCENE_STATE_READY
        SCENE_STATE_OUT
        SCENE_STATE_GAMEOVER
        SCENE_STATE_CLEAR
        SCENE_STATE_REST

        //定数
        HIT_RAD = 12
        HIT_ENEMY_RAD = 8
        HIT_PANTY_RAD = 14
        MODE_TIME = (60 * 6 / 4)
        WARP_TIME = 20
        STEP_SPEED = 4
        FIRST_SPEED = 4
        TILE_WIDTH = 16

        STAGE_MAX = 3
        STAGE_WIDTH = 12//縦横両用
        POWER_MAX = 3
        REMAIN_MAX = 3
        REMAIN_DEFAULT = 2
        SCORE_DIGIT = 6//スコアの桁
        SCORE_WIDTH = 8

        REF_X = 64//ステージの左上座標
        REF_Y = 16
        SCORE_X = 248//スコアの表示位置
        SCORE_Y = 218
        HISCORE_X = 248
        HISCORE_Y = 228
        BAR_X = 160
        BAR_Y = 112
        BAR_REST_Y = 184
        REMAIN_X = 96
        REMAIN_Y = 218
        POWER_X = 96
        POWER_Y = 204
        ILLUST_X = 72
        ILLUST_Y = 24

        EN_NUM = 3
        EN_TYPE_NONE = -1
        EN_TYPE_WAVE = 0
        EN_TYPE_CURE
        EN_TYPE_SPARK

        EN_STATE_NORMAL = 0
        EN_STATE_HARDEN
        EN_STATE_WAIT

        ME_TYPE = 0
        ME_STATE
        ME_TIMER
        ME_POWER
        ME_CELL
        ME_DIR
        ME_CUR_X
        ME_CUR_Y
        ME_TAG_X
        ME_TAG_Y
        SIZE_OF_EN

        mType  = v[ME_TYPE + ele]
        mState = v[ME_STATE + ele]
        mTimer = v[ME_TIMER + ele]
        mPower = v[ME_POWER + ele]
        mCell  = v[ME_CELL + ele]
        mDir   = v[ME_DIR + ele]
        mCurX  = v[ME_CUR_X + ele]
        mCurY  = v[ME_CUR_Y + ele]
        mTagX  = v[ME_TAG_X + ele]
        mTagY  = v[ME_TAG_Y + ele]
    }

    def {
        basePicCmd = bl {
            .chromakey(1)
            .mapLayer(BASE_LAYER)
            .eraseWhenTransfer
            .affectedByTint
            .affectedByFlash
            .affectedByShake

        }

        bgPicCmd = bl {
            PATH_BACK
            .topLeft
            .scale(100)
            .trans(0)
            basePicCmd
        }

        coverPicCmd = bl {
            PATH_COVER
            .center
            basePicCmd
        }

        illustPicCmd = bl {
            PATH_ILLUST
            .topLeft
            .scale(100)
            .grid(4, 1)
            basePicCmd
        }

        stagePicCmd = bl {
            PATH_STAGE
            .scale(100)
            basePicCmd
        }

        charaPicCmd = bl {
            PATH_CHARA
            .bottom
            .scale(100)
            .grid(12, 9)
            basePicCmd
        }

        warpPicCmd = bl {
            PATH_WARP
            .bottom
            .scale(100)
            .grid(3, 1)
            basePicCmd
        }

        scorePicCmd = bl {
            PATH_COUNT
            .bottomRight
            .scale(100)
            .grid(10, 1)
            basePicCmd
        }

        remainPicCmd = bl {
            PATH_REMAIN
            .topLeft
            .scale(100)
            .grid(1, 4)
            basePicCmd
        }

        barPicCmd = bl {
            PATH_BAR
            .scale(100)
            .grid(1, 4)
            basePicCmd
        }

        powerPicCmd = bl {
            PATH_POWER
            .scale(100)
            .grid(1, 4)
            basePicCmd
        }

        pantyPicCmd = bl {
            PATH_PANTY
            .scale(100)
            .grid(4, 1)
            basePicCmd
        }
    }

    //変数定義
    defv {
        varHead = TV_MINIGAME

        ipt
        ele
        idx
        pid
        cell
        tm1
        tm2
        ax
        ay
        tx
        ty
        dx
        dy

        clear
        gameSpeed
        remain
        score
        warpPower
        nextExtend
        dotNum
        waveEffect

        sceneState//以下の変数はリトライする度に初期化される
        sceneTimer
        modeTimer
        pantyTimer
        triggerFlg
        inputWarp
        combo
        plWalk
        plCell
        plDir
        plCurX
        plCurY
        plTagX
        plTagY
        warpX
        warpY

        enemyHead

        varFoot = __id(enemyHead) + SIZE_OF_EN * EN_NUM

    }
    
    commentRangeOfVariables(varFoot, TV_MINIGAME, NUM_OF_VAR, NUM_OF_STR, NUM_OF_PIC)

    //お邪魔キャラの変数位置を取得する
    __fn _getEnemyPointer $d $i bl {
        v[__id($d)] = __id(enemyHead) + ($i) * SIZE_OF_EN
    }

    //お邪魔キャラの状態を変更する
    //eleを使用する
    __fn _changeEnemyState $st bl {
        mState = $st
        mTimer = 0
    }

    //タイルの色を取得する
    __fn _getMapColor $d $x $y bl {
        //範囲外を参照するとエラーが出る
        @if `between($x, 0, TILE_WIDTH * STAGE_WIDTH - 2) &&
            between($y, 0, TILE_WIDTH * STAGE_WIDTH - 2) bl {
            @pic.getInfo[PIC_MAP] .pixel($x, $y, 1, 1) .xywh .dst($d) .static

        //範囲外は壁として扱う
        } .else bl {
            v[__id($d)] = COLOR_WALL
        }
    }

    //キャラクターのセル番号を取得する
    __fn _getCharaCell $d $chara $row $pat bl {
        v[ __id($d) ] = 1 + ($pat) + ($chara) * 3 + ($row) * 12
    }

    //状態を変える
    __fn _changeScene $st bl {
        sceneState = $st
        sceneTimer = -1
    }

    //スコアを加算する
    __fn _addScore $a bl {
        bitOn(triggerFlg, TR_BIT_SCORE)
        score = clamp(score + ($a), 0, SCORE_MAX)
    }

    //パワーを加算する
    __fn _addPower $a bl {
        bitOn(triggerFlg, TR_BIT_POWER)
        warpPower = clamp(warpPower + ($a), 0, POWER_MAX)
    }

    //残機を加算する
    __fn _addRemain $a bl {
        bitOn(triggerFlg, TR_BIT_REMAIN)
        remain = clamp(remain + ($a), 0, REMAIN_MAX)
    }

    //縄張り座標を取得する
    __fn _getTerritoryPosition $d $i bl {
        v[0 + __id($d)] = [10,  1, 10][$i] * TILE_WIDTH + TILE_WIDTH / 2
        v[1 + __id($d)] = [10, 10,  1][$i] * TILE_WIDTH + TILE_WIDTH / 2
    }

    //ピクセル座標からタイル中央のピクセル座標を取得する
    __fn _getCenterOnTile $d $s bl {
        v[0 + __id($d)] = v[0 + __id($s)] / TILE_WIDTH * TILE_WIDTH + TILE_WIDTH / 2
        v[1 + __id($d)] = v[1 + __id($s)] / TILE_WIDTH * TILE_WIDTH + TILE_WIDTH / 2
    }

    //タイル座標からタイル中央のピクセル座標を取得する
    __fn _getCenterOnTile2 $d $s bl {
        v[0 + __id($d)] = v[0 + __id($s)] * TILE_WIDTH + TILE_WIDTH / 2
        v[1 + __id($d)] = v[1 + __id($s)] * TILE_WIDTH + TILE_WIDTH / 2
    }

    //スコア表示を更新する
    //ax,ay,tm1,tm2,pid,cellを使用する
    __fn _updateScorePicture $score $pid $x $y {
        ax = ($x) + SCORE_WIDTH
        ay = ($y)
        @loop SCORE_DIGIT .dst(idx) bl {
            ax -= SCORE_WIDTH
            tm2 = pow(10, idx)

            pid = $pid + idx
            cell = 1 + $score % (tm2 * 10) / tm2
            tm1 = ($score / tm2 > 0 || idx <= 0) ? 0 : 100

            @pic.show[pid] .pos(ax, ay) .trans(tm1) .cell(cell) scorePicCmd
        }
    }

    //ハイスコアを更新する
    __fn _updateHighScore bl {
        pankuManScore = max(pankuManScore, score)
    }

    //------------------------------------------------------------------------------------
    //開始処理
    bl {
        initPicturesAndVariables(PIC_HEAD, NUM_OF_PIC, TV_MINIGAME, NUM_OF_VAR, 0, 0)
        storeAndStopBGM()
        msgBottom()
        //ピクチャ
        @pic.show[PIC_BACK] .pos(0, 0) bgPicCmd
        @pic.show[PIC_ILLUST] .trans(100) .cell(1) illustPicCmd
        @pic.show[PIC_COVER] .trans(100) coverPicCmd
        @pic.show[PIC_WARP] .trans(100) .anim(4) warpPicCmd
        @pic.show[PIC_PANTY] .trans(100) pantyPicCmd

        //暗転
        fastFadeInTintOnly(1)
        @wait(1)

        @label.jump "gameLoop"
    }

    //------------------------------------------------------------------------------------
    //ゲーム処理
    @label.set "gameLoop"
    bl {
        //----------------------------
        //ゲームオーバーから復帰すると、ここから始まる
        @label.set "replay"
        clear = 0
        score = 0
        nextExtend = SCORE_EXTEND
        remain = REMAIN_DEFAULT
        warpPower = 0

        //----------------------------
        //ステージが変わると、ここから始まる
        @label.set "startStage"

        //一部の変数を初期化する
        v[__id(sceneState)..__id(warpY)] = 0

        //ピクチャを一瞬だけ透明化
        hidePicturesForEach( [PIC_PLAYER, PIC_WARP, PIC_MAP] )
        @wait(0)

        //2周すると最高速に達し、3週目で戻る
        gameSpeed = [4, 3, 2][ (clear / STAGE_MAX) % 3 ]

        //ワープポイントの初期位置
        V2_set(ax, 1, 1)
        _getCenterOnTile2(warpX, ax)

        //ドットの数
        dotNum = [58, 61, 63][ clear % STAGE_MAX ]

        //ステージピクチャ
        cell = clear % STAGE_MAX
        @pic.show[PIC_MAP] .repl(1, cell) .pos(REF_X, REF_Y) .topLeft stagePicCmd

        //ビットでお邪魔キャラの有無を指定する
        //3周するとキャラが増える
        @if clear >= STAGE_MAX * 3 bl {
            tm1 = 0x1 | 0x2 | 0x4
        //ステージによって組み合わせが変わる
        } .else bl {
            tm1 = [ 0x1 | 0x2, 0x2 | 0x4, 0x1 | 0x4 ][ clear % STAGE_MAX ]
        }

        //お邪魔キャラを設置する
        @loop EN_NUM .dst(idx) bl {
            _getEnemyPointer(ele, idx)

            @if `tm1 & (1 << idx) bl {
                //初期位置はキャラタイプによって固定
                _getTerritoryPosition(ax, idx)
                //変数初期化
                v[ele..ele + SIZE_OF_EN - 1] = 0
                mType = idx
                mState = EN_STATE_WAIT
                mDir = DIR_DOWN
                mCurX = ax
                mCurY = ay
                mTagX = ax
                mTagY = ay

                _getCharaCell(idx, mType + 1, mDir, 0)
                mCell = idx
                //ピクチャの設置は後で行う

            //設置しない
            } .else bl {
                mType = EN_TYPE_NONE
                //ピクチャを透明化する
                pid = PIC_ENEMY + idx
                @pic.move[pid] .trans(100)
            }
        }

        //特に意味のない、ブレる演出
        //本当に意味がないが、せっかくなので残す
        @if `!waveEffect bl {
            waveEffect = TRUE

            @se.play "Switch2" .opt(80, 80, 50)
            @pic.move [PIC_MAP] .relative .pos(0, 0) .scale(0) .trans( 50) .keepRgbs .wave(1)
            @wait .frame(4)
            @pic.move [PIC_MAP] .relative .pos(0, 0) .scale(0) .trans(-50) .keepRgbs
            @wait(0)
        }

        //----------------------------
        //残機が減った後、ここから始まる
        @label.set "return"
        _changeScene(SCENE_STATE_READY)
        triggerFlg = TR_BIT_SCORE | TR_BIT_HISCORE | TR_BIT_MYCHARA | TR_BIT_WARP | TR_BIT_REMAIN | TR_BIT_POWER | TR_BIT_ENEMY
        //入力を初期化する
        inputWarp = 0
        //最初は縄張りモードだが、時間は通常の半分となる
        modeTimer = MODE_TIME / 2
        //お邪魔キャラが一時的に止まる
        @loop EN_NUM .dst(idx) bl {
            _getEnemyPointer(ele, idx)
            @if `mType != EN_TYPE_NONE bl {
                _changeEnemyState(EN_STATE_WAIT)
                //怒り状態を解除
                mPower = FALSE
                //位置を修正する
                ax = mCurX / TILE_WIDTH * TILE_WIDTH + TILE_WIDTH / 2
                ay = mCurY / TILE_WIDTH * TILE_WIDTH + TILE_WIDTH / 2
                mCurX = ax
                mCurY = ay
                mTagX = ax
                mTagY = ay
            }
        }

        //自キャラはワープポイントから始まる
        V2_copy(plTagX, warpX)
        V2_copy(plCurX, warpX)
        _getCharaCell(plCell, 0, DIR_DOWN, 1)
        plDir = DIR_DOWN

        //----------------------------
        //ループ
        @loop bl {
            @wait(0)

            //----------------------------
            //ポーズ
            pauseProcces(TRUE, ipt, "gameEnd")

            //----------------------------
            //タイマー
            sceneTimer += 1
            //通常
            @if sceneState == SCENE_STATE_NORMAL bl {
                //----------------------------
                //プレイヤー
                //ワープポイントとの距離
                V2_sub(ax, warpX, plCurX)
                //決定キーでワープ
                @key.input .dst(ipt) .decision
                //一度押すとワープを予約した状態になる
                @if `inputWarp == 0 && ipt bl {
                    inputWarp = 1

                    //近すぎず、パワーエサを取っていると足元にワープポイントを設置する
                    //条件を満たさなくとも予約した状態になる
                    @if `max( abs(ax), abs(ay) ) >= HIT_RAD && warpPower > 0 bl {
                        bitOn(triggerFlg, TR_BIT_WARP)
                        _getCenterOnTile(warpX, plCurX)

                        @se.play "Raise2" .opt(80, 150, 50)
                    }
                }

                //予約した状態で離すとワープする
                @if `inputWarp == 1 && !ipt bl {
                    inputWarp = 0
                    //近すぎる、あるいはパワーエサが無い場合はそのまま不発となる
                    @if `warpPower > 0 && max( abs(ax), abs(ay) ) >= HIT_RAD bl {
                        inputWarp = 0

                        _changeScene(SCENE_STATE_WARP)

                        //消費
                        bitOn(triggerFlg, TR_BIT_POWER)
                        warpPower -= 1

                        //コンボリセット
                        combo = 0

                        //向き
                        @if `abs(ax) >= abs(ay) bl {
                            plDir = ax > 0 ? DIR_RIGHT : DIR_LEFT
                        } .else bl {
                            plDir = ay > 0 ? DIR_DOWN : DIR_UP
                        }

                        @se.play "Teleport1" .opt(100, 150, 50)
                    }
                }

                //ワープした瞬間
                @if sceneState == SCENE_STATE_WARP bl {
                
                //クリア判定
                } .elif dotNum <= 0 bl {
                    _changeScene(SCENE_STATE_CLEAR)
                    //クリアボーナス
                    _addScore(SCORE_CLEAR)
                
                //次の移動待ち
                } .elif `sceneTimer % gameSpeed == 0 bl {
                    //行動パターン切り替えタイマー
                    modeTimer = (modeTimer + 1) % (MODE_TIME * 2)
                    //入力
                    V2_getInput(ax, ipt)
                    //目標位置に壁があるかチェックする
                    //入力方向の半歩先を調べる
                    tm1 = COLOR_WALL
                    tm2 = -1
                    @loop 2 .dst(idx) bl {
                        //横軸、縦軸の順に調べ、壁のない方の結果を残す
                        @if `v[idx + __id(ax)] bl {
                            $w = (TILE_WIDTH)
                            $c = ($w / 2 + 2)
                            //[1, 0][0, 1]
                            tx = (plCurX + ((idx + 1) % 2) * ax * $c) / $w * $w + $w / 2
                            ty = (plCurY + ((idx + 0) % 2) * ay * $c) / $w * $w + $w / 2
                            _getMapColor(tm1, tx, ty)
                            @if tm1 != COLOR_WALL bl {
                                tm2 = idx
                                @break
                            }
                        }
                    }

                    //移動先と向きを更新する
                    @if tm2 >= 0 bl {
                        //移動先
                        V2_copy(plTagX, tx)
                        //向き
                        @if tm2 == 0 bl {
                            plDir = ax > 0 ? DIR_RIGHT : DIR_LEFT
                        } .elif tm2 == 1 bl {
                            plDir = ay > 0 ? DIR_DOWN : DIR_UP
                        }
                    }

                    //目標位置までの距離
                    V2_sub(dx, plTagX, plCurX)
                    //停止中
                    @if `abs( dx ) + abs( dy ) == 0 bl {
                        bitOn(triggerFlg, TR_BIT_MYCHARA)
                        _getCharaCell(plCell, 0, plDir, 1)
                        plWalk = 0

                    //移動中
                    } .else bl {
                        bitOn(triggerFlg, TR_BIT_MYCHARA)
                        plWalk += 1
                        _getCharaCell(plCell, 0, plDir, [2, 1, 0, 1][ plWalk % 4 ] )

                        plCurX += clamp( dx, -STEP_SPEED, STEP_SPEED )
                        plCurY += clamp( dy, -STEP_SPEED, STEP_SPEED )

                        //中心に近づいたとき、足元を調べる
                        @if `max( abs( dx ), abs( dy ) ) <= HIT_RAD bl {
                            _getCenterOnTile(tx, plCurX)
                            _getMapColor(tm1, tx, ty)

                            //ドット
                            @if tm1 == COLOR_DOT bl {
                                _addScore(SCORE_DOT)
                                @se.play "Cancel1" .opt(80, 200, 50)
                            }

                            //パワーエサ
                            @if tm1 == COLOR_POWER bl {
                                _addPower(1)
                                _addScore(SCORE_POWER)

                                @se.play "Song" .opt(100, 150, 50)
                            }

                            //ドットかパワーエサ
                            @if `tm1 == COLOR_DOT || tm1 == COLOR_POWER bl {
                                //足元のピクチャを塗り替える
                                //.gridコマンドと相性が悪い
                                tx = tx / TILE_WIDTH * TILE_WIDTH
                                ty = ty / TILE_WIDTH * TILE_WIDTH
                                @pic.drawTile[PIC_MAP] .xywh(tx, ty, 1, 1) .single(TILE_ID_NONE) .tilesetId(TILESET_ID) .lower .disableAutoTile
                                //ドット数減少
                                dotNum -= 1
                            }
                        }
                    }

                    //----------------------------
                    //お邪魔キャラ
                    @loop EN_NUM .dst(idx) bl {
                        _getEnemyPointer(ele, idx)
                        @if `mType != EN_TYPE_NONE bl {
                            //タイマー
                            mTimer += 1
                            //通常 or 怒り状態
                            @if `mState == EN_STATE_NORMAL bl {
                                //移動
                                V2_set(dx, mTagX - mCurX, mTagY - mCurY)
                                @if `abs( dx ) + abs( dy ) > 0 bl {
                                    tm1 = mDir + (mPower ? 4 : 0)
                                    _getCharaCell(cell, mType + 1, tm1, [2, 1, 0, 1][ mTimer % 4 ] )
                                    mCell = cell

                                    mCurX += clamp( dx, -STEP_SPEED, STEP_SPEED)
                                    mCurY += clamp( dy, -STEP_SPEED, STEP_SPEED)

                                    //距離を更新する
                                    V2_set(dx, mTagX - mCurX, mTagY - mCurY)
                                }

                                //１マス分移動した
                                @if `abs( dx ) + abs( dy ) <= 0 bl {
                                    $w = (TILE_WIDTH)
                                    //キャラの種類
                                    tm1 = mType
                                    //目標座標
                                    //自キャラ
                                    @if `modeTimer > MODE_TIME || mPower bl {
                                        V2_copy(tx, plCurX)
                                        //ウェーブ
                                        //ひたすら追いかける
                                        @if tm1 == EN_TYPE_WAVE bl {
                                            //何も変わらない
                                        }

                                        //キュアー
                                        //近いと曲がらなくなる
                                        @if tm1 == EN_TYPE_CURE bl {
                                            tm2 = abs(mCurX - tx) + abs(mCurY - ty)
                                            //2マス分
                                            @if tm2 <= TILE_WIDTH * 2 bl {
                                                tm2 = mDir
                                                tx = mCurX + [ 0, 1, 0,-1][tm2] * $w
                                                ty = mCurY + [-1, 0, 1, 0][tm2] * $w
                                            }
                                        }

                                        //スパーク
                                        //X軸、Y軸に分け、短い方に合わせる
                                        @if tm1 == EN_TYPE_SPARK bl {
                                            //X軸を合わせる
                                            @if `abs(mCurX - tx) < abs(mCurY - ty) bl {
                                                ty = mCurY + ( mCurY < ty ? 1 : -1 ) * $w / 2
                                            //Y軸を合わせる
                                            } .elif `abs(mCurX - tx) > abs(mCurY - ty) bl {
                                                tx = mCurX + ( mCurX < tx ? 1 : -1 ) * $w / 2
                                            }
                                        }
                                        
                                    //縄張り
                                    //この状態の時は真っ直ぐ向かう
                                    } .else bl {
                                        tm2 = mType
                                        _getTerritoryPosition(tx, tm2)
                                    }

                                    //周囲４マスの壁を調べ、進行方向を選ぶ
                                    //方向と距離の二乗
                                    ipt = -1
                                    cell = 99999999
                                    @loop 4 .dst(tm1) bl {
                                        //u,r,d,l
                                        ax = mCurX + [ 0, 1, 0,-1][tm1] * $w
                                        ay = mCurY + [-1, 0, 1, 0][tm1] * $w
                                        _getMapColor(tm2, ax, ay)
                                        @if tm2 != COLOR_WALL bl {
                                            V2_distSq(tm2, tx, ax)
                                            //反対方向は選ばない
                                            @if `tm2 < cell && mDir != (tm1 + 2) % 4 bl {
                                                cell = tm2
                                                ipt = tm1
                                            }
                                        }
                                    }

                                    //袋小路に入った場合は反転する
                                    @if ipt == -1 bl {
                                        mDir = (mDir + 2) % 4
                                    //向きを変えて移動する
                                    } .else bl {
                                        mDir  = ipt
                                        mTagX = mTagX + [ 0, 1, 0,-1][ipt] * $w
                                        mTagY = mTagY + [-1, 0, 1, 0][ipt] * $w
                                    }
                                }

                                //自キャラとの衝突判定
                                //クリアした瞬間は無効となる
                                @if dotNum > 0 bl {
                                    V2_set(dx, plCurX - mCurX, plCurY - mCurY)
                                    @if `abs( dx ) + abs( dy ) <= HIT_ENEMY_RAD bl {
                                        _changeScene(SCENE_STATE_OUT)
                                    }
                                }

                            //めくられた
                            } .elif `mState == EN_STATE_HARDEN bl {
                                //ひらひら
                                @if `mTimer < 30 bl {
                                    _getCharaCell(cell, mType + 1, 8, [0, 1][mTimer % 2] )
                                    mCell = cell
                                //怒る / 落ち着く
                                } .else bl {
                                    mPower = mPower ? FALSE : TRUE
                                    _changeEnemyState(EN_STATE_NORMAL)
                                }
                            //停止
                            } .elif `mState == EN_STATE_WAIT bl {
                                //向きをランダムに変える
                                @if `mTimer % 5 == 0 bl {
                                    mDir = rnd(0, 3)
                                    _getCharaCell(cell, mType + 1, mDir, 0)
                                    mCell = cell
                                }
                                //動き出す
                                @if `mTimer > 16 bl {
                                    _changeEnemyState(EN_STATE_NORMAL)
                                }
                            }
                        }
                    }
                    //お邪魔キャラのピクチャを更新する
                    bitOn(triggerFlg, TR_BIT_ENEMY)
                }

            //ワープ中 or ミスからの復帰
            } .elif `sceneState == SCENE_STATE_WARP || sceneState == SCENE_STATE_RETURN bl {
                //plTagXを始点とする
                @if sceneTimer == 0 bl {
                    V2_copy(plTagX, plCurX)
                }

                //一直線に移動する
                V2_lerp(plCurX, plTagX, warpX, sceneTimer, WARP_TIME)

                //スカートめくり判定
                @if sceneState == SCENE_STATE_WARP bl {
                    tm1 = -1
                    @loop EN_NUM .dst(idx) bl {
                        _getEnemyPointer(ele, idx)
                        @if `mType != EN_TYPE_NONE bl {
                            V2_set(dx, mCurX - plCurX, mCurY - plCurY)

                            @if `max( abs( dx ), abs( dy ) ) <= HIT_PANTY_RAD && mState != EN_STATE_HARDEN bl {
                                _changeEnemyState(EN_STATE_HARDEN)
                                _getCharaCell(cell, mType + 1, 8, 0 )
                                mCell = cell
                                //連続してパンツを取ると追加点がある
                                _addScore( SCORE_PANTY + 100 * combo )
                                combo += 1
                                //パンツのセル番号と表示位置
                                tm1 = mType + 1
                                tx = REF_X + mCurX
                                ty = REF_Y + mCurY - 8
                            }
                        }
                    }

                    //めくり成功
                    @if tm1 > 0 bl {
                        bitOn(triggerFlg, TR_BIT_ENEMY)
                        //パンツアイコンを表示する
                        pantyTimer = 60

                        cell = tm1
                        @pic.show[PIC_PANTY] .pos(tx, ty) .trans(0) .cell(cell) pantyPicCmd
                        @pic.move[PIC_PANTY] .relative .pos(0, -8) .scale(0) .trans(0) .time(2)
                        @se.play "Recovery3" .opt(80, 150, 50)
                    }
                }

                //半秒で到着する
                @if sceneTimer >= WARP_TIME bl {
                    V2_copy(plCurX, warpX)
                    V2_copy(plTagX, warpX)

                    _getCharaCell(plCell, 0, plDir, 1 )
                    plDir = DIR_DOWN

                    //ワープ終了
                    @if sceneState == SCENE_STATE_WARP bl {
                        _changeScene(SCENE_STATE_NORMAL)
                    //準備完了
                    } .else bl {
                        //もう一度
                        @label.jump "return"
                    }

                //光りながら移動する
                } .else bl {
                    _getCharaCell(plCell, 0, plDir + 4, [0, 1, 2][sceneTimer % 6 / 2] )
                }

                //毎F更新
                bitOn(triggerFlg, TR_BIT_MYCHARA)

            //準備
            } .elif sceneState == SCENE_STATE_READY bl {
                //文字を表示する
                @if sceneTimer == 0 bl {
                    //お邪魔キャラのピクチャも更新する
                    bitOn(triggerFlg, TR_BIT_ENEMY)
                    @pic.show[PIC_BAR] .pos(BAR_X, BAR_Y) .center .cell(1) barPicCmd
                }

                //入力を受け付けるまで間がある
                @if sceneTimer > 10 bl {
                    getAnyKey(ipt, FALSE)
                    //何らかのキーを押すと開始する
                    @if `ipt bl {
                        _changeScene(SCENE_STATE_NORMAL)
                        //BGM
                        startBGM("picopicomusic", FALSE, 0, 100, 100, 50)
                        //文字を隠す
                        @pic.move[PIC_BAR] .trans(100)
                    }
                }

            //捕まった
            } .elif sceneState == SCENE_STATE_OUT bl {
                //効果音
                @if sceneTimer == 0 bl {
                    @se.play "Damage2" .opt(100, 120, 50)
                    @se.play "Fall1" .opt(100, 100, 50)
                }

                //じたばた
                @if `sceneTimer < 30 bl {
                    bitOn(triggerFlg, TR_BIT_MYCHARA)
                    _getCharaCell(plCell, 0, 8, [0, 1][sceneTimer % 8 / 4] )
                }

                //残機チェック
                @if sceneTimer >= 60 bl {
                    //ゲームオーバー
                    @if remain <= 0 bl {
                        _changeScene(SCENE_STATE_GAMEOVER)
                    //リトライ
                    } .else bl {
                        _changeScene(SCENE_STATE_RETURN)

                        bitOn(triggerFlg, TR_BIT_REMAIN)

                        //無敵モード中は残機が減らない
                        @if invincibleSwitch.isOff bl {
                            remain -= 1
                        }
                    }
                }

            //ゲームオーバー
            } .elif sceneState == SCENE_STATE_GAMEOVER bl {
                //文字を表示する
                @if sceneTimer == 0 bl {
                    @pic.show[PIC_BAR] .pos(BAR_X, BAR_Y) .center .cell(2) barPicCmd
                    @se.play "Sleep" .opt(100, 50, 50)
                    stopBGM(0)
                }

                //もう一回やる？
                @if sceneTimer >= 120 bl {
                    _updateHighScore()
                    replayProcess("replay", "gameEnd")
                }

            //ステージクリア
            } .elif sceneState == SCENE_STATE_CLEAR bl {
                //効果音
                @if sceneTimer == 0 bl {
                    @se.play "Item1" .opt(80, 150, 50)
                    stopBGM(0)
                }

                //文字を表示してジングルを鳴らす
                @if sceneTimer == 60 bl {
                    @pic.show[PIC_BAR] .pos(BAR_X, BAR_Y) .center .cell(3) barPicCmd
                    @se.play "itemget2" .opt(100, 100, 50)
                }

                //次のステージへ
                @if sceneTimer >= 160 bl {
                    clear += 1
                    //実績
                    checkSetAchievement(achievedPanty, clear >= ACHIEVE_CLEAR)
                    //一周した場合、休憩する
                    @if `clear % STAGE_MAX == 0 bl {
                        _changeScene(SCENE_STATE_REST)
                    } .else bl {
                        @label.jump "startStage"
                    }
                }

            //休憩
            } .elif sceneState == SCENE_STATE_REST bl {
                //最初に実行する
                @if sceneTimer == 0 bl {
                    //BGMを停止する
                    stopBGM(0)
            
                    //ピクチャを隠す
                    hidePicturesForEach( [PIC_PLAYER, PIC_WARP, PIC_MAP, PIC_BAR, PIC_ENEMY + 0, PIC_ENEMY + 1, PIC_ENEMY + 2] )
                    //一枚絵と隠しを表示する
                    cell = 1 + ( (clear - 1) / STAGE_MAX ) % 4
                    @pic.show[PIC_ILLUST] .pos(ILLUST_X, ILLUST_Y) .cell(cell) .trans(0) illustPicCmd
                    @pic.show[PIC_COVER] .pos(160, 112) .scale2(1100, 1100) coverPicCmd//10倍に広げる
                    @pic.move[PIC_COVER] .relative .pos(0, 0) .scale2(0, -1100) .time(10 * 2)
                }

                //文字を表示する
                @if sceneTimer == 60 * 2 bl {
                    @pic.show[PIC_BAR] .pos(BAR_X, BAR_REST_Y) .center .cell(4) barPicCmd
                }

                //一枚絵が表示されてから入力を受け付ける
                @if sceneTimer > 60 * 2 bl {
                    getAnyKey(ipt, FALSE)
                    //何らかのキーを押すと開始する
                    @if `ipt bl {
                        _changeScene(SCENE_STATE_READY)
                        //ピクチャを隠す
                        hidePicturesForEach( [PIC_ILLUST, PIC_COVER, PIC_BAR] )
                        @label.jump "startStage"
                    }
                }
            }

            //----------------------------
            //パンツを消す
            @if pantyTimer > 0 bl {
                pantyTimer -= 1
                @if pantyTimer <= 0 bl {
                    @pic.move[PIC_PANTY] .trans(100) 
                }
            }

            //----------------------------
            //エクステンド判定
            @if score >= nextExtend bl {
                //次のノルマ
                nextExtend = (score / SCORE_EXTEND + 1) * SCORE_EXTEND
                //残機が最大の場合は効果音も鳴らない
                @if remain < REMAIN_MAX bl {
                    _addRemain(1)
                    @se.play "Item1" .opt(80, 150, 50)
                }
            }

            //----------------------------
            //フラグ消化
            @if `triggerFlg bl {
                //----------------------------
                //自キャラのピクチャを更新する
                @if `triggerFlg & TR_BIT_MYCHARA bl {
                    bitOff(triggerFlg, TR_BIT_MYCHARA)
                    //ピクチャを更新する
                    cell = plCell
                    V2_set(ax, REF_X + plCurX, REF_Y + TILE_WIDTH / 2 + plCurY)
                    @pic.show[PIC_PLAYER] .pos(ax, ay) .cell(cell) charaPicCmd
                }

                //----------------------------
                //ワープポイントのピクチャを更新する
                @if `triggerFlg & TR_BIT_WARP bl {
                    bitOff(triggerFlg, TR_BIT_WARP)
                    //ピクチャを更新する
                    V2_set(ax, REF_X + warpX, REF_Y + TILE_WIDTH / 2 + warpY)
                    @pic.move[PIC_WARP] .pos(ax, ay) .bottom
                }

                //----------------------------
                //お邪魔キャラのピクチャを更新する
                @if `triggerFlg & TR_BIT_ENEMY bl {
                    bitOff(triggerFlg, TR_BIT_ENEMY)
                    @loop EN_NUM .dst(idx) bl {
                        _getEnemyPointer(ele, idx)
                        @if `mType != EN_TYPE_NONE bl {
                            pid = PIC_ENEMY + idx
                            cell = mCell

                            V2_set(ax, REF_X + mCurX, REF_Y + TILE_WIDTH / 2 + mCurY)
                            @pic.show[pid] .pos(ax, ay) .cell(cell) charaPicCmd
                        }
                    }
                }

                //----------------------------
                //パワーエサの取得状態を表示する
                @if `triggerFlg & TR_BIT_POWER bl {
                    bitOff(triggerFlg, TR_BIT_POWER)

                    cell = 1 + warpPower
                    @pic.show[PIC_POWER] .pos(POWER_X, POWER_Y) .topLeft .cell(cell) powerPicCmd
                }

                //----------------------------
                //残機表示を更新
                @if `triggerFlg & TR_BIT_REMAIN bl {
                    bitOff(triggerFlg, TR_BIT_REMAIN)

                    cell = 1 + remain
                    @pic.show[PIC_REMAIN] .pos(REMAIN_X, REMAIN_Y) .cell(cell) remainPicCmd
                }

                //----------------------------
                //スコア表示を更新
                @if `triggerFlg & TR_BIT_SCORE bl {
                    bitOff(triggerFlg, TR_BIT_SCORE)
                    _updateScorePicture(score, PIC_SCORE, SCORE_X, SCORE_Y)
                }

                //----------------------------
                //ハイスコア表示を更新
                @if `triggerFlg & TR_BIT_HISCORE bl {
                    bitOff(triggerFlg, TR_BIT_HISCORE)
                    _updateScorePicture(pankuManScore, PIC_HISCORE, HISCORE_X, HISCORE_Y)
                }
            }
        }
    }

    //------------------------------------------------------------------------------------
    //終了する
    @label.set "gameEnd"
    bl {
        _updateHighScore()

        initPicturesAndVariables(PIC_HEAD, NUM_OF_PIC, TV_MINIGAME, NUM_OF_VAR, 0, 0)
        restoreBGM()
        fastFadeInTintOnly(1)
    }
}