Index: client.c
===================================================================
RCS file: /home/cvs/tunneler/tunneler/client.c,v
retrieving revision 1.2
diff -u -r1.2 client.c
--- client.c	20 Jan 2005 19:06:19 -0000	1.2
+++ client.c	20 Jan 2005 20:09:43 -0000
@@ -3,6 +3,7 @@
 #include <stdlib.h>
 #include <assert.h>
 #include <signal.h>
+#include <sysexits.h>
 #include "xmalloc.h"
 #include "debug.h"
 #include "udp.h"
@@ -32,14 +33,25 @@
 /* Options */
 int multispeed = 0;
 
-/* Direction and speed */
-enum {
-	SPEED_INC = -1,
-	SPEED_DEC = -2,
-} accel_chr;
-#define is_accel_chr(c) (c < 0)
+/* Keybindings */
+enum key_action {
+	ACT_NONE,
+	ACT_FIRE,
+	ACT_UP, ACT_URIGHT, ACT_RIGHT, ACT_DRIGHT, ACT_DOWN, ACT_DLEFT, ACT_LEFT, ACT_ULEFT,
+	ACT_ACCEL, ACT_DECCEL,
+	ACT_EXIT,
+	ACT_MAX
+};
+static enum key_action kbdbind[256];
+const char *key_actnames[] = {
+	"none",
+	"fire",
+	"up", "uright", "right", "dright", "down", "dleft", "left", "uleft",
+	"accel", "deccel",
+	"exit",
+};
 
-_s8	drchr[] = { SPEED_DEC, 5, 4, 3, 6, SPEED_INC, 2, 7, 0, 1 };
+/* Direction and speed */
 int     speed = 0, key_direction = 0, key_shot = 0;
 
 GFXOBJ	*gfx_obj[4];
@@ -143,6 +155,82 @@
 }
 
 
+void    load_kbdbind(void)
+{
+	FILE *f;
+	char line[128];
+	int lineno;
+
+	/* TODO: sysconfpath or smt. --pasky */
+	f = fopen("kbdbind.conf", "r");
+	if (!f) {
+		perror("kbdbind.conf");
+		exit(EX_UNAVAILABLE);
+	}
+
+	for (lineno = 0; fgets(line, 128, f); lineno++) {
+		/* <char><sep><..action..> (<sep> can be anything, usually \t) */
+		/* /^##/ is a comment; blank lines permitted */
+		unsigned char key = *line, *action = line + 2;
+		enum key_action i;
+
+		if (line[0] == '\0') continue; /* blank line */
+		if (line[0] == '#' && line[1] == '#') continue; /* comment */
+
+		action[strlen(action) - 1] = 0; /* chop */
+		for (i = 0; i < ACT_MAX; i++) {
+			if (!strcasecmp(action, key_actnames[i])) {
+				kbdbind[key] = i;
+				goto next_line;
+			}
+		}
+
+		fprintf(stderr, "kbdbind.conf: Unknown action %s on line %d\n", action, lineno);
+next_line:;
+	}
+}
+
+void    input_char(int chr)
+{
+	switch (kbdbind[chr]) {
+		case ACT_FIRE:    key_shot = !key_shot; break;
+
+		case ACT_UP:      key_direction = 0; break;
+		case ACT_URIGHT:  key_direction = 1; break;
+		case ACT_RIGHT:   key_direction = 2; break;
+		case ACT_DRIGHT:  key_direction = 3; break;
+		case ACT_DOWN:    key_direction = 4; break;
+		case ACT_DLEFT:   key_direction = 5; break;
+		case ACT_LEFT:    key_direction = 6; break;
+		case ACT_ULEFT:   key_direction = 7; break;
+
+		case ACT_ACCEL:
+			if (multispeed) {
+				if (speed < 1) speed = 1;
+				speed *= 2;
+				if (speed > TANK_SPEED) speed = TANK_SPEED;
+			} else {
+				speed = TANK_SPEED;
+			}
+			break;
+
+		case ACT_DECCEL:
+			if (multispeed) {
+				speed /= 2;
+			} else {
+				speed = 0;
+			}
+			break;
+
+		case ACT_EXIT:    doexit = 1; break;
+
+		case ACT_NONE:    break;
+		default:          assert(0); break;
+	}
+	DEBUG("keys: %d %d %d", key_shot, speed, key_direction);
+}
+
+
 
 /**********/
 
@@ -169,30 +257,7 @@
 			game_update();
 		else if (FD_ISSET(0, &fdt)) {
 			read(0, &chr, 1);
-			if (chr == ' ') {
-				key_shot = !key_shot;
-			} else if (chr >= '0' && chr <= '9') {
-				chr = drchr[chr-'0'];
-				if (is_accel_chr(chr)) {
-					if (multispeed) {
-						switch (chr) {
-						case SPEED_INC:
-							if (speed < 1) speed = 1;
-							speed *= 2;
-							if (speed > TANK_SPEED) speed = TANK_SPEED;
-							break;
-						case SPEED_DEC:
-							speed /= 2;
-							break;
-						}
-					} else {
-						speed = (chr == SPEED_INC ? TANK_SPEED : 0);
-					}
-				} else {
-					key_direction = chr;
-				}
-			}
-			DEBUG("keys: %d %d %d", key_shot, speed, key_direction);
+			input_char(chr);
 		} else if (FD_ISSET(server->fd, &fdt)) {
 			if (! pck_recv(server, &packet))
 				continue;
@@ -204,7 +269,7 @@
 		cleanup_term();
 	udp_close(server);
 	printf("bye...\n");
-	exit(0);
+	exit(EX_OK);
 }
 
 
@@ -217,9 +282,11 @@
 	DEBUG("tunneler client starting...");
 	if (argc < 3) {
 		printf("tunneler client -- 2005,ment\nusage: %s <ip> <port> [-start]\n", argv[0]);
-		exit(1);
+		exit(EX_USAGE);
 	}
 
+	load_kbdbind();
+
 	gfx_obj[0] = load_gfxobj("tank", 8);
 	gfx_obj[1] = load_gfxobj("explosion", 8);
 	gfx_obj[2] = load_gfxobj("bullet", 8);
@@ -229,7 +296,7 @@
 	server = udp_client(argv[1], port);
 	if (server->state == UCS_ERROR) {
 		perror("socket");
-		exit(43);
+		exit(EX_OSERR);
 	}
 
 	/* Options */
@@ -242,6 +309,6 @@
 
 	DEBUG("socket created, looping");
 	mainloop();
-	return 0;
+	return EX_OK;
 }
 
Index: kbdbind.conf
===================================================================
RCS file: kbdbind.conf
diff -N kbdbind.conf
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ kbdbind.conf	20 Jan 2005 20:09:58 -0000
@@ -0,0 +1,19 @@
+ 	fire
+
+8	up
+9	uright
+6	right
+3	dright
+2	down
+1	dleft
+4	left
+7	uleft
+
+5	accel
+0	deccel
+
+## Stunts/Grandprix like:
+a	accel
+z	deccel
+
+q	exit
