void CreateGCs P((void));
void CreateXIMPieces P((void));
void CreateXPMPieces P((void));
+void CreateXPMBoard P((char *s, int n));
void CreatePieces P((void));
void CreatePieceMenus P((void));
Widget CreateMenuBar P((Menu *mb));
Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
-int useImages, useImageSqs;
+Pixmap xpmBoardBitmap[2];
+int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
\"Send to second chess program:\",,2) \n";
char boardTranslations[] =
- "<Btn1Down>: HandleUserMove() \n \
- <Btn1Up>: HandleUserMove() \n \
+ "<Btn1Down>: HandleUserMove(0) \n \
+ Shift<Btn1Up>: HandleUserMove(1) \n \
+ <Btn1Up>: HandleUserMove(0) \n \
<Btn1Motion>: AnimateUserMove() \n \
<Btn3Motion>: HandlePV() \n \
<Btn3Up>: PieceMenuPopup(menuB) \n \
fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
}
}
+ if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
/* [HR] height treated separately (hacked) */
boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
CreatePieces();
} else {
CreateXPMPieces();
+ CreateXPMBoard(appData.liteBackTextureFile, 1);
+ CreateXPMBoard(appData.darkBackTextureFile, 0);
}
#else
CreateXIMPieces();
}
#if HAVE_LIBXPM
+void CreateXPMBoard(char *s, int kind)
+{
+ XpmAttributes attr;
+ attr.valuemask = 0;
+ if(s == NULL || *s == 0 || *s == '*') return;
+ if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
+ useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
+ }
+}
+
void CreateXPMPieces()
{
int piece, kind, r;
SetPremoveHighlights(-1, -1, -1, -1);
}
-static void BlankSquare(x, y, color, piece, dest)
- int x, y, color;
+static int CutOutSquare(x, y, x0, y0, kind)
+ int x, y, *x0, *y0, kind;
+{
+ int W = BOARD_WIDTH, H = BOARD_HEIGHT;
+ int nx = x/(squareSize + lineGap), ny = y/(squareSize + lineGap);
+ *x0 = 0; *y0 = 0;
+ if(textureW[kind] < squareSize || textureH[kind] < squareSize) return 0;
+ if(textureW[kind] < W*squareSize)
+ *x0 = (textureW[kind] - squareSize) * nx/(W-1);
+ else
+ *x0 = textureW[kind]*nx / W + (textureW[kind] - W*squareSize) / (2*W);
+ if(textureH[kind] < H*squareSize)
+ *y0 = (textureH[kind] - squareSize) * ny/(H-1);
+ else
+ *y0 = textureH[kind]*ny / H + (textureH[kind] - H*squareSize) / (2*H);
+ return 1;
+}
+
+static void BlankSquare(x, y, color, piece, dest, fac)
+ int x, y, color, fac;
ChessSquare piece;
Drawable dest;
-{
+{ // [HGM] extra param 'fac' for forcing destination to (0,0) for copying to animation buffer
+ int x0, y0;
+ if (useImages && color != 2 && (useTexture & color+1) && CutOutSquare(x, y, &x0, &y0, color)) {
+ XCopyArea(xDisplay, xpmBoardBitmap[color], dest, wlPieceGC, x0, y0,
+ squareSize, squareSize, x*fac, y*fac);
+ } else
if (useImages && useImageSqs) {
Pixmap pm;
switch (color) {
break;
}
XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
- squareSize, squareSize, x, y);
+ squareSize, squareSize, x*fac, y*fac);
} else {
GC gc;
switch (color) {
gc = jailSquareGC;
break;
}
- XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
+ XFillRectangle(xDisplay, dest, gc, x*fac, y*fac, squareSize, squareSize);
}
}
int square_color, x, y;
Drawable dest;
{
- int kind;
+ int kind, p = piece;
switch (square_color) {
case 1: /* light */
break;
}
if(appData.upsideDown && flipView) kind ^= 2; // swap white and black pieces
+ if(useTexture & square_color+1) {
+ BlankSquare(x, y, square_color, piece, dest, 1); // erase previous contents with background
+ XSetClipMask(xDisplay, wlPieceGC, xpmMask[p]);
+ XSetClipOrigin(xDisplay, wlPieceGC, x, y);
+ XCopyArea(xDisplay, xpmPieceBitmap[kind][piece], dest, wlPieceGC, 0, 0, squareSize, squareSize, x, y);
+ XSetClipMask(xDisplay, wlPieceGC, None);
+ XSetClipOrigin(xDisplay, wlPieceGC, 0, 0);
+ } else
XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
dest, wlPieceGC, 0, 0,
squareSize, squareSize, x, y);
column == BOARD_LEFT-1 || column == BOARD_RGHT
|| (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
|| (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
- BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
+ BlankSquare(x, y, 2, EmptySquare, xBoardWindow, 1);
// [HGM] print piece counts next to holdings
string[1] = NULLCHAR;
}
} else {
if (piece == EmptySquare || appData.blindfold) {
- BlankSquare(x, y, square_color, piece, xBoardWindow);
+ BlankSquare(x, y, square_color, piece, xBoardWindow, 1);
} else {
drawfunc = ChooseDrawFunc();
if (do_flash && appData.flashCount > 0) {
XSync(xDisplay, False);
do_flash_delay(flash_delay);
- BlankSquare(x, y, square_color, piece, xBoardWindow);
+ BlankSquare(x, y, square_color, piece, xBoardWindow, 1);
XSync(xDisplay, False);
do_flash_delay(flash_delay);
}
Cardinal *nprms;
{
if (w != boardWidget || errorExitStatus != -1) return;
+ if(nprms) shiftKey = !strcmp(prms[0], "1");
if (promotionUp) {
if (event->type == ButtonPress) {
} else if (strcmp(name, _("Knight")) == 0) {
promoChar = 'n';
} else if (strcmp(name, _("Promote")) == 0) {
- promoChar = '+';
+ promoChar = '^';
} else if (strcmp(name, _("Defer")) == 0) {
promoChar = '=';
} else {
Pixmap mask;
/* The old buffer is initialised with the start square (empty) */
- BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
+ BlankSquare(start->x, start->y, startColor, EmptySquare, anim->saveBuf, 0);
anim->prevFrame = *start;
/* The piece will be drawn using its own bitmap as a matte */
EndAnimation(anim, finish);
}
+void
+AnimateAtomicCapture(Board board, int fromX, int fromY, int toX, int toY)
+{
+ int i, x, y;
+ ChessSquare piece = board[fromY][toY];
+ board[fromY][toY] = EmptySquare;
+ DrawPosition(FALSE, board);
+ if (flipView) {
+ x = lineGap + ((BOARD_WIDTH-1)-toX) * (squareSize + lineGap);
+ y = lineGap + toY * (squareSize + lineGap);
+ } else {
+ x = lineGap + toX * (squareSize + lineGap);
+ y = lineGap + ((BOARD_HEIGHT-1)-toY) * (squareSize + lineGap);
+ }
+ for(i=1; i<4*kFactor; i++) {
+ int r = squareSize * 9 * i/(20*kFactor - 5);
+ XFillArc(xDisplay, xBoardWindow, highlineGC,
+ x + squareSize/2 - r, y+squareSize/2 - r, 2*r, 2*r, 0, 64*360);
+ FrameDelay(appData.animSpeed);
+ }
+ board[fromY][toY] = piece;
+}
+
/* Main control logic for deciding what to animate and how */
void
#if DONT_HOP
hop = FALSE;
#else
- hop = (piece == WhiteKnight || piece == BlackKnight);
+ hop = abs(fromX-toX) == 1 && abs(fromY-toY) == 2 || abs(fromX-toX) == 2 && abs(fromY-toY) == 1;
#endif
if (appData.debugMode) {
ScreenSquare(toX, toY, &finish, &endColor);
if (hop) {
- /* Knight: make diagonal movement then straight */
+ /* Knight: make straight movement then diagonal */
if (abs(toY - fromY) < abs(toX - fromX)) {
mid.x = start.x + (finish.x - start.x) / 2;
- mid.y = finish.y;
+ mid.y = start.y;
} else {
- mid.x = finish.x;
+ mid.x = start.x;
mid.y = start.y + (finish.y - start.y) / 2;
}
} else {
else
Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
+ if(Explode(board, fromX, fromY, toX, toY)) { // mark as damaged
+ int i,j;
+ for(i=0; i<BOARD_WIDTH; i++) for(j=0; j<BOARD_HEIGHT; j++)
+ if((i-toX)*(i-toX) + (j-toY)*(j-toY) < 6) damage[0][j][i] = True;
+ }
/* Be sure end square is redrawn */
damage[0][toY][toX] = True;
it's being dragged around the board. So we erase the square
that the piece is on and draw it at the last known drag point. */
BlankSquare(player.startSquare.x, player.startSquare.y,
- player.startColor, EmptySquare, xBoardWindow);
+ player.startColor, EmptySquare, xBoardWindow, 1);
AnimationFrame(&player, &player.prevFrame, player.dragPiece);
damage[0][player.startBoardY][player.startBoardX] = TRUE;
}