mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Marc Kleine-Budde <mkl@pengutronix.de>
To: barebox@lists.infradead.org
Subject: [PATCH] 2048: port to barebox
Date: Tue,  8 Apr 2014 23:50:42 +0200	[thread overview]
Message-ID: <1396993842-31482-1-git-send-email-mkl@pengutronix.de> (raw)
In-Reply-To: <53446E09.4080208@pengutronix.de>

Signed-off-by: Marc Kleine-Budde <mkl@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


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

  reply	other threads:[~2014-04-08 21:51 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-05 19:00 RFC: barebox-x86 as a coreboot payload Antony Pavlov
2014-04-05 19:02 ` Alexander Shiyan
2014-04-05 19:27   ` Alexander Aring
2021-04-01 13:52     ` Ahmad Fatoum
2021-04-02  5:23       ` Antony Pavlov
2014-04-08  6:48   ` Jean-Christophe PLAGNIOL-VILLARD
2014-04-08 21:45   ` Marc Kleine-Budde
2014-04-08 21:50     ` Marc Kleine-Budde [this message]
2014-04-09  3:27       ` [PATCH] 2048: port to barebox Alexander Aring
2014-04-09  7:20     ` RFC: barebox-x86 as a coreboot payload Sascha Hauer
2014-04-06 14:32 ` Michel Stam
2014-04-08  6:47   ` Jean-Christophe PLAGNIOL-VILLARD
2014-04-10  5:52   ` Sascha Hauer
2014-04-10 11:30     ` Michel Stam

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1396993842-31482-1-git-send-email-mkl@pengutronix.de \
    --to=mkl@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox