 
          
        
        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; }