Skip to content

Instantly share code, notes, and snippets.

@iznax
Created February 23, 2012 04:24
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iznax/1890185 to your computer and use it in GitHub Desktop.
Save iznax/1890185 to your computer and use it in GitHub Desktop.
Mini Tetris in less than 140 bytes

Mini Tetris

A slightly more well-behaved version of Tetris than some other 140 byte projects. The left and right sides of the screen block player movement. The game view is larger and the width and height of the screen are included as constants you can manipulate.

Play 140-character Version

I made a more accurate version of the game with proper all the rotating pieces. This of course is larger and the core logic takes 256 characters.

Play Full Version

Display

 Empty       Fall      Frozen
........   ........   ........
........   ........   ........
........   ...@@...   ........
........   ........   ........
........   ........   ...##...
========   ========   ========

Controls

Left  Arrow = Move left
Right Arrow = Move right
Down  Arrow = Fall

The Inner Core

This function is the core logic of the game. It processes all input signals and manipulates the game data. I know it's cheating a bit to ignore the outer script, but I'm following the pattern of some others and agree that the display mechanism is arbitrary and less important, for my purposes.

// h = horizontal position
// v = vertical position
// t = tetronimo bits 1,3
// g = array of row lines
// d = delta key input signal -1,0,1

function Inner(h,v,t,g,d)
{
    // Check if the next block-position collides with the game board.
    // t << h+d = the shape bits shifted to (h) horizontal position + (d) movement
    if(g[v+=!d] & t<<h+d)
    {
        // If (d==0) the block is falling and not moving horizontally.
        if(!d)
        {
            // The shape is blocked from below so freeze the bits onto the game view
            // If the resulting bit pattern equals (F) the full-row pattern
            // Then splice() to remove the row from the array of lines
            // And unshift() to add the (Z) blank value at the top of the view
            // The F&Z works because the splice() returns the row value removed.
            (g[--v] |= t<<h) < F ? 0 : g.unshift( g.splice(v,1)&Z );
            // Reset to the middle of the screen W/2
            h=4;
            // Reset to the top of the screen
            v=0;
            // Pick a random bit pattern (1 or 3) for the tetris block to drop
            t = new Date&2|1
        }
        // Cancel the horizontal movement value.
        d=0
    }
    // Return the updated x,y,shape,game values.
    return[h+d,v,t,g]
}

Compact = 139 characters

The function can be stripped of white-space, formatted as an anonymous function with less than 140 characters and assigned to a variable to be called.

function(h,v,t,g,d){if(g[v+=!d]&t<<h+d){if(!d){(g[--v]|=t<<h)<F?0:g.unshift(g.splice(v,1)&Z);h=4;v=0;t=new Date&2|1}d=0}return[h+d,v,t,g]}

Information

Thanks to aemkei for the inspiration.

// h = horizontal position
// v = vertical position
// t = tetronimo bits 1,3
// g = array of row lines
// d = delta key input signal -1,0,1
function Inner(h,v,t,g,d)
{
// Check if the next block-position collides with the game board.
// t << h+d = the shape bits shifted to (h) horizontal position + (d) movement
if(g[v+=!d] & t<<h+d)
{
// If (d==0) the block is falling and not moving horizontally.
if(!d)
{
// The shape is blocked from below so freeze the bits onto the game view
// If the resulting bit pattern equals (F) the full-row pattern
// Then splice() to remove the row from the array of lines
// And unshift() to add the (Z) blank value at the top of the view
// The F&Z works because the splice() returns the row value removed.
(g[--v] |= t<<h) < F ? 0 : g.unshift( g.splice(v,1)&Z );
// Reset to the middle of the screen W/2
h=4;
// Reset to the top of the screen
v=0;
// Pick a random bit pattern (1 or 3) for the tetris block to drop
t = new Date&2|1
}
// Cancel the horizontal movement value.
d=0
}
// Return the updated x,y,shape,game values.
return[h+d,v,t,g]
}
function(h,v,t,g,d){if(g[v+=!d]&t<<h+d){if(!d){(g[--v]|=t<<h)<F?0:g.unshift(g.splice(v,1)&Z);h=4;v=0;t=new Date&2|1}d=0}return[h+d,v,t,g]}
{
"name": "MiniTetris",
"description": "Mini version of Tetris with core logic less than 140 bytes",
"keywords": [
"game",
"javascript",
"tetris",
]
}
<html>
<style>body{ font-family: monospace; font-size: 20px}</style>
<div id="out"></div>
</html>
<script>
var out = document.getElementById("out");
var N=8; // Number of rows in the play field
var W=8; // Number of columns
var Z=2<<W|1; // Zero row with side-bars
var F=Z*2-3; // Full row value
var time = 4<<8;
var px=0,py=N-1,pz=1;
var game=[]; for(var i=N;i--;)game[i]=Z;game[N]=F;
function Inner(h,v,t,g,d)
{
if(g[v+=!d]&t<<h+d)
{
if(!d)
{
(g[--v]|=t<<h)<F?0:g.unshift(g.splice(v,1)&Z);
h=4;v=0;t=new Date&2|1
}
d=0
}
return[h+d,v,t,g]
}
function DrawGame()
{
var display = "";
for (var j=0; j<N; j++)
{
for (var b=2; b<2<<W; b*=2)
{
display += (j==py)*(pz<<px)&b?"■":game[j]&b?"#":".";
}
display += "<br>";
}
out.innerHTML = display+"========";
}
function Update(d)
{
var r = Inner(px,py,pz,game,d);
px=r[0], py=r[1], pz=r[2], game=r[3];
DrawGame();
}
// Map arrow keys Left(37)=(-1) Right(39)=(+1) Down(40)=(0)
onkeydown = function(e) { if(e="1032"[e.keyCode-37])Update(e-2); }
function Mainloop()
{
Update(0);
setTimeout(Mainloop, time-=2);
}
Mainloop();
</script>
@aemkei
Copy link

aemkei commented Feb 27, 2012

Nice one!

But save 4 bytes by rearranging the return statement and use ? instead of if:

function(a,b,c,d,e){return d[b+=!e]&c<<a+e&&(e||((d[--b]|=c<<a)<F?0:d.unshift(d.splice(b,1)&Z),a=4,b=0,c=new Date&2|1),e=0),[a+e,b,c,d]}

@P-six
Copy link

P-six commented Jul 9, 2012

Some mor bytes for IE
document.onkeydown=function(e)
{
if(e=K[!e?window.event.keyCode:e.keyCode])out.innerHTML=Update(e);
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment