tetris-fumen
Version:
Fumen parser for tetris
337 lines (336 loc) • 13.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getPieces = exports.getBlocks = exports.getBlockXYs = exports.getBlockPositions = exports.PlayField = exports.InnerField = exports.createInnerField = exports.createNewInnerField = void 0;
var defines_1 = require("./defines");
var FieldConstants = {
Width: 10,
Height: 23,
PlayBlocks: 23 * 10, // Height * Width
};
function createNewInnerField() {
return new InnerField({});
}
exports.createNewInnerField = createNewInnerField;
function createInnerField(field) {
var innerField = new InnerField({});
for (var y = -1; y < FieldConstants.Height; y += 1) {
for (var x = 0; x < FieldConstants.Width; x += 1) {
var at = field.at(x, y);
innerField.setNumberAt(x, y, (0, defines_1.parsePiece)(at));
}
}
return innerField;
}
exports.createInnerField = createInnerField;
var InnerField = /** @class */ (function () {
function InnerField(_a) {
var _b = _a.field, field = _b === void 0 ? InnerField.create(FieldConstants.PlayBlocks) : _b, _c = _a.garbage, garbage = _c === void 0 ? InnerField.create(FieldConstants.Width) : _c;
this.field = field;
this.garbage = garbage;
}
InnerField.create = function (length) {
return new PlayField({ length: length });
};
InnerField.prototype.fill = function (operation) {
this.field.fill(operation);
};
InnerField.prototype.fillAll = function (positions, type) {
this.field.fillAll(positions, type);
};
InnerField.prototype.canFill = function (piece, rotation, x, y) {
var _this = this;
var positions = getBlockPositions(piece, rotation, x, y);
return positions.every(function (_a) {
var px = _a[0], py = _a[1];
return 0 <= px && px < 10
&& 0 <= py && py < FieldConstants.Height
&& _this.getNumberAt(px, py) === defines_1.Piece.Empty;
});
};
InnerField.prototype.canFillAll = function (positions) {
var _this = this;
return positions.every(function (_a) {
var x = _a.x, y = _a.y;
return 0 <= x && x < 10
&& 0 <= y && y < FieldConstants.Height
&& _this.getNumberAt(x, y) === defines_1.Piece.Empty;
});
};
InnerField.prototype.isOnGround = function (piece, rotation, x, y) {
return !this.canFill(piece, rotation, x, y - 1);
};
InnerField.prototype.clearLine = function () {
this.field.clearLine();
};
InnerField.prototype.riseGarbage = function () {
this.field.up(this.garbage);
this.garbage.clearAll();
};
InnerField.prototype.mirror = function () {
this.field.mirror();
};
InnerField.prototype.shiftToLeft = function () {
this.field.shiftToLeft();
};
InnerField.prototype.shiftToRight = function () {
this.field.shiftToRight();
};
InnerField.prototype.shiftToUp = function () {
this.field.shiftToUp();
};
InnerField.prototype.shiftToBottom = function () {
this.field.shiftToBottom();
};
InnerField.prototype.copy = function () {
return new InnerField({ field: this.field.copy(), garbage: this.garbage.copy() });
};
InnerField.prototype.equals = function (other) {
return this.field.equals(other.field) && this.garbage.equals(other.garbage);
};
InnerField.prototype.addNumber = function (x, y, value) {
if (0 <= y) {
this.field.addOffset(x, y, value);
}
else {
this.garbage.addOffset(x, -(y + 1), value);
}
};
InnerField.prototype.setNumberFieldAt = function (index, value) {
this.field.setAt(index, value);
};
InnerField.prototype.setNumberGarbageAt = function (index, value) {
this.garbage.setAt(index, value);
};
InnerField.prototype.setNumberAt = function (x, y, value) {
return 0 <= y ? this.field.set(x, y, value) : this.garbage.set(x, -(y + 1), value);
};
InnerField.prototype.getNumberAt = function (x, y) {
return 0 <= y ? this.field.get(x, y) : this.garbage.get(x, -(y + 1));
};
InnerField.prototype.getNumberAtIndex = function (index, isField) {
if (isField) {
return this.getNumberAt(index % 10, Math.floor(index / 10));
}
return this.getNumberAt(index % 10, -(Math.floor(index / 10) + 1));
};
InnerField.prototype.toFieldNumberArray = function () {
return this.field.toArray();
};
InnerField.prototype.toGarbageNumberArray = function () {
return this.garbage.toArray();
};
return InnerField;
}());
exports.InnerField = InnerField;
var PlayField = /** @class */ (function () {
function PlayField(_a) {
var pieces = _a.pieces, _b = _a.length, length = _b === void 0 ? FieldConstants.PlayBlocks : _b;
if (pieces !== undefined) {
this.pieces = pieces;
}
else {
this.pieces = Array.from({ length: length }).map(function () { return defines_1.Piece.Empty; });
}
this.length = length;
}
PlayField.load = function () {
var lines = [];
for (var _i = 0; _i < arguments.length; _i++) {
lines[_i] = arguments[_i];
}
var blocks = lines.join('').trim();
return PlayField.loadInner(blocks);
};
PlayField.loadMinify = function () {
var lines = [];
for (var _i = 0; _i < arguments.length; _i++) {
lines[_i] = arguments[_i];
}
var blocks = lines.join('').trim();
return PlayField.loadInner(blocks, blocks.length);
};
PlayField.loadInner = function (blocks, length) {
var len = length !== undefined ? length : blocks.length;
if (len % 10 !== 0) {
throw new Error('Num of blocks in field should be mod 10');
}
var field = length !== undefined ? new PlayField({ length: length }) : new PlayField({});
for (var index = 0; index < len; index += 1) {
var block = blocks[index];
field.set(index % 10, Math.floor((len - index - 1) / 10), (0, defines_1.parsePiece)(block));
}
return field;
};
PlayField.prototype.get = function (x, y) {
return this.pieces[x + y * FieldConstants.Width];
};
PlayField.prototype.addOffset = function (x, y, value) {
this.pieces[x + y * FieldConstants.Width] += value;
};
PlayField.prototype.set = function (x, y, piece) {
this.setAt(x + y * FieldConstants.Width, piece);
};
PlayField.prototype.setAt = function (index, piece) {
this.pieces[index] = piece;
};
PlayField.prototype.fill = function (_a) {
var type = _a.type, rotation = _a.rotation, x = _a.x, y = _a.y;
var blocks = getBlocks(type, rotation);
for (var _i = 0, blocks_1 = blocks; _i < blocks_1.length; _i++) {
var block = blocks_1[_i];
var _b = [x + block[0], y + block[1]], nx = _b[0], ny = _b[1];
this.set(nx, ny, type);
}
};
PlayField.prototype.fillAll = function (positions, type) {
for (var _i = 0, positions_1 = positions; _i < positions_1.length; _i++) {
var _a = positions_1[_i], x = _a.x, y = _a.y;
this.set(x, y, type);
}
};
PlayField.prototype.clearLine = function () {
var newField = this.pieces.concat();
var top = this.pieces.length / FieldConstants.Width - 1;
for (var y = top; 0 <= y; y -= 1) {
var line = this.pieces.slice(y * FieldConstants.Width, (y + 1) * FieldConstants.Width);
var isFilled = line.every(function (value) { return value !== defines_1.Piece.Empty; });
if (isFilled) {
var bottom = newField.slice(0, y * FieldConstants.Width);
var over = newField.slice((y + 1) * FieldConstants.Width);
newField = bottom.concat(over, Array.from({ length: FieldConstants.Width }).map(function () { return defines_1.Piece.Empty; }));
}
}
this.pieces = newField;
};
PlayField.prototype.up = function (blockUp) {
this.pieces = blockUp.pieces.concat(this.pieces).slice(0, this.length);
};
PlayField.prototype.mirror = function () {
var newField = [];
for (var y = 0; y < this.pieces.length; y += 1) {
var line = this.pieces.slice(y * FieldConstants.Width, (y + 1) * FieldConstants.Width);
line.reverse();
for (var _i = 0, line_1 = line; _i < line_1.length; _i++) {
var obj = line_1[_i];
newField.push(obj);
}
}
this.pieces = newField;
};
PlayField.prototype.shiftToLeft = function () {
var height = this.pieces.length / 10;
for (var y = 0; y < height; y += 1) {
for (var x = 0; x < FieldConstants.Width - 1; x += 1) {
this.pieces[x + y * FieldConstants.Width] = this.pieces[x + 1 + y * FieldConstants.Width];
}
this.pieces[9 + y * FieldConstants.Width] = defines_1.Piece.Empty;
}
};
PlayField.prototype.shiftToRight = function () {
var height = this.pieces.length / 10;
for (var y = 0; y < height; y += 1) {
for (var x = FieldConstants.Width - 1; 1 <= x; x -= 1) {
this.pieces[x + y * FieldConstants.Width] = this.pieces[x - 1 + y * FieldConstants.Width];
}
this.pieces[y * FieldConstants.Width] = defines_1.Piece.Empty;
}
};
PlayField.prototype.shiftToUp = function () {
var blanks = Array.from({ length: 10 }).map(function () { return defines_1.Piece.Empty; });
this.pieces = blanks.concat(this.pieces).slice(0, this.length);
};
PlayField.prototype.shiftToBottom = function () {
var blanks = Array.from({ length: 10 }).map(function () { return defines_1.Piece.Empty; });
this.pieces = this.pieces.slice(10, this.length).concat(blanks);
};
PlayField.prototype.toArray = function () {
return this.pieces.concat();
};
Object.defineProperty(PlayField.prototype, "numOfBlocks", {
get: function () {
return this.pieces.length;
},
enumerable: false,
configurable: true
});
PlayField.prototype.copy = function () {
return new PlayField({ pieces: this.pieces.concat(), length: this.length });
};
PlayField.prototype.toShallowArray = function () {
return this.pieces;
};
PlayField.prototype.clearAll = function () {
this.pieces = this.pieces.map(function () { return defines_1.Piece.Empty; });
};
PlayField.prototype.equals = function (other) {
if (this.pieces.length !== other.pieces.length) {
return false;
}
for (var index = 0; index < this.pieces.length; index += 1) {
if (this.pieces[index] !== other.pieces[index]) {
return false;
}
}
return true;
};
return PlayField;
}());
exports.PlayField = PlayField;
function getBlockPositions(piece, rotation, x, y) {
return getBlocks(piece, rotation).map(function (position) {
position[0] += x;
position[1] += y;
return position;
});
}
exports.getBlockPositions = getBlockPositions;
function getBlockXYs(piece, rotation, x, y) {
return getBlocks(piece, rotation).map(function (position) {
return { x: position[0] + x, y: position[1] + y };
});
}
exports.getBlockXYs = getBlockXYs;
function getBlocks(piece, rotation) {
var blocks = getPieces(piece);
switch (rotation) {
case defines_1.Rotation.Spawn:
return blocks;
case defines_1.Rotation.Left:
return rotateLeft(blocks);
case defines_1.Rotation.Reverse:
return rotateReverse(blocks);
case defines_1.Rotation.Right:
return rotateRight(blocks);
}
throw new Error('Unsupported block');
}
exports.getBlocks = getBlocks;
function getPieces(piece) {
switch (piece) {
case defines_1.Piece.I:
return [[0, 0], [-1, 0], [1, 0], [2, 0]];
case defines_1.Piece.T:
return [[0, 0], [-1, 0], [1, 0], [0, 1]];
case defines_1.Piece.O:
return [[0, 0], [1, 0], [0, 1], [1, 1]];
case defines_1.Piece.L:
return [[0, 0], [-1, 0], [1, 0], [1, 1]];
case defines_1.Piece.J:
return [[0, 0], [-1, 0], [1, 0], [-1, 1]];
case defines_1.Piece.S:
return [[0, 0], [-1, 0], [0, 1], [1, 1]];
case defines_1.Piece.Z:
return [[0, 0], [1, 0], [0, 1], [-1, 1]];
}
throw new Error('Unsupported rotation');
}
exports.getPieces = getPieces;
function rotateRight(positions) {
return positions.map(function (current) { return [current[1], -current[0]]; });
}
function rotateLeft(positions) {
return positions.map(function (current) { return [-current[1], current[0]]; });
}
function rotateReverse(positions) {
return positions.map(function (current) { return [-current[0], -current[1]]; });
}