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, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Free
\r
9 * Software Foundation, Inc.
\r
11 * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,
\r
12 * which was written and is copyrighted by Wayne Christopher.
\r
14 * The following terms apply to Digital Equipment Corporation's copyright
\r
15 * interest in XBoard:
\r
16 * ------------------------------------------------------------------------
\r
17 * All Rights Reserved
\r
19 * Permission to use, copy, modify, and distribute this software and its
\r
20 * documentation for any purpose and without fee is hereby granted,
\r
21 * provided that the above copyright notice appear in all copies and that
\r
22 * both that copyright notice and this permission notice appear in
\r
23 * supporting documentation, and that the name of Digital not be
\r
24 * used in advertising or publicity pertaining to distribution of the
\r
25 * software without specific, written prior permission.
\r
27 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
\r
28 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
\r
29 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
\r
30 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
\r
31 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
\r
32 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
\r
34 * ------------------------------------------------------------------------
\r
36 * The following terms apply to the enhanced version of XBoard
\r
37 * distributed by the Free Software Foundation:
\r
38 * ------------------------------------------------------------------------
\r
40 * GNU XBoard is free software: you can redistribute it and/or modify
\r
41 * it under the terms of the GNU General Public License as published by
\r
42 * the Free Software Foundation, either version 3 of the License, or (at
\r
43 * your option) any later version.
\r
45 * GNU XBoard is distributed in the hope that it will be useful, but
\r
46 * WITHOUT ANY WARRANTY; without even the implied warranty of
\r
47 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
48 * General Public License for more details.
\r
50 * You should have received a copy of the GNU General Public License
\r
51 * along with this program. If not, see http://www.gnu.org/licenses/. *
\r
53 *------------------------------------------------------------------------
\r
54 ** See the file ChangeLog for a revision history. */
\r
56 // This file collects all patches for the JAWS version, so they can all be included in winboard.c
\r
57 // in one big swoop. At the bottom of this file you can read instructions for how to patch
\r
58 // WinBoard to work with JAWS with the aid of this file. Note that the code in this file
\r
59 // is for WinBoard 4.3 and later; for older WB versions you would have to throw out the
\r
60 // piece names for all pieces from Guard to Unicorn, #define ONE as '1', AAA as 'a',
\r
61 // BOARD_LEFT as 0, BOARD_RGHT and BOARD_HEIGHT as 8, and set holdingssizes to 0.
\r
62 // You will need to build with jaws.rc in stead of winboard.rc.
\r
66 #define IDM_PossibleAttackMove 1800
\r
67 #define IDM_PossibleAttacked 1801
\r
68 #define IDM_SayMachineMove 1802
\r
69 #define IDM_ReadRow 1803
\r
70 #define IDM_ReadColumn 1804
\r
71 #define IDM_SayCurrentPos 1805
\r
72 #define IDM_SayAllBoard 1806
\r
73 #define IDM_SayUpperDiagnols 1807
\r
74 #define IDM_SayLowerDiagnols 1808
\r
75 #define IDM_SayClockTime 1810
\r
76 #define IDM_SayWhosTurn 1811
\r
77 #define IDM_SayKnightMoves 1812
\r
78 #define ID_SHITTY_HI 1813
\r
79 #define IDM_SayWhitePieces 1816
\r
80 #define IDM_SayBlackPieces 1817
\r
83 // from common.h, but 'extern' added to it, so the actual declaraton can remain in backend.c
\r
85 extern long whiteTimeRemaining, blackTimeRemaining, timeControl, timeIncrement;
\r
87 // from moves.c, added WinBoard_F piece types and ranks / files
\r
89 char *squareToChar[] = { "ay", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l" };
\r
91 char *squareToNum[] = {"naught", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
\r
93 char *ordinals[] = {"zeroth", "first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "nineth"};
\r
95 char *pieceToName[] = {
\r
96 "White Pawn", "White Knight", "White Bishop", "White Rook", "White Queen",
\r
97 "White Guard", "White Elephant", "White Arch Bishop", "White Chancellor",
\r
98 "White General", "White Man", "White Cannon", "White Night Rider",
\r
99 "White Crowned Bishop", "White Crowned Rook", "White Grass Hopper", "White Veteran",
\r
100 "White Falcon", "White Amazon", "White Snake", "White Unicorn",
\r
102 "Black Pawn", "Black Knight", "Black Bishop", "Black Rook", "Black Queen",
\r
103 "Black Guard", "Black Elephant", "Black Arch Bishop", "Black Chancellor",
\r
104 "Black General", "Black Man", "Black Cannon", "Black Night Rider",
\r
105 "Black Crowned Bishop", "Black Crowned Rook", "Black Grass Hopper", "Black Veteran",
\r
106 "Black Falcon", "Black Amazon", "Black Snake", "Black Unicorn",
\r
111 char *pieceTypeName[] = {
\r
112 "Pawn", "Knight", "Bishop", "Rook", "Queen",
\r
113 "Guard", "Elephant", "Arch Bishop", "Chancellor",
\r
114 "General", "Man", "Cannon", "Night Rider",
\r
115 "Crowned Bishop", "Crowned Rook", "Grass Hopper", "Veteran",
\r
116 "Falcon", "Amazon", "Snake", "Unicorn",
\r
118 "Pawn", "Knight", "Bishop", "Rook", "Queen",
\r
119 "Guard", "Elephant", "Arch Bishop", "Chancellor",
\r
120 "General", "Man", "Cannon", "Night Rider",
\r
121 "Crowned Bishop", "Crowned Rook", "Grass Hopper", "Veteran",
\r
122 "Falcon", "Amazon", "Snake", "Unicorn",
\r
130 if(isdigit(c)) return c - ONE;
\r
131 if(c >= 'a') return c - AAA;
\r
135 char* PieceToName(p, i)
\r
139 if(i) return pieceToName[(int) p];
\r
140 return pieceTypeName[(int) p];
\r
143 char* SquareToChar(x)
\r
146 return squareToChar[x - BOARD_LEFT];
\r
149 char* SquareToNum(y)
\r
152 return squareToNum[y + (gameInfo.boardHeight < 10)];
\r
156 // from winboard.c: all new routines
\r
157 #define JFWAPI __declspec(dllimport)
\r
158 JFWAPI BOOL WINAPI JFWSayString (LPCTSTR lpszStrinToSpeak, BOOL bInterrupt);
\r
160 typedef JFWAPI BOOL (WINAPI *PSAYSTRING)(LPCTSTR lpszStrinToSpeak, BOOL bInterrupt);
\r
162 PSAYSTRING RealSayString;
\r
164 VOID SayString(char *mess, BOOL flag)
\r
165 { // for debug file
\r
166 static char buf[8000], *p;
\r
167 int l = strlen(buf);
\r
168 if(appData.debugMode) fprintf(debugFP, "SAY '%s'\n", mess);
\r
169 if(l) buf[l++] = ' '; // separate by space from previous
\r
170 safeStrCpy(buf+l, _(mess), 8000-1-l); // buffer
\r
171 if(!flag) return; // wait for flush
\r
172 if(p = StrCaseStr(buf, "Xboard adjudication:")) {
\r
174 for(i=19; i>1; i--) p[i] = p[i-1];
\r
177 RealSayString(buf, !strcmp(mess, " ")); // kludge to indicate flushing of interruptable speach
\r
178 if(appData.debugMode) fprintf(debugFP, "SPEAK '%s'\n", buf);
\r
182 //static int fromX = 0, fromY = 0;
\r
183 static int oldFromX, oldFromY;
\r
184 static int timeflag;
\r
185 static int suppressClocks = 0;
\r
186 static int suppressOneKey = 0;
\r
187 static HANDLE hAccelJAWS;
\r
189 typedef struct { char *name; int code; } MenuItemDesc;
\r
191 MenuItemDesc menuItemJAWS[] = {
\r
192 {"Say Clock &Time\tAlt+T", IDM_SayClockTime },
\r
194 {"Say Last &Move\tAlt+M", IDM_SayMachineMove },
\r
195 {"Say W&ho's Turn\tAlt+X", IDM_SayWhosTurn },
\r
197 {"Say Complete &Position\tAlt+P",IDM_SayAllBoard },
\r
198 {"Say &White Pieces\tAlt+W", IDM_SayWhitePieces },
\r
199 {"Say &Black Pieces\tAlt+B", IDM_SayBlackPieces },
\r
200 {"Say Board &Rank\tAlt+R", IDM_ReadRow },
\r
201 {"Say Board &File\tAlt+F", IDM_ReadColumn },
\r
203 {"Say &Upper Diagonals\tAlt+U", IDM_SayUpperDiagnols },
\r
204 {"Say &Lower Diagonals\tAlt+L", IDM_SayLowerDiagnols },
\r
205 {"Say K&night Moves\tAlt+N", IDM_SayKnightMoves },
\r
206 {"Say Current &Square\tAlt+S", IDM_SayCurrentPos },
\r
207 {"Say &Attacks\tAlt+A", IDM_PossibleAttackMove },
\r
208 {"Say Attacke&d\tAlt+D", IDM_PossibleAttacked },
\r
212 ACCEL acceleratorsJAWS[] = {
\r
213 {FVIRTKEY|FALT, 'T', IDM_SayClockTime },
\r
214 {FVIRTKEY|FALT, 'M', IDM_SayMachineMove },
\r
215 {FVIRTKEY|FALT, 'X', IDM_SayWhosTurn },
\r
216 {FVIRTKEY|FALT, 'P', IDM_SayAllBoard },
\r
217 {FVIRTKEY|FALT, 'W', IDM_SayWhitePieces },
\r
218 {FVIRTKEY|FALT, 'B', IDM_SayBlackPieces },
\r
219 {FVIRTKEY|FALT, 'R', IDM_ReadRow },
\r
220 {FVIRTKEY|FALT, 'F', IDM_ReadColumn },
\r
221 {FVIRTKEY|FALT, 'U', IDM_SayUpperDiagnols },
\r
222 {FVIRTKEY|FALT, 'L', IDM_SayLowerDiagnols },
\r
223 {FVIRTKEY|FALT, 'N', IDM_SayKnightMoves },
\r
224 {FVIRTKEY|FALT, 'S', IDM_SayCurrentPos },
\r
225 {FVIRTKEY|FALT, 'A', IDM_PossibleAttackMove },
\r
226 {FVIRTKEY|FALT, 'D', IDM_PossibleAttacked }
\r
232 HMENU menuMain, menuJAWS;
\r
233 MENUBARINFO helpMenuInfo;
\r
236 helpMenuInfo.cbSize = sizeof(helpMenuInfo);
\r
237 menuMain = GetMenu(hwndMain);
\r
238 menuJAWS = CreatePopupMenu();
\r
240 for(i=0; menuItemJAWS[i].name; i++) {
\r
241 if(menuItemJAWS[i].name[0] == '-')
\r
242 AppendMenu(menuJAWS, MF_SEPARATOR, (UINT_PTR) 0, NULL);
\r
243 else AppendMenu(menuJAWS, MF_ENABLED|MF_STRING,
\r
244 (UINT_PTR) menuItemJAWS[i].code, (LPCTSTR) _(menuItemJAWS[i].name));
\r
246 InsertMenu(menuMain, 7, MF_BYPOSITION|MF_POPUP|MF_ENABLED|MF_STRING,
\r
247 (UINT_PTR) menuJAWS, "&JAWS");
\r
248 oldMenuItemState[8] = oldMenuItemState[7];
\r
249 DrawMenuBar(hwndMain);
\r
254 { // to be called at beginning of WinMain, after InitApplication and InitInstance
\r
255 HINSTANCE hApi = LoadLibrary("jfwapi32.dll");
\r
257 DisplayInformation("Missing jfwapi32.dll");
\r
261 RealSayString = (PSAYSTRING)GetProcAddress(hApi, "JFWSayString");
\r
262 if(!RealSayString) {
\r
263 DisplayInformation("SayString returned a null pointer");
\r
268 // [HGM] kludge to reduce need for modification of winboard.c: make tinyLayout menu identical
\r
269 // to standard layout, so that code for switching between them does not have to be deleted
\r
273 menuBarText[0][8] = menuBarText[0][7]; menuBarText[0][7] = "&JAWS";
\r
274 for(i=0; i<9; i++) menuBarText[2][i] = menuBarText[1][i] = menuBarText[0][i];
\r
277 hAccelJAWS = CreateAcceleratorTable(acceleratorsJAWS, 14);
\r
279 /* initialize cursor position */
\r
281 SetHighlights(fromX, fromY, -1, -1);
\r
282 DrawPosition(FALSE, NULL);
\r
283 oldFromX = oldFromY = -1;
\r
285 if(hwndConsole) SetFocus(hwndConsole);
\r
289 int beeps[] = { 1, 0, 0, 0, 0 };
\r
290 int beepCodes[] = { 0, MB_OK, MB_ICONERROR, MB_ICONQUESTION, MB_ICONEXCLAMATION, MB_ICONASTERISK };
\r
291 static int dropX = -1, dropY = -1;
\r
294 KeyboardEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
296 ChessSquare currentPiece;
\r
297 char *piece, *xchar, *ynum ;
\r
298 int n, beepType = 1; // empty beep
\r
300 if(fromX == -1 || fromY == -1) { // if we just dropped piece, stay at that square
\r
301 fromX = dropX; fromY = dropY;
\r
302 dropX = dropY = -1; // but only once
\r
304 if(fromX == -1 || fromY == -1) {
\r
305 fromX = BOARD_LEFT; fromY = 0;
\r
309 if(fromX == BOARD_RGHT+1) fromX -= 2; else
\r
310 if(fromX == BOARD_LEFT) { if(fromY >= BOARD_HEIGHT - gameInfo.holdingsSize) fromX -= 2; else beepType = 0; } else
\r
311 if(fromX > BOARD_LEFT) fromX--; else beepType = 0; // off-board beep
\r
314 if(fromX == BOARD_LEFT-2) fromX += 2; else
\r
315 if(fromX == BOARD_RGHT-1) { if(fromY < gameInfo.holdingsSize) fromX += 2; else beepType = 0; } else
\r
316 if(fromX < BOARD_RGHT-1) fromX++; else beepType = 0;
\r
319 if(fromX == BOARD_RGHT+1) { if(fromY < gameInfo.holdingsSize - 1) fromY++; else beepType = 0; } else
\r
320 if(fromY < BOARD_HEIGHT-1) fromY++; else beepType = 0;
\r
323 if(fromX == BOARD_LEFT-2) { if(fromY > BOARD_HEIGHT - gameInfo.holdingsSize) fromY--; else beepType = 0; } else
\r
324 if(fromY > 0) fromY--; else beepType = 0;
\r
327 SetHighlights(fromX, fromY, -1, -1);
\r
328 DrawPosition(FALSE, NULL);
\r
329 currentPiece = boards[currentMove][fromY][fromX];
\r
330 piece = PieceToName(currentPiece,1);
\r
331 if(beepType == 1 && currentPiece != EmptySquare) beepType = currentPiece < (int) BlackPawn ? 2 : 3; // white or black beep
\r
332 if(beeps[beepType] == beeps[1] && (fromX == BOARD_RGHT+1 || fromX == BOARD_LEFT-2)) beepType = 4; // holdings beep
\r
333 beepType = beeps[beepType]%6;
\r
334 if(beepType) MessageBeep(beepCodes[beepType]);
\r
335 if(fromX == BOARD_LEFT - 2) {
\r
336 SayString("black holdings", FALSE);
\r
337 if(currentPiece != EmptySquare) {
\r
339 n = boards[currentMove][fromY][1];
\r
340 snprintf(buf, MSG_SIZ, "%d %s%s", n, PieceToName(currentPiece,0), n == 1 ? "" : "s");
\r
341 SayString(buf, FALSE);
\r
343 SayString(" ", TRUE);
\r
345 if(fromX == BOARD_RGHT + 1) {
\r
346 SayString("white holdings", FALSE);
\r
347 if(currentPiece != EmptySquare) {
\r
349 n = boards[currentMove][fromY][BOARD_WIDTH-2];
\r
350 snprintf(buf, MSG_SIZ,"%d %s%s", n, PieceToName(currentPiece,0), n == 1 ? "" : "s");
\r
351 SayString(buf, FALSE);
\r
353 SayString(" ", TRUE);
\r
355 if(fromX >= BOARD_LEFT && fromX < BOARD_RGHT) {
\r
357 xchar = SquareToChar(fromX);
\r
358 ynum = SquareToNum(fromY);
\r
359 if(currentPiece != EmptySquare) {
\r
360 snprintf(buf, MSG_SIZ, "%s %s %s", xchar, ynum, piece);
\r
361 } else snprintf(buf, MSG_SIZ, "%s %s", xchar, ynum);
\r
362 SayString(buf, FALSE);
\r
363 SayString(" ", TRUE);
\r
368 int PosFlags(int nr);
\r
371 int rf, ff, rt, ft;
\r
376 extern void ReadCallback P((Board board, int flags, ChessMove kind,
\r
377 int rf, int ff, int rt, int ft,
\r
378 VOIDSTAR closure));
\r
380 void ReadCallback(board, flags, kind, rf, ff, rt, ft, closure)
\r
384 int rf, ff, rt, ft;
\r
387 register ReadClosure *cl = (ReadClosure *) closure;
\r
388 ChessSquare possiblepiece;
\r
389 char *piece, *xchar, *ynum ;
\r
391 //if(appData.debugMode) fprintf(debugFP, "%c%c%c%c\n", ff+AAA, rf+ONE, ft+AAA, rt+ONE);
\r
392 if(cl->ff == ff && cl->rf == rf) {
\r
393 possiblepiece = board[rt][ft];
\r
394 if(possiblepiece != EmptySquare) {
\r
395 piece = PieceToName(possiblepiece,1);
\r
396 xchar = SquareToChar(ft);
\r
397 ynum = SquareToNum(rt);
\r
398 SayString(xchar , FALSE);
\r
399 SayString(ynum, FALSE);
\r
400 SayString(piece, FALSE);
\r
404 if(cl->ft == ft && cl->rt == rt) {
\r
405 possiblepiece = board[rf][ff];
\r
406 piece = PieceToName(possiblepiece,1);
\r
407 xchar = SquareToChar(ff);
\r
408 ynum = SquareToNum(rf);
\r
409 SayString(xchar , FALSE);
\r
410 SayString(ynum, FALSE);
\r
411 SayString(piece, FALSE);
\r
417 PossibleAttackMove()
\r
420 ChessSquare piece, victim;
\r
421 int removedSelectedPiece = 0, swapColor;
\r
423 //if(appData.debugMode) fprintf(debugFP, "PossibleAttackMove %d %d %d %d\n", fromX, fromY, oldFromX, oldFromY);
\r
424 if(fromY < 0 || fromY >= BOARD_HEIGHT) return;
\r
425 if(fromX < BOARD_LEFT || fromX >= BOARD_RGHT) { SayString("holdings",TRUE); return; }
\r
427 piece = boards[currentMove][fromY][fromX];
\r
428 if(piece == EmptySquare) { // if square is empty, try to substitute selected piece
\r
429 if(oldFromX >= 0 && oldFromY >= 0) {
\r
430 piece = boards[currentMove][oldFromY][oldFromX];
\r
431 boards[currentMove][oldFromY][oldFromX] = EmptySquare;
\r
432 removedSelectedPiece = 1;
\r
433 SayString("Your", FALSE);
\r
434 SayString(PieceToName(piece, 0), FALSE);
\r
435 SayString("would have", FALSE);
\r
436 } else { SayString("You must select a piece first", TRUE); return; }
\r
439 victim = boards[currentMove][fromY][fromX];
\r
440 boards[currentMove][fromY][fromX] = piece; // make sure piece is actally there
\r
441 SayString("possible captures from here are", FALSE);
\r
443 swapColor = piece < (int)BlackPawn && !WhiteOnMove(currentMove) ||
\r
444 piece >= (int)BlackPawn && WhiteOnMove(currentMove);
\r
445 cl.count = 0; cl.rf = fromY; cl.ff = fromX; cl.rt = cl.ft = -1;
\r
446 GenLegal(boards[currentMove], PosFlags(currentMove + swapColor), ReadCallback, (VOIDSTAR) &cl);
\r
447 if(cl.count == 0) SayString("None", FALSE);
\r
448 SayString("", TRUE); // flush
\r
449 boards[currentMove][fromY][fromX] = victim; // repair
\r
451 if( removedSelectedPiece ) boards[currentMove][oldFromY][oldFromX] = piece;
\r
459 ChessSquare piece = EmptySquare, victim;
\r
461 if(fromY < 0 || fromY >= BOARD_HEIGHT) return;
\r
462 if(fromX < BOARD_LEFT || fromX >= BOARD_RGHT) { SayString("holdings",TRUE); return; }
\r
464 if(oldFromX >= 0 && oldFromY >= 0) { // if piece is selected, remove it
\r
465 piece = boards[currentMove][oldFromY][oldFromX];
\r
466 boards[currentMove][oldFromY][oldFromX] = EmptySquare;
\r
469 SayString("Pieces that can capture you are", FALSE);
\r
471 victim = boards[currentMove][fromY][fromX]; // put dummy piece on target square, to activate Pawn captures
\r
472 boards[currentMove][fromY][fromX] = WhiteOnMove(currentMove) ? WhiteQueen : BlackQueen;
\r
473 cl.count = 0; cl.rt = fromY; cl.ft = fromX; cl.rf = cl.ff = -1;
\r
474 GenLegal(boards[currentMove], PosFlags(currentMove+1), ReadCallback, (VOIDSTAR) &cl);
\r
475 if(cl.count == 0) SayString("None", FALSE);
\r
477 SayString("You are defended by", FALSE);
\r
479 boards[currentMove][fromY][fromX] = WhiteOnMove(currentMove) ? BlackQueen : WhiteQueen;
\r
480 cl.count = 0; cl.rt = fromY; cl.ft = fromX; cl.rf = cl.ff = -1;
\r
481 GenLegal(boards[currentMove], PosFlags(currentMove), ReadCallback, (VOIDSTAR) &cl);
\r
482 if(cl.count == 0) SayString("None", FALSE);
\r
483 SayString("", TRUE); // flush
\r
484 boards[currentMove][fromY][fromX] = victim; // put back original occupant
\r
486 if(oldFromX >= 0 && oldFromY >= 0) { // put back possibl selected piece
\r
487 boards[currentMove][oldFromY][oldFromX] = piece;
\r
494 ChessSquare currentpiece;
\r
495 char *piece, *xchar, *ynum ;
\r
497 ynum = SquareToNum(fromY);
\r
499 if(fromY < 0) return;
\r
501 for (xPos=BOARD_LEFT; xPos<BOARD_RGHT; xPos++) {
\r
502 currentpiece = boards[currentMove][fromY][xPos];
\r
503 if(currentpiece != EmptySquare) {
\r
504 piece = PieceToName(currentpiece,1);
\r
505 xchar = SquareToChar(xPos);
\r
506 SayString(xchar , FALSE);
\r
507 SayString(ynum, FALSE);
\r
508 SayString(piece, FALSE);
\r
513 SayString("rank", FALSE);
\r
514 SayString(ynum, FALSE);
\r
515 SayString("empty", FALSE);
\r
517 SayString("", TRUE); // flush
\r
523 ChessSquare currentpiece;
\r
524 char *piece, *xchar, *ynum ;
\r
526 xchar = SquareToChar(fromX);
\r
528 if(fromX < 0) return;
\r
530 for (yPos=0; yPos<BOARD_HEIGHT; yPos++) {
\r
531 currentpiece = boards[currentMove][yPos][fromX];
\r
532 if(currentpiece != EmptySquare) {
\r
533 piece = PieceToName(currentpiece,1);
\r
534 ynum = SquareToNum(yPos);
\r
535 SayString(xchar , FALSE);
\r
536 SayString(ynum, FALSE);
\r
537 SayString(piece, FALSE);
\r
542 SayString(xchar, FALSE);
\r
543 SayString("file empty", FALSE);
\r
545 SayString("", TRUE); // flush
\r
551 ChessSquare currentpiece;
\r
552 char *piece, *xchar, *ynum ;
\r
555 if(fromX < 0 || fromY < 0) return;
\r
557 if(fromX < BOARD_RGHT-1 && fromY < BOARD_HEIGHT-1) {
\r
558 SayString("The diagnol squares to your upper right contain", FALSE);
\r
561 while(yPos<BOARD_HEIGHT && xPos<BOARD_RGHT) {
\r
562 currentpiece = boards[currentMove][yPos][xPos];
\r
563 piece = PieceToName(currentpiece,1);
\r
564 xchar = SquareToChar(xPos);
\r
565 ynum = SquareToNum(yPos);
\r
566 SayString(xchar , FALSE);
\r
567 SayString(ynum, FALSE);
\r
568 SayString(piece, FALSE);
\r
573 else SayString("There is no squares to your upper right", FALSE);
\r
575 if(fromX > BOARD_LEFT && fromY < BOARD_HEIGHT-1) {
\r
576 SayString("The diagnol squares to your upper left contain", FALSE);
\r
579 while(yPos<BOARD_HEIGHT && xPos>=BOARD_LEFT) {
\r
580 currentpiece = boards[currentMove][yPos][xPos];
\r
581 piece = PieceToName(currentpiece,1);
\r
582 xchar = SquareToChar(xPos);
\r
583 ynum = SquareToNum(yPos);
\r
584 SayString(xchar , FALSE);
\r
585 SayString(ynum, FALSE);
\r
586 SayString(piece, FALSE);
\r
591 else SayString("There is no squares to your upper left", FALSE);
\r
592 SayString("", TRUE); // flush
\r
598 ChessSquare currentpiece;
\r
599 char *piece, *xchar, *ynum ;
\r
602 if(fromX < 0 || fromY < 0) return;
\r
604 if(fromX < BOARD_RGHT-1 && fromY > 0) {
\r
605 SayString("The diagnol squares to your lower right contain", FALSE);
\r
608 while(yPos>=0 && xPos<BOARD_RGHT) {
\r
609 currentpiece = boards[currentMove][yPos][xPos];
\r
610 piece = PieceToName(currentpiece,1);
\r
611 xchar = SquareToChar(xPos);
\r
612 ynum = SquareToNum(yPos);
\r
613 SayString(xchar , FALSE);
\r
614 SayString(ynum, FALSE);
\r
615 SayString(piece, FALSE);
\r
620 else SayString("There is no squares to your lower right", FALSE);
\r
622 if(fromX > BOARD_LEFT && fromY > 0) {
\r
623 SayString("The diagnol squares to your lower left contain", FALSE);
\r
626 while(yPos>=0 && xPos>=BOARD_LEFT) {
\r
627 currentpiece = boards[currentMove][yPos][xPos];
\r
628 piece = PieceToName(currentpiece,1);
\r
629 xchar = SquareToChar(xPos);
\r
630 ynum = SquareToNum(yPos);
\r
631 SayString(xchar , FALSE);
\r
632 SayString(ynum, FALSE);
\r
633 SayString(piece, FALSE);
\r
638 else SayString("There is no squares to your lower left", FALSE);
\r
639 SayString("", TRUE); // flush
\r
645 ChessSquare currentpiece, oldpiece;
\r
646 char *piece, *xchar, *ynum ;
\r
648 oldpiece = boards[currentMove][fromY][fromX];
\r
649 if(oldpiece == WhiteKnight || oldpiece == BlackKnight)
\r
650 SayString("The possible squares a Knight could move to are", FALSE);
\r
652 SayString("The squares a Knight could possibly attack from are", FALSE);
\r
654 if (fromY+2 < BOARD_HEIGHT && fromX-1 >= BOARD_LEFT) {
\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+2 < BOARD_HEIGHT && fromX+1 < BOARD_RGHT) {
\r
670 currentpiece = boards[currentMove][fromY+2][fromX+1];
\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+1);
\r
677 ynum = SquareToNum(fromY+2);
\r
678 SayString(xchar , FALSE);
\r
679 SayString(ynum, FALSE);
\r
680 SayString(piece, FALSE);
\r
684 if (fromY+1 < BOARD_HEIGHT && 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-1 >= 0 && fromX+2 < BOARD_RGHT) {
\r
700 currentpiece = boards[currentMove][fromY-1][fromX+2];
\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+2);
\r
707 ynum = SquareToNum(fromY-1);
\r
708 SayString(xchar , FALSE);
\r
709 SayString(ynum, FALSE);
\r
710 SayString(piece, FALSE);
\r
714 if (fromY-2 >= 0 && fromX+1 < BOARD_RGHT) {
\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-2 >= 0 && fromX-1 >= BOARD_LEFT) {
\r
730 currentpiece = boards[currentMove][fromY-2][fromX-1];
\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-1);
\r
737 ynum = SquareToNum(fromY-2);
\r
738 SayString(xchar , FALSE);
\r
739 SayString(ynum, FALSE);
\r
740 SayString(piece, FALSE);
\r
744 if (fromY-1 >= 0 && 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
759 if (fromY+1 < BOARD_HEIGHT && fromX-2 >= BOARD_LEFT) {
\r
760 currentpiece = boards[currentMove][fromY+1][fromX-2];
\r
761 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
762 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
763 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
765 piece = PieceToName(currentpiece,1);
\r
766 xchar = SquareToChar(fromX-2);
\r
767 ynum = SquareToNum(fromY+1);
\r
768 SayString(xchar , FALSE);
\r
769 SayString(ynum, FALSE);
\r
770 SayString(piece, FALSE);
\r
773 SayString("", TRUE); // flush
\r
777 SayPieces(ChessSquare p)
\r
779 ChessSquare currentpiece;
\r
780 char *piece, *xchar, *ynum ;
\r
781 int yPos, xPos, count = 0;
\r
784 if(p == WhitePlay) SayString("White pieces", FALSE); else
\r
785 if(p == BlackPlay) SayString("Black pieces", FALSE); else
\r
786 if(p == EmptySquare) SayString("Pieces", FALSE); else {
\r
787 snprintf(buf, sizeof(buf)/sizeof(buf[0]),"%ss", PieceToName(p,1));
\r
788 SayString(buf, FALSE);
\r
790 SayString("are located", FALSE);
\r
791 for(yPos=0; yPos<BOARD_HEIGHT; yPos++) {
\r
792 for(xPos=BOARD_LEFT; xPos<BOARD_RGHT; xPos++) {
\r
793 currentpiece = boards[currentMove][yPos][xPos];
\r
794 if(p == BlackPlay && currentpiece >= BlackPawn && currentpiece <= BlackKing ||
\r
795 p == WhitePlay && currentpiece >= WhitePawn && currentpiece <= WhiteKing )
\r
796 piece = PieceToName(currentpiece,0);
\r
797 else if(p == EmptySquare && currentpiece != EmptySquare)
\r
798 piece = PieceToName(currentpiece,1);
\r
799 else if(p == currentpiece)
\r
803 if(count == 0) SayString("at", FALSE);
\r
804 xchar = SquareToChar(xPos);
\r
805 ynum = SquareToNum(yPos);
\r
806 SayString(xchar , FALSE);
\r
807 SayString(ynum, FALSE);
\r
808 if(piece) SayString(piece, FALSE);
\r
812 if(count == 0) SayString("nowhere", FALSE);
\r
813 SayString("", TRUE); // flush
\r
819 ChessSquare currentpiece;
\r
820 char *piece, *xchar, *ynum ;
\r
821 if(fromX < BOARD_LEFT) { SayString("You strayed into the white holdings", FALSE); return; }
\r
822 if(fromX >= BOARD_RGHT) { SayString("You strayed into the black holdings", FALSE); return; }
\r
823 currentpiece = boards[currentMove][fromY][fromX];
\r
824 piece = PieceToName(currentpiece,1);
\r
825 ynum = SquareToNum(fromY);
\r
826 xchar = SquareToChar(fromX);
\r
827 SayString("Your current position is", FALSE);
\r
828 SayString(xchar, FALSE);
\r
829 SayString(ynum, FALSE);
\r
830 SayString(piece, FALSE);
\r
831 if(((fromX-BOARD_LEFT) ^ fromY)&1)
\r
832 SayString("on a light square",FALSE);
\r
834 SayString("on a dark square",FALSE);
\r
836 PossibleAttacked();
\r
837 SayString("", TRUE); // flush
\r
844 ChessSquare currentpiece;
\r
845 char *piece, *ynum ;
\r
847 if(gameInfo.holdingsWidth) {
\r
849 for(Ypos=0; Ypos<gameInfo.holdingsSize; Ypos++) {
\r
850 int n = boards[currentMove][Ypos][BOARD_WIDTH-2];
\r
854 SayString("white holds", FALSE);
\r
855 currentpiece = boards[currentMove][Ypos][BOARD_WIDTH-1];
\r
856 piece = PieceToName(currentpiece,0);
\r
857 snprintf(buf, MSG_SIZ,"%d %s%s", n, piece, (n==1 ? "" : "s") );
\r
858 SayString(buf, FALSE);
\r
862 for(Ypos=BOARD_HEIGHT-1; Ypos>=BOARD_HEIGHT - gameInfo.holdingsSize; Ypos--) {
\r
863 int n = boards[currentMove][Ypos][1];
\r
867 SayString("black holds", FALSE);
\r
868 currentpiece = boards[currentMove][Ypos][0];
\r
869 piece = PieceToName(currentpiece,0);
\r
870 snprintf(buf, MSG_SIZ, "%d %s%s", n, piece, (n==1 ? "" : "s") );
\r
871 SayString(buf, FALSE);
\r
876 for(Ypos=BOARD_HEIGHT-1; Ypos>=0; Ypos--) {
\r
877 ynum = ordinals[Ypos + (gameInfo.boardHeight < 10)];
\r
878 SayString(ynum, FALSE);
\r
879 SayString("rank", FALSE);
\r
880 for(Xpos=BOARD_LEFT; Xpos<BOARD_RGHT; Xpos++) {
\r
881 currentpiece = boards[currentMove][Ypos][Xpos];
\r
882 if(currentpiece != EmptySquare) {
\r
885 piece = PieceToName(currentpiece,1);
\r
886 while(Xpos < BOARD_RGHT && boards[currentMove][Ypos][Xpos] == currentpiece)
\r
889 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%d %ss", count, piece);
\r
891 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s", piece);
\r
893 SayString(buf, FALSE);
\r
895 int count = 0, oldX = Xpos;
\r
896 while(Xpos < BOARD_RGHT && boards[currentMove][Ypos][Xpos] == EmptySquare)
\r
898 if(Xpos == BOARD_RGHT && oldX == BOARD_LEFT)
\r
899 SayString("all", FALSE);
\r
903 snprintf(buf, sizeof(buf)/sizeof(buf[0]),"%d", count);
\r
904 SayString(buf, FALSE);
\r
908 SayString("empty", FALSE);
\r
912 SayString("", TRUE); // flush
\r
918 if(gameMode == MachinePlaysBlack || gameMode == IcsPlayingWhite) {
\r
919 if(WhiteOnMove(currentMove))
\r
920 SayString("It is your turn", FALSE);
\r
921 else SayString("It is your opponents turn", FALSE);
\r
922 } else if(gameMode == MachinePlaysWhite || gameMode == IcsPlayingBlack) {
\r
923 if(WhiteOnMove(currentMove))
\r
924 SayString("It is your opponents turn", FALSE);
\r
925 else SayString("It is your turn", FALSE);
\r
927 if(WhiteOnMove(currentMove))
\r
928 SayString("White is on move here", FALSE);
\r
929 else SayString("Black is on move here", FALSE);
\r
931 SayString("", TRUE); // flush
\r
934 extern char *commentList[];
\r
937 SayMachineMove(int evenIfDuplicate)
\r
939 int len, xPos, yPos, moveNr, secondSpace = 0, castle = 0, n;
\r
940 ChessSquare currentpiece;
\r
941 char *piece, *xchar, *ynum, *p, checkMark = 0;
\r
942 char c, buf[MSG_SIZ], comment[MSG_SIZ];
\r
943 static char disambiguation[2];
\r
944 static int previousMove = 0;
\r
946 if(appData.debugMode) fprintf(debugFP, "Message = '%s'\n", messageText);
\r
947 if(gameMode == BeginningOfGame) return;
\r
948 if(messageText[0] == '[') return;
\r
950 if(isdigit(messageText[0])) { // message is move, possibly with thinking output
\r
951 int dotCount = 0, spaceCount = 0;
\r
952 sscanf(messageText, "%d", &moveNr);
\r
954 // [HGM] show: better extraction of move
\r
955 while (messageText[len] != NULLCHAR) {
\r
956 if(messageText[len] == '.' && spaceCount == 0) dotCount++;
\r
957 if(messageText[len] == ' ') { if(++spaceCount == 2) secondSpace = len; }
\r
958 if(messageText[len] == '{') { // we detected a comment
\r
959 if(isalpha(messageText[len+1]) ) sscanf(messageText+len, "{%[^}]}", comment);
\r
962 if(messageText[len] == '[') { // we detected thinking output
\r
963 int depth; float score=0; char c, lastMover = (dotCount == 3 ? 'B' : 'W');
\r
964 if(sscanf(messageText+len+1, "%d]%c%f", &depth, &c, &score) > 1) {
\r
965 if(c == ' ') { // if not explicitly specified, figure out source of thinking output
\r
967 case MachinePlaysWhite:
\r
968 case IcsPlayingWhite:
\r
970 case IcsPlayingBlack:
\r
971 case MachinePlaysBlack:
\r
977 if(c != lastMover && !evenIfDuplicate) return; // line is thinking output of future move, ignore.
\r
978 if(2*moveNr - (dotCount < 2) == previousMove)
\r
979 return; // do not repeat same move; likely ponder output
\r
980 snprintf(buf, MSG_SIZ, "score %s %d at %d ply",
\r
981 score > 0 ? "plus" : score < 0 ? "minus" : "",
\r
982 (int) (fabs(score)*100+0.5),
\r
984 SayString(buf, FALSE); // move + thinking output describing it; say it.
\r
986 while(messageText[len-1] == ' ') len--; // position just behind move;
\r
989 if(messageText[len] == '(') { // ICS time printed behind move
\r
990 while(messageText[len+1] && messageText[len] != ')') len++; // skip it
\r
994 if(secondSpace) len = secondSpace; // position behind move
\r
995 if(messageText[len-1] == '+' || messageText[len-1] == '#') { /* you are in checkmate */
\r
996 len--; // strip off check or mate indicator
\r
997 checkMark = messageText[len]; // make sure still seen after we stip off promo piece
\r
999 if(messageText[len-2] == '=') { /* promotion */
\r
1000 len-=2; // strip off promotion piece
\r
1001 SayString("promotion", FALSE);
\r
1004 n = 2*moveNr - (dotCount < 2);
\r
1006 if(previousMove != 2*moveNr + (dotCount > 1) || evenIfDuplicate) {
\r
1008 previousMove = 2*moveNr + (dotCount > 1); // remember move nr of move last spoken
\r
1009 snprintf(number, sizeof(number)/sizeof(number[0]),"%d", moveNr);
\r
1011 yPos = CoordToNum(messageText[len-1]); /* turn char coords to ints */
\r
1012 xPos = CoordToNum(messageText[len-2]);
\r
1013 if(xPos < 0 || xPos > 11) return; // prevent crashes if no coord string available to speak
\r
1014 if(yPos < 0 || yPos > 9) return;
\r
1015 currentpiece = boards[n][yPos][xPos];
\r
1016 piece = PieceToName(currentpiece,0);
\r
1017 ynum = SquareToNum(yPos);
\r
1018 xchar = SquareToChar(xPos);
\r
1019 c = messageText[len-3];
\r
1020 if(c == 'x') c = messageText[len-4];
\r
1021 if(!isdigit(c) && c < 'a' && c != '@') c = 0;
\r
1022 disambiguation[0] = c;
\r
1023 SayString(WhiteOnMove(n) ? "Black" : "White", FALSE);
\r
1024 SayString("move", FALSE);
\r
1025 SayString(number, FALSE);
\r
1026 // if(c==0 || c=='@') SayString("a", FALSE);
\r
1027 // intercept castling moves
\r
1028 p = StrStr(messageText, "O-O-O");
\r
1029 if(p && p-messageText < len) {
\r
1030 SayString("queen side castling",FALSE);
\r
1033 p = StrStr(messageText, "O-O");
\r
1034 if(p && p-messageText < len) {
\r
1035 SayString("king side castling",FALSE);
\r
1040 SayString(piece, FALSE);
\r
1041 if(c == '@') SayString("dropped on", FALSE); else
\r
1042 if(c) SayString(disambiguation, FALSE);
\r
1043 SayString("to", FALSE);
\r
1044 SayString(xchar, FALSE);
\r
1045 SayString(ynum, FALSE);
\r
1046 if(messageText[len-3] == 'x') {
\r
1047 currentpiece = boards[n-1][yPos][xPos];
\r
1048 if(currentpiece != EmptySquare) {
\r
1049 piece = PieceToName(currentpiece,0);
\r
1050 SayString("Capturing a",FALSE);
\r
1051 SayString(piece, FALSE);
\r
1052 } else SayString("Capturing onn passann",FALSE);
\r
1055 if(checkMark == '+') SayString("check", FALSE); else
\r
1056 if(checkMark == '#') {
\r
1057 SayString("finishing off", FALSE);
\r
1058 SayString(WhiteOnMove(n) ? "White" : "Black", FALSE);
\r
1062 /* say comment after move, possibly with result */
\r
1064 if(StrStr(messageText, " 1-0")) p = "white wins"; else
\r
1065 if(StrStr(messageText, " 0-1")) p = "black wins"; else
\r
1066 if(StrStr(messageText, " 1/2-1/2")) p = "game ends in a draw";
\r
1069 if(!StrCaseStr(comment, "draw") &&
\r
1070 !StrCaseStr(comment, "white") &&
\r
1071 !StrCaseStr(comment, "black") ) {
\r
1072 SayString(p, FALSE);
\r
1073 SayString("due to", FALSE);
\r
1076 SayString(comment, FALSE); // alphabetic comment (usually game end)
\r
1077 } else if(p) SayString(p, FALSE);
\r
1079 if(commentDialog && commentList[currentMove]) SetFocus(commentDialog);
\r
1082 /* starts not with digit */
\r
1083 if(StrCaseStr(messageText, "illegal")) PlayIcsUnfinishedSound();
\r
1084 SayString(messageText, FALSE);
\r
1087 SayString("", TRUE); // flush
\r
1093 char buf1[50], buf2[50];
\r
1094 char *str1, *str2;
\r
1095 static long int lastWhiteTime, lastBlackTime;
\r
1097 suppressClocks = 1; // if user is using alt+T command, no reason to display them
\r
1098 if(abs(lastWhiteTime - whiteTimeRemaining) < 1000 && abs(lastBlackTime - blackTimeRemaining) < 1000)
\r
1099 suppressClocks = 0; // back on after two requests in rapid succession
\r
1100 snprintf(buf1, sizeof(buf1)/sizeof(buf1[0]),"%s", TimeString(whiteTimeRemaining));
\r
1102 SayString("White clock", FALSE);
\r
1103 SayString(str1, FALSE);
\r
1104 snprintf(buf2, sizeof(buf2)/sizeof(buf2[0]), "%s", TimeString(blackTimeRemaining));
\r
1106 SayString("Black clock", FALSE);
\r
1107 SayString(str2, FALSE);
\r
1108 lastWhiteTime = whiteTimeRemaining;
\r
1109 lastBlackTime = blackTimeRemaining;
\r
1110 SayString("", TRUE); // flush
\r
1114 Toggle(Boolean *b, char *mess)
\r
1117 SayString(mess, FALSE);
\r
1118 SayString("is now", FALSE);
\r
1119 SayString(*b ? "on" : "off", FALSE);
\r
1120 SayString("", TRUE); // flush
\r
1123 /* handles keyboard moves in a click-click fashion */
\r
1125 KeyboardMove(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
1127 ChessSquare currentpiece;
\r
1130 static BOOLEAN sameAgain = FALSE;
\r
1131 switch (message) {
\r
1133 sameAgain = FALSE;
\r
1134 if(oldFromX == fromX && oldFromY == fromY) {
\r
1136 /* click on same square */
\r
1139 else if(oldFromX != -1) {
\r
1141 ChessSquare pdown, pup;
\r
1142 pdown = boards[currentMove][oldFromY][oldFromX];
\r
1143 pup = boards[currentMove][fromY][fromX];
\r
1145 if (gameMode == EditPosition ||
\r
1146 !((WhitePawn <= pdown && pdown <= WhiteKing &&
\r
1147 WhitePawn <= pup && pup <= WhiteKing) ||
\r
1148 (BlackPawn <= pdown && pdown <= BlackKing &&
\r
1149 BlackPawn <= pup && pup <= BlackKing))) {
\r
1150 /* EditPosition, empty square, or different color piece;
\r
1151 click-click move is possible */
\r
1152 char promoChoice = NULLCHAR;
\r
1154 if (HasPromotionChoice(oldFromX, oldFromY, fromX, fromY, &promoChoice)) {
\r
1155 if (appData.alwaysPromoteToQueen) {
\r
1156 UserMoveEvent(oldFromX, oldFromY, fromX, fromY, 'q');
\r
1159 toX = fromX; toY = fromY; fromX = oldFromX; fromY = oldFromY;
\r
1160 PromotionPopup(hwnd);
\r
1161 fromX = toX; fromY = toY;
\r
1165 UserMoveEvent(oldFromX, oldFromY, fromX, fromY, promoChoice);
\r
1167 oldFromX = oldFromY = -1;
\r
1172 /* First downclick, or restart on a square with same color piece */
\r
1173 if (OKToStartUserMove(fromX, fromY)) {
\r
1176 currentpiece = boards[currentMove][fromY][fromX];
\r
1177 piece = PieceToName(currentpiece,1);
\r
1178 SayString(piece, FALSE);
\r
1179 SayString("selected", TRUE);
\r
1182 oldFromX = oldFromY = -1;
\r
1187 if (oldFromX == fromX && oldFromY == fromY) {
\r
1188 /* Upclick on same square */
\r
1190 /* Clicked same square twice: abort click-click move */
\r
1191 oldFromX = oldFromY = -1;
\r
1192 currentpiece = boards[currentMove][fromY][fromX];
\r
1193 piece = PieceToName(currentpiece,0);
\r
1194 SayString(piece, FALSE);
\r
1195 SayString("unselected", TRUE);
\r
1203 { // return TRUE for times we want to announce
\r
1205 x = (x+50)/100; // tenth of seconds
\r
1206 if(x <= 100) return (x%10 == 0);
\r
1207 if(x <= 600) return (x%100 == 0);
\r
1208 if(x <= 6000) return (x%600 == 0);
\r
1209 return (x%3000 == 0);
\r
1212 #define JAWS_ARGS \
\r
1213 { "beepOffBoard", ArgInt, (LPVOID) beeps, TRUE, (ArgIniType) 1 },\
\r
1214 { "beepEmpty", ArgInt, (LPVOID) (beeps+1), TRUE, (ArgIniType) 0 },\
\r
1215 { "beepWhite", ArgInt, (LPVOID) (beeps+2), TRUE, (ArgIniType) 0 },\
\r
1216 { "beepBlack", ArgInt, (LPVOID) (beeps+3), TRUE, (ArgIniType) 0 },\
\r
1217 { "beepHoldings", ArgInt, (LPVOID) (beeps+4), TRUE, (ArgIniType) 0 },\
\r
1219 #define JAWS_ALT_INTERCEPT \
\r
1220 if(suppressOneKey) {\
\r
1221 suppressOneKey = 0;\
\r
1222 if(GetKeyState(VK_MENU) < 0 && GetKeyState(VK_CONTROL) < 0) break;\
\r
1224 if ((char)wParam == 022 && gameMode == EditPosition) { /* <Ctl R>. Pop up piece menu */\
\r
1225 POINT pt; int x, y;\
\r
1226 SquareToPos(fromY, fromX, &x, &y);\
\r
1227 dropX = fromX; dropY = fromY;\
\r
1228 pt.x = x; pt.y = y;\
\r
1229 if(gameInfo.variant != VariantShogi)\
\r
1230 MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1);\
\r
1232 MenuPopup(hwnd, pt, LoadMenu(hInst, "ShogiPieceMenu"), -1);\
\r
1236 #define JAWS_REPLAY \
\r
1237 case '\020': /* ctrl P */\
\r
1238 { char buf[MSG_SIZ];\
\r
1239 if(GetWindowText(hwnd, buf, MSG_SIZ-1))\
\r
1240 SayString(buf, TRUE);\
\r
1244 #define JAWS_KBDOWN_NAVIGATION \
\r
1247 if(GetKeyState(VK_MENU) < 0 && GetKeyState(VK_CONTROL) < 0) {\
\r
1248 /* Control + Alt + letter used for speaking piece positions */\
\r
1249 static int lastTime; static char lastChar;\
\r
1250 int mine = 0, time = GetTickCount(); char c;\
\r
1252 if((char)wParam == lastChar && time-lastTime < 250) mine = 1;\
\r
1253 lastChar = wParam; lastTime = time;\
\r
1256 if(gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) mine = !mine;\
\r
1258 if(ToLower(c) == 'x') {\
\r
1259 SayPieces(mine ? WhitePlay : BlackPlay);\
\r
1260 suppressOneKey = 1;\
\r
1263 if(CharToPiece(c) != EmptySquare) {\
\r
1264 SayPieces(CharToPiece(mine ? ToUpper(c) : ToLower(c)));\
\r
1265 suppressOneKey = 1;\
\r
1270 switch (wParam) {\
\r
1275 KeyboardEvent(hwnd, message, wParam, lParam);\
\r
1278 shiftKey = GetKeyState(VK_SHIFT) < 0;\
\r
1279 KeyboardMove(hwnd, message, wParam, lParam);\
\r
1283 #define JAWS_KBUP_NAVIGATION \
\r
1284 switch (wParam) {\
\r
1286 KeyboardMove(hwnd, message, wParam, lParam);\
\r
1290 #define JAWS_MENU_ITEMS \
\r
1291 case IDM_PossibleAttackMove: /*What can I possible attack from here */\
\r
1292 PossibleAttackMove();\
\r
1295 case IDM_PossibleAttacked: /*what can possible attack this square*/\
\r
1296 PossibleAttacked();\
\r
1299 case IDM_ReadRow: /* Read the current row of pieces */\
\r
1303 case IDM_ReadColumn: /* Read the current column of pieces */\
\r
1307 case IDM_SayCurrentPos: /* Say current position including color */\
\r
1311 case IDM_SayAllBoard: /* Say the whole board from bottom to top */\
\r
1315 case IDM_SayMachineMove: /* Say the last move made */\
\r
1317 SayMachineMove(1);\
\r
1320 case IDM_SayUpperDiagnols: /* Says the diagnol positions above you */\
\r
1321 SayUpperDiagnols();\
\r
1324 case IDM_SayLowerDiagnols: /* Say the diagnol positions below you */\
\r
1325 SayLowerDiagnols();\
\r
1328 case IDM_SayBlackPieces: /*Say the opponents pieces */\
\r
1329 SayPieces(BlackPlay);\
\r
1332 case IDM_SayWhitePieces: /*Say the opponents pieces */\
\r
1333 SayPieces(WhitePlay);\
\r
1336 case IDM_SayClockTime: /*Say the clock time */\
\r
1340 case IDM_SayWhosTurn: /* Say whos turn it its */\
\r
1344 case IDM_SayKnightMoves: /* Say Knights (L-shaped) move */\
\r
1345 SayKnightMoves();\
\r
1348 case OPT_PonderNextMove: /* Toggle option setting */\
\r
1349 Toggle(&appData.ponderNextMove, "ponder");\
\r
1352 case OPT_AnimateMoving: /* Toggle option setting */\
\r
1353 Toggle(&appData.animate, "animate moving");\
\r
1356 case OPT_AutoFlag: /* Toggle option setting */\
\r
1357 Toggle(&appData.autoCallFlag, "auto flag");\
\r
1360 case OPT_AlwaysQueen: /* Toggle option setting */\
\r
1361 Toggle(&appData.alwaysPromoteToQueen, "always promote to queen");\
\r
1364 case OPT_TestLegality: /* Toggle option setting */\
\r
1365 Toggle(&appData.testLegality, "legality testing");\
\r
1368 case OPT_HideThinkFromHuman: /* Toggle option setting */\
\r
1369 Toggle(&appData.hideThinkingFromHuman, "hide thinking");\
\r
1370 ShowThinkingEvent();\
\r
1373 case OPT_SaveExtPGN: /* Toggle option setting */\
\r
1374 Toggle(&appData.saveExtendedInfoInPGN, "extended P G N info");\
\r
1377 case OPT_ExtraInfoInMoveHistory: /* Toggle option setting */\
\r
1378 Toggle(&appData.showEvalInMoveHistory, "extra info in move histoty");\
\r
1383 #define JAWS_ACCEL \
\r
1384 !(!frozen && TranslateAccelerator(hwndMain, hAccelJAWS, &msg)) &&
\r
1386 #define JAWS_INIT if (!InitJAWS()) return (FALSE);
\r
1388 #define JAWS_DELETE(X)
\r
1390 #define JAWS_SILENCE if(suppressClocks) return;
\r
1392 #define JAWS_COPYRIGHT \
\r
1393 SetDlgItemText(hDlg, OPT_MESS, "Auditory/Keyboard Enhancements By: Ed Rodriguez (sort of)");
\r
1395 #define SAY(S) SayString((S), TRUE)
\r
1397 #define SAYMACHINEMOVE() SayMachineMove(0)
\r
1399 // After inclusion of this file somewhere early in winboard.c, the remaining part of the patch
\r
1400 // is scattered over winboard.c for actually calling the routines.
\r