Skip to content
Snippets Groups Projects
Commit f419dcaf authored by KosmX's avatar KosmX
Browse files

snek is now a snake

parent e1d64f03
No related branches found
No related tags found
No related merge requests found
File added
......@@ -20,4 +20,3 @@
║ ║
║ ║
╚═════════════════════════════════╝
\ No newline at end of file
#include "debugmalloc.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "debugmalloc.h"
#include<locale.h>
#include<ctype.h>
#include<time.h>
......@@ -386,7 +387,7 @@ void updateFood(Matrix *map, int *foodTick, int feedAmount, snakeChain *firstSna
map->matrix[pos.x][pos.y].isFood = 1;
map->matrix[pos.x][pos.y].data.FRand = rand();
c.data.chars[0].bytes.c[0] = 'X';
c.data.chars[0].bytes.c[0] = 'X';
c.data.chars[1].bytes.c[0] = 'X';
printf(green);
print(c, pos, scrDat, map->width, map->height);
printf("\e[0m");
......@@ -439,9 +440,14 @@ int updateSnake(Matrix *map, screenData *scrDat, Direction d, snakeChain *head,
if(isNotWall(map->matrix[pos.x][pos.y])){
int isFood = map->matrix[pos.x][pos.y].isFood;
head->pos = pos;
if(isFood){
map->matrix[pos.x][pos.y].isFood = false;
map->matrix[pos.x][pos.y].data.chars[0].bytes.c[0] = ' ';
map->matrix[pos.x][pos.y].data.chars[1].bytes.c[0] = ' ';
}
snakeChain *snake = head;
Pos tmp_pos1 = head->pos, tmp_pos2;
head->pos = pos;
while (snake->next != 0)
{
snake = snake->next;
......@@ -449,13 +455,15 @@ int updateSnake(Matrix *map, screenData *scrDat, Direction d, snakeChain *head,
if(snake != head && snake->pos.x == head->pos.x && snake->pos.y == head->pos.y){
if(snake->next != NULL){
if(canBite){
snakeChain *current = snake, *tmp_snek = snake;
tmp_snek = tmp_snek->next;
snakeChain *current = snake, *tmp_snek = snake->next;
current->next = NULL;
while (tmp_snek != NULL)
{
current = tmp_snek;
tmp_snek = tmp_snek->next;
c.data.chars[0].bytes.c[0] = ' ';
c.data.chars[1].bytes.c[0] = ' ';
print(c, current->pos, scrDat, map->width, map->height);
free(current);
}
}
......@@ -478,13 +486,12 @@ int updateSnake(Matrix *map, screenData *scrDat, Direction d, snakeChain *head,
c.data.chars[1].bytes.c[0] = '<';
if(snake->next == NULL && isFood){
isFood = false;
snake->next = malloc(sizeof(snake));
snake->next = malloc(sizeof(snakeChain));
if(snake->next == NULL){
return EOF;
}
snake->next->next = NULL;
snake->pos.x = -1;
snake->pos.y = -1;
snake->next->pos = tmp_pos1;
}
if(snake->pos.x == -1){
continue; //don't render snake part with initial position
......@@ -580,6 +587,8 @@ int tick(Matrix *map, screenData *scrDat, snakeChain *snake, Direction *d, int f
if(scrDat->commands[0] != NONE){
*d = scrDat->commands[0];
}
scrDat->commands[0] = scrDat->commands[1];
scrDat->commands[1] = NONE;
updateScreen(map, scrDat, snake, *d);
if(*d == NONE){
chunk c;
......@@ -591,7 +600,10 @@ int tick(Matrix *map, screenData *scrDat, snakeChain *snake, Direction *d, int f
return 0; // waiting for user input.
}
updateFood(map, &foodTick, feedAmount, snake, scrDat);
updateSnake(map, scrDat, *d, snake, canBite);
if(updateSnake(map, scrDat, *d, snake, canBite)){
*d = NONE;
//TODO Game over or remove 1 hp or ...
}
//printf("\e[0;0H\n"); //Update the terminal (mostly on Unix based systems)
fflush(stdout);
return 0;
......
File added
#include "debugmalloc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char txt[] = "hello";
char *p = malloc((strlen(txt) + 1) * sizeof(char));
strcpy(p, txt);
printf("TXT: %s\n", p);
debugmalloc_dump();
free(p);
return 0;
}
\ No newline at end of file
#ifndef DEBUGMALLOC_H
#define DEBUGMALLOC_H
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdarg.h>
enum {
/* size of canary in bytes. should be multiple of largest alignment
* required by any data type (usually 8 or 16) */
debugmalloc_canary_size = 64,
/* canary byte */
debugmalloc_canary_char = 'K',
/* hash table size for allocated entries */
debugmalloc_tablesize = 256,
/* max block size for allocation, can be modified with debugmalloc_max_block_size() */
debugmalloc_max_block_size_default = 1048576
};
/* make getpid and putenv "crossplatform". deprecated on windows but they work just fine,
* however not declared. */
#ifdef _WIN32
/* windows */
#include <process.h>
#ifdef _MSC_VER
/* visual studio, getenv/getpid deprecated warning */
#pragma warning(disable: 4996)
#else
/* other windows. the declaration is unfortunately hidden
* in mingw header files by ifdefs. */
int putenv(const char *);
#endif
#else
/* posix */
#include <unistd.h>
#endif
/* linked list entry for allocated blocks */
typedef struct DebugmallocEntry {
void *real_mem; /* the address of the real allocation */
void *user_mem; /* address shown to the user */
size_t size; /* size of block requested by user */
char file[64]; /* malloc called in this file */
unsigned line; /* malloc called at this line in file */
char func[32]; /* allocation function called (malloc, calloc, realloc) */
char expr[128]; /* expression calculating the size of allocation */
struct DebugmallocEntry *prev, *next; /* for doubly linked list */
} DebugmallocEntry;
/* debugmalloc singleton, storing all state */
typedef struct DebugmallocData {
char logfile[256]; /* log file name or empty string */
long max_block_size; /* max size of a single block allocated */
long alloc_count; /* currently allocated; decreased with free */
long long alloc_bytes;
long all_alloc_count; /* all allocations, never decreased */
long long all_alloc_bytes;
DebugmallocEntry head[debugmalloc_tablesize], tail[debugmalloc_tablesize]; /* head and tail elements of allocation lists */
} DebugmallocData;
/* this forward declaration is required by the singleton manager function */
static DebugmallocData * debugmalloc_create(void);
/* creates singleton instance. as this function is static included to different
* translation units, multiple instances of the static variables are created.
* to make sure it is really a singleton, these instances must know each other
* somethow. an environment variable is used for that purpose, ie. the address
* of the singleton allocated is stored by the operating system.
* this implementation is not thread-safe. */
static DebugmallocData * debugmalloc_singleton(void) {
static char envstr[100];
static void *instance = NULL;
/* if we do not know the address of the singleton:
* - maybe we are the one to create it (env variable also does not exist)
* - or it is already created, and stored in the env variable. */
if (instance == NULL) {
char envvarname[100] = "";
sprintf(envvarname, "%s%d", "debugmallocsingleton", (int) getpid());
char *envptr = getenv(envvarname);
if (envptr == NULL) {
/* no env variable: create singleton. */
instance = debugmalloc_create();
sprintf(envstr, "%s=%p", envvarname, instance);
putenv(envstr);
} else {
/* another copy of this function already created it. */
int ok = sscanf(envptr, "%p", &instance);
if (ok != 1) {
fprintf(stderr, "debugmalloc: nem lehet ertelmezni: %s!\n", envptr);
abort();
}
}
}
return (DebugmallocData *) instance;
}
/* better version of strncpy, always terminates string with \0. */
static void debugmalloc_strlcpy(char *dest, char const *src, size_t destsize) {
strncpy(dest, src, destsize);
dest[destsize - 1] = '\0';
}
/* set the name of the log file for debugmalloc. empty filename
* means logging to stderr. */
static void debugmalloc_log_file(char const *logfilename) {
if (logfilename == NULL)
logfilename = "";
DebugmallocData *instance = debugmalloc_singleton();
debugmalloc_strlcpy(instance->logfile, logfilename, sizeof(instance->logfile));
}
/* set the maximum size of one block. useful for debugging purposes. */
static void debugmalloc_max_block_size(long max_block_size) {
DebugmallocData *instance = debugmalloc_singleton();
instance->max_block_size = max_block_size;
}
/* printf to the log file, or stderr. */
static void debugmalloc_log(char const *format, ...) {
DebugmallocData *instance = debugmalloc_singleton();
FILE *f = stderr;
if (instance->logfile[0] != '\0') {
f = fopen(instance->logfile, "at");
if (f == NULL) {
f = stderr;
fprintf(stderr, "debugmalloc: nem tudom megnyitni a %s fajlt irasra!\n", instance->logfile);
debugmalloc_strlcpy(instance->logfile, "", sizeof(instance->logfile));
}
}
va_list ap;
va_start(ap, format);
vfprintf(f, format, ap);
va_end(ap);
if (f != stderr)
fclose(f);
}
/* initialize a memory block allocated for the user. the start and the end
* of the block is initialized with the canary characters. if 'zero' is
* true, the user memory area is zero-initialized, otherwise it is also
* filled with the canary character to simulate garbage in memory. */
static void debugmalloc_memory_init(DebugmallocEntry *elem, bool zero) {
unsigned char *real_mem = (unsigned char *) elem->real_mem;
unsigned char *user_mem = (unsigned char *) elem->user_mem;
unsigned char *canary1 = real_mem;
unsigned char *canary2 = real_mem + debugmalloc_canary_size + elem->size;
memset(canary1, debugmalloc_canary_char, debugmalloc_canary_size);
memset(canary2, debugmalloc_canary_char, debugmalloc_canary_size);
memset(user_mem, zero ? 0 : debugmalloc_canary_char, elem->size);
}
/* check canary, return true if ok, false if corrupted. */
static bool debugmalloc_canary_ok(DebugmallocEntry const *elem) {
unsigned char *real_mem = (unsigned char *) elem->real_mem;
unsigned char *canary1 = real_mem;
unsigned char *canary2 = real_mem + debugmalloc_canary_size + elem->size;
for (size_t i = 0; i < debugmalloc_canary_size; ++i) {
if (canary1[i] != debugmalloc_canary_char)
return false;
if (canary2[i] != debugmalloc_canary_char)
return false;
}
return true;
}
/* dump memory contents to log file. */
static void debugmalloc_dump_memory(char const *mem, size_t size) {
for (unsigned y = 0; y < (size + 15) / 16; y++) {
char line[80];
int pos = 0;
pos += sprintf(line + pos, " %04x ", y * 16);
for (unsigned x = 0; x < 16; x++) {
if (y * 16 + x < size)
pos += sprintf(line + pos, "%02x ", mem[y * 16 + x]);
else
pos += sprintf(line + pos, " ");
}
pos += sprintf(line + pos, " ");
for (unsigned x = 0; x < 16; x++) {
if (y * 16 + x < size) {
unsigned char c = mem[y * 16 + x];
pos += sprintf(line + pos, "%c", isprint(c) ? c : '.');
}
else {
pos += sprintf(line + pos, " ");
}
}
debugmalloc_log("%s\n", line);
}
}
/* dump data of allocated memory block.
* if the canary is corrupted, it is also written to the log. */
static void debugmalloc_dump_elem(DebugmallocEntry const *elem) {
bool canary_ok = debugmalloc_canary_ok(elem);
debugmalloc_log(" %p, %u bajt, kanari: %s\n"
" %s:%u, %s(%s)\n",
elem->user_mem, (unsigned) elem->size, canary_ok ? "ok" : "**SERULT**",
elem->file, elem->line,
elem->func, elem->expr);
if (!canary_ok) {
debugmalloc_log(" ELOTTE kanari: \n");
debugmalloc_dump_memory((char const *) elem->real_mem, debugmalloc_canary_size);
}
debugmalloc_dump_memory((char const *) elem->user_mem, elem->size > 64 ? 64 : elem->size);
if (!canary_ok) {
debugmalloc_log(" UTANA kanari: \n");
debugmalloc_dump_memory((char const *) elem->real_mem + debugmalloc_canary_size + elem->size, debugmalloc_canary_size);
}
}
/* dump data of all memory blocks allocated. */
static void debugmalloc_dump(void) {
DebugmallocData *instance = debugmalloc_singleton();
debugmalloc_log("** DEBUGMALLOC DUMP ************************************\n");
int cnt = 0;
for (size_t i = 0; i < debugmalloc_tablesize; i++) {
DebugmallocEntry *head = &instance->head[i];
for (DebugmallocEntry *iter = head->next; iter->next != NULL; iter = iter->next) {
++cnt;
debugmalloc_log("** %d/%d. rekord:\n", cnt, instance->alloc_count);
debugmalloc_dump_elem(iter);
}
}
debugmalloc_log("** DEBUGMALLOC DUMP VEGE *******************************\n");
}
/* called at program exit to dump data if there is a leak,
* ie. allocated block remained. */
static void debugmalloc_atexit_dump(void) {
DebugmallocData *instance = debugmalloc_singleton();
if (instance->alloc_count > 0) {
debugmalloc_log("\n"
"********************************************************\n"
"* MEMORIASZIVARGAS VAN A PROGRAMBAN!!!\n"
"********************************************************\n"
"\n");
debugmalloc_dump();
} else {
debugmalloc_log("****************************************************\n"
"* Debugmalloc: nincs memoriaszivargas a programban.\n"
"* Osszes foglalas: %d blokk, %d bajt.\n"
"****************************************************\n",
instance->all_alloc_count, instance->all_alloc_bytes);
}
}
/* hash function for bucket hash. */
static size_t debugmalloc_hash(void *address) {
/* the last few bits are ignored, as they are usually zero for
* alignment purposes. all tested architectures used 16 byte allocation. */
size_t cut = (size_t)address >> 4;
return cut % debugmalloc_tablesize;
}
/* insert element to hash table. */
static void debugmalloc_insert(DebugmallocEntry *entry) {
DebugmallocData *instance = debugmalloc_singleton();
size_t idx = debugmalloc_hash(entry->user_mem);
DebugmallocEntry *head = &instance->head[idx];
entry->prev = head;
entry->next = head->next;
head->next->prev = entry;
head->next = entry;
instance->alloc_count += 1;
instance->alloc_bytes += entry->size;
instance->all_alloc_count += 1;
instance->all_alloc_bytes += entry->size;
}
/* remove element from hash table */
static void debugmalloc_remove(DebugmallocEntry *entry) {
DebugmallocData *instance = debugmalloc_singleton();
entry->next->prev = entry->prev;
entry->prev->next = entry->next;
instance->alloc_count -= 1;
instance->alloc_bytes -= entry->size;
}
/* find element in hash table, given with the memory address that the user sees.
* @return the linked list entry, or null if not found. */
static DebugmallocEntry *debugmalloc_find(void *mem) {
DebugmallocData *instance = debugmalloc_singleton();
size_t idx = debugmalloc_hash(mem);
DebugmallocEntry *head = &instance->head[idx];
for (DebugmallocEntry *iter = head->next; iter->next != NULL; iter = iter->next)
if (iter->user_mem == mem)
return iter;
return NULL;
}
/* allocate memory. this function is called via the macro. */
static void *debugmalloc_malloc_full(size_t size, char const *func, char const *expr, char const *file, unsigned line, bool zero) {
/* imitate standard malloc: return null if size is zero */
if (size == 0)
return NULL;
/* check max size */
DebugmallocData *instance = debugmalloc_singleton();
if (size > instance->max_block_size) {
debugmalloc_log("debugmalloc: %s @ %s:%u: a blokk merete tul nagy, %u bajt; debugmalloc_max_block_size() fuggvennyel novelheto.\n", func, file, line, (unsigned) size);
abort();
}
/* allocate more memory, make room for canary */
void *real_mem = malloc(size + 2 * debugmalloc_canary_size);
if (real_mem == NULL) {
debugmalloc_log("debugmalloc: %s @ %s:%u: nem sikerult %u meretu memoriat foglalni!\n", func, file, line, (unsigned) size);
return NULL;
}
/* allocate memory for linked list element */
DebugmallocEntry *newentry = (DebugmallocEntry *) malloc(sizeof(DebugmallocEntry));
if (newentry == NULL) {
free(real_mem);
debugmalloc_log("debugmalloc: %s @ %s:%u: le tudtam foglalni %u memoriat, de utana a sajatnak nem, sry\n", func, file, line, (unsigned) size);
abort();
}
/* metadata of allocation: caller function, code line etc. */
debugmalloc_strlcpy(newentry->func, func, sizeof(newentry->func));
debugmalloc_strlcpy(newentry->expr, expr, sizeof(newentry->expr));
debugmalloc_strlcpy(newentry->file, file, sizeof(newentry->file));
newentry->line = line;
/* address of allocated memory chunk */
newentry->real_mem = real_mem;
newentry->user_mem = (unsigned char *) real_mem + debugmalloc_canary_size;
newentry->size = size;
debugmalloc_memory_init(newentry, zero);
/* store in list and return pointer to user area */
debugmalloc_insert(newentry);
return newentry->user_mem;
}
/* free memory and remove list item. before deleting, the chuck is filled with
* the canary byte to make sure that the user will see garbage if the memory
* is accessed after freeing. */
static void debugmalloc_free_inner(DebugmallocEntry *deleted) {
debugmalloc_remove(deleted);
/* fill with garbage, then remove from linked list */
memset(deleted->real_mem, debugmalloc_canary_char, deleted->size + 2 * debugmalloc_canary_size);
free(deleted->real_mem);
free(deleted);
}
/* free memory - called via the macro.
* as all allocations are tracked in the list, this function can terminate the program
* if a block is freed twice or the free function is called with an invalid address. */
static void debugmalloc_free_full(void *mem, char const *func, char const *file, unsigned line) {
/* imitate standard free function: if ptr is null, no operation is performed */
if (mem == NULL)
return;
/* find allocation, abort if not found */
DebugmallocEntry *deleted = debugmalloc_find(mem);
if (deleted == NULL) {
debugmalloc_log("debugmalloc: %s @ %s:%u: olyan teruletet probalsz felszabaditani, ami nincs lefoglalva!\n", func, file, line);
abort();
}
/* check canary and then free memory */
if (!debugmalloc_canary_ok(deleted)) {
debugmalloc_log("debugmalloc: %s @ %s:%u: a %p memoriateruletet tulindexelted!\n", func, file, line, mem);
debugmalloc_dump_elem(deleted);
}
debugmalloc_free_inner(deleted);
}
/* realloc-like function. */
static void *debugmalloc_realloc_full(void *oldmem, size_t newsize, char const *func, char const *expr, char const *file, unsigned line) {
/* imitate standard realloc: equivalent to free if size is null. */
if (newsize == 0) {
debugmalloc_free_full(oldmem, func, file, line);
return NULL;
}
/* imitate standard realloc: equivalent to malloc if first param is NULL */
if (oldmem == NULL)
return debugmalloc_malloc_full(newsize, func, expr, file, line, 0);
/* find old allocation. abort if not found. */
DebugmallocEntry *oldentry = debugmalloc_find(oldmem);
if (oldentry == NULL) {
debugmalloc_log("debugmalloc: %s @ %s:%u: olyan teruletet probalsz atmeretezni, ami nincs lefoglalva!\n", func, file, line);
abort();
}
/* create new allocation, copy & free old data */
void *newmem = debugmalloc_malloc_full(newsize, func, expr, file, line, false);
if (newmem == NULL) {
debugmalloc_log("debugmalloc: %s @ %s:%u: nem sikerult uj memoriat foglalni az atmeretezeshez!\n", func, file, line);
/* imitate standard realloc: original block is untouched, but return NULL */
return NULL;
}
size_t smaller = oldentry->size < newsize ? oldentry->size : newsize;
memcpy(newmem, oldmem, smaller);
debugmalloc_free_inner(oldentry);
return newmem;
}
/* initialize debugmalloc singleton. returns the newly allocated instance */
static DebugmallocData * debugmalloc_create(void) {
/* config check */
if (debugmalloc_canary_size % 16 != 0) {
debugmalloc_log("debugmalloc: a kanari merete legyen 16-tal oszthato\n");
abort();
}
if (debugmalloc_canary_char == 0) {
debugmalloc_log("debugmalloc: a kanari legyen 0-tol kulonbozo\n");
abort();
}
/* avoid compiler warning if these functions are not used */
(void) debugmalloc_realloc_full;
(void) debugmalloc_log_file;
(void) debugmalloc_max_block_size;
/* create and initialize instance */
DebugmallocData *instance = (DebugmallocData *) malloc(sizeof(DebugmallocData));
if (instance == NULL) {
debugmalloc_log("debugmalloc: nem sikerult elinditani a memoriakezelest\n");
abort();
}
debugmalloc_strlcpy(instance->logfile, "", sizeof(instance->logfile));
instance->max_block_size = debugmalloc_max_block_size_default;
instance->alloc_count = 0;
instance->alloc_bytes = 0;
instance->all_alloc_count = 0;
instance->all_alloc_bytes = 0;
for (size_t i = 0; i < debugmalloc_tablesize; i++) {
instance->head[i].prev = NULL;
instance->head[i].next = &instance->tail[i];
instance->tail[i].next = NULL;
instance->tail[i].prev = &instance->head[i];
}
atexit(debugmalloc_atexit_dump);
return instance;
}
/* These macro-like functions forward all allocation/free
* calls to debugmalloc. Usage is the same, malloc(size)
* gives the address of a new memory block, free(ptr)
* deallocates etc.
*
* If you use this file, make sure that you include this
* in *ALL* translation units (*.c) of your source. The
* builtin free() function cannot deallocate a memory block
* that was allocated via debugmalloc, yet the name of
* the function is the same! */
#define malloc(S) debugmalloc_malloc_full((S), "malloc", #S, __FILE__, __LINE__, false)
#define calloc(N,S) debugmalloc_malloc_full((N)*(S), "calloc", #N ", " #S, __FILE__, __LINE__, true)
#define realloc(P,S) debugmalloc_realloc_full((P), (S), "realloc", #S, __FILE__, __LINE__)
#define free(P) debugmalloc_free_full((P), "free", __FILE__, __LINE__)
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment