Skip to content

Instantly share code, notes, and snippets.

@justecorruptio
Created April 9, 2014 09:52
Show Gist options
  • Save justecorruptio/10248923 to your computer and use it in GitHub Desktop.
Save justecorruptio/10248923 to your computer and use it in GitHub Desktop.
Annotated version of 2048.c
/* Annotated version of 2048.c */
M[16], // The board
X=16, // Shorthand for 16
W, // Game over bit mask: 1=won, 2=not lost
k;
main(){
T( // Call main game logic
system("stty cbreak") // Set tty mode to not wait for enter key
);
puts(W&1?"WIN":"LOSE"); // Detect game over state, and print message
}
K[]={2,3,1}; // Translation table between keyboard key
// code and direction. Note that since
// K[3] is in BSS and most likely 0, but not
// guaranteed.
s( // Declare our shift function
f, // If false, will simulate a shift only
d, // Direction to shift in
i, // Temp var to hold current row
j, // The read head
l, // Temp var to store last value read in row
P // Temp var to hold current value in row
// k is the write head
){
for(i=4;i--;) // Loop over each row
for(j=k=l=0;k<4;) // Loop over each column
j<4? // Are there still values to read in the row?
P=M[w(d,i,j++)], // Store the read value in row accounting for
// direction, increment read head
W|=P>>11, // Is stored value 2048 (1<<11)? if so, flip
// the first bit in winning mask
l*P&&( // If last value read and current value are not 0
f?M[w(d,i,k)]= // If not read only, use write head to write:
l<<(l==P):0 // The last value if not equal to current or
// double the last value if it is
,k++ // Increment the write head
),
l=l?P?l-P?P:0:l:P // Set the last value according to the value
// of the last and current values.
:( // Else: there are no more values to read in row
f?M[w(d,i,k)]=l:0, // If not read-only, write the last value (may be zero)
++k, // Increment the write head
W|=2*!l, // If we are write a 0 here, that means board isn't full
// so set winning mask bit 2
l=0 // Set last to zero so that the next write will be padding
);
}
w( // Declare translation function from direction and
// relative position to absolute position
d, // The direction
i, // Row number
j // Column
){
return d? // If direction is non-zero
w(d-1,j,3-i) // Recusively call myself to find direction - 1
:
4*i+j; // Base case at direction 0
}
T( // Declare main game logic function
i // General temp variable
){
// Algorithm to find an empty cell:
for(
i=X+rand()%X; // First, set i to be a random number grater than 16
M[i%X]*i; // Loop while i mod 16 points to a filled cell and i > 0
i-- // Decrement i
);
i? // If i is zero, it means we've looped over the board
// at least once and did not find an empty cell
M[i%X]=2<<rand()%2 // Set empty cell to be 2 or 4
:
0;
for(W=i=0;i<4;) // Clear winning mask, loop over all four directions
s(0,i++); // and simuilate shifts in read-only mode.
for( // Display loop
i=X,puts("\e[2J\e[H"); // Clear screen and move cursor to 1,1 using ANSI codes.
i--;
i%4||puts("") // Print a newline every fourth cell
)
printf(
M[i]? // Is cell non-empty
"%4d|" // Print lpadded integer value of cell
:
" |", // Print empty cell
M[i] // C gladly ignore unused interpolation values
);
W-2|| // If we haven't won
read(0,&k,3)| // Read 3 bytes of cursor scancode into k as an int
T( // Recursively call myself to process next iteration
// of game loop
s( // But first, shift based on key pressed
1, // Not in read-only mode
K[(k>>X)%4] // Rshift scancode buffer by two bytes, and lookup
// direction in translation table
)
);
}//[2048] // Flair
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment