* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
*
* Enhancements Copyright 2005 Alessandro Scotti
*
static int exiting = 0; /* [HGM] moved to top */
static int setboardSpoiledMachineBlack = 0 /*, errorExitFlag = 0*/;
int startedFromPositionFile = FALSE; Board filePosition; /* [HGM] loadPos */
+int rightsBoard[BOARD_RANKS][BOARD_FILES]; /* [HGM] editrights */
char endingGame = 0; /* [HGM] crash: flag to prevent recursion of GameEnds() */
int whiteNPS, blackNPS; /* [HGM] nps: for easily making clocks aware of NPS */
VariantClass currentlyInitializedVariant; /* [HGM] variantswitch */
click-click move is possible */
if (toX == -2 || toY == -2) {
boards[0][fromY][fromX] = EmptySquare;
+ rightsBoard[fromY][fromX] = 0;
return AmbiguousMove;
} else if (toX >= 0 && toY >= 0) {
boards[0][toY][toX] = boards[0][fromY][fromX];
}
} else
boards[0][fromY][fromX] = EmptySquare;
+ rightsBoard[fromY][fromX] = rightsBoard[toY][toX] = 0;
return AmbiguousMove;
}
return ImpossibleMove;
FinishMove(moveType, fromX, fromY, toX, toY, promoChar);
}
-void
-PromoDialog(int h, int w, Board board, Boolean clearBoard)
-{ // dummy routine to mimic with pseudo-popup what front-end should do:
- // display a popup with h x w mini-board
- int i, j;
- DisplayMessage("Click on your piece of choice", "");
- DrawPosition(TRUE, board);
-}
-
int hTab[(int)EmptySquare/2+1] = { 1,1,1,1,1,1,2,1,2,3,2,3,3,3,2,3,4,3,3,4,4,3,4 };
int wTab[(int)EmptySquare/2+1] = { 1,1,2,3,4,5,3,7,4,3,5,4,4,5,7,5,4,6,6,5,5,7,6 };
Board promoBoard;
int promotionChoice = 0;
-void PromoPopUp(ChessSquare piece)
+void
+PiecePopUp(int x, int y)
+{
+ int i, j, h, w, nWhite=0, nBlack=0;
+ ChessSquare list[EmptySquare];
+ for(i=0; i<EmptySquare/2; i++) {
+ if(PieceToChar(i) != '.') list[nWhite++] = i;
+ if(PieceToChar(i+EmptySquare/2) != '.') list[EmptySquare - ++nBlack] = i + EmptySquare/2;
+ }
+ CopyBoard(promoBoard, boards[currentMove]);
+ for(i=0; i<BOARD_HEIGHT; i++) for(j=BOARD_LEFT; j<BOARD_RGHT; j++) promoBoard[i][j] = EmptySquare;
+ j = nWhite + nBlack + 1;
+ h = sqrt((j+1)/2 + 1.); w = (j+h-1)/h;
+ if(w>BOARD_RGHT-BOARD_LEFT) { w = BOARD_RGHT - BOARD_LEFT; h = (j+w-1)/w; }
+ for(i=0; i<nWhite; i++) promoBoard[i/w][BOARD_LEFT+i%w] = list[nWhite-1-i];
+ if(h==2 && nWhite == nBlack)
+ for(i=0; i<nWhite; i++) promoBoard[1][BOARD_LEFT+i%w] = list[EmptySquare-nBlack+i];
+ else
+ for(i=0; i<nBlack; i++) promoBoard[h-1-i/w][BOARD_LEFT+w-1-i%w] = list[EmptySquare-nBlack+i];
+ promotionChoice = 3;
+ ClearHighlights();
+ PromoDialog(h, w, promoBoard, TRUE, _("Select piece:"), x, y);
+}
+
+void
+PromoPopUp(ChessSquare piece)
{ // determine the layout of the piece-choice dialog
int w, h, i, j, nr;
ChessSquare list[EmptySquare];
+ for(i=0; i<BOARD_HEIGHT; i++) for(j=BOARD_LEFT; j<BOARD_RGHT; j++) promoBoard[i][j] = EmptySquare;
if(gameInfo.variant == VariantShogi) {
// non-Pawn promotes; must be shogi
- h = 1; w = 1; list[0] = piece;
+ h = 1; w = 1; promoBoard[0][BOARD_LEFT+0] = piece;
if(PieceToChar(PROMOTED piece) != '.') {
// promoted version is enabled
- w = 2; list[1] = PROMOTED piece;
+ w = 2; promoBoard[0][BOARD_LEFT+1] = PROMOTED piece;
}
} else {
// Pawn, promotes to any enabled other piece
h = 1; w = nr = 0;
for(i=1; i<EmptySquare/2; i++) {
if(PieceToChar(piece+i) != '.'
- && PieceToChar(PROMOTED piece + i) != '~' // suppress bughouse true pieces
+ && PieceToChar(piece + i) != '~' // suppress bughouse true pieces
) {
list[w++] = piece+i; nr++;
}
}
- if(appData.testLegality && gameInfo.variant != VariantSuicide) nr--,w--; // remove King
+ if(appData.testLegality && gameInfo.variant != VariantSuicide
+ && gameInfo.variant != VariantGiveaway) nr--,w--; // remove King
h = hTab[nr]; w = wTab[nr]; // factorize with nice ratio
- for(i=0; i<BOARD_HEIGHT; i++) for(j=BOARD_LEFT; j<BOARD_RGHT; j++) promoBoard[i][j] = EmptySquare;
- for(i=0; i < nr; i++) promoBoard[BOARD_LEFT+i/w][i%w] = list[i]; // layout
+ for(i=0; i < nr; i++) promoBoard[i/w][BOARD_LEFT+i%w] = list[i]; // layout
}
promotionChoice = 2; // wait for click on board
- PromoDialog(h, w, promoBoard, FALSE);
+ PromoDialog(h, w, promoBoard, FALSE, _("Promote to:"), -1, -1);
}
void
if(promotionChoice) { // we are waiting for a click to indicate promotion piece
ChessSquare p = EmptySquare; Boolean inHoldings;
+ if(promotionChoice == 3) {
+ if(clickType == Press) EditPositionMenuEvent(promoBoard[y][x], fromX, fromY);
+ else if(clickType == Release) promotionChoice = 0;
+ fromX = fromY = -1;
+ return;
+ }
if(clickType == Release) return; // ignore upclick of click-click destination
if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
inHoldings = gameInfo.holdingsWidth &&
p = promoBoard[y][x];
if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
if(p != EmptySquare) {
- FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
+ char promoChar = PieceToChar(p);
+ if(gameInfo.variant == VariantShogi && promoChar != '+') promoChar = '=';
+ FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(promoChar));
fromX = fromY = -1;
promotionChoice = 0;
return;
}
}
-int RightClick(ClickType action, int x, int y, int *fromX, int *fromY)
+int RightClick(ClickType action, int x, int y, int *xx, int *yy)
{ // front-end-free part taken out of PieceMenuPopup
int whichMenu; int xSqr, ySqr;
xSqr = EventToSquare(x, BOARD_WIDTH);
ySqr = EventToSquare(y, BOARD_HEIGHT);
+ if (flipView)
+ xSqr = BOARD_WIDTH - 1 - xSqr;
+ else
+ ySqr = BOARD_HEIGHT - 1 - ySqr;
+ if(promotionChoice == 3 && action == Release) {
+ EditPositionMenuEvent(promoBoard[ySqr][xSqr], fromX, fromY);
+ fromX = fromY = -1;
+ promotionChoice = 0;
+ return -1;
+ }
if (action == Release) UnLoadPV(); // [HGM] pv
if (action != Press) return -2; // return code to be ignored
switch (gameMode) {
return -1;
}
- if (((*fromX = xSqr) < 0) ||
- ((*fromY = ySqr) < 0)) {
- *fromX = *fromY = -1;
+ if (((*xx = xSqr) < 0) ||
+ ((*yy = ySqr) < 0)) {
+ *xx = *yy = -1;
return -1;
}
- if (flipView)
- *fromX = BOARD_WIDTH - 1 - *fromX;
- else
- *fromY = BOARD_HEIGHT - 1 - *fromY;
+
+ fromX = *xx; fromY = *yy;
+ if(whichMenu == 0) { PiecePopUp(x, y); return -1; } // suppress EditPosition menu
return whichMenu;
}
SetGameInfo();
}
-
void
EditPositionEvent()
{
SetGameInfo();
if (currentMove > 0)
CopyBoard(boards[0], boards[currentMove]);
-
+ { int i, r, f; // [HGM] editrights: take note of existing rights
+ for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) rightsBoard[r][f] = 0;
+ for(i=0; i<nrCastlingRights; i++) {
+ if(boards[0][CASTLING][i] != NoRights)
+ rightsBoard [castlingRank[i]] [boards[0][CASTLING][i]] = 1 + (i == 2 || i == 5);
+ }
+ }
+
blackPlaysFirst = !WhiteOnMove(currentMove);
ResetClocks();
currentMove = forwardMostMove = backwardMostMove = 0;
startedFromSetupPosition = TRUE;
InitChessProgram(&first, FALSE);
if(fakeRights) { // [HGM] suppress this if we just pasted a FEN.
+ int i, r, f, kf, err;
+ for(i=0; i<nrCastlingRights; i++) boards[0][CASTLING][i] = NoRights;
+ kf = NoRights; err = 0;
+ for(f=BOARD_RGHT-1; f>=0; f--)
+ if(rightsBoard[0][f] == 2) { if(kf != NoRights) err=10; boards[0][CASTLING][2] = kf = f; }
+ if(kf == NoRights) kf = 4;
+ for(f=BOARD_RGHT-1; f>=0; f--)
+ if(rightsBoard[0][f] == 1) { err++; boards[0][CASTLING][f<kf] = f; }
+ kf = NoRights; err = 0;
+ for(f=BOARD_RGHT-1; f>=0; f--)
+ if(rightsBoard[BOARD_HEIGHT-1][f] == 2) { if(kf != NoRights) err=10; boards[0][CASTLING][5] = kf = f; }
+ if(kf == NoRights) kf = 4;
+ for(f=BOARD_RGHT-1; f>=0; f--)
+ if(rightsBoard[BOARD_HEIGHT-1][f] == 1) { err++; boards[0][CASTLING][3+(f<kf)] = f; }
+ if(err + 2 > nrCastlingRights) DisplayError("unclear castling rights", 0);
+
boards[0][EP_STATUS] = EP_NONE;
+#if 0
boards[0][CASTLING][2] = boards[0][CASTLING][5] = BOARD_WIDTH>>1;
if(boards[0][0][BOARD_WIDTH>>1] == king) {
boards[0][CASTLING][1] = boards[0][0][BOARD_LEFT] == WhiteRook ? 0 : NoRights;
boards[0][CASTLING][4] = boards[0][BOARD_HEIGHT-1][BOARD_LEFT] == BlackRook ? 0 : NoRights;
boards[0][CASTLING][3] = boards[0][BOARD_HEIGHT-1][BOARD_RGHT-1] == BlackRook ? BOARD_RGHT-1 : NoRights;
} else boards[0][CASTLING][5] = NoRights;
+#endif
}
SendToProgram("force\n", &first);
if (blackPlaysFirst) {
{
char buf[MSG_SIZ];
ChessSquare piece = boards[0][y][x];
+ int rights = 0; // [HGM] editrights: most new pieces get no castling rights
if (gameMode != EditPosition && gameMode != IcsExamining) return;
}
} else {
boards[0][y][x] = p;
+ rightsBoard[y][x] = 0; // [HGM] editrights: clear all castling rights
}
}
}
SetBlackToPlayEvent();
break;
+ case NoRights:
+ rightsBoard[y][x] = 0;
+ break;
+
+ case GrantRights:
+ { ChessSquare p = boards[0][y][x];
+ rightsBoard[y][x] = 1;
+ if(p == WhiteKing || p == WhiteUnicorn || p == BlackKing || p == BlackUnicorn)
+ rightsBoard[y][x] = 2;
+ }
+ break;
+
case EmptySquare:
if (gameMode == IcsExamining) {
if (x < BOARD_LEFT || x >= BOARD_RGHT) break; // [HGM] holdings
selection = (ChessSquare)((int)selection - (int)WhiteQueen + (int)WhiteFerz);
goto defaultlabel;
+ case WhiteRook: // [HGM] editrights: corner Rooks get castling rights by default
+ if(y == 0 && (x == BOARD_LEFT || x == BOARD_RGHT-1)) rights = 1;
+ goto defaultlabel;
+
+ case BlackRook:
+ if(y == BOARD_HEIGHT-1 && (x == BOARD_LEFT || x == BOARD_RGHT-1)) rights = 1;
+ goto defaultlabel;
+
case WhiteKing:
case BlackKing:
if(gameInfo.variant == VariantXiangqi)
selection = (ChessSquare)((int)selection - (int)WhiteKing + (int)WhiteWazir);
if(gameInfo.variant == VariantKnightmate)
selection = (ChessSquare)((int)selection - (int)WhiteKing + (int)WhiteUnicorn);
+ case WhiteUnicorn:
+ case BlackUnicorn:
+ if(y == (selection <= WhiteKing ? 0 : BOARD_HEIGHT-1) && (x == BOARD_WIDTH>>1))
+ rights = 2; // [HGM] editrights: King on right-center file gets rights
default:
defaultlabel:
if (gameMode == IcsExamining) {
}
} else
boards[0][y][x] = selection;
+ rightsBoard[y][x] = rights; // [HGM] editrights: set default rights of created piece
DrawPosition(TRUE, boards[0]);
}
break;