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[8000], *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 menuJAWS = CreatePopupMenu();
\r
234 for(i=0; menuItemJAWS[i].name; i++) {
\r
235 if(menuItemJAWS[i].name[0] == '-')
\r
236 AppendMenu(menuJAWS, MF_SEPARATOR, (UINT_PTR) 0, NULL);
\r
237 else AppendMenu(menuJAWS, MF_ENABLED|MF_STRING,
\r
238 (UINT_PTR) menuItemJAWS[i].code, (LPCTSTR) menuItemJAWS[i].name);
\r
240 InsertMenu(menuMain, 5, MF_BYPOSITION|MF_POPUP|MF_ENABLED|MF_STRING,
\r
241 (UINT_PTR) menuJAWS, "&JAWS");
\r
242 oldMenuItemState[6] = oldMenuItemState[5];
\r
243 DrawMenuBar(hwndMain);
\r
248 { // to be called at beginning of WinMain, after InitApplication and InitInstance
\r
249 HINSTANCE hApi = LoadLibrary("jfwapi32.dll");
\r
251 DisplayInformation("Missing jfwapi32.dll");
\r
255 RealSayString = (PSAYSTRING)GetProcAddress(hApi, "JFWSayString");
\r
256 if(!RealSayString) {
\r
257 DisplayInformation("SayString returned a null pointer");
\r
262 // [HGM] kludge to reduce need for modification of winboard.c: make tinyLayout menu identical
\r
263 // to standard layout, so that code for switching between them does not have to be deleted
\r
267 menuBarText[0][5] = "&JAWS";
\r
268 for(i=0; i<7; i++) menuBarText[1][i] = menuBarText[0][i];
\r
271 hAccelJAWS = CreateAcceleratorTable(acceleratorsJAWS, 14);
\r
273 /* initialize cursor position */
\r
275 SetHighlights(fromX, fromY, -1, -1);
\r
276 DrawPosition(FALSE, NULL);
\r
277 oldFromX = oldFromY = -1;
\r
279 if(hwndConsole) SetFocus(hwndConsole);
\r
283 int beeps[] = { 1, 0, 0, 0, 0 };
\r
284 int beepCodes[] = { 0, MB_OK, MB_ICONERROR, MB_ICONQUESTION, MB_ICONEXCLAMATION, MB_ICONASTERISK };
\r
287 KeyboardEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
289 ChessSquare currentPiece;
\r
290 char *piece, *xchar, *ynum ;
\r
291 int n, beepType = 1; // empty beep
\r
293 if(fromX == -1 || fromY == -1) {
\r
294 fromX = BOARD_LEFT; fromY = 0;
\r
298 if(fromX == BOARD_RGHT+1) fromX -= 2; else
\r
299 if(fromX == BOARD_LEFT) { if(fromY >= BOARD_HEIGHT - gameInfo.holdingsSize) fromX -= 2; else beepType = 0; } else
\r
300 if(fromX > BOARD_LEFT) fromX--; else beepType = 0; // off-board beep
\r
303 if(fromX == BOARD_LEFT-2) fromX += 2; else
\r
304 if(fromX == BOARD_RGHT-1) { if(fromY < gameInfo.holdingsSize) fromX += 2; else beepType = 0; } else
\r
305 if(fromX < BOARD_RGHT-1) fromX++; else beepType = 0;
\r
308 if(fromX == BOARD_RGHT+1) { if(fromY < gameInfo.holdingsSize - 1) fromY++; else beepType = 0; } else
\r
309 if(fromY < BOARD_HEIGHT-1) fromY++; else beepType = 0;
\r
312 if(fromX == BOARD_LEFT-2) { if(fromY > BOARD_HEIGHT - gameInfo.holdingsSize) fromY--; else beepType = 0; } else
\r
313 if(fromY > 0) fromY--; else beepType = 0;
\r
316 SetHighlights(fromX, fromY, -1, -1);
\r
317 DrawPosition(FALSE, NULL);
\r
318 currentPiece = boards[currentMove][fromY][fromX];
\r
319 piece = PieceToName(currentPiece,1);
\r
320 if(beepType == 1 && currentPiece != EmptySquare) beepType = currentPiece < (int) BlackPawn ? 2 : 3; // white or black beep
\r
321 if(beeps[beepType] == beeps[1] && (fromX == BOARD_RGHT+1 || fromX == BOARD_LEFT-2)) beepType = 4; // holdings beep
\r
322 beepType = beeps[beepType]%6;
\r
323 if(beepType) MessageBeep(beepCodes[beepType]);
\r
324 if(fromX == BOARD_LEFT - 2) {
\r
325 SayString("black holdings", FALSE);
\r
326 if(currentPiece != EmptySquare) {
\r
328 n = boards[currentMove][fromY][1];
\r
329 sprintf(buf, "%d %s%s", n, PieceToName(currentPiece,0), n == 1 ? "" : "s");
\r
330 SayString(buf, TRUE);
\r
333 if(fromX == BOARD_RGHT + 1) {
\r
334 SayString("white holdings", FALSE);
\r
335 if(currentPiece != EmptySquare) {
\r
337 n = boards[currentMove][fromY][BOARD_WIDTH-2];
\r
338 sprintf(buf, "%d %s%s", n, PieceToName(currentPiece,0), n == 1 ? "" : "s");
\r
339 SayString(buf, TRUE);
\r
342 if(fromX >= BOARD_LEFT && fromX < BOARD_RGHT) {
\r
344 xchar = SquareToChar(fromX);
\r
345 ynum = SquareToNum(fromY);
\r
346 if(currentPiece != EmptySquare) {
\r
347 // SayString(piece[0] == 'W' ? "white" : "black", TRUE);
\r
348 sprintf(buf, "%s %s %s", piece, xchar, ynum);
\r
349 } else sprintf(buf, "%s %s", xchar, ynum);
\r
350 SayString(buf, TRUE);
\r
355 extern char castlingRights[MAX_MOVES][BOARD_SIZE];
\r
356 int PosFlags(int nr);
\r
359 int rf, ff, rt, ft;
\r
364 extern void ReadCallback P((Board board, int flags, ChessMove kind,
\r
365 int rf, int ff, int rt, int ft,
\r
366 VOIDSTAR closure));
\r
368 void ReadCallback(board, flags, kind, rf, ff, rt, ft, closure)
\r
372 int rf, ff, rt, ft;
\r
375 register ReadClosure *cl = (ReadClosure *) closure;
\r
376 ChessSquare possiblepiece;
\r
377 char *piece, *xchar, *ynum ;
\r
379 //if(appData.debugMode) fprintf(debugFP, "%c%c%c%c\n", ff+AAA, rf+ONE, ft+AAA, rt+ONE);
\r
380 if(cl->ff == ff && cl->rf == rf) {
\r
381 possiblepiece = board[rt][ft];
\r
382 if(possiblepiece != EmptySquare) {
\r
383 piece = PieceToName(possiblepiece,1);
\r
384 xchar = SquareToChar(ft);
\r
385 ynum = SquareToNum(rt);
\r
386 SayString(xchar , FALSE);
\r
387 SayString(ynum, FALSE);
\r
388 SayString(piece, FALSE);
\r
392 if(cl->ft == ft && cl->rt == rt) {
\r
393 possiblepiece = board[rf][ff];
\r
394 piece = PieceToName(possiblepiece,1);
\r
395 xchar = SquareToChar(ff);
\r
396 ynum = SquareToNum(rf);
\r
397 SayString(xchar , FALSE);
\r
398 SayString(ynum, FALSE);
\r
399 SayString(piece, FALSE);
\r
405 PossibleAttackMove()
\r
408 ChessSquare piece, victim;
\r
409 int removedSelectedPiece = 0, swapColor;
\r
411 //if(appData.debugMode) fprintf(debugFP, "PossibleAttackMove %d %d %d %d\n", fromX, fromY, oldFromX, oldFromY);
\r
412 if(fromY < 0 || fromY >= BOARD_HEIGHT) return;
\r
413 if(fromX < BOARD_LEFT || fromX >= BOARD_RGHT) { SayString("holdings",FALSE); return; }
\r
415 piece = boards[currentMove][fromY][fromX];
\r
416 if(piece == EmptySquare) { // if square is empty, try to substitute selected piece
\r
417 if(oldFromX >= 0 && oldFromY >= 0) {
\r
418 piece = boards[currentMove][oldFromY][oldFromX];
\r
419 boards[currentMove][oldFromY][oldFromX] = EmptySquare;
\r
420 removedSelectedPiece = 1;
\r
421 SayString("Your", FALSE);
\r
422 SayString(PieceToName(piece, 0), FALSE);
\r
423 SayString("would have", FALSE);
\r
424 } else { SayString("You must select a piece first", FALSE); return; }
\r
427 victim = boards[currentMove][fromY][fromX];
\r
428 boards[currentMove][fromY][fromX] = piece; // make sure piece is actally there
\r
429 SayString("possible captures from here are", FALSE);
\r
431 swapColor = piece < (int)BlackPawn && !WhiteOnMove(currentMove) ||
\r
432 piece >= (int)BlackPawn && WhiteOnMove(currentMove);
\r
433 cl.count = 0; cl.rf = fromY; cl.ff = fromX; cl.rt = cl.ft = -1;
\r
434 GenLegal(boards[currentMove], PosFlags(currentMove + swapColor), EP_NONE,
\r
435 castlingRights[currentMove], ReadCallback, (VOIDSTAR) &cl);
\r
436 if(cl.count == 0) SayString("None", FALSE);
\r
437 boards[currentMove][fromY][fromX] = victim; // repair
\r
439 if( removedSelectedPiece ) boards[currentMove][oldFromY][oldFromX] = piece;
\r
447 ChessSquare piece = EmptySquare, victim;
\r
449 if(fromY < 0 || fromY >= BOARD_HEIGHT) return;
\r
450 if(fromX < BOARD_LEFT || fromX >= BOARD_RGHT) { SayString("holdings",FALSE); return; }
\r
452 if(oldFromX >= 0 && oldFromY >= 0) { // if piece is selected, remove it
\r
453 piece = boards[currentMove][oldFromY][oldFromX];
\r
454 boards[currentMove][oldFromY][oldFromX] = EmptySquare;
\r
457 SayString("Pieces that can capture you are", FALSE);
\r
459 victim = boards[currentMove][fromY][fromX]; // put dummy piece on target square, to activate Pawn captures
\r
460 boards[currentMove][fromY][fromX] = WhiteOnMove(currentMove) ? WhiteQueen : BlackQueen;
\r
461 cl.count = 0; cl.rt = fromY; cl.ft = fromX; cl.rf = cl.ff = -1;
\r
462 GenLegal(boards[currentMove], PosFlags(currentMove+1), EP_NONE,
\r
463 castlingRights[currentMove], ReadCallback, (VOIDSTAR) &cl);
\r
464 if(cl.count == 0) SayString("None", FALSE);
\r
466 SayString("You are defended by", FALSE);
\r
468 boards[currentMove][fromY][fromX] = WhiteOnMove(currentMove) ? BlackQueen : WhiteQueen;
\r
469 cl.count = 0; cl.rt = fromY; cl.ft = fromX; cl.rf = cl.ff = -1;
\r
470 GenLegal(boards[currentMove], PosFlags(currentMove), EP_NONE,
\r
471 castlingRights[currentMove], ReadCallback, (VOIDSTAR) &cl);
\r
472 if(cl.count == 0) SayString("None", FALSE);
\r
473 boards[currentMove][fromY][fromX] = victim; // put back original occupant
\r
475 if(oldFromX >= 0 && oldFromY >= 0) { // put back possibl selected piece
\r
476 boards[currentMove][oldFromY][oldFromX] = piece;
\r
483 ChessSquare currentpiece;
\r
484 char *piece, *xchar, *ynum ;
\r
486 ynum = SquareToNum(fromY);
\r
488 if(fromY < 0) return;
\r
490 for (xPos=BOARD_LEFT; xPos<BOARD_RGHT; xPos++) {
\r
491 currentpiece = boards[currentMove][fromY][xPos];
\r
492 if(currentpiece != EmptySquare) {
\r
493 piece = PieceToName(currentpiece,1);
\r
494 xchar = SquareToChar(xPos);
\r
495 SayString(xchar , FALSE);
\r
496 SayString(ynum, FALSE);
\r
497 SayString(piece, FALSE);
\r
502 SayString("rank", FALSE);
\r
503 SayString(ynum, FALSE);
\r
504 SayString("empty", FALSE);
\r
511 ChessSquare currentpiece;
\r
512 char *piece, *xchar, *ynum ;
\r
514 xchar = SquareToChar(fromX);
\r
516 if(fromX < 0) return;
\r
518 for (yPos=0; yPos<BOARD_HEIGHT; yPos++) {
\r
519 currentpiece = boards[currentMove][yPos][fromX];
\r
520 if(currentpiece != EmptySquare) {
\r
521 piece = PieceToName(currentpiece,1);
\r
522 ynum = SquareToNum(yPos);
\r
523 SayString(xchar , FALSE);
\r
524 SayString(ynum, FALSE);
\r
525 SayString(piece, FALSE);
\r
530 SayString(xchar, FALSE);
\r
531 SayString("file empty", FALSE);
\r
538 ChessSquare currentpiece;
\r
539 char *piece, *xchar, *ynum ;
\r
542 if(fromX < 0 || fromY < 0) return;
\r
544 if(fromX < BOARD_RGHT-1 && fromY < BOARD_HEIGHT-1) {
\r
545 SayString("The diagnol squares to your upper right contain", FALSE);
\r
548 while(yPos<BOARD_HEIGHT && xPos<BOARD_RGHT) {
\r
549 currentpiece = boards[currentMove][yPos][xPos];
\r
550 piece = PieceToName(currentpiece,1);
\r
551 xchar = SquareToChar(xPos);
\r
552 ynum = SquareToNum(yPos);
\r
553 SayString(xchar , FALSE);
\r
554 SayString(ynum, FALSE);
\r
555 SayString(piece, FALSE);
\r
560 else SayString("There is no squares to your upper right", FALSE);
\r
562 if(fromX > BOARD_LEFT && fromY < BOARD_HEIGHT-1) {
\r
563 SayString("The diagnol squares to your upper left contain", FALSE);
\r
566 while(yPos<BOARD_HEIGHT && xPos>=BOARD_LEFT) {
\r
567 currentpiece = boards[currentMove][yPos][xPos];
\r
568 piece = PieceToName(currentpiece,1);
\r
569 xchar = SquareToChar(xPos);
\r
570 ynum = SquareToNum(yPos);
\r
571 SayString(xchar , FALSE);
\r
572 SayString(ynum, FALSE);
\r
573 SayString(piece, FALSE);
\r
578 else SayString("There is no squares to your upper left", FALSE);
\r
584 ChessSquare currentpiece;
\r
585 char *piece, *xchar, *ynum ;
\r
588 if(fromX < 0 || fromY < 0) return;
\r
590 if(fromX < BOARD_RGHT-1 && fromY > 0) {
\r
591 SayString("The diagnol squares to your lower right contain", FALSE);
\r
594 while(yPos>=0 && xPos<BOARD_RGHT) {
\r
595 currentpiece = boards[currentMove][yPos][xPos];
\r
596 piece = PieceToName(currentpiece,1);
\r
597 xchar = SquareToChar(xPos);
\r
598 ynum = SquareToNum(yPos);
\r
599 SayString(xchar , FALSE);
\r
600 SayString(ynum, FALSE);
\r
601 SayString(piece, FALSE);
\r
606 else SayString("There is no squares to your lower right", FALSE);
\r
608 if(fromX > BOARD_LEFT && fromY > 0) {
\r
609 SayString("The diagnol squares to your lower left contain", FALSE);
\r
612 while(yPos>=0 && xPos>=BOARD_LEFT) {
\r
613 currentpiece = boards[currentMove][yPos][xPos];
\r
614 piece = PieceToName(currentpiece,1);
\r
615 xchar = SquareToChar(xPos);
\r
616 ynum = SquareToNum(yPos);
\r
617 SayString(xchar , FALSE);
\r
618 SayString(ynum, FALSE);
\r
619 SayString(piece, FALSE);
\r
624 else SayString("There is no squares to your lower left", FALSE);
\r
630 ChessSquare currentpiece, oldpiece;
\r
631 char *piece, *xchar, *ynum ;
\r
633 oldpiece = boards[currentMove][fromY][fromX];
\r
634 if(oldpiece == WhiteKnight || oldpiece == BlackKnight)
\r
635 SayString("The possible squares a Knight could move to are", FALSE);
\r
637 SayString("The squares a Knight could possibly attack from are", FALSE);
\r
639 if (fromY+2 < BOARD_HEIGHT && fromX-1 >= BOARD_LEFT) {
\r
640 currentpiece = boards[currentMove][fromY+2][fromX-1];
\r
641 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
642 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
643 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
645 piece = PieceToName(currentpiece,1);
\r
646 xchar = SquareToChar(fromX-1);
\r
647 ynum = SquareToNum(fromY+2);
\r
648 SayString(xchar , FALSE);
\r
649 SayString(ynum, FALSE);
\r
650 SayString(piece, FALSE);
\r
654 if (fromY+2 < BOARD_HEIGHT && fromX+1 < BOARD_RGHT) {
\r
655 currentpiece = boards[currentMove][fromY+2][fromX+1];
\r
656 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
657 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
658 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
660 piece = PieceToName(currentpiece,1);
\r
661 xchar = SquareToChar(fromX+1);
\r
662 ynum = SquareToNum(fromY+2);
\r
663 SayString(xchar , FALSE);
\r
664 SayString(ynum, FALSE);
\r
665 SayString(piece, FALSE);
\r
669 if (fromY+1 < BOARD_HEIGHT && fromX+2 < BOARD_RGHT) {
\r
670 currentpiece = boards[currentMove][fromY+1][fromX+2];
\r
671 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
672 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
673 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
675 piece = PieceToName(currentpiece,1);
\r
676 xchar = SquareToChar(fromX+2);
\r
677 ynum = SquareToNum(fromY+1);
\r
678 SayString(xchar , FALSE);
\r
679 SayString(ynum, FALSE);
\r
680 SayString(piece, FALSE);
\r
684 if (fromY-1 >= 0 && fromX+2 < BOARD_RGHT) {
\r
685 currentpiece = boards[currentMove][fromY-1][fromX+2];
\r
686 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
687 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
688 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
690 piece = PieceToName(currentpiece,1);
\r
691 xchar = SquareToChar(fromX+2);
\r
692 ynum = SquareToNum(fromY-1);
\r
693 SayString(xchar , FALSE);
\r
694 SayString(ynum, FALSE);
\r
695 SayString(piece, FALSE);
\r
699 if (fromY-2 >= 0 && fromX+1 < BOARD_RGHT) {
\r
700 currentpiece = boards[currentMove][fromY-2][fromX+1];
\r
701 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
702 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
703 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
705 piece = PieceToName(currentpiece,1);
\r
706 xchar = SquareToChar(fromX+1);
\r
707 ynum = SquareToNum(fromY-2);
\r
708 SayString(xchar , FALSE);
\r
709 SayString(ynum, FALSE);
\r
710 SayString(piece, FALSE);
\r
714 if (fromY-2 >= 0 && fromX-1 >= BOARD_LEFT) {
\r
715 currentpiece = boards[currentMove][fromY-2][fromX-1];
\r
716 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
717 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
718 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
720 piece = PieceToName(currentpiece,1);
\r
721 xchar = SquareToChar(fromX-1);
\r
722 ynum = SquareToNum(fromY-2);
\r
723 SayString(xchar , FALSE);
\r
724 SayString(ynum, FALSE);
\r
725 SayString(piece, FALSE);
\r
729 if (fromY-1 >= 0 && fromX-2 >= BOARD_LEFT) {
\r
730 currentpiece = boards[currentMove][fromY-1][fromX-2];
\r
731 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
732 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
733 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
735 piece = PieceToName(currentpiece,1);
\r
736 xchar = SquareToChar(fromX-2);
\r
737 ynum = SquareToNum(fromY-1);
\r
738 SayString(xchar , FALSE);
\r
739 SayString(ynum, FALSE);
\r
740 SayString(piece, FALSE);
\r
744 if (fromY+1 < BOARD_HEIGHT && fromX-2 >= BOARD_LEFT) {
\r
745 currentpiece = boards[currentMove][fromY+1][fromX-2];
\r
746 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
747 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
748 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
750 piece = PieceToName(currentpiece,1);
\r
751 xchar = SquareToChar(fromX-2);
\r
752 ynum = SquareToNum(fromY+1);
\r
753 SayString(xchar , FALSE);
\r
754 SayString(ynum, FALSE);
\r
755 SayString(piece, FALSE);
\r
761 SayPieces(ChessSquare p)
\r
763 ChessSquare currentpiece;
\r
764 char *piece, *xchar, *ynum ;
\r
765 int yPos, xPos, count = 0;
\r
768 if(p == WhitePlay) SayString("White pieces", FALSE); else
\r
769 if(p == BlackPlay) SayString("Black pieces", FALSE); else
\r
770 if(p == EmptySquare) SayString("Pieces", FALSE); else {
\r
771 sprintf(buf, "%ss", PieceToName(p,1));
\r
772 SayString(buf, FALSE);
\r
774 SayString("are located", FALSE);
\r
775 for(yPos=0; yPos<BOARD_HEIGHT; yPos++) {
\r
776 for(xPos=BOARD_LEFT; xPos<BOARD_RGHT; xPos++) {
\r
777 currentpiece = boards[currentMove][yPos][xPos];
\r
778 if(p == BlackPlay && currentpiece >= BlackPawn && currentpiece <= BlackKing ||
\r
779 p == WhitePlay && currentpiece >= WhitePawn && currentpiece <= WhiteKing )
\r
780 piece = PieceToName(currentpiece,0);
\r
781 else if(p == EmptySquare && currentpiece != EmptySquare)
\r
782 piece = PieceToName(currentpiece,1);
\r
783 else if(p == currentpiece)
\r
787 if(count == 0) SayString("at", FALSE);
\r
788 xchar = SquareToChar(xPos);
\r
789 ynum = SquareToNum(yPos);
\r
790 SayString(xchar , FALSE);
\r
791 SayString(ynum, FALSE);
\r
792 if(piece) SayString(piece, FALSE);
\r
796 if(count == 0) SayString("nowhere", FALSE);
\r
802 ChessSquare currentpiece;
\r
803 char *piece, *xchar, *ynum ;
\r
804 if(fromX < BOARD_LEFT) { SayString("You strayed into the white holdings", FALSE); return; }
\r
805 if(fromX >= BOARD_RGHT) { SayString("You strayed into the black holdings", FALSE); return; }
\r
806 currentpiece = boards[currentMove][fromY][fromX];
\r
807 piece = PieceToName(currentpiece,1);
\r
808 ynum = SquareToNum(fromY);
\r
809 xchar = SquareToChar(fromX);
\r
810 SayString("Your current position is", FALSE);
\r
811 SayString(xchar, FALSE);
\r
812 SayString(ynum, FALSE);
\r
813 SayString(piece, FALSE);
\r
814 if(((fromX-BOARD_LEFT) ^ fromY)&1)
\r
815 SayString("on a light square",FALSE);
\r
817 SayString("on a dark square",FALSE);
\r
819 PossibleAttacked();
\r
827 ChessSquare currentpiece;
\r
828 char *piece, *ynum ;
\r
830 if(gameInfo.holdingsWidth) {
\r
832 for(Ypos=0; Ypos<gameInfo.holdingsSize; Ypos++) {
\r
833 int n = boards[currentMove][Ypos][BOARD_WIDTH-2];
\r
834 if(n) { char buf[MSG_SIZ];
\r
835 if(!first++) SayString("white holds", FALSE);
\r
836 currentpiece = boards[currentMove][Ypos][BOARD_WIDTH-1];
\r
837 piece = PieceToName(currentpiece,0);
\r
838 sprintf(buf, "%d %s%s", n, piece, (n==1 ? "" : "s") );
\r
839 SayString(buf, FALSE);
\r
843 for(Ypos=BOARD_HEIGHT-1; Ypos>=BOARD_HEIGHT - gameInfo.holdingsSize; Ypos--) {
\r
844 int n = boards[currentMove][Ypos][1];
\r
845 if(n) { char buf[MSG_SIZ];
\r
846 if(!first++) SayString("black holds", FALSE);
\r
847 currentpiece = boards[currentMove][Ypos][0];
\r
848 piece = PieceToName(currentpiece,0);
\r
849 sprintf(buf, "%d %s%s", n, piece, (n==1 ? "" : "s") );
\r
850 SayString(buf, FALSE);
\r
855 for(Ypos=BOARD_HEIGHT-1; Ypos>=0; Ypos--) {
\r
856 ynum = ordinals[Ypos + (gameInfo.boardHeight < 10)];
\r
857 SayString(ynum, FALSE);
\r
858 SayString("rank", FALSE);
\r
859 for(Xpos=BOARD_LEFT; Xpos<BOARD_RGHT; Xpos++) {
\r
860 currentpiece = boards[currentMove][Ypos][Xpos];
\r
861 if(currentpiece != EmptySquare) {
\r
864 piece = PieceToName(currentpiece,1);
\r
865 while(Xpos < BOARD_RGHT && boards[currentMove][Ypos][Xpos] == currentpiece)
\r
868 sprintf(buf, "%d %ss", count, piece);
\r
869 } else sprintf(buf, "%s", piece);
\r
871 SayString(buf, FALSE);
\r
873 int count = 0, oldX = Xpos;
\r
874 while(Xpos < BOARD_RGHT && boards[currentMove][Ypos][Xpos] == EmptySquare)
\r
876 if(Xpos == BOARD_RGHT && oldX == BOARD_LEFT)
\r
877 SayString("all", FALSE);
\r
881 sprintf(buf, "%d", count);
\r
882 SayString(buf, FALSE);
\r
886 SayString("empty", FALSE);
\r
896 if(gameMode == MachinePlaysBlack || gameMode == IcsPlayingBlack) {
\r
897 if(WhiteOnMove(currentMove))
\r
898 SayString("It is your turn", FALSE);
\r
899 else SayString("It is your opponents turn", FALSE);
\r
900 } else if(gameMode == MachinePlaysWhite || gameMode == IcsPlayingWhite) {
\r
901 if(WhiteOnMove(currentMove))
\r
902 SayString("It is your opponents turn", FALSE);
\r
903 else SayString("It is your turn", FALSE);
\r
905 if(WhiteOnMove(currentMove))
\r
906 SayString("White is on move here", FALSE);
\r
907 else SayString("Black is on move here", FALSE);
\r
911 extern char *commentList[];
\r
914 SayMachineMove(int evenIfDuplicate)
\r
916 int len, xPos, yPos, moveNr, secondSpace = 0, castle = 0, n;
\r
917 ChessSquare currentpiece;
\r
918 char *piece, *xchar, *ynum, *p, checkMark = 0;
\r
919 char c, buf[MSG_SIZ], comment[MSG_SIZ];
\r
920 static char disambiguation[2];
\r
921 static int previousMove = 0;
\r
923 if(appData.debugMode) fprintf(debugFP, "Message = '%s'\n", messageText);
\r
924 if(gameMode == BeginningOfGame) return;
\r
925 if(messageText[0] == '[') return;
\r
927 if(isdigit(messageText[0])) { // message is move, possibly with thinking output
\r
928 int dotCount = 0, spaceCount = 0;
\r
929 sscanf(messageText, "%d", &moveNr);
\r
931 // [HGM] show: better extraction of move
\r
932 while (messageText[len] != NULLCHAR) {
\r
933 if(messageText[len] == '.' && spaceCount == 0) dotCount++;
\r
934 if(messageText[len] == ' ') { if(++spaceCount == 2) secondSpace = len; }
\r
935 if(messageText[len] == '{') { // we detected a comment
\r
936 if(isalpha(messageText[len+1]) ) sscanf(messageText+len, "{%[^}]}", comment);
\r
939 if(messageText[len] == '[') { // we detected thinking output
\r
940 int depth; float score=0; char c, lastMover = (dotCount == 3 ? 'B' : 'W');
\r
941 if(sscanf(messageText+len+1, "%d]%c%f", &depth, &c, &score) > 1) {
\r
942 if(c == ' ') { // if not explicitly specified, figure out source of thinking output
\r
944 case MachinePlaysWhite:
\r
945 case IcsPlayingWhite:
\r
947 case IcsPlayingBlack:
\r
948 case MachinePlaysBlack:
\r
954 if(c != lastMover) return; // line is thinking output of future move, ignore.
\r
955 if(2*moveNr - (dotCount < 2) == previousMove)
\r
956 return; // do not repeat same move; likely ponder output
\r
957 sprintf(buf, "score %s %d at %d ply",
\r
958 score > 0 ? "plus" : score < 0 ? "minus" : "",
\r
959 (int) (fabs(score)*100+0.5),
\r
961 SayString(buf, FALSE); // move + thinking output describing it; say it.
\r
963 while(messageText[len-1] == ' ') len--; // position just behind move;
\r
966 if(messageText[len] == '(') { // ICS time printed behind move
\r
967 while(messageText[len+1] && messageText[len] != ')') len++; // skip it
\r
971 if(secondSpace) len = secondSpace; // position behind move
\r
972 if(messageText[len-1] == '+' || messageText[len-1] == '#') { /* you are in checkmate */
\r
973 len--; // strip off check or mate indicator
\r
974 checkMark = messageText[len]; // make sure still seen after we stip off promo piece
\r
976 if(messageText[len-2] == '=') { /* promotion */
\r
977 len-=2; // strip off promotion piece
\r
978 SayString("promotion", FALSE);
\r
981 n = 2*moveNr - (dotCount < 2);
\r
983 if(previousMove != 2*moveNr + (dotCount > 1) || evenIfDuplicate) {
\r
985 previousMove = 2*moveNr + (dotCount > 1); // remember move nr of move last spoken
\r
986 sprintf(number, "%d", moveNr);
\r
988 yPos = CoordToNum(messageText[len-1]); /* turn char coords to ints */
\r
989 xPos = CoordToNum(messageText[len-2]);
\r
990 if(xPos < 0 || xPos > 11) return; // prevent crashes if no coord string available to speak
\r
991 if(yPos < 0 || yPos > 9) return;
\r
992 currentpiece = boards[n][yPos][xPos];
\r
993 piece = PieceToName(currentpiece,0);
\r
994 ynum = SquareToNum(yPos);
\r
995 xchar = SquareToChar(xPos);
\r
996 c = messageText[len-3];
\r
997 if(c == 'x') c = messageText[len-4];
\r
998 if(!isdigit(c) && c < 'a' && c != '@') c = 0;
\r
999 disambiguation[0] = c;
\r
1000 SayString(WhiteOnMove(n) ? "Black" : "White", FALSE);
\r
1001 SayString("move", FALSE);
\r
1002 SayString(number, FALSE);
\r
1003 // if(c==0 || c=='@') SayString("a", FALSE);
\r
1004 // intercept castling moves
\r
1005 p = StrStr(messageText, "O-O-O");
\r
1006 if(p && p-messageText < len) {
\r
1007 SayString("queen side castling",FALSE);
\r
1010 p = StrStr(messageText, "O-O");
\r
1011 if(p && p-messageText < len) {
\r
1012 SayString("king side castling",FALSE);
\r
1017 SayString(piece, FALSE);
\r
1018 if(c == '@') SayString("dropped on", FALSE); else
\r
1019 if(c) SayString(disambiguation, FALSE);
\r
1020 SayString("to", FALSE);
\r
1021 SayString(xchar, FALSE);
\r
1022 SayString(ynum, FALSE);
\r
1023 if(messageText[len-3] == 'x') {
\r
1024 currentpiece = boards[n-1][yPos][xPos];
\r
1025 if(currentpiece != EmptySquare) {
\r
1026 piece = PieceToName(currentpiece,0);
\r
1027 SayString("Capturing a",FALSE);
\r
1028 SayString(piece, FALSE);
\r
1029 } else SayString("Capturing onn passann",FALSE);
\r
1032 if(checkMark == '+') SayString("check", FALSE); else
\r
1033 if(checkMark == '#') {
\r
1034 SayString("finishing off", FALSE);
\r
1035 SayString(WhiteOnMove(n) ? "White" : "Black", FALSE);
\r
1039 /* say comment after move, possibly with result */
\r
1041 if(StrStr(messageText, " 1-0")) p = "white wins"; else
\r
1042 if(StrStr(messageText, " 0-1")) p = "black wins"; else
\r
1043 if(StrStr(messageText, " 1/2-1/2")) p = "game ends in a draw";
\r
1046 if(!StrCaseStr(comment, "draw") &&
\r
1047 !StrCaseStr(comment, "white") &&
\r
1048 !StrCaseStr(comment, "black") ) {
\r
1049 SayString(p, FALSE);
\r
1050 SayString("due to", FALSE);
\r
1053 SayString(comment, FALSE); // alphabetic comment (usually game end)
\r
1054 } else if(p) SayString(p, FALSE);
\r
1056 if(commentDialog && commentList[currentMove]) SetFocus(commentDialog);
\r
1059 /* starts not with digit */
\r
1060 if(StrCaseStr(messageText, "illegal")) PlayIcsUnfinishedSound();
\r
1061 SayString(messageText, FALSE);
\r
1069 char buf1[50], buf2[50];
\r
1070 char *str1, *str2;
\r
1071 static long int lastWhiteTime, lastBlackTime;
\r
1073 suppressClocks = 1; // if user is using alt+T command, no reason to display them
\r
1074 if(abs(lastWhiteTime - whiteTimeRemaining) < 1000 && abs(lastBlackTime - blackTimeRemaining) < 1000)
\r
1075 suppressClocks = 0; // back on after two requests in rapid succession
\r
1076 sprintf(buf1, "%s", TimeString(whiteTimeRemaining));
\r
1078 SayString("White's remaining time is", FALSE);
\r
1079 SayString(str1, FALSE);
\r
1080 sprintf(buf2, "%s", TimeString(blackTimeRemaining));
\r
1082 SayString("Black's remaining time is", FALSE);
\r
1083 SayString(str2, FALSE);
\r
1084 lastWhiteTime = whiteTimeRemaining;
\r
1085 lastBlackTime = blackTimeRemaining;
\r
1089 Toggle(Boolean *b, char *mess)
\r
1092 SayString(mess, FALSE);
\r
1093 SayString("is now", FALSE);
\r
1094 SayString(*b ? "on" : "off", FALSE);
\r
1097 /* handles keyboard moves in a click-click fashion */
\r
1099 KeyboardMove(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
1101 ChessSquare currentpiece;
\r
1104 static BOOLEAN sameAgain = FALSE;
\r
1105 switch (message) {
\r
1107 sameAgain = FALSE;
\r
1108 if(oldFromX == fromX && oldFromY == fromY) {
\r
1110 /* click on same square */
\r
1113 else if(oldFromX != -1) {
\r
1115 ChessSquare pdown, pup;
\r
1116 pdown = boards[currentMove][oldFromY][oldFromX];
\r
1117 pup = boards[currentMove][fromY][fromX];
\r
1119 if (gameMode == EditPosition ||
\r
1120 !((WhitePawn <= pdown && pdown <= WhiteKing &&
\r
1121 WhitePawn <= pup && pup <= WhiteKing) ||
\r
1122 (BlackPawn <= pdown && pdown <= BlackKing &&
\r
1123 BlackPawn <= pup && pup <= BlackKing))) {
\r
1124 /* EditPosition, empty square, or different color piece;
\r
1125 click-click move is possible */
\r
1126 char promoChoice = NULLCHAR;
\r
1128 if (HasPromotionChoice(oldFromX, oldFromY, fromX, fromY, &promoChoice)) {
\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, promoChoice);
\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