X-Git-Url: http://winboard.nl/cgi-bin?p=xboard.git;a=blobdiff_plain;f=board.c;h=a0ce36e003b70adabd801e25da9e1e1147f83fab;hp=dd0e7abaa5ea53f6ef74f6b1a56f4293d457a2cd;hb=HEAD;hpb=b9c6b5e9fcd6321336ec28f25833530db79b928d diff --git a/board.c b/board.c index dd0e7ab..a0ce36e 100644 --- a/board.c +++ b/board.c @@ -5,7 +5,8 @@ * Massachusetts. * * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006, - * 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Free + * Software Foundation, Inc. * * The following terms apply to Digital Equipment Corporation's copyright * interest in XBoard: @@ -96,8 +97,10 @@ extern char *getenv(); #include "common.h" #include "frontend.h" #include "backend.h" +#include "xboard2.h" #include "moves.h" #include "board.h" +#include "draw.h" #ifdef __EMX__ @@ -108,7 +111,7 @@ extern char *getenv(); #endif -int squareSize, lineGap, hOffset; +int squareSize, lineGap; int damage[2][BOARD_RANKS][BOARD_FILES]; @@ -118,6 +121,9 @@ int damage[2][BOARD_RANKS][BOARD_FILES]; AnimState anims[NrOfAnims]; static void DrawSquare P((int row, int column, ChessSquare piece, int do_flash)); +static Boolean IsDrawArrowEnabled P((void)); +static void DrawArrowHighlight P((int fromX, int fromY, int toX,int toY)); +static void ArrowDamage P((int s_col, int s_row, int d_col, int d_row)); static void drawHighlight (int file, int rank, int type) @@ -136,7 +142,7 @@ drawHighlight (int file, int rank, int type) (squareSize + lineGap); } - DrawBorder(x,y, type); + DrawBorder(x,y, type, lineGap & 1); // pass whether lineGap is odd } int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1; @@ -144,31 +150,26 @@ int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1; void SetHighlights (int fromX, int fromY, int toX, int toY) -{ - if (hi1X != fromX || hi1Y != fromY) { - if (hi1X >= 0 && hi1Y >= 0) { - drawHighlight(hi1X, hi1Y, 0); - } - } // [HGM] first erase both, then draw new! +{ // [HGM] schedule old for erasure, and leave drawing new to DrawPosition + int change = 0; - if (hi2X != toX || hi2Y != toY) { - if (hi2X >= 0 && hi2Y >= 0) { - drawHighlight(hi2X, hi2Y, 0); - } - } - if (hi1X != fromX || hi1Y != fromY) { - if (fromX >= 0 && fromY >= 0) { - drawHighlight(fromX, fromY, 1); + if (hi1X >= 0 && hi1Y >= 0) { + if (hi1X != fromX || hi1Y != fromY) { + damage[0][hi1Y][hi1X] |= 2; + change |= 1; } + change |= 4; } - if (hi2X != toX || hi2Y != toY) { - if (toX >= 0 && toY >= 0) { - drawHighlight(toX, toY, 1); + + if (hi2X >= 0 && hi2Y >= 0) { + if (hi2X != toX || hi2Y != toY) { + damage[0][hi2Y][hi2X] |= 2; + change |= 2; } + change |= 8; } - if(toX<0) // clearing the highlights must have damaged arrow - DrawArrowHighlight(hi1X, hi1Y, hi2X, hi2Y); // for now, redraw it (should really be cleared!) + if(change > 12 && IsDrawArrowEnabled()) ArrowDamage(hi1X, hi1Y, hi2X, hi2Y); hi1X = fromX; hi1Y = fromY; @@ -188,18 +189,12 @@ SetPremoveHighlights (int fromX, int fromY, int toX, int toY) { if (pm1X != fromX || pm1Y != fromY) { if (pm1X >= 0 && pm1Y >= 0) { - drawHighlight(pm1X, pm1Y, 0); - } - if (fromX >= 0 && fromY >= 0) { - drawHighlight(fromX, fromY, 2); + damage[0][pm1Y][pm1X] |= 2; } } if (pm2X != toX || pm2Y != toY) { if (pm2X >= 0 && pm2Y >= 0) { - drawHighlight(pm2X, pm2Y, 0); - } - if (toX >= 0 && toY >= 0) { - drawHighlight(toX, toY, 2); + damage[0][pm2Y][pm2X] |= 2; } } pm1X = fromX; @@ -468,12 +463,12 @@ AnimationFrame (AnimNr anr, Pnt *frame, ChessSquare piece) MyRectangle updates[4]; MyRectangle overlap; Pnt pt; - int count, i; AnimState *anim = &anims[anr]; + int count, i, x, y, w, h; /* Save what we are about to draw into the new buffer */ CopyRectangle(anr, DISP, 0, - frame->x, frame->y, squareSize, squareSize, + x = frame->x, y = frame->y, w = squareSize, h = squareSize, 0, 0); /* Erase bits of the previous frame */ @@ -492,11 +487,17 @@ AnimationFrame (AnimNr anr, Pnt *frame, ChessSquare piece) updates[i].y - anim->prevFrame.y, updates[i].width, updates[i].height, updates[i].x, updates[i].y); + /* [HGM] correct expose rectangle to encompass both overlapping squares */ + if(x > anim->prevFrame.x) w += x - anim->prevFrame.x, x = anim->prevFrame.x; + else w += anim->prevFrame.x - x; + if(y > anim->prevFrame.y) h += y - anim->prevFrame.y, y = anim->prevFrame.y; + else h += anim->prevFrame.y - y; } else { /* Easy when no overlap */ CopyRectangle(anr, 2, DISP, 0, 0, squareSize, squareSize, anim->prevFrame.x, anim->prevFrame.y); + GraphExpose(currBoard, anim->prevFrame.x, anim->prevFrame.y, squareSize, squareSize); } /* Save this frame for next time round */ @@ -511,6 +512,7 @@ AnimationFrame (AnimNr anr, Pnt *frame, ChessSquare piece) CopyRectangle(anr, 0, DISP, 0, 0, squareSize, squareSize, frame->x, frame->y); + GraphExpose(currBoard, x, y, w, h); } static void @@ -572,6 +574,7 @@ AnimateAtomicCapture (Board board, int fromX, int fromY, int toX, int toY) FrameDelay(appData.animSpeed); } board[fromY][toY] = piece; + DrawGrid(); } /* Main control logic for deciding what to animate and how */ @@ -580,23 +583,32 @@ void AnimateMove (Board board, int fromX, int fromY, int toX, int toY) { ChessSquare piece; - int hop; + int hop, x = toX, y = toY, x2 = kill2X; Pnt start, finish, mid; Pnt frames[kFactor * 2 + 1]; int nFrames, startColor, endColor; + if(killX >= 0 && IS_LION(board[fromY][fromX])) Roar(); + /* Are we animating? */ if (!appData.animate || appData.blindfold) return; if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing || - board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing) + board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing || + board[toY][toX] == WhiteKing && board[fromY][fromX] == WhiteRook || // [HGM] seirawan + board[toY][toX] == BlackKing && board[fromY][fromX] == BlackRook) return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return; piece = board[fromY][fromX]; if (piece >= EmptySquare) return; + if(x2 >= 0) toX = kill2X, toY = kill2Y; else + if(killX >= 0) toX = killX, toY = killY; // [HGM] lion: first to kill square + +again: + #if DONT_HOP hop = FALSE; #else @@ -629,11 +641,14 @@ AnimateMove (Board board, int fromX, int fromY, int toX, int toY) if(Explode(board, fromX, fromY, toX, toY)) { // mark as damaged int i,j; for(i=0; i= BOARD_LEFT && column < BOARD_RGHT) { - string[0] = 'a' + column - BOARD_LEFT; + bString[0] = 'a' + column - BOARD_LEFT; align = 1; // coord in lower-right corner } if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) { - string[0] = ONE + row; + snprintf(tString, 3, "%d", ONE - '0' + row); align = 2; // coord in upper-left corner } if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) { - string[0] = '0' + piece; + snprintf(tString, 3, "%d", piece); align = 3; // holdings count in upper-right corner } if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) { - string[0] = '0' + piece; + snprintf(tString, 3, "%d", piece); align = 4; // holdings count in upper-left corner } + if(piece == DarkSquare) square_color = 2; if(square_color == 2 || appData.blindfold) piece = EmptySquare; if (do_flash && piece != EmptySquare && appData.flashCount > 0) { for (i=0; i 0) - DrawGrid(twoBoards & partnerUp); + DrawGrid(); for (i = 0; i < BOARD_HEIGHT; i++) for (j = 0; j < BOARD_WIDTH; j++) { DrawSquare(i, j, board[i][j], 0); damage[nr][i][j] = False; } + + exposeAll = True; } CopyBoard(lastBoard[nr], board); lastBoardValid[nr] = 1; if(nr == 0) { // [HGM] dual: no highlights on second board yet lastFlipView = flipView; + for (i = 0; i < BOARD_HEIGHT; i++) + for (j = 0; j < BOARD_WIDTH; j++) + lastMarker[i][j] = marker[i][j]; /* Draw highlights */ if (pm1X >= 0 && pm1Y >= 0) { drawHighlight(pm1X, pm1Y, 2); + if(lineGap) damage[nr][pm1Y][pm1X] |= 2; } if (pm2X >= 0 && pm2Y >= 0) { drawHighlight(pm2X, pm2Y, 2); + if(lineGap) damage[nr][pm2Y][pm2X] |= 2; } if (hi1X >= 0 && hi1Y >= 0) { drawHighlight(hi1X, hi1Y, 1); + if(lineGap) damage[nr][hi1Y][hi1X] |= 2; } if (hi2X >= 0 && hi2Y >= 0) { drawHighlight(hi2X, hi2Y, 1); + if(lineGap) damage[nr][hi2Y][hi2X] |= 2; } DrawArrowHighlight(hi1X, hi1Y, hi2X, hi2Y); } + else DrawArrowHighlight (board[EP_STATUS-3], board[EP_STATUS-4], board[EP_STATUS-1], board[EP_STATUS-2]); + /* If piece being dragged around board, must redraw that too */ DrawDragPiece(); + if(exposeAll) + GraphExpose(currBoard, 0, 0, BOARD_WIDTH*(squareSize + lineGap) + lineGap, BOARD_HEIGHT*(squareSize + lineGap) + lineGap); + else { + for (i = 0; i < BOARD_HEIGHT; i++) + for (j = 0; j < BOARD_WIDTH; j++) + if(damage[nr][i][j]) { + if(damage[nr][i][j] & 2) // damage by old or new arrow + SquareExpose(i, j, lineGap); + else + SquareExpose(i, j, 0); + if(nr == 0) damage[nr][i][j] = 0; // on auxiliary board we retain arrow damage + } + } + FlashDelay(0); // this flushes drawing queue; + if(nr) SwitchWindow(1); + else { + TimeMark now; + GetTimeMark(&now); + if(repaint && SubtractTimeMarks(&now, &programStartTime) < 1000) { + char *p = appData.message, *q; + i = 0; + while(*p) { + q = strchr(p, '\n'); + if(q) *q = NULLCHAR; + if(!strstr(appData.suppress, p)) { + if(i == 0) DrawSeekBackground(2*squareSize, 3*squareSize, 6.5*squareSize, 5*squareSize); + DrawText(p, 2*squareSize + 5, (int) ((3 + 0.3*i++)*squareSize) + 5, 2); + } + if(q) *q++ = '\n'; else q = ""; + p = q; + } + GraphExpose(currBoard, 2*squareSize, 3*squareSize, 4*squareSize, 2*squareSize); + messedUp = TRUE; + } else messedUp = FALSE; + } } /* [AS] Arrow highlighting support */ @@ -1009,7 +1103,7 @@ SquareToPos (int rank, int file, int *x, int *y) } /* Draw an arrow between two points using current settings */ -void +static void DrawArrowBetweenPoints (int s_x, int s_y, int d_x, int d_y) { Pnt arrow[8]; @@ -1112,25 +1206,32 @@ DrawArrowBetweenPoints (int s_x, int s_y, int d_x, int d_y) // Polygon( hdc, arrow, 7 ); } -void +static void ArrowDamage (int s_col, int s_row, int d_col, int d_row) { - int hor, vert, i; - hor = 64*s_col + 32; vert = 64*s_row + 32; + int hor, vert, i, n = partnerUp * twoBoards, delta = abs(d_row - s_row); + + if( 2*(d_row - s_row) > abs(d_col - s_col) ) d_row = 4*d_row + 1; else + if( 2*(s_row - d_row) > abs(d_col - s_col) ) d_row = 4*d_row + 3; else d_row = 4*d_row + 2; + if( 2*(d_col - s_col) > delta ) d_col = 4*d_col + 1; else + if( 2*(s_col - d_col) > delta ) d_col = 4*d_col + 3; else d_col = 4*d_col + 2; + s_row = 4*s_row + 2; s_col = 4*s_col + 2; + + hor = 64*s_col; vert = 64*s_row; for(i=0; i<= 64; i++) { - damage[0][vert+6>>6][hor+6>>6] = True; - damage[0][vert-6>>6][hor+6>>6] = True; - damage[0][vert+6>>6][hor-6>>6] = True; - damage[0][vert-6>>6][hor-6>>6] = True; + damage[n][vert+30>>8][hor+30>>8] |= 2; + damage[n][vert-30>>8][hor+30>>8] |= 2; + damage[n][vert+30>>8][hor-30>>8] |= 2; + damage[n][vert-30>>8][hor-30>>8] |= 2; hor += d_col - s_col; vert += d_row - s_row; } } /* [AS] Draw an arrow between two squares */ -void +static void DrawArrowBetweenSquares (int s_col, int s_row, int d_col, int d_row) { - int s_x, s_y, d_x, d_y; + int s_x, s_y, d_x, d_y, delta_y; if( s_col == d_col && s_row == d_row ) { return; @@ -1139,21 +1240,22 @@ DrawArrowBetweenSquares (int s_col, int s_row, int d_col, int d_row) /* Get source and destination points */ SquareToPos( s_row, s_col, &s_x, &s_y); SquareToPos( d_row, d_col, &d_x, &d_y); + delta_y = abs(d_y - s_y); - if( d_y > s_y ) { + if( d_y > s_y && 2*(d_y - s_y) > abs(d_x - s_x)) { d_y += squareSize / 2 - squareSize / 4; // [HGM] round towards same centers on all sides! } - else if( d_y < s_y ) { + else if( d_y < s_y && 2*(s_y - d_y) > abs(d_x - s_x)) { d_y += squareSize / 2 + squareSize / 4; } else { d_y += squareSize / 2; } - if( d_x > s_x ) { + if( d_x > s_x && 2*(d_x - s_x) > delta_y) { d_x += squareSize / 2 - squareSize / 4; } - else if( d_x < s_x ) { + else if( d_x < s_x && 2*(s_x - d_x) > delta_y) { d_x += squareSize / 2 + squareSize / 4; } else { @@ -1170,17 +1272,15 @@ DrawArrowBetweenSquares (int s_col, int s_row, int d_col, int d_row) ArrowDamage(s_col, s_row, d_col, d_row); } -Boolean +static Boolean IsDrawArrowEnabled () { - return appData.highlightMoveWithArrow && squareSize >= 32; + return (appData.highlightMoveWithArrow || twoBoards && partnerUp) && squareSize >= 32; } -void +static void DrawArrowHighlight (int fromX, int fromY, int toX,int toY) { if( IsDrawArrowEnabled() && fromX >= 0 && fromY >= 0 && toX >= 0 && toY >= 0) DrawArrowBetweenSquares(fromX, fromY, toX, toY); } - -