eleven/eleven.core.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;
}