diff --git a/xwords4/common/board.c b/xwords4/common/board.c index a08f14407..176843944 100644 --- a/xwords4/common/board.c +++ b/xwords4/common/board.c @@ -256,7 +256,9 @@ board_makeFromStream( MPFORMAL XWStreamCtxt* stream, ModelCtxt* model, arrow->vert = (XP_Bool)stream_getBits( stream, 1 ); arrow->visible = (XP_Bool)stream_getBits( stream, 1 ); - pti->dividerLoc = (XP_U8)stream_getBits( stream, NTILES_NBITS ); + if ( STREAM_VERS_MULTIADDR > version ) { + (void)stream_getBits( stream, NTILES_NBITS ); + } pti->traySelBits = (TileBit)stream_getBits( stream, MAX_TRAY_TILES ); pti->tradeInProgress = (XP_Bool)stream_getBits( stream, 1 ); @@ -343,7 +345,6 @@ board_writeToStream( const BoardCtxt* board, XWStreamCtxt* stream ) stream_putBits( stream, 1, arrow->vert ); stream_putBits( stream, 1, arrow->visible ); - stream_putBits( stream, NTILES_NBITS, pti->dividerLoc ); stream_putBits( stream, MAX_TRAY_TILES, pti->traySelBits ); stream_putBits( stream, 1, pti->tradeInProgress ); @@ -383,7 +384,6 @@ board_reset( BoardCtxt* board ) PerTurnInfo* pti = &board->pti[ii]; pti->traySelBits = 0; pti->tradeInProgress = XP_FALSE; - pti->dividerLoc = 0; XP_MEMSET( &pti->boardArrow, 0, sizeof(pti->boardArrow) ); } board->gameOver = XP_FALSE; @@ -2026,6 +2026,7 @@ board_requestHint( BoardCtxt* board, EngineCtxt* engine = server_getEngineFor( board->server, selPlayer ); const TrayTileSet* tileSet; ModelCtxt* model = board->model; + XP_U16 dividerLoc = model_getDividerLoc( model, selPlayer ); if ( !!engine && preflight( board, XP_TRUE ) ) { @@ -2047,7 +2048,7 @@ board_requestHint( BoardCtxt* board, } tileSet = model_getPlayerTiles( model, selPlayer ); - nTiles = tileSet->nTiles - pti->dividerLoc; + nTiles = tileSet->nTiles - dividerLoc; result = nTiles > 0; } @@ -2063,7 +2064,7 @@ board_requestHint( BoardCtxt* board, (void)board_replaceTiles( board ); - tiles = tileSet->tiles + pti->dividerLoc; + tiles = tileSet->tiles + dividerLoc; board_pushTimerSave( board ); @@ -2080,7 +2081,7 @@ board_requestHint( BoardCtxt* board, #ifdef XWFEATURE_BONUSALL XP_U16 allTilesBonus = 0; # ifdef XWFEATURE_BONUSALLHINT - if ( 0 == pti->dividerLoc ) { + if ( 0 == dividerLoc ) { allTilesBonus = server_figureFinishBonus( board->server, selPlayer ); } @@ -3219,7 +3220,7 @@ invalFocusOwner( BoardCtxt* board ) case OBJ_TRAY: if ( board->focusHasDived ) { XP_S16 loc = pti->trayCursorLoc; - if ( loc == pti->dividerLoc ) { + if ( loc == model_getDividerLoc(board->model, board->selPlayer)) { board->dividerInvalid = XP_TRUE; } else { adjustForDivider( board, &loc ); diff --git a/xwords4/common/boardp.h b/xwords4/common/boardp.h index d91d2866f..ede2dc4d2 100644 --- a/xwords4/common/boardp.h +++ b/xwords4/common/boardp.h @@ -111,7 +111,6 @@ typedef struct _PerTurnInfo { #endif BoardArrow boardArrow; XP_U16 scoreDims; - XP_U8 dividerLoc; /* 0 means left of 0th tile, etc. */ TileBit traySelBits; #ifdef XWFEATURE_SEARCHLIMIT BdHintLimits limits; diff --git a/xwords4/common/dragdrpp.c b/xwords4/common/dragdrpp.c index befcbacee..839124eac 100644 --- a/xwords4/common/dragdrpp.c +++ b/xwords4/common/dragdrpp.c @@ -156,7 +156,8 @@ ddStartTray( BoardCtxt* board, XP_U16 x, XP_U16 y ) if ( canDrag ) { if ( onDivider ) { board->dividerInvalid = XP_TRUE; - ds->start.u.tray.index = board->selInfo->dividerLoc; + ds->start.u.tray.index = + model_getDividerLoc( board->model, board->selPlayer ); ds->dtype = DT_DIVIDER; } else { diff --git a/xwords4/common/model.c b/xwords4/common/model.c index eadeb0ace..493f08346 100644 --- a/xwords4/common/model.c +++ b/xwords4/common/model.c @@ -1822,6 +1822,23 @@ model_moveTileOnTray( ModelCtxt* model, XP_S16 turn, XP_S16 indexCur, notifyTrayListeners( model, turn, indexCur, indexNew ); } /* model_moveTileOnTray */ +XP_U16 +model_getDividerLoc( const ModelCtxt* model, XP_S16 turn ) +{ + XP_ASSERT( turn >= 0 ); + PlayerCtxt* player = &model->players[turn]; + return player->dividerLoc; +} + +void +model_setDividerLoc( const ModelCtxt* model, XP_S16 turn, XP_U16 loc ) +{ + XP_ASSERT( turn >= 0 ); + PlayerCtxt* player = &model->players[turn]; + XP_ASSERT( loc < 0xFF ); + player->dividerLoc = (XP_U8)loc; +} + static void assignPlayerTiles( ModelCtxt* model, XP_S16 turn, const TrayTileSet* tiles ) { @@ -1851,7 +1868,8 @@ model_sortTiles( ModelCtxt* model, XP_S16 turn ) TrayTileSet sorted; const TrayTileSet* curTiles = model_getPlayerTiles( model, turn ); - sortTiles( &sorted, curTiles, XP_MIN( 3, curTiles->nTiles) ); + XP_U16 dividerLoc = model_getDividerLoc( model, turn ); + sortTiles( &sorted, curTiles, dividerLoc ); nTiles = sorted.nTiles; while ( nTiles > 0 ) { @@ -2441,6 +2459,10 @@ loadPlayerCtxt( const ModelCtxt* model, XWStreamCtxt* stream, XP_U16 version, } else { XP_ASSERT( 0 == pc->nUndone ); } + XP_ASSERT( 0 == pc->dividerLoc ); + if ( STREAM_VERS_MULTIADDR <= version ) { + pc->dividerLoc = stream_getBits( stream, NTILES_NBITS ); + } nTiles = pc->nPending + pc->nUndone; for ( pt = pc->pendingTiles; nTiles-- > 0; ++pt ) { @@ -2475,6 +2497,7 @@ writePlayerCtxt( const ModelCtxt* model, XWStreamCtxt* stream, stream_putBits( stream, NTILES_NBITS, pc->nPending ); stream_putBits( stream, NTILES_NBITS, pc->nUndone ); + stream_putBits( stream, NTILES_NBITS, pc->dividerLoc ); nTiles = pc->nPending + pc->nUndone; for ( pt = pc->pendingTiles; nTiles-- > 0; ++pt ) { diff --git a/xwords4/common/model.h b/xwords4/common/model.h index 07e85d992..74f897120 100644 --- a/xwords4/common/model.h +++ b/xwords4/common/model.h @@ -152,6 +152,8 @@ void model_addPlayerTile( ModelCtxt* model, XP_S16 turn, XP_S16 index, Tile tile ); void model_moveTileOnTray( ModelCtxt* model, XP_S16 turn, XP_S16 indexCur, XP_S16 indexNew ); +XP_U16 model_getDividerLoc( const ModelCtxt* model, XP_S16 turn ); +void model_setDividerLoc( const ModelCtxt* model, XP_S16 turn, XP_U16 loc ); /* As an optimization, return a pointer to the model's array of tiles for a player. Don't even think about modifying the array!!!! */ diff --git a/xwords4/common/modelp.h b/xwords4/common/modelp.h index 1b54c70de..47cca9080 100644 --- a/xwords4/common/modelp.h +++ b/xwords4/common/modelp.h @@ -41,6 +41,7 @@ typedef struct PlayerCtxt { TrayTileSet trayTiles; XP_U8 nPending; /* still in tray but "on board" */ XP_U8 nUndone; /* tiles above nPending we can reuse */ + XP_U8 dividerLoc; PendingTile pendingTiles[MAX_TRAY_TILES]; } PlayerCtxt; diff --git a/xwords4/common/tray.c b/xwords4/common/tray.c index f96e22053..669ae2ee8 100644 --- a/xwords4/common/tray.c +++ b/xwords4/common/tray.c @@ -48,6 +48,12 @@ trayLocToIndex( BoardCtxt* board, XP_U16 loc ) return loc; } /* trayLocToIndex */ +static XP_U16 +getDividerLoc( const BoardCtxt* board ) +{ + return model_getDividerLoc( board->model, board->selPlayer ); +} + XP_S16 pointToTileIndex( BoardCtxt* board, XP_U16 x, XP_U16 y, XP_Bool* onDividerP ) { @@ -96,7 +102,7 @@ figureTrayTileRect( BoardCtxt* board, XP_U16 index, XP_Rect* rect ) rect->width = board->trayScaleH; rect->height = board->trayScaleV; - if ( board->selInfo->dividerLoc <= index ) { + if ( getDividerLoc( board ) <= index ) { rect->left += board->dividerWidth; } } /* figureTileRect */ @@ -143,7 +149,7 @@ drawTray( BoardCtxt* board ) #ifdef KEYBOARD_NAV XP_S16 cursorTile = pti->trayCursorLoc; if ( (board->focussed == OBJ_TRAY) && !board->hideFocus ) { - cursorOnDivider = pti->dividerLoc == cursorTile; + cursorOnDivider = getDividerLoc(board) == cursorTile; if ( board->focusHasDived ) { if ( !cursorOnDivider ) { adjustForDivider( board, &cursorTile ); @@ -348,7 +354,8 @@ drawPendingScore( BoardCtxt* board, XP_S16 turnScore, XP_Bool hasCursor ) static void figureDividerRect( BoardCtxt* board, XP_Rect* rect ) { - figureTrayTileRect( board, board->selInfo->dividerLoc, rect ); + XP_U16 dividerLoc = getDividerLoc( board ); + figureTrayTileRect( board, dividerLoc, rect ); rect->left -= board->dividerWidth; rect->width = board->dividerWidth; } /* figureDividerRect */ @@ -495,10 +502,10 @@ indexForBits( XP_U8 bits ) XP_Bool dividerMoved( BoardCtxt* board, XP_U8 newLoc ) { - XP_U8 oldLoc = board->selInfo->dividerLoc; + XP_U8 oldLoc = getDividerLoc( board ); XP_Bool moved = oldLoc != newLoc; if ( moved ) { - board->selInfo->dividerLoc = newLoc; + model_setDividerLoc( board->model, board->selPlayer, newLoc ); /* This divider's index corresponds to the tile it's to the left of, and there's no need to invalidate any tiles to the left of the uppermore @@ -562,7 +569,7 @@ board_juggleTray( BoardCtxt* board ) if ( checkRevealTray( board ) ) { XP_S16 nTiles; - XP_U16 dividerLoc = board->selInfo->dividerLoc; + XP_U16 dividerLoc = getDividerLoc( board ); ModelCtxt* model = board->model; nTiles = model_getNumTilesInTray( model, turn ) - dividerLoc; @@ -597,7 +604,7 @@ board_juggleTray( BoardCtxt* board ) void adjustForDivider( const BoardCtxt* board, XP_S16* index ) { - XP_U16 dividerLoc = board->selInfo->dividerLoc; + XP_U16 dividerLoc = getDividerLoc( board ); if ( dividerLoc <= *index ) { --*index; } @@ -630,7 +637,8 @@ tray_moveCursor( BoardCtxt* board, XP_Key cursorKey, XP_Bool preflightOnly, XP_U16 nTiles = board->trayVisState == TRAY_REVEALED ? model_getNumTilesInTray( board->model, selPlayer ) : MAX_TRAY_TILES; - XP_Bool cursorOnDivider = trayCursorLoc == pti->dividerLoc; + XP_U16 dividerLoc = getDividerLoc( board ); + XP_Bool cursorOnDivider = trayCursorLoc == dividerLoc; XP_Bool cursorObjSelected; XP_S16 newTileLoc; @@ -642,13 +650,13 @@ tray_moveCursor( BoardCtxt* board, XP_Key cursorKey, XP_Bool preflightOnly, /* nothing to do */ } else if ( cursorOnDivider ) { /* just drag the divider */ - pti->dividerLoc = newLoc; + model_setDividerLoc( board->model, board->selPlayer, newLoc ); resetEngine = XP_TRUE; } else if ( pti->tradeInProgress ) { /* nothing to do */ } else { /* drag the tile, skipping over the divider if needed */ - if ( (newLoc == pti->dividerLoc) && (newLoc > 0) ) { + if ( (newLoc == dividerLoc) && (newLoc > 0) ) { newLoc += delta; resetEngine = XP_TRUE; } @@ -675,7 +683,7 @@ tray_moveCursor( BoardCtxt* board, XP_Key cursorKey, XP_Bool preflightOnly, adjustForDivider( board, &newTileLoc ); if ( (newTileLoc > nTiles) - && (newLoc != pti->dividerLoc) + && (newLoc != dividerLoc) && (newTileLoc < MAX_TRAY_TILES-1) ) { continue; } @@ -702,9 +710,8 @@ getFocussedTileCenter( BoardCtxt* board, XP_U16* xp, XP_U16* yp ) XP_Rect rect; PerTurnInfo* pti = board->selInfo; XP_S16 cursorTile = pti->trayCursorLoc; - XP_Bool cursorOnDivider = pti->dividerLoc == cursorTile; - if ( cursorOnDivider ) { + if ( getDividerLoc( board ) == cursorTile ) { /* cursor on divider? */ figureDividerRect( board, &rect ); } else { XP_S16 indx = pti->trayCursorLoc; @@ -723,7 +730,7 @@ board_moveDivider( BoardCtxt* board, XP_Bool right ) { XP_Bool result = board->trayVisState == TRAY_REVEALED; if ( result ) { - XP_U8 loc = board->selInfo->dividerLoc; + XP_U8 loc = getDividerLoc( board ); loc += MAX_TRAY_TILES + 1; loc += right? 1:-1; loc %= MAX_TRAY_TILES + 1;