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


cev[CEV_KIMETU_NO_YAIBA] .name("mg_木滅の刃") {

    def {
        NUM_OF_VAR = 128
        NUM_OF_STR = 0
        NUM_OF_PIC = 40

        BASE_LAYER = 6

        PATH_BACK     = "ky\ba"
        PATH_FRAME    = "ky\fr"
        PATH_LOGO     = "ky\lo"
        PATH_LIFE     = "ky\li"
        PATH_CHARA    = "ky\ch"
        PATH_TREE     = "ky\tr"
        PATH_COUNT    = "ky\co"

        PIC_HEAD     = 1
        PIC_BACK     = 2
        PIC_TREE     = 3//+0_3
        PIC_CHAR     = 7//+0_7
        PIC_PLAYER   = 15
        PIC_LIFE     = 16
        PIC_CHANCE   = 17
        PIC_ADDSCORE = 18//+0_+4
        PIC_SCORE    = 23//+0_+4
        PIC_HISCORE  = 28//+0_+4
        PIC_STAGE    = 33//+0_+1
        PIC_LOGO     = 35
        PIC_FRAME    = 36

        //トリガー
        TR_BIT_ERASE   = 1 << 0
        TR_BIT_PLAYER  = 1 << 1
        TR_BIT_SCORE   = 1 << 2
        TR_BIT_HISCORE = 1 << 3
        TR_BIT_CHANCE  = 1 << 4
        TR_BIT_LIFE    = 1 << 5
        TR_BIT_STAGE   = 1 << 6

        //実績
        KY_ACHIEVE_COUNT = 7000

        //シーン
        SCENE_MOVE = 0
        SCENE_RETRY
        SCENE_CREATE_LEVEL
        SCENE_DEFEAT
        SCENE_CLEAR
        SCENE_EXTEND
        SCENE_GAMEOVER

        //プレイヤー
        PLAYER_STATE_MOVE = 0
        PLAYER_STATE_ATTACK
        PLAYER_STATE_DAMAGE

        //木
        TREE_NUM = 4
        TREE_LIFE = 7
        TREE_BODY_WIDTH = 10
        TREE_ATK_WIDTH = 128

        MT_STATE = 0
        MT_TIMER
        MT_DIR
        MT_LEFT
        MT_RIGHT
        MT_X
        SIZE_OF_TREE

        TR_STATE_NONE = 0
        TR_STATE_DELETE
        TR_STATE_STAND
        TR_STATE_DAMAGE
        TR_STATE_FELL

        mTrState = v[ptr + MT_STATE]
        mTrTimer = v[ptr + MT_TIMER]
        mTrDir   = v[ptr + MT_DIR]
        mTrLeft  = v[ptr + MT_LEFT]
        mTrRight = v[ptr + MT_RIGHT]
        mTrX     = v[ptr + MT_X]

        //キャラ
        CHAR_NUM = 7

        MC_STATE = 0
        MC_TIMER
        MC_DIR
        MC_TYPE
        MC_HIT
        MC_X
        MC_Y
        SIZE_OF_CHAR

        CH_STATE_NONE = 0
        CH_STATE_DELETE
        CH_STATE_MOVE
        CH_STATE_DAMAGE

        CH_TYPE_NONE = 0
        CH_TYPE_BOAR
        CH_TYPE_SNAKE
        CH_TYPE_BIRD
        CH_TYPE_BOMB
        CH_TYPE_BRANCH

        mChState = v[ptr + MC_STATE]
        mChTimer = v[ptr + MC_TIMER]
        mChDir   = v[ptr + MC_DIR]
        mChType  = v[ptr + MC_TYPE]
        mChHit   = v[ptr + MC_HIT]
        mChX     = v[ptr + MC_X]
        mChY     = v[ptr + MC_Y]

        mChState2 = v[ptr2 + MC_STATE]
        mChTimer2 = v[ptr2 + MC_TIMER]
        mChDir2   = v[ptr2 + MC_DIR]
        mChType2  = v[ptr2 + MC_TYPE]
        mChHit2   = v[ptr2 + MC_HIT]
        mChX2     = v[ptr2 + MC_X]
        mChY2     = v[ptr2 + MC_Y]

        //スコア
        SCORE_TREE_FELL = 100
        SCORE_TREE_DAMAGE = 10
        SCORE_CHAR = 20
        SCORE_EASTER = 80

        //定数
        OUT_RANGE = -320

        REF_X = 8
        REF_Y = 16

        FIELD_WIDTH = 240
        COUNTER_WIDTH = 16
        GROUND_Y = 160
        STAGE_EXTEND = 4
        BRANCH_EST = 15
        TIME_LIMIT = 60

        SCORE_X = 232
        SCORE_Y = 32
        SCORE_DIGIT = 5
        SCORE_MAX = 99999

        HISCORE_X  = 232
        HISCORE_Y  = 8

        ADDSCORE_X = 144
        ADDSCORE_Y = 16

        STAGE_X = 48
        STAGE_Y = 16
        STAGE_DIGIT = 2

        CHANCE_X = 0
        CHANCE_Y = 208
        CHANCE_MAX = 4
        CHANCE_DEFAULT = 3

        LIFE_X = 0
        LIFE_Y = 192

        PLAYER_LIFE = 2
        PLAYER_SPEED = 1
        PLAYER_ATK_FRAME  = 16
        PLAYER_ATK_LENGTH = 22
        PLAYER_DMG_TIME = 60
        PLAYER_WIDTH = 24
    }

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

        countPicCmd = {
            PATH_COUNT
            .grid(10, 1)
            basePicCmd
        }

        lifePicCmd = {
            PATH_LIFE
            .grid(1, 10)
            basePicCmd
        }

        logoPicCmd = {
            PATH_LOGO
            .grid(1, 2)
            basePicCmd
        }

        charaPicCmd = {
            PATH_CHARA
            .grid(4, 7)
            basePicCmd
        }

        treePicCmd = {
            PATH_TREE
            .grid(2, 1)
            basePicCmd
        }
    }

    defv {
        varHead = TV_MINIGAME
        
        ipt
        pid
        cell
        idx
        ptr
        idx2
        ptr2
        state
        timer
        type
        dir
        hit
        flag
        ix
        iy
        sx
        sy
        ftA
        ftB

        initHead

        triggerFlg
        sceneState
        sceneTimer

        score
        addScore
        addScoreTimer
        stageClear
        charNum
        
        geneTimer
        geneFreq

        plState
        plTimer
        plDir
        plCell
        plLife
        plChance
        plX
        plY

        treeCnt
        treeTimer

        treeHead
        charHead  = __id(treeHead) + (SIZE_OF_TREE * TREE_NUM)
        varFoot = __id(charHead) + (SIZE_OF_CHAR * CHAR_NUM)
    }

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

    //フレーズ
    //樹木とジェダイ(樹大)とかシスとポリノシスを掛けているが、遠すぎる
    //帝国のマーチ1
    $SE_RETRY_LENGTH = 19
    $SE_RETRY = [ F_C6, 0, 0, F_C6, 0, 0, F_C6, 0, 0, F_C6S, 0, F_A5S, F_F5S, 0, 0, F_D5S, 0, F_A5S, F_G5, 0][ idx ]
    //与作
    //$SE_RETRY_LENGTH = 8
    //$SE_RETRY = [F_F5, F_F5, F_D5, 0, F_E5, F_E5, F_C5, 0, 0][ idx ]

    //帝国のマーチ2
    $SE_CLEAR_LENGTH = 19
    $SE_CLEAR = [ F_G5, 0, 0, F_G5, 0, 0, F_G5, 0, 0, F_D5S, 0, F_A5S, F_G5, 0, 0, F_D5S, 0, F_A5S, F_G5, 0][ idx ]

    //トッカータとフーガ
    $SE_GAMEOVER_LENGTH = 13
    $SE_GAMEOVER = [ F_A5, F_G5, F_A5, 0, 0, F_G5, F_F5, F_E5, F_D5, F_C5S, 0, 0, F_D5, 0][ idx ]


    //数値を表示する
    __fn _showCounter $num $pid $dig $x $y bl {
        iy = 1
        @loop $dig .dst(ix) bl {
            v[__id(sx)..__id(sy)] = [($x) - ix * COUNTER_WIDTH, ($y)]
            pid  = ($pid) + ix
            cell = (($num) < iy && iy != 1) ? (0) : (1 + ($num) % (iy * 10) / iy)
            @pic.show [pid] .pos(sx, sy) .topRight .scale(100) .cell(cell) countPicCmd  
            //次の桁
            iy *= 10
        }
    }

    //プレイヤーの状態を変える
    __fn _setPlayerState $state bl {
        v[__id(plState)..__id(plState) + 1] = [$state, -1]
    }

    //木のポインタを取得する
    __fn _getTreePtr $dvDst $idx bl {
        v[__id($dvDst)] = __id(treeHead) + ($idx) * SIZE_OF_TREE
    }

    //木のメンバ変数を初期化する
    __fn _setTreeMembers $ptr $arr bl {
        v[$ptr..$ptr + SIZE_OF_TREE - 1] = $arr
    }

    //木の状態を変える
    __fn _setTreeState $ptr $state bl {
        v[$ptr + MT_STATE] = $state
        v[$ptr + MT_TIMER] = -1
    }

    //キャラのポインタを取得する
    __fn _getCharPtr $dvDst $idx bl {
        v[__id($dvDst)] = __id(charHead) + ($idx) * SIZE_OF_CHAR
    }

    //キャラのメンバ変数を初期化する
    __fn _setCharMembers $ptr $arr bl {
        v[$ptr..$ptr + SIZE_OF_CHAR - 1] = $arr
    }

    //キャラの状態を変える
    __fn _setCharState $ptr $state bl {
        v[$ptr + MC_STATE] = $state
        v[$ptr + MC_TIMER] = -1
    }

    //指定したタイプのキャラを探し、ポインタ
    //見つからない場合はゼロを返す
    __fn _searchChar $dvDst $type bl {
        v[__id($dvDst)] = 0
        @loop CHAR_NUM .dst(ftA) bl {
            ftB = __id(charHead) + ftA * SIZE_OF_CHAR
            @if `v[ftB + MC_TYPE] == $type bl {
                v[__id($dvDst)] = ftB
                @break
            }
        }
    }

    //スコアを加算する
    __fn _addScore $score bl {
        addScore += $score
    }

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

    //シーンの状態を変える
    __fn _setSceneState $state bl {
        v[__id(sceneState)..__id(sceneTimer)] = [$state, -1]
    }

    //------------------------------------------------------------------------------------
    //開始処理
    bl {
        //変数を初期化
        initPicturesAndVariables(PIC_HEAD, NUM_OF_PIC, TV_MINIGAME, NUM_OF_VAR, TS_MINIGAME, NUM_OF_STR)
        //BGMを停止させる
        storeAndStopBGM()
        //メッセージの表示位置
        msgBottom()
        //ピクチャ
        @pic.show [PIC_FRAME] PATH_FRAME .pos(0, 0) .topLeft basePicCmd
        @pic.show [PIC_BACK] PATH_BACK .pos(REF_X, REF_Y) .topLeft basePicCmd
        @pic.show [PIC_LOGO] .pos(OUT_RANGE, OUT_RANGE) .trans(100) .cell(0) logoPicCmd
        @pic.show [PIC_LIFE] .pos(OUT_RANGE, OUT_RANGE) .trans(100) .cell(0) lifePicCmd
        @pic.show [PIC_CHANCE] .pos(OUT_RANGE, OUT_RANGE) .trans(100) .cell(0) lifePicCmd
        @pic.show [PIC_PLAYER] .pos(OUT_RANGE, OUT_RANGE) .trans(100) .cell(0) charaPicCmd
        //木
        @loop TREE_NUM .dst(idx) bl {
            pid = PIC_TREE + idx
            @pic.show [pid] .pos(OUT_RANGE, OUT_RANGE) .trans(100) .cell(0) treePicCmd
        }
        //暗転
        fastFadeInTintOnly(1)
        @wait(1)
        @label.jump "gameLoop"
    }

    //------------------------------------------------------------------------------------
    //ゲーム処理
    @label.set "gameLoop"
    bl {
        //変数を一括で初期化する
        assignVarUsingDeclared(initHead, varFoot, 0)
        //ステージ開始
        _setSceneState(SCENE_CREATE_LEVEL)
        //ステージクリア数
        stageClear = 0
        //初期残機
        plChance = CHANCE_DEFAULT
        //プレイヤーの初期位置を画面外に設定する
        V2_set(plX, OUT_RANGE, OUT_RANGE)
        //ピクチャを掃除する
        @loop TREE_NUM .dst(pid) bl {
            pid += PIC_TREE
            hidePicture(pid)
        }

        @loop CHAR_NUM .dst(pid) bl {
            pid += PIC_CHAR
            hidePicture(pid)
        }

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

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

            //----------------------------
            //シーン
            //カウントアップ
            sceneTimer += 1

            //----------------------------
            //ゲーム中
            @if sceneState == SCENE_MOVE bl {
                //キャラの発生
                @if `sceneTimer >= 30 bl {
                    geneTimer += 1
                    @if `!(geneTimer % geneFreq) bl {
                        _searchChar(ptr, CH_TYPE_NONE)
                        @if ptr > 0 bl {
                            //タイプを選ぶ
                            type = [ CH_TYPE_BOAR, CH_TYPE_SNAKE, CH_TYPE_BIRD ][ rnd(0, 2) ]
                            //猪
                            @if type == CH_TYPE_BOAR bl {
                                dir = [1, -1][rnd(0, 1)]//向き
                                ix = (dir > 0) ? 0 : FIELD_WIDTH//初期X座標
                                _setCharMembers(ptr, [ CH_STATE_MOVE, -1, dir, CH_TYPE_BOAR, FALSE, ix, GROUND_Y ] )
                            //蛇
                            } .elif type == CH_TYPE_SNAKE bl {
                                //蛇に限り出現タイミングが前倒しになる
                                geneTimer += geneFreq / 2

                                ix = plX
                                _setCharMembers(ptr, [ CH_STATE_MOVE, -1, 1, CH_TYPE_SNAKE, FALSE, ix, 200 ] )
                            //鳥
                            } .elif type == CH_TYPE_BIRD bl {
                                dir = [1, -1][rnd(0, 1)]//向き
                                ix = (dir > 0) ? (0 - 24) : (FIELD_WIDTH + 24)//初期X座標
                                _setCharMembers(ptr, [ CH_STATE_MOVE, -1, dir, CH_TYPE_BIRD, FALSE, ix, 64 ] )
                            }
                        }
                    }
                }

                //木を全て切り倒した
                @if treeCnt <= 0 bl {
                    treeTimer += 1
                    //切り倒してからクリア処理に移るまで少し間がある
                    @if treeTimer >= 60 bl {
                        _setSceneState(SCENE_CLEAR)
                        stageClear += 1
                    }
                }

            //----------------------------
            //残機が減る
            } .elif sceneState == SCENE_DEFEAT bl {
                //最初のフレーム
                @if sceneTimer == 0 bl {
                    bitOn(triggerFlg, TR_BIT_CHANCE)
                    //残機が減る
                    plChance -= 1
                }

                //昇天
                @if `between(sceneTimer, 60, 100) bl {
                    @if sceneTimer == 60 bl {
                        plCell = 7
                        @se.play "bell1" .opt(100, 60, 50)
                    }

                    $SPEED = 6
                    @if `sceneTimer % $SPEED == 0 bl {
                        plY -= 4
                        plX += (sceneTimer % ($SPEED * 2)) ? 2 : -2
                    }
                }

                @if sceneTimer >= 140 bl {
                    //ゲームオーバー
                    @if plChance <= 0 bl {
                        _setSceneState(SCENE_GAMEOVER)
                    //復帰
                    } .else bl {
                        _setSceneState(SCENE_RETRY)
                    }
                }

            //----------------------------
            //ステージ開始
            } .elif sceneState == SCENE_CREATE_LEVEL bl {
                //キャラを消去する
                bitOn(triggerFlg, TR_BIT_ERASE | TR_BIT_PLAYER | TR_BIT_SCORE | TR_BIT_HISCORE | TR_BIT_STAGE | TR_BIT_CHANCE | TR_BIT_LIFE)
                //キャラの発生頻度(f)
                //25ステージほどで最速になる
                geneFreq  = max(320 - stageClear * 8, 120)
                //木の数
                treeCnt = clamp(1 + stageClear % 4, 1, 4)
                treeTimer = 0
                //木を生やす
                @loop TREE_NUM .dst(idx) bl {
                    _getTreePtr(ptr, idx)
                    //有効
                    @if `idx < treeCnt bl {
                        //木の位置
                        sx = [ 120, 0, 0, 0,
                        80, 160, 0, 0,
                        60, 120, 180, 0,
                        48, 96, 144, 192 ][idx + TREE_NUM * (treeCnt - 1)]
                        _setTreeMembers(ptr, [ TR_STATE_STAND, -1, 1, 0, 0, sx ] )

                    //無効
                    } .else bl {
                        _setTreeState(ptr, TR_STATE_DELETE)
                    }
                }

                //ゲーム開始
                _setSceneState(SCENE_RETRY)

            //----------------------------
            //エクステンド
            } .elif sceneState == SCENE_EXTEND bl {
                //増える
                @if sceneTimer == 0 bl {
                    bitOn(triggerFlg, TR_BIT_CHANCE)
                    plChance = clamp(plChance + 1, 0, CHANCE_MAX)
                    @se.play "Item2" .opt(90, 100, 50)
                }

                //次のステージへ
                @if sceneTimer >= 40 bl {
                    _setSceneState(SCENE_CREATE_LEVEL)
                }

            //----------------------------
            //ステージ開始 / ステージクリア / ゲームオーバー
            } .elif `sceneState == SCENE_RETRY ||
                     sceneState == SCENE_CLEAR ||
                     sceneState == SCENE_GAMEOVER bl {
                //キー入力で演出をキャンセルする
                @key.input .dst(ipt) bl {
                    .up
                    .down
                    .right
                    .left
                    .decision
                }
                cell = 0//音階

                //ステージ開始
                @if sceneState == SCENE_RETRY bl {
                    @if sceneTimer == 0 bl {
                        //キャラを発生させるタイマーの初期値
                        geneTimer = geneFreq - 30
                        //キャラを消去する
                        bitOn(triggerFlg, TR_BIT_ERASE | TR_BIT_PLAYER | TR_BIT_SCORE | TR_BIT_HISCORE | TR_BIT_CHANCE | TR_BIT_LIFE)
                        //文字を表示する
                        @pic.show [PIC_LOGO] .pos(REF_X + FIELD_WIDTH / 2, REF_Y + 72) .cell(1) logoPicCmd
                    }

                    //演奏
                    $SPEED = 10
                    @if `between(sceneTimer, 0, $SPEED * $SE_RETRY_LENGTH) && sceneTimer % $SPEED == 0 bl {
                        idx = sceneTimer / $SPEED
                        cell = $SE_RETRY
                    }

                    //ゲーム開始
                    @if `sceneTimer >= 240 || (ipt && sceneTimer >= 30) bl {
                        _setSceneState(SCENE_MOVE)
                        @pic.move [PIC_LOGO] .pos(OUT_RANGE, OUT_RANGE) .trans(100)
                        //重複を防ぐ為、効果音を止める
                        @se.stop
                        @se.play "rect1" .opt(100, F_D6, 50)
                    }

                //ステージクリア
                } .elif sceneState == SCENE_CLEAR bl {
                    //文字を表示する
                    @if sceneTimer == 0 bl {
                        @pic.show [PIC_LOGO] .pos(REF_X + FIELD_WIDTH / 2, REF_Y + 72) .cell(2) logoPicCmd
                    }

                    //演奏
                    $SPEED = 10
                    @if `between(sceneTimer, 0, 0 + $SPEED * $SE_CLEAR_LENGTH) && sceneTimer % $SPEED == 0 bl {
                        idx = sceneTimer / $SPEED
                        cell = $SE_CLEAR
                    }

                    //次のステージへ
                    @if `sceneTimer >= 240 || (ipt && sceneTimer >= 30) bl {
                        //その前にエクステンド
                        @if `!(stageClear % STAGE_EXTEND) && plChance < CHANCE_MAX bl {
                            _setSceneState(SCENE_EXTEND)
                        } .else bl {
                            _setSceneState(SCENE_CREATE_LEVEL)
                        }
                        //文字を隠す
                        @pic.move [PIC_LOGO] .pos(OUT_RANGE, OUT_RANGE) .trans(100)
                    }

                //ゲームオーバー
                } .elif sceneState == SCENE_GAMEOVER bl {
                    $SPEED = 10
                    @if `between(sceneTimer, 0, 0 + $SPEED * $SE_GAMEOVER_LENGTH) && sceneTimer % $SPEED == 0 bl {
                        idx = (sceneTimer - 0) / $SPEED
                        cell = $SE_GAMEOVER
                    }

                    //ゲーム終了
                    @if `sceneTimer >= 180 || (ipt && sceneTimer >= 30) bl {
                        //ハイスコアの更新判定
                        _updateHighScore()
                        //もう一度遊ぶ？
                        replayProcess("gameLoop", "gameEnd")
                    }
                }

                //矩形波
                @if cell > 0 bl {
                    @se.play "rect1" .opt(100, cell, 50)
                }
            }

            //----------------------------
            //プレイヤーを更新する
            //操作
            @if sceneState == SCENE_MOVE bl {
                //入力を取得する
                sx = 0
                @key.input .dst(ipt) .left
                sx -= ipt ? 1 : 0
                @key.input .dst(ipt) .right
                sx += ipt ? 1 : 0
                @key.input .dst(ipt) bl {
                    .decision
                    .up
                    .down
                }
                sy = ipt ? TRUE : FALSE
                //攻撃動作へ移行
                @if `plState == PLAYER_STATE_MOVE && sy bl {
                    _setPlayerState(PLAYER_STATE_ATTACK)
                }

                //カウンター
                plTimer += 1

                //立ち / 移動
                @if plState == PLAYER_STATE_MOVE bl {
                    //歩き
                    @if `sx bl {
                        //方向転換
                        @if  sx != plDir bl {
                            plTimer = 0
                            plDir = sx
                        }
                        plX += sx * PLAYER_SPEED

                        $SPEED = 6
                        plCell = (plTimer % ($SPEED * 2) < $SPEED) ? 2 : 1

                    //立ち状態
                    } .else bl {
                        plTimer = -1
                        plCell = 1
                    }

                    //ダメージ
                    //@key.input .dst(ipt) .shift
                    //@if `ipt bl {
                    //    _setPlayerState(PLAYER_STATE_DAMAGE)
                    //}

                //攻撃
                } .elif plState == PLAYER_STATE_ATTACK bl {
                    //ヒットフラグ
                    hit = FALSE
                    //攻撃判定
                    @if plTimer == 0 bl {
                        plCell = 5
                        //木への攻撃
                        @loop TREE_NUM .dst(idx) bl {
                            _getTreePtr(ptr, idx)
                            //通常状態のみ
                            state = mTrState
                            @if `state != TR_STATE_STAND bl {
                                @continue
                            }

                            //衝突判定
                            sx = abs(plX + plDir * PLAYER_ATK_LENGTH - mTrX)
                            @if `sx <= TREE_BODY_WIDTH / 2 bl {
                                hit = TRUE
                                //プレイヤーの向きによって変数位置が変わる
                                //カウンタのポインタ
                                sx = ((plDir > 0) ? (MT_LEFT) : MT_RIGHT) + ptr
                                v[sx] += 1
                                //左右カウンタ
                                ix = mTrLeft
                                iy = mTrRight
                                //左右の合計値が一定以上が、左右どちらかに極端に偏ったときに倒れる
                                @if `ix + iy >= TREE_LIFE || max(ix, iy) >= TREE_LIFE - 1 bl {
                                    //スコア
                                    _addScore(SCORE_TREE_FELL)
                                    //倒れる
                                    _setTreeState(ptr, TR_STATE_FELL)
                                    //多く切った方向に向き直す
                                    mTrDir = (ix > iy) ? -1 : 1
                                    @se.play "bat1" .opt(100, 120, 50)

                                //通常ダメージ
                                } .else bl {
                                    //スコア
                                    _addScore(SCORE_TREE_DAMAGE)
                                    //ダメージモーション
                                    _setTreeState(ptr, TR_STATE_DAMAGE)
                                    //プレイヤーの向きに合わせる
                                    mTrDir = plDir
                                    //打ち付ける回数によって周波数が変わる
                                    sy = (v[sx] % 2) ? 100 : 80
                                    @se.play "bat1" .opt(100, sy, 50)
                                }
                            }
                        }

                        //キャラへの攻撃
                        @loop CHAR_NUM .dst(idx) bl {
                            _getCharPtr(ptr, idx)
                            //タイプが有効である場合のみ
                            type = mChType
                            state = mChState
                            @if type == CH_TYPE_NONE bl {
                                @continue
                            }
                            //フラグ
                            flag = FALSE
                            //判定距離
                            V2_set(sx,
                                abs(plX + plDir * PLAYER_ATK_LENGTH - mChX),
                                abs(plY - mChY)
                            ) 
                            //判定の大きさはキャラクター共通
                            @if `state == CH_STATE_MOVE && sx <= 12 && sy <= 12 bl {
                                flag = TRUE
                            }
                            //当たった
                            @if `flag bl {
                                @se.play "Earth7" .opt(100, 120, 50)
                                hit = TRUE
                                _setCharState(ptr, CH_STATE_DAMAGE)
                                //スコア
                                _addScore(SCORE_CHAR)
                            }
                        }

                        //当たらなかったとき、効果音を鳴らす
                        @if `!hit bl {
                            @se.play "Evade2" .opt(80, 90, 50)
                        }
                    }

                    //見た目だけ少し早めに戻る
                    @if plTimer == PLAYER_ATK_FRAME - 4 bl {
                        plCell = 1
                    }

                    //通常状態に戻る
                    @if plTimer >= PLAYER_ATK_FRAME bl {
                        _setPlayerState(PLAYER_STATE_MOVE)
                    }

                //怯み
                } .elif plState == PLAYER_STATE_DAMAGE bl {
                    //無敵モードの時はライフが減らない
                    @if invincibleSwitch.isOn bl {
                        bitOn(triggerFlg, TR_BIT_LIFE)
                        plLife = max(plLife, 1)
                    }

                    //ライフが無い
                    @if plLife <= 0 bl {
                        //ライフ減少
                        @if plTimer == 0 bl {
                            bitOn(triggerFlg, TR_BIT_LIFE)
                            plCell = 4
                            @se.play "Damage2" .opt(100, 100, 50)
                        }

                        //死亡
                        @if `plTimer == 8 bl {
                            _setSceneState(SCENE_DEFEAT)
                            plCell = 6
                            plY += 6//少し埋める
                        }

                    //怯み
                    } .else bl {
                        @if plTimer == 0 bl {
                            bitOn(triggerFlg, TR_BIT_LIFE)
                            @se.play "Damage2" .opt(100, 100, 50)
                        }

                        //解除
                        @if plTimer >= PLAYER_DMG_TIME bl {
                            _setPlayerState(PLAYER_STATE_MOVE)
                        //ダメージモーション
                        } .else bl {
                            $SPEED = 4
                            plCell = (plTimer % ($SPEED * 2) < $SPEED) ? 3 : 4
                        }
                    }
                }
                //位置修正
                plX = clamp(plX, PLAYER_WIDTH / 2, FIELD_WIDTH - PLAYER_WIDTH / 2 )
            }

            //ピクチャ
            //斧が延びている分だけ画像が後退している為、向いている方向に少しずらす
            V2_set(sx,
                REF_X + plX + plDir * 4,
                REF_Y + plY
            )
            @if plDir > 0 bl {
                @pic.show [PIC_PLAYER] .pos(sx, sy) .bottom .cell(plCell) charaPicCmd
            } .else bl {
                @pic.show [PIC_PLAYER] .pos(sx, sy) .bottom .cell(plCell) .hrev charaPicCmd
            }

            //----------------------------
            //木を更新する
            @loop TREE_NUM .dst(idx) bl {
                _getTreePtr(ptr, idx)
                //なし
                @if `mTrState == TR_STATE_NONE bl {
                    @continue
                }
                //タイマー
                mTrTimer += 1
                //一時変数
                state = mTrState
                timer = mTrTimer
                dir = mTrDir
                type = FALSE//発光フラグ
                //基本位置
                V2_set(sx,
                    REF_X + mTrX,
                    REF_Y + GROUND_Y
                )
                //基本ピクチャID
                pid = PIC_TREE + idx
                //セル番号(0以上で更新する)
                cell = -1
                //消去する
                @if state == TR_STATE_DELETE bl {
                    _setTreeState(ptr, TR_STATE_NONE)
                    cell = 0
                    V2_set(sx, OUT_RANGE, OUT_RANGE)

                //立っている
                } .elif state == TR_STATE_STAND bl {
                    //表示する
                    @if timer == 0 bl {
                        cell = 1
                    }

                //ダメージ
                } .elif state == TR_STATE_DAMAGE bl {
                    //揺れる
                    @if timer == 0 bl {
                        cell = 1
                        type = TRUE
                        sx += 2 * dir
                        //向きを固定する
                        mTrDir = 1
                        dir = 1
                        //枝を落とす
                        //キャラの数が5以下の時
                        @if `rnd(0, 99) < BRANCH_EST && charNum <= 5 bl {
                            //未使用の場所を見つける
                            _searchChar(ptr2, CH_TYPE_NONE)
                            @if ptr2 > 0 bl {
                                ix = mTrX + rnd(-32, 32)
                                iy = rnd(80, 100)
                                _setCharMembers(ptr2, [ CH_STATE_MOVE, -1, 1, CH_TYPE_BRANCH, FALSE, ix, iy ] )
                                @se.play "Buzzer3" .opt(90, 90, 50)
                            }
                        }
                    }

                    @if `timer == 4 bl {
                        cell = 1
                    }

                    @if timer >= 8 bl {
                        _setTreeState(ptr, TR_STATE_STAND)
                    }

                //倒れる
                } .elif state == TR_STATE_FELL bl {
                    //めきめき
                    @if timer == 0 bl {
                        cell = 1
                        type = TRUE
                        @se.play "Thunder8" .opt(80, 60, 50)
                    }

                    //揺れる
                    @if `between(timer, 0, 2 * 15) && !(timer % 2) bl {
                        cell = 1
                        type = TRUE
                        sx += (timer % 4) ? (2 * dir) : 0
                    }

                    //倒れる
                    @if timer == 32 bl {
                        //移動させる
                        cell = 2
                        sx += dir * 52
                        //カウンタ
                        treeCnt -= 1
                        //プレイヤーへの攻撃
                        ix = mTrX + dir * 64
                        @if `plLife > 0 && abs(ix - plX) <= TREE_ATK_WIDTH / 2 bl {
                            _setPlayerState(PLAYER_STATE_DAMAGE)
                            plLife -= 2
                        }
                        @se.play "Earth5" .opt(100, 100, 50)
                    }
                }

                //ピクチャを更新する
                @if cell >= 0 bl {
                    //発光するが、向きは無視される
                    @if `type bl {
                        @pic.show [pid] .pos(sx, sy) .bottom .cell(cell) .rgbs(150, 75, 75, 100) treePicCmd
                    //通常
                    } .elif dir > 0 bl {
                        @pic.show [pid] .pos(sx, sy) .bottom .cell(cell) treePicCmd
                    //横反転
                    } .else bl {
                        @pic.show [pid] .pos(sx, sy) .bottom .cell(cell) .hrev treePicCmd
                    }
                }
            }

            //----------------------------
            //キャラの数を数える
            charNum = 0
            @loop CHAR_NUM .dst(idx) bl {
                _getCharPtr(ptr, idx)
                @if `mChType != CH_TYPE_NONE bl {
                    charNum += 1
                }
            }

            //キャラを更新する
            @loop CHAR_NUM .dst(idx) bl {
                _getCharPtr(ptr, idx)
                //なし
                @if `mChType == CH_TYPE_NONE bl {
                    @continue
                }
                //タイマー
                mChTimer += 1
                //一時変数
                state = mChState
                timer = mChTimer
                type = mChType
                dir = mChDir
                hit = mChHit
                pid = PIC_CHAR + idx
                cell = -1
                //基本位置
                V2_set(sx,
                    REF_X + mChX,
                    REF_Y + mChY
                )
                //----------------------------
                //共通処理:消去
                @if state == CH_STATE_DELETE bl {
                    _setCharState(ptr, CH_STATE_NONE)
                    mChType = CH_TYPE_NONE
                    cell = 0
                    V2_set(sx, OUT_RANGE, OUT_RANGE)

                //タイプによって分岐する
                //ゲーム中のみ更新する
                } .elif sceneState == SCENE_MOVE bl {
                    //----------------------------
                    //猪
                    @if type == CH_TYPE_BOAR bl {
                        //突進
                        @if state == CH_STATE_MOVE bl {
                            //登場
                            @if timer == 0 bl {
                                cell = 13
                                @se.play "Attack1" .opt(80, 120, 50)
                            //突進
                            } .elif timer >= 40 bl {
                                //足音
                                @if `!(timer % 12) bl {
                                    @se.play "Earth3" .opt(90, 120, 50)
                                }
                                //アニメーション
                                cell = (timer % (12 * 2) < 12) ? 14 : 13
                                //移動
                                mChX += dir * 1
                                sx += dir * 1
                                //攻撃判定
                                @if `!hit && abs(plX - mChX) <= 24 && abs(plY - mChY) <= 6 bl {
                                    mChHit = TRUE
                                    _setPlayerState(PLAYER_STATE_DAMAGE)
                                    plLife -= 1
                                }
                            }

                            //画面外にはみ出た
                            @if `!between(mChX, 0 - 16, FIELD_WIDTH + 16) bl {
                                _setCharState(ptr, CH_STATE_DELETE)
                                cell = 0
                            }

                        //攻撃を受けた
                        } .elif state == CH_STATE_DAMAGE bl {
                            //アニメーション
                            cell = (timer % 4 < 2) ? 15 : 16
                            //消滅
                            @if timer >= 60 bl {
                                _setCharState(ptr, CH_STATE_DELETE)
                            }
                        }

                    //----------------------------
                    //蛇
                    } .elif type == CH_TYPE_SNAKE bl {
                        //表示位置を下にずらす
                        sy += 38
                        //上昇下降
                        @if state == CH_STATE_MOVE bl {
                            //登場
                            @if timer == 0 bl {
                                @se.play "Ensnare" .opt(90, 150, 50)
                            }

                            //時間経過で消える
                            @if timer > 240 bl {
                                _setCharState(ptr, CH_STATE_DELETE)
                            }

                            //アニメーション
                            cell = (timer % (12 * 2) < 12) ? 18 : 17
                            @if `!(timer % 2) bl {
                                //上昇
                                @if timer <= 90 bl {
                                    iy = -1
                                //下降
                                } .elif timer >= 140 bl {
                                    iy = 1
                                //停止
                                } .else bl {
                                    iy = 0
                                }
                                mChY += iy
                                sy += iy
                            }

                            //攻撃判定
                            @if `!hit && abs(plX - mChX) <= 16 && abs(plY - mChY) <= 6 bl {
                                mChHit = TRUE
                                _setPlayerState(PLAYER_STATE_DAMAGE)
                                plLife -= 1
                            }

                        //攻撃を受けた
                        } .elif state == CH_STATE_DAMAGE bl {
                            //アニメーション
                            cell = (timer % 4 < 2) ? 19 : 20
                            //消滅
                            @if timer >= 60 bl {
                                _setCharState(ptr, CH_STATE_DELETE)
                            }
                        }

                    //----------------------------
                    //鳥
                    //mChHitは投下数として使う
                    } .elif type == CH_TYPE_BIRD bl {
                        //最初に画面端まで移動し、戻ってくる際に落とす
                        @if state == CH_STATE_MOVE bl {
                            //登場
                            @if timer == 0 bl {
                                @se.play "Wind3" .opt(90, 100, 50)
                            }

                            //消滅
                            @if timer >= 260 bl {
                                _setCharState(ptr, CH_STATE_DELETE)
                            }

                            //反転して少し下降する
                            @if `between(timer, 130, 140) bl {
                                //反転
                                @if timer == 130 bl {
                                    dir *= -1
                                    mChDir = dir
                                }
                                
                                mChY += 2
                                sy += 2
                            }
                            //アニメーション
                            cell = (timer % (12 * 2) < 12) ? 21 : 22
                            //移動
                            mChX += dir * 2
                            sx += dir * 2

                            //反転後でかつ、プレイヤーに近い時、ビーダマを投下する
                            //数は2つまでで、キャラの数が5以下の時
                            //タイミングはシーン用のタイマーでずらす
                            @if `timer >= 130 && !(sceneTimer % 24) bl {
                                V2_set(ix,
                                    mChX,
                                    mChY
                                )
                                @if `abs(ix - plX) <= 48 && hit < 2 && charNum <= 5 bl {
                                    _searchChar(ptr2, CH_TYPE_NONE)
                                    @if ptr2 > 0 bl {
                                        _setCharMembers(ptr2, [ CH_STATE_MOVE, -1, 1, CH_TYPE_BOMB, FALSE, ix, iy + 20 ] )
                                        //投下数
                                        mChHit += 1
                                        @se.play "pon" .opt(70, 140, 50)
                                    }
                                }
                            }

                        //攻撃を受けた
                        } .elif state == CH_STATE_DAMAGE bl {
                            //アニメーション
                            cell = (timer % 8 < 4) ? 23 : 24
                            //消滅
                            @if timer >= 80 bl {
                                _setCharState(ptr, CH_STATE_DELETE)
                            }
                        }

                    //----------------------------
                    //落とし物
                    } .elif type == CH_TYPE_BOMB bl {
                        //下降
                        @if state == CH_STATE_MOVE bl {
                            //下降しきると消える
                            @if `mChY - 20 >= GROUND_Y bl {
                                _setCharState(ptr, CH_STATE_DELETE)
                            }
                            //アニメーション
                            cell = (timer % (12 * 2) < 12) ? 11 : 12
                            //下降
                            mChY += 1
                            sy += 1
                            //攻撃判定
                            @if `!hit && abs(plX - mChX) <= 16 && abs(plY - mChY) <= 20 bl {
                                mChHit = TRUE
                                _setPlayerState(PLAYER_STATE_DAMAGE)
                                plLife -= 1
                            }
                        //攻撃を受けた
                        } .elif state == CH_STATE_DAMAGE bl {
                            //向きをプレイヤーに合わせる
                            @if timer == 0 bl {
                                dir = plDir
                                mChDir = dir
                            }
                            cell = 11
                            //吹っ飛ぶ
                            mChX += dir * 8
                            mChY -= 4
                            sx += dir * 8
                            sy -= 4
                            //衝突判定
                            @loop CHAR_NUM .dst(idx2) bl {
                                _getCharPtr(ptr2, idx2)
                                @if `mChType2 == CH_TYPE_BIRD && mChState2 == CH_STATE_MOVE bl {
                                    @if `abs(mChX - mChX2) <= 24 && abs(mChY - mChY2) <= 24 bl {
                                        _setCharState(ptr2, CH_STATE_DAMAGE)
                                        _setCharState(ptr, CH_STATE_DELETE)
                                        _addScore(SCORE_EASTER)
                                        @se.play "Slash8" .opt(90, 100, 50)
                                    }
                                }
                            }
                            //消滅
                            @if timer >= 30 bl {
                                _setCharState(ptr, CH_STATE_DELETE)
                            }
                        }

                    //----------------------------
                    //枝
                    } .elif type == CH_TYPE_BRANCH bl {
                        //下降
                        @if state == CH_STATE_MOVE bl {
                            //下降しきると消える
                            @if `mChY - 20 >= GROUND_Y bl {
                                _setCharState(ptr, CH_STATE_DELETE)
                            }
                            //アニメーション
                            cell = (timer % (12 * 2) < 12) ? 26 : 25
                            //下降
                            @if `!(timer % 2) bl {
                                mChY += 1
                                sy += 1
                            }
                            //攻撃判定
                            @if `!hit && abs(plX - mChX) <= 20 && abs(plY - mChY) <= 20 bl {
                                mChHit = TRUE
                                _setPlayerState(PLAYER_STATE_DAMAGE)
                                plLife -= 1
                            }

                        //攻撃を受けた
                        } .elif state == CH_STATE_DAMAGE bl {
                            //アニメーション
                            cell = (timer % 4 < 2) ? 27 : 28
                            //消滅
                            @if timer >= 60 bl {
                                _setCharState(ptr, CH_STATE_DELETE)
                            }
                        }
                    }
                }

                //ピクチャ
                @if cell >= 0 bl {
                    @if dir > 0 bl {
                        @pic.show [pid] .pos(sx, sy) .bottom .cell(cell) charaPicCmd
                    } .else bl {
                        @pic.show [pid] .pos(sx, sy) .bottom .cell(cell) .hrev charaPicCmd
                    }
                }
            }

            //----------------------------
            //スコア追加
            @if addScoreTimer > 0 bl {
                addScoreTimer -= 1
                @if addScoreTimer <= 0 bl {
                    @loop SCORE_DIGIT .dst(pid) bl {
                        pid += PIC_ADDSCORE
                        @pic.move [pid] .trans(100) 
                    }
                }
            }
            
            @if addScore > 0 bl {
                //60秒経つとスコアが入らなくなる
                @if `sceneTimer >= UNIT_FPS * TIME_LIMIT bl {
                    addScore = 0
                } .else bl {
                    bitOn(triggerFlg, TR_BIT_SCORE)
                    //少し上下する
                    _showCounter(addScore, PIC_ADDSCORE, SCORE_DIGIT, ADDSCORE_X + REF_X,ADDSCORE_Y + REF_Y + 8)
                    @loop SCORE_DIGIT .dst(pid) bl {
                        pid += PIC_ADDSCORE
                        @pic.move [pid] .relative .pos(0, -8) .time(4)
                    }
                    //スコア加算
                    score = clamp(score + addScore, 0, SCORE_MAX)
                    addScore = 0
                    //一秒程表示する
                    addScoreTimer = 80
                    //実績
                    checkSetAchievement(achievedKimetu, score >= KY_ACHIEVE_COUNT)
                }
            }

            //----------------------------
            //トリガー
            @if `triggerFlg bl {
                //キャラクタを消去する
                @if `triggerFlg & TR_BIT_ERASE bl {
                    bitOff(triggerFlg, TR_BIT_ERASE)
                    charNum = 0
                    @loop CHAR_NUM .dst(idx) bl {
                        _getCharPtr(ptr, idx)
                        state = mChState
                        @if state != CH_STATE_NONE bl {
                            _setCharState(ptr, CH_STATE_DELETE)
                        }
                    }
                }

                //プレイヤーの初期化
                @if `triggerFlg & TR_BIT_PLAYER bl {
                    bitOff(triggerFlg, TR_BIT_PLAYER)
                    //プレイヤー
                    _setPlayerState(PLAYER_STATE_MOVE)
                    plDir = 1
                    plCell = 1
                    plLife = PLAYER_LIFE
                    V2_set(plX, FIELD_WIDTH / 2, GROUND_Y)
                }

                //スコア
                @if `triggerFlg & TR_BIT_SCORE bl {
                    bitOff(triggerFlg, TR_BIT_SCORE)
                    _showCounter(score, PIC_SCORE, SCORE_DIGIT, SCORE_X + REF_X, SCORE_Y + REF_Y)
                }

                //ハイスコア
                @if `triggerFlg & TR_BIT_HISCORE bl {
                    bitOff(triggerFlg, TR_BIT_HISCORE)
                    _showCounter(kimetuNoYaibaScore, PIC_HISCORE, SCORE_DIGIT, HISCORE_X + REF_X, HISCORE_Y + REF_Y)
                }

                //ステージ数
                @if `triggerFlg & TR_BIT_STAGE bl {
                    bitOff(triggerFlg, TR_BIT_STAGE)
                    flag = stageClear + 1
                    _showCounter(flag, PIC_STAGE, STAGE_DIGIT, STAGE_X + REF_X, STAGE_Y + REF_Y)
                }


                //ダークアーディスの残りの数
                @if `triggerFlg & TR_BIT_CHANCE bl {
                    bitOff(triggerFlg, TR_BIT_CHANCE)
                    cell = clamp(plChance, 0, 4) + 1
                    @pic.show [PIC_CHANCE] .pos(CHANCE_X + REF_X, CHANCE_Y + REF_Y) .bottomLeft .cell(cell) lifePicCmd
                }

                //ダークアーディスの体力
                @if `triggerFlg & TR_BIT_LIFE bl {
                    bitOff(triggerFlg, TR_BIT_LIFE)
                    cell = clamp(plLife, 0, 2) + 6
                    @pic.show [PIC_LIFE] .pos(LIFE_X + REF_X, LIFE_Y + REF_Y) .bottomLeft .cell(cell) lifePicCmd
                }
            }
        }
    }

    //------------------------------------------------------------------------------------
    //終了する
    @label.set "gameEnd"
    bl {
        //ハイスコアを更新する
        _updateHighScore()

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