2 * JAWS.c -- Code for Windows front end to XBoard to use it with JAWS
\r
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
\r
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
\r
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
\r
10 * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,
\r
11 * which was written and is copyrighted by Wayne Christopher.
\r
13 * The following terms apply to Digital Equipment Corporation's copyright
\r
14 * interest in XBoard:
\r
15 * ------------------------------------------------------------------------
\r
16 * All Rights Reserved
\r
18 * Permission to use, copy, modify, and distribute this software and its
\r
19 * documentation for any purpose and without fee is hereby granted,
\r
20 * provided that the above copyright notice appear in all copies and that
\r
21 * both that copyright notice and this permission notice appear in
\r
22 * supporting documentation, and that the name of Digital not be
\r
23 * used in advertising or publicity pertaining to distribution of the
\r
24 * software without specific, written prior permission.
\r
26 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
\r
27 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
\r
28 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
\r
29 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
\r
30 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
\r
31 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
\r
33 * ------------------------------------------------------------------------
\r
35 * The following terms apply to the enhanced version of XBoard
\r
36 * distributed by the Free Software Foundation:
\r
37 * ------------------------------------------------------------------------
\r
39 * GNU XBoard is free software: you can redistribute it and/or modify
\r
40 * it under the terms of the GNU General Public License as published by
\r
41 * the Free Software Foundation, either version 3 of the License, or (at
\r
42 * your option) any later version.
\r
44 * GNU XBoard is distributed in the hope that it will be useful, but
\r
45 * WITHOUT ANY WARRANTY; without even the implied warranty of
\r
46 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
47 * General Public License for more details.
\r
49 * You should have received a copy of the GNU General Public License
\r
50 * along with this program. If not, see http://www.gnu.org/licenses/. *
\r
52 *------------------------------------------------------------------------
\r
53 ** See the file ChangeLog for a revision history. */
\r
55 // This file collects all patches for the JAWS version, so they can all be included in winboard.c
\r
56 // in one big swoop. At the bottom of this file you can read instructions for how to patch
\r
57 // WinBoard to work with JAWS with the aid of this file. Note that the code in this file
\r
58 // is for WinBoard 4.3 and later; for older WB versions you would have to throw out the
\r
59 // piece names for all pieces from Guard to Unicorn, #define ONE as '1', AAA as 'a',
\r
60 // BOARD_LEFT as 0, BOARD_RGHT and BOARD_HEIGHT as 8, and set holdingssizes to 0.
\r
61 // You will need to build with jaws.rc in stead of winboard.rc.
\r
65 #define IDM_PossibleAttackMove 1800
\r
66 #define IDM_PossibleAttacked 1801
\r
67 #define IDM_SayMachineMove 1802
\r
68 #define IDM_ReadRow 1803
\r
69 #define IDM_ReadColumn 1804
\r
70 #define IDM_SayCurrentPos 1805
\r
71 #define IDM_SayAllBoard 1806
\r
72 #define IDM_SayUpperDiagnols 1807
\r
73 #define IDM_SayLowerDiagnols 1808
\r
74 #define IDM_SayClockTime 1810
\r
75 #define IDM_SayWhosTurn 1811
\r
76 #define IDM_SayKnightMoves 1812
\r
77 #define ID_SHITTY_HI 1813
\r
78 #define IDM_SayWhitePieces 1816
\r
79 #define IDM_SayBlackPieces 1817
\r
82 // from common.h, but 'extern' added to it, so the actual declaraton can remain in backend.c
\r
84 extern long whiteTimeRemaining, blackTimeRemaining, timeControl, timeIncrement;
\r
87 // from moves.h, but no longer needed, as the new routines are all moved to winboard.c
\r
89 extern char* PieceToName P((ChessSquare p, int i));
\r
90 extern char* SquareToChar P((int Xpos));
\r
91 extern char* SquareToNum P((int Ypos));
\r
92 extern int CoordToNum P((char c));
\r
96 // from moves.c, added WinBoard_F piece types and ranks / files
\r
98 char *squareToChar[] = { "ay", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l" };
\r
100 char *squareToNum[] = {"naught", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
\r
102 char *ordinals[] = {"zeroth", "first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "nineth"};
\r
104 char *pieceToName[] = {
\r
105 "White Pawn", "White Knight", "White Bishop", "White Rook", "White Queen",
\r
106 "White Guard", "White Elephant", "White Arch Bishop", "White Chancellor",
\r
107 "White General", "White Man", "White Cannon", "White Night Rider",
\r
108 "White Crowned Bishop", "White Crowned Rook", "White Grass Hopper", "White Veteran",
\r
109 "White Falcon", "White Amazon", "White Snake", "White Unicorn",
\r
111 "Black Pawn", "Black Knight", "Black Bishop", "Black Rook", "Black Queen",
\r
112 "Black Guard", "Black Elephant", "Black Arch Bishop", "Black Chancellor",
\r
113 "Black General", "Black Man", "Black Cannon", "Black Night Rider",
\r
114 "Black Crowned Bishop", "Black Crowned Rook", "Black Grass Hopper", "Black Veteran",
\r
115 "Black Falcon", "Black Amazon", "Black Snake", "Black Unicorn",
\r
123 if(isdigit(c)) return c - ONE;
\r
124 if(c >= 'a') return c - AAA;
\r
128 char* PieceToName(p, i)
\r
132 if(i) return pieceToName[(int) p];
\r
133 return pieceToName[(int) p]+6;
\r
136 char* SquareToChar(x)
\r
139 return squareToChar[x - BOARD_LEFT];
\r
142 char* SquareToNum(y)
\r
145 return squareToNum[y + (gameInfo.boardHeight < 10)];
\r
149 // from winboard.c: all new routines
\r
150 #define JFWAPI __declspec(dllimport)
\r
151 JFWAPI BOOL WINAPI JFWSayString (LPCTSTR lpszStrinToSpeak, BOOL bInterrupt);
\r
153 typedef JFWAPI BOOL (WINAPI *PSAYSTRING)(LPCTSTR lpszStrinToSpeak, BOOL bInterrupt);
\r
155 PSAYSTRING RealSayString;
\r
157 VOID SayString(char *mess, BOOL flag)
\r
158 { // for debug file
\r
159 char buf[MSG_SIZ], *p;
\r
160 if(appData.debugMode) fprintf(debugFP, "SAY '%s'\n", mess);
\r
162 if(p = StrCaseStr(buf, "Xboard adjudication:")) {
\r
164 for(i=19; i>1; i--) p[i] = p[i-1];
\r
167 RealSayString(buf, flag);
\r
170 //static int fromX = 0, fromY = 0;
\r
171 static int oldFromX, oldFromY;
\r
172 static int timeflag;
\r
173 static int suppressClocks = 0;
\r
174 static int suppressOneKey = 0;
\r
175 static HANDLE hAccelJAWS;
\r
177 typedef struct { char *name; int code; } MenuItemDesc;
\r
179 MenuItemDesc menuItemJAWS[] = {
\r
180 {"Say Clock &Time\tAlt+T", IDM_SayClockTime },
\r
182 {"Say Last &Move\tAlt+M", IDM_SayMachineMove },
\r
183 {"Say W&ho's Turn\tAlt+X", IDM_SayWhosTurn },
\r
185 {"Say Complete &Position\tAlt+P",IDM_SayAllBoard },
\r
186 {"Say &White Pieces\tAlt+W", IDM_SayWhitePieces },
\r
187 {"Say &Black Pieces\tAlt+B", IDM_SayBlackPieces },
\r
188 {"Say Board &Rank\tAlt+R", IDM_ReadRow },
\r
189 {"Say Board &File\tAlt+F", IDM_ReadColumn },
\r
191 {"Say &Upper Diagonals\tAlt+U", IDM_SayUpperDiagnols },
\r
192 {"Say &Lower Diagonals\tAlt+L", IDM_SayLowerDiagnols },
\r
193 {"Say K&night Moves\tAlt+N", IDM_SayKnightMoves },
\r
194 {"Say Current &Square\tAlt+S", IDM_SayCurrentPos },
\r
195 {"Say &Attacks\tAlt+A", IDM_PossibleAttackMove },
\r
196 {"Say Attacke&d\tAlt+D", IDM_PossibleAttacked },
\r
200 ACCEL acceleratorsJAWS[] = {
\r
201 {FVIRTKEY|FALT, 'T', IDM_SayClockTime },
\r
202 {FVIRTKEY|FALT, 'M', IDM_SayMachineMove },
\r
203 {FVIRTKEY|FALT, 'X', IDM_SayWhosTurn },
\r
204 {FVIRTKEY|FALT, 'P', IDM_SayAllBoard },
\r
205 {FVIRTKEY|FALT, 'W', IDM_SayWhitePieces },
\r
206 {FVIRTKEY|FALT, 'B', IDM_SayBlackPieces },
\r
207 {FVIRTKEY|FALT, 'R', IDM_ReadRow },
\r
208 {FVIRTKEY|FALT, 'F', IDM_ReadColumn },
\r
209 {FVIRTKEY|FALT, 'U', IDM_SayUpperDiagnols },
\r
210 {FVIRTKEY|FALT, 'L', IDM_SayLowerDiagnols },
\r
211 {FVIRTKEY|FALT, 'N', IDM_SayKnightMoves },
\r
212 {FVIRTKEY|FALT, 'S', IDM_SayCurrentPos },
\r
213 {FVIRTKEY|FALT, 'A', IDM_PossibleAttackMove },
\r
214 {FVIRTKEY|FALT, 'D', IDM_PossibleAttacked }
\r
220 HMENU menuMain, menuJAWS;
\r
221 MENUBARINFO helpMenuInfo;
\r
224 helpMenuInfo.cbSize = sizeof(helpMenuInfo);
\r
225 menuMain = GetMenu(hwndMain);
\r
226 if(appData.debugMode) fprintf(debugFP, "hwndMain: %8x %8x\n", hwndMain, menuMain);
\r
227 menuJAWS = CreatePopupMenu();
\r
229 for(i=0; menuItemJAWS[i].name; i++) {
\r
230 if(menuItemJAWS[i].name[0] == '-')
\r
231 AppendMenu(menuJAWS, MF_SEPARATOR, (UINT_PTR) 0, NULL);
\r
232 else AppendMenu(menuJAWS, MF_ENABLED|MF_STRING,
\r
233 (UINT_PTR) menuItemJAWS[i].code, (LPCTSTR) menuItemJAWS[i].name);
\r
235 InsertMenu(menuMain, 5, MF_BYPOSITION|MF_POPUP|MF_ENABLED|MF_STRING,
\r
236 (UINT_PTR) menuJAWS, "&JAWS");
\r
237 oldMenuItemState[6] = oldMenuItemState[5];
\r
238 DrawMenuBar(hwndMain);
\r
243 { // to be called at beginning of WinMain, after InitApplication and InitInstance
\r
244 HINSTANCE hApi = LoadLibrary("jfwapi32.dll");
\r
246 DisplayInformation("Missing jfwapi32.dll");
\r
250 RealSayString = (PSAYSTRING)GetProcAddress(hApi, "JFWSayString");
\r
251 if(!RealSayString) {
\r
252 DisplayInformation("SayString returned a null pointer");
\r
257 // [HGM] kludge to reduce need for modification of winboard.c: make tinyLayout menu identical
\r
258 // to standard layout, so that code for switching between them does not have to be deleted
\r
262 menuBarText[0][5] = "&JAWS";
\r
263 for(i=0; i<7; i++) menuBarText[1][i] = menuBarText[0][i];
\r
266 hAccelJAWS = CreateAcceleratorTable(acceleratorsJAWS, 14);
\r
268 /* initialize cursor position */
\r
270 SetHighlights(fromX, fromY, -1, -1);
\r
271 DrawPosition(FALSE, NULL);
\r
272 oldFromX = oldFromY = -1;
\r
274 if(hwndConsole) SetFocus(hwndConsole);
\r
279 KeyboardEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
281 ChessSquare currentPiece;
\r
282 char *piece, *xchar, *ynum ;
\r
285 if(fromX == -1 || fromY == -1) {
\r
286 fromX = BOARD_LEFT; fromY = 0;
\r
290 if(fromX == BOARD_RGHT+1) fromX -= 2; else
\r
291 if(fromX == BOARD_LEFT) { if(fromY >= BOARD_HEIGHT - gameInfo.holdingsSize) fromX -= 2; } else
\r
292 if(fromX > BOARD_LEFT) fromX--;
\r
295 if(fromX == BOARD_LEFT-2) fromX += 2; else
\r
296 if(fromX == BOARD_RGHT-1) { if(fromY < gameInfo.holdingsSize) fromX += 2; } else
\r
297 if(fromX < BOARD_RGHT-1) fromX++;
\r
300 if(fromX == BOARD_RGHT+1) { if(fromY < gameInfo.holdingsSize - 1) fromY++; } else
\r
301 if(fromY < BOARD_HEIGHT-1) fromY++;
\r
304 if(fromX == BOARD_LEFT-2) { if(fromY > BOARD_HEIGHT - gameInfo.holdingsSize) fromY--; } else
\r
305 if(fromY > 0) fromY--;
\r
308 SetHighlights(fromX, fromY, -1, -1);
\r
309 DrawPosition(FALSE, NULL);
\r
310 currentPiece = boards[currentMove][fromY][fromX];
\r
311 piece = PieceToName(currentPiece,1);
\r
312 if(currentPiece != EmptySquare) MessageBeep(currentPiece < (int)BlackPawn ? MB_OK : MB_ICONEXCLAMATION);
\r
313 if(fromX == BOARD_LEFT - 2) {
\r
314 SayString("black holdings", FALSE);
\r
315 if(currentPiece != EmptySquare) {
\r
317 n = boards[currentMove][fromY][1];
\r
318 sprintf(buf, "%d %s%s", n, piece+6, n == 1 ? "" : "s");
\r
319 SayString(buf, TRUE);
\r
322 if(fromX == BOARD_RGHT + 1) {
\r
323 SayString("white holdings", FALSE);
\r
324 if(currentPiece != EmptySquare) {
\r
326 n = boards[currentMove][fromY][BOARD_WIDTH-2];
\r
327 sprintf(buf, "%d %s%s", n, piece+6, n == 1 ? "" : "s");
\r
328 SayString(buf, TRUE);
\r
331 if(fromX >= BOARD_LEFT && fromX < BOARD_RGHT) {
\r
333 xchar = SquareToChar(fromX);
\r
334 ynum = SquareToNum(fromY);
\r
335 if(currentPiece != EmptySquare) {
\r
336 // SayString(piece[0] == 'W' ? "white" : "black", TRUE);
\r
337 sprintf(buf, "%s %s %s", piece, xchar, ynum);
\r
338 } else sprintf(buf, "%s %s", xchar, ynum);
\r
339 SayString(buf, TRUE);
\r
344 extern char castlingRights[MAX_MOVES][BOARD_SIZE];
\r
345 int PosFlags(int nr);
\r
348 int rf, ff, rt, ft;
\r
353 extern void ReadCallback P((Board board, int flags, ChessMove kind,
\r
354 int rf, int ff, int rt, int ft,
\r
355 VOIDSTAR closure));
\r
357 void ReadCallback(board, flags, kind, rf, ff, rt, ft, closure)
\r
361 int rf, ff, rt, ft;
\r
364 register ReadClosure *cl = (ReadClosure *) closure;
\r
365 ChessSquare possiblepiece;
\r
366 char *piece, *xchar, *ynum ;
\r
368 //if(appData.debugMode) fprintf(debugFP, "%c%c%c%c\n", ff+AAA, rf+ONE, ft+AAA, rt+ONE);
\r
369 if(cl->ff == ff && cl->rf == rf) {
\r
370 possiblepiece = board[rt][ft];
\r
371 if(possiblepiece != EmptySquare) {
\r
372 piece = PieceToName(possiblepiece,1);
\r
373 xchar = SquareToChar(ft);
\r
374 ynum = SquareToNum(rt);
\r
375 SayString(xchar , FALSE);
\r
376 SayString(ynum, FALSE);
\r
377 SayString(piece, FALSE);
\r
381 if(cl->ft == ft && cl->rt == rt) {
\r
382 possiblepiece = board[rf][ff];
\r
383 piece = PieceToName(possiblepiece,1);
\r
384 xchar = SquareToChar(ff);
\r
385 ynum = SquareToNum(rf);
\r
386 SayString(xchar , FALSE);
\r
387 SayString(ynum, FALSE);
\r
388 SayString(piece, FALSE);
\r
394 PossibleAttackMove()
\r
397 ChessSquare piece, victim;
\r
398 int removedSelectedPiece = 0, swapColor;
\r
400 //if(appData.debugMode) fprintf(debugFP, "PossibleAttackMove %d %d %d %d\n", fromX, fromY, oldFromX, oldFromY);
\r
401 if(fromY < 0 || fromY >= BOARD_HEIGHT) return;
\r
402 if(fromX < BOARD_LEFT || fromX >= BOARD_RGHT) { SayString("holdings",FALSE); return; }
\r
404 piece = boards[currentMove][fromY][fromX];
\r
405 if(piece == EmptySquare) { // if square is empty, try to substitute selected piece
\r
406 if(oldFromX >= 0 && oldFromY >= 0) {
\r
407 piece = boards[currentMove][oldFromY][oldFromX];
\r
408 boards[currentMove][oldFromY][oldFromX] = EmptySquare;
\r
409 removedSelectedPiece = 1;
\r
410 SayString("Your", FALSE);
\r
411 SayString(PieceToName(piece, 0), FALSE);
\r
412 SayString("would have", FALSE);
\r
413 } else { SayString("You must select a piece first", FALSE); return; }
\r
416 victim = boards[currentMove][fromY][fromX];
\r
417 boards[currentMove][fromY][fromX] = piece; // make sure piece is actally there
\r
418 SayString("possible captures from here are", FALSE);
\r
420 swapColor = piece < (int)BlackPawn && !WhiteOnMove(currentMove) ||
\r
421 piece >= (int)BlackPawn && WhiteOnMove(currentMove);
\r
422 cl.count = 0; cl.rf = fromY; cl.ff = fromX; cl.rt = cl.ft = -1;
\r
423 GenLegal(boards[currentMove], PosFlags(currentMove + swapColor), EP_NONE,
\r
424 castlingRights[currentMove], ReadCallback, (VOIDSTAR) &cl);
\r
425 if(cl.count == 0) SayString("None", FALSE);
\r
426 boards[currentMove][fromY][fromX] = victim; // repair
\r
428 if( removedSelectedPiece ) boards[currentMove][oldFromY][oldFromX] = piece;
\r
436 ChessSquare piece = EmptySquare, victim;
\r
438 if(fromY < 0 || fromY >= BOARD_HEIGHT) return;
\r
439 if(fromX < BOARD_LEFT || fromX >= BOARD_RGHT) { SayString("holdings",FALSE); return; }
\r
441 if(oldFromX >= 0 && oldFromY >= 0) { // if piece is selected, remove it
\r
442 piece = boards[currentMove][oldFromY][oldFromX];
\r
443 boards[currentMove][oldFromY][oldFromX] = EmptySquare;
\r
446 SayString("Pieces that can capture you are", FALSE);
\r
448 victim = boards[currentMove][fromY][fromX]; // put dummy piece on target square, to activate Pawn captures
\r
449 boards[currentMove][fromY][fromX] = WhiteOnMove(currentMove) ? WhiteQueen : BlackQueen;
\r
450 cl.count = 0; cl.rt = fromY; cl.ft = fromX; cl.rf = cl.ff = -1;
\r
451 GenLegal(boards[currentMove], PosFlags(currentMove+1), EP_NONE,
\r
452 castlingRights[currentMove], ReadCallback, (VOIDSTAR) &cl);
\r
453 if(cl.count == 0) SayString("None", FALSE);
\r
455 SayString("You are defended by", FALSE);
\r
457 boards[currentMove][fromY][fromX] = WhiteOnMove(currentMove) ? BlackQueen : WhiteQueen;
\r
458 cl.count = 0; cl.rt = fromY; cl.ft = fromX; cl.rf = cl.ff = -1;
\r
459 GenLegal(boards[currentMove], PosFlags(currentMove), EP_NONE,
\r
460 castlingRights[currentMove], ReadCallback, (VOIDSTAR) &cl);
\r
461 if(cl.count == 0) SayString("None", FALSE);
\r
462 boards[currentMove][fromY][fromX] = victim; // put back original occupant
\r
464 if(oldFromX >= 0 && oldFromY >= 0) { // put back possibl selected piece
\r
465 boards[currentMove][oldFromY][oldFromX] = piece;
\r
472 ChessSquare currentpiece;
\r
473 char *piece, *xchar, *ynum ;
\r
475 ynum = SquareToNum(fromY);
\r
477 if(fromY < 0) return;
\r
479 for (xPos=BOARD_LEFT; xPos<BOARD_RGHT; xPos++) {
\r
480 currentpiece = boards[currentMove][fromY][xPos];
\r
481 if(currentpiece != EmptySquare) {
\r
482 piece = PieceToName(currentpiece,1);
\r
483 xchar = SquareToChar(xPos);
\r
484 SayString(xchar , FALSE);
\r
485 SayString(ynum, FALSE);
\r
486 SayString(piece, FALSE);
\r
491 SayString("rank", FALSE);
\r
492 SayString(ynum, FALSE);
\r
493 SayString("empty", FALSE);
\r
500 ChessSquare currentpiece;
\r
501 char *piece, *xchar, *ynum ;
\r
503 xchar = SquareToChar(fromX);
\r
505 if(fromX < 0) return;
\r
507 for (yPos=0; yPos<BOARD_HEIGHT; yPos++) {
\r
508 currentpiece = boards[currentMove][yPos][fromX];
\r
509 if(currentpiece != EmptySquare) {
\r
510 piece = PieceToName(currentpiece,1);
\r
511 ynum = SquareToNum(yPos);
\r
512 SayString(xchar , FALSE);
\r
513 SayString(ynum, FALSE);
\r
514 SayString(piece, FALSE);
\r
519 SayString(xchar, FALSE);
\r
520 SayString("file empty", FALSE);
\r
527 ChessSquare currentpiece;
\r
528 char *piece, *xchar, *ynum ;
\r
531 if(fromX < 0 || fromY < 0) return;
\r
533 if(fromX < BOARD_RGHT-1 && fromY < BOARD_HEIGHT-1) {
\r
534 SayString("The diagnol squares to your upper right contain", FALSE);
\r
537 while(yPos<BOARD_HEIGHT && xPos<BOARD_RGHT) {
\r
538 currentpiece = boards[currentMove][yPos][xPos];
\r
539 piece = PieceToName(currentpiece,1);
\r
540 xchar = SquareToChar(xPos);
\r
541 ynum = SquareToNum(yPos);
\r
542 SayString(xchar , FALSE);
\r
543 SayString(ynum, FALSE);
\r
544 SayString(piece, FALSE);
\r
549 else SayString("There is no squares to your upper right", FALSE);
\r
551 if(fromX > BOARD_LEFT && fromY < BOARD_HEIGHT-1) {
\r
552 SayString("The diagnol squares to your upper left contain", FALSE);
\r
555 while(yPos<BOARD_HEIGHT && xPos>=BOARD_LEFT) {
\r
556 currentpiece = boards[currentMove][yPos][xPos];
\r
557 piece = PieceToName(currentpiece,1);
\r
558 xchar = SquareToChar(xPos);
\r
559 ynum = SquareToNum(yPos);
\r
560 SayString(xchar , FALSE);
\r
561 SayString(ynum, FALSE);
\r
562 SayString(piece, FALSE);
\r
567 else SayString("There is no squares to your upper left", FALSE);
\r
573 ChessSquare currentpiece;
\r
574 char *piece, *xchar, *ynum ;
\r
577 if(fromX < 0 || fromY < 0) return;
\r
579 if(fromX < BOARD_RGHT-1 && fromY > 0) {
\r
580 SayString("The diagnol squares to your lower right contain", FALSE);
\r
583 while(yPos>=0 && xPos<BOARD_RGHT) {
\r
584 currentpiece = boards[currentMove][yPos][xPos];
\r
585 piece = PieceToName(currentpiece,1);
\r
586 xchar = SquareToChar(xPos);
\r
587 ynum = SquareToNum(yPos);
\r
588 SayString(xchar , FALSE);
\r
589 SayString(ynum, FALSE);
\r
590 SayString(piece, FALSE);
\r
595 else SayString("There is no squares to your lower right", FALSE);
\r
597 if(fromX > BOARD_LEFT && fromY > 0) {
\r
598 SayString("The diagnol squares to your lower left contain", FALSE);
\r
601 while(yPos>=0 && xPos>=BOARD_LEFT) {
\r
602 currentpiece = boards[currentMove][yPos][xPos];
\r
603 piece = PieceToName(currentpiece,1);
\r
604 xchar = SquareToChar(xPos);
\r
605 ynum = SquareToNum(yPos);
\r
606 SayString(xchar , FALSE);
\r
607 SayString(ynum, FALSE);
\r
608 SayString(piece, FALSE);
\r
613 else SayString("There is no squares to your lower left", FALSE);
\r
619 ChessSquare currentpiece, oldpiece;
\r
620 char *piece, *xchar, *ynum ;
\r
622 oldpiece = boards[currentMove][fromY][fromX];
\r
623 if(oldpiece == WhiteKnight || oldpiece == BlackKnight)
\r
624 SayString("The possible squares a Knight could move to are", FALSE);
\r
626 SayString("The squares a Knight could possibly attack from are", FALSE);
\r
628 if (fromY+2 < BOARD_HEIGHT && fromX-1 >= BOARD_LEFT) {
\r
629 currentpiece = boards[currentMove][fromY+2][fromX-1];
\r
630 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
631 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
632 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
634 piece = PieceToName(currentpiece,1);
\r
635 xchar = SquareToChar(fromX-1);
\r
636 ynum = SquareToNum(fromY+2);
\r
637 SayString(xchar , FALSE);
\r
638 SayString(ynum, FALSE);
\r
639 SayString(piece, FALSE);
\r
643 if (fromY+2 < BOARD_HEIGHT && fromX+1 < BOARD_RGHT) {
\r
644 currentpiece = boards[currentMove][fromY+2][fromX+1];
\r
645 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
646 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
647 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
649 piece = PieceToName(currentpiece,1);
\r
650 xchar = SquareToChar(fromX+1);
\r
651 ynum = SquareToNum(fromY+2);
\r
652 SayString(xchar , FALSE);
\r
653 SayString(ynum, FALSE);
\r
654 SayString(piece, FALSE);
\r
658 if (fromY+1 < BOARD_HEIGHT && fromX+2 < BOARD_RGHT) {
\r
659 currentpiece = boards[currentMove][fromY+1][fromX+2];
\r
660 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
661 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
662 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
664 piece = PieceToName(currentpiece,1);
\r
665 xchar = SquareToChar(fromX+2);
\r
666 ynum = SquareToNum(fromY+1);
\r
667 SayString(xchar , FALSE);
\r
668 SayString(ynum, FALSE);
\r
669 SayString(piece, FALSE);
\r
673 if (fromY-1 >= 0 && fromX+2 < BOARD_RGHT) {
\r
674 currentpiece = boards[currentMove][fromY-1][fromX+2];
\r
675 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
676 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
677 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
679 piece = PieceToName(currentpiece,1);
\r
680 xchar = SquareToChar(fromX+2);
\r
681 ynum = SquareToNum(fromY-1);
\r
682 SayString(xchar , FALSE);
\r
683 SayString(ynum, FALSE);
\r
684 SayString(piece, FALSE);
\r
688 if (fromY-2 >= 0 && fromX+1 < BOARD_RGHT) {
\r
689 currentpiece = boards[currentMove][fromY-2][fromX+1];
\r
690 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
691 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
692 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
694 piece = PieceToName(currentpiece,1);
\r
695 xchar = SquareToChar(fromX+1);
\r
696 ynum = SquareToNum(fromY-2);
\r
697 SayString(xchar , FALSE);
\r
698 SayString(ynum, FALSE);
\r
699 SayString(piece, FALSE);
\r
703 if (fromY-2 >= 0 && fromX-1 >= BOARD_LEFT) {
\r
704 currentpiece = boards[currentMove][fromY-2][fromX-1];
\r
705 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
706 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
707 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
709 piece = PieceToName(currentpiece,1);
\r
710 xchar = SquareToChar(fromX-1);
\r
711 ynum = SquareToNum(fromY-2);
\r
712 SayString(xchar , FALSE);
\r
713 SayString(ynum, FALSE);
\r
714 SayString(piece, FALSE);
\r
718 if (fromY-1 >= 0 && fromX-2 >= BOARD_LEFT) {
\r
719 currentpiece = boards[currentMove][fromY-1][fromX-2];
\r
720 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
721 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
722 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
724 piece = PieceToName(currentpiece,1);
\r
725 xchar = SquareToChar(fromX-2);
\r
726 ynum = SquareToNum(fromY-1);
\r
727 SayString(xchar , FALSE);
\r
728 SayString(ynum, FALSE);
\r
729 SayString(piece, FALSE);
\r
733 if (fromY+1 < BOARD_HEIGHT && fromX-2 >= BOARD_LEFT) {
\r
734 currentpiece = boards[currentMove][fromY+1][fromX-2];
\r
735 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
736 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
737 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
739 piece = PieceToName(currentpiece,1);
\r
740 xchar = SquareToChar(fromX-2);
\r
741 ynum = SquareToNum(fromY+1);
\r
742 SayString(xchar , FALSE);
\r
743 SayString(ynum, FALSE);
\r
744 SayString(piece, FALSE);
\r
750 SayPieces(ChessSquare p)
\r
752 ChessSquare currentpiece;
\r
753 char *piece, *xchar, *ynum ;
\r
754 int yPos, xPos, count = 0;
\r
757 if(p == WhitePlay) SayString("White pieces", FALSE); else
\r
758 if(p == BlackPlay) SayString("Black pieces", FALSE); else
\r
759 if(p == EmptySquare) SayString("Pieces", FALSE); else {
\r
760 sprintf(buf, "%ss", PieceToName(p,1));
\r
761 SayString(buf, FALSE);
\r
763 SayString("are located", FALSE);
\r
764 for(yPos=0; yPos<BOARD_HEIGHT; yPos++) {
\r
765 for(xPos=BOARD_LEFT; xPos<BOARD_RGHT; xPos++) {
\r
766 currentpiece = boards[currentMove][yPos][xPos];
\r
767 if(p == BlackPlay && currentpiece >= BlackPawn && currentpiece <= BlackKing ||
\r
768 p == WhitePlay && currentpiece >= WhitePawn && currentpiece <= WhiteKing )
\r
769 piece = PieceToName(currentpiece,0);
\r
770 else if(p == EmptySquare && currentpiece != EmptySquare)
\r
771 piece = PieceToName(currentpiece,1);
\r
772 else if(p == currentpiece)
\r
776 if(count == 0) SayString("at", FALSE);
\r
777 xchar = SquareToChar(xPos);
\r
778 ynum = SquareToNum(yPos);
\r
779 SayString(xchar , FALSE);
\r
780 SayString(ynum, FALSE);
\r
781 if(piece) SayString(piece, FALSE);
\r
785 if(count == 0) SayString("nowhere", FALSE);
\r
791 ChessSquare currentpiece;
\r
792 char *piece, *xchar, *ynum ;
\r
793 if(fromX < BOARD_LEFT) { SayString("You strayed into the white holdings", FALSE); return; }
\r
794 if(fromX >= BOARD_RGHT) { SayString("You strayed into the black holdings", FALSE); return; }
\r
795 currentpiece = boards[currentMove][fromY][fromX];
\r
796 piece = PieceToName(currentpiece,1);
\r
797 ynum = SquareToNum(fromY);
\r
798 xchar = SquareToChar(fromX);
\r
799 SayString("Your current position is", FALSE);
\r
800 SayString(xchar, FALSE);
\r
801 SayString(ynum, FALSE);
\r
802 SayString(piece, FALSE);
\r
803 if(((fromX-BOARD_LEFT) ^ fromY)&1)
\r
804 SayString("on a light square",FALSE);
\r
806 SayString("on a dark square",FALSE);
\r
808 PossibleAttacked();
\r
816 ChessSquare currentpiece;
\r
817 char *piece, *xchar, *ynum ;
\r
819 if(gameInfo.holdingsWidth) {
\r
821 for(Ypos=0; Ypos<gameInfo.holdingsSize; Ypos++) {
\r
822 int n = boards[currentMove][Ypos][BOARD_WIDTH-2];
\r
823 if(n) { char buf[MSG_SIZ];
\r
824 if(!first++) SayString("white holds", FALSE);
\r
825 currentpiece = boards[currentMove][Ypos][BOARD_WIDTH-1];
\r
826 piece = PieceToName(currentpiece,0);
\r
827 sprintf(buf, "%d %s%s", n, piece, (n==1 ? "" : "s") );
\r
828 SayString(buf, FALSE);
\r
832 for(Ypos=BOARD_HEIGHT-1; Ypos>=BOARD_HEIGHT - gameInfo.holdingsSize; Ypos--) {
\r
833 int n = boards[currentMove][Ypos][1];
\r
834 if(n) { char buf[MSG_SIZ];
\r
835 if(!first++) SayString("black holds", FALSE);
\r
836 currentpiece = boards[currentMove][Ypos][0];
\r
837 piece = PieceToName(currentpiece,0);
\r
838 sprintf(buf, "%d %s%s", n, piece, (n==1 ? "" : "s") );
\r
839 SayString(buf, FALSE);
\r
844 for(Ypos=BOARD_HEIGHT-1; Ypos>=0; Ypos--) {
\r
845 ynum = ordinals[Ypos + (gameInfo.boardHeight < 10)];
\r
846 SayString(ynum, FALSE);
\r
847 SayString("rank", FALSE);
\r
848 for(Xpos=BOARD_LEFT; Xpos<BOARD_RGHT; Xpos++) {
\r
849 currentpiece = boards[currentMove][Ypos][Xpos];
\r
850 if(currentpiece != EmptySquare) {
\r
851 int count = 0, oldX = Xpos;
\r
853 piece = PieceToName(currentpiece,1);
\r
854 while(Xpos < BOARD_RGHT && boards[currentMove][Ypos][Xpos] == currentpiece)
\r
857 sprintf(buf, "%d %ss", count, piece);
\r
858 } else sprintf(buf, "%s", piece);
\r
860 SayString(buf, FALSE);
\r
862 int count = 0, oldX = Xpos;
\r
863 while(Xpos < BOARD_RGHT && boards[currentMove][Ypos][Xpos] == EmptySquare)
\r
865 if(Xpos == BOARD_RGHT && oldX == BOARD_LEFT)
\r
866 SayString("all", FALSE);
\r
870 sprintf(buf, "%d", count);
\r
871 SayString(buf, FALSE);
\r
875 SayString("empty", FALSE);
\r
885 if(gameMode == MachinePlaysBlack || gameMode == IcsPlayingBlack) {
\r
886 if(WhiteOnMove(currentMove))
\r
887 SayString("It is your turn", FALSE);
\r
888 else SayString("It is your opponents turn", FALSE);
\r
889 } else if(gameMode == MachinePlaysWhite || gameMode == IcsPlayingWhite) {
\r
890 if(WhiteOnMove(currentMove))
\r
891 SayString("It is your opponents turn", FALSE);
\r
892 else SayString("It is your turn", FALSE);
\r
894 if(WhiteOnMove(currentMove))
\r
895 SayString("White is on move here", FALSE);
\r
896 else SayString("Black is on move here", FALSE);
\r
902 SayMachineMove(int evenIfDuplicate)
\r
904 int len, xPos, yPos, moveNr, secondSpace = 0, castle = 0, n;
\r
905 ChessSquare currentpiece;
\r
906 char *piece, *xchar, *ynum, *p;
\r
907 char c, buf[MSG_SIZ], comment[MSG_SIZ];
\r
908 static char disambiguation[2];
\r
909 static int previousMove = 0;
\r
911 if(appData.debugMode) fprintf(debugFP, "Message = '%s'\n", messageText);
\r
912 if(gameMode == BeginningOfGame) return;
\r
913 if(messageText[0] == '[') return;
\r
915 if(isdigit(messageText[0])) { // message is move, possibly with thinking output
\r
916 int dotCount = 0, spaceCount = 0;
\r
917 sscanf(messageText, "%d", &moveNr);
\r
919 // [HGM] show: better extraction of move
\r
920 while (messageText[len] != NULLCHAR) {
\r
921 if(messageText[len] == '.' && spaceCount == 0) dotCount++;
\r
922 if(messageText[len] == ' ') { if(++spaceCount == 2) secondSpace = len; }
\r
923 if(messageText[len] == '{') { // we detected a comment
\r
924 if(isalpha(messageText[len+1]) ) sscanf(messageText+len, "{%[^}]}", comment);
\r
927 if(messageText[len] == '[') { // we detected thinking output
\r
928 int depth; float score=0; char c, lastMover = (dotCount == 3 ? 'B' : 'W');
\r
929 if(sscanf(messageText+len+1, "%d]%c%f", &depth, &c, &score) > 1) {
\r
930 if(c == ' ') { // if not explicitly specified, figure out source of thinking output
\r
932 case MachinePlaysWhite:
\r
933 case IcsPlayingWhite:
\r
935 case IcsPlayingBlack:
\r
936 case MachinePlaysBlack:
\r
942 if(c != lastMover) return; // line is thinking output of future move, ignore.
\r
943 if(2*moveNr - (dotCount < 2) == previousMove)
\r
944 return; // do not repeat same move; likely ponder output
\r
945 sprintf(buf, "score %s %d at %d ply",
\r
946 score > 0 ? "plus" : score < 0 ? "minus" : "",
\r
947 (int) (fabs(score)*100+0.5),
\r
949 SayString(buf, FALSE); // move + thinking output describing it; say it.
\r
951 while(messageText[len-1] == ' ') len--; // position just behind move;
\r
954 if(messageText[len] == '(') { // ICS time printed behind move
\r
955 while(messageText[len+1] && messageText[len] != ')') len++; // skip it
\r
959 if(secondSpace) len = secondSpace; // position behind move
\r
960 if(messageText[len-1] == '+' || messageText[len-1] == '#') { /* you are in checkmate */
\r
961 len--; // strip off check or mate indicator
\r
963 if(messageText[len-2] == '=') { /* promotion */
\r
964 len-=2; // strip off promotion piece
\r
965 SayString("promotion", FALSE);
\r
968 n = 2*moveNr - (dotCount < 2);
\r
970 if(previousMove != 2*moveNr + (dotCount > 1) || evenIfDuplicate) {
\r
972 previousMove = 2*moveNr + (dotCount > 1); // remember move nr of move last spoken
\r
973 sprintf(number, "%d", moveNr);
\r
975 yPos = CoordToNum(messageText[len-1]); /* turn char coords to ints */
\r
976 xPos = CoordToNum(messageText[len-2]);
\r
977 if(xPos < 0 || xPos > 11) return; // prevent crashes if no coord string available to speak
\r
978 if(yPos < 0 || yPos > 9) return;
\r
979 currentpiece = boards[n][yPos][xPos];
\r
980 piece = PieceToName(currentpiece,0);
\r
981 ynum = SquareToNum(yPos);
\r
982 xchar = SquareToChar(xPos);
\r
983 c = messageText[len-3];
\r
984 if(c == 'x') c = messageText[len-4];
\r
985 if(!isdigit(c) && c < 'a' && c != '@') c = 0;
\r
986 disambiguation[0] = c;
\r
987 SayString(WhiteOnMove(n) ? "Black" : "White", FALSE);
\r
988 SayString("move", FALSE);
\r
989 SayString(number, FALSE);
\r
990 // if(c==0 || c=='@') SayString("a", FALSE);
\r
991 // intercept castling moves
\r
992 p = StrStr(messageText, "O-O-O");
\r
993 if(p && p-messageText < len) {
\r
994 SayString("queen side castling",FALSE);
\r
997 p = StrStr(messageText, "O-O");
\r
998 if(p && p-messageText < len) {
\r
999 SayString("king side castling",FALSE);
\r
1004 SayString(piece, FALSE);
\r
1005 if(c == '@') SayString("dropped on", FALSE); else
\r
1006 if(c) SayString(disambiguation, FALSE);
\r
1007 SayString("to", FALSE);
\r
1008 SayString(xchar, FALSE);
\r
1009 SayString(ynum, FALSE);
\r
1010 if(messageText[len-3] == 'x') {
\r
1011 currentpiece = boards[n-1][yPos][xPos];
\r
1012 if(currentpiece != EmptySquare) {
\r
1013 piece = PieceToName(currentpiece,0);
\r
1014 SayString("Capturing a",FALSE);
\r
1015 SayString(piece, FALSE);
\r
1016 } else SayString("Capturing onn passann",FALSE);
\r
1018 if(messageText[len] == '+') SayString("check", FALSE); else
\r
1019 if(messageText[len] == '#') {
\r
1020 SayString("finishing off", FALSE);
\r
1021 SayString(WhiteOnMove(n) ? "White" : "Black", FALSE);
\r
1026 /* say comment after move, possibly with result */
\r
1028 if(StrStr(messageText, " 1-0")) p = "white wins"; else
\r
1029 if(StrStr(messageText, " 0-1")) p = "black wins"; else
\r
1030 if(StrStr(messageText, " 1/2-1/2")) p = "game ends in a draw";
\r
1033 if(!StrCaseStr(comment, "draw") &&
\r
1034 !StrCaseStr(comment, "white") &&
\r
1035 !StrCaseStr(comment, "black") ) {
\r
1036 SayString(p, FALSE);
\r
1037 SayString("due to", FALSE);
\r
1040 SayString(comment, FALSE); // alphabetic comment (usually game end)
\r
1041 } else if(p) SayString(p, FALSE);
\r
1044 /* starts not with digit */
\r
1045 if(StrCaseStr(messageText, "illegal")) PlayIcsUnfinishedSound();
\r
1046 SayString(messageText, FALSE);
\r
1054 char buf1[50], buf2[50];
\r
1055 char *str1, *str2;
\r
1056 static long int lastWhiteTime, lastBlackTime;
\r
1058 suppressClocks = 1; // if user is using alt+T command, no reason to display them
\r
1059 if(abs(lastWhiteTime - whiteTimeRemaining) < 1000 && abs(lastBlackTime - blackTimeRemaining) < 1000)
\r
1060 suppressClocks = 0; // back on after two requests in rapid succession
\r
1061 sprintf(buf1, "%s", TimeString(whiteTimeRemaining));
\r
1063 SayString("White's remaining time is", FALSE);
\r
1064 SayString(str1, FALSE);
\r
1065 sprintf(buf2, "%s", TimeString(blackTimeRemaining));
\r
1067 SayString("Black's remaining time is", FALSE);
\r
1068 SayString(str2, FALSE);
\r
1069 lastWhiteTime = whiteTimeRemaining;
\r
1070 lastBlackTime = blackTimeRemaining;
\r
1074 Toggle(Boolean *b, char *mess)
\r
1077 SayString(mess, FALSE);
\r
1078 SayString("is now", FALSE);
\r
1079 SayString(*b ? "on" : "off", FALSE);
\r
1082 /* handles keyboard moves in a click-click fashion */
\r
1084 KeyboardMove(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
1086 ChessSquare currentpiece;
\r
1089 static BOOLEAN sameAgain = FALSE;
\r
1090 switch (message) {
\r
1092 sameAgain = FALSE;
\r
1093 if(oldFromX == fromX && oldFromY == fromY) {
\r
1095 /* click on same square */
\r
1098 else if(oldFromX != -1) {
\r
1100 ChessSquare pdown, pup;
\r
1101 pdown = boards[currentMove][oldFromY][oldFromX];
\r
1102 pup = boards[currentMove][fromY][fromX];
\r
1104 if (gameMode == EditPosition ||
\r
1105 !((WhitePawn <= pdown && pdown <= WhiteKing &&
\r
1106 WhitePawn <= pup && pup <= WhiteKing) ||
\r
1107 (BlackPawn <= pdown && pdown <= BlackKing &&
\r
1108 BlackPawn <= pup && pup <= BlackKing))) {
\r
1109 /* EditPosition, empty square, or different color piece;
\r
1110 click-click move is possible */
\r
1112 if (IsPromotion(oldFromX, oldFromY, fromX, fromY)) {
\r
1113 if (appData.alwaysPromoteToQueen) {
\r
1114 UserMoveEvent(oldFromX, oldFromY, fromX, fromY, 'q');
\r
1117 toX = fromX; toY = fromY; fromX = oldFromX; fromY = oldFromY;
\r
1118 PromotionPopup(hwnd);
\r
1119 fromX = toX; fromY = toY;
\r
1123 UserMoveEvent(oldFromX, oldFromY, fromX, fromY, NULLCHAR);
\r
1125 oldFromX = oldFromY = -1;
\r
1130 /* First downclick, or restart on a square with same color piece */
\r
1131 if (OKToStartUserMove(fromX, fromY)) {
\r
1134 currentpiece = boards[currentMove][fromY][fromX];
\r
1135 piece = PieceToName(currentpiece,1);
\r
1136 SayString(piece, FALSE);
\r
1137 SayString("selected", FALSE);
\r
1140 oldFromX = oldFromY = -1;
\r
1145 if (oldFromX == fromX && oldFromY == fromY) {
\r
1146 /* Upclick on same square */
\r
1148 /* Clicked same square twice: abort click-click move */
\r
1149 oldFromX = oldFromY = -1;
\r
1150 currentpiece = boards[currentMove][fromY][fromX];
\r
1151 piece = PieceToName(currentpiece,0);
\r
1152 SayString(piece, FALSE);
\r
1153 SayString("unselected", FALSE);
\r
1161 { // return TRUE for times we want to announce
\r
1163 x = (x+50)/100; // tenth of seconds
\r
1164 if(x <= 100) return (x%10 == 0);
\r
1165 if(x <= 600) return (x%100 == 0);
\r
1166 if(x <= 6000) return (x%600 == 0);
\r
1167 return (x%3000 == 0);
\r
1171 if(isalpha((char)wParam)) {
\r
1172 /* capitals of any ind are intercepted and distinguished by left and right shift */
\r
1173 int mine = GetKeyState(VK_RSHIFT) < 0;
\r
1174 if(mine || GetKeyState(VK_LSHIFT) < 0) {
\r
1177 #define JAWS_ALT_INTERCEPT \
\r
1178 if(suppressOneKey) {\
\r
1179 suppressOneKey = 0;\
\r
1180 if(GetKeyState(VK_MENU) < 0 && GetKeyState(VK_CONTROL) < 0) break;\
\r
1182 if ((char)wParam == 022 && gameMode == EditPosition) { /* <Ctl R>. Pop up piece menu */\
\r
1183 POINT pt; int x, y;\
\r
1184 SquareToPos(fromY, fromX, &x, &y);\
\r
1185 pt.x = x; pt.y = y;\
\r
1186 if(gameInfo.variant != VariantShogi)\
\r
1187 MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1);\
\r
1189 MenuPopup(hwnd, pt, LoadMenu(hInst, "ShogiPieceMenu"), -1);\
\r
1193 #define JAWS_REPLAY \
\r
1194 case '\020': /* ctrl P */\
\r
1195 { char buf[MSG_SIZ];\
\r
1196 if(GetWindowText(hwnd, buf, MSG_SIZ-1))\
\r
1197 SayString(buf, FALSE);\
\r
1201 #define JAWS_KB_NAVIGATION \
\r
1205 if(GetKeyState(VK_MENU) < 0 && GetKeyState(VK_CONTROL) < 0) {\
\r
1206 /* Control + Alt + letter used for speaking piece positions */\
\r
1207 static int lastTime; static char lastChar;\
\r
1208 int mine = 0, time = GetTickCount(); char c;\
\r
1210 if((char)wParam == lastChar && time-lastTime < 250) mine = 1;\
\r
1211 lastChar = wParam; lastTime = time;\
\r
1214 if(gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) mine = !mine;\
\r
1216 if(ToLower(c) == 'x') {\
\r
1217 SayPieces(mine ? WhitePlay : BlackPlay);\
\r
1218 suppressOneKey = 1;\
\r
1221 if(CharToPiece(c) != EmptySquare) {\
\r
1222 SayPieces(CharToPiece(mine ? ToUpper(c) : ToLower(c)));\
\r
1223 suppressOneKey = 1;\
\r
1228 switch (wParam) {\
\r
1233 KeyboardEvent(hwnd, message, wParam, lParam);\
\r
1236 KeyboardMove(hwnd, message, wParam, lParam);\
\r
1241 switch (wParam) {\
\r
1243 KeyboardMove(hwnd, message, wParam, lParam);\
\r
1248 #define JAWS_MENU_ITEMS \
\r
1249 case IDM_PossibleAttackMove: /*What can I possible attack from here */\
\r
1250 PossibleAttackMove();\
\r
1253 case IDM_PossibleAttacked: /*what can possible attack this square*/\
\r
1254 PossibleAttacked();\
\r
1257 case IDM_ReadRow: /* Read the current row of pieces */\
\r
1261 case IDM_ReadColumn: /* Read the current column of pieces */\
\r
1265 case IDM_SayCurrentPos: /* Say current position including color */\
\r
1269 case IDM_SayAllBoard: /* Say the whole board from bottom to top */\
\r
1273 case IDM_SayMachineMove: /* Say the last move made */\
\r
1275 SayMachineMove(1);\
\r
1278 case IDM_SayUpperDiagnols: /* Says the diagnol positions above you */\
\r
1279 SayUpperDiagnols();\
\r
1282 case IDM_SayLowerDiagnols: /* Say the diagnol positions below you */\
\r
1283 SayLowerDiagnols();\
\r
1286 case IDM_SayBlackPieces: /*Say the opponents pieces */\
\r
1287 SayPieces(BlackPlay);\
\r
1290 case IDM_SayWhitePieces: /*Say the opponents pieces */\
\r
1291 SayPieces(WhitePlay);\
\r
1294 case IDM_SayClockTime: /*Say the clock time */\
\r
1298 case IDM_SayWhosTurn: /* Say whos turn it its */\
\r
1302 case IDM_SayKnightMoves: /* Say Knights (L-shaped) move */\
\r
1303 SayKnightMoves();\
\r
1306 case OPT_PonderNextMove: /* Toggle option setting */\
\r
1307 Toggle(&appData.ponderNextMove, "ponder");\
\r
1310 case OPT_AnimateMoving: /* Toggle option setting */\
\r
1311 Toggle(&appData.animate, "animate moving");\
\r
1314 case OPT_AutoFlag: /* Toggle option setting */\
\r
1315 Toggle(&appData.autoCallFlag, "auto flag");\
\r
1318 case OPT_AlwaysQueen: /* Toggle option setting */\
\r
1319 Toggle(&appData.alwaysPromoteToQueen, "always promote to queen");\
\r
1322 case OPT_TestLegality: /* Toggle option setting */\
\r
1323 Toggle(&appData.testLegality, "legality testing");\
\r
1326 case OPT_HideThinkFromHuman: /* Toggle option setting */\
\r
1327 Toggle(&appData.hideThinkingFromHuman, "hide thinking");\
\r
1328 ShowThinkingEvent();\
\r
1331 case OPT_SaveExtPGN: /* Toggle option setting */\
\r
1332 Toggle(&appData.saveExtendedInfoInPGN, "extended P G N info");\
\r
1335 case OPT_ExtraInfoInMoveHistory: /* Toggle option setting */\
\r
1336 Toggle(&appData.showEvalInMoveHistory, "extra info in move histoty");\
\r
1341 #define JAWS_ACCEL \
\r
1342 !(!frozen && TranslateAccelerator(hwndMain, hAccelJAWS, &msg)) &&
\r
1344 #define JAWS_INIT if (!InitJAWS()) return (FALSE);
\r
1346 #define JAWS_DELETE(X)
\r
1348 #define JAWS_SILENCE if(suppressClocks) return;
\r
1350 #define JAWS_COPYRIGHT \
\r
1351 SetDlgItemText(hDlg, OPT_MESS, "Auditory/Keyboard Enhancements By: Ed Rodriguez (sort of)");
\r
1353 #define SAY(S) SayString((S), FALSE)
\r
1355 #define SAYMACHINEMOVE() SayMachineMove(0)
\r
1357 // After inclusion of this file somewhere early in winboard.c, the remaining part of the patch
\r
1358 // is scattered over winboard.c for actually calling the routines.
\r