[Commit] rrserver dispatch.5c,1.16,1.17 games.5c,1.14,1.15 protocol,1.24,1.25 rr.5c,1.8,1.9 send.5c,1.6,1.7 server.5c,1.8,1.9

Keith Packard commit at keithp.com
Sat May 31 10:00:12 PDT 2003


Committed by: keithp

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

Modified Files:
	dispatch.5c games.5c protocol rr.5c send.5c server.5c 
Log Message:
Rename solved to done, permit moves in done state (but ignore them)

Index: dispatch.5c
===================================================================
RCS file: /local/src/CVS/rrserver/dispatch.5c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- dispatch.5c	31 May 2003 05:28:14 -0000	1.16
+++ dispatch.5c	31 May 2003 16:00:09 -0000	1.17
@@ -339,7 +339,7 @@
 		int	    turn = 17 - dim (g.targets);
 		
 		int	    remain = 0;
-		if (g.state == GameState.Bidding)
+		if (g.state == GameState.BID)
 		{
 		    remain = g.expire_time - time();
 		    if (remain < 0) remain = 0;
@@ -352,12 +352,8 @@
 		}
 
 		string	    active = "";
-		switch (g.state) {
-		case GameState.Showing:
-		case GameState.Solved:
+		if (g.state == GameState.SHOW)
 		    active = g.active.client.user.username;
-		    break;
-		}
 
 		respond ("GAMEINFO %d %C %S %G %d %d %s\n",
 			 turn, 
@@ -480,7 +476,7 @@
 	    void	turn () {
 		assert_user ();
 		assert_game ();
-		Games::next_turn (&c.game.game, &c);
+		Games::turn (&c.game.game, &c);
 		respond ("TURN\n");
 	    }
 

Index: games.5c
===================================================================
RCS file: /local/src/CVS/rrserver/games.5c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- games.5c	31 May 2003 05:28:14 -0000	1.14
+++ games.5c	31 May 2003 16:00:09 -0000	1.15
@@ -30,8 +30,12 @@
 
 extend namespace Server {
     public namespace Games {
+	/* array of all games */
 	public (&Game)[0]	games = {};
 
+	/* raised when attempting to find a nonexistant game */
+	public exception no_such_game (string name);
+	
 	&Game insert () {
 	    return Array::append (&games, reference ((Game) {}));
 	}
@@ -45,17 +49,30 @@
 	    Array::iterate (&games, f);
 	}
     
-	public exception no_such_game (string name);
-	
 	void assert_active (&Game g, &Client c) {
 	    if (g.active != (ClientRef.client) (&c))
 		raise error (Error.NOTACTIVE);
 	}
 
+	void assert_active_or_done (&Game g, &Client c) {
+	    if (g.state == GameState.DONE)
+		return;
+	    if (g.state == GameState.SHOW &&
+	        g.active == (ClientRef.client) (&c))
+		return;
+	    raise error (Error.NOTACTIVE);
+	}
+
 	void assert_playing (&Game c, &Client c) {
 	    if (!c.playing)
 		raise error (Error.NOTPLAYING);
 	}
+
+	void assert_done (&Game g) {
+	    if (g.state == GameState.DONE)
+		return;
+	    raise error (Error.NOTDONE);
+	}
 	
 	/* find a game by name */
 	public &Game find (string name) {
@@ -71,19 +88,6 @@
 	    raise no_such_game (name);
 	}
 
-	bool exists (string name) {
-	    exception	found (&Game g);
-	    try {
-		iterate (void func (&Game g) {
-		    if (g.name == name)
-			raise found (&g);
-		});
-	    } catch found (&Game g) {
-		return true;
-	    }
-	    return false;
-	}
-
 	/* list clients associated with a game */
 	public void iterate_client (&Game g, void (&Client c) f, 
 				    bool playing, bool watching) {
@@ -94,14 +98,16 @@
 	    Array::iterate (&g.clients, pick);
 	}
 
-	public void game_send (&Game g, string fmt, poly args...) {
+	/* broadcast message to all game users */
+	void game_send (&Game g, string fmt, poly args...) {
 	    void	message_client (&Client o) {
 		Clients::client_send (&o, fmt, args...);
 	    }
 	    iterate_client (&g, message_client, true, true);
 	}
 
-	public void game_send_client_scores (&Game g, string fmt, poly args...) {
+	/* broadcast message including players and scores to all game users */
+	void game_send_client_scores (&Game g, string fmt, poly args...) {
 	    void	message_client (&Client c) {
 		Clients::client_send (&c, fmt, args...);
 
@@ -114,6 +120,20 @@
 	    iterate_client (&g, message_client, true, true);
 	}
 
+	/* does the given game exist? */
+	bool exists (string name) {
+	    exception	found (&Game g);
+	    try {
+		iterate (void func (&Game g) {
+		    if (g.name == name)
+			raise found (&g);
+		});
+	    } catch found (&Game g) {
+		return true;
+	    }
+	    return false;
+	}
+
 	bool any_bids (&Game g) {
 	    bool    any = false;
 	    void bid_set (&Client c) {
@@ -176,11 +196,11 @@
 	    g.state = state;
 	    game_send (&g, "NOTICE GAMESTATE %G\n", state);
 	    switch (state) {
-	    case GameState.Bidding:
+	    case GameState.BID:
 		int timer_serial = ++g.timer_serial;
 		
 		bool validate () {
-		    if (g.state != GameState.Bidding || 
+		    if (g.state != GameState.BID || 
 			g.timer_serial != timer_serial)
 			    return false;
 		    return true;
@@ -191,39 +211,20 @@
 		}
 
 		void expire () {
-		    set_state (&g, GameState.Showing);
+		    set_state (&g, GameState.SHOW);
 		}
 
 		g.expire_time = Timer::start (g.expire_interval, 10, 
 					      lock, unlock, 
 					      validate, notify, expire);
 		break;
-	    case GameState.Showing:
+	    case GameState.SHOW:
 		g.active = ClientRef.none;
 		set_active (&g);
 		break;
-	    }
-	}
-
-	/* remove a client from any game */
-	public void remove_client (&Client c) {
-	    if (c.game == GameRef.none)
-		return;
-	    &Game g = &c.game.game;
-	    Array::remove (&g.clients, &c);
-	    game_send (&g, "NOTICE PART %s\n", c.user.username);
-	    /* correct the state if necessary */
-	    switch (g.state) {
-	    case GameState.New:
-		break;
-	    case GameState.Bidding:
-		if (!any_bids (&g))
-		    set_state (&g, GameState.New);
-		break;
-	    case GameState.Showing:
-		set_active (&g);
-		break;
-	    case GameState.Solved:
+	    case GameState.DONE:
+		g.active = ClientRef.none;
+		g.next_board = (BoardOrNone.board) g.board;
 		break;
 	    }
 	}
@@ -245,21 +246,6 @@
 	    }
 	}
 	
-	/* add a client to a game */
-	public &Client add_client (&Game g, &Client c, bool playing) {
-	    remove_client (&c);
-	    c.game = (GameRef.game) (&g);
-	    c.playing = playing;
-	    c.score = 0;
-	    c.bid = Bid.none;
-	    c.abandon = false;
-	    Array::append (&g.clients, &c);
-	    game_send (&g, "NOTICE %s %s\n", 
-		       playing ? "JOIN" : "WATCH",
-		       c.user.username);
-	    return &c;
-	}
-
     	void next_game (&Game g);
 
 	/* select the next target */
@@ -271,11 +257,15 @@
 		return;
 	    }
 
+	    union switch (g.next_board) {
+	    case none: break;
+	    case board b: g.board = b; break;
+	    }
 	    g.target = g.targets[0];
 	    g.targets = (Target[dim(g.targets)-1]) { [i] = g.targets[i+1] };
 	    g.history = (ObjectLoc[*]) {};
 	    g.expire_time = 0;
-	    g.state = GameState.New;
+	    g.state = GameState.NEW;
 	    Boards::set_target (&g.board, g.target.color, g.target.shape);
 
 	    void reset_client (&Client c) {
@@ -286,25 +276,6 @@
 	    game_send (&g, "NOTICE TURN %C %S\n", g.target.color, g.target.shape);
 	}
 
-	public void next_turn (&Game g, &Client c) {
-	    assert_playing (&g, &c);
-	    switch (g.state) {
-	    case GameState.New:
-	    case GameState.Bidding:
-		if (!all_abandon (&g))
-		    raise error (Error.NOTFINISHED);
-		break;
-	    case GameState.Showing:
-		if (any_bids (&g))
-		    raise error (Error.NOTFINISHED);
-		reset_move (&g);
-		break;
-	    case GameState.Solved:
-		break;
-	    }
-	    next_target (&g);
-	}
-
 	Target[*] random_targets () {
 	    static Color[4]    colors = {
 		Color.Red, Color.Yellow, Color.Green, Color.Blue
@@ -332,9 +303,46 @@
 	    g.targets = random_targets ();
 	    g.active = ClientRef.none;
 	    g.timer_serial = 0;
+	    g.next_board = BoardOrNone.none;
 	    next_target (&g);
 	}
 	
+	void next_game (&Game g) {
+	    ClientRef	winner = ClientRef.none;
+	    void find_winner (&Client c) {
+		if (c.score > 0 &&
+		    (winner == ClientRef.none || c.score >
+		    winner.client.score))
+		    winner = (ClientRef.client) (&c);
+	    }
+	    iterate_client (&g, find_winner, true, false);
+	    if (winner != ClientRef.none)
+		winner.client.games++;
+	    game_send_client_scores (&g, "NOTICE GAMEOVER");
+	    init (&g);
+	}
+	
+	void assert_bidding (&Game g) {
+	    switch (g.state) {
+	    case GameState.NEW:
+	    case GameState.BID:
+		break;
+	    case GameState.SHOW:
+	    case GameState.DONE:
+		raise error (Error.NOTBIDDING);
+		break;
+	    }
+	    
+	}
+	
+	public int count (&Game g) {
+	    return dim (g.history);
+	}
+
+	/*
+	 * Game management commands
+	 */
+
 	public &Game new (string suggestion) {
 	    string name;
 	    for (int n = 0; 
@@ -360,67 +368,53 @@
 	    Clients::server_send ("NOTICE DISPOSE %s\n", g.name);
 	}
 
-	void next_game (&Game g) {
-	    ClientRef	winner = ClientRef.none;
-	    void find_winner (&Client c) {
-		if (c.score > 0 &&
-		    (winner == ClientRef.none || c.score >
-		    winner.client.score))
-		    winner = (ClientRef.client) (&c);
-	    }
-	    iterate_client (&g, find_winner, true, false);
-	    if (winner != ClientRef.none)
-		winner.client.games++;
-	    game_send_client_scores (&g, "NOTICE GAMEOVER");
-	    init (&g);
-	}
-	
-	public ClientRef active_client (&Game g) {
-	    return g.active;
-	}
-
-	void assert_bidding (&Game g) {
+	/* remove a client from any game */
+	public void remove_client (&Client c) {
+	    if (c.game == GameRef.none)
+		return;
+	    &Game g = &c.game.game;
+	    Array::remove (&g.clients, &c);
+	    game_send (&g, "NOTICE PART %s\n", c.user.username);
+	    /* correct the state if necessary */
 	    switch (g.state) {
-	    case GameState.New:
-	    case GameState.Bidding:
+	    case GameState.NEW:
 		break;
-	    case GameState.Showing:
-	    case GameState.Solved:
-		raise error (Error.NOTBIDDING);
+	    case GameState.BID:
+		if (!any_bids (&g))
+		    set_state (&g, GameState.NEW);
+		break;
+	    case GameState.SHOW:
+		set_active (&g);
+		break;
+	    case GameState.DONE:
 		break;
-	    }
-	    
-	}
-	
-	public void undo (&Game g, &Client c) {
-	    assert_playing (&g, &c);
-	    assert_active (&g, &c);
-	    if (dim (g.history) > 0)
-	    {
-		undo_move (&g);
-		game_send (&g, "NOTICE UNDO\n");
 	    }
 	}
 
-	public void reset (&Game g, &Client c) {
-	    assert_playing (&g, &c);
-	    assert_active (&g, &c);
-	    reset_move (&g);
-	}
-
-	public void pass (&Game g, &Client c) {
-	    assert_playing (&g, &c);
-	    assert_active (&g, &c);
-	    reset (&g, &c);
+	/* add a client to a game */
+	public &Client add_client (&Game g, &Client c, bool playing) {
+	    remove_client (&c);
+	    c.game = (GameRef.game) (&g);
+	    c.playing = playing;
+	    c.score = 0;
 	    c.bid = Bid.none;
-	    set_active (&g);
+	    c.abandon = false;
+	    Array::append (&g.clients, &c);
+	    game_send (&g, "NOTICE %s %s\n", 
+		       playing ? "JOIN" : "WATCH",
+		       c.user.username);
+	    return &c;
 	}
+
+	/*
+	 * BID state commands
+	 */
 	
 	public void bid (&Game g, &Client c, int number) {
 	    assert_playing (&g, &c);
 	    assert_bidding (&g);
-	    if (g.state == GameState.New)
-		set_state (&g, GameState.Bidding);
+	    if (g.state == GameState.NEW)
+		set_state (&g, GameState.BID);
 	    /*
 	    if (c.bid != Bid.none && c.bid.number <= number)
 		raise error (Error.NOTLOWER);
@@ -437,7 +431,7 @@
 	    c.bid = Bid.none;
 	    game_send (&g, "NOTICE REVOKE %s\n", c.user.username);
 	    if (!any_bids(&g))
-		set_state (&g, GameState.New);
+		set_state (&g, GameState.NEW);
 	}
 
 	public void abandon (&Game g, &Client c) {
@@ -448,17 +442,46 @@
 		game_send (&g, "NOTICE ABANDON %s\n", c.user.username);
 		if (c.bid != Bid.none)
 		    revoke (&g, &c);
+		if (all_abandon (&g))
+		    set_state (&g, GameState.DONE);
 	    }
 	}
 	
-	public int count (&Game g) {
-	    return dim (g.history);
+	/*
+	 * MOVE state commands
+	 */
+	
+	public void undo (&Game g, &Client c) {
+	    assert_playing (&g, &c);
+	    assert_active_or_done (&g, &c);
+	    if (dim (g.history) > 0)
+	    {
+		undo_move (&g);
+		game_send (&g, "NOTICE UNDO\n");
+	    }
 	}
 
-	public void move (&Game g, &Client c, Color color, Direction dir) {
+	public void reset (&Game g, &Client c) {
+	    assert_playing (&g, &c);
+	    assert_active_or_done (&g, &c);
+	    reset_move (&g);
+	}
+
+	public void pass (&Game g, &Client c) {
 	    assert_playing (&g, &c);
 	    assert_active (&g, &c);
-	    if (count (&g) >= c.bid.number)
+	    reset (&g, &c);
+	    c.bid = Bid.none;
+	    set_active (&g);
+	    if (g.active == ClientRef.none)
+		set_state (&g, GameState.DONE);
+	}
+	
+	public void move (&Game g, &Client c, Color color, Direction dir) {
+	    assert_playing (&g, &c);
+	    assert_active_or_done (&g, &c);
+	    if (g.state == GameState.SHOW &&
+		count (&g) >= c.bid.number)
 		raise error (Error.TOOMANYMOVES);
 	    ObjectLoc	src = Boards::find_robot (&g.board, color);
 	    ObjectLoc	dst = Boards::move_robot (&g.board, color, dir);
@@ -467,7 +490,7 @@
 	    Array::push (&g.history, src);
 	    Boards::position_robot (&g.board, color, dst.x, dst.y);
 	    game_send (&g, "NOTICE MOVE %d %C %D\n", count (&g), color, dir);
-	    if (g.state != GameState.Solved && Boards::solved (&g.board))
+	    if (g.state != GameState.DONE && Boards::solved (&g.board))
 	    {
 		if (g.active != ClientRef.none)
 		{
@@ -477,12 +500,18 @@
 			       g.active.client.user.username,
 			       g.active.client.score);
 		}
-		set_state (&g, GameState.Solved);
+		set_state (&g, GameState.DONE);
 	    }
 	}
 
-	public bool solved (&Game g) {
-	    return Boards::solved (&g.board);
+	/*
+	 * DONE state command
+	 */
+	
+	public void turn (&Game g, &Client c) {
+	    assert_playing (&g, &c);
+	    assert_done (&g);
+	    next_target (&g);
 	}
     }
 }

Index: protocol
===================================================================
RCS file: /local/src/CVS/rrserver/protocol,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- protocol	31 May 2003 05:28:14 -0000	1.24
+++ protocol	31 May 2003 16:00:09 -0000	1.25
@@ -128,12 +128,12 @@
 			<bid> indicates the minimum bid
 		show	Bidding closed and solution being demonstrated
 			<active> indicates the person demonstrating
-		solved 	Solution succesfully demonstrated that
-			is less than the active users bid. <active>
-			indicates the winner.
+		done 	Current turn is over.  Either a solution
+                        was demonstrated or the players have all
+			given up trying to find a solution.
 	<time> is valid only in BID state, else it's 0
 	<bid> is valid in all but NEW state where it's 0
-	<active> is valid in SHOW and SOLVED states, else it's ""
+	<active> is valid in SHOW state, else it's ""
 
 	Possible errors: NOGAME
 
@@ -255,16 +255,10 @@
 	    TURN
     
 	    Advance the game to the next turn, (which will have a new
-	    target square). The robots will start in their final positions
-	    at the end of the first successfully demonstrated solution.
-    
-	    TURN succeeds if one of the following is true:
-    
-		+ a solution has been demonstrated
-		+ all players have passed
-		+ all players have abandoned the turn
+	    target square).  TURN is valid only when the game is in
+	    the DONE state
 		    
-	    Possible errors: NOTINGAME, NOTFINISHED
+	    Possible errors: NOTINGAME, NOTDONE
     
 	1.5.1.3. Part
     
@@ -604,16 +598,11 @@
 	    A command was executed by a watching user that is
 	    permitted only to players
 
-	3.6.1.3. Not finished
-    
-	    ERROR NOTFINISHED
-    
-	    TURN was requested and one of:
+	3.6.1.3. Not done
     
-		+ bidding and not all abandoned
-		+ showing and not all passed
+	    ERROR NOTDONE
     
-	    is true
+	    TURN was requested and the game is not in DONE state.
     
     3.6.2. Bidding errors 
     

Index: rr.5c
===================================================================
RCS file: /local/src/CVS/rrserver/rr.5c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- rr.5c	31 May 2003 05:28:14 -0000	1.8
+++ rr.5c	31 May 2003 16:00:09 -0000	1.9
@@ -63,10 +63,10 @@
     } Object;
 
     public typedef enum {
-	New,	    /* no bids yet */
-	Bidding,    /* some bids, timer running */
-	Showing,    /* timer expired, waiting for solution */
-	Solved	    /* game solved */
+	NEW,	    /* no bids yet */
+	BID,	    /* some bids, timer running */
+	SHOW,	    /* timer expired, waiting for solution */
+	DONE	    /* turn done (solved, or bailed) */
     } GameState;
     
     public typedef Object[Width,Height]	Board;
@@ -213,7 +213,7 @@
 	NOTLOWER,
 	NOBID,
 	NOTACTIVE,
-	NOTFINISHED,
+	NOTDONE,
 	NOTNUMBER,
 	BLOCKED,
 	NOTEMPTY,

Index: send.5c
===================================================================
RCS file: /local/src/CVS/rrserver/send.5c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- send.5c	31 May 2003 05:28:14 -0000	1.6
+++ send.5c	31 May 2003 16:00:09 -0000	1.7
@@ -91,10 +91,10 @@
 
 	    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;
+		case GameState.NEW:	File::fprintf (f, "NEW"); break;
+		case GameState.BID:	File::fprintf (f, "BID"); break;
+		case GameState.SHOW:	File::fprintf (f, "SHOW"); break;
+		case GameState.DONE:	File::fprintf (f, "DONE"); break;
 		}
 	    }
 
@@ -108,7 +108,7 @@
 		case Error.NOTLOWER:	File::fprintf (f, "NOTLOWER"); break;
 		case Error.NOBID:	File::fprintf (f, "NOBID"); break;
 		case Error.NOTACTIVE:	File::fprintf (f, "NOTACTIVE"); break;
-		case Error.NOTFINISHED:	File::fprintf (f, "NOTFINISHED"); break;
+		case Error.NOTDONE:	File::fprintf (f, "NOTDONE"); break;
 		case Error.NOTNUMBER:	File::fprintf (f, "NOTNUMBER"); break;
 		case Error.BLOCKED:	File::fprintf (f, "BLOCKED"); break;
 		case Error.COMMAND:	File::fprintf (f, "COMMAND"); break;

Index: server.5c
===================================================================
RCS file: /local/src/CVS/rrserver/server.5c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- server.5c	30 May 2003 22:15:14 -0000	1.8
+++ server.5c	31 May 2003 16:00:09 -0000	1.9
@@ -92,6 +92,11 @@
 	&Client	client;
     } ClientRef;
     
+    public typedef union {
+	void	none;
+	Board	board;
+    } BoardOrNone;
+
     public typedef struct {
 	string		name;
 	GameState	state;
@@ -104,6 +109,7 @@
 	ClientRef	active;
 	ObjectLoc[*]    history;
 	int		timer_serial;
+	BoardOrNone	next_board;
     } Game;
 
     public exception notreached ();




More information about the Commit mailing list