Merge branch 'relay_proxy' of ssh://xwords.git.sourceforge.net/gitroot/xwords/xwords into relay_proxy

This commit is contained in:
Eric House 2010-11-01 21:54:28 -07:00
commit 892f30692b
13 changed files with 256 additions and 115 deletions

View file

@ -25,6 +25,13 @@
android:layout_height="fill_parent"
android:orientation="vertical">
<CheckBox android:id="@+id/game_locked_check"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/game_locked"
android:visibility="gone"
/>
<!-- players -->
<TextView style="@style/config_separator"
android:id="@+id/players_label"

View file

@ -49,6 +49,10 @@
<string name="key_notagain_zoom">key_notagain_zoom</string>
<string name="key_notagain_undo">key_notagain_undo</string>
<string name="key_notagain_done">key_notagain_done</string>
<string name="key_notagain_unlock">key_notagain_unlock</string>
<string name="key_notagain_conndall">key_notagain_conndall</string>
<string name="key_notagain_conndfirst">key_notagain_conndfirst</string>
<string name="key_notagain_conndmid">key_notagain_conndmid</string>
<string name="relayids_extra">org.eehouse.android.xw4.relayids_extra</string>

View file

@ -79,8 +79,8 @@
<string name="board_menu_done">Turn done</string>
<string name="board_menu_juggle">Shuffle</string>
<string name="board_menu_flip">Flip</string>
<string name="board_menu_trade">Exchange</string>
<string name="board_menu_tray">Hide tray</string>
<string name="board_menu_trade">Exchange tiles</string>
<string name="board_menu_tray">Hide rack</string>
<string name="board_submenu_undo">Undo</string>
<string name="board_menu_undo_current">Undo current</string>
<string name="board_menu_undo_last">Undo last</string>
@ -112,7 +112,7 @@
<string name="str_pass"> - %d [time]</string>
<string name="strs_move_across">move (from %s across)</string>
<string name="strs_move_down">move (from %s down)</string>
<string name="strs_tray_at_start">Tray at start: %s</string>
<string name="strs_tray_at_start">Rack at start: %s</string>
<string name="strss_traded_for">Exchanged %s for %s.</string>
<string name="str_phony_rejected">Illegal word in move; turn lost!</string>
<string name="strd_cumulative_score">Cumulative score: %d</string>
@ -153,6 +153,7 @@
<string name="players_label_standalone">Players</string>
<string name="players_label_host">Players (%d local, %d off-device)</string>
<string name="players_label_guest">Players -- local only</string>
<string name="game_locked">Lock settings</string>
<string name="button_add_player">Add player</string>
<string name="button_juggle_players">Shuffle players</string>
@ -184,8 +185,14 @@
<string name="confirm_save">This game is in play. If you
save these changes it must be restarted. Do you want to save
these changes?</string>
<string name="confirm_delete_all">Are you sure you want to
delete all games? This action cannot be undone.</string>
<string name="confirm_delete">Are you sure you want to delete this
game?</string>
<string name="confirm_delete_all">Are you sure you want to delete
all games?</string>
<string name="confirm_reset">Are you sure you want to reset this
game? Resetting erases all moves and any connection
information.</string>
<string name="confirm_delete_dict">Are you sure you want to delete
this dictionary? You will not be able to open any games that use
it.</string>
@ -197,8 +204,8 @@
<string name="color_tiles_summary">Draw tiles using color of
player who played them</string>
<string name="show_arrow">Show board arrow</string>
<string name="show_arrow_summary">Tapped tray tiles land on this
arrow when it is visible</string>
<string name="show_arrow_summary">Tapped rack tiles land on this
arrow when it is visible</string>
<string name="explain_robot">Explain robot moves</string>
<string name="explain_robot_summary">Display score summary after
every robot turn</string>
@ -206,8 +213,8 @@
<string name="skip_confirm_turn_summary">Do NOT display score
summary after every human turn</string>
<string name="title_sort_tiles">Sort new tiles</string>
<string name="summary_sort_tiles">Sort trays whenever new tiles
are added</string>
<string name="summary_sort_tiles">Sort racks whenever new tiles
are added</string>
<string name="ringer_zoom">Volume keys zoom</string>
<string name="ringer_zoom_summary">Zoom board using volume keys</string>
<string name="hide_title">Hide titlebar</string>
@ -292,8 +299,8 @@
<string name="tab_sms">SMS (broken)</string>
<string name="tab_bluetooth">Bluetooth (pending)</string>
<string name="msg_relay_waiting">Connected to relay in room
\"%s\". Waiting for %d player[s].</string>
<string name="msg_relay_waiting">Device %d connected to relay in
room \"%s\". Waiting for %d player[s].</string>
<string name="msg_relay_all_heref">All players are here in room
\"%s\".</string>
<string name="title_relay_status">Connection status.</string>
@ -418,9 +425,15 @@
Or try joining or creating a public room.</string>
<string name="not_again_newgame">The new game you have created has
two players, the first a robot, both on this device. To play
the game, tap it; to change its configuration or for other
options, long-tap it.</string>
two players, the first a robot, both on this device. Tap it to
play; long-tap it to change its configuration or for other
options.</string>
<string name="not_again_newgamenet">The new game you have created
has two players but only one is on this device. To play the
game, tap it, and it will begin by connecting over the internet
looking for that other player in the default no-name
room. Long-tap it to configure - e.g. change the room name - or
for other options.</string>
<string name="not_again_hintprev">This button shows all possible
moves in ascending order (using tiles to the right of the rack
@ -438,9 +451,25 @@
<string name="not_again_undo">This button undos or redoes the
current turn.</string>
<string name="not_again_newgamenet">The new game you have created </string>
<string name="not_again_done">The \"pts\" counter that appears at
the right end of the rack is an alternative to this menu
item.</string>
<string name="not_again_done">Tapping the \"pts\" counter that
appears at the right end of the rack is the easiest way to
commit a move. (There is no shortcut for ending a
trade.)</string>
<string name="not_again_unlock">This game is in play. Some
settings, e.g. the number of players, cannot be changed without
restarting it. When you leave this page you will have a chance
to discard changes to avoid a restart.</string>
<string name="not_again_conndall">You have connected and joined a
game on the relay; the room is now full. The device that
created the room will now assign your initial tiles and play can
begin.</string>
<string name="not_again_conndfirst">You have connected and started
a game in a new room. Once the remaining devices have joined
your room and Crosswords has assigned them tiles the game can
begin.</string>
<string name="not_again_conndmid">You have connected and joined a
game on the relay. You will be notified when the remaining
device[s] have joined your room and play can begin.</string>
</resources>

View file

@ -471,7 +471,7 @@ public class BoardActivity extends XWActivity implements UtilCtxt {
// cmd = JNIThread.JNICmd.CMD_FLIP;
// break;
case R.id.board_menu_trade:
cmd = JNIThread.JNICmd.CMD_TOGGLE_TRADE;
cmd = JNIThread.JNICmd.CMD_TRADE;
break;
case R.id.board_menu_tray:
cmd = JNIThread.JNICmd.CMD_TOGGLE_TRAY;
@ -625,7 +625,9 @@ public class BoardActivity extends XWActivity implements UtilCtxt {
{
CommsTransport.ConndMsg cndmsg =
(CommsTransport.ConndMsg)msg.obj;
Utils.logf( "handleConndMessage: devOrder=%d", cndmsg.m_devOrder );
int naMsg = 0;
int naKey = 0;
String str = null;
if ( cndmsg.m_allHere ) {
// All players have now joined the game. The device that
@ -633,16 +635,38 @@ public class BoardActivity extends XWActivity implements UtilCtxt {
// the first player's turn
String fmt = getString( R.string.msg_relay_all_heref );
str = String.format( fmt, cndmsg.m_room );
if ( cndmsg.m_devOrder > 1 ) {
naMsg = R.string.not_again_conndall;
naKey = R.string.key_notagain_conndall;
}
} else if ( cndmsg.m_nMissing > 0 ) {
String fmt = getString( R.string.msg_relay_waiting );
str = String.format( fmt, cndmsg.m_room, cndmsg.m_nMissing );
str = String.format( fmt, cndmsg.m_devOrder,
cndmsg.m_room, cndmsg.m_nMissing );
if ( cndmsg.m_devOrder == 1 ) {
naMsg = R.string.not_again_conndfirst;
naKey = R.string.key_notagain_conndfirst;
} else {
naMsg = R.string.not_again_conndmid;
naKey = R.string.key_notagain_conndmid;
}
}
if ( null != str ) {
Toast.makeText( BoardActivity.this, str,
Toast.LENGTH_SHORT).show();
final String fstr = str;
Runnable proc = new Runnable() {
public void run() {
Toast.makeText( BoardActivity.this, fstr,
Toast.LENGTH_SHORT).show();
}
};
if ( naMsg == 0 ) {
proc.run();
} else {
showNotAgainDlgThen( naMsg, naKey, proc );
}
}
}
} // handleConndMessage
//////////////////////////////////////////
// XW_UtilCtxt interface implementation //

View file

@ -69,6 +69,8 @@ public class GameConfig extends XWActivity
private static final int NO_NAME_FOUND = PLAYER_EDIT + 4;
private CheckBox m_joinPublicCheck;
private CheckBox m_gameLockedCheck;
private boolean m_isLocked;
private LinearLayout m_publicRoomsSet;
private LinearLayout m_privateRoomsSet;
@ -98,9 +100,23 @@ public class GameConfig extends XWActivity
private CommonPrefs m_cp;
private boolean m_canDoSMS = false;
private boolean m_canDoBT = false;
private int m_nMoves = 0;
private boolean m_gameStarted = false;
private CommsAddrRec.CommsConnType[] m_types;
private String[] m_connStrings;
private static final int[] s_disabledWhenLocked = { R.id.juggle_players
,R.id.add_player
,R.id.dict_spinner
,R.id.join_public_room_check
,R.id.room_edit
,R.id.advertise_new_room_check
,R.id.room_spinner
,R.id.refresh_button
,R.id.hints_allowed
,R.id.use_timer
,R.id.timer_minutes_edit
,R.id.smart_robot
,R.id.phonies_spinner
};
class RemoteChoices extends XWListAdapter {
public RemoteChoices() { super( GameConfig.this, m_gi.nPlayers ); }
@ -127,7 +143,7 @@ public class GameConfig extends XWActivity
}
@Override
protected Dialog onCreateDialog( int id )
protected Dialog onCreateDialog( final int id )
{
Dialog dialog = super.onCreateDialog( id );
if ( null == dialog ) {
@ -199,41 +215,40 @@ public class GameConfig extends XWActivity
}
});
break;
case CONFIRM_CHANGE:
dialog = new AlertDialog.Builder( this )
.setTitle( R.string.confirm_save_title )
.setMessage( R.string.confirm_save )
.setPositiveButton( R.string.button_save,
new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg,
int whichButton ) {
applyChanges( true );
finish();
}
})
.setNegativeButton( R.string.button_discard,
new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg,
int whichButton ) {
finish();
}
})
.create();
break;
case CONFIRM_CHANGE_PLAY:
dialog = new AlertDialog.Builder( this )
case CONFIRM_CHANGE:
dlpos = new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg,
int whichButton ) {
applyChanges( true );
if ( CONFIRM_CHANGE_PLAY == id ) {
launchGame();
}
}
};
ab = new AlertDialog.Builder( this )
.setTitle( R.string.confirm_save_title )
.setMessage( R.string.confirm_save )
.setPositiveButton( R.string.button_save,
new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg,
int whichButton ) {
applyChanges( true );
launchGame();
}
})
.setNegativeButton( R.string.button_cancel, null )
.create();
.setPositiveButton( R.string.button_save, dlpos );
if ( CONFIRM_CHANGE_PLAY == id ) {
dlpos = new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg,
int whichButton ) {
launchGame();
}
};
} else {
dlpos = null;
}
ab.setNegativeButton( R.string.button_discard, dlpos );
dialog = ab.create();
dialog.setOnDismissListener( new DialogInterface.
OnDismissListener() {
public void onDismiss( DialogInterface di ) {
finish();
}
});
break;
case NO_NAME_FOUND:
dialog = new AlertDialog.Builder( this )
@ -350,11 +365,23 @@ public class GameConfig extends XWActivity
m_path = m_path.substring( 1 );
}
setContentView(R.layout.game_config);
int gamePtr = XwJNI.initJNI();
m_giOrig = new CurGameInfo( this );
GameUtils.loadMakeGame( this, gamePtr, m_giOrig, m_path );
m_nMoves = XwJNI.model_getNMoves( gamePtr );
m_giOrig.setInProgress( 0 < m_nMoves );
m_gameStarted = XwJNI.model_getNMoves( gamePtr ) > 0
|| XwJNI.comms_isConnected( gamePtr );
m_giOrig.setInProgress( m_gameStarted );
if ( m_gameStarted ) {
m_gameLockedCheck = (CheckBox)findViewById( R.id.game_locked_check );
m_gameLockedCheck.setVisibility( View.VISIBLE );
m_gameLockedCheck.setChecked( true );
m_gameLockedCheck.setOnClickListener( this );
handleLockedChange();
}
int curSel = listAvailableDicts( m_giOrig.dictName );
m_giOrig.dictLang =
DictLangCache.getLangCode( this,
@ -373,8 +400,6 @@ public class GameConfig extends XWActivity
m_car = new CommsAddrRec( m_carOrig );
setContentView(R.layout.game_config);
m_notNetworkedGame = DeviceRole.SERVER_STANDALONE == m_gi.serverRole;
if ( !m_notNetworkedGame ) {
@ -463,6 +488,14 @@ public class GameConfig extends XWActivity
loadPlayers();
} else if ( m_joinPublicCheck == view ) {
adjustConnectStuff();
} else if ( m_gameLockedCheck == view ) {
showNotAgainDlgThen( R.string.not_again_unlock,
R.string.key_notagain_unlock,
new Runnable() {
public void run() {
handleLockedChange();
}
});
} else if ( m_refreshRoomsButton == view ) {
refreshNames();
} else if ( m_playButton == view ) {
@ -471,7 +504,7 @@ public class GameConfig extends XWActivity
// from here if there's no confirmation needed, or launch
// a new dialog whose OK button does the same thing.
saveChanges();
if ( 0 >= m_nMoves ) { // no confirm needed
if ( !m_gameStarted ) { // no confirm needed
applyChanges( true );
launchGame();
} else if ( m_giOrig.changesMatter(m_gi)
@ -494,7 +527,7 @@ public class GameConfig extends XWActivity
boolean consumed = false;
if ( keyCode == KeyEvent.KEYCODE_BACK ) {
saveChanges();
if ( 0 >= m_nMoves ) { // no confirm needed
if ( !m_gameStarted ) { // no confirm needed
applyChanges( true );
} else if ( m_giOrig.changesMatter(m_gi)
|| (! m_notNetworkedGame
@ -544,6 +577,7 @@ public class GameConfig extends XWActivity
}
} );
m_playerLayout.addView( view );
view.setEnabled( !m_isLocked );
View divider = factory.inflate( R.layout.divider_view, null );
divider.setVisibility( View.VISIBLE );
@ -700,6 +734,26 @@ public class GameConfig extends XWActivity
m_publicRoomsSet.setVisibility( View.GONE );
}
}
// User's toggling whether everything's locked. That should mean
// we enable/disable a bunch of widgits. And if we're going from
// unlocked to locked we need to confirm that everything can be
// reverted.
private void handleLockedChange()
{
boolean locking = m_gameLockedCheck.isChecked();
m_isLocked = locking;
for ( int id : s_disabledWhenLocked ) {
View view = findViewById( id );
view.setEnabled( !m_isLocked );
}
if ( null != m_playerLayout ) {
for ( int ii = m_playerLayout.getChildCount()-1; ii >= 0; --ii ) {
View view = m_playerLayout.getChildAt( ii );
view.setEnabled( !m_isLocked );
}
}
}
private int connTypeToPos( CommsAddrRec.CommsConnType typ )
{

View file

@ -274,15 +274,32 @@ public class GamesList extends XWListActivity
private boolean handleMenuItem( int menuID, int position )
{
boolean handled = true;
byte[] stream;
String invalPath = null;
String path = GameUtils.gamesList( this )[position];
final String path = GameUtils.gamesList( this )[position];
if ( R.id.list_item_delete == menuID ) {
GameUtils.deleteGame( this, path );
invalPath = path;
DialogInterface.OnClickListener lstnr =
new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg, int ii ) {
GameUtils.deleteGame( GamesList.this, path );
m_adapter.inval( path );
onContentChanged();
}
};
showConfirmThen( R.string.confirm_delete, lstnr );
} else if ( R.id.list_item_reset == menuID ) {
DialogInterface.OnClickListener lstnr =
new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg, int ii ) {
GameUtils.resetGame( GamesList.this,
path, path );
m_adapter.inval( path );
onContentChanged();
}
};
showConfirmThen( R.string.confirm_reset, lstnr );
} else {
String invalPath = null;
String[] missingName = new String[1];
int[] missingLang = new int[1];
boolean hasDict = GameUtils.gameDictHere( this, path,
@ -296,11 +313,6 @@ public class GamesList extends XWListActivity
m_invalPath = path;
break;
case R.id.list_item_reset:
// TODO confirm_data_loss();
GameUtils.resetGame( this, path, path );
invalPath = path;
break;
case R.id.list_item_new_from:
String newName = GameUtils.resetGame( this, path );
invalPath = newName;
@ -311,7 +323,7 @@ public class GamesList extends XWListActivity
if ( summary.inNetworkGame() ) {
showOKOnlyDialog( R.string.no_copy_network );
} else {
stream = GameUtils.savedGame( this, path );
byte[] stream = GameUtils.savedGame( this, path );
newName = GameUtils.saveGame( this, stream );
DBUtils.saveSummary( this, newName, summary );
}
@ -331,14 +343,13 @@ public class GamesList extends XWListActivity
break;
}
}
}
if ( null != invalPath ) {
m_adapter.inval( invalPath );
}
if ( handled ) {
onContentChanged();
if ( null != invalPath ) {
m_adapter.inval( invalPath );
}
if ( handled ) {
onContentChanged();
}
}
return handled;

View file

@ -30,7 +30,6 @@ import android.graphics.Rect;
public class XWListItem extends LinearLayout {
private int m_position;
private ImageButton m_button;
private Context m_context;
DeleteCallback m_cb;
@ -64,4 +63,15 @@ public class XWListItem extends LinearLayout {
} );
button.setVisibility( View.VISIBLE );
}
@Override
public void setEnabled( boolean enabled )
{
ImageButton button = (ImageButton)getChildAt( 1 );
button.setEnabled( enabled );
// calling super here means the list item can't be opened for
// the user to inspect data. Might want to reconsider this.
// PENDING
super.setEnabled( enabled );
}
}

View file

@ -61,7 +61,7 @@ public class JNIThread extends Thread {
CMD_JUGGLE,
CMD_FLIP,
CMD_TOGGLE_TRAY,
CMD_TOGGLE_TRADE,
CMD_TRADE,
CMD_UNDO_CUR,
CMD_UNDO_LAST,
CMD_HINT,
@ -365,7 +365,7 @@ public class JNIThread extends Thread {
case CMD_TOGGLE_TRAY:
draw = toggleTray();
break;
case CMD_TOGGLE_TRADE:
case CMD_TRADE:
draw = XwJNI.board_beginTrade( m_jniGamePtr );
break;
case CMD_UNDO_CUR:

View file

@ -1215,10 +1215,8 @@ invalCellsWithTiles( BoardCtxt* board )
*/
for ( row = model_numRows( model )-1; row >= 0; --row ) {
for ( col = model_numCols( model )-1; col >= 0; --col ) {
Tile tile;
XP_Bool ignore;
if ( model_getTile( model, col, row, includePending,
turn, &tile, &ignore, &ignore, &ignore ) ) {
turn, NULL, NULL, NULL, NULL ) ) {
XP_U16 boardCol, boardRow;
flipIf( board, col, row, &boardCol, &boardRow );
invalCell( board, boardCol, boardRow );
@ -2327,13 +2325,12 @@ cellOccupied( const BoardCtxt* board, XP_U16 col, XP_U16 row,
XP_Bool inclPending )
{
Tile tile;
XP_Bool ignr;
XP_Bool result;
flipIf( board, col, row, &col, &row );
result = model_getTile( board->model, col, row, inclPending,
board->selPlayer, &tile,
&ignr, &ignr, &ignr );
NULL, NULL, NULL );
return result;
} /* cellOccupied */
@ -2379,13 +2376,13 @@ XP_Bool
holdsPendingTile( BoardCtxt* board, XP_U16 pencol, XP_U16 penrow )
{
Tile tile;
XP_Bool ignore, isPending;
XP_Bool isPending;
XP_U16 modcol, modrow;
flipIf( board, pencol, penrow, &modcol, &modrow );
return model_getTile( board->model, modcol, modrow, XP_TRUE,
board->selPlayer, &tile, &ignore, &isPending,
(XP_Bool*)NULL )
board->selPlayer, &tile, NULL, &isPending,
NULL )
&& isPending;
} /* holdsPendingTile */
@ -3232,16 +3229,14 @@ boardCellChanged( void* p_board, XP_U16 turn, XP_U16 modelCol, XP_U16 modelRow,
XP_Bool added )
{
BoardCtxt* board = (BoardCtxt*)p_board;
XP_Bool pending, found, ignoreBlank;
Tile ignoreTile;
XP_Bool pending, found;
XP_U16 col, row;
flipIf( board, modelCol, modelRow, &col, &row );
/* for each player, check if the tile overwrites the cursor */
found = model_getTile( board->model, modelCol, modelRow, XP_TRUE, turn,
&ignoreTile, &ignoreBlank, &pending,
(XP_Bool*)NULL );
NULL, NULL, &pending, NULL );
XP_ASSERT( !added || found ); /* if added is true so must found be */

View file

@ -91,14 +91,13 @@ ddStartBoard( BoardCtxt* board, XP_U16 xx, XP_U16 yy )
trayVisible = board->trayVisState == TRAY_REVEALED;
if ( trayVisible && holdsPendingTile( board, col, row ) ) {
XP_U16 modelc, modelr;
XP_Bool ignore;
ds->dtype = DT_TILE;
flipIf( board, col, row, &modelc, &modelr );
found = model_getTile( board->model, modelc, modelr, XP_TRUE,
board->selPlayer, &ds->tile, &ds->isBlank,
&ignore, &ignore );
NULL, NULL );
XP_ASSERT( found );
} else {
/* If we're not dragging a tile, we can either drag the board (scroll)

View file

@ -732,7 +732,7 @@ localGetBoardTile( EngineCtxt* engine, XP_U16 col, XP_U16 row,
XP_Bool substBlank )
{
Tile result;
XP_Bool isBlank, ignore;
XP_Bool isBlank;
if ( !engine->searchHorizontal ) {
XP_U16 tmp = col;
@ -742,7 +742,7 @@ localGetBoardTile( EngineCtxt* engine, XP_U16 col, XP_U16 row,
if ( model_getTile( engine->model, col, row, XP_FALSE,
0, /* don't get pending, so turn doesn't matter */
&result, &isBlank, &ignore, (XP_Bool*)NULL ) ) {
&result, &isBlank, NULL, NULL ) ) {
if ( isBlank && substBlank ) {
result = engine->blankTile;
}

View file

@ -327,10 +327,16 @@ model_getTile( const ModelCtxt* model, XP_U16 col, XP_U16 row,
if ( (cellTile & TILE_EMPTY_BIT) != 0 ) {
return XP_FALSE;
}
*tileP = cellTile & TILE_VALUE_MASK;
*isBlank = IS_BLANK(cellTile);
*pendingP = pending;
if ( NULL != tileP ) {
*tileP = cellTile & TILE_VALUE_MASK;
}
if ( NULL != isBlank ) {
*isBlank = IS_BLANK(cellTile);
}
if ( NULL != pendingP ) {
*pendingP = pending;
}
if ( !!recentP ) {
*recentP = (cellTile & PREV_MOVE_BIT) != 0;
}
@ -1007,12 +1013,11 @@ model_moveTrayToBoard( ModelCtxt* model, XP_S16 turn, XP_U16 col, XP_U16 row,
XP_Bool
model_redoPendingTiles( ModelCtxt* model, XP_S16 turn )
{
XP_Bool changed = XP_FALSE;
XP_U16 actualCnt = 0;
PlayerCtxt* player = &model->players[turn];
XP_U16 nUndone = player->nUndone;
changed = nUndone > 0;
if ( changed ) {
if ( nUndone > 0 ) {
PendingTile pendingTiles[nUndone];
PendingTile* pt = pendingTiles;
@ -1031,11 +1036,16 @@ model_redoPendingTiles( ModelCtxt* model, XP_S16 turn )
}
foundAt = model_trayContains( model, turn, tile );
XP_ASSERT( foundAt >= 0 );
model_moveTrayToBoard( model, turn, pt->col, pt->row,
foundAt, pt->tile & ~TILE_BLANK_BIT );
if ( !model_getTile( model, pt->col, pt->row, XP_FALSE, turn,
NULL, NULL, NULL, NULL ) ) {
model_moveTrayToBoard( model, turn, pt->col, pt->row,
foundAt, pt->tile & ~TILE_BLANK_BIT );
++actualCnt;
}
}
}
return changed;
return actualCnt > 0;
}
void

View file

@ -317,11 +317,10 @@ static XP_Bool
modelIsEmptyAt( const ModelCtxt* model, XP_U16 col, XP_U16 row )
{
Tile tile;
XP_Bool ignore;
XP_Bool found;
found = model_getTile( model, col, row, XP_FALSE, -1, &tile,
&ignore, &ignore, (XP_Bool*)NULL );
NULL, NULL, NULL );
return !found;
} /* modelIsEmptyAt */
@ -643,11 +642,10 @@ scoreWord( const ModelCtxt* model, MoveInfo* movei, /* new tiles */
++tiles;
--nTiles;
} else { /* placed on the board before this move */
XP_Bool ignore;
tileMultiplier = 1;
(void)model_getTile( model, col, row, XP_FALSE, -1, &tile,
&isBlank, &ignore, (XP_Bool*)NULL );
&isBlank, NULL, NULL );
XP_ASSERT( (tile & TILE_VALUE_MASK) == tile );
}