mtd: nand: raw: atmel: Add error handling when rb-gpios missing
[platform/kernel/u-boot.git] / cmd / 2048.c
1 // SPDX-License-Identifier: MIT
2 // SPDX-FileCopyrightText: © 2014 Maurits van der Schee
3
4 /* Console version of the game "2048" for GNU/Linux */
5
6 #include <common.h>
7 #include <cli.h>
8 #include <command.h>
9 #include <rand.h>
10 #include <linux/delay.h>
11
12 #define SIZE 4
13 static uint score;
14
15 static void getColor(uint value, char *color, size_t length)
16 {
17         u8 original[] = {
18                 8, 255, 1, 255, 2, 255, 3, 255,
19                 4, 255, 5, 255, 6, 255, 7, 255,
20                 9, 0, 10, 0, 11, 0, 12, 0, 13,
21                 0, 14, 0, 255, 0, 255, 0};
22         u8 *scheme = original;
23         u8 *background = scheme + 0;
24         u8 *foreground = scheme + 1;
25
26         if (value > 0) {
27                 while (value >>= 1) {
28                         if (background + 2 < scheme + sizeof(original)) {
29                                 background += 2;
30                                 foreground += 2;
31                         }
32                 }
33         }
34         snprintf(color, length, "\033[38;5;%d;48;5;%dm", *foreground,
35                  *background);
36 }
37
38 static void drawBoard(u16 board[SIZE][SIZE])
39 {
40         int x, y;
41         char color[40], reset[] = "\033[0m";
42
43         printf("\033[H");
44         printf("2048.c %17d pts\n\n", score);
45
46         for (y = 0; y < SIZE; y++) {
47                 for (x = 0; x < SIZE; x++) {
48                         getColor(board[x][y], color, 40);
49                         printf("%s", color);
50                         printf("       ");
51                         printf("%s", reset);
52                 }
53                 printf("\n");
54                 for (x = 0; x < SIZE; x++) {
55                         getColor(board[x][y], color, 40);
56                         printf("%s", color);
57                         if (board[x][y] != 0) {
58                                 char s[8];
59                                 s8 t;
60
61                                 snprintf(s, 8, "%u", board[x][y]);
62                                 t = 7 - strlen(s);
63                                 printf("%*s%s%*s", t - t / 2, "", s, t / 2, "");
64                         } else {
65                                 printf("   ·   ");
66                         }
67                         printf("%s", reset);
68                 }
69                 printf("\n");
70                 for (x = 0; x < SIZE; x++) {
71                         getColor(board[x][y], color, 40);
72                         printf("%s", color);
73                         printf("       ");
74                         printf("%s", reset);
75                 }
76                 printf("\n");
77         }
78         printf("\n");
79         printf("        ←, ↑, →, ↓ or q        \n");
80         printf("\033[A");
81 }
82
83 static int8_t findTarget(u16 array[SIZE], int x, int stop)
84 {
85         int t;
86
87         /* if the position is already on the first, don't evaluate */
88         if (x == 0)
89                 return x;
90         for (t = x - 1; t >= 0; t--) {
91                 if (array[t]) {
92                         if (array[t] != array[x]) {
93                                 /* merge is not possible, take next position */
94                                 return t + 1;
95                         }
96                         return t;
97                 }
98
99                 /* we should not slide further, return this one */
100                 if (t == stop)
101                         return t;
102         }
103         /* we did not find a */
104         return x;
105 }
106
107 static bool slideArray(u16 array[SIZE])
108 {
109         bool success = false;
110         int x, t, stop = 0;
111
112         for (x = 0; x < SIZE; x++) {
113                 if (array[x] != 0) {
114                         t = findTarget(array, x, stop);
115                         /*
116                          * if target is not original position, then move or
117                          * merge
118                          */
119                         if (t != x) {
120                                 /*
121                                  * if target is not zero, set stop to avoid
122                                  * double merge
123                                  */
124                                 if (array[t]) {
125                                         score += array[t] + array[x];
126                                         stop = t + 1;
127                                 }
128                                 array[t] += array[x];
129                                 array[x] = 0;
130                                 success = true;
131                         }
132                 }
133         }
134         return success;
135 }
136
137 static void rotateBoard(u16 board[SIZE][SIZE])
138 {
139         s8 i, j, n = SIZE;
140         int tmp;
141
142         for (i = 0; i < n / 2; i++) {
143                 for (j = i; j < n - i - 1; j++) {
144                         tmp = board[i][j];
145                         board[i][j] = board[j][n - i - 1];
146                         board[j][n - i - 1] = board[n - i - 1][n - j - 1];
147                         board[n - i - 1][n - j - 1] = board[n - j - 1][i];
148                         board[n - j - 1][i] = tmp;
149                 }
150         }
151 }
152
153 static bool moveUp(u16 board[SIZE][SIZE])
154 {
155         bool success = false;
156         int x;
157
158         for (x = 0; x < SIZE; x++)
159                 success |= slideArray(board[x]);
160
161         return success;
162 }
163
164 static bool moveLeft(u16 board[SIZE][SIZE])
165 {
166         bool success;
167
168         rotateBoard(board);
169         success = moveUp(board);
170         rotateBoard(board);
171         rotateBoard(board);
172         rotateBoard(board);
173         return success;
174 }
175
176 static bool moveDown(u16 board[SIZE][SIZE])
177 {
178         bool success;
179
180         rotateBoard(board);
181         rotateBoard(board);
182         success = moveUp(board);
183         rotateBoard(board);
184         rotateBoard(board);
185         return success;
186 }
187
188 static bool moveRight(u16 board[SIZE][SIZE])
189 {
190         bool success;
191
192         rotateBoard(board);
193         rotateBoard(board);
194         rotateBoard(board);
195         success = moveUp(board);
196         rotateBoard(board);
197         return success;
198 }
199
200 static bool findPairDown(u16 board[SIZE][SIZE])
201 {
202         bool success = false;
203         int x, y;
204
205         for (x = 0; x < SIZE; x++) {
206                 for (y = 0; y < SIZE - 1; y++) {
207                         if (board[x][y] == board[x][y + 1])
208                                 return true;
209                 }
210         }
211
212         return success;
213 }
214
215 static int16_t countEmpty(u16 board[SIZE][SIZE])
216 {
217         int x, y;
218         int count = 0;
219
220         for (x = 0; x < SIZE; x++) {
221                 for (y = 0; y < SIZE; y++) {
222                         if (board[x][y] == 0)
223                                 count++;
224                 }
225         }
226         return count;
227 }
228
229 static bool gameEnded(u16 board[SIZE][SIZE])
230 {
231         bool ended = true;
232
233         if (countEmpty(board) > 0)
234                 return false;
235         if (findPairDown(board))
236                 return false;
237         rotateBoard(board);
238         if (findPairDown(board))
239                 ended = false;
240         rotateBoard(board);
241         rotateBoard(board);
242         rotateBoard(board);
243
244         return ended;
245 }
246
247 static void addRandom(u16 board[SIZE][SIZE])
248 {
249         int x, y;
250         int r, len = 0;
251         u16 n, list[SIZE * SIZE][2];
252
253         for (x = 0; x < SIZE; x++) {
254                 for (y = 0; y < SIZE; y++) {
255                         if (board[x][y] == 0) {
256                                 list[len][0] = x;
257                                 list[len][1] = y;
258                                 len++;
259                         }
260                 }
261         }
262
263         if (len > 0) {
264                 r = rand() % len;
265                 x = list[r][0];
266                 y = list[r][1];
267                 n = ((rand() % 10) / 9 + 1) * 2;
268                 board[x][y] = n;
269         }
270 }
271
272 static int test(void)
273 {
274         u16 array[SIZE];
275         u16 data[] = {
276                 0, 0, 0, 2,     2, 0, 0, 0,
277                 0, 0, 2, 2,     4, 0, 0, 0,
278                 0, 2, 0, 2,     4, 0, 0, 0,
279                 2, 0, 0, 2,     4, 0, 0, 0,
280                 2, 0, 2, 0,     4, 0, 0, 0,
281                 2, 2, 2, 0,     4, 2, 0, 0,
282                 2, 0, 2, 2,     4, 2, 0, 0,
283                 2, 2, 0, 2,     4, 2, 0, 0,
284                 2, 2, 2, 2,     4, 4, 0, 0,
285                 4, 4, 2, 2,     8, 4, 0, 0,
286                 2, 2, 4, 4,     4, 8, 0, 0,
287                 8, 0, 2, 2,     8, 4, 0, 0,
288                 4, 0, 2, 2,     4, 4, 0, 0
289         };
290         u16 *in, *out;
291         u16 t, tests;
292         int i;
293         bool success = true;
294
295         tests = (sizeof(data) / sizeof(data[0])) / (2 * SIZE);
296         for (t = 0; t < tests; t++) {
297                 in = data + t * 2 * SIZE;
298                 out = in + SIZE;
299                 for (i = 0; i < SIZE; i++)
300                         array[i] = in[i];
301                 slideArray(array);
302                 for (i = 0; i < SIZE; i++) {
303                         if (array[i] != out[i])
304                                 success = false;
305                 }
306                 if (!success) {
307                         for (i = 0; i < SIZE; i++)
308                                 printf("%d ", in[i]);
309                         printf(" = > ");
310                         for (i = 0; i < SIZE; i++)
311                                 printf("%d ", array[i]);
312                         printf("expected ");
313                         for (i = 0; i < SIZE; i++)
314                                 printf("%d ", in[i]);
315                         printf(" = > ");
316                         for (i = 0; i < SIZE; i++)
317                                 printf("%d ", out[i]);
318                         printf("\n");
319                         break;
320                 }
321         }
322         if (success)
323                 printf("All %u tests executed successfully\n", tests);
324
325         return !success;
326 }
327
328 static int do_2048(struct cmd_tbl *cmdtp, int flag, int argc,
329                    char *const argv[])
330 {
331         struct cli_ch_state cch_s, *cch = &cch_s;
332         u16 board[SIZE][SIZE];
333         bool success;
334
335         if (argc == 2 && strcmp(argv[1], "test") == 0)
336                 return test();
337
338         score = 0;
339
340         printf("\033[?25l\033[2J\033[H");
341
342         memset(board, 0, sizeof(board));
343         addRandom(board);
344         addRandom(board);
345         drawBoard(board);
346         cli_ch_init(cch);
347         while (true) {
348                 int c;
349
350                 c = cli_ch_process(cch, 0);
351                 if (!c) {
352                         c = getchar();
353                         c = cli_ch_process(cch, c);
354                 }
355                 switch (c) {
356                 case CTL_CH('b'): /* left arrow */
357                         success = moveLeft(board);
358                         break;
359                 case CTL_CH('f'): /* right arrow */
360                         success = moveRight(board);
361                         break;
362                 case CTL_CH('p'):/* up arrow */
363                         success = moveUp(board);
364                         break;
365                 case CTL_CH('n'): /* down arrow */
366                         success = moveDown(board);
367                         break;
368                 default:
369                         success = false;
370                 }
371                 if (success) {
372                         drawBoard(board);
373                         mdelay(150);
374                         addRandom(board);
375                         drawBoard(board);
376                         if (gameEnded(board)) {
377                                 printf("         GAME OVER          \n");
378                                 break;
379                         }
380                 }
381                 if (c == 'q') {
382                         printf("            QUIT            \n");
383                         break;
384                 }
385         }
386
387         printf("\033[?25h");
388
389         return 0;
390 }
391
392 U_BOOT_CMD(
393         2048,   2,      1,      do_2048,
394         "The 2048 game",
395         "Use your arrow keys to move the tiles. When two tiles with "
396         "the same number touch, they merge into one!"
397 );