[Commit] rrserver clients.5c,1.1,1.2 dispatch.5c,1.5,1.6 games.5c,1.3,1.4 main.5c,1.2,1.3 protocol,1.14,1.15 rr.5c,1.1,1.2 send.5c,1.1,1.2 server.5c,1.3,1.4

Keith Packard commit@keithp.com
Fri May 30 07:47:08 PDT 2003


Committed by: keithp

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

Modified Files:
	clients.5c dispatch.5c games.5c main.5c protocol rr.5c send.5c 
	server.5c 
Log Message:
Add bidding

Index: clients.5c
===================================================================
RCS file: /local/src/CVS/rrserver/clients.5c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- clients.5c	29 May 2003 17:46:29 -0000	1.1
+++ clients.5c	30 May 2003 06:47:05 -0000	1.2
@@ -22,6 +22,9 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+autoload Array
+autoload RR
+autoload RR::Send
 autoload Server
 
 extend namespace Server {
@@ -29,12 +32,31 @@
 	(&Client)[0]    clients = {};
 
 	public void iterate (void (&Client c) f) {
-	    for (int i = 0; i < dim (clients); i++)
-		f (&clients[i]);
+	    Array::iterate (&clients, f);
 	}
 
 	public exception no_such_client (file f);
 
+	public void client_send (&Client c, string fmt, poly args...) {
+	    RR::Send::send (c.f, fmt, args...);
+	    File::flush (c.f);
+	}
+
+	public void server_send (string fmt, poly args...) {
+	    void	message_client (&Client o) {
+		client_send (&o, fmt, args...);
+	    }
+	    Clients::iterate (message_client);
+	}
+
+	public void game_send (&Game g, string fmt, poly args...) {
+	    void	message_client (&Client o) {
+		if (o.game == (GameRef.game) (&g))
+		    client_send (&o, fmt, args...);
+	    }
+	    Clients::iterate (message_client);
+	}
+
 	public &Client select (file f) {
 	    exception found (&Client c);
 	    try {
@@ -64,27 +86,18 @@
 	}
 	
 	public &Client new (file f) {
-	    clients = ((&Client)[dim(clients)+1]) { 
-		[i] = i < dim(clients) ? 
-		&clients[i] : 
-		reference ((Client) { 
-		    f = f, 
-		    user = User.none, 
-		    game = GameRef.none,
-		    score = 0,
-		})
-	    };
+	    return Array::append (&clients, 
+				  reference ((Client) { 
+				    f = f, 
+				    user = User.none, 
+				    game = GameRef.none,
+				    score = 0,
+				  }));
 	    return &clients[dim(clients)-1];
 	}
 
 	public void dispose (&Client c) {
-	    bool found = false;
-
-	    clients = ((&Client)[dim(clients)-1]) { 
-		[i] = found ? &clients[i+1] : (&clients[i] == &c ? 
-					      (found=true, &clients[i+1]) :
-					      &clients[i])
-	    };
+	    Array::remove (&clients, &c);
 	}
 
 	public void print (&Client c) {

Index: dispatch.5c
===================================================================
RCS file: /local/src/CVS/rrserver/dispatch.5c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- dispatch.5c	29 May 2003 17:46:29 -0000	1.5
+++ dispatch.5c	30 May 2003 06:47:05 -0000	1.6
@@ -32,36 +32,16 @@
 
 extend namespace Server {
     public namespace Dispatch {
-	string	server_id = "RicochetServer";
-
-	public void set_server_id (string id) { server_id = id; }
-
-	void client_locked (file f) {
-	    &Client	c = Clients::new (f);
+	
+	void client_locked (file f, &Client c) {
 	    
 	    exception	notactive ();
 	    exception	notingame ();
 	    exception	invalidname ();
 	    exception	nonameset ();
 
-	    void	broadcast (string fmt, poly args...) {
-		RR::Send::send (stdout, "broadcast: ");
-		RR::Send::send (stdout, fmt, args...);
-		void	message_client (&Client o) {
-		    if (&o != &c)
-		    {
-			RR::Send::send (o.f, fmt, args...);
-			File::flush (o.f);
-		    }
-		}
-		Clients::iterate (message_client);
-		RR::Send::send (stdout, "done\n");
-	    }
-
 	    void	respond (string fmt, poly args...) {
-		RR::Send::send (stdout, "respond: ");
-		RR::Send::send (stdout, fmt, args...);
-		RR::Send::send (f, fmt, args...);
+		Clients::client_send (&c, fmt, args...);
 	    }
 
 	    void print_client (&Client o) {
@@ -84,21 +64,35 @@
 		}
 	    }
 	    
+	    void assert_user ()
+	    {
+		if (c.user == User.none)
+		    raise nonameset ();
+	    }
+
+	    void assert_game ()
+	    {
+		if (c.game == GameRef.none)
+		    raise notingame ();
+	    }
+		
 	    void	helo (string username) {
 		if (Clients::find (username) != ClientRef.none)
 		    raise invalidname ();
 		c.user.username = username;
 		respond ("HELO %s\n", server_id);
-		broadcast ("NOTICE USER %s\n", username);
+		Clients::server_send ("NOTICE USER %s\n", username);
 	    }
 
 	    void	who () {
+		assert_user ();
 		respond ("WHO");
 		Clients::iterate (print_client);
 		respond ("\n");
 	    }
 
 	    void	games() {
+		assert_user ();
 		respond ("GAMES");
 		Games::iterate (void func(&Game g) {
 		    respond (" %s", g.name);
@@ -107,6 +101,7 @@
 	    }
 
 	    void	users(string game) {
+		assert_user ();
 		&Game	g = Games::find (game);
 		respond ("USERS");
 		Games::iterate_client (&g, print_client_score);
@@ -114,96 +109,75 @@
 	    }
 
 	    void	join (string game) {
+		assert_user ();
 		&Game g = Games::find (game);
-		Games::add_client (&g, &c);
+		Games::add_client (&g, &c, true);
 		respond ("JOIN\n");
-		broadcast ("NOTICE JOIN %s %s\n", g.name, c.user.username);
 	    }
 	    
 	    void	new(string game) {
+		assert_user ();
 		&Game g =Games::new (game);
-		Games::add_client (&g, &c);
+		Games::add_client (&g, &c, false);
 		respond ("NEW %s\n", g.name);
-		broadcast ("NOTICE NEW %s\n", g.name);
+		Clients::server_send ("NOTICE NEW %s\n", g.name);
 	    }
 
 	    void	show () {
-		union switch (c.game) {
-		case none:
-		    raise notingame ();
-		    break;
-		case game g:
-		    File::fprintf (f, "SHOW \"\n");
-		    Show::show (f, &g.board);
-		    File::fprintf (f, "\"\n");
-		    break;
-		}
+		assert_user ();
+		assert_game ();
+		File::fprintf (f, "SHOW \"\n");
+		Show::show (f, &c.game.game.board);
+		File::fprintf (f, "\"\n");
 	    }
 
 	    void	bid (int number) {
+		assert_user ();
+		assert_game ();
+		Games::bid (&c.game.game, &c, number);
 		respond ("BID\n");
-		broadcast ("BID %s %d\n", c.user.username, number);
 	    }
 
 	    void	move (Color color, Direction direction) {
-		union switch (c.game) {
-		case none:
-		    raise notingame ();
-		case game g:
-		    Games::move (&g, &c, color, direction);
-		    respond ("MOVE\n");
-		    break;
-		}
-		broadcast ("NOTICE MOVE %C %D\n", color, direction);
+		assert_user ();
+		assert_game ();
+		Games::move (&c.game.game, &c, color, direction);
+		respond ("MOVE %d\n", Games::count (&c.game.game));
 	    }
 
 	    void	undo () {
-		union switch (c.game) {
-		case none:
-		    raise notingame ();
-		    break;
-		case game g:
-		    Games::undo (&g, &c);
-		    respond ("UNDO\n");
-		    break;
-		}
-		broadcast ("NOTICE UNDO\n");
+		assert_user ();
+		assert_game ();
+		Games::undo (&c.game.game, &c);
+		respond ("UNDO\n");
 	    }
 
 	    void	reset () {
-		union switch (c.game) {
-		case none:
-		    raise notingame ();
-		    break;
-		case game g:
-		    Games::reset (&g, &c);
-		    respond ("RESET\n");
-		    break;
-		}
-		broadcast ("NOTICE RESET\n");
+		assert_user ();
+		assert_game ();
+		Games::reset (&c.game.game, &c);
+		respond ("RESET\n");
 	    }
 
 	    void	turn () {
-		union switch (c.game) {
-		case none:
-		    raise notingame ();
-		case game g:
-		    if (Games::solved (&g))
-			Games::next_turn (&g);
-		    respond ("TURN\n");
-		    break;
-		}
-		broadcast ("NOTICE TURN\n");
+		assert_user ();
+		assert_game ();
+		if (Games::solved (&c.game.game))
+		    Games::next_turn (&c.game.game);
+		respond ("TURN\n");
 	    }
 
 	    void	pass () {
+		assert_user ();
+		assert_game ();
 	    }
 
 	    void	message (string text) {
+		assert_user ();
 		respond ("MESSAGE\n");
 		string u = (c.user == User.none ? "anonymous" :
 			    c.user.username);
-		broadcast ("NOTICE MESSAGE %s %s\n", u, text);
+		Clients::server_send ("NOTICE MESSAGE %s %s\n", u, text);
 	    }
 
 	    void	quit () {
@@ -217,15 +191,7 @@
 		try {
 		    File::flush (f);
 		    Request	r = Readreq::read (f);
-		    union switch (r) {
-		    case HELO:
-		    case QUIT:
-			 break;
-		    default:
-			if (c.user == User.none)
-			    raise nonameset ();
-			break;
-		    }
+		    
 		    union switch (r) {
 		    case HELO h:    
 			helo (h.username);
@@ -296,22 +262,36 @@
 		    respond ("ERROR NONAMESET\n");
 		} catch invalidname () {
 		    respond ("ERROR INVALIDNAME\n");
+		} catch Games::notbidding (&Game g) {
+		    respond ("ERROR NOTBIDDING\n");
+		} catch Games::toomanymoves (&Game g, &Client c) {
+		    respond ("ERROR TOOMANYMOVES\n");
+		} catch Games::blocked (&Game g, &Client c) {
+		    respond ("ERROR BLOCKED\n");
 		} catch Readreq::request_closed () {
 		    User user = c.user;
 		    printf ("Client closed %v\n", c.user);
 		    Clients::dispose (&c);
-		    File::close (f);
 		    if (c.user != User.none)
-			broadcast ("NOTICE PART %s\n", c.user.username);
+			Clients::server_send ("NOTICE PART %s\n", c.user.username);
 		    return;
 		}
 	    }
 	}
 
+	void client_cleanup (&Client c) {
+	    if (c.game != GameRef.none)
+		Games::remove_client (&c.game.game, &c);
+	    Clients::dispose (&c);
+	}
+	
 	public void client (file f)
 	{
-	    twixt (lock (); unlock ())
-		client_locked (f);
+    	    twixt (true; File::close (f))
+		twixt (lock (); unlock ())
+		    twixt ((&Client c = Clients::new (f)), true;
+			   client_cleanup (&c))
+			client_locked (f, &c);
 	}
     }
 }

Index: games.5c
===================================================================
RCS file: /local/src/CVS/rrserver/games.5c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- games.5c	29 May 2003 17:46:29 -0000	1.3
+++ games.5c	30 May 2003 06:47:05 -0000	1.4
@@ -24,7 +24,9 @@
 
 autoload Server
 autoload Array
+autoload Timer
 autoload Server::Boards
+autoload Server::Clients
 
 extend namespace Server {
     public namespace Games {
@@ -43,7 +45,12 @@
 	}
     
 	public exception no_such_game (string name);
-    
+	public exception notactive (&Game g, &Client c);
+	public exception notbidding (&Game g);
+	public exception notlower (&Game g, &Client c, int bid);
+	public exception toomanymoves (&Game g, &Client c);
+	public exception blocked (&Game g, &Client c);
+	
 	public &Game find (string name) {
 	    exception	found (&Game g);
 	    try {
@@ -70,6 +77,30 @@
 	    return false;
 	}
 
+	public void remove_client (&Game g, &Client c) {
+	    if (g.active == (ClientRef.client) (&c))
+		g.active = ClientRef.none;
+	    Array::remove (&g.clients, &c);
+	}
+
+	public &Client add_client (&Game g, &Client c, bool playing) {
+	    if (c.game != GameRef.none)
+		remove_client (&c.game.game, &c);
+	    c.game = (GameRef.game) (&g);
+	    c.playing = playing;
+	    c.score = 0;
+	    c.bid = Bid.none;
+	    Array::append (&g.clients, &c);
+	    Clients::game_send (&g, "NOTICE %s %s %s\n", 
+				playing ? "JOIN" : "WATCH",
+				g.name, c.user.username);
+	    return &c;
+	}
+
+	public void iterate_client (&Game g, void (&Client c) f) {
+	    Array::iterate (&g.clients, f);
+	}
+
 	Target[*] random_targets () {
 	    static Color[4]    colors = {
 		Color.Red, Color.Yellow, Color.Green, Color.Blue
@@ -97,7 +128,14 @@
 	    g.targets = (Target[dim(g.targets)-1]) { [i] = g.targets[i+1] };
 	    g.history = (ObjectLoc[*]) {};
 	    g.time = Time.none;
+	    g.state = GameState.New;
 	    Boards::set_target (&g.board, t.color, t.shape);
+
+	    void reset_client (&Client c) {
+		c.bid = Bid.none;
+	    }
+	    iterate_client (&g, reset_client);
+	    Clients::game_send (&g, "NOTICE TURN %C %S\n", t.color, t.shape);
 	}
 
 	public void next_turn (&Game g) {
@@ -117,61 +155,142 @@
 	    g.board = Boards::random_board ();
 	    g.targets = random_targets ();
 	    g.active = ClientRef.none;
+	    g.timer_serial = 0;
 	    next_target (&g);
 	    return &g;
 	}
 
-	public void remove_client (&Game g, &Client c) {
-	    Array::remove (&g.clients, &c);
-	}
-
-	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) {
+	void assert_active (&Game g, &Client c) {
 	    if (g.active != (ClientRef.client) (&c))
 		raise notactive (&g, &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;
+	}
+	
+	void undo_move (&Game g)
+	{
+	    ObjectLoc ol = Array::pop (&g.history);
+	    Boards::position_robot (&g.board, ol.object.robot.robot.color,
+				    ol.x, ol.y);
+	}
+	
+	public void undo (&Game g, &Client c) {
+	    assert_active (&g, &c);
+	    if (dim (g.history) > 0)
+	    {
+		undo_move (&g);
+		Clients::game_send (&g, "NOTICE UNDO\n");
 	    }
-	    return true;
 	}
 
 	public void reset (&Game g, &Client c) {
+	    assert_active (&g, &c);
 	    while (dim (g.history) > 0)
 		undo (&g, &c);
+	    Clients::game_send (&g, "NOTICE RESEt\n");
 	}
 
-	public bool move (&Game g, &Client c, Color color, Direction dir) {
-	    if (g.active != (ClientRef.client) (&c))
-		raise notactive (&g, &c);
+	ClientRef lowest_bidder (&Game g) {
+	    Bid		min = Bid.none;
+	    ClientRef	min_client = ClientRef.none;
+	    void lower_bid (&Client c) {
+		union switch (c.bid) {
+		case none:
+		    break;
+		case number n:
+		    if (min == Bid.none || min.number > n)
+		    {
+			min = (Bid.number) n;
+			min_client = (ClientRef.client) (&c);
+		    }
+		    break;
+		}
+	    }
+	    iterate_client (&g, lower_bid);
+	    return min_client;
+	}
+
+	void set_active (&Game g) {
+	    g.active = lowest_bidder (&g);
+
+	    union switch (g.active) {
+	    case none:
+		break;
+	    case client c:
+		Clients::game_send (&g, "NOTICE ACTIVE %s %d\n",
+				    c.user.username, c.bid.number);
+		break;
+	    }
+	}
+
+	void set_state (&Game g, GameState state) {
+	    g.state = state;
+	    Clients::game_send (&g, "NOTICE GAMESTATE %G\n", state);
+	    switch (state) {
+	    case GameState.Bidding:
+		int timer_serial = ++g.timer_serial;
+		
+		bool validate () {
+		    if (g.state != GameState.Bidding || 
+			g.timer_serial != timer_serial)
+			    return false;
+		    return true;
+		}
+		
+		void notify (int remain) {
+		    Clients::game_send (&g, "NOTICE TIMER %d\n",
+					remain);
+		}
+
+		void expire () {
+		    set_state (&g, GameState.Showing);
+		}
+
+		Timer::start (60, 10, lock, unlock, validate, notify, expire);
+		break;
+	    case GameState.Showing:
+		set_active (&g);
+		break;
+	    }
+	}
+
+	public void bid (&Game g, &Client c, int number) {
+	    switch (g.state) {
+	    case GameState.New:
+		set_state (&g, GameState.Bidding);
+	    case GameState.Bidding:
+		break;
+	    case GameState.Showing:
+	    case GameState.Solved:
+		raise notbidding (&g);
+		break;
+	    }
+	    if (c.bid != Bid.none && c.bid.number <= number)
+		raise notlower (&g, &c, number);
+	    c.bid = (Bid.number) number;
+	    Clients::game_send (&g, "NOTICE BID %s %d\n", c.user.username, number);
+	}
+	
+	public int count (&Game g) {
+	    return dim (g.history);
+	}
+
+	public void move (&Game g, &Client c, Color color, Direction dir) {
+	    assert_active (&g, &c);
+	    if (count (&g) >= c.bid.number)
+		raise toomanymoves (&g, &c);
 	    ObjectLoc	src = Boards::find_robot (&g.board, color);
 	    ObjectLoc	dst = Boards::move_robot (&g.board, color, dir);
 	    if (src == dst)
-		return false;
+		raise blocked (&g, &c);
 	    Array::push (&g.history, src);
 	    Boards::position_robot (&g.board, color, dst.x, dst.y);
-	    return true;
+	    Clients::game_send (&g, "NOTICE MOVE %d %C %D\n",
+				Games::count (&g), color, dir);
+	    if (Boards::solved (&g.board))
+		set_state (&g, GameState.Solved);
 	}
 
 	public bool solved (&Game g) {

Index: main.5c
===================================================================
RCS file: /local/src/CVS/rrserver/main.5c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- main.5c	29 May 2003 18:02:52 -0000	1.2
+++ main.5c	30 May 2003 06:47:05 -0000	1.3
@@ -22,12 +22,14 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+autoload PRNG;
 autoload Server::Net
 autoload Server::Dispatch
 
 extend namespace Server {
     public namespace Main {
 	public void main () {
+	    PRNG::dev_srandom (32);
 	    file    f = Net::create (RR::Port);
 	    File::fprintf (stderr, "RR server started on port %d.\n", RR::Port);
     	    Net::listen (Dispatch::client, f);

Index: protocol
===================================================================
RCS file: /local/src/CVS/rrserver/protocol,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- protocol	30 May 2003 04:10:38 -0000	1.14
+++ protocol	30 May 2003 06:47:05 -0000	1.15
@@ -82,12 +82,12 @@
 	<turn> is a number from 1 to 17 indicating the current turn
 	<color> <shape> indicate the active piece
 	<state> is one of:
-		NEW	Turn just started, no bids yet
-		BID	Bidding opened.  <time> indicates time remaining,
+		new	Turn just started, no bids yet
+		bid	Bidding opened.  <time> indicates time remaining,
 			<bid> indicates the minimum bid
-		SHOW	Bidding closed and solution being demonstrated
+		show	Bidding closed and solution being demonstrated
 			<active> indicates the person demonstrating
-		SOLVED 	Solution succesfully demonstrated that
+		solved 	Solution succesfully demonstrated that
 			is less than the active users bid. <active>
 			indicates the winner.
 	<time> is valid only in BID state, else it's 0
@@ -193,7 +193,7 @@
 
 	BID
 
-	Possible errors: NOTINGAME, TIMEOUT, NOTNUMBER
+	Possible errors: NOTINGAME, NOTBIDDING, NOTNUMBER, NOTLOWER
 
 1.12. Move
 
@@ -201,12 +201,12 @@
 
 	->
 
-	MOVE
+	MOVE <count>
 
 	<color> is one of 'R', 'Y', 'G' or 'B', <dir> is one of 'N', 'E',
 	'S' or 'W'.
 
-	Possible errors: NOTINGAME, NOTACTIVE, BLOCKED
+	Possible errors: NOTINGAME, NOTACTIVE, BLOCKED, TOOMANYMOVES
 
 1.13. Undo
 
@@ -307,7 +307,7 @@
 
 2.1. Move notice (game)
 
-	NOTICE MOVE <color> <dir>
+	NOTICE MOVE <count> <color> <dir>
 
 2.2. New users (all)
 
@@ -337,10 +337,14 @@
 
 2.8. Select active player (game)
 
-	NOTICE ACTIVE <username>
+	NOTICE ACTIVE <username> <bid>
 
 	Only the active player may move the robots
 
+2.9. Game state change
+
+	NOTICE GAMESTATE <state>
+
 2.9. Undo (game)
 
 	NOTICE UNDO
@@ -392,15 +396,23 @@
 	Possibly returned by: SHOW, MOVE, RESET, UNDO, TURN, PASS,
 	MESSAGE.
 
-3.2. Time out
+3.2. Not bidding
 
-	ERROR TIMEOUT
+	ERROR NOTBIDDING
 
-	A bid was submitted after the timer expired.
+	A bid was submitted after the bidding closed
 
 	Possibly returned by: BID
 
-3.3. Not active
+3.3. Not lower
+
+	ERROR NOTLOWER
+
+	A bid was submitted that was higher than previous bid.
+
+	Possibly returned by: BID
+
+3.4. Not active
 
 	ERROR NOTACTIVE
 
@@ -409,13 +421,13 @@
 	
 	Possibly returned by: MOVE, RESET, UNDO
 
-3.4. Not number
+3.5. Not number
 
 	ERROR NOTNUMBER
 
 	A non-numeric value was supplied where a number was required
 	
-3.5. Blocked
+3.6. Blocked
 
 	ERROR BLOCKED
 

Index: rr.5c
===================================================================
RCS file: /local/src/CVS/rrserver/rr.5c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- rr.5c	29 May 2003 06:45:37 -0000	1.1
+++ rr.5c	30 May 2003 06:47:05 -0000	1.2
@@ -62,6 +62,13 @@
 	Walls		walls;
     } Object;
 
+    public typedef enum {
+	New,	    /* no bids yet */
+	Bidding,    /* some bids, timer running */
+	Showing,    /* timer expired, waiting for solution */
+	Solved	    /* game solved */
+    } GameState;
+    
     public typedef Object[Width,Height]	Board;
 
     public typedef union {

Index: send.5c
===================================================================
RCS file: /local/src/CVS/rrserver/send.5c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- send.5c	29 May 2003 17:46:29 -0000	1.1
+++ send.5c	30 May 2003 06:47:05 -0000	1.2
@@ -27,7 +27,10 @@
 extend namespace RR {
     public namespace Send {
 	bool needsquote (string s) {
-	    for (int i = 0; i < String::length (s); i++)
+	    int	len = String::length (s);
+	    if (len == 0)
+		return true;
+	    for (int i = 0; i < len; i++)
 		if (Ctype::isblank (s[i]) || s[i] == '"' || s[i] == '\\')
 		    return true;
 	    return false;
@@ -86,6 +89,15 @@
 		}
 	    }
 
+	    void put_gamestate (GameState s) {
+		switch (s) {
+		case GameState.New:	File::fprintf (f, "new"); break;
+		case GameState.Bidding:	File::fprintf (f, "bid"); break;
+		case GameState.Showing:	File::fprintf (f, "show"); break;
+		case GameState.Solved:	File::fprintf (f, "solved"); break;
+		}
+	    }
+
 	    void put_number (int n) {
 		File::fprintf (f, "%d", n);
 	    }
@@ -172,6 +184,7 @@
 		    case 'C':	put_color (a); break;
 		    case 'D':	put_direction (a); break;
 		    case 'S':	put_shape (a); break;
+		    case 'G':	put_gamestate (a); break;
 		    }
 		}
 		else

Index: server.5c
===================================================================
RCS file: /local/src/CVS/rrserver/server.5c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- server.5c	29 May 2003 17:46:29 -0000	1.3
+++ server.5c	30 May 2003 06:47:05 -0000	1.4
@@ -33,14 +33,18 @@
 
     mutex   server_mutex = Mutex::new ();
 
+    string	server_id = "RicochetServer";
+
+    public void set_server_id (string id) { server_id = id; }
+
     public bool lock () {
 	Mutex::acquire (server_mutex);
-	printf ("lock %v\n", Thread::current ());
+#	printf ("lock %v\n", Thread::current());
 	return true;
     }
 
     public bool unlock () {
-	printf ("unlock %v\n", Thread::current ());
+#	printf ("unlock %v\n", Thread::current());
 	Mutex::release (server_mutex);
 	return true;
     }
@@ -60,11 +64,18 @@
 	&Game	game;
     } GameRef;
 
+    public typedef union {
+	void	none;
+	int	number;
+    } Bid;
+    
     public typedef struct {
 	file	    f;
 	User	    user;
 	GameRef	    game;
 	int	    score;
+	Bid	    bid;
+	bool	    playing;
     } Client;
 
     public typedef union {
@@ -79,12 +90,14 @@
     
     public typedef struct {
 	string		name;
+	GameState	state;
 	(&Client)[*]	clients;
 	Target[*]	targets;
 	Board		board;
 	Time		time;
 	ClientRef	active;
 	ObjectLoc[*]    history;
+	int		timer_serial;
     } Game;
 
     public exception notreached ();





More information about the Commit mailing list