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 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
285 static int dropX = -1, dropY = -1;
\r
288 KeyboardEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
290 ChessSquare currentPiece;
\r
291 char *piece, *xchar, *ynum ;
\r
292 int n, beepType = 1; // empty beep
\r
294 if(fromX == -1 || fromY == -1) { // if we just dropped piece, stay at that square
\r
295 fromX = dropX; fromY = dropY;
\r
296 dropX = dropY = -1; // but only once
\r
298 if(fromX == -1 || fromY == -1) {
\r
299 fromX = BOARD_LEFT; fromY = 0;
\r
303 if(fromX == BOARD_RGHT+1) fromX -= 2; else
\r
304 if(fromX == BOARD_LEFT) { if(fromY >= BOARD_HEIGHT - gameInfo.holdingsSize) fromX -= 2; else beepType = 0; } else
\r
305 if(fromX > BOARD_LEFT) fromX--; else beepType = 0; // off-board beep
\r
308 if(fromX == BOARD_LEFT-2) fromX += 2; else
\r
309 if(fromX == BOARD_RGHT-1) { if(fromY < gameInfo.holdingsSize) fromX += 2; else beepType = 0; } else
\r
310 if(fromX < BOARD_RGHT-1) fromX++; else beepType = 0;
\r
313 if(fromX == BOARD_RGHT+1) { if(fromY < gameInfo.holdingsSize - 1) fromY++; else beepType = 0; } else
\r
314 if(fromY < BOARD_HEIGHT-1) fromY++; else beepType = 0;
\r
317 if(fromX == BOARD_LEFT-2) { if(fromY > BOARD_HEIGHT - gameInfo.holdingsSize) fromY--; else beepType = 0; } else
\r
318 if(fromY > 0) fromY--; else beepType = 0;
\r
321 SetHighlights(fromX, fromY, -1, -1);
\r
322 DrawPosition(FALSE, NULL);
\r
323 currentPiece = boards[currentMove][fromY][fromX];
\r
324 piece = PieceToName(currentPiece,1);
\r
325 if(beepType == 1 && currentPiece != EmptySquare) beepType = currentPiece < (int) BlackPawn ? 2 : 3; // white or black beep
\r
326 if(beeps[beepType] == beeps[1] && (fromX == BOARD_RGHT+1 || fromX == BOARD_LEFT-2)) beepType = 4; // holdings beep
\r
327 beepType = beeps[beepType]%6;
\r
328 if(beepType) MessageBeep(beepCodes[beepType]);
\r
329 if(fromX == BOARD_LEFT - 2) {
\r
330 SayString("black holdings", FALSE);
\r
331 if(currentPiece != EmptySquare) {
\r
333 n = boards[currentMove][fromY][1];
\r
334 sprintf(buf, "%d %s%s", n, PieceToName(currentPiece,0), n == 1 ? "" : "s");
\r
335 SayString(buf, TRUE);
\r
338 if(fromX == BOARD_RGHT + 1) {
\r
339 SayString("white holdings", FALSE);
\r
340 if(currentPiece != EmptySquare) {
\r
342 n = boards[currentMove][fromY][BOARD_WIDTH-2];
\r
343 sprintf(buf, "%d %s%s", n, PieceToName(currentPiece,0), n == 1 ? "" : "s");
\r
344 SayString(buf, TRUE);
\r
347 if(fromX >= BOARD_LEFT && fromX < BOARD_RGHT) {
\r
349 xchar = SquareToChar(fromX);
\r
350 ynum = SquareToNum(fromY);
\r
351 if(currentPiece != EmptySquare) {
\r
352 // SayString(piece[0] == 'W' ? "white" : "black", TRUE);
\r
353 sprintf(buf, "%s %s %s", xchar, ynum, piece);
\r
354 } else sprintf(buf, "%s %s", xchar, ynum);
\r
355 SayString(buf, TRUE);
\r
360 int PosFlags(int nr);
\r
363 int rf, ff, rt, ft;
\r
368 extern void ReadCallback P((Board board, int flags, ChessMove kind,
\r
369 int rf, int ff, int rt, int ft,
\r
370 VOIDSTAR closure));
\r
372 void ReadCallback(board, flags, kind, rf, ff, rt, ft, closure)
\r
376 int rf, ff, rt, ft;
\r
379 register ReadClosure *cl = (ReadClosure *) closure;
\r
380 ChessSquare possiblepiece;
\r
381 char *piece, *xchar, *ynum ;
\r
383 //if(appData.debugMode) fprintf(debugFP, "%c%c%c%c\n", ff+AAA, rf+ONE, ft+AAA, rt+ONE);
\r
384 if(cl->ff == ff && cl->rf == rf) {
\r
385 possiblepiece = board[rt][ft];
\r
386 if(possiblepiece != EmptySquare) {
\r
387 piece = PieceToName(possiblepiece,1);
\r
388 xchar = SquareToChar(ft);
\r
389 ynum = SquareToNum(rt);
\r
390 SayString(xchar , FALSE);
\r
391 SayString(ynum, FALSE);
\r
392 SayString(piece, FALSE);
\r
396 if(cl->ft == ft && cl->rt == rt) {
\r
397 possiblepiece = board[rf][ff];
\r
398 piece = PieceToName(possiblepiece,1);
\r
399 xchar = SquareToChar(ff);
\r
400 ynum = SquareToNum(rf);
\r
401 SayString(xchar , FALSE);
\r
402 SayString(ynum, FALSE);
\r
403 SayString(piece, FALSE);
\r
409 PossibleAttackMove()
\r
412 ChessSquare piece, victim;
\r
413 int removedSelectedPiece = 0, swapColor;
\r
415 //if(appData.debugMode) fprintf(debugFP, "PossibleAttackMove %d %d %d %d\n", fromX, fromY, oldFromX, oldFromY);
\r
416 if(fromY < 0 || fromY >= BOARD_HEIGHT) return;
\r
417 if(fromX < BOARD_LEFT || fromX >= BOARD_RGHT) { SayString("holdings",FALSE); return; }
\r
419 piece = boards[currentMove][fromY][fromX];
\r
420 if(piece == EmptySquare) { // if square is empty, try to substitute selected piece
\r
421 if(oldFromX >= 0 && oldFromY >= 0) {
\r
422 piece = boards[currentMove][oldFromY][oldFromX];
\r
423 boards[currentMove][oldFromY][oldFromX] = EmptySquare;
\r
424 removedSelectedPiece = 1;
\r
425 SayString("Your", FALSE);
\r
426 SayString(PieceToName(piece, 0), FALSE);
\r
427 SayString("would have", FALSE);
\r
428 } else { SayString("You must select a piece first", FALSE); return; }
\r
431 victim = boards[currentMove][fromY][fromX];
\r
432 boards[currentMove][fromY][fromX] = piece; // make sure piece is actally there
\r
433 SayString("possible captures from here are", FALSE);
\r
435 swapColor = piece < (int)BlackPawn && !WhiteOnMove(currentMove) ||
\r
436 piece >= (int)BlackPawn && WhiteOnMove(currentMove);
\r
437 cl.count = 0; cl.rf = fromY; cl.ff = fromX; cl.rt = cl.ft = -1;
\r
438 GenLegal(boards[currentMove], PosFlags(currentMove + swapColor), ReadCallback, (VOIDSTAR) &cl);
\r
439 if(cl.count == 0) SayString("None", FALSE);
\r
440 boards[currentMove][fromY][fromX] = victim; // repair
\r
442 if( removedSelectedPiece ) boards[currentMove][oldFromY][oldFromX] = piece;
\r
450 ChessSquare piece = EmptySquare, victim;
\r
452 if(fromY < 0 || fromY >= BOARD_HEIGHT) return;
\r
453 if(fromX < BOARD_LEFT || fromX >= BOARD_RGHT) { SayString("holdings",FALSE); return; }
\r
455 if(oldFromX >= 0 && oldFromY >= 0) { // if piece is selected, remove it
\r
456 piece = boards[currentMove][oldFromY][oldFromX];
\r
457 boards[currentMove][oldFromY][oldFromX] = EmptySquare;
\r
460 SayString("Pieces that can capture you are", FALSE);
\r
462 victim = boards[currentMove][fromY][fromX]; // put dummy piece on target square, to activate Pawn captures
\r
463 boards[currentMove][fromY][fromX] = WhiteOnMove(currentMove) ? WhiteQueen : BlackQueen;
\r
464 cl.count = 0; cl.rt = fromY; cl.ft = fromX; cl.rf = cl.ff = -1;
\r
465 GenLegal(boards[currentMove], PosFlags(currentMove+1), ReadCallback, (VOIDSTAR) &cl);
\r
466 if(cl.count == 0) SayString("None", FALSE);
\r
468 SayString("You are defended by", FALSE);
\r
470 boards[currentMove][fromY][fromX] = WhiteOnMove(currentMove) ? BlackQueen : WhiteQueen;
\r
471 cl.count = 0; cl.rt = fromY; cl.ft = fromX; cl.rf = cl.ff = -1;
\r
472 GenLegal(boards[currentMove], PosFlags(currentMove), ReadCallback, (VOIDSTAR) &cl);
\r
473 if(cl.count == 0) SayString("None", FALSE);
\r
474 boards[currentMove][fromY][fromX] = victim; // put back original occupant
\r
476 if(oldFromX >= 0 && oldFromY >= 0) { // put back possibl selected piece
\r
477 boards[currentMove][oldFromY][oldFromX] = piece;
\r
484 ChessSquare currentpiece;
\r
485 char *piece, *xchar, *ynum ;
\r
487 ynum = SquareToNum(fromY);
\r
489 if(fromY < 0) return;
\r
491 for (xPos=BOARD_LEFT; xPos<BOARD_RGHT; xPos++) {
\r
492 currentpiece = boards[currentMove][fromY][xPos];
\r
493 if(currentpiece != EmptySquare) {
\r
494 piece = PieceToName(currentpiece,1);
\r
495 xchar = SquareToChar(xPos);
\r
496 SayString(xchar , FALSE);
\r
497 SayString(ynum, FALSE);
\r
498 SayString(piece, FALSE);
\r
503 SayString("rank", FALSE);
\r
504 SayString(ynum, FALSE);
\r
505 SayString("empty", FALSE);
\r
512 ChessSquare currentpiece;
\r
513 char *piece, *xchar, *ynum ;
\r
515 xchar = SquareToChar(fromX);
\r
517 if(fromX < 0) return;
\r
519 for (yPos=0; yPos<BOARD_HEIGHT; yPos++) {
\r
520 currentpiece = boards[currentMove][yPos][fromX];
\r
521 if(currentpiece != EmptySquare) {
\r
522 piece = PieceToName(currentpiece,1);
\r
523 ynum = SquareToNum(yPos);
\r
524 SayString(xchar , FALSE);
\r
525 SayString(ynum, FALSE);
\r
526 SayString(piece, FALSE);
\r
531 SayString(xchar, FALSE);
\r
532 SayString("file empty", FALSE);
\r
539 ChessSquare currentpiece;
\r
540 char *piece, *xchar, *ynum ;
\r
543 if(fromX < 0 || fromY < 0) return;
\r
545 if(fromX < BOARD_RGHT-1 && fromY < BOARD_HEIGHT-1) {
\r
546 SayString("The diagnol squares to your upper right contain", FALSE);
\r
549 while(yPos<BOARD_HEIGHT && xPos<BOARD_RGHT) {
\r
550 currentpiece = boards[currentMove][yPos][xPos];
\r
551 piece = PieceToName(currentpiece,1);
\r
552 xchar = SquareToChar(xPos);
\r
553 ynum = SquareToNum(yPos);
\r
554 SayString(xchar , FALSE);
\r
555 SayString(ynum, FALSE);
\r
556 SayString(piece, FALSE);
\r
561 else SayString("There is no squares to your upper right", FALSE);
\r
563 if(fromX > BOARD_LEFT && fromY < BOARD_HEIGHT-1) {
\r
564 SayString("The diagnol squares to your upper left contain", FALSE);
\r
567 while(yPos<BOARD_HEIGHT && xPos>=BOARD_LEFT) {
\r
568 currentpiece = boards[currentMove][yPos][xPos];
\r
569 piece = PieceToName(currentpiece,1);
\r
570 xchar = SquareToChar(xPos);
\r
571 ynum = SquareToNum(yPos);
\r
572 SayString(xchar , FALSE);
\r
573 SayString(ynum, FALSE);
\r
574 SayString(piece, FALSE);
\r
579 else SayString("There is no squares to your upper left", FALSE);
\r
585 ChessSquare currentpiece;
\r
586 char *piece, *xchar, *ynum ;
\r
589 if(fromX < 0 || fromY < 0) return;
\r
591 if(fromX < BOARD_RGHT-1 && fromY > 0) {
\r
592 SayString("The diagnol squares to your lower right contain", FALSE);
\r
595 while(yPos>=0 && xPos<BOARD_RGHT) {
\r
596 currentpiece = boards[currentMove][yPos][xPos];
\r
597 piece = PieceToName(currentpiece,1);
\r
598 xchar = SquareToChar(xPos);
\r
599 ynum = SquareToNum(yPos);
\r
600 SayString(xchar , FALSE);
\r
601 SayString(ynum, FALSE);
\r
602 SayString(piece, FALSE);
\r
607 else SayString("There is no squares to your lower right", FALSE);
\r
609 if(fromX > BOARD_LEFT && fromY > 0) {
\r
610 SayString("The diagnol squares to your lower left contain", FALSE);
\r
613 while(yPos>=0 && xPos>=BOARD_LEFT) {
\r
614 currentpiece = boards[currentMove][yPos][xPos];
\r
615 piece = PieceToName(currentpiece,1);
\r
616 xchar = SquareToChar(xPos);
\r
617 ynum = SquareToNum(yPos);
\r
618 SayString(xchar , FALSE);
\r
619 SayString(ynum, FALSE);
\r
620 SayString(piece, FALSE);
\r
625 else SayString("There is no squares to your lower left", FALSE);
\r
631 ChessSquare currentpiece, oldpiece;
\r
632 char *piece, *xchar, *ynum ;
\r
634 oldpiece = boards[currentMove][fromY][fromX];
\r
635 if(oldpiece == WhiteKnight || oldpiece == BlackKnight)
\r
636 SayString("The possible squares a Knight could move to are", FALSE);
\r
638 SayString("The squares a Knight could possibly attack from are", FALSE);
\r
640 if (fromY+2 < BOARD_HEIGHT && fromX-1 >= BOARD_LEFT) {
\r
641 currentpiece = boards[currentMove][fromY+2][fromX-1];
\r
642 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
643 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
644 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
646 piece = PieceToName(currentpiece,1);
\r
647 xchar = SquareToChar(fromX-1);
\r
648 ynum = SquareToNum(fromY+2);
\r
649 SayString(xchar , FALSE);
\r
650 SayString(ynum, FALSE);
\r
651 SayString(piece, FALSE);
\r
655 if (fromY+2 < BOARD_HEIGHT && fromX+1 < BOARD_RGHT) {
\r
656 currentpiece = boards[currentMove][fromY+2][fromX+1];
\r
657 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
658 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
659 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
661 piece = PieceToName(currentpiece,1);
\r
662 xchar = SquareToChar(fromX+1);
\r
663 ynum = SquareToNum(fromY+2);
\r
664 SayString(xchar , FALSE);
\r
665 SayString(ynum, FALSE);
\r
666 SayString(piece, FALSE);
\r
670 if (fromY+1 < BOARD_HEIGHT && fromX+2 < BOARD_RGHT) {
\r
671 currentpiece = boards[currentMove][fromY+1][fromX+2];
\r
672 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
673 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
674 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
676 piece = PieceToName(currentpiece,1);
\r
677 xchar = SquareToChar(fromX+2);
\r
678 ynum = SquareToNum(fromY+1);
\r
679 SayString(xchar , FALSE);
\r
680 SayString(ynum, FALSE);
\r
681 SayString(piece, FALSE);
\r
685 if (fromY-1 >= 0 && fromX+2 < BOARD_RGHT) {
\r
686 currentpiece = boards[currentMove][fromY-1][fromX+2];
\r
687 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
688 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
689 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
691 piece = PieceToName(currentpiece,1);
\r
692 xchar = SquareToChar(fromX+2);
\r
693 ynum = SquareToNum(fromY-1);
\r
694 SayString(xchar , FALSE);
\r
695 SayString(ynum, FALSE);
\r
696 SayString(piece, FALSE);
\r
700 if (fromY-2 >= 0 && fromX+1 < BOARD_RGHT) {
\r
701 currentpiece = boards[currentMove][fromY-2][fromX+1];
\r
702 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
703 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
704 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
706 piece = PieceToName(currentpiece,1);
\r
707 xchar = SquareToChar(fromX+1);
\r
708 ynum = SquareToNum(fromY-2);
\r
709 SayString(xchar , FALSE);
\r
710 SayString(ynum, FALSE);
\r
711 SayString(piece, FALSE);
\r
715 if (fromY-2 >= 0 && fromX-1 >= BOARD_LEFT) {
\r
716 currentpiece = boards[currentMove][fromY-2][fromX-1];
\r
717 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
718 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
719 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
721 piece = PieceToName(currentpiece,1);
\r
722 xchar = SquareToChar(fromX-1);
\r
723 ynum = SquareToNum(fromY-2);
\r
724 SayString(xchar , FALSE);
\r
725 SayString(ynum, FALSE);
\r
726 SayString(piece, FALSE);
\r
730 if (fromY-1 >= 0 && fromX-2 >= BOARD_LEFT) {
\r
731 currentpiece = boards[currentMove][fromY-1][fromX-2];
\r
732 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
733 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
734 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
736 piece = PieceToName(currentpiece,1);
\r
737 xchar = SquareToChar(fromX-2);
\r
738 ynum = SquareToNum(fromY-1);
\r
739 SayString(xchar , FALSE);
\r
740 SayString(ynum, FALSE);
\r
741 SayString(piece, FALSE);
\r
745 if (fromY+1 < BOARD_HEIGHT && fromX-2 >= BOARD_LEFT) {
\r
746 currentpiece = boards[currentMove][fromY+1][fromX-2];
\r
747 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
748 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
749 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
751 piece = PieceToName(currentpiece,1);
\r
752 xchar = SquareToChar(fromX-2);
\r
753 ynum = SquareToNum(fromY+1);
\r
754 SayString(xchar , FALSE);
\r
755 SayString(ynum, FALSE);
\r
756 SayString(piece, FALSE);
\r
762 SayPieces(ChessSquare p)
\r
764 ChessSquare currentpiece;
\r
765 char *piece, *xchar, *ynum ;
\r
766 int yPos, xPos, count = 0;
\r
769 if(p == WhitePlay) SayString("White pieces", FALSE); else
\r
770 if(p == BlackPlay) SayString("Black pieces", FALSE); else
\r
771 if(p == EmptySquare) SayString("Pieces", FALSE); else {
\r
772 sprintf(buf, "%ss", PieceToName(p,1));
\r
773 SayString(buf, FALSE);
\r
775 SayString("are located", FALSE);
\r
776 for(yPos=0; yPos<BOARD_HEIGHT; yPos++) {
\r
777 for(xPos=BOARD_LEFT; xPos<BOARD_RGHT; xPos++) {
\r
778 currentpiece = boards[currentMove][yPos][xPos];
\r
779 if(p == BlackPlay && currentpiece >= BlackPawn && currentpiece <= BlackKing ||
\r
780 p == WhitePlay && currentpiece >= WhitePawn && currentpiece <= WhiteKing )
\r
781 piece = PieceToName(currentpiece,0);
\r
782 else if(p == EmptySquare && currentpiece != EmptySquare)
\r
783 piece = PieceToName(currentpiece,1);
\r
784 else if(p == currentpiece)
\r
788 if(count == 0) SayString("at", FALSE);
\r
789 xchar = SquareToChar(xPos);
\r
790 ynum = SquareToNum(yPos);
\r
791 SayString(xchar , FALSE);
\r
792 SayString(ynum, FALSE);
\r
793 if(piece) SayString(piece, FALSE);
\r
797 if(count == 0) SayString("nowhere", FALSE);
\r
803 ChessSquare currentpiece;
\r
804 char *piece, *xchar, *ynum ;
\r
805 if(fromX < BOARD_LEFT) { SayString("You strayed into the white holdings", FALSE); return; }
\r
806 if(fromX >= BOARD_RGHT) { SayString("You strayed into the black holdings", FALSE); return; }
\r
807 currentpiece = boards[currentMove][fromY][fromX];
\r
808 piece = PieceToName(currentpiece,1);
\r
809 ynum = SquareToNum(fromY);
\r
810 xchar = SquareToChar(fromX);
\r
811 SayString("Your current position is", FALSE);
\r
812 SayString(xchar, FALSE);
\r
813 SayString(ynum, FALSE);
\r
814 SayString(piece, FALSE);
\r
815 if(((fromX-BOARD_LEFT) ^ fromY)&1)
\r
816 SayString("on a light square",FALSE);
\r
818 SayString("on a dark square",FALSE);
\r
820 PossibleAttacked();
\r
828 ChessSquare currentpiece;
\r
829 char *piece, *ynum ;
\r
831 if(gameInfo.holdingsWidth) {
\r
833 for(Ypos=0; Ypos<gameInfo.holdingsSize; Ypos++) {
\r
834 int n = boards[currentMove][Ypos][BOARD_WIDTH-2];
\r
835 if(n) { char buf[MSG_SIZ];
\r
836 if(!first++) SayString("white holds", FALSE);
\r
837 currentpiece = boards[currentMove][Ypos][BOARD_WIDTH-1];
\r
838 piece = PieceToName(currentpiece,0);
\r
839 sprintf(buf, "%d %s%s", n, piece, (n==1 ? "" : "s") );
\r
840 SayString(buf, FALSE);
\r
844 for(Ypos=BOARD_HEIGHT-1; Ypos>=BOARD_HEIGHT - gameInfo.holdingsSize; Ypos--) {
\r
845 int n = boards[currentMove][Ypos][1];
\r
846 if(n) { char buf[MSG_SIZ];
\r
847 if(!first++) SayString("black holds", FALSE);
\r
848 currentpiece = boards[currentMove][Ypos][0];
\r
849 piece = PieceToName(currentpiece,0);
\r
850 sprintf(buf, "%d %s%s", n, piece, (n==1 ? "" : "s") );
\r
851 SayString(buf, FALSE);
\r
856 for(Ypos=BOARD_HEIGHT-1; Ypos>=0; Ypos--) {
\r
857 ynum = ordinals[Ypos + (gameInfo.boardHeight < 10)];
\r
858 SayString(ynum, FALSE);
\r
859 SayString("rank", FALSE);
\r
860 for(Xpos=BOARD_LEFT; Xpos<BOARD_RGHT; Xpos++) {
\r
861 currentpiece = boards[currentMove][Ypos][Xpos];
\r
862 if(currentpiece != EmptySquare) {
\r
865 piece = PieceToName(currentpiece,1);
\r
866 while(Xpos < BOARD_RGHT && boards[currentMove][Ypos][Xpos] == currentpiece)
\r
869 sprintf(buf, "%d %ss", count, piece);
\r
870 } else sprintf(buf, "%s", piece);
\r
872 SayString(buf, FALSE);
\r
874 int count = 0, oldX = Xpos;
\r
875 while(Xpos < BOARD_RGHT && boards[currentMove][Ypos][Xpos] == EmptySquare)
\r
877 if(Xpos == BOARD_RGHT && oldX == BOARD_LEFT)
\r
878 SayString("all", FALSE);
\r
882 sprintf(buf, "%d", count);
\r
883 SayString(buf, FALSE);
\r
887 SayString("empty", FALSE);
\r
897 if(gameMode == MachinePlaysBlack || gameMode == IcsPlayingBlack) {
\r
898 if(WhiteOnMove(currentMove))
\r
899 SayString("It is your turn", FALSE);
\r
900 else SayString("It is your opponents turn", FALSE);
\r
901 } else if(gameMode == MachinePlaysWhite || gameMode == IcsPlayingWhite) {
\r
902 if(WhiteOnMove(currentMove))
\r
903 SayString("It is your opponents turn", FALSE);
\r
904 else SayString("It is your turn", FALSE);
\r
906 if(WhiteOnMove(currentMove))
\r
907 SayString("White is on move here", FALSE);
\r
908 else SayString("Black is on move here", FALSE);
\r
912 extern char *commentList[];
\r
915 SayMachineMove(int evenIfDuplicate)
\r
917 int len, xPos, yPos, moveNr, secondSpace = 0, castle = 0, n;
\r
918 ChessSquare currentpiece;
\r
919 char *piece, *xchar, *ynum, *p, checkMark = 0;
\r
920 char c, buf[MSG_SIZ], comment[MSG_SIZ];
\r
921 static char disambiguation[2];
\r
922 static int previousMove = 0;
\r
924 if(appData.debugMode) fprintf(debugFP, "Message = '%s'\n", messageText);
\r
925 if(gameMode == BeginningOfGame) return;
\r
926 if(messageText[0] == '[') return;
\r
928 if(isdigit(messageText[0])) { // message is move, possibly with thinking output
\r
929 int dotCount = 0, spaceCount = 0;
\r
930 sscanf(messageText, "%d", &moveNr);
\r
932 // [HGM] show: better extraction of move
\r
933 while (messageText[len] != NULLCHAR) {
\r
934 if(messageText[len] == '.' && spaceCount == 0) dotCount++;
\r
935 if(messageText[len] == ' ') { if(++spaceCount == 2) secondSpace = len; }
\r
936 if(messageText[len] == '{') { // we detected a comment
\r
937 if(isalpha(messageText[len+1]) ) sscanf(messageText+len, "{%[^}]}", comment);
\r
940 if(messageText[len] == '[') { // we detected thinking output
\r
941 int depth; float score=0; char c, lastMover = (dotCount == 3 ? 'B' : 'W');
\r
942 if(sscanf(messageText+len+1, "%d]%c%f", &depth, &c, &score) > 1) {
\r
943 if(c == ' ') { // if not explicitly specified, figure out source of thinking output
\r
945 case MachinePlaysWhite:
\r
946 case IcsPlayingWhite:
\r
948 case IcsPlayingBlack:
\r
949 case MachinePlaysBlack:
\r
955 if(c != lastMover && !evenIfDuplicate) return; // line is thinking output of future move, ignore.
\r
956 if(2*moveNr - (dotCount < 2) == previousMove)
\r
957 return; // do not repeat same move; likely ponder output
\r
958 sprintf(buf, "score %s %d at %d ply",
\r
959 score > 0 ? "plus" : score < 0 ? "minus" : "",
\r
960 (int) (fabs(score)*100+0.5),
\r
962 SayString(buf, FALSE); // move + thinking output describing it; say it.
\r
964 while(messageText[len-1] == ' ') len--; // position just behind move;
\r
967 if(messageText[len] == '(') { // ICS time printed behind move
\r
968 while(messageText[len+1] && messageText[len] != ')') len++; // skip it
\r
972 if(secondSpace) len = secondSpace; // position behind move
\r
973 if(messageText[len-1] == '+' || messageText[len-1] == '#') { /* you are in checkmate */
\r
974 len--; // strip off check or mate indicator
\r
975 checkMark = messageText[len]; // make sure still seen after we stip off promo piece
\r
977 if(messageText[len-2] == '=') { /* promotion */
\r
978 len-=2; // strip off promotion piece
\r
979 SayString("promotion", FALSE);
\r
982 n = 2*moveNr - (dotCount < 2);
\r
984 if(previousMove != 2*moveNr + (dotCount > 1) || evenIfDuplicate) {
\r
986 previousMove = 2*moveNr + (dotCount > 1); // remember move nr of move last spoken
\r
987 sprintf(number, "%d", moveNr);
\r
989 yPos = CoordToNum(messageText[len-1]); /* turn char coords to ints */
\r
990 xPos = CoordToNum(messageText[len-2]);
\r
991 if(xPos < 0 || xPos > 11) return; // prevent crashes if no coord string available to speak
\r
992 if(yPos < 0 || yPos > 9) return;
\r
993 currentpiece = boards[n][yPos][xPos];
\r
994 piece = PieceToName(currentpiece,0);
\r
995 ynum = SquareToNum(yPos);
\r
996 xchar = SquareToChar(xPos);
\r
997 c = messageText[len-3];
\r
998 if(c == 'x') c = messageText[len-4];
\r
999 if(!isdigit(c) && c < 'a' && c != '@') c = 0;
\r
1000 disambiguation[0] = c;
\r
1001 SayString(WhiteOnMove(n) ? "Black" : "White", FALSE);
\r
1002 SayString("move", FALSE);
\r
1003 SayString(number, FALSE);
\r
1004 // if(c==0 || c=='@') SayString("a", FALSE);
\r
1005 // intercept castling moves
\r
1006 p = StrStr(messageText, "O-O-O");
\r
1007 if(p && p-messageText < len) {
\r
1008 SayString("queen side castling",FALSE);
\r
1011 p = StrStr(messageText, "O-O");
\r
1012 if(p && p-messageText < len) {
\r
1013 SayString("king side castling",FALSE);
\r
1018 SayString(piece, FALSE);
\r
1019 if(c == '@') SayString("dropped on", FALSE); else
\r
1020 if(c) SayString(disambiguation, FALSE);
\r
1021 SayString("to", FALSE);
\r
1022 SayString(xchar, FALSE);
\r
1023 SayString(ynum, FALSE);
\r
1024 if(messageText[len-3] == 'x') {
\r
1025 currentpiece = boards[n-1][yPos][xPos];
\r
1026 if(currentpiece != EmptySquare) {
\r
1027 piece = PieceToName(currentpiece,0);
\r
1028 SayString("Capturing a",FALSE);
\r
1029 SayString(piece, FALSE);
\r
1030 } else SayString("Capturing onn passann",FALSE);
\r
1033 if(checkMark == '+') SayString("check", FALSE); else
\r
1034 if(checkMark == '#') {
\r
1035 SayString("finishing off", FALSE);
\r
1036 SayString(WhiteOnMove(n) ? "White" : "Black", FALSE);
\r
1040 /* say comment after move, possibly with result */
\r
1042 if(StrStr(messageText, " 1-0")) p = "white wins"; else
\r
1043 if(StrStr(messageText, " 0-1")) p = "black wins"; else
\r
1044 if(StrStr(messageText, " 1/2-1/2")) p = "game ends in a draw";
\r
1047 if(!StrCaseStr(comment, "draw") &&
\r
1048 !StrCaseStr(comment, "white") &&
\r
1049 !StrCaseStr(comment, "black") ) {
\r
1050 SayString(p, FALSE);
\r
1051 SayString("due to", FALSE);
\r
1054 SayString(comment, FALSE); // alphabetic comment (usually game end)
\r
1055 } else if(p) SayString(p, FALSE);
\r
1057 if(commentDialog && commentList[currentMove]) SetFocus(commentDialog);
\r
1060 /* starts not with digit */
\r
1061 if(StrCaseStr(messageText, "illegal")) PlayIcsUnfinishedSound();
\r
1062 SayString(messageText, FALSE);
\r
1070 char buf1[50], buf2[50];
\r
1071 char *str1, *str2;
\r
1072 static long int lastWhiteTime, lastBlackTime;
\r
1074 suppressClocks = 1; // if user is using alt+T command, no reason to display them
\r
1075 if(abs(lastWhiteTime - whiteTimeRemaining) < 1000 && abs(lastBlackTime - blackTimeRemaining) < 1000)
\r
1076 suppressClocks = 0; // back on after two requests in rapid succession
\r
1077 sprintf(buf1, "%s", TimeString(whiteTimeRemaining));
\r
1079 SayString("White clock", FALSE);
\r
1080 SayString(str1, FALSE);
\r
1081 sprintf(buf2, "%s", TimeString(blackTimeRemaining));
\r
1083 SayString("Black clock", FALSE);
\r
1084 SayString(str2, FALSE);
\r
1085 lastWhiteTime = whiteTimeRemaining;
\r
1086 lastBlackTime = blackTimeRemaining;
\r
1090 Toggle(Boolean *b, char *mess)
\r
1093 SayString(mess, FALSE);
\r
1094 SayString("is now", FALSE);
\r
1095 SayString(*b ? "on" : "off", FALSE);
\r
1098 /* handles keyboard moves in a click-click fashion */
\r
1100 KeyboardMove(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
1102 ChessSquare currentpiece;
\r
1105 static BOOLEAN sameAgain = FALSE;
\r
1106 switch (message) {
\r
1108 sameAgain = FALSE;
\r
1109 if(oldFromX == fromX && oldFromY == fromY) {
\r
1111 /* click on same square */
\r
1114 else if(oldFromX != -1) {
\r
1116 ChessSquare pdown, pup;
\r
1117 pdown = boards[currentMove][oldFromY][oldFromX];
\r
1118 pup = boards[currentMove][fromY][fromX];
\r
1120 if (gameMode == EditPosition ||
\r
1121 !((WhitePawn <= pdown && pdown <= WhiteKing &&
\r
1122 WhitePawn <= pup && pup <= WhiteKing) ||
\r
1123 (BlackPawn <= pdown && pdown <= BlackKing &&
\r
1124 BlackPawn <= pup && pup <= BlackKing))) {
\r
1125 /* EditPosition, empty square, or different color piece;
\r
1126 click-click move is possible */
\r
1127 char promoChoice = NULLCHAR;
\r
1129 if (HasPromotionChoice(oldFromX, oldFromY, fromX, fromY, &promoChoice)) {
\r
1130 if (appData.alwaysPromoteToQueen) {
\r
1131 UserMoveEvent(oldFromX, oldFromY, fromX, fromY, 'q');
\r
1134 toX = fromX; toY = fromY; fromX = oldFromX; fromY = oldFromY;
\r
1135 PromotionPopup(hwnd);
\r
1136 fromX = toX; fromY = toY;
\r
1140 UserMoveEvent(oldFromX, oldFromY, fromX, fromY, promoChoice);
\r
1142 oldFromX = oldFromY = -1;
\r
1147 /* First downclick, or restart on a square with same color piece */
\r
1148 if (OKToStartUserMove(fromX, fromY)) {
\r
1151 currentpiece = boards[currentMove][fromY][fromX];
\r
1152 piece = PieceToName(currentpiece,1);
\r
1153 SayString(piece, FALSE);
\r
1154 SayString("selected", FALSE);
\r
1157 oldFromX = oldFromY = -1;
\r
1162 if (oldFromX == fromX && oldFromY == fromY) {
\r
1163 /* Upclick on same square */
\r
1165 /* Clicked same square twice: abort click-click move */
\r
1166 oldFromX = oldFromY = -1;
\r
1167 currentpiece = boards[currentMove][fromY][fromX];
\r
1168 piece = PieceToName(currentpiece,0);
\r
1169 SayString(piece, FALSE);
\r
1170 SayString("unselected", FALSE);
\r
1178 { // return TRUE for times we want to announce
\r
1180 x = (x+50)/100; // tenth of seconds
\r
1181 if(x <= 100) return (x%10 == 0);
\r
1182 if(x <= 600) return (x%100 == 0);
\r
1183 if(x <= 6000) return (x%600 == 0);
\r
1184 return (x%3000 == 0);
\r
1187 #define JAWS_ARGS \
\r
1188 { "beepOffBoard", ArgInt, (LPVOID) beeps, TRUE, (ArgIniType) 1 },\
\r
1189 { "beepEmpty", ArgInt, (LPVOID) (beeps+1), TRUE, (ArgIniType) 0 },\
\r
1190 { "beepWhite", ArgInt, (LPVOID) (beeps+2), TRUE, (ArgIniType) 0 },\
\r
1191 { "beepBlack", ArgInt, (LPVOID) (beeps+3), TRUE, (ArgIniType) 0 },\
\r
1192 { "beepHoldings", ArgInt, (LPVOID) (beeps+4), TRUE, (ArgIniType) 0 },\
\r
1194 #define JAWS_ALT_INTERCEPT \
\r
1195 if(suppressOneKey) {\
\r
1196 suppressOneKey = 0;\
\r
1197 if(GetKeyState(VK_MENU) < 0 && GetKeyState(VK_CONTROL) < 0) break;\
\r
1199 if ((char)wParam == 022 && gameMode == EditPosition) { /* <Ctl R>. Pop up piece menu */\
\r
1200 POINT pt; int x, y;\
\r
1201 SquareToPos(fromY, fromX, &x, &y);\
\r
1202 dropX = fromX; dropY = fromY;\
\r
1203 pt.x = x; pt.y = y;\
\r
1204 if(gameInfo.variant != VariantShogi)\
\r
1205 MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1);\
\r
1207 MenuPopup(hwnd, pt, LoadMenu(hInst, "ShogiPieceMenu"), -1);\
\r
1211 #define JAWS_REPLAY \
\r
1212 case '\020': /* ctrl P */\
\r
1213 { char buf[MSG_SIZ];\
\r
1214 if(GetWindowText(hwnd, buf, MSG_SIZ-1))\
\r
1215 SayString(buf, FALSE);\
\r
1219 #define JAWS_KB_NAVIGATION \
\r
1223 if(GetKeyState(VK_MENU) < 0 && GetKeyState(VK_CONTROL) < 0) {\
\r
1224 /* Control + Alt + letter used for speaking piece positions */\
\r
1225 static int lastTime; static char lastChar;\
\r
1226 int mine = 0, time = GetTickCount(); char c;\
\r
1228 if((char)wParam == lastChar && time-lastTime < 250) mine = 1;\
\r
1229 lastChar = wParam; lastTime = time;\
\r
1232 if(gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) mine = !mine;\
\r
1234 if(ToLower(c) == 'x') {\
\r
1235 SayPieces(mine ? WhitePlay : BlackPlay);\
\r
1236 suppressOneKey = 1;\
\r
1239 if(CharToPiece(c) != EmptySquare) {\
\r
1240 SayPieces(CharToPiece(mine ? ToUpper(c) : ToLower(c)));\
\r
1241 suppressOneKey = 1;\
\r
1246 switch (wParam) {\
\r
1251 KeyboardEvent(hwnd, message, wParam, lParam);\
\r
1254 KeyboardMove(hwnd, message, wParam, lParam);\
\r
1259 switch (wParam) {\
\r
1261 KeyboardMove(hwnd, message, wParam, lParam);\
\r
1266 #define JAWS_MENU_ITEMS \
\r
1267 case IDM_PossibleAttackMove: /*What can I possible attack from here */\
\r
1268 PossibleAttackMove();\
\r
1271 case IDM_PossibleAttacked: /*what can possible attack this square*/\
\r
1272 PossibleAttacked();\
\r
1275 case IDM_ReadRow: /* Read the current row of pieces */\
\r
1279 case IDM_ReadColumn: /* Read the current column of pieces */\
\r
1283 case IDM_SayCurrentPos: /* Say current position including color */\
\r
1287 case IDM_SayAllBoard: /* Say the whole board from bottom to top */\
\r
1291 case IDM_SayMachineMove: /* Say the last move made */\
\r
1293 SayMachineMove(1);\
\r
1296 case IDM_SayUpperDiagnols: /* Says the diagnol positions above you */\
\r
1297 SayUpperDiagnols();\
\r
1300 case IDM_SayLowerDiagnols: /* Say the diagnol positions below you */\
\r
1301 SayLowerDiagnols();\
\r
1304 case IDM_SayBlackPieces: /*Say the opponents pieces */\
\r
1305 SayPieces(BlackPlay);\
\r
1308 case IDM_SayWhitePieces: /*Say the opponents pieces */\
\r
1309 SayPieces(WhitePlay);\
\r
1312 case IDM_SayClockTime: /*Say the clock time */\
\r
1316 case IDM_SayWhosTurn: /* Say whos turn it its */\
\r
1320 case IDM_SayKnightMoves: /* Say Knights (L-shaped) move */\
\r
1321 SayKnightMoves();\
\r
1324 case OPT_PonderNextMove: /* Toggle option setting */\
\r
1325 Toggle(&appData.ponderNextMove, "ponder");\
\r
1328 case OPT_AnimateMoving: /* Toggle option setting */\
\r
1329 Toggle(&appData.animate, "animate moving");\
\r
1332 case OPT_AutoFlag: /* Toggle option setting */\
\r
1333 Toggle(&appData.autoCallFlag, "auto flag");\
\r
1336 case OPT_AlwaysQueen: /* Toggle option setting */\
\r
1337 Toggle(&appData.alwaysPromoteToQueen, "always promote to queen");\
\r
1340 case OPT_TestLegality: /* Toggle option setting */\
\r
1341 Toggle(&appData.testLegality, "legality testing");\
\r
1344 case OPT_HideThinkFromHuman: /* Toggle option setting */\
\r
1345 Toggle(&appData.hideThinkingFromHuman, "hide thinking");\
\r
1346 ShowThinkingEvent();\
\r
1349 case OPT_SaveExtPGN: /* Toggle option setting */\
\r
1350 Toggle(&appData.saveExtendedInfoInPGN, "extended P G N info");\
\r
1353 case OPT_ExtraInfoInMoveHistory: /* Toggle option setting */\
\r
1354 Toggle(&appData.showEvalInMoveHistory, "extra info in move histoty");\
\r
1359 #define JAWS_ACCEL \
\r
1360 !(!frozen && TranslateAccelerator(hwndMain, hAccelJAWS, &msg)) &&
\r
1362 #define JAWS_INIT if (!InitJAWS()) return (FALSE);
\r
1364 #define JAWS_DELETE(X)
\r
1366 #define JAWS_SILENCE if(suppressClocks) return;
\r
1368 #define JAWS_COPYRIGHT \
\r
1369 SetDlgItemText(hDlg, OPT_MESS, "Auditory/Keyboard Enhancements By: Ed Rodriguez (sort of)");
\r
1371 #define SAY(S) SayString((S), FALSE)
\r
1373 #define SAYMACHINEMOVE() SayMachineMove(0)
\r
1375 // After inclusion of this file somewhere early in winboard.c, the remaining part of the patch
\r
1376 // is scattered over winboard.c for actually calling the routines.
\r