[Commit] rrserver array.5c,1.1,1.2 boards.5c,1.1,1.2 connect.5c,1.1,1.2 dispatch.5c,1.1,1.2 games.5c,1.1,1.2 lex.5c,1.1,1.2 server.5c,1.1,1.2 show.5c,1.1,1.2

Keith Packard commit@keithp.com
Thu, 29 May 2003 01:15:47 -0700


Committed by: keithp

Update of /local/src/CVS/rrserver
In directory home.keithp.com:/tmp/cvs-serv15854

Modified Files:
	array.5c boards.5c connect.5c dispatch.5c games.5c lex.5c 
	server.5c show.5c 
Log Message:
add robot movement

Index: array.5c
===================================================================
RCS file: /local/src/CVS/rrserver/array.5c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- array.5c	29 May 2003 06:45:37 -0000	1.1
+++ array.5c	29 May 2003 08:15:44 -0000	1.2
@@ -37,6 +37,21 @@
 	return v;
     }
 
+    public poly push (&poly[*] a, poly v) {
+	a = (poly[dim(a)+1]) { [i] = i < dim(a) ? a[i] : v };
+	return v;
+    }
+	
+    public exception	empty (&poly[*] a);
+    
+    public poly pop (&poly[*] a) {
+	if (dim(a) == 0)
+	    raise empty (a);
+	poly v = a[dim(a)-1];
+	a = (poly[dim(a)-1]) { [i] = a[i] };
+	return v;
+    }
+
     public void iterate (&poly[*] a, void (poly v) f) {
 	for (int i = 0; i < dim (a); i++)
 	    f(a[i]);

Index: boards.5c
===================================================================
RCS file: /local/src/CVS/rrserver/boards.5c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- boards.5c	29 May 2003 06:45:37 -0000	1.1
+++ boards.5c	29 May 2003 08:15:44 -0000	1.2
@@ -390,7 +390,6 @@
 			target = TargetOrNone.none,
 			robot = RobotOrNone.none,
 			walls = walls (W.below, W.right) }};
-		printf ("placing %v\n", TransformLoc (l, transforms[i]));
 		PlaceObject (&b, l, transforms[i]);
 	    }
 
@@ -454,7 +453,7 @@
 	    return ol;
 	}
 
-	public ObjectLoc[*] find_robot (&Board b, Color color)
+	public ObjectLoc[*] find_robots (&Board b, Color color)
 	{
 	    bool match (Object o) {
 		union switch (o.robot) {
@@ -468,6 +467,15 @@
 	    return find (&b, match);
 	}
 
+	public exception invalid_robot (Color color);
+
+	public ObjectLoc find_robot (&Board b, Color color) {
+	    ObjectLoc[*] ol = find_robots (&b, color);
+	    if (dim (ol) != 1)
+		raise invalid_robot (color);
+	    return ol[0];
+	}
+	
 	public ObjectLoc[*] find_active_robot (&Board b)
 	{
 	    bool match (Object o) {
@@ -482,7 +490,7 @@
 	    return find (&b, match);
 	}
 
-	public ObjectLoc[*] find_target (&Board b, Color color, Shape shape)
+	public ObjectLoc[*] find_targets (&Board b, Color color, Shape shape)
 	{
 	    bool match (Object o) {
 		union switch (o.target) {
@@ -496,8 +504,7 @@
 	    return find (&b, match);
 	}
 
-	public ObjectLoc[*] find_active_target (&Board b)
-	{
+	public ObjectLoc[*] find_active_target (&Board b) {
 	    bool match (Object o) {
 		union switch (o.target) {
 		case target t: 
@@ -510,8 +517,7 @@
 	    return find (&b, match);
 	}
 
-	public void set_target (&Board b, Color color, Shape shape)
-	{
+	public void set_target (&Board b, Color color, Shape shape) {
 	    void    set_robot_active (ObjectLoc[*] ol, bool active) {
 		for (int o = 0; o < dim (ol); o++)
 		    b[ol[o].x, ol[o].y].robot.robot.active = active;
@@ -523,8 +529,76 @@
 	    set_robot_active (find_active_robot (&b), false);
 	    set_target_active (find_active_target (&b), false);
 	    
-	    set_robot_active (find_robot (&b, color), true);
-	    set_target_active (find_target (&b, color, shape), true);
+	    set_robot_active (find_robots (&b, color), true);
+	    set_target_active (find_targets (&b, color, shape), true);
+	}
+
+	public void position_robot (&Board b, Color color, int x, int y) {
+	    ObjectLoc ol = find_robot (&b, color);
+	    b[ol.x, ol.y].robot = RobotOrNone.none;
+	    b[x, y].robot = ol.object.robot;
+	}
+
+	typedef struct {
+	    int	dx;
+	    int dy;
+	} Delta;
+
+	bool blocked_wall (Direction direction, Walls walls) {
+	    switch (direction) {
+	    case Direction.North: return walls.above;
+	    case Direction.East:  return walls.right;
+	    case Direction.South: return walls.below;
+	    case Direction.West:  return walls.left;
+	    }
+	    return false;
+	}
+
+	bool blocked_robot (&Board b, int x, int y) {
+	    if (x < 0 || Width <= x) return true;
+	    if (y < 0 || Height <= y) return true;
+	    return b[x,y].robot != RobotOrNone.none;
+	}
+
+	Delta delta (Direction direction) {
+	    switch (direction) {
+	    case Direction.North: return (Delta) { dx =  0, dy = -1 };
+	    case Direction.East:  return (Delta) { dx =  1, dy =  0 };
+	    case Direction.South: return (Delta) { dx =  0, dy =  1 };
+	    case Direction.West:
+	    default:
+	    }
+	    return (Delta) { dx = -1, dy =  0 };
+	}
+
+	ObjectLoc find_dst (&Board b, int x, int y, Direction direction) {
+	    Delta   d = delta (direction);
+	    while (!blocked_wall (direction, b[x,y].walls) &&
+		   !blocked_robot (&b, x + d.dx, y + d.dy))
+	    {
+		x += d.dx;
+		y += d.dy;
+	    }
+	    return (ObjectLoc) { x = x, y = y, object = b[x,y] };
+	}
+	    
+	public ObjectLoc move_robot (&Board b, Color color, Direction direction) {
+	    ObjectLoc	src = find_robot (&b, color);
+	    ObjectLoc	dst = find_dst (&b, src.x, src.y, direction);
+	    return dst;
+	}
+
+	public bool solved (&Board b) {
+	    ObjectLoc[*]    target = find_active_target (&b);
+
+	    if (dim(target) != 1)
+		return false;
+	    union switch (target[0].object.robot) {
+	    case robot r:
+		return r.active;
+	    default:
+	    }
+	    return false;
 	}
     }
 }

Index: connect.5c
===================================================================
RCS file: /local/src/CVS/rrserver/connect.5c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- connect.5c	29 May 2003 06:45:37 -0000	1.1
+++ connect.5c	29 May 2003 08:15:44 -0000	1.2
@@ -56,7 +56,8 @@
 		reference ((Client) { 
 		    f = f, 
 		    user = User.none, 
-		    game = GameRef.none 
+		    game = GameRef.none,
+		    score = 0
 		})
 	    };
 	    return &clients[dim(clients)-1];

Index: dispatch.5c
===================================================================
RCS file: /local/src/CVS/rrserver/dispatch.5c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- dispatch.5c	29 May 2003 06:45:37 -0000	1.1
+++ dispatch.5c	29 May 2003 08:15:44 -0000	1.2
@@ -27,6 +27,7 @@
 autoload Server::Connect
 autoload Server::Readreq
 autoload Server::Show
+autoload Server::Games
 
 extend namespace Server {
     public namespace Dispatch {
@@ -42,20 +43,66 @@
 		File::fprintf (f, "HELO \"%s\"\n", server_id);
 	    }
 
+	    void print_client (&Client c) {
+		union switch (c.user) {
+		case none:
+		    break;
+		case username u:
+		    File::fprintf (f, " \"%s\"", u);
+		    break;
+		}
+	    }
+	    
+	    void print_client_score (&Client c) {
+		union switch (c.user) {
+		case none:
+		    break;
+		case username u:
+		    File::fprintf (f, " \"%s\" %d", u, c.score);
+		    break;
+		}
+	    }
+	    
 	    void	who () {
 		File::fprintf (f, "WHO");
-		Connect::iterate (void func(&Client c) {
-		    union switch (c.user) {
-		    case none:
-			break;
-		    case username u:
-			File::fprintf (f, " \"%s\"", u);
-			break;
-		    }
+		Connect::iterate (print_client);
+		File::fprintf (f, "\n");
+	    }
+
+	    void	games() {
+		File::fprintf (f, "GAMES");
+		Games::iterate (void func(&Game g) {
+		    File::fprintf (f, " \"%s\"", g.name);
 		});
 		File::fprintf (f, "\n");
 	    }
 
+	    void	users(string game) {
+		try {
+		    &Game	g = Games::find (game);
+		    File::fprintf (f, "USERS");
+		    Games::iterate_client (&g, print_client_score);
+		    File::fprintf (f, "\n");
+		} catch Games::no_such_game (string name) {
+		    File::fprintf (f, "ERROR NOGAME\n");
+		}
+	    }
+
+	    void	join (string game) {
+		try {
+		    &Game g = Games::find (game);
+		    Games::add_client (&g, &c);
+		} catch Games::no_such_game (string game) {
+		    File::fprintf (f, "ERROR NOGAME\n");
+		}
+	    }
+	    
+	    void	new(string game) {
+		&Game g = Games::new (game);
+		join (g.name);
+		File::fprintf (f, "NEW \"%s\"\n", g.name);
+	    }
+
 	    void	show () {
 		union switch (c.game) {
 		case none:
@@ -69,6 +116,82 @@
 		}
 	    }
 
+	    void	bid (int number) {
+		File::fprintf (f, "BID\n");
+	    }
+
+	    void	move (Color color, Direction direction) {
+		union switch (c.game) {
+		case none:
+		    File::fprintf (f, "ERROR NOTINGAME\n");
+		    break;
+		case game g:
+		    try {
+			Games::move (&g, &c, color, direction);
+			File::fprintf (f, "MOVE\n");
+		    } catch Games::notactive (&Game g, &Client c) {
+			File::fprintf (f, "ERROR NOTACTIVE\n");
+		    }
+		    break;
+		}
+	    }
+
+	    void	undo () {
+		union switch (c.game) {
+		case none:
+		    File::fprintf (f, "ERROR NOTINGAME\n");
+		    break;
+		case game g:
+		    try {
+			Games::undo (&g, &c);
+			File::fprintf (f, "UNDO\n");
+		    } catch Games::notactive (&Game g, &Client c) {
+			File::fprintf (f, "ERROR NOTACTIVE\n");
+		    }
+		    break;
+		}
+	    }
+
+	    void	reset () {
+		union switch (c.game) {
+		case none:
+		    File::fprintf (f, "ERROR NOTINGAME\n");
+		    break;
+		case game g:
+		    try {
+			Games::reset (&g, &c);
+			File::fprintf (f, "RESET\n");
+		    } catch Games::notactive (&Game g, &Client c) {
+			File::fprintf (f, "ERROR NOTACTIVE\n");
+		    }
+		    break;
+		}
+	    }
+
+	    void	turn () {
+		union switch (c.game) {
+		case none:
+		    File::fprintf (f, "ERROR NOTINGAME\n");
+		    break;
+		case game g:
+		    if (Games::solved (&g))
+			Games::next_target (&g);
+		    File::fprintf (f, "TURN\n");
+		    break;
+		}
+	    }
+
+	    void	pass () {
+	    }
+
+	    void	message (string text) {
+		Connect::iterate (void func (&Client c) {
+		    File::fprintf (c.f, "NOTICE MESSAGE \"%s\"\n", text);
+		    File::flush (c.f);
+		});
+		File::fprintf (f, "MESSAGE\n");
+	    }
+
 	    void	quit () {
 		File::fprintf (f, "QUIT\n");
 		raise Readreq::request_closed();
@@ -87,14 +210,47 @@
 		    case WHO:
 			who ();
 			break;
+		    case GAMES:
+			games ();
+			break;
+		    case USERS u:
+			users (u.game);
+			break;
+		    case NEW n:
+			new (n.game);
+			break;
+		    case JOIN j:
+			join (j.game);
+			break;
+		    case WATCH w:
+#			watch (w.game);
+			break;
 		    case SHOW:
 			show ();
 			break;
+		    case BID b:
+			bid (b.number);
+			break;
+		    case MOVE m:
+			move (m.color, m.direction);
+			break;
+		    case UNDO:
+			undo ();
+			break;
+		    case RESET:
+			reset ();
+			break;
+		    case TURN:
+			turn ();
+			break;
+		    case PASS:
+			pass ();
+			break;
+		    case MESSAGE m:
+			message (m.text);
+			break;
 		    case QUIT:
 			quit ();
-			break;
-		    default:
-			printf ("not done yet %v\n", r);
 			break;
 		    }
 		} catch Readreq::invalid_request (string w) {

Index: games.5c
===================================================================
RCS file: /local/src/CVS/rrserver/games.5c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- games.5c	29 May 2003 06:45:37 -0000	1.1
+++ games.5c	29 May 2003 08:15:44 -0000	1.2
@@ -95,6 +95,8 @@
 	public void next_target (&Game g) {
 	    Target  t = g.targets[0];
 	    g.targets = (Target[dim(g.targets)-1]) { [i] = g.targets[i+1] };
+	    g.history = (ObjectLoc[*]) {};
+	    g.time = Time.none;
 	    Boards::set_target (&g.board, t.color, t.shape);
 	}
 
@@ -110,23 +112,67 @@
 	    g.clients = ((&Client)[*]) {};
 	    g.board = Boards::random_board ();
 	    g.targets = random_targets ();
-	    g.time = Time.none;
 	    g.active = ClientRef.none;
-	    g.history = (ObjectLoc[*]) {};
 	    next_target (&g);
 	    return &g;
 	}
 
-	public &Client add_client (&Game g, &Client c) {
-	    return Array::append (&g.clients, &c);
-	}
-
 	public void remove_client (&Game g, &Client c) {
 	    Array::remove (&g.clients, &c);
+	    c.score = 0;
+	}
+
+	public &Client add_client (&Game g, &Client c) {
+	    if (c.game != GameRef.none)
+		remove_client (&c.game.game, &c);
+	    c.game = (GameRef.game) (&g);
+	    if (g.active == ClientRef.none)
+		g.active = (ClientRef.client) (&c);
+	    return Array::append (&g.clients, &c);
 	}
 
 	public void iterate_client (&Game g, void (&Client c) f) {
 	    Array::iterate (&g.clients, f);
+	}
+
+	public ClientRef active_client (&Game g) {
+	    return g.active;
+	}
+
+	public exception notactive (&Game g, &Client c);
+	
+	public bool undo (&Game g, &Client c) {
+	    try {
+		ObjectLoc ol = Array::pop (&g.history);
+		Boards::position_robot (&g.board, ol.object.robot.robot.color,
+					ol.x, ol.y);
+	    } catch Array::empty (&ObjectLoc[*] a) {
+		return false;
+	    }
+	    return true;
+	}
+
+	public void reset (&Game g, &Client c) {
+	    if (g.active != (ClientRef.client) (&c))
+		raise notactive (&g, &c);
+	    while (dim (g.history) > 0)
+		undo (&g, &c);
+	}
+
+	public bool move (&Game g, &Client c, Color color, Direction dir) {
+	    if (g.active != (ClientRef.client) (&c))
+		raise notactive (&g, &c);
+	    ObjectLoc	src = Boards::find_robot (&g.board, color);
+	    ObjectLoc	dst = Boards::move_robot (&g.board, color, dir);
+	    if (src == dst)
+		return false;
+	    Array::push (&g.history, src);
+	    Boards::position_robot (&g.board, color, dst.x, dst.y);
+	    return true;
+	}
+
+	public bool solved (&Game g) {
+	    return Boards::solved (&g.board);
 	}
     }
 }

Index: lex.5c
===================================================================
RCS file: /local/src/CVS/rrserver/lex.5c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- lex.5c	29 May 2003 06:45:37 -0000	1.1
+++ lex.5c	29 May 2003 08:15:44 -0000	1.2
@@ -91,7 +91,6 @@
 		}
 		s = s + String::new(c);
 	    }
-	    printf ("word: %s\n", s);
 	    return s;
 	}
 

Index: server.5c
===================================================================
RCS file: /local/src/CVS/rrserver/server.5c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- server.5c	29 May 2003 06:45:37 -0000	1.1
+++ server.5c	29 May 2003 08:15:44 -0000	1.2
@@ -46,16 +46,11 @@
 	&Game	game;
     } GameRef;
 
-    public typedef union {
-	void	none;
-	thread	t;
-    } UserThread;
-
     public typedef struct {
-	file	f;
-	User	user;
-	GameRef	game;
-	UserThread	t;
+	file	    f;
+	User	    user;
+	GameRef	    game;
+	int	    score;
     } Client;
 
     public typedef union {

Index: show.5c
===================================================================
RCS file: /local/src/CVS/rrserver/show.5c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- show.5c	29 May 2003 06:45:37 -0000	1.1
+++ show.5c	29 May 2003 08:15:44 -0000	1.2
@@ -33,7 +33,7 @@
 		File::fprintf (f, "   ");
 	}
 	
-	void show_color (Color c, bool active) {
+	void show_color (file f, Color c, bool active) {
 	    int	ch;
 	    switch (c) {
 	    case Color.Red:	ch = 'r'; break;
@@ -44,10 +44,10 @@
 	    }
 	    if (active)
 		ch = Ctype::toupper (ch);
-	    printf ("%c", ch);
+	    File::fprintf (f, "%c", ch);
 	}
 
-	void show_shape (Shape s, bool active) {
+	void show_shape (file f, Shape s, bool active) {
 	    int ch;
 	    switch (s) {
 	    case Shape.Triangle:    ch = 't'; break;
@@ -58,7 +58,7 @@
 	    }
 	    if (active)
 		ch = Ctype::toupper (ch);
-	    printf ("%c", ch);
+	    File::fprintf (f, "%c", ch);
 	}
 	
 	void show_second_object (file f, &Object o) {
@@ -71,8 +71,8 @@
 		File::fprintf (f, "..");
 		break;
 	    case robot r:
-		show_color (r.color, r.active);
-		show_color (r.color, r.active);
+		show_color (f, r.color, r.active);
+		show_color (f, r.color, r.active);
 		break;
 	    }
 	}
@@ -87,8 +87,8 @@
 		File::fprintf (f, "..");
 		break;
 	    case target t:
-		show_color (t.color, t.active);
-		show_shape (t.shape, t.active);
+		show_color (f, t.color, t.active);
+		show_shape (f, t.shape, t.active);
 		break;
 	    }
 	}
@@ -125,9 +125,9 @@
 	    for (int col = 0; col < Width; col++)
 	    {
 		if (b[col,Height-1].walls.below)
-		    printf (" ==");
+		    File::fprintf (f, " ==");
 		else
-		    printf ("   ");
+		    File::fprintf (f, "   ");
 	    }
 	}