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


cev[CEV_ENNORYU] .name("mg_炎の龍") {

    def {
        NUM_OF_VAR = 64
        NUM_OF_STR = 0
        NUM_OF_PIC = 16

        BASE_LAYER = 6

        PATH_FRAME  = "er\fr"
        PATH_BACK   = "er\ba"
        PATH_SELECT = "er\se"
        PATH_LIFE   = "er\li"
        PATH_TEXT   = "er\te"
        PATH_UNDER  = "er\un"
        PATH_INFO   = "er\if"
        PATH_KO     = "er\ko"
        PATH_CHARA  = "er\ch0"

        PIC_HEAD = 1
        PIC_BACK
        PIC_SELECT
        PIC_UNDER
        PIC_KO
        PIC_CHAR_1P
        PIC_CHAR_2P
        PIC_LIFE_1P
        PIC_LIFE_2P
        PIC_INFO
        PIC_TEXT
        PIC_FRAME
        PIC_DEBUG

        //その他定数
        ER_ACHIEVE_COUNT = 5

        SCREEN_WIDTH  = 160
        SCREEN_HEIGHT = 128
        SCREEN_REF_X = 80
        SCREEN_REF_Y = 48
        CHAR_WIDTH = 12
        TEXT_GRID = 3
        MAX_LIFE = 100
        WEAK_MOVE = 4
        STRONG_MOVE = 16
        ATTACK_RANGE = 42
        ATTACK_HIT = 15
        ATTACK_GUARD = 5
        
        //ゲームモード
        MODE_1P_VS_CPU = 0
        MODE_CTRL_VS_2P
        MODE_1P_VS_2P
        MODE_CTRL_VS_CPU
        MODE_END
        MODE_NUM

        //キャラクターの状態
        STATE_STAND = 0
        STATE_STEP
        STATE_WIN
        STATE_LOSE
        STATE_GUARD
        STATE_DAMAGE
        STATE_FRONT
        STATE_BACK
        STATE_WEAK1
        STATE_WEAK2
        STATE_WEAK3
        STATE_WEAK4
        STATE_STRONG1
        STATE_STRONG2
        STATE_STRONG3
        STATE_STRONG4

        //ゲームの状態
        SCENE_STATE_START = 0
        SCENE_STATE_BATTLE
        SCENE_STATE_KO
        SCENE_STATE_SELECT

        //操作タイプ
        CTRL_TYPE_PLAYER = -1
        CTRL_TYPE_SIMPLE = 0
        CTRL_TYPE_FEINT
        CTRL_TYPE_WEAK
        CTRL_TYPE_STRONG
        CTRL_NUM

        //キャラクターデータの構造
        MC_CTRL_TYPE = 0
        MC_CTRL_STATE
        MC_CTRL_TIMER
        MC_STATE
        MC_STATE_TIMER
        MC_LIFE
        MC_X
        MC_L
        MC_R
        MC_A

        //CPU操作用のビットフラグ
        CTRL_NEUTRAL      = 0x000
        CTRL_WAIT         = 0x002
        CTRL_FRONT        = 0x004
        CTRL_BACK         = 0x008
        CTRL_WEAK         = 0x010
        CTRL_STRONG       = 0x020
        CTRL_STEP         = 0x040
        CTRL_FRONT_STEP   = 0x080
        CTRL_BACK_STEP    = 0x100
        CTRL_WEAK_FRONT   = (CTRL_WEAK | CTRL_STEP | CTRL_FRONT_STEP)
        CTRL_WEAK_BACK    = (CTRL_WEAK | CTRL_STEP | CTRL_BACK_STEP)
        CTRL_STRONG_FRONT = (CTRL_STRONG | CTRL_STEP | CTRL_FRONT_STEP)
        CTRL_STRONG_BACK  = (CTRL_STRONG | CTRL_STEP | CTRL_BACK_STEP)

        //反復処理の内で使用する変数を定義する
        ePic     = PIC_CHAR_1P + idx
        eBar     = PIC_LIFE_1P + idx
        mCtrl    = v[MC_CTRL_TYPE + ele]
        mCtState = v[MC_CTRL_STATE + ele]
        mCtTimer = v[MC_CTRL_TIMER + ele]
        mState   = v[MC_STATE + ele]
        mStTimer = v[MC_STATE_TIMER + ele]
        mLife    = v[MC_LIFE + ele]
        mPos     = v[MC_X + ele]
        mInputB  = v[MC_L + ele]
        mInputF  = v[MC_R + ele]
        mInputA  = v[MC_A + ele]

        //入力判定
        enteredLeft   = (ipt == KEY_DECISION || ipt == KEY_DOWN)
        enteredRight  = (ipt == KEY_CANCEL || ipt == KEY_RIGHT)
        enteredAttack = (ipt == KEY_SHIFT || ipt == KEY_LEFT)
        enteredEsc    = (ipt == $KEY_NUM_ESC)
        enableInput   = (scState == SCENE_STATE_BATTLE)//試合中の操作受付
    }

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

    //キー
    $KEY_1P_BACK   = .decision
    $KEY_1P_FRONT  = .cancel
    $KEY_1P_ATTACK = .shift
    $KEY_2P_BACK   = .right
    $KEY_2P_FRONT  = .down
    $KEY_2P_ATTACK = .left
    $KEY_NUM_ESC   = KEY_NUMBER_1

    //ピクチャの共通コマンド
    def {
        basePicCmd = {
            .chromakey(1)
            .mapLayer(BASE_LAYER)
            .eraseWhenTransfer
            .affectedByTint
            .affectedByFlash
            .affectedByShake
        }

        backPicCmd = {
            .topLeft
            .scale(100)
            .trans(0)
            .rgbs(100, 100, 100, 100)
            basePicCmd
        }
        
        readyPicCmd = {
            .topLeft
            .pos(0, 0)
            .scale(100)
            .trans(100)
            .rgbs(100, 100, 100, 100)
            basePicCmd
        }

        textPicCmd = {
            PATH_TEXT
            .topLeft
            .rgbs(100, 100, 100, 100)
            .grid(1, TEXT_GRID)
            basePicCmd
        }

        charaPicCmd = {
            PATH_CHARA
            .bottom
            .rgbs(100, 100, 100, 100)
            .grid(3, 6)
            basePicCmd
        }

        flashPicCmd = {
            .relative
            .pos(0, 0) 
            .scale(0)
        }
    }

    //変数定義
    defv {
        varHead = TV_MINIGAME
        
        ipt
        tm1
        tm2
        tm3
        ax
        ay
        ele
        idx

        cpuRnd//CPU用一時変数
        cpuDist
        cpuEdeg
        cpuMyState
        cpuEnState

        mode
        scState
        scTimer
        hitFlag
        hitStop

        ctrlType1//1P
        ctrlState1
        ctrlTimer1
        state1
        stateTimer1
        life1
        pos1
        iptBack1
        iptFront1
        iptAtk1

        ctrlType2//2P
        ctrlState2
        ctrlTimer2
        state2
        stateTimer2
        life2
        pos2
        iptBack2
        iptFront2
        iptAtk2

        varFoot

    }

    //一時配列を使って状態変数を取得する
    __fn _getStateId $d $idx {
        v[__id($d)] = [ __id(ctrlType1), __id(ctrlType2) ][$idx]
    }

    //処理中のキャラクターの状態を変更する
    __fn _changeCharaState $state $time {
        mState = $state
        mStTimer = $time
    }

    //CPUの行動を予約する
    __fn _setCtrlState $state $timer {
        mCtState = $state
        mCtTimer = $timer
    }

    //場面の状態を変更する
    __fn _changeScene $state {
        scState = $state
        scTimer = -1
    }

    //中央に帯を表示する
    __fn _showText $cell $time {
        @pic.show[PIC_TEXT] .pos(SCREEN_REF_X - SCREEN_WIDTH, SCREEN_REF_Y + 36) .scale(100) .trans(0) .cell($cell) textPicCmd
        @pic.move[PIC_TEXT] .relative .pos(SCREEN_WIDTH, 0) .scale(0) .trans(0) .time($time)
    }

    //背景を移動させる
    //$cellは定数のみ対応
    __fn _slideBackground $cell {
        @pic.move[PIC_BACK] {
            .pos(SCREEN_REF_X, SCREEN_REF_Y - ($cell - 1) * 128) .topLeft
            .scale(100)
            .trans(0)
            .time(2) .wait
        }
    }

    //------------------------------------------------------------------------------------
    //開始処理
    bl {
        initPicturesAndVariables(PIC_HEAD, NUM_OF_PIC, TV_MINIGAME, NUM_OF_VAR, 0, 0)
        storeAndStopBGM()
        msgBottom()
        //背景
        @pic.show[PIC_FRAME] PATH_FRAME .pos(0, 0) backPicCmd
        @pic.show[PIC_BACK]  PATH_BACK   .pos(SCREEN_REF_X, SCREEN_REF_Y) backPicCmd
        //ピクチャを準備する
        @pic.show[PIC_SELECT]  PATH_SELECT readyPicCmd
        @pic.show[PIC_INFO]    PATH_INFO readyPicCmd
        @pic.show[PIC_LIFE_1P] PATH_LIFE readyPicCmd
        @pic.show[PIC_LIFE_2P] PATH_LIFE readyPicCmd
        @pic.show[PIC_KO]      PATH_KO readyPicCmd
        @pic.show[PIC_UNDER]   PATH_UNDER readyPicCmd
        @pic.show[PIC_TEXT]    .pos(0, 0) .scale(100) .trans(100) .cell(1) textPicCmd
        @foreach [PIC_CHAR_1P, PIC_CHAR_2P] .dst(ele) bl {
            @pic.show[ele] .repl(1, idx) .pos(0, 0) .scale(100) .trans(100) .cell(1) charaPicCmd
        }
        //暗転
        fastFadeInTintOnly(1)
        @label.jump "modeSelect"
    }

    //------------------------------------------------------------------------------------
    //タイトル画面
    @label.set "modeSelect"
    bl {
        //変数を初期化する
        ipt = 0
        //背景を移動させる
        _slideBackground(1)
        //選択するまでループする
        @loop bl {
            //カーソルピクチャの位置を更新する
            ax = SCREEN_REF_X + 32
            ay = SCREEN_REF_Y + 64 + 12 * mode
            @pic.move[PIC_SELECT] {
                .topLeft
                .pos(ax, ay) 
                .scale(100)
                .trans(0)
            }
            @wait(0)

            //決定
            @if `ipt == KEY_DECISION || ipt == KEY_CANCEL || enteredEsc bl {
                //決定音
                @se.stop
                @se.play "Decision2" .opt 80, 100, 50
                //カーソル点滅
                @wait(0)
                @loop 4 bl {
                    @foreach [100, -100] .dst(ele) bl {
                        @pic.move[PIC_SELECT] .trans(ele) flashPicCmd
                        @wait .frame(4)
                    }
                }
                @break
            }

            //入力を待つ
            @key.input .wait .dst(ipt) {
                .up
                .down
                .decision
                .cancel
                .number
            }

            //上下入力
            mode += (ipt == KEY_DOWN ? 1 : 0) + (ipt == KEY_UP ? -1 : 0)
            mode = (mode + MODE_NUM) % MODE_NUM

            //終了
            @if `ipt == KEY_CANCEL || enteredEsc bl {
                mode = MODE_END
            }

            //カーソル音
            @se.stop
            @se.play "Cursor1" .opt(80, 100, 50)
        }

        //ピクチャを隠す
        //moveコマンドが重複しないようにする為、ウェイトを挟む
        hidePicture(PIC_SELECT)
        @wait(0)

        //ゲーム終了
        @if mode == MODE_END bl {
            @label.jump "gameEnd"
        //ゲームモード = mode
        } .else bl {
            @label.jump "startBattle"
        }
    }

    //----------------------------
    //試合開始
    @label.set "startBattle"
    bl {
        //背景を移動させる
        _slideBackground(2)
        //ピクチャを設置する
        @pic.move[PIC_INFO] .pos(SCREEN_REF_X, SCREEN_REF_Y) .topLeft .scale(100) .trans(0)
        //CPUの行動パターンを決定する
        ctrlType1 = (mode == MODE_1P_VS_2P || mode == MODE_1P_VS_CPU)  ? CTRL_TYPE_PLAYER : rnd(0, CTRL_NUM - 1)
        ctrlType2 = (mode == MODE_1P_VS_2P || mode == MODE_CTRL_VS_2P) ? CTRL_TYPE_PLAYER : rnd(0, CTRL_NUM - 1)
        //ctrlType2 = CTRL_TYPE_STRONG
        //BGM
        startBGM("sakura_battle", FALSE, 0, 80, 90, 50)
        @label.jump "retry"
    }

    //----------------------------
    //リトライ
    @label.set "retry"
    bl {
        //ピクチャを隠す
        hidePicture(PIC_UNDER)
        //試合の状態
        _changeScene(SCENE_STATE_START)
        //体力バーを更新する
        hitFlag = -1
        hitStop = 0
        //キャラクターの変数を初期化する
        //ctrlTypeは除く
        assignVarUsingDeclared(ctrlState1, iptAtk1, 0)
        assignVarUsingDeclared(ctrlState2, iptAtk2, 0)
        life1 = MAX_LIFE
        life2 = MAX_LIFE

        $x = 40
        pos1  = $x
        pos2  = SCREEN_WIDTH - $x

        //試合中
        @loop bl {
            @wait(0)

            //----------------------------
            //強制終了
            @key.input .dst(ipt) .number
            @if `ipt == $KEY_NUM_ESC bl {
                @break
            }

            //----------------------------
            //シーン

            //シーンタイマー
            scTimer += 1

            //開始時
            @if scState == SCENE_STATE_START bl {
                @if scTimer == 0 bl {
                    _showText(1, 1)
                    @se.play "Flash1" .opt(100, 120, 50)
                }

                @if scTimer >= 60 bl {
                    hidePicture(PIC_TEXT)
                    _changeScene(SCENE_STATE_BATTLE)
                }

            //KO演出
            } .elif scState == SCENE_STATE_KO bl {
                //勝った方
                tm1 = life1 <= 0 ? 1 : 0
                //負けた方
                tm2 = life1 <= 0 ? 0 : 1
                //時間停止
                @if scTimer == 0 bl {
                    @pic.move[PIC_KO] .pos(SCREEN_REF_X, SCREEN_REF_Y) .topLeft .scale(100) .trans(0)

                    //勝利数をここでカウントする
                    @if `(mode == MODE_1P_VS_CPU && life2 <= 0) || (mode == MODE_CTRL_VS_2P && life1 <= 0) bl {
                        enNoRyuScore += 1
                        checkSetAchievement(achievedEnNoRyu, enNoRyuScore >= ER_ACHIEVE_COUNT)
                    }
                }

                //スローモーション
                @if `scTimer < 100 && scTimer % 4 != 0 bl {
                    hitStop = max(hitStop, 1)
                }

                //背景を戻す
                @if scTimer == 48 bl {
                    hidePicture(PIC_KO)
                }

                //崩れる
                @if scTimer == 100 bl {
                    _getStateId(ele, tm2)
                    mState = STATE_LOSE
                    @se.play "Blow1" .opt(100, 90, 50)
                }

                //勝ち
                @if scTimer == 160 bl {
                    _getStateId(ele, tm1)
                    mState = STATE_WIN
                    //帯
                    tm3 = tm1 + 2
                    _showText(tm3, 1)
                    //選択
                    _changeScene(SCENE_STATE_SELECT)
                    @se.play "Flash2" .opt(100, 100, 50)
                }

            //選択
            } .elif scState == SCENE_STATE_SELECT bl {
                @if scTimer == 0 bl {
                    //帯
                    @pic.move[PIC_UNDER] .pos(SCREEN_REF_X, SCREEN_REF_Y + SCREEN_HEIGHT - 16) .topLeft .scale(100) .trans(0)

                    //負けるとCPUの行動パターンを変更する
                    @loop 2 .dst(idx) bl {
                        _getStateId(ele, idx)
                        @if `mCtrl != CTRL_TYPE_PLAYER && mLife <= 0 bl {
                            tm1 = rnd(1, CTRL_NUM - 1)
                            mCtrl = (mCtrl + tm1) % CTRL_NUM
                        }
                    }
                }

                //入力
                @key.input .dst(ipt) {
                    $KEY_1P_BACK
                    $KEY_2P_BACK
                    $KEY_1P_FRONT
                    $KEY_2P_FRONT
                    $KEY_1P_ATTACK
                    $KEY_2P_ATTACK
                }

                //再戦
                @if `enteredLeft || enteredAttack bl {
                    @se.play "Decision2" .opt(80, 100, 50)
                    @wait(5)
                    @label.jump "retry"
                //終了
                } .elif `enteredRight bl {
                    @se.play "Cancel2" .opt(100, 100, 50)
                    @wait(5)
                    @break
                }
            }

            //----------------------------
            //入力状態を更新
            @loop 2 .dst(idx) bl {
                _getStateId(ele, idx)
                //----------------------------
                //プレイヤー
                @if `mCtrl == CTRL_TYPE_PLAYER bl {
                    //押している時間を保ちたいので、試合外でも処理する
                    //入力状態を更新する
                    __fn updateInput $d $key {
                        @key.input .dst(ipt) $key
                        v[__id($d)] = (ipt != 0) ? (v[__id($d)] + 1) : 0
                    }

                    //1P
                    @if `idx == 0 bl {
                        updateInput(iptBack1,  $KEY_1P_BACK)
                        updateInput(iptFront1, $KEY_1P_FRONT)
                        updateInput(iptAtk1,   $KEY_1P_ATTACK)
                    }

                    //2P
                    @if `idx == 1 bl {
                        updateInput(iptBack2,  $KEY_2P_BACK)
                        updateInput(iptFront2, $KEY_2P_FRONT)
                        updateInput(iptAtk2,   $KEY_2P_ATTACK)
                    }

                //----------------------------
                //CPU
                } .else bl {
                    //行動を予約する
                    @if `mCtState == CTRL_NEUTRAL && enableInput bl {
                        //乱数
                        cpuRnd = rnd(0, 99)
                        //相手との距離
                        cpuDist = abs(pos1 - pos2)
                        //壁との距離
                        cpuEdeg = ((idx == 0) ? (pos1) : (SCREEN_WIDTH - pos2))
                        //自身の状態
                        cpuMyState = mState
                        //相手の状態
                        cpuEnState = (idx == 0) ? (state2) : (state1)
                        //自身の状態が立ちか歩きか
                        $standOrStep = (cpuMyState == STATE_STAND || cpuMyState == STATE_STEP)
                        //相手が攻撃前の状態か
                        $mayBeAttacked = (cpuEnState == STATE_WEAK1 || cpuEnState == STATE_WEAK2 || cpuEnState == STATE_STRONG1 || cpuEnState == STATE_STRONG2)
                        //相手が強攻撃前の状態か
                        $mayBeStrongAttacked = (cpuEnState == STATE_STRONG1 || cpuEnState == STATE_STRONG2)

                        //バックステップを予約する時は、フレーム数は2以上を指定する

                        //----------------------------
                        //ひたすら近づき、ランダムに行動する
                        @if `mCtrl == CTRL_TYPE_SIMPLE bl {
                            @if `$standOrStep bl {
                                _setCtrlState(CTRL_WAIT, 15)

                                //遠い
                                @if `cpuDist > ATTACK_RANGE + STRONG_MOVE / 2 bl {
                                    @if `cpuRnd < 75 bl {
                                        _setCtrlState(CTRL_FRONT, 30)
                                    }
                                //近い
                                } .elif `cpuRnd < 30 bl {
                                    _setCtrlState(CTRL_WEAK, 1)
                                } .elif `cpuRnd < 60 bl {
                                    _setCtrlState(CTRL_STRONG, 1)
                                } .elif `cpuRnd < 80 bl {
                                    _setCtrlState(CTRL_BACK, 15)
                                }
                            }
                        }

                        //----------------------------
                        //フェイントを仕掛ける
                        @if `mCtrl == CTRL_TYPE_FEINT bl {
                            @if `$standOrStep bl {
                                _setCtrlState(CTRL_WAIT, 15)

                                //遠い
                                @if `cpuDist > ATTACK_RANGE + STRONG_MOVE / 2 bl {
                                    @if `cpuRnd < 70 bl {
                                        _setCtrlState(CTRL_FRONT, 20)
                                    } .elif `cpuRnd < 80 bl {
                                        _setCtrlState(CTRL_WEAK_FRONT, 2)
                                    }

                                //近い
                                } .elif `cpuRnd < 40 bl {
                                    _setCtrlState(CTRL_WEAK, 1)
                                } .elif `cpuRnd < 60 bl {
                                    _setCtrlState(CTRL_STRONG, 1)
                                } .elif `cpuRnd < 80 bl {
                                    //画面端ではバックステップをしない
                                    @if `cpuEdeg > CHAR_WIDTH * 2 + 8 bl {
                                        @if `cpuRnd < 70 bl {
                                            _setCtrlState(CTRL_WEAK_BACK, 20)
                                        } .elif `cpuRnd < 80 bl {
                                            _setCtrlState(CTRL_STRONG_BACK, 20)
                                        }
                                    }
                                }
                            }
                        }

                        //----------------------------
                        //ひたすら弱攻撃をこする
                        @if `mCtrl == CTRL_TYPE_WEAK bl {
                            @if `$standOrStep bl {
                                //遠い
                                @if `cpuDist > ATTACK_RANGE bl {
                                    _setCtrlState(CTRL_FRONT, 20)

                                //相手が攻撃しようとしているときは前進か待機する
                                } .elif `$mayBeAttacked bl {
                                    @if `cpuRnd < 60 bl {
                                        _setCtrlState(CTRL_WAIT, 20)
                                    } .else bl {
                                        _setCtrlState(CTRL_FRONT, 10)
                                    }

                                //近い
                                } .elif `cpuRnd < 90 bl {
                                    _setCtrlState(CTRL_WEAK, 1)
                                } .else {
                                    //稀に強攻撃を出す
                                    _setCtrlState(CTRL_STRONG, 1)
                                }
                            }
                        }

                        //----------------------------
                        //超反応で攻撃を回避する
                        @if `mCtrl == CTRL_TYPE_STRONG bl {
                            @if `$standOrStep bl {
                                _setCtrlState(CTRL_WAIT, 15)

                                //画面端に追い詰められたら弱攻撃しかない
                                @if `cpuEdeg < CHAR_WIDTH + 8 && cpuDist < CHAR_WIDTH * 2 + 16 bl {
                                    _setCtrlState(CTRL_WEAK, 1)

                                //弱攻撃の射程内
                                } .elif `cpuDist < ATTACK_RANGE bl {
                                    @if `cpuRnd < 30 bl {
                                        _setCtrlState(CTRL_WEAK, 1)
                                    } .elif `cpuRnd < 40 && $mayBeAttacked bl {
                                        _setCtrlState(CTRL_STRONG, 1)
                                    }

                                //強攻撃の射程内
                                } .elif `cpuDist < ATTACK_RANGE + STRONG_MOVE + 4 bl {
                                    //相手が強攻撃の動作中は下がる
                                    @if `cpuRnd < 20 || $mayBeStrongAttacked bl {
                                        _setCtrlState(CTRL_BACK, 20)
                                    } .elif `cpuRnd < 80 bl {
                                        _setCtrlState(CTRL_STRONG, 1)
                                    }

                                //遠い
                                } .else bl {
                                    @if `cpuRnd < 80 bl {
                                        _setCtrlState(CTRL_FRONT, 20)
                                    } .elif `cpuRnd < 90 bl {
                                        _setCtrlState(CTRL_WEAK_FRONT, 2)
                                    }
                                }

                            //強攻撃中の弱攻撃はバックステップで避ける
                            } .elif `cpuDist < ATTACK_RANGE + WEAK_MOVE &&
                                (cpuMyState == STATE_STRONG1 || cpuMyState == STATE_STRONG2) &&
                                (cpuEnState == STATE_WEAK2) bl {
                                _setCtrlState(CTRL_WEAK, 1)
                            }
                        }
                    }

                    //デバッグ
                    //2Pのみ
                    //@if idx == 1 bl {
                    //    tm1 = mCtState
                    //    tm2 = mCtTimer
                    //    @pic.strpic [PIC_DEBUG] __str("st:\",tm1, "ti:\",tm2, "rn:\",cpuRnd) .pos(0, 0) .topLeft
                    //}

                    //入力を全て初期化する
                    mInputF = 0
                    mInputB = 0
                    mInputA = 0

                    @if `mCtTimer > 0 bl {
                        mCtTimer -= 1
                        //予約内容
                        tm1 = mCtState
                        //フェイント
                        @if `tm1 & CTRL_STEP bl {
                            @if `tm1 & CTRL_WEAK bl {
                                mInputB = 1
                                mInputA = 1
                            }

                            @if `tm1 & CTRL_STRONG bl {
                                mInputF = 1
                                mInputA = 1
                            }
                            //ビットを取り除く
                            mCtState &= (-1) ^ (CTRL_WEAK | CTRL_STRONG | CTRL_STEP)
                        }

                        //発火
                        @if `mCtTimer <= 0 bl {
                            //攻撃 or ステップ
                            @if `tm1 & (CTRL_STRONG | CTRL_FRONT_STEP) bl {
                                mInputF = 1
                                mInputA = 1
                            }
                            @if `tm1 & (CTRL_WEAK | CTRL_BACK_STEP) bl {
                                mInputB = 1
                                mInputA = 1
                            }
                            //予約を消化した
                            mCtState = CTRL_NEUTRAL

                        //経過
                        } .else bl {
                            //移動
                            @if `tm1 & CTRL_FRONT bl {
                                mInputF = 1
                            }
                            @if `tm1 & CTRL_BACK bl {
                                mInputB = 1
                            }
                        }
                    }
                }
            }

            //----------------------------
            //ヒットストップ
            @if hitStop > 0 bl {
                hitStop -= 1
            //ヒットストップ中は以下の処理をスキップする
            } .else bl {
                //----------------------------
                //攻撃判定
                $1pHit = (0x01)
                $2pHit = (0x02)
                //距離とゲームの状態
                @if enableInput bl {
                    @if `pos2 - pos1 < ATTACK_RANGE bl {
                        //ヒットフラグ
                        __fn chkAttack $stateA $stateD $bit {
                            //自分が攻撃動作中、かつ相手がガードorダメージ状態でない
                            @if `($stateA == STATE_WEAK3 || $stateA == STATE_STRONG3) &&
                                ($stateD != STATE_GUARD && $stateD != STATE_DAMAGE) bl {
                                hitFlag |= $bit
                            }
                        }

                        chkAttack(state1, state2, $1pHit)
                        chkAttack(state2, state1, $2pHit)

                        //相殺すると少し下がる
                        @if `hitFlag == ($1pHit | $2pHit) bl {
                            @loop 2 .dst(idx) bl {
                                _getStateId(ele, idx)
                                _changeCharaState(STATE_GUARD, 10) //タイマーを少し進める
                            }

                            hitStop = 4

                            @se.stop
                            @se.play "Sword2" .opt(100, 100, 50)

                        //攻撃が当たった
                        } .elif `hitFlag & ($1pHit | $2pHit) bl {
                            //攻撃対象
                            tm1 = hitFlag == $1pHit ? 1 : 0
                            _getStateId(ele, tm1)
                            //ガードに成功したか
                            tm2 = (mState == STATE_STAND || mState == STATE_STEP) ? TRUE : FALSE
                            //ダメージ
                            //無敵モード中はどちらの体力も減らない
                            @if invincibleSwitch.isOff bl {
                                mLife -= (tm2 == TRUE) ? ATTACK_GUARD : ATTACK_HIT
                            }
                            //削り切られるとガードに失敗した扱いになる
                            tm3 = (tm2 == TRUE && mLife > 0) ? STATE_GUARD : STATE_DAMAGE
                            //状態を変更する
                            _changeCharaState(tm3, -1)
                            //KO
                            @se.stop
                            @if `mLife <= 0 bl {
                                hitStop = 48
                                @se.play "hit_db" .opt(100, 100, 50)
                                _changeScene(SCENE_STATE_KO)

                            //防いだ
                            } .elif `mState == STATE_GUARD bl {
                                hitStop = 4
                                @se.play "Sword2" .opt(100, 100, 50)

                            //通常
                            } .else bl {
                                hitStop = 24
                                @se.play "Damage1" .opt(100, 90, 50)
                            }
                        }
                    }
                }

                //----------------------------
                //体力バーを更新する
                @if `hitFlag bl {
                    @loop 2 .dst(idx) bl {
                        _getStateId(ele, idx)

                        $x = 16
                        $y = 13
                        $l = 50

                        tm1   = eBar
                        tm2   = mLife * $l / MAX_LIFE//体力に応じて横にずらす
                        ax = SCREEN_REF_X + (idx == 0 ? ($x - $l + tm2) : (160 - $x - tm2))
                        ay = SCREEN_REF_Y + $y
                        @pic.move[tm1] {
                            .topLeft
                            .pos(ax, ay)
                            .scale(100)
                            .trans(0)
                            .time(0)
                        }
                    }
                    //ヒットフラグ初期化
                    hitFlag = 0x00
                }

                //----------------------------
                //めりこみ修正
                @if `pos2 - pos1 < CHAR_WIDTH * 2 bl {
                    pos1 -= 1
                    pos2 += 1
                }

                //攻撃動作中かつ画面端にいる場合、自身が下がる
                @if `pos1 > SCREEN_WIDTH - CHAR_WIDTH * 4 && (state2 == STATE_GUARD || state2 == STATE_DAMAGE) bl {
                    pos1 -= 1
                }

                @if `pos2 < CHAR_WIDTH * 4 && (state1 == STATE_GUARD || state1 == STATE_DAMAGE) bl {
                    pos2 += 1
                }

                //----------------------------
                //キャラクター更新
                @loop 2 .dst(idx) bl {
                    _getStateId(ele, idx)

                    //一時変数
                    tm1 = mState
                    tm2 = mStTimer
                    tm3 = (idx == 0 ? 1 : -1)

                    //----------------------------
                    //立ち/歩き/勝ち/負け
                    //何もしない

                    //----------------------------
                    //ガード/ダメージ
                    @if `tm1 == STATE_GUARD || tm1 == STATE_DAMAGE bl {
                        $t1 = 10
                        $t2 = 20
                        $t3 = 25

                        //後ずさる
                        @if `tm2 < $t1 bl {
                            mPos -= 1 * tm3
                        } .elif `tm2 < $t2 bl {
                            mPos -= (tm2 % 2 == 0 ? 1 : 0) * tm3//1px/2f
                        }

                        //体力が無いと復帰しない
                        @if `tm2 >= $t3 && mLife > 0 bl {
                            _changeCharaState(STATE_STAND, -1)
                        }
                    }

                    //----------------------------
                    //クイックステップ
                    @if `tm1 == STATE_FRONT || tm1 == STATE_BACK bl {
                        $t1 = 4
                        $t2 = 25

                        //効果音
                        @if `tm2 == 0 bl {
                            @se.play "Bow2" .opt(80, 100, 50)
                        }

                        //後ずさる
                        @if `tm2 < $t1 bl {
                            mPos += 5 * tm3 * (tm1 == STATE_FRONT ? 1 : -1)
                        }

                        @if `tm2 >= $t2 bl {
                            _changeCharaState(STATE_STAND, -1)
                        }
                    }

                    //----------------------------
                    //弱攻撃
                    @if `tm1 >= STATE_WEAK1 && tm1 <= STATE_WEAK4 bl {
                        $t1 = 8
                        $t2 = 22
                        $t3 = 27
                        $t4 = 60

                        @if `tm2 == $t1 || tm2 == $t2 || tm2 == $t3 bl {
                            mState += 1
                        }

                        @if `tm2 == $t1 bl {
                            mPos += WEAK_MOVE * tm3//少し前に出る
                        }                    

                        @if `tm2 == $t2 bl {
                            @se.play "Wind7" .opt(100, 50, 50)
                        }
                        
                        @if `tm2 >= $t4 bl {
                            _changeCharaState(STATE_STAND, -1)
                        }
                    }

                    //----------------------------
                    //強攻撃
                    @if `tm1 >= STATE_STRONG1 && tm1 <= STATE_STRONG4 bl {
                        $t1 = 8
                        $t2 = 40
                        $t3 = 45
                        $t4 = 65//弱攻撃より総フレーム数が少し多い

                        @if `tm2 == $t1 || tm2 == $t2 || tm2 == $t3 bl {
                            mState += 1
                        }

                        @if `tm2 == $t2 bl {
                            mPos += STRONG_MOVE * tm3//前に出る
                            @se.play "Breath" .opt(100, 150, 50)
                        }

                        @if `tm2 >= $t4 bl {
                            _changeCharaState(STATE_STAND, -1)
                        }
                    }

                    //----------------------------
                    //入力受付
                    @if `enableInput bl {

                        //状態
                        tm1 = mState
                        tm2 = mStTimer

                        //クイックステップ
                        @if `tm1 == STATE_WEAK1 || tm1 == STATE_WEAK2 || tm1 == STATE_STRONG1 || tm1 == STATE_STRONG2 bl {
                            @if `mInputA == 1 bl {
                                //バックステップ
                                @if `mInputB > 10bl {
                                    _changeCharaState(STATE_BACK, -1)
                                }
                                
                                //フロントステップ
                                @if `mInputF > 0 bl {
                                    _changeCharaState(STATE_FRONT, -1)
                                }
                            }
                        //攻撃、移動
                        } .elif `tm1 == STATE_STAND || tm1 == STATE_STEP bl {
                            //攻撃
                            //入力猶予
                            $t1 = 8//攻撃
                            //$t2 = 16//方向

                            @if `between( mInputA, 1, $t1 ) bl {
                                //前方向を入力すると強攻撃になる
                                //後ろ方向も入力されていると弱攻撃になる
                                //ipt = mInputB <= 0 && between( mInputF, 1, $t2 ) ? STATE_STRONG1 : STATE_WEAK1
                                ipt = mInputB <= 0 && mInputF >= 1 ? STATE_STRONG1 : STATE_WEAK1
                                _changeCharaState(ipt, -1)

                            //歩き
                            } .else bl {
                                ipt = (mInputB != 0 ? -1 : 0) + (mInputF != 0 ? 1 : 0)
                                @if `ipt != 0 bl {
                                    mState = (mStTimer % 8 > 4) ? STATE_STEP : STATE_STAND //歩行アニメーション
                                    mPos += (mStTimer % 2 == 0 ? 1 : 0) * tm3 * ipt //1px/2f
                                //入力が無いと立ち状態へ戻る
                                } .else bl {
                                    _changeCharaState(STATE_STAND, -1)
                                }
                            }
                        }
                    }

                    //----------------------------
                    //位置制限
                    mPos = clamp(mPos, 0 + CHAR_WIDTH, SCREEN_WIDTH - CHAR_WIDTH)

                    //----------------------------
                    //タイマー
                    mStTimer += 1

                    //----------------------------
                    //ピクチャ
                    $x = mPos
                    $y = 100

                    tm1   = ePic
                    tm2   = mState + 1//セル = 状態 + 1
                    ax = SCREEN_REF_X + $x
                    ay = SCREEN_REF_Y + $y
                    @pic.show[tm1] .repl(1, idx) .pos(ax, ay) .scale(100) .trans(0) .cell(tm2) charaPicCmd
                }
            }
        }

        //ピクチャを隠す
        hidePicturesForEach( [PIC_INFO, PIC_TEXT, PIC_UNDER, PIC_KO, PIC_LIFE_1P, PIC_LIFE_2P, PIC_CHAR_1P, PIC_CHAR_2P] )
        @wait(0)
        //BGM
        stopBGM(0)
        //選択画面へ戻る
        @label.jump "modeSelect"
    }

    //------------------------------------------------------------------------------------
    //終了する
    @label.set "gameEnd"
    bl {
        initPicturesAndVariables(PIC_HEAD, NUM_OF_PIC, TV_MINIGAME, NUM_OF_VAR, 0, 0)
        restoreBGM()
        fastFadeInTintOnly(1)
    }
}