[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
- Previous message: [Commit] fontconfig/fc-list fc-list.1,NONE,1.1 Makefile.am,1.3,1.4
fc-list.c,1.7,1.8 fc-list.man,1.2,NONE
- Next message: [Commit] rrserver dispatch.5c,1.17,1.18 games.5c,1.15,1.16
protocol,1.25,1.26 readreq.5c,1.8,1.9 rr.5c,1.9,1.10
server.5c,1.9,1.10
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
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 ();
- Previous message: [Commit] fontconfig/fc-list fc-list.1,NONE,1.1 Makefile.am,1.3,1.4
fc-list.c,1.7,1.8 fc-list.man,1.2,NONE
- Next message: [Commit] rrserver dispatch.5c,1.17,1.18 games.5c,1.15,1.16
protocol,1.25,1.26 readreq.5c,1.8,1.9 rr.5c,1.9,1.10
server.5c,1.9,1.10
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the Commit
mailing list