Index: Makefile
===================================================================
RCS file: /home/cvs/tunneler/tunneler/Makefile,v
retrieving revision 1.3
diff -u -r1.3 Makefile
--- Makefile	20 Jan 2005 22:26:14 -0000	1.3
+++ Makefile	20 Jan 2005 23:17:29 -0000
@@ -1,14 +1,14 @@
 CC=/opt/gcc-3.3/bin/gcc-3.3
 CFLAGS=-Wall -ggdb -DEBUG
 LD=ld
-SRCS=server.c game.c client.c udp.c debug.c virtual.c sprite.c term.c viewpoint.c packet.c state.c xmalloc.c conn.c
+SRCS=ai.c server.c game.c client.c udp.c debug.c virtual.c sprite.c term.c viewpoint.c packet.c state.c xmalloc.c conn.c
 
 all: server client
 
 %.o : %.c
 	$(CC) $(CFLAGS) -c -o $@ $<
 
-server: server.o udp.o debug.o game.o sprite.o viewpoint.o packet.o state.o xmalloc.o conn.o bytef.o buffer.o
+server: ai.o server.o udp.o debug.o game.o sprite.o viewpoint.o packet.o state.o xmalloc.o conn.o bytef.o buffer.o
 	$(CC) -o $@ $^ 
 
 client: client.o udp.o debug.o virtual.o sprite.o term.o viewpoint.o packet.o state.o xmalloc.o conn.o buffer.o bytef.o
Index: README
===================================================================
RCS file: /home/cvs/tunneler/tunneler/README,v
retrieving revision 1.3
diff -u -r1.3 README
--- README	20 Jan 2005 22:26:14 -0000	1.3
+++ README	20 Jan 2005 23:12:06 -0000
@@ -10,4 +10,5 @@
 
 Parametry serveru:
 
+  a - spawn AI (muzete a-cek napsat vic)
   f - Ferda the Zametac
