summary refs log tree commit diff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--bin/.gitignore3
-rw-r--r--bin/Makefile56
-rw-r--r--bin/README1
-rw-r--r--bin/klon.c359
-rw-r--r--bin/man/bin.73
-rw-r--r--bin/man/klon.645
6 files changed, 27 insertions, 440 deletions
diff --git a/bin/.gitignore b/bin/.gitignore
index 35364af3..d209e684 100644
--- a/bin/.gitignore
+++ b/bin/.gitignore
@@ -1,6 +1,6 @@
+*.o
 tags
 scheme.h
-*.o
 atch
 dtch
 glitch
@@ -21,5 +21,4 @@ bri
 fbatt
 fbclock
 psfed
-klon
 scheme.png
diff --git a/bin/Makefile b/bin/Makefile
index 23643871..10ab1156 100644
--- a/bin/Makefile
+++ b/bin/Makefile
@@ -16,66 +16,62 @@ BINS += ttpre
 BINS += wake
 BINS += xx
 
-BINS_BSD = watch
-BINS_LINUX = bri fbatt fbclock psfed
-BINS_ALL = $(BINS) $(BINS_BSD) $(BINS_LINUX)
+BINS_BSD += watch
 
-GAMES_BSD = klon
-GAMES_ALL = $(GAMES_BSD)
+BINS_LINUX += bri
+BINS_LINUX += fbatt
+BINS_LINUX += fbclock
+BINS_LINUX += psfed
 
-MAN1 = $(BINS_ALL:%=man/%.1)
-MAN6 = $(GAMES_ALL:%=man/%.6)
+BINS_ALL = $(BINS) $(BINS_BSD) $(BINS_LINUX)
+MAN1_ALL = $(BINS_ALL:%=man/%.1)
 
 CFLAGS += -Wall -Wextra -Wpedantic
 LDLIBS = -lcurses -lm -lutil -lz
 
 any: .gitignore tags $(BINS)
 
-bsd: any $(BINS_BSD) $(GAMES_BSD)
+bsd: any $(BINS_BSD)
 
 linux: any $(BINS_LINUX)
 
-tags: *.c
-	ctags -w *.c
-
-scheme.h: scheme
-	./scheme -c > scheme.h
+.gitignore: Makefile
+	echo '*.o' tags scheme.h $(BINS_ALL) scheme.png \
+		| tr ' ' '\n' \
+		> .gitignore
 
-fbatt.o fbclock.o: scheme.h
+tags: *.h *.c
+	ctags -w *.h *.c
 
 atch: dtch
 	ln -f dtch atch
 
+fbatt.o fbclock.o: scheme.h
+
+scheme.h: scheme
+	./scheme -c > scheme.h
+
 open pbcopy pbpaste: pbd
 	ln -f pbd $@
 
 scheme.png: scheme
 	./scheme -t -g > scheme.png
 
-setuid: bri
-	chown root bri
-	chmod u+s bri
-
 clean:
-	rm -f tags scheme.h *.o $(BINS_ALL) $(GAMES_ALL) scheme.png
+	rm -f *.o tags scheme.h $(BINS_ALL) scheme.png
 
 README: man/bin.7
 	mandoc man/bin.7 | col -b -x > README
 
-.gitignore: Makefile
-	echo tags scheme.h *.o $(BINS_ALL) $(GAMES_ALL) scheme.png \
-		| tr ' ' '\n' \
-		> .gitignore
+setuid: bri
+	chown root bri
+	chmod u+s bri
 
 link:
-	mkdir -p $(PREFIX)/bin $(PREFIX)/share/man/man1 $(PREFIX)/share/man/man6
+	mkdir -p $(PREFIX)/bin $(PREFIX)/share/man/man1
 	ln -s -f $(BINS_ALL:%=$(PWD)/%) $(PREFIX)/bin
-	ln -s -f $(GAMES_ALL:%=$(PWD)/%) $(PREFIX)/bin
-	ln -s -f $(MAN1:%=$(PWD)/%) $(PREFIX)/share/man/man1
-	ln -s -f $(MAN6:%=$(PWD)/%) $(PREFIX)/share/man/man6
+	ln -s -f $(MAN1_ALL:%=$(PWD)/%) $(PREFIX)/share/man/man1
 
 unlink:
 	rm -f $(BINS_ALL:%=$(PREFIX)/bin/%)
