radare2/libr/cons/2048.c
2023-06-13 00:14:46 +02:00

194 lines
4.5 KiB
C

/* radare2 - LGPL - Copyright 2008-2022 - pancake */
#include <r_cons.h>
typedef struct game_state_t {
ut8 twok_buf[4][4];
int score;
int moves;
} GameState;
static void twok_init(GameState *state) {
memset (state, 0, sizeof (GameState));
}
static void twok_add(GameState *state) {
int i, j;
while (true) {
i = r_num_rand (4);
j = r_num_rand (4);
if (!state->twok_buf[i][j]) {
state->twok_buf[i][j] = 1 + (r_num_rand (10) == 1);
break;
}
}
}
static bool twok_fin(GameState *state) {
int i, j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
if (!state->twok_buf[i][j]) {
return true;
}
}
}
for (i = 0; i < 4; i++) {
for (j = 0; j < 3; j++) {
if (state->twok_buf[i][j] == state->twok_buf[i][j + 1]) {
return true;
}
}
}
for (i = 0; i < 3; i++) {
for (j = 0; j < 4; j++) {
if (state->twok_buf[i][j] == state->twok_buf[i + 1][j]) {
return true;
}
}
}
return false;
}
static void twok_move(GameState *state, int u, int v) {
int i, j, k;
int nKI = 0, nKJ = 0, nIK = 0, nJK = 0;
int moved = 0;
for (k = 0; k < 4; k++) {
for (i = 0; i < 4; i++) {
for (j = i + 1; j < 4 && !state->twok_buf[nKJ = u ? k : v ? j : 3 - j][nJK = !u ? k : v ? j : 3 - j]; j++) {
;
}
if (j == 4) {
continue;
}
nKI = u? k: v? i: 3 - i;
nIK = !u? k: v? i: 3 - i;
if (!state->twok_buf[nKI][nIK]) {
state->twok_buf[nKI][nIK] = state->twok_buf[nKJ][nJK];
state->twok_buf[nKJ][nJK] = 0;
--i;
moved = 1;
} else if (state->twok_buf[nKI][nIK] == state->twok_buf[nKJ][nJK]) {
state->score += 1 << ++state->twok_buf[nKI][nIK];
state->twok_buf[nKJ][nJK] = 0;
moved = 1;
}
}
}
if (moved) {
twok_add (state);
state->moves++;
}
}
static void getval(GameState *state, bool color, char *val0, int i, int x) {
const char * colorarray[] = {
Color_WHITE,
Color_RED,
Color_GREEN,
Color_MAGENTA,
Color_YELLOW,
Color_CYAN,
Color_BLUE,
Color_GRAY
};
if (state->twok_buf[i][x]) {
if (color) {
snprintf (val0, 31, "%s%4d"Color_RESET, colorarray [state->twok_buf [i][x] % 8 ], 1 << state->twok_buf[i][x]);
} else {
snprintf (val0, 31, "%4d", 1 << state->twok_buf[i][x]);
}
} else {
strcpy (val0, " ");
}
}
static void twok_print(GameState *state, bool color) {
char val0[32];
char val1[32];
char val2[32];
char val3[32];
int i;
if (color) {
printf (Color_BBLUE" +------+------+------+------+\n");
} else {
printf (" +------+------+------+------+\n");
}
for (i = 0; i < 4; i++) {
getval (state, color, val0, i, 0);
getval (state, color, val1, i, 1);
getval (state, color, val2, i, 2);
getval (state, color, val3, i, 3);
if (color) {
printf (Color_BBLUE" | | | | |\n");
printf (" |"Color_RESET" %s "Color_BBLUE"|"Color_RESET" %s "
Color_BBLUE"|"Color_RESET" %s "Color_BBLUE"|"Color_RESET" %s "Color_BBLUE"|\n",
val0, val1, val2, val3);
printf (" | | | | |\n");
printf (" +------+------+------+------+\n"Color_RESET);
} else {
printf (" | | | | |\n");
printf (" | %s | %s | %s | %s |\n",
val0, val1, val2, val3);
printf (" | | | | |\n");
printf (" +------+------+------+------+\n");
}
}
printf ("Hexboard: 'hjkl' and 'q'uit\n");
for (i = 0; i < 4; i++) {
printf (" %02x %02x %02x %02x\n",
state->twok_buf[i][0], state->twok_buf[i][1],
state->twok_buf[i][2], state->twok_buf[i][3]);
}
}
R_API void r_cons_2048(bool color) {
GameState state;
int ch;
r_cons_set_raw (1);
twok_init (&state);
twok_add (&state);
twok_add (&state);
while (twok_fin (&state)) {
r_cons_clear00 ();
if (color) {
r_cons_printf (Color_GREEN"[r2048]"Color_BYELLOW" score: %d moves: %d\n"Color_RESET, state.score, state.moves);
} else {
r_cons_printf ("[r2048] score: %d moves: %d\n", state.score, state.moves);
}
r_cons_flush ();
twok_print (&state, color);
ch = r_cons_readchar ();
ch = r_cons_arrow_to_hjkl (ch);
switch (ch) {
case 'h':
twok_move (&state, 1, 1);
break;
case 'j':
twok_move (&state, 0, 0);
break;
case 'k':
twok_move (&state, 0, 1);
break;
case 'l':
twok_move (&state, 1, 0);
break;
}
if (ch < 1 || ch == 'q') {
break;
}
}
r_cons_clear00 ();
r_cons_printf ("[r2048] score: %d\n", state.score);
r_cons_flush ();
twok_print (&state, color);
r_cons_printf ("\n [r2048.score] %d\n", state.score);
do {
ch = r_cons_any_key ("Press 'q' to quit.");
} while (ch != 'q' && ch >= 1);
r_cons_set_raw (0);
}