This commit is contained in:
stacksmith 2022-02-04 13:54:35 -05:00
commit daa9fee4c4
4 changed files with 281 additions and 0 deletions

21
Makefile Normal file
View File

@ -0,0 +1,21 @@
CFLAGS = -Wall -g
#-Wall -g -O3
SRCS = eleven.core.c eleven.term.c
OBJS = $(SRCS:.c=.o)
default: eleven.term
eleven.core.o: eleven.core.c eleven.h
gcc $(CFLAGS) -c eleven.core.c -o eleven.core.o
eleven.term.o: eleven.term.c eleven.h
gcc $(CFLAGS) -c eleven.term.c -o eleven.term.o
eleven.term: eleven.core.o eleven.term.o
gcc $(CFLAGS) -o eleven eleven.core.o eleven.term.o
strip eleven
clean:
rm -f *.o
rm -f eleven
rm -f *~

141
eleven.core.c Normal file
View File

@ -0,0 +1,141 @@
#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)
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;
}

20
eleven.h Normal file
View File

@ -0,0 +1,20 @@
#include <stdint.h>
#define SIZE 4
typedef uint8_t U8;
typedef uint32_t U32;
typedef U8 (*pTiles)[SIZE][SIZE];
enum {
DOWN, //0
UP, //1
LEFT, //2
RIGHT,
MOVES
};
void init(U8* tiles);
U32 move(U8* tiles, int way);

99
eleven.term.c Normal file
View File

@ -0,0 +1,99 @@
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <termios.h>
#include <unistd.h>
//https://gist.github.com/ibaned/41481b2fdddbb61a4291
#include "eleven.h"
const char* tochar(int val){
// int i = 'A'-2;
const char* chars[] = //{"①","②","③","④","⑤","⑥","⑦","⑧","⑨","⑩","⑪","⑫","⑬","⑭","⑮","⑯"} ;
{" ","","","","","","","","","","","","","","",""};//,"⓰","⓱","⓲","⓳","⓴"
return chars[val & 0xF];
}
void format_cell_2(char* buf,U8 val){
sprintf(buf,"%s", tochar(val));
}
void format_cell_256(char* buf,U8 val){
// const U8 col[9]={196,1,161,126,91,62,27,27,27};
//const U8 col[9]={196,207,171,135,99,63,27,27,27};
//const U8 col[9]={202,219,183,147,111,75,39,39,39};
const U8 col[3]={33,141,196};
U32 icol = val>>4;
sprintf(buf,"\033[38;5;%dm%s\033[m", col[icol],tochar(val));
}
void print(U8* tiles){
int i,j;
char buf[32];
printf("╭────────╮\n");
for (j = SIZE - 1; j >= 0; --j) {
printf("");
for (i = 0; i < SIZE; ++i) {
format_cell_256(buf,tiles[i*SIZE+j]);
printf("%s ", buf);
}
printf("");
// for (i = 0; i < SIZE; ++i) printf("%X ", (tiles[i*SIZE+j]));
printf("\n");
}
printf("╰────────╯\n");
}
int read_move(void){
char keys[MOVES] = {'k','i','j','l'};
int c;
int i;
while (isspace(c = getchar()));
if (c == EOF)
return c;
for (i = 0; i < MOVES; ++i)
if (c == keys[i])
return i;
return EOF;
}
static struct termios backup;
static struct termios current;
void take_stdin(void){
tcgetattr(STDIN_FILENO, &backup);
current = backup;
current.c_lflag &= (~ICANON & ~ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &current);
}
void give_stdin(void){
tcsetattr(STDIN_FILENO, TCSANOW, &backup);
}
#include <time.h>
int main(){
int moves=0;
int c;
U8 tiles[] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
srand(time(0));
init(tiles);
print(tiles);
take_stdin();
while ((c = read_move()) != EOF) {
if(move(tiles, c)){
moves++;
print(tiles);
}
else {
// zeros++;
// if(zeros>4)
// printf("Ready to give up?\n");
}
}
printf("%d moves\n",moves);
give_stdin();
return 0;
}