case VariantGrand:
flags &= ~F_ALL_CASTLE_OK;
break;
+ case VariantChu:
+ case VariantChuChess:
+ case VariantLion:
+ flags |= F_NULL_MOVE;
+ break;
default:
break;
}
cps->analyzing = FALSE;
cps->initDone = FALSE;
cps->reload = FALSE;
+ cps->pseudo = appData.pseudo[n];
/* New features added by Tord: */
cps->useFEN960 = FALSE;
char lastLoadGameTitle[MSG_SIZ], lastLoadPositionTitle[MSG_SIZ];
ChessMove lastLoadGameStart = EndOfFile;
int doubleClick;
+Boolean addToBookFlag;
void
UserMoveEvent(int fromX, int fromY, int toX, int toY, int promoChar)
DrawPosition(FALSE, boards[currentMove]);
return;
} else if (toX >= 0 && toY >= 0) {
+ if(!appData.pieceMenu && toX == fromX && toY == fromY && boards[0][rf][ff] != EmptySquare) {
+ ChessSquare q, p = boards[0][rf][ff];
+ if(p >= BlackPawn) p = BLACK_TO_WHITE p;
+ if(CHUPROMOTED p < BlackPawn) p = q = CHUPROMOTED boards[0][rf][ff];
+ else p = CHUDEMOTED (q = boards[0][rf][ff]);
+ if(PieceToChar(q) == '+') gatingPiece = p;
+ }
boards[0][toY][toX] = boards[0][fromY][fromX];
if(fromX == BOARD_LEFT-2) { // handle 'moves' out of holdings
if(boards[0][fromY][0] != EmptySquare) {
return;
}
- if(toX < 0 || toY < 0) return;
+ if((toX < 0 || toY < 0) && (fromY != DROP_RANK || fromX != EmptySquare)) return;
pup = boards[currentMove][toY][toX];
/* [HGM] If move started in holdings, it means a drop. Convert to standard form */
moveType = LegalityTest(boards[currentMove], PosFlags(currentMove),
fromY, fromX, toY, toX, promoChar);
- if(fromY == DROP_RANK && fromX == EmptySquare && (gameMode == AnalyzeMode || gameMode == EditGame)) moveType = NormalMove;
+ if(fromY == DROP_RANK && fromX == EmptySquare && (gameMode == AnalyzeMode || gameMode == EditGame || PosFlags(0) & F_NULL_MOVE)) moveType = NormalMove;
/* [HGM] but possibly ignore an IllegalMove result */
if (appData.testLegality) {
return;
}
+ if(addToBookFlag) { // adding moves to book
+ char buf[MSG_SIZ], move[MSG_SIZ];
+ CoordsToAlgebraic(boards[currentMove], PosFlags(currentMove), fromY, fromX, toY, toX, promoChar, move);
+ snprintf(buf, MSG_SIZ, " 0.0%% 1 %s\n", move);
+ AddBookMove(buf);
+ addToBookFlag = FALSE;
+ ClearHighlights();
+ return;
+ }
+
FinishMove(moveType, fromX, fromY, toX, toY, promoChar);
}
}
/* [AS] Adjudicate game if needed (note: remember that forwardMostMove now points past the last move) */
- if( gameMode == TwoMachinesPlay && adjudicateLossThreshold != 0 && forwardMostMove >= adjudicateLossPlies ) {
+ if( gameMode == TwoMachinesPlay && appData.adjudicateLossThreshold != 0 && forwardMostMove >= adjudicateLossPlies ) {
int count = 0;
while( count < adjudicateLossPlies ) {
if( count & 1 ) {
score = -score; /* Flip score for winning side */
}
-
- if( score > adjudicateLossThreshold ) {
+printf("score=%d count=%d\n",score,count);
+ if( score > appData.adjudicateLossThreshold ) {
break;
}
(unsigned int)programStats.nodes / (10*abs(programStats.time) + 1.),
programStats.movelist);
SendToICS(buf);
-if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.nodes, programStats.nodes);
}
}
#endif
int dummy, w, h, hand, s=6; char buf[MSG_SIZ], varName[MSG_SIZ];
if(appData.icsActive || forwardMostMove != 0 || cps != &first) return;
*buf = NULLCHAR;
- if(sscanf(message, "setup (%s", buf) == 1) s = 8 + strlen(buf), buf[s-9] = NULLCHAR, SetCharTable(pieceToChar, buf);
+ if(sscanf(message, "setup (%s", buf) == 1) {
+ s = 8 + strlen(buf), buf[s-9] = NULLCHAR, SetCharTable(pieceToChar, buf);
+ ASSIGN(appData.pieceToCharTable, buf);
+ }
if(startedFromSetupPosition) return;
dummy = sscanf(message+s, "%dx%d+%d_%s", &w, &h, &hand, varName);
if(dummy >= 3) {
Don't use it. */
cps->sendTime = 0;
}
+ if (cps->pseudo) { // [HGM] pseudo-engine, granted unusual powers
+ if (sscanf(message, "wtime %ld\n", &whiteTimeRemaining) == 1 || // adjust clock times
+ sscanf(message, "btime %ld\n", &blackTimeRemaining) == 1 ) return;
+ }
/*
* If chess program startup fails, exit with an error message.
SendToProgram(buf, cps);
}
+ setboardSpoiledMachineBlack = FALSE;
SendToProgram(cps->initString, cps);
if (gameInfo.variant != VariantNormal &&
gameInfo.variant != VariantLoadable
SWAP(accumulateTC, h)
SWAP(drawDepth, h)
SWAP(host, p)
+ SWAP(pseudo, h)
}
int
int
QuickScan (Board board, Move *move)
{ // reconstruct game,and compare all positions in it
- int cnt=0, stretch=0, total = MakePieceList(board, counts);
+ int cnt=0, stretch=0, found = -1, total = MakePieceList(board, counts);
do {
int piece = move->piece;
int to = move->to, from = pieceList[piece];
+ if(!found) { // if already found just scan to game end for final piece count
+ if(QuickCompare(soughtBoard, minSought, maxSought) ||
+ appData.ignoreColors && QuickCompare(reverseBoard, minReverse, maxReverse) ||
+ flipSearch && (QuickCompare(flipBoard, minSought, maxSought) ||
+ appData.ignoreColors && QuickCompare(rotateBoard, minReverse, maxReverse))
+ ) {
+ static int lastCounts[EmptySquare+1];
+ int i;
+ if(stretch) for(i=0; i<EmptySquare; i++) if(lastCounts[i] != counts[i]) { stretch = 0; break; } // reset if material changes
+ if(stretch++ == 0) for(i=0; i<EmptySquare; i++) lastCounts[i] = counts[i]; // remember actual material
+ } else stretch = 0;
+ if(stretch && (appData.searchMode == 1 || stretch >= appData.stretch)) found = cnt + 1 - stretch;
+ if(found && !appData.minPieces) return found;
+ }
if(piece <= Q_PROMO) { // special moves encoded by otherwise invalid piece numbers 1-4
- if(!piece) return -1;
+ if(!piece) return (appData.minPieces && (total < appData.minPieces || total > appData.maxPieces) ? -1 : found);
if(piece == Q_PROMO) { // promotion, encoded as (Q_PROMO, to) + (piece, promoType)
piece = (++move)->piece;
from = pieceList[piece];
quickBoard[to] = piece;
pieceList[piece] = to;
cnt++; turn ^= 3;
- if(QuickCompare(soughtBoard, minSought, maxSought) ||
- appData.ignoreColors && QuickCompare(reverseBoard, minReverse, maxReverse) ||
- flipSearch && (QuickCompare(flipBoard, minSought, maxSought) ||
- appData.ignoreColors && QuickCompare(rotateBoard, minReverse, maxReverse))
- ) {
- static int lastCounts[EmptySquare+1];
- int i;
- if(stretch) for(i=0; i<EmptySquare; i++) if(lastCounts[i] != counts[i]) { stretch = 0; break; } // reset if material changes
- if(stretch++ == 0) for(i=0; i<EmptySquare; i++) lastCounts[i] = counts[i]; // remember actual material
- } else stretch = 0;
- if(stretch && (appData.searchMode == 1 || stretch >= appData.stretch)) return cnt + 1 - stretch;
move++;
} while(1);
}
boards[0][y][x] = p;
}
}
- menuBoard[1][x] = menuBoard[BOARD_HEIGHT-2][x] = p;
}
if(gameMode != IcsExamining) { // [HGM] editpos: cycle trough boards
- for(x = BOARD_LEFT; x < BOARD_RGHT; x++) { // create 'menu board' by removing duplicates
- ChessSquare p = menuBoard[0][x];
- for(y = x + 1; y < BOARD_RGHT; y++) if(menuBoard[0][y] == p) menuBoard[0][y] = EmptySquare;
- p = menuBoard[BOARD_HEIGHT-1][x];
- for(y = x + 1; y < BOARD_RGHT; y++) if(menuBoard[BOARD_HEIGHT-1][y] == p) menuBoard[BOARD_HEIGHT-1][y] = EmptySquare;
+ int r;
+ for(r = 0; r < BOARD_HEIGHT; r++) {
+ for(x = BOARD_LEFT; x < BOARD_RGHT; x++) { // create 'menu board' by removing duplicates
+ ChessSquare p = menuBoard[r][x];
+ for(y = x + 1; y < BOARD_RGHT; y++) if(menuBoard[r][y] == p) menuBoard[r][y] = EmptySquare;
+ }
}
DisplayMessage("Clicking clock again restores position", "");
if(gameInfo.variant != lastVariant) lastVariant = gameInfo.variant, CopyBoard(erasedBoard, boards[0]);
if (gameMode == EditPosition || gameMode == IcsExamining) {
if(!appData.pieceMenu && blackPlaysFirst) EditPositionMenuEvent(ClearBoard, 0, 0);
SetBlackToPlayEvent();
- } else if ((gameMode == AnalyzeMode || gameMode == EditGame) && !blackFlag && WhiteOnMove(currentMove)) {
+ } else if ((gameMode == AnalyzeMode || gameMode == EditGame ||
+ gameMode == MachinePlaysBlack && PosFlags(0) & F_NULL_MOVE && !blackFlag && !shiftKey) && WhiteOnMove(currentMove)) {
UserMoveEvent((int)EmptySquare, DROP_RANK, 0, 0, 0); // [HGM] multi-move: if not out of time, enters null move
} else if (shiftKey) {
AdjustClock(which, -1);
if (gameMode == EditPosition || gameMode == IcsExamining) {
if(!appData.pieceMenu && !blackPlaysFirst) EditPositionMenuEvent(ClearBoard, 0, 0);
SetWhiteToPlayEvent();
- } else if ((gameMode == AnalyzeMode || gameMode == EditGame) && !whiteFlag && !WhiteOnMove(currentMove)) {
+ } else if ((gameMode == AnalyzeMode || gameMode == EditGame ||
+ gameMode == MachinePlaysWhite && PosFlags(0) & F_NULL_MOVE && !whiteFlag && !shiftKey) && !WhiteOnMove(currentMove)) {
UserMoveEvent((int)EmptySquare, DROP_RANK, 0, 0, 0); // [HGM] multi-move
} else if (shiftKey) {
AdjustClock(which, -1);
if(PieceToChar(piece) == '+') {
/* [HGM] write promoted pieces as '+<unpromoted>' (Shogi) */
*p++ = '+';
- piece = (ChessSquare)(DEMOTED piece);
+ piece = (ChessSquare)(CHUDEMOTED piece);
}
*p++ = (piece == DarkSquare ? '*' : PieceToChar(piece));
if(p[-1] == '~') {
/* [HGM] flag promoted pieces as '<promoted>~' (Crazyhouse) */
- p[-1] = PieceToChar((ChessSquare)(DEMOTED piece));
+ p[-1] = PieceToChar((ChessSquare)(CHUDEMOTED piece));
*p++ = '~';
}
}
appData.NrRanks = gameInfo.boardHeight - i; i=0;
}
break;
-#if(BOARD_FILES >= 10)
+#if(BOARD_FILES >= 10)*0
} else if(*p=='x' || *p=='X') { /* [HGM] X means 10 */
p++; emptycount=10;
if (j + emptycount > gameInfo.boardWidth) return FALSE;