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
86 // from moves.c, added WinBoard_F piece types and ranks / files
\r
88 char *squareToChar[] = { "ay", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l" };
\r
90 char *squareToNum[] = {"naught", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
\r
92 char *ordinals[] = {"zeroth", "first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "nineth"};
\r
94 char *pieceToName[] = {
\r
95 "White Pawn", "White Knight", "White Bishop", "White Rook", "White Queen",
\r
96 "White Guard", "White Elephant", "White Arch Bishop", "White Chancellor",
\r
97 "White General", "White Man", "White Cannon", "White Night Rider",
\r
98 "White Crowned Bishop", "White Crowned Rook", "White Grass Hopper", "White Veteran",
\r
99 "White Falcon", "White Amazon", "White Snake", "White Unicorn",
\r
101 "Black Pawn", "Black Knight", "Black Bishop", "Black Rook", "Black Queen",
\r
102 "Black Guard", "Black Elephant", "Black Arch Bishop", "Black Chancellor",
\r
103 "Black General", "Black Man", "Black Cannon", "Black Night Rider",
\r
104 "Black Crowned Bishop", "Black Crowned Rook", "Black Grass Hopper", "Black Veteran",
\r
105 "Black Falcon", "Black Amazon", "Black Snake", "Black Unicorn",
\r
110 char *pieceTypeName[] = {
\r
111 "Pawn", "Knight", "Bishop", "Rook", "Queen",
\r
112 "Guard", "Elephant", "Arch Bishop", "Chancellor",
\r
113 "General", "Man", "Cannon", "Night Rider",
\r
114 "Crowned Bishop", "Crowned Rook", "Grass Hopper", "Veteran",
\r
115 "Falcon", "Amazon", "Snake", "Unicorn",
\r
117 "Pawn", "Knight", "Bishop", "Rook", "Queen",
\r
118 "Guard", "Elephant", "Arch Bishop", "Chancellor",
\r
119 "General", "Man", "Cannon", "Night Rider",
\r
120 "Crowned Bishop", "Crowned Rook", "Grass Hopper", "Veteran",
\r
121 "Falcon", "Amazon", "Snake", "Unicorn",
\r
129 if(isdigit(c)) return c - ONE;
\r
130 if(c >= 'a') return c - AAA;
\r
134 char* PieceToName(p, i)
\r
138 if(i) return pieceToName[(int) p];
\r
139 return pieceTypeName[(int) p];
\r
142 char* SquareToChar(x)
\r
145 return squareToChar[x - BOARD_LEFT];
\r
148 char* SquareToNum(y)
\r
151 return squareToNum[y + (gameInfo.boardHeight < 10)];
\r
155 // from winboard.c: all new routines
\r
156 #define JFWAPI __declspec(dllimport)
\r
157 JFWAPI BOOL WINAPI JFWSayString (LPCTSTR lpszStrinToSpeak, BOOL bInterrupt);
\r
159 typedef JFWAPI BOOL (WINAPI *PSAYSTRING)(LPCTSTR lpszStrinToSpeak, BOOL bInterrupt);
\r
161 PSAYSTRING RealSayString;
\r
163 VOID SayString(char *mess, BOOL flag)
\r
164 { // for debug file
\r
165 char buf[MSG_SIZ], *p;
\r
166 if(appData.debugMode) fprintf(debugFP, "SAY '%s'\n", mess);
\r
168 if(p = StrCaseStr(buf, "Xboard adjudication:")) {
\r
170 for(i=19; i>1; i--) p[i] = p[i-1];
\r
173 RealSayString(buf, flag);
\r
176 //static int fromX = 0, fromY = 0;
\r
177 static int oldFromX, oldFromY;
\r
178 static int timeflag;
\r
179 static int suppressClocks = 0;
\r
180 static int suppressOneKey = 0;
\r
181 static HANDLE hAccelJAWS;
\r
183 typedef struct { char *name; int code; } MenuItemDesc;
\r
185 MenuItemDesc menuItemJAWS[] = {
\r
186 {"Say Clock &Time\tAlt+T", IDM_SayClockTime },
\r
188 {"Say Last &Move\tAlt+M", IDM_SayMachineMove },
\r
189 {"Say W&ho's Turn\tAlt+X", IDM_SayWhosTurn },
\r
191 {"Say Complete &Position\tAlt+P",IDM_SayAllBoard },
\r
192 {"Say &White Pieces\tAlt+W", IDM_SayWhitePieces },
\r
193 {"Say &Black Pieces\tAlt+B", IDM_SayBlackPieces },
\r
194 {"Say Board &Rank\tAlt+R", IDM_ReadRow },
\r
195 {"Say Board &File\tAlt+F", IDM_ReadColumn },
\r
197 {"Say &Upper Diagonals\tAlt+U", IDM_SayUpperDiagnols },
\r
198 {"Say &Lower Diagonals\tAlt+L", IDM_SayLowerDiagnols },
\r
199 {"Say K&night Moves\tAlt+N", IDM_SayKnightMoves },
\r
200 {"Say Current &Square\tAlt+S", IDM_SayCurrentPos },
\r
201 {"Say &Attacks\tAlt+A", IDM_PossibleAttackMove },
\r
202 {"Say Attacke&d\tAlt+D", IDM_PossibleAttacked },
\r
206 ACCEL acceleratorsJAWS[] = {
\r
207 {FVIRTKEY|FALT, 'T', IDM_SayClockTime },
\r
208 {FVIRTKEY|FALT, 'M', IDM_SayMachineMove },
\r
209 {FVIRTKEY|FALT, 'X', IDM_SayWhosTurn },
\r
210 {FVIRTKEY|FALT, 'P', IDM_SayAllBoard },
\r
211 {FVIRTKEY|FALT, 'W', IDM_SayWhitePieces },
\r
212 {FVIRTKEY|FALT, 'B', IDM_SayBlackPieces },
\r
213 {FVIRTKEY|FALT, 'R', IDM_ReadRow },
\r
214 {FVIRTKEY|FALT, 'F', IDM_ReadColumn },
\r
215 {FVIRTKEY|FALT, 'U', IDM_SayUpperDiagnols },
\r
216 {FVIRTKEY|FALT, 'L', IDM_SayLowerDiagnols },
\r
217 {FVIRTKEY|FALT, 'N', IDM_SayKnightMoves },
\r
218 {FVIRTKEY|FALT, 'S', IDM_SayCurrentPos },
\r
219 {FVIRTKEY|FALT, 'A', IDM_PossibleAttackMove },
\r
220 {FVIRTKEY|FALT, 'D', IDM_PossibleAttacked }
\r
226 HMENU menuMain, menuJAWS;
\r
227 MENUBARINFO helpMenuInfo;
\r
230 helpMenuInfo.cbSize = sizeof(helpMenuInfo);
\r
231 menuMain = GetMenu(hwndMain);
\r
232 if(appData.debugMode) fprintf(debugFP, "hwndMain: %8x %8x\n", hwndMain, menuMain);
\r
233 menuJAWS = CreatePopupMenu();
\r
235 for(i=0; menuItemJAWS[i].name; i++) {
\r
236 if(menuItemJAWS[i].name[0] == '-')
\r
237 AppendMenu(menuJAWS, MF_SEPARATOR, (UINT_PTR) 0, NULL);
\r
238 else AppendMenu(menuJAWS, MF_ENABLED|MF_STRING,
\r
239 (UINT_PTR) menuItemJAWS[i].code, (LPCTSTR) menuItemJAWS[i].name);
\r
241 InsertMenu(menuMain, 5, MF_BYPOSITION|MF_POPUP|MF_ENABLED|MF_STRING,
\r
242 (UINT_PTR) menuJAWS, "&JAWS");
\r
243 oldMenuItemState[6] = oldMenuItemState[5];
\r
244 DrawMenuBar(hwndMain);
\r
249 { // to be called at beginning of WinMain, after InitApplication and InitInstance
\r
250 HINSTANCE hApi = LoadLibrary("jfwapi32.dll");
\r
252 DisplayInformation("Missing jfwapi32.dll");
\r
256 RealSayString = (PSAYSTRING)GetProcAddress(hApi, "JFWSayString");
\r
257 if(!RealSayString) {
\r
258 DisplayInformation("SayString returned a null pointer");
\r
263 // [HGM] kludge to reduce need for modification of winboard.c: make tinyLayout menu identical
\r
264 // to standard layout, so that code for switching between them does not have to be deleted
\r
268 menuBarText[0][5] = "&JAWS";
\r
269 for(i=0; i<7; i++) menuBarText[1][i] = menuBarText[0][i];
\r
272 hAccelJAWS = CreateAcceleratorTable(acceleratorsJAWS, 14);
\r
274 /* initialize cursor position */
\r
276 SetHighlights(fromX, fromY, -1, -1);
\r
277 DrawPosition(FALSE, NULL);
\r
278 oldFromX = oldFromY = -1;
\r
280 if(hwndConsole) SetFocus(hwndConsole);
\r
284 int beeps[] = { 1, 0, 0, 0, 0 };
\r
285 int beepCodes[] = { 0, MB_OK, MB_ICONERROR, MB_ICONQUESTION, MB_ICONEXCLAMATION, MB_ICONASTERISK };
\r
288 KeyboardEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
290 ChessSquare currentPiece;
\r
291 char *piece, *xchar, *ynum ;
\r
292 int n, beepType = 1; // empty beep
\r
294 if(fromX == -1 || fromY == -1) {
\r
295 fromX = BOARD_LEFT; fromY = 0;
\r
299 if(fromX == BOARD_RGHT+1) fromX -= 2; else
\r
300 if(fromX == BOARD_LEFT) { if(fromY >= BOARD_HEIGHT - gameInfo.holdingsSize) fromX -= 2; else beepType = 0; } else
\r
301 if(fromX > BOARD_LEFT) fromX--; else beepType = 0; // off-board beep
\r
304 if(fromX == BOARD_LEFT-2) fromX += 2; else
\r
305 if(fromX == BOARD_RGHT-1) { if(fromY < gameInfo.holdingsSize) fromX += 2; else beepType = 0; } else
\r
306 if(fromX < BOARD_RGHT-1) fromX++; else beepType = 0;
\r
309 if(fromX == BOARD_RGHT+1) { if(fromY < gameInfo.holdingsSize - 1) fromY++; else beepType = 0; } else
\r
310 if(fromY < BOARD_HEIGHT-1) fromY++; else beepType = 0;
\r
313 if(fromX == BOARD_LEFT-2) { if(fromY > BOARD_HEIGHT - gameInfo.holdingsSize) fromY--; else beepType = 0; } else
\r
314 if(fromY > 0) fromY--; else beepType = 0;
\r
317 SetHighlights(fromX, fromY, -1, -1);
\r
318 DrawPosition(FALSE, NULL);
\r
319 currentPiece = boards[currentMove][fromY][fromX];
\r
320 piece = PieceToName(currentPiece,1);
\r
321 if(beepType == 1 && currentPiece != EmptySquare) beepType = currentPiece < (int) BlackPawn ? 2 : 3; // white or black beep
\r
322 if(beeps[beepType] == beeps[1] && (fromX == BOARD_RGHT+1 || fromX == BOARD_LEFT-2)) beepType = 4; // holdings beep
\r
323 beepType = beeps[beepType]%6;
\r
324 if(beepType) MessageBeep(beepCodes[beepType]);
\r
325 if(fromX == BOARD_LEFT - 2) {
\r
326 SayString("black holdings", FALSE);
\r
327 if(currentPiece != EmptySquare) {
\r
329 n = boards[currentMove][fromY][1];
\r
330 sprintf(buf, "%d %s%s", n, PieceToName(currentPiece,0), n == 1 ? "" : "s");
\r
331 SayString(buf, TRUE);
\r
334 if(fromX == BOARD_RGHT + 1) {
\r
335 SayString("white holdings", FALSE);
\r
336 if(currentPiece != EmptySquare) {
\r
338 n = boards[currentMove][fromY][BOARD_WIDTH-2];
\r
339 sprintf(buf, "%d %s%s", n, PieceToName(currentPiece,0), n == 1 ? "" : "s");
\r
340 SayString(buf, TRUE);
\r
343 if(fromX >= BOARD_LEFT && fromX < BOARD_RGHT) {
\r
345 xchar = SquareToChar(fromX);
\r
346 ynum = SquareToNum(fromY);
\r
347 if(currentPiece != EmptySquare) {
\r
348 // SayString(piece[0] == 'W' ? "white" : "black", TRUE);
\r
349 sprintf(buf, "%s %s %s", piece, xchar, ynum);
\r
350 } else sprintf(buf, "%s %s", xchar, ynum);
\r
351 SayString(buf, TRUE);
\r
356 extern char castlingRights[MAX_MOVES][BOARD_SIZE];
\r
357 int PosFlags(int nr);
\r
360 int rf, ff, rt, ft;
\r
365 extern void ReadCallback P((Board board, int flags, ChessMove kind,
\r
366 int rf, int ff, int rt, int ft,
\r
367 VOIDSTAR closure));
\r
369 void ReadCallback(board, flags, kind, rf, ff, rt, ft, closure)
\r
373 int rf, ff, rt, ft;
\r
376 register ReadClosure *cl = (ReadClosure *) closure;
\r
377 ChessSquare possiblepiece;
\r
378 char *piece, *xchar, *ynum ;
\r
380 //if(appData.debugMode) fprintf(debugFP, "%c%c%c%c\n", ff+AAA, rf+ONE, ft+AAA, rt+ONE);
\r
381 if(cl->ff == ff && cl->rf == rf) {
\r
382 possiblepiece = board[rt][ft];
\r
383 if(possiblepiece != EmptySquare) {
\r
384 piece = PieceToName(possiblepiece,1);
\r
385 xchar = SquareToChar(ft);
\r
386 ynum = SquareToNum(rt);
\r
387 SayString(xchar , FALSE);
\r
388 SayString(ynum, FALSE);
\r
389 SayString(piece, FALSE);
\r
393 if(cl->ft == ft && cl->rt == rt) {
\r
394 possiblepiece = board[rf][ff];
\r
395 piece = PieceToName(possiblepiece,1);
\r
396 xchar = SquareToChar(ff);
\r
397 ynum = SquareToNum(rf);
\r
398 SayString(xchar , FALSE);
\r
399 SayString(ynum, FALSE);
\r
400 SayString(piece, FALSE);
\r
406 PossibleAttackMove()
\r
409 ChessSquare piece, victim;
\r
410 int removedSelectedPiece = 0, swapColor;
\r
412 //if(appData.debugMode) fprintf(debugFP, "PossibleAttackMove %d %d %d %d\n", fromX, fromY, oldFromX, oldFromY);
\r
413 if(fromY < 0 || fromY >= BOARD_HEIGHT) return;
\r
414 if(fromX < BOARD_LEFT || fromX >= BOARD_RGHT) { SayString("holdings",FALSE); return; }
\r
416 piece = boards[currentMove][fromY][fromX];
\r
417 if(piece == EmptySquare) { // if square is empty, try to substitute selected piece
\r
418 if(oldFromX >= 0 && oldFromY >= 0) {
\r
419 piece = boards[currentMove][oldFromY][oldFromX];
\r
420 boards[currentMove][oldFromY][oldFromX] = EmptySquare;
\r
421 removedSelectedPiece = 1;
\r
422 SayString("Your", FALSE);
\r
423 SayString(PieceToName(piece, 0), FALSE);
\r
424 SayString("would have", FALSE);
\r
425 } else { SayString("You must select a piece first", FALSE); return; }
\r
428 victim = boards[currentMove][fromY][fromX];
\r
429 boards[currentMove][fromY][fromX] = piece; // make sure piece is actally there
\r
430 SayString("possible captures from here are", FALSE);
\r
432 swapColor = piece < (int)BlackPawn && !WhiteOnMove(currentMove) ||
\r
433 piece >= (int)BlackPawn && WhiteOnMove(currentMove);
\r
434 cl.count = 0; cl.rf = fromY; cl.ff = fromX; cl.rt = cl.ft = -1;
\r
435 GenLegal(boards[currentMove], PosFlags(currentMove + swapColor), EP_NONE,
\r
436 castlingRights[currentMove], ReadCallback, (VOIDSTAR) &cl);
\r
437 if(cl.count == 0) SayString("None", FALSE);
\r
438 boards[currentMove][fromY][fromX] = victim; // repair
\r
440 if( removedSelectedPiece ) boards[currentMove][oldFromY][oldFromX] = piece;
\r
448 ChessSquare piece = EmptySquare, victim;
\r
450 if(fromY < 0 || fromY >= BOARD_HEIGHT) return;
\r
451 if(fromX < BOARD_LEFT || fromX >= BOARD_RGHT) { SayString("holdings",FALSE); return; }
\r
453 if(oldFromX >= 0 && oldFromY >= 0) { // if piece is selected, remove it
\r
454 piece = boards[currentMove][oldFromY][oldFromX];
\r
455 boards[currentMove][oldFromY][oldFromX] = EmptySquare;
\r
458 SayString("Pieces that can capture you are", FALSE);
\r
460 victim = boards[currentMove][fromY][fromX]; // put dummy piece on target square, to activate Pawn captures
\r
461 boards[currentMove][fromY][fromX] = WhiteOnMove(currentMove) ? WhiteQueen : BlackQueen;
\r
462 cl.count = 0; cl.rt = fromY; cl.ft = fromX; cl.rf = cl.ff = -1;
\r
463 GenLegal(boards[currentMove], PosFlags(currentMove+1), EP_NONE,
\r
464 castlingRights[currentMove], ReadCallback, (VOIDSTAR) &cl);
\r
465 if(cl.count == 0) SayString("None", FALSE);
\r
467 SayString("You are defended by", FALSE);
\r
469 boards[currentMove][fromY][fromX] = WhiteOnMove(currentMove) ? BlackQueen : WhiteQueen;
\r
470 cl.count = 0; cl.rt = fromY; cl.ft = fromX; cl.rf = cl.ff = -1;
\r
471 GenLegal(boards[currentMove], PosFlags(currentMove), EP_NONE,
\r
472 castlingRights[currentMove], ReadCallback, (VOIDSTAR) &cl);
\r
473 if(cl.count == 0) SayString("None", FALSE);
\r
474 boards[currentMove][fromY][fromX] = victim; // put back original occupant
\r
476 if(oldFromX >= 0 && oldFromY >= 0) { // put back possibl selected piece
\r
477 boards[currentMove][oldFromY][oldFromX] = piece;
\r
484 ChessSquare currentpiece;
\r
485 char *piece, *xchar, *ynum ;
\r
487 ynum = SquareToNum(fromY);
\r
489 if(fromY < 0) return;
\r
491 for (xPos=BOARD_LEFT; xPos<BOARD_RGHT; xPos++) {
\r
492 currentpiece = boards[currentMove][fromY][xPos];
\r
493 if(currentpiece != EmptySquare) {
\r
494 piece = PieceToName(currentpiece,1);
\r
495 xchar = SquareToChar(xPos);
\r
496 SayString(xchar , FALSE);
\r
497 SayString(ynum, FALSE);
\r
498 SayString(piece, FALSE);
\r
503 SayString("rank", FALSE);
\r
504 SayString(ynum, FALSE);
\r
505 SayString("empty", FALSE);
\r
512 ChessSquare currentpiece;
\r
513 char *piece, *xchar, *ynum ;
\r
515 xchar = SquareToChar(fromX);
\r
517 if(fromX < 0) return;
\r
519 for (yPos=0; yPos<BOARD_HEIGHT; yPos++) {
\r
520 currentpiece = boards[currentMove][yPos][fromX];
\r
521 if(currentpiece != EmptySquare) {
\r
522 piece = PieceToName(currentpiece,1);
\r
523 ynum = SquareToNum(yPos);
\r
524 SayString(xchar , FALSE);
\r
525 SayString(ynum, FALSE);
\r
526 SayString(piece, FALSE);
\r
531 SayString(xchar, FALSE);
\r
532 SayString("file empty", FALSE);
\r
539 ChessSquare currentpiece;
\r
540 char *piece, *xchar, *ynum ;
\r
543 if(fromX < 0 || fromY < 0) return;
\r
545 if(fromX < BOARD_RGHT-1 && fromY < BOARD_HEIGHT-1) {
\r
546 SayString("The diagnol squares to your upper right contain", FALSE);
\r
549 while(yPos<BOARD_HEIGHT && xPos<BOARD_RGHT) {
\r
550 currentpiece = boards[currentMove][yPos][xPos];
\r
551 piece = PieceToName(currentpiece,1);
\r
552 xchar = SquareToChar(xPos);
\r
553 ynum = SquareToNum(yPos);
\r
554 SayString(xchar , FALSE);
\r
555 SayString(ynum, FALSE);
\r
556 SayString(piece, FALSE);
\r
561 else SayString("There is no squares to your upper right", FALSE);
\r
563 if(fromX > BOARD_LEFT && fromY < BOARD_HEIGHT-1) {
\r
564 SayString("The diagnol squares to your upper left contain", FALSE);
\r
567 while(yPos<BOARD_HEIGHT && xPos>=BOARD_LEFT) {
\r
568 currentpiece = boards[currentMove][yPos][xPos];
\r
569 piece = PieceToName(currentpiece,1);
\r
570 xchar = SquareToChar(xPos);
\r
571 ynum = SquareToNum(yPos);
\r
572 SayString(xchar , FALSE);
\r
573 SayString(ynum, FALSE);
\r
574 SayString(piece, FALSE);
\r
579 else SayString("There is no squares to your upper left", FALSE);
\r
585 ChessSquare currentpiece;
\r
586 char *piece, *xchar, *ynum ;
\r
589 if(fromX < 0 || fromY < 0) return;
\r
591 if(fromX < BOARD_RGHT-1 && fromY > 0) {
\r
592 SayString("The diagnol squares to your lower right contain", FALSE);
\r
595 while(yPos>=0 && xPos<BOARD_RGHT) {
\r
596 currentpiece = boards[currentMove][yPos][xPos];
\r
597 piece = PieceToName(currentpiece,1);
\r
598 xchar = SquareToChar(xPos);
\r
599 ynum = SquareToNum(yPos);
\r
600 SayString(xchar , FALSE);
\r
601 SayString(ynum, FALSE);
\r
602 SayString(piece, FALSE);
\r
607 else SayString("There is no squares to your lower right", FALSE);
\r
609 if(fromX > BOARD_LEFT && fromY > 0) {
\r
610 SayString("The diagnol squares to your lower left contain", FALSE);
\r
613 while(yPos>=0 && xPos>=BOARD_LEFT) {
\r
614 currentpiece = boards[currentMove][yPos][xPos];
\r
615 piece = PieceToName(currentpiece,1);
\r
616 xchar = SquareToChar(xPos);
\r
617 ynum = SquareToNum(yPos);
\r
618 SayString(xchar , FALSE);
\r
619 SayString(ynum, FALSE);
\r
620 SayString(piece, FALSE);
\r
625 else SayString("There is no squares to your lower left", FALSE);
\r
631 ChessSquare currentpiece, oldpiece;
\r
632 char *piece, *xchar, *ynum ;
\r
634 oldpiece = boards[currentMove][fromY][fromX];
\r
635 if(oldpiece == WhiteKnight || oldpiece == BlackKnight)
\r
636 SayString("The possible squares a Knight could move to are", FALSE);
\r
638 SayString("The squares a Knight could possibly attack from are", FALSE);
\r
640 if (fromY+2 < BOARD_HEIGHT && fromX-1 >= BOARD_LEFT) {
\r
641 currentpiece = boards[currentMove][fromY+2][fromX-1];
\r
642 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
643 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
644 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
646 piece = PieceToName(currentpiece,1);
\r
647 xchar = SquareToChar(fromX-1);
\r
648 ynum = SquareToNum(fromY+2);
\r
649 SayString(xchar , FALSE);
\r
650 SayString(ynum, FALSE);
\r
651 SayString(piece, FALSE);
\r
655 if (fromY+2 < BOARD_HEIGHT && fromX+1 < BOARD_RGHT) {
\r
656 currentpiece = boards[currentMove][fromY+2][fromX+1];
\r
657 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
658 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
659 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
661 piece = PieceToName(currentpiece,1);
\r
662 xchar = SquareToChar(fromX+1);
\r
663 ynum = SquareToNum(fromY+2);
\r
664 SayString(xchar , FALSE);
\r
665 SayString(ynum, FALSE);
\r
666 SayString(piece, FALSE);
\r
670 if (fromY+1 < BOARD_HEIGHT && fromX+2 < BOARD_RGHT) {
\r
671 currentpiece = boards[currentMove][fromY+1][fromX+2];
\r
672 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
673 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
674 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
676 piece = PieceToName(currentpiece,1);
\r
677 xchar = SquareToChar(fromX+2);
\r
678 ynum = SquareToNum(fromY+1);
\r
679 SayString(xchar , FALSE);
\r
680 SayString(ynum, FALSE);
\r
681 SayString(piece, FALSE);
\r
685 if (fromY-1 >= 0 && fromX+2 < BOARD_RGHT) {
\r
686 currentpiece = boards[currentMove][fromY-1][fromX+2];
\r
687 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
688 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
689 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
691 piece = PieceToName(currentpiece,1);
\r
692 xchar = SquareToChar(fromX+2);
\r
693 ynum = SquareToNum(fromY-1);
\r
694 SayString(xchar , FALSE);
\r
695 SayString(ynum, FALSE);
\r
696 SayString(piece, FALSE);
\r
700 if (fromY-2 >= 0 && fromX+1 < BOARD_RGHT) {
\r
701 currentpiece = boards[currentMove][fromY-2][fromX+1];
\r
702 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
703 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
704 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
706 piece = PieceToName(currentpiece,1);
\r
707 xchar = SquareToChar(fromX+1);
\r
708 ynum = SquareToNum(fromY-2);
\r
709 SayString(xchar , FALSE);
\r
710 SayString(ynum, FALSE);
\r
711 SayString(piece, FALSE);
\r
715 if (fromY-2 >= 0 && fromX-1 >= BOARD_LEFT) {
\r
716 currentpiece = boards[currentMove][fromY-2][fromX-1];
\r
717 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
718 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
719 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
721 piece = PieceToName(currentpiece,1);
\r
722 xchar = SquareToChar(fromX-1);
\r
723 ynum = SquareToNum(fromY-2);
\r
724 SayString(xchar , FALSE);
\r
725 SayString(ynum, FALSE);
\r
726 SayString(piece, FALSE);
\r
730 if (fromY-1 >= 0 && fromX-2 >= BOARD_LEFT) {
\r
731 currentpiece = boards[currentMove][fromY-1][fromX-2];
\r
732 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
733 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
734 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
736 piece = PieceToName(currentpiece,1);
\r
737 xchar = SquareToChar(fromX-2);
\r
738 ynum = SquareToNum(fromY-1);
\r
739 SayString(xchar , FALSE);
\r
740 SayString(ynum, FALSE);
\r
741 SayString(piece, FALSE);
\r
745 if (fromY+1 < BOARD_HEIGHT && fromX-2 >= BOARD_LEFT) {
\r
746 currentpiece = boards[currentMove][fromY+1][fromX-2];
\r
747 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
748 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
749 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
751 piece = PieceToName(currentpiece,1);
\r
752 xchar = SquareToChar(fromX-2);
\r
753 ynum = SquareToNum(fromY+1);
\r
754 SayString(xchar , FALSE);
\r
755 SayString(ynum, FALSE);
\r
756 SayString(piece, FALSE);
\r
762 SayPieces(ChessSquare p)
\r
764 ChessSquare currentpiece;
\r
765 char *piece, *xchar, *ynum ;
\r
766 int yPos, xPos, count = 0;
\r
769 if(p == WhitePlay) SayString("White pieces", FALSE); else
\r
770 if(p == BlackPlay) SayString("Black pieces", FALSE); else
\r
771 if(p == EmptySquare) SayString("Pieces", FALSE); else {
\r
772 sprintf(buf, "%ss", PieceToName(p,1));
\r
773 SayString(buf, FALSE);
\r
775 SayString("are located", FALSE);
\r
776 for(yPos=0; yPos<BOARD_HEIGHT; yPos++) {
\r
777 for(xPos=BOARD_LEFT; xPos<BOARD_RGHT; xPos++) {
\r
778 currentpiece = boards[currentMove][yPos][xPos];
\r
779 if(p == BlackPlay && currentpiece >= BlackPawn && currentpiece <= BlackKing ||
\r
780 p == WhitePlay && currentpiece >= WhitePawn && currentpiece <= WhiteKing )
\r
781 piece = PieceToName(currentpiece,0);
\r
782 else if(p == EmptySquare && currentpiece != EmptySquare)
\r
783 piece = PieceToName(currentpiece,1);
\r
784 else if(p == currentpiece)
\r
788 if(count == 0) SayString("at", FALSE);
\r
789 xchar = SquareToChar(xPos);
\r
790 ynum = SquareToNum(yPos);
\r
791 SayString(xchar , FALSE);
\r
792 SayString(ynum, FALSE);
\r
793 if(piece) SayString(piece, FALSE);
\r
797 if(count == 0) SayString("nowhere", FALSE);
\r
803 ChessSquare currentpiece;
\r
804 char *piece, *xchar, *ynum ;
\r
805 if(fromX < BOARD_LEFT) { SayString("You strayed into the white holdings", FALSE); return; }
\r
806 if(fromX >= BOARD_RGHT) { SayString("You strayed into the black holdings", FALSE); return; }
\r
807 currentpiece = boards[currentMove][fromY][fromX];
\r
808 piece = PieceToName(currentpiece,1);
\r
809 ynum = SquareToNum(fromY);
\r
810 xchar = SquareToChar(fromX);
\r
811 SayString("Your current position is", FALSE);
\r
812 SayString(xchar, FALSE);
\r
813 SayString(ynum, FALSE);
\r
814 SayString(piece, FALSE);
\r
815 if(((fromX-BOARD_LEFT) ^ fromY)&1)
\r
816 SayString("on a light square",FALSE);
\r
818 SayString("on a dark square",FALSE);
\r
820 PossibleAttacked();
\r
828 ChessSquare currentpiece;
\r
829 char *piece, *ynum ;
\r
831 if(gameInfo.holdingsWidth) {
\r
833 for(Ypos=0; Ypos<gameInfo.holdingsSize; Ypos++) {
\r
834 int n = boards[currentMove][Ypos][BOARD_WIDTH-2];
\r
835 if(n) { char buf[MSG_SIZ];
\r
836 if(!first++) SayString("white holds", FALSE);
\r
837 currentpiece = boards[currentMove][Ypos][BOARD_WIDTH-1];
\r
838 piece = PieceToName(currentpiece,0);
\r
839 sprintf(buf, "%d %s%s", n, piece, (n==1 ? "" : "s") );
\r
840 SayString(buf, FALSE);
\r
844 for(Ypos=BOARD_HEIGHT-1; Ypos>=BOARD_HEIGHT - gameInfo.holdingsSize; Ypos--) {
\r
845 int n = boards[currentMove][Ypos][1];
\r
846 if(n) { char buf[MSG_SIZ];
\r
847 if(!first++) SayString("black holds", FALSE);
\r
848 currentpiece = boards[currentMove][Ypos][0];
\r
849 piece = PieceToName(currentpiece,0);
\r
850 sprintf(buf, "%d %s%s", n, piece, (n==1 ? "" : "s") );
\r
851 SayString(buf, FALSE);
\r
856 for(Ypos=BOARD_HEIGHT-1; Ypos>=0; Ypos--) {
\r
857 ynum = ordinals[Ypos + (gameInfo.boardHeight < 10)];
\r
858 SayString(ynum, FALSE);
\r
859 SayString("rank", FALSE);
\r
860 for(Xpos=BOARD_LEFT; Xpos<BOARD_RGHT; Xpos++) {
\r
861 currentpiece = boards[currentMove][Ypos][Xpos];
\r
862 if(currentpiece != EmptySquare) {
\r
865 piece = PieceToName(currentpiece,1);
\r
866 while(Xpos < BOARD_RGHT && boards[currentMove][Ypos][Xpos] == currentpiece)
\r
869 sprintf(buf, "%d %ss", count, piece);
\r
870 } else sprintf(buf, "%s", piece);
\r
872 SayString(buf, FALSE);
\r
874 int count = 0, oldX = Xpos;
\r
875 while(Xpos < BOARD_RGHT && boards[currentMove][Ypos][Xpos] == EmptySquare)
\r
877 if(Xpos == BOARD_RGHT && oldX == BOARD_LEFT)
\r
878 SayString("all", FALSE);
\r
882 sprintf(buf, "%d", count);
\r
883 SayString(buf, FALSE);
\r
887 SayString("empty", FALSE);
\r
897 if(gameMode == MachinePlaysBlack || gameMode == IcsPlayingBlack) {
\r
898 if(WhiteOnMove(currentMove))
\r
899 SayString("It is your turn", FALSE);
\r
900 else SayString("It is your opponents turn", FALSE);
\r
901 } else if(gameMode == MachinePlaysWhite || gameMode == IcsPlayingWhite) {
\r
902 if(WhiteOnMove(currentMove))
\r
903 SayString("It is your opponents turn", FALSE);
\r
904 else SayString("It is your turn", FALSE);
\r
906 if(WhiteOnMove(currentMove))
\r
907 SayString("White is on move here", FALSE);
\r
908 else SayString("Black is on move here", FALSE);
\r
912 extern char *commentList[];
\r
915 SayMachineMove(int evenIfDuplicate)
\r
917 int len, xPos, yPos, moveNr, secondSpace = 0, castle = 0, n;
\r
918 ChessSquare currentpiece;
\r
919 char *piece, *xchar, *ynum, *p, checkMark = 0;
\r
920 char c, buf[MSG_SIZ], comment[MSG_SIZ];
\r
921 static char disambiguation[2];
\r
922 static int previousMove = 0;
\r
924 if(appData.debugMode) fprintf(debugFP, "Message = '%s'\n", messageText);
\r
925 if(gameMode == BeginningOfGame) return;
\r
926 if(messageText[0] == '[') return;
\r
928 if(isdigit(messageText[0])) { // message is move, possibly with thinking output
\r
929 int dotCount = 0, spaceCount = 0;
\r
930 sscanf(messageText, "%d", &moveNr);
\r
932 // [HGM] show: better extraction of move
\r
933 while (messageText[len] != NULLCHAR) {
\r
934 if(messageText[len] == '.' && spaceCount == 0) dotCount++;
\r
935 if(messageText[len] == ' ') { if(++spaceCount == 2) secondSpace = len; }
\r
936 if(messageText[len] == '{') { // we detected a comment
\r
937 if(isalpha(messageText[len+1]) ) sscanf(messageText+len, "{%[^}]}", comment);
\r
940 if(messageText[len] == '[') { // we detected thinking output
\r
941 int depth; float score=0; char c, lastMover = (dotCount == 3 ? 'B' : 'W');
\r
942 if(sscanf(messageText+len+1, "%d]%c%f", &depth, &c, &score) > 1) {
\r
943 if(c == ' ') { // if not explicitly specified, figure out source of thinking output
\r
945 case MachinePlaysWhite:
\r
946 case IcsPlayingWhite:
\r
948 case IcsPlayingBlack:
\r
949 case MachinePlaysBlack:
\r
955 if(c != lastMover) return; // line is thinking output of future move, ignore.
\r
956 if(2*moveNr - (dotCount < 2) == previousMove)
\r
957 return; // do not repeat same move; likely ponder output
\r
958 sprintf(buf, "score %s %d at %d ply",
\r
959 score > 0 ? "plus" : score < 0 ? "minus" : "",
\r
960 (int) (fabs(score)*100+0.5),
\r
962 SayString(buf, FALSE); // move + thinking output describing it; say it.
\r
964 while(messageText[len-1] == ' ') len--; // position just behind move;
\r
967 if(messageText[len] == '(') { // ICS time printed behind move
\r
968 while(messageText[len+1] && messageText[len] != ')') len++; // skip it
\r
972 if(secondSpace) len = secondSpace; // position behind move
\r
973 if(messageText[len-1] == '+' || messageText[len-1] == '#') { /* you are in checkmate */
\r
974 len--; // strip off check or mate indicator
\r
975 checkMark = messageText[len]; // make sure still seen after we stip off promo piece
\r
977 if(messageText[len-2] == '=') { /* promotion */
\r
978 len-=2; // strip off promotion piece
\r
979 SayString("promotion", FALSE);
\r
982 n = 2*moveNr - (dotCount < 2);
\r
984 if(previousMove != 2*moveNr + (dotCount > 1) || evenIfDuplicate) {
\r
986 previousMove = 2*moveNr + (dotCount > 1); // remember move nr of move last spoken
\r
987 sprintf(number, "%d", moveNr);
\r
989 yPos = CoordToNum(messageText[len-1]); /* turn char coords to ints */
\r
990 xPos = CoordToNum(messageText[len-2]);
\r
991 if(xPos < 0 || xPos > 11) return; // prevent crashes if no coord string available to speak
\r
992 if(yPos < 0 || yPos > 9) return;
\r
993 currentpiece = boards[n][yPos][xPos];
\r
994 piece = PieceToName(currentpiece,0);
\r
995 ynum = SquareToNum(yPos);
\r
996 xchar = SquareToChar(xPos);
\r
997 c = messageText[len-3];
\r
998 if(c == 'x') c = messageText[len-4];
\r
999 if(!isdigit(c) && c < 'a' && c != '@') c = 0;
\r
1000 disambiguation[0] = c;
\r
1001 SayString(WhiteOnMove(n) ? "Black" : "White", FALSE);
\r
1002 SayString("move", FALSE);
\r
1003 SayString(number, FALSE);
\r
1004 // if(c==0 || c=='@') SayString("a", FALSE);
\r
1005 // intercept castling moves
\r
1006 p = StrStr(messageText, "O-O-O");
\r
1007 if(p && p-messageText < len) {
\r
1008 SayString("queen side castling",FALSE);
\r
1011 p = StrStr(messageText, "O-O");
\r
1012 if(p && p-messageText < len) {
\r
1013 SayString("king side castling",FALSE);
\r
1018 SayString(piece, FALSE);
\r
1019 if(c == '@') SayString("dropped on", FALSE); else
\r
1020 if(c) SayString(disambiguation, FALSE);
\r
1021 SayString("to", FALSE);
\r
1022 SayString(xchar, FALSE);
\r
1023 SayString(ynum, FALSE);
\r
1024 if(messageText[len-3] == 'x') {
\r
1025 currentpiece = boards[n-1][yPos][xPos];
\r
1026 if(currentpiece != EmptySquare) {
\r
1027 piece = PieceToName(currentpiece,0);
\r
1028 SayString("Capturing a",FALSE);
\r
1029 SayString(piece, FALSE);
\r
1030 } else SayString("Capturing onn passann",FALSE);
\r
1033 if(checkMark == '+') SayString("check", FALSE); else
\r
1034 if(checkMark == '#') {
\r
1035 SayString("finishing off", FALSE);
\r
1036 SayString(WhiteOnMove(n) ? "White" : "Black", FALSE);
\r
1040 /* say comment after move, possibly with result */
\r
1042 if(StrStr(messageText, " 1-0")) p = "white wins"; else
\r
1043 if(StrStr(messageText, " 0-1")) p = "black wins"; else
\r
1044 if(StrStr(messageText, " 1/2-1/2")) p = "game ends in a draw";
\r
1047 if(!StrCaseStr(comment, "draw") &&
\r
1048 !StrCaseStr(comment, "white") &&
\r
1049 !StrCaseStr(comment, "black") ) {
\r
1050 SayString(p, FALSE);
\r
1051 SayString("due to", FALSE);
\r
1054 SayString(comment, FALSE); // alphabetic comment (usually game end)
\r
1055 } else if(p) SayString(p, FALSE);
\r
1057 if(commentDialog && commentList[currentMove]) SetFocus(commentDialog);
\r
1060 /* starts not with digit */
\r
1061 if(StrCaseStr(messageText, "illegal")) PlayIcsUnfinishedSound();
\r
1062 SayString(messageText, FALSE);
\r
1070 char buf1[50], buf2[50];
\r
1071 char *str1, *str2;
\r
1072 static long int lastWhiteTime, lastBlackTime;
\r
1074 suppressClocks = 1; // if user is using alt+T command, no reason to display them
\r
1075 if(abs(lastWhiteTime - whiteTimeRemaining) < 1000 && abs(lastBlackTime - blackTimeRemaining) < 1000)
\r
1076 suppressClocks = 0; // back on after two requests in rapid succession
\r
1077 sprintf(buf1, "%s", TimeString(whiteTimeRemaining));
\r
1079 SayString("White's remaining time is", FALSE);
\r
1080 SayString(str1, FALSE);
\r
1081 sprintf(buf2, "%s", TimeString(blackTimeRemaining));
\r
1083 SayString("Black's remaining time is", FALSE);
\r
1084 SayString(str2, FALSE);
\r
1085 lastWhiteTime = whiteTimeRemaining;
\r
1086 lastBlackTime = blackTimeRemaining;
\r
1090 Toggle(Boolean *b, char *mess)
\r
1093 SayString(mess, FALSE);
\r
1094 SayString("is now", FALSE);
\r
1095 SayString(*b ? "on" : "off", FALSE);
\r
1098 /* handles keyboard moves in a click-click fashion */
\r
1100 KeyboardMove(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
1102 ChessSquare currentpiece;
\r
1105 static BOOLEAN sameAgain = FALSE;
\r
1106 switch (message) {
\r
1108 sameAgain = FALSE;
\r
1109 if(oldFromX == fromX && oldFromY == fromY) {
\r
1111 /* click on same square */
\r
1114 else if(oldFromX != -1) {
\r
1116 ChessSquare pdown, pup;
\r
1117 pdown = boards[currentMove][oldFromY][oldFromX];
\r
1118 pup = boards[currentMove][fromY][fromX];
\r
1120 if (gameMode == EditPosition ||
\r
1121 !((WhitePawn <= pdown && pdown <= WhiteKing &&
\r
1122 WhitePawn <= pup && pup <= WhiteKing) ||
\r
1123 (BlackPawn <= pdown && pdown <= BlackKing &&
\r
1124 BlackPawn <= pup && pup <= BlackKing))) {
\r
1125 /* EditPosition, empty square, or different color piece;
\r
1126 click-click move is possible */
\r
1128 if (IsPromotion(oldFromX, oldFromY, fromX, fromY)) {
\r
1129 if (appData.alwaysPromoteToQueen) {
\r
1130 UserMoveEvent(oldFromX, oldFromY, fromX, fromY, 'q');
\r
1133 toX = fromX; toY = fromY; fromX = oldFromX; fromY = oldFromY;
\r
1134 PromotionPopup(hwnd);
\r
1135 fromX = toX; fromY = toY;
\r
1139 UserMoveEvent(oldFromX, oldFromY, fromX, fromY, NULLCHAR);
\r
1141 oldFromX = oldFromY = -1;
\r
1146 /* First downclick, or restart on a square with same color piece */
\r
1147 if (OKToStartUserMove(fromX, fromY)) {
\r
1150 currentpiece = boards[currentMove][fromY][fromX];
\r
1151 piece = PieceToName(currentpiece,1);
\r
1152 SayString(piece, FALSE);
\r
1153 SayString("selected", FALSE);
\r
1156 oldFromX = oldFromY = -1;
\r
1161 if (oldFromX == fromX && oldFromY == fromY) {
\r
1162 /* Upclick on same square */
\r
1164 /* Clicked same square twice: abort click-click move */
\r
1165 oldFromX = oldFromY = -1;
\r
1166 currentpiece = boards[currentMove][fromY][fromX];
\r
1167 piece = PieceToName(currentpiece,0);
\r
1168 SayString(piece, FALSE);
\r
1169 SayString("unselected", FALSE);
\r
1177 { // return TRUE for times we want to announce
\r
1179 x = (x+50)/100; // tenth of seconds
\r
1180 if(x <= 100) return (x%10 == 0);
\r
1181 if(x <= 600) return (x%100 == 0);
\r
1182 if(x <= 6000) return (x%600 == 0);
\r
1183 return (x%3000 == 0);
\r
1186 #define JAWS_ARGS \
\r
1187 { "beepOffBoard", ArgInt, (LPVOID) beeps, TRUE },\
\r
1188 { "beepEmpty", ArgInt, (LPVOID) (beeps+1), TRUE },\
\r
1189 { "beepWhite", ArgInt, (LPVOID) (beeps+2), TRUE },\
\r
1190 { "beepBlack", ArgInt, (LPVOID) (beeps+3), TRUE },\
\r
1191 { "beepHoldings", ArgInt, (LPVOID) (beeps+4), TRUE },\
\r
1193 #define JAWS_ALT_INTERCEPT \
\r
1194 if(suppressOneKey) {\
\r
1195 suppressOneKey = 0;\
\r
1196 if(GetKeyState(VK_MENU) < 0 && GetKeyState(VK_CONTROL) < 0) break;\
\r
1198 if ((char)wParam == 022 && gameMode == EditPosition) { /* <Ctl R>. Pop up piece menu */\
\r
1199 POINT pt; int x, y;\
\r
1200 SquareToPos(fromY, fromX, &x, &y);\
\r
1201 pt.x = x; pt.y = y;\
\r
1202 if(gameInfo.variant != VariantShogi)\
\r
1203 MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1);\
\r
1205 MenuPopup(hwnd, pt, LoadMenu(hInst, "ShogiPieceMenu"), -1);\
\r
1209 #define JAWS_REPLAY \
\r
1210 case '\020': /* ctrl P */\
\r
1211 { char buf[MSG_SIZ];\
\r
1212 if(GetWindowText(hwnd, buf, MSG_SIZ-1))\
\r
1213 SayString(buf, FALSE);\
\r
1217 #define JAWS_KB_NAVIGATION \
\r
1221 if(GetKeyState(VK_MENU) < 0 && GetKeyState(VK_CONTROL) < 0) {\
\r
1222 /* Control + Alt + letter used for speaking piece positions */\
\r
1223 static int lastTime; static char lastChar;\
\r
1224 int mine = 0, time = GetTickCount(); char c;\
\r
1226 if((char)wParam == lastChar && time-lastTime < 250) mine = 1;\
\r
1227 lastChar = wParam; lastTime = time;\
\r
1230 if(gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) mine = !mine;\
\r
1232 if(ToLower(c) == 'x') {\
\r
1233 SayPieces(mine ? WhitePlay : BlackPlay);\
\r
1234 suppressOneKey = 1;\
\r
1237 if(CharToPiece(c) != EmptySquare) {\
\r
1238 SayPieces(CharToPiece(mine ? ToUpper(c) : ToLower(c)));\
\r
1239 suppressOneKey = 1;\
\r
1244 switch (wParam) {\
\r
1249 KeyboardEvent(hwnd, message, wParam, lParam);\
\r
1252 KeyboardMove(hwnd, message, wParam, lParam);\
\r
1257 switch (wParam) {\
\r
1259 KeyboardMove(hwnd, message, wParam, lParam);\
\r
1264 #define JAWS_MENU_ITEMS \
\r
1265 case IDM_PossibleAttackMove: /*What can I possible attack from here */\
\r
1266 PossibleAttackMove();\
\r
1269 case IDM_PossibleAttacked: /*what can possible attack this square*/\
\r
1270 PossibleAttacked();\
\r
1273 case IDM_ReadRow: /* Read the current row of pieces */\
\r
1277 case IDM_ReadColumn: /* Read the current column of pieces */\
\r
1281 case IDM_SayCurrentPos: /* Say current position including color */\
\r
1285 case IDM_SayAllBoard: /* Say the whole board from bottom to top */\
\r
1289 case IDM_SayMachineMove: /* Say the last move made */\
\r
1291 SayMachineMove(1);\
\r
1294 case IDM_SayUpperDiagnols: /* Says the diagnol positions above you */\
\r
1295 SayUpperDiagnols();\
\r
1298 case IDM_SayLowerDiagnols: /* Say the diagnol positions below you */\
\r
1299 SayLowerDiagnols();\
\r
1302 case IDM_SayBlackPieces: /*Say the opponents pieces */\
\r
1303 SayPieces(BlackPlay);\
\r
1306 case IDM_SayWhitePieces: /*Say the opponents pieces */\
\r
1307 SayPieces(WhitePlay);\
\r
1310 case IDM_SayClockTime: /*Say the clock time */\
\r
1314 case IDM_SayWhosTurn: /* Say whos turn it its */\
\r
1318 case IDM_SayKnightMoves: /* Say Knights (L-shaped) move */\
\r
1319 SayKnightMoves();\
\r
1322 case OPT_PonderNextMove: /* Toggle option setting */\
\r
1323 Toggle(&appData.ponderNextMove, "ponder");\
\r
1326 case OPT_AnimateMoving: /* Toggle option setting */\
\r
1327 Toggle(&appData.animate, "animate moving");\
\r
1330 case OPT_AutoFlag: /* Toggle option setting */\
\r
1331 Toggle(&appData.autoCallFlag, "auto flag");\
\r
1334 case OPT_AlwaysQueen: /* Toggle option setting */\
\r
1335 Toggle(&appData.alwaysPromoteToQueen, "always promote to queen");\
\r
1338 case OPT_TestLegality: /* Toggle option setting */\
\r
1339 Toggle(&appData.testLegality, "legality testing");\
\r
1342 case OPT_HideThinkFromHuman: /* Toggle option setting */\
\r
1343 Toggle(&appData.hideThinkingFromHuman, "hide thinking");\
\r
1344 ShowThinkingEvent();\
\r
1347 case OPT_SaveExtPGN: /* Toggle option setting */\
\r
1348 Toggle(&appData.saveExtendedInfoInPGN, "extended P G N info");\
\r
1351 case OPT_ExtraInfoInMoveHistory: /* Toggle option setting */\
\r
1352 Toggle(&appData.showEvalInMoveHistory, "extra info in move histoty");\
\r
1357 #define JAWS_ACCEL \
\r
1358 !(!frozen && TranslateAccelerator(hwndMain, hAccelJAWS, &msg)) &&
\r
1360 #define JAWS_INIT if (!InitJAWS()) return (FALSE);
\r
1362 #define JAWS_DELETE(X)
\r
1364 #define JAWS_SILENCE if(suppressClocks) return;
\r
1366 #define JAWS_COPYRIGHT \
\r
1367 SetDlgItemText(hDlg, OPT_MESS, "Auditory/Keyboard Enhancements By: Ed Rodriguez (sort of)");
\r
1369 #define SAY(S) SayString((S), FALSE)
\r
1371 #define SAYMACHINEMOVE() SayMachineMove(0)
\r
1373 // After inclusion of this file somewhere early in winboard.c, the remaining part of the patch
\r
1374 // is scattered over winboard.c for actually calling the routines.
\r