mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2024-12-30 10:26:58 +01:00
toward making tile picking work through rotations
Make face-up tile picker util method return void and add mechanism for passing in selected tiles asynchronously, as has been done recently with the rest of the once-blocking util callbacks. Works perfectly in the gtk case. Likely crashes in curses (if picking face-up option is on.) In java all the callbacks are there but rather than put up a UI we pretend the user says "pick 'em for me" each time. Putting up a UI is next.
This commit is contained in:
parent
70b3aaa263
commit
6e5973c55b
19 changed files with 385 additions and 131 deletions
|
@ -1869,16 +1869,32 @@ public class BoardDelegate extends DelegateBase
|
|||
}
|
||||
|
||||
@Override
|
||||
public int userPickTileTray( int playerNum, String[] texts,
|
||||
String[] curTiles, int nPicked )
|
||||
public void informNeedPickTiles( final boolean isInitial,
|
||||
final int playerNum, int nToPick,
|
||||
String[] texts, int[] counts )
|
||||
{
|
||||
String curTilesStr = TextUtils.join( ", ", curTiles );
|
||||
boolean canUndoTiles = 0 < nPicked;
|
||||
waitBlockingDialog( DlgID.PICK_TILE_REQUESTTRAY_BLK,
|
||||
UtilCtxt.PICKER_PICKALL, texts, curTilesStr,
|
||||
canUndoTiles );
|
||||
return m_resultCode;
|
||||
post( new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int[] noNewTiles = new int[0];
|
||||
if ( isInitial ) {
|
||||
handleViaThread( JNICmd.CMD_TILES_PICKED, playerNum, noNewTiles );
|
||||
} else {
|
||||
handleViaThread( JNICmd.CMD_COMMIT, true, true, noNewTiles );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
// public int userPickTileTray( int playerNum, String[] texts,
|
||||
// String[] curTiles, int nPicked )
|
||||
// {
|
||||
// String curTilesStr = TextUtils.join( ", ", curTiles );
|
||||
// boolean canUndoTiles = 0 < nPicked;
|
||||
// waitBlockingDialog( DlgID.PICK_TILE_REQUESTTRAY_BLK,
|
||||
// UtilCtxt.PICKER_PICKALL, texts, curTilesStr,
|
||||
// canUndoTiles );
|
||||
// return m_resultCode;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void informNeedPassword( int player, String name )
|
||||
|
|
|
@ -72,6 +72,7 @@ public class JNIThread extends Thread {
|
|||
CMD_KEYUP,
|
||||
CMD_TIMER_FIRED,
|
||||
CMD_COMMIT,
|
||||
CMD_TILES_PICKED,
|
||||
CMD_JUGGLE,
|
||||
CMD_FLIP,
|
||||
CMD_TOGGLE_TRAY,
|
||||
|
@ -552,9 +553,17 @@ public class JNIThread extends Thread {
|
|||
? false : (Boolean)args[0];
|
||||
boolean turnConfirmed = args.length < 2
|
||||
? false : (Boolean)args[1];
|
||||
int[] newTiles = args.length < 3 ? null : (int[])args[2];
|
||||
draw = XwJNI.board_commitTurn( m_jniGamePtr, phoniesConfirmed,
|
||||
turnConfirmed );
|
||||
turnConfirmed, newTiles );
|
||||
break;
|
||||
|
||||
case CMD_TILES_PICKED:
|
||||
int playerNum = (Integer)args[0];
|
||||
int[] tiles = (int[])args[1];
|
||||
XwJNI.server_tilesPicked( m_jniGamePtr, playerNum, tiles );
|
||||
break;
|
||||
|
||||
case CMD_JUGGLE:
|
||||
draw = XwJNI.board_juggleTray( m_jniGamePtr );
|
||||
break;
|
||||
|
|
|
@ -38,8 +38,9 @@ public interface UtilCtxt {
|
|||
public static final int PICKER_BACKUP = -2;
|
||||
|
||||
void notifyPickTileBlank( int playerNum, int col, int row, String[] texts );
|
||||
int userPickTileTray( int playerNum, String[] tiles,
|
||||
String[] curTiles, int nPicked );
|
||||
|
||||
void informNeedPickTiles( boolean isInitial, int playerNum, int nToPick,
|
||||
String[] texts, int[] counts );
|
||||
|
||||
void informNeedPassword( int player, String name );
|
||||
|
||||
|
|
|
@ -54,11 +54,10 @@ public class UtilCtxtImpl implements UtilCtxt {
|
|||
subclassOverride( "userPickTileBlank" );
|
||||
}
|
||||
|
||||
public int userPickTileTray( int playerNum, String[] texts,
|
||||
String[] curTiles, int nPicked )
|
||||
public void informNeedPickTiles( boolean isInitial, int playerNum, int nToPick,
|
||||
String[] texts, int[] counts )
|
||||
{
|
||||
subclassOverride( "userPickTileTray" );
|
||||
return 0;
|
||||
subclassOverride( "informNeedPickTiles" );
|
||||
}
|
||||
|
||||
public void informNeedPassword( int player, String name )
|
||||
|
|
|
@ -300,7 +300,8 @@ public class XwJNI {
|
|||
public static native boolean board_toggle_showValues( GamePtr gamePtr );
|
||||
public static native boolean board_commitTurn( GamePtr gamePtr,
|
||||
boolean phoniesConfirmed,
|
||||
boolean turnConfirmed );
|
||||
boolean turnConfirmed,
|
||||
int[] newTiles );
|
||||
|
||||
public static native boolean board_flip( GamePtr gamePtr );
|
||||
public static native boolean board_replaceTiles( GamePtr gamePtr );
|
||||
|
@ -358,6 +359,8 @@ public class XwJNI {
|
|||
public static native void server_reset( GamePtr gamePtr );
|
||||
public static native void server_handleUndo( GamePtr gamePtr );
|
||||
public static native boolean server_do( GamePtr gamePtr );
|
||||
public static native void server_tilesPicked( GamePtr gamePtr, int player, int[] tiles );
|
||||
|
||||
public static native String server_formatDictCounts( GamePtr gamePtr, int nCols );
|
||||
public static native boolean server_getGameIsOver( GamePtr gamePtr );
|
||||
public static native String server_writeFinalScores( GamePtr gamePtr );
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*-mode: C; compile-command: "cd ..; ../scripts/ndkbuild.sh -j3"; -*- */
|
||||
/* -*-mode: C; compile-command: "find-and-gradle.sh insXwdDeb"; -*- */
|
||||
/*
|
||||
* Copyright 2001-2010 by Eric House (xwords@eehouse.org). All rights
|
||||
* reserved.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
|
||||
/* -*- compile-command: "find-and-gradle.sh insXw4Deb"; -*- */
|
||||
/*
|
||||
* Copyright 2001-2014 by Eric House (xwords@eehouse.org). All rights
|
||||
* Copyright 2001 - 2017 by Eric House (xwords@eehouse.org). All rights
|
||||
* reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -162,24 +162,23 @@ and_util_notifyPickTileBlank( XW_UtilCtxt* uc, XP_U16 playerNum,
|
|||
UTIL_CBK_TAIL();
|
||||
}
|
||||
|
||||
static XP_S16
|
||||
and_util_userPickTileTray( XW_UtilCtxt* uc, const PickInfo* pi,
|
||||
XP_U16 playerNum, const XP_UCHAR** tileFaces,
|
||||
XP_U16 nTiles )
|
||||
static void
|
||||
and_util_informNeedPickTiles( XW_UtilCtxt* uc, XP_Bool isInitial,
|
||||
XP_U16 player, XP_U16 nToPick,
|
||||
XP_U16 nFaces, const XP_UCHAR** faces,
|
||||
const XP_U16* counts )
|
||||
{
|
||||
XP_S16 result = -1;
|
||||
UTIL_CBK_HEADER("userPickTileTray",
|
||||
"(I[Ljava/lang/String;[Ljava/lang/String;I)I" );
|
||||
jobject jtexts = makeStringArray( env, nTiles, tileFaces );
|
||||
jobject jcurtiles = makeStringArray( env, pi->nCurTiles, pi->curTiles );
|
||||
result = (*env)->CallIntMethod( env, util->jutil, mid,
|
||||
playerNum, jtexts, jcurtiles,
|
||||
pi->thisPick );
|
||||
deleteLocalRefs( env, jtexts, jcurtiles, DELETE_NO_REF );
|
||||
|
||||
UTIL_CBK_HEADER("informNeedPickTiles",
|
||||
"(ZII[Ljava/lang/String;[I)V" );
|
||||
jobject jtexts = makeStringArray( env, nFaces, faces );
|
||||
jobject jcounts = makeIntArray( env, nFaces, counts );
|
||||
|
||||
(*env)->CallVoidMethod( env, util->jutil, mid, isInitial, player,
|
||||
nToPick, jtexts, jcounts );
|
||||
|
||||
deleteLocalRefs( env, jtexts, jcounts, DELETE_NO_REF );
|
||||
UTIL_CBK_TAIL();
|
||||
return result;
|
||||
} /* and_util_userPickTile */
|
||||
} /* and_util_informNeedPickTiles */
|
||||
|
||||
static void
|
||||
and_util_informNeedPassword( XW_UtilCtxt* uc, XP_U16 player,
|
||||
|
@ -707,7 +706,7 @@ makeUtil( MPFORMAL EnvThreadInfo* ti, jobject jutil, CurGameInfo* gi,
|
|||
SET_PROC(notifyMove);
|
||||
SET_PROC(notifyTrade);
|
||||
SET_PROC(notifyPickTileBlank);
|
||||
SET_PROC(userPickTileTray);
|
||||
SET_PROC(informNeedPickTiles);
|
||||
SET_PROC(informNeedPassword);
|
||||
SET_PROC(trayHiddenChange);
|
||||
SET_PROC(yOffsetChange);
|
||||
|
|
|
@ -220,6 +220,21 @@ envForMe( EnvThreadInfo* ti, const char* caller )
|
|||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
tilesArrayToTileSet( JNIEnv* env, jintArray jtiles, TrayTileSet* tset )
|
||||
{
|
||||
if ( jtiles != NULL ) {
|
||||
jsize nTiles = (*env)->GetArrayLength( env, jtiles );
|
||||
int tmp[MAX_TRAY_TILES];
|
||||
getIntsFromArray( env, tmp, jtiles, nTiles, XP_FALSE );
|
||||
|
||||
tset->nTiles = nTiles;
|
||||
for ( int ii = 0; ii < nTiles; ++ii ) {
|
||||
tset->tiles[ii] = tmp[ii];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GAMEPTR_IS_OBJECT
|
||||
static JNIState*
|
||||
getState( JNIEnv* env, GamePtrType gamePtr )
|
||||
|
@ -1282,13 +1297,21 @@ Java_org_eehouse_android_xw4_jni_XwJNI_board_1toggle_1showValues
|
|||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_org_eehouse_android_xw4_jni_XwJNI_board_1commitTurn
|
||||
(JNIEnv* env, jclass C, GamePtrType gamePtr, jboolean phoniesConfirmed,
|
||||
jboolean turnConfirmed)
|
||||
( JNIEnv* env, jclass C, GamePtrType gamePtr, jboolean phoniesConfirmed,
|
||||
jboolean turnConfirmed, jintArray jNewTiles )
|
||||
{
|
||||
jboolean result;
|
||||
XWJNI_START();
|
||||
TrayTileSet* newTilesP = NULL;
|
||||
TrayTileSet newTiles;
|
||||
|
||||
if ( jNewTiles != NULL ) {
|
||||
tilesArrayToTileSet( env, jNewTiles, &newTiles );
|
||||
newTilesP = &newTiles;
|
||||
}
|
||||
|
||||
result = board_commitTurn( state->game.board, phoniesConfirmed,
|
||||
turnConfirmed );
|
||||
turnConfirmed, newTilesP );
|
||||
XWJNI_END();
|
||||
return result;
|
||||
}
|
||||
|
@ -1356,6 +1379,17 @@ Java_org_eehouse_android_xw4_jni_XwJNI_server_1do
|
|||
return result;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_eehouse_android_xw4_jni_XwJNI_server_1tilesPicked
|
||||
( JNIEnv* env, jclass C, GamePtrType gamePtr, jint player, jintArray jNewTiles )
|
||||
{
|
||||
XWJNI_START();
|
||||
TrayTileSet newTiles;
|
||||
tilesArrayToTileSet( env, jNewTiles, &newTiles );
|
||||
server_tilesPicked( state->game.server, player, &newTiles );
|
||||
XWJNI_END();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_eehouse_android_xw4_jni_XwJNI_board_1resetEngine
|
||||
(JNIEnv* env, jclass C, GamePtrType gamePtr )
|
||||
|
|
|
@ -1026,17 +1026,19 @@ boardNotifyTrade( BoardCtxt* board, const TrayTileSet* tiles )
|
|||
|
||||
XP_Bool
|
||||
board_commitTurn( BoardCtxt* board, XP_Bool phoniesConfirmed,
|
||||
XP_Bool turnConfirmed /* includes trade */ )
|
||||
XP_Bool turnConfirmed /* includes trade */,
|
||||
TrayTileSet* newTiles )
|
||||
{
|
||||
XP_Bool result = XP_FALSE;
|
||||
const XP_S16 turn = server_getCurrentTurn( board->server, NULL );
|
||||
PerTurnInfo* pti = board->pti + turn;
|
||||
ModelCtxt* model = board->model;
|
||||
|
||||
if ( board->gameOver || turn < 0 ) {
|
||||
/* do nothing */
|
||||
} else if ( turn != board->selPlayer ) {
|
||||
util_userError( board->util, ERR_NOT_YOUR_TURN );
|
||||
} else if ( 0 == model_getNumTilesTotal( board->model, turn ) ) {
|
||||
} else if ( 0 == model_getNumTilesTotal( model, turn ) ) {
|
||||
/* game's over but still undoable so turn hasn't changed; do
|
||||
nothing */
|
||||
} else if ( phoniesConfirmed || turnConfirmed || checkRevealTray( board ) ) {
|
||||
|
@ -1051,11 +1053,15 @@ board_commitTurn( BoardCtxt* board, XP_Bool phoniesConfirmed,
|
|||
TrayTileSet selTiles;
|
||||
getSelTiles( board, traySelBits, &selTiles );
|
||||
if ( turnConfirmed ) {
|
||||
/* server_commitTrade() changes selPlayer, so board_endTrade
|
||||
must be called first() */
|
||||
(void)board_endTrade( board );
|
||||
if ( !server_askPickTiles( board->server, turn, newTiles,
|
||||
selTiles.nTiles ) ) {
|
||||
/* server_commitTrade() changes selPlayer, so board_endTrade
|
||||
must be called first() */
|
||||
(void)board_endTrade( board );
|
||||
|
||||
(void)server_commitTrade( board->server, &selTiles );
|
||||
(void)server_commitTrade( board->server, &selTiles,
|
||||
newTiles );
|
||||
}
|
||||
} else {
|
||||
boardNotifyTrade( board, &selTiles );
|
||||
}
|
||||
|
@ -1081,13 +1087,13 @@ board_commitTurn( BoardCtxt* board, XP_Bool phoniesConfirmed,
|
|||
info.proc = saveBadWords;
|
||||
info.closure = &bwl;
|
||||
}
|
||||
legal = model_checkMoveLegal( board->model, turn, stream,
|
||||
legal = model_checkMoveLegal( model, turn, stream,
|
||||
warn? &info:(WordNotifierInfo*)NULL);
|
||||
}
|
||||
|
||||
if ( 0 < bwl.bwi.nWords && !phoniesConfirmed ) {
|
||||
bwl.bwi.dictName =
|
||||
dict_getShortName( model_getPlayerDict( board->model, turn ) );
|
||||
dict_getShortName( model_getPlayerDict( model, turn ) );
|
||||
util_notifyIllegalWords( board->util, &bwl.bwi, turn, XP_FALSE );
|
||||
} else {
|
||||
/* Hide the tray so no peeking. Leave it hidden even if user
|
||||
|
@ -1099,14 +1105,20 @@ board_commitTurn( BoardCtxt* board, XP_Bool phoniesConfirmed,
|
|||
}
|
||||
|
||||
if ( board->skipCommitConfirm || turnConfirmed ) {
|
||||
result = server_commitMove( board->server ) || result;
|
||||
/* invalidate all tiles in case we'll be drawing this tray
|
||||
again rather than some other -- as is the case in a
|
||||
two-player game where one's a robot. We really only
|
||||
need the selected tiles and the rightmost (in case it's
|
||||
showing points-this-turn), but this is easier. */
|
||||
board_invalTrayTiles( board, ALLTILES );
|
||||
pti->traySelBits = 0x00;
|
||||
XP_U16 nToPick = MAX_TRAY_TILES -
|
||||
model_getNumTilesInTray( model, turn );
|
||||
if ( !server_askPickTiles( board->server, turn, newTiles,
|
||||
nToPick ) ) {
|
||||
result = server_commitMove( board->server, newTiles )
|
||||
|| result;
|
||||
/* invalidate all tiles in case we'll be drawing this tray
|
||||
again rather than some other -- as is the case in a
|
||||
two-player game where one's a robot. We really only
|
||||
need the selected tiles and the rightmost (in case it's
|
||||
showing points-this-turn), but this is easier. */
|
||||
board_invalTrayTiles( board, ALLTILES );
|
||||
pti->traySelBits = 0x00;
|
||||
}
|
||||
} else {
|
||||
util_notifyMove( board->util, stream );
|
||||
}
|
||||
|
|
|
@ -177,7 +177,7 @@ XP_Bool board_setBlankValue( BoardCtxt* board, XP_U16 XP_UNUSED(player),
|
|||
void board_resetEngine( BoardCtxt* board );
|
||||
|
||||
XP_Bool board_commitTurn( BoardCtxt* board, XP_Bool phoniesConfirmed,
|
||||
XP_Bool turnConfirmed );
|
||||
XP_Bool turnConfirmed, TrayTileSet* newTiles );
|
||||
|
||||
void board_pushTimerSave( BoardCtxt* board );
|
||||
void board_popTimerSave( BoardCtxt* board );
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "pool.h"
|
||||
#include "engine.h"
|
||||
#include "strutils.h"
|
||||
#include "dbgutil.h"
|
||||
|
||||
#include "LocalizedStrIncludes.h"
|
||||
|
||||
|
@ -132,6 +133,8 @@ struct ServerCtxt {
|
|||
|
||||
/******************************* prototypes *******************************/
|
||||
static void assignTilesToAll( ServerCtxt* server );
|
||||
static void makePoolOnce( ServerCtxt* server );
|
||||
|
||||
static void resetEngines( ServerCtxt* server );
|
||||
static void nextTurn( ServerCtxt* server, XP_S16 nxtTurn );
|
||||
|
||||
|
@ -142,6 +145,9 @@ static void badWordMoveUndoAndTellUser( ServerCtxt* server,
|
|||
static XP_Bool tileCountsOk( const ServerCtxt* server );
|
||||
static void setTurn( ServerCtxt* server, XP_S16 turn );
|
||||
static XWStreamCtxt* mkServerStream( ServerCtxt* server );
|
||||
static void fetchTiles( ServerCtxt* server, XP_U16 playerNum, XP_U16 nToFetch,
|
||||
const TrayTileSet* tradedTiles,
|
||||
TrayTileSet* resultTiles );
|
||||
|
||||
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||
static XWStreamCtxt* messageStreamWithHeader( ServerCtxt* server,
|
||||
|
@ -900,7 +906,7 @@ makeRobotMove( ServerCtxt* server )
|
|||
if ( trade ) {
|
||||
TrayTileSet oldTiles = *model_getPlayerTiles( model, turn );
|
||||
XP_LOGF( "%s: robot trading %d tiles", __func__, oldTiles.nTiles );
|
||||
result = server_commitTrade( server, &oldTiles );
|
||||
result = server_commitTrade( server, &oldTiles, NULL );
|
||||
|
||||
/* Quick hack to fix gremlin bug where all-robot game seen none
|
||||
able to trade for tiles to move and blowing the undo stack.
|
||||
|
@ -933,7 +939,7 @@ makeRobotMove( ServerCtxt* server )
|
|||
server->nv.prevMoveStream = stream;
|
||||
server->nv.prevWordsStream = wordsStream;
|
||||
}
|
||||
result = server_commitMove( server );
|
||||
result = server_commitMove( server, NULL );
|
||||
} else {
|
||||
result = XP_FALSE;
|
||||
}
|
||||
|
@ -1047,6 +1053,64 @@ showPrevScore( ServerCtxt* server )
|
|||
SETSTATE( server, server->nv.stateAfterShow );
|
||||
} /* showPrevScore */
|
||||
|
||||
void
|
||||
server_tilesPicked( ServerCtxt* server, XP_U16 player,
|
||||
const TrayTileSet* newTilesP )
|
||||
{
|
||||
TrayTileSet newTiles = *newTilesP;
|
||||
pool_removeTiles( server->pool, &newTiles );
|
||||
|
||||
fetchTiles( server, player, MAX_TRAY_TILES, NULL, &newTiles );
|
||||
model_assignPlayerTiles( server->vol.model, player, &newTiles );
|
||||
|
||||
util_requestTime( server->vol.util );
|
||||
}
|
||||
|
||||
static void
|
||||
informNeedPickTiles( ServerCtxt* server, XP_Bool initial, XP_U16 turn,
|
||||
XP_U16 nToPick )
|
||||
{
|
||||
ModelCtxt* model = server->vol.model;
|
||||
DictionaryCtxt* dict = model_getDictionary(model);
|
||||
XP_U16 nFaces = dict_numTileFaces( dict );
|
||||
XP_U16 counts[MAX_UNIQUE_TILES];
|
||||
const XP_UCHAR* faces[MAX_UNIQUE_TILES];
|
||||
|
||||
XP_U16 nLeft = pool_getNTilesLeft( server->pool );
|
||||
if ( nLeft < nToPick ) {
|
||||
nToPick = nLeft;
|
||||
}
|
||||
|
||||
for ( Tile tile = 0; tile < nFaces; ++tile ) {
|
||||
faces[tile] = dict_getTileString( dict, tile );
|
||||
counts[tile] = pool_getNTilesLeftFor( server->pool, tile );
|
||||
}
|
||||
util_informNeedPickTiles( server->vol.util, initial, turn,
|
||||
nToPick, nFaces, faces, counts );
|
||||
}
|
||||
|
||||
static XP_Bool
|
||||
askedForTiles( ServerCtxt* server )
|
||||
{
|
||||
XP_Bool asked = XP_FALSE;
|
||||
CurGameInfo* gi = server->vol.gi;
|
||||
if ( gi->serverRole == SERVER_STANDALONE && gi->allowPickTiles ) {
|
||||
XP_U16 nPlayers = gi->nPlayers;
|
||||
ModelCtxt* model = server->vol.model;
|
||||
makePoolOnce( server );
|
||||
for ( XP_U16 turn = 0; !asked && turn < nPlayers; ++turn ) {
|
||||
LocalPlayer* player = &gi->players[turn];
|
||||
XP_U16 nTiles = model_getNumTilesInTray( model, turn );
|
||||
if ( nTiles == 0 && !LP_IS_ROBOT(player) ) {
|
||||
informNeedPickTiles( server, XP_TRUE, turn, MAX_TRAY_TILES );
|
||||
asked = XP_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG_RETURNF( "%s", boolToStr(asked));
|
||||
return asked;
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
server_do( ServerCtxt* server )
|
||||
{
|
||||
|
@ -1062,10 +1126,12 @@ server_do( ServerCtxt* server )
|
|||
case XWSTATE_BEGIN:
|
||||
if ( server->nv.pendingRegistrations == 0 ) { /* all players on
|
||||
device */
|
||||
assignTilesToAll( server );
|
||||
SETSTATE( server, XWSTATE_INTURN );
|
||||
setTurn( server, 0 );
|
||||
moreToDo = XP_TRUE;
|
||||
if ( !askedForTiles( server ) ) {
|
||||
assignTilesToAll( server );
|
||||
SETSTATE( server, XWSTATE_INTURN );
|
||||
setTurn( server, 0 );
|
||||
moreToDo = XP_TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1359,8 +1425,8 @@ client_readInitialMessage( ServerCtxt* server, XWStreamCtxt* stream )
|
|||
dict_unref( newDict ); /* new owner will have ref'd */
|
||||
|
||||
XP_ASSERT( !server->pool );
|
||||
pool = server->pool = pool_make( MPPARM_NOCOMMA(server->mpool) );
|
||||
pool_initFromDict( server->pool, model_getDictionary(model));
|
||||
makePoolOnce( server );
|
||||
pool = server->pool;
|
||||
|
||||
/* now read the assigned tiles for each player from the stream, and
|
||||
remove them from the newly-created local pool. */
|
||||
|
@ -1755,6 +1821,23 @@ curTrayAsTexts( ServerCtxt* server, XP_U16 turn, const TrayTileSet* notInTray,
|
|||
*nUsedP = nUsed;
|
||||
} /* curTrayAsTexts */
|
||||
|
||||
/**
|
||||
* Return true (after calling util_informPickTiles()) IFF allowPickTiles is
|
||||
* TRUE and the tile set passed in is NULL. If it doesn't contain as many
|
||||
* tiles as are needed that's cool: server code will later interpret that as
|
||||
* meaning the remainder should be assigned randomly as usual.
|
||||
*/
|
||||
XP_Bool
|
||||
server_askPickTiles( ServerCtxt* server, XP_U16 turn, TrayTileSet* newTiles,
|
||||
XP_U16 nToPick )
|
||||
{
|
||||
XP_Bool asked = newTiles == NULL && server->vol.gi->allowPickTiles;
|
||||
if ( asked ) {
|
||||
informNeedPickTiles( server, XP_FALSE, turn, nToPick );
|
||||
}
|
||||
return asked;
|
||||
}
|
||||
|
||||
/* Get tiles for one user. If picking is available, let user pick until
|
||||
* cancels. Otherwise, and after cancel, pick for 'im.
|
||||
*/
|
||||
|
@ -1763,7 +1846,7 @@ fetchTiles( ServerCtxt* server, XP_U16 playerNum, XP_U16 nToFetch,
|
|||
const TrayTileSet* tradedTiles, TrayTileSet* resultTiles )
|
||||
{
|
||||
XP_Bool ask;
|
||||
XP_U16 nSoFar = 0;
|
||||
XP_U16 nSoFar = resultTiles->nTiles;
|
||||
XP_U16 nLeft;
|
||||
PoolContext* pool = server->pool;
|
||||
TrayTileSet oneTile;
|
||||
|
@ -1796,17 +1879,17 @@ fetchTiles( ServerCtxt* server, XP_U16 playerNum, XP_U16 nToFetch,
|
|||
|
||||
#ifdef FEATURE_TRAY_EDIT /* good compiler would note ask==0, but... */
|
||||
/* First ask until cancelled */
|
||||
for ( nSoFar = 0; ask && nSoFar < nToFetch; ) {
|
||||
for ( ; ask && nSoFar < nToFetch; ) {
|
||||
const XP_UCHAR* texts[MAX_UNIQUE_TILES];
|
||||
Tile tiles[MAX_UNIQUE_TILES];
|
||||
XP_S16 chosen;
|
||||
XP_U16 nUsed = MAX_UNIQUE_TILES;
|
||||
|
||||
// XP_ASSERT(0); /* should no longer happen!!! */
|
||||
model_packTilesUtil( server->vol.model, pool,
|
||||
XP_TRUE, &nUsed, texts, tiles );
|
||||
|
||||
chosen = util_userPickTileTray( server->vol.util, &pi, playerNum,
|
||||
texts, nUsed );
|
||||
chosen = PICKER_PICKALL; /*util_userPickTileTray( server->vol.util,
|
||||
&pi, playerNum, texts, nUsed );*/
|
||||
|
||||
if ( chosen == PICKER_PICKALL ) {
|
||||
ask = XP_FALSE;
|
||||
|
@ -1846,6 +1929,18 @@ fetchTiles( ServerCtxt* server, XP_U16 playerNum, XP_U16 nToFetch,
|
|||
resultTiles->nTiles = (XP_U8)nSoFar;
|
||||
} /* fetchTiles */
|
||||
|
||||
static void
|
||||
makePoolOnce( ServerCtxt* server )
|
||||
{
|
||||
ModelCtxt* model = server->vol.model;
|
||||
XP_ASSERT( model_getDictionary(model) != NULL );
|
||||
if ( server->pool == NULL ) {
|
||||
server->pool = pool_make( MPPARM_NOCOMMA(server->mpool) );
|
||||
XP_STATUSF( "initing pool" );
|
||||
pool_initFromDict( server->pool, model_getDictionary(model));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
assignTilesToAll( ServerCtxt* server )
|
||||
{
|
||||
|
@ -1855,12 +1950,7 @@ assignTilesToAll( ServerCtxt* server )
|
|||
XP_U16 nPlayers = server->vol.gi->nPlayers;
|
||||
|
||||
XP_ASSERT( server->vol.gi->serverRole != SERVER_ISCLIENT );
|
||||
XP_ASSERT( model_getDictionary(model) != NULL );
|
||||
if ( server->pool == NULL ) {
|
||||
server->pool = pool_make( MPPARM_NOCOMMA(server->mpool) );
|
||||
XP_STATUSF( "initing pool" );
|
||||
pool_initFromDict( server->pool, model_getDictionary(model));
|
||||
}
|
||||
makePoolOnce( server );
|
||||
|
||||
XP_STATUSF( "assignTilesToAll" );
|
||||
|
||||
|
@ -1871,9 +1961,11 @@ assignTilesToAll( ServerCtxt* server )
|
|||
numAssigned = MAX_TRAY_TILES;
|
||||
}
|
||||
for ( ii = 0; ii < nPlayers; ++ii ) {
|
||||
TrayTileSet newTiles;
|
||||
fetchTiles( server, ii, numAssigned, NULL, &newTiles );
|
||||
model_assignPlayerTiles( model, ii, &newTiles );
|
||||
if ( 0 == model_getNumTilesInTray( model, ii ) ) {
|
||||
TrayTileSet newTiles = {0};
|
||||
fetchTiles( server, ii, numAssigned, NULL, &newTiles );
|
||||
model_assignPlayerTiles( model, ii, &newTiles );
|
||||
}
|
||||
sortTilesIf( server, ii );
|
||||
}
|
||||
|
||||
|
@ -2345,16 +2437,20 @@ reflectMove( ServerCtxt* server, XWStreamCtxt* stream )
|
|||
* if it was legal -- but only if DISALLOW is set.
|
||||
*/
|
||||
XP_Bool
|
||||
server_commitMove( ServerCtxt* server )
|
||||
server_commitMove( ServerCtxt* server, TrayTileSet* newTilesP )
|
||||
{
|
||||
XP_S16 turn = server->nv.currentTurn;
|
||||
ModelCtxt* model = server->vol.model;
|
||||
CurGameInfo* gi = server->vol.gi;
|
||||
TrayTileSet newTiles;
|
||||
TrayTileSet newTiles = {0};
|
||||
XP_U16 nTilesMoved;
|
||||
XP_Bool isLegalMove = XP_TRUE;
|
||||
XP_Bool isClient = gi->serverRole == SERVER_ISCLIENT;
|
||||
|
||||
if ( !!newTilesP ) {
|
||||
newTiles = *newTilesP;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if ( LP_IS_ROBOT( &gi->players[turn] ) ) {
|
||||
XP_ASSERT( model_checkMoveLegal( model, turn, (XWStreamCtxt*)NULL,
|
||||
|
@ -2408,9 +2504,13 @@ server_commitMove( ServerCtxt* server )
|
|||
} /* server_commitMove */
|
||||
|
||||
XP_Bool
|
||||
server_commitTrade( ServerCtxt* server, const TrayTileSet* oldTiles )
|
||||
server_commitTrade( ServerCtxt* server, const TrayTileSet* oldTiles,
|
||||
TrayTileSet* newTilesP )
|
||||
{
|
||||
TrayTileSet newTiles;
|
||||
TrayTileSet newTiles = {0};
|
||||
if ( !!newTilesP ) {
|
||||
newTiles = *newTilesP;
|
||||
}
|
||||
XP_U16 turn = server->nv.currentTurn;
|
||||
|
||||
fetchTiles( server, turn, oldTiles->nTiles, oldTiles, &newTiles );
|
||||
|
|
|
@ -102,12 +102,18 @@ XP_U32 server_getLastMoveTime( const ServerCtxt* server );
|
|||
/* Signed in case no dictionary available */
|
||||
XP_S16 server_countTilesInPool( ServerCtxt* server );
|
||||
|
||||
XP_Bool server_askPickTiles( ServerCtxt* server, XP_U16 player,
|
||||
TrayTileSet* newTiles, XP_U16 nToPick );
|
||||
void server_tilesPicked( ServerCtxt* server, XP_U16 player,
|
||||
const TrayTileSet* newTiles );
|
||||
|
||||
XP_U16 server_getPendingRegs( const ServerCtxt* server );
|
||||
|
||||
XP_Bool server_do( ServerCtxt* server );
|
||||
|
||||
XP_Bool server_commitMove( ServerCtxt* server );
|
||||
XP_Bool server_commitTrade( ServerCtxt* server, const TrayTileSet* oldTiles );
|
||||
XP_Bool server_commitMove( ServerCtxt* server, TrayTileSet* newTiles );
|
||||
XP_Bool server_commitTrade( ServerCtxt* server, const TrayTileSet* oldTiles,
|
||||
TrayTileSet* newTiles );
|
||||
|
||||
/* call this when user wants to end the game */
|
||||
void server_endGame( ServerCtxt* server );
|
||||
|
|
|
@ -460,7 +460,7 @@ handleActionInTray( BoardCtxt* board, XP_S16 index, XP_Bool onDivider )
|
|||
}
|
||||
#endif
|
||||
} else if ( index == -(MAX_TRAY_TILES) ) { /* pending score tile */
|
||||
result = board_commitTurn( board, XP_FALSE, XP_FALSE );
|
||||
result = board_commitTurn( board, XP_FALSE, XP_FALSE, NULL );
|
||||
#if defined XWFEATURE_TRAYUNDO_ALL
|
||||
} else if ( index < 0 ) { /* other empty area */
|
||||
/* it better be true */
|
||||
|
|
|
@ -101,14 +101,14 @@ typedef struct UtilVtable {
|
|||
void (*m_util_notifyMove)( XW_UtilCtxt* uc, XWStreamCtxt* stream );
|
||||
void (*m_util_notifyTrade)( XW_UtilCtxt* uc, const XP_UCHAR** tiles,
|
||||
XP_U16 nTiles );
|
||||
/* return of < 0 means computer should pick */
|
||||
void (*m_util_notifyPickTileBlank)( XW_UtilCtxt* uc, XP_U16 playerNum,
|
||||
XP_U16 col, XP_U16 row,
|
||||
const XP_UCHAR** tileFaces,
|
||||
XP_U16 nTiles );
|
||||
XP_S16 (*m_util_userPickTileTray)( XW_UtilCtxt* uc, const PickInfo* pi,
|
||||
XP_U16 playerNum,
|
||||
const XP_UCHAR** texts, XP_U16 nTiles );
|
||||
void (*m_util_informNeedPickTiles)( XW_UtilCtxt* uc, XP_Bool isInitial,
|
||||
XP_U16 player, XP_U16 nToPick,
|
||||
XP_U16 nFaces, const XP_UCHAR** faces,
|
||||
const XP_U16* counts );
|
||||
|
||||
void (*m_util_informNeedPassword)( XW_UtilCtxt* uc, XP_U16 playerNum,
|
||||
const XP_UCHAR* name );
|
||||
|
@ -236,9 +236,11 @@ struct XW_UtilCtxt {
|
|||
(uc)->vtable->m_util_notifyTrade((uc), (tx), (nt))
|
||||
|
||||
#define util_notifyPickTileBlank( uc, c, r, n, tx, nt ) \
|
||||
(uc)->vtable->m_util_notifyPickTileBlank( (uc), (c), (r), (n), (tx), (nt) )
|
||||
#define util_userPickTileTray( uc, w, n, tx, nt ) \
|
||||
(uc)->vtable->m_util_userPickTileTray( (uc), (w), (n), (tx), (nt) )
|
||||
(uc)->vtable->m_util_notifyPickTileBlank( (uc), (c), (r), (n), (tx), (nt) )
|
||||
|
||||
#define util_informNeedPickTiles( uc, ii, pl, np, nt, fc, cn ) \
|
||||
(uc)->vtable->m_util_informNeedPickTiles( (uc), (ii), (pl), (np), (nt), (fc), (cn) )
|
||||
|
||||
#define util_informNeedPassword( uc, pn, n ) \
|
||||
(uc)->vtable->m_util_informNeedPassword( (uc), (pn), (n) )
|
||||
|
||||
|
|
|
@ -243,22 +243,26 @@ curses_util_notifyPickTileBlank( XW_UtilCtxt* uc, XP_U16 playerNum,
|
|||
// return index;
|
||||
} /* util_userPickTile */
|
||||
|
||||
static XP_S16
|
||||
curses_util_userPickTileTray( XW_UtilCtxt* uc, const PickInfo* XP_UNUSED(pi),
|
||||
XP_U16 playerNum, const XP_UCHAR** texts,
|
||||
XP_U16 nTiles )
|
||||
static void
|
||||
curses_util_informNeedPickTiles( XW_UtilCtxt* XP_UNUSED(uc),
|
||||
XP_Bool XP_UNUSED(isInitial),
|
||||
XP_U16 XP_UNUSED(player),
|
||||
XP_U16 XP_UNUSED(nToPick),
|
||||
XP_U16 XP_UNUSED(nFaces),
|
||||
const XP_UCHAR** XP_UNUSED(faces),
|
||||
const XP_U16* XP_UNUSED(counts) )
|
||||
{
|
||||
CursesAppGlobals* globals = (CursesAppGlobals*)uc->closure;
|
||||
char query[128];
|
||||
XP_S16 index;
|
||||
char* playerName = globals->cGlobals.gi->players[playerNum].name;
|
||||
/* CursesAppGlobals* globals = (CursesAppGlobals*)uc->closure; */
|
||||
/* char query[128]; */
|
||||
/* XP_S16 index; */
|
||||
/* char* playerName = globals->cGlobals.gi->players[playerNum].name; */
|
||||
|
||||
snprintf( query, sizeof(query),
|
||||
"Pick tile for %s! (Tab or type letter to select "
|
||||
"then hit <cr>.)", playerName );
|
||||
/* snprintf( query, sizeof(query), */
|
||||
/* "Pick tile for %s! (Tab or type letter to select " */
|
||||
/* "then hit <cr>.)", playerName ); */
|
||||
|
||||
index = curses_askLetter( globals, query, texts, nTiles );
|
||||
return index;
|
||||
/* index = curses_askLetter( globals, query, texts, nTiles ); */
|
||||
/* return index; */
|
||||
} /* util_userPickTile */
|
||||
|
||||
static void
|
||||
|
@ -620,7 +624,7 @@ static XP_Bool
|
|||
handleCommit( CursesAppGlobals* globals )
|
||||
{
|
||||
globals->doDraw = board_commitTurn( globals->cGlobals.game.board,
|
||||
XP_FALSE, XP_FALSE );
|
||||
XP_FALSE, XP_FALSE, NULL );
|
||||
return XP_TRUE;
|
||||
} /* handleCommit */
|
||||
|
||||
|
@ -1456,7 +1460,7 @@ setupCursesUtilCallbacks( CursesAppGlobals* globals, XW_UtilCtxt* util )
|
|||
util->vtable->m_util_notifyMove = curses_util_notifyMove;
|
||||
util->vtable->m_util_notifyTrade = curses_util_notifyTrade;
|
||||
util->vtable->m_util_notifyPickTileBlank = curses_util_notifyPickTileBlank;
|
||||
util->vtable->m_util_userPickTileTray = curses_util_userPickTileTray;
|
||||
util->vtable->m_util_informNeedPickTiles = curses_util_informNeedPickTiles;
|
||||
util->vtable->m_util_trayHiddenChange = curses_util_trayHiddenChange;
|
||||
util->vtable->m_util_informMove = curses_util_informMove;
|
||||
util->vtable->m_util_informUndo = curses_util_informUndo;
|
||||
|
|
|
@ -1445,7 +1445,8 @@ handle_trade_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
|||
static void
|
||||
handle_done_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
||||
{
|
||||
if ( board_commitTurn( globals->cGlobals.game.board, XP_FALSE, XP_FALSE ) ) {
|
||||
if ( board_commitTurn( globals->cGlobals.game.board, XP_FALSE,
|
||||
XP_FALSE, NULL ) ) {
|
||||
board_draw( globals->cGlobals.game.board );
|
||||
disenable_buttons( globals );
|
||||
}
|
||||
|
@ -1543,7 +1544,8 @@ handle_hide_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
|||
static void
|
||||
handle_commit_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
||||
{
|
||||
if ( board_commitTurn( globals->cGlobals.game.board, XP_FALSE, XP_FALSE ) ) {
|
||||
if ( board_commitTurn( globals->cGlobals.game.board, XP_FALSE,
|
||||
XP_FALSE, NULL ) ) {
|
||||
board_draw( globals->cGlobals.game.board );
|
||||
}
|
||||
} /* handle_commit_button */
|
||||
|
@ -1693,7 +1695,7 @@ ask_blank( gpointer data )
|
|||
|
||||
XP_UCHAR* name = globals->cGlobals.gi->players[cGlobals->selPlayer].name;
|
||||
XP_S16 result = gtkletterask( NULL, XP_FALSE, name,
|
||||
cGlobals->nTiles, cGlobals->tiles );
|
||||
cGlobals->nTiles, cGlobals->tiles, NULL );
|
||||
|
||||
for ( int ii = 0; ii < cGlobals->nTiles; ++ii ) {
|
||||
g_free( (gpointer)cGlobals->tiles[ii] );
|
||||
|
@ -1725,18 +1727,78 @@ gtk_util_notifyPickTileBlank( XW_UtilCtxt* uc, XP_U16 playerNum, XP_U16 col,
|
|||
(void)g_idle_add( ask_blank, globals );
|
||||
}
|
||||
|
||||
static XP_S16
|
||||
gtk_util_userPickTileTray( XW_UtilCtxt* uc, const PickInfo* pi,
|
||||
XP_U16 playerNum, const XP_UCHAR** texts,
|
||||
XP_U16 nTiles )
|
||||
static gint
|
||||
ask_tiles( gpointer data )
|
||||
{
|
||||
XP_S16 chosen;
|
||||
GtkGameGlobals* globals = (GtkGameGlobals*)uc->closure;
|
||||
XP_UCHAR* name = globals->cGlobals.gi->players[playerNum].name;
|
||||
GtkGameGlobals* globals = (GtkGameGlobals*)data;
|
||||
CommonGlobals* cGlobals = &globals->cGlobals;
|
||||
|
||||
chosen = gtkletterask( pi, XP_TRUE, name, nTiles, texts );
|
||||
return chosen;
|
||||
} /* gtk_util_userPickTile */
|
||||
TrayTileSet newTiles = {0};
|
||||
XP_UCHAR* name = cGlobals->gi->players[cGlobals->selPlayer].name;
|
||||
for ( XP_Bool done = XP_FALSE; !done; ) {
|
||||
XP_S16 picked = gtkletterask( &newTiles, XP_TRUE, name,
|
||||
cGlobals->nTiles, cGlobals->tiles,
|
||||
cGlobals->tileCounts );
|
||||
switch ( picked ) {
|
||||
case PICKER_PICKALL:
|
||||
done = XP_TRUE;
|
||||
break;
|
||||
case PICKER_BACKUP:
|
||||
if ( newTiles.nTiles > 0 ) {
|
||||
Tile backed = newTiles.tiles[--newTiles.nTiles];
|
||||
++cGlobals->tileCounts[backed];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
XP_ASSERT( picked >= 0 && picked < cGlobals->nTiles );
|
||||
--cGlobals->tileCounts[picked];
|
||||
newTiles.tiles[newTiles.nTiles++] = picked;
|
||||
done = newTiles.nTiles == cGlobals->nToPick;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for ( int ii = 0; ii < cGlobals->nTiles; ++ii ) {
|
||||
g_free( (gpointer)cGlobals->tiles[ii] );
|
||||
}
|
||||
|
||||
BoardCtxt* board = cGlobals->game.board;
|
||||
XP_Bool draw = XP_TRUE;
|
||||
if ( cGlobals->pickIsInitial ) {
|
||||
server_tilesPicked( cGlobals->game.server, cGlobals->selPlayer,
|
||||
&newTiles );
|
||||
} else {
|
||||
draw = board_commitTurn( cGlobals->game.board, XP_TRUE, XP_TRUE,
|
||||
&newTiles );
|
||||
}
|
||||
|
||||
if ( draw ) {
|
||||
board_draw( board );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_util_informNeedPickTiles( XW_UtilCtxt* uc, XP_Bool isInitial,
|
||||
XP_U16 player, XP_U16 nToPick,
|
||||
XP_U16 nFaces, const XP_UCHAR** faces,
|
||||
const XP_U16* counts )
|
||||
{
|
||||
GtkGameGlobals* globals = (GtkGameGlobals*)uc->closure;
|
||||
CommonGlobals* cGlobals = &globals->cGlobals;
|
||||
cGlobals->selPlayer = player;
|
||||
cGlobals->pickIsInitial = isInitial;
|
||||
|
||||
cGlobals->nToPick = nToPick;
|
||||
cGlobals->nTiles = nFaces;
|
||||
for ( int ii = 0; ii < nFaces; ++ii ) {
|
||||
cGlobals->tiles[ii] = g_strdup( faces[ii] );
|
||||
cGlobals->tileCounts[ii] = counts[ii];
|
||||
}
|
||||
|
||||
(void)g_idle_add( ask_tiles, globals );
|
||||
} /* gtk_util_informNeedPickTiles */
|
||||
|
||||
static gint
|
||||
ask_password( gpointer data )
|
||||
|
@ -2125,7 +2187,7 @@ ask_bad_words( gpointer data )
|
|||
|
||||
if ( GTK_RESPONSE_YES == gtkask( globals->window, cGlobals->question,
|
||||
GTK_BUTTONS_YES_NO, NULL ) ) {
|
||||
board_commitTurn( cGlobals->game.board, XP_TRUE, XP_FALSE );
|
||||
board_commitTurn( cGlobals->game.board, XP_TRUE, XP_FALSE, NULL );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -2275,7 +2337,7 @@ ask_move( gpointer data )
|
|||
gint chosen = gtkask( globals->window, cGlobals->question, buttons, NULL );
|
||||
if ( GTK_RESPONSE_OK == chosen || chosen == GTK_RESPONSE_YES ) {
|
||||
BoardCtxt* board = cGlobals->game.board;
|
||||
if ( board_commitTurn( board, XP_TRUE, XP_TRUE ) ) {
|
||||
if ( board_commitTurn( board, XP_TRUE, XP_TRUE, NULL ) ) {
|
||||
board_draw( board );
|
||||
}
|
||||
}
|
||||
|
@ -2314,7 +2376,7 @@ ask_trade( gpointer data )
|
|||
cGlobals->question,
|
||||
GTK_BUTTONS_YES_NO, NULL ) ) {
|
||||
BoardCtxt* board = cGlobals->game.board;
|
||||
if ( board_commitTurn( board, XP_TRUE, XP_TRUE ) ) {
|
||||
if ( board_commitTurn( board, XP_TRUE, XP_TRUE, NULL ) ) {
|
||||
board_draw( board );
|
||||
}
|
||||
}
|
||||
|
@ -2466,7 +2528,7 @@ setupGtkUtilCallbacks( GtkGameGlobals* globals, XW_UtilCtxt* util )
|
|||
util->vtable->m_util_notifyTrade = gtk_util_notifyTrade;
|
||||
util->vtable->m_util_getVTManager = gtk_util_getVTManager;
|
||||
util->vtable->m_util_notifyPickTileBlank = gtk_util_notifyPickTileBlank;
|
||||
util->vtable->m_util_userPickTileTray = gtk_util_userPickTileTray;
|
||||
util->vtable->m_util_informNeedPickTiles = gtk_util_informNeedPickTiles;
|
||||
util->vtable->m_util_informNeedPassword = gtk_util_informNeedPassword;
|
||||
util->vtable->m_util_trayHiddenChange = gtk_util_trayHiddenChange;
|
||||
util->vtable->m_util_yOffsetChange = gtk_util_yOffsetChange;
|
||||
|
|
|
@ -42,8 +42,8 @@ abort_button_event( GtkWidget* XP_UNUSED(widget), gpointer XP_UNUSED(closure) )
|
|||
#define BUTTONS_PER_ROW 13
|
||||
|
||||
XP_S16
|
||||
gtkletterask( const PickInfo* pi, XP_Bool forTray, const XP_UCHAR* name,
|
||||
XP_U16 nTiles, const XP_UCHAR** texts )
|
||||
gtkletterask( const TrayTileSet* curPick, XP_Bool forTray, const XP_UCHAR* name,
|
||||
XP_U16 nTiles, const XP_UCHAR** texts, const XP_U16* counts )
|
||||
{
|
||||
GtkWidget* dialog;
|
||||
GtkWidget* label;
|
||||
|
@ -70,7 +70,9 @@ gtkletterask( const PickInfo* pi, XP_Bool forTray, const XP_UCHAR* name,
|
|||
gtk_box_pack_start( GTK_BOX(hbox), button, FALSE, TRUE, 0 );
|
||||
g_signal_connect( button, "clicked",
|
||||
G_CALLBACK(set_bool_and_quit), &results[ii] );
|
||||
gtk_widget_show( button );
|
||||
|
||||
/* disable if we don't have any tiles! */
|
||||
gtk_widget_set_sensitive( button, !counts || counts[ii] > 0 );
|
||||
|
||||
if ( ii+1 == nTiles || (ii % BUTTONS_PER_ROW == 0) ) {
|
||||
gtk_widget_show( hbox );
|
||||
|
@ -118,9 +120,10 @@ gtkletterask( const PickInfo* pi, XP_Bool forTray, const XP_UCHAR* name,
|
|||
char curTilesBuf[64];
|
||||
int len = snprintf( curTilesBuf, sizeof(curTilesBuf), "%s",
|
||||
"Tiles so far: " );
|
||||
for ( ii = 0; ii < pi->nCurTiles; ++ii ) {
|
||||
for ( ii = 0; ii < curPick->nTiles; ++ii ) {
|
||||
Tile tile = curPick->tiles[ii];
|
||||
len += snprintf( &curTilesBuf[len], sizeof(curTilesBuf) - len, "%s ",
|
||||
pi->curTiles[ii] );
|
||||
texts[tile] );
|
||||
}
|
||||
|
||||
GtkWidget* curTilesLabel = gtk_label_new( curTilesBuf );
|
||||
|
|
|
@ -26,9 +26,10 @@
|
|||
|
||||
#include "gtkboard.h"
|
||||
|
||||
XP_S16 gtkletterask( const PickInfo* pi, XP_Bool forTray,
|
||||
XP_S16 gtkletterask( const TrayTileSet* curPick, XP_Bool forTray,
|
||||
const XP_UCHAR* name,
|
||||
XP_U16 nTiles, const XP_UCHAR** texts );
|
||||
XP_U16 nTiles, const XP_UCHAR** texts,
|
||||
const XP_U16* counts );
|
||||
|
||||
|
||||
#endif /* _GTKLETTERASK_H_ */
|
||||
|
|
|
@ -220,10 +220,13 @@ struct CommonGlobals {
|
|||
char question[256*4];
|
||||
const XP_UCHAR* askPassName;
|
||||
XP_U16 nTiles;
|
||||
XP_U16 nToPick;
|
||||
XP_U16 blankCol;
|
||||
XP_U16 blankRow;
|
||||
XP_Bool pickIsInitial;
|
||||
|
||||
const XP_UCHAR* tiles[MAX_UNIQUE_TILES];
|
||||
XP_U16 tileCounts[MAX_UNIQUE_TILES];
|
||||
|
||||
#ifdef XWFEATURE_RELAY
|
||||
int relaySocket; /* tcp connection to relay */
|
||||
|
|
Loading…
Reference in a new issue