(???) / TODO rotate board instead of tetromino?
(???) onst blocks =
(???) 'defgaeimdefgaeimdefjaeibdhijibfjdhefaeijhifjabfjeifjeifj' +
(???) 'eifjeifjheifaefjheifaefjdeifaeifheijebfjdeijeibfdeijeibf'
(???) onst randomBlock = () => new Date() % 7
(???) onst [W, H] = [10, 25]
(???) et score = 0, lines = 0, block = 0, rotation = 0,
(???) next = randomBlock(),
(???) X = 3, Y = 0,
(???) timer = -1
(???) onst Bucket = document.getElementById('t')
(???) onst NextBucket = document.getElementById('n')
(???) onst addRow = (bucket, width) => {
(???) for (let r = bucket.insertRow(0), x = width; x--;) {
(???) r.insertCell(0).appendChild(document.createTextNode('\u00a0'))
(???) }
(???)
(???) onst iterate = (block, rotation, callback) => {
(???) // TODO yield
(???) for (let i = 4; i--;) {
(???) const q = blocks.charCodeAt(block * 16 + rotation * 4 + i) - 96
(???) callback(q % 4, q >> 2)
(???) }
(???)
(???) onst Draw = (color, X, Y, block, rotation, bucket = Bucket) => {
(???) iterate(block, rotation, (x, y) => {
(???) const p = ' #' + (color ? '0ff00f808'.substring(block, block + 3) : 'fff')
(???) const v = bucket.rows[Y + y].cells[X + x]
(???) const o = v.style
(???) o.background = p
(???) o.border = (color ? 'outset' : 'solid') + p
(???) v.s = color
(???) })
(???)
(???) onst Move = (dx, dy, drotation) => {
(???) Draw(0, X, Y, block, rotation)
(???) let c = true
(???) iterate(block, drotation, (x, y) => {
(???) x += X + dx
(???) y += Y + dy
(???) if (x < 0 || x >= W || y >= H || Bucket.rows[y].cells[x].s) {
(???) c = false
(???) }
(???) })
(???) if (c) {
(???) X += dx
(???) Y += dy
(???) rotation = drotation
(???) }
(???) Draw(1, X, Y, block, rotation)
(???) return c
(???)
(???) onst Clear = () => {
(???) X = 3
(???) // full lines?
(???) let p = 0
(???) for (let y = Y; y < H; y++) {
(???) let f = 0
(???) let x = 0
(???) for (f = 0, x = W; x--;) f |= !Bucket.rows[y].cells[x].s
(???) if (!f) {
(???) Bucket.deleteRow(y)
(???) addRow(Bucket, W)
(???) p++
(???) }
(???) }
(???) document.getElementById('s').innerHTML = '\nScore: ' + (score += 9 << p) + '\n\nLines: ' + (lines += p)
(???) clearInterval(timer)
(???) timer = setInterval(Down, 650 - lines)
(???) // clear current next
(???) Draw(0, 1, 1, next, 0, NextBucket)
(???) // choose next
(???) block = next
(???) next = randomBlock()
(???) Draw(-1, 1, 1, next, 0, NextBucket)
(???) Y = 0
(???) rotation = 0
(???) // game over?
(???) if (!Move(0, 1, rotation)) {
(???) clearInterval(timer)
(???) alert('Game over!')
(???) }
(???)
(???) onst Down = () => {
(???) if (!Move(0, 1, rotation)) {
(???) Clear()
(???) }
(???)
(???) onst scrollTable = (table, direction) => {
(???) for (let y = 0; y < table.rows.length; y++) {
(???) const row = table.rows[y];
(???) if (direction == 1) {
(???) const orgCell = row.cells[0];
(???) const cell = row.insertCell(row.cells.length);
(???) cell.innerHTML = orgCell.innerHTML;
(???) cell.style.border = orgCell.style.border;
(???) cell.style.backgroundColor = orgCell.style.backgroundColor;
(???) cell.s = orgCell.s;
(???) row.deleteCell(0);
(???) } else {
(???) const orgCell = row.cells[row.cells.length - 1];
(???) const cell = row.insertCell(0);
(???) cell.innerHTML = orgCell.innerHTML;
(???) cell.style.border = orgCell.style.border;
(???) cell.style.backgroundColor = orgCell.style.backgroundColor;
(???) cell.s = orgCell.s;
(???) row.deleteCell(row.cells.length - 1);
(???) }
(???) }
(???)
(???) onst k = e => {
(???) switch (e.code) {
(???) case 'ArrowLeft':
(???) case 'KeyJ':
(???) Draw(0, X, Y, block, rotation)
(???) // if (Move(0, 0, r)) {
(???) scrollTable(Bucket, -1);
(???) // }
(???) Draw(1, X, Y, block, rotation)
(???) break
(???) case 'ArrowUp':
(???) case 'KeyK':
(???) Move(0, 0, (rotation + 1) % 4)
(???) break
(???) case 'ArrowRight':
(???) case 'KeyL':
(???) Draw(0, X, Y, block, rotation)
(???) // if (Move(0, 0, r)) {
(???) scrollTable(Bucket, 1);
(???) // }
(???) Draw(1, X, Y, block, rotation)
(???) break
(???) case 'Space':
(???) clearInterval(timer)
(???) timer = setInterval(Down, 9)
(???) // fallthrough
(???) case 'ArrowDown':
(???) case 'KeyM':
(???) case 'KeyI':
(???) Down()
(???) }
(???)
(???) or (let y = H; y--;) {
(???) addRow(Bucket, W)
(???)
(???) or (let y = 6; y--;) {
(???) addRow(NextBucket, 6)
(???)
(???) lear()
(???) ddEventListener('keydown', k)