[PATCH] 2048: port to barebox

Marc Kleine-Budde mkl at pengutronix.de
Tue Apr 8 14:50:42 PDT 2014


Signed-off-by: Marc Kleine-Budde <mkl at pengutronix.de>
---
 common/2048/2048.c    | 357 ++++++++++++++++++++++++++++++++++++++++++++++++++
 common/2048/LICENSE   |  21 +++
 common/2048/Makefile  |   1 +
 common/2048/README.md |  32 +++++
 common/Makefile       |   1 +
 5 files changed, 412 insertions(+)
 create mode 100644 common/2048/2048.c
 create mode 100644 common/2048/LICENSE
 create mode 100644 common/2048/Makefile
 create mode 100644 common/2048/README.md

diff --git a/common/2048/2048.c b/common/2048/2048.c
new file mode 100644
index 0000000..fe9970e
--- /dev/null
+++ b/common/2048/2048.c
@@ -0,0 +1,357 @@
+/*
+ ============================================================================
+ Name        : 2048.c
+ Author      : Maurits van der Schee
+ Description : Console version of the game "2048" for GNU/Linux
+ ============================================================================
+ */
+
+#include <common.h>
+#include <readkey.h>
+#include <command.h>
+#include <stdlib.h>
+
+#define SIZE 4
+static uint32_t score;
+
+static void getColor(uint16_t value, char *color, size_t length) {
+#if 0
+	uint8_t blackwhite[] = {232,255,234,255,236,255,238,255,240,255,242,255,244,255,246,0,248,0,249,0,250,0,251,0,252,0,253,0,254,0,255,0};
+	uint8_t bluered[] = {235,255,63,255,57,255,93,255,129,255,165,255,201,255,200,255,199,255,198,255,197,255,196,255,196,255,196,255,196,255,196,255};
+#endif
+	uint8_t original[] = {8,255,1,255,2,255,3,255,4,255,5,255,6,255,7,255,9,0,10,0,11,0,12,0,13,0,14,0,255,0,255,0};
+	uint8_t *scheme = original;
+	uint8_t *background = scheme+0;
+	uint8_t *foreground = scheme+1;
+	if (value > 0) while (value >>= 1) {
+		if (background+2<scheme+sizeof(original)) {
+			background+=2;
+			foreground+=2;
+		}
+	}
+	snprintf(color,length,"\033[38;5;%d;48;5;%dm",*foreground,*background);
+}
+
+static void drawBoard(uint16_t board[SIZE][SIZE]) {
+	int8_t x,y;
+	char color[40], reset[] = "\033[m";
+	printf("\033[H");
+
+	printf("2048.c %17d pts\n\n",score);
+
+	for (y=0;y<SIZE;y++) {
+		for (x=0;x<SIZE;x++) {
+			getColor(board[x][y],color,40);
+			printf("%s",color);
+			printf("       ");
+			printf("%s",reset);
+		}
+		printf("\n");
+		for (x=0;x<SIZE;x++) {
+			getColor(board[x][y],color,40);
+			printf("%s",color);
+			if (board[x][y]!=0) {
+				char s[8];
+				int8_t t;
+				snprintf(s,8,"%u",board[x][y]);
+				t = 7-strlen(s);
+				printf("%*s%s%*s",t-t/2,"",s,t/2,"");
+			} else {
+				printf("   ·   ");
+			}
+			printf("%s",reset);
+		}
+		printf("\n");
+		for (x=0;x<SIZE;x++) {
+			getColor(board[x][y],color,40);
+			printf("%s",color);
+			printf("       ");
+			printf("%s",reset);
+		}
+		printf("\n");
+	}
+	printf("\n");
+	printf("        ←,↑,→,↓ or q        \n");
+	printf("\033[A");
+}
+
+static int8_t findTarget(uint16_t array[SIZE],int8_t x,int8_t stop) {
+	int8_t t;
+	// if the position is already on the first, don't evaluate
+	if (x==0) {
+		return x;
+	}
+	for(t=x-1;t>=0;t--) {
+		if (array[t]!=0) {
+			if (array[t]!=array[x]) {
+				// merge is not possible, take next position
+				return t+1;
+			}
+			return t;
+		} else {
+			// we should not slide further, return this one
+			if (t==stop) {
+				return t;
+			}
+		}
+	}
+	// we did not find a
+	return x;
+}
+
+static bool slideArray(uint16_t array[SIZE]) {
+	bool success = false;
+	int8_t x,t,stop=0;
+
+	for (x=0;x<SIZE;x++) {
+		if (array[x]!=0) {
+			t = findTarget(array,x,stop);
+			// if target is not original position, then move or merge
+			if (t!=x) {
+				// if target is not zero, set stop to avoid double merge
+				if (array[t]!=0) {
+					score+=array[t]+array[x];
+					stop = t+1;
+				}
+				array[t]+=array[x];
+				array[x]=0;
+				success = true;
+			}
+		}
+	}
+	return success;
+}
+
+static void rotateBoard(uint16_t board[SIZE][SIZE]) {
+	int8_t i,j,n=SIZE;
+	uint16_t tmp;
+	for (i=0; i<n/2; i++){
+		for (j=i; j<n-i-1; j++){
+			tmp = board[i][j];
+			board[i][j] = board[j][n-i-1];
+			board[j][n-i-1] = board[n-i-1][n-j-1];
+			board[n-i-1][n-j-1] = board[n-j-1][i];
+			board[n-j-1][i] = tmp;
+		}
+	}
+}
+
+static bool moveUp(uint16_t board[SIZE][SIZE]) {
+	bool success = false;
+	int8_t x;
+	for (x=0;x<SIZE;x++) {
+		success |= slideArray(board[x]);
+	}
+	return success;
+}
+
+static bool moveLeft(uint16_t board[SIZE][SIZE]) {
+	bool success;
+	rotateBoard(board);
+	success = moveUp(board);
+	rotateBoard(board);
+	rotateBoard(board);
+	rotateBoard(board);
+	return success;
+}
+
+static bool moveDown(uint16_t board[SIZE][SIZE]) {
+	bool success;
+	rotateBoard(board);
+	rotateBoard(board);
+	success = moveUp(board);
+	rotateBoard(board);
+	rotateBoard(board);
+	return success;
+}
+
+static bool moveRight(uint16_t board[SIZE][SIZE]) {
+	bool success;
+	rotateBoard(board);
+	rotateBoard(board);
+	rotateBoard(board);
+	success = moveUp(board);
+	rotateBoard(board);
+	return success;
+}
+
+static bool findPairDown(uint16_t board[SIZE][SIZE]) {
+	bool success = false;
+	int8_t x,y;
+	for (x=0;x<SIZE;x++) {
+		for (y=0;y<SIZE-1;y++) {
+			if (board[x][y]==board[x][y+1]) return true;
+		}
+	}
+	return success;
+}
+
+static int16_t countEmpty(uint16_t board[SIZE][SIZE]) {
+	int8_t x,y;
+	int16_t count=0;
+	for (x=0;x<SIZE;x++) {
+		for (y=0;y<SIZE;y++) {
+			if (board[x][y]==0) {
+				count++;
+			}
+		}
+	}
+	return count;
+}
+
+static bool gameEnded(uint16_t board[SIZE][SIZE]) {
+	bool ended = true;
+	if (countEmpty(board)>0) return false;
+	if (findPairDown(board)) return false;
+	rotateBoard(board);
+	if (findPairDown(board)) ended = false;
+	rotateBoard(board);
+	rotateBoard(board);
+	rotateBoard(board);
+	return ended;
+}
+
+static void addRandom(uint16_t board[SIZE][SIZE]) {
+	int8_t x,y;
+	int16_t r,len=0;
+	uint16_t n,list[SIZE*SIZE][2];
+
+	for (x=0;x<SIZE;x++) {
+		for (y=0;y<SIZE;y++) {
+			if (board[x][y]==0) {
+				list[len][0]=x;
+				list[len][1]=y;
+				len++;
+			}
+		}
+	}
+
+	if (len>0) {
+		r = rand()%len;
+		x = list[r][0];
+		y = list[r][1];
+		n = ((rand()%10)/9+1)*2;
+		board[x][y]=n;
+	}
+}
+
+static int test(void) {
+	uint16_t array[SIZE];
+	uint16_t data[] = {
+		0,0,0,2,	2,0,0,0,
+		0,0,2,2,	4,0,0,0,
+		0,2,0,2,	4,0,0,0,
+		2,0,0,2,	4,0,0,0,
+		2,0,2,0,	4,0,0,0,
+		2,2,2,0,	4,2,0,0,
+		2,0,2,2,	4,2,0,0,
+		2,2,0,2,	4,2,0,0,
+		2,2,2,2,	4,4,0,0,
+		4,4,2,2,	8,4,0,0,
+		2,2,4,4,	4,8,0,0,
+		8,0,2,2,	8,4,0,0,
+		4,0,2,2,	4,4,0,0
+	};
+	uint16_t *in,*out;
+	uint16_t t,tests;
+	uint8_t i;
+	bool success = true;
+
+	tests = (sizeof(data)/sizeof(data[0]))/(2*SIZE);
+	for (t=0;t<tests;t++) {
+		in = data+t*2*SIZE;
+		out = in + SIZE;
+		for (i=0;i<SIZE;i++) {
+			array[i] = in[i];
+		}
+		slideArray(array);
+		for (i=0;i<SIZE;i++) {
+			if (array[i] != out[i]) {
+				success = false;
+			}
+		}
+		if (success==false) {
+			for (i=0;i<SIZE;i++) {
+				printf("%d ",in[i]);
+			}
+			printf("=> ");
+			for (i=0;i<SIZE;i++) {
+				printf("%d ",array[i]);
+			}
+			printf("expected ");
+			for (i=0;i<SIZE;i++) {
+				printf("%d ",in[i]);
+			}
+			printf("=> ");
+			for (i=0;i<SIZE;i++) {
+				printf("%d ",out[i]);
+			}
+			printf("\n");
+			break;
+		}
+	}
+	if (success) {
+		printf("All %u tests executed successfully\n",tests);
+	}
+	return !success;
+}
+
+static int do_2048(int argc, char *argv[]) {
+	uint16_t board[SIZE][SIZE];
+	char c;
+	bool success;
+
+	if (argc == 2 && strcmp(argv[1],"test")==0) {
+		return test();
+	}
+
+	printf("\033[?25l\033[2J\033[H");
+
+	memset(board,0,sizeof(board));
+	addRandom(board);
+	addRandom(board);
+	drawBoard(board);
+	while (true) {
+		c=read_key();
+		switch(c) {
+			case BB_KEY_LEFT:	// left arrow
+				success = moveLeft(board);  break;
+			case BB_KEY_RIGHT:	// right arrow
+				success = moveRight(board); break;
+			case BB_KEY_UP:	// up arrow
+				success = moveUp(board);    break;
+			case BB_KEY_DOWN:	// down arrow
+				success = moveDown(board);  break;
+			default: success = false;
+		}
+		if (success) {
+			drawBoard(board);
+			udelay(150000);
+			addRandom(board);
+			drawBoard(board);
+			if (gameEnded(board)) {
+				printf("         GAME OVER          \n");
+				break;
+			}
+		}
+		if (c=='q') {
+			printf("            QUIT            \n");
+			break;
+		}
+	}
+
+	printf("\033[?25h");
+
+	return 0;
+}
+
+BAREBOX_CMD_HELP_START(2048)
+BAREBOX_CMD_HELP_USAGE("2048\n")
+BAREBOX_CMD_HELP_SHORT("The 2048 game\n")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(2048)
+	.cmd		= do_2048,
+	.usage		= "Usage: 2048",
+	BAREBOX_CMD_HELP(cmd_2048_help)
+BAREBOX_CMD_END
diff --git a/common/2048/LICENSE b/common/2048/LICENSE
new file mode 100644
index 0000000..cdc5c15
--- /dev/null
+++ b/common/2048/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Maurits van der Schee
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/common/2048/Makefile b/common/2048/Makefile
new file mode 100644
index 0000000..aefd9c3
--- /dev/null
+++ b/common/2048/Makefile
@@ -0,0 +1 @@
+obj-y += 2048.o
diff --git a/common/2048/README.md b/common/2048/README.md
new file mode 100644
index 0000000..61f2b0f
--- /dev/null
+++ b/common/2048/README.md
@@ -0,0 +1,32 @@
+2048.c
+======
+
+![screenshot](http://www.leaseweblabs.com/wp-content/uploads/2014/03/20481.png)
+
+Console version of the game "2048" for GNU/Linux
+
+### Gameplay
+
+You can move the tiles in four directions using the arrow keys: up, down, left, and right. All numbers on the board will slide into that direction until they hit the wall and if they bump into each other then two numbers will be combined into one if they have the same value. Each number will only be combined once per move. Every move a new number 2 or 4 appears. If you have a 2048 on the board you have won, but you lose once the board is full and you cannot make a move. 
+
+### Requirements
+
+- C compiler
+- GNU/Linux
+
+### Installation
+
+```
+wget https://raw.githubusercontent.com/mevdschee/2048.c/master/2048.c
+gcc -o 2048 2048.c
+./2048
+```
+
+### Contributing
+
+Contributions are very welcome. Always run the tests before committing using:
+
+```
+$ ./2048 test
+All 13 tests executed successfully
+```
diff --git a/common/Makefile b/common/Makefile
index 204241c..b40a078 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_SHELL_HUSH)	+= hush.o
 obj-$(CONFIG_SHELL_SIMPLE)	+= parser.o
 obj-$(CONFIG_UIMAGE)		+= image.o uimage.o
 obj-$(CONFIG_MENUTREE) += menutree.o
+obj-y				+= 2048/
 
 quiet_cmd_pwd_h = PWDH    $@
 ifdef CONFIG_PASSWORD
-- 
1.9.0.279.gdc9e3eb




More information about the barebox mailing list