From dfee56609a870b01d3acc33d36f0bd9364a6bd16 Mon Sep 17 00:00:00 2001 From: ehouse Date: Fri, 4 Jan 2008 14:47:52 +0000 Subject: [PATCH] Warn user, and refuse to continue, when new game is as host and has no remote players. API changes, so other platforms won't compile until changed. --- common/nwgamest.c | 45 ++++++++++++++++++++++++++++++++++++++------- common/nwgamest.h | 2 +- common/util.h | 1 + linux/gtknewgame.c | 9 +++++++-- linux/linuxmain.c | 8 ++++++++ 5 files changed, 55 insertions(+), 10 deletions(-) diff --git a/common/nwgamest.c b/common/nwgamest.c index 8be8d6cea..d9852191e 100644 --- a/common/nwgamest.c +++ b/common/nwgamest.c @@ -43,7 +43,7 @@ struct NewGameCtx { XP_TriEnable enabled[NG_NUM_COLS][MAX_NUM_PLAYERS]; XP_U16 nPlayersShown; /* real nPlayers lives in gi */ XP_U16 nPlayersTotal; /* used only until changedNPlayers set */ - XP_U16 nLocalPlayers; + XP_U16 nLocalPlayers; /* not changed except in ngc_load */ DeviceRole role; XP_Bool isNewGame; XP_Bool changedNPlayers; @@ -62,6 +62,7 @@ static void considerEnableJuggle( NewGameCtx* ngc ); static void storePlayer( NewGameCtx* ngc, XP_U16 player, LocalPlayer* lp ); static void loadPlayer( NewGameCtx* ngc, XP_U16 player, const LocalPlayer* lp ); +static XP_Bool checkConsistent( NewGameCtx* ngc, XP_Bool warnUser ); NewGameCtx* newg_make( MPFORMAL XP_Bool isNewGame, @@ -201,19 +202,23 @@ cpToLP( NGValue value, const void* cbClosure ) } } /* cpToLP */ -void -newg_store( NewGameCtx* ngc, CurGameInfo* gi ) +XP_Bool +newg_store( NewGameCtx* ngc, CurGameInfo* gi, XP_Bool warn ) { XP_U16 player; + XP_Bool consistent = checkConsistent( ngc, warn ); - gi->nPlayers = ngc->nPlayersShown; + if ( consistent ) { + gi->nPlayers = ngc->nPlayersShown; #ifndef XWFEATURE_STANDALONE_ONLY - gi->serverRole = ngc->role; + gi->serverRole = ngc->role; #endif - for ( player = 0; player < MAX_NUM_PLAYERS; ++player ) { - storePlayer( ngc, player, &gi->players[player] ); + for ( player = 0; player < MAX_NUM_PLAYERS; ++player ) { + storePlayer( ngc, player, &gi->players[player] ); + } } + return consistent; } /* newg_store */ void @@ -320,6 +325,32 @@ newg_juggle( NewGameCtx* ngc ) return changed; } /* newg_juggle */ +static XP_Bool +checkConsistent( NewGameCtx* ngc, XP_Bool warnUser ) +{ + XP_Bool consistent; + XP_U16 i; + + /* If ISSERVER, make sure there's at least one non-local player. */ + consistent = ngc->role != SERVER_ISSERVER; + for ( i = 0; !consistent && i < ngc->nPlayersShown; ++i ) { + DeepValue dValue; + dValue.col = NG_COL_REMOTE; + (*ngc->getColProc)( ngc->closure, i, NG_COL_REMOTE, + deepCopy, &dValue ); + if ( dValue.value.ng_bool ) { + consistent = XP_TRUE; + } + } + if ( !consistent && warnUser ) { + util_userError( ngc->util, ERR_REG_SERVER_SANS_REMOTE ); + } + + /* Add other consistency checks, and error messages, here. */ + + return consistent; +} /* checkConsistent */ + static void enableOne( NewGameCtx* ngc, XP_U16 player, NewGameColumn col, XP_TriEnable enable, XP_Bool force ) diff --git a/common/nwgamest.h b/common/nwgamest.h index dd3491df0..afd7d1959 100644 --- a/common/nwgamest.h +++ b/common/nwgamest.h @@ -98,7 +98,7 @@ NewGameCtx* newg_make( MPFORMAL XP_Bool isNewGame, void newg_destroy( NewGameCtx* ngc ); void newg_load( NewGameCtx* ngc, const CurGameInfo* gi ); -void newg_store( NewGameCtx* ngc, CurGameInfo* gi ); +XP_Bool newg_store( NewGameCtx* ngc, CurGameInfo* gi, XP_Bool warn ); void newg_colChanged( NewGameCtx* ngc, XP_U16 player ); void newg_attrChanged( NewGameCtx* ngc, NewGameAttr attr, diff --git a/common/util.h b/common/util.h index a345d0e39..8df3dc4bd 100644 --- a/common/util.h +++ b/common/util.h @@ -48,6 +48,7 @@ typedef enum { ERR_NO_PEEK_REMOTE_TILES, ERR_REG_UNEXPECTED_USER, /* server asked to register too many remote users */ + ERR_REG_SERVER_SANS_REMOTE, #endif ERR_CANT_TRADE_MID_MOVE, /* ERR_CANT_ENGINE_MID_MOVE, */ diff --git a/linux/gtknewgame.c b/linux/gtknewgame.c index 20487ea87..d85daadc9 100644 --- a/linux/gtknewgame.c +++ b/linux/gtknewgame.c @@ -498,8 +498,13 @@ newGameDialog( GtkAppGlobals* globals, XP_Bool isNewGame ) gtk_main(); if ( !state.cancelled && !state.revert ) { - newg_store( state.newGameCtxt, &globals->cGlobals.params->gi ); - globals->cGlobals.params->gi.boardSize = state.nCols; + if ( newg_store( state.newGameCtxt, &globals->cGlobals.params->gi, + XP_TRUE ) ) { + globals->cGlobals.params->gi.boardSize = state.nCols; + } else { + /* Do it again if we warned user of inconsistency. */ + state.revert = XP_TRUE; + } } gtk_widget_destroy( dialog ); diff --git a/linux/linuxmain.c b/linux/linuxmain.c index ccad669c9..297b498a6 100644 --- a/linux/linuxmain.c +++ b/linux/linuxmain.c @@ -166,6 +166,8 @@ linux_getErrString( UtilErrID id, XP_Bool* silent ) case ERR_NO_PEEK_ROBOT_TILES: message = "No peeking at the robot's tiles!"; break; + +#ifndef XWFEATURE_STANDALONE_ONLY case ERR_NO_PEEK_REMOTE_TILES: message = "No peeking at remote players' tiles!"; break; @@ -176,6 +178,12 @@ linux_getErrString( UtilErrID id, XP_Bool* silent ) message = "Conflict between Host and Guest dictionaries; Host wins."; XP_WARNF( "GTK may have problems here." ); break; + case ERR_REG_SERVER_SANS_REMOTE: + message = "At least one player must be marked remote for a game " + "started as Host."; + break; +#endif + case ERR_CANT_UNDO_TILEASSIGN: message = "Tile assignment can't be undone."; break;