changeset 11:fa252ebd583c

Core: clean up and use nsnake_ prefix for functions
author David Demelier <markand@malikania.fr>
date Fri, 26 Feb 2016 12:43:53 +0100
parents 8b877aae471c
children 9ae0adf264b1
files nsnake.c nsnake.h
diffstat 2 files changed, 392 insertions(+), 373 deletions(-) [+]
line wrap: on
line diff
--- a/nsnake.c	Fri Feb 26 12:15:07 2016 +0100
+++ b/nsnake.c	Fri Feb 26 12:43:53 2016 +0100
@@ -16,288 +16,46 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <time.h>
-
-#include <curses.h>
-
-#if defined(_WIN32)
-#  include <io.h>
-#  include <lmcons.h>
-#  include <Windows.h>
-#else
-#  include <sys/types.h>
-#  include <pwd.h>
-#endif
-
-#include "config.h"
-
-#if defined(HAVE_ERR)
-#  include <err.h>
-#endif
-
-#if !defined(HAVE_RANDOM)
-#  define random rand
-#  define srandom srand
-#endif
-
-#define	HEIGHT		23
-#define WIDTH		78
-#define SIZE		((HEIGHT - 2) * (WIDTH - 2))
-
-#define EMPTY		0
-#define WALL		1
-#define SNAKE		2
-#define FOOD		3
-
-#define WSET(frame, pair)	if (setcolors) wattron(frame, pair)
-#define WUNSET(frame, pair)	if (setcolors) wattroff(frame, pair)
-#define REFRESH()		refresh(); wrefresh(top); wrefresh(frame);
+#include "nsnake.h"
 
 /* --------------------------------------------------------
- * structure definitions
- * -------------------------------------------------------- */
-
-struct snake {
-	uint32_t	score;		/* user score */
-	uint16_t	length;		/* snake's size */
-	int8_t		dirx;		/* direction in x could be 0, 1 or -1 */
-	int8_t		diry;		/* same for y */
-
-	struct {
-		uint8_t x;		/* each snake part has (x, y) position */
-		uint8_t y;		/* each part will be displayed */
-	} pos[SIZE];
-};
-
-struct food {
-	enum {
-		NORM = 0,		/* both increase the score but only NORM */
-		FREE			/* increase the snake's length too */
-	} type;
-
-	uint8_t x;			/* Position of the current food, will be used */
-	uint8_t y;			/* in grid[][]. */
-};
-
-struct score {
-#if defined(_WIN32)
-#  define NAMELEN UNLEN
-#else
-#  define NAMELEN 32
-#endif
-	char		name[NAMELEN + 1];	/* highscore's name */
-	uint32_t	score;			/* score */
-	time_t		time;			/* when? */
-	uint8_t		wc;			/* wallcrossing or not */
-};
-
-/* --------------------------------------------------------
- * global variables and options
- * -------------------------------------------------------- */
-
-static int	setcolors	= 1;	/* enable colors */
-static int	warp		= 1;	/* enable wall crossing */
-static int	color		= 2;	/* green color by default */
-static int	noscore		= 0;	/* do not score */
-static int	verbose		= 0;	/* be verbose */
-
-static uint8_t	grid[HEIGHT][WIDTH] = { { EMPTY } };
-static WINDOW	*top = NULL;
-static WINDOW	*frame = NULL;
-
-/* --------------------------------------------------------
- * prototypes
+ * global options and variables
  * -------------------------------------------------------- */
 
