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
151 #include "jfwapi.h"
\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 Diagnols\tAlt+U", IDM_SayUpperDiagnols },
\r
192 {"Say &Lower Diagnols\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 DrawMenuBar(hwndMain);
\r
242 { // to be called at beginning of WinMain, after InitApplication and InitInstance
\r
243 HINSTANCE hApi = LoadLibrary("jfwapi32.dll");
\r
245 DisplayInformation("Missing jfwapi32.dll");
\r
249 RealSayString = (PSAYSTRING)GetProcAddress(hApi, "JFWSayString");
\r
250 if(!RealSayString) {
\r
251 DisplayInformation("SayString returned a null pointer");
\r
256 // [HGM] kludge to reduce need for modification of winboard.c: make tinyLayout menu identical
\r
257 // to standard layout, so that code for switching between them does not have to be deleted
\r
261 menuBarText[0][5] = "&JAWS";
\r
262 for(i=0; i<7; i++) menuBarText[1][i] = menuBarText[0][i];
\r
265 hAccelJAWS = CreateAcceleratorTable(acceleratorsJAWS, 14);
\r
267 /* initialize cursor position */
\r
269 SetHighlights(fromX, fromY, -1, -1);
\r
270 DrawPosition(FALSE, NULL);
\r
271 oldFromX = oldFromY = -1;
\r
273 if(hwndConsole) SetFocus(hwndConsole);
\r
278 KeyboardEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
280 ChessSquare currentPiece;
\r
281 char *piece, *xchar, *ynum ;
\r
284 if(fromX == -1 || fromY == -1) {
\r
285 fromX = BOARD_LEFT; fromY = 0;
\r
289 if(fromX == BOARD_RGHT+1) fromX -= 2; else
\r
290 if(fromX == BOARD_LEFT) { if(fromY >= BOARD_HEIGHT - gameInfo.holdingsSize) fromX -= 2; } else
\r
291 if(fromX > BOARD_LEFT) fromX--;
\r
294 if(fromX == BOARD_LEFT-2) fromX += 2; else
\r
295 if(fromX == BOARD_RGHT-1) { if(fromY < gameInfo.holdingsSize) fromX += 2; } else
\r
296 if(fromX < BOARD_RGHT-1) fromX++;
\r
299 if(fromX == BOARD_RGHT+1) { if(fromY < gameInfo.holdingsSize - 1) fromY++; } else
\r
300 if(fromY < BOARD_HEIGHT-1) fromY++;
\r
303 if(fromX == BOARD_LEFT-2) { if(fromY > BOARD_HEIGHT - gameInfo.holdingsSize) fromY--; } else
\r
304 if(fromY > 0) fromY--;
\r
307 SetHighlights(fromX, fromY, -1, -1);
\r
308 DrawPosition(FALSE, NULL);
\r
309 currentPiece = boards[currentMove][fromY][fromX];
\r
310 piece = PieceToName(currentPiece,1);
\r
311 if(currentPiece != EmptySquare) MessageBeep(currentPiece < (int)BlackPawn ? MB_OK : MB_ICONEXCLAMATION);
\r
312 if(fromX == BOARD_LEFT - 2) {
\r
313 SayString("black holdings", FALSE);
\r
314 if(currentPiece != EmptySquare) {
\r
316 n = boards[currentMove][fromY][1];
\r
317 sprintf(buf, "%d %s%s", n, piece+6, n == 1 ? "" : "s");
\r
318 SayString(buf, TRUE);
\r
321 if(fromX == BOARD_RGHT + 1) {
\r
322 SayString("white holdings", FALSE);
\r
323 if(currentPiece != EmptySquare) {
\r
325 n = boards[currentMove][fromY][BOARD_WIDTH-2];
\r
326 sprintf(buf, "%d %s%s", n, piece+6, n == 1 ? "" : "s");
\r
327 SayString(buf, TRUE);
\r
330 if(fromX >= BOARD_LEFT && fromX < BOARD_RGHT) {
\r
332 xchar = SquareToChar(fromX);
\r
333 ynum = SquareToNum(fromY);
\r
334 if(currentPiece != EmptySquare) {
\r
335 // SayString(piece[0] == 'W' ? "white" : "black", TRUE);
\r
336 sprintf(buf, "%s %s %s", piece, xchar, ynum);
\r
337 } else sprintf(buf, "%s %s", xchar, ynum);
\r
338 SayString(buf, TRUE);
\r
343 extern char castlingRights[MAX_MOVES][BOARD_SIZE];
\r
344 int PosFlags(int nr);
\r
347 int rf, ff, rt, ft;
\r
352 extern void ReadCallback P((Board board, int flags, ChessMove kind,
\r
353 int rf, int ff, int rt, int ft,
\r
354 VOIDSTAR closure));
\r
356 void ReadCallback(board, flags, kind, rf, ff, rt, ft, closure)
\r
360 int rf, ff, rt, ft;
\r
363 register ReadClosure *cl = (ReadClosure *) closure;
\r
364 ChessSquare possiblepiece;
\r
365 char *piece, *xchar, *ynum ;
\r
367 //if(appData.debugMode) fprintf(debugFP, "%c%c%c%c\n", ff+AAA, rf+ONE, ft+AAA, rt+ONE);
\r
368 if(cl->ff == ff && cl->rf == rf) {
\r
369 possiblepiece = board[rt][ft];
\r
370 if(possiblepiece != EmptySquare) {
\r
371 piece = PieceToName(possiblepiece,1);
\r
372 xchar = SquareToChar(ft);
\r
373 ynum = SquareToNum(rt);
\r
374 SayString(xchar , FALSE);
\r
375 SayString(ynum, FALSE);
\r
376 SayString(piece, FALSE);
\r
380 if(cl->ft == ft && cl->rt == rt) {
\r
381 possiblepiece = board[rf][ff];
\r
382 piece = PieceToName(possiblepiece,1);
\r
383 xchar = SquareToChar(ff);
\r
384 ynum = SquareToNum(rf);
\r
385 SayString(xchar , FALSE);
\r
386 SayString(ynum, FALSE);
\r
387 SayString(piece, FALSE);
\r
393 PossibleAttackMove()
\r
396 ChessSquare piece, victim;
\r
397 int removedSelectedPiece = 0, swapColor;
\r
399 //if(appData.debugMode) fprintf(debugFP, "PossibleAttackMove %d %d %d %d\n", fromX, fromY, oldFromX, oldFromY);
\r
400 if(fromY < 0 || fromY >= BOARD_HEIGHT) return;
\r
401 if(fromX < BOARD_LEFT || fromX >= BOARD_RGHT) { SayString("holdings",FALSE); return; }
\r
403 piece = boards[currentMove][fromY][fromX];
\r
404 if(piece == EmptySquare) { // if square is empty, try to substitute selected piece
\r
405 if(oldFromX >= 0 && oldFromY >= 0) {
\r
406 piece = boards[currentMove][oldFromY][oldFromX];
\r
407 boards[currentMove][oldFromY][oldFromX] = EmptySquare;
\r
408 removedSelectedPiece = 1;
\r
409 SayString("Your", FALSE);
\r
410 SayString(PieceToName(piece, 0), FALSE);
\r
411 SayString("would have", FALSE);
\r
412 } else { SayString("You must select a piece first", FALSE); return; }
\r
415 victim = boards[currentMove][fromY][fromX];
\r
416 boards[currentMove][fromY][fromX] = piece; // make sure piece is actally there
\r
417 SayString("possible captures from here are", FALSE);
\r
419 swapColor = piece < (int)BlackPawn && !WhiteOnMove(currentMove) ||
\r
420 piece >= (int)BlackPawn && WhiteOnMove(currentMove);
\r
421 cl.count = 0; cl.rf = fromY; cl.ff = fromX; cl.rt = cl.ft = -1;
\r
422 GenLegal(boards[currentMove], PosFlags(currentMove + swapColor), EP_NONE,
\r
423 castlingRights[currentMove], ReadCallback, (VOIDSTAR) &cl);
\r
424 if(cl.count == 0) SayString("None", FALSE);
\r
425 boards[currentMove][fromY][fromX] = victim; // repair
\r
427 if( removedSelectedPiece ) boards[currentMove][oldFromY][oldFromX] = piece;
\r
435 ChessSquare piece = EmptySquare, victim;
\r
437 if(fromY < 0 || fromY >= BOARD_HEIGHT) return;
\r
438 if(fromX < BOARD_LEFT || fromX >= BOARD_RGHT) { SayString("holdings",FALSE); return; }
\r
440 if(oldFromX >= 0 && oldFromY >= 0) { // if piece is selected, remove it
\r
441 piece = boards[currentMove][oldFromY][oldFromX];
\r
442 boards[currentMove][oldFromY][oldFromX] = EmptySquare;
\r
445 SayString("Pieces that can capture you are", FALSE);
\r
447 victim = boards[currentMove][fromY][fromX]; // put dummy piece on target square, to activate Pawn captures
\r
448 boards[currentMove][fromY][fromX] = WhiteOnMove(currentMove) ? WhiteQueen : BlackQueen;
\r
449 cl.count = 0; cl.rt = fromY; cl.ft = fromX; cl.rf = cl.ff = -1;
\r
450 GenLegal(boards[currentMove], PosFlags(currentMove+1), EP_NONE,
\r
451 castlingRights[currentMove], ReadCallback, (VOIDSTAR) &cl);
\r
452 if(cl.count == 0) SayString("None", FALSE);
\r
454 SayString("You are defended by", FALSE);
\r
456 boards[currentMove][fromY][fromX] = WhiteOnMove(currentMove) ? BlackQueen : WhiteQueen;
\r
457 cl.count = 0; cl.rt = fromY; cl.ft = fromX; cl.rf = cl.ff = -1;
\r
458 GenLegal(boards[currentMove], PosFlags(currentMove), EP_NONE,
\r
459 castlingRights[currentMove], ReadCallback, (VOIDSTAR) &cl);
\r
460 if(cl.count == 0) SayString("None", FALSE);
\r
461 boards[currentMove][fromY][fromX] = victim; // put back original occupant
\r
463 if(oldFromX >= 0 && oldFromY >= 0) { // put back possibl selected piece
\r
464 boards[currentMove][oldFromY][oldFromX] = piece;
\r
471 ChessSquare currentpiece;
\r
472 char *piece, *xchar, *ynum ;
\r
474 ynum = SquareToNum(fromY);
\r
476 if(fromY < 0) return;
\r
478 for (xPos=BOARD_LEFT; xPos<BOARD_RGHT; xPos++) {
\r
479 currentpiece = boards[currentMove][fromY][xPos];
\r
480 if(currentpiece != EmptySquare) {
\r
481 piece = PieceToName(currentpiece,1);
\r
482 xchar = SquareToChar(xPos);
\r
483 SayString(xchar , FALSE);
\r
484 SayString(ynum, FALSE);
\r
485 SayString(piece, FALSE);
\r
490 SayString("rank", FALSE);
\r
491 SayString(ynum, FALSE);
\r
492 SayString("empty", FALSE);
\r
499 ChessSquare currentpiece;
\r
500 char *piece, *xchar, *ynum ;
\r
502 xchar = SquareToChar(fromX);
\r
504 if(fromX < 0) return;
\r
506 for (yPos=0; yPos<BOARD_HEIGHT; yPos++) {
\r
507 currentpiece = boards[currentMove][yPos][fromX];
\r
508 if(currentpiece != EmptySquare) {
\r
509 piece = PieceToName(currentpiece,1);
\r
510 ynum = SquareToNum(yPos);
\r
511 SayString(xchar , FALSE);
\r
512 SayString(ynum, FALSE);
\r
513 SayString(piece, FALSE);
\r
518 SayString(xchar, FALSE);
\r
519 SayString("file empty", FALSE);
\r
526 ChessSquare currentpiece;
\r
527 char *piece, *xchar, *ynum ;
\r
530 if(fromX < 0 || fromY < 0) return;
\r
532 if(fromX < BOARD_RGHT-1 && fromY < BOARD_HEIGHT-1) {
\r
533 SayString("The diagnol squares to your upper right contain", FALSE);
\r
536 while(yPos<BOARD_HEIGHT && xPos<BOARD_RGHT) {
\r
537 currentpiece = boards[currentMove][yPos][xPos];
\r
538 piece = PieceToName(currentpiece,1);
\r
539 xchar = SquareToChar(xPos);
\r
540 ynum = SquareToNum(yPos);
\r
541 SayString(xchar , FALSE);
\r
542 SayString(ynum, FALSE);
\r
543 SayString(piece, FALSE);
\r
548 else SayString("There is no squares to your upper right", FALSE);
\r
550 if(fromX > BOARD_LEFT && fromY < BOARD_HEIGHT-1) {
\r
551 SayString("The diagnol squares to your upper left contain", FALSE);
\r
554 while(yPos<BOARD_HEIGHT && xPos>=BOARD_LEFT) {
\r
555 currentpiece = boards[currentMove][yPos][xPos];
\r
556 piece = PieceToName(currentpiece,1);
\r
557 xchar = SquareToChar(xPos);
\r
558 ynum = SquareToNum(yPos);
\r
559 SayString(xchar , FALSE);
\r
560 SayString(ynum, FALSE);
\r
561 SayString(piece, FALSE);
\r
566 else SayString("There is no squares to your upper left", FALSE);
\r
572 ChessSquare currentpiece;
\r
573 char *piece, *xchar, *ynum ;
\r
576 if(fromX < 0 || fromY < 0) return;
\r
578 if(fromX < BOARD_RGHT-1 && fromY > 0) {
\r
579 SayString("The diagnol squares to your lower right contain", FALSE);
\r
582 while(yPos>=0 && xPos<BOARD_RGHT) {
\r
583 currentpiece = boards[currentMove][yPos][xPos];
\r
584 piece = PieceToName(currentpiece,1);
\r
585 xchar = SquareToChar(xPos);
\r
586 ynum = SquareToNum(yPos);
\r
587 SayString(xchar , FALSE);
\r
588 SayString(ynum, FALSE);
\r
589 SayString(piece, FALSE);
\r
594 else SayString("There is no squares to your lower right", FALSE);
\r
596 if(fromX > BOARD_LEFT && fromY > 0) {
\r
597 SayString("The diagnol squares to your lower left contain", FALSE);
\r
600 while(yPos>=0 && xPos>=BOARD_LEFT) {
\r
601 currentpiece = boards[currentMove][yPos][xPos];
\r
602 piece = PieceToName(currentpiece,1);
\r
603 xchar = SquareToChar(xPos);
\r
604 ynum = SquareToNum(yPos);
\r
605 SayString(xchar , FALSE);
\r
606 SayString(ynum, FALSE);
\r
607 SayString(piece, FALSE);
\r
612 else SayString("There is no squares to your lower left", FALSE);
\r
618 ChessSquare currentpiece, oldpiece;
\r
619 char *piece, *xchar, *ynum ;
\r
621 oldpiece = boards[currentMove][fromY][fromX];
\r
622 if(oldpiece == WhiteKnight || oldpiece == BlackKnight)
\r
623 SayString("The possible squares a Knight could move to are", FALSE);
\r
625 SayString("The squares a Knight could possibly attack from are", FALSE);
\r
627 if (fromY+2 < BOARD_HEIGHT && fromX-1 >= BOARD_LEFT) {
\r
628 currentpiece = boards[currentMove][fromY+2][fromX-1];
\r
629 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
630 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
631 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
633 piece = PieceToName(currentpiece,1);
\r
634 xchar = SquareToChar(fromX-1);
\r
635 ynum = SquareToNum(fromY+2);
\r
636 SayString(xchar , FALSE);
\r
637 SayString(ynum, FALSE);
\r
638 SayString(piece, FALSE);
\r
642 if (fromY+2 < BOARD_HEIGHT && fromX+1 < BOARD_RGHT) {
\r
643 currentpiece = boards[currentMove][fromY+2][fromX+1];
\r
644 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
645 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
646 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
648 piece = PieceToName(currentpiece,1);
\r
649 xchar = SquareToChar(fromX+1);
\r
650 ynum = SquareToNum(fromY+2);
\r
651 SayString(xchar , FALSE);
\r
652 SayString(ynum, FALSE);
\r
653 SayString(piece, FALSE);
\r
657 if (fromY+1 < BOARD_HEIGHT && fromX+2 < BOARD_RGHT) {
\r
658 currentpiece = boards[currentMove][fromY+1][fromX+2];
\r
659 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
660 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
661 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
663 piece = PieceToName(currentpiece,1);
\r
664 xchar = SquareToChar(fromX+2);
\r
665 ynum = SquareToNum(fromY+1);
\r
666 SayString(xchar , FALSE);
\r
667 SayString(ynum, FALSE);
\r
668 SayString(piece, FALSE);
\r
672 if (fromY-1 >= 0 && fromX+2 < BOARD_RGHT) {
\r
673 currentpiece = boards[currentMove][fromY-1][fromX+2];
\r
674 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
675 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
676 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
678 piece = PieceToName(currentpiece,1);
\r
679 xchar = SquareToChar(fromX+2);
\r
680 ynum = SquareToNum(fromY-1);
\r
681 SayString(xchar , FALSE);
\r
682 SayString(ynum, FALSE);
\r
683 SayString(piece, FALSE);
\r
687 if (fromY-2 >= 0 && fromX+1 < BOARD_RGHT) {
\r
688 currentpiece = boards[currentMove][fromY-2][fromX+1];
\r
689 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
690 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
691 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
693 piece = PieceToName(currentpiece,1);
\r
694 xchar = SquareToChar(fromX+1);
\r
695 ynum = SquareToNum(fromY-2);
\r
696 SayString(xchar , FALSE);
\r
697 SayString(ynum, FALSE);
\r
698 SayString(piece, FALSE);
\r
702 if (fromY-2 >= 0 && fromX-1 >= BOARD_LEFT) {
\r
703 currentpiece = boards[currentMove][fromY-2][fromX-1];
\r
704 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
705 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
706 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
708 piece = PieceToName(currentpiece,1);
\r
709 xchar = SquareToChar(fromX-1);
\r
710 ynum = SquareToNum(fromY-2);
\r
711 SayString(xchar , FALSE);
\r
712 SayString(ynum, FALSE);
\r
713 SayString(piece, FALSE);
\r
717 if (fromY-1 >= 0 && fromX-2 >= BOARD_LEFT) {
\r
718 currentpiece = boards[currentMove][fromY-1][fromX-2];
\r
719 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
720 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
721 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
723 piece = PieceToName(currentpiece,1);
\r
724 xchar = SquareToChar(fromX-2);
\r
725 ynum = SquareToNum(fromY-1);
\r
726 SayString(xchar , FALSE);
\r
727 SayString(ynum, FALSE);
\r
728 SayString(piece, FALSE);
\r
732 if (fromY+1 < BOARD_HEIGHT && fromX-2 >= BOARD_LEFT) {
\r
733 currentpiece = boards[currentMove][fromY+1][fromX-2];
\r
734 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
735 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
736 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
738 piece = PieceToName(currentpiece,1);
\r
739 xchar = SquareToChar(fromX-2);
\r
740 ynum = SquareToNum(fromY+1);
\r
741 SayString(xchar , FALSE);
\r
742 SayString(ynum, FALSE);
\r
743 SayString(piece, FALSE);
\r
749 SayPieces(ChessSquare p)
\r
751 ChessSquare currentpiece;
\r
752 char *piece, *xchar, *ynum ;
\r
753 int yPos, xPos, count = 0;
\r
756 if(p == WhitePlay) SayString("White pieces", FALSE); else
\r
757 if(p == BlackPlay) SayString("Black pieces", FALSE); else
\r
758 if(p == EmptySquare) SayString("Pieces", FALSE); else {
\r
759 sprintf(buf, "%ss", PieceToName(p,1));
\r
760 SayString(buf, FALSE);
\r
762 SayString("are located", FALSE);
\r
763 for(yPos=0; yPos<BOARD_HEIGHT; yPos++) {
\r
764 for(xPos=BOARD_LEFT; xPos<BOARD_RGHT; xPos++) {
\r
765 currentpiece = boards[currentMove][yPos][xPos];
\r
766 if(p == BlackPlay && currentpiece >= BlackPawn && currentpiece <= BlackKing ||
\r
767 p == WhitePlay && currentpiece >= WhitePawn && currentpiece <= WhiteKing )
\r
768 piece = PieceToName(currentpiece,0);
\r
769 else if(p == EmptySquare && currentpiece != EmptySquare)
\r
770 piece = PieceToName(currentpiece,1);
\r
771 else if(p == currentpiece)
\r
775 if(count == 0) SayString("at", FALSE);
\r
776 xchar = SquareToChar(xPos);
\r
777 ynum = SquareToNum(yPos);
\r
778 SayString(xchar , FALSE);
\r
779 SayString(ynum, FALSE);
\r
780 if(piece) SayString(piece, FALSE);
\r
784 if(count == 0) SayString("nowhere", FALSE);
\r
790 ChessSquare currentpiece;
\r
791 char *piece, *xchar, *ynum ;
\r
792 if(fromX < BOARD_LEFT) { SayString("You strayed into the white holdings", FALSE); return; }
\r
793 if(fromX >= BOARD_RGHT) { SayString("You strayed into the black holdings", FALSE); return; }
\r
794 currentpiece = boards[currentMove][fromY][fromX];
\r
795 piece = PieceToName(currentpiece,1);
\r
796 ynum = SquareToNum(fromY);
\r
797 xchar = SquareToChar(fromX);
\r
798 SayString("Your current position is", FALSE);
\r
799 SayString(xchar, FALSE);
\r
800 SayString(ynum, FALSE);
\r
801 SayString(piece, FALSE);
\r
802 if(((fromX-BOARD_LEFT) ^ fromY)&1)
\r
803 SayString("on a light square",FALSE);
\r
805 SayString("on a dark square",FALSE);
\r
807 PossibleAttacked();
\r
815 ChessSquare currentpiece;
\r
816 char *piece, *xchar, *ynum ;
\r
818 if(gameInfo.holdingsWidth) {
\r
820 for(Ypos=0; Ypos<gameInfo.holdingsSize; Ypos++) {
\r
821 int n = boards[currentMove][Ypos][BOARD_WIDTH-2];
\r
822 if(n) { char buf[MSG_SIZ];
\r
823 if(!first++) SayString("white holds", FALSE);
\r
824 currentpiece = boards[currentMove][Ypos][BOARD_WIDTH-1];
\r
825 piece = PieceToName(currentpiece,0);
\r
826 sprintf(buf, "%d %s%s", n, piece, (n==1 ? "" : "s") );
\r
827 SayString(buf, FALSE);
\r
831 for(Ypos=BOARD_HEIGHT-1; Ypos>=BOARD_HEIGHT - gameInfo.holdingsSize; Ypos--) {
\r
832 int n = boards[currentMove][Ypos][1];
\r
833 if(n) { char buf[MSG_SIZ];
\r
834 if(!first++) SayString("black holds", FALSE);
\r
835 currentpiece = boards[currentMove][Ypos][0];
\r
836 piece = PieceToName(currentpiece,0);
\r
837 sprintf(buf, "%d %s%s", n, piece, (n==1 ? "" : "s") );
\r
838 SayString(buf, FALSE);
\r
843 for(Ypos=BOARD_HEIGHT-1; Ypos>=0; Ypos--) {
\r
844 ynum = ordinals[Ypos + (gameInfo.boardHeight < 10)];
\r
845 SayString(ynum, FALSE);
\r
846 SayString("rank", FALSE);
\r
847 for(Xpos=BOARD_LEFT; Xpos<BOARD_RGHT; Xpos++) {
\r
848 currentpiece = boards[currentMove][Ypos][Xpos];
\r
849 if(currentpiece != EmptySquare) {
\r
850 int count = 0, oldX = Xpos;
\r
852 piece = PieceToName(currentpiece,1);
\r
853 while(Xpos < BOARD_RGHT && boards[currentMove][Ypos][Xpos] == currentpiece)
\r
856 sprintf(buf, "%d %ss", count, piece);
\r
857 } else sprintf(buf, "%s", piece);
\r
859 SayString(buf, FALSE);
\r
861 int count = 0, oldX = Xpos;
\r
862 while(Xpos < BOARD_RGHT && boards[currentMove][Ypos][Xpos] == EmptySquare)
\r
864 if(Xpos == BOARD_RGHT && oldX == BOARD_LEFT)
\r
865 SayString("all", FALSE);
\r
869 sprintf(buf, "%d", count);
\r
870 SayString(buf, FALSE);
\r
874 SayString("empty", FALSE);
\r
884 if(gameMode == MachinePlaysBlack || gameMode == IcsPlayingBlack) {
\r
885 if(WhiteOnMove(currentMove))
\r
886 SayString("It is your turn", FALSE);
\r
887 else SayString("It is your opponents turn", FALSE);
\r
888 } else if(gameMode == MachinePlaysWhite || gameMode == IcsPlayingWhite) {
\r
889 if(WhiteOnMove(currentMove))
\r
890 SayString("It is your opponents turn", FALSE);
\r
891 else SayString("It is your turn", FALSE);
\r
893 if(WhiteOnMove(currentMove))
\r
894 SayString("White is on move here", FALSE);
\r
895 else SayString("Black is on move here", FALSE);
\r
901 SayMachineMove(int evenIfDuplicate)
\r
903 int len, xPos, yPos, moveNr, secondSpace = 0, castle = 0, n;
\r
904 ChessSquare currentpiece;
\r
905 char *piece, *xchar, *ynum, *p;
\r
906 char c, buf[MSG_SIZ], comment[MSG_SIZ];
\r
907 static char disambiguation[2];
\r
908 static int previousMove = 0;
\r
910 if(appData.debugMode) fprintf(debugFP, "Message = '%s'\n", messageText);
\r
911 if(gameMode == BeginningOfGame) return;
\r
912 if(messageText[0] == '[') return;
\r
914 if(isdigit(messageText[0])) { // message is move, possibly with thinking output
\r
915 int dotCount = 0, spaceCount = 0;
\r
916 sscanf(messageText, "%d", &moveNr);
\r
918 // [HGM] show: better extraction of move
\r
919 while (messageText[len] != NULLCHAR) {
\r
920 if(messageText[len] == '.' && spaceCount == 0) dotCount++;
\r
921 if(messageText[len] == ' ') { if(++spaceCount == 2) secondSpace = len; }
\r
922 if(messageText[len] == '{') { // we detected a comment
\r
923 if(isalpha(messageText[len+1]) ) sscanf(messageText+len, "{%[^}]}", comment);
\r
926 if(messageText[len] == '[') { // we detected thinking output
\r
927 int depth; float score=0; char c, lastMover = (dotCount == 3 ? 'B' : 'W');
\r
928 if(sscanf(messageText+len+1, "%d]%c%f", &depth, &c, &score) > 1) {
\r
929 if(c == ' ') { // if not explicitly specified, figure out source of thinking output
\r
931 case MachinePlaysWhite:
\r
932 case IcsPlayingWhite:
\r
934 case IcsPlayingBlack:
\r
935 case MachinePlaysBlack:
\r
941 if(c != lastMover) return; // line is thinking output of future move, ignore.
\r
942 if(2*moveNr - (dotCount < 2) == previousMove)
\r
943 return; // do not repeat same move; likely ponder output
\r
944 sprintf(buf, "score %s %d at %d ply",
\r
945 score > 0 ? "plus" : score < 0 ? "minus" : "",
\r
946 (int) (fabs(score)*100+0.5),
\r
948 SayString(buf, FALSE); // move + thinking output describing it; say it.
\r
950 while(messageText[len-1] == ' ') len--; // position just behind move;
\r
953 if(messageText[len] == '(') { // ICS time printed behind move
\r
954 while(messageText[len+1] && messageText[len] != ')') len++; // skip it
\r
958 if(secondSpace) len = secondSpace; // position behind move
\r
959 if(messageText[len-1] == '+' || messageText[len-1] == '#') { /* you are in checkmate */
\r
960 len--; // strip off check or mate indicator
\r
962 if(messageText[len-2] == '=') { /* promotion */
\r
963 len-=2; // strip off promotion piece
\r
964 SayString("promotion", FALSE);
\r
967 n = 2*moveNr - (dotCount < 2);
\r
969 if(previousMove != 2*moveNr + (dotCount > 1) || evenIfDuplicate) {
\r
971 previousMove = 2*moveNr + (dotCount > 1); // remember move nr of move last spoken
\r
972 sprintf(number, "%d", moveNr);
\r
974 yPos = CoordToNum(messageText[len-1]); /* turn char coords to ints */
\r
975 xPos = CoordToNum(messageText[len-2]);
\r
976 if(xPos < 0 || xPos > 11) return; // prevent crashes if no coord string available to speak
\r
977 if(yPos < 0 || yPos > 9) return;
\r
978 currentpiece = boards[n][yPos][xPos];
\r
979 piece = PieceToName(currentpiece,0);
\r
980 ynum = SquareToNum(yPos);
\r
981 xchar = SquareToChar(xPos);
\r
982 c = messageText[len-3];
\r
983 if(c == 'x') c = messageText[len-4];
\r
984 if(!isdigit(c) && c < 'a' && c != '@') c = 0;
\r
985 disambiguation[0] = c;
\r
986 SayString(WhiteOnMove(n) ? "Black" : "White", FALSE);
\r
987 SayString("move", FALSE);
\r
988 SayString(number, FALSE);
\r
989 // if(c==0 || c=='@') SayString("a", FALSE);
\r
990 // intercept castling moves
\r
991 p = StrStr(messageText, "O-O-O");
\r
992 if(p && p-messageText < len) {
\r
993 SayString("queen side castling",FALSE);
\r
996 p = StrStr(messageText, "O-O");
\r
997 if(p && p-messageText < len) {
\r
998 SayString("king side castling",FALSE);
\r
1003 SayString(piece, FALSE);
\r
1004 if(c == '@') SayString("dropped on", FALSE); else
\r
1005 if(c) SayString(disambiguation, FALSE);
\r
1006 SayString("to", FALSE);
\r
1007 SayString(xchar, FALSE);
\r
1008 SayString(ynum, FALSE);
\r
1009 if(messageText[len-3] == 'x') {
\r
1010 currentpiece = boards[n-1][yPos][xPos];
\r
1011 if(currentpiece != EmptySquare) {
\r
1012 piece = PieceToName(currentpiece,0);
\r
1013 SayString("Capturing a",FALSE);
\r
1014 SayString(piece, FALSE);
\r
1015 } else SayString("Capturing onn passann",FALSE);
\r
1017 if(messageText[len] == '+') SayString("check", FALSE); else
\r
1018 if(messageText[len] == '#') {
\r
1019 SayString("finishing off", FALSE);
\r
1020 SayString(WhiteOnMove(n) ? "White" : "Black", FALSE);
\r
1025 /* say comment after move, possibly with result */
\r
1027 if(StrStr(messageText, " 1-0")) p = "white wins"; else
\r
1028 if(StrStr(messageText, " 0-1")) p = "black wins"; else
\r
1029 if(StrStr(messageText, " 1/2-1/2")) p = "game ends in a draw";
\r
1032 if(!StrCaseStr(comment, "draw") &&
\r
1033 !StrCaseStr(comment, "white") &&
\r
1034 !StrCaseStr(comment, "black") ) {
\r
1035 SayString(p, FALSE);
\r
1036 SayString("due to", FALSE);
\r
1039 SayString(comment, FALSE); // alphabetic comment (usually game end)
\r
1040 } else if(p) SayString(p, FALSE);
\r
1043 /* starts not with digit */
\r
1044 if(StrCaseStr(messageText, "illegal")) PlayIcsUnfinishedSound();
\r
1045 SayString(messageText, FALSE);
\r
1053 char buf1[50], buf2[50];
\r
1054 char *str1, *str2;
\r
1055 static long int lastWhiteTime, lastBlackTime;
\r
1057 suppressClocks = 1; // if user is using alt+T command, no reason to display them
\r
1058 if(abs(lastWhiteTime - whiteTimeRemaining) < 1000 && abs(lastBlackTime - blackTimeRemaining) < 1000)
\r
1059 suppressClocks = 0; // back on after two requests in rapid succession
\r
1060 sprintf(buf1, "%s", TimeString(whiteTimeRemaining));
\r
1062 SayString("White's remaining time is", FALSE);
\r
1063 SayString(str1, FALSE);
\r
1064 sprintf(buf2, "%s", TimeString(blackTimeRemaining));
\r
1066 SayString("Black's remaining time is", FALSE);
\r
1067 SayString(str2, FALSE);
\r
1068 lastWhiteTime = whiteTimeRemaining;
\r
1069 lastBlackTime = blackTimeRemaining;
\r
1073 Toggle(Boolean *b, char *mess)
\r
1076 SayString(mess, FALSE);
\r
1077 SayString("is now", FALSE);
\r
1078 SayString(*b ? "on" : "off", FALSE);
\r
1081 /* handles keyboard moves in a click-click fashion */
\r
1083 KeyboardMove(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
1085 ChessSquare currentpiece;
\r
1088 static BOOLEAN sameAgain = FALSE;
\r
1089 switch (message) {
\r
1091 sameAgain = FALSE;
\r
1092 if(oldFromX == fromX && oldFromY == fromY) {
\r
1094 /* click on same square */
\r
1097 else if(oldFromX != -1) {
\r
1099 ChessSquare pdown, pup;
\r
1100 pdown = boards[currentMove][oldFromY][oldFromX];
\r
1101 pup = boards[currentMove][fromY][fromX];
\r
1103 if (gameMode == EditPosition ||
\r
1104 !((WhitePawn <= pdown && pdown <= WhiteKing &&
\r
1105 WhitePawn <= pup && pup <= WhiteKing) ||
\r
1106 (BlackPawn <= pdown && pdown <= BlackKing &&
\r
1107 BlackPawn <= pup && pup <= BlackKing))) {
\r
1108 /* EditPosition, empty square, or different color piece;
\r
1109 click-click move is possible */
\r
1111 if (IsPromotion(oldFromX, oldFromY, fromX, fromY)) {
\r
1112 if (appData.alwaysPromoteToQueen) {
\r
1113 UserMoveEvent(oldFromX, oldFromY, fromX, fromY, 'q');
\r
1116 toX = fromX; toY = fromY; fromX = oldFromX; fromY = oldFromY;
\r
1117 PromotionPopup(hwnd);
\r
1118 fromX = toX; fromY = toY;
\r
1122 UserMoveEvent(oldFromX, oldFromY, fromX, fromY, NULLCHAR);
\r
1124 oldFromX = oldFromY = -1;
\r
1129 /* First downclick, or restart on a square with same color piece */
\r
1130 if (OKToStartUserMove(fromX, fromY)) {
\r
1133 currentpiece = boards[currentMove][fromY][fromX];
\r
1134 piece = PieceToName(currentpiece,1);
\r
1135 SayString(piece, FALSE);
\r
1136 SayString("selected", FALSE);
\r
1139 oldFromX = oldFromY = -1;
\r
1144 if (oldFromX == fromX && oldFromY == fromY) {
\r
1145 /* Upclick on same square */
\r
1147 /* Clicked same square twice: abort click-click move */
\r
1148 oldFromX = oldFromY = -1;
\r
1149 currentpiece = boards[currentMove][fromY][fromX];
\r
1150 piece = PieceToName(currentpiece,0);
\r
1151 SayString(piece, FALSE);
\r
1152 SayString("unselected", FALSE);
\r
1160 { // return TRUE for times we want to announce
\r
1162 x = (x+50)/100; // tenth of seconds
\r
1163 if(x <= 100) return (x%10 == 0);
\r
1164 if(x <= 600) return (x%100 == 0);
\r
1165 if(x <= 6000) return (x%600 == 0);
\r
1166 return (x%3000 == 0);
\r
1170 if(isalpha((char)wParam)) {
\r
1171 /* capitals of any ind are intercepted and distinguished by left and right shift */
\r
1172 int mine = GetKeyState(VK_RSHIFT) < 0;
\r
1173 if(mine || GetKeyState(VK_LSHIFT) < 0) {
\r
1176 #define JAWS_ALT_INTERCEPT \
\r
1177 if(suppressOneKey) {\
\r
1178 suppressOneKey = 0;\
\r
1179 if(GetKeyState(VK_MENU) < 0 && GetKeyState(VK_CONTROL) < 0) break;\
\r
1181 if ((char)wParam == 022 && gameMode == EditPosition) { /* <Ctl R>. Pop up piece menu */\
\r
1182 POINT pt; int x, y;\
\r
1183 SquareToPos(fromY, fromX, &x, &y);\
\r
1184 pt.x = x; pt.y = y;\
\r
1185 if(gameInfo.variant != VariantShogi)\
\r
1186 MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1);\
\r
1188 MenuPopup(hwnd, pt, LoadMenu(hInst, "ShogiPieceMenu"), -1);\
\r
1192 #define JAWS_REPLAY \
\r
1193 case '\020': /* ctrl P */\
\r
1194 { char buf[MSG_SIZ];\
\r
1195 if(GetWindowText(hwnd, buf, MSG_SIZ-1))\
\r
1196 SayString(buf, FALSE);\
\r
1200 #define JAWS_KB_NAVIGATION \
\r
1204 if(GetKeyState(VK_MENU) < 0 && GetKeyState(VK_CONTROL) < 0) {\
\r
1205 /* Control + Alt + letter used for speaking piece positions */\
\r
1206 static int lastTime; static char lastChar;\
\r
1207 int mine = 0, time = GetTickCount(); char c;\
\r
1209 if((char)wParam == lastChar && time-lastTime < 250) mine = 1;\
\r
1210 lastChar = wParam; lastTime = time;\
\r
1213 if(gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) mine = !mine;\
\r
1215 if(ToLower(c) == 'x') {\
\r
1216 SayPieces(mine ? WhitePlay : BlackPlay);\
\r
1217 suppressOneKey = 1;\
\r
1220 if(CharToPiece(c) != EmptySquare) {\
\r
1221 SayPieces(CharToPiece(mine ? ToUpper(c) : ToLower(c)));\
\r
1222 suppressOneKey = 1;\
\r
1227 switch (wParam) {\
\r
1232 KeyboardEvent(hwnd, message, wParam, lParam);\
\r
1235 KeyboardMove(hwnd, message, wParam, lParam);\
\r
1240 switch (wParam) {\
\r
1242 KeyboardMove(hwnd, message, wParam, lParam);\
\r
1247 #define JAWS_MENU_ITEMS \
\r
1248 case IDM_PossibleAttackMove: /*What can I possible attack from here */\
\r
1249 PossibleAttackMove();\
\r
1252 case IDM_PossibleAttacked: /*what can possible attack this square*/\
\r
1253 PossibleAttacked();\
\r
1256 case IDM_ReadRow: /* Read the current row of pieces */\
\r
1260 case IDM_ReadColumn: /* Read the current column of pieces */\
\r
1264 case IDM_SayCurrentPos: /* Say current position including color */\
\r
1268 case IDM_SayAllBoard: /* Say the whole board from bottom to top */\
\r
1272 case IDM_SayMachineMove: /* Say the last move made */\
\r
1274 SayMachineMove(1);\
\r
1277 case IDM_SayUpperDiagnols: /* Says the diagnol positions above you */\
\r
1278 SayUpperDiagnols();\
\r
1281 case IDM_SayLowerDiagnols: /* Say the diagnol positions below you */\
\r
1282 SayLowerDiagnols();\
\r
1285 case IDM_SayBlackPieces: /*Say the opponents pieces */\
\r
1286 SayPieces(BlackPlay);\
\r
1289 case IDM_SayWhitePieces: /*Say the opponents pieces */\
\r
1290 SayPieces(WhitePlay);\
\r
1293 case IDM_SayClockTime: /*Say the clock time */\
\r
1297 case IDM_SayWhosTurn: /* Say whos turn it its */\
\r
1301 case IDM_SayKnightMoves: /* Say Knights (L-shaped) move */\
\r
1302 SayKnightMoves();\
\r
1305 case OPT_PonderNextMove: /* Toggle option setting */\
\r
1306 Toggle(&appData.ponderNextMove, "ponder");\
\r
1309 case OPT_AnimateMoving: /* Toggle option setting */\
\r
1310 Toggle(&appData.animate, "animate moving");\
\r
1313 case OPT_AutoFlag: /* Toggle option setting */\
\r
1314 Toggle(&appData.autoCallFlag, "auto flag");\
\r
1317 case OPT_AlwaysQueen: /* Toggle option setting */\
\r
1318 Toggle(&appData.alwaysPromoteToQueen, "always promote to queen");\
\r
1321 case OPT_TestLegality: /* Toggle option setting */\
\r
1322 Toggle(&appData.testLegality, "legality testing");\
\r
1325 case OPT_HideThinkFromHuman: /* Toggle option setting */\
\r
1326 Toggle(&appData.hideThinkingFromHuman, "hide thinking");\
\r
1327 ShowThinkingEvent();\
\r
1330 case OPT_SaveExtPGN: /* Toggle option setting */\
\r
1331 Toggle(&appData.saveExtendedInfoInPGN, "extended P G N info");\
\r
1334 case OPT_ExtraInfoInMoveHistory: /* Toggle option setting */\
\r
1335 Toggle(&appData.showEvalInMoveHistory, "extra info in move histoty");\
\r
1340 #define JAWS_ACCEL \
\r
1341 !(!frozen && TranslateAccelerator(hwndMain, hAccelJAWS, &msg)) &&
\r
1343 #define JAWS_INIT if (!InitJAWS()) return (FALSE);
\r
1345 #define JAWS_DELETE(X)
\r
1347 #define JAWS_SILENCE if(suppressClocks) return;
\r
1349 #define JAWS_COPYRIGHT \
\r
1350 SetDlgItemText(hDlg, OPT_MESS, "Auditory/Keyboard Enhancements By: Ed Rodriguez (sort of)");
\r
1352 #define SAY(S) SayString((S), FALSE)
\r
1354 #define SAYMACHINEMOVE() SayMachineMove(0)
\r
1356 // After inclusion of this file somewhere early in winboard.c, the remaining part of the patch
\r
1357 // is scattered over winboard.c for actually calling the routines.
\r