Index: ai.c
===================================================================
RCS file: ai.c
diff -N ai.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ai.c	21 Jan 2005 00:32:39 -0000
@@ -0,0 +1,130 @@
+#include <stdlib.h>
+#include "game.h"
+#include "server.h"
+#include "debug.h"
+#include "xmalloc.h"
+#include "console.h"
+
+
+/* Some AI, really trivial for now. */
+
+/* Mostly guessing. */
+#define GOOD_SHOT_RADIUS  600
+
+
+void    reset_ai (AI *ai)
+{
+	ai->pursuing = NULL;
+}
+
+void    hit_ai_hook (struct _plr_t *victim, struct _plr_t *trespasser)
+{
+	/* TODO: Keep some relation to all players and change the pursuee
+	 * only if relation difference is over certain threshold (increase
+	 * relation for each hostile act, decrease (parabolically) over time).
+	 * --pasky */
+	victim->ai.pursuing = trespasser;
+}
+
+void    stop_ai_pursue (plr_t *p)
+{
+	plr_t *bot;
+
+	/* Turn the pursuers to confused schizo-bots on lunch. */
+	foreach(bot, players)
+		if (bot->ai.pursuing == p)
+			bot->ai.pursuing = NULL;
+}
+
+
+/* Returns squared distance. */
+long    distance (int x1, int y1, int x2, int y2)
+{
+	int dx = x1 - x2, dy = y1 - y2;
+
+	return dx * dx + dy * dy;
+}
+
+/* Determines whether <from> and <target> are well-aligned for shooting. */
+int     good_shot (TANK *from, TANK *target)
+{
+	int    fromx, fromy; /* Tank coords */
+	int    dx, dy;       /* Delta */
+	SPOS   bpos;         /* Our virtual bullet */
+
+	tankborder(from->current_pos.sprite, from->angle, &fromx, &fromy);
+	fromx = from->x + fromx*XPOINTS_PERCHAR;
+	fromy = from->y + fromy*YPOINTS_PERCHAR;
+	conv_angle(from->angle, BULLET_SPEED, &dx, &dy);
+	conv_coords(fromx, fromy, from->angle, gfx_bullet, &bpos);
+
+	while (!tank_in_region(target, bpos.sx, bpos.sy, bpos.sprite->width, bpos.sprite->height)) {
+		bpos.sx += dx; bpos.sy += dy;
+		if (distance(fromx, fromy, bpos.sx, bpos.sy) > GOOD_SHOT_RADIUS * GOOD_SHOT_RADIUS)
+			return 0;
+	}
+
+	return 1;
+}
+
+/* Determines the proper angle of <from> heading to <target>. */
+int     get_angle (TANK *from, TANK *target)
+{
+	/* XXX: Do we get it right even for short distances? */
+
+	/* Yes, I could probably construct a single huge logical expression
+	 * for this. No, I couldn't understand it in 20 seconds then. */
+
+	/* Assuming tanks are always at least 3 chars wide: */
+	if (abs(from->y - target->y) <= 1*YPOINTS_PERCHAR)
+		return 2 + (from->x < target->x ? 0 : 4);
+	if (abs(from->x - target->x) <= 1*XPOINTS_PERCHAR)
+		return 0 + (from->y < target->y ? 4 : 0);
+
+	if (from->x > target->x) {
+		return 4 + (from->y < target->y ? 1 : 3);
+	} else {
+		return 0 + (from->y < target->y ? 3 : 1);
+	}
+}
+
+/* Compute difference between two angles. */
+int     delta_angle (int a1, int a2)
+{
+	int d = abs(a1 - a2);
+	return d < 8 - d ? d : 8 - d;
+}
+
+
+void    bot_update (struct _plr_t *bot)
+{
+	plr_t *victim = bot->ai.pursuing;
+	int angle;
+	int speed = TANK_SPEED;
+
+	if (!victim) {
+		/* *Yawn*. Make sure we aren't madly running around or something. */
+		bot->tank.speed = 0;
+		bot->tank.fire = 0;
+		return; /*yawn*/
+	}
+
+	/* Set the right angle if we didn't yet. Possibly change it a bit randomly. */
+	/* TODO: Try to back out a little if this angle is impossible. --pasky */
+	angle = (get_angle(&bot->tank, &victim->tank)
+		 + (mkrand(7) == 0 ? mkrand(2) - 1 : 0)
+		 + (mkrand(9) == 0 ? mkrand(4) - 2 : 0)) % 8;
+	if (angle != bot->tank.angle) {
+		/* Try to make the AI less deadly - slow down when turning around. */
+		speed /= delta_angle(angle, bot->tank.angle) + 1;
+		bot->tank.next_angle = angle;
+	}
+
+	/* Shooting angle? (We can hit the tank's corner even from wrong angle.) */
+	if (good_shot(&bot->tank, &victim->tank)) {
+		bot->tank.fire = 1; /* Rat-ta-tat-ta-ra-ta-tat-ta-ta! */
+	}
+
+	/* Pursue on. */
+	bot->tank.speed = speed;
+}
Index: ai.h
===================================================================
RCS file: ai.h
diff -N ai.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ai.h	20 Jan 2005 23:54:23 -0000
@@ -0,0 +1,19 @@
+#ifndef __INCLUDED_AI_H
+#define __INCLUDED_AI_H
+
+#include "game.h"
+
+struct	_plr_t;
+
+typedef struct _ai_t {
+	struct _plr_t *pursuing;
+} AI;
+
+void    hit_ai_hook (struct _plr_t *victim, struct _plr_t *trespasser);
+
+void    reset_ai (AI *ai);
+void    stop_ai_pursue (struct _plr_t *p);
+
+void    bot_update (struct _plr_t *bot);
+
+#endif
Index: ai.o
===================================================================
RCS file: ai.o
diff -N ai.o
Binary files /dev/null and ai.o differ
Index: client.c
===================================================================
RCS file: /home/cvs/tunneler/tunneler/client.c,v
retrieving revision 1.5
diff -u -r1.5 client.c
--- client.c	20 Jan 2005 22:26:14 -0000	1.5
+++ client.c	20 Jan 2005 23:37:23 -0000
@@ -75,7 +75,7 @@
 	tick++;
 	tv.tv_sec = 0;
 	tv.tv_usec = TICKMS*1000;