-	rm -f $(GAMES_ALL:%=$(PREFIX)/bin/%)
-	rm -f $(MAN1:%=$(PREFIX)/share/man/man1/%)
-	rm -f $(MAN6:%=$(PREFIX)/share/man/man6/%)
+	rm -f $(MAN1_ALL:%=$(PREFIX)/share/man/man1/%)
diff --git a/bin/README b/bin/README
index f6ac0046..9c4f546b 100644
--- a/bin/README
+++ b/bin/README
@@ -13,7 +13,6 @@ DESCRIPTION
      fbclock(1)  framebuffer clock
      glitch(1)   PNG glitcher
      hnel(1)     PTY input remapper
-     klon(6)     Klondike solitaire
      modem(1)    fixed baud rate wrapper
      pbd(1)      macOS pasteboard daemon
      pngo(1)     PNG optimizer
diff --git a/bin/klon.c b/bin/klon.c
deleted file mode 100644
index 548a505b..00000000
--- a/bin/klon.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/* Copyright (c) 2018, Curtis McEnroe <programble@gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <assert.h>
-#include <curses.h>
-#include <locale.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-typedef uint8_t Card;
-
-enum {
-	MaskRank   = 0x0F,
-	MaskSuit   = 0x30,
-	MaskColor  = 0x10,
-	MaskUp     = 0x40,
-	MaskSelect = 0x80,
-};
-
-enum {
-	SuitClub    = 0x00,
-	SuitDiamond = 0x10,
-	SuitSpade   = 0x20,
-	SuitHeart   = 0x30,
-};
-
-struct Stack {
-	Card data[52];
-	uint8_t index;
-};
-#define EMPTY { .data = {0}, .index = 52 }
-
-static void push(struct Stack *stack, Card card) {
-	assert(stack->index > 0);
-	stack->data[--stack->index] = card;
-}
-
-static Card pop(struct Stack *stack) {
-	assert(stack->index < 52);
-	return stack->data[stack->index++];
-}
-
-static Card get(const struct Stack *stack, uint8_t i) {
-	if (stack->index + i > 51) return 0;
-	return stack->data[stack->index + i];
-}
-
-static uint8_t len(const struct Stack *stack) {
-	return 52 - stack->index;
-}
-
-struct State {
-	struct Stack stock;
-	struct Stack waste;
-	struct Stack found[4];
-	struct Stack table[7];
-};
-
-static struct State g = {
-	.stock = {
-		.data = {
-			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
-			0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-			0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
-			0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
-			0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D,
-			0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-			0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D,
-		},
-		.index = 0,
-	},
-	.waste = EMPTY,
-	.found = { EMPTY, EMPTY, EMPTY, EMPTY },
-	.table = {
-		EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY
-	},
-};
-
-static struct State save;
-
-static void checkpoint(void) {
-	memcpy(&save, &g, sizeof(struct State));
-}
-
-static void undo(void) {
-	memcpy(&g, &save, sizeof(struct State));
-}
-
-static void shuffle(void) {
-	for (int i = 51; i > 0; --i) {
-		int j = arc4random_uniform(i + 1);
-		uint8_t x = g.stock.data[i];
-		g.stock.data[i] = g.stock.data[j];
-		g.stock.data[j] = x;
-	}
-}
-
-static void deal(void) {
-	for (int i = 0; i < 7; ++i) {
-		for (int j = i; j < 7; ++j) {
-			push(&g.table[j], pop(&g.stock));
-		}
-	}
-}
-
-static void reveal(void) {
-	for (int i = 0; i < 7; ++i) {
-		if (get(&g.table[i], 0)) {
-			push(&g.table[i], pop(&g.table[i]) | MaskUp);
-		}
-	}
-}
-
-static void draw(void) {
-	if (get(&g.stock, 0)) push(&g.waste, pop(&g.stock) | MaskUp);
-	if (get(&g.stock, 0)) push(&g.waste, pop(&g.stock) | MaskUp);
-	if (get(&g.stock, 0)) push(&g.waste, pop(&g.stock) | MaskUp);
-}
-
-static void wasted(void) {
-	uint8_t n = len(&g.waste);
-	for (int i = 0; i < n; ++i) {
-		push(&g.stock, pop(&g.waste) & ~MaskUp);
-	}
-}
-
-static void transfer(struct Stack *dest, struct Stack *src, uint8_t n) {
-	struct Stack temp = EMPTY;
-	for (int i = 0; i < n; ++i) {
-		push(&temp, pop(src));
-	}
-	for (int i = 0; i < n; ++i) {
-		push(dest, pop(&temp));
-	}
-}
-
-static bool canFound(const struct Stack *found, Card card) {
-	if (!get(found, 0)) return (card & MaskRank) == 1;
-	if ((card & MaskSuit) != (get(found, 0) & MaskSuit)) return false;
-	return (card & MaskRank) == (get(found, 0) & MaskRank) + 1;
-}
-
-static bool canTable(const struct Stack *table, Card card) {
-	if (!get(table, 0)) return (card & MaskRank) == 13;
-	if ((card & MaskColor) == (get(table, 0) & MaskColor)) return false;
-	return (card & MaskRank) == (get(table, 0) & MaskRank) - 1;
-}
-
-enum {
-	PairEmpty = 1,
-	PairBack,
-	PairBlack,
-	PairRed,
-};
-
-static void curse(void) {
-	setlocale(LC_CTYPE, "");
-
-	initscr();
-	cbreak();
-	noecho();
-	keypad(stdscr, true);
-	set_escdelay(100);
-	curs_set(0);
-
-	start_color();
-	assume_default_colors(-1, -1);
-	init_pair(PairEmpty, COLOR_WHITE, COLOR_BLACK);
-	init_pair(PairBack,  COLOR_WHITE, COLOR_BLUE);
-	init_pair(PairBlack, COLOR_BLACK, COLOR_WHITE);
-	init_pair(PairRed,   COLOR_RED,   COLOR_WHITE);
-}
-
-static const char Rank[] = "\0A23456789TJQK";
-static const char *Suit[] = {
-	[SuitHeart]   = "♥",
-	[SuitClub]    = "♣",
-	[SuitDiamond] = "♦",
-	[SuitSpade]   = "♠",
-};
-
-static void renderCard(int y, int x, Card card) {
-	if (card & MaskUp) {
-		bkgdset(
-			COLOR_PAIR(card & MaskColor ? PairRed : PairBlack)
-			| (card & MaskSelect ? A_REVERSE : A_NORMAL)
-		);
-
-		move(y, x);
-		addch(Rank[card & MaskRank]);
-		addstr(Suit[card & MaskSuit]);
-		addch(' ');
-
-		move(y + 1, x);
-		addstr(Suit[card & MaskSuit]);
-		addch(' ');
-		addstr(Suit[card & MaskSuit]);
-
-		move(y + 2, x);
-		addch(' ');
-		addstr(Suit[card & MaskSuit]);
-		addch(Rank[card & MaskRank]);
-
-	} else {
-		bkgdset(COLOR_PAIR(card ? PairBack : PairEmpty));
-		mvaddstr(y, x, "   ");
-		mvaddstr(y + 1, x, "   ");
-		mvaddstr(y + 2, x, "   ");
-	}
-}
-
-static void render(void) {
-	bkgdset(COLOR_PAIR(0));
-	erase();
-
-	int x = 2;
-	int y = 1;
-
-	renderCard(y, x, get(&g.stock, 0));
-
-	x += 5;
-	renderCard(y, x++, get(&g.waste, 2));
-	renderCard(y, x++, get(&g.waste, 1));
-	renderCard(y, x, get(&g.waste, 0));
-
-	x += 5;
-	for (int i = 0; i < 4; ++i) {
-		renderCard(y, x, get(&g.found[i], 0));
-		x += 4;
-	}
-
-	x = 2;
-	for (int i = 0; i < 7; ++i) {
-		y = 5;
-		renderCard(y, x, 0);
-		for (int j = len(&g.table[i]); j > 0; --j) {
-			renderCard(y, x, get(&g.table[i], j - 1));
-			y++;
-		}
-		x += 4;
-	}
-}
-
-static struct {
-	struct Stack *stack;
-	uint8_t depth;
-} input;
-
-static void deepen(void) {
-	assert(input.stack);
-	if (input.depth == len(input.stack)) return;
-	if (!(get(input.stack, input.depth) & MaskUp)) return;
-	input.stack->data[input.stack->index + input.depth] |= MaskSelect;
-	input.depth++;
-}
-
-static void select(struct Stack *stack) {
-	if (!get(stack, 0)) return;
-	input.stack = stack;
-	input.depth = 0;
-	deepen();
-}
-
-static void commit(struct Stack *dest) {
-	assert(input.stack);
-	for (int i = 0; i < input.depth; ++i) {
-		input.stack->data[input.stack->index + i] &= ~MaskSelect;
-	}
-	if (dest) {
-		checkpoint();
-		transfer(dest, input.stack, input.depth);
-	}
-	input.stack = NULL;
-	input.depth = 0;
-}
-
-int main() {
-	curse();
-
-	shuffle();
-	deal();
-	checkpoint();
-
-	for (;;) {
-		reveal();
-		render();
-
-		int c = getch();
-		if (!input.stack) {
-			if (c == 'q') {
-				break;
-			} else if (c == 'u') {
-				undo();
-			} else if (c == 's' || c == ' ') {
-				if (get(&g.stock, 0)) {
-					checkpoint();
-					draw();
-				} else {
-					wasted();
-				}
-			} else if (c == 'w') {
-				select(&g.waste);
-			} else if (c >= 'a' && c <= 'd') {
-				select(&g.found[c - 'a']);
-			} else if (c >= '1' && c <= '7') {
-				select(&g.table[c - '1']);
-			}
-
-		} else {
-			if (c >= '1' && c <= '7') {
-				struct Stack *table = &g.table[c - '1'];
-				if (input.stack == table) {
-					deepen();
-				} else if (canTable(table, get(input.stack, input.depth - 1))) {
-					commit(table);
-				} else {
-					commit(NULL);
-				}
-			} else if (input.depth == 1 && c >= 'a' && c <= 'd') {
-				struct Stack *found = &g.found[c - 'a'];
-				if (canFound(found, get(input.stack, 0))) {
-					commit(found);
-				} else {
-					commit(NULL);
-				}
-			} else if (input.depth == 1 && (c == 'f' || c == '\n')) {
-				struct Stack *found;
-				for (int i = 0; i < 4; ++i) {
-					found = &g.found[i];
-					if (canFound(found, get(input.stack, 0))) break;
-					found = NULL;
-				}
-				commit(found);
-			} else {
-				commit(NULL);
-			}
-		}
-	}
-
-	endwin();
-	return 0;
-}
diff --git a/bin/man/bin.7 b/bin/man/bin.7
index 8698c8f8..fcd12a0a 100644
--- a/bin/man/bin.7
+++ b/bin/man/bin.7
@@ -34,9 +34,6 @@ PNG glitcher
 .It Xr hnel 1
 PTY input remapper
 .
-.It Xr klon 6
-Klondike solitaire
-.
 .It Xr modem 1
 fixed baud rate wrapper
 .
diff --git a/bin/man/klon.6 b/bin/man/klon.6
deleted file mode 100644
index b78f1827..00000000
--- a/bin/man/klon.6
+++ /dev/null
@@ -1,45 +0,0 @@
-.Dd September 7, 2018
-.Dt KLON 6
-.Os "Causal Agency"
-.
-.Sh NAME
-.Nm klon
-.Nd Klondike solitaire
-.
-.Sh SYNOPSIS
-.Nm
-.
-.Sh DESCRIPTION
-.Nm
-is a curses Klondike solitaire game.
-.
-.Pp
-The keys are as follows:
-.Bl -tag -width Ds
-.It Ic q
-Quit.
-.
-.It Ic u
-Undo.
-.
-.It Ic space
-Draw from stock to waste.
-.
-.It Ic w
-Select waste.
-.
-.It Ic a-d
-Select foundation.
-.
-.It Ic 1-7
-Select tableau.
-.
-.It Ic enter
-Move to any foundation.
-.El
-.
-.Sh CAVEATS
-.Nm
-does not support Linux
-since it uses
-.Xr arc4random_uniform 3 .