mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-26 07:58:52 +01:00
add server_listWordsPlayed, and implement via function in model.c that
uses existing stack and undo features to run a WordNotifierInfo over some number of scoring passes to gather the words seen. Seems to work as tested from gtk version. Now need to try from android....
This commit is contained in:
parent
63893b8a0d
commit
9eacdb3856
9 changed files with 131 additions and 38 deletions
|
@ -64,12 +64,12 @@ static void makeTileTrade( ModelCtxt* model, XP_S16 player,
|
|||
TrayTileSet* oldTiles, TrayTileSet* newTiles );
|
||||
static XP_S16 commitTurn( ModelCtxt* model, XP_S16 turn,
|
||||
TrayTileSet* newTiles, XWStreamCtxt* stream,
|
||||
XP_Bool useStack );
|
||||
WordNotifierInfo* wni, XP_Bool useStack );
|
||||
static void buildModelFromStack( ModelCtxt* model, StackCtxt* stack,
|
||||
XWStreamCtxt* stream,
|
||||
XP_Bool useStack, XP_U16 initial,
|
||||
XWStreamCtxt* stream, WordNotifierInfo* wni,
|
||||
MovePrintFuncPre mpfpr,
|
||||
MovePrintFuncPost mpfpo,
|
||||
void* closure );
|
||||
MovePrintFuncPost mpfpo, void* closure );
|
||||
static void setPendingCounts( ModelCtxt* model, XP_S16 turn );
|
||||
static void loadPlayerCtxt( XWStreamCtxt* stream, XP_U16 version,
|
||||
PlayerCtxt* pc );
|
||||
|
@ -135,9 +135,9 @@ model_makeFromStream( MPFORMAL XWStreamCtxt* stream, DictionaryCtxt* dict,
|
|||
|
||||
stack_loadFromStream( model->vol.stack, stream );
|
||||
|
||||
buildModelFromStack( model, model->vol.stack, (XWStreamCtxt*)NULL,
|
||||
(MovePrintFuncPre)NULL,
|
||||
(MovePrintFuncPost)NULL, NULL );
|
||||
buildModelFromStack( model, model->vol.stack, XP_FALSE, 0,
|
||||
(XWStreamCtxt*)NULL, (WordNotifierInfo*)NULL,
|
||||
(MovePrintFuncPre)NULL, (MovePrintFuncPost)NULL, NULL );
|
||||
|
||||
for ( i = 0; i < model->nPlayers; ++i ) {
|
||||
loadPlayerCtxt( stream, version, &model->players[i] );
|
||||
|
@ -244,19 +244,19 @@ model_destroy( ModelCtxt* model )
|
|||
} /* model_destroy */
|
||||
|
||||
static void
|
||||
buildModelFromStack( ModelCtxt* model, StackCtxt* stack,
|
||||
XWStreamCtxt* stream,
|
||||
MovePrintFuncPre mpf_pre, MovePrintFuncPost mpf_post,
|
||||
void* closure )
|
||||
buildModelFromStack( ModelCtxt* model, StackCtxt* stack, XP_Bool useStack,
|
||||
XP_U16 initial, XWStreamCtxt* stream,
|
||||
WordNotifierInfo* wni, MovePrintFuncPre mpf_pre,
|
||||
MovePrintFuncPost mpf_post, void* closure )
|
||||
{
|
||||
StackEntry entry;
|
||||
XP_U16 i;
|
||||
XP_U16 ii;
|
||||
XP_S16 moveScore = 0; /* keep compiler happy */
|
||||
|
||||
for ( i = 0; stack_getNthEntry( stack, i, &entry ); ++i ) {
|
||||
for ( ii = initial; stack_getNthEntry( stack, ii, &entry ); ++ii ) {
|
||||
|
||||
if ( !!mpf_pre ) {
|
||||
(*mpf_pre)( model, i, &entry, closure );
|
||||
(*mpf_pre)( model, ii, &entry, closure );
|
||||
}
|
||||
|
||||
switch ( entry.moveType ) {
|
||||
|
@ -265,7 +265,8 @@ buildModelFromStack( ModelCtxt* model, StackCtxt* stack,
|
|||
model_makeTurnFromMoveInfo( model, entry.playerNum,
|
||||
&entry.u.move.moveInfo);
|
||||
moveScore = commitTurn( model, entry.playerNum,
|
||||
&entry.u.move.newTiles, stream, XP_FALSE);
|
||||
&entry.u.move.newTiles,
|
||||
stream, wni, useStack );
|
||||
break;
|
||||
case TRADE_TYPE:
|
||||
makeTileTrade( model, entry.playerNum, &entry.u.trade.oldTiles,
|
||||
|
@ -280,7 +281,7 @@ buildModelFromStack( ModelCtxt* model, StackCtxt* stack,
|
|||
&entry.u.phony.moveInfo);
|
||||
/* do something here to cause it to print */
|
||||
(void)getCurrentMoveScoreIfLegal( model, entry.playerNum, stream,
|
||||
&moveScore );
|
||||
wni, &moveScore );
|
||||
moveScore = 0;
|
||||
model_resetCurrentTurn( model, entry.playerNum );
|
||||
|
||||
|
@ -290,7 +291,7 @@ buildModelFromStack( ModelCtxt* model, StackCtxt* stack,
|
|||
}
|
||||
|
||||
if ( !!mpf_post ) {
|
||||
(*mpf_post)( model, i, &entry, moveScore, closure );
|
||||
(*mpf_post)( model, ii, &entry, moveScore, closure );
|
||||
}
|
||||
}
|
||||
} /* buildModelFromStack */
|
||||
|
@ -668,10 +669,10 @@ model_undoLatestMoves( ModelCtxt* model, PoolContext* pool,
|
|||
XP_U16 turn = 0;
|
||||
Tile blankTile = dict_getBlankTile( model_getDictionary(model) );
|
||||
XP_Bool success = XP_TRUE;
|
||||
XP_S16 moveSought = *moveNumP;
|
||||
XP_S16 moveSought = !!moveNumP ? *moveNumP : -1;
|
||||
XP_U16 nMovesUndone;
|
||||
XP_U16 nStackEntries;
|
||||
|
||||
|
||||
nStackEntries = stack_getNEntries( stack );
|
||||
if ( nStackEntries < nMovesSought ) {
|
||||
return XP_FALSE;
|
||||
|
@ -772,10 +773,16 @@ model_undoLatestMoves( ModelCtxt* model, PoolContext* pool,
|
|||
}
|
||||
|
||||
if ( success ) {
|
||||
*turnP = turn;
|
||||
*moveNumP = entry.moveNum;
|
||||
if ( !!turnP ) {
|
||||
*turnP = turn;
|
||||
}
|
||||
if ( !!moveNumP ) {
|
||||
*moveNumP = entry.moveNum;
|
||||
}
|
||||
} else {
|
||||
while ( nMovesUndone-- ) {
|
||||
/* undo isn't enough here: pool's got tiles in it!! */
|
||||
XP_ASSERT( 0 );
|
||||
stack_redo( stack );
|
||||
}
|
||||
}
|
||||
|
@ -873,11 +880,11 @@ model_makeTurnFromStream( ModelCtxt* model, XP_U16 playerNum,
|
|||
|
||||
void
|
||||
model_makeTurnFromMoveInfo( ModelCtxt* model, XP_U16 playerNum,
|
||||
MoveInfo* newMove )
|
||||
const MoveInfo* newMove )
|
||||
{
|
||||
XP_U16 col, row, i;
|
||||
XP_U16* other;
|
||||
MoveInfoTile* tinfo;
|
||||
const MoveInfoTile* tinfo;
|
||||
Tile blank;
|
||||
XP_U16 numTiles;
|
||||
|
||||
|
@ -1389,7 +1396,7 @@ putBackOtherPlayersTiles( ModelCtxt* model, XP_U16 notMyTurn,
|
|||
*/
|
||||
static XP_S16
|
||||
commitTurn( ModelCtxt* model, XP_S16 turn, TrayTileSet* newTiles,
|
||||
XWStreamCtxt* stream, XP_Bool useStack )
|
||||
XWStreamCtxt* stream, WordNotifierInfo* wni, XP_Bool useStack )
|
||||
{
|
||||
XP_U16 ii;
|
||||
PlayerCtxt* player;
|
||||
|
@ -1403,7 +1410,7 @@ commitTurn( ModelCtxt* model, XP_S16 turn, TrayTileSet* newTiles,
|
|||
|
||||
#ifdef DEBUG
|
||||
XP_ASSERT( getCurrentMoveScoreIfLegal( model, turn, (XWStreamCtxt*)NULL,
|
||||
&score ) );
|
||||
(WordNotifierInfo*)NULL, &score ) );
|
||||
invalidateScore( model, turn );
|
||||
#endif
|
||||
|
||||
|
@ -1450,7 +1457,7 @@ commitTurn( ModelCtxt* model, XP_S16 turn, TrayTileSet* newTiles,
|
|||
++model->vol.nTilesOnBoard;
|
||||
}
|
||||
|
||||
(void)getCurrentMoveScoreIfLegal( model, turn, stream, &score );
|
||||
(void)getCurrentMoveScoreIfLegal( model, turn, stream, wni, &score );
|
||||
XP_ASSERT( score >= 0 );
|
||||
player->score += score;
|
||||
|
||||
|
@ -1473,7 +1480,8 @@ commitTurn( ModelCtxt* model, XP_S16 turn, TrayTileSet* newTiles,
|
|||
void
|
||||
model_commitTurn( ModelCtxt* model, XP_S16 turn, TrayTileSet* newTiles )
|
||||
{
|
||||
(void)commitTurn( model, turn, newTiles, (XWStreamCtxt*)NULL, XP_TRUE );
|
||||
(void)commitTurn( model, turn, newTiles, (XWStreamCtxt*)NULL,
|
||||
(WordNotifierInfo*)NULL, XP_TRUE );
|
||||
} /* model_commitTurn */
|
||||
|
||||
/* Given a rack of new tiles and of old, remove all the old from the tray and
|
||||
|
@ -1904,8 +1912,8 @@ makeTmpModel( ModelCtxt* model, XWStreamCtxt* stream,
|
|||
model_numRows(model));
|
||||
model_setNPlayers( tmpModel, model->nPlayers );
|
||||
|
||||
buildModelFromStack( tmpModel, model->vol.stack, stream,
|
||||
mpf_pre, mpf_post, closure );
|
||||
buildModelFromStack( tmpModel, model->vol.stack, XP_FALSE, 0, stream,
|
||||
(WordNotifierInfo*)NULL, mpf_pre, mpf_post, closure );
|
||||
|
||||
return tmpModel;
|
||||
} /* makeTmpModel */
|
||||
|
@ -2025,6 +2033,50 @@ model_recentPassCountOk( ModelCtxt* model )
|
|||
return count < okCount;
|
||||
}
|
||||
|
||||
static XP_Bool
|
||||
recordWord( const XP_UCHAR* word, XP_Bool isLegal, void* closure )
|
||||
{
|
||||
XWStreamCtxt* stream = (XWStreamCtxt*)closure;
|
||||
XP_ASSERT( isLegal );
|
||||
XP_LOGF( "%s(%s)", __func__, word );
|
||||
stream_catString( stream, word );
|
||||
stream_putU8( stream, '\n' );
|
||||
return XP_TRUE;
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
model_getWordsPlayed( ModelCtxt* model, PoolContext* pool,
|
||||
XP_U16 nTurns, XWStreamCtxt* stream )
|
||||
{
|
||||
XP_ASSERT( !!stream );
|
||||
StackCtxt* stack = model->vol.stack;
|
||||
StackCtxt* tmpStack = stack_copy( stack );
|
||||
|
||||
XP_U16 nPlayers = model->nPlayers;
|
||||
XP_U16 nEntries = stack_getNEntries( stack );
|
||||
nEntries -= nPlayers; /* skip assignments */
|
||||
if ( nTurns > nEntries ) {
|
||||
nTurns = nEntries;
|
||||
}
|
||||
|
||||
if ( model_undoLatestMoves( model, pool, nTurns, NULL, NULL ) ) {
|
||||
WordNotifierInfo notifyInfo = { .proc = recordWord,
|
||||
.closure = stream,
|
||||
};
|
||||
|
||||
/* Now push the undone moves back into the model one at a time.
|
||||
recordWord() will add each played word to the stream as it's
|
||||
scored */
|
||||
buildModelFromStack( model, tmpStack, XP_TRUE,
|
||||
nEntries - nTurns + nPlayers,/* skip assignments */
|
||||
(XWStreamCtxt*)NULL, ¬ifyInfo,
|
||||
(MovePrintFuncPre)NULL, (MovePrintFuncPost)NULL,
|
||||
NULL );
|
||||
}
|
||||
stack_destroy( tmpStack );
|
||||
return XP_TRUE;
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
model_getPlayersLastScore( ModelCtxt* model, XP_S16 player,
|
||||
XP_UCHAR* expl, XP_U16* explLen )
|
||||
|
|
|
@ -197,7 +197,7 @@ void model_currentMoveToStream( ModelCtxt* model, XP_S16 turn,
|
|||
void model_makeTurnFromStream( ModelCtxt* model, XP_U16 playerNum,
|
||||
XWStreamCtxt* stream );
|
||||
void model_makeTurnFromMoveInfo( ModelCtxt* model, XP_U16 playerNum,
|
||||
MoveInfo* newMove );
|
||||
const MoveInfo* newMove );
|
||||
|
||||
void model_resetCurrentTurn( ModelCtxt* model, XP_S16 turn );
|
||||
XP_S16 model_getNMoves( const ModelCtxt* model );
|
||||
|
@ -246,11 +246,14 @@ typedef struct WordNotifierInfo {
|
|||
} WordNotifierInfo;
|
||||
|
||||
XP_Bool getCurrentMoveScoreIfLegal( ModelCtxt* model, XP_S16 turn,
|
||||
XWStreamCtxt* stream, XP_S16* score );
|
||||
XWStreamCtxt* stream,
|
||||
WordNotifierInfo* wni, XP_S16* score );
|
||||
XP_S16 model_getPlayerScore( ModelCtxt* model, XP_S16 player );
|
||||
|
||||
XP_Bool model_getPlayersLastScore( ModelCtxt* model, XP_S16 player,
|
||||
XP_UCHAR* expl, XP_U16* explLen );
|
||||
XP_Bool model_getWordsPlayed( ModelCtxt* model, PoolContext* pool,
|
||||
XP_U16 nTurns, XWStreamCtxt* stream );
|
||||
|
||||
/* Have there been too many passes (so game should end)? */
|
||||
XP_Bool model_recentPassCountOk( ModelCtxt* model );
|
||||
|
|
|
@ -108,7 +108,7 @@ stack_loadFromStream( StackCtxt* stack, XWStreamCtxt* stream )
|
|||
} /* stack_makeFromStream */
|
||||
|
||||
void
|
||||
stack_writeToStream( StackCtxt* stack, XWStreamCtxt* stream )
|
||||
stack_writeToStream( const StackCtxt* stack, XWStreamCtxt* stream )
|
||||
{
|
||||
XP_U16 nBytes;
|
||||
XWStreamCtxt* data = stack->data;
|
||||
|
@ -138,6 +138,21 @@ stack_writeToStream( StackCtxt* stack, XWStreamCtxt* stream )
|
|||
}
|
||||
} /* stack_writeToStream */
|
||||
|
||||
StackCtxt*
|
||||
stack_copy( const StackCtxt* stack )
|
||||
{
|
||||
StackCtxt* newStack = NULL;
|
||||
XWStreamCtxt* stream = mem_stream_make( MPPARM(stack->mpool)
|
||||
stack->vtmgr, NULL, 0, NULL );
|
||||
stack_writeToStream( stack, stream );
|
||||
|
||||
newStack = stack_make( MPPARM(stack->mpool) stack->vtmgr );
|
||||
stack_loadFromStream( newStack, stream );
|
||||
stack_setBitsPerTile( newStack, stack->bitsPerTile );
|
||||
stream_destroy( stream );
|
||||
return newStack;
|
||||
}
|
||||
|
||||
static void
|
||||
pushEntry( StackCtxt* stack, const StackEntry* entry )
|
||||
{
|
||||
|
|
|
@ -72,7 +72,8 @@ void stack_init( StackCtxt* stack );
|
|||
void stack_setBitsPerTile( StackCtxt* stack, XP_U16 bitsPerTile );
|
||||
|
||||
void stack_loadFromStream( StackCtxt* stack, XWStreamCtxt* stream );
|
||||
void stack_writeToStream( StackCtxt* stack, XWStreamCtxt* stream );
|
||||
void stack_writeToStream( const StackCtxt* stack, XWStreamCtxt* stream );
|
||||
StackCtxt* stack_copy( const StackCtxt* stack );
|
||||
|
||||
void stack_addMove( StackCtxt* stack, XP_U16 turn, MoveInfo* moveInfo,
|
||||
TrayTileSet* newTiles );
|
||||
|
|
|
@ -75,7 +75,8 @@ static void formatSummary( XWStreamCtxt* stream, const ModelCtxt* model,
|
|||
* invalidate the score.
|
||||
*/
|
||||
static void
|
||||
scoreCurrentMove( ModelCtxt* model, XP_S16 turn, XWStreamCtxt* stream )
|
||||
scoreCurrentMove( ModelCtxt* model, XP_S16 turn, XWStreamCtxt* stream,
|
||||
WordNotifierInfo* notifyInfo )
|
||||
{
|
||||
PlayerCtxt* player = &model->players[turn];
|
||||
XP_S16 score;
|
||||
|
@ -84,7 +85,7 @@ scoreCurrentMove( ModelCtxt* model, XP_S16 turn, XWStreamCtxt* stream )
|
|||
|
||||
/* recalc goes here */
|
||||
score = checkScoreMove( model, turn, (EngineCtxt*)NULL, stream,
|
||||
XP_TRUE, (WordNotifierInfo*)NULL );
|
||||
XP_TRUE, notifyInfo );
|
||||
XP_ASSERT( score >= 0 || score == ILLEGAL_MOVE_SCORE );
|
||||
|
||||
player->curMoveScore = score;
|
||||
|
@ -127,11 +128,12 @@ invalidateScore( ModelCtxt* model, XP_S16 turn )
|
|||
|
||||
XP_Bool
|
||||
getCurrentMoveScoreIfLegal( ModelCtxt* model, XP_S16 turn,
|
||||
XWStreamCtxt* stream, XP_S16* score )
|
||||
XWStreamCtxt* stream,
|
||||
WordNotifierInfo* wni, XP_S16* score )
|
||||
{
|
||||
PlayerCtxt* player = &model->players[turn];
|
||||
if ( !player->curMoveValid ) {
|
||||
scoreCurrentMove( model, turn, stream );
|
||||
scoreCurrentMove( model, turn, stream, wni );
|
||||
}
|
||||
|
||||
*score = player->curMoveScore;
|
||||
|
|
|
@ -2631,6 +2631,12 @@ server_formatRemainingTiles( ServerCtxt* server, XWStreamCtxt* stream,
|
|||
}
|
||||
} /* server_formatRemainingTiles */
|
||||
|
||||
void
|
||||
server_listWordsPlayed( ServerCtxt* server, XWStreamCtxt* stream, XP_U16 nMoves )
|
||||
{
|
||||
(void)model_getWordsPlayed( server->vol.model, server->pool, nMoves, stream );
|
||||
}
|
||||
|
||||
#define IMPOSSIBLY_LOW_SCORE -1000
|
||||
void
|
||||
server_writeFinalScores( ServerCtxt* server, XWStreamCtxt* stream )
|
||||
|
|
|
@ -124,6 +124,8 @@ void server_formatDictCounts( ServerCtxt* server, XWStreamCtxt* stream,
|
|||
void server_formatRemainingTiles( ServerCtxt* server, XWStreamCtxt* stream,
|
||||
XP_S16 player );
|
||||
|
||||
void server_listWordsPlayed( ServerCtxt* server, XWStreamCtxt* stream, XP_U16 nMoves );
|
||||
|
||||
void server_writeFinalScores( ServerCtxt* server, XWStreamCtxt* stream );
|
||||
|
||||
#ifdef CPLUS
|
||||
|
|
|
@ -314,7 +314,9 @@ drawPendingScore( BoardCtxt* board, XP_Bool hasCursor )
|
|||
XP_Rect lastTileR;
|
||||
|
||||
(void)getCurrentMoveScoreIfLegal( board->model, selPlayer,
|
||||
(XWStreamCtxt*)NULL, &turnScore );
|
||||
(XWStreamCtxt*)NULL,
|
||||
(WordNotifierInfo*)NULL,
|
||||
&turnScore );
|
||||
figureTrayTileRect( board, MAX_TRAY_TILES-1, &lastTileR );
|
||||
draw_score_pendingScore( board->draw, &lastTileR, turnScore,
|
||||
selPlayer,
|
||||
|
|
|
@ -1709,6 +1709,15 @@ gtk_util_playerScoreHeld( XW_UtilCtxt* uc, XP_U16 player )
|
|||
|
||||
GtkAppGlobals* globals = (GtkAppGlobals*)uc->closure;
|
||||
|
||||
#if 1
|
||||
XP_USE( player );
|
||||
XWStreamCtxt* stream =
|
||||
mem_stream_make( MEMPOOL globals->cGlobals.params->vtMgr, globals,
|
||||
CHANNEL_NONE, catOnClose );
|
||||
server_listWordsPlayed( globals->cGlobals.game.server, stream, 1000 );
|
||||
stream_destroy( stream );
|
||||
#else
|
||||
|
||||
XP_UCHAR scoreExpl[48];
|
||||
XP_U16 explLen = sizeof(scoreExpl);
|
||||
|
||||
|
@ -1716,6 +1725,7 @@ gtk_util_playerScoreHeld( XW_UtilCtxt* uc, XP_U16 player )
|
|||
player, scoreExpl, &explLen ) ) {
|
||||
XP_LOGF( "got: %s", scoreExpl );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue