Created
April 9, 2014 09:52
-
-
Save justecorruptio/10248923 to your computer and use it in GitHub Desktop.
Annotated version of 2048.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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