(function() {"use strict";var __module = CC_EDITOR ? module : {exports:{}};var __filename = 'preview-scripts/assets/Script/Model/GameModel.js';var __require = CC_EDITOR ? function (request) {return cc.require(request, require);} : function (request) {return cc.require(request, __filename);};function __define (exports, require, module) {"use strict";
cc._RF.push(module, 'fb5f0xFexhNabDIchjtJi8l', 'GameModel', __filename);
// Script/Model/GameModel.ts

Object.defineProperty(exports, "__esModule", { value: true });
var CellModel_1 = require("./CellModel");
var ConstValue_1 = require("./ConstValue");
var Utils_1 = require("../Tools/Utils");
/**
 * 游戏数据模型
 */
var GameModel = /** @class */ (function () {
    function GameModel() {
        /**
         * 格子
         */
        this.cells = [];
        // cellBgs;
        this.lastPos = cc.p(-1, -1);
        this.cellTypeNum = ConstValue_1.TYPE_NUM;
        this.cellCreateType = [];
        this.changeModels = [];
        this.effectsQueue = [];
        this.curTime = 0;
        this.scores = {};
        this.round = 0;
        this.cellTypeCount = {};
        this.firstCellTypeLimit = 0;
        this.guideCells = [];
    }
    /**
     * 初始化
     * @param cellTypeNum 方块种类数量
     * @param firstCellTypeLimit 第一种方块类型数量的限制, 0则为不限制
     */
    GameModel.prototype.init = function (cellTypeNum, firstCellTypeLimit) {
        var _this = this;
        if (cellTypeNum === void 0) { cellTypeNum = ConstValue_1.TYPE_NUM; }
        if (firstCellTypeLimit === void 0) { firstCellTypeLimit = 0; }
        this.firstCellTypeLimit = firstCellTypeLimit;
        this.scores = {};
        Object.keys(ConstValue_1.CELL_TYPE).filter(function (o) { return !isNaN(parseInt(o)); }).forEach(function (key) { return _this.scores[key] = 0; });
        this.round = 0;
        this.cells = [];
        this.setCellTypeNum(cellTypeNum);
        for (var i = 1; i <= ConstValue_1.GRID_HEIGHT; i++) {
            this.cells[i] = [];
            for (var j = 1; j <= ConstValue_1.GRID_WIDTH; j++) {
                this.cells[i][j] = new CellModel_1.CellModel();
            }
        }
        for (var i = 1; i <= ConstValue_1.GRID_HEIGHT; i++) {
            for (var j = 1; j <= ConstValue_1.GRID_WIDTH; j++) {
                var cell = this.cells[i][j];
                if (cell.isInitialized) {
                    continue;
                }
                var flag = true;
                while (flag) {
                    flag = false;
                    cell.init(this.getRandomCellType());
                    var pos = cc.p(j, i);
                    var result = this.checkPoint(pos)[0];
                    if (result.length > 2) {
                        flag = true;
                    }
                    cell.setXY(pos);
                    cell.setStartXY(pos);
                }
            }
        }
        //this.generateGuideCells(); 
    };
    GameModel.prototype.generateGuideCells = function () {
        var pos = [cc.p(3, 2), cc.p(4, 3), cc.p(4, 4)];
        var type = this.getRandomCellType();
        for (var i = 0; i < 3; i++) {
            this.guideCells[i] = this.cells[pos[i].y][pos[i].x];
            this.guideCells[i].init(type);
            this.guideCells[i].setStartXY(pos[i]);
            this.guideCells[i].setXY(pos[i]);
            this.guideCells[i].isGuide = true;
        }
        var down = this.cells[1][4];
        var right = this.cells[2][5];
        down.init(this.generateOtherType(type));
        right.init(this.generateOtherType(type));
        down.setStartXY(cc.p(4, 1));
        down.setXY(cc.p(4, 1));
        right.setStartXY(cc.p(5, 2));
        right.setXY(cc.p(5, 2));
    };
    GameModel.prototype.generateOtherType = function (type) {
        var newType = this.getRandomCellType();
        while (newType === type) {
            newType = this.getRandomCellType();
        }
        return newType;
    };
    GameModel.prototype.clearGuide = function () {
        if (this.guideCells.length > 0) {
            for (var _i = 0, _a = this.guideCells; _i < _a.length; _i++) {
                var c = _a[_i];
                c.isGuide = false;
            }
            this.guideCells.length = 0;
        }
    };
    /**
     * 设置方块种类数量
     * @param num 数量
     */
    GameModel.prototype.setCellTypeNum = function (num) {
        this.cellTypeNum = num;
        this.cellCreateType = [];
        this.cellTypeCount = {};
        for (var i = 1; i <= num; i++) {
            this.cellCreateType.push(i);
            // while (true) {
            //     let randomNum = GameUtils.randomInt(CELL_BASENUM) + 1;
            //     // let randomNum = i;
            //     if (!GameUtils.isInArray(this.cellCreateType, randomNum)) {
            //         this.cellCreateType.push(randomNum);
            //         break;
            //     }
            // }
        }
        // cc.log("cellCreateType", this.cellCreateType);
    };
    /**
     * 随机生成一个方块类型
     */
    GameModel.prototype.getRandomCellType = function () {
        var index = Utils_1.GameUtils.randomInt(this.cellTypeNum);
        var cellType = this.cellCreateType[index];
        if (!this.cellTypeCount[cellType])
            this.cellTypeCount[cellType] = 0;
        if (!this.firstCellTypeLimit || index !== 0 || this.cellTypeCount[cellType] < this.firstCellTypeLimit) {
            this.cellTypeCount[cellType] += 1;
            return cellType;
        }
        else {
            index = 1 + Utils_1.GameUtils.randomInt(this.cellTypeNum - 1);
            cellType = this.cellCreateType[index];
            this.cellTypeCount[cellType] = (this.cellTypeCount[cellType] || 0) + 1;
            return cellType;
        }
    };
    /**
     * 检查方块四周
     * @param p 方块坐标
     */
    GameModel.prototype.checkPoint = function (p) {
        var rowResult = this.checkWithDirection(p, [cc.p(1, 0), cc.p(-1, 0)]);
        var colResult = this.checkWithDirection(p, [cc.p(0, -1), cc.p(0, 1)]);
        var result = [];
        var newCellStatus = ConstValue_1.CELL_STATUS.COMMON;
        // 禁用大炸弹
        // if (rowResult.length >= 5 || colResult.length >= 5) {
        //     newCellStatus = CELL_STATUS.BIRD;
        // } else 
        // if (rowResult.length >= 3 && colResult.length >= 3) {
        //     newCellStatus = CELL_STATUS.WRAP;
        // } else if (rowResult.length >= 4) {
        //     newCellStatus = CELL_STATUS.LINE;
        // } else if (colResult.length >= 4) {
        //     newCellStatus = CELL_STATUS.COLUMN;
        // }
        if (rowResult.length >= 3) {
            result = rowResult;
        }
        if (colResult.length >= 3) {
            result = Utils_1.GameUtils.mergeArray(result, colResult);
        }
        return [result, newCellStatus, this.cells[p.y][p.x].type];
    };
    /**
     * 检查方块
     * @param p 方块坐标
     * @param directions 检查方向
     */
    GameModel.prototype.checkWithDirection = function (p, directions) {
        var queue = [];
        var vis = [];
        var front = 0;
        vis[p.x + (p.y - 1) * ConstValue_1.GRID_WIDTH] = true;
        queue.push(p);
        while (front < queue.length) {
            //let direction = [cc.p(0, -1), cc.p(0, 1), cc.p(1, 0), cc.p(-1, 0)];
            var point = queue[front];
            var cellModel = this.cells[point.y][point.x];
            front++;
            if (!cellModel) {
                continue;
            }
            for (var _i = 0, directions_1 = directions; _i < directions_1.length; _i++) {
                var direction = directions_1[_i];
                var tmpX = point.x + direction.x;
                var tmpY = point.y + direction.y;
                if (tmpX < 1 || tmpX > ConstValue_1.GRID_WIDTH
                    || tmpY < 1 || tmpY > ConstValue_1.GRID_HEIGHT
                    || vis[tmpX + (tmpY - 1) * ConstValue_1.GRID_WIDTH]
                    || !this.cells[tmpY][tmpX]) {
                    continue;
                }
                if (cellModel.type == this.cells[tmpY][tmpX].type) {
                    vis[tmpX + (tmpY - 1) * ConstValue_1.GRID_WIDTH] = true;
                    queue.push(cc.p(tmpX, tmpY));
                }
            }
        }
        return queue;
    };
    GameModel.prototype.printInfo = function () {
        for (var i = 1; i <= ConstValue_1.GRID_WIDTH; i++) {
            var printStr = "";
            for (var j = 1; j <= ConstValue_1.GRID_HEIGHT; j++) {
                printStr += this.cells[i][j].type + " ";
            }
            console.log(printStr);
        }
    };
    GameModel.prototype.getCells = function () {
        return this.cells;
    };
    /**
     * 选中方块
     * @param pos 坐标
     */
    GameModel.prototype.selectCell = function (pos) {
        this.changeModels = []; // 发生改变的model，将作为返回值，给view播动作
        this.effectsQueue = []; // 动物消失，爆炸等特效
        var lastPos = this.lastPos;
        // 检查是否为相邻方块
        var delta = Math.abs(pos.x - lastPos.x) + Math.abs(pos.y - lastPos.y);
        if (delta !== 1) {
            this.lastPos = pos;
            return [[], []];
        }
        this.exchangeCell(lastPos, pos);
        var result1 = this.checkPoint(pos)[0];
        var result2 = this.checkPoint(lastPos)[0];
        this.curTime = 0; // 动画播放的当前时间
        this.pushToChangeModels(this.cells[pos.y][pos.x]);
        this.pushToChangeModels(this.cells[lastPos.y][lastPos.x]);
        var isCanBomb = false;
        // let isCanBomb = (this.cells[pos.y][pos.x].status != CELL_STATUS.COMMON && // 判断两个是否是特殊的动物 
        //     this.cells[lastPos.y][lastPos.x].status != CELL_STATUS.COMMON) ||
        //     this.cells[pos.y][pos.x].status == CELL_STATUS.BIRD ||
        //     this.cells[lastPos.y][lastPos.x].status == CELL_STATUS.BIRD;
        if (result1.length < 3 && result2.length < 3 && !isCanBomb) { //不能消除的情况
            this.exchangeCell(lastPos, pos); //交换回去
            // 设置移动并弹回的动画
            this.cells[pos.y][pos.x].moveToAndBack(lastPos);
            this.cells[lastPos.y][lastPos.x].moveToAndBack(pos);
            this.lastPos = cc.p(-1, -1);
            return [this.changeModels, []];
        }
        else { //可以消除的情况
            // 设置移动动画
            this.cells[pos.y][pos.x].moveTo(pos, this.curTime);
            this.cells[lastPos.y][lastPos.x].moveTo(lastPos, this.curTime);
            var checkPoint = [pos, lastPos];
            this.curTime += ConstValue_1.ANITIME.TOUCH_MOVE;
            this.processCrush(checkPoint); //开始消除
            this.lastPos = cc.p(-1, -1);
            return [this.changeModels, this.effectsQueue];
        }
    };
    /**
     * 交换方块位置
     * @param pos1
     * @param pos2
     */
    GameModel.prototype.exchangeCell = function (pos1, pos2) {
        var cell1 = this.cells[pos1.y][pos1.x];
        var cell2 = this.cells[pos2.y][pos2.x];
        cell1.x = pos2.x;
        cell1.y = pos2.y;
        cell2.x = pos1.x;
        cell2.y = pos1.y;
        this.cells[pos1.y][pos1.x] = cell2;
        this.cells[pos2.y][pos2.x] = cell1;
    };
    /**
     * 清除命令序列
     */
    GameModel.prototype.cleanCmd = function () {
        this.cells.forEach(function (row) { return row.forEach(function (c) { return c.cmd = []; }); });
    };
    /**
     * 添加到变化模型数组
     * @param model
     */
    GameModel.prototype.pushToChangeModels = function (model) {
        Utils_1.GameUtils.addToArray(this.changeModels, model);
    };
    /**
     * 下落生成新的方块
     */
    GameModel.prototype.down = function () {
        var newCheckPoint = []; // 需要检查的方块数组
        for (var i = 1; i <= ConstValue_1.GRID_HEIGHT; i++) {
            for (var j = 1; j <= ConstValue_1.GRID_WIDTH; j++) {
                if (!this.cells[i][j]) { // 为空
                    // 从当前位置向上处理落下
                    var curRow = i;
                    for (var k = curRow; k <= ConstValue_1.GRID_HEIGHT; k++) {
                        var curCell = this.cells[k][j];
                        if (curCell) { // 存在方块就落下
                            this.cells[curRow][j] = curCell;
                            this.cells[k][j] = null;
                            this.pushToChangeModels(curCell);
                            // newCheckPoint.push(curCell);
                            Utils_1.GameUtils.addToArray(newCheckPoint, curCell);
                            // 向下落
                            var pos = cc.p(j, curRow);
                            curCell.setXY(pos);
                            curCell.moveTo(pos, this.curTime);
                            curRow++;
                        }
                    }
                    // 生成新方块
                    var count = 1;
                    for (var k = curRow; k <= ConstValue_1.GRID_HEIGHT; k++) {
                        var newCell = new CellModel_1.CellModel();
                        newCell.init(this.getRandomCellType());
                        // 将方块的开始位置设置在矩阵外，并且排队，准备依次落下
                        var pos = cc.p(j, count + ConstValue_1.GRID_HEIGHT);
                        newCell.setStartXY(pos);
                        newCell.setXY(pos);
                        // 设置方块应该落到的位置
                        newCell.moveTo(cc.p(j, k), this.curTime);
                        count++; //用于排列，防止坐标重合
                        this.cells[k][j] = newCell;
                        this.changeModels.push(newCell);
                        newCheckPoint.push(newCell);
                        newCell.round = this.round;
                    }
                }
            }
        }
        this.curTime += ConstValue_1.ANITIME.TOUCH_MOVE + 0.3;
        return newCheckPoint;
    };
    /**
     * 创建新的方块
     * @param pos 坐标
     * @param status 状态
     * @param type 类型
     */
    GameModel.prototype.createNewCell = function (pos, status, type) {
        if (status == null) {
            return;
        }
        if (status == ConstValue_1.CELL_STATUS.BIRD) {
            type = ConstValue_1.CELL_TYPE.BIRD;
        }
        var model = new CellModel_1.CellModel();
        this.cells[pos.y][pos.x] = model;
        model.init(type);
        model.setStartXY(pos);
        model.setXY(pos);
        model.setStatus(status);
        model.setVisible(0, false);
        model.setVisible(this.curTime, true);
        this.changeModels.push(model);
        model.round = this.round;
        return model;
    };
    /**
     * 处理消除
     * @param checkPoints 检查点
     */
    GameModel.prototype.processCrush = function (checkPoints) {
        var cycleCount = 0; // 循环处理次数
        while (checkPoints.length > 0) {
            this.round++;
            var bombModels = []; // 炸弹方块
            // if (cycleCount == 0 && checkPoints.length == 2) { //特殊消除
            //     let pos1 = checkPoints[0];
            //     let pos2 = checkPoints[1];
            //     let model1 = this.cells[pos1.y][pos1.x];
            //     let model2 = this.cells[pos2.y][pos2.x];
            //     if (model1.status == CELL_STATUS.BIRD && model2.status == CELL_STATUS.BIRD) {
            //         bombModels.push(model1);
            //         bombModels.push(model2);
            //     }
            //     else if (model1.status === CELL_STATUS.BIRD && model2.status !== CELL_STATUS.COMMON) {
            //         for (let i = 1; i <= GRID_HEIGHT; i++) {
            //             for (let j = 1; j <= GRID_WIDTH; j++) {
            //                 let cell = this.cells[i][j];
            //                 if (cell.type === model2.type) {
            //                     cell.statusTo(model2.status, this.curTime);
            //                 }
            //                 // bombModels.push(cell);
            //             }
            //         }
            //         model1.type = model2.type;
            //         bombModels.push(model1);
            //     } else if (model2.status === CELL_STATUS.BIRD && model1.status !== CELL_STATUS.COMMON) {
            //         for (let i = 1; i <= GRID_HEIGHT; i++) {
            //             for (let j = 1; j <= GRID_WIDTH; j++) {
            //                 let cell = this.cells[i][j];
            //                 if (cell.type === model1.type) {
            //                     cell.statusTo(model1.status, this.curTime);
            //                 }
            //                 // bombModels.push(cell);
            //             }
            //         }
            //         model2.type = model1.type;
            //         bombModels.push(model2);
            //     }
            //     else if (model1.status == CELL_STATUS.BIRD || model2.status == CELL_STATUS.BIRD) {
            //         // let bombModel = null;
            //         if (model1.status == CELL_STATUS.BIRD) {
            //             model1.type = model2.type;
            //             bombModels.push(model1);
            //         } else {
            //             model2.type = model1.type;
            //             bombModels.push(model2);
            //         }
            //     } else if (model1.status !== CELL_STATUS.COMMON && model2.status !== CELL_STATUS.COMMON) {
            //         bombModels.push(model1);
            //         bombModels.push(model2);
            //     }
            // }
            for (var _i = 0, checkPoints_1 = checkPoints; _i < checkPoints_1.length; _i++) {
                var pos = checkPoints_1[_i];
                if (!this.cells[pos.y][pos.x]) {
                    continue;
                }
                if (pos instanceof CellModel_1.CellModel) {
                    pos = cc.p(pos.x, pos.y);
                }
                var _a = this.checkPoint(pos), result = _a[0], newCellStatus = _a[1], newCellType = _a[2];
                // 小于3个不能消除，跳过
                if (result.length < 3) {
                    continue;
                }
                if (this.crushCallback) {
                    this.crushCallback(cycleCount);
                }
                for (var _b = 0, result_1 = result; _b < result_1.length; _b++) {
                    var p = result_1[_b];
                    var model = this.cells[p.y][p.x];
                    if (model && model.round !== this.round) {
                        this.crushCell(p);
                        if (model.status != ConstValue_1.CELL_STATUS.COMMON) {
                            bombModels.push(model);
                        }
                    }
                }
                // bombModels=[]
                if (newCellStatus !== ConstValue_1.CELL_STATUS.COMMON) {
                    this.createNewCell(pos, newCellStatus, newCellType);
                }
            }
            // this.processBomb(bombModels); // 处理炸弹
            this.curTime += ConstValue_1.ANITIME.DIE;
            checkPoints = this.down(); // 生成新方块
            cycleCount++;
        }
    };
    // 判断棋盘是否无解
    GameModel.prototype.isUnSolvable = function () {
        if (true) {
            this.init(ConstValue_1.TYPE_NUM, this.firstCellTypeLimit);
        }
    };
    /**
     * 处理炸弹
     * @param bombModels 炸弹方块
     */
    GameModel.prototype.processBomb = function (bombModels) {
        var _this = this;
        var _loop_1 = function () {
            var newBombModel = [];
            var bombTime = ConstValue_1.ANITIME.BOMB_DELAY;
            var callCrushCell = function (x, y, model, crushType) {
                if (_this.cells[y][x] && _this.cells[y][x].round !== _this.round) {
                    if (crushType && _this.cells[y][x].type !== crushType) {
                        return;
                    }
                    if (_this.cells[y][x].status === ConstValue_1.CELL_STATUS.BIRD) {
                        _this.cells[y][x].type = model.type;
                    }
                    if (_this.cells[y][x].status != ConstValue_1.CELL_STATUS.COMMON) {
                        newBombModel.push(_this.cells[y][x]);
                    }
                    _this.crushCell(cc.p(x, y), !!crushType && model.status === ConstValue_1.CELL_STATUS.COMMON);
                }
            };
            for (var _i = 0, bombModels_1 = bombModels; _i < bombModels_1.length; _i++) {
                var model = bombModels_1[_i];
                if (model.status == ConstValue_1.CELL_STATUS.LINE) {
                    for (var i = 1; i <= ConstValue_1.GRID_WIDTH; i++) {
                        callCrushCell(i, model.y, model);
                    }
                    this_1.addRowBomb(this_1.curTime, cc.p(model.x, model.y));
                }
                else if (model.status == ConstValue_1.CELL_STATUS.COLUMN) {
                    for (var i = 1; i <= ConstValue_1.GRID_HEIGHT; i++) {
                        callCrushCell(model.x, i, model);
                    }
                    this_1.addColBomb(this_1.curTime, cc.p(model.x, model.y));
                }
                else if (model.status == ConstValue_1.CELL_STATUS.WRAP) {
                    var x = model.x;
                    var y = model.y;
                    for (var i = 1; i <= ConstValue_1.GRID_HEIGHT; i++) {
                        for (var j = 1; j <= ConstValue_1.GRID_WIDTH; j++) {
                            var delta = Math.abs(x - j) + Math.abs(y - i);
                            if (delta <= 2) {
                                callCrushCell(j, i, model);
                            }
                        }
                    }
                }
                else if (model.status == ConstValue_1.CELL_STATUS.BIRD) {
                    var crushType = model.type;
                    if (bombTime < ConstValue_1.ANITIME.BOMB_BIRD_DELAY) {
                        bombTime = ConstValue_1.ANITIME.BOMB_BIRD_DELAY;
                    }
                    if (crushType == ConstValue_1.CELL_TYPE.BIRD) {
                        crushType = this_1.getRandomCellType();
                    }
                    for (var i = 1; i <= ConstValue_1.GRID_HEIGHT; i++) {
                        for (var j = 1; j <= ConstValue_1.GRID_WIDTH; j++) {
                            callCrushCell(j, i, model, crushType);
                        }
                    }
                    this_1.crushCell(cc.p(model.x, model.y));
                }
            }
            if (bombModels.length > 0) {
                this_1.curTime += bombTime;
            }
            bombModels = newBombModel;
        };
        var this_1 = this;
        while (bombModels.length > 0) {
            _loop_1();
        }
    };
    /**
     * 添加消除效果
     * @param playTime
     * @param pos
     */
    GameModel.prototype.addCrushEffect = function (playTime, pos) {
        this.effectsQueue.push({
            playTime: playTime, pos: pos,
            action: "crush"
        });
    };
    /**
     * 添加横向炸弹
     * @param playTime
     * @param pos
     */
    GameModel.prototype.addRowBomb = function (playTime, pos) {
        this.effectsQueue.push({
            playTime: playTime, pos: pos,
            action: "rowBomb"
        });
    };
    /**
     * 添加纵向炸弹
     * @param playTime
     * @param pos
     */
    GameModel.prototype.addColBomb = function (playTime, pos) {
        this.effectsQueue.push({
            playTime: playTime, pos: pos,
            action: "colBomb"
        });
    };
    GameModel.prototype.addWrapBomb = function (playTime, pos) {
        // TODO
    };
    /**
     * 消除方块
     * @param pos 方块坐标
     * @param needShake 是否抖动，默认否
     */
    GameModel.prototype.crushCell = function (pos, needShake) {
        if (needShake === void 0) { needShake = false; }
        var model = this.cells[pos.y][pos.x];
        if (!model)
            return; // 已经被消除了
        this.pushToChangeModels(model);
        if (needShake) {
            model.toShake(this.curTime);
            model.toDie(this.curTime + ConstValue_1.ANITIME.DIE_SHAKE / 2);
        }
        else {
            model.toDie(this.curTime);
        }
        this.addCrushEffect(this.curTime, pos);
        this.cells[pos.y][pos.x] = null;
    };
    GameModel.prototype.addScore = function (cellModel) {
        this.scores[cellModel.type]++;
    };
    GameModel.prototype.setCrushCallback = function (crushCallback) {
        this.crushCallback = crushCallback;
    };
    return GameModel;
}());
exports.GameModel = GameModel;

cc._RF.pop();
        }
        if (CC_EDITOR) {
            __define(__module.exports, __require, __module);
        }
        else {
            cc.registerModuleFunc(__filename, function () {
                __define(__module.exports, __require, __module);
            });
        }
        })();
        //# sourceMappingURL=GameModel.js.map
        