UNPKG

@haelp/teto

Version:

A typescript-based controllable TETR.IO client.

2,980 lines (2,970 loc) 134 kB
// src/utils/events.ts var EventEmitter = class { #listeners; #maxListeners = 10; /** Enables more debugging logs for memory leaks */ verbose = false; constructor() { this.#listeners = []; } on(event, cb) { this.#listeners.push([event, cb, false]); const listeners = this.#listeners.filter(([e]) => e === event); if (listeners.length > this.#maxListeners) { console.warn( `Max listeners exceeded for event "${String(event)}". Current: ${this.#listeners.filter(([e]) => e === event).length}, Max: ${this.#maxListeners}` ); if (this.verbose) console.warn( `Trace: ${new Error().stack} Listeners: `, listeners.map(([_, fn]) => fn.toString()).join("\n\n") ); } return this; } off(event, cb) { this.#listeners = this.#listeners.filter( ([e, c]) => e !== event || c !== cb ); return this; } emit(event, data) { const toRemove = /* @__PURE__ */ new Set(); this.#listeners.forEach(([e, cb, once], idx) => { if (e !== event) return; cb(data); if (once) toRemove.add(idx); }); this.#listeners = this.#listeners.filter((_, idx) => !toRemove.has(idx)); return this; } once(event, cb) { this.#listeners.push([event, cb, true]); return this; } removeAllListeners(event) { if (event) { this.#listeners = this.#listeners.filter(([e]) => e !== event); } else { this.#listeners = []; } } set maxListeners(n) { if (n <= 0 || !Number.isInteger(n)) { throw new RangeError("Max listeners must be a positive integer"); } this.#maxListeners = n; } get maxListeners() { return this.#maxListeners; } export() { return { listeners: this.#listeners.map(([event, cb, once]) => ({ event, cb, once })), maxListeners: this.#maxListeners, verbose: this.verbose }; } import(data) { data.listeners.forEach(({ event, cb, once }) => { if (once) { this.once(event, cb); } else { this.on(event, cb); } }); this.#maxListeners = data.maxListeners; this.verbose = data.verbose; return this; } }; // src/engine/queue/types.ts var Mino = /* @__PURE__ */ ((Mino2) => { Mino2["I"] = "i"; Mino2["J"] = "j"; Mino2["L"] = "l"; Mino2["O"] = "o"; Mino2["S"] = "s"; Mino2["T"] = "t"; Mino2["Z"] = "z"; Mino2["GARBAGE"] = "gb"; Mino2["BOMB"] = "bomb"; return Mino2; })(Mino || {}); // src/engine/board/index.ts var Board = class { state; _height; _width; _buffer; constructor(options) { this._width = options.width; this._height = options.height; this._buffer = options.buffer; this.state = Array(this.fullHeight).fill(null).map(() => Array(this.width).fill(null)); } get height() { return this._height; } set height(value) { this._height = value; } get width() { return this._width; } set width(value) { this._width = value; } get buffer() { return this._buffer; } set buffer(value) { this._buffer = value; } get fullHeight() { return this.height + this.buffer; } add(...blocks) { blocks.forEach(([char, x, y]) => { if (y < 0 || y >= this.fullHeight || x < 0 || x >= this.width) return; this.state[y][x] = char; }); } clearLines() { let garbageCleared = 0; const lines = []; this.state.forEach((row, idx) => { if (row.every((block) => block !== null && block !== "bomb" /* BOMB */)) { lines.push(idx); if (row.some((block) => block === "gb" /* GARBAGE */)) garbageCleared++; } }); [...lines].reverse().forEach((line) => { this.state.splice(line, 1); this.state.push(new Array(this.width).fill(null)); }); return { lines: lines.length, garbageCleared }; } clearBombs(placedBlocks) { let lowestY = placedBlocks.reduce( (acc, [_, y]) => Math.min(acc, y), this.fullHeight ); if (lowestY === 0) return { lines: 0, garbageCleared: 0 }; const lowestBlocks = placedBlocks.filter(([_, y]) => y === lowestY); const bombColumns = lowestBlocks.filter(([x, y]) => this.state[y - 1][x] === "bomb" /* BOMB */).map(([x, _]) => x); if (bombColumns.length === 0) return { lines: 0, garbageCleared: 0 }; const lines = []; while (lowestY > 0 && bombColumns.some((col) => this.state[lowestY - 1][col] === "bomb" /* BOMB */)) { lines.push(--lowestY); } if (lines.length === 0) return { lines: 0, garbageCleared: 0 }; lines.forEach((line) => { this.state.splice(line, 1); this.state.push(new Array(this.width).fill(null)); }); return { lines: lines.length, garbageCleared: lines.length }; } clearBombsAndLines(placedBlocks) { const bombs = this.clearBombs(placedBlocks); const lines = this.clearLines(); return { lines: lines.lines + bombs.lines, garbageCleared: bombs.garbageCleared + lines.garbageCleared }; } get perfectClear() { return this.state.every((row) => row.every((block) => block === null)); } insertGarbage({ amount, size, column, bombs }) { this.state.splice( 0, 0, ...Array.from( { length: amount }, () => Array.from( { length: this.width }, (_, idx) => idx >= column && idx < column + size ? bombs ? "bomb" /* BOMB */ : null : "gb" /* GARBAGE */ ) ) ); this.state.splice(this.fullHeight - amount - 1, amount); } }; // src/engine/constants/index.ts var constants; ((constants2) => { let flags; ((flags2) => { flags2.ROTATION_LEFT = 1; flags2.ROTATION_RIGHT = 2; flags2.ROTATION_180 = 4; flags2.ROTATION_SPIN = 8; flags2.ROTATION_MINI = 16; flags2.ROTATION_SPIN_ALL = 32; flags2.ROTATION_ALL = flags2.ROTATION_LEFT | flags2.ROTATION_RIGHT | flags2.ROTATION_180 | flags2.ROTATION_SPIN | flags2.ROTATION_MINI | flags2.ROTATION_SPIN_ALL; flags2.STATE_WALL = 64; flags2.STATE_SLEEP = 128; flags2.STATE_FLOOR = 256; flags2.STATE_NODRAW = 512; flags2.STATE_ALL = flags2.STATE_WALL | flags2.STATE_SLEEP | flags2.STATE_FLOOR | flags2.STATE_NODRAW; flags2.ACTION_IHS = 1024; flags2.ACTION_FORCELOCK = 2048; flags2.ACTION_SOFTDROP = 4096; flags2.ACTION_MOVE = 8192; flags2.ACTION_ROTATE = 16384; flags2.FLAGS_COUNT = 15; })(flags = constants2.flags || (constants2.flags = {})); })(constants || (constants = {})); // src/engine/utils/damageCalc/index.ts var garbageData = { single: 0, double: 1, triple: 2, quad: 4, penta: 5, tspinMini: 0, tspin: 0, tspinMiniSingle: 0, tspinSingle: 2, tspinMiniDouble: 1, tspinMiniTriple: 2, tspinDouble: 4, tspinTriple: 6, tspinQuad: 10, tspinPenta: 12, backtobackBonus: 1, backtobackBonusLog: 0.8, comboMinifier: 1, comboMinifierLog: 1.25, comboBonus: 0.25, allClear: 10, comboTable: { none: [0], "classic guideline": [0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5], "modern guideline": [0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4] } }; var garbageCalcV2 = (data, config) => { let garbage = 0; const { spin: rawSpin, lines, piece, combo, b2b, enemies } = data; const { spinBonuses, comboTable, garbageTargetBonus, b2b: b2bOptions } = config; const spin = rawSpin === "none" ? null : rawSpin; switch (lines) { case 0: garbage = spin === "mini" ? garbageData.tspinMini : spin === "normal" ? garbageData.tspin : 0; break; case 1: garbage = spin === "mini" ? garbageData.tspinMiniSingle : spin === "normal" ? garbageData.tspinSingle : garbageData.single; break; case 2: garbage = spin === "mini" ? garbageData.tspinMiniDouble : spin === "normal" ? garbageData.tspinDouble : garbageData.double; break; case 3: garbage = spin === "mini" ? garbageData.tspinMiniTriple : spin === "normal" ? garbageData.tspinTriple : garbageData.triple; break; case 4: garbage = spin ? garbageData.tspinQuad : garbageData.quad; break; case 5: garbage = spin ? garbageData.tspinPenta : garbageData.penta; break; default: { const t = lines - 5; garbage = spin ? garbageData.tspinPenta + 2 * t : garbageData.penta + t; break; } } if (spin && spinBonuses === "handheld" && piece.toUpperCase() !== "T") { garbage /= 2; } if (lines > 0 && b2b > 0) { if (b2bOptions.chaining) { const b2bGains = garbageData.backtobackBonus * (Math.floor(1 + Math.log1p(b2b * garbageData.backtobackBonusLog)) + (b2b == 1 ? 0 : (1 + Math.log1p(b2b * garbageData.backtobackBonusLog) % 1) / 3)); garbage += b2bGains; } else { garbage += garbageData.backtobackBonus; } } if (combo > 0) { if (comboTable === "multiplier") { garbage *= 1 + garbageData.comboBonus * combo; if (combo > 1) { garbage = Math.max( Math.log1p( garbageData.comboMinifier * combo * garbageData.comboMinifierLog ), garbage ); } } else { const comboTableData = garbageData.comboTable[comboTable] || [0]; garbage += comboTableData[Math.max(0, Math.min(combo - 1, comboTableData.length - 1))]; } } let garbageBonus = 0; if (lines > 0 && garbageTargetBonus !== "none") { let targetBonus = 0; switch (enemies) { case 0: case 1: break; case 2: targetBonus += 1; break; case 3: targetBonus += 3; break; case 4: targetBonus += 5; break; case 5: targetBonus += 7; break; default: targetBonus += 9; } if (garbageTargetBonus === "normal") { garbage += targetBonus; } else { garbageBonus = targetBonus; } } return { garbage, bonus: garbageBonus }; }; // src/engine/utils/increase/index.ts var IncreaseTracker = class { #value; base; increase; margin; frame; constructor(base, increase, margin) { this.#value = this.base = base; this.increase = increase; this.margin = margin; this.frame = 0; } reset() { this.#value = this.base; this.frame = 0; } tick() { this.frame++; if (this.frame > this.margin) this.#value += this.increase / 60; return this.get(); } get() { return this.#value; } set(value) { this.#value = value; } }; // src/engine/utils/kicks/data.ts var kicks = { SRS: { kicks: { "01": [ [-1, 0], [-1, -1], [0, 2], [-1, 2] ], 10: [ [1, 0], [1, 1], [0, -2], [1, -2] ], 12: [ [1, 0], [1, 1], [0, -2], [1, -2] ], 21: [ [-1, 0], [-1, -1], [0, 2], [-1, 2] ], 23: [ [1, 0], [1, -1], [0, 2], [1, 2] ], 32: [ [-1, 0], [-1, 1], [0, -2], [-1, -2] ], 30: [ [-1, 0], [-1, 1], [0, -2], [-1, -2] ], "03": [ [1, 0], [1, -1], [0, 2], [1, 2] ], "02": [ [0, -1], [1, -1], [-1, -1], [1, 0], [-1, 0] ], 13: [ [1, 0], [1, -2], [1, -1], [0, -2], [0, -1] ], 20: [ [0, 1], [-1, 1], [1, 1], [-1, 0], [1, 0] ], 31: [ [-1, 0], [-1, -2], [-1, -1], [0, -2], [0, -1] ] }, i_kicks: { "01": [ [-2, 0], [1, 0], [-2, 1], [1, -2] ], 10: [ [2, 0], [-1, 0], [2, -1], [-1, 2] ], 12: [ [-1, 0], [2, 0], [-1, -2], [2, 1] ], 21: [ [1, 0], [-2, 0], [1, 2], [-2, -1] ], 23: [ [2, 0], [-1, 0], [2, -1], [-1, 2] ], 32: [ [-2, 0], [1, 0], [-2, 1], [1, -2] ], 30: [ [1, 0], [-2, 0], [1, 2], [-2, -1] ], "03": [ [-1, 0], [2, 0], [-1, -2], [2, 1] ], "02": [], 13: [], 20: [], 31: [] }, i2_kicks: { "01": [ [0, -1], [-1, 0], [-1, -1] ], 10: [ [0, 1], [1, 0], [1, 1] ], 12: [ [1, 0], [0, -1], [1, 0] ], 21: [ [-1, 0], [0, 1], [-1, 0] ], 23: [ [0, 1], [1, 0], [1, -1] ], 32: [ [0, -1], [-1, 0], [-1, 1] ], 30: [ [-1, 0], [0, 1], [-1, 2] ], "03": [ [1, 0], [0, -1], [1, -2] ], "02": [], 13: [], 20: [], 31: [] }, i3_kicks: { "01": [ [1, 0], [-1, 0], [0, 1], [0, -1] ], 10: [ [-1, 0], [1, 0], [0, -1], [0, 1] ], 12: [ [1, 0], [-1, 0], [0, -2], [0, 2] ], 21: [ [-1, 0], [1, 0], [0, 2], [0, -2] ], 23: [ [-1, 0], [1, 0], [0, 1], [0, -1] ], 32: [ [1, 0], [-1, 0], [0, -1], [0, 1] ], 30: [ [-1, 0], [1, 0], [0, 0], [0, 0] ], "03": [ [1, 0], [-1, 0], [0, 0], [0, 0] ], "02": [], 13: [], 20: [], 31: [] }, l3_kicks: { "01": [ [-1, 0], [1, 0] ], 10: [ [1, 0], [-1, 0] ], 12: [ [0, -1], [0, 1] ], 21: [ [0, 1], [0, -1] ], 23: [ [1, 0], [-1, 0] ], 32: [ [-1, 0], [1, 0] ], 30: [ [0, 1], [0, -1] ], "03": [ [0, -1], [0, 1] ], "02": [], 13: [], 20: [], 31: [] }, i5_kicks: { "01": [ [-2, 0], [2, 0], [-2, 1], [2, -2] ], 10: [ [2, 0], [-2, 0], [2, -1], [-2, 2] ], 12: [ [-2, 0], [2, 0], [-2, -2], [2, 1] ], 21: [ [2, 0], [-2, 0], [2, 2], [-2, -1] ], 23: [ [2, 0], [-2, 0], [2, -1], [-2, 2] ], 32: [ [-2, 0], [2, 0], [-2, 1], [2, -2] ], 30: [ [2, 0], [-2, 0], [2, 2], [-2, -1] ], "03": [ [-2, 0], [2, 0], [-2, -2], [2, 1] ], "02": [], 13: [], 20: [], 31: [] }, oo_kicks: { "01": [ [0, -1], [-1, -1], [0, 1], [-1, 1], [1, 0], [1, -1], [1, 1] ], 10: [ [1, 0], [0, -1], [1, 1], [1, -1], [-1, 0], [-1, -1], [-1, 1] ], 12: [ [-1, 0], [0, -1], [-1, 1], [-1, -1], [1, 0], [1, -1], [1, 1] ], 21: [ [0, -1], [1, -1], [0, 1], [1, 1], [-1, 0], [-1, -1], [-1, 1] ], 23: [ [0, -1], [-1, -1], [0, 1], [-1, 1], [1, 0], [1, -1], [1, 1] ], 32: [ [1, 0], [0, -1], [1, 1], [1, -1], [-1, 0], [-1, -1], [-1, 1] ], 30: [ [-1, 0], [0, -1], [-1, 1], [-1, -1], [1, 0], [1, -1], [1, 1] ], "03": [ [0, -1], [1, -1], [0, 1], [1, 1], [-1, 0], [-1, -1], [-1, 1] ], "02": [[0, -1]], 13: [[1, 0]], 20: [[0, 1]], 31: [[-1, 0]] }, additional_offsets: {}, spawn_rotation: {}, colorMap: { i1: "i", i2: "i", i3: "i", l3: "j", i5: "i", z: "z", l: "l", o: "o", s: "s", i: "i", j: "j", t: "t", oo: "o", g: "g", d: "d", gb: "gb", gbd: "gbd" }, preview_overrides: {} }, "SRS+": { kicks: { "01": [ [-1, 0], [-1, -1], [0, 2], [-1, 2] ], 10: [ [1, 0], [1, 1], [0, -2], [1, -2] ], 12: [ [1, 0], [1, 1], [0, -2], [1, -2] ], 21: [ [-1, 0], [-1, -1], [0, 2], [-1, 2] ], 23: [ [1, 0], [1, -1], [0, 2], [1, 2] ], 32: [ [-1, 0], [-1, 1], [0, -2], [-1, -2] ], 30: [ [-1, 0], [-1, 1], [0, -2], [-1, -2] ], "03": [ [1, 0], [1, -1], [0, 2], [1, 2] ], "02": [ [0, -1], [1, -1], [-1, -1], [1, 0], [-1, 0] ], 13: [ [1, 0], [1, -2], [1, -1], [0, -2], [0, -1] ], 20: [ [0, 1], [-1, 1], [1, 1], [-1, 0], [1, 0] ], 31: [ [-1, 0], [-1, -2], [-1, -1], [0, -2], [0, -1] ] }, i_kicks: { "01": [ [1, 0], [-2, 0], [-2, 1], [1, -2] ], 10: [ [-1, 0], [2, 0], [-1, 2], [2, -1] ], 12: [ [-1, 0], [2, 0], [-1, -2], [2, 1] ], 21: [ [-2, 0], [1, 0], [-2, -1], [1, 2] ], 23: [ [2, 0], [-1, 0], [2, -1], [-1, 2] ], 32: [ [1, 0], [-2, 0], [1, -2], [-2, 1] ], 30: [ [1, 0], [-2, 0], [1, 2], [-2, -1] ], "03": [ [-1, 0], [2, 0], [2, 1], [-1, -2] ], "02": [[0, -1]], 13: [[1, 0]], 20: [[0, 1]], 31: [[-1, 0]] }, i2_kicks: { "01": [ [0, -1], [-1, 0], [-1, -1] ], 10: [ [0, 1], [1, 0], [1, 1] ], 12: [ [1, 0], [0, -1], [1, 0] ], 21: [ [-1, 0], [0, 1], [-1, 0] ], 23: [ [0, 1], [1, 0], [1, -1] ], 32: [ [0, -1], [-1, 0], [-1, 1] ], 30: [ [-1, 0], [0, 1], [-1, 2] ], "03": [ [1, 0], [0, -1], [1, -2] ], "02": [], 13: [], 20: [], 31: [] }, i3_kicks: { "01": [ [1, 0], [-1, 0], [0, 1], [0, -1] ], 10: [ [-1, 0], [1, 0], [0, -1], [0, 1] ], 12: [ [1, 0], [-1, 0], [0, -2], [0, 2] ], 21: [ [-1, 0], [1, 0], [0, 2], [0, -2] ], 23: [ [-1, 0], [1, 0], [0, 1], [0, -1] ], 32: [ [1, 0], [-1, 0], [0, -1], [0, 1] ], 30: [ [-1, 0], [1, 0], [0, 0], [0, 0] ], "03": [ [1, 0], [-1, 0], [0, 0], [0, 0] ], "02": [], 13: [], 20: [], 31: [] }, l3_kicks: { "01": [ [-1, 0], [1, 0] ], 10: [ [1, 0], [-1, 0] ], 12: [ [0, -1], [0, 1] ], 21: [ [0, 1], [0, -1] ], 23: [ [1, 0], [-1, 0] ], 32: [ [-1, 0], [1, 0] ], 30: [ [0, 1], [0, -1] ], "03": [ [0, -1], [0, 1] ], "02": [], 13: [], 20: [], 31: [] }, i5_kicks: { "01": [ [-2, 0], [2, 0], [-2, 1], [2, -2] ], 10: [ [2, 0], [-2, 0], [2, -1], [-2, 2] ], 12: [ [-2, 0], [2, 0], [-2, -2], [2, 1] ], 21: [ [2, 0], [-2, 0], [2, 2], [-2, -1] ], 23: [ [2, 0], [-2, 0], [2, -1], [-2, 2] ], 32: [ [-2, 0], [2, 0], [-2, 1], [2, -2] ], 30: [ [2, 0], [-2, 0], [2, 2], [-2, -1] ], "03": [ [-2, 0], [2, 0], [-2, -2], [2, 1] ], "02": [], 13: [], 20: [], 31: [] }, oo_kicks: { "01": [ [0, -1], [-1, -1], [0, 1], [-1, 1], [1, 0], [1, -1], [1, 1] ], 10: [ [1, 0], [0, -1], [1, 1], [1, -1], [-1, 0], [-1, -1], [-1, 1] ], 12: [ [-1, 0], [0, -1], [-1, 1], [-1, -1], [1, 0], [1, -1], [1, 1] ], 21: [ [0, -1], [1, -1], [0, 1], [1, 1], [-1, 0], [-1, -1], [-1, 1] ], 23: [ [0, -1], [-1, -1], [0, 1], [-1, 1], [1, 0], [1, -1], [1, 1] ], 32: [ [1, 0], [0, -1], [1, 1], [1, -1], [-1, 0], [-1, -1], [-1, 1] ], 30: [ [-1, 0], [0, -1], [-1, 1], [-1, -1], [1, 0], [1, -1], [1, 1] ], "03": [ [0, -1], [1, -1], [0, 1], [1, 1], [-1, 0], [-1, -1], [-1, 1] ], "02": [[0, -1]], 13: [[1, 0]], 20: [[0, 1]], 31: [[-1, 0]] }, additional_offsets: {}, spawn_rotation: {}, colorMap: { i1: "i", i2: "i", i3: "i", l3: "j", i5: "i", z: "z", l: "l", o: "o", s: "s", i: "i", j: "j", t: "t", oo: "o", g: "g", d: "d", gb: "gb", gbd: "gbd" }, preview_overrides: {} }, "SRS-X": { kicks: { "01": [ [-1, 0], [-1, -1], [0, 2], [-1, 2] ], 10: [ [1, 0], [1, 1], [0, -2], [1, -2] ], 12: [ [1, 0], [1, 1], [0, -2], [1, -2] ], 21: [ [-1, 0], [-1, -1], [0, 2], [-1, 2] ], 23: [ [1, 0], [1, -1], [0, 2], [1, 2] ], 32: [ [-1, 0], [-1, 1], [0, -2], [-1, -2] ], 30: [ [-1, 0], [-1, 1], [0, -2], [-1, -2] ], "03": [ [1, 0], [1, -1], [0, 2], [1, 2] ], "02": [ [1, 0], [2, 0], [1, 1], [2, 1], [-1, 0], [-2, 0], [-1, 1], [-2, 1], [0, -1], [3, 0], [-3, 0] ], 13: [ [0, 1], [0, 2], [-1, 1], [-1, 2], [0, -1], [0, -2], [-1, -1], [-1, -2], [1, 0], [0, 3], [0, -3] ], 20: [ [-1, 0], [-2, 0], [-1, -1], [-2, -1], [1, 0], [2, 0], [1, -1], [2, -1], [0, 1], [-3, 0], [3, 0] ], 31: [ [0, 1], [0, 2], [1, 1], [1, 2], [0, -1], [0, -2], [1, -1], [1, -2], [-1, 0], [0, 3], [0, -3] ] }, i_kicks: { "01": [ [-2, 0], [1, 0], [-2, 1], [1, -2] ], 10: [ [2, 0], [-1, 0], [2, -1], [-1, 2] ], 12: [ [-1, 0], [2, 0], [-1, -2], [2, 1] ], 21: [ [1, 0], [-2, 0], [1, 2], [-2, -1] ], 23: [ [2, 0], [-1, 0], [2, -1], [-1, 2] ], 32: [ [-2, 0], [1, 0], [-2, 1], [1, -2] ], 30: [ [1, 0], [-2, 0], [1, 2], [-2, -1] ], "03": [ [-1, 0], [2, 0], [-1, -2], [2, 1] ], "02": [ [-1, 0], [-2, 0], [1, 0], [2, 0], [0, 1] ], 13: [ [0, 1], [0, 2], [0, -1], [0, -2], [-1, 0] ], 20: [ [1, 0], [2, 0], [-1, 0], [-2, 0], [0, -1] ], 31: [ [0, 1], [0, 2], [0, -1], [0, -2], [1, 0] ] }, i2_kicks: { "01": [ [0, -1], [-1, 0], [-1, -1] ], 10: [ [0, 1], [1, 0], [1, 1] ], 12: [ [1, 0], [0, -1], [1, 0] ], 21: [ [-1, 0], [0, 1], [-1, 0] ], 23: [ [0, 1], [1, 0], [1, -1] ], 32: [ [0, -1], [-1, 0], [-1, 1] ], 30: [ [-1, 0], [0, 1], [-1, 2] ], "03": [ [1, 0], [0, -1], [1, -2] ], "02": [ [-1, 0], [-2, 0], [1, 0], [2, 0], [0, 1] ], 13: [ [0, 1], [0, 2], [0, -1], [0, -2], [-1, 0] ], 20: [ [1, 0], [2, 0], [-1, 0], [-2, 0], [0, -1] ], 31: [ [0, 1], [0, 2], [0, -1], [0, -2], [1, 0] ] }, i3_kicks: { "01": [ [1, 0], [-1, 0], [0, 1], [0, -1] ], 10: [ [-1, 0], [1, 0], [0, -1], [0, 1] ], 12: [ [1, 0], [-1, 0], [0, -2], [0, 2] ], 21: [ [-1, 0], [1, 0], [0, 2], [0, -2] ], 23: [ [-1, 0], [1, 0], [0, 1], [0, -1] ], 32: [ [1, 0], [-1, 0], [0, -1], [0, 1] ], 30: [ [-1, 0], [1, 0], [0, 0], [0, 0] ], "03": [ [1, 0], [-1, 0], [0, 0], [0, 0] ], "02": [ [1, 0], [2, 0], [1, 1], [2, 1], [-1, 0], [-2, 0], [-1, 1], [-2, 1], [0, -1], [3, 0], [-3, 0] ], 13: [ [0, 1], [0, 2], [-1, 1], [-1, 2], [0, -1], [0, -2], [-1, -1], [-1, -2], [1, 0], [0, 3], [0, -3] ], 20: [ [-1, 0], [-2, 0], [-1, -1], [-2, -1], [1, 0], [2, 0], [1, -1], [2, -1], [0, 1], [-3, 0], [3, 0] ], 31: [ [0, 1], [0, 2], [1, 1], [1, 2], [0, -1], [0, -2], [1, -1], [1, -2], [-1, 0], [0, 3], [0, -3] ] }, l3_kicks: { "01": [ [-1, 0], [1, 0] ], 10: [ [1, 0], [-1, 0] ], 12: [ [0, -1], [0, 1] ], 21: [ [0, 1], [0, -1] ], 23: [ [1, 0], [-1, 0] ], 32: [ [-1, 0], [1, 0] ], 30: [ [0, 1], [0, -1] ], "03": [ [0, -1], [0, 1] ], "02": [ [1, 0], [2, 0], [1, 1], [2, 1], [-1, 0], [-2, 0], [-1, 1], [-2, 1], [0, -1], [3, 0], [-3, 0] ], 13: [ [0, 1], [0, 2], [-1, 1], [-1, 2], [0, -1], [0, -2], [-1, -1], [-1, -2], [1, 0], [0, 3], [0, -3] ], 20: [ [-1, 0], [-2, 0], [-1, -1], [-2, -1], [1, 0], [2, 0], [1, -1], [2, -1], [0, 1], [-3, 0], [3, 0] ], 31: [ [0, 1], [0, 2], [1, 1], [1, 2], [0, -1], [0, -2], [1, -1], [1, -2], [-1, 0], [0, 3], [0, -3] ] }, i5_kicks: { "01": [ [-2, 0], [2, 0], [-2, 1], [2, -2] ], 10: [ [2, 0], [-2, 0], [2, -1], [-2, 2] ], 12: [ [-2, 0], [2, 0], [-2, -2], [2, 1] ], 21: [ [2, 0], [-2, 0], [2, 2], [-2, -1] ], 23: [ [2, 0], [-2, 0], [2, -1], [-2, 2] ], 32: [ [-2, 0], [2, 0], [-2, 1], [2, -2] ], 30: [ [2, 0], [-2, 0], [2, 2], [-2, -1] ], "03": [ [-2, 0], [2, 0], [-2, -2], [2, 1] ], "02": [ [1, 0], [2, 0], [1, 1], [2, 1], [-1, 0], [-2, 0], [-1, 1], [-2, 1], [0, -1], [3, 0], [-3, 0] ], 13: [ [0, 1], [0, 2], [-1, 1], [-1, 2], [0, -1], [0, -2], [-1, -1], [-1, -2], [1, 0], [0, 3], [0, -3] ], 20: [ [-1, 0], [-2, 0], [-1, -1], [-2, -1], [1, 0], [2, 0], [1, -1], [2, -1], [0, 1], [-3, 0], [3, 0] ], 31: [ [0, 1], [0, 2], [1, 1], [1, 2], [0, -1], [0, -2], [1, -1], [1, -2], [-1, 0], [0, 3], [0, -3] ] }, oo_kicks: { "01": [ [0, -1], [-1, -1], [0, 1], [-1, 1], [1, 0], [1, -1], [1, 1] ], 10: [ [1, 0], [0, -1], [1, 1], [1, -1], [-1, 0], [-1, -1], [-1, 1] ], 12: [ [-1, 0], [0, -1], [-1, 1], [-1, -1], [1, 0], [1, -1], [1, 1] ], 21: [ [0, -1], [1, -1], [0, 1], [1, 1], [-1, 0], [-1, -1], [-1, 1] ], 23: [ [0, -1], [-1, -1], [0, 1], [-1, 1], [1, 0], [1, -1], [1, 1] ], 32: [ [1, 0], [0, -1], [1, 1], [1, -1], [-1, 0], [-1, -1], [-1, 1] ], 30: [ [-1, 0], [0, -1], [-1, 1], [-1, -1], [1, 0], [1, -1], [1, 1] ], "03": [ [0, -1], [1, -1], [0, 1], [1, 1], [-1, 0], [-1, -1], [-1, 1] ], "02": [[0, -1]], 13: [[1, 0]], 20: [[0, 1]], 31: [[-1, 0]] }, additional_offsets: {}, spawn_rotation: {}, colorMap: { i1: "i", i2: "i", i3: "i", l3: "j", i5: "i", z: "z", l: "l", o: "o", s: "s", i: "i", j: "j", t: "t", oo: "o", g: "g", d: "d", gb: "gb", gbd: "gbd" }, preview_overrides: {} }, "TETRA-X": { kicks: { "01": [ [0, 1], [-1, 0], [1, 0], [-1, 1], [1, 1], [0, -1], [-1, -1], [1, -1] ], 10: [ [0, 1], [1, 0], [-1, 0], [1, 1], [-1, 1], [0, -1], [1, -1], [-1, -1] ], 12: [ [0, 1], [-1, 0], [1, 0], [-1, 1], [1, 1], [0, -1], [-1, -1], [1, -1] ], 21: [ [0, 1], [1, 0], [-1, 0], [1, 1], [-1, 1], [0, -1], [1, -1], [-1, -1] ], 23: [ [0, 1], [-1, 0], [1, 0], [-1, 1], [1, 1], [0, -1], [-1, -1], [1, -1] ], 32: [ [0, 1], [1, 0], [-1, 0], [1, 1], [-1, 1], [0, -1], [1, -1], [-1, -1] ], 30: [ [0, 1], [-1, 0], [1, 0], [-1, 1], [1, 1], [0, -1], [-1, -1], [1, -1] ], "03": [ [0, 1], [1, 0], [-1, 0], [1, 1], [-1, 1], [0, -1], [1, -1], [-1, -1] ], "02": [ [0, 1], [0, -1], [-1, 0], [1, 0] ], 13: [ [0, 1], [0, -1], [-1, 0], [1, 0] ], 20: [ [0, 1], [0, -1], [-1, 0], [1, 0] ], 31: [ [0, 1], [0, -1], [-1, 0], [1, 0] ] }, i_kicks: { "01": [ [0, -1], [0, -2], [0, 1], [1, -1], [-1, -1], [1, -2], [-1, -2] ], 10: [ [0, -1], [0, -2], [0, 1], [-1, 0], [1, 0], [2, 0] ], 12: [ [0, -1], [0, -2], [0, 1], [-1, 0], [1, 0], [2, 0] ], 21: [ [0, 1], [0, 2], [0, -1], [-1, 1], [1, 1], [-1, 2], [1, 2] ], 23: [ [0, 1], [0, 2], [0, -1], [1, 1], [-1, 1], [1, 2], [-1, 2] ], 32: [ [0, -1], [0, -2], [0, 1], [1, 0], [-1, 0], [-2, 0] ], 30: [ [0, -1], [0, -2], [0, 1], [1, 0], [-1, 0], [-2, 0] ], "03": [ [0, -1], [0, -2], [0, 1], [-1, -1], [1, -1], [-1, -2], [1, -2] ], "02": [ [0, -1], [0, 1] ], 13: [ [0, -1], [0, 1] ], 20: [ [0, -1], [0, 1] ], 31: [ [0, -1], [0, 1] ] }, additional_offsets: {}, spawn_rotation: {}, colorMap: { i1: "i", i2: "i", i3: "i", l3: "j", i5: "i", z: "z", l: "o", o: "s", s: "i", i: "l", j: "j", t: "t", oo: "o", g: "g", d: "d", gb: "gb", gbd: "gbd" }, preview_overrides: {} }, NRS: { kicks: { "01": [], 10: [], 12: [], 21: [], 23: [], 32: [], 30: [], "03": [], "02": [], 13: [], 20: [], 31: [] }, additional_offsets: { z: [ [1, 1], [1, 0], [1, 0], [2, 0] ], l: [ [1, 0], [1, 0], [1, 0], [1, 0] ], o: [ [0, 0], [0, 0], [0, 0], [0, 0] ], s: [ [1, 1], [1, 0], [1, 0], [2, 0] ], i: [ [0, 1], [0, 0], [0, 0], [1, 0] ], j: [ [1, 0], [1, 0], [1, 0], [1, 0] ], t: [ [1, 0], [1, 0], [1, 0], [1, 0] ] }, spawn_rotation: { z: 0, l: 2, o: 0, s: 0, i: 0, j: 2, t: 2 }, colorMap: { i1: "i", i2: "i", i3: "i", l3: "j", i5: "i", z: "z", l: "l", o: "o", s: "s", i: "i", j: "j", t: "t", oo: "o", g: "g", d: "d", gb: "gb", gbd: "gbd" }, preview_overrides: { l: [ [0, 0, 201], [1, 0, 68], [2, 0, 124], [0, 1, 31] ], j: [ [0, 0, 199], [1, 0, 68], [2, 0, 114], [2, 1, 31] ], t: [ [0, 0, 199], [1, 0, 74], [2, 0, 124], [1, 1, 31] ] } }, ARS: { kicks: { "01": [ [1, 0], [-1, 0] ], 10: [ [1, 0], [-1, 0] ], 12: [ [1, 0], [-1, 0] ], 21: [ [1, 0], [-1, 0] ], 23: [ [1, 0], [-1, 0] ], 32: [ [1, 0], [-1, 0] ], 30: [ [1, 0], [-1, 0] ], "03": [ [1, 0], [-1, 0] ], "02": [ [1, 0], [-1, 0] ], 13: [ [1, 0], [-1, 0] ], 20: [ [1, 0], [-1, 0] ], 31: [ [1, 0], [-1, 0] ] }, additional_offsets: { i1: [ [0, 0], [0, 0], [0, 0], [0, 0] ], z: [ [0, 1], [0, 0], [0, 0], [1, 0] ], l: [ [0, 1], [0, 0], [0, 0], [0, 0] ], o: [ [0, 0], [0, 0], [0, 0], [0, 0] ], s: [ [0, 1], [-1, 0], [0, 0], [0, 0] ], i: [ [0, 0], [0, 0], [0, -1], [1, 0] ], j: [ [0, 1], [0, 0], [0, 0], [0, 0] ], t: [ [0, 1], [0, 0], [0, 0], [0, 0] ] }, spawn_rotation: { z: 0, l: 2, o: 0, s: 0, i: 0, j: 2, t: 2 }, colorMap: { i1: "i", i2: "i", i3: "i", l3: "j", i5: "i", z: "s", l: "l", o: "o", s: "t", i: "z", j: "j", t: "i", g: "g", d: "d", gb: "gb", gbd: "gbd" }, preview_overrides: { l: [ [0, 0, 201], [1, 0, 68], [2, 0, 124], [0, 1, 31] ], j: [ [0, 0, 199], [1, 0, 68], [2, 0, 114], [2, 1, 31] ], t: [ [0, 0, 199], [1, 0, 74], [2, 0, 124], [1, 1, 31] ] }, center_column: [ [-1, -1], [0, -1], [1, -1], [-1, 0], [0, 0], [1, 0], [-1, 1], [0, 1], [1, 1] ] }, ASC: { kicks: { "01": [ [-1, 0], [0, 1], [-1, 1], [0, 2], [-1, 2], [-2, 0], [-2, 1], [-2, 2], [1, 0], [1, 1], [0, -1], [-1, -1], [-2, -1], [1, 2], [2, 0], [0, -2], [-1, -2], [-2, -2], [2, 1], [2, 2], [1, -1] ], 10: [ [1, 0], [0, 1], [1, 1], [0, 2], [1, 2], [2, 0], [2, 1], [2, 2], [-1, 0], [-1, 1], [0, -1], [1, -1], [2, -1], [-1, 2], [-2, 0], [0, -2], [1, -2], [2, -2], [-2, 1], [-2, 2], [-1, -1] ], 12: [ [-1, 0], [0, 1], [-1, 1], [0, 2], [-1, 2], [-2, 0], [-2, 1], [-2, 2], [1, 0], [1, 1], [0, -1], [-1, -1], [-2, -1], [1, 2], [2, 0], [0, -2], [-1, -2], [-2, -2], [2, 1], [2, 2], [1, -1] ], 21: [ [1, 0], [0, 1], [1, 1], [0, 2], [1, 2], [2, 0], [2, 1], [2, 2], [-1, 0], [-1, 1], [0, -1], [1, -1], [2, -1], [-1, 2], [-2, 0], [0, -2], [1, -2], [2, -2], [-2, 1], [-2, 2], [-1, -1] ], 23: [ [-1, 0], [0, 1], [-1, 1], [0, 2], [-1, 2], [-2, 0], [-2, 1], [-2, 2], [1, 0], [1, 1], [0, -1], [-1, -1], [-2, -1], [1, 2], [2, 0], [0, -2], [-1, -2], [-2, -2], [2, 1], [2, 2], [1, -1] ], 32: [ [1, 0], [0, 1], [1, 1], [0, 2], [1, 2], [2, 0], [2, 1], [2, 2], [-1, 0], [-1, 1], [0, -1], [1, -1], [2, -1], [-1, 2], [-2, 0], [0, -2], [1, -2], [2, -2], [-2, 1], [-2, 2], [-1, -1] ], 30: [ [-1, 0], [0, 1], [-1, 1], [0, 2], [-1, 2], [-2, 0], [-2, 1], [-2, 2], [1, 0], [1, 1], [0, -1], [-1, -1], [-2, -1], [1, 2], [2, 0], [0, -2], [-1, -2], [-2, -2], [2, 1], [2, 2], [1, -1] ], "03": [ [1, 0], [0, 1], [1, 1], [0, 2], [1, 2], [2, 0], [2, 1], [2, 2], [-1, 0], [-1, 1], [0, -1], [1, -1], [2, -1], [-1, 2], [-2, 0], [0, -2], [1, -2], [2, -2], [-2, 1], [-2, 2], [-1, -1] ], "02": [], 13: [], 20: [], 31: [] }, i_kicks: { "01": [ [-1, 0], [0, 1], [-1, 1], [0, 2], [-1, 2], [-2, 0], [-2, 1], [-2, 2], [1, 0], [1, 1], [0, -1], [-1, -1], [-2, -1], [1, 2], [2, 0], [0, -2], [-1, -2], [-2, -2], [2, 1], [2, 2], [1, -1] ], 10: [ [1, 0], [0, 1], [1, 1], [0, 2], [1, 2], [2, 0], [2, 1], [2, 2], [-1, 0], [-1, 1], [0, -1], [1, -1], [2, -1], [-1, 2], [-2, 0], [0, -2], [1, -2], [2, -2], [-2, 1], [-2, 2], [-1, -1] ], 12: [ [-1, 0], [0, 1], [-1, 1], [0, 2], [-1, 2], [-2, 0], [-2, 1], [-2, 2], [1, 0], [1, 1], [0, -1], [-1, -1], [-2, -1], [1, 2], [2, 0], [0, -2], [-1, -2], [-2, -2], [2, 1], [2, 2], [1, -1] ], 21: [ [1, 0], [0, 1], [1, 1], [0, 2], [1, 2], [2, 0], [2, 1], [2, 2], [-1, 0], [-1, 1], [0, -1], [1, -1], [2, -1], [-1, 2], [-2, 0], [0, -2], [1, -2], [2, -2], [-2, 1], [-2, 2], [-1, -1] ], 23: [ [-1, 0], [0, 1], [-1, 1], [0, 2], [-1, 2], [-2, 0], [-2, 1], [-2, 2], [1, 0], [1, 1], [0, -1], [-1, -1], [-2, -1], [1, 2], [2, 0], [0, -2], [-1, -2], [-2, -2], [2, 1], [2, 2], [1, -1] ], 32: [ [1, 0], [0, 1], [1, 1], [0, 2], [1, 2], [2, 0], [2, 1], [2, 2], [-1, 0], [-1, 1], [0, -1], [1, -1], [2, -1], [-1, 2], [-2, 0], [0, -2], [1, -2], [2, -2], [-2, 1], [-2, 2], [-1, -1] ], 30: [ [-1, 0], [0, 1], [-1, 1], [0, 2], [-1, 2], [-2, 0], [-2, 1], [-2, 2], [1, 0], [1, 1], [0, -1], [-1, -1], [-2, -1], [1, 2], [2, 0], [0, -2], [-1, -2], [-2, -2], [2, 1], [2, 2], [1, -1] ], "03": [ [1, 0], [0, 1], [1, 1], [0, 2], [1, 2], [2, 0], [2, 1], [2, 2], [-1, 0], [-1, 1], [0, -1], [1, -1], [2, -1], [-1, 2], [-2, 0], [0, -2], [1, -2], [2, -2], [-2, 1], [-2, 2], [-1, -1] ], "02": [], 13: [], 20: [], 31: [] }, allow_o_kick: true, additional_offsets: { i1: [ [0, 0], [0, 0], [0, 0], [0, 0] ], z: [ [0, 0], [0, 0], [0, 0], [0, 0] ], l: [ [0, 0], [0, 0], [0, 0], [0, 0] ], o: [ [0, 0], [0, 1], [-1, 1], [-1, 0] ], s: [ [0, 0], [0, 0], [0, 0], [0, 0] ], i: [ [0, 0], [0, -1], [1, -1], [1, 0] ], j: [ [0, 0], [0, 0], [0, 0], [0, 0] ], t: [ [0, 0], [0, 0], [0, 0], [0, 0] ] }, colorMap: { i1: "i", i2: "i", i3: "i", l3: "j", i5: "i", z: "z", l: "l", o: "o", s: "s", i: "i", j: "j", t: "t", oo: "o", g: "g", d: "d", gb: "gb", gbd: "gbd" }, spawn_rotation: {}, preview_overrides: {} }, none: { kicks: { "01": [], 10: [], 12: [], 21: [], 23: [], 32: [], 30: [], "03": [], "02": [], 13: [], 20: [], 31: [] }, additional_offsets: {}, colorMap: { i1: "i", i2: "i", i3: "i", l3: "j", i5: "i", z: "z", l: "l", o: "o", s: "s", i: "i", j: "j", t: "t", oo: "o", g: "g", d: "d", gb: "gb", gbd: "gbd" }, spawn_rotation: {}, preview_overrides: {} } }; // src/engine/utils/kicks/index.ts var legal = (blocks, board) => { if (board.length === 0) return false; for (const block of blocks) { if (block[0] < 0) return false; if (block[0] >= board[0].length) return false; if (block[1] < 0) return false; if (block[1] >= board.length) return false; if (board[block[1]][block[0]]) return false; } return true; }; var performKick = (kicktable, piece, pieceLocation, ao, maxMovement, blocks, startRotation, endRotation, board) => { try { if (legal( blocks.map((block) => [ pieceLocation[0] + block[0] - ao[0], Math.floor(pieceLocation[1]) - block[1] - ao[1] ]), board )) return true; const kickID = `${startRotation}${endRotation}`; const table = kicks[kicktable]; const customKicksetID = `${piece.toLowerCase()}_kicks`; const kickset = customKicksetID in table ? table[customKicksetID][kickID] : table.kicks[kickID]; for (let i = 0; i < kickset.length; i++) { const [dx, dy] = kickset[i]; const newY = maxMovement ? pieceLocation[1] - dy - ao[1] : Math.ceil(pieceLocation[1]) - 0.1 - dy - ao[1]; if (legal( blocks.map((block) => [ pieceLocation[0] + block[0] + dx - ao[0], Math.floor(newY) - block[1] ]), board )) { return { newLocation: [pieceLocation[0] + dx - ao[0], newY], kick: [dx, -dy], id: kickID, index: i }; } } return false; } catch { return false; } }; // src/engine/utils/tetromino/data.ts var tetrominoes = { i1: { matrix: { w: 1, h: 1, dx: 0, dy: 1, data: [[[0, 0, 255]], [[0, 0, 255]], [[0, 0, 255]], [[0, 0, 255]]] }, preview: { w: 1, h: 1, data: [[0, 0, 255]] } }, i2: { matrix: { w: 2, h: 2, dx: 0, dy: 1, data: [ [ [0, 0, 199], [1, 0, 124] ], [ [1, 0, 241], [1, 1, 31] ], [ [1, 1, 124], [0, 1, 199] ], [ [0, 1, 31], [0, 0, 241] ] ] }, preview: { w: 2, h: 1, data: [ [0, 0, 199], [1, 0, 124] ] } }, i3: { matrix: { w: 3, h: 3, dx: 1, dy: 1, data: [ [ [0, 1, 199], [1, 1, 68], [2, 1, 124] ], [ [1, 0, 241], [1, 1, 17], [1, 2, 31] ], [ [2, 1, 124], [1, 1, 68], [0, 1, 199] ], [ [1, 2, 31], [1, 1, 17], [1, 0, 241] ] ] }, preview: { w: 3, h: 1, data: [ [0, 0, 199], [1, 0, 68], [2, 0, 124]