New feature, meant for testing relay, makes robot skip random number

of seconds within specified range before making a move.  Working only
on gtk so far, and will probably never be used other than on linux
clients.
This commit is contained in:
ehouse 2009-07-09 12:43:51 +00:00
parent 854b3d9349
commit 184a154c52
6 changed files with 153 additions and 9 deletions

View file

@ -104,6 +104,9 @@ typedef enum {
TIMER_TIMERTICK,
#ifndef XWFEATURE_STANDALONE_ONLY
TIMER_COMMS,
#endif
#ifdef XWFEATURE_SLOW_ROBOT
TIMER_SLOWROBOT,
#endif
NUM_TIMERS_PLUS_ONE /* must be last */
} XWTimerReason;
@ -124,6 +127,9 @@ typedef struct CommonPrefs {
XP_Bool showRobotScores; /* applies to all games */
XP_Bool hideTileValues;
XP_Bool reserved2; /* get to 32-bit for ARM... */
#ifdef XWFEATURE_SLOW_ROBOT
XP_U16 robotThinkMin, robotThinkMax;
#endif
} CommonPrefs;
#ifdef XWFEATURE_BLUETOOTH

View file

@ -92,6 +92,10 @@ typedef struct ServerNonvolatiles {
XP_U8 pendingRegistrations;
XP_Bool showRobotScores;
#ifdef XWFEATURE_SLOW_ROBOT
XP_U16 robotThinkMin, robotThinkMax; /* not saved (yet) */
#endif
RemoteAddress addresses[MAX_NUM_PLAYERS];
} ServerNonvolatiles;
@ -108,9 +112,18 @@ struct ServerCtxt {
ServerPlayer players[MAX_NUM_PLAYERS];
XP_Bool serverDoing;
#ifdef XWFEATURE_SLOW_ROBOT
XP_Bool robotWaiting;
#endif
MPSLOT
};
#ifdef XWFEATURE_SLOW_ROBOT
# define ROBOTWAITING(s) (s)->robotWaiting
#else
# define ROBOTWAITING(s) XP_FALSE
#endif
#define NPASSES_OK(s) model_recentPassCountOk((s)->vol.model)
@ -123,7 +136,7 @@ static void doEndGame( ServerCtxt* server );
static void endGameInternal( ServerCtxt* server, GameEndReason why );
static void badWordMoveUndoAndTellUser( ServerCtxt* server,
BadWordInfo* bwi );
static XP_Bool tileCountsOk( ServerCtxt* server );
static XP_Bool tileCountsOk( const ServerCtxt* server );
static void setTurn( ServerCtxt* server, XP_S16 turn );
#ifndef XWFEATURE_STANDALONE_ONLY
@ -404,10 +417,31 @@ server_destroy( ServerCtxt* server )
XP_FREE( server->mpool, server );
} /* server_destroy */
#ifdef XWFEATURE_SLOW_ROBOT
static int
figureSleepTime( const ServerCtxt* server )
{
int result = 0;
XP_U16 min = server->nv.robotThinkMin;
XP_U16 max = server->nv.robotThinkMax;
if ( min < max ) {
int diff = max - min + 1;
result = XP_RANDOM() % diff;
}
result += min;
return result;
}
#endif
void
server_prefsChanged( ServerCtxt* server, CommonPrefs* cp )
{
server->nv.showRobotScores = cp->showRobotScores;
#ifdef XWFEATURE_SLOW_ROBOT
server->nv.robotThinkMin = cp->robotThinkMin;
server->nv.robotThinkMax = cp->robotThinkMax;
#endif
} /* server_prefsChanged */
XP_S16
@ -701,18 +735,55 @@ makeRobotMove( ServerCtxt* server )
return result; /* always return TRUE after robot move? */
} /* makeRobotMove */
static XP_Bool
robotMovePending( ServerCtxt* server )
#ifdef XWFEATURE_SLOW_ROBOT
static XP_Bool
wakeRobotProc( void* closure, XWTimerReason why )
{
XP_ASSERT( TIMER_SLOWROBOT == why );
ServerCtxt* server = (ServerCtxt*)closure;
XP_ASSERT( ROBOTWAITING(server) );
server->robotWaiting = XP_FALSE;
util_requestTime( server->vol.util );
return XP_FALSE;
}
#endif
static XP_Bool
robotMovePending( const ServerCtxt* server )
{
XP_Bool result = XP_FALSE;
XP_S16 turn = server->nv.currentTurn;
if ( turn >= 0 && tileCountsOk(server) && NPASSES_OK(server) ) {
CurGameInfo* gi = server->vol.gi;
LocalPlayer* player = &gi->players[turn];
return IS_ROBOT(player) && IS_LOCAL(player);
result = IS_ROBOT(player) && IS_LOCAL(player);
}
return XP_FALSE;
return result;
} /* robotMovePending */
#ifdef XWFEATURE_SLOW_ROBOT
static XP_Bool
postponeRobotMove( ServerCtxt* server )
{
XP_Bool result = XP_FALSE;
XP_ASSERT( robotMovePending(server) );
if ( !ROBOTWAITING(server) ) {
XP_U16 sleepTime = figureSleepTime(server);
if ( 0 != sleepTime ) {
server->robotWaiting = XP_TRUE;
util_setTimer( server->vol.util, TIMER_SLOWROBOT, sleepTime,
wakeRobotProc, server );
result = XP_TRUE;
}
}
return result;
}
# define POSTPONEROBOTMOVE(s) postponeRobotMove(s)
#else
# define POSTPONEROBOTMOVE(s) XP_FALSE
#endif
static void
showPrevScore( ServerCtxt* server )
{
@ -822,10 +893,11 @@ server_do( ServerCtxt* server )
moreToDo = XP_TRUE; /* either process turn or end game... */
break;
case XWSTATE_INTURN:
if ( robotMovePending( server ) ) {
if ( robotMovePending( server ) && !ROBOTWAITING(server) ) {
result = makeRobotMove( server );
/* if robot was interrupted, we need to schedule again */
moreToDo = !result || robotMovePending( server );
moreToDo = !result ||
(robotMovePending( server ) && !POSTPONEROBOTMOVE(server));
}
break;
@ -1587,7 +1659,7 @@ nextTurn( ServerCtxt* server, XP_S16 nxtTurn )
XP_ASSERT( server->nv.gameState != XWSTATE_GAMEOVER );
callTurnChangeListener( server );
if ( robotMovePending(server) ) {
if ( robotMovePending(server) && !POSTPONEROBOTMOVE(server) ) {
moreToDo = XP_TRUE;
}
@ -2100,7 +2172,7 @@ server_endGame( ServerCtxt* server )
/* If game is about to end because one player's out of tiles, we don't want to
* keep trying to move */
static XP_Bool
tileCountsOk( ServerCtxt* server )
tileCountsOk( const ServerCtxt* server )
{
XP_Bool maybeOver = 0 == pool_getNTilesLeft( server->pool );
if ( maybeOver ) {

View file

@ -92,6 +92,9 @@ DEFINES += ${BLUETOOTH}
DEFINES += -DXWFEATURE_RELAY
DEFINES += -DXWFEATURE_SMS
# Robot can be made to think, to simulate for relay mostly
DEFINES += -DXWFEATURE_SLOW_ROBOT
# Support device-to-device connection via UDP, e.g. using wifi on a
# LAN or where the host/server isn't behind a firewall.
# DEFINES += -DXWFEATURE_IP_DIRECT

View file

@ -1250,6 +1250,18 @@ comms_timer_func( gpointer data )
}
#endif
#ifdef XWFEATURE_SLOW_ROBOT
static gint
slowrob_timer_func( gpointer data )
{
GtkAppGlobals* globals = (GtkAppGlobals*)data;
linuxFireTimer( &globals->cGlobals, TIMER_SLOWROBOT );
return (gint)0;
}
#endif
static void
gtk_util_setTimer( XW_UtilCtxt* uc, XWTimerReason why,
XP_U16 XP_UNUSED_STANDALONE(when),
@ -1276,6 +1288,10 @@ gtk_util_setTimer( XW_UtilCtxt* uc, XWTimerReason why,
#ifndef XWFEATURE_STANDALONE_ONLY
} else if ( why == TIMER_COMMS ) {
newSrc = g_timeout_add( 1000 * when, comms_timer_func, globals );
#endif
#ifdef XWFEATURE_SLOW_ROBOT
} else if ( why == TIMER_SLOWROBOT ) {
newSrc = g_timeout_add( 1000 * when, slowrob_timer_func, globals );
#endif
} else {
XP_ASSERT( 0 );
@ -1866,6 +1882,10 @@ gtkmain( LaunchParams* params, int argc, char *argv[] )
globals.cp.showBoardArrow = XP_TRUE;
globals.cp.hideTileValues = params->hideValues;
globals.cp.showRobotScores = params->showRobotScores;
#ifdef XWFEATURE_SLOW_ROBOT
globals.cp.robotThinkMin = params->robotThinkMin;
globals.cp.robotThinkMax = params->robotThinkMax;
#endif
setupGtkUtilCallbacks( &globals, params->util );

View file

@ -215,6 +215,10 @@ usage( char* appName, char* msg )
"\t -d xwd_file # provides tile counts & values\n"
"\t\t # list each player as local or remote\n"
"\t [-N]* # remote client (listen for connection)\n"
#ifdef XWFEATURE_SLOW_ROBOT
"\t [-z min:max] # robot sleeps random min<=seconds<=max \n"
#endif
"\t # before turn \n"
#ifdef XWFEATURE_RELAY
"\t [-p relay_port] # relay is at this port\n"
"\t [-a relay_addr] # use relay (via port spec'd above)\n"
@ -649,6 +653,29 @@ nameToBtAddr( const char* name, bdaddr_t* ba )
} /* nameToBtAddr */
#endif
#ifdef XWFEATURE_SLOW_ROBOT
static bool
parsePair( const char* optarg, XP_U16* min, XP_U16* max )
{
bool success = false;
char* colon = strstr( optarg, ":" );
if ( !colon ) {
fprintf( stderr, ": not found in argument\n" );
} else {
int intmin, intmax;
if ( 2 == sscanf( optarg, "%d:%d", &intmin, &intmax ) ) {
if ( intmin <= intmin ) {
success = true;
*min = intmin;
*max = intmax;
fprintf( stderr, "min: %d; max: %d\n", *min, *max );
}
}
}
return success;
}
#endif
int
main( int argc, char** argv )
{
@ -741,6 +768,9 @@ main( int argc, char** argv )
"h:I"
#endif
"kKf:ln:Nsd:e:r:b:q:w:Sit:UmvcVP"
#ifdef XWFEATURE_SLOW_ROBOT
"z:"
#endif
#ifdef XWFEATURE_SMS
"M:"
#endif
@ -889,6 +919,15 @@ main( int argc, char** argv )
case 'v':
mainParams.verticalScore = XP_TRUE;
break;
#ifdef XWFEATURE_SLOW_ROBOT
case 'z':
if ( !parsePair( optarg, &mainParams.robotThinkMin,
&mainParams.robotThinkMax ) ) {
usage(argv[0], "bad param to -z" );
}
break;
#endif
#if defined PLATFORM_GTK && defined PLATFORM_NCURSES
case 'g':
useCurses = XP_FALSE;

View file

@ -67,6 +67,10 @@ typedef struct LaunchParams {
XP_Bool allowHintRect;
#endif
#ifdef XWFEATURE_SLOW_ROBOT
XP_U16 robotThinkMin, robotThinkMax;
#endif
DeviceRole serverRole;
CommsConnType conType;