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


cev[CEV_LOOP_HELL] .name("mg_ループヘル") {
    def {
        NUM_OF_VAR = 128
        NUM_OF_STR = 0
        NUM_OF_PIC = 85

        BASE_LAYER = 6

        PATH_CHIP   = "lh\ci"
        PATH_CURSOR = "lh\cu"
        PATH_COUNT  = "lh\co"
        PATH_BACK   = "lh\ba"
        PATH_EFFECT = "lh\ef"
        PATH_FIRE   = "lh\fi"

        PIC_HEAD     = 1
        PIC_FIRE     = 2//+0_+15
        PIC_BACK     = 19
        PIC_CHIP     = 20//+0_+35
        PIC_CURSOR   = 59
        PIC_SCORE    = 60//+0_+4
        PIC_HISCORE  = 65//+0_+4
        PIC_ADDSCORE = 70//+0_+4
        PIC_ERASE    = 75//+0_+1
        PIC_QUOTA    = 77//+0_+1
        PIC_EFFECT   = 79//+0_+3

        //実績
        ACHIEVE_SCORE = 5000

        //トリガー
        TR_BIT_SCORE    = (1 << 0)
        TR_BIT_HISCORE  = (1 << 1)
        TR_BIT_ADDSCORE = (1 << 2)
        TR_BIT_QUOTA    = (1 << 3)

        //シーン
        SCENE_NEXT_TURN = 0
        SCENE_SELECT
        SCENE_ROOT
        SCENE_ERASE
        SCENE_FALL
        SCENE_PAD

        //入力
        INPUT_NONE = -1
        INPUT_RIGHT = 0//right_upは連番
        INPUT_DOWN
        INPUT_LEFT
        INPUT_UP
        INPUT_DECISION

        MOVE_NONE = 0
        MOVE_WALL
        MOVE_BACK
        MOVE_STEP
        MOVE_LOOP

        //定数
        OUT_RANGE = -320
        INPUT_REPEAT = 8
        COUNTER_WIDTH = 8
        CHIP_WIDTH = 24
        FALL_TIME = 2

        HISCORE_X = 208
        HISCORE_Y = 30

        SCORE_X = 208
        SCORE_Y = 42
        SCORE_DIGIT = 5
        SCORE_MAX   = 99999

        ADDSCORE_X = 220
        ADDSCORE_Y = 54
        ADDSCORE_MX = 8
        ADDSCORE_TIMER = 120

        ERASE_X = 220
        ERASE_Y = 66
        ERASE_DIGIT = 2

        QUOTA_X = 168
        QUOTA_Y = 66
        QUOTA_NUM = 18//初期ノルマ
        QUOTA_DIGIT = 2

        FIELD_X = 100
        FIELD_Y = 80
        FIELD_WIDTH = 5
        FIELD_HEIGHT= 6

        EFFECT_NUM = 4
        FIRE_NUM = 16
    }

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

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

        chipPicCmd = bl {
            PATH_CHIP
            .grid(4, 1)
            basePicCmd
        }

        cursorPicCmd = bl{
            PATH_CURSOR
            .grid(4, 1)
            basePicCmd
        }

        effectPicCmd = bl {
            PATH_EFFECT
            basePicCmd
        }

        firePicCmd = bl {
            PATH_FIRE
            basePicCmd
        }
    }

    defv {
        varHead = TV_MINIGAME
        
        ipt
        pid
        cell
        mark
        type
        time
        ix
        iy
        tx
        ty
        sx
        sy

        triggerFlg
        sceneState
        sceneTimer

        score
        addScore

        turnNumber
        quotaNumber
        blockNumber
        eraseNumber
        waitTime

        iptH
        iptHCounter
        iptV
        iptVCounter
        iptDec
        iptType

        cursorX
        cursorY

        firstX
        firstY

        fireCounter
        fireTimer
        fireX
        fireY

        fieldArr
        markArr = (__id(fieldArr) + FIELD_WIDTH * FIELD_HEIGHT)

        varFoot = (__id(markArr) + FIELD_WIDTH * FIELD_HEIGHT)

    }

    commentRangeOfVariables(varFoot, TV_MINIGAME, NUM_OF_VAR, NUM_OF_STR, NUM_OF_PIC)
    
    //ハイスコアを更新する
    __fn _updateHighScore bl {
        loopHellScore = max(loopHellScore, score)
    }

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

    //場にブロックIDを代入する
    __fn _setBlock $src $dvPtr $x $y bl {
        v[__id($dvPtr) + ($x) + ($y) * FIELD_WIDTH] = $src
    }

    //場のブロックIDを取得する
    __fn _getBlock $dvDst $dvPtr $x $y bl {
        v[__id($dvDst)] = v[__id($dvPtr) + ($x) + ($y) * FIELD_WIDTH]
    }

    //ブロックのピクチャIDを取得する
    __fn _getBlockPicture $dvDst $x $y bl {
        v[__id($dvDst)] = PIC_CHIP + (($x) + ($y) * FIELD_WIDTH)
    }

    //ブロックの位置を取得する
    __fn _V2_getBlockPosition $dvDst $x $y bl {
        v[__id($dvDst) + 0..__id($dvDst) + 1] = [ FIELD_X + ($x) * CHIP_WIDTH + CHIP_WIDTH / 2, FIELD_Y + ($y) * CHIP_WIDTH + CHIP_WIDTH / 2 ]
    }

    //カーソルピクチャを置き直す
    __fn _setCursorPicture $type bl {
        _V2_getBlockPosition(sx, cursorX, cursorY)

        __if $type == 0 bl {
            $TIME = 16
            $CELL1 = 1
            $CELL2 = 2
        } .else bl {
            $TIME = 8
            $CELL1 = 3
            $CELL2 = 4
        }
        @pic.show [PIC_CURSOR] .pos(sx, sy) .rangeAnim($TIME, $CELL1, $CELL2) cursorPicCmd
    }

    //数値を表示する
    __fn _showCounter $num $type $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 = 1 + ($num) % (iy * 10) / iy

            @if `($num) < iy && iy != 1 bl {
                @pic.show [pid] .pos(sx, sy) .topRight .scale(100) .cell(0) countPicCmd

            } .else bl {
                //$type == 1 : 振動する
                __if $type == 1 bl {
                    sy -= 2
                    @pic.show [pid] .pos(sx, sy) .topRight .scale(100) .cell(cell) countPicCmd
                    @pic.move [pid] .relative .pos(0, 2) .scale(0) .trans(0) .time(1)

                //$type == 2 : 右から左へスライドする
                } .elif $type == 2 bl {
                    sx += 8
                    @pic.show [pid] .pos(sx, sy) .topRight .scale(100) .trans(100) .cell(cell) countPicCmd
                    @pic.move [pid] .relative .pos(-8, 0) .scale(0) .trans(-100) .time(1)

                } .else bl {
                    @pic.show [pid] .pos(sx, sy) .topRight .scale(100) .cell(cell) countPicCmd  
                }
            }
            //次の桁
            iy *= 10
        }
    }

    //------------------------------------------------------------------------------------
    //開始処理
    bl {
        initPicturesAndVariables(PIC_HEAD, NUM_OF_PIC, TV_MINIGAME, NUM_OF_VAR, 0, 0)
        msgBottom()
        
        @scr.tint .rgbs(0, 0, 0, 100) .time(0)
        @wait(0)
        @scr.tint .rgbs(30, 30, 30, 100) .time(1)

        //ピクチャ
        @pic.show [PIC_BACK] PATH_BACK .pos(0, 0) .topLeft basePicCmd
        @loop EFFECT_NUM .dst(pid) bl {
            pid += PIC_EFFECT
            @pic.show [pid] .pos(OUT_RANGE, OUT_RANGE) .trans(100) effectPicCmd
        }

        @loop FIRE_NUM .dst(pid) bl {
            pid += PIC_FIRE
            @pic.show [pid] .pos(OUT_RANGE, OUT_RANGE) .trans(100) .add firePicCmd
        }

        @wait(1)
        @label.jump "gameLoop"
    }

    //------------------------------------------------------------------------------------
    //ゲーム処理
    @label.set "gameLoop"
    bl {
        //最初に補充する
        _setSceneState(SCENE_NEXT_TURN)
        //カウンターを初期化する
        triggerFlg = TR_BIT_SCORE | TR_BIT_HISCORE | TR_BIT_ADDSCORE
        score = 0
        addScore = 0
        turnNumber = -1
        //カーソルを中央に移動させる
        V2_set(cursorX, FIELD_WIDTH / 2, FIELD_HEIGHT / 2)
        _setCursorPicture(0)
        //フィールドの空白を埋め立てる
        v[__id(fieldArr)..__id(fieldArr) + FIELD_WIDTH * FIELD_HEIGHT] = 0
        //ブロックのピクチャを全て隠す
        time = FIELD_WIDTH * FIELD_HEIGHT
        @loop time .dst(pid) bl {
            pid += PIC_CHIP
            @pic.move [pid] .pos(OUT_RANGE, OUT_RANGE) .trans(100)
        }

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

            //----------------------------
            //ポーズ
            @key.input .dst(ipt) .cancel
            @if `ipt bl {
                @se.play "Cancel2" .opt(100, 100, 50)
                @msg.choice bl {
                    .cancel(0)
                    .case "\>つづける" bl {
                        @wait(3)
                    }
                    .case "\>\c[2]最初から始める\c[0]" bl {
                        //ハイスコアを更新する
                        _updateHighScore()
                        @label.jump "gameLoop"
                    }
                    .case "\>やめる" bl {
                        @label.jump "gameEnd"
                    }
                }
            }
            //----------------------------
            //入力
            @key.input .dst(ipt) .decision
            iptDec   = ipt ? iptDec   + 1 : 0
            @key.input .dst(ipt) {
                .left
                .right
            }
            iptH = ipt == KEY_LEFT ? -1 : 1
            iptHCounter = ipt ? iptHCounter + 1 : 0
            @key.input .dst(ipt) {
                .up
                .down
            }
            iptV = ipt == KEY_UP ? -1 : 1
            iptVCounter = ipt ? iptVCounter + 1 : 0

            //操作
            iptType = INPUT_NONE
            @if `!((iptHCounter - 1) % INPUT_REPEAT) bl {
                @if `iptH < 0 && cursorX > 0 bl {
                    iptType = INPUT_LEFT
                } .elif `iptH > 0 && cursorX < FIELD_WIDTH - 1 bl {
                    iptType = INPUT_RIGHT
                }
            }

            @if `!((iptVCounter - 1) % INPUT_REPEAT) bl {
                @if `iptV < 0 && cursorY > 0 bl {
                    iptType = INPUT_UP
                } .elif `iptV > 0 && cursorY < FIELD_HEIGHT - 1 bl {
                    iptType = INPUT_DOWN
                }
            }

            @if iptDec == 1 bl {
                iptType = INPUT_DECISION
            }

            //----------------------------
            //シーン
            //カウントアップ
            sceneTimer += 1
            //敷設モード以外の時はカーソルは自由に動かせる
            @if sceneState != SCENE_ROOT bl {
                //移動
                @if `between(iptType, 0, 3) bl {
                    //移動先
                    V2_set(tx,
                        clamp( cursorX + [1, 0,-1, 0][iptType], 0, FIELD_WIDTH  - 1 ),
                        clamp( cursorY + [0, 1, 0,-1][iptType], 0, FIELD_HEIGHT - 1 )
                    )
                    //カーソル移動
                    @if `tx != cursorX || ty != cursorY bl {
                        V2_copy(cursorX, tx)
                        //カーソルピクチャを移動
                        _V2_getBlockPosition(sx, cursorX, cursorY)
                        @pic.move [PIC_CURSOR] .pos(sx, sy) .center .time(1)
                        //効果音
                        cell = [80, 100, 60, 120][iptType]
                        @se.play "trigger1" .opt(60, cell, 50)
                    }
                }
            }

            //次のターン
            @if sceneState == SCENE_NEXT_TURN bl {
                //カウンター
                @if sceneTimer == 0 bl {
                    bitOn(triggerFlg, TR_BIT_QUOTA)
                    //ターン数
                    turnNumber += 1
                    //次のノルマ
                    //最終的には残せるのは２個だけになる
                    quotaNumber = min(QUOTA_NUM + turnNumber, FIELD_WIDTH * FIELD_HEIGHT - 2)
                    //ブロック数
                    blockNumber = FIELD_WIDTH * FIELD_HEIGHT
                }

                //一列ずつブロックを落とす
                @if `!(sceneTimer % 4) bl {
                    iy = FIELD_HEIGHT - sceneTimer / 4 - 1
                    //落としきったら次の状態へ
                    @if iy < 0 bl {
                        _setSceneState(SCENE_SELECT)
                    //ブロックを落とす
                    } .else bl {
                        //落とした数
                        type = 0
                        @loop FIELD_WIDTH .dst(ix) bl {
                            _getBlock( cell, fieldArr, ix, iy )
                            @if cell <= 0 bl {
                                cell = rnd(1, 4)
                                //cell = 1
                                _setBlock( cell, fieldArr, ix, iy )
                                //移動時間
                                time = iy * FALL_TIME * -1
                                //落とした数
                                type += 1

                                _getBlockPicture(pid, ix, iy)
                                _V2_getBlockPosition(sx, ix,  0)
                                @pic.show[pid] .pos(sx, sy) .center .trans(100) .cell(cell) chipPicCmd
                                _V2_getBlockPosition(sx, ix, iy)
                                @pic.move[pid] .pos(sx, sy) .center .trans(0) .time(time)
                            }
                        }

                        //一つでも落としたとき、効果音を鳴らす
                        @if type > 0 bl {
                            @se.play "trigger1" .opt(80, 50, 50)
                        }
                    }
                }

            //選択
            } .elif sceneState == SCENE_SELECT bl {
                //カーソルピクチャ
                @if sceneTimer == 0 bl {
                    _setCursorPicture(0)
                }

                //敷設モードへ
                @if iptType == INPUT_DECISION bl {
                    //空白マスを選択している
                    _getBlock(cell, fieldArr, cursorX, cursorY)
                    @if cell <= 0 bl {
                        @se.play "Cancel1" .opt(80, 100, 50)
                    //矢印マスを選択している
                    } .else bl {
                        _setSceneState(SCENE_ROOT)
                        //敷設状態を初期化する
                        v[__id(markArr) + 0..__id(markArr) + FIELD_WIDTH * FIELD_HEIGHT] = 0
                        //最初のマスを記録する
                        V2_copy(firstX, cursorX)

                        _getBlock(cell, fieldArr, cursorX, cursorY)
                        _setBlock(cell, markArr, cursorX, cursorY)

                        @se.play "trigger1" .opt(100, 120, 50)
                    }
                }

            //敷設モード
            } .elif sceneState == SCENE_ROOT bl {
                //カーソルピクチャ
                @if sceneTimer == 0 bl {
                    _setCursorPicture(1)
                }

                //最初に選択したマスが定期的に光る
                @if `sceneTimer % 16 <= 1 bl {
                    _getBlockPicture(pid, firstX, firstY)
                    @if `sceneTimer % 16 == 0 bl {
                        @pic.move[pid] .relative .pos(0, 0) .scale(0) .trans(0) .rgbs(200, 200, 200, 50)
                    } .else bl {
                        @pic.move[pid] .relative .pos(0, 0) .scale(0) .trans(0) .rgbs(100, 100, 100, 50) .time(2)
                    }
                }

                //移動
                @if `between(iptType, 0, 3) bl {
                    //移動先
                    V2_set(tx,
                        clamp( cursorX + [1, 0,-1, 0][iptType], 0, FIELD_WIDTH  - 1 ),
                        clamp( cursorY + [0, 1, 0,-1][iptType], 0, FIELD_HEIGHT - 1 )
                    )
                    //移動先のブロック
                    _getBlock(cell, fieldArr, tx, ty)
                    _getBlock(mark, markArr, tx, ty)
                    //対面パターン
                    time = [3, 4, 1, 2][iptType]
                    //移動できていない
                    @if `tx == cursorX && ty == cursorY bl {
                        type = MOVE_NONE
                    //最初のマスで、敷設したブロックが対面していない
                    } .elif `tx == firstX && ty == firstY && mark != time bl {
                        type = MOVE_LOOP
                    //既に敷設されていて、敷設したブロックが対面している
                    } .elif `mark > 0 && mark == time bl {
                        type = MOVE_BACK
                    //既に敷設されている
                    } .elif `mark > 0 bl {
                        type = MOVE_WALL
                    //空白か、対面している
                    //無敵モードの時は対面していても通れる
                    } .elif `cell <= 0 || (cell == time && !invincibleSwitch) bl {
                        type = MOVE_WALL
                    //いずれでもない
                    } .else bl {
                        type = MOVE_STEP
                    }

                    //何もしない
                    @if type == MOVE_NONE bl {
                    //ぶつかった
                    } .elif type == MOVE_WALL bl {
                        //移動の邪魔になっているマスを光らせる
                        _V2_getBlockPosition(sx, tx, ty)
                        _getBlockPicture(pid, tx, ty)

                        @if mark > 0 bl {
                            @pic.show[pid] .pos(sx, sy) .center .scale(125) .trans(0) .cell(mark) .rgbs(200, 0, 0, 0) chipPicCmd
                            @pic.move[pid] .relative .pos(-2, -2) .scale(-25) .trans(0) .rgbs(100, 100, 100, 0) .time(2)
                        } .else bl {
                            @pic.show[pid] .pos(sx, sy) .center .scale(125) .trans(0) .cell(cell) .rgbs(200, 0, 0, 100) chipPicCmd
                            @pic.move[pid] .relative .pos(0, 0) .scale(-25) .trans(0) .rgbs(100, 100, 100, 100) .time(2)
                        }

                        @se.play "Cancel1" .opt(80, 100, 50)

                    //カーソルを進める
                    } .else bl {
                        //通った後に矢印を敷く
                        @if `type == MOVE_LOOP || type == MOVE_STEP bl {
                            mark = [1, 2, 3, 4][iptType]
                            _setBlock(mark, markArr, cursorX, cursorY)

                            _V2_getBlockPosition(sx, cursorX, cursorY)
                            _getBlockPicture(pid, cursorX, cursorY)
                            @pic.show[pid] .pos(sx, sy) .center .scale(100) .trans(0) .cell(mark) .rgbs(200, 200, 200, 0) chipPicCmd
                            @pic.move[pid] .relative .pos(-2, -2) .scale(  0) .trans(0) .rgbs(100, 100, 100, 0) .time(2)
                        }

                        //カーソル移動
                        V2_copy(cursorX, tx)
                        //カーソルピクチャを移動
                        _V2_getBlockPosition(sx, cursorX, cursorY)
                        @pic.move [PIC_CURSOR] .pos(sx, sy) .center .time(1)

                        //敷いた矢印を片付ける
                        @if type == MOVE_BACK bl {
                            _setBlock(0, markArr, cursorX, cursorY)

                            _getBlock(cell, fieldArr, cursorX, cursorY)
                            _V2_getBlockPosition(sx, cursorX, cursorY)
                            _getBlockPicture(pid, cursorX, cursorY)
                            @pic.show[pid] .pos(sx, sy) .center .scale(100) .trans(0) .cell(cell) .rgbs(200, 200, 200, 100) chipPicCmd
                            @pic.move[pid] .relative .pos(0, 0) .scale(0) .trans(0) .rgbs(100, 100, 100, 100) .time(2)
                        }

                        //敷設済みだった場合、消去処理へ移る
                        @if `type == MOVE_LOOP bl {
                            _setSceneState(SCENE_ERASE)
                        } .else bl {
                            //効果音
                            cell = [80, 100, 60, 120][iptType]
                            @se.play "trigger1" .opt(60, cell, 50)
                        }
                    }

                //キャンセル
                } .elif iptType == INPUT_DECISION bl {
                    _setSceneState(SCENE_SELECT)
                    //敷設したマスのピクチャを元に戻す
                    @loop FIELD_HEIGHT .dst(iy) bl {
                        @loop FIELD_WIDTH .dst(ix) bl {
                            _getBlock(mark, markArr, ix, iy)
                            @if `mark > 0 || (ix == cursorX && iy == cursorY) bl {
                                _getBlock(cell, fieldArr, ix, iy)
                                _V2_getBlockPosition(sx, ix, iy)
                                _getBlockPicture(pid, ix, iy)
                                @pic.show[pid] .pos(sx, sy) .center .scale(100) .trans(0) .cell(cell) chipPicCmd
                            }
                        }
                    }
                    @se.play "trigger1" .opt(100, 60, 50)
                }

            //消去
            } .elif sceneState == SCENE_ERASE bl {
                //カウンターを初期化する
                @if sceneTimer == 0 bl {
                    addScore = 0
                    eraseNumber = 0
                }

                //一つずつ消していく
                @if `!(sceneTimer % 2) bl {
                    //消すべきマスがない場合、落下させる
                    _getBlock(mark, markArr, firstX, firstY)
                    @if mark <= 0 bl {
                        _setSceneState(SCENE_FALL)

                        bitOn(triggerFlg, TR_BIT_SCORE | TR_BIT_ADDSCORE)                        

                        //基本スコアは消した数の二乗
                        addScore = eraseNumber * eraseNumber

                        //全消しで二倍
                        @if blockNumber <= 0 bl {
                            addScore *= 2
                            fireCounter = 6
                            //演出
                            @scr.flash .once(2) .rgbv(31, 31, 31, 31)
                            @se.play "Holy7" .opt(100, 100, 50)
                            @se.play "cheers" .opt(100, 80, 50)
                        //数によって花火の数と効果音が変わる
                        } .elif eraseNumber <= 6 bl {
                            @se.play "Attack2" .opt(80, 100, 50)
                        } .elif eraseNumber <= 12 bl {
                            fireCounter = 1
                            @se.play "Decision2" .opt(80, 120, 50)
                        } .elif eraseNumber <= 18 bl {
                            fireCounter = 2
                            @se.play "Holy9" .opt(80, 100, 50)
                        } .else bl {
                            fireCounter = 4
                            @se.play "Ice11" .opt(80, 100, 50)
                            @se.play "cheers" .opt(100, 100, 50)
                        }

                        //スコア追加
                        score = min(score + addScore, SCORE_MAX)
                        //実績
                        checkSetAchievement(achievedLoop, score >= ACHIEVE_SCORE)

                    } .else bl {
                        bitOn(triggerFlg, TR_BIT_QUOTA)

                        cell = 0
                        _setBlock(cell, fieldArr, firstX, firstY)
                        _setBlock(cell, markArr, firstX, firstY)

                        _V2_getBlockPosition(sx, firstX, firstY)
                        _getBlockPicture(pid, firstX, firstY)
                        @pic.show[pid] .pos(sx, sy) .center .scale2(120, 120) .trans(0) .cell(cell) .add chipPicCmd

                        //次のマスへ
                        V2_set(firstX,
                            clamp(firstX + [0, 1, 0,-1, 0][mark], 0, FIELD_WIDTH  - 1),
                            clamp(firstY + [0, 0, 1, 0,-1][mark], 0, FIELD_HEIGHT - 1)
                        )

                        //ブロックが減る
                        blockNumber -= 1
                        eraseNumber += 1

                        //ノルマ
                        @if quotaNumber > 0 bl {
                            quotaNumber -= 1
                            //ノルマ達成
                            @if quotaNumber <= 0 bl {
                                @se.play "Buff" .opt(100, 100, 50)
                            }
                        }

                        //消去エフェクト
                        pid = PIC_EFFECT + eraseNumber % EFFECT_NUM
                        @pic.show [pid] .pos(sx, sy) .center effectPicCmd
                        @pic.move [pid] .relative .pos(0, -16) .center .scale2(-80, 200) .trans(100) .add .time(2)
                        @se.play "con2" .opt(80, 50, 50)
                    }
                }

            //落下
            } .elif sceneState == SCENE_FALL bl {
                @if sceneTimer == 0 bl {
                    waitTime = 0
                    @loop FIELD_HEIGHT .dst(iy) bl {
                        //下から上へ判定していく
                        iy = (FIELD_HEIGHT - 1) - iy
                        @loop FIELD_WIDTH .dst(ix) bl {
                            //空白だった
                            _getBlock(cell, fieldArr, ix, iy)
                            @if cell <= 0 bl {
                                //上にブロックがあるか
                                @loop FIELD_HEIGHT .dst(ty) bl {
                                    //判定座標
                                    V2_set(tx,
                                        ix,
                                        iy - ty - 1
                                    )

                                    //Y座標が範囲外に出た
                                    @if ty < 0 bl {
                                        @break
                                    }

                                    //ブロックがあった
                                    _getBlock(cell, fieldArr, tx, ty)
                                    @if cell > 0 bl {
                                        //ブロックを消す
                                        _setBlock(0, fieldArr, tx, ty)

                                        _getBlockPicture(pid, tx, ty)
                                        _V2_getBlockPosition(sx, tx, ty)
                                        @pic.show [pid] .pos(sx, sy) .cell(0) chipPicCmd

                                        //ブロックを置く
                                        _setBlock(cell, fieldArr, ix, iy)

                                        //ピクチャを落下させる
                                        //移動時間
                                        time = abs(ty - iy) * FALL_TIME

                                        //落下しきるまでの時間(f)
                                        waitTime = max(waitTime, time)

                                        //ピクチャの移動時間をフレーム単位で指定する
                                        time *= -1

                                        _getBlockPicture(pid, ix, iy)
                                        _V2_getBlockPosition(sx, tx, ty)
                                        @pic.show [pid] .pos(sx, sy) .cell(cell) chipPicCmd
                                        _V2_getBlockPosition(sx, ix, iy)
                                        @pic.move [pid] .pos(sx, sy) .time(time)

                                        @break
                                    }
                                }
                            }
                        }
                    }
                }

                //左に詰める
                @if sceneTimer > waitTime bl {
                    _setSceneState(SCENE_PAD)
                }

            //左に詰める
            } .elif sceneState == SCENE_PAD bl {
                @if sceneTimer == 0 bl {
                    waitTime = 0
                    @loop FIELD_WIDTH .dst(ix) bl {
                        //列を調べてブロックがあるかどうか調べる
                        @loop FIELD_HEIGHT .dst(iy) bl {
                            _getBlock(cell, fieldArr, ix, iy)
                            @if cell > 0 bl {
                                //ある場合は詰められないので、その列での処理は終わる
                                @continue(2)
                            }
                        }

                        //なかった場合、右の列を調べる
                        @loop FIELD_WIDTH .dst(tx) bl {
                            tx += ix + 1
                            @if `tx > FIELD_WIDTH - 1 bl {
                                //詰めるべき列が見つからなかったので、反復処理が終わる
                                @break(2)
                            }

                            //列を調べる
                            @loop FIELD_HEIGHT .dst(ty) bl {
                                _getBlock(cell, fieldArr, tx, ty)
                                @if cell > 0 bl {
                                    //詰めるべき列を見つけた
                                    @break(2)
                                }
                            }
                        }

                        //ixの列にtxの列を詰める
                        @loop FIELD_HEIGHT .dst(ty) bl {
                            iy = ty
                            //空白でない
                            _getBlock(cell, fieldArr, tx, ty)
                            @if cell > 0 bl {
                                //ブロックを消す
                                _setBlock( 0, fieldArr, tx, ty)

                                _getBlockPicture(pid, tx, ty)
                                _V2_getBlockPosition(sx, tx, ty)
                                @pic.show [pid] .pos(sx, sy) .cell(0) chipPicCmd

                                //ブロックを置く
                                _setBlock(cell, fieldArr, ix, iy)

                                //ピクチャを詰める
                                //移動時間
                                time = abs(tx - ix) * FALL_TIME

                                //移動が終わるまでの時間(f)
                                waitTime = max(waitTime, time)

                                //ピクチャの移動時間をフレーム単位で指定する
                                time *= -1

                                _getBlockPicture(pid, ix, iy)
                                _V2_getBlockPosition(sx, tx, ty)
                                @pic.show [pid] .pos(sx, sy) .cell(cell) chipPicCmd
                                _V2_getBlockPosition(sx, ix, iy)
                                @pic.move [pid] .pos(sx, sy) .time(time)
                            }
                        }
                    }
                }

                @if sceneTimer > waitTime bl {
                    //ノルマを達成すると次のターンへ
                    @if quotaNumber <= 0 bl {
                        _setSceneState(SCENE_NEXT_TURN)
                    //選択を待つ
                    } .else bl {
                        _setSceneState(SCENE_SELECT)
                    }
                }
            }

            //----------------------------
            //花火
            @if `fireTimer <= 0 && fireCounter > 0 bl {
                fireCounter -= 1

                fireTimer = 1
                fireX = rnd(160 - 64,160 + 64)
                fireY = rnd(120 - 80,120 + 40)

                //色を設定する
                ix = rnd(0, 5)
                tx = [200, 200,  80,  80,  80, 200][ix]
                ty = [ 80, 200, 200, 200,  80,  80][ix]
                sx = [ 80,  80,  80, 200, 200, 200][ix]
                sy = 100

                @loop FIRE_NUM .dst(ix) bl {
                    pid = PIC_FIRE + ix
                    @pic.move [pid] .pos(OUT_RANGE, OUT_RANGE) .scale(100) .trans(100) .rgbs(tx, ty, sx, sy) .keepBlend
                }

            } .elif fireTimer > 0 bl {
                fireTimer += 1
                //花火を消す
                @if fireTimer > 32 bl {
                    fireTimer = 0
                    @loop FIRE_NUM .dst(ix) bl {
                        pid = PIC_FIRE + ix
                        @pic.move [pid] .pos(OUT_RANGE, OUT_RANGE) .scale(100) .trans(100) .keepBlend .keepRgbs
                    }

                //落下
                } .else bl {
                    @loop FIRE_NUM .dst(ix) bl {
                        //angle
                        tx = (ix % 8) * (360 / 8)
                        //radius
                        ty = fireTimer * 4 - fireTimer * fireTimer / 16 - (ix / 8) * 12
                        //position
                        V2_getCosSin(sx, tx, 1, 8 + ty)
                        V2_asAdd(sx, fireX)
                        //scale
                        iy = max(100 - fireTimer * 2 - (ix / 8) * 20, 10)

                        pid = PIC_FIRE + ix
                        @pic.move [pid] .pos(sx, sy) .scale(iy) .trans(0) .keepBlend .keepRgbs
                    }

                    //少し落ちる
                    @if `!(fireTimer % 2) && fireTimer > 16 bl {
                        fireY += 1
                    }
                }
            }

            //----------------------------
            //トリガー
            @if `triggerFlg bl {
                //ノルマ
                @if `triggerFlg & TR_BIT_QUOTA bl {
                    bitOff(triggerFlg, TR_BIT_QUOTA)
                    _showCounter(quotaNumber, 1, PIC_QUOTA, QUOTA_DIGIT, QUOTA_X, QUOTA_Y)
                }

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

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

                //追加スコア
                @if `triggerFlg & TR_BIT_ADDSCORE bl {
                    bitOff(triggerFlg, TR_BIT_ADDSCORE)
                    //加算量はゼロ以下の場合はピクチャを消去する
                    @if addScore <= 0 bl {
                        @loop SCORE_DIGIT .dst(pid) bl {
                            pid += PIC_ADDSCORE
                            @pic.move [pid] .pos(OUT_RANGE, OUT_RANGE) .scale(100) .trans(100) .time(0)
                        }

                        @loop ERASE_DIGIT .dst(pid) bl {
                            pid += PIC_ERASE
                            @pic.move [pid] .pos(OUT_RANGE, OUT_RANGE) .scale(100) .trans(100) .time(0)
                        }
                        
                    } .else bl {
                        //追加スコア
                        _showCounter(addScore, 2, PIC_ADDSCORE, SCORE_DIGIT, ADDSCORE_X, ADDSCORE_Y)
                        //消去数
                        _showCounter(eraseNumber, 2, PIC_ERASE, ERASE_DIGIT, ERASE_X, ERASE_Y)
                    }
                }
            }
        }
    }

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

        initPicturesAndVariables(PIC_HEAD, NUM_OF_PIC, TV_MINIGAME, NUM_OF_VAR, 0, 0)
        @scr.tint .rgbs(100, 100, 100, 100) .time(1) .wait
    }
}