171 lines
3.0 KiB
C
171 lines
3.0 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <unistd.h>
|
|
#include <string.h> //memcpy
|
|
//https://gist.github.com/ibaned/41481b2fdddbb61a4291
|
|
#include "eleven.h"
|
|
|
|
/* The game state is represented by a 4x4 U8 array. The low nybble
|
|
contains the numeric value of the tile (0 means empty). The high
|
|
nybble contains the tile status:
|
|
2 = newly-spawned;
|
|
1 = displaced
|
|
0 = static
|
|
|
|
The board must be square, as rotation is implemented as a flip/twist
|
|
combination of some sort.
|
|
|
|
|
|
|
|
void pr(U8* tiles){
|
|
for(int i=0;i<4;i++){
|
|
for(int j=0;j<4;j++){
|
|
printf("%02X ",*(tiles+i*SIZE+j));
|
|
}
|
|
printf("\n");
|
|
}}
|
|
*/
|
|
#define RND (rand()%SIZE)
|
|
/* Orientation of the board, as shown by a bar:
|
|
* 0 = bottom
|
|
* 1 = left
|
|
* 2 = top
|
|
* 3 = right
|
|
*/
|
|
|
|
int orientation = 0;
|
|
|
|
|
|
void twist(U8* tiles){
|
|
int i,j;
|
|
U8 t2[SIZE*SIZE];
|
|
for (i = 0; i < SIZE; ++i)
|
|
for (j = 0; j < SIZE; ++j)
|
|
t2[i*SIZE+j] = tiles[j*SIZE+i];
|
|
memcpy(tiles,t2,SIZE*SIZE);
|
|
}
|
|
|
|
void flip(U8* tiles){
|
|
int i,j;
|
|
U8 t2[SIZE*SIZE];
|
|
for (i = 0; i < SIZE; ++i)
|
|
for (j = 0; j < SIZE; ++j)
|
|
t2[i*SIZE+j] = tiles[i*SIZE+(SIZE - j - 1)];
|
|
memcpy(tiles,t2,SIZE*SIZE);
|
|
}
|
|
|
|
void spawn(U8* tiles){;
|
|
while (1) {
|
|
int i = RND;
|
|
int j = RND;
|
|
if (!tiles[i*SIZE+j]) {
|
|
tiles[i*SIZE+j] = (rand() % 10) ? 0x21 : 0x22; // 2 status means new
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
int dif(U8*new, U8*old){
|
|
int i,n;
|
|
n=0; //number of changes
|
|
for (i = 0; i < SIZE*SIZE; ++i){
|
|
if (new[i] && (new[i] != old[i])){
|
|
new[i] += 0x10;
|
|
n++;
|
|
}
|
|
}
|
|
return n;
|
|
}
|
|
|
|
|
|
void init(U8* tiles){
|
|
memset(tiles,0,SIZE*SIZE);
|
|
tiles[0]=8;
|
|
tiles[4]=7;
|
|
tiles[8]=6;
|
|
tiles[12]=5;
|
|
|
|
tiles[1]=4;
|
|
tiles[5]=3;
|
|
tiles[9]=2;
|
|
tiles[13]=1;
|
|
spawn((U8*)tiles);
|
|
spawn((U8*)tiles);
|
|
}
|
|
|
|
void drop_col(U8* a, U8* b){
|
|
int i,j;
|
|
int prev = 0;
|
|
j = 0;
|
|
for (i = 0; i < SIZE; ++i){
|
|
if (a[i]) {
|
|
if ( (0xF & a[i]) == prev) {
|
|
b[j-1]++;
|
|
prev = 0;
|
|
} else {
|
|
b[j++] = a[i];
|
|
prev = (0xF & a[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
U32 drop(U8* tiles){
|
|
U8 t2[SIZE*SIZE];
|
|
memset(t2,0,SIZE*SIZE);
|
|
|
|
for (int i = 0; i < SIZE*SIZE; i=i+SIZE)
|
|
drop_col(tiles+i, ((U8*)t2)+i);
|
|
|
|
U32 n = dif(t2,tiles); // return the dif count
|
|
memcpy(tiles,t2,SIZE*SIZE);
|
|
return n;
|
|
}
|
|
|
|
void map_clear(U8* tiles){
|
|
int i;
|
|
for (i = 0; i < SIZE*SIZE; ++i)
|
|
tiles[i] &= 0xF;
|
|
}
|
|
|
|
U32 step(U8* tiles){
|
|
map_clear(tiles);
|
|
U8 old[SIZE*SIZE];
|
|
memcpy(old,tiles,SIZE*SIZE);
|
|
U32 dif;
|
|
if((dif=drop(tiles))) //return difference count
|
|
spawn(tiles);
|
|
return dif;
|
|
}
|
|
|
|
|
|
U32 move(U8* tiles, int way){
|
|
if (way / 2) twist(tiles);
|
|
if (way % 2) flip(tiles);
|
|
U32 n = step(tiles);
|
|
if (way % 2) flip(tiles);
|
|
if (way / 2) twist(tiles);
|
|
|
|
return n;
|
|
}
|
|
|
|
|
|
U32 moverot(U8* tiles, int way){
|
|
//if (way / 2) twist(tiles);
|
|
//if (way % 2) flip(tiles);
|
|
twist(tiles);
|
|
flip(tiles);
|
|
orientation = (orientation + 1) & 0x3;
|
|
if(way==2) {
|
|
twist(tiles);
|
|
flip(tiles);
|
|
twist(tiles);
|
|
flip(tiles);
|
|
orientation = (orientation + 2) & 0x3;
|
|
}
|
|
U32 n = step(tiles);
|
|
|
|
//if (way / 2) flip(tiles);
|
|
return n;
|
|
}
|