combine all per-player arrays in board into a single array of structs.

access can then be via a ptr, more effecient and faster.  The change
seems to save 1K of generated code.  No changes to algorithms, only to
field access.
This commit is contained in:
ehouse 2008-07-18 07:49:00 +00:00
parent 5422b82fd3
commit c20e85eccd
6 changed files with 192 additions and 172 deletions

View file

@ -1,4 +1,4 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; compile-command: "cd ../linux && make MEMDEBUG=TRUE"; -*- */ /* -*-mode: C; fill-column: 78; compile-command: "cd ../linux && make MEMDEBUG=TRUE"; -*- */
/* /*
* Copyright 1997 - 2008 by Eric House (xwords@eehouse.org). All rights * Copyright 1997 - 2008 by Eric House (xwords@eehouse.org). All rights
* reserved. * reserved.
@ -164,9 +164,10 @@ board_make( MPFORMAL ModelCtxt* model, ServerCtxt* server, DrawCtx* draw,
/* set up some useful initial values */ /* set up some useful initial values */
XP_U16 i; XP_U16 i;
for ( i = 0; i < MAX_NUM_PLAYERS; ++i ) { for ( i = 0; i < MAX_NUM_PLAYERS; ++i ) {
result->trayCursorLoc[i] = 1; PerTurnInfo* pti = result->pti + i;
result->bdCursor[i].col = 5; pti->trayCursorLoc = 1;
result->bdCursor[i].row = 7; pti->bdCursor.col = 5;
pti->bdCursor.row = 7;
} }
} }
#endif #endif
@ -209,41 +210,43 @@ board_makeFromStream( MPFORMAL XWStreamCtxt* stream, ModelCtxt* model,
XP_ASSERT( !!server ); XP_ASSERT( !!server );
for ( i = 0; i < nPlayers; ++i ) { for ( i = 0; i < nPlayers; ++i ) {
BoardArrow* arrow = &board->boardArrow[i]; PerTurnInfo* pti = &board->pti[i];
BoardArrow* arrow = &pti->boardArrow;
arrow->col = (XP_U8)stream_getBits( stream, NUMCOLS_NBITS ); arrow->col = (XP_U8)stream_getBits( stream, NUMCOLS_NBITS );
arrow->row = (XP_U8)stream_getBits( stream, NUMCOLS_NBITS ); arrow->row = (XP_U8)stream_getBits( stream, NUMCOLS_NBITS );
arrow->vert = (XP_Bool)stream_getBits( stream, 1 ); arrow->vert = (XP_Bool)stream_getBits( stream, 1 );
arrow->visible = (XP_Bool)stream_getBits( stream, 1 ); arrow->visible = (XP_Bool)stream_getBits( stream, 1 );
board->dividerLoc[i] = (XP_U8)stream_getBits( stream, NTILES_NBITS ); pti->dividerLoc = (XP_U8)stream_getBits( stream, NTILES_NBITS );
board->traySelBits[i] = (TileBit)stream_getBits( stream, pti->traySelBits = (TileBit)stream_getBits( stream,
MAX_TRAY_TILES ); MAX_TRAY_TILES );
board->tradeInProgress[i] = (XP_Bool)stream_getBits( stream, 1 ); pti->tradeInProgress = (XP_Bool)stream_getBits( stream, 1 );
#ifdef KEYBOARD_NAV #ifdef KEYBOARD_NAV
if ( version >= STREAM_VERS_KEYNAV ) { if ( version >= STREAM_VERS_KEYNAV ) {
board->bdCursor[i].col = stream_getBits( stream, 4 ); pti->bdCursor.col = stream_getBits( stream, 4 );
board->bdCursor[i].row = stream_getBits( stream, 4 ); pti->bdCursor.row = stream_getBits( stream, 4 );
board->trayCursorLoc[i] = stream_getBits( stream, 3 ); pti->trayCursorLoc = stream_getBits( stream, 3 );
} }
#endif #endif
#ifdef XWFEATURE_SEARCHLIMIT #ifdef XWFEATURE_SEARCHLIMIT
if ( version >= STREAM_VERS_41B4 ) { if ( version >= STREAM_VERS_41B4 ) {
board->hasHintRect[i] = stream_getBits( stream, 1 ); pti->hasHintRect = stream_getBits( stream, 1 );
} else { } else {
board->hasHintRect[i] = XP_FALSE; pti->hasHintRect = XP_FALSE;
} }
if ( board->hasHintRect[i] ) { if ( pti->hasHintRect ) {
board->limits[i].left = stream_getBits( stream, 4 ); pti->limits.left = stream_getBits( stream, 4 );
board->limits[i].top = stream_getBits( stream, 4 ); pti->limits.top = stream_getBits( stream, 4 );
board->limits[i].right = stream_getBits( stream, 4 ); pti->limits.right = stream_getBits( stream, 4 );
board->limits[i].bottom = stream_getBits( stream, 4 ); pti->limits.bottom = stream_getBits( stream, 4 );
} }
#endif #endif
} }
board->selPlayer = (XP_U8)stream_getBits( stream, PLAYERNUM_NBITS ); board->selPlayer = (XP_U8)stream_getBits( stream, PLAYERNUM_NBITS );
board->selInfo = &board->pti[board->selPlayer];
board->trayVisState = (XW_TrayVisState)stream_getBits( stream, 2 ); board->trayVisState = (XW_TrayVisState)stream_getBits( stream, 2 );
XP_ASSERT( stream_getU32( stream ) == bEND ); XP_ASSERT( stream_getU32( stream ) == bEND );
@ -270,28 +273,29 @@ board_writeToStream( BoardCtxt* board, XWStreamCtxt* stream )
nPlayers = board->gi->nPlayers; nPlayers = board->gi->nPlayers;
for ( i = 0; i < nPlayers; ++i ) { for ( i = 0; i < nPlayers; ++i ) {
BoardArrow* arrow = &board->boardArrow[i]; PerTurnInfo* pti = &board->pti[i];
BoardArrow* arrow = &pti->boardArrow;
stream_putBits( stream, NUMCOLS_NBITS, arrow->col ); stream_putBits( stream, NUMCOLS_NBITS, arrow->col );
stream_putBits( stream, NUMCOLS_NBITS, arrow->row ); stream_putBits( stream, NUMCOLS_NBITS, arrow->row );
stream_putBits( stream, 1, arrow->vert ); stream_putBits( stream, 1, arrow->vert );
stream_putBits( stream, 1, arrow->visible ); stream_putBits( stream, 1, arrow->visible );
stream_putBits( stream, NTILES_NBITS, board->dividerLoc[i] ); stream_putBits( stream, NTILES_NBITS, pti->dividerLoc );
stream_putBits( stream, MAX_TRAY_TILES, board->traySelBits[i] ); stream_putBits( stream, MAX_TRAY_TILES, pti->traySelBits );
stream_putBits( stream, 1, board->tradeInProgress[i] ); stream_putBits( stream, 1, pti->tradeInProgress );
#ifdef KEYBOARD_NAV #ifdef KEYBOARD_NAV
stream_putBits( stream, 4, board->bdCursor[i].col ); stream_putBits( stream, 4, pti->bdCursor.col );
stream_putBits( stream, 4, board->bdCursor[i].row ); stream_putBits( stream, 4, pti->bdCursor.row );
stream_putBits( stream, 3, board->trayCursorLoc[i] ); stream_putBits( stream, 3, pti->trayCursorLoc );
#endif #endif
#ifdef XWFEATURE_SEARCHLIMIT #ifdef XWFEATURE_SEARCHLIMIT
stream_putBits( stream, 1, board->hasHintRect[i] ); stream_putBits( stream, 1, pti->hasHintRect );
if ( board->hasHintRect[i] ) { if ( pti->hasHintRect ) {
stream_putBits( stream, 4, board->limits[i].left ); stream_putBits( stream, 4, pti->limits.left );
stream_putBits( stream, 4, board->limits[i].top ); stream_putBits( stream, 4, pti->limits.top );
stream_putBits( stream, 4, board->limits[i].right ); stream_putBits( stream, 4, pti->limits.right );
stream_putBits( stream, 4, board->limits[i].bottom ); stream_putBits( stream, 4, pti->limits.bottom );
} }
#endif #endif
} }
@ -314,13 +318,15 @@ board_reset( BoardCtxt* board )
/* This is appropriate for a new game *ONLY*. reset */ /* This is appropriate for a new game *ONLY*. reset */
for ( i = 0; i < MAX_NUM_PLAYERS; ++i ) { for ( i = 0; i < MAX_NUM_PLAYERS; ++i ) {
board->traySelBits[i] = 0; PerTurnInfo* pti = &board->pti[i];
board->tradeInProgress[i] = XP_FALSE; pti->traySelBits = 0;
board->dividerLoc[i] = 0; pti->tradeInProgress = XP_FALSE;
pti->dividerLoc = 0;
XP_MEMSET( &pti->boardArrow, 0, sizeof(pti->boardArrow) );
} }
XP_MEMSET( &board->boardArrow, 0, sizeof(board->boardArrow) );
board->gameOver = XP_FALSE; board->gameOver = XP_FALSE;
board->selPlayer = 0; board->selPlayer = 0;
board->selInfo = board->pti;
board->star_row = (XP_U16)(model_numRows(board->model) / 2); board->star_row = (XP_U16)(model_numRows(board->model) / 2);
newState = board->boardObscuresTray? TRAY_HIDDEN:TRAY_REVERSED; newState = board->boardObscuresTray? TRAY_HIDDEN:TRAY_REVERSED;
@ -388,8 +394,7 @@ board_prefsChanged( BoardCtxt* board, CommonPrefs* cp )
} }
#ifdef XWFEATURE_SEARCHLIMIT #ifdef XWFEATURE_SEARCHLIMIT
if ( !board->gi->allowHintRect if ( !board->gi->allowHintRect && board->selInfo->hasHintRect ) {
&& board->hasHintRect[board->selPlayer] ) {
EngineCtxt* engine = server_getEngineFor( board->server, EngineCtxt* engine = server_getEngineFor( board->server,
board->selPlayer ); board->selPlayer );
@ -470,14 +475,14 @@ board_getFocusOwner( BoardCtxt* board )
static void static void
invalArrowCell( BoardCtxt* board ) invalArrowCell( BoardCtxt* board )
{ {
BoardArrow* arrow = &board->boardArrow[board->selPlayer]; BoardArrow* arrow = &board->selInfo->boardArrow;
invalCell( board, arrow->col, arrow->row ); invalCell( board, arrow->col, arrow->row );
} /* invalArrowCell */ } /* invalArrowCell */
static void static void
flipArrow( BoardCtxt* board ) flipArrow( BoardCtxt* board )
{ {
BoardArrow* arrow = &board->boardArrow[board->selPlayer]; BoardArrow* arrow = &board->selInfo->boardArrow;
XP_U16 tmp = arrow->col; XP_U16 tmp = arrow->col;
arrow->col = arrow->row; arrow->col = arrow->row;
arrow->row = tmp; arrow->row = tmp;
@ -488,7 +493,7 @@ flipArrow( BoardCtxt* board )
static void static void
invalCursorCell( BoardCtxt* board ) invalCursorCell( BoardCtxt* board )
{ {
BdCursorLoc loc = board->bdCursor[board->selPlayer]; BdCursorLoc loc = board->selInfo->bdCursor;
invalCell( board, loc.col, loc.row ); invalCell( board, loc.col, loc.row );
} /* invalCursorCell */ } /* invalCursorCell */
#endif #endif
@ -498,7 +503,7 @@ invalTradeWindow( BoardCtxt* board, XP_S16 turn, XP_Bool redraw )
{ {
XP_ASSERT( turn >= 0 ); XP_ASSERT( turn >= 0 );
if ( board->tradeInProgress[turn] ) { if ( board->pti[turn].tradeInProgress ) {
MiniWindowStuff* stuff = &board->miniWindowStuff[MINIWINDOW_TRADING]; MiniWindowStuff* stuff = &board->miniWindowStuff[MINIWINDOW_TRADING];
invalCellsUnderRect( board, &stuff->rect ); invalCellsUnderRect( board, &stuff->rect );
if ( redraw ) { if ( redraw ) {
@ -549,31 +554,32 @@ XP_Bool
board_commitTurn( BoardCtxt* board ) board_commitTurn( BoardCtxt* board )
{ {
XP_Bool result = XP_FALSE; XP_Bool result = XP_FALSE;
XP_S16 turn = server_getCurrentTurn( board->server ); const XP_S16 turn = server_getCurrentTurn( board->server );
PerTurnInfo* pti = board->pti + turn;
if ( board->gameOver || turn < 0 ) { if ( board->gameOver || turn < 0 ) {
/* do nothing */ /* do nothing */
} else if ( turn != board->selPlayer ) { } else if ( turn != board->selPlayer ) {
if ( board->tradeInProgress[board->selPlayer] ) { if ( board->selInfo->tradeInProgress ) {
result = exitTradeMode( board ); result = exitTradeMode( board );
} else { } else {
util_userError( board->util, ERR_NOT_YOUR_TURN ); util_userError( board->util, ERR_NOT_YOUR_TURN );
} }
} else if ( checkRevealTray( board ) ) { } else if ( checkRevealTray( board ) ) {
if ( board->tradeInProgress[turn] ) { if ( pti->tradeInProgress ) {
result = XP_TRUE; /* there's at least the window to clean up result = XP_TRUE; /* there's at least the window to clean up
after */ after */
invalSelTradeWindow( board ); invalSelTradeWindow( board );
board->tradeInProgress[turn] = XP_FALSE; pti->tradeInProgress = XP_FALSE;
if ( util_userQuery( board->util, QUERY_COMMIT_TRADE, if ( util_userQuery( board->util, QUERY_COMMIT_TRADE,
(XWStreamCtxt*)NULL ) ) { (XWStreamCtxt*)NULL ) ) {
result = server_commitTrade( board->server, result = server_commitTrade( board->server,
board->traySelBits[turn] ); pti->traySelBits );
/* XP_DEBUGF( "server_commitTrade returned %d\n", result ); */ /* XP_DEBUGF( "server_commitTrade returned %d\n", result ); */
} }
board->traySelBits[turn] = 0x00; pti->traySelBits = 0x00;
} else { } else {
XP_Bool warn, legal; XP_Bool warn, legal;
WordNotifierInfo info; WordNotifierInfo info;
@ -612,8 +618,8 @@ board_commitTurn( BoardCtxt* board )
/* invalidate any selected tiles in case we'll be drawing /* invalidate any selected tiles in case we'll be drawing
this tray again rather than some other -- as is the this tray again rather than some other -- as is the
case in a two-player game where one's a robot. */ case in a two-player game where one's a robot. */
board_invalTrayTiles( board, board->traySelBits[turn] ); board_invalTrayTiles( board, pti->traySelBits );
board->traySelBits[turn] = 0x00; pti->traySelBits = 0x00;
} }
} }
stream_destroy( stream ); stream_destroy( stream );
@ -641,6 +647,7 @@ selectPlayerImpl( BoardCtxt* board, XP_U16 newPlayer, XP_Bool reveal )
checkRevealTray( board ); checkRevealTray( board );
} }
} else { } else {
PerTurnInfo* newInfo = &board->pti[newPlayer];
XP_U16 oldPlayer = board->selPlayer; XP_U16 oldPlayer = board->selPlayer;
model_foreachPendingCell( board->model, newPlayer, model_foreachPendingCell( board->model, newPlayer,
boardCellChanged, board ); boardCellChanged, board );
@ -657,26 +664,26 @@ selectPlayerImpl( BoardCtxt* board, XP_U16 newPlayer, XP_Bool reveal )
/* Just in case somebody started a trade when it wasn't his turn and /* Just in case somebody started a trade when it wasn't his turn and
there were plenty of tiles but now there aren't. */ there were plenty of tiles but now there aren't. */
if ( board->tradeInProgress[newPlayer] && if ( newInfo->tradeInProgress &&
server_countTilesInPool(board->server) < MIN_TRADE_TILES ) { server_countTilesInPool(board->server) < MIN_TRADE_TILES ) {
board->tradeInProgress[newPlayer] = XP_FALSE; newInfo->tradeInProgress = XP_FALSE;
board->traySelBits[newPlayer] = 0x00; /* clear any selected */ newInfo->traySelBits = 0x00; /* clear any selected */
} }
invalTradeWindow( board, oldPlayer, invalTradeWindow( board, oldPlayer, newInfo->tradeInProgress );
board->tradeInProgress[newPlayer] );
#ifdef XWFEATURE_SEARCHLIMIT #ifdef XWFEATURE_SEARCHLIMIT
if ( board->hasHintRect[oldPlayer] ) { if ( board->pti[oldPlayer].hasHintRect ) {
invalCurHintRect( board, oldPlayer ); invalCurHintRect( board, oldPlayer );
} }
if ( board->hasHintRect[newPlayer] ) { if ( newInfo->hasHintRect ) {
invalCurHintRect( board, newPlayer ); invalCurHintRect( board, newPlayer );
} }
#endif #endif
invalArrowCell( board ); invalArrowCell( board );
board->selPlayer = (XP_U8)newPlayer; board->selPlayer = (XP_U8)newPlayer;
board->selInfo = newInfo;
invalArrowCell( board ); invalArrowCell( board );
board_invalTrayTiles( board, ALLTILES ); board_invalTrayTiles( board, ALLTILES );
@ -970,7 +977,7 @@ flipAllLimits( BoardCtxt* board )
XP_U16 nPlayers = board->gi->nPlayers; XP_U16 nPlayers = board->gi->nPlayers;
XP_U16 i; XP_U16 i;
for ( i = 0; i < nPlayers; ++i ) { for ( i = 0; i < nPlayers; ++i ) {
flipLimits( &board->limits[i] ); flipLimits( &board->pti[i].limits );
} }
} }
#endif #endif
@ -1402,14 +1409,15 @@ board_requestHint( BoardCtxt* board,
XP_Bool result = XP_FALSE; XP_Bool result = XP_FALSE;
XP_S16 nTiles; XP_S16 nTiles;
const Tile* tiles; const Tile* tiles;
XP_U16 selPlayer; const XP_U16 selPlayer = board->selPlayer;
PerTurnInfo* pti;
EngineCtxt* engine; EngineCtxt* engine;
XP_Bool searchComplete = XP_TRUE; XP_Bool searchComplete = XP_TRUE;
XP_Bool redraw = XP_FALSE; XP_Bool redraw = XP_FALSE;
*workRemainsP = XP_FALSE; /* in case we exit without calling engine */ *workRemainsP = XP_FALSE; /* in case we exit without calling engine */
selPlayer = board->selPlayer; pti = board->pti + selPlayer;
engine = server_getEngineFor( board->server, selPlayer ); engine = server_getEngineFor( board->server, selPlayer );
/* engine may be null, if e.g. hint menu's chosen for a remote player */ /* engine may be null, if e.g. hint menu's chosen for a remote player */
result = !!engine && !board->gi->hintsNotAllowed && preflight( board ); result = !!engine && !board->gi->hintsNotAllowed && preflight( board );
@ -1436,7 +1444,7 @@ board_requestHint( BoardCtxt* board,
} }
tileSet = model_getPlayerTiles( model, selPlayer ); tileSet = model_getPlayerTiles( model, selPlayer );
nTiles = tileSet->nTiles - board->dividerLoc[selPlayer]; nTiles = tileSet->nTiles - pti->dividerLoc;
result = nTiles > 0; result = nTiles > 0;
if ( result ) { if ( result ) {
#ifdef XWFEATURE_SEARCHLIMIT #ifdef XWFEATURE_SEARCHLIMIT
@ -1450,15 +1458,14 @@ board_requestHint( BoardCtxt* board,
(void)board_replaceTiles( board ); (void)board_replaceTiles( board );
tiles = tileSet->tiles + board->dividerLoc[selPlayer]; tiles = tileSet->tiles + pti->dividerLoc;
board_pushTimerSave( board ); board_pushTimerSave( board );
#ifdef XWFEATURE_SEARCHLIMIT #ifdef XWFEATURE_SEARCHLIMIT
XP_ASSERT( board->gi->allowHintRect XP_ASSERT( board->gi->allowHintRect || !pti->hasHintRect );
|| !board->hasHintRect[selPlayer] ); if ( board->gi->allowHintRect && pti->hasHintRect ) {
if ( board->gi->allowHintRect && board->hasHintRect[selPlayer] ) { limits = pti->limits;
limits = board->limits[selPlayer];
lp = &limits; lp = &limits;
if ( board->isFlipped ) { if ( board->isFlipped ) {
flipLimits( lp ); flipLimits( lp );
@ -1632,7 +1639,7 @@ XP_Bool
moveTileToArrowLoc( BoardCtxt* board, XP_U8 index ) moveTileToArrowLoc( BoardCtxt* board, XP_U8 index )
{ {
XP_Bool result; XP_Bool result;
BoardArrow* arrow = &board->boardArrow[board->selPlayer]; BoardArrow* arrow = &board->selInfo->boardArrow;
if ( arrow->visible ) { if ( arrow->visible ) {
result = moveTileToBoard( board, arrow->col, arrow->row, result = moveTileToBoard( board, arrow->col, arrow->row,
(XP_U16)index, EMPTY_TILE ); (XP_U16)index, EMPTY_TILE );
@ -1682,7 +1689,7 @@ board_beginTrade( BoardCtxt* board )
} else { } else {
board->tradingMiniWindowInvalid = XP_TRUE; board->tradingMiniWindowInvalid = XP_TRUE;
board->needsDrawing = XP_TRUE; board->needsDrawing = XP_TRUE;
board->tradeInProgress[board->selPlayer] = XP_TRUE; board->selInfo->tradeInProgress = XP_TRUE;
setArrowVisible( board, XP_FALSE ); setArrowVisible( board, XP_FALSE );
result = XP_TRUE; result = XP_TRUE;
} }
@ -1738,7 +1745,7 @@ invalCellRegion( BoardCtxt* board, XP_U16 colA, XP_U16 rowA, XP_U16 colB,
void void
invalCurHintRect( BoardCtxt* board, XP_U16 player ) invalCurHintRect( BoardCtxt* board, XP_U16 player )
{ {
BdHintLimits* limits = &board->limits[player]; BdHintLimits* limits = &board->pti[player].limits;
invalCellRegion( board, limits->left, limits->top, invalCellRegion( board, limits->left, limits->top,
limits->right, limits->bottom ); limits->right, limits->bottom );
} /* invalCurHintRect */ } /* invalCurHintRect */
@ -1747,7 +1754,7 @@ static void
clearCurHintRect( BoardCtxt* board ) clearCurHintRect( BoardCtxt* board )
{ {
invalCurHintRect( board, board->selPlayer ); invalCurHintRect( board, board->selPlayer );
board->hasHintRect[board->selPlayer] = XP_FALSE; board->selInfo->hasHintRect = XP_FALSE;
} /* clearCurHintRect */ } /* clearCurHintRect */
#endif /* XWFEATURE_SEARCHLIMIT */ #endif /* XWFEATURE_SEARCHLIMIT */
@ -1762,7 +1769,7 @@ handlePenDownOnBoard( BoardCtxt* board, XP_U16 xx, XP_U16 yy )
util_setTimer( board->util, TIMER_PENDOWN, 0, util_setTimer( board->util, TIMER_PENDOWN, 0,
p_board_timerFired, board ); p_board_timerFired, board );
if ( !board->tradeInProgress[board->selPlayer] ) { if ( !board->selInfo->tradeInProgress ) {
result = dragDropStart( board, OBJ_BOARD, xx, yy ); result = dragDropStart( board, OBJ_BOARD, xx, yy );
} }
} }
@ -1851,7 +1858,7 @@ handleLikeDown( BoardCtxt* board, BoardObjectType onWhich, XP_U16 x, XP_U16 y )
case OBJ_TRAY: case OBJ_TRAY:
if ( checkRevealTray(board) if ( checkRevealTray(board)
&& !board->tradeInProgress[board->selPlayer] ) { && !board->selInfo->tradeInProgress ) {
result = dragDropStart( board, OBJ_TRAY, x, y ) || result; result = dragDropStart( board, OBJ_TRAY, x, y ) || result;
} }
break; break;
@ -1920,7 +1927,7 @@ moveSelTileToBoardXY( BoardCtxt* board, XP_U16 col, XP_U16 row )
{ {
XP_Bool result; XP_Bool result;
XP_U16 selPlayer = board->selPlayer; XP_U16 selPlayer = board->selPlayer;
TileBit bits = board->traySelBits[selPlayer]; TileBit bits = board->selInfo->traySelBits;
XP_U16 tileIndex; XP_U16 tileIndex;
if ( bits == NO_TILES ) { if ( bits == NO_TILES ) {
@ -1942,7 +1949,7 @@ moveSelTileToBoardXY( BoardCtxt* board, XP_U16 col, XP_U16 row )
bits = 1 << (tileIndex-1); bits = 1 << (tileIndex-1);
board_invalTrayTiles( board, bits ); board_invalTrayTiles( board, bits );
} }
board->traySelBits[selPlayer] = bits; board->selInfo->traySelBits = bits;
} }
return result; return result;
@ -1973,7 +1980,7 @@ tryMoveArrow( BoardCtxt* board, XP_U16 col, XP_U16 row )
if ( !cellOccupied( board, col, row, if ( !cellOccupied( board, col, row,
board->trayVisState == TRAY_REVEALED ) ) { board->trayVisState == TRAY_REVEALED ) ) {
BoardArrow* arrow = &board->boardArrow[board->selPlayer]; BoardArrow* arrow = &board->selInfo->boardArrow;
if ( arrow->visible && arrow->col == col && arrow->row == row ) { if ( arrow->visible && arrow->col == col && arrow->row == row ) {
/* change it; if vertical, hide; else if horizontal make /* change it; if vertical, hide; else if horizontal make
@ -2049,11 +2056,11 @@ handleActionInCell( BoardCtxt* board, XP_U16 col, XP_U16 row, XP_Bool isPen )
static XP_Bool static XP_Bool
exitTradeMode( BoardCtxt* board ) exitTradeMode( BoardCtxt* board )
{ {
XP_U16 selPlayer = board->selPlayer; PerTurnInfo* pti = board->selInfo;
invalSelTradeWindow( board ); invalSelTradeWindow( board );
board->tradeInProgress[selPlayer] = XP_FALSE; pti->tradeInProgress = XP_FALSE;
board_invalTrayTiles( board, board->traySelBits[selPlayer] ); board_invalTrayTiles( board, pti->traySelBits );
board->traySelBits[selPlayer] = 0x00; pti->traySelBits = 0x00;
return XP_TRUE; return XP_TRUE;
} /* exitTradeMode */ } /* exitTradeMode */
@ -2143,8 +2150,7 @@ static void
getFocussedCellCenter( BoardCtxt* board, XP_U16* xp, XP_U16* yp ) getFocussedCellCenter( BoardCtxt* board, XP_U16* xp, XP_U16* yp )
{ {
XP_Rect rect; XP_Rect rect;
XP_U16 selPlayer = board->selPlayer; BdCursorLoc* cursorLoc = &board->selInfo->bdCursor;
BdCursorLoc* cursorLoc = &board->bdCursor[selPlayer];
getCellRect( board, cursorLoc->col, cursorLoc->row, &rect ); getCellRect( board, cursorLoc->col, cursorLoc->row, &rect );
getRectCenter( &rect, xp, yp ); getRectCenter( &rect, xp, yp );
@ -2153,7 +2159,7 @@ getFocussedCellCenter( BoardCtxt* board, XP_U16* xp, XP_U16* yp )
static void static void
getFocussedScoreCenter( BoardCtxt* board, XP_U16* xp, XP_U16* yp ) getFocussedScoreCenter( BoardCtxt* board, XP_U16* xp, XP_U16* yp )
{ {
getRectCenter( &board->scoreRects[board->scoreCursorLoc], xp, yp ); getRectCenter( &board->pti[board->scoreCursorLoc].scoreRects, xp, yp );
} }
static XP_Bool static XP_Bool
@ -2361,14 +2367,14 @@ static XP_Bool
invalFocusOwner( BoardCtxt* board ) invalFocusOwner( BoardCtxt* board )
{ {
XP_Bool draw = XP_TRUE; XP_Bool draw = XP_TRUE;
XP_S16 selPlayer = board->selPlayer; PerTurnInfo* pti = board->selInfo;
switch( board->focussed ) { switch( board->focussed ) {
case OBJ_SCORE: case OBJ_SCORE:
board->scoreBoardInvalid = XP_TRUE; board->scoreBoardInvalid = XP_TRUE;
break; break;
case OBJ_BOARD: case OBJ_BOARD:
if ( board->focusHasDived ) { if ( board->focusHasDived ) {
BdCursorLoc loc = board->bdCursor[selPlayer]; BdCursorLoc loc = pti->bdCursor;
invalCell( board, loc.col, loc.row ); invalCell( board, loc.col, loc.row );
} else { } else {
#ifdef PERIMETER_FOCUS #ifdef PERIMETER_FOCUS
@ -2380,7 +2386,7 @@ invalFocusOwner( BoardCtxt* board )
break; break;
case OBJ_TRAY: case OBJ_TRAY:
if ( board->focusHasDived ) { if ( board->focusHasDived ) {
XP_U16 loc = board->trayCursorLoc[selPlayer]; XP_U16 loc = pti->trayCursorLoc;
board_invalTrayTiles( board, 1 << loc ); board_invalTrayTiles( board, 1 << loc );
} else { } else {
board_invalTrayTiles( board, ALLTILES ); board_invalTrayTiles( board, ALLTILES );
@ -2446,7 +2452,7 @@ board_focusChanged( BoardCtxt* board, BoardObjectType typ, XP_Bool gained )
XP_Bool XP_Bool
board_toggle_arrowDir( BoardCtxt* board ) board_toggle_arrowDir( BoardCtxt* board )
{ {
BoardArrow* arrow = &board->boardArrow[board->selPlayer]; BoardArrow* arrow = &board->selInfo->boardArrow;
if ( arrow->visible ) { if ( arrow->visible ) {
arrow->vert = !arrow->vert; arrow->vert = !arrow->vert;
invalArrowCell( board ); invalArrowCell( board );
@ -2461,7 +2467,7 @@ board_toggle_arrowDir( BoardCtxt* board )
static XP_Bool static XP_Bool
advanceArrow( BoardCtxt* board ) advanceArrow( BoardCtxt* board )
{ {
XP_Key key = board->boardArrow[board->selPlayer].vert ? XP_Key key = board->selInfo->boardArrow.vert ?
XP_CURSOR_KEY_DOWN : XP_CURSOR_KEY_RIGHT; XP_CURSOR_KEY_DOWN : XP_CURSOR_KEY_RIGHT;
XP_ASSERT( board->trayVisState == TRAY_REVEALED ); XP_ASSERT( board->trayVisState == TRAY_REVEALED );
@ -2584,7 +2590,8 @@ static XP_Bool
board_moveCursor( BoardCtxt* board, XP_Key cursorKey, XP_Bool preflightOnly, board_moveCursor( BoardCtxt* board, XP_Key cursorKey, XP_Bool preflightOnly,
XP_Bool* up ) XP_Bool* up )
{ {
BdCursorLoc loc = board->bdCursor[board->selPlayer]; PerTurnInfo* pti = board->selInfo;
BdCursorLoc loc = pti->bdCursor;
XP_U16 col = loc.col; XP_U16 col = loc.col;
XP_U16 row = loc.row; XP_U16 row = loc.row;
XP_Bool changed; XP_Bool changed;
@ -2599,7 +2606,7 @@ board_moveCursor( BoardCtxt* board, XP_Key cursorKey, XP_Bool preflightOnly,
invalCell( board, col, row ); invalCell( board, col, row );
loc.col = col; loc.col = col;
loc.row = row; loc.row = row;
board->bdCursor[board->selPlayer] = loc; pti->bdCursor = loc;
checkScrollCell( board, col, row ); checkScrollCell( board, col, row );
} }
return changed; return changed;
@ -2730,7 +2737,7 @@ moveKeyTileToBoard( BoardCtxt* board, XP_Key cursorKey, XP_Bool* gotArrow )
*gotArrow = haveDest; *gotArrow = haveDest;
#ifdef KEYBOARD_NAV #ifdef KEYBOARD_NAV
if ( !haveDest && (board->focussed == OBJ_BOARD) && board->focusHasDived ) { if ( !haveDest && (board->focussed == OBJ_BOARD) && board->focusHasDived ) {
BdCursorLoc loc = board->bdCursor[board->selPlayer]; BdCursorLoc loc = board->selInfo->bdCursor;
col = loc.col; col = loc.col;
row = loc.row; row = loc.row;
haveDest = XP_TRUE; haveDest = XP_TRUE;
@ -2752,7 +2759,7 @@ moveKeyTileToBoard( BoardCtxt* board, XP_Key cursorKey, XP_Bool* gotArrow )
static void static void
setArrowFor( BoardCtxt* board, XP_U16 player, XP_U16 col, XP_U16 row ) setArrowFor( BoardCtxt* board, XP_U16 player, XP_U16 col, XP_U16 row )
{ {
BoardArrow* arrow = &board->boardArrow[player]; BoardArrow* arrow = &board->pti[player].boardArrow;
invalCell( board, arrow->col, arrow->row ); invalCell( board, arrow->col, arrow->row );
invalCell( board, col, row ); invalCell( board, col, row );
@ -2771,7 +2778,7 @@ setArrow( BoardCtxt* board, XP_U16 col, XP_U16 row )
static XP_Bool static XP_Bool
getArrowFor( BoardCtxt* board, XP_U16 player, XP_U16* col, XP_U16* row ) getArrowFor( BoardCtxt* board, XP_U16 player, XP_U16* col, XP_U16* row )
{ {
BoardArrow* arrow = &board->boardArrow[player]; BoardArrow* arrow = &board->pti[player].boardArrow;
*col = arrow->col; *col = arrow->col;
*row = arrow->row; *row = arrow->row;
return arrow->visible; return arrow->visible;
@ -2792,7 +2799,7 @@ setArrowVisible( BoardCtxt* board, XP_Bool visible )
static XP_Bool static XP_Bool
setArrowVisibleFor( BoardCtxt* board, XP_U16 player, XP_Bool visible ) setArrowVisibleFor( BoardCtxt* board, XP_U16 player, XP_Bool visible )
{ {
BoardArrow* arrow = &board->boardArrow[player]; BoardArrow* arrow = &board->pti[player].boardArrow;
XP_Bool result = arrow->visible; XP_Bool result = arrow->visible;
if ( arrow->visible != visible ) { if ( arrow->visible != visible ) {
arrow->visible = visible; arrow->visible = visible;

View file

@ -172,8 +172,8 @@ figureHintAtts( BoardCtxt* board, XP_U16 col, XP_U16 row )
BdHintLimits limits; BdHintLimits limits;
if ( dragDropGetHintLimits( board, &limits ) ) { if ( dragDropGetHintLimits( board, &limits ) ) {
/* do nothing */ /* do nothing */
} else if ( board->hasHintRect[board->selPlayer] ) { } else if ( board->selInfo->hasHintRect ) {
limits = board->limits[board->selPlayer]; limits = board->selInfo->limits;
} else { } else {
break; break;
} }
@ -278,7 +278,7 @@ drawBoard( BoardCtxt* board )
} }
if ( board->trayVisState == TRAY_REVEALED ) { if ( board->trayVisState == TRAY_REVEALED ) {
BoardArrow* arrow = &board->boardArrow[board->selPlayer]; BoardArrow* arrow = &board->selInfo->boardArrow;
if ( arrow->visible ) { if ( arrow->visible ) {
XP_U16 col = arrow->col; XP_U16 col = arrow->col;
@ -440,8 +440,8 @@ cellFocused( const BoardCtxt* board, XP_U16 col, XP_U16 row )
if ( board->focussed == OBJ_BOARD ) { if ( board->focussed == OBJ_BOARD ) {
if ( board->focusHasDived ) { if ( board->focusHasDived ) {
if ( (col == board->bdCursor[board->selPlayer].col) if ( (col == board->selInfo->bdCursor.col)
&& (row == board->bdCursor[board->selPlayer].row) ) { && (row == board->selInfo->bdCursor.row) ) {
focussed = XP_TRUE; focussed = XP_TRUE;
} }
} else { } else {

View file

@ -1,4 +1,4 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */ /* -*-mode: C; fill-column: 78; -*- */
/* /*
* Copyright 1997 - 2007 by Eric House (xwords@eehouse.org). All rights reserved. * Copyright 1997 - 2007 by Eric House (xwords@eehouse.org). All rights reserved.
* *
@ -54,7 +54,7 @@ typedef enum {
} DragType; } DragType;
typedef struct DragState { typedef struct _DragState {
DragType dtype; DragType dtype;
XP_Bool didMove; /* there was change during the drag; not a XP_Bool didMove; /* there was change during the drag; not a
tap */ tap */
@ -65,7 +65,7 @@ typedef struct DragState {
DragObjInfo cur; DragObjInfo cur;
} DragState; } DragState;
typedef struct BoardArrow { /* gets flipped along with board */ typedef struct _BoardArrow { /* gets flipped along with board */
XP_U8 col; XP_U8 col;
XP_U8 row; XP_U8 row;
XP_Bool vert; XP_Bool vert;
@ -73,7 +73,7 @@ typedef struct BoardArrow { /* gets flipped along with board */
} BoardArrow; } BoardArrow;
#ifdef KEYBOARD_NAV #ifdef KEYBOARD_NAV
typedef struct BdCursorLoc { typedef struct _BdCursorLoc {
XP_U8 col; XP_U8 col;
XP_U8 row; XP_U8 row;
} BdCursorLoc; } BdCursorLoc;
@ -83,7 +83,7 @@ typedef struct BdCursorLoc {
trading window. There's never more than of the former since it lives only trading window. There's never more than of the former since it lives only
as long as the pen is down. There are, in theory, as many trading windows as long as the pen is down. There are, in theory, as many trading windows
as there are (local) players, but they can all use the same window. */ as there are (local) players, but they can all use the same window. */
typedef struct MiniWindowStuff { typedef struct _MiniWindowStuff {
void* closure; void* closure;
const XP_UCHAR* text; const XP_UCHAR* text;
XP_Rect rect; XP_Rect rect;
@ -92,6 +92,29 @@ typedef struct MiniWindowStuff {
enum { MINIWINDOW_VALHINT, MINIWINDOW_TRADING }; enum { MINIWINDOW_VALHINT, MINIWINDOW_TRADING };
typedef XP_U16 MiniWindowType; /* one of the two above */ typedef XP_U16 MiniWindowType; /* one of the two above */
typedef struct _PerTurnInfo {
#ifdef KEYBOARD_NAV
XP_Rect scoreRects;
BdCursorLoc bdCursor;
#endif
BoardArrow boardArrow;
XP_U16 scoreDims;
XP_U8 dividerLoc; /* 0 means left of 0th tile, etc. */
TileBit traySelBits;
#ifdef XWFEATURE_SEARCHLIMIT
BdHintLimits limits;
#endif
#ifdef KEYBOARD_NAV
XP_U8 trayCursorLoc; /* includes divider!!! */
#endif
XP_Bool dividerSelected; /* probably need to save this */
XP_Bool tradeInProgress;
#ifdef XWFEATURE_SEARCHLIMIT
XP_Bool hasHintRect;
#endif
} PerTurnInfo;
struct BoardCtxt { struct BoardCtxt {
/* BoardVTable* vtable; */ /* BoardVTable* vtable; */
ModelCtxt* model; ModelCtxt* model;
@ -133,7 +156,6 @@ struct BoardCtxt {
XP_Bool disableArrow; XP_Bool disableArrow;
XP_Bool hideValsInTray; XP_Bool hideValsInTray;
XP_Bool tradeInProgress[MAX_NUM_PLAYERS];
XP_Bool eraseTray; XP_Bool eraseTray;
XP_Bool boardObscuresTray; XP_Bool boardObscuresTray;
XP_Bool boardHidesTray; XP_Bool boardHidesTray;
@ -144,22 +166,18 @@ struct BoardCtxt {
/* Unless KEYBOARD_NAV is defined, this does not change */ /* Unless KEYBOARD_NAV is defined, this does not change */
BoardObjectType focussed; BoardObjectType focussed;
BoardArrow boardArrow[MAX_NUM_PLAYERS];
#ifdef KEYBOARD_NAV #ifdef KEYBOARD_NAV
XP_Rect scoreRects[MAX_NUM_PLAYERS];
BdCursorLoc bdCursor[MAX_NUM_PLAYERS];
XP_Bool focusHasDived; XP_Bool focusHasDived;
#endif #endif
XP_U8 dividerLoc[MAX_NUM_PLAYERS]; /* 0 means left of 0th tile, etc. */
XP_Bool dividerSelected[MAX_NUM_PLAYERS]; /* probably need to save this */
XP_U16 scoreDims[MAX_NUM_PLAYERS];
/* scoreboard state */ /* scoreboard state */
XP_Rect scoreBdBounds; XP_Rect scoreBdBounds;
XP_Rect timerBounds; XP_Rect timerBounds;
XP_U8 selPlayer; /* which player is selected (!= turn) */ XP_U8 selPlayer; /* which player is selected (!= turn) */
PerTurnInfo pti[MAX_NUM_PLAYERS];
PerTurnInfo* selInfo;
/* tray state */ /* tray state */
XP_U8 trayScaleH; XP_U8 trayScaleH;
XP_U8 trayScaleV; XP_U8 trayScaleV;
@ -175,9 +193,7 @@ struct BoardCtxt {
XP_Bool tradingMiniWindowInvalid; XP_Bool tradingMiniWindowInvalid;
TileBit trayInvalBits; TileBit trayInvalBits;
TileBit traySelBits[MAX_NUM_PLAYERS];
#ifdef KEYBOARD_NAV #ifdef KEYBOARD_NAV
XP_U8 trayCursorLoc[MAX_NUM_PLAYERS]; /* includes divider!!! */
XP_U8 scoreCursorLoc; XP_U8 scoreCursorLoc;
#endif #endif
@ -186,10 +202,6 @@ struct BoardCtxt {
XP_Bool showCellValues; XP_Bool showCellValues;
XP_Bool showColors; XP_Bool showColors;
#ifdef XWFEATURE_SEARCHLIMIT
XP_Bool hasHintRect[MAX_NUM_PLAYERS];
BdHintLimits limits[MAX_NUM_PLAYERS];
#endif
MPSLOT MPSLOT
}; };
@ -197,7 +209,7 @@ struct BoardCtxt {
#define valHintMiniWindowActive( board ) \ #define valHintMiniWindowActive( board ) \
((XP_Bool)((board)->miniWindowStuff[MINIWINDOW_VALHINT].text != NULL)) ((XP_Bool)((board)->miniWindowStuff[MINIWINDOW_VALHINT].text != NULL))
#define MY_TURN(b) ((b)->selPlayer == server_getCurrentTurn( (b)->server )) #define MY_TURN(b) ((b)->selPlayer == server_getCurrentTurn( (b)->server ))
#define TRADE_IN_PROGRESS(b) ((b)->tradeInProgress[(b)->selPlayer]==XP_TRUE) #define TRADE_IN_PROGRESS(b) ((b)->selInfo->tradeInProgress==XP_TRUE)
/* tray-related functions */ /* tray-related functions */
XP_Bool handlePenUpTray( BoardCtxt* board, XP_U16 x, XP_U16 y ); XP_Bool handlePenUpTray( BoardCtxt* board, XP_U16 x, XP_U16 y );

View file

@ -1,4 +1,4 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; compile-command: "cd ../linux && make MEMDEBUG=TRUE"; -*- */ /* -*-mode: C; fill-column: 78; compile-command: "cd ../linux && make MEMDEBUG=TRUE"; -*- */
/* /*
* Copyright 1997 - 2008 by Eric House (xwords@eehouse.org). All rights * Copyright 1997 - 2008 by Eric House (xwords@eehouse.org). All rights
* reserved. * reserved.
@ -114,15 +114,14 @@ ddStartTray( BoardCtxt* board, XP_U16 x, XP_U16 y )
XP_S16 index = pointToTileIndex( board, x, y, &onDivider ); XP_S16 index = pointToTileIndex( board, x, y, &onDivider );
canDrag = onDivider || index >= 0; canDrag = onDivider || index >= 0;
if ( canDrag ) { if ( canDrag ) {
XP_S16 selPlayer = board->selPlayer;
if ( onDivider ) { if ( onDivider ) {
board->dividerInvalid = XP_TRUE; board->dividerInvalid = XP_TRUE;
ds->start.u.tray.index = board->dividerLoc[selPlayer]; ds->start.u.tray.index = board->selInfo->dividerLoc;
ds->dtype = DT_DIVIDER; ds->dtype = DT_DIVIDER;
} else { } else {
Tile tile; Tile tile;
tile = model_getPlayerTile( board->model, selPlayer, index ); tile = model_getPlayerTile( board->model, board->selPlayer, index );
ds->isBlank = ds->isBlank =
tile == dict_getBlankTile( model_getDictionary(board->model) ); tile == dict_getBlankTile( model_getDictionary(board->model) );
ds->tile = tile; ds->tile = tile;
@ -131,7 +130,7 @@ ddStartTray( BoardCtxt* board, XP_U16 x, XP_U16 y )
/* during drag the moving tile is drawn as selected, so inval /* during drag the moving tile is drawn as selected, so inval
currently selected tile. */ currently selected tile. */
board_invalTrayTiles( board, board->traySelBits[selPlayer] ); board_invalTrayTiles( board, board->selInfo->traySelBits );
ds->dtype = DT_TILE; ds->dtype = DT_TILE;
} }
@ -218,9 +217,9 @@ dragDropEnd( BoardCtxt* board, XP_U16 xx, XP_U16 yy, XP_Bool* dragged )
} else if ( ds->dtype == DT_HINTRGN ) { } else if ( ds->dtype == DT_HINTRGN ) {
if ( OBJ_BOARD == newObj && ds->didMove ) { if ( OBJ_BOARD == newObj && ds->didMove ) {
XP_Bool makeActive = ds->start.u.board.row <= ds->cur.u.board.row; XP_Bool makeActive = ds->start.u.board.row <= ds->cur.u.board.row;
board->hasHintRect[board->selPlayer] = makeActive; board->selInfo->hasHintRect = makeActive;
if ( makeActive ) { if ( makeActive ) {
setLimitsFrom( board, &board->limits[board->selPlayer] ); setLimitsFrom( board, &board->selInfo->limits );
} else { } else {
invalHintRectDiffs( board, &ds->cur, NULL ); invalHintRectDiffs( board, &ds->cur, NULL );
} }

View file

@ -1,4 +1,4 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */ /* -*-mode: C; fill-column: 78; compile-command: "cd ../linux && make MEMDEBUG=TRUE"; -*- */
/* /*
* Copyright 1997 - 2007 by Eric House (xwords@eehouse.org). All rights reserved. * Copyright 1997 - 2007 by Eric House (xwords@eehouse.org). All rights reserved.
* *
@ -164,7 +164,7 @@ drawScoreBoard( BoardCtxt* board )
for ( dp = datum, i = 0; i < nPlayers; ++dp, ++i ) { for ( dp = datum, i = 0; i < nPlayers; ++dp, ++i ) {
XP_Rect innerRect; XP_Rect innerRect;
XP_U16 dim = isVertical? dp->height:dp->width; XP_U16 dim = isVertical? dp->height:dp->width;
*adjustDim = board->scoreDims[i] = dim + extra; *adjustDim = board->pti[i].scoreDims = dim + extra;
innerRect.width = dp->width; innerRect.width = dp->width;
innerRect.height = dp->height; innerRect.height = dp->height;
@ -176,7 +176,7 @@ drawScoreBoard( BoardCtxt* board )
draw_score_drawPlayer( board->draw, &innerRect, &scoreRect, draw_score_drawPlayer( board->draw, &innerRect, &scoreRect,
&dp->dsi ); &dp->dsi );
#ifdef KEYBOARD_NAV #ifdef KEYBOARD_NAV
XP_MEMCPY( &board->scoreRects[i], &scoreRect, XP_MEMCPY( &board->pti[i].scoreRects, &scoreRect,
sizeof(scoreRect) ); sizeof(scoreRect) );
if ( i == cursorIndex ) { if ( i == cursorIndex ) {
cursorRect = scoreRect; cursorRect = scoreRect;
@ -245,10 +245,11 @@ figureScorePlayerTapped( BoardCtxt* board, XP_U16 x, XP_U16 y )
left -= board->remDim; left -= board->remDim;
if ( left >= 0 ) { if ( left >= 0 ) {
for ( result = 0; result < nPlayers; ++result ) { for ( result = 0; result < nPlayers; ++result ) {
if ( left < board->scoreDims[result] ) { PerTurnInfo* pti = board->pti + result;
if ( left < pti->scoreDims ) {
break; break;
} }
left -= board->scoreDims[result]; left -= pti->scoreDims;
} }
} }
if ( result >= nPlayers ) { if ( result >= nPlayers ) {

View file

@ -95,7 +95,7 @@ figureTrayTileRect( BoardCtxt* board, XP_U16 index, XP_Rect* rect )
rect->width = board->trayScaleH; rect->width = board->trayScaleH;
rect->height = board->trayScaleV; rect->height = board->trayScaleV;
if ( board->dividerLoc[board->selPlayer] <= index ) { if ( board->selInfo->dividerLoc <= index ) {
rect->left += board->dividerWidth; rect->left += board->dividerWidth;
} }
} /* figureTileRect */ } /* figureTileRect */
@ -128,7 +128,8 @@ drawTray( BoardCtxt* board )
XP_Rect tileRect; XP_Rect tileRect;
if ( (board->trayInvalBits != 0) || board->dividerInvalid ) { if ( (board->trayInvalBits != 0) || board->dividerInvalid ) {
XP_S16 turn = board->selPlayer; const XP_S16 turn = board->selPlayer;
PerTurnInfo* pti = board->selInfo;
if ( draw_trayBegin( board->draw, &board->trayBounds, turn, if ( draw_trayBegin( board->draw, &board->trayBounds, turn,
dfsFor( board, OBJ_TRAY ) ) ) { dfsFor( board, OBJ_TRAY ) ) ) {
@ -136,9 +137,9 @@ drawTray( BoardCtxt* board )
XP_S16 cursorBits = 0; XP_S16 cursorBits = 0;
XP_Bool cursorOnDivider = XP_FALSE; XP_Bool cursorOnDivider = XP_FALSE;
#ifdef KEYBOARD_NAV #ifdef KEYBOARD_NAV
XP_S16 cursorTile = board->trayCursorLoc[turn]; XP_S16 cursorTile = pti->trayCursorLoc;
if ( board->focussed == OBJ_TRAY ) { if ( board->focussed == OBJ_TRAY ) {
cursorOnDivider = board->dividerLoc[turn] == cursorTile; cursorOnDivider = pti->dividerLoc == cursorTile;
if ( board->focusHasDived ) { if ( board->focusHasDived ) {
if ( !cursorOnDivider ) { if ( !cursorOnDivider ) {
adjustForDivider( board, &cursorTile ); adjustForDivider( board, &cursorTile );
@ -187,7 +188,7 @@ drawTray( BoardCtxt* board )
XP_UCHAR buf[4]; XP_UCHAR buf[4];
XP_Bitmap bitmap = NULL; XP_Bitmap bitmap = NULL;
XP_UCHAR* textP = (XP_UCHAR*)NULL; XP_UCHAR* textP = (XP_UCHAR*)NULL;
XP_U8 traySelBits = board->traySelBits[turn]; XP_U8 traySelBits = pti->traySelBits;
XP_S16 value; XP_S16 value;
Tile tile; Tile tile;
@ -240,7 +241,7 @@ drawTray( BoardCtxt* board )
CellFlags flags = cursorOnDivider? CELL_ISCURSOR : CELL_NONE; CellFlags flags = cursorOnDivider? CELL_ISCURSOR : CELL_NONE;
XP_Rect divider; XP_Rect divider;
figureDividerRect( board, &divider ); figureDividerRect( board, &divider );
if ( board->dividerSelected[turn] if ( pti->dividerSelected
|| dragDropIsDividerDrag(board) ) { || dragDropIsDividerDrag(board) ) {
flags |= CELL_HIGHLIGHT; flags |= CELL_HIGHLIGHT;
} }
@ -327,7 +328,7 @@ drawPendingScore( BoardCtxt* board, XP_Bool hasCursor )
static void static void
figureDividerRect( BoardCtxt* board, XP_Rect* rect ) figureDividerRect( BoardCtxt* board, XP_Rect* rect )
{ {
figureTrayTileRect( board, board->dividerLoc[board->selPlayer], rect ); figureTrayTileRect( board, board->selInfo->dividerLoc, rect );
rect->left -= board->dividerWidth; rect->left -= board->dividerWidth;
rect->width = board->dividerWidth; rect->width = board->dividerWidth;
} /* figureDividerRect */ } /* figureDividerRect */
@ -365,7 +366,7 @@ handleTrayDuringTrade( BoardCtxt* board, XP_S16 index )
XP_ASSERT( index >= 0 ); XP_ASSERT( index >= 0 );
bits = 1 << index; bits = 1 << index;
board->traySelBits[board->selPlayer] ^= bits; board->selInfo->traySelBits ^= bits;
board_invalTrayTiles( board, bits ); board_invalTrayTiles( board, bits );
return XP_TRUE; return XP_TRUE;
} /* handleTrayDuringTrade */ } /* handleTrayDuringTrade */
@ -374,15 +375,16 @@ static XP_Bool
handleActionInTray( BoardCtxt* board, XP_S16 index, XP_Bool onDivider ) handleActionInTray( BoardCtxt* board, XP_S16 index, XP_Bool onDivider )
{ {
XP_Bool result = XP_FALSE; XP_Bool result = XP_FALSE;
XP_U16 selPlayer = board->selPlayer; const XP_U16 selPlayer = board->selPlayer;
PerTurnInfo* pti = board->selInfo;
if ( onDivider ) { if ( onDivider ) {
/* toggle divider sel state */ /* toggle divider sel state */
board->dividerSelected[selPlayer] = !board->dividerSelected[selPlayer]; pti->dividerSelected = !pti->dividerSelected;
board->dividerInvalid = XP_TRUE; board->dividerInvalid = XP_TRUE;
board->traySelBits[selPlayer] = NO_TILES; pti->traySelBits = NO_TILES;
result = XP_TRUE; result = XP_TRUE;
} else if ( board->tradeInProgress[selPlayer] ) { } else if ( pti->tradeInProgress ) {
if ( index >= 0 ) { if ( index >= 0 ) {
result = handleTrayDuringTrade( board, index ); result = handleTrayDuringTrade( board, index );
} }
@ -390,25 +392,25 @@ handleActionInTray( BoardCtxt* board, XP_S16 index, XP_Bool onDivider )
result = moveTileToArrowLoc( board, (XP_U8)index ); result = moveTileToArrowLoc( board, (XP_U8)index );
if ( !result ) { if ( !result ) {
TileBit newBits = 1 << index; TileBit newBits = 1 << index;
XP_U8 selBits = board->traySelBits[selPlayer]; XP_U8 selBits = pti->traySelBits;
/* Tap on selected tile unselects. If we don't do this, /* Tap on selected tile unselects. If we don't do this,
then there's no way to unselect and so no way to turn then there's no way to unselect and so no way to turn
off the placement arrow */ off the placement arrow */
if ( newBits == selBits ) { if ( newBits == selBits ) {
board_invalTrayTiles( board, selBits ); board_invalTrayTiles( board, selBits );
board->traySelBits[selPlayer] = NO_TILES; pti->traySelBits = NO_TILES;
} else if ( selBits != 0 ) { } else if ( selBits != 0 ) {
XP_U16 selIndex = indexForBits( selBits ); XP_U16 selIndex = indexForBits( selBits );
model_moveTileOnTray( board->model, board->selPlayer, model_moveTileOnTray( board->model, selPlayer,
selIndex, index ); selIndex, index );
board->traySelBits[selPlayer] = NO_TILES; pti->traySelBits = NO_TILES;
} else { } else {
board_invalTrayTiles( board, newBits ); board_invalTrayTiles( board, newBits );
board->traySelBits[selPlayer] = newBits; pti->traySelBits = newBits;
} }
board->dividerInvalid = board->dividerInvalid =
board->dividerInvalid || board->dividerSelected[selPlayer]; board->dividerInvalid || pti->dividerSelected;
board->dividerSelected[selPlayer] = XP_FALSE; pti->dividerSelected = XP_FALSE;
result = XP_TRUE; result = XP_TRUE;
} }
} else if ( index == -(MAX_TRAY_TILES) ) { /* pending score tile */ } else if ( index == -(MAX_TRAY_TILES) ) { /* pending score tile */
@ -447,10 +449,10 @@ indexForBits( XP_U8 bits )
XP_Bool XP_Bool
dividerMoved( BoardCtxt* board, XP_U8 newLoc ) dividerMoved( BoardCtxt* board, XP_U8 newLoc )
{ {
XP_U8 oldLoc = board->dividerLoc[board->selPlayer]; XP_U8 oldLoc = board->selInfo->dividerLoc;
XP_Bool moved = oldLoc != newLoc; XP_Bool moved = oldLoc != newLoc;
if ( moved ) { if ( moved ) {
board->dividerLoc[board->selPlayer] = newLoc; board->selInfo->dividerLoc = newLoc;
/* This divider's index corresponds to the tile it's to the left of, and /* 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 there's no need to invalidate any tiles to the left of the uppermore
@ -508,11 +510,11 @@ XP_Bool
board_juggleTray( BoardCtxt* board ) board_juggleTray( BoardCtxt* board )
{ {
XP_Bool result = XP_FALSE; XP_Bool result = XP_FALSE;
XP_S16 turn = board->selPlayer; const XP_S16 turn = board->selPlayer;
if ( checkRevealTray( board ) ) { if ( checkRevealTray( board ) ) {
XP_S16 nTiles; XP_S16 nTiles;
XP_U16 dividerLoc = board->dividerLoc[board->selPlayer]; XP_U16 dividerLoc = board->selInfo->dividerLoc;
ModelCtxt* model = board->model; ModelCtxt* model = board->model;
nTiles = model_getNumTilesInTray( model, turn ) - dividerLoc; nTiles = model_getNumTilesInTray( model, turn ) - dividerLoc;
@ -536,7 +538,7 @@ board_juggleTray( BoardCtxt* board )
(void)model_removePlayerTile( model, turn, -1 ); (void)model_removePlayerTile( model, turn, -1 );
model_addPlayerTile( model, turn, dividerLoc, tmpT[i] ); model_addPlayerTile( model, turn, dividerLoc, tmpT[i] );
} }
board->traySelBits[turn] = 0; board->selInfo->traySelBits = 0;
result = XP_TRUE; result = XP_TRUE;
} }
} }
@ -547,7 +549,7 @@ board_juggleTray( BoardCtxt* board )
static void static void
adjustForDivider( const BoardCtxt* board, XP_S16* index ) adjustForDivider( const BoardCtxt* board, XP_S16* index )
{ {
XP_U16 dividerLoc = board->dividerLoc[board->selPlayer]; XP_U16 dividerLoc = board->selInfo->dividerLoc;
if ( dividerLoc <= *index ) { if ( dividerLoc <= *index ) {
--*index; --*index;
} }
@ -566,8 +568,9 @@ tray_moveCursor( BoardCtxt* board, XP_Key cursorKey, XP_Bool preflightOnly,
} else if ( cursorKey == XP_CURSOR_KEY_RIGHT } else if ( cursorKey == XP_CURSOR_KEY_RIGHT
|| cursorKey == XP_CURSOR_KEY_LEFT ) { || cursorKey == XP_CURSOR_KEY_LEFT ) {
XP_S16 delta = cursorKey == XP_CURSOR_KEY_RIGHT ? 1 : -1; XP_S16 delta = cursorKey == XP_CURSOR_KEY_RIGHT ? 1 : -1;
XP_U16 selPlayer = board->selPlayer; const XP_U16 selPlayer = board->selPlayer;
XP_S16 trayCursorLoc = board->trayCursorLoc[selPlayer]; PerTurnInfo* pti = board->selInfo;
XP_S16 trayCursorLoc = pti->trayCursorLoc;
XP_S16 newLoc = trayCursorLoc + delta; XP_S16 newLoc = trayCursorLoc + delta;
if ( newLoc < 0 || newLoc > MAX_TRAY_TILES ) { if ( newLoc < 0 || newLoc > MAX_TRAY_TILES ) {
XP_LOGF( "moving up: newLoc: %d", newLoc ); XP_LOGF( "moving up: newLoc: %d", newLoc );
@ -575,27 +578,25 @@ tray_moveCursor( BoardCtxt* board, XP_Key cursorKey, XP_Bool preflightOnly,
} else if ( !preflightOnly ) { } else if ( !preflightOnly ) {
XP_S16 tileLoc = trayCursorLoc; XP_S16 tileLoc = trayCursorLoc;
XP_U16 nTiles = model_getNumTilesInTray( board->model, selPlayer ); XP_U16 nTiles = model_getNumTilesInTray( board->model, selPlayer );
XP_Bool cursorOnDivider XP_Bool cursorOnDivider = trayCursorLoc == pti->dividerLoc;
= trayCursorLoc == board->dividerLoc[selPlayer];
XP_Bool cursorObjSelected; XP_Bool cursorObjSelected;
adjustForDivider( board, &tileLoc ); adjustForDivider( board, &tileLoc );
cursorObjSelected = cursorOnDivider? cursorObjSelected = cursorOnDivider?
board->dividerSelected[selPlayer] pti->dividerSelected : pti->traySelBits == (1 << tileLoc);
: board->traySelBits[selPlayer] == (1 << tileLoc);
if ( !cursorObjSelected ) { if ( !cursorObjSelected ) {
/* nothing to do */ /* nothing to do */
} else if ( cursorOnDivider ) { } else if ( cursorOnDivider ) {
/* just drag the divider */ /* just drag the divider */
board->dividerLoc[selPlayer] = newLoc; pti->dividerLoc = newLoc;
} else if ( board->tradeInProgress[selPlayer] ) { } else if ( pti->tradeInProgress ) {
/* nothing to do */ /* nothing to do */
} else { } else {
XP_S16 newTileLoc; XP_S16 newTileLoc;
/* drag the tile, skipping over the divider if needed */ /* drag the tile, skipping over the divider if needed */
if ( (newLoc == board->dividerLoc[selPlayer]) && (newLoc > 0) ) { if ( (newLoc == pti->dividerLoc) && (newLoc > 0) ) {
newLoc += delta; newLoc += delta;
} }
newTileLoc = newLoc; newTileLoc = newLoc;
@ -606,13 +607,13 @@ tray_moveCursor( BoardCtxt* board, XP_Key cursorKey, XP_Bool preflightOnly,
if ( newTileLoc < nTiles ) { if ( newTileLoc < nTiles ) {
model_moveTileOnTray( board->model, selPlayer, model_moveTileOnTray( board->model, selPlayer,
tileLoc, newTileLoc ); tileLoc, newTileLoc );
board->traySelBits[selPlayer] = (1 << newTileLoc); pti->traySelBits = (1 << newTileLoc);
} else { } else {
board->traySelBits[selPlayer] = 0; /* clear selection */ pti->traySelBits = 0; /* clear selection */
} }
} }
} }
board->trayCursorLoc[selPlayer] = newLoc; pti->trayCursorLoc = newLoc;
/* fix this!!! */ /* fix this!!! */
board->dividerInvalid = XP_TRUE; board->dividerInvalid = XP_TRUE;
@ -700,14 +701,14 @@ void
getFocussedTileCenter( BoardCtxt* board, XP_U16* xp, XP_U16* yp ) getFocussedTileCenter( BoardCtxt* board, XP_U16* xp, XP_U16* yp )
{ {
XP_Rect rect; XP_Rect rect;
XP_S16 selPlayer = board->selPlayer; PerTurnInfo* pti = board->selInfo;
XP_S16 cursorTile = board->trayCursorLoc[selPlayer]; XP_S16 cursorTile = pti->trayCursorLoc;
XP_Bool cursorOnDivider = board->dividerLoc[selPlayer] == cursorTile; XP_Bool cursorOnDivider = pti->dividerLoc == cursorTile;
if ( cursorOnDivider ) { if ( cursorOnDivider ) {
figureDividerRect( board, &rect ); figureDividerRect( board, &rect );
} else { } else {
XP_S16 indx = board->trayCursorLoc[selPlayer]; XP_S16 indx = pti->trayCursorLoc;
adjustForDivider( board, &indx ); adjustForDivider( board, &indx );
XP_ASSERT( indx >= 0 ); XP_ASSERT( indx >= 0 );
figureTrayTileRect( board, indx, &rect ); figureTrayTileRect( board, indx, &rect );
@ -723,7 +724,7 @@ board_moveDivider( BoardCtxt* board, XP_Bool right )
{ {
XP_Bool result = board->trayVisState == TRAY_REVEALED; XP_Bool result = board->trayVisState == TRAY_REVEALED;
if ( result ) { if ( result ) {
XP_U8 loc = board->dividerLoc[board->selPlayer]; XP_U8 loc = board->selInfo->dividerLoc;
loc += MAX_TRAY_TILES + 1; loc += MAX_TRAY_TILES + 1;
loc += right? 1:-1; loc += right? 1:-1;
loc %= MAX_TRAY_TILES + 1; loc %= MAX_TRAY_TILES + 1;