snake.c 9.96 KiB
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<locale.h>
#include<ctype.h>
#ifdef __linux__
#include<sys/ioctl.h>
#include<unistd.h>
#include<time.h>
#else
#include<Windows.h>
#endif
//#define windows 1
//typedef unsigned long long int pointer; //Not optimal
//int isUnicodeEncoding = 0;
int isUnicodeEncoding(int set){
static int bl = 0;
if(set){
bl = 1;
}
return bl;
}
typedef enum Direcion{
UP,
RIGHT,
DOWN,
LEFT,
}Direction;
typedef struct Vec2i{
int x;
int y;
}Pos;
typedef struct snakeChain
{
int num;
struct Vec2i pos;
struct snakeChain *next;
}snakeChain;
typedef union unichar{
int isUnicone : 1;
struct{
char c[4];
}bytes;
}unichar;
typedef struct chunk //struct stores 2 chars and it's color :D
{
unichar chars[2];
/*
struct{
int fg : 3; //3 bit color codes.
int bg : 3; //red green blue black white and 3 other (idk these)
}color;*/
}chunk;
typedef struct state{
struct Vec2i displaySize;
struct Vec2i displayPos;
int commands[2];
}globalState;
typedef struct linkedString{
unichar value;
struct linkedString *next;
}linkedString;
typedef struct chunkMatrix{
chunk **matrix;
int width;
int height;
}Matrix;
typedef struct food{
Pos pos;
int rand;
struct food *next;
}food;
typedef struct screenData{
Pos pos;
Pos size;
}screenData;
//-----------methods--------------
struct Vec2i getWindowSize(){
struct Vec2i size;
#ifdef __linux__
struct winsize info;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &info);
size.x = info.ws_col;
size.y = info.ws_row;
#else
CONSOLE_SCREEN_BUFFER_INFO info;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
size.x = info.srWindow.Right - info.srWindow.Left + 1;
size.y = info.srWindow.Bottom - info.srWindow.Top + 1;
#endif
return size;
}
void unisleep(int milisec){
#ifdef __linux__
struct timespec ts;
ts.tv_sec = milisec / 1000;
ts.tv_nsec = (milisec % 1000) * 1000000;
nanosleep(&ts, NULL);
#else
Sleep(milisec);
#endif
}
/**
* Only the first byte is required
*/
int checkUnicharLen(char c){
int i = 0;
if(!isUnicodeEncoding){
return 1; //int windows-xyzw every char has 1 len;
}
if(!(c & 0x80)){
return 1;
}
while(c & 0x80){
i++;
c = c << 1;
if(i > 8){
return EOF;
}
}
return i;
}
void printChar(unichar c){
int len;
len = checkUnicharLen(c.bytes.c[0]);
for(int i = 0; i < len; i++){
printf("%c", c.bytes.c[i]);
}
}
//fueoetoeoecsoeoe *next
int readFile(FILE *file, Matrix *matrix){
int c, len, maxLineLen = 0, lineCount = (3,1), lineLen = 0; //lineCount = (3,1) ??? why?... i was just bored
struct Vec2i pos;
pos.x = 0;
pos.y = 0;
linkedString *linkedStr = 0, *current = 0, *next;
//linkedStr = malloc(sizeof(linkedString));
while(c = fgetc(file)){
next = malloc(sizeof(linkedString));
if(next == NULL){
return EOF;
}
memset(next, 0, sizeof(linkedString)); //TODO remove after debugging
next->next = 0;
if(c == -1){
break;
}
while (c == '\r')
{
c = fgetc(file);
if(c == -1){
break;
}
}
next->value.bytes.c[0] = c;
len = checkUnicharLen(c);
if(isUnicodeEncoding && len -1){
for (int i = 1; i < len; i++){
c = fgetc(file);
if(c == -1){
return EOF;
}
next->value.bytes.c[i] = c;
}
}
else if(c == '\n'){ //checking newline (unichar can't be a newline char (\n))
lineCount++;
if(lineLen > maxLineLen){
maxLineLen = lineLen;
}
lineLen = -1;
}
lineLen++;
//next.value = chars;
if(current != 0){
current->next = next;
}
else
{
linkedStr = next;
//current = next;
}
current = next;
}
maxLineLen = maxLineLen / 2 + maxLineLen % 2;
matrix->height = lineCount;
matrix->width = maxLineLen;
matrix->matrix = calloc(maxLineLen, sizeof(chunk*));
if(matrix->matrix == NULL){
printf("failed to allocate memory for the matrix");
return EOF-1;
}
for (int i = 0; i < maxLineLen; i++){
matrix->matrix[i] = calloc(lineCount, sizeof(chunk));
if(matrix->matrix[i] == NULL){
printf("failed to allocate memory for the matrix");
return EOF-1;
}
for(int n = 0; n < lineCount; n++){
for(int a = 0; a < 2; a++){
matrix->matrix[i][n].chars[a].bytes.c[0] = ' ';
}
}
}
current = linkedStr;
while(current != 0){
//tmp = current;
//current = current->next;
//free(tmp);
if(current->value.bytes.c[0] == '\n'){
pos.x = 0;
pos.y++;
//break;
}
else{
for(int charPos = 0; charPos < 4; charPos++){
matrix->matrix[pos.x/2][pos.y].chars[pos.x%2].bytes.c[charPos] = current->value.bytes.c[charPos];
}
pos.x++;
}
next = current;
current = current->next;
free(next);
}
return 0;
}
void rmMatrix(Matrix *map){
for(int i = 0; i < map->width; i++){
free(map->matrix[i]);
}
free(map->matrix);
}
//Use printChar
void printChunk(chunk ch, Pos pos, screenData *scrDat){
pos.x -= scrDat->pos.x;
pos.y -= scrDat->pos.y;
if(pos.x < 0 || pos.y < 0 || pos.x >= scrDat->pos.x || pos.y >= scrDat->pos.y){
return; //if pos is not on the screen, just do nothing.
}
}
//------------config loader------------
int loadConfig(int *tickSpeed){
FILE *config;
config = fopen("config.cfg", "r");
//int stillFile = 1; //boolean to show file is ended...
if(config == NULL){
return -1;
}
while(1){
char name[32] = {0}, c; //it have to be enough;
while(c = fgetc(config), c != -1 && isspace(c));
if(c == -1){
break;
}
//name[0] = c;
for(int i = 0; i < 32 && !isspace(c) && c != '='; i++, c = fgetc(config)){
name[i] = c;
}
//c = fgetc(config);
while(c != '='){
c = fgetc(config);
if(c == -1){
printf("I can't understand the config file: %s", name);
return EOF;
}
}
if(strncmp(name, "use_utf8", 9) == 0){
int bl;
fscanf(config, " %d", &bl);
isUnicodeEncoding(bl);
}
else if(strncmp(name, "tickspeed", 10) == 0){
fscanf(config, " %d", tickSpeed);
}
else{
printf("Unknown keyword: %s", name);
}
}
return 0;
}
//------------LOOP METHOD--------------
int loop(Matrix *matrix, int tickspeed){
unisleep(tickspeed); //Special sleep to work both in windows and unix environment
return 0;
}
//------------TESTING METHODS-------------
void _testprint(Matrix *map){
for (int y = 0; y < map->height; y++){
for(int x = 0; x < map->width; x++){
for(int i = 0; i < 2; i++){
//printf("%c", map->matrix[x][y].chars->bytes.c[i * 4]); //WTF... I didn't indexed correctly, but accidentaly I've got the right value...
printChar(map->matrix[x][y].chars[i]);
}
//printf("|");
}
printf("\n");
}
}
void _print1char(Matrix *map){
int x, y;
while(scanf(" %d%d", &x, &y) == 2){
if(x >= 0 && y >= 0 && x < map->width && y < map->height){
for(int i = 0;i < 2; i++){
printf("\nvalue: %hhx, %hhx, %hhx, %hhx\n",
(unsigned)map->matrix[x][y].chars[i].bytes.c[0],
(unsigned)map->matrix[x][y].chars[i].bytes.c[1],
(unsigned)map->matrix[x][y].chars[i].bytes.c[2],
(unsigned)map->matrix[x][y].chars[i].bytes.c[3]);
printf("as character: \"");
printChar(map->matrix[x][y].chars[i]);
printf("\"\n");
}
}
}
}
//-------------CORE METHOD----------------
int core(int argc, char const *argv[])
{
FILE *f;
Matrix map;
int tickspeed = 100; // if no config, default value
//----load config----
if(loadConfig(&tickspeed)){
printf("Error while loading config...");
}
//----init tasks----
if(isUnicodeEncoding(0)){
#ifndef __linux__
setlocale(LC_ALL, ".utf-8");
#endif
}
//----import map----
if(argc == 1){
printf("Usage: snake <map name> [<snake skin>]");
return 0;
}
else{
f = fopen(argv[1], "rb");
if(f == NULL){
printf("Map file not found: %s", argv[1]);
return EOF;
}
readFile(f, &map);
}
//test code
printf("map:\n");
_testprint(&map);
_print1char(&map);
/* code */
//free stuff
rmMatrix(&map);
return 0;
}
/*
int main(int argc, char const *argv[])
{
return core(argc, argv);
}
*/
int main(int argc, char const *argv[])
{
2 + 3; //... this does nothing...
int ret;
char const *array[] = {argv[0], "map1.txt"};
ret = core(2, array);
printf("\npress any key to continue");
getchar();
return 0, ret; //Miért van ez a függvény tele szeméttel??? pl 0, smt...
}