aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.clang-format17
-rw-r--r--.gitignore1
-rw-r--r--2048.c202
-rw-r--r--2048_minified.c33
-rw-r--r--2048_renamed.c201
-rw-r--r--Makefile18
6 files changed, 472 insertions, 0 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..704da21
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,17 @@
+# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
+
+Language: Cpp
+Standard: Latest
+BasedOnStyle: LLVM
+
+AccessModifierOffset: -4
+AlignEscapedNewlines: DontAlign
+AlignTrailingComments: false
+AllowShortFunctionsOnASingleLine: None
+AlwaysBreakTemplateDeclarations: Yes
+BreakStringLiterals: false
+ColumnLimit: 120
+IndentWidth: 4
+KeepEmptyLinesAtTheStartOfBlocks: false
+MaxEmptyLinesToKeep: 1
+PointerAlignment: Right
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5e56e04
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/bin
diff --git a/2048.c b/2048.c
new file mode 100644
index 0000000..ac58325
--- /dev/null
+++ b/2048.c
@@ -0,0 +1,202 @@
+#include <ncurses.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#define waddstr_(text) waddstr(main_window, text)
+#define waddch_(ch) waddch(main_window, ch)
+#define wprintw_(format, data) wprintw(main_window, format, data)
+#define newline waddch_('\n')
+
+#define repeat(i, n) for (int i = 0; i < n; ++i)
+
+#define get_tile_at(k) (grid + y * ((x + size) % (size + 1) + k * x) + (size + 1 - y) * i)
+
+WINDOW *main_window;
+char *message = "\0";
+int size, num_rows, num_columns, new_tile_pos, num_empty_slots, changed, last_empty_tile_index, *last_non_empty_tile,
+ *this_tile, grid_buf[128], *grid = grid_buf;
+
+void draw_frame_1() {
+ waddch_('+');
+ repeat(i, 8 * size - 1) {
+ waddch_('-');
+ }
+ waddch_('+');
+ newline;
+}
+
+void draw_frame_2() {
+ waddch_('|');
+ repeat(i, size) {
+ repeat(j, 8) {
+ waddch_(32);
+ }
+ waddch_('\b');
+ waddch_('|');
+ }
+ newline;
+}
+
+void show_grid() {
+ draw_frame_1();
+ repeat(i, size) {
+ draw_frame_2();
+
+ waddstr_("| ");
+ repeat(j, size) {
+ if (!*grid) {
+ waddstr_(" | ");
+ } else if (*grid >= 1024) {
+ wprintw_(" %2dk | ", *grid / 1024);
+ } else {
+ wprintw_("%4d | ", *grid);
+ }
+ ++grid;
+ }
+ newline;
+
+ draw_frame_2();
+
+ if (i < size - 1) {
+ waddch_('|');
+ repeat(j, size) {
+ repeat(j, 8) {
+ waddch_('-');
+ }
+ waddch_('\b');
+ if (j < size - 1) {
+ waddch_('+');
+ }
+ }
+ waddch_('|');
+ newline;
+ }
+ }
+ draw_frame_1();
+ grid -= size * size;
+}
+
+int move_grid(int x, int y, int do_change) {
+ changed = 0;
+ repeat(i, size) {
+ last_empty_tile_index = 0;
+ last_non_empty_tile = 0;
+ repeat(j, size) {
+ this_tile = get_tile_at(j);
+ if (*this_tile) {
+ if (last_non_empty_tile && *this_tile == *last_non_empty_tile) {
+ if (do_change) {
+ *last_non_empty_tile *= 2;
+ *this_tile = 0;
+ }
+ last_non_empty_tile = 0;
+ changed = 1;
+ } else {
+ last_non_empty_tile = get_tile_at(last_empty_tile_index);
+ if (do_change) {
+ *last_non_empty_tile = *this_tile;
+ }
+ ++last_empty_tile_index;
+ }
+ }
+ }
+ for (; last_empty_tile_index < size; ++last_empty_tile_index) {
+ this_tile = get_tile_at(last_empty_tile_index);
+ changed |= *this_tile;
+ if (do_change) {
+ *this_tile = 0;
+ }
+ }
+ }
+ return !changed;
+}
+
+void put_new_tile() {
+ num_empty_slots = 0;
+ repeat(i, size * size) {
+ if (!grid[i]) {
+ ++num_empty_slots;
+ }
+ }
+ if (num_empty_slots == 0) {
+ return;
+ }
+ new_tile_pos = rand() % num_empty_slots;
+ repeat(i, size * size) {
+ if (!grid[i] && --num_empty_slots == new_tile_pos) {
+ grid[i] = rand() % 8 ? 2 : 4;
+ }
+ }
+}
+
+int main(int argc, char **argv) {
+ srand(time(0));
+
+ initscr();
+ cbreak();
+ noecho();
+ curs_set(0);
+ getmaxyx(stdscr, num_rows, num_columns);
+
+ size = argc > 1 ? (*argv[1] - '0') : 4;
+ if (size <= 1 || size > 8) {
+ message = "\1Invalid size given.\n";
+ goto quit;
+ }
+
+ main_window = newwin(0, 0, (num_rows - 4 * size) / 2, (num_columns - 8 * size) / 2);
+ if (!main_window) {
+ message = "\1Terminal too small.\n";
+ goto quit;
+ }
+
+ put_new_tile();
+ put_new_tile();
+
+ while (1) {
+ wclear(main_window);
+ show_grid();
+ waddstr_(" h,j,k,l: move q: quit");
+ wrefresh(main_window);
+
+ switch (wgetch(main_window)) {
+ case 'q':
+ goto quit;
+
+ case 'h':
+ move_grid(1, 1, 1);
+ goto move_end;
+ case 'j':
+ move_grid(-1, size, 1);
+ goto move_end;
+ case 'k':
+ move_grid(1, size, 1);
+ goto move_end;
+ case 'l':
+ move_grid(-1, 1, 1);
+ goto move_end;
+
+ move_end:
+ if (changed) {
+ put_new_tile();
+ }
+ if (move_grid(1, 1, 0) & move_grid(-1, 1, 0) & move_grid(1, size, 0) & move_grid(-1, size, 0)) {
+ message = "\0Game over.\n";
+ goto quit;
+ }
+ usleep(2048 * 8);
+ break;
+ }
+ }
+
+quit:
+ if (main_window) {
+ delwin(main_window);
+ }
+ endwin();
+
+ fputs(message + 1, stderr);
+ return *message;
+}
diff --git a/2048_minified.c b/2048_minified.c
new file mode 100644
index 0000000..bdd9d1f
--- /dev/null
+++ b/2048_minified.c
@@ -0,0 +1,33 @@
+#include <ncurses.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#define s(_)waddstr(W,_)
+#define c(_)waddch(W,_)
+#define f(f,_)wprintw(W,f,_)
+#define n c('\n')
+#define r(_,n)for(int _=0;_<n;++_)
+#define t(_)G+y*((x+S)%(S+1)+_*x)+(S+1-y)*i
+
+WINDOW*W;char*M="\0" ;int S,R,C,N,E,*L,*T ,F[128], *G=F;void _(){c('+');r(i,8*S-1
+){c('-');}c('+');n;} void l(){c('|');r(i, S){r(j,8 ){c(32); }c('\b');c('|');}n;}
+void g(){_();r(i,S){ l();s("| ");r(j,S){ if(!*G){ s(" " " | ");}else if(*G>=
+1024){f(" %2dk | ", *G/1024);}else{f( "%4d | " ,*G);}++ G;}n;l();if(i<S-1){c
+ ('|' ); r(j,S){r (j,8){c( '-');}c( '\b');if (j<S-1){ c('+');}
+ }c('|'); n;}}_(); G-=S*S;} int m(int x,int y, int d){C =0;r(i,S
+ ){E=0;L= 0;r(j,S) {T=t(j); if(*T){if (L&& *T== *L){if(d ){*L*=2;
+ *T=0;}L= 0;C=1;} else{L= t(E);if( d){*L=*T ;}++E;}} }for(;E<
+S;++E){T=t(E);C|=*T; if(d){*T =0;}}} return!C;}void p(){E=0;r(i,S*S){if(!G[i]){
+++E;}}if(E==0){return ;}N=rand ()%E;r(i ,S*S){if(!G[i]&&--E ==N){G[i]=rand()%8?2
+:4;}}}int main(int argc,char **argv){ srand(time(0));initscr();cbreak();noecho();
+curs_set(0);getmaxyx (stdscr, R,C);S= argc>1?(*argv[1]-'0' ):4;if(S<=1||S>8){M=
+"\1Invalid size giv" "en.\n"; goto q;} W=newwin(0,0,(R-4*S) /2,(C-8*S)/2);if(!W)
+{M="\1T" "ermina" "l too " "small." "\n";goto q;}p();p
+();while (1){wclear (W);g(); s(" h," "j,k,l:" " move "
+" " " q: q" "uit"); wrefresh (W);switch (wgetch(
+W)){case 'q':goto q;case'h' :m(1,1,1 );goto e; case'j':
+m(-1,S,1);goto e;case 'k':m(1,S,1);goto e; case'l': m(-1,1,1);goto e;e:if
+(C){p();}if(m(1,1,0) &m(-1,1,0)&m(1,S,0)& m(-1,S,0 )){M="\0Game over.\n"
+;goto q;}usleep(2048 *8);break;}}q:if(W){ delwin(W );}endwin();fputs(M+
+1,stderr);return*M;} /*2^11*/
diff --git a/2048_renamed.c b/2048_renamed.c
new file mode 100644
index 0000000..c4d0d53
--- /dev/null
+++ b/2048_renamed.c
@@ -0,0 +1,201 @@
+#include <ncurses.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#define s(_) waddstr(W, _)
+#define c(_) waddch(W, _)
+#define f(f, _) wprintw(W, f, _)
+#define n c('\n')
+
+#define r(_, n) for (int _ = 0; _ < n; ++_)
+
+#define t(_) (G + y * ((x + S) % (S + 1) + _ * x) + (S + 1 - y) * i)
+
+WINDOW *W;
+char *M = "\0";
+int S, R, C, N, E, *L, *T, F[128], *G = F;
+
+void _() {
+ c('+');
+ r(i, 8 * S - 1) {
+ c('-');
+ }
+ c('+');
+ n;
+}
+
+void l() {
+ c('|');
+ r(i, S) {
+ r(j, 8) {
+ c(32);
+ }
+ c('\b');
+ c('|');
+ }
+ n;
+}
+
+void g() {
+ _();
+ r(i, S) {
+ l();
+
+ s("| ");
+ r(j, S) {
+ if (!*G) {
+ s(" | ");
+ } else if (*G >= 1024) {
+ f(" %2dk | ", *G / 1024);
+ } else {
+ f("%4d | ", *G);
+ }
+ ++G;
+ }
+ n;
+
+ l();
+
+ if (i < S - 1) {
+ c('|');
+ r(j, S) {
+ r(j, 8) {
+ c('-');
+ }
+ c('\b');
+ if (j < S - 1) {
+ c('+');
+ }
+ }
+ c('|');
+ n;
+ }
+ }
+ _();
+ G -= S * S;
+}
+
+int m(int x, int y, int d) {
+ C = 0;
+ r(i, S) {
+ E = 0;
+ L = 0;
+ r(j, S) {
+ T = t(j);
+ if (*T) {
+ if (L && *T == *L) {
+ if (d) {
+ *L *= 2;
+ *T = 0;
+ }
+ L = 0;
+ C = 1;
+ } else {
+ L = t(E);
+ if (d) {
+ *L = *T;
+ }
+ ++E;
+ }
+ }
+ }
+ for (; E < S; ++E) {
+ T = t(E);
+ C |= *T;
+ if (d) {
+ *T = 0;
+ }
+ }
+ }
+ return !C;
+}
+
+void p() {
+ E = 0;
+ r(i, S * S) {
+ if (!G[i]) {
+ ++E;
+ }
+ }
+ if (E == 0) {
+ return;
+ }
+ N = rand() % E;
+ r(i, S * S) {
+ if (!G[i] && --E == N) {
+ G[i] = rand() % 8 ? 2 : 4;
+ }
+ }
+}
+
+int main(int argc, char **argv) {
+ srand(time(0));
+
+ initscr();
+ cbreak();
+ noecho();
+ curs_set(0);
+ getmaxyx(stdscr, R, C);
+
+ S = argc > 1 ? (*argv[1] - '0') : 4;
+ if (S <= 1 || S > 8) {
+ M = "\1Invalid size given.\n";
+ goto q;
+ }
+
+ W = newwin(0, 0, (R - 4 * S) / 2, (C - 8 * S) / 2);
+ if (!W) {
+ M = "\1Terminal too small.\n";
+ goto q;
+ }
+
+ p();
+ p();
+
+ while (1) {
+ wclear(W);
+ g();
+ s(" h,j,k,l: move q: quit");
+ wrefresh(W);
+
+ switch (wgetch(W)) {
+ case 'q':
+ goto q;
+
+ case 'h':
+ m(1, 1, 1);
+ goto e;
+ case 'j':
+ m(-1, S, 1);
+ goto e;
+ case 'k':
+ m(1, S, 1);
+ goto e;
+ case 'l':
+ m(-1, 1, 1);
+ goto e;
+
+ e:
+ if (C) {
+ p();
+ }
+ if (m(1, 1, 0) & m(-1, 1, 0) & m(1, S, 0) & m(-1, S, 0)) {
+ M = "\0Game over.\n";
+ goto q;
+ }
+ usleep(2048 * 8);
+ break;
+ }
+ }
+
+q:
+ if (W) {
+ delwin(W);
+ }
+ endwin();
+
+ fputs(M + 1, stderr);
+ return *M;
+}
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..5189178
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,18 @@
+DIST := bin
+SUFFIX := _minified
+PROGRAM := $(DIST)/2048$(SUFFIX)
+
+all: run
+
+run: build
+ ./$(PROGRAM)
+
+build: $(DIST) $(PROGRAM)
+
+$(PROGRAM): 2048$(SUFFIX).c
+ gcc $^ -lncurses -o $@
+
+$(DIST):
+ @mkdir $@
+
+.PHONY: all run build