-static int	uinit(void);
-static void	setgrid(struct snake *);
-static void	draw(const struct snake *, const struct food *);
-static int	isdead(const struct snake *);
-static int	iseaten(const struct snake *);
-static void	spawn(struct food *);
-static void	direction(struct snake *, int);
-static int	registerscore(const struct snake *);
-static int	appendscore(const struct score *);
-static int	insertscore(const struct score *);
-static void	showscores(void);
-static void	wait(unsigned ms);
-
-#if defined(HAVE_SIGWINCH)
-static void	resizehandler(int);
-#endif
-
-static void	quit(const struct snake *);
-static void	usage(void);
-
-/* Portability */
-#if !defined(HAVE_ERR)
-
-static void err(int, const char *, ...);
-static void errx(int, const char *, ...);
-
-#endif
-
-int
-main(int argc, char *argv[])
-{
-	int running;
-	int x, y, ch;
-	int showscore = 0;
-
-	struct snake sn = { 0, 4, 1, 0, {
-		{5, 10}, {5, 9}, {5, 8}, {5, 7} }
-	};
-
-	struct food fd = { NORM, 0, 0 };
+static int setcolors = 1;	/* enable colors */
+static int warp = 1;		/* enable wall crossing */
+static int color = 2;		/* green color by default */
+static int noscore = 0;		/* do not score */
+static int verbose = 0;		/* be verbose */
 
-	/* Process options */
-	while ((ch = getopt(argc, argv, "cC:nsvw")) != -1) {
-		switch (ch) {
-		case 'c': setcolors = 0;	break;
-		case 'C': color = atoi(optarg);	break;
-		case 'n': noscore = 1;		break;
-		case 's': showscore = 1;	break;
-		case 'v': verbose = 1;		break;
-		case 'w': warp = 0;		break;
-		case '?':
-		default :
-			  usage();
-			  /* NOTREACHED */
-		}
-	}
-
-	if (showscore)
-		showscores();
-
-	argc -= optind;
-	argv += optind;
-
-	/* Game init */
-	srandom((unsigned)time(NULL));
-
-#if defined(HAVE_SIGWINCH)
-	signal(SIGWINCH, resizehandler);
-#endif
-
-	if (!uinit()) {
-		quit(NULL);
-		errx(1, "Terminal too small, aborting");
-	}
-		
-	if (top == NULL || frame == NULL) {
-		endwin();
-		errx(1, "ncurses failed to init");
-	}
-
-	/* Apply WALL to the edges */
-	for (y = 0; y < HEIGHT; ++y)
-		grid[y][0] = grid[y][WIDTH - 1] = WALL;
-	for (x = 0; x < WIDTH; ++x)
-		grid[0][x] = grid[HEIGHT - 1][x] = WALL;
-
-	/* Do not spawn food on snake */
-	setgrid(&sn);
-	spawn(&fd);
+static uint8_t grid[HEIGHT][WIDTH] = { { GridEmpty } };
+static WINDOW *top = NULL;
+static WINDOW *frame = NULL;
 
-	/* Apply food on the grid */
-	grid[fd.y][fd.x] = FOOD;
-	draw(&sn, &fd);
-
-	/* First direction is to right */
-	sn.pos[0].x += sn.dirx;
-
-	running = 1;
-	while (!isdead(&sn) && running) {
-		if (iseaten(&sn)) {
-			int i;
-
-			if (fd.type == NORM)
-				sn.length += 2;
-
-			for (i = 0; i < sn.length; ++i)
-				grid[sn.pos[i].y][sn.pos[i].x] = SNAKE;
-
-			/* If the screen is totally filled */
-			if (sn.length >= SIZE) {
-				/* Emulate new game */
-				for (i = 4; i < SIZE; ++i) {
-					(void)mvwaddch(frame, sn.pos[i].y, sn.pos[i].x, ' ');
-					grid[sn.pos[i].y][sn.pos[i].x] = EMPTY;
-				}
-
-				sn.length = 4;
-			}
-
-			if (fd.type == NORM)
-				setgrid(&sn);
-
-			/* Prevent food spawning on snake's tail */
-			spawn(&fd);
-
-			sn.score += 1;
-			grid[fd.y][fd.x] = FOOD;
-		}
-
-		/* Draw and define grid with snake parts */
-		draw(&sn, &fd);
-		setgrid(&sn);
+static void
+nsnake_wset(WINDOW *frame, int pair)
+{
+	if (setcolors)
+		wattron(frame, pair);
+}
 
-		/* Go to the next position */
-		sn.pos[0].x += sn.dirx;
-		sn.pos[0].y += sn.diry;
-
-		ch = getch();
-		if (ch == 'p') {
-			nodelay(stdscr, FALSE);
-			while ((ch = getch()) != 'p' && ch != 'q')
-				;
-
-			if (ch == 'q')
-				running = 0;
-
-			nodelay(stdscr, TRUE);
-		} else if (ch == 'q')
-			running = 0;
-		else if (ch == 'c')
-			color = (color + 1) % 8;
-		else if (ch)
-			direction(&sn, ch);
+static void
+nsnake_wunset(WINDOW *frame, int pair)
+{
+	if (setcolors)
+		wattroff(frame, pair);
+}
 
-		/* If warp enabled, touching wall cross to the opposite */
-		if (warp) {
-			if (sn.pos[0].x == WIDTH - 1)
-				sn.pos[0].x = 1;
-			else if (sn.pos[0].x == 0)
-				sn.pos[0].x = WIDTH - 2;
-			else if (sn.pos[0].y == HEIGHT - 1)
-				sn.pos[0].y = 1;
-			else if (sn.pos[0].y == 0)
-				sn.pos[0].y = HEIGHT - 2;
-		}
-
-		wait(100);
-	}
-
-	/* The snake is dead. */
-	quit(&sn);
-
-	/* User has left or is he dead? */
-	printf("%sScore: %d\n", (grid[sn.pos[0].y][sn.pos[0].x] != EMPTY) ?
-	    "You died...\n" : "", sn.score);
-
-	if (!noscore && !registerscore(&sn))
-		err(1, "Could not write score file %s", NSNAKE_SCOREFILE);
-
-	return 0;
+static void
+nsnake_refresh(void)
+{
+	refresh();
+	wrefresh(top);
+	wrefresh(frame);
 }
 
 static int
-uinit(void)
+nsnake_init(void)
 {
 	/* Ncurses init */
 	initscr();
@@ -306,8 +64,8 @@
 	keypad(stdscr, TRUE);
 	nodelay(stdscr, TRUE);
 
-	if (COLS < (WIDTH + 1) || LINES < (HEIGHT + 1))	
-		return 0;
+	if (COLS < (WIDTH + 1) || LINES < (HEIGHT + 1))
+		return -1;
 
 	if (color < 0 || color > 8)
 		color = 4;
@@ -336,83 +94,82 @@
 		wattrset(top, COLOR_PAIR(0) | A_BOLD);
 	}
 
-	REFRESH();
+	nsnake_refresh();
 
 	return 1;
 }
 
 static void