-	pck_send_cupdate(server, cur_ack, (key_speed?128:0) + (key_shot?64:0) + key_direction);
+	pck_send_cupdate(server, cur_ack, (speed<<3) + (key_shot?128:0) + key_direction);
 }
 
 void	game_packet(pck_t *pck)
@@ -301,8 +301,8 @@
 			else
 				tv.tv_sec = 1;
 		} else if (FD_ISSET(0, &fdt)) {
-			DEBUG("*** KEY...");
 			read(0, &chr, 1);
+			DEBUG("*** KEY...%c", chr);
 			if (chr >= 'a' && chr <= 'z') {
 				*mesgp++ = chr;
 			} else if (chr == '\n') {
Index: game.c
===================================================================
RCS file: /home/cvs/tunneler/tunneler/game.c,v
retrieving revision 1.4
diff -u -r1.4 game.c
--- game.c	20 Jan 2005 22:26:14 -0000	1.4
+++ game.c	20 Jan 2005 23:54:34 -0000
@@ -10,8 +10,8 @@
 SPOS	sprites;
 BOT     ferda;
 
-#define	IF_INTERSEC(x1,y1,w1,h1,x2,y2,w2,h2) \
-	if (((x1)+(w1) > (x2)) && ((y1)+(h1) > (y2)) && ((x1) <= (x2)+(w2)) && ((y1) <= (y2)+(h2)))
+#define	INTERSEC(x1,y1,w1,h1,x2,y2,w2,h2) \
+	(((x1)+(w1) > (x2)) && ((y1)+(h1) > (y2)) && ((x1) <= (x2)+(w2)) && ((y1) <= (y2)+(h2)))
 
 /****************************************************************************/
 
@@ -68,7 +68,7 @@
 	DEBUG("x:%d y:%d angle:%d sx:%d sy:%d", x, y, angle, p->sx, p->sy);
 }
 
-void	conv_angle(_u16 angle, _s16 add, _s16 *ax, _s16 *ay)
+void	conv_angle(_u16 angle, _s16 add, int *ax, int *ay)
 {
 	*ax = *ay = 0;
 
@@ -85,7 +85,7 @@
 	DEBUG("angle:%d speed:%d ax:%d ay:%d", angle, add, *ax, *ay);
 }
 
-void    tankborder(SPRITE *s, _u16 angle, _s16 *sx, _s16 *sy)
+void    tankborder(SPRITE *s, _u16 angle, int *sx, int *sy)
 {
         *sx = -s->center_x;
         *sy = -s->center_y;
@@ -173,7 +173,7 @@
 BULLET	*new_bullet (TANK *t)
 {
 	BULLET	*b = ALLOC(sizeof(BULLET));
-	_s16 	sx, sy;
+	int 	sx, sy;
 
 	tankborder(t->current_pos.sprite, t->angle, &sx, &sy);
 	
@@ -204,6 +204,7 @@
 
 void	explode(plr_t *p)
 {
+	stop_ai_pursue(p);
 	p->tank.exploding = 1;
 	surface_drc_sprite(&(p->tank.current_pos), G_EMPTY, G_HOME);
 	p->tank.current_pos.gfxid = GFX_EXPL_ID;
@@ -211,17 +212,25 @@
 	return;
 }
 
+void    reset_tank(TANK *tank)
+{
+	tank->x = tank->home_x;
+	tank->y = tank->home_y;
+	tank->speed = tank->speed_deficit = 0;
+	tank->angle = 0;
+	tank->next_angle = -1;
+	tank->fire = tank->firing = 0;
+	tank->energy = MAX_ENERGY;
+	tank->shields = MAX_SHIELDS;
+	tank->exploding = 0;
+}
+
 void	spawn(plr_t *p)
 {
-	p->tank.x = p->tank.home_x;
-	p->tank.y = p->tank.home_y;
-	p->tank.speed = p->tank.speed_deficit = 0;
-	p->tank.angle = 0;
-	p->tank.next_angle = -1;
-	p->tank.fire = p->tank.firing = 0;
-	p->tank.energy = MAX_ENERGY;
-	p->tank.shields = MAX_SHIELDS;
-	p->tank.exploding = 0;
+	reset_tank(&p->tank);
+	stop_ai_pursue(p); /* Just to be sure... */
+	if (player_is_ai(p))
+		reset_ai(&p->ai);
 
 	p->tank.current_pos.gfxid = GFX_TANK_ID;
 	p->tank.current_pos.color = p->tank.color;
@@ -240,6 +249,8 @@
 		send->score++;
 		explode(recv->player);
 	}
+	if (player_is_ai(recv->player))
+		hit_ai_hook(recv->player, send->player);
 }
 
 /* 
@@ -249,7 +260,7 @@
 {
 	BOT	*b = &ferda;
 	_u16 	i, best=8, min=100, max=0, eat;
-	_s16	x_add, y_add;
+	int	x_add, y_add;
 	SPOS 	new_pos = b->current_pos, *np = &new_pos, *cp = &(b->current_pos);
 
 	/*printf("mypos: %d %d\n", b->x, b->y);*/
@@ -291,7 +302,7 @@
 	TANK	*t = &(p->tank);
 	plr_t	*q;
 	SPOS 	new_pos = t->current_pos, *np = &new_pos, *cp = &(t->current_pos);
-	_s16	x_add, y_add;
+	int	x_add, y_add;
 	_u16	dirt;
 
 
@@ -355,7 +366,7 @@
 		cp = &(p->tank.home_pos);
 		foreach (q, players) {
 			np = &(q->tank.current_pos);
-			IF_INTERSEC(np->sx, np->sy, np->sprite->width, np->sprite->height, cp->sx, cp->sy, cp->sprite->width, cp->sprite->height) {
+			if (INTERSEC(np->sx, np->sy, np->sprite->width, np->sprite->height, cp->sx, cp->sy, cp->sprite->width, cp->sprite->height)) {
 				_u16 adde = (p==q?ADDE_HOME:ADDE_FOREIGN);
 				_u16 adds = (p==q?ADDS_HOME:0);
 				if (q->tank.energy < MAX_ENERGY && (q->tank.energy += adde) > MAX_ENERGY)
@@ -367,7 +378,7 @@
 	}
 
 	if (t->speed > 0) 
-		t->energy -= 2 + t->speed >> 3;
+		t->energy -= 2 + (t->speed >> 3);
 	else if (tick % 3)
 		t->energy -= 1;
 
@@ -378,17 +389,22 @@
 }
 
 
+int     tank_in_region(TANK *tank, int x, int y, int wx, int wy)
+{
+	SPOS *cp = &(tank->current_pos);
+
+	//DEBUG("x1(%d)y1(%d)w1(%d)h1(%d) x2(%d)y2(%d)w1(%d)h1(%d)", x,y,wx,wy,cp->sx,cp->sy
+	return INTERSEC(x,y,wx,wy,cp->sx,cp->sy,cp->sprite->width,cp->sprite->height);
+}
+
 plr_t	*find_player_by_xy (_u16 x, _u16 y, _u16 wx, _u16 wy)
 {
 	plr_t	*p;
-	SPOS 	*cp;
-	foreach(p, players) {
-		cp = &(p->tank.current_pos);
-		//DEBUG("x1(%d)y1(%d)w1(%d)h1(%d) x2(%d)y2(%d)w1(%d)h1(%d)", x,y,wx,wy,cp->sx,cp->sy
-		IF_INTERSEC(x,y,wx,wy,cp->sx,cp->sy,cp->sprite->width,cp->sprite->height) {
+
+	foreach(p, players)
+		if (tank_in_region(&p->tank, x, y, wx, wy))
 			return p;
-		}
-	}
+
 	return NULL;
 }
 
@@ -464,7 +480,7 @@
 	i = 0;
 
 	foreach(s, sprites) {
-		IF_INTERSEC(sx,sy,VIEWPNT_WIDTH,VIEWPNT_HEIGHT,s->sx, s->sy, s->sprite->width, s->sprite->height) {
+		if (INTERSEC(sx,sy,VIEWPNT_WIDTH,VIEWPNT_HEIGHT,s->sx, s->sy, s->sprite->width, s->sprite->height)) {
 			v->obj[i].ox = s->sx - sx;
 			v->obj[i].oy = s->sy - sy;
 			v->obj[i].angle = ((s->angle)&7) + (((s->gfxid)&3)<<3) + (((s->color)&7)<<5);
@@ -585,6 +601,7 @@
 			FREE(b);
 		}
 	}
+	stop_ai_pursue(p);
 
 	surface_drc_sprite(&(p->tank.current_pos), G_EMPTY, G_DIRT);
 	del_from_list(&(p->tank.current_pos));
Index: game.h
===================================================================
RCS file: /home/cvs/tunneler/tunneler/game.h,v
retrieving revision 1.3
diff -u -r1.3 game.h
--- game.h	20 Jan 2005 21:03:31 -0000	1.3
+++ game.h	20 Jan 2005 23:20:52 -0000
@@ -71,7 +71,7 @@
 
 	LIST_HEAD(struct _bullet_t);
 	_u16	x, y;
-	_s16 	xadd, yadd;
+	int 	xadd, yadd;
 	_s16	power;
 	_u16	angle;
 	TANK	*owner;
@@ -85,6 +85,12 @@
 
 extern	_u8 surface[SURFACE_WIDTH][SURFACE_HEIGHT];
 
+_u32	mkrand(long max);
+void    tankborder(SPRITE *s, _u16 angle, int *sx, int *sy);
+int     tank_in_region(TANK *tank, int x, int y, int wx, int wy);
+void	conv_angle(_u16 angle, _s16 add, int *ax, int *ay);
+void	conv_coords(int x, int y, int angle, GFXOBJ *g, SPOS *p);
+
 void	player_update (struct _plr_t *p);
 void	bullets_update (void);
 void	player_move (struct _plr_t *p, _u8 direction, _u8 speed, _u8 firing);
Index: server.c
===================================================================
RCS file: /home/cvs/tunneler/tunneler/server.c,v
retrieving revision 1.4
diff -u -r1.4 server.c
--- server.c	20 Jan 2005 22:26:14 -0000	1.4
+++ server.c	20 Jan 2005 23:24:35 -0000
@@ -26,6 +26,7 @@
 
 /* Options */
 int     do_ferda = 0;
+int     bots_to_spawn = 0;
 
 GFXOBJ	*gfx_tank, *gfx_bullet, *gfx_home, *gfx_explosion;
 
@@ -40,7 +41,7 @@
 {
 	plr_t *p;
 	foreach(p, players) 
-		if (p->initialized) 
+		if (p->initialized && !player_is_ai(p)) 
 			unicast(p, msg, len);
 }
 
@@ -61,7 +62,7 @@
 	DEBUG("::: BCAST_JOIN @%d as '%s'", p->id, p->name);
 	bytef(msg1, 40, "wwwwq", CH_MSGJOIN, len1, p->id, p->tank.score, p->name, len1);
 	foreach (q, players) {
-		if (q->initialized) {
+		if (q->initialized && !player_is_ai(q)) {
 			len2 = strlen(q->name);
 			bytef(msg2, 40, "wwwwq", CH_MSGJOIN, len2, q->id, q->tank.score, q->name, len2);
 			if (p != q)
@@ -107,6 +108,18 @@
 	return p;
 }
 
+plr_t   *alloc_bot (void)
+{
+	plr_t *p;
+	/* FIXME: No CALLOC :-(. */
+	p = (plr_t *) calloc(1, sizeof(plr_t));
+	p->id = newobj();
+	p->initialized = 0;
+
+	add_to_list(players, p);
+	return p;
+}
+
 void	join (plr_t *p)
 {
 	if (p->initialized)
@@ -130,14 +143,50 @@
 		finit_player(p);
 		free(p->name);
 
-		p->udp->fd = -1;
-		udp_destroy(p->udp);
+		if (p->udp) {
+			p->udp->fd = -1;
+			udp_destroy(p->udp);
+		}
 	}
-	conn_destroy(p->tcp);
+	if (p->tcp) conn_destroy(p->tcp);
 	del_from_list(p);
 	FREE(p);
 }
 
+char *  name_bot (void)
+{
+#define BOT_NAMES 17
+	static char *names[BOT_NAMES] = {
+		"brm", "Muaddib", "Antonov", "len1n", "Karkulka", "Bonk",
+		"miruz", "id9848948", "matfyzak", "[zl]", "vlk", "Potemkin",
+		"Snoopy", "FragHunter", "3v1l0r", "kacenka", "l33tm4st4",
+	};
+	static int avail_names = BOT_NAMES;
+	char dyn[16];
+
+	int i;
+
+	if (avail_names <= 0) {
+		snprintf(dyn, 16, "[b] %c%d", 'A' + (char)mkrand('Z' - 'A' + 1), -avail_names);
+		avail_names--;
+	} else {
+		do { i = mkrand(BOT_NAMES); } while (names[i] == NULL);
+		snprintf(dyn, 64, "[b] %s", names[i]);
+		avail_names--; names[i] = NULL;
+	}
+	return strdup(dyn);
+#undef BOT_NAMES
+}
+
+void    spawn_bot (void)
+{
+	plr_t *bot = alloc_bot ();
+
+	/* Figure out some name. */
+	bot->name = name_bot ();
+	join (bot);
+}
+
 /**********/
 
 void	parse(plr_t *p)
@@ -238,11 +287,14 @@
 	tick++;
 
 	DEBUG("game update!");
-	foreachsafe(p, n, players) 
+	foreachsafe(p, n, players)
+		if (p->initialized && player_is_ai(p))
+			bot_update(p);
+	foreachsafe(p, n, players)
 		if (p->initialized)
 			player_update(p);
 	foreachsafe(p, n, players)
-		if (p->initialized)
+		if (p->initialized && !player_is_ai(p))
 			send_update(p);
 	bullets_update();
 	if (do_ferda) runferda();
@@ -278,6 +330,7 @@
 	pck_t 	packet;
 	plr_t	*p, *n;
 	conn_t	*newc;
+	int i;
 
 	FD_ZERO(&fdr);
 	FD_SET(server->fd, &fdr);
@@ -286,6 +339,9 @@
 	init_surface();
 	init_players();
 	num_players = 0;
+	for (i = 0; i < bots_to_spawn; i++)
+		spawn_bot();
+
 	tv.tv_sec = tv.tv_usec = 0;
 
 	DEBUG("main loop");
@@ -301,7 +357,7 @@
 				DEBUG("*** UDP PACKET");
 			 	pck_recv(server, &packet);
 				foreachsafe(p, n, players) {
-					if (udp_cmp(p->udp, &(packet.from))) 
+					if (!player_is_ai(p) && udp_cmp(p->udp, &(packet.from))) 
 			 			game_packet(p, &packet);
 				}
 			} else if (FD_ISSET(chatserver->fd, &fdt)) {
@@ -312,7 +368,7 @@
 				alloc_client(newc);
 			} else {
 				DEBUG("*** TCP ACTIVITY");
-				foreachsafe (p, n, players) if (FD_ISSET(p->tcp->fd, &fdt)) {
+				foreachsafe (p, n, players) if (!player_is_ai(p) && FD_ISSET(p->tcp->fd, &fdt)) {
 					if (buffer_read(p->tcp->in, p->tcp->fd) <= 0) {
 						DEBUG("`--- KICKING, no data");
 						FD_CLR(p->tcp->fd, &fdr);
@@ -369,7 +425,15 @@
 	CONSOLE("bound ports %d/tcp and %d/udp", tport, uport);
 
 	/* Options */
-	do_ferda = (argc > 3 && argv[3] && strchr(argv[3], 'f') != NULL);
+	if (argc > 3 && argv[3]) {
+		char *opt;
+		for (opt = argv[3]; *opt; opt++) {
+			switch (*opt) {
+				case 'f': do_ferda = 1; break;
+				case 'a': bots_to_spawn++; break;
+			}
+		}
+	}
 
 	mainloop();
 	return 0;
Index: server.h
===================================================================
RCS file: /home/cvs/tunneler/tunneler/server.h,v
retrieving revision 1.3
diff -u -r1.3 server.h
--- server.h	20 Jan 2005 22:26:14 -0000	1.3
+++ server.h	20 Jan 2005 23:16:07 -0000
@@ -5,6 +5,7 @@
 #include "udp.h"
 #include "conn.h"
 #include "game.h"
+#include "ai.h"
 #include "packet.h"
 #include "state.h"
 
@@ -19,10 +20,13 @@
 	uconn_t	*udp;
 	_u8	current_direction;
 	TANK	tank;
+	AI	ai; /* TODO: union with some other struct containing udp,tcp,seqs,... */
 	_u16	cur_seq, last_seq;
 	stq_t	state;
 } plr_t;
 
+#define player_is_ai(player) (player->udp == NULL && player->tcp == NULL)
+
 extern	plr_t players;
 extern _u32 tick;
 
Index: ai.c
===================================================================
RCS file: /home/cvs/tunneler/tunneler/ai.c,v
retrieving revision 1.1
diff -u -r1.1 ai.c
--- ai.c	21 Jan 2005 00:40:37 -0000	1.1
+++ ai.c	21 Jan 2005 00:53:44 -0000
@@ -7,8 +7,32 @@
 
 
 /* Some AI, really trivial for now. */
+/* Currently, the AI will notice only if you shoot it - then it will play
+ * a quick search'n'destroy game with you, leaving you no chance to
+ * survive >:).
+ *
+ * TODO:
+ * * More intelligent turning around - currently it often gets miserably stuck.
+ * * Self-preservation instinct - if low on stuff, seek home.
+ * * Be active - lay route for playing an explorer, kill enemies on sight.
+ * * Difficulty levels - adjusts speed, intelligence, aggressivity
+ * * Characters, for that matter - each bot has those attributes laid differently
+ *                                 (sum of them being constant, though)
+ * * Some strategy? Defensive - hiding behind stone and in homes,
+ *                              even tricks to move the enemy's attention
+ *                              to another bot?
+ *                  Agressive - ambushing in front of home, getting the start
+ *                              of an enemy?
+ *                  Cooperative - short time defensive/agressive alliances
+ *                                (based on score?)
+ * * Communication - shout at the player.
+ *                 - have an intelligent conversation about weapons,
+ *                   mobile warfare, culture and quantum physics
+ *                   with the player.
+ */
 
-/* Mostly guessing. */
+
+/* Operational parameters. Mostly guessing. */
 #define GOOD_SHOT_RADIUS  600
 
 
