extern int chatCount;
int chattingPartner;
char marker[BOARD_RANKS][BOARD_FILES]; /* [HGM] marks for target squares */
+char legal[BOARD_RANKS][BOARD_FILES]; /* [HGM] legal target squares */
char lastMsg[MSG_SIZ];
ChessSquare pieceSweep = EmptySquare;
ChessSquare promoSweep = EmptySquare, defaultPromoChoice;
cps->scoreIsAbsolute = appData.scoreIsAbsolute[n]; /* [AS] */
cps->isUCI = appData.isUCI[n]; /* [AS] */
cps->hasOwnBookUCI = appData.hasOwnBookUCI[n]; /* [AS] */
+ cps->highlight = 0;
if (appData.protocolVersion[n] > PROTOVER
|| appData.protocolVersion[n] < 1)
case VariantMakruk:
pieces = makrukArray;
nrCastlingRights = 0;
- startedFromSetupPosition = TRUE;
SetCharTable(pieceToChar, "PN.R.M....SKpn.r.m....sk");
break;
case VariantASEAN:
pieces = aseanArray;
nrCastlingRights = 0;
- startedFromSetupPosition = TRUE;
SetCharTable(pieceToChar, "PN.R.Q....BKpn.r.q....bk");
break;
case VariantTwoKings:
}
void
+MarkByFEN(char *fen)
+{
+ int r, f;
+ if(!appData.markers || !appData.highlightDragging) return;
+ for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) marker[r][f] = legal[r][f] = 0;
+ r=BOARD_HEIGHT-1; f=BOARD_LEFT;
+ while(*fen) {
+ int s = 0;
+ marker[r][f] = 0;
+ if(*fen >= 'A' && *fen <= 'Z') legal[r][f] = 1; else
+ if(*fen >= 'a' && *fen <= 'z') *fen += 'A' - 'a';
+ if(*fen == '/' && f > BOARD_LEFT) f = BOARD_LEFT, r--; else
+ if(*fen == 'T') marker[r][f++] = 0; else
+ if(*fen == 'Y') marker[r][f++] = 1; else
+ if(*fen == 'R') marker[r][f++] = 2; else {
+ while(*fen <= '9' && *fen >= '0') s = 10*s + *fen++ - '0';
+ f += s; fen -= s>0;
+ }
+ while(f >= BOARD_RGHT) f -= BOARD_RGHT - BOARD_LEFT, r--;
+ if(r < 0) break;
+ fen++;
+ }
+ DrawPosition(TRUE, NULL);
+}
+
+void
Mark (Board board, int flags, ChessMove kind, int rf, int ff, int rt, int ft, VOIDSTAR closure)
{
typedef char Markers[BOARD_RANKS][BOARD_FILES];
void
MarkTargetSquares (int clear)
{
- int x, y;
- if(clear) // no reason to ever suppress clearing
- for(x=0; x<BOARD_WIDTH; x++) for(y=0; y<BOARD_HEIGHT; y++) marker[y][x] = 0;
- if(!appData.markers || !appData.highlightDragging || appData.icsActive && gameInfo.variant < VariantShogi ||
- !appData.testLegality || gameMode == EditPosition) return;
- if(!clear) {
+ int x, y, sum=0;
+ if(clear) { // no reason to ever suppress clearing
+ for(x=0; x<BOARD_WIDTH; x++) for(y=0; y<BOARD_HEIGHT; y++) sum += marker[y][x], marker[y][x] = 0;
+ if(!sum) return; // nothing was cleared,no redraw needed
+ } else {
int capt = 0;
+ if(!appData.markers || !appData.highlightDragging || appData.icsActive && gameInfo.variant < VariantShogi ||
+ !appData.testLegality || gameMode == EditPosition) return;
GenLegal(boards[currentMove], PosFlags(currentMove), Mark, (void*) marker, EmptySquare);
if(PosFlags(0) & F_MANDATORY_CAPTURE) {
for(x=0; x<BOARD_WIDTH; x++) for(y=0; y<BOARD_HEIGHT; y++) if(marker[y][x]>1) capt++;
piece == WhiteLance && y == BOARD_HEIGHT-2 );
}
+void ReportClick(char *action, int x, int y)
+{
+ char buf[MSG_SIZ]; // Inform engine of what user does
+ int r, f;
+ if(action[0] == 'l') // mark any target square of a lifted piece as legal to-square
+ for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) legal[r][f] = 1;
+ if(!first.highlight || gameMode == EditPosition) return;
+ snprintf(buf, MSG_SIZ, "%s %c%d%s\n", action, x+AAA, y+ONE-'0', controlKey && action[0]=='p' ? "," : "");
+ SendToProgram(buf, &first);
+}
+
void
LeftClick (ClickType clickType, int xPix, int yPix)
{
/* First square */
if (OKToStartUserMove(fromX, fromY)) {
second = 0;
+ ReportClick("lift", x, y);
MarkTargetSquares(0);
if(gameMode == EditPosition && controlKey) gatingPiece = boards[currentMove][fromY][fromX];
DragPieceBegin(xPix, yPix, FALSE); dragging = 1;
}
promoDefaultAltered = FALSE;
MarkTargetSquares(1);
- if(!second || appData.oneClick && !OnlyMove(&x, &y, TRUE)) {
+ if(!(second && appData.oneClick && OnlyMove(&x, &y, TRUE))) {
if (appData.highlightDragging) {
SetHighlights(x, y, -1, -1);
} else {
else gatingPiece = doubleClick ? fromP : EmptySquare;
fromX = x;
fromY = y; dragging = 1;
+ ReportClick("lift", x, y);
MarkTargetSquares(0);
DragPieceBegin(xPix, yPix, FALSE);
if(appData.sweepSelect && CanPromote(piece = boards[currentMove][y][x], y)) {
second = sweepSelecting = 0;
fromX = fromY = -1;
gatingPiece = EmptySquare;
+ MarkTargetSquares(1);
ClearHighlights();
gotPremove = 0;
ClearPremoveHighlights();
clearFlag = 0;
+ if(gameMode != EditPosition && !appData.testLegality && !legal[y][x]) {
+ if(dragging) DragPieceEnd(xPix, yPix), dragging = 0;
+ DisplayMessage(_("only marked squares are legal"),"");
+ DrawPosition(TRUE, NULL);
+ return; // ignore to-click
+ }
+
/* we now have a different from- and (possibly off-board) to-square */
/* Completed move */
if(!sweepSelecting) {
// off-board moves should not be highlighted
if(x < 0 || y < 0) ClearHighlights();
+ else ReportClick("put", x, y);
if(gatingPiece != EmptySquare && gameInfo.variant == VariantSChess) promoChoice = ToLower(PieceToChar(gatingPiece));
SendToProgram("force\n", cps);
cps->bookSuspend = TRUE; // flag indicating it has to be restarted
}
+ if(bookHit) setboardSpoiledMachineBlack = FALSE; // suppress 'go' in SendMoveToProgram
if(!initial) SendMoveToProgram(moveNr, cps); // with hit on initial position there is no move
// now arrange restart after book miss
if(bookHit) {
MakeMove(fromX, fromY, toX, toY, promoChar);/*updates forwardMostMove*/
+ /* Test suites abort the 'game' after one move */
+ if(*appData.finger) {
+ static FILE *f;
+ char *fen = PositionToFEN(backwardMostMove, NULL, 0); // no counts in EPD
+ if(!f) f = fopen(appData.finger, "w");
+ if(f) fprintf(f, "%s bm %s;\n", fen, parseList[backwardMostMove]), fflush(f);
+ else { DisplayFatalError("Bad output file", errno, 0); return; }
+ free(fen);
+ GameEnds(GameUnfinished, NULL, GE_XBOARD);
+ }
+
/* [AS] Adjudicate game if needed (note: remember that forwardMostMove now points past the last move) */
if( gameMode == TwoMachinesPlay && adjudicateLossThreshold != 0 && forwardMostMove >= adjudicateLossPlies ) {
int count = 0;
if (sscanf(message, "pong %d", &cps->lastPong) == 1) {
return;
}
+ if(!strncmp(message, "highlight ", 10)) {
+ if(appData.testLegality && appData.markers) return;
+ MarkByFEN(message+10); // [HGM] alien: allow engine to mark board squares
+ return;
+ }
/*
* If the move is illegal, cancel it and redraw the board.
* Also deal with other error cases. Matching is rather loose
PlayIcsUnfinishedSound();
}
}
+ if(appData.quitNext) { ExitEvent(0); return; }
} else if (gameMode == EditGame ||
gameMode == PlayFromGameFile ||
gameMode == AnalyzeMode ||
CreateBookEvent ()
{
ListGame * lg = (ListGame *) gameList.head;
- FILE *f;
+ FILE *f, *g;
int nItem;
static int secondTime = FALSE;
return;
}
- if(!secondTime && (f = fopen(appData.polyglotBook, "r"))) {
- fclose(f);
+ if(!secondTime && (g = fopen(appData.polyglotBook, "r"))) {
+ fclose(g);
secondTime++;
DisplayNote(_("Book file exists! Try again for overwrite."));
return;
/* End of additions by Tord */
/* [HGM] added features: */
+ if (BoolFeature(&p, "highlight", &cps->highlight, cps)) continue;
if (BoolFeature(&p, "debug", &cps->debug, cps)) continue;
if (BoolFeature(&p, "nps", &cps->supportsNPS, cps)) continue;
if (IntFeature(&p, "level", &cps->maxNrOfSessions, cps)) continue;