-setgrid(struct snake *sn)
+nsnake_set_grid(struct snake *sn)
 {
 	uint16_t i;
 
 	for (i = 0; i < sn->length; ++i)
-		grid[sn->pos[i].y][sn->pos[i].x] = SNAKE;
+		grid[sn->pos[i].y][sn->pos[i].x] = GridSnake;
 
 	/*
 	 * each snake part must follow the last part, pos[0] is head, then
 	 * pos[2] takes pos[1] place, pos[3] takes pos[2] and so on.
 	 */
-	grid[sn->pos[sn->length-1].y][sn->pos[sn->length-1].x] = EMPTY;
+	grid[sn->pos[sn->length-1].y][sn->pos[sn->length-1].x] = GridEmpty;
 	memmove(&sn->pos[1], &sn->pos[0], sizeof (sn->pos) - sizeof (sn->pos[0]));
 }
 
 static void
-draw(const struct snake *sn, const struct food *fd)
+nsnake_draw(const struct snake *sn, const struct food *fd)
 {
 	uint16_t i;
 
 	for (i = 0; i < sn->length; ++i) {
-		WSET(frame, COLOR_PAIR(color));
-		(void)mvwaddch(frame, sn->pos[i].y, sn->pos[i].x, '#');
-		WUNSET(frame, COLOR_PAIR(color));
+		nsnake_wset(frame, COLOR_PAIR(color));
+		mvwaddch(frame, sn->pos[i].y, sn->pos[i].x, '#');
+		nsnake_wunset(frame, COLOR_PAIR(color));
 	}
 
 	/* Print head */
-	WSET(frame, COLOR_PAIR(color) | A_BOLD);
-	(void)mvwaddch(frame, sn->pos[0].y, sn->pos[0].x, '@');
-	WUNSET(frame, COLOR_PAIR(color) | A_BOLD);
+	nsnake_wset(frame, COLOR_PAIR(color) | A_BOLD);
+	mvwaddch(frame, sn->pos[0].y, sn->pos[0].x, '@');
+	nsnake_wunset(frame, COLOR_PAIR(color) | A_BOLD);
 
 	/* Erase the snake's tail */
-	(void)mvwaddch(frame, sn->pos[sn->length].y, sn->pos[sn->length].x, ' ');
+	mvwaddch(frame, sn->pos[sn->length].y, sn->pos[sn->length].x, ' ');
 
 	/* Print food */
-	WSET(frame, COLOR_PAIR(1) | A_BOLD);
-	(void)mvwaddch(frame, fd->y, fd->x, (fd->type == FREE) ? '*' : '+');
-	WUNSET(frame, COLOR_PAIR(1) | A_BOLD);
+	nsnake_wset(frame, COLOR_PAIR(1) | A_BOLD);
+	mvwaddch(frame, fd->y, fd->x, (fd->type == FREE) ? '*' : '+');
+	nsnake_wunset(frame, COLOR_PAIR(1) | A_BOLD);
 
 	/* Print score */
-	(void)wmove(top, 0, 0);
-	(void)wprintw(top, "Score : %d", sn->score);
-
-	REFRESH();
+	wmove(top, 0, 0);
+	wprintw(top, "Score : %d", sn->score);
+	nsnake_refresh();
 }
 
 static int
-isdead(const struct snake *sn)
+nsnake_is_dead(const struct snake *sn)
 {
-	if (grid[sn->pos[0].y][sn->pos[0].x] == SNAKE)
+	if (grid[sn->pos[0].y][sn->pos[0].x] == GridSnake)
 		return 1;
 
 	/* No warp enabled means dead in wall */
-	return (!warp && grid[sn->pos[0].y][sn->pos[0].x] == WALL);
+	return (!warp && grid[sn->pos[0].y][sn->pos[0].x] == GridWall);
 }
 
 static int
-iseaten(const struct snake *sn)
+nsnake_is_eaten(const struct snake *sn)
 {
-	return grid[sn->pos[0].y][sn->pos[0].x] == FOOD;
+	return grid[sn->pos[0].y][sn->pos[0].x] == GridFood;
 }
 
 static void
-spawn(struct food *fd)
+nsnake_spawn(struct food *fd)
 {
 	int num;
 
 	do {
 		fd->x = (random() % (WIDTH - 2)) + 1;
 		fd->y = (random() % (HEIGHT - 2)) + 1;
-	} while (grid[fd->y][fd->x] != EMPTY);
+	} while (grid[fd->y][fd->x] != GridEmpty);
 
 	/* Free food does not grow the snake */
 	num		= ((random() % 7) - 1) + 1;
@@ -420,54 +177,44 @@
 }
 
 static void
-direction(struct snake *sn, int ch)
+nsnake_direction(struct snake *sn, int ch)
 {
 	switch (ch) {
 	case KEY_LEFT: case 'h': case 'H':
-		if (sn->dirx != 1) { sn->dirx = -1; sn->diry = 0; }
+		if (sn->dirx != 1) {
+			sn->dirx = -1;
+			sn->diry = 0;
+		}
+
 		break;
 	case KEY_UP: case 'k': case 'K':
-		if (sn->diry != 1) { sn->dirx = 0; sn->diry = -1; }
+		if (sn->diry != 1) {
+			sn->dirx = 0;
+			sn->diry = -1;
+		}
+
 		break;
 	case KEY_DOWN: case 'j': case 'J':
-		if (sn->diry != -1) { sn->dirx = 0; sn->diry = 1; }
+		if (sn->diry != -1) {
+			sn->dirx = 0;
+			sn->diry = 1;
+		}
+
 		break;
 	case KEY_RIGHT: case 'l': case 'L':
-		if (sn->dirx != -1) { sn->dirx = 1; sn->diry = 0; }
+		if (sn->dirx != -1) {
+			sn->dirx = 1;
+			sn->diry = 0;
+		}
+
+		break;
 	default:
 		break;
 	}
 }
 
 static int
-registerscore(const struct snake *sn)
-{
-	struct score sc;
-	int (*reshandler)(const struct score *);
-
-	memset(&sc, 0, sizeof (sc));
-
-#if defined(_WIN32)
-	DWORD length = NAMELEN + 1;
-	GetUserNameA(sc.name, &length);
-#else
-	strncpy(sc.name, getpwuid(getuid())->pw_name, sizeof (sc.name));
-#endif
-	sc.score	= sn->score;
-	sc.time		= time(NULL);
-	sc.wc		= warp;
-
-	reshandler = (access(NSNAKE_SCOREFILE, F_OK) == -1) ? &appendscore : &insertscore;
-
-	return reshandler(&sc);
-}
-
-/*
- * Create the file and append the score when it does not exists.
- */
-
-static int
-appendscore(const struct score *sc)
+nsnake_append_score(const struct score *sc)
 {
 	FILE *fp;
 	char header[12] = "nsnake-score";
@@ -479,14 +226,13 @@
 	fwrite(header, sizeof (header), 1, fp);
 	fwrite(&nscore, sizeof (nscore), 1, fp);
 	fwrite(sc, sizeof (*sc), 1, fp);
-
 	fclose(fp);
 
 	return 1;
 }
 
 static int
-insertscore(const struct score *sc)
+nsnake_insert_score(const struct score *sc)
 {
 	FILE *fp;
 	uint32_t nscore, i;
@@ -531,15 +277,37 @@
 	/* Finally write */
 	fseek(fp, sizeof (header) + sizeof (nscore), SEEK_SET);
 	fwrite(buffer, sizeof (*sc), nscore, fp);
-
 	free(buffer);
 	fclose (fp);
 
 	return 1;
 }
 
-static void
-showscores(void)
+static int
+nsnake_register_score(const struct snake *sn)
+{
+	struct score sc;
+	int (*reshandler)(const struct score *);
+
+	memset(&sc, 0, sizeof (sc));
+
+#if defined(_WIN32)
+	DWORD length = NAMELEN + 1;
+	GetUserNameA(sc.name, &length);
+#else
+	strncpy(sc.name, getpwuid(getuid())->pw_name, sizeof (sc.name));
+#endif
+	sc.score	= sn->score;
+	sc.time		= time(NULL);
+	sc.wc		= warp;
+
+	reshandler = (access(NSNAKE_SCOREFILE, F_OK) == -1) ? &nsnake_append_score : &nsnake_insert_score;
+
+	return reshandler(&sc);
+}
+
+void
+nsnake_show_scores(void)
 {
 	FILE *fp;
 	uint32_t nscore, i;
@@ -573,8 +341,8 @@
 	exit(0);
 }
 
-static void
-wait(unsigned ms)
+void
+nsnake_wait(unsigned ms)
 {
 #if defined(_WIN32)
 	Sleep(ms);
@@ -586,7 +354,7 @@
 #if defined(HAVE_SIGWINCH)
 
 void
-resizehandler(int signal)
+nsnake_resize_handler(int signal)
 {
 	int x, y;
 
@@ -615,65 +383,187 @@
 	}
 
 	mvwin(frame, (y / 2) - (HEIGHT / 2), (x / 2) - (WIDTH / 2));
-
-	REFRESH();
+	nsnake_refresh();
 }
 
 #endif
 
 static void
-quit(const struct snake *sn)
+nsnake_quit(const struct snake *sn)
 {
 	uint16_t i;
 
 	if (sn != NULL) {
 		for (i = 0; i < sn->length; ++i) {
-			(void)mvwaddch(frame, sn->pos[i].y, sn->pos[i].x, ' ');
-			wait(50);
-			REFRESH();
+			mvwaddch(frame, sn->pos[i].y, sn->pos[i].x, ' ');
+			nsnake_wait(50);
+			nsnake_refresh();
 		}
 	}
 
-	delwin(top); delwin(frame); delwin(stdscr);
+	delwin(top);
+	delwin(frame);
+	delwin(stdscr);
 	endwin();
 }
 
 static void
-usage(void)
+nsnake_usage(void)
 {
 	fprintf(stderr, "usage: nsnake [-cnsvw] [-C color]\n");
 	exit(1);
 }
 
-#if !defined(HAVE_ERR)
-
-#include <errno.h>
-
-static void
-err(int code, const char *fmt, ...)
+int
+main(int argc, char *argv[])
 {
-	va_list ap;
+	int running;
+	int x, y, ch;
+	int showscore = 0;
+
+	struct snake sn = { 0, 4, 1, 0, {
+		{5, 10}, {5, 9}, {5, 8}, {5, 7} }
+	};
+
+	struct food fd = { NORM, 0, 0 };
+
+	/* Process options */
+	while ((ch = getopt(argc, argv, "cC:nsvw")) != -1) {
+		switch (ch) {
+		case 'c': setcolors = 0;	break;
+		case 'C': color = atoi(optarg);	break;
+		case 'n': noscore = 1;		break;
+		case 's': showscore = 1;	break;
+		case 'v': verbose = 1;		break;
+		case 'w': warp = 0;		break;
+		case '?':
+		default :
+			nsnake_usage();
+			/* NOTREACHED */
+		}
+	}
+
+	if (showscore)
+		nsnake_show_scores();
+
+	argc -= optind;
+	argv += optind;
+
+	/* Game init */
+	srandom((unsigned)time(NULL));
 
-	va_start(ap, fmt);
-	fprintf(stderr, "nsnake: ");
-	vfprintf(stderr, fmt, ap);
-	fprintf(stderr, ": %s", strerror(errno));
-	va_end(ap);
+#if defined(HAVE_SIGWINCH)
+	signal(SIGWINCH, nsnake_resize_handler);
+#endif
+
+	if (!nsnake_init()) {
+		nsnake_quit(NULL);
+		errx(1, "Terminal too small, aborting");
+	}
+		
+	if (top == NULL || frame == NULL) {
+		endwin();
+		errx(1, "ncurses failed to init");
+	}
+
+	/* Apply GridWall to the edges */
+	for (y = 0; y < HEIGHT; ++y)
+		grid[y][0] = grid[y][WIDTH - 1] = GridWall;
+	for (x = 0; x < WIDTH; ++x)
+		grid[0][x] = grid[HEIGHT - 1][x] = GridWall;
+
+	/* Do not spawn food on snake */
+	nsnake_set_grid(&sn);
+	nsnake_spawn(&fd);
+
+	/* Apply food on the grid */
+	grid[fd.y][fd.x] = GridFood;
+	nsnake_draw(&sn, &fd);
+
+	/* First direction is to right */
+	sn.pos[0].x += sn.dirx;
+
+	running = 1;
+	while (!nsnake_is_dead(&sn) && running) {
+		if (nsnake_is_eaten(&sn)) {
+			int i;
+
+			if (fd.type == NORM)
+				sn.length += 2;
 
-	exit(code);
-}
+			for (i = 0; i < sn.length; ++i)
+				grid[sn.pos[i].y][sn.pos[i].x] = GridSnake;
+
+			/* If the screen is totally filled */
+			if (sn.length >= SIZE) {
+				/* Emulate new game */
+				for (i = 4; i < SIZE; ++i) {
+					mvwaddch(frame, sn.pos[i].y, sn.pos[i].x, ' ');
+					grid[sn.pos[i].y][sn.pos[i].x] = GridEmpty;
+				}
+
+				sn.length = 4;
+			}
+
+			if (fd.type == NORM)
+				nsnake_set_grid(&sn);
 
-static void
-errx(int code, const char *fmt, ...)
-{
-	va_list ap;
+			/* Prevent food spawning on snake's tail */
+			nsnake_spawn(&fd);
+
+			sn.score += 1;
+			grid[fd.y][fd.x] = GridFood;
+		}
+
+		/* Draw and define grid with snake parts */
+		nsnake_draw(&sn, &fd);
+		nsnake_set_grid(&sn);
+
+		/* Go to the next position */
+		sn.pos[0].x += sn.dirx;
+		sn.pos[0].y += sn.diry;
+
+		ch = getch();
+		if (ch == 'p') {
+			nodelay(stdscr, FALSE);
+			while ((ch = getch()) != 'p' && ch != 'q')
+				;
 
-	va_start(ap, fmt);
-	fprintf(stderr, "nsnake: ");
-	vfprintf(stderr, fmt, ap);
-	va_end(ap);
+			if (ch == 'q')
+				running = 0;
+
+			nodelay(stdscr, TRUE);
+		} else if (ch == 'q')
+			running = 0;
+		else if (ch == 'c')
+			color = (color + 1) % 8;
+		else if (ch)
+			nsnake_direction(&sn, ch);
 
-	exit(code);
+		/* If warp enabled, touching wall cross to the opposite */
+		if (warp) {
+			if (sn.pos[0].x == WIDTH - 1)
+				sn.pos[0].x = 1;
+			else if (sn.pos[0].x == 0)
+				sn.pos[0].x = WIDTH - 2;
+			else if (sn.pos[0].y == HEIGHT - 1)
+				sn.pos[0].y = 1;
+			else if (sn.pos[0].y == 0)
+				sn.pos[0].y = HEIGHT - 2;
+		}
+
+		nsnake_wait(100);
+	}
+
+	/* The snake is dead. */
+	nsnake_quit(&sn);
+
+	/* User has left or is he dead? */
+	printf("%sScore: %d\n", (grid[sn.pos[0].y][sn.pos[0].x] != GridEmpty) ?
+	    "You died...\n" : "", sn.score);
+
+	if (!noscore && !nsnake_register_score(&sn))
+		err(1, "Could not write score file %s", NSNAKE_SCOREFILE);
+
+	return 0;
 }
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nsnake.h	Fri Feb 26 12:43:53 2016 +0100
@@ -0,0 +1,129 @@
+/*
+ * nsnake.h -- a snake game for your terminal
+ *
+ * Copyright (c) 2011-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _NSNAKE_H_
+#define _NSNAKE_H_
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <time.h>
+
+#include <curses.h>
+
+#if defined(_WIN32)
+#  include <io.h>
+#  include <lmcons.h>
+#  include <Windows.h>
+#else
+#  include <sys/types.h>
+#  include <pwd.h>
+#endif
+
+#include "config.h"
+
+#if defined(HAVE_ERR)
+#  include <err.h>
+#endif
+
+#if !defined(HAVE_RANDOM)
+#  define random rand
+#  define srandom srand
+#endif
+
+#define	HEIGHT		23
+#define WIDTH		78
+#define SIZE		((HEIGHT - 2) * (WIDTH - 2))
+
+enum Grid {
+	GridEmpty,
+	GridWall,
+	GridSnake,
+	GridFood
+};
+
+struct snake {
+	uint32_t	score;		/* user score */
+	uint16_t	length;		/* snake's size */
+	int8_t		dirx;		/* direction in x could be 0, 1 or -1 */
+	int8_t		diry;		/* same for y */
+
+	struct {
+		uint8_t x;		/* each snake part has (x, y) position */
+		uint8_t y;		/* each part will be displayed */
+	} pos[SIZE];
+};
+
+struct food {
+	enum {
+		NORM = 0,		/* both increase the score but only NORM */
+		FREE			/* increase the snake's length too */
+	} type;
+
+	uint8_t x;			/* Position of the current food, will be used */
+	uint8_t y;			/* in grid[][]. */
+};
+
+struct score {
+#if defined(_WIN32)
+#  define NAMELEN UNLEN
+#else
+#  define NAMELEN 32
+#endif
+	char		name[NAMELEN + 1];	/* highscore's name */
+	uint32_t	score;			/* score */
+	time_t		time;			/* when? */
+	uint8_t		wc;			/* wallcrossing or not */
+};
+
+#if !defined(HAVE_ERR)
+
+#include <errno.h>
+
+static void
+err(int code, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	fprintf(stderr, "nsnake: ");
+	vfprintf(stderr, fmt, ap);
+	fprintf(stderr, ": %s", strerror(errno));
+	va_end(ap);
+
+	exit(code);
+}
+
+static void
+errx(int code, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	fprintf(stderr, "nsnake: ");
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+
+	exit(code);
+}
+
+#endif /* _HAVE_ERR */
+
+#endif /* !_NSNAKE_H_ */
\ No newline at end of file