fix assert with reporting no bad words

Several changes toward not allowing bad things to happen
while waiting for a confirmation from the host
This commit is contained in:
Eric House 2020-04-21 14:44:02 -07:00
parent 0dc39b5d85
commit 29dbeebc94
4 changed files with 31 additions and 29 deletions

View file

@ -536,6 +536,7 @@ gi_copy( MPFORMAL CurGameInfo* destGI, const CurGameInfo* srcGI )
void void
gi_setNPlayers( CurGameInfo* gi, XP_U16 nTotal, XP_U16 nHere ) gi_setNPlayers( CurGameInfo* gi, XP_U16 nTotal, XP_U16 nHere )
{ {
LOGGI( gi, "before" );
XP_ASSERT( nTotal <= MAX_NUM_PLAYERS ); XP_ASSERT( nTotal <= MAX_NUM_PLAYERS );
XP_ASSERT( nHere < nTotal ); XP_ASSERT( nHere < nTotal );
@ -564,7 +565,7 @@ gi_setNPlayers( CurGameInfo* gi, XP_U16 nTotal, XP_U16 nHere )
} }
} }
} }
LOGGI( gi, __func__ ); LOGGI( gi, "after" );
} }
XP_U16 XP_U16

View file

@ -123,9 +123,7 @@ struct ServerCtxt {
PoolContext* pool; PoolContext* pool;
BadWordInfo illegalWordInfo; BadWordInfo illegalWordInfo;
#ifndef XWFEATURE_STANDALONE_ONLY
XP_U16 lastMoveSource; XP_U16 lastMoveSource;
#endif
ServerPlayer players[MAX_NUM_PLAYERS]; ServerPlayer players[MAX_NUM_PLAYERS];
XP_Bool serverDoing; XP_Bool serverDoing;
@ -159,8 +157,7 @@ static void nextTurn( ServerCtxt* server, XP_S16 nxtTurn );
static void doEndGame( ServerCtxt* server, XP_S16 quitter ); static void doEndGame( ServerCtxt* server, XP_S16 quitter );
static void endGameInternal( ServerCtxt* server, GameEndReason why, XP_S16 quitter ); static void endGameInternal( ServerCtxt* server, GameEndReason why, XP_S16 quitter );
static void badWordMoveUndoAndTellUser( ServerCtxt* server, static void badWordMoveUndoAndTellUser( ServerCtxt* server, BadWordInfo* bwi );
BadWordInfo* bwi );
static XP_Bool tileCountsOk( const ServerCtxt* server ); static XP_Bool tileCountsOk( const ServerCtxt* server );
static void setTurn( ServerCtxt* server, XP_S16 turn ); static void setTurn( ServerCtxt* server, XP_S16 turn );
static XWStreamCtxt* mkServerStream( ServerCtxt* server ); static XWStreamCtxt* mkServerStream( ServerCtxt* server );
@ -203,6 +200,7 @@ static void writeProto( const ServerCtxt* server, XWStreamCtxt* stream,
#endif #endif
#define PICK_NEXT -1 #define PICK_NEXT -1
#define PICK_CUR -2
#if defined DEBUG && ! defined XWFEATURE_STANDALONE_ONLY #if defined DEBUG && ! defined XWFEATURE_STANDALONE_ONLY
static char* static char*
@ -227,8 +225,7 @@ getStateStr( XW_State st )
} }
#endif #endif
#if 0 #ifdef DEBUG
//def DEBUG
static void static void
logNewState( XW_State old, XW_State newst, const char* caller ) logNewState( XW_State old, XW_State newst, const char* caller )
{ {
@ -238,10 +235,10 @@ logNewState( XW_State old, XW_State newst, const char* caller )
XP_LOGFF( "state transition %s => %s (from %s())", oldStr, newStr, caller ); XP_LOGFF( "state transition %s => %s (from %s())", oldStr, newStr, caller );
} }
} }
# define SETSTATE( s, st ) { \ # define SETSTATE( server, st ) { \
XW_State old = (s)->nv.gameState; \ XW_State old = (server)->nv.gameState; \
(s)->nv.gameState = (st); \ (server)->nv.gameState = (st); \
logNewState( old, st, __func__); \ logNewState( old, st, __func__); \
} }
#else #else
# define SETSTATE( s, st ) (s)->nv.gameState = (st) # define SETSTATE( s, st ) (s)->nv.gameState = (st)
@ -405,6 +402,7 @@ putNV( XWStreamCtxt* stream, const ServerNonvolatiles* nv, XP_U16 nPlayers )
stream_putBits( stream, XWSTATE_NBITS, nv->stateAfterShow ); stream_putBits( stream, XWSTATE_NBITS, nv->stateAfterShow );
/* +1: make -1 (NOTURN) into a positive number */ /* +1: make -1 (NOTURN) into a positive number */
XP_ASSERT( -1 <= nv->currentTurn && nv->currentTurn < MAX_NUM_PLAYERS );
stream_putBits( stream, NPLAYERS_NBITS, nv->currentTurn+1 ); stream_putBits( stream, NPLAYERS_NBITS, nv->currentTurn+1 );
stream_putBits( stream, NPLAYERS_NBITS, nv->quitter+1 ); stream_putBits( stream, NPLAYERS_NBITS, nv->quitter+1 );
stream_putBits( stream, NPLAYERS_NBITS, nv->pendingRegistrations ); stream_putBits( stream, NPLAYERS_NBITS, nv->pendingRegistrations );
@ -546,11 +544,7 @@ server_writeToStream( const ServerCtxt* server, XWStreamCtxt* stream )
} }
} }
#ifndef XWFEATURE_STANDALONE_ONLY
stream_putBits( stream, 2, server->lastMoveSource ); stream_putBits( stream, 2, server->lastMoveSource );
#else
stream_putBits( stream, 2, 0 );
#endif
writeStreamIf( stream, server->nv.prevMoveStream ); writeStreamIf( stream, server->nv.prevMoveStream );
writeStreamIf( stream, server->nv.prevWordsStream ); writeStreamIf( stream, server->nv.prevWordsStream );
@ -2057,14 +2051,14 @@ static void
bwiFromStream( MPFORMAL XWStreamCtxt* stream, BadWordInfo* bwi ) bwiFromStream( MPFORMAL XWStreamCtxt* stream, BadWordInfo* bwi )
{ {
XP_U16 nWords = stream_getBits( stream, 4 ); XP_U16 nWords = stream_getBits( stream, 4 );
const XP_UCHAR** sp = bwi->words;
bwi->nWords = nWords; bwi->nWords = nWords;
bwi->dictName = ( STREAM_VERS_DICTNAME <= stream_getVersion( stream ) ) bwi->dictName = ( STREAM_VERS_DICTNAME <= stream_getVersion( stream ) )
? stringFromStream( mpool, stream ) : NULL; ? stringFromStream( mpool, stream ) : NULL;
for ( sp = bwi->words; nWords; ++sp, --nWords ) { for ( int ii = 0; ii < nWords; ++ii ) {
*sp = (const XP_UCHAR*)stringFromStream( mpool, stream ); bwi->words[ii] = (const XP_UCHAR*)stringFromStream( mpool, stream );
} }
bwi->words[nWords] = NULL;
} /* bwiFromStream */ } /* bwiFromStream */
#ifdef DEBUG #ifdef DEBUG
@ -2129,6 +2123,10 @@ sendBadWordMsgs( ServerCtxt* server )
bwiToStream( stream, &server->illegalWordInfo ); bwiToStream( stream, &server->illegalWordInfo );
/* XP_U32 hash = model_getHash( server->vol.model ); */
/* stream_putU32( stream, hash ); */
/* XP_LOGFF( "wrote hash: %X", hash ); */
stream_destroy( stream ); stream_destroy( stream );
freeBWI( MPPARM(server->mpool) &server->illegalWordInfo ); freeBWI( MPPARM(server->mpool) &server->illegalWordInfo );
@ -2521,11 +2519,12 @@ nextTurn( ServerCtxt* server, XP_S16 nxtTurn )
{ {
XP_LOGFF( "(nxtTurn=%d)", nxtTurn ); XP_LOGFF( "(nxtTurn=%d)", nxtTurn );
CurGameInfo* gi = server->vol.gi; CurGameInfo* gi = server->vol.gi;
XP_Bool playerTilesLeft = XP_FALSE;
XP_S16 currentTurn = server->nv.currentTurn; XP_S16 currentTurn = server->nv.currentTurn;
XP_Bool moreToDo = XP_FALSE; XP_Bool moreToDo = XP_FALSE;
if ( nxtTurn == PICK_NEXT ) { if ( nxtTurn == PICK_CUR ) {
nxtTurn = model_getNextTurn( server->vol.model );
} else if ( nxtTurn == PICK_NEXT ) {
XP_ASSERT( server->nv.gameState == XWSTATE_INTURN ); XP_ASSERT( server->nv.gameState == XWSTATE_INTURN );
if ( server->nv.gameState != XWSTATE_INTURN ) { if ( server->nv.gameState != XWSTATE_INTURN ) {
XP_LOGFF( "doing nothing; state %s != XWSTATE_INTURN", XP_LOGFF( "doing nothing; state %s != XWSTATE_INTURN",
@ -2533,7 +2532,6 @@ nextTurn( ServerCtxt* server, XP_S16 nxtTurn )
XP_ASSERT( !moreToDo ); XP_ASSERT( !moreToDo );
goto exit; goto exit;
} else if ( currentTurn >= 0 ) { } else if ( currentTurn >= 0 ) {
playerTilesLeft = tileCountsOk( server );
if ( inDuplicateMode(server) ) { if ( inDuplicateMode(server) ) {
nxtTurn = dupe_nextTurn( server ); nxtTurn = dupe_nextTurn( server );
} else { } else {
@ -2546,9 +2544,9 @@ nextTurn( ServerCtxt* server, XP_S16 nxtTurn )
/* We're doing an undo, and so won't bother figuring out who the /* We're doing an undo, and so won't bother figuring out who the
previous turn was or how many tiles he had: it's a sure thing he previous turn was or how many tiles he had: it's a sure thing he
"has" enough to be allowed to take the turn just undone. */ "has" enough to be allowed to take the turn just undone. */
playerTilesLeft = XP_TRUE;
XP_ASSERT( nxtTurn == model_getNextTurn( server->vol.model ) ); XP_ASSERT( nxtTurn == model_getNextTurn( server->vol.model ) );
} }
XP_Bool playerTilesLeft = tileCountsOk( server );
SETSTATE( server, XWSTATE_INTURN ); /* even if game over, if undoing */ SETSTATE( server, XWSTATE_INTURN ); /* even if game over, if undoing */
if ( playerTilesLeft && NPASSES_OK(server) ){ if ( playerTilesLeft && NPASSES_OK(server) ){
@ -3835,6 +3833,9 @@ setTurn( ServerCtxt* server, XP_S16 turn )
if ( inDupMode || server->nv.currentTurn != turn || 1 == server->vol.gi->nPlayers ) { if ( inDupMode || server->nv.currentTurn != turn || 1 == server->vol.gi->nPlayers ) {
if ( DUP_PLAYER == turn && inDupMode ) { if ( DUP_PLAYER == turn && inDupMode ) {
turn = dupe_nextTurn( server ); turn = dupe_nextTurn( server );
} else if ( PICK_CUR == turn ) {
XP_ASSERT( !inDupMode );
turn = model_getNextTurn( server->vol.model );
} else if ( 0 <= turn && !inDupMode ) { } else if ( 0 <= turn && !inDupMode ) {
XP_ASSERT( turn == model_getNextTurn( server->vol.model ) ); XP_ASSERT( turn == model_getNextTurn( server->vol.model ) );
} }
@ -3851,6 +3852,7 @@ tellMoveWasLegal( ServerCtxt* server )
XWStreamCtxt* stream = XWStreamCtxt* stream =
messageStreamWithHeader( server, server->lastMoveSource, messageStreamWithHeader( server, server->lastMoveSource,
XWPROTO_MOVE_CONFIRM ); XWPROTO_MOVE_CONFIRM );
stream_destroy( stream ); stream_destroy( stream );
SETSTATE( server, XWSTATE_INTURN ); SETSTATE( server, XWSTATE_INTURN );
@ -3880,8 +3882,7 @@ handleMoveOk( ServerCtxt* server, XWStreamCtxt* XP_UNUSED(incoming) )
XP_ASSERT( server->nv.gameState == XWSTATE_MOVE_CONFIRM_WAIT ); XP_ASSERT( server->nv.gameState == XWSTATE_MOVE_CONFIRM_WAIT );
SETSTATE( server, XWSTATE_INTURN ); SETSTATE( server, XWSTATE_INTURN );
setTurn( server, 0 ); nextTurn( server, PICK_CUR );
nextTurn( server, PICK_NEXT );
return accepted; return accepted;
} /* handleMoveOk */ } /* handleMoveOk */
@ -4129,8 +4130,7 @@ server_receiveMessage( ServerCtxt* server, XWStreamCtxt* incoming )
case XWPROTO_BADWORD_INFO: case XWPROTO_BADWORD_INFO:
accepted = handleIllegalWord( server, incoming ); accepted = handleIllegalWord( server, incoming );
if ( accepted && server->nv.gameState != XWSTATE_GAMEOVER ) { if ( accepted && server->nv.gameState != XWSTATE_GAMEOVER ) {
setTurn( server, 0 ); nextTurn( server, PICK_CUR );
nextTurn( server, PICK_NEXT );
} }
break; break;

View file

@ -71,10 +71,11 @@ typedef struct PickInfo {
XP_U16 thisPick; /* <= nTotal */ XP_U16 thisPick; /* <= nTotal */
} PickInfo; } PickInfo;
typedef struct BadWordInfo { typedef struct _BadWordInfo {
XP_U16 nWords; XP_U16 nWords;
const XP_UCHAR* dictName; const XP_UCHAR* dictName;
const XP_UCHAR* words[MAX_TRAY_TILES+1]; /* can form in both directions */ /* Null-terminated array of ptrs */
const XP_UCHAR* words[MAX_TRAY_TILES+2]; /* can form in both directions */
} BadWordInfo; } BadWordInfo;
/* XWTimerProc returns true if redraw was necessitated by what the proc did */ /* XWTimerProc returns true if redraw was necessitated by what the proc did */

View file

@ -1870,7 +1870,7 @@ gtk_util_notifyIllegalWords( XW_UtilCtxt* uc, BadWordInfo* bwi, XP_U16 player,
XP_UCHAR* name = cGlobals->gi->players[player].name; XP_UCHAR* name = cGlobals->gi->players[player].name;
XP_ASSERT( !!name ); XP_ASSERT( !!name );
sprintf( buf, "Player %d (%s) played illegal word[s] %s; loses turn.", sprintf( buf, "Player %d (%s) played illegal word[s] \"%s\"; loses turn.",
player+1, name, strs ); player+1, name, strs );
if ( cGlobals->params->skipWarnings ) { if ( cGlobals->params->skipWarnings ) {