take
@@ -25,12 +25,12 @@
New with this release
- - Don't crash (even occasionally) when closing the wordlist
- browser. (Reported via Google; thanks!)
- - Prevent setting wordlist browser min word length higher than
- max
- - Don't include current player's tiles in remaining
- tiles display
+ - For better navigation with lots of saved games, make the
+ scrollbar thumb draggable (and move it to the left side
+ where it doesn't obscure anything)
+ - When space is limited in Games List display, truncate player
+ name rather than score
+ - Include latest Catalan translations (from Weblate)
(The full changelog
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTService.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTService.java
index 402680e8b..2f1ebcc0d 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTService.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTService.java
@@ -1095,60 +1095,29 @@ public class BTService extends XWService {
m_sender = null;
}
+ @Override
+ void postNotification( String device, int gameID, long rowid )
+ {
+ String body = LocUtils.getString( this, R.string.new_bt_body_fmt,
+ device );
+
+ GameUtils.postInvitedNotification( this, gameID, body, rowid );
+
+ postEvent( MultiEvent.BT_GAME_CREATED, rowid );
+ }
+
private BTCmd makeOrNotify( NetLaunchInfo nli, String btName,
String btAddr )
{
BTCmd result;
- if ( checkNotDupe( nli ) ) {
- if ( DictLangCache.haveDict( this, nli.lang, nli.dict ) ) {
- result = makeGame( nli, btName, btAddr );
- } else {
- Intent intent = MultiService
- .makeMissingDictIntent( this, nli,
- DictFetchOwner.OWNER_BT );
- // NetLaunchInfo.putExtras( intent, gameID, btName, btAddr );
- MultiService.postMissingDictNotification( this, intent,
- nli.gameID() );
- result = BTCmd.INVITE_ACCPT; // ???
- }
+ if ( handleInvitation( nli, btName, DictFetchOwner.OWNER_BT ) ) {
+ result = BTCmd.INVITE_ACCPT;
} else {
result = BTCmd.INVITE_DUP_INVITE; // dupe of rematch
}
return result;
}
- private BTCmd makeGame( NetLaunchInfo nli, String sender,
- String senderAddress )
- {
- BTCmd result;
- long[] rowids = DBUtils.getRowIDsFor( BTService.this, nli.gameID() );
- if ( null == rowids || 0 == rowids.length ) {
- CommsAddrRec addr = nli.makeAddrRec( BTService.this );
- long rowid = GameUtils.makeNewMultiGame( BTService.this, nli,
- m_btMsgSink,
- getUtilCtxt() );
- if ( DBUtils.ROWID_NOTFOUND == rowid ) {
- result = BTCmd.INVITE_FAILED;
- } else {
- if ( null != nli.gameName && 0 < nli.gameName.length() ) {
- DBUtils.setName( BTService.this, rowid, nli.gameName );
- }
- result = BTCmd.INVITE_ACCPT;
- String body = LocUtils.getString( BTService.this,
- R.string.new_bt_body_fmt,
- sender );
-
- GameUtils.postInvitedNotification( this, nli.gameID(), body,
- rowid );
-
- postEvent( MultiEvent.BT_GAME_CREATED, rowid );
- }
- } else {
- result = BTCmd.INVITE_DUPID;
- }
- return result;
- }
-
private DataOutputStream connect( BluetoothSocket socket, BTCmd cmd )
{
String name = socket.getRemoteDevice().getName();
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardCanvas.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardCanvas.java
index 5b0dcd7a3..f58412ae9 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardCanvas.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardCanvas.java
@@ -510,7 +510,9 @@ public class BoardCanvas extends Canvas implements DrawCtx {
public void score_pendingScore( Rect rect, int score, int playerNum,
int curTurn, int flags )
{
- String text = score >= 0? String.format( "%d", score ) : "??";
+ Log.d( TAG, "pendingScore(playerNum=%d, curTurn=%d)",
+ playerNum, curTurn );
+
int otherIndx = (0 == (flags & CELL_ISCURSOR))
? CommonPrefs.COLOR_BACKGRND : CommonPrefs.COLOR_FOCUS;
++rect.top;
@@ -522,6 +524,7 @@ public class BoardCanvas extends Canvas implements DrawCtx {
}
m_fillPaint.setColor( playerColor );
+ String text = score >= 0? String.format( "%d", score ) : "??";
rect.bottom -= rect.height() / 2;
drawCentered( text, rect, null );
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DbgUtils.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DbgUtils.java
index cddf31432..f6116d8de 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DbgUtils.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DbgUtils.java
@@ -20,18 +20,24 @@
package org.eehouse.android.xw4;
-
import android.content.Context;
+import android.content.Intent;
import android.database.Cursor;
import android.database.DatabaseUtils;
+import android.os.Bundle;
import android.os.Looper;
+import android.text.TextUtils;
import android.text.format.Time;
+import java.util.ArrayList;
+import java.util.Formatter;
+import java.util.Iterator;
+import java.util.Set;
+
import junit.framework.Assert;
import org.eehouse.android.xw4.loc.LocUtils;
-import java.util.Formatter;
public class DbgUtils {
private static final String TAG = DbgUtils.class.getSimpleName();
@@ -117,21 +123,17 @@ public class DbgUtils {
}
}
- // public static void printIntent( Intent intent )
- // {
- // if ( s_doLog ) {
- // Bundle bundle = intent.getExtras();
- // ArrayList al = new ArrayList();
- // if ( null != bundle ) {
- // Set keys = bundle.keySet();
- // Iterator iter = keys.iterator();
- // while ( iter.hasNext() ) {
- // al.add( iter.next() );
- // }
- // }
- // DbgUtils.logf( "intent extras: %s", TextUtils.join( ", ", al ) );
- // }
- // }
+ static String extrasToString( Intent intent )
+ {
+ Bundle bundle = intent.getExtras();
+ ArrayList al = new ArrayList();
+ if ( null != bundle ) {
+ for ( String key : bundle.keySet() ) {
+ al.add( key + ":" + bundle.get(key) );
+ }
+ }
+ return TextUtils.join( ", ", al );
+ }
public static void dumpCursor( Cursor cursor )
{
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GameUtils.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GameUtils.java
index c52574756..97e6b8b70 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GameUtils.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GameUtils.java
@@ -1257,7 +1257,6 @@ public class GameUtils {
private static class ResendTask extends AsyncTask {
private Context m_context;
- private HashMap m_games;
private ResendDoneProc m_doneProc;
private CommsConnType m_filter;
private int m_nSent = 0;
@@ -1273,15 +1272,16 @@ public class GameUtils {
@Override
protected Void doInBackground( Void... unused )
{
- m_games = DBUtils.getGamesWithSendsPending( m_context );
+ HashMap games
+ = DBUtils.getGamesWithSendsPending( m_context );
- Iterator iter = m_games.keySet().iterator();
+ Iterator iter = games.keySet().iterator();
while ( iter.hasNext() ) {
long rowid = iter.next();
// If we're looking for a specific type, check
if ( null != m_filter ) {
- CommsConnTypeSet gameSet = m_games.get( rowid );
+ CommsConnTypeSet gameSet = games.get( rowid );
if ( gameSet != null && ! gameSet.contains( m_filter ) ) {
continue;
}
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java
index b2b09d385..9296d70d6 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java
@@ -2476,6 +2476,7 @@ public class GamesListDelegate extends ListDelegateBase
private void tryStartsFromIntent( Intent intent )
{
+ Log.d( TAG, "tryStartsFromIntent(extras={%s})", DbgUtils.extrasToString( intent ) );
startFirstHasDict( intent );
startNewNetGame( intent );
startHasGameID( intent );
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayService.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayService.java
index b0df9dd35..b4ce7a02f 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayService.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayService.java
@@ -23,7 +23,6 @@ package org.eehouse.android.xw4;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
-import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.text.TextUtils;
@@ -267,51 +266,16 @@ public class RelayService extends XWService
{
Log.d( TAG, "receiveInvitation: got nli from %d: %s", srcDevID,
nli.toString() );
- if ( checkNotDupe( nli ) ) {
- makeOrNotify( nli );
+ if ( !handleInvitation( nli, null, DictFetchOwner.OWNER_RELAY ) ) {
+ Log.d( TAG, "handleInvitation() failed" );
}
}
- private void makeOrNotify( NetLaunchInfo nli )
+ @Override
+ void postNotification( String device, int gameID, long rowid )
{
- if ( DictLangCache.haveDict( this, nli.lang, nli.dict ) ) {
- makeGame( nli );
- } else {
- Intent intent = MultiService
- .makeMissingDictIntent( this, nli,
- DictFetchOwner.OWNER_RELAY );
- MultiService.postMissingDictNotification( this, intent,
- nli.gameID() );
- }
- }
-
- private void makeGame( NetLaunchInfo nli )
- {
- long[] rowids = DBUtils.getRowIDsFor( this, nli.gameID() );
- if ( (null == rowids || 0 == rowids.length)
- || XWPrefs.getRelayInviteToSelfEnabled( this )) {
-
- if ( DictLangCache.haveDict( this, nli.lang, nli.dict ) ) {
- long rowid = GameUtils.makeNewMultiGame( this, nli,
- new RelayMsgSink(),
- getUtilCtxt() );
- if ( DBUtils.ROWID_NOTFOUND != rowid ) {
- if ( null != nli.gameName && 0 < nli.gameName.length() ) {
- DBUtils.setName( this, rowid, nli.gameName );
- }
- String body = LocUtils.getString( this,
- R.string.new_relay_body );
- GameUtils.postInvitedNotification( this, nli.gameID(), body,
- rowid );
- }
- } else {
- Intent intent = MultiService
- .makeMissingDictIntent( this, nli,
- DictFetchOwner.OWNER_RELAY );
- MultiService.postMissingDictNotification( this, intent,
- nli.gameID() );
- }
- }
+ String body = LocUtils.getString( this, R.string.new_relay_body );
+ GameUtils.postInvitedNotification( this, gameID, body, rowid );
}
// Exists to get incoming data onto the main thread
@@ -1268,19 +1232,18 @@ public class RelayService extends XWService
}
- private static class AsyncSender extends AsyncTask {
+ private static class AsyncSender extends Thread {
private Context m_context;
private HashMap> m_msgHash;
- public AsyncSender( Context context,
- HashMap> msgHash )
+ AsyncSender( Context context, HashMap> msgHash )
{
m_context = context;
m_msgHash = msgHash;
}
@Override
- protected Void doInBackground( Void... ignored )
+ public void run()
{
// format: total msg lenth: 2
// number-of-relayIDs: 2
@@ -1327,9 +1290,9 @@ public class RelayService extends XWService
}
msgLen += thisLen;
}
+
// Now open a real socket, write size and proto, and
// copy in the formatted buffer
-
Socket socket = NetUtils.makeProxySocket( m_context, 8000 );
if ( null != socket ) {
DataOutputStream outStream =
@@ -1345,15 +1308,14 @@ public class RelayService extends XWService
} catch ( java.io.IOException ioe ) {
Log.ex( TAG, ioe );
}
- return null;
- } // doInBackground
+ } // run
}
private static void sendToRelay( Context context,
HashMap> msgHash )
{
if ( null != msgHash ) {
- new AsyncSender( context, msgHash ).execute();
+ new AsyncSender( context, msgHash ).start();
} else {
Log.w( TAG, "sendToRelay: null msgs" );
}
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/SMSService.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/SMSService.java
index c5a226eec..30b35be4f 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/SMSService.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/SMSService.java
@@ -504,20 +504,7 @@ public class SMSService extends XWService {
switch( cmd ) {
case INVITE:
String nliData = dis.readUTF();
- NetLaunchInfo nli = new NetLaunchInfo( this, nliData );
- if ( nli.isValid() && checkNotDupe( nli ) ) {
- if ( DictLangCache.haveDict( this, nli.lang, nli.dict ) ) {
- makeForInvite( phone, nli );
- } else {
- Intent intent = MultiService
- .makeMissingDictIntent( this, nli,
- DictFetchOwner.OWNER_SMS );
- MultiService.postMissingDictNotification( this, intent,
- nli.gameID() );
- }
- } else {
- Log.w( TAG, "invalid nli from: %s", nliData );
- }
+ makeForInvite( phone, new NetLaunchInfo( this, nliData ) );
break;
case DATA:
int gameID = dis.readInt();
@@ -632,7 +619,8 @@ public class SMSService extends XWService {
return success;
}
- private void postNotification( String phone, int gameID, long rowid )
+ @Override
+ protected void postNotification( String phone, int gameID, long rowid )
{
String owner = Utils.phoneToContact( this, phone, true );
String body = LocUtils.getString( this, R.string.new_name_body_fmt,
@@ -642,11 +630,9 @@ public class SMSService extends XWService {
private void makeForInvite( String phone, NetLaunchInfo nli )
{
- long rowid = GameUtils.makeNewMultiGame( this, nli,
- new SMSMsgSink( this ),
- getUtilCtxt() );
- postNotification( phone, nli.gameID(), rowid );
- ackInvite( phone, nli.gameID() );
+ if ( handleInvitation( nli, phone, DictFetchOwner.OWNER_SMS ) ) {
+ ackInvite( phone, nli.gameID() );
+ }
}
private PendingIntent makeStatusIntent( String msg )
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/WiDirService.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/WiDirService.java
index 09dd4c081..91220a8da 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/WiDirService.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/WiDirService.java
@@ -762,19 +762,18 @@ public class WiDirService extends XWService {
String nliData = intent.getStringExtra( KEY_NLI );
NetLaunchInfo nli = new NetLaunchInfo( this, nliData );
String returnMac = intent.getStringExtra( KEY_SRC );
- if ( checkNotDupe( nli ) ) {
- if ( DictLangCache.haveDict( this, nli.lang, nli.dict ) ) {
- makeGame( nli, returnMac );
- } else {
- Intent dictIntent = MultiService
- .makeMissingDictIntent( this, nli,
- DictFetchOwner.OWNER_P2P );
- MultiService.postMissingDictNotification( this, dictIntent,
- nli.gameID() );
- }
+
+ if ( !handleInvitation( nli, returnMac, DictFetchOwner.OWNER_P2P ) ) {
+ Log.d( TAG, "handleInvitation() failed" );
}
}
+ @Override
+ void postNotification( String device, int gameID, long rowid )
+ {
+ Log.e( TAG, "postNotification() doing nothing" );
+ }
+
private void handleGameGone( Intent intent )
{
int gameID = intent.getIntExtra( KEY_GAMEID, 0 );
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWPrefs.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWPrefs.java
index ccf1779b7..5bad7482e 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWPrefs.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWPrefs.java
@@ -77,11 +77,6 @@ public class XWPrefs {
return getPrefsBoolean( context, R.string.key_show_gcm, false );
}
- public static boolean getRelayInviteToSelfEnabled( Context context )
- {
- return getPrefsBoolean( context, R.string.key_enable_relay_toself, false );
- }
-
public static boolean getSMSToSelfEnabled( Context context )
{
return getPrefsBoolean( context, R.string.key_enable_sms_toself, false );
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWService.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWService.java
index fc2e666ae..f407e6f76 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWService.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWService.java
@@ -27,6 +27,7 @@ import android.os.IBinder;
import junit.framework.Assert;
+import org.eehouse.android.xw4.MultiService.DictFetchOwner;
import org.eehouse.android.xw4.MultiService.MultiEvent;
import org.eehouse.android.xw4.jni.CommsAddrRec;
import org.eehouse.android.xw4.jni.JNIThread;
@@ -36,7 +37,7 @@ import org.eehouse.android.xw4.jni.UtilCtxtImpl;
import java.util.HashSet;
import java.util.Set;
-class XWService extends Service {
+abstract class XWService extends Service {
private static final String TAG = XWService.class.getSimpleName();
public static enum ReceiveResult { OK, GAME_GONE, UNCONSUMED };
@@ -72,7 +73,7 @@ class XWService extends Service {
// Check that we aren't already processing an invitation with this
// inviteID.
- protected boolean checkNotDupe( NetLaunchInfo nli )
+ private boolean checkNotDupe( NetLaunchInfo nli )
{
String inviteID = nli.inviteID();
boolean isDupe;
@@ -86,6 +87,40 @@ class XWService extends Service {
return !isDupe;
}
+ abstract void postNotification( String device, int gameID, long rowid );
+
+ protected boolean handleInvitation( NetLaunchInfo nli, String device,
+ DictFetchOwner dfo )
+ {
+ boolean success = false;
+ long[] rowids = DBUtils.getRowIDsFor( this, nli.gameID() );
+ if ( 0 == rowids.length
+ || ( rowids.length < nli.nPlayersT // will break for two-per-device game
+ && XWPrefs.getSecondInviteAllowed( this ) ) ) {
+
+ if ( nli.isValid() && checkNotDupe( nli ) ) {
+
+ if ( DictLangCache.haveDict( this, nli.lang, nli.dict ) ) {
+ long rowid = GameUtils.makeNewMultiGame( this, nli,
+ getSink( 0 ),
+ getUtilCtxt() );
+
+ if ( null != nli.gameName && 0 < nli.gameName.length() ) {
+ DBUtils.setName( this, rowid, nli.gameName );
+ }
+
+ postNotification( device, nli.gameID(), rowid );
+ } else {
+ Intent intent = MultiService
+ .makeMissingDictIntent( this, nli, dfo );
+ MultiService.postMissingDictNotification( this, intent,
+ nli.gameID() );
+ }
+ }
+ }
+ return success;
+ }
+
protected UtilCtxt getUtilCtxt()
{
if ( null == m_utilCtxt ) {
@@ -128,8 +163,7 @@ class XWService extends Service {
consumed = true;
jniThread.receive( msg, addr ).release();
} else {
- GameUtils.BackMoveResult bmr =
- new GameUtils.BackMoveResult();
+ GameUtils.BackMoveResult bmr = new GameUtils.BackMoveResult();
if ( null == sink ) {
sink = getSink( rowid );
}
diff --git a/xwords4/android/app/src/main/res/values/common_rsrc.xml b/xwords4/android/app/src/main/res/values/common_rsrc.xml
index acbdf7243..984ff5cdc 100644
--- a/xwords4/android/app/src/main/res/values/common_rsrc.xml
+++ b/xwords4/android/app/src/main/res/values/common_rsrc.xml
@@ -125,7 +125,6 @@
key_enable_dup_invite
key_enable_nfc_toself
key_enable_sms_toself
- key_enable_relay_toself
key_ignore_gcm
key_show_gcm
key_nag_intervals
diff --git a/xwords4/android/app/src/main/res/values/strings.xml b/xwords4/android/app/src/main/res/values/strings.xml
index e345eca1a..8a35abac2 100644
--- a/xwords4/android/app/src/main/res/values/strings.xml
+++ b/xwords4/android/app/src/main/res/values/strings.xml
@@ -2600,9 +2600,6 @@
devices and I think it\'s rare that people play with more than
two. Let me know if I\'m wrong and I\'ll up the priority.
- Enable relay invites to self
- (To aid testing and debugging)
-
Ignore incoming GCM messages
Mimic life without a google account
diff --git a/xwords4/android/app/src/main/res/xml/xwprefs.xml b/xwords4/android/app/src/main/res/xml/xwprefs.xml
index 67963ed6e..8ea8c8a6d 100644
--- a/xwords4/android/app/src/main/res/xml/xwprefs.xml
+++ b/xwords4/android/app/src/main/res/xml/xwprefs.xml
@@ -393,11 +393,6 @@
-
moveInfo.nTiles;
+ /* Hack: When a single-tile move involves two words it'll be found by
+ both the horizontal and vertical passes. Since it's really the same
+ move both times we don't want both. It'd be better I think to
+ change the move comparison code to detect it as a duplicate, but
+ that's a lot of work. Instead, add a callback in the single-tile
+ vertical case to count words, and when the count it > 1 drop the
+ move.*/
WordNotifierInfo* wiip = NULL;
WordNotifierInfo wii;
- XP_U16 wordCount = 0;
- if ( 1 == nTiles ) {
+ XP_U16 singleTileWordCount = 0;
+ if ( !engine->searchHorizontal && 1 == posmove->moveInfo.nTiles ) {
wii.proc = countWords;
- wii.closure = &wordCount;
+ wii.closure = &singleTileWordCount;
wiip = &wii;
}
- score = figureMoveScore( engine->model, engine->turn,
- &posmove->moveInfo,
- engine, (XWStreamCtxt*)NULL, wiip );
-#ifdef XWFEATURE_BONUSALL
- if ( 0 != engine->allTilesBonus && 0 == engine->nTilesMax ) {
- XP_LOGF( "%s: adding bonus: %d becoming %d", __func__, score ,
- score + engine->allTilesBonus );
- score += engine->allTilesBonus;
- }
-#endif
- /* First, check that the score is even what we're interested in. If
- it is, then go to the expense of filling in a PossibleMove to be
- compared in full */
- if ( 1 == nTiles && 1 < wordCount && !engine->searchHorizontal ) {
+ XP_U16 score = figureMoveScore( engine->model, engine->turn,
+ &posmove->moveInfo,
+ engine, (XWStreamCtxt*)NULL, wiip );
+
+ if ( singleTileWordCount > 1 ) { /* only set by special-case code above */
+ XP_ASSERT( singleTileWordCount == 2 ); /* I think this is the limit */
// XP_LOGF( "%s(): dropping", __func__ );
- } else if ( scoreQualifies( engine, score ) ) {
+ } else {
+#ifdef XWFEATURE_BONUSALL
+ if ( 0 != engine->allTilesBonus && 0 == engine->nTilesMax ) {
+ XP_LOGF( "%s: adding bonus: %d becoming %d", __func__, score ,
+ score + engine->allTilesBonus );
+ score += engine->allTilesBonus;
+ }
+#endif
posmove->score = score;
XP_MEMSET( &posmove->blankVals, 0, sizeof(posmove->blankVals) );
for ( ii = 0; ii < usedBlanksCount; ++ii ) {
@@ -1342,43 +1345,6 @@ move_cache_empty( const EngineCtxt* engine )
return empty;
}
-static XP_Bool
-scoreQualifies( EngineCtxt* engine, XP_U16 score )
-{
- XP_Bool qualifies = XP_FALSE;
- XP_Bool usePrev = engine->usePrev;
- MoveIterationData* miData = &engine->miData;
-
- if ( usePrev && score < miData->lastSeenMove.score ) {
- /* drop it */
- } else if ( !usePrev && score > miData->lastSeenMove.score
- /* || (score < miData->lowestSavedScore) */ ) {
- /* drop it */
- } else {
- XP_S16 ii;
- PossibleMove* savedMoves = miData->savedMoves;
- /* Look at each saved score, and return true as soon as one's found
- with a lower or equal score to this. As an optimization,
- consider remembering what the lowest score is *once there are
- NUM_SAVED_ENGINE_MOVES moves in here* and doing a quick test on
- that. Or better, keeping the list in sorted order. */
- for ( ii = 0, savedMoves = miData->savedMoves;
- ii < engine->nMovesToSave; ++ii, ++savedMoves ) {
- if ( savedMoves->score == 0 ) { /* empty slot */
- qualifies = XP_TRUE;
- } else if ( usePrev && score <= savedMoves->score ) {
- qualifies = XP_TRUE;
- break;
- } else if ( !usePrev && score >= savedMoves->score ) {
- qualifies = XP_TRUE;
- break;
- }
- }
- }
- //XP_LOGF( "%s(%d)->%d", __func__, score, qualifies );
- return qualifies;
-} /* scoreQualifies */
-
static array_edge*
edge_from_tile( const DictionaryCtxt* dict, array_edge* from, Tile tile )
{
diff --git a/xwords4/common/model.c b/xwords4/common/model.c
index c9ad0bda8..81cae3622 100644
--- a/xwords4/common/model.c
+++ b/xwords4/common/model.c
@@ -1120,6 +1120,28 @@ model_makeTurnFromStream( ModelCtxt* model, XP_U16 playerNum,
return success;
} /* model_makeTurnFromStream */
+#ifdef DEBUG
+void
+juggleMoveIfDebug( MoveInfo* move )
+{
+ XP_U16 nTiles = move->nTiles;
+ // XP_LOGF( "%s(): move len: %d", __func__, nTiles );
+ MoveInfoTile tiles[MAX_TRAY_TILES];
+ XP_MEMCPY( tiles, move->tiles, sizeof(tiles) );
+
+ for ( int ii = 0; ii < nTiles; ++ii ) {
+ int last = nTiles - ii;
+ int choice = XP_RANDOM() % last;
+ move->tiles[ii] = tiles[choice];
+ // XP_LOGF( "%s(): setting %d to %d", __func__, ii, choice );
+ if ( choice != --last ) {
+ tiles[choice] = tiles[last];
+ // XP_LOGF( "%s(): replacing %d with %d", __func__, choice, last );
+ }
+ }
+}
+#endif
+
void
model_makeTurnFromMoveInfo( ModelCtxt* model, XP_U16 playerNum,
const MoveInfo* newMove )
@@ -1127,11 +1149,8 @@ model_makeTurnFromMoveInfo( ModelCtxt* model, XP_U16 playerNum,
XP_U16 col, row, ii;
XP_U16* other;
const MoveInfoTile* tinfo;
- Tile blank;
- XP_U16 numTiles;
-
- blank = dict_getBlankTile( model_getDictionary( model ) );
- numTiles = newMove->nTiles;
+ Tile blank = dict_getBlankTile( model_getDictionary( model ) );
+ XP_U16 numTiles = newMove->nTiles;
col = row = newMove->commonCoord; /* just assign both */
other = newMove->isHorizontal? &col: &row;
@@ -1667,15 +1686,7 @@ static XP_S16
commitTurn( ModelCtxt* model, XP_S16 turn, const TrayTileSet* newTiles,
XWStreamCtxt* stream, WordNotifierInfo* wni, XP_Bool useStack )
{
- XP_U16 ii;
- PlayerCtxt* player;
- PendingTile* pt;
XP_S16 score = -1;
- XP_Bool isHorizontal;
- const Tile* newTilesP;
- XP_U16 nTiles;
-
- nTiles = newTiles->nTiles;
#ifdef DEBUG
XP_ASSERT( getCurrentMoveScoreIfLegal( model, turn, (XWStreamCtxt*)NULL,
@@ -1687,10 +1698,11 @@ commitTurn( ModelCtxt* model, XP_S16 turn, const TrayTileSet* newTiles,
clearLastMoveInfo( model );
- player = &model->players[turn];
+ PlayerCtxt* player = &model->players[turn];
if ( useStack ) {
MoveInfo moveInfo = {0};
+ XP_Bool isHorizontal;
#ifdef DEBUG
XP_Bool inLine =
#endif
@@ -1701,19 +1713,16 @@ commitTurn( ModelCtxt* model, XP_S16 turn, const TrayTileSet* newTiles,
stack_addMove( model->vol.stack, turn, &moveInfo, newTiles );
}
- for ( ii = 0, pt=player->pendingTiles; ii < player->nPending;
- ++ii, ++pt ) {
- XP_U16 col, row;
- CellTile tile;
- XP_U16 val;
-
- col = pt->col;
- row = pt->row;
- tile = getModelTileRaw( model, col, row );
+ /* Where's it removed from tray? Need to assert there! */
+ for ( int ii = 0; ii < player->nPending; ++ii ) {
+ const PendingTile* pt = &player->pendingTiles[ii];
+ XP_U16 col = pt->col;
+ XP_U16 row = pt->row;
+ CellTile tile = getModelTileRaw( model, col, row );
XP_ASSERT( (tile & TILE_PENDING_BIT) != 0 );
- val = tile & TILE_VALUE_MASK;
+ XP_U16 val = tile & TILE_VALUE_MASK;
if ( val > 1 ) { /* somebody else is using this square too! */
putBackOtherPlayersTiles( model, turn, col, row );
}
@@ -1734,17 +1743,18 @@ commitTurn( ModelCtxt* model, XP_S16 turn, const TrayTileSet* newTiles,
player->score += score;
/* Why is this next loop necessary? */
- for ( ii = 0; ii < model->nPlayers; ++ii ) {
+ for ( int ii = 0; ii < model->nPlayers; ++ii ) {
invalidateScore( model, ii );
}
player->nPending = 0;
player->nUndone = 0;
- newTilesP = newTiles->tiles;
- while ( nTiles-- ) {
- model_addPlayerTile( model, turn, -1, *newTilesP++ );
+ /* Move new tiles into tray */
+ for ( int ii = newTiles->nTiles - 1; ii >= 0; --ii ) {
+ model_addPlayerTile( model, turn, -1, newTiles->tiles[ii] );
}
+
return score;
} /* commitTurn */
@@ -2045,72 +2055,67 @@ static void
printMovePre( ModelCtxt* model, XP_U16 XP_UNUSED(moveN), const StackEntry* entry,
void* p_closure )
{
- XWStreamCtxt* stream;
- const XP_UCHAR* format;
- XP_UCHAR buf[64];
- XP_UCHAR traybuf[MAX_TRAY_TILES+1];
- MovePrintClosure* closure = (MovePrintClosure*)p_closure;
+ if ( entry->moveType != ASSIGN_TYPE ) {
+ const XP_UCHAR* format;
+ XP_UCHAR buf[64];
+ XP_UCHAR traybuf[MAX_TRAY_TILES+1];
+ MovePrintClosure* closure = (MovePrintClosure*)p_closure;
+ XWStreamCtxt* stream = closure->stream;
- if ( entry->moveType == ASSIGN_TYPE ) {
- return;
- }
-
- stream = closure->stream;
-
- XP_SNPRINTF( buf, sizeof(buf), (XP_UCHAR*)"%d:%d ", ++closure->nPrinted,
- entry->playerNum+1 );
- printString( stream, (XP_UCHAR*)buf );
-
- if ( entry->moveType == TRADE_TYPE ) {
- } else {
- XP_UCHAR letter[2] = {'\0','\0'};
- XP_Bool isHorizontal = entry->u.move.moveInfo.isHorizontal;
- XP_U16 col, row;
- const MoveInfo* mi;
- XP_Bool isPass = XP_FALSE;
-
- if ( entry->moveType == PHONY_TYPE ) {
- mi = &entry->u.phony.moveInfo;
- } else {
- mi = &entry->u.move.moveInfo;
- if ( mi->nTiles == 0 ) {
- isPass = XP_TRUE;
- }
- }
-
- if ( isPass ) {
- format = util_getUserString( model->vol.util, STR_PASS );
- XP_SNPRINTF( buf, VSIZE(buf), "%s", format );
- } else {
- if ( isHorizontal ) {
- format = util_getUserString( model->vol.util, STRS_MOVE_ACROSS );
- } else {
- format = util_getUserString( model->vol.util, STRS_MOVE_DOWN );
- }
-
- row = mi->commonCoord;
- col = mi->tiles[0].varCoord;
- if ( !isHorizontal ) {
- XP_U16 tmp = col; col = row; row = tmp;
- }
- letter[0] = 'A' + col;
-
- XP_SNPRINTF( traybuf, sizeof(traybuf), (XP_UCHAR *)"%s%d",
- letter, row + 1 );
- XP_SNPRINTF( buf, sizeof(buf), format, traybuf );
- }
+ XP_SNPRINTF( buf, sizeof(buf), (XP_UCHAR*)"%d:%d ", ++closure->nPrinted,
+ entry->playerNum+1 );
printString( stream, (XP_UCHAR*)buf );
- }
- if ( !closure->keepHidden ) {
- format = util_getUserString( model->vol.util, STRS_TRAY_AT_START );
- formatTray( model_getPlayerTiles( model, entry->playerNum ),
- closure->dict, (XP_UCHAR*)traybuf, sizeof(traybuf),
- XP_FALSE );
- XP_SNPRINTF( buf, sizeof(buf), format, traybuf );
- printString( stream, buf );
- }
+ if ( entry->moveType == TRADE_TYPE ) {
+ } else {
+ XP_UCHAR letter[2] = {'\0','\0'};
+ XP_Bool isHorizontal = entry->u.move.moveInfo.isHorizontal;
+ XP_U16 col, row;
+ const MoveInfo* mi;
+ XP_Bool isPass = XP_FALSE;
+ if ( entry->moveType == PHONY_TYPE ) {
+ mi = &entry->u.phony.moveInfo;
+ } else {
+ mi = &entry->u.move.moveInfo;
+ if ( mi->nTiles == 0 ) {
+ isPass = XP_TRUE;
+ }
+ }
+
+ if ( isPass ) {
+ format = util_getUserString( model->vol.util, STR_PASS );
+ XP_SNPRINTF( buf, VSIZE(buf), "%s", format );
+ } else {
+ if ( isHorizontal ) {
+ format = util_getUserString( model->vol.util, STRS_MOVE_ACROSS );
+ } else {
+ format = util_getUserString( model->vol.util, STRS_MOVE_DOWN );
+ }
+
+ row = mi->commonCoord;
+ col = mi->tiles[0].varCoord;
+ if ( !isHorizontal ) {
+ XP_U16 tmp = col; col = row; row = tmp;
+ }
+ letter[0] = 'A' + col;
+
+ XP_SNPRINTF( traybuf, sizeof(traybuf), (XP_UCHAR *)"%s%d",
+ letter, row + 1 );
+ XP_SNPRINTF( buf, sizeof(buf), format, traybuf );
+ }
+ printString( stream, (XP_UCHAR*)buf );
+ }
+
+ if ( !closure->keepHidden ) {
+ format = util_getUserString( model->vol.util, STRS_TRAY_AT_START );
+ formatTray( model_getPlayerTiles( model, entry->playerNum ),
+ closure->dict, (XP_UCHAR*)traybuf, sizeof(traybuf),
+ XP_FALSE );
+ XP_SNPRINTF( buf, sizeof(buf), format, traybuf );
+ printString( stream, buf );
+ }
+ }
} /* printMovePre */
static void
@@ -2118,69 +2123,66 @@ printMovePost( ModelCtxt* model, XP_U16 XP_UNUSED(moveN),
const StackEntry* entry, XP_S16 XP_UNUSED(score),
void* p_closure )
{
- MovePrintClosure* closure = (MovePrintClosure*)p_closure;
- XWStreamCtxt* stream = closure->stream;
- DictionaryCtxt* dict = closure->dict;
- const XP_UCHAR* format;
- XP_U16 nTiles;
- XP_S16 totalScore;
- XP_UCHAR buf[100];
- XP_UCHAR traybuf1[MAX_TRAY_TILES+1];
- XP_UCHAR traybuf2[MAX_TRAY_TILES+1];
- const MoveInfo* mi;
+ if ( entry->moveType != ASSIGN_TYPE ) {
+ MovePrintClosure* closure = (MovePrintClosure*)p_closure;
+ XWStreamCtxt* stream = closure->stream;
+ DictionaryCtxt* dict = closure->dict;
+ const XP_UCHAR* format;
+ XP_U16 nTiles;
- if ( entry->moveType == ASSIGN_TYPE ) {
- return;
- }
+ XP_UCHAR buf[100];
+ XP_UCHAR traybuf1[MAX_TRAY_TILES+1];
+ XP_UCHAR traybuf2[MAX_TRAY_TILES+1];
+ const MoveInfo* mi;
+ XP_S16 totalScore = model_getPlayerScore( model, entry->playerNum );
- totalScore = model_getPlayerScore( model, entry->playerNum );
+ switch( entry->moveType ) {
+ case TRADE_TYPE:
+ formatTray( (const TrayTileSet*)&entry->u.trade.oldTiles,
+ dict, traybuf1, sizeof(traybuf1), closure->keepHidden );
+ formatTray( (const TrayTileSet*) &entry->u.trade.newTiles,
+ dict, traybuf2, sizeof(traybuf2), closure->keepHidden );
- switch( entry->moveType ) {
- case TRADE_TYPE:
- formatTray( (const TrayTileSet*)&entry->u.trade.oldTiles,
- dict, traybuf1, sizeof(traybuf1), closure->keepHidden );
- formatTray( (const TrayTileSet*) &entry->u.trade.newTiles,
- dict, traybuf2, sizeof(traybuf2), closure->keepHidden );
+ format = util_getUserString( model->vol.util, STRSS_TRADED_FOR );
+ XP_SNPRINTF( buf, sizeof(buf), format, traybuf1, traybuf2 );
+ printString( stream, buf );
+ printString( stream, (XP_UCHAR*)XP_CR );
+ break;
- format = util_getUserString( model->vol.util, STRSS_TRADED_FOR );
- XP_SNPRINTF( buf, sizeof(buf), format, traybuf1, traybuf2 );
- printString( stream, buf );
- printString( stream, (XP_UCHAR*)XP_CR );
- break;
-
- case PHONY_TYPE:
- format = util_getUserString( model->vol.util, STR_PHONY_REJECTED );
- printString( stream, format );
- case MOVE_TYPE:
- format = util_getUserString( model->vol.util, STRD_CUMULATIVE_SCORE );
- XP_SNPRINTF( buf, sizeof(buf), format, totalScore );
- printString( stream, buf );
-
- if ( entry->moveType == PHONY_TYPE ) {
- mi = &entry->u.phony.moveInfo;
- } else {
- mi = &entry->u.move.moveInfo;
- }
- nTiles = mi->nTiles;
- if ( nTiles > 0 ) {
+ case PHONY_TYPE:
+ format = util_getUserString( model->vol.util, STR_PHONY_REJECTED );
+ printString( stream, format );
+ case MOVE_TYPE:
+ format = util_getUserString( model->vol.util, STRD_CUMULATIVE_SCORE );
+ XP_SNPRINTF( buf, sizeof(buf), format, totalScore );
+ printString( stream, buf );
if ( entry->moveType == PHONY_TYPE ) {
- /* printString( stream, (XP_UCHAR*)"phony rejected " ); */
- } else if ( !closure->keepHidden ) {
- format = util_getUserString(model->vol.util, STRS_NEW_TILES);
- XP_SNPRINTF( buf, sizeof(buf), format,
- formatTray( &entry->u.move.newTiles, dict,
- traybuf1, sizeof(traybuf1),
- XP_FALSE ) );
- printString( stream, buf );
- stream_catString( stream, (XP_UCHAR*)XP_CR );
+ mi = &entry->u.phony.moveInfo;
+ } else {
+ mi = &entry->u.move.moveInfo;
}
+ nTiles = mi->nTiles;
+ if ( nTiles > 0 ) {
+
+ if ( entry->moveType == PHONY_TYPE ) {
+ /* printString( stream, (XP_UCHAR*)"phony rejected " ); */
+ } else if ( !closure->keepHidden ) {
+ format = util_getUserString(model->vol.util, STRS_NEW_TILES);
+ XP_SNPRINTF( buf, sizeof(buf), format,
+ formatTray( &entry->u.move.newTiles, dict,
+ traybuf1, sizeof(traybuf1),
+ XP_FALSE ) );
+ printString( stream, buf );
+ stream_catString( stream, (XP_UCHAR*)XP_CR );
+ }
+ }
+
+ break;
}
- break;
+ printString( stream, (XP_UCHAR*)XP_CR );
}
-
- printString( stream, (XP_UCHAR*)XP_CR );
} /* printMovePost */
static void
diff --git a/xwords4/common/model.h b/xwords4/common/model.h
index 09adede89..327deaa87 100644
--- a/xwords4/common/model.h
+++ b/xwords4/common/model.h
@@ -221,6 +221,12 @@ XP_Bool model_makeTurnFromStream( ModelCtxt* model, XP_U16 playerNum,
void model_makeTurnFromMoveInfo( ModelCtxt* model, XP_U16 playerNum,
const MoveInfo* newMove );
+#ifdef DEBUG
+void juggleMoveIfDebug( MoveInfo* move );
+#else
+# define juggleMoveIfDebug(newMove)
+#endif
+
void model_resetCurrentTurn( ModelCtxt* model, XP_S16 turn );
XP_S16 model_getNMoves( const ModelCtxt* model );
diff --git a/xwords4/common/movestak.c b/xwords4/common/movestak.c
index ee94b4803..a76450fb5 100644
--- a/xwords4/common/movestak.c
+++ b/xwords4/common/movestak.c
@@ -316,10 +316,9 @@ void
stack_addMove( StackCtxt* stack, XP_U16 turn, const MoveInfo* moveInfo,
const TrayTileSet* newTiles )
{
- StackEntry move;
-
- move.playerNum = (XP_U8)turn;
- move.moveType = MOVE_TYPE;
+ StackEntry move = {.playerNum = (XP_U8)turn,
+ .moveType = MOVE_TYPE,
+ };
XP_MEMCPY( &move.u.move.moveInfo, moveInfo, sizeof(move.u.move.moveInfo));
move.u.move.newTiles = *newTiles;
@@ -330,10 +329,9 @@ stack_addMove( StackCtxt* stack, XP_U16 turn, const MoveInfo* moveInfo,
void
stack_addPhony( StackCtxt* stack, XP_U16 turn, const MoveInfo* moveInfo )
{
- StackEntry move;
-
- move.playerNum = (XP_U8)turn;
- move.moveType = PHONY_TYPE;
+ StackEntry move = {.playerNum = (XP_U8)turn,
+ .moveType = PHONY_TYPE,
+ };
XP_MEMCPY( &move.u.phony.moveInfo, moveInfo,
sizeof(move.u.phony.moveInfo));
@@ -345,10 +343,9 @@ void
stack_addTrade( StackCtxt* stack, XP_U16 turn,
const TrayTileSet* oldTiles, const TrayTileSet* newTiles )
{
- StackEntry move;
-
- move.playerNum = (XP_U8)turn;
- move.moveType = TRADE_TYPE;
+ StackEntry move = { .playerNum = (XP_U8)turn,
+ .moveType = TRADE_TYPE,
+ };
move.u.trade.oldTiles = *oldTiles;
move.u.trade.newTiles = *newTiles;
@@ -359,10 +356,9 @@ stack_addTrade( StackCtxt* stack, XP_U16 turn,
void
stack_addAssign( StackCtxt* stack, XP_U16 turn, const TrayTileSet* tiles )
{
- StackEntry move;
-
- move.playerNum = (XP_U8)turn;
- move.moveType = ASSIGN_TYPE;
+ StackEntry move = { .playerNum = (XP_U8)turn,
+ .moveType = ASSIGN_TYPE,
+ };
move.u.assign.tiles = *tiles;
diff --git a/xwords4/common/mscore.c b/xwords4/common/mscore.c
index 246ddad62..3024474f5 100644
--- a/xwords4/common/mscore.c
+++ b/xwords4/common/mscore.c
@@ -615,9 +615,13 @@ scoreWord( const ModelCtxt* model, XP_U16 turn,
* each time through in the debug case */
if ( 0 ) { /* makes keeping parens balanced easier */
#ifdef DEBUG
+ /* Always run in DEBUG case */
} else if ( 1 ) {
#else
- } else if ( engine == NULL ) {
+ /* If notifyInfo is set, we're counting on the side-effect of its
+ proc getting called. So skip caching in that case even on
+ release builds. */
+ } else if ( engine == NULL || notifyInfo != NULL ) {
#endif
Tile checkWordBuf[MAX_ROWS];
Tile* curTile = checkWordBuf;
@@ -688,7 +692,8 @@ scoreWord( const ModelCtxt* model, XP_U16 turn,
#else
} else { /* non-debug case we know it's non-null */
#endif
- XP_ASSERT( nTiles==1 );
+ XP_ASSERT( nTiles == 1 );
+ XP_ASSERT( notifyInfo == NULL );
XP_ASSERT( engine_getScoreCache( engine, movei->commonCoord )
== restScore );
restScore = engine_getScoreCache( engine, movei->commonCoord );
diff --git a/xwords4/common/server.c b/xwords4/common/server.c
index ba7abe933..663bd01b4 100644
--- a/xwords4/common/server.c
+++ b/xwords4/common/server.c
@@ -929,6 +929,7 @@ makeRobotMove( ServerCtxt* server )
/* if canMove is false, this is a fake move, a pass */
if ( canMove || NPASSES_OK(server) ) {
+ juggleMoveIfDebug( &newMove );
model_makeTurnFromMoveInfo( model, turn, &newMove );
XP_LOGF( "%s: robot making %d tile move", __func__, newMove.nTiles );
@@ -1832,10 +1833,7 @@ fetchTiles( ServerCtxt* server, XP_U16 playerNum, XP_U16 nToFetch,
{
XP_Bool ask;
XP_U16 nSoFar = resultTiles->nTiles;
- XP_U16 nLeft;
PoolContext* pool = server->pool;
- TrayTileSet oneTile;
- PickInfo pi;
const XP_UCHAR* curTray[MAX_TRAY_TILES];
#ifdef FEATURE_TRAY_EDIT
DictionaryCtxt* dict = model_getDictionary( server->vol.model );
@@ -1849,22 +1847,22 @@ fetchTiles( ServerCtxt* server, XP_U16 playerNum, XP_U16 nToFetch,
ask = XP_FALSE;
#endif
- nLeft = pool_getNTilesLeft( pool );
+ XP_U16 nLeft = pool_getNTilesLeft( pool );
if ( nLeft < nToFetch ) {
nToFetch = nLeft;
}
- oneTile.nTiles = 1;
-
- pi.nTotal = nToFetch;
- pi.thisPick = 0;
- pi.curTiles = curTray;
+ TrayTileSet oneTile = {.nTiles = 1};
+ PickInfo pi = { .nTotal = nToFetch,
+ .thisPick = 0,
+ .curTiles = curTray,
+ };
curTrayAsTexts( server, playerNum, tradedTiles, &pi.nCurTiles, curTray );
#ifdef FEATURE_TRAY_EDIT /* good compiler would note ask==0, but... */
/* First ask until cancelled */
- for ( ; ask && nSoFar < nToFetch; ) {
+ while ( ask && nSoFar < nToFetch ) {
const XP_UCHAR* texts[MAX_UNIQUE_TILES];
Tile tiles[MAX_UNIQUE_TILES];
XP_S16 chosen;
@@ -1901,12 +1899,7 @@ fetchTiles( ServerCtxt* server, XP_U16 playerNum, XP_U16 nToFetch,
/* Then fetch the rest without asking */
if ( nSoFar < nToFetch ) {
XP_U8 nLeft = nToFetch - nSoFar;
- Tile tiles[MAX_TRAY_TILES];
-
- pool_requestTiles( pool, tiles, &nLeft );
-
- XP_MEMCPY( &resultTiles->tiles[nSoFar], tiles,
- nLeft * sizeof(resultTiles->tiles[0]) );
+ pool_requestTiles( pool, &resultTiles->tiles[nSoFar], &nLeft );
nSoFar += nLeft;
}
@@ -2462,8 +2455,9 @@ server_commitMove( ServerCtxt* server, TrayTileSet* newTilesP )
if client, send to server. */
XP_ASSERT( turn >= 0 );
- nTilesMoved = model_getCurrentMoveCount( model, turn );
pool_removeTiles( server->pool, &newTiles );
+
+ nTilesMoved = model_getCurrentMoveCount( model, turn );
fetchTiles( server, turn, nTilesMoved, NULL, &newTiles );
#ifndef XWFEATURE_STANDALONE_ONLY
diff --git a/xwords4/linux/cursesmain.c b/xwords4/linux/cursesmain.c
index c02e5fe60..c1f6d7fa7 100644
--- a/xwords4/linux/cursesmain.c
+++ b/xwords4/linux/cursesmain.c
@@ -1372,8 +1372,8 @@ curses_util_getVTManager(XW_UtilCtxt* uc)
static void
curses_util_informNeedPassword( XW_UtilCtxt* XP_UNUSED(uc),
- XP_U16 playerNum,
- const XP_UCHAR* name )
+ XP_U16 XP_UNUSED_DBG(playerNum),
+ const XP_UCHAR* XP_UNUSED_DBG(name) )
{
XP_WARNF( "curses_util_informNeedPassword(num=%d, name=%s", playerNum, name );
} /* curses_util_askPassword */
@@ -1391,7 +1391,7 @@ curses_util_yOffsetChange( XW_UtilCtxt* XP_UNUSED(uc),
#ifdef XWFEATURE_TURNCHANGENOTIFY
static void
-curses_util_turnChanged( XW_UtilCtxt* XP_UNUSED(uc), XP_S16 newTurn )
+curses_util_turnChanged( XW_UtilCtxt* XP_UNUSED(uc), XP_S16 XP_UNUSED_DBG(newTurn) )
{
XP_LOGF( "%s(turn=%d)", __func__, newTurn );
}
@@ -1725,7 +1725,7 @@ cursesGotBuf( void* closure, const CommsAddrRec* addr,
static void
cursesGotForRow( void* closure, const CommsAddrRec* from,
- sqlite3_int64 rowid, const XP_U8* buf,
+ sqlite3_int64 XP_UNUSED_DBG(rowid), const XP_U8* buf,
XP_U16 len )
{
LOG_FUNC();
diff --git a/xwords4/linux/gamesdb.c b/xwords4/linux/gamesdb.c
index 377a0dac0..123a3fb12 100644
--- a/xwords4/linux/gamesdb.c
+++ b/xwords4/linux/gamesdb.c
@@ -31,8 +31,8 @@ static void getColumnText( sqlite3_stmt *ppStmt, int iCol, XP_UCHAR* buf,
int len );
#ifdef DEBUG
static char* sqliteErr2str( int err );
-static void assertPrintResult( sqlite3* pDb, int result, int expect );
#endif
+static void assertPrintResult( sqlite3* pDb, int result, int expect );
sqlite3*
openGamesDB( const char* dbName )
@@ -590,17 +590,15 @@ sqliteErr2str( int err )
}
return "";
}
+#endif
static void
-assertPrintResult( sqlite3* pDb, int result, int expect )
+assertPrintResult( sqlite3* pDb, int XP_UNUSED_DBG(result), int expect )
{
int code = sqlite3_errcode( pDb );
XP_ASSERT( code == result ); /* do I need to pass it? */
if ( code != expect ) {
- const char* msg = sqlite3_errmsg( pDb );
- XP_LOGF( "sqlite3 error: %s", msg );
+ XP_LOGF( "sqlite3 error: %s", sqlite3_errmsg( pDb ) );
XP_ASSERT(0);
}
}
-
-#endif
diff --git a/xwords4/linux/gtkboard.c b/xwords4/linux/gtkboard.c
index 0930e3935..1e506edea 100644
--- a/xwords4/linux/gtkboard.c
+++ b/xwords4/linux/gtkboard.c
@@ -435,7 +435,7 @@ tryConnectToServer(CommonGlobals* cGlobals)
{
LaunchParams* params = cGlobals->params;
XWStreamCtxt* stream =
- mem_stream_make( cGlobals->util->mpool, params->vtMgr,
+ mem_stream_make( MPPARM(cGlobals->util->mpool) params->vtMgr,
cGlobals, CHANNEL_NONE,
sendOnClose );
(void)server_initClientConnection( cGlobals->game.server,
diff --git a/xwords4/linux/gtkdraw.c b/xwords4/linux/gtkdraw.c
index fa04326ad..c2491466e 100644
--- a/xwords4/linux/gtkdraw.c
+++ b/xwords4/linux/gtkdraw.c
@@ -1460,8 +1460,7 @@ gtkDrawCtxtMake( GtkWidget* drawing_area, GtkGameGlobals* globals )
dctx->drawing_area = drawing_area;
dctx->globals = globals;
- GdkWindow* window = gtk_widget_get_window(drawing_area);
- XP_ASSERT( !!window );
+ XP_ASSERT( !!gtk_widget_get_window(drawing_area) );
#ifdef USE_CAIRO
/* dctx->cairo = gdk_cairo_create( window ); */
/* XP_LOGF( "dctx->cairo=%p", dctx->cairo ); */
@@ -1514,6 +1513,7 @@ removeSurface( GtkDrawCtx* dctx )
dctx->surface = NULL;
}
+#ifdef DEBUG
static cairo_status_t
write_func( void *closure, const unsigned char *data,
unsigned int length )
@@ -1522,16 +1522,19 @@ write_func( void *closure, const unsigned char *data,
stream_putBytes( stream, data, length );
return CAIRO_STATUS_SUCCESS;
}
+#endif
void
-getImage( GtkDrawCtx* dctx, XWStreamCtxt* stream )
+getImage( GtkDrawCtx* XP_UNUSED_DBG(dctx), XWStreamCtxt* XP_UNUSED_DBG(stream) )
{
LOG_FUNC();
XP_ASSERT( !!dctx->surface );
+#ifdef DEBUG
cairo_status_t status =
cairo_surface_write_to_png_stream( dctx->surface,
write_func, stream );
XP_ASSERT( CAIRO_STATUS_SUCCESS == status );
+#endif
}
void
diff --git a/xwords4/linux/linuxmain.c b/xwords4/linux/linuxmain.c
index ffdc68917..3c992e2b6 100644
--- a/xwords4/linux/linuxmain.c
+++ b/xwords4/linux/linuxmain.c
@@ -1242,7 +1242,7 @@ linux_reset( void* closure )
#endif
XP_S16
-linux_send( const XP_U8* buf, XP_U16 buflen, const XP_UCHAR* msgNo,
+linux_send( const XP_U8* buf, XP_U16 buflen, const XP_UCHAR* XP_UNUSED_DBG(msgNo),
const CommsAddrRec* addrRec, CommsConnType conType, XP_U32 gameID,
void* closure )
{
diff --git a/xwords4/linux/relaycon.c b/xwords4/linux/relaycon.c
index 6f0c2a534..b156b268a 100644
--- a/xwords4/linux/relaycon.c
+++ b/xwords4/linux/relaycon.c
@@ -480,8 +480,9 @@ relayThread( void* arg )
while ( !storage->relayTaskList ) {
pthread_cond_wait( &storage->relayCondVar, &storage->relayMutex );
}
-
+#ifdef DEBUG
int len = g_slist_length( storage->relayTaskList );
+#endif
gchar* strs = listTasks( storage->relayTaskList );
GSList* head = storage->relayTaskList;
storage->relayTaskList = g_slist_remove_link( storage->relayTaskList,
@@ -740,12 +741,16 @@ relaycon_cleanup( LaunchParams* params )
RelayConStorage* storage = (RelayConStorage*)params->relayConStorage;
if ( storage->params->useHTTP ) {
pthread_mutex_lock( &storage->relayMutex );
+#ifdef DEBUG
int nRelayTasks = g_slist_length( storage->relayTaskList );
+#endif
gchar* taskStrs = listTasks( storage->relayTaskList );
pthread_mutex_unlock( &storage->relayMutex );
pthread_mutex_lock( &storage->gotDataMutex );
+#ifdef DEBUG
int nDataTasks = g_slist_length( storage->gotDataTaskList );
+#endif
gchar* gotStrs = listTasks( storage->gotDataTaskList );
pthread_mutex_unlock( &storage->gotDataMutex );
@@ -905,17 +910,16 @@ onGotQueryData( RelayTask* task )
if ( !!reply ) {
CommsAddrRec addr = {0};
addr_addType( &addr, COMMS_CONN_RELAY );
-
+#ifdef DEBUG
GList* ids = g_hash_table_get_keys( task->u.query.map );
- const char* xxx = ids->data;
-
+#endif
json_object* jMsgs;
if ( json_object_object_get_ex( reply, "msgs", &jMsgs ) ) {
/* Currently there's an array of arrays for each relayID (value) */
XP_LOGF( "%s: got result of len %d", __func__, json_object_object_length(jMsgs) );
XP_ASSERT( json_object_object_length(jMsgs) <= 1 );
json_object_object_foreach(jMsgs, relayID, arrOfArrOfMoves) {
- XP_ASSERT( 0 == strcmp( relayID, xxx ) );
+ XP_ASSERT( 0 == strcmp( relayID, ids->data ) );
int len1 = json_object_array_length( arrOfArrOfMoves );
if ( len1 > 0 ) {
sqlite3_int64 rowid = *(sqlite3_int64*)g_hash_table_lookup( task->u.query.map, relayID );
diff --git a/xwords4/relay/crefmgr.cpp b/xwords4/relay/crefmgr.cpp
index 882f0eb27..c3d76202e 100644
--- a/xwords4/relay/crefmgr.cpp
+++ b/xwords4/relay/crefmgr.cpp
@@ -220,7 +220,7 @@ CRefMgr::getMakeCookieRef( const char* cookie, int nPlayersH, int nPlayersT,
int langCode, int seed, int clientIndx,
bool wantsPublic, bool makePublic, bool* seenSeed )
{
- CidInfo* cinfo;
+ CidInfo* cinfo = NULL;
/* We have a cookie from a new connection or from a reconnect. This may
be the first time it's been seen, or there may be a game currently in
@@ -229,8 +229,8 @@ CRefMgr::getMakeCookieRef( const char* cookie, int nPlayersH, int nPlayersT,
a new one. Pass the connName which will be used if set, but if not set
we'll be generating another later when the game is complete.
*/
- for ( ; ; ) {
- /* What's this for loop thing. It's to fix a race condition. One
+ for ( int ii = 0; ; ++ii ) {
+ /* What's this for loop thing? It's to fix a race condition. One
thread has "claim" on cid , which is in the DB. Another comes
into this function and looks it up in the DB, retrieving , but
progress is blocked inside getCookieRef_impl which calls Claim().
@@ -238,6 +238,13 @@ CRefMgr::getMakeCookieRef( const char* cookie, int nPlayersH, int nPlayersT,
cref before calling Relinquish so that when Claim() returns there's
no cref. So we test for that case and retry. */
+ /* I'm now seeing an infinte loop here. Until it's tracked down, let's
+ assert out. Note that I've seen it here, not at any of the other
+ places where I'm replacing FOREVER loops with this test*/
+ if ( ii > 5 ) {
+ assert(0);
+ break;
+ }
CookieID cid;
char connNameBuf[MAX_CONNNAME_LEN+1] = {0};
@@ -295,7 +302,13 @@ CRefMgr::getMakeCookieRef( const char* connName, const char* cookie,
CookieRef* cref = NULL;
CidInfo* cinfo = NULL;
- for ( ; ; ) { /* for: see comment above */
+ for ( int ii = 0; ; ++ii ) { /* for: see comment above */
+
+ if ( ii > 5 ) {
+ assert(0);
+ break;
+ }
+
/* fetch these from DB */
char curCookie[MAX_INVITE_LEN+1];
int curLangCode;
@@ -346,7 +359,12 @@ CRefMgr::getMakeCookieRef( const char* const connName, HostID hid, bool* isDead
int nPlayersT = 0;
int nAlreadyHere = 0;
- for ( ; ; ) { /* for: see comment above */
+ for ( int ii = 0; ; ++ii ) { /* for: see comment above */
+ if ( ii > 5 ) {
+ assert(0);
+ break;
+ }
+
CookieID cid = m_db->FindGame( connName, hid, curCookie, sizeof(curCookie),
&curLangCode, &nPlayersT, &nAlreadyHere,
isDead );
@@ -385,7 +403,12 @@ CRefMgr::getMakeCookieRef( const AddrInfo::ClientToken clientToken, HostID srcID
int nPlayersT = 0;
int nAlreadyHere = 0;
- for ( ; ; ) { /* for: see comment above */
+ for ( int ii = 0; ; ++ii ) { /* for: see comment above */
+ if ( ii > 5 ) {
+ assert(0);
+ break;
+ }
+
char connName[MAX_CONNNAME_LEN+1] = {0};
CookieID cid = m_db->FindGame( clientToken, srcID,
connName, sizeof(connName),
diff --git a/xwords4/relay/xwrelay.cpp b/xwords4/relay/xwrelay.cpp
index e94fd7666..55be63001 100644
--- a/xwords4/relay/xwrelay.cpp
+++ b/xwords4/relay/xwrelay.cpp
@@ -691,12 +691,14 @@ send_msg_via_udp( const AddrInfo* addr, AddrInfo::ClientToken clientToken,
uint32_t asNetTok = htonl(clientToken);
ssize_t nSent = send_via_udp( addr, packetIDP, XWPDEV_MSG, &asNetTok,
sizeof(asNetTok), buf, bufLen, NULL );
- logf( XW_LOGINFO, "%s: sent %d bytes (plus header) on UDP socket, "
- "token=%x(%d)", __func__, bufLen, clientToken,
- clientToken );
result = 0 < nSent;
- logf( XW_LOGINFO, "%s()=>%d", __func__, result );
+ if (result) {
+ logf( XW_LOGINFO, "%s: sent %d bytes (plus header) on UDP socket, "
+ "token=%x(%d)", __func__, bufLen, clientToken,
+ clientToken );
+ }
}
+ // logf( XW_LOGINFO, "%s()=>%d", __func__, result );
return result;
}
@@ -1802,8 +1804,8 @@ handle_udp_packet( PacketThreadClosure* ptc )
handlePutMessage( scr, hid, &addr, end - ptr, &ptr, end );
assert( ptr == end ); // DON'T CHECK THIS IN!!!
} else {
- logf( XW_LOGERROR, "%s: invalid scr for %s", __func__,
- connName );
+ logf( XW_LOGERROR, "%s: invalid scr for %s/%d", __func__,
+ connName, hid );
}
} else {
logf( XW_LOGERROR, "no clientToken found!!!" );