Skip to content
Snippets Groups Projects
snake.c 11.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • KosmX's avatar
    :D
    KosmX committed
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    161400@bme.hu's avatar
    161400@bme.hu committed
    #include<locale.h>
    
    KosmX's avatar
    KosmX committed
    #include<ctype.h>
    
    #ifdef __linux__
    #include<sys/ioctl.h>
    #include<unistd.h>
    #include<time.h>
    #else
    #include<Windows.h>
    #endif
    
    KosmX's avatar
    :D
    KosmX committed
    
    //#define windows 1
    
    //typedef unsigned long long int pointer; //Not optimal
    
    
    161400@bme.hu's avatar
    161400@bme.hu committed
    //int isUnicodeEncoding = 0;
    
    KosmX's avatar
    KosmX committed
    
    
    
    161400@bme.hu's avatar
    161400@bme.hu committed
    int isUnicodeEncoding(int set){
        static int bl = 0;
        if(set){
            bl = 1;
        }
        return bl;
    }
    
    KosmX's avatar
    :D
    KosmX committed
    
    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;
    
    
    KosmX's avatar
    KosmX committed
    typedef struct food{
        Pos pos;
        int rand;
        struct food *next;
    }food;
    
    typedef struct screenData{
        Pos pos;
        Pos size;
    
    KosmX's avatar
    KosmX committed
        int repeatMap;
        int isXRepeat;
        int isYRepeat;
    
    KosmX's avatar
    KosmX committed
    }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
    }
    
    
    KosmX's avatar
    :D
    KosmX committed
    /**
     * 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){
    
    161400@bme.hu's avatar
    161400@bme.hu committed
        int c, len, maxLineLen = 0, lineCount = (3,1), lineLen = 0; //lineCount = (3,1) ??? why?... i was just bored
    
    KosmX's avatar
    :D
    KosmX committed
        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);
    }
    
    
    KosmX's avatar
    KosmX committed
    //Use what chunk,
    //witch screen coordinates?
    //just the screen data
    
    KosmX's avatar
    KosmX committed
    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.
        }
        
    }
    
    
    KosmX's avatar
    KosmX committed
    int updateScreenSize(Matrix *map, screenData *scrDat){
        struct Vec2i size = getWindowSize();
        if(size.x == scrDat->size.x && size.y == scrDat->size.y){
            return 0; //no change happened
        }
        scrDat->size.x = size.x;
        scrDat->size.y = size.y;
        if(scrDat->repeatMap){
            scrDat->isXRepeat = size.x < map->width;
            scrDat->isYRepeat = size.y < map->height;
        }
        return 1;
    }
    
    //Update screen if required 
    void  updateScreen(Matrix *map, screenData *scrDat, snakeChain *head){
        int do_update;
        do_update = updateScreenSize(map, scrDat);
        if(scrDat->isXRepeat){
            if(head->pos.x < scrDat->pos.x - 6){
                
            }
        }
        else{
            scrDat->pos.x = 0;
        }
    }
    
    //Tick the game, step the snake, collect and place food.
    void tick(Matrix *map, screenData *scrDat, snakeChain *snake){
    
    }
    
    KosmX's avatar
    KosmX committed
    
    //------------config loader------------
    
    
    KosmX's avatar
    KosmX committed
    int loadConfig(int *tickSpeed, int *repeatMap){
    
    KosmX's avatar
    KosmX committed
        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);
            }
    
    KosmX's avatar
    KosmX committed
            else if(strncmp(name, "repeatMap", 10) == 0){
                fscanf(config, " %d", repeatMap);
            }
    
    KosmX's avatar
    KosmX committed
            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;
    }
    
    KosmX's avatar
    :D
    KosmX committed
    
    //------------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++){
    
    unknown's avatar
    unknown committed
                    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]);
    
    KosmX's avatar
    :D
    KosmX committed
                    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;
    
    161400@bme.hu's avatar
    161400@bme.hu committed
    
    
    KosmX's avatar
    KosmX committed
        int tickspeed = 100, repeatMap = 0; // if no config, default value
    
    KosmX's avatar
    KosmX committed
    
        //----load config----
    
    
    KosmX's avatar
    KosmX committed
        if(loadConfig(&tickspeed, &repeatMap)){
    
    KosmX's avatar
    KosmX committed
            printf("Error while loading config...");
        }
    
    
    161400@bme.hu's avatar
    161400@bme.hu committed
        //----init tasks----
    
    
    KosmX's avatar
    KosmX committed
        if(isUnicodeEncoding(0)){
    
    KosmX's avatar
    KosmX committed
            #ifndef __linux__
    
    KosmX's avatar
    KosmX committed
            setlocale(LC_ALL, ".utf-8");
    
    KosmX's avatar
    KosmX committed
            #endif
    
    KosmX's avatar
    KosmX committed
        }
    
    161400@bme.hu's avatar
    161400@bme.hu committed
    
        //----import map----
    
    
    KosmX's avatar
    :D
    KosmX committed
        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);
    
    unknown's avatar
    unknown committed
        _print1char(&map);
    
    KosmX's avatar
    :D
    KosmX committed
        /* 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[])
    {
    
    161400@bme.hu's avatar
    161400@bme.hu committed
        2 + 3;  //... this does nothing...
    
    KosmX's avatar
    :D
    KosmX committed
        int ret;
    
    161400@bme.hu's avatar
    161400@bme.hu committed
        char const *array[] = {argv[0], "map1.txt"};
    
    KosmX's avatar
    :D
    KosmX committed
        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...
    }