FreecCell in 1k with randomly generated card art. What else is there to say?
for(_='),z9608zy(eHYH,E,G0,FG6FWf,eVA=BUa()P||O==N400>x?MD[Lc[c.]="))this.P&&(99=f.client42,25,l,m=new S([],=function(b(1)w.};.push();b(0)return ffor( onmouseusx,";,9630+R(257,t){YH,I,8Fg*R(z9017+R(10V,I,g,n){xAcenterxBmiddlen]=I+"px ariallShsl(F%,"+g+"%)lT]( D in c)c[L2]+[L4]]]=D;var h=p=J=r=Fu=[],w,Q,U=Date.now(RA^=A<<3;A^=A>>2;?A%f:0Sn=I;gU+g;Nw?H=h,I=p,JOc(Q):(,,,r!=J35>h-e-35<h-e60>p-n-60<p-nJ?1>g!Pc(wzQ=):P0<g+1NNO!)O0>g!O!g!O1+N-)%2c()E=I; D of f)l=L1]%2?50:Fn=E,G,FyG95,,yU+L1],WlW0Wlm=(L0]+3)%13,TH-2FE-=4>m?"JQKA"[m]:L0]+1zTH+2FE+zE+=g?0:50b[-1][t]ct.f(f.pop(a.lengthfft)if(2Ng) i=52;i--;)f.splice(R(+1zF[i%13,i/13|0])wFF2 x=;a(x+=){25F0) K=M7:6;K--;)c(s,M-1:1}uwsetInterval(ClS#223lR](FF1E4,1E4 v of u)v.g(r=J},16Tn,V)YString.fromCharCode(nzV)downJ=1upJ=0movehX;pY';G=/[-L-PU-WF-Hyz]/.exec(_);)with(_.split(G))_=join(shift());eval(_)
Zm9yKF89Jyksejk2MDh6eShlSFlILEUsRzAsRkc2RldmLGVWQT1CVWEoKVB8fE89PU40MDA+eD9NRFtMY1tjLh9dPSIeKSkddGhpcxwcLhsbUBomJhkZKBg5ORc9Zi5jbGllbnQWNDIsMjUsbCxtFT1uZXcgUyhbXSwUPWZ1bmN0aW9uKBNiKDEpEncuEX07EC5wdXNoKA8pOw5iKDApDHJldHVybiBmC2ZvcigJEG9ubW91c2UIdQ9zFHgsByI7HwYsOTYzMCtSKDI1Nx0sBRN0KXsEWUgsSSw4RmcqUigXejkwMTcrUigxMB0DE1YsSSxnLG4pewICH3hBHmNlbnRlcgZ4Qh5taWRkbGUGbl09SSsicHggYXJpYWwGbFMeaHNsKEYXJSwiK2crIiUpBmxUXSgBCUQgaW4gYyljW0wyXStbTDRdXV09RDt2YXIgaD1wPUo9cj1GdT1bXSx3LFEsVT1EYXRlLm5vdygOUgJBXj1BPDwzO0FePUE+PjI7Cz9BJWY6MBBTAm49STsbZwRVK2c7HE53P0g9aCxJPXAsGhhKTxtjKFEdKTooAywDLAMsAw5yIT1KGTM1PmgtZRktMzU8aC1lGTYwPnAtbhktNjA8cC1uGEo/GhkxPmcZIRFQGBtjKHd6UT0cKToRUBgwPGcYGhkbDCsxThEMGRESThsSTyERDClPMD5nGSEaTyFnGCEaTzErEQxOGwwYERItGxIpJTIdGRFjKBwpDkU9STsJRCBvZiBmKWw9TDFdJTI/NTA6Rm49RSxHFyxGeUc5NSwXLHlVK0wxXSxXbAVXMAVXbAVtPShMMF0rMyklMTMsVEgtMkZFLRU9ND5tPyJKUUtBIlttXTpMMF0rMXpUSCsyRkUrFXpFKz1nPzA6NTAQG2IEC1saLTFdW3RdEBtjBHQuZihmLnBvcCgdEBthBAsubGVuZ3RoEBtmBGYPdCkQaWYoMk5nKQlpPTUyO2ktLTspZi5zcGxpY2UoUigaKzF6RltpJTEzLGkvMTN8MF0pEHcURkYyDgl4PRc7EWEoDngrPRcpewcyNUYwKQ4JSz1NNzo2O0stLTspEWMocw4HFyxNLTE6MR19dQ93DnNldEludGVydmFsKEMCH2xTHiMyMjMGbFJdKEZGMUU0LDFFNA4JdiBvZiB1KXYuZygOcj1KfSwxNg5UAW4sVikQWQFTdHJpbmcuZnJvbUNoYXJDb2RlKG56VikIZG93bgJKPTEIdXACSj0wCG1vdmUCaBZYO3AWWRAnO0c9L1sBLR9MLVBVLVdGLUh5el0vLmV4ZWMoXyk7KXdpdGgoXy5zcGxpdChHKSlfPWpvaW4oc2hpZnQoKSk7ZXZhbChfKQ==
///////////////////////////////////////////////////////////////////////
//
// One Thousand Free Cells
// A tiny freecell implementation with random card art.
// By Frank Force - 2019
///////////////////////////////////////////////////////////////////////////////
// globals
///////////////////////////////////////////////////////////////////////////////
var mouseX=0, mouseY=0,mouseDown=0, mouseWasDown=0, // input
stacks=[], playerHand, lastTouchedStack, // game stuff
randSeed = Date.now(), cardSeed=Date.now(); // card stuff
// random number generator
R=function(max){randSeed^=randSeed<<3;randSeed^=randSeed>>2;return max?randSeed%max:0;}
//////////////////////////////////////////////////////////////////////////////
// stack object
//////////////////////////////////////////////////////////////////////////////
S=function(cards, x, y, type, topY)
{
topY = y; // save position of top card
this.U=function() // stack update
{
randSeed = cardSeed + type;
if (this == playerHand) // check if player hand
{
x = mouseX; // update mouse pos
y = mouseY;
if (this.S()) // if we have cards
{
if (!mouseDown) // mouse was released but we still have cards
{
stacks.push(s=new S([cards.pop()],x,y,-1)) // god mode
//this.M(lastTouchedStack); // move card to last stack
}
}
}
else
{
Y(x, y, 80,type*R(99), 9017+R(10)); // render empty stack ⌹⍌⍔⌸
Y(x, y, 80,type*R(99), 9017+R(10)); // render empty stack ⌹⍌⍔⌸
Y(x, y, 80,type*R(99), 9017+R(10)); // render empty stack ⌹⍌⍔⌸
Y(x, y, 80,type*R(99), 9017+R(10)); // render empty stack ⌹⍌⍔⌸
}
//c.strokeStyle ="#F00";c.strokeRect(x-35,topY-60,70,120);// debug hitbox
if (mouseWasDown != mouseDown && // mouse changed
mouseX-x<35 && // check mouse for overlap
mouseX-x>-35 &&
mouseY-topY<60 &&
mouseY-topY>-60)
{
if (mouseDown) // try to grab
{
if (this.S() && type<1 && // if it has cards and is not foundation
!playerHand.S()) // only if player isn't holding a card
{
this.M(playerHand); // give card to player
lastTouchedStack = this; // remember us incase player drops in bad spot
}
}
else if (playerHand.S() && // try to drop
(
type > 0 && // moving to foundation
(
this.S() && // not empty
this.T(0)+1 == playerHand.T(0) && // is one more then
playerHand.T(1) == this.T(1) || // must be same suit
!playerHand.T(0) // or an ace works too
) ||
type < 0 && !this.S() || // moving to free cell ok if empty
!type && // moving to cascade
(!this.S() || // if its not empty
1+playerHand.T(0) == this.T(0) && // is one more then
(playerHand.T(1)-this.T(1))%2) // must alternate suit
)
)
playerHand.M(this); // place card if valid
}
j = y; // start at our y
for(i=0;i<cards.length;++i) // go through all the cards in the stack
{
W = cards[i];
l = W[1]%2?50:0; // get lightness value
topY = j; // save topY for selecting next frame
Y(x,j, 99, 0, 9608); // black border
Y(x,j, 95, 99, 9608); // white background
randSeed = cardSeed + W[1]; // set our suit seed
Y(x, j, 60, l, 9630 + R(257)); // random seeded card suit ☮☻♛⛄
Y(x, j, 60, 0, 9630 + R(257)); // random seeded card suit ☮☻♛⛄
Y(x, j, 60, l, 9630 + R(257)); // random seeded card suit ☮☻♛⛄
m = (W[0]+3)%13; // shift it so ace is above king
T(x-20, j-42, 25, l,m=m<4?"JQKA"[m]:W[0]+1); // card value 2-A
T(x+20, j+42, 25, l,m); // card value in other corner
j += type?0:50; // move down the cascade
}
}
this.T=function(s) { return cards[this.S()-1][s]; } // get top card value/suit
this.M=function(newStack, checkValid) // move card if valid
{ newStack.A(cards.pop()); } // move the card to the other stack
this.S=function(newCard) { return cards.length; } // get size of stack
this.A=function(newCard) { cards.push(newCard); } // add a card to top of stack
if (type == 2) // build shuffled deck
{ for(i=52;i--;) cards.splice(R(this.S()+1),0,[i%13,i/13|0]);} // create shuffled deck
}
//////////////////////////////////////////////////////////////////////////////
// game setup
//////////////////////////////////////////////////////////////////////////////
playerHand = new S([],0,0,2); // give player randomized deck
for(x = 99; playerHand.S(); x += 99) // 8 cascades
{
stacks.push(s=new S([], x, 250, 0)) // add to cascade stack
for(y=(x<400?7:6);y--;) // put 7 on one stack and 6 on the other
playerHand.M(s);
stacks.push(s=new S([], x, 99, x<400?-1:1)) // foundations and freecells
}
// push hand to top of stack so it renders last
stacks.push(playerHand);
///////////////////////////////////////////////////////////////////////////////
// main update loop
///////////////////////////////////////////////////////////////////////////////
setInterval(G=function()
{
c.fillStyle="#223";c.fillRect(0,0,1e4,1e4); // draw background
//randSeed = cardSeed;
//for(i=9;--i;)
// Y(R(1999), R(1999), 999, R(10), 9630 + R(257));
for(v=0; v<stacks.length; ++v) // update/render stacks
stacks[v].U();
mouseWasDown = mouseDown; // track when mouse goes down
// debug stuff
//c.fillStyle="#FFF";c.fillText(playerCardCount,100,100);
//c.strokeStyle ="#F00";c.strokeRect(0,0,1280,720); // 720p
//c.strokeStyle ="#F00";c.strokeRect(a.width/2-20,a.height/2-20,40,40); // center
},16);
///////////////////////////////////////////////////////////////////////////////
// text rendering system
///////////////////////////////////////////////////////////////////////////////
T = function(x, y, size, v, text) // render text
{
c.textAlign = "center";
c.textBaseline = "middle";
c.font = size + "px arial"; // set font size
c.fillStyle="hsl(0,99%,"+v+"%)"; // set hsl color
c.fillText(text,x,y); // render text
}
Y = function(x, y, size, v, char) // render text
{
c.textAlign = "center";
c.textBaseline = "middle";
c.font = size + "px arial";
c.fillStyle="hsl(0,99%,"+v+"%)";
c.fillText(String.fromCharCode(char),x,y);
//T(x, y, size, v,String.fromCharCode(char));
// it packs better to have this duplicate block
}
///////////////////////////////////////////////////////////////////////////////
// mouse input
///////////////////////////////////////////////////////////////////////////////
onmousedown = function(x) { mouseDown = 1; }
onmouseup = function(x) { mouseDown = 0; }
onmousemove = function(x) { mouseX = x.clientX, mouseY = x.clientY; }