/*
* zippy.c -- Implements Zippy the Pinhead chess player on ICS in XBoard
- * $Id$
*
- * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.
- * Enhancements Copyright 1992-2001 Free Software Foundation, Inc.
+ * Copyright 1991 by Digital Equipment Corporation, Maynard,
+ * Massachusetts.
+ *
+ * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
+ * 2007, 2008, 2009 Free Software Foundation, Inc.
+ *
+ * Enhancements Copyright 2005 Alessandro Scotti
*
* The following terms apply to Digital Equipment Corporation's copyright
* interest in XBoard:
* SOFTWARE.
* ------------------------------------------------------------------------
*
- * The following terms apply to the enhanced version of XBoard distributed
- * by the Free Software Foundation:
+ * The following terms apply to the enhanced version of XBoard
+ * distributed by the Free Software Foundation:
* ------------------------------------------------------------------------
- * This program is free software; you can redistribute it and/or modify
+ *
+ * GNU XBoard 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.
+ * the Free Software Foundation, either version 3 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.
+ * GNU XBoard 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.
- * ------------------------------------------------------------------------
- */
+ * along with this program. If not, see http://www.gnu.org/licenses/.
+ *
+ *------------------------------------------------------------------------
+ ** See the file ChangeLog for a revision history. */
#include "config.h"
#include "backend.h"
#include "backendz.h"
+char *SendMoveToBookUser P((int nr, ChessProgramState *cps, int initial)); // [HGM] book
+void HandleMachineMove P((char *message, ChessProgramState *cps));
+
static char zippyPartner[MSG_SIZ];
static char zippyLastOpp[MSG_SIZ];
+static char zippyOffender[MSG_SIZ]; // [HGM] aborter
static int zippyConsecGames;
static time_t zippyLastGameEnd;
if ( p != NULL ) {
appData.zippyAcceptOnly = p;
}
-
+
/* Should Zippy use "i" command? */
/* Defaults to 1=true */
p = getenv("ZIPPYUSEI");
*/
-char *swifties[] = {
+char *swifties[] = {
"i acclaims:", "i admonishes:", "i advertises:", "i advises:",
"i advocates:", "i affirms:", "i alleges:", "i anathematizes:",
"i animadverts:", "i announces:", "i apostrophizes:",
"i hosannas:", "i howls:", "i hums:", "i hypothecates:",
"i hypothesizes:", "i imagines:", "i implies:", "i implores:",
"i imprecates:", "i indicates:", "i infers:",
- "i informs everyone:", "i instructs:", "i interjects:",
+ "i informs everyone:", "i instructs:", "i interjects:",
"i interposes:", "i intimates:", "i intones:", "i introspects:",
"i inveighs:", "i jabbers:", "i japes:", "i jests:", "i jibes:",
"i jives:", "i jokes:", "i joshes:", "i keens:", "i laments:",
#define MAX_SPEECH 250
-void Speak(how, whom)
+void Speak(how, whom)
char *how, *whom;
{
static FILE *zipfile = NULL;
char *p;
int c, speechlen;
Boolean done;
-
+
if (strcmp(how, "shout") == 0) {
now = time((time_t *) NULL);
if (now - lastShout < 1*60) return;
}
fstat(fileno(zipfile), &zipstat);
}
-
+
for (;;) {
fseek(zipfile, (unsigned) random() % zipstat.st_size, 0);
do {
static char opp_name[128][32];
static int num_opps=0;
+extern ColorClass curColor;
+
+static void SetCurColor( ColorClass color )
+{
+ curColor = color;
+}
+
+static void ColorizeEx( ColorClass color, int cont )
+{
+ if( appData.colorize ) {
+ Colorize( color, cont );
+ SetCurColor( color );
+ }
+}
+
int ZippyControl(buf, i)
char *buf;
int *i;
char *player, *p;
char reply[MSG_SIZ];
-#if TRIVIA
-#include "trivia.c"
-#endif
-
/* Possibly reject Crafty as opponent */
if (appData.zippyPlay && appData.zippyNoplayCrafty && forwardMostMove < 4
- && looking_at(buf, i, "* kibitzes: Hello from Crafty")) {
+ && looking_at(buf, i, "* kibitzes: Hello from Crafty"))
+ {
player = StripHighlightAndTitle(star_match[0]);
if ((gameMode == IcsPlayingWhite &&
StrCaseCmp(player, gameInfo.black) == 0) ||
/* If this is a computer, save the name. Then later, once the */
/* game is really started, we will send the "computer" notice to */
- /* the engine. */
+ /* the engine. */
if (appData.zippyPlay &&
looking_at(buf, i, "* is in the computer list")) {
int i;
}
/* Tells and says */
- if (appData.zippyPlay &&
+ if (appData.zippyPlay &&
(looking_at(buf, i, "* offers to be your bughouse partner") ||
looking_at(buf, i, "* tells you: [automatic message] I chose you"))) {
player = StripHighlightAndTitle(star_match[0]);
}
if (looking_at(buf, i, "* tells you: *") ||
- looking_at(buf, i, "* says: *")) {
+ looking_at(buf, i, "* says: *"))
+ {
player = StripHighlightAndTitle(star_match[0]);
if (appData.zippyPassword[0] != NULLCHAR &&
strncmp(star_match[1], appData.zippyPassword,
Speak("tell", player);
}
}
+
+ ColorizeEx( ColorTell, FALSE );
+
return TRUE;
}
+ if( appData.colorize && looking_at(buf, i, "* (*) seeking") ) {
+ ColorizeEx(ColorSeek, FALSE);
+ return FALSE;
+ }
+
if (looking_at(buf, i, "* spoofs you:")) {
player = StripHighlightAndTitle(star_match[0]);
sprintf(reply, "spoofedby %s\n", player);
SendToICS(reply);
}
+
return FALSE;
}
/* Shouts and emotes */
if (looking_at(buf, i, "--> * *") ||
- looking_at(buf, i, "* shouts: *")) {
+ looking_at(buf, i, "* shouts: *"))
+ {
if (appData.zippyTalk) {
char *player = StripHighlightAndTitle(star_match[0]);
if (strcmp(player, ics_handle) == 0) {
Speak("shout", NULL);
}
}
+
+ ColorizeEx(ColorShout, FALSE);
+
return TRUE;
}
Speak("kibitz", NULL);
}
}
+
+ ColorizeEx(ColorKibitz, FALSE);
+
return TRUE;
}
Speak("whisper", NULL);
}
}
+
+ ColorizeEx(ColorKibitz, FALSE);
+
return TRUE;
}
channel++;
}
channel[strlen(channel)-1] = NULLCHAR;
-#if 0
- /* Always tell to the channel (probability 90%) */
- if (strcmp(player, ics_handle) != 0 &&
- ((unsigned) random() % 10) < 9) {
- Speak("tell", channel);
- }
-#else
+
/* Tell to the channel only if someone mentions our name */
if (ZippyCalled(star_match[2])) {
Speak("tell", channel);
}
-#endif
+
+ ColorizeEx( atoi(channel) == 1 ? ColorChannel1 : ColorChannel, FALSE );
}
return TRUE;
}
SendToICS(reply);
Speak("tell", player);
}
- }
+ }
if (looking_at(buf, i, "Notification: * has departed")) {
if (((unsigned) random() % 3) == 0) {
sprintf(reply, "farewell %s\n", player);
SendToICS(reply);
}
- }
+ }
if (looking_at(buf, i, "Not sent -- * is censoring you")) {
char *player = StripHighlightAndTitle(star_match[0]);
sprintf(reply, "%s-notify %s\n", ics_prefix, player);
SendToICS(reply);
}
- }
+ }
if (looking_at(buf, i, "command is currently turned off")) {
appData.zippyUseI = 0;
SendToICS("\n");
}
zippyLastGameEnd = time(0);
+ if(forwardMostMove < appData.zippyShortGame)
+ strcpy(zippyOffender, zippyLastOpp); else zippyOffender[0] = 0; // [HGM] aborter
}
/*
char *srated, *swild, *sbase, *sincrement, *opponent;
{
char buf[MSG_SIZ];
- int base, increment;
+ int base, increment, i=0;
char rated;
VariantClass variant;
char *varname;
base = atoi(sbase);
increment = atoi(sincrement);
- /* If icsAnalyzeEngine active
- we don't accept automatic games */
- if (appData.icsActive)
- if (appData.icsEngineAnalyze) return;
+ /* [DM] If icsAnalyzeEngine active we don't accept automatic games */
+ if (appData.icsActive && appData.icsEngineAnalyze) return;
/* If desired, you can insert more code here to decline matches
based on rated, variant, base, and increment, but it is
SendToICS(buf);
return;
}
- if (StrStr(appData.zippyVariants, varname) == NULL) {
+ if (StrStr(appData.zippyVariants, varname) == NULL ||
+ ((i=first.protocolVersion) != 1 && StrStr(first.variants, varname) == NULL) /* [HGM] zippyvar */
+ ) {
sprintf(buf,
"%stell %s This computer can't play %s [%s], only %s\n%sdecline %s\n",
- ics_prefix, opponent, swild, varname, appData.zippyVariants,
+ ics_prefix, opponent, swild, varname,
+ i ? first.variants : appData.zippyVariants, /* [HGM] zippyvar */
ics_prefix, opponent);
SendToICS(buf);
return;
/* Yes, and this isn't him. Ignore challenge. */
return;
}
-
+
/* Too many consecutive games with same opponent? If so, make him
wait until someone else has played or a timeout has elapsed. */
if (appData.zippyMaxGames &&
return;
}
+ /* [HGM] aborter: opponent is cheater that aborts games he doesn't like on first move. Make him wait */
+ if (strcmp(opponent, zippyOffender) == 0 &&
+ difftime(time(0), zippyLastGameEnd) < appData.zippyReplayTimeout) {
+ sprintf(buf, "%stell %s Sorry, your previous game against %s was rather short. "
+ " It will wait %d seconds to see if a tougher opponent comes along.\n%sdecline %s\n",
+ ics_prefix, opponent, ics_handle,
+ appData.zippyReplayTimeout, ics_prefix, opponent);
+ SendToICS(buf);
+ return;
+ }
+
/* Engine not yet initialized or still thinking about last game? */
if (!first.initDone || first.lastPing != first.lastPong) {
sprintf(buf, "%stell %s I'm not quite ready for a new game yet; try again soon.\n%sdecline %s\n",
if (looking_at(buf, i, "Challenge: * (*) *(*) * * * * Loaded from *")) {
/* note: star_match[2] can include "[white] " or "[black] "
before our own name. */
- ZippyHandleChallenge(star_match[4], star_match[8],
+ if(star_match[8] == NULL || star_match[8][0] == 0) // [HGM] chessd: open-source ICS has file on next line
+ ZippyHandleChallenge(star_match[4], star_match[5],
+ star_match[6], star_match[7], StripHighlightAndTitle(star_match[0]));
+ else ZippyHandleChallenge(star_match[4], star_match[8],
star_match[6], star_match[7],
StripHighlightAndTitle(star_match[0]));
return TRUE;
return TRUE;
}
- if (ics_type == ICS_ICC) {
- if (looking_at(buf, i, "Your opponent offers you a draw")) {
- if (first.sendDrawOffers && first.initDone)
- SendToProgram("draw\n", &first);
- return TRUE;
- }
- } else {
- if (looking_at(buf, i, "offers you a draw")) {
- if (first.sendDrawOffers && first.initDone) {
- SendToProgram("draw\n", &first);
- }
- return TRUE;
- }
- }
+
+ if (ics_type == ICS_ICC) { // [DM]
+ if (looking_at(buf, i, "Your opponent offers you a draw")) {
+ if (first.sendDrawOffers && first.initDone)
+ SendToProgram("draw\n", &first);
+ return TRUE;
+ }
+ } else {
+ if (looking_at(buf, i, "offers you a draw")) {
+ if (first.sendDrawOffers && first.initDone) {
+ SendToProgram("draw\n", &first);
+ }
+ return TRUE;
+ }
+ }
if (looking_at(buf, i, "requests that the game be aborted") ||
looking_at(buf, i, "would like to abort")) {
return FALSE;
}
-/* Initialize chess program with data from the first board
+/* Initialize chess program with data from the first board
* of a new or resumed game.
*/
void ZippyFirstBoard(moveNum, basetime, increment)
int w, b;
char *opp = (gameMode==IcsPlayingWhite ? gameInfo.black : gameInfo.white);
Boolean sentPos = FALSE;
+ char *bookHit = NULL; // [HGM] book
if (!first.initDone) {
/* Game is starting prematurely. We can't deal with this */
message from ICS." Send 0 in that case */
w = (gameInfo.whiteRating >= 0) ? gameInfo.whiteRating : 0;
b = (gameInfo.blackRating >= 0) ? gameInfo.blackRating : 0;
-
+
firstMove = FALSE;
if (gameMode == IcsPlayingWhite) {
if (first.sendName) {
SendTimeRemaining(&first, TRUE);
}
}
- SendToProgram("go\n", &first);
+ bookHit = SendMoveToBookUser(forwardMostMove-1, &first, TRUE); // [HGM] book: send go or retrieve book move
} else {
/* Engine's opponent is on move now */
if (first.usePlayother) {
SendTimeRemaining(&first, TRUE);
}
}
- SendToProgram("go\n", &first);
+// SendToProgram("go\n", &first);
+ bookHit = SendMoveToBookUser(forwardMostMove-1, &first, TRUE); // [HGM] book: send go or retrieve book move
}
}
} else if (gameMode == IcsPlayingBlack) {
SendTimeRemaining(&first, FALSE);
}
}
- SendToProgram("go\n", &first);
+// SendToProgram("go\n", &first);
+ bookHit = SendMoveToBookUser(forwardMostMove-1, &first, TRUE); // [HGM] book: send go or retrieve book move
} else {
/* Engine's opponent is on move now */
if (first.usePlayother) {
} else {
/* Position not sent above, move list might be sent later */
/* Nothing needs to be done here */
- }
+ }
+ }
+
+ if(bookHit) { // [HGM] book: simulate book reply
+ static char bookMove[MSG_SIZ]; // a bit generous?
+
+ programStats.depth = programStats.nodes = programStats.time =
+ programStats.score = programStats.got_only_move = 0;
+ sprintf(programStats.movelist, "%s (xbook)", bookHit);
+
+ strcpy(bookMove, "move ");
+ strcat(bookMove, bookHit);
+ HandleMachineMove(bookMove, &first);
}
}