mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-09 22:00:39 +01:00
Add option to choose how rematch-game players will be ordered
When rematching, some users have a convention that e.g. lowest scoring player in the "parent" game goes first. So allow that, providing the choice on each rematch until a default has been chosen. Support changing that default in a new prefs setting. The place I chose to enforce the order was on the host as invitees are registering and being assigned slots. But by then there's no longer any connection to the game that was rematched, e.g. to use its scores. So during the rematched game creation process I create and store with the new game the necessary ordering information. For the 3-and-4 device case, it was also necessary to tweak the information about other guests that the host sends guests (added during earlier work on rematching.)
This commit is contained in:
parent
2936869b45
commit
1181e908dc
39 changed files with 1354 additions and 253 deletions
|
@ -65,6 +65,7 @@ public enum DlgID {
|
||||||
GAMES_LIST_NEWGAME,
|
GAMES_LIST_NEWGAME,
|
||||||
CHANGE_CONN,
|
CHANGE_CONN,
|
||||||
GAMES_LIST_NAME_REMATCH,
|
GAMES_LIST_NAME_REMATCH,
|
||||||
|
GAMES_LIST_GET_RO,
|
||||||
ASK_DUP_PAUSE,
|
ASK_DUP_PAUSE,
|
||||||
CHOOSE_TILES,
|
CHOOSE_TILES,
|
||||||
SHOW_TILES,
|
SHOW_TILES,
|
||||||
|
|
|
@ -52,6 +52,7 @@ import org.eehouse.android.xw4.jni.UtilCtxt;
|
||||||
import org.eehouse.android.xw4.jni.UtilCtxtImpl;
|
import org.eehouse.android.xw4.jni.UtilCtxtImpl;
|
||||||
import org.eehouse.android.xw4.jni.XwJNI;
|
import org.eehouse.android.xw4.jni.XwJNI;
|
||||||
import org.eehouse.android.xw4.jni.XwJNI.GamePtr;
|
import org.eehouse.android.xw4.jni.XwJNI.GamePtr;
|
||||||
|
import org.eehouse.android.xw4.jni.XwJNI.RematchOrder;
|
||||||
import org.eehouse.android.xw4.loc.LocUtils;
|
import org.eehouse.android.xw4.loc.LocUtils;
|
||||||
import org.eehouse.android.xw4.Utils.ISOCode;
|
import org.eehouse.android.xw4.Utils.ISOCode;
|
||||||
|
|
||||||
|
@ -72,6 +73,14 @@ public class GameUtils {
|
||||||
void onResendDone( Context context, int numSent );
|
void onResendDone( Context context, int numSent );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface NeedRematchOrder {
|
||||||
|
// Return null if unable to produce it immediately. Implementation may
|
||||||
|
// want to start a query at the same time and from its
|
||||||
|
// ok-button-handler call makeRematch() again with a different
|
||||||
|
// implementation that simply returns a cached RematchOrder
|
||||||
|
RematchOrder getRematchOrder();
|
||||||
|
}
|
||||||
|
|
||||||
private static Integer s_minScreen;
|
private static Integer s_minScreen;
|
||||||
// Used to determine whether to resend all messages on networking coming
|
// Used to determine whether to resend all messages on networking coming
|
||||||
// back up. The length of the array determines the number of times in the
|
// back up. The length of the array determines the number of times in the
|
||||||
|
@ -574,7 +583,8 @@ public class GameUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long makeRematch( Context context, long srcRowid,
|
public static long makeRematch( Context context, long srcRowid,
|
||||||
long groupID, String gameName )
|
long groupID, String gameName,
|
||||||
|
NeedRematchOrder nro )
|
||||||
{
|
{
|
||||||
long rowid = DBUtils.ROWID_NOTFOUND;
|
long rowid = DBUtils.ROWID_NOTFOUND;
|
||||||
try ( GameLock lock = GameLock.tryLockRO( srcRowid ) ) {
|
try ( GameLock lock = GameLock.tryLockRO( srcRowid ) ) {
|
||||||
|
@ -582,10 +592,18 @@ public class GameUtils {
|
||||||
CurGameInfo gi = new CurGameInfo( context );
|
CurGameInfo gi = new CurGameInfo( context );
|
||||||
try ( GamePtr gamePtr = loadMakeGame( context, gi, lock ) ) {
|
try ( GamePtr gamePtr = loadMakeGame( context, gi, lock ) ) {
|
||||||
if ( null != gamePtr ) {
|
if ( null != gamePtr ) {
|
||||||
|
RematchOrder ro = RematchOrder.RO_SAME;
|
||||||
|
if ( XwJNI.server_canOfferRematch( gamePtr ) ) {
|
||||||
|
ro = XWPrefs.getDefaultRematchOrder( context );
|
||||||
|
if ( null == ro ) {
|
||||||
|
ro = nro.getRematchOrder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( null != ro ) {
|
||||||
UtilCtxt util = new UtilCtxtImpl( context );
|
UtilCtxt util = new UtilCtxtImpl( context );
|
||||||
CommonPrefs cp = CommonPrefs.get(context);
|
CommonPrefs cp = CommonPrefs.get( context );
|
||||||
try ( GamePtr gamePtrNew = XwJNI
|
try ( GamePtr gamePtrNew = XwJNI
|
||||||
.game_makeRematch( gamePtr, util, cp, gameName ) ) {
|
.game_makeRematch( gamePtr, util, cp, gameName, ro ) ) {
|
||||||
if ( null != gamePtrNew ) {
|
if ( null != gamePtrNew ) {
|
||||||
rowid = saveNewGame1( context, gamePtrNew,
|
rowid = saveNewGame1( context, gamePtrNew,
|
||||||
groupID, gameName );
|
groupID, gameName );
|
||||||
|
@ -595,6 +613,7 @@ public class GameUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Log.d( TAG, "makeRematch() => %d", rowid );
|
Log.d( TAG, "makeRematch() => %d", rowid );
|
||||||
return rowid;
|
return rowid;
|
||||||
|
|
|
@ -67,6 +67,7 @@ import org.eehouse.android.xw4.jni.CurGameInfo;
|
||||||
import org.eehouse.android.xw4.jni.GameSummary;
|
import org.eehouse.android.xw4.jni.GameSummary;
|
||||||
import org.eehouse.android.xw4.jni.LastMoveInfo;
|
import org.eehouse.android.xw4.jni.LastMoveInfo;
|
||||||
import org.eehouse.android.xw4.jni.XwJNI;
|
import org.eehouse.android.xw4.jni.XwJNI;
|
||||||
|
import org.eehouse.android.xw4.jni.XwJNI.RematchOrder;
|
||||||
import org.eehouse.android.xw4.loc.LocUtils;
|
import org.eehouse.android.xw4.loc.LocUtils;
|
||||||
import static org.eehouse.android.xw4.DBUtils.ROWID_NOTFOUND;
|
import static org.eehouse.android.xw4.DBUtils.ROWID_NOTFOUND;
|
||||||
|
|
||||||
|
@ -874,6 +875,12 @@ public class GamesListDelegate extends ListDelegateBase
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GAMES_LIST_GET_RO: {
|
||||||
|
NRO nro = (NRO)params[0];
|
||||||
|
dialog = mkRematchConfigDlg( nro );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case GAMES_LIST_NAME_REMATCH: {
|
case GAMES_LIST_NAME_REMATCH: {
|
||||||
final LinearLayout view = (LinearLayout)
|
final LinearLayout view = (LinearLayout)
|
||||||
LocUtils.inflate( m_activity, R.layout.msg_label_and_edit );
|
LocUtils.inflate( m_activity, R.layout.msg_label_and_edit );
|
||||||
|
@ -1577,6 +1584,30 @@ public class GamesListDelegate extends ListDelegateBase
|
||||||
return handled || super.onDismissed( action, params );
|
return handled || super.onDismissed( action, params );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Dialog mkRematchConfigDlg( NRO nro )
|
||||||
|
{
|
||||||
|
final RematchConfigView view = (RematchConfigView)
|
||||||
|
LocUtils.inflate( m_activity, R.layout.rematch_config );
|
||||||
|
|
||||||
|
int iconResID = nro.isSolo()
|
||||||
|
? R.drawable.ic_sologame : R.drawable.ic_multigame;
|
||||||
|
AlertDialog.Builder ab = makeAlertBuilder()
|
||||||
|
.setView( view )
|
||||||
|
.setIcon( iconResID )
|
||||||
|
.setTitle( R.string.button_rematch )
|
||||||
|
.setNegativeButton( android.R.string.cancel, null )
|
||||||
|
.setPositiveButton( android.R.string.ok,
|
||||||
|
new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick( DialogInterface dlg, int ii ) {
|
||||||
|
RematchOrder ro = view.onOkClicked();
|
||||||
|
nro.rerun( ro );
|
||||||
|
}
|
||||||
|
} )
|
||||||
|
;
|
||||||
|
return ab.create();
|
||||||
|
}
|
||||||
|
|
||||||
private Dialog mkLoadStoreDlg( final Uri uri )
|
private Dialog mkLoadStoreDlg( final Uri uri )
|
||||||
{
|
{
|
||||||
final BackupConfigView view = (BackupConfigView)
|
final BackupConfigView view = (BackupConfigView)
|
||||||
|
@ -2358,6 +2389,7 @@ public class GamesListDelegate extends ListDelegateBase
|
||||||
button.setVisibility( View.VISIBLE );
|
button.setVisibility( View.VISIBLE );
|
||||||
final boolean solo = isSolos[ii];
|
final boolean solo = isSolos[ii];
|
||||||
button.setOnClickListener( new View.OnClickListener() {
|
button.setOnClickListener( new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
public void onClick( View view ) {
|
public void onClick( View view ) {
|
||||||
curThis().handleNewGameButton( solo );
|
curThis().handleNewGameButton( solo );
|
||||||
}
|
}
|
||||||
|
@ -2710,7 +2742,52 @@ public class GamesListDelegate extends ListDelegateBase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class NRO implements Serializable, GameUtils.NeedRematchOrder {
|
||||||
|
private RematchOrder mChosenOrder = null;
|
||||||
|
private Bundle mExtras;
|
||||||
|
private String mGameName;
|
||||||
|
private CommsConnTypeSet mAddrs;
|
||||||
|
|
||||||
|
NRO( Bundle extras, String gameName, CommsConnTypeSet addrs )
|
||||||
|
{
|
||||||
|
mExtras = extras;
|
||||||
|
mGameName = gameName;
|
||||||
|
mAddrs = addrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RematchOrder getRematchOrder()
|
||||||
|
{
|
||||||
|
RematchOrder result = mChosenOrder;
|
||||||
|
if ( null == result ) {
|
||||||
|
showDialogFragment( DlgID.GAMES_LIST_GET_RO, this );
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isSolo() { return mExtras.getBoolean( REMATCH_IS_SOLO, true ); }
|
||||||
|
|
||||||
|
void rerun( RematchOrder ro )
|
||||||
|
{
|
||||||
|
mChosenOrder = ro;
|
||||||
|
m_rematchExtras = mExtras;
|
||||||
|
runOnUiThread( new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
rematchWithNameAndPerm( mGameName, mAddrs, NRO.this );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
} // class NRO
|
||||||
|
|
||||||
private void rematchWithNameAndPerm( String gameName, CommsConnTypeSet addrs )
|
private void rematchWithNameAndPerm( String gameName, CommsConnTypeSet addrs )
|
||||||
|
{
|
||||||
|
NRO nro = new NRO( m_rematchExtras, gameName, addrs );
|
||||||
|
rematchWithNameAndPerm( gameName, addrs, nro );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rematchWithNameAndPerm( String gameName, CommsConnTypeSet addrs,
|
||||||
|
NRO nro )
|
||||||
{
|
{
|
||||||
if ( null != gameName && 0 < gameName.length() ) {
|
if ( null != gameName && 0 < gameName.length() ) {
|
||||||
Bundle extras = m_rematchExtras;
|
Bundle extras = m_rematchExtras;
|
||||||
|
@ -2720,8 +2797,9 @@ public class GamesListDelegate extends ListDelegateBase
|
||||||
DBUtils.GROUPID_UNSPEC );
|
DBUtils.GROUPID_UNSPEC );
|
||||||
|
|
||||||
long newid = GameUtils.makeRematch( m_activity, srcRowID,
|
long newid = GameUtils.makeRematch( m_activity, srcRowID,
|
||||||
groupID, gameName );
|
groupID, gameName, nro );
|
||||||
|
|
||||||
|
if ( DBUtils.ROWID_NOTFOUND != newid ) {
|
||||||
if ( extras.getBoolean( REMATCH_DELAFTER_EXTRA, false ) ) {
|
if ( extras.getBoolean( REMATCH_DELAFTER_EXTRA, false ) ) {
|
||||||
String name = DBUtils.getName( m_activity, srcRowID );
|
String name = DBUtils.getName( m_activity, srcRowID );
|
||||||
makeConfirmThenBuilder( Action.LAUNCH_AFTER_DEL,
|
makeConfirmThenBuilder( Action.LAUNCH_AFTER_DEL,
|
||||||
|
@ -2733,6 +2811,7 @@ public class GamesListDelegate extends ListDelegateBase
|
||||||
launchGame( newid );
|
launchGame( newid );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
m_rematchExtras = null;
|
m_rematchExtras = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
/* -*- compile-command: "find-and-gradle.sh inXw4dDeb"; -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2020 by Eric House (xwords@eehouse.org). All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.eehouse.android.xw4;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.AdapterView.OnItemSelectedListener;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.RadioButton;
|
||||||
|
import android.widget.RadioGroup;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eehouse.android.xw4.jni.XwJNI.RematchOrder;
|
||||||
|
import org.eehouse.android.xw4.loc.LocUtils;
|
||||||
|
|
||||||
|
public class RematchConfigView extends LinearLayout
|
||||||
|
{
|
||||||
|
private Context mContext;
|
||||||
|
private RadioGroup mGroup;
|
||||||
|
Map<Integer, RematchOrder> mRos = new HashMap<>();
|
||||||
|
|
||||||
|
public RematchConfigView( Context cx, AttributeSet as )
|
||||||
|
{
|
||||||
|
super( cx, as );
|
||||||
|
mContext = cx;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onFinishInflate()
|
||||||
|
{
|
||||||
|
mGroup = (RadioGroup)findViewById( R.id.group );
|
||||||
|
for ( RematchOrder ro : RematchOrder.values() ) {
|
||||||
|
RadioButton button = new RadioButton( mContext );
|
||||||
|
button.setText( LocUtils.getString( mContext, ro.getStrID() ) );
|
||||||
|
mGroup.addView( button );
|
||||||
|
mRos.put( button.getId(), ro );
|
||||||
|
if ( 1 == mRos.size() ) {
|
||||||
|
button.setChecked( true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RematchOrder onOkClicked()
|
||||||
|
{
|
||||||
|
int id = mGroup.getCheckedRadioButtonId();
|
||||||
|
RematchOrder ro = mRos.get(id);
|
||||||
|
|
||||||
|
// Save it if default button checked
|
||||||
|
CheckBox check = (CheckBox)findViewById( R.id.make_default );
|
||||||
|
if ( check.isChecked() ) {
|
||||||
|
XWPrefs.setDefaultRematchOrder( mContext, ro );
|
||||||
|
}
|
||||||
|
|
||||||
|
return ro;
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,6 +32,8 @@ import org.json.JSONObject;
|
||||||
|
|
||||||
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
|
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
|
||||||
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnTypeSet;
|
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnTypeSet;
|
||||||
|
import org.eehouse.android.xw4.jni.XwJNI.RematchOrder;
|
||||||
|
|
||||||
|
|
||||||
public class XWPrefs {
|
public class XWPrefs {
|
||||||
private static final String TAG = XWPrefs.class.getSimpleName();
|
private static final String TAG = XWPrefs.class.getSimpleName();
|
||||||
|
@ -328,6 +330,30 @@ public class XWPrefs {
|
||||||
return groupID;
|
return groupID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setDefaultRematchOrder( Context context, RematchOrder ro )
|
||||||
|
{
|
||||||
|
String storedStr = null == ro ? "" : context.getString( ro.getStrID() );
|
||||||
|
setPrefsString( context, R.string.key_rematch_order, storedStr );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RematchOrder getDefaultRematchOrder( Context context )
|
||||||
|
{
|
||||||
|
String storedStr = getPrefsString( context, R.string.key_rematch_order );
|
||||||
|
|
||||||
|
// Let's try to get this from the enum...
|
||||||
|
RematchOrder ro = null;
|
||||||
|
for ( RematchOrder one: RematchOrder.values() ) {
|
||||||
|
int strID = one.getStrID();
|
||||||
|
String str = context.getString( strID );
|
||||||
|
if ( str.equals( storedStr ) ) {
|
||||||
|
ro = one;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ro;
|
||||||
|
}
|
||||||
|
|
||||||
public static void setDefaultNewGameGroup( Context context, long val )
|
public static void setDefaultNewGameGroup( Context context, long val )
|
||||||
{
|
{
|
||||||
Assert.assertTrue( DBUtils.GROUPID_UNSPEC != val );
|
Assert.assertTrue( DBUtils.GROUPID_UNSPEC != val );
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.eehouse.android.xw4.DbgUtils;
|
||||||
import org.eehouse.android.xw4.Log;
|
import org.eehouse.android.xw4.Log;
|
||||||
import org.eehouse.android.xw4.NetLaunchInfo;
|
import org.eehouse.android.xw4.NetLaunchInfo;
|
||||||
import org.eehouse.android.xw4.Quarantine;
|
import org.eehouse.android.xw4.Quarantine;
|
||||||
|
import org.eehouse.android.xw4.R;
|
||||||
import org.eehouse.android.xw4.Utils.ISOCode;
|
import org.eehouse.android.xw4.Utils.ISOCode;
|
||||||
import org.eehouse.android.xw4.Utils;
|
import org.eehouse.android.xw4.Utils;
|
||||||
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
|
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
|
||||||
|
@ -336,11 +337,24 @@ public class XwJNI {
|
||||||
return gamePtr;
|
return gamePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keep in sync with server.h
|
||||||
|
public enum RematchOrder {
|
||||||
|
RO_SAME(R.string.ro_same),
|
||||||
|
RO_LOW_SCORE_FIRST(R.string.ro_low_score_first),
|
||||||
|
RO_HIGH_SCORE_FIRST(R.string.ro_high_score_first),
|
||||||
|
RO_JUGGLE(R.string.ro_juggle),
|
||||||
|
;
|
||||||
|
private int mStrID;
|
||||||
|
private RematchOrder(int str) { mStrID = str; }
|
||||||
|
public int getStrID() { return mStrID; }
|
||||||
|
};
|
||||||
|
|
||||||
public static GamePtr game_makeRematch( GamePtr gamePtr, UtilCtxt util,
|
public static GamePtr game_makeRematch( GamePtr gamePtr, UtilCtxt util,
|
||||||
CommonPrefs cp, String gameName )
|
CommonPrefs cp, String gameName,
|
||||||
|
RematchOrder ro )
|
||||||
{
|
{
|
||||||
GamePtr gamePtrNew = initGameJNI( 0 );
|
GamePtr gamePtrNew = initGameJNI( 0 );
|
||||||
if ( !game_makeRematch( gamePtr, gamePtrNew, util, cp, gameName ) ) {
|
if ( !game_makeRematch( gamePtr, gamePtrNew, util, cp, gameName, ro ) ) {
|
||||||
gamePtrNew.release();
|
gamePtrNew.release();
|
||||||
gamePtrNew = null;
|
gamePtrNew = null;
|
||||||
}
|
}
|
||||||
|
@ -384,7 +398,7 @@ public class XwJNI {
|
||||||
private static native boolean game_makeRematch( GamePtr gamePtr,
|
private static native boolean game_makeRematch( GamePtr gamePtr,
|
||||||
GamePtr gamePtrNew,
|
GamePtr gamePtrNew,
|
||||||
UtilCtxt util, CommonPrefs cp,
|
UtilCtxt util, CommonPrefs cp,
|
||||||
String gameName );
|
String gameName, RematchOrder ro );
|
||||||
|
|
||||||
private static native boolean game_makeFromInvite( GamePtr gamePtr, NetLaunchInfo nli,
|
private static native boolean game_makeFromInvite( GamePtr gamePtr, NetLaunchInfo nli,
|
||||||
UtilCtxt util,
|
UtilCtxt util,
|
||||||
|
@ -536,6 +550,7 @@ public class XwJNI {
|
||||||
public static native boolean server_getGameIsConnected( GamePtr gamePtr );
|
public static native boolean server_getGameIsConnected( GamePtr gamePtr );
|
||||||
public static native String server_writeFinalScores( GamePtr gamePtr );
|
public static native String server_writeFinalScores( GamePtr gamePtr );
|
||||||
public static native boolean server_initClientConnection( GamePtr gamePtr );
|
public static native boolean server_initClientConnection( GamePtr gamePtr );
|
||||||
|
public static native boolean server_canOfferRematch( GamePtr gamePtr );
|
||||||
public static native void server_endGame( GamePtr gamePtr );
|
public static native void server_endGame( GamePtr gamePtr );
|
||||||
|
|
||||||
// hybrid to save work
|
// hybrid to save work
|
||||||
|
|
32
xwords4/android/app/src/main/res/layout/rematch_config.xml
Normal file
32
xwords4/android/app/src/main/res/layout/rematch_config.xml
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<org.eehouse.android.xw4.RematchConfigView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:padding="8dp"
|
||||||
|
>
|
||||||
|
|
||||||
|
<TextView android:id="@+id/explanation"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:text="@string/expl_rematch_order"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<RadioGroup android:id="@+id/group"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<CheckBox android:id="@+id/make_default"
|
||||||
|
android:text="@string/dicts_item_select"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_marginLeft="12dp"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</org.eehouse.android.xw4.RematchConfigView>
|
|
@ -83,6 +83,7 @@
|
||||||
<string name="key_robot_name">key_robot_name</string>
|
<string name="key_robot_name">key_robot_name</string>
|
||||||
<string name="key_default_robodict">key_default_robodict</string>
|
<string name="key_default_robodict">key_default_robodict</string>
|
||||||
<string name="key_default_phonies">key_default_phonies2</string>
|
<string name="key_default_phonies">key_default_phonies2</string>
|
||||||
|
<string name="key_rematch_order">key_rematch_order</string>
|
||||||
<string name="key_default_timerenabled">key_default_timerenabled</string>
|
<string name="key_default_timerenabled">key_default_timerenabled</string>
|
||||||
<string name="key_notify_sound">key_notify_sound</string>
|
<string name="key_notify_sound">key_notify_sound</string>
|
||||||
<string name="key_disable_mqtt">key_disable_mqtt</string>
|
<string name="key_disable_mqtt">key_disable_mqtt</string>
|
||||||
|
@ -222,6 +223,14 @@
|
||||||
<item>@string/phonies_block</item>
|
<item>@string/phonies_block</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="ro_names">
|
||||||
|
<item>@string/ro_no_default</item>
|
||||||
|
<item>@string/ro_same</item>
|
||||||
|
<item>@string/ro_low_score_first</item>
|
||||||
|
<item>@string/ro_high_score_first</item>
|
||||||
|
<item>@string/ro_juggle</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<string-array name="robot_levels">
|
<string-array name="robot_levels">
|
||||||
<item>@string/robot_smartest</item>
|
<item>@string/robot_smartest</item>
|
||||||
<item>@string/robot_smarter</item>
|
<item>@string/robot_smarter</item>
|
||||||
|
|
|
@ -5,4 +5,12 @@
|
||||||
|
|
||||||
<string name="dup_allscores_fmt">All scores: %1$s</string>
|
<string name="dup_allscores_fmt">All scores: %1$s</string>
|
||||||
|
|
||||||
|
<string name="expl_rematch_order">Choose how to order players in the new game</string>
|
||||||
|
<string name="title_rematch_order">Rematched Players Order</string>
|
||||||
|
<string name="ro_no_default">Ask each time</string>
|
||||||
|
<string name="ro_same">Same as this game</string>
|
||||||
|
<string name="ro_low_score_first">Low scorer goes first</string>
|
||||||
|
<string name="ro_high_score_first">High scorer goes first</string>
|
||||||
|
<string name="ro_juggle">Randomly</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -16,6 +16,13 @@
|
||||||
android:title="@string/title_addrs_pref"
|
android:title="@string/title_addrs_pref"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<org.eehouse.android.xw4.XWListPreference
|
||||||
|
android:key="@string/key_rematch_order"
|
||||||
|
android:title="@string/title_rematch_order"
|
||||||
|
android:entries="@array/ro_names"
|
||||||
|
android:entryValues="@array/ro_names"
|
||||||
|
/>
|
||||||
|
|
||||||
<Preference app:title="@string/prefs_dicts"
|
<Preference app:title="@string/prefs_dicts"
|
||||||
app:summary="@string/prefs_dicts_summary"
|
app:summary="@string/prefs_dicts_summary"
|
||||||
app:fragment="org.eehouse.android.xw4.gen.PrefsWrappers$prefs_dflts_dicts"
|
app:fragment="org.eehouse.android.xw4.gen.PrefsWrappers$prefs_dflts_dicts"
|
||||||
|
|
|
@ -1423,7 +1423,7 @@ initGameGlobals( JNIEnv* env, JNIState* state, jobject jutil, jobject jprocs )
|
||||||
JNIEXPORT jboolean JNICALL
|
JNIEXPORT jboolean JNICALL
|
||||||
Java_org_eehouse_android_xw4_jni_XwJNI_game_1makeRematch
|
Java_org_eehouse_android_xw4_jni_XwJNI_game_1makeRematch
|
||||||
( JNIEnv* env, jclass C, GamePtrType gamePtr, GamePtrType gamePtrNew,
|
( JNIEnv* env, jclass C, GamePtrType gamePtr, GamePtrType gamePtrNew,
|
||||||
jobject jutil, jobject jcp, jstring jGameName )
|
jobject jutil, jobject jcp, jstring jGameName, jobject jRo )
|
||||||
{
|
{
|
||||||
jboolean success = false;
|
jboolean success = false;
|
||||||
XWJNI_START_GLOBALS(gamePtr);
|
XWJNI_START_GLOBALS(gamePtr);
|
||||||
|
@ -1437,8 +1437,10 @@ Java_org_eehouse_android_xw4_jni_XwJNI_game_1makeRematch
|
||||||
loadCommonPrefs( env, &cp, jcp );
|
loadCommonPrefs( env, &cp, jcp );
|
||||||
|
|
||||||
const char* gameName = (*env)->GetStringUTFChars( env, jGameName, NULL );
|
const char* gameName = (*env)->GetStringUTFChars( env, jGameName, NULL );
|
||||||
|
RematchOrder ro = jEnumToInt( env, jRo );
|
||||||
success = game_makeRematch( &oldState->game, env, globals->util, &cp,
|
success = game_makeRematch( &oldState->game, env, globals->util, &cp,
|
||||||
(TransportProcs*)NULL, &state->game, gameName );
|
(TransportProcs*)NULL, &state->game,
|
||||||
|
gameName, ro );
|
||||||
(*env)->ReleaseStringUTFChars( env, jGameName, gameName );
|
(*env)->ReleaseStringUTFChars( env, jGameName, gameName );
|
||||||
|
|
||||||
if ( success ) {
|
if ( success ) {
|
||||||
|
@ -2200,6 +2202,19 @@ Java_org_eehouse_android_xw4_jni_XwJNI_server_1initClientConnection
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
Java_org_eehouse_android_xw4_jni_XwJNI_server_1canOfferRematch
|
||||||
|
( JNIEnv* env, jclass C, GamePtrType gamePtr )
|
||||||
|
{
|
||||||
|
jboolean result;
|
||||||
|
XWJNI_START_GLOBALS(gamePtr);
|
||||||
|
XP_Bool canOffer;
|
||||||
|
XP_Bool canRematch= server_canRematch( state->game.server, &canOffer );
|
||||||
|
result = canRematch && canOffer;
|
||||||
|
XWJNI_END();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_org_eehouse_android_xw4_jni_XwJNI_comms_1start
|
Java_org_eehouse_android_xw4_jni_XwJNI_comms_1start
|
||||||
( JNIEnv* env, jclass C, GamePtrType gamePtr )
|
( JNIEnv* env, jclass C, GamePtrType gamePtr )
|
||||||
|
|
|
@ -239,6 +239,7 @@ struct CommsCtxt {
|
||||||
|
|
||||||
#define FLAG_HARVEST_DONE 1
|
#define FLAG_HARVEST_DONE 1
|
||||||
#define FLAG_QUASHED 2
|
#define FLAG_QUASHED 2
|
||||||
|
|
||||||
#define QUASHED(COMMS) (0 != ((COMMS)->flags & FLAG_QUASHED))
|
#define QUASHED(COMMS) (0 != ((COMMS)->flags & FLAG_QUASHED))
|
||||||
|
|
||||||
#if defined XWFEATURE_IP_DIRECT || defined XWFEATURE_DIRECTIP
|
#if defined XWFEATURE_IP_DIRECT || defined XWFEATURE_DIRECTIP
|
||||||
|
@ -655,7 +656,7 @@ comms_setConnID( CommsCtxt* comms, XP_U32 connID, XP_U16 streamVersion )
|
||||||
XP_ASSERT( 0 == comms->streamVersion
|
XP_ASSERT( 0 == comms->streamVersion
|
||||||
|| streamVersion == comms->streamVersion );
|
|| streamVersion == comms->streamVersion );
|
||||||
comms->streamVersion = streamVersion;
|
comms->streamVersion = streamVersion;
|
||||||
XP_LOGFF( "set connID (gameID) to %x, streamVersion to 0x%X",
|
XP_LOGFF( "set connID (gameID) to %X, streamVersion to 0x%X",
|
||||||
connID, streamVersion );
|
connID, streamVersion );
|
||||||
THREAD_CHECK_END();
|
THREAD_CHECK_END();
|
||||||
} /* comms_setConnID */
|
} /* comms_setConnID */
|
||||||
|
@ -724,6 +725,7 @@ addrFromStreamOne( CommsAddrRec* addrP, XWStreamCtxt* stream, CommsConnType typ
|
||||||
void
|
void
|
||||||
addrFromStream( CommsAddrRec* addrP, XWStreamCtxt* stream )
|
addrFromStream( CommsAddrRec* addrP, XWStreamCtxt* stream )
|
||||||
{
|
{
|
||||||
|
XP_MEMSET( addrP, 0, sizeof(*addrP) );
|
||||||
XP_U8 tmp = stream_getU8( stream );
|
XP_U8 tmp = stream_getU8( stream );
|
||||||
XP_U16 version = stream_getVersion( stream );
|
XP_U16 version = stream_getVersion( stream );
|
||||||
XP_ASSERT( 0 < version );
|
XP_ASSERT( 0 < version );
|
||||||
|
@ -1381,6 +1383,41 @@ comms_getChannelAddr( const CommsCtxt* comms, XP_PlayerAddr channelNo,
|
||||||
XP_ASSERT( found );
|
XP_ASSERT( found );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static XP_Bool
|
||||||
|
addrs_same( const CommsAddrRec* addr1, const CommsAddrRec* addr2 )
|
||||||
|
{
|
||||||
|
/* Empty addresses are the same only if both are empty */
|
||||||
|
XP_Bool same = addr1->_conTypes == 0 && addr2->_conTypes == 0;
|
||||||
|
|
||||||
|
CommsConnType typ;
|
||||||
|
for ( XP_U32 st = 0; !same && addr_iter( addr1, &typ, &st ); ) {
|
||||||
|
if ( addr_hasType( addr2, typ ) ) {
|
||||||
|
switch ( typ ) {
|
||||||
|
case COMMS_CONN_MQTT:
|
||||||
|
same = addr1->u.mqtt.devID == addr2->u.mqtt.devID;
|
||||||
|
break;
|
||||||
|
case COMMS_CONN_SMS:
|
||||||
|
same = addr1->u.sms.port == addr2->u.sms.port
|
||||||
|
&& 0 == XP_STRCMP(addr1->u.sms.phone, addr2->u.sms.phone );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
XP_LOGFF( "ignoring %s", ConnType2Str(typ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return same;
|
||||||
|
}
|
||||||
|
|
||||||
|
XP_Bool
|
||||||
|
comms_addrsAreSame( const CommsCtxt* XP_UNUSED(comms),
|
||||||
|
const CommsAddrRec* addr1,
|
||||||
|
const CommsAddrRec* addr2 )
|
||||||
|
{
|
||||||
|
XP_Bool result = addrs_same( addr1, addr2 );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct _NonAcks {
|
typedef struct _NonAcks {
|
||||||
int count;
|
int count;
|
||||||
} NonAcks;
|
} NonAcks;
|
||||||
|
@ -3604,16 +3641,16 @@ static void
|
||||||
logAddrComms( const CommsCtxt* comms, const CommsAddrRec* addr,
|
logAddrComms( const CommsCtxt* comms, const CommsAddrRec* addr,
|
||||||
const char* caller )
|
const char* caller )
|
||||||
{
|
{
|
||||||
logAddr( MPPARM(comms->mpool) comms->dutil, addr, caller );
|
logAddr( comms->dutil, addr, caller );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
logAddr( MPFORMAL XW_DUtilCtxt* dutil, const CommsAddrRec* addr,
|
logAddr( XW_DUtilCtxt* dutil, const CommsAddrRec* addr,
|
||||||
const char* caller )
|
const char* caller )
|
||||||
{
|
{
|
||||||
if ( !!addr ) {
|
if ( !!addr ) {
|
||||||
char buf[128];
|
char buf[128];
|
||||||
XWStreamCtxt* stream = mem_stream_make_raw( MPPARM(mpool)
|
XWStreamCtxt* stream = mem_stream_make_raw( MPPARM(dutil->mpool)
|
||||||
dutil_getVTManager(dutil));
|
dutil_getVTManager(dutil));
|
||||||
if ( !!caller ) {
|
if ( !!caller ) {
|
||||||
snprintf( buf, sizeof(buf), "called on %p from %s:\n",
|
snprintf( buf, sizeof(buf), "called on %p from %s:\n",
|
||||||
|
@ -3872,6 +3909,14 @@ types_hasType( XP_U16 conTypes, CommsConnType typ )
|
||||||
return hasType;
|
return hasType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XP_Bool
|
||||||
|
addr_isEmpty( const CommsAddrRec* addr )
|
||||||
|
{
|
||||||
|
CommsConnType typ;
|
||||||
|
XP_U32 st = 0;
|
||||||
|
return !addr_iter( addr, &typ, &st );
|
||||||
|
}
|
||||||
|
|
||||||
CommsConnType
|
CommsConnType
|
||||||
addr_getType( const CommsAddrRec* addr )
|
addr_getType( const CommsAddrRec* addr )
|
||||||
{
|
{
|
||||||
|
|
|
@ -219,6 +219,8 @@ XP_S16 comms_resendAll( CommsCtxt* comms, XWEnv xwe, CommsConnType filter,
|
||||||
XP_U16 comms_getChannelSeed( CommsCtxt* comms );
|
XP_U16 comms_getChannelSeed( CommsCtxt* comms );
|
||||||
void comms_getChannelAddr( const CommsCtxt* comms, XP_PlayerAddr channelNo,
|
void comms_getChannelAddr( const CommsCtxt* comms, XP_PlayerAddr channelNo,
|
||||||
CommsAddrRec* addr );
|
CommsAddrRec* addr );
|
||||||
|
XP_Bool comms_addrsAreSame( const CommsCtxt* comms, const CommsAddrRec* addr1,
|
||||||
|
const CommsAddrRec* addr2 );
|
||||||
|
|
||||||
#ifdef XWFEATURE_COMMSACK
|
#ifdef XWFEATURE_COMMSACK
|
||||||
void comms_ackAny( CommsCtxt* comms, XWEnv xwe );
|
void comms_ackAny( CommsCtxt* comms, XWEnv xwe );
|
||||||
|
@ -256,6 +258,7 @@ void comms_gameJoined( CommsCtxt* comms, const XP_UCHAR* connname, XWHostID hid
|
||||||
XP_Bool augmentAddr( CommsAddrRec* addr, const CommsAddrRec* newer,
|
XP_Bool augmentAddr( CommsAddrRec* addr, const CommsAddrRec* newer,
|
||||||
XP_Bool isNewer );
|
XP_Bool isNewer );
|
||||||
|
|
||||||
|
XP_Bool addr_isEmpty( const CommsAddrRec* addr );
|
||||||
CommsConnType addr_getType( const CommsAddrRec* addr );
|
CommsConnType addr_getType( const CommsAddrRec* addr );
|
||||||
void addr_setType( CommsAddrRec* addr, CommsConnType type );
|
void addr_setType( CommsAddrRec* addr, CommsConnType type );
|
||||||
void addr_addType( CommsAddrRec* addr, CommsConnType type );
|
void addr_addType( CommsAddrRec* addr, CommsConnType type );
|
||||||
|
@ -283,7 +286,7 @@ void comms_setAddrDisabled( CommsCtxt* comms, CommsConnType typ,
|
||||||
XP_Bool send, XP_Bool enabled );
|
XP_Bool send, XP_Bool enabled );
|
||||||
XP_Bool comms_getAddrDisabled( const CommsCtxt* comms, CommsConnType typ,
|
XP_Bool comms_getAddrDisabled( const CommsCtxt* comms, CommsConnType typ,
|
||||||
XP_Bool send );
|
XP_Bool send );
|
||||||
void logAddr( MPFORMAL XW_DUtilCtxt* dutil, const CommsAddrRec* addr,
|
void logAddr( XW_DUtilCtxt* dutil, const CommsAddrRec* addr,
|
||||||
const char* caller );
|
const char* caller );
|
||||||
|
|
||||||
# else
|
# else
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#define MAX_COLS MAX_ROWS
|
#define MAX_COLS MAX_ROWS
|
||||||
#define MIN_COLS 11
|
#define MIN_COLS 11
|
||||||
|
|
||||||
|
#define STREAM_VERS_REMATCHORDER 0x25
|
||||||
#define STREAM_VERS_REMATCHADDRS 0x24
|
#define STREAM_VERS_REMATCHADDRS 0x24
|
||||||
#define STREAM_VERS_MSGSTREAMVERS 0x23
|
#define STREAM_VERS_MSGSTREAMVERS 0x23
|
||||||
#define STREAM_VERS_NORELAY 0x22
|
#define STREAM_VERS_NORELAY 0x22
|
||||||
|
@ -99,7 +100,7 @@
|
||||||
#define STREAM_VERS_405 0x01
|
#define STREAM_VERS_405 0x01
|
||||||
|
|
||||||
/* search for FIX_NEXT_VERSION_CHANGE next time this is changed */
|
/* search for FIX_NEXT_VERSION_CHANGE next time this is changed */
|
||||||
#define CUR_STREAM_VERS STREAM_VERS_REMATCHADDRS
|
#define CUR_STREAM_VERS STREAM_VERS_REMATCHORDER
|
||||||
|
|
||||||
typedef struct XP_Rect {
|
typedef struct XP_Rect {
|
||||||
XP_S16 left;
|
XP_S16 left;
|
||||||
|
|
|
@ -237,14 +237,14 @@ game_makeNewGame( MPFORMAL XWEnv xwe, XWGame* game, CurGameInfo* gi,
|
||||||
XP_Bool
|
XP_Bool
|
||||||
game_makeRematch( const XWGame* oldGame, XWEnv xwe, XW_UtilCtxt* newUtil,
|
game_makeRematch( const XWGame* oldGame, XWEnv xwe, XW_UtilCtxt* newUtil,
|
||||||
const CommonPrefs* newCp, const TransportProcs* procs,
|
const CommonPrefs* newCp, const TransportProcs* procs,
|
||||||
XWGame* newGame, const XP_UCHAR* newName )
|
XWGame* newGame, const XP_UCHAR* newName, RematchOrder ro )
|
||||||
{
|
{
|
||||||
XP_Bool success = XP_FALSE;
|
XP_Bool success = XP_FALSE;
|
||||||
XP_LOGFF( "(newName=%s)", newName );
|
XP_LOGFF( "(newName=%s, ro=%s)", newName, RO2Str(ro) );
|
||||||
|
|
||||||
RematchAddrs ra;
|
RematchInfo* rip;
|
||||||
if ( server_getRematchInfo( oldGame->server, newUtil,
|
if ( server_getRematchInfo( oldGame->server, newUtil,
|
||||||
makeGameID( newUtil ), &ra ) ) {
|
makeGameID( newUtil ), ro, &rip ) ) {
|
||||||
CommsAddrRec* selfAddrP = NULL;
|
CommsAddrRec* selfAddrP = NULL;
|
||||||
CommsAddrRec selfAddr;
|
CommsAddrRec selfAddr;
|
||||||
if ( !!oldGame->comms ) {
|
if ( !!oldGame->comms ) {
|
||||||
|
@ -255,20 +255,31 @@ game_makeRematch( const XWGame* oldGame, XWEnv xwe, XW_UtilCtxt* newUtil,
|
||||||
if ( game_makeNewGame( MPPARM(newUtil->mpool) xwe, newGame,
|
if ( game_makeNewGame( MPPARM(newUtil->mpool) xwe, newGame,
|
||||||
newUtil->gameInfo, selfAddrP, (CommsAddrRec*)NULL,
|
newUtil->gameInfo, selfAddrP, (CommsAddrRec*)NULL,
|
||||||
newUtil, (DrawCtx*)NULL, newCp, procs ) ) {
|
newUtil, (DrawCtx*)NULL, newCp, procs ) ) {
|
||||||
|
if ( !!newGame->comms ) {
|
||||||
|
server_setRematchOrder( newGame->server, rip );
|
||||||
|
|
||||||
const CurGameInfo* newGI = newUtil->gameInfo;
|
const CurGameInfo* newGI = newUtil->gameInfo;
|
||||||
for ( int ii = 0; ii < ra.nAddrs; ++ii ) {
|
for ( int ii = 0; ; ++ii ) {
|
||||||
|
CommsAddrRec guestAddr;
|
||||||
|
XP_U16 nPlayersH;
|
||||||
|
if ( !server_ri_getAddr( rip, ii, &guestAddr, &nPlayersH ) ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
XP_ASSERT( !comms_addrsAreSame( newGame->comms, &guestAddr,
|
||||||
|
&selfAddr ) );
|
||||||
|
|
||||||
NetLaunchInfo nli;
|
NetLaunchInfo nli;
|
||||||
/* hard-code one player per device -- for now */
|
nli_init( &nli, newGI, selfAddrP, nPlayersH, ii + 1 );
|
||||||
nli_init( &nli, newGI, selfAddrP, 1, ii + 1 );
|
|
||||||
if ( !!newName ) {
|
if ( !!newName ) {
|
||||||
nli_setGameName( &nli, newName );
|
nli_setGameName( &nli, newName );
|
||||||
}
|
}
|
||||||
LOGNLI( &nli );
|
LOGNLI( &nli );
|
||||||
comms_invite( newGame->comms, xwe, &nli, &ra.addrs[ii], XP_TRUE );
|
comms_invite( newGame->comms, xwe, &nli, &guestAddr, XP_TRUE );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
success = XP_TRUE;
|
success = XP_TRUE;
|
||||||
}
|
}
|
||||||
|
server_disposeRematchInfo( oldGame->server, &rip );
|
||||||
}
|
}
|
||||||
LOG_RETURNF( "%s", boolToStr(success) );
|
LOG_RETURNF( "%s", boolToStr(success) );
|
||||||
return success;
|
return success;
|
||||||
|
@ -518,8 +529,7 @@ game_getState( const XWGame* game, XWEnv xwe, GameStateInfo* gsi )
|
||||||
gsi->canTrade = board_canTrade( board, xwe );
|
gsi->canTrade = board_canTrade( board, xwe );
|
||||||
gsi->nPendingMessages = !!game->comms ?
|
gsi->nPendingMessages = !!game->comms ?
|
||||||
comms_countPendingPackets(game->comms, NULL) : 0;
|
comms_countPendingPackets(game->comms, NULL) : 0;
|
||||||
|
gsi->canRematch = server_canRematch( server, NULL );
|
||||||
gsi->canRematch = server_canRematch( server );
|
|
||||||
gsi->canPause = server_canPause( server );
|
gsi->canPause = server_canPause( server );
|
||||||
gsi->canUnpause = server_canUnpause( server );
|
gsi->canUnpause = server_canUnpause( server );
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,9 +86,11 @@ XP_Bool game_makeNewGame( MPFORMAL XWEnv xwe, XWGame* game, CurGameInfo* gi,
|
||||||
,XP_U16 gameSeed
|
,XP_U16 gameSeed
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
|
|
||||||
XP_Bool game_makeRematch( const XWGame* game, XWEnv xwe, XW_UtilCtxt* util,
|
XP_Bool game_makeRematch( const XWGame* game, XWEnv xwe, XW_UtilCtxt* util,
|
||||||
const CommonPrefs* cp, const TransportProcs* procs,
|
const CommonPrefs* cp, const TransportProcs* procs,
|
||||||
XWGame* newGame, const XP_UCHAR* newName );
|
XWGame* newGame, const XP_UCHAR* newName,
|
||||||
|
RematchOrder ro );
|
||||||
|
|
||||||
void game_changeDict( MPFORMAL XWGame* game, XWEnv xwe, CurGameInfo* gi,
|
void game_changeDict( MPFORMAL XWGame* game, XWEnv xwe, CurGameInfo* gi,
|
||||||
DictionaryCtxt* dict );
|
DictionaryCtxt* dict );
|
||||||
|
|
|
@ -275,7 +275,7 @@ typedef struct WordNotifierInfo {
|
||||||
XP_Bool getCurrentMoveScoreIfLegal( ModelCtxt* model, XWEnv xwe,
|
XP_Bool getCurrentMoveScoreIfLegal( ModelCtxt* model, XWEnv xwe,
|
||||||
XP_S16 turn, XWStreamCtxt* stream,
|
XP_S16 turn, XWStreamCtxt* stream,
|
||||||
WordNotifierInfo* wni, XP_S16* score );
|
WordNotifierInfo* wni, XP_S16* score );
|
||||||
XP_S16 model_getPlayerScore( ModelCtxt* model, XP_S16 player );
|
XP_S16 model_getPlayerScore( const ModelCtxt* model, XP_S16 player );
|
||||||
|
|
||||||
XP_Bool model_getPlayersLastScore( ModelCtxt* model, XWEnv xwe, XP_S16 player,
|
XP_Bool model_getPlayersLastScore( ModelCtxt* model, XWEnv xwe, XP_S16 player,
|
||||||
LastMoveInfo* info );
|
LastMoveInfo* info );
|
||||||
|
@ -299,9 +299,12 @@ XP_Bool model_checkMoveLegal( ModelCtxt* model, XWEnv xwe, XP_S16 player,
|
||||||
WordNotifierInfo* notifyInfo );
|
WordNotifierInfo* notifyInfo );
|
||||||
|
|
||||||
typedef struct _ScoresArray { XP_S16 arr[MAX_NUM_PLAYERS]; } ScoresArray;
|
typedef struct _ScoresArray { XP_S16 arr[MAX_NUM_PLAYERS]; } ScoresArray;
|
||||||
void model_figureFinalScores( ModelCtxt* model, ScoresArray* scores,
|
void model_figureFinalScores( const ModelCtxt* model, ScoresArray* scores,
|
||||||
ScoresArray* tilePenalties );
|
ScoresArray* tilePenalties );
|
||||||
|
|
||||||
|
void model_getCurScores( const ModelCtxt* model, ScoresArray* scores,
|
||||||
|
XP_Bool gameOver );
|
||||||
|
|
||||||
/* figureMoveScore is meant only for the engine's use */
|
/* figureMoveScore is meant only for the engine's use */
|
||||||
XP_U16 figureMoveScore( const ModelCtxt* model, XWEnv xwe, XP_U16 turn,
|
XP_U16 figureMoveScore( const ModelCtxt* model, XWEnv xwe, XP_U16 turn,
|
||||||
const MoveInfo* mvInfo, EngineCtxt* engine,
|
const MoveInfo* mvInfo, EngineCtxt* engine,
|
||||||
|
|
|
@ -145,7 +145,7 @@ getCurrentMoveScoreIfLegal( ModelCtxt* model, XWEnv xwe, XP_S16 turn,
|
||||||
} /* getCurrentMoveScoreIfLegal */
|
} /* getCurrentMoveScoreIfLegal */
|
||||||
|
|
||||||
XP_S16
|
XP_S16
|
||||||
model_getPlayerScore( ModelCtxt* model, XP_S16 player )
|
model_getPlayerScore( const ModelCtxt* model, XP_S16 player )
|
||||||
{
|
{
|
||||||
return model->players[player].score;
|
return model->players[player].score;
|
||||||
} /* model_getPlayerScore */
|
} /* model_getPlayerScore */
|
||||||
|
@ -155,7 +155,7 @@ model_getPlayerScore( ModelCtxt* model, XP_S16 player )
|
||||||
* player.
|
* player.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
model_figureFinalScores( ModelCtxt* model, ScoresArray* finalScoresP,
|
model_figureFinalScores( const ModelCtxt* model, ScoresArray* finalScoresP,
|
||||||
ScoresArray* tilePenaltiesP )
|
ScoresArray* tilePenaltiesP )
|
||||||
{
|
{
|
||||||
XP_S16 ii, jj;
|
XP_S16 ii, jj;
|
||||||
|
@ -164,7 +164,7 @@ model_figureFinalScores( ModelCtxt* model, ScoresArray* finalScoresP,
|
||||||
XP_U16 nPlayers = model->nPlayers;
|
XP_U16 nPlayers = model->nPlayers;
|
||||||
XP_S16 firstDoneIndex = -1; /* not set unless FIRST_DONE_BONUS is set */
|
XP_S16 firstDoneIndex = -1; /* not set unless FIRST_DONE_BONUS is set */
|
||||||
const TrayTileSet* tray;
|
const TrayTileSet* tray;
|
||||||
PlayerCtxt* player;
|
const PlayerCtxt* player;
|
||||||
const DictionaryCtxt* dict = model_getDictionary( model );
|
const DictionaryCtxt* dict = model_getDictionary( model );
|
||||||
CurGameInfo* gi = model->vol.gi;
|
CurGameInfo* gi = model->vol.gi;
|
||||||
|
|
||||||
|
@ -217,6 +217,20 @@ model_figureFinalScores( ModelCtxt* model, ScoresArray* finalScoresP,
|
||||||
}
|
}
|
||||||
} /* model_figureFinalScores */
|
} /* model_figureFinalScores */
|
||||||
|
|
||||||
|
void
|
||||||
|
model_getCurScores( const ModelCtxt* model, ScoresArray* scores,
|
||||||
|
XP_Bool gameOver )
|
||||||
|
{
|
||||||
|
if ( gameOver ) {
|
||||||
|
model_figureFinalScores( model, scores, NULL );
|
||||||
|
} else {
|
||||||
|
int nPlayers = model->vol.gi->nPlayers;
|
||||||
|
for ( int ii = 0; ii < nPlayers; ++ii ) {
|
||||||
|
scores->arr[ii] = model_getPlayerScore( model, ii );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct _BlockCheckState {
|
typedef struct _BlockCheckState {
|
||||||
ModelCtxt* model;
|
ModelCtxt* model;
|
||||||
XWStreamCtxt* stream;
|
XWStreamCtxt* stream;
|
||||||
|
|
|
@ -33,8 +33,8 @@ typedef enum {OSType_NONE, OSType_LINUX, OSType_ANDROID, } XP_OSType;
|
||||||
typedef struct _NetLaunchInfo {
|
typedef struct _NetLaunchInfo {
|
||||||
XP_U16 _conTypes;
|
XP_U16 _conTypes;
|
||||||
|
|
||||||
XP_UCHAR gameName[MAX_GAME_NAME_LEN];
|
XP_UCHAR gameName[MAX_GAME_NAME_LEN+1];
|
||||||
XP_UCHAR dict[MAX_DICT_NAME_LEN];
|
XP_UCHAR dict[MAX_DICT_NAME_LEN+1];
|
||||||
XP_UCHAR isoCodeStr[MAX_ISO_CODE_LEN+1];
|
XP_UCHAR isoCodeStr[MAX_ISO_CODE_LEN+1];
|
||||||
XP_U8 forceChannel;
|
XP_U8 forceChannel;
|
||||||
XP_U8 nPlayersT;
|
XP_U8 nPlayersT;
|
||||||
|
@ -42,6 +42,9 @@ typedef struct _NetLaunchInfo {
|
||||||
XP_Bool remotesAreRobots;
|
XP_Bool remotesAreRobots;
|
||||||
XP_Bool inDuplicateMode;
|
XP_Bool inDuplicateMode;
|
||||||
|
|
||||||
|
XP_U32 gameID;
|
||||||
|
XP_UCHAR inviteID[32]; /* still used? */
|
||||||
|
|
||||||
/* Relay */
|
/* Relay */
|
||||||
XP_UCHAR room[MAX_INVITE_LEN + 1];
|
XP_UCHAR room[MAX_INVITE_LEN + 1];
|
||||||
XP_U32 devID; /* not used on android; remove?? */
|
XP_U32 devID; /* not used on android; remove?? */
|
||||||
|
@ -53,12 +56,9 @@ typedef struct _NetLaunchInfo {
|
||||||
// SMS
|
// SMS
|
||||||
XP_UCHAR phone[32];
|
XP_UCHAR phone[32];
|
||||||
XP_Bool isGSM;
|
XP_Bool isGSM;
|
||||||
XP_OSType osType;
|
XP_OSType osType; /* used? */
|
||||||
XP_U32 osVers;
|
XP_U32 osVers;
|
||||||
|
|
||||||
XP_U32 gameID;
|
|
||||||
XP_UCHAR inviteID[32];
|
|
||||||
|
|
||||||
/* MQTT */
|
/* MQTT */
|
||||||
XP_UCHAR mqttDevID[17];
|
XP_UCHAR mqttDevID[17];
|
||||||
} NetLaunchInfo;
|
} NetLaunchInfo;
|
||||||
|
|
|
@ -200,16 +200,10 @@ drawScoreBoard( BoardCtxt* board, XWEnv xwe )
|
||||||
#endif
|
#endif
|
||||||
/* Get the scores from the model or by calculating them based on
|
/* Get the scores from the model or by calculating them based on
|
||||||
the end-of-game state. */
|
the end-of-game state. */
|
||||||
if ( board->gameOver ) {
|
model_getCurScores( model, &scores, board->gameOver );
|
||||||
model_figureFinalScores( model, &scores, NULL );
|
|
||||||
} else {
|
|
||||||
for ( ii = 0; ii < nPlayers; ++ii ) {
|
|
||||||
scores.arr[ii] = model_getPlayerScore( model, ii );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( draw_scoreBegin( board->draw, xwe, &board->scoreBdBounds, nPlayers,
|
if ( draw_scoreBegin( board->draw, xwe, &board->scoreBdBounds,
|
||||||
scores.arr, nTilesInPool,
|
nPlayers, scores.arr, nTilesInPool,
|
||||||
dfsFor( board, OBJ_SCORE ) ) ) {
|
dfsFor( board, OBJ_SCORE ) ) ) {
|
||||||
XP_U16 totalDim = 0; /* not counting rem */
|
XP_U16 totalDim = 0; /* not counting rem */
|
||||||
XP_U16 gotPct;
|
XP_U16 gotPct;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -88,7 +88,7 @@ XP_S16 server_getTimerSeconds( const ServerCtxt* server, XWEnv xwe, XP_U16 turn
|
||||||
XP_Bool server_dupTurnDone( const ServerCtxt* server, XP_U16 turn );
|
XP_Bool server_dupTurnDone( const ServerCtxt* server, XP_U16 turn );
|
||||||
XP_Bool server_canPause( const ServerCtxt* server );
|
XP_Bool server_canPause( const ServerCtxt* server );
|
||||||
XP_Bool server_canUnpause( const ServerCtxt* server );
|
XP_Bool server_canUnpause( const ServerCtxt* server );
|
||||||
XP_Bool server_canRematch( const ServerCtxt* server );
|
XP_Bool server_canRematch( const ServerCtxt* server, XP_Bool* canOrder );
|
||||||
void server_pause( ServerCtxt* server, XWEnv xwe, XP_S16 turn, const XP_UCHAR* msg );
|
void server_pause( ServerCtxt* server, XWEnv xwe, XP_S16 turn, const XP_UCHAR* msg );
|
||||||
void server_unpause( ServerCtxt* server, XWEnv xwe, XP_S16 turn, const XP_UCHAR* msg );
|
void server_unpause( ServerCtxt* server, XWEnv xwe, XP_S16 turn, const XP_UCHAR* msg );
|
||||||
|
|
||||||
|
@ -146,18 +146,46 @@ XP_U16 server_figureFinishBonus( const ServerCtxt* server, XP_U16 turn );
|
||||||
XP_Bool server_getIsHost( const ServerCtxt* server );
|
XP_Bool server_getIsHost( const ServerCtxt* server );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct _RematchAddrs {
|
typedef enum {
|
||||||
CommsAddrRec addrs[MAX_NUM_PLAYERS];
|
RO_SAME, /* preserve the parent game's order */
|
||||||
XP_U16 nAddrs;
|
RO_LOW_SCORE_FIRST, /* lowest scorer in parent goes first, etc */
|
||||||
} RematchAddrs;
|
RO_HIGH_SCORE_FIRST, /* highest scorer in parent goes first, etc */
|
||||||
|
RO_JUGGLE, /* rearrange randomly */
|
||||||
|
#ifdef XWFEATURE_RO_BYNAME
|
||||||
|
RO_BY_NAME, /* alphabetical -- for testing only! :-) */
|
||||||
|
#endif
|
||||||
|
RO_NUM_ROS,
|
||||||
|
} RematchOrder;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
const XP_UCHAR* RO2Str(RematchOrder ro);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Info about remote addresses that lets us determine an order for invited
|
||||||
|
players as they arrive. It stores the addresses of all remote devices, and
|
||||||
|
for each a mask of which players will come from that address.
|
||||||
|
|
||||||
|
No need for a count: once we find a playersMask == 0 we're done
|
||||||
|
*/
|
||||||
|
|
||||||
/* Sets up newUtil->gameInfo correctly, and returns with a set of
|
/* Sets up newUtil->gameInfo correctly, and returns with a set of
|
||||||
addresses to which invitation should be sent. But: meant to be called
|
addresses to which invitation should be sent. But: meant to be called
|
||||||
only from game.c anyway.
|
only from game.c anyway.
|
||||||
*/
|
*/
|
||||||
|
typedef struct RematchInfo RematchInfo;
|
||||||
XP_Bool server_getRematchInfo( const ServerCtxt* server, XW_UtilCtxt* newUtil,
|
XP_Bool server_getRematchInfo( const ServerCtxt* server, XW_UtilCtxt* newUtil,
|
||||||
XP_U32 gameID, RematchAddrs* ra );
|
XP_U32 gameID, RematchOrder ro, RematchInfo** ripp );
|
||||||
|
void server_disposeRematchInfo( ServerCtxt* server, RematchInfo** rip );
|
||||||
|
XP_Bool server_ri_getAddr( const RematchInfo* ri, XP_U16 nth,
|
||||||
|
CommsAddrRec* addr, XP_U16* nPlayersH );
|
||||||
|
|
||||||
|
/* Pass in the info the server will need to hang onto until all invitees have
|
||||||
|
registered, at which point it can set and communicate the player order for
|
||||||
|
the game. To be called only from game.c! */
|
||||||
|
void server_setRematchOrder( ServerCtxt* server, const RematchInfo* ri );
|
||||||
|
|
||||||
|
XP_Bool server_isFromRematch( const ServerCtxt* server );
|
||||||
|
|
||||||
#ifdef CPLUS
|
#ifdef CPLUS
|
||||||
}
|
}
|
||||||
|
|
|
@ -518,6 +518,17 @@ randIntArray( XP_U16* rnums, XP_U16 count )
|
||||||
return changed;
|
return changed;
|
||||||
} /* randIntArray */
|
} /* randIntArray */
|
||||||
|
|
||||||
|
XP_U16
|
||||||
|
countBits( XP_U32 mask )
|
||||||
|
{
|
||||||
|
XP_U16 result = 0;
|
||||||
|
while ( 0 != mask ) {
|
||||||
|
++result;
|
||||||
|
mask &= mask - 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef XWFEATURE_BASE64
|
#ifdef XWFEATURE_BASE64
|
||||||
/* base-64 encode binary data as a message legal for SMS. See
|
/* base-64 encode binary data as a message legal for SMS. See
|
||||||
* http://www.ietf.org/rfc/rfc2045.txt for the algorithm. glib uses this and
|
* http://www.ietf.org/rfc/rfc2045.txt for the algorithm. glib uses this and
|
||||||
|
|
|
@ -122,6 +122,8 @@ XP_UCHAR* emptyStringIfNull( XP_UCHAR* str );
|
||||||
/* Produce an array of ints 0..count-1, juggled */
|
/* Produce an array of ints 0..count-1, juggled */
|
||||||
XP_Bool randIntArray( XP_U16* rnums, XP_U16 count );
|
XP_Bool randIntArray( XP_U16* rnums, XP_U16 count );
|
||||||
|
|
||||||
|
XP_U16 countBits( XP_U32 mask );
|
||||||
|
|
||||||
#ifdef XWFEATURE_BASE64
|
#ifdef XWFEATURE_BASE64
|
||||||
void binToSms( XP_UCHAR* out, XP_U16* outlen, const XP_U8* in, XP_U16 inlen );
|
void binToSms( XP_UCHAR* out, XP_U16* outlen, const XP_U8* in, XP_U16 inlen );
|
||||||
XP_Bool smsToBin( XP_U8* out, XP_U16* outlen, const XP_UCHAR* in, XP_U16 inlen );
|
XP_Bool smsToBin( XP_U8* out, XP_U16* outlen, const XP_UCHAR* in, XP_U16 inlen );
|
||||||
|
|
|
@ -186,17 +186,6 @@ adjustCurSel( CursGameList* cgl )
|
||||||
cgl_draw( cgl );
|
cgl_draw( cgl );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
countBits( int bits )
|
|
||||||
{
|
|
||||||
int result = 0;
|
|
||||||
while ( 0 != bits ) {
|
|
||||||
++result;
|
|
||||||
bits &= bits - 1;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
cgl_draw( CursGameList* cgl )
|
cgl_draw( CursGameList* cgl )
|
||||||
{
|
{
|
||||||
|
|
|
@ -135,7 +135,8 @@ static void relay_requestJoin_curses( void* closure, const XP_UCHAR* devID,
|
||||||
XP_U16 nPlayersTotal, XP_U16 seed, XP_U16 lang );
|
XP_U16 nPlayersTotal, XP_U16 seed, XP_U16 lang );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static XP_Bool rematch_and_save( CursesBoardGlobals* bGlobals, XP_U32* newGameIDP );
|
static XP_Bool rematch_and_save( CursesBoardGlobals* bGlobals, RematchOrder ro,
|
||||||
|
XP_U32* newGameIDP );
|
||||||
static void disposeBoard( CursesBoardGlobals* bGlobals );
|
static void disposeBoard( CursesBoardGlobals* bGlobals );
|
||||||
static void initCP( CommonGlobals* cGlobals );
|
static void initCP( CommonGlobals* cGlobals );
|
||||||
static CursesBoardGlobals* commonInit( CursesBoardState* cbState,
|
static CursesBoardGlobals* commonInit( CursesBoardState* cbState,
|
||||||
|
@ -697,16 +698,17 @@ cb_addInvite( CursesBoardState* cbState, XP_U32 gameID, XP_U16 forceChannel,
|
||||||
|
|
||||||
NetLaunchInfo nli;
|
NetLaunchInfo nli;
|
||||||
nli_init( &nli, cGlobals->gi, &selfAddr, 1, forceChannel );
|
nli_init( &nli, cGlobals->gi, &selfAddr, 1, forceChannel );
|
||||||
nli.remotesAreRobots = XP_TRUE;
|
|
||||||
|
|
||||||
comms_invite( comms, NULL_XWE, &nli, destAddr, XP_TRUE );
|
comms_invite( comms, NULL_XWE, &nli, destAddr, XP_TRUE );
|
||||||
}
|
}
|
||||||
|
|
||||||
XP_Bool
|
XP_Bool
|
||||||
cb_makeRematch( CursesBoardState* cbState, XP_U32 gameID, XP_U32* newGameIDP )
|
cb_makeRematch( CursesBoardState* cbState, XP_U32 gameID, RematchOrder ro,
|
||||||
|
XP_U32* newGameIDP )
|
||||||
{
|
{
|
||||||
CursesBoardGlobals* bGlobals = findOrOpenForGameID( cbState, gameID, NULL, NULL );
|
CursesBoardGlobals* bGlobals = findOrOpenForGameID( cbState, gameID,
|
||||||
XP_Bool success = rematch_and_save( bGlobals, newGameIDP );
|
NULL, NULL );
|
||||||
|
XP_Bool success = rematch_and_save( bGlobals, ro, newGameIDP );
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -727,9 +729,11 @@ cb_makeMoveIf( CursesBoardState* cbState, XP_U32 gameID )
|
||||||
XP_FALSE,
|
XP_FALSE,
|
||||||
#endif
|
#endif
|
||||||
XP_FALSE, &ignored );
|
XP_FALSE, &ignored );
|
||||||
if ( success ) {
|
if ( !success ) {
|
||||||
success = board_commitTurn( board, NULL_XWE, XP_TRUE, XP_TRUE, NULL );
|
XP_LOGFF( "unable to find hint; so PASSing" );
|
||||||
}
|
}
|
||||||
|
success = board_commitTurn( board, NULL_XWE, XP_TRUE, XP_TRUE,
|
||||||
|
NULL );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG_RETURNF( "%s", boolToStr(success) );
|
LOG_RETURNF( "%s", boolToStr(success) );
|
||||||
|
@ -994,7 +998,7 @@ curses_util_informUndo( XW_UtilCtxt* uc, XWEnv XP_UNUSED(xwe) )
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rematch_and_save_once( CursesBoardGlobals* bGlobals )
|
rematch_and_save_once( CursesBoardGlobals* bGlobals, RematchOrder ro )
|
||||||
{
|
{
|
||||||
LOG_FUNC();
|
LOG_FUNC();
|
||||||
CommonGlobals* cGlobals = &bGlobals->cGlobals;
|
CommonGlobals* cGlobals = &bGlobals->cGlobals;
|
||||||
|
@ -1006,7 +1010,7 @@ rematch_and_save_once( CursesBoardGlobals* bGlobals )
|
||||||
&& 0 != alreadyDone ) {
|
&& 0 != alreadyDone ) {
|
||||||
XP_LOGFF( "already rematched game %X", cGlobals->gi->gameID );
|
XP_LOGFF( "already rematched game %X", cGlobals->gi->gameID );
|
||||||
} else {
|
} else {
|
||||||
if ( rematch_and_save( bGlobals, NULL ) ) {
|
if ( rematch_and_save( bGlobals, ro, NULL ) ) {
|
||||||
gdb_storeInt( cGlobals->params->pDb, key, 1 );
|
gdb_storeInt( cGlobals->params->pDb, key, 1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1014,7 +1018,8 @@ rematch_and_save_once( CursesBoardGlobals* bGlobals )
|
||||||
}
|
}
|
||||||
|
|
||||||
static XP_Bool
|
static XP_Bool
|
||||||
rematch_and_save( CursesBoardGlobals* bGlobals, XP_U32* newGameIDP )
|
rematch_and_save( CursesBoardGlobals* bGlobals, RematchOrder ro,
|
||||||
|
XP_U32* newGameIDP )
|
||||||
{
|
{
|
||||||
LOG_FUNC();
|
LOG_FUNC();
|
||||||
CommonGlobals* cGlobals = &bGlobals->cGlobals;
|
CommonGlobals* cGlobals = &bGlobals->cGlobals;
|
||||||
|
@ -1025,7 +1030,7 @@ rematch_and_save( CursesBoardGlobals* bGlobals, XP_U32* newGameIDP )
|
||||||
XP_Bool success = game_makeRematch( &bGlobals->cGlobals.game, NULL_XWE,
|
XP_Bool success = game_makeRematch( &bGlobals->cGlobals.game, NULL_XWE,
|
||||||
bGlobalsNew->cGlobals.util,
|
bGlobalsNew->cGlobals.util,
|
||||||
&cGlobals->cp, &bGlobalsNew->cGlobals.procs,
|
&cGlobals->cp, &bGlobalsNew->cGlobals.procs,
|
||||||
&bGlobalsNew->cGlobals.game, "newName" );
|
&bGlobalsNew->cGlobals.game, "newName", ro );
|
||||||
if ( success ) {
|
if ( success ) {
|
||||||
if ( !!newGameIDP ) {
|
if ( !!newGameIDP ) {
|
||||||
*newGameIDP = bGlobalsNew->cGlobals.gi->gameID;
|
*newGameIDP = bGlobalsNew->cGlobals.gi->gameID;
|
||||||
|
@ -1038,13 +1043,13 @@ rematch_and_save( CursesBoardGlobals* bGlobals, XP_U32* newGameIDP )
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
curses_util_notifyGameOver( XW_UtilCtxt* uc, XWEnv XP_UNUSED(xwe), XP_S16 quitter )
|
curses_util_notifyGameOver( XW_UtilCtxt* uc, XWEnv xwe, XP_S16 quitter )
|
||||||
{
|
{
|
||||||
LOG_FUNC();
|
LOG_FUNC();
|
||||||
CursesBoardGlobals* bGlobals = (CursesBoardGlobals*)uc->closure;
|
CursesBoardGlobals* bGlobals = (CursesBoardGlobals*)uc->closure;
|
||||||
CommonGlobals* cGlobals = &bGlobals->cGlobals;
|
CommonGlobals* cGlobals = &bGlobals->cGlobals;
|
||||||
LaunchParams* params = cGlobals->params;
|
LaunchParams* params = cGlobals->params;
|
||||||
board_draw( cGlobals->game.board, NULL_XWE );
|
board_draw( cGlobals->game.board, xwe );
|
||||||
|
|
||||||
/* game belongs in cGlobals... */
|
/* game belongs in cGlobals... */
|
||||||
if ( params->printHistory ) {
|
if ( params->printHistory ) {
|
||||||
|
@ -1057,14 +1062,15 @@ curses_util_notifyGameOver( XW_UtilCtxt* uc, XWEnv XP_UNUSED(xwe), XP_S16 quitte
|
||||||
sleep( params->quitAfter );
|
sleep( params->quitAfter );
|
||||||
handleQuit( bGlobals->cbState->aGlobals, 0 );
|
handleQuit( bGlobals->cbState->aGlobals, 0 );
|
||||||
} else if ( params->undoWhenDone ) {
|
} else if ( params->undoWhenDone ) {
|
||||||
server_handleUndo( cGlobals->game.server, NULL_XWE, 0 );
|
server_handleUndo( cGlobals->game.server, xwe, 0 );
|
||||||
} else if ( !params->skipGameOver && !!bGlobals->boardWin ) {
|
} else if ( !params->skipGameOver && !!bGlobals->boardWin ) {
|
||||||
/* This is modal. Don't show if quitting */
|
/* This is modal. Don't show if quitting */
|
||||||
cursesShowFinalScores( bGlobals );
|
cursesShowFinalScores( bGlobals );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( params->rematchOnDone ) {
|
if ( params->rematchOnDone ) {
|
||||||
rematch_and_save_once( bGlobals );
|
XP_ASSERT( !!params->rematchOrder );
|
||||||
|
rematch_and_save_once( bGlobals, roFromStr(params->rematchOrder) );
|
||||||
}
|
}
|
||||||
} /* curses_util_notifyGameOver */
|
} /* curses_util_notifyGameOver */
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,8 @@ void cb_feedGame( CursesBoardState* cbState, XP_U32 gameID,
|
||||||
const XP_U8* buf, XP_U16 len, const CommsAddrRec* from );
|
const XP_U8* buf, XP_U16 len, const CommsAddrRec* from );
|
||||||
void cb_addInvite( CursesBoardState* cbState, XP_U32 gameID, XP_U16 forceChannel,
|
void cb_addInvite( CursesBoardState* cbState, XP_U32 gameID, XP_U16 forceChannel,
|
||||||
const CommsAddrRec* destAddr );
|
const CommsAddrRec* destAddr );
|
||||||
XP_Bool cb_makeRematch( CursesBoardState* cbState, XP_U32 gameID, XP_U32* newGameID );
|
XP_Bool cb_makeRematch( CursesBoardState* cbState, XP_U32 gameID,
|
||||||
|
RematchOrder ro, XP_U32* newGameID );
|
||||||
XP_Bool cb_makeMoveIf( CursesBoardState* cbState, XP_U32 gameID );
|
XP_Bool cb_makeMoveIf( CursesBoardState* cbState, XP_U32 gameID );
|
||||||
|
|
||||||
const CommonGlobals* cb_getForGameID( CursesBoardState* cbState, XP_U32 gameID );
|
const CommonGlobals* cb_getForGameID( CursesBoardState* cbState, XP_U32 gameID );
|
||||||
|
|
|
@ -1530,7 +1530,6 @@ makeGameFromArgs( CursesAppGlobals* aGlobals, cJSON* args )
|
||||||
params->localName );
|
params->localName );
|
||||||
for ( int ii = 0; ii < gi.nPlayers; ++ii ) {
|
for ( int ii = 0; ii < gi.nPlayers; ++ii ) {
|
||||||
gi.players[ii].isLocal = ii == hostPosn;
|
gi.players[ii].isLocal = ii == hostPosn;
|
||||||
gi.players[ii].robotIQ = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = cJSON_GetObjectItem( args, "dict" );
|
tmp = cJSON_GetObjectItem( args, "dict" );
|
||||||
|
@ -1601,8 +1600,11 @@ rematchFromArgs( CursesAppGlobals* aGlobals, cJSON* args )
|
||||||
|
|
||||||
XP_U32 gameID = gidFromObject( args );
|
XP_U32 gameID = gidFromObject( args );
|
||||||
|
|
||||||
|
cJSON* tmp = cJSON_GetObjectItem( args, "rematchOrder" );
|
||||||
|
RematchOrder ro = roFromStr( tmp->valuestring );
|
||||||
|
|
||||||
XP_U32 newGameID = 0;
|
XP_U32 newGameID = 0;
|
||||||
if ( cb_makeRematch( aGlobals->cbState, gameID, &newGameID ) ) {
|
if ( cb_makeRematch( aGlobals->cbState, gameID, ro, &newGameID ) ) {
|
||||||
result = newGameID;
|
result = newGameID;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -75,6 +75,26 @@ gtkask_timeout( GtkWidget* parent, const gchar* message,
|
||||||
|
|
||||||
LOG_RETURNF( "%d", response );
|
LOG_RETURNF( "%d", response );
|
||||||
return response;
|
return response;
|
||||||
} /* gtkask */
|
} /* gtkask_timeout */
|
||||||
|
|
||||||
|
bool
|
||||||
|
gtkask_radios( GtkWidget* parent, const gchar *message,
|
||||||
|
const AskPair* buttxts, int* chosen )
|
||||||
|
{
|
||||||
|
gint askResponse = gtkask_timeout( parent, message, GTK_BUTTONS_CANCEL, buttxts, 0 );
|
||||||
|
bool result = askResponse != GTK_RESPONSE_CANCEL;
|
||||||
|
if ( result ) {
|
||||||
|
for ( int ii = 0; ; ++ii ) {
|
||||||
|
if ( !buttxts[ii].txt ) {
|
||||||
|
XP_ASSERT(0);
|
||||||
|
break;
|
||||||
|
} else if ( askResponse == buttxts[ii].result ) {
|
||||||
|
*chosen = ii;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
|
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
|
||||||
/*
|
/*
|
||||||
* Copyright 2000 by Eric House (xwords@eehouse.org). All rights reserved.
|
* Copyright 2000-2023 by Eric House (xwords@eehouse.org). All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -40,5 +40,11 @@ gint gtkask_timeout( GtkWidget* parent, const gchar *message,
|
||||||
GtkButtonsType buttons, const AskPair* buttxts,
|
GtkButtonsType buttons, const AskPair* buttxts,
|
||||||
uint32_t timeoutMS );
|
uint32_t timeoutMS );
|
||||||
|
|
||||||
|
/* Put up buttxts as radio buttons/single choice with and OK button to confirm
|
||||||
|
and a cancel. That's later; for now just call gtkask() with a ton of
|
||||||
|
buttons. */
|
||||||
|
bool gtkask_radios( GtkWidget* parent, const gchar *message,
|
||||||
|
const AskPair* buttxts, int* chosen );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif /* PLATFORM_GTK */
|
#endif /* PLATFORM_GTK */
|
||||||
|
|
|
@ -1095,8 +1095,12 @@ makeMenus( GtkGameGlobals* globals )
|
||||||
static void
|
static void
|
||||||
disenable_buttons( GtkGameGlobals* globals )
|
disenable_buttons( GtkGameGlobals* globals )
|
||||||
{
|
{
|
||||||
XP_U16 nPending = server_getPendingRegs( globals->cGlobals.game.server );
|
XWGame* game = &globals->cGlobals.game;
|
||||||
if ( !globals->invite_button && 0 < nPending && !!globals->buttons_hbox ) {
|
XP_U16 nPending = server_getPendingRegs( game->server );
|
||||||
|
if ( !globals->invite_button
|
||||||
|
&& 0 < nPending
|
||||||
|
&& !server_isFromRematch( game->server )
|
||||||
|
&& !!globals->buttons_hbox ) {
|
||||||
globals->invite_button =
|
globals->invite_button =
|
||||||
addButton( globals->buttons_hbox, "Invite",
|
addButton( globals->buttons_hbox, "Invite",
|
||||||
G_CALLBACK(handle_invite_button), globals );
|
G_CALLBACK(handle_invite_button), globals );
|
||||||
|
@ -1584,7 +1588,7 @@ ask_tiles( gpointer data )
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
} /* ask_tiles */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_util_informNeedPickTiles( XW_UtilCtxt* uc, XWEnv XP_UNUSED(xwe),
|
gtk_util_informNeedPickTiles( XW_UtilCtxt* uc, XWEnv XP_UNUSED(xwe),
|
||||||
|
|
|
@ -1083,7 +1083,7 @@ formatScoreText( PangoLayout* layout, XP_UCHAR* buf, XP_U16 bufLen,
|
||||||
{
|
{
|
||||||
XP_S16 score = dsi->totalScore;
|
XP_S16 score = dsi->totalScore;
|
||||||
XP_U16 nTilesLeft = dsi->nTilesLeft;
|
XP_U16 nTilesLeft = dsi->nTilesLeft;
|
||||||
XP_Bool isTurn = dsi->isTurn;
|
XP_Bool isTurn = XP_TRUE; // dsi->isTurn;
|
||||||
XP_S16 maxWidth = bounds->width;
|
XP_S16 maxWidth = bounds->width;
|
||||||
XP_UCHAR numBuf[16];
|
XP_UCHAR numBuf[16];
|
||||||
int width, height;
|
int width, height;
|
||||||
|
|
|
@ -363,6 +363,32 @@ handle_open_button( GtkWidget* XP_UNUSED(widget), void* closure )
|
||||||
void
|
void
|
||||||
make_rematch( GtkAppGlobals* apg, const CommonGlobals* cGlobals )
|
make_rematch( GtkAppGlobals* apg, const CommonGlobals* cGlobals )
|
||||||
{
|
{
|
||||||
|
XP_Bool canOffer;
|
||||||
|
XP_Bool canRematch = server_canRematch( cGlobals->game.server, &canOffer );
|
||||||
|
XP_ASSERT( canRematch );
|
||||||
|
|
||||||
|
RematchOrder ro = RO_SAME;
|
||||||
|
if ( canOffer ) {
|
||||||
|
const AskPair buttons[] = {
|
||||||
|
{"Juggle", RO_JUGGLE},
|
||||||
|
{"Low score first", RO_LOW_SCORE_FIRST},
|
||||||
|
{"High score first", RO_HIGH_SCORE_FIRST},
|
||||||
|
#ifdef XWFEATURE_RO_BYNAME
|
||||||
|
{ "Alphabetical", RO_BY_NAME },
|
||||||
|
#endif
|
||||||
|
{ "Keep existing", RO_SAME },
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
gint response;
|
||||||
|
if ( gtkask_radios( apg->window, "rematch? choose new order",
|
||||||
|
buttons, &response ) ) {
|
||||||
|
ro = buttons[response].result;
|
||||||
|
} else {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LaunchParams* params = apg->cag.params;
|
LaunchParams* params = apg->cag.params;
|
||||||
GtkGameGlobals* newGlobals = calloc( 1, sizeof(*newGlobals) );
|
GtkGameGlobals* newGlobals = calloc( 1, sizeof(*newGlobals) );
|
||||||
initBoardGlobalsGtk( newGlobals, params, NULL );
|
initBoardGlobalsGtk( newGlobals, params, NULL );
|
||||||
|
@ -373,13 +399,15 @@ make_rematch( GtkAppGlobals* apg, const CommonGlobals* cGlobals )
|
||||||
snprintf( buf, VSIZE(buf), "Game %lX", XP_RANDOM() % 256 );
|
snprintf( buf, VSIZE(buf), "Game %lX", XP_RANDOM() % 256 );
|
||||||
game_makeRematch( &cGlobals->game, NULL_XWE, util, cp,
|
game_makeRematch( &cGlobals->game, NULL_XWE, util, cp,
|
||||||
&newGlobals->cGlobals.procs,
|
&newGlobals->cGlobals.procs,
|
||||||
&newGlobals->cGlobals.game, buf );
|
&newGlobals->cGlobals.game, buf, ro );
|
||||||
|
|
||||||
linuxSaveGame( &newGlobals->cGlobals );
|
linuxSaveGame( &newGlobals->cGlobals );
|
||||||
sqlite3_int64 rowid = newGlobals->cGlobals.rowid;
|
sqlite3_int64 rowid = newGlobals->cGlobals.rowid;
|
||||||
freeGlobals( newGlobals );
|
freeGlobals( newGlobals );
|
||||||
|
|
||||||
open_row( apg, rowid, XP_TRUE );
|
open_row( apg, rowid, XP_TRUE );
|
||||||
|
exit:
|
||||||
|
return;
|
||||||
} /* make_rematch */
|
} /* make_rematch */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -409,7 +409,7 @@ makeNewGameDialog( GtkNewGameState* state )
|
||||||
GtkWidget* hbox;
|
GtkWidget* hbox;
|
||||||
#ifndef XWFEATURE_STANDALONE_ONLY
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||||
GtkWidget* roleCombo;
|
GtkWidget* roleCombo;
|
||||||
char* roles[] = { "Standalone", "Host", "Guest" };
|
char* roles[] = { "Standalone", "Host" };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dialog = gtk_dialog_new();
|
dialog = gtk_dialog_new();
|
||||||
|
@ -641,9 +641,14 @@ gtk_newgame_col_set( void* closure, XP_U16 player, NewGameColumn col,
|
||||||
gchar buf[32];
|
gchar buf[32];
|
||||||
cp = !!value.ng_cp ? value.ng_cp : "";
|
cp = !!value.ng_cp ? value.ng_cp : "";
|
||||||
if ( NG_COL_NAME == col && '\0' == cp[0] ) {
|
if ( NG_COL_NAME == col && '\0' == cp[0] ) {
|
||||||
|
LaunchParams* params = state->globals->cGlobals.params;
|
||||||
|
if ( !!params->localName ) {
|
||||||
|
cp = params->localName;
|
||||||
|
} else {
|
||||||
sprintf( buf, "Linuser %d", 1 + player );
|
sprintf( buf, "Linuser %d", 1 + player );
|
||||||
cp = buf;
|
cp = buf;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
gtk_entry_set_text( GTK_ENTRY(widget), cp );
|
gtk_entry_set_text( GTK_ENTRY(widget), cp );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2533,6 +2533,32 @@ makeSelfAddress( CommsAddrRec* selfAddr, const LaunchParams* params )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RematchOrder
|
||||||
|
roFromStr(const char* rematchOrder )
|
||||||
|
{
|
||||||
|
RematchOrder result;
|
||||||
|
struct {
|
||||||
|
char* str;
|
||||||
|
RematchOrder ro;
|
||||||
|
} vals [] = {
|
||||||
|
{ "same", RO_SAME },
|
||||||
|
{ "low_score_first", RO_LOW_SCORE_FIRST },
|
||||||
|
{ "high_score_first", RO_HIGH_SCORE_FIRST },
|
||||||
|
{ "juggle", RO_JUGGLE },
|
||||||
|
#ifdef XWFEATURE_RO_BYNAME
|
||||||
|
{ "by_name", RO_BY_NAME },
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
for ( int ii = 0; ii < VSIZE(vals); ++ii ) {
|
||||||
|
if ( 0 == strcmp( rematchOrder, vals[ii].str ) ) {
|
||||||
|
result = vals[ii].ro;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XP_LOGFF( "(%s) => %d", rematchOrder, result );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
writeStatus( const char* statusSocket, const char* dbName )
|
writeStatus( const char* statusSocket, const char* dbName )
|
||||||
{
|
{
|
||||||
|
|
|
@ -117,6 +117,8 @@ void tryConnectToServer( CommonGlobals* cGlobals );
|
||||||
void ensureLocalPlayerNames( LaunchParams* params, CurGameInfo* gi );
|
void ensureLocalPlayerNames( LaunchParams* params, CurGameInfo* gi );
|
||||||
void cancelTimers( CommonGlobals* cGlobals );
|
void cancelTimers( CommonGlobals* cGlobals );
|
||||||
|
|
||||||
|
RematchOrder roFromStr(const char* rematchOrder );
|
||||||
|
|
||||||
/* void initParams( LaunchParams* params ); */
|
/* void initParams( LaunchParams* params ); */
|
||||||
/* void freeParams( LaunchParams* params ); */
|
/* void freeParams( LaunchParams* params ); */
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* -*- compile-command: "make MEMDEBUG=TRUE -j3"; -*- */
|
/* -*- compile-command: "make MEMDEBUG=TRUE -j3"; -*- */
|
||||||
/*
|
/*
|
||||||
* Copyright 2001 - 2020 by Eric House (xwords@eehouse.org). All rights
|
* Copyright 2001 - 2023 by Eric House (xwords@eehouse.org). All rights
|
||||||
* reserved.
|
* reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
|
@ -157,6 +157,8 @@ typedef struct _LaunchParams {
|
||||||
const XP_UCHAR* iterTestPatStr;
|
const XP_UCHAR* iterTestPatStr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const char* rematchOrder;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
void (*quit)(void* params);
|
void (*quit)(void* params);
|
||||||
} cmdProcs;
|
} cmdProcs;
|
||||||
|
|
|
@ -4,6 +4,8 @@ import argparse, datetime, json, os, random, shutil, signal, \
|
||||||
socket, struct, subprocess, sys, threading, time
|
socket, struct, subprocess, sys, threading, time
|
||||||
|
|
||||||
g_NAMES = ['Brynn', 'Ariela', 'Kati', 'Eric']
|
g_NAMES = ['Brynn', 'Ariela', 'Kati', 'Eric']
|
||||||
|
# These must correspond to what the linux app is looking for in roFromStr()
|
||||||
|
g_ROS = ['same', 'low_score_first', 'high_score_first', 'juggle', 'by_name',]
|
||||||
gDone = False
|
gDone = False
|
||||||
gGamesMade = 0
|
gGamesMade = 0
|
||||||
g_LOGFILE = None
|
g_LOGFILE = None
|
||||||
|
@ -292,7 +294,9 @@ class Device():
|
||||||
# way. But how I figure out the other players differs.
|
# way. But how I figure out the other players differs.
|
||||||
def rematch(self, game):
|
def rematch(self, game):
|
||||||
gid = game.gid
|
gid = game.gid
|
||||||
newGid = self._sendWaitReply('rematch', gid=gid).get('newGid')
|
rematchOrder = self.figureRematchOrder()
|
||||||
|
newGid = self._sendWaitReply('rematch', gid=gid, rematchOrder=rematchOrder) \
|
||||||
|
.get('newGid')
|
||||||
if newGid:
|
if newGid:
|
||||||
guests = Device.playersIn(gid)
|
guests = Device.playersIn(gid)
|
||||||
guests.remove(self.host)
|
guests.remove(self.host)
|
||||||
|
@ -326,6 +330,11 @@ class Device():
|
||||||
self.guestGames.append(GuestGameInfo(self, gid, rematchLevel))
|
self.guestGames.append(GuestGameInfo(self, gid, rematchLevel))
|
||||||
self.launchIfNot()
|
self.launchIfNot()
|
||||||
|
|
||||||
|
def figureRematchOrder(self):
|
||||||
|
ro = self.args.REMATCH_ORDER
|
||||||
|
if not ro: ro = random.choice(g_ROS)
|
||||||
|
return ro
|
||||||
|
|
||||||
# Return true only if all games I host are finished on all games.
|
# Return true only if all games I host are finished on all games.
|
||||||
# But: what about games I don't host? For now, let's make it all
|
# But: what about games I don't host? For now, let's make it all
|
||||||
# games!
|
# games!
|
||||||
|
@ -671,6 +680,8 @@ def mkParser():
|
||||||
|
|
||||||
parser.add_argument('--rematch-level', dest = 'REMATCH_LEVEL', type = int, default = 0,
|
parser.add_argument('--rematch-level', dest = 'REMATCH_LEVEL', type = int, default = 0,
|
||||||
help = 'rematch games down to this ancestry/depth')
|
help = 'rematch games down to this ancestry/depth')
|
||||||
|
parser.add_argument('--rematch-order', dest = 'REMATCH_ORDER', type = str, default = None,
|
||||||
|
help = 'order rematched games one of these ways: {}'.format(g_ROS))
|
||||||
|
|
||||||
# envpat = 'DISCON_COREPAT'
|
# envpat = 'DISCON_COREPAT'
|
||||||
# parser.add_argument('--core-pat', dest = 'CORE_PAT', default = os.environ.get(envpat),
|
# parser.add_argument('--core-pat', dest = 'CORE_PAT', default = os.environ.get(envpat),
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# I use this thing this way: playnum.sh 10 2>&1 | ./wordlens.pl
|
|
||||||
|
|
||||||
NUM=$1
|
|
||||||
echo "NUM=$NUM"
|
|
||||||
|
|
||||||
while :; do
|
|
||||||
|
|
||||||
../linux/xwords -u -s -r Eric -d ../linux/dicts/OSPD2to15.xwd -q -i
|
|
||||||
|
|
||||||
NUM=$(( NUM - 1 ));
|
|
||||||
|
|
||||||
if (( $NUM <= 0 )); then exit 0; fi
|
|
||||||
done
|
|
Loading…
Add table
Reference in a new issue