diff --git a/xwords4/android/app/build.gradle b/xwords4/android/app/build.gradle index e79abf113..0a38e4a07 100644 --- a/xwords4/android/app/build.gradle +++ b/xwords4/android/app/build.gradle @@ -1,6 +1,6 @@ def INITIAL_CLIENT_VERS = 8 -def VERSION_CODE_BASE = 129 -def VERSION_NAME = '4.4.133' +def VERSION_CODE_BASE = 130 +def VERSION_NAME = '4.4.134' def FABRIC_API_KEY = System.getenv("FABRIC_API_KEY") def GCM_SENDER_ID = System.getenv("GCM_SENDER_ID") def BUILD_INFO_NAME = "build-info.txt" diff --git a/xwords4/android/app/src/main/assets/changes.html b/xwords4/android/app/src/main/assets/changes.html index fec4cf74c..323264cb1 100644 --- a/xwords4/android/app/src/main/assets/changes.html +++ b/xwords4/android/app/src/main/assets/changes.html @@ -13,9 +13,9 @@ -

CrossWords 4.4.133 release

+

CrossWords 4.4.134 release

-

This release fixes a crash closing the wordlist browser.

+

This release makes a few UI tweaks.

Please take @@ -25,12 +25,12 @@

New with this release

(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!!!" );