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

View file

@ -172,8 +172,8 @@ figureHintAtts( BoardCtxt* board, XP_U16 col, XP_U16 row )
BdHintLimits limits;
if ( dragDropGetHintLimits( board, &limits ) ) {
/* do nothing */
} else if ( board->hasHintRect[board->selPlayer] ) {
limits = board->limits[board->selPlayer];
} else if ( board->selInfo->hasHintRect ) {
limits = board->selInfo->limits;
} else {
break;
}
@ -278,7 +278,7 @@ drawBoard( BoardCtxt* board )
}
if ( board->trayVisState == TRAY_REVEALED ) {
BoardArrow* arrow = &board->boardArrow[board->selPlayer];
BoardArrow* arrow = &board->selInfo->boardArrow;
if ( arrow->visible ) {
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->focusHasDived ) {
if ( (col == board->bdCursor[board->selPlayer].col)
&& (row == board->bdCursor[board->selPlayer].row) ) {
if ( (col == board->selInfo->bdCursor.col)
&& (row == board->selInfo->bdCursor.row) ) {
focussed = XP_TRUE;
}
} 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.
*
@ -54,7 +54,7 @@ typedef enum {
} DragType;
typedef struct DragState {
typedef struct _DragState {
DragType dtype;
XP_Bool didMove; /* there was change during the drag; not a
tap */
@ -65,7 +65,7 @@ typedef struct DragState {
DragObjInfo cur;
} DragState;
typedef struct BoardArrow { /* gets flipped along with board */
typedef struct _BoardArrow { /* gets flipped along with board */
XP_U8 col;
XP_U8 row;
XP_Bool vert;
@ -73,7 +73,7 @@ typedef struct BoardArrow { /* gets flipped along with board */
} BoardArrow;
#ifdef KEYBOARD_NAV
typedef struct BdCursorLoc {
typedef struct _BdCursorLoc {
XP_U8 col;
XP_U8 row;
} BdCursorLoc;
@ -83,7 +83,7 @@ typedef struct BdCursorLoc {
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 there are (local) players, but they can all use the same window. */
typedef struct MiniWindowStuff {
typedef struct _MiniWindowStuff {
void* closure;
const XP_UCHAR* text;
XP_Rect rect;
@ -92,6 +92,29 @@ typedef struct MiniWindowStuff {
enum { MINIWINDOW_VALHINT, MINIWINDOW_TRADING };
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 {
/* BoardVTable* vtable; */
ModelCtxt* model;
@ -133,7 +156,6 @@ struct BoardCtxt {
XP_Bool disableArrow;
XP_Bool hideValsInTray;
XP_Bool tradeInProgress[MAX_NUM_PLAYERS];
XP_Bool eraseTray;
XP_Bool boardObscuresTray;
XP_Bool boardHidesTray;
@ -144,22 +166,18 @@ struct BoardCtxt {
/* Unless KEYBOARD_NAV is defined, this does not change */
BoardObjectType focussed;
BoardArrow boardArrow[MAX_NUM_PLAYERS];
#ifdef KEYBOARD_NAV
XP_Rect scoreRects[MAX_NUM_PLAYERS];
BdCursorLoc bdCursor[MAX_NUM_PLAYERS];
XP_Bool focusHasDived;
#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 */
XP_Rect scoreBdBounds;
XP_Rect timerBounds;
XP_U8 selPlayer; /* which player is selected (!= turn) */
PerTurnInfo pti[MAX_NUM_PLAYERS];
PerTurnInfo* selInfo;
/* tray state */
XP_U8 trayScaleH;
XP_U8 trayScaleV;
@ -175,9 +193,7 @@ struct BoardCtxt {
XP_Bool tradingMiniWindowInvalid;
TileBit trayInvalBits;
TileBit traySelBits[MAX_NUM_PLAYERS];
#ifdef KEYBOARD_NAV
XP_U8 trayCursorLoc[MAX_NUM_PLAYERS]; /* includes divider!!! */
XP_U8 scoreCursorLoc;
#endif
@ -186,10 +202,6 @@ struct BoardCtxt {
XP_Bool showCellValues;
XP_Bool showColors;
#ifdef XWFEATURE_SEARCHLIMIT
XP_Bool hasHintRect[MAX_NUM_PLAYERS];
BdHintLimits limits[MAX_NUM_PLAYERS];
#endif
MPSLOT
};
@ -197,7 +209,7 @@ struct BoardCtxt {
#define valHintMiniWindowActive( board ) \
((XP_Bool)((board)->miniWindowStuff[MINIWINDOW_VALHINT].text != NULL))
#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 */
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
* reserved.
@ -114,15 +114,14 @@ ddStartTray( BoardCtxt* board, XP_U16 x, XP_U16 y )
XP_S16 index = pointToTileIndex( board, x, y, &onDivider );
canDrag = onDivider || index >= 0;
if ( canDrag ) {
XP_S16 selPlayer = board->selPlayer;
if ( onDivider ) {
board->dividerInvalid = XP_TRUE;
ds->start.u.tray.index = board->dividerLoc[selPlayer];
ds->start.u.tray.index = board->selInfo->dividerLoc;
ds->dtype = DT_DIVIDER;
} else {
Tile tile;
tile = model_getPlayerTile( board->model, selPlayer, index );
tile = model_getPlayerTile( board->model, board->selPlayer, index );
ds->isBlank =
tile == dict_getBlankTile( model_getDictionary(board->model) );
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
currently selected tile. */
board_invalTrayTiles( board, board->traySelBits[selPlayer] );
board_invalTrayTiles( board, board->selInfo->traySelBits );
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 ) {
if ( OBJ_BOARD == newObj && ds->didMove ) {
XP_Bool makeActive = ds->start.u.board.row <= ds->cur.u.board.row;
board->hasHintRect[board->selPlayer] = makeActive;
board->selInfo->hasHintRect = makeActive;
if ( makeActive ) {
setLimitsFrom( board, &board->limits[board->selPlayer] );
setLimitsFrom( board, &board->selInfo->limits );
} else {
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.
*
@ -164,7 +164,7 @@ drawScoreBoard( BoardCtxt* board )
for ( dp = datum, i = 0; i < nPlayers; ++dp, ++i ) {
XP_Rect innerRect;
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.height = dp->height;
@ -176,7 +176,7 @@ drawScoreBoard( BoardCtxt* board )
draw_score_drawPlayer( board->draw, &innerRect, &scoreRect,
&dp->dsi );
#ifdef KEYBOARD_NAV
XP_MEMCPY( &board->scoreRects[i], &scoreRect,
XP_MEMCPY( &board->pti[i].scoreRects, &scoreRect,
sizeof(scoreRect) );
if ( i == cursorIndex ) {
cursorRect = scoreRect;
@ -245,10 +245,11 @@ figureScorePlayerTapped( BoardCtxt* board, XP_U16 x, XP_U16 y )
left -= board->remDim;
if ( left >= 0 ) {
for ( result = 0; result < nPlayers; ++result ) {
if ( left < board->scoreDims[result] ) {
PerTurnInfo* pti = board->pti + result;
if ( left < pti->scoreDims ) {
break;
}
left -= board->scoreDims[result];
left -= pti->scoreDims;
}
}
if ( result >= nPlayers ) {

View file

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