Clear the field by removing groups of more than one colored square; the larger the group you remove, the more points you get.
for(_='c=W&&V),Ut(L(b,dK=KJ0;I,cHH,g,kFlientERecLDMath.AnK)@?0:(c,bu,n),k,q,2=f.getb=e[1,--;)1Ib);-4)/260>{let ?-1:~~((Aabsr(c+for()VdH)+uK=b.cE m*m-4*m+4h.fill20*d+b)=>d=!Id;)!Style="#;W2Ice=[],f=window.a,hContexL"2d"Ul,m,nJb||d||19<b||9<d],p=((!(m=l=0~~(4*Arandom()+1Ud{20Idd]=b(d])},rJF=g{"+"336c65aba58cfb7113732555245753449f87eee9cffea224".substr(3*b,3DdF)},tJ{r(15,0,0,528,288h.font="12px sans-serif";fff";TexL`[New] Score: ${l} `+(1<m?`Marked: ${m} (+${})`:m?"Game Over":""U8,2802Ib1IdW(@Ug=@,k=26*b+4,q=26*d+4;5610510*g,k+q+24gV5,8+k,8+q,10)}},uJH=@||c!=@(]=-c1+u(b--c)+u(b++cUvJH,g{;W20*g+c;g=b];b]=c];c]=g};p(Lf.onmousedown=>dBoundingCED)H X-d.left;b Y-d.top;42>cV268<bV288>bVp(W4>cc4>bbif(n1<m){p(>bb)1;1b;b++)!nn-1vH,b-d=!0W1;2c;c++)if(!n(c-9n(c,9))!0,vH-bl+=;m=-1m=1<)m}p(m=m?m:L)};}';G=/[^ -?BCGM-TX-~]/.exec(_);)with(_.split(G))_=join(shift());eval(_)Zm9yKF89J2M9VyYmViksVXQoTChiLGRLPUtKMDtJLGNISCxnLGtGbGllbnRFUmVjTERNYXRoLkFuSylAPzA6HyhjLGIedR4sbh4pHSxrLHEsMhw9Zi5nZXQbYj0aZVsZMSwYLS07KRcaMUliFxYpOxUtNCkvMjYVFDA+E3tsZXQgEj8tMTp+figoEUFhYnMQcihjKw9mb3IoDilWDBhkSCkrdUsLPWIuY0UJbSptLTQqbSs0CGguZmlsbAcyMCpkK2IGKT0+BQ5kPQQEIUlkOykEIRgDB1N0eWxlPSIjAjsOVzJJYxcBEmU9W10sZj13aW5kb3cuYSxoG0NvbnRleEwiMmQiVWwsbSxuSgUTYnx8E2R8fDE5PGJ8fDk8ZB8ZBl0scD0oGigFIShtPWw9MAx+fig0KkFyYW5kb20oKSsxVWQFewQyMElkFxlkXT1iKBlkXSl9LHJKRj1nBXsCIisiMzM2YzY1YWJhNThjZmI3MTEzNzMyNTU1MjQ1NzUzNDQ5Zjg3ZWVlOWNmZmVhMjI0Ii5zdWJzdHIoMypiLDMVB0RkRil9LHRKBXtyKDE1LDAsMCw1MjgsMjg4FWguZm9udD0iMTJweCBzYW5zLXNlcmlmIjsCZmZmIjsHVGV4TGBbTmV3XSAgICBTY29yZTogJHtsfSAgICBgKygxPG0/YE1hcmtlZDogJHttfSAoKyR7CH0pYDoTbT8iR2FtZSBPdmVyIjoiIlU4LDI4MBUOGjJJYhcEMUlkFxJXEChAVWc9E0Asaz0yNipiKzQscT0yNipkKzQ7DzUcNhUPMTAcNRUPMTAqZyxrKxhxKxgyNBVnVg81LDgrayw4K3EsMTApfX0sdUpIBRM9QHx8YyE9QB8oGQZdPS1jDDErdShiLQstGGMpK3UoYisLKxhjVXZKSCxnBXsaBjtXMjAqZytjO2c9GWJdOxliXT0ZY107GWNdPWd9O3AoFUwVZi5vbm1vdXNlZG93bj0aPhJkG0JvdW5kaW5nQ0VEKUgJWC1kLmxlZnQ7YglZLWQudG9wOzQyPmNWMjY4PGJWMjg4PmJWcCgVVzQ+YxFjFBo0PmIRYhRpZigTbh4MMTxtKXtwKBo+E2IfYikBAxoxOzETYjtiKyspIW4eDG4eLTEMdh5ILGItGGQ9ITAVA1cxOzITYztjKyspaWYoIW4oYy0YOQxuKGMsOSkpBCEwLBZ2HkgtGGIVbCs9CDttPS0xAQ4WbT0xPB0pH219cCgQFW09E20/bTodFUwpfTt9JztHPS9bXiAtP0JDR00tVFgtfl0vLmV4ZWMoXyk7KXdpdGgoXy5zcGxpdChHKSlfPWpvaW4oc2hpZnQoKSk7ZXZhbChfKQ==/*
* samegame1k
* js1k-2017 entry
* @author Gabor Bata
* @license MIT
*/
{
let
s, // score
m; // number of marked tiles, -1: game over
const
// canvas size: 528 x 288
WIDTH = 20, // number of columns
HEIGHT = 10, // number of rows
TILE = 26, // tile size in pixels
STATUS = 20, // status bar height
BORDER = 4, // border size
MARKER = 8, // padding of marker rectangle
table = [], // array of tiles
canvas = window['a'],
context = canvas.getContext('2d'),
// calculate points by the formula: (m - 2) ^ 2
points = () => m * m - 4 * m 4,
// get tile state - positive: base, negative: marked, zero: removed
state = (x, y) =>
x < 0 || y < 0 || x > WIDTH - 1 || y > HEIGHT - 1 ?
0 : table[WIDTH * y x],
// reset values of the table with the given function (f), starts new game by default
reset = (f = () => !(m = s = 0) && ~~(Math.random() * 4 1)) => {
for (let v = WIDTH * HEIGHT; v--;) {
table[v] = f(table[v]);
}
},
// draw rectangle: if height (h) is not provided, the width (w) value will be used
rect = (c, x, y, w, h = w) => {
// color indices (c):
// 0-4: base, removed tile (1) tiles (4)
// 5-9: darker, removed (1) tiles (4)
// 10-14: brighter, removed (1) tiles (4)
// 15: canvas background
context.fillStyle = '#' '336c65aba58cfb7113732555245753449f87eee9cffea224'.substr(c * 3, 3);
context.fillRect(x, y, w, h);
},
// draw the canvas
draw = () => {
// canvas background
rect(15, 0, 0, WIDTH * TILE BORDER * 2, HEIGHT * TILE BORDER * 2 STATUS);
// draw status bar
context.font = '12px sans-serif';
context.fillStyle = '#fff';
context.fillText(
`[New] Score: ${s} `
(m > 1 ? `Marked: ${m} ( ${points()})` : (m < 0 ? 'Game Over' : '')),
BORDER * 2, HEIGHT * TILE BORDER * 2 STATUS / 2 2);
// draw tiles
for (let i = WIDTH; i--;) {
for (let j = HEIGHT; j--;) {
let c = Math.abs(state(i, j)), // color index
h = state(i, j) < 0, // marked state of tile
x = i * TILE BORDER,
y = j * TILE BORDER;
// add simple bevel effect
rect(c 5, x, y, TILE); // darker color (shadow)
rect(c 10, x, y, TILE - 1); // brighter color (light)
rect(c h * 10, x 1, y 1, TILE - 2); // base tile color
// show marker rectangle
if (h) {
rect(c 5, MARKER x, MARKER y, TILE - MARKER * 2);
}
}
}
},
// mark tiles recursively
mark = (x, y, c) =>
state(x, y) <= 0 || c != state(x, y) ? 0 : // skip removed/marked or non-matching color
(table[WIDTH * y x] = -c) && // mark tile and check neighbors (non-zero values are considered true)
1 mark(x - 1, y, c) mark(x, y - 1, c) mark(x 1, y, c) mark(x, y 1, c),
// swap tiles based on the given coordinates
swap = (x1, y1, x2, y2) => {
let pos1 = WIDTH * y1 x1,
pos2 = WIDTH * y2 x2,
temp = table[pos1];
table[pos1] = table[pos2];
table[pos2] = temp;
};
// initialize game
reset();
draw();
// define handler for mousedown event
canvas.onmousedown = (event) => {
// get coordinates of mouse event
let c = canvas.getBoundingClientRect(),
j = event.clientX - c.left,
k = event.clientY - c.top;
// handle click on the text '[New]'; 42 is the approximate width of the text
// ...and also the "Answer to the Ultimate Question of Life, the Universe, and Everything"
if (j < 42 && k > HEIGHT * TILE BORDER * 2 && k < HEIGHT * TILE BORDER * 2 STATUS) {
reset();
}
// normalize coordinates
j = j < BORDER ? -1 : ~~((j - BORDER) / TILE);
k = k < BORDER ? -1 : ~~((k - BORDER) / TILE);
// check if tiles can be removed
if (state(j, k) < 0 && m > 1) {
// remove marked tiles
reset(v => v < 0 ? 0 : v);
// drop down tiles to fill the empty space
for (j = WIDTH; j--;) {
for (c = true; c;) {
for (c = false, k = 1; k < HEIGHT; k ) {
if (!state(j, k) && state(j, k - 1)) {
swap(j, k, j, k - 1, c = true);
}
}
}
}
// shift columns to the left
for (c = true; c;) {
for (c = false, j = 1; j < WIDTH; j ) {
if (!state(j - 1, HEIGHT - 1) && state(j, HEIGHT - 1)) {
for (c = true, k = HEIGHT; k--;) {
swap(j, k, j - 1, k);
}
}
}
}
// increase score based on the removed tiles
s = points();
// determine game end
for (m = -1, j = WIDTH; j--;) {
for (k = HEIGHT; k--;) {
m = mark(j, k, state(j, k)) > 1 ? 0 : m;
}
}
}
// unmark tiles
reset(Math.abs);
// mark tiles if the event happened on an unmarked tile (i.e. j and k are non-negative),
// or if there are still tiles to remove (m is non-negative)
m = m < 0 ? m : mark(j, k, state(j, k));
// redraw canvas
draw();
};
}