2 * JAWS.c -- Code for Windows front end to XBoard to use it with JAWS
\r
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
\r
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
\r
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
\r
10 * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,
\r
11 * which was written and is copyrighted by Wayne Christopher.
\r
13 * The following terms apply to Digital Equipment Corporation's copyright
\r
14 * interest in XBoard:
\r
15 * ------------------------------------------------------------------------
\r
16 * All Rights Reserved
\r
18 * Permission to use, copy, modify, and distribute this software and its
\r
19 * documentation for any purpose and without fee is hereby granted,
\r
20 * provided that the above copyright notice appear in all copies and that
\r
21 * both that copyright notice and this permission notice appear in
\r
22 * supporting documentation, and that the name of Digital not be
\r
23 * used in advertising or publicity pertaining to distribution of the
\r
24 * software without specific, written prior permission.
\r
26 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
\r
27 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
\r
28 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
\r
29 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
\r
30 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
\r
31 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
\r
33 * ------------------------------------------------------------------------
\r
35 * The following terms apply to the enhanced version of XBoard
\r
36 * distributed by the Free Software Foundation:
\r
37 * ------------------------------------------------------------------------
\r
39 * GNU XBoard is free software: you can redistribute it and/or modify
\r
40 * it under the terms of the GNU General Public License as published by
\r
41 * the Free Software Foundation, either version 3 of the License, or (at
\r
42 * your option) any later version.
\r
44 * GNU XBoard is distributed in the hope that it will be useful, but
\r
45 * WITHOUT ANY WARRANTY; without even the implied warranty of
\r
46 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
47 * General Public License for more details.
\r
49 * You should have received a copy of the GNU General Public License
\r
50 * along with this program. If not, see http://www.gnu.org/licenses/. *
\r
52 *------------------------------------------------------------------------
\r
53 ** See the file ChangeLog for a revision history. */
\r
55 // This file collects all patches for the JAWS version, so they can all be included in winboard.c
\r
56 // in one big swoop. At the bottom of this file you can read instructions for how to patch
\r
57 // WinBoard to work with JAWS with the aid of this file. Note that the code in this file
\r
58 // is for WinBoard 4.3 and later; for older WB versions you would have to throw out the
\r
59 // piece names for all pieces from Guard to Unicorn, #define ONE as '1', AAA as 'a',
\r
60 // BOARD_LEFT as 0, BOARD_RGHT and BOARD_HEIGHT as 8, and set holdingssizes to 0.
\r
61 // You will need to build with jaws.rc in stead of winboard.rc.
\r
65 #define IDM_PossibleAttackMove 1800
\r
66 #define IDM_PossibleAttacked 1801
\r
67 #define IDM_SayMachineMove 1802
\r
68 #define IDM_ReadRow 1803
\r
69 #define IDM_ReadColumn 1804
\r
70 #define IDM_SayCurrentPos 1805
\r
71 #define IDM_SayAllBoard 1806
\r
72 #define IDM_SayUpperDiagnols 1807
\r
73 #define IDM_SayLowerDiagnols 1808
\r
74 #define IDM_SayClockTime 1810
\r
75 #define IDM_SayWhosTurn 1811
\r
76 #define IDM_SayKnightMoves 1812
\r
77 #define ID_SHITTY_HI 1813
\r
78 #define IDM_SayWhitePieces 1816
\r
79 #define IDM_SayBlackPieces 1817
\r
82 // from common.h, but 'extern' added to it, so the actual declaraton can remain in backend.c
\r
84 extern long whiteTimeRemaining, blackTimeRemaining, timeControl, timeIncrement;
\r
86 // from moves.c, added WinBoard_F piece types and ranks / files
\r
88 char *squareToChar[] = { "ay", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l" };
\r
90 char *squareToNum[] = {"naught", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
\r
92 char *ordinals[] = {"zeroth", "first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "nineth"};
\r
94 char *pieceToName[] = {
\r
95 "White Pawn", "White Knight", "White Bishop", "White Rook", "White Queen",
\r
96 "White Guard", "White Elephant", "White Arch Bishop", "White Chancellor",
\r
97 "White General", "White Man", "White Cannon", "White Night Rider",
\r
98 "White Crowned Bishop", "White Crowned Rook", "White Grass Hopper", "White Veteran",
\r
99 "White Falcon", "White Amazon", "White Snake", "White Unicorn",
\r
101 "Black Pawn", "Black Knight", "Black Bishop", "Black Rook", "Black Queen",
\r
102 "Black Guard", "Black Elephant", "Black Arch Bishop", "Black Chancellor",
\r
103 "Black General", "Black Man", "Black Cannon", "Black Night Rider",
\r
104 "Black Crowned Bishop", "Black Crowned Rook", "Black Grass Hopper", "Black Veteran",
\r
105 "Black Falcon", "Black Amazon", "Black Snake", "Black Unicorn",
\r
110 char *pieceTypeName[] = {
\r
111 "Pawn", "Knight", "Bishop", "Rook", "Queen",
\r
112 "Guard", "Elephant", "Arch Bishop", "Chancellor",
\r
113 "General", "Man", "Cannon", "Night Rider",
\r
114 "Crowned Bishop", "Crowned Rook", "Grass Hopper", "Veteran",
\r
115 "Falcon", "Amazon", "Snake", "Unicorn",
\r
117 "Pawn", "Knight", "Bishop", "Rook", "Queen",
\r
118 "Guard", "Elephant", "Arch Bishop", "Chancellor",
\r
119 "General", "Man", "Cannon", "Night Rider",
\r
120 "Crowned Bishop", "Crowned Rook", "Grass Hopper", "Veteran",
\r
121 "Falcon", "Amazon", "Snake", "Unicorn",
\r
129 if(isdigit(c)) return c - ONE;
\r
130 if(c >= 'a') return c - AAA;
\r
134 char* PieceToName(p, i)
\r
138 if(i) return pieceToName[(int) p];
\r
139 return pieceTypeName[(int) p];
\r
142 char* SquareToChar(x)
\r
145 return squareToChar[x - BOARD_LEFT];
\r
148 char* SquareToNum(y)
\r
151 return squareToNum[y + (gameInfo.boardHeight < 10)];
\r
155 // from winboard.c: all new routines
\r
156 #define JFWAPI __declspec(dllimport)
\r
157 JFWAPI BOOL WINAPI JFWSayString (LPCTSTR lpszStrinToSpeak, BOOL bInterrupt);
\r
159 typedef JFWAPI BOOL (WINAPI *PSAYSTRING)(LPCTSTR lpszStrinToSpeak, BOOL bInterrupt);
\r
161 PSAYSTRING RealSayString;
\r
163 VOID SayString(char *mess, BOOL flag)
\r
164 { // for debug file
\r
165 char buf[8000], *p;
\r
166 if(appData.debugMode) fprintf(debugFP, "SAY '%s'\n", mess);
\r
168 if(p = StrCaseStr(buf, "Xboard adjudication:")) {
\r
170 for(i=19; i>1; i--) p[i] = p[i-1];
\r
173 RealSayString(buf, flag);
\r
176 //static int fromX = 0, fromY = 0;
\r
177 static int oldFromX, oldFromY;
\r
178 static int timeflag;
\r
179 static int suppressClocks = 0;
\r
180 static int suppressOneKey = 0;
\r
181 static HANDLE hAccelJAWS;
\r
183 typedef struct { char *name; int code; } MenuItemDesc;
\r
185 MenuItemDesc menuItemJAWS[] = {
\r
186 {"Say Clock &Time\tAlt+T", IDM_SayClockTime },
\r
188 {"Say Last &Move\tAlt+M", IDM_SayMachineMove },
\r
189 {"Say W&ho's Turn\tAlt+X", IDM_SayWhosTurn },
\r
191 {"Say Complete &Position\tAlt+P",IDM_SayAllBoard },
\r
192 {"Say &White Pieces\tAlt+W", IDM_SayWhitePieces },
\r
193 {"Say &Black Pieces\tAlt+B", IDM_SayBlackPieces },
\r
194 {"Say Board &Rank\tAlt+R", IDM_ReadRow },
\r
195 {"Say Board &File\tAlt+F", IDM_ReadColumn },
\r
197 {"Say &Upper Diagonals\tAlt+U", IDM_SayUpperDiagnols },
\r
198 {"Say &Lower Diagonals\tAlt+L", IDM_SayLowerDiagnols },
\r
199 {"Say K&night Moves\tAlt+N", IDM_SayKnightMoves },
\r
200 {"Say Current &Square\tAlt+S", IDM_SayCurrentPos },
\r
201 {"Say &Attacks\tAlt+A", IDM_PossibleAttackMove },
\r
202 {"Say Attacke&d\tAlt+D", IDM_PossibleAttacked },
\r
206 ACCEL acceleratorsJAWS[] = {
\r
207 {FVIRTKEY|FALT, 'T', IDM_SayClockTime },
\r
208 {FVIRTKEY|FALT, 'M', IDM_SayMachineMove },
\r
209 {FVIRTKEY|FALT, 'X', IDM_SayWhosTurn },
\r
210 {FVIRTKEY|FALT, 'P', IDM_SayAllBoard },
\r
211 {FVIRTKEY|FALT, 'W', IDM_SayWhitePieces },
\r
212 {FVIRTKEY|FALT, 'B', IDM_SayBlackPieces },
\r
213 {FVIRTKEY|FALT, 'R', IDM_ReadRow },
\r
214 {FVIRTKEY|FALT, 'F', IDM_ReadColumn },
\r
215 {FVIRTKEY|FALT, 'U', IDM_SayUpperDiagnols },
\r
216 {FVIRTKEY|FALT, 'L', IDM_SayLowerDiagnols },
\r
217 {FVIRTKEY|FALT, 'N', IDM_SayKnightMoves },
\r
218 {FVIRTKEY|FALT, 'S', IDM_SayCurrentPos },
\r
219 {FVIRTKEY|FALT, 'A', IDM_PossibleAttackMove },
\r
220 {FVIRTKEY|FALT, 'D', IDM_PossibleAttacked }
\r
226 HMENU menuMain, menuJAWS;
\r
227 MENUBARINFO helpMenuInfo;
\r
230 helpMenuInfo.cbSize = sizeof(helpMenuInfo);
\r
231 menuMain = GetMenu(hwndMain);
\r
232 menuJAWS = CreatePopupMenu();
\r
234 for(i=0; menuItemJAWS[i].name; i++) {
\r
235 if(menuItemJAWS[i].name[0] == '-')
\r
236 AppendMenu(menuJAWS, MF_SEPARATOR, (UINT_PTR) 0, NULL);
\r
237 else AppendMenu(menuJAWS, MF_ENABLED|MF_STRING,
\r
238 (UINT_PTR) menuItemJAWS[i].code, (LPCTSTR) menuItemJAWS[i].name);
\r
240 InsertMenu(menuMain, 5, MF_BYPOSITION|MF_POPUP|MF_ENABLED|MF_STRING,
\r
241 (UINT_PTR) menuJAWS, "&JAWS");
\r
242 oldMenuItemState[6] = oldMenuItemState[5];
\r
243 DrawMenuBar(hwndMain);
\r
248 { // to be called at beginning of WinMain, after InitApplication and InitInstance
\r
249 HINSTANCE hApi = LoadLibrary("jfwapi32.dll");
\r
251 DisplayInformation("Missing jfwapi32.dll");
\r
255 RealSayString = (PSAYSTRING)GetProcAddress(hApi, "JFWSayString");
\r
256 if(!RealSayString) {
\r
257 DisplayInformation("SayString returned a null pointer");
\r
262 // [HGM] kludge to reduce need for modification of winboard.c: make tinyLayout menu identical
\r
263 // to standard layout, so that code for switching between them does not have to be deleted
\r
267 menuBarText[0][5] = "&JAWS";
\r
268 for(i=0; i<7; i++) menuBarText[1][i] = menuBarText[0][i];
\r
271 hAccelJAWS = CreateAcceleratorTable(acceleratorsJAWS, 14);
\r
273 /* initialize cursor position */
\r
275 SetHighlights(fromX, fromY, -1, -1);
\r
276 DrawPosition(FALSE, NULL);
\r
277 oldFromX = oldFromY = -1;
\r
279 if(hwndConsole) SetFocus(hwndConsole);
\r
283 int beeps[] = { 1, 0, 0, 0, 0 };
\r
284 int beepCodes[] = { 0, MB_OK, MB_ICONERROR, MB_ICONQUESTION, MB_ICONEXCLAMATION, MB_ICONASTERISK };
\r
287 KeyboardEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
289 ChessSquare currentPiece;
\r
290 char *piece, *xchar, *ynum ;
\r
291 int n, beepType = 1; // empty beep
\r
293 if(fromX == -1 || fromY == -1) {
\r
294 fromX = BOARD_LEFT; fromY = 0;
\r
298 if(fromX == BOARD_RGHT+1) fromX -= 2; else
\r
299 if(fromX == BOARD_LEFT) { if(fromY >= BOARD_HEIGHT - gameInfo.holdingsSize) fromX -= 2; else beepType = 0; } else
\r
300 if(fromX > BOARD_LEFT) fromX--; else beepType = 0; // off-board beep
\r
303 if(fromX == BOARD_LEFT-2) fromX += 2; else
\r
304 if(fromX == BOARD_RGHT-1) { if(fromY < gameInfo.holdingsSize) fromX += 2; else beepType = 0; } else
\r
305 if(fromX < BOARD_RGHT-1) fromX++; else beepType = 0;
\r
308 if(fromX == BOARD_RGHT+1) { if(fromY < gameInfo.holdingsSize - 1) fromY++; else beepType = 0; } else
\r
309 if(fromY < BOARD_HEIGHT-1) fromY++; else beepType = 0;
\r
312 if(fromX == BOARD_LEFT-2) { if(fromY > BOARD_HEIGHT - gameInfo.holdingsSize) fromY--; else beepType = 0; } else
\r
313 if(fromY > 0) fromY--; else beepType = 0;
\r
316 SetHighlights(fromX, fromY, -1, -1);
\r
317 DrawPosition(FALSE, NULL);
\r
318 currentPiece = boards[currentMove][fromY][fromX];
\r
319 piece = PieceToName(currentPiece,1);
\r
320 if(beepType == 1 && currentPiece != EmptySquare) beepType = currentPiece < (int) BlackPawn ? 2 : 3; // white or black beep
\r
321 if(beeps[beepType] == beeps[1] && (fromX == BOARD_RGHT+1 || fromX == BOARD_LEFT-2)) beepType = 4; // holdings beep
\r
322 beepType = beeps[beepType]%6;
\r
323 if(beepType) MessageBeep(beepCodes[beepType]);
\r
324 if(fromX == BOARD_LEFT - 2) {
\r
325 SayString("black holdings", FALSE);
\r
326 if(currentPiece != EmptySquare) {
\r
328 n = boards[currentMove][fromY][1];
\r
329 sprintf(buf, "%d %s%s", n, PieceToName(currentPiece,0), n == 1 ? "" : "s");
\r
330 SayString(buf, TRUE);
\r
333 if(fromX == BOARD_RGHT + 1) {
\r
334 SayString("white holdings", FALSE);
\r
335 if(currentPiece != EmptySquare) {
\r
337 n = boards[currentMove][fromY][BOARD_WIDTH-2];
\r
338 sprintf(buf, "%d %s%s", n, PieceToName(currentPiece,0), n == 1 ? "" : "s");
\r
339 SayString(buf, TRUE);
\r
342 if(fromX >= BOARD_LEFT && fromX < BOARD_RGHT) {
\r
344 xchar = SquareToChar(fromX);
\r
345 ynum = SquareToNum(fromY);
\r
346 if(currentPiece != EmptySquare) {
\r
347 // SayString(piece[0] == 'W' ? "white" : "black", TRUE);
\r
348 sprintf(buf, "%s %s %s", piece, xchar, ynum);
\r
349 } else sprintf(buf, "%s %s", xchar, ynum);
\r
350 SayString(buf, TRUE);
\r
355 int PosFlags(int nr);
\r
358 int rf, ff, rt, ft;
\r
363 extern void ReadCallback P((Board board, int flags, ChessMove kind,
\r
364 int rf, int ff, int rt, int ft,
\r
365 VOIDSTAR closure));
\r
367 void ReadCallback(board, flags, kind, rf, ff, rt, ft, closure)
\r
371 int rf, ff, rt, ft;
\r
374 register ReadClosure *cl = (ReadClosure *) closure;
\r
375 ChessSquare possiblepiece;
\r
376 char *piece, *xchar, *ynum ;
\r
378 //if(appData.debugMode) fprintf(debugFP, "%c%c%c%c\n", ff+AAA, rf+ONE, ft+AAA, rt+ONE);
\r
379 if(cl->ff == ff && cl->rf == rf) {
\r
380 possiblepiece = board[rt][ft];
\r
381 if(possiblepiece != EmptySquare) {
\r
382 piece = PieceToName(possiblepiece,1);
\r
383 xchar = SquareToChar(ft);
\r
384 ynum = SquareToNum(rt);
\r
385 SayString(xchar , FALSE);
\r
386 SayString(ynum, FALSE);
\r
387 SayString(piece, FALSE);
\r
391 if(cl->ft == ft && cl->rt == rt) {
\r
392 possiblepiece = board[rf][ff];
\r
393 piece = PieceToName(possiblepiece,1);
\r
394 xchar = SquareToChar(ff);
\r
395 ynum = SquareToNum(rf);
\r
396 SayString(xchar , FALSE);
\r
397 SayString(ynum, FALSE);
\r
398 SayString(piece, FALSE);
\r
404 PossibleAttackMove()
\r
407 ChessSquare piece, victim;
\r
408 int removedSelectedPiece = 0, swapColor;
\r
410 //if(appData.debugMode) fprintf(debugFP, "PossibleAttackMove %d %d %d %d\n", fromX, fromY, oldFromX, oldFromY);
\r
411 if(fromY < 0 || fromY >= BOARD_HEIGHT) return;
\r
412 if(fromX < BOARD_LEFT || fromX >= BOARD_RGHT) { SayString("holdings",FALSE); return; }
\r
414 piece = boards[currentMove][fromY][fromX];
\r
415 if(piece == EmptySquare) { // if square is empty, try to substitute selected piece
\r
416 if(oldFromX >= 0 && oldFromY >= 0) {
\r
417 piece = boards[currentMove][oldFromY][oldFromX];
\r
418 boards[currentMove][oldFromY][oldFromX] = EmptySquare;
\r
419 removedSelectedPiece = 1;
\r
420 SayString("Your", FALSE);
\r
421 SayString(PieceToName(piece, 0), FALSE);
\r
422 SayString("would have", FALSE);
\r
423 } else { SayString("You must select a piece first", FALSE); return; }
\r
426 victim = boards[currentMove][fromY][fromX];
\r
427 boards[currentMove][fromY][fromX] = piece; // make sure piece is actally there
\r
428 SayString("possible captures from here are", FALSE);
\r
430 swapColor = piece < (int)BlackPawn && !WhiteOnMove(currentMove) ||
\r
431 piece >= (int)BlackPawn && WhiteOnMove(currentMove);
\r
432 cl.count = 0; cl.rf = fromY; cl.ff = fromX; cl.rt = cl.ft = -1;
\r
433 GenLegal(boards[currentMove], PosFlags(currentMove + swapColor), ReadCallback, (VOIDSTAR) &cl);
\r
434 if(cl.count == 0) SayString("None", FALSE);
\r
435 boards[currentMove][fromY][fromX] = victim; // repair
\r
437 if( removedSelectedPiece ) boards[currentMove][oldFromY][oldFromX] = piece;
\r
445 ChessSquare piece = EmptySquare, victim;
\r
447 if(fromY < 0 || fromY >= BOARD_HEIGHT) return;
\r
448 if(fromX < BOARD_LEFT || fromX >= BOARD_RGHT) { SayString("holdings",FALSE); return; }
\r
450 if(oldFromX >= 0 && oldFromY >= 0) { // if piece is selected, remove it
\r
451 piece = boards[currentMove][oldFromY][oldFromX];
\r
452 boards[currentMove][oldFromY][oldFromX] = EmptySquare;
\r
455 SayString("Pieces that can capture you are", FALSE);
\r
457 victim = boards[currentMove][fromY][fromX]; // put dummy piece on target square, to activate Pawn captures
\r
458 boards[currentMove][fromY][fromX] = WhiteOnMove(currentMove) ? WhiteQueen : BlackQueen;
\r
459 cl.count = 0; cl.rt = fromY; cl.ft = fromX; cl.rf = cl.ff = -1;
\r
460 GenLegal(boards[currentMove], PosFlags(currentMove+1), ReadCallback, (VOIDSTAR) &cl);
\r
461 if(cl.count == 0) SayString("None", FALSE);
\r
463 SayString("You are defended by", FALSE);
\r
465 boards[currentMove][fromY][fromX] = WhiteOnMove(currentMove) ? BlackQueen : WhiteQueen;
\r
466 cl.count = 0; cl.rt = fromY; cl.ft = fromX; cl.rf = cl.ff = -1;
\r
467 GenLegal(boards[currentMove], PosFlags(currentMove), ReadCallback, (VOIDSTAR) &cl);
\r
468 if(cl.count == 0) SayString("None", FALSE);
\r
469 boards[currentMove][fromY][fromX] = victim; // put back original occupant
\r
471 if(oldFromX >= 0 && oldFromY >= 0) { // put back possibl selected piece
\r
472 boards[currentMove][oldFromY][oldFromX] = piece;
\r
479 ChessSquare currentpiece;
\r
480 char *piece, *xchar, *ynum ;
\r
482 ynum = SquareToNum(fromY);
\r
484 if(fromY < 0) return;
\r
486 for (xPos=BOARD_LEFT; xPos<BOARD_RGHT; xPos++) {
\r
487 currentpiece = boards[currentMove][fromY][xPos];
\r
488 if(currentpiece != EmptySquare) {
\r
489 piece = PieceToName(currentpiece,1);
\r
490 xchar = SquareToChar(xPos);
\r
491 SayString(xchar , FALSE);
\r
492 SayString(ynum, FALSE);
\r
493 SayString(piece, FALSE);
\r
498 SayString("rank", FALSE);
\r
499 SayString(ynum, FALSE);
\r
500 SayString("empty", FALSE);
\r
507 ChessSquare currentpiece;
\r
508 char *piece, *xchar, *ynum ;
\r
510 xchar = SquareToChar(fromX);
\r
512 if(fromX < 0) return;
\r
514 for (yPos=0; yPos<BOARD_HEIGHT; yPos++) {
\r
515 currentpiece = boards[currentMove][yPos][fromX];
\r
516 if(currentpiece != EmptySquare) {
\r
517 piece = PieceToName(currentpiece,1);
\r
518 ynum = SquareToNum(yPos);
\r
519 SayString(xchar , FALSE);
\r
520 SayString(ynum, FALSE);
\r
521 SayString(piece, FALSE);
\r
526 SayString(xchar, FALSE);
\r
527 SayString("file empty", FALSE);
\r
534 ChessSquare currentpiece;
\r
535 char *piece, *xchar, *ynum ;
\r
538 if(fromX < 0 || fromY < 0) return;
\r
540 if(fromX < BOARD_RGHT-1 && fromY < BOARD_HEIGHT-1) {
\r
541 SayString("The diagnol squares to your upper right contain", FALSE);
\r
544 while(yPos<BOARD_HEIGHT && xPos<BOARD_RGHT) {
\r
545 currentpiece = boards[currentMove][yPos][xPos];
\r
546 piece = PieceToName(currentpiece,1);
\r
547 xchar = SquareToChar(xPos);
\r
548 ynum = SquareToNum(yPos);
\r
549 SayString(xchar , FALSE);
\r
550 SayString(ynum, FALSE);
\r
551 SayString(piece, FALSE);
\r
556 else SayString("There is no squares to your upper right", FALSE);
\r
558 if(fromX > BOARD_LEFT && fromY < BOARD_HEIGHT-1) {
\r
559 SayString("The diagnol squares to your upper left contain", FALSE);
\r
562 while(yPos<BOARD_HEIGHT && xPos>=BOARD_LEFT) {
\r
563 currentpiece = boards[currentMove][yPos][xPos];
\r
564 piece = PieceToName(currentpiece,1);
\r
565 xchar = SquareToChar(xPos);
\r
566 ynum = SquareToNum(yPos);
\r
567 SayString(xchar , FALSE);
\r
568 SayString(ynum, FALSE);
\r
569 SayString(piece, FALSE);
\r
574 else SayString("There is no squares to your upper left", FALSE);
\r
580 ChessSquare currentpiece;
\r
581 char *piece, *xchar, *ynum ;
\r
584 if(fromX < 0 || fromY < 0) return;
\r
586 if(fromX < BOARD_RGHT-1 && fromY > 0) {
\r
587 SayString("The diagnol squares to your lower right contain", FALSE);
\r
590 while(yPos>=0 && xPos<BOARD_RGHT) {
\r
591 currentpiece = boards[currentMove][yPos][xPos];
\r
592 piece = PieceToName(currentpiece,1);
\r
593 xchar = SquareToChar(xPos);
\r
594 ynum = SquareToNum(yPos);
\r
595 SayString(xchar , FALSE);
\r
596 SayString(ynum, FALSE);
\r
597 SayString(piece, FALSE);
\r
602 else SayString("There is no squares to your lower right", FALSE);
\r
604 if(fromX > BOARD_LEFT && fromY > 0) {
\r
605 SayString("The diagnol squares to your lower left contain", FALSE);
\r
608 while(yPos>=0 && xPos>=BOARD_LEFT) {
\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 left", FALSE);
\r
626 ChessSquare currentpiece, oldpiece;
\r
627 char *piece, *xchar, *ynum ;
\r
629 oldpiece = boards[currentMove][fromY][fromX];
\r
630 if(oldpiece == WhiteKnight || oldpiece == BlackKnight)
\r
631 SayString("The possible squares a Knight could move to are", FALSE);
\r
633 SayString("The squares a Knight could possibly attack from are", FALSE);
\r
635 if (fromY+2 < BOARD_HEIGHT && fromX-1 >= BOARD_LEFT) {
\r
636 currentpiece = boards[currentMove][fromY+2][fromX-1];
\r
637 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
638 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
639 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
641 piece = PieceToName(currentpiece,1);
\r
642 xchar = SquareToChar(fromX-1);
\r
643 ynum = SquareToNum(fromY+2);
\r
644 SayString(xchar , FALSE);
\r
645 SayString(ynum, FALSE);
\r
646 SayString(piece, FALSE);
\r
650 if (fromY+2 < BOARD_HEIGHT && fromX+1 < BOARD_RGHT) {
\r
651 currentpiece = boards[currentMove][fromY+2][fromX+1];
\r
652 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
653 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
654 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
656 piece = PieceToName(currentpiece,1);
\r
657 xchar = SquareToChar(fromX+1);
\r
658 ynum = SquareToNum(fromY+2);
\r
659 SayString(xchar , FALSE);
\r
660 SayString(ynum, FALSE);
\r
661 SayString(piece, FALSE);
\r
665 if (fromY+1 < BOARD_HEIGHT && fromX+2 < BOARD_RGHT) {
\r
666 currentpiece = boards[currentMove][fromY+1][fromX+2];
\r
667 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
668 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
669 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
671 piece = PieceToName(currentpiece,1);
\r
672 xchar = SquareToChar(fromX+2);
\r
673 ynum = SquareToNum(fromY+1);
\r
674 SayString(xchar , FALSE);
\r
675 SayString(ynum, FALSE);
\r
676 SayString(piece, FALSE);
\r
680 if (fromY-1 >= 0 && fromX+2 < BOARD_RGHT) {
\r
681 currentpiece = boards[currentMove][fromY-1][fromX+2];
\r
682 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
683 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
684 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
686 piece = PieceToName(currentpiece,1);
\r
687 xchar = SquareToChar(fromX+2);
\r
688 ynum = SquareToNum(fromY-1);
\r
689 SayString(xchar , FALSE);
\r
690 SayString(ynum, FALSE);
\r
691 SayString(piece, FALSE);
\r
695 if (fromY-2 >= 0 && fromX+1 < BOARD_RGHT) {
\r
696 currentpiece = boards[currentMove][fromY-2][fromX+1];
\r
697 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
698 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
699 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
701 piece = PieceToName(currentpiece,1);
\r
702 xchar = SquareToChar(fromX+1);
\r
703 ynum = SquareToNum(fromY-2);
\r
704 SayString(xchar , FALSE);
\r
705 SayString(ynum, FALSE);
\r
706 SayString(piece, FALSE);
\r
710 if (fromY-2 >= 0 && fromX-1 >= BOARD_LEFT) {
\r
711 currentpiece = boards[currentMove][fromY-2][fromX-1];
\r
712 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
713 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
714 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
716 piece = PieceToName(currentpiece,1);
\r
717 xchar = SquareToChar(fromX-1);
\r
718 ynum = SquareToNum(fromY-2);
\r
719 SayString(xchar , FALSE);
\r
720 SayString(ynum, FALSE);
\r
721 SayString(piece, FALSE);
\r
725 if (fromY-1 >= 0 && fromX-2 >= BOARD_LEFT) {
\r
726 currentpiece = boards[currentMove][fromY-1][fromX-2];
\r
727 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
728 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
729 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
731 piece = PieceToName(currentpiece,1);
\r
732 xchar = SquareToChar(fromX-2);
\r
733 ynum = SquareToNum(fromY-1);
\r
734 SayString(xchar , FALSE);
\r
735 SayString(ynum, FALSE);
\r
736 SayString(piece, FALSE);
\r
740 if (fromY+1 < BOARD_HEIGHT && fromX-2 >= BOARD_LEFT) {
\r
741 currentpiece = boards[currentMove][fromY+1][fromX-2];
\r
742 if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))
\r
743 || ((oldpiece == BlackKnight) && (currentpiece < BlackPawn || currentpiece == EmptySquare))
\r
744 || (oldpiece == EmptySquare) && (currentpiece == WhiteKnight || currentpiece == BlackKnight))
\r
746 piece = PieceToName(currentpiece,1);
\r
747 xchar = SquareToChar(fromX-2);
\r
748 ynum = SquareToNum(fromY+1);
\r
749 SayString(xchar , FALSE);
\r
750 SayString(ynum, FALSE);
\r
751 SayString(piece, FALSE);
\r
757 SayPieces(ChessSquare p)
\r
759 ChessSquare currentpiece;
\r
760 char *piece, *xchar, *ynum ;
\r
761 int yPos, xPos, count = 0;
\r
764 if(p == WhitePlay) SayString("White pieces", FALSE); else
\r
765 if(p == BlackPlay) SayString("Black pieces", FALSE); else
\r
766 if(p == EmptySquare) SayString("Pieces", FALSE); else {
\r
767 sprintf(buf, "%ss", PieceToName(p,1));
\r
768 SayString(buf, FALSE);
\r
770 SayString("are located", FALSE);
\r
771 for(yPos=0; yPos<BOARD_HEIGHT; yPos++) {
\r
772 for(xPos=BOARD_LEFT; xPos<BOARD_RGHT; xPos++) {
\r
773 currentpiece = boards[currentMove][yPos][xPos];
\r
774 if(p == BlackPlay && currentpiece >= BlackPawn && currentpiece <= BlackKing ||
\r
775 p == WhitePlay && currentpiece >= WhitePawn && currentpiece <= WhiteKing )
\r
776 piece = PieceToName(currentpiece,0);
\r
777 else if(p == EmptySquare && currentpiece != EmptySquare)
\r
778 piece = PieceToName(currentpiece,1);
\r
779 else if(p == currentpiece)
\r
783 if(count == 0) SayString("at", FALSE);
\r
784 xchar = SquareToChar(xPos);
\r
785 ynum = SquareToNum(yPos);
\r
786 SayString(xchar , FALSE);
\r
787 SayString(ynum, FALSE);
\r
788 if(piece) SayString(piece, FALSE);
\r
792 if(count == 0) SayString("nowhere", FALSE);
\r
798 ChessSquare currentpiece;
\r
799 char *piece, *xchar, *ynum ;
\r
800 if(fromX < BOARD_LEFT) { SayString("You strayed into the white holdings", FALSE); return; }
\r
801 if(fromX >= BOARD_RGHT) { SayString("You strayed into the black holdings", FALSE); return; }
\r
802 currentpiece = boards[currentMove][fromY][fromX];
\r
803 piece = PieceToName(currentpiece,1);
\r
804 ynum = SquareToNum(fromY);
\r
805 xchar = SquareToChar(fromX);
\r
806 SayString("Your current position is", FALSE);
\r
807 SayString(xchar, FALSE);
\r
808 SayString(ynum, FALSE);
\r
809 SayString(piece, FALSE);
\r
810 if(((fromX-BOARD_LEFT) ^ fromY)&1)
\r
811 SayString("on a light square",FALSE);
\r
813 SayString("on a dark square",FALSE);
\r
815 PossibleAttacked();
\r
823 ChessSquare currentpiece;
\r
824 char *piece, *ynum ;
\r
826 if(gameInfo.holdingsWidth) {
\r
828 for(Ypos=0; Ypos<gameInfo.holdingsSize; Ypos++) {
\r
829 int n = boards[currentMove][Ypos][BOARD_WIDTH-2];
\r
830 if(n) { char buf[MSG_SIZ];
\r
831 if(!first++) SayString("white holds", FALSE);
\r
832 currentpiece = boards[currentMove][Ypos][BOARD_WIDTH-1];
\r
833 piece = PieceToName(currentpiece,0);
\r
834 sprintf(buf, "%d %s%s", n, piece, (n==1 ? "" : "s") );
\r
835 SayString(buf, FALSE);
\r
839 for(Ypos=BOARD_HEIGHT-1; Ypos>=BOARD_HEIGHT - gameInfo.holdingsSize; Ypos--) {
\r
840 int n = boards[currentMove][Ypos][1];
\r
841 if(n) { char buf[MSG_SIZ];
\r
842 if(!first++) SayString("black holds", FALSE);
\r
843 currentpiece = boards[currentMove][Ypos][0];
\r
844 piece = PieceToName(currentpiece,0);
\r
845 sprintf(buf, "%d %s%s", n, piece, (n==1 ? "" : "s") );
\r
846 SayString(buf, FALSE);
\r
851 for(Ypos=BOARD_HEIGHT-1; Ypos>=0; Ypos--) {
\r
852 ynum = ordinals[Ypos + (gameInfo.boardHeight < 10)];
\r
853 SayString(ynum, FALSE);
\r
854 SayString("rank", FALSE);
\r
855 for(Xpos=BOARD_LEFT; Xpos<BOARD_RGHT; Xpos++) {
\r
856 currentpiece = boards[currentMove][Ypos][Xpos];
\r
857 if(currentpiece != EmptySquare) {
\r
860 piece = PieceToName(currentpiece,1);
\r
861 while(Xpos < BOARD_RGHT && boards[currentMove][Ypos][Xpos] == currentpiece)
\r
864 sprintf(buf, "%d %ss", count, piece);
\r
865 } else sprintf(buf, "%s", piece);
\r
867 SayString(buf, FALSE);
\r
869 int count = 0, oldX = Xpos;
\r
870 while(Xpos < BOARD_RGHT && boards[currentMove][Ypos][Xpos] == EmptySquare)
\r
872 if(Xpos == BOARD_RGHT && oldX == BOARD_LEFT)
\r
873 SayString("all", FALSE);
\r
877 sprintf(buf, "%d", count);
\r
878 SayString(buf, FALSE);
\r
882 SayString("empty", FALSE);
\r
892 if(gameMode == MachinePlaysBlack || gameMode == IcsPlayingBlack) {
\r
893 if(WhiteOnMove(currentMove))
\r
894 SayString("It is your turn", FALSE);
\r
895 else SayString("It is your opponents turn", FALSE);
\r
896 } else if(gameMode == MachinePlaysWhite || gameMode == IcsPlayingWhite) {
\r
897 if(WhiteOnMove(currentMove))
\r
898 SayString("It is your opponents turn", FALSE);
\r
899 else SayString("It is your turn", FALSE);
\r
901 if(WhiteOnMove(currentMove))
\r
902 SayString("White is on move here", FALSE);
\r
903 else SayString("Black is on move here", FALSE);
\r
907 extern char *commentList[];
\r
910 SayMachineMove(int evenIfDuplicate)
\r
912 int len, xPos, yPos, moveNr, secondSpace = 0, castle = 0, n;
\r
913 ChessSquare currentpiece;
\r
914 char *piece, *xchar, *ynum, *p, checkMark = 0;
\r
915 char c, buf[MSG_SIZ], comment[MSG_SIZ];
\r
916 static char disambiguation[2];
\r
917 static int previousMove = 0;
\r
919 if(appData.debugMode) fprintf(debugFP, "Message = '%s'\n", messageText);
\r
920 if(gameMode == BeginningOfGame) return;
\r
921 if(messageText[0] == '[') return;
\r
923 if(isdigit(messageText[0])) { // message is move, possibly with thinking output
\r
924 int dotCount = 0, spaceCount = 0;
\r
925 sscanf(messageText, "%d", &moveNr);
\r
927 // [HGM] show: better extraction of move
\r
928 while (messageText[len] != NULLCHAR) {
\r
929 if(messageText[len] == '.' && spaceCount == 0) dotCount++;
\r
930 if(messageText[len] == ' ') { if(++spaceCount == 2) secondSpace = len; }
\r
931 if(messageText[len] == '{') { // we detected a comment
\r
932 if(isalpha(messageText[len+1]) ) sscanf(messageText+len, "{%[^}]}", comment);
\r
935 if(messageText[len] == '[') { // we detected thinking output
\r
936 int depth; float score=0; char c, lastMover = (dotCount == 3 ? 'B' : 'W');
\r
937 if(sscanf(messageText+len+1, "%d]%c%f", &depth, &c, &score) > 1) {
\r
938 if(c == ' ') { // if not explicitly specified, figure out source of thinking output
\r
940 case MachinePlaysWhite:
\r
941 case IcsPlayingWhite:
\r
943 case IcsPlayingBlack:
\r
944 case MachinePlaysBlack:
\r
950 if(c != lastMover) return; // line is thinking output of future move, ignore.
\r
951 if(2*moveNr - (dotCount < 2) == previousMove)
\r
952 return; // do not repeat same move; likely ponder output
\r
953 sprintf(buf, "score %s %d at %d ply",
\r
954 score > 0 ? "plus" : score < 0 ? "minus" : "",
\r
955 (int) (fabs(score)*100+0.5),
\r
957 SayString(buf, FALSE); // move + thinking output describing it; say it.
\r
959 while(messageText[len-1] == ' ') len--; // position just behind move;
\r
962 if(messageText[len] == '(') { // ICS time printed behind move
\r
963 while(messageText[len+1] && messageText[len] != ')') len++; // skip it
\r
967 if(secondSpace) len = secondSpace; // position behind move
\r
968 if(messageText[len-1] == '+' || messageText[len-1] == '#') { /* you are in checkmate */
\r
969 len--; // strip off check or mate indicator
\r
970 checkMark = messageText[len]; // make sure still seen after we stip off promo piece
\r
972 if(messageText[len-2] == '=') { /* promotion */
\r
973 len-=2; // strip off promotion piece
\r
974 SayString("promotion", FALSE);
\r
977 n = 2*moveNr - (dotCount < 2);
\r
979 if(previousMove != 2*moveNr + (dotCount > 1) || evenIfDuplicate) {
\r
981 previousMove = 2*moveNr + (dotCount > 1); // remember move nr of move last spoken
\r
982 sprintf(number, "%d", moveNr);
\r
984 yPos = CoordToNum(messageText[len-1]); /* turn char coords to ints */
\r
985 xPos = CoordToNum(messageText[len-2]);
\r
986 if(xPos < 0 || xPos > 11) return; // prevent crashes if no coord string available to speak
\r
987 if(yPos < 0 || yPos > 9) return;
\r
988 currentpiece = boards[n][yPos][xPos];
\r
989 piece = PieceToName(currentpiece,0);
\r
990 ynum = SquareToNum(yPos);
\r
991 xchar = SquareToChar(xPos);
\r
992 c = messageText[len-3];
\r
993 if(c == 'x') c = messageText[len-4];
\r
994 if(!isdigit(c) && c < 'a' && c != '@') c = 0;
\r
995 disambiguation[0] = c;
\r
996 SayString(WhiteOnMove(n) ? "Black" : "White", FALSE);
\r
997 SayString("move", FALSE);
\r
998 SayString(number, FALSE);
\r
999 // if(c==0 || c=='@') SayString("a", FALSE);
\r
1000 // intercept castling moves
\r
1001 p = StrStr(messageText, "O-O-O");
\r
1002 if(p && p-messageText < len) {
\r
1003 SayString("queen side castling",FALSE);
\r
1006 p = StrStr(messageText, "O-O");
\r
1007 if(p && p-messageText < len) {
\r
1008 SayString("king side castling",FALSE);
\r
1013 SayString(piece, FALSE);
\r
1014 if(c == '@') SayString("dropped on", FALSE); else
\r
1015 if(c) SayString(disambiguation, FALSE);
\r
1016 SayString("to", FALSE);
\r
1017 SayString(xchar, FALSE);
\r
1018 SayString(ynum, FALSE);
\r
1019 if(messageText[len-3] == 'x') {
\r
1020 currentpiece = boards[n-1][yPos][xPos];
\r
1021 if(currentpiece != EmptySquare) {
\r
1022 piece = PieceToName(currentpiece,0);
\r
1023 SayString("Capturing a",FALSE);
\r
1024 SayString(piece, FALSE);
\r
1025 } else SayString("Capturing onn passann",FALSE);
\r
1028 if(checkMark == '+') SayString("check", FALSE); else
\r
1029 if(checkMark == '#') {
\r
1030 SayString("finishing off", FALSE);
\r
1031 SayString(WhiteOnMove(n) ? "White" : "Black", FALSE);
\r
1035 /* say comment after move, possibly with result */
\r
1037 if(StrStr(messageText, " 1-0")) p = "white wins"; else
\r
1038 if(StrStr(messageText, " 0-1")) p = "black wins"; else
\r
1039 if(StrStr(messageText, " 1/2-1/2")) p = "game ends in a draw";
\r
1042 if(!StrCaseStr(comment, "draw") &&
\r
1043 !StrCaseStr(comment, "white") &&
\r
1044 !StrCaseStr(comment, "black") ) {
\r
1045 SayString(p, FALSE);
\r
1046 SayString("due to", FALSE);
\r
1049 SayString(comment, FALSE); // alphabetic comment (usually game end)
\r
1050 } else if(p) SayString(p, FALSE);
\r
1052 if(commentDialog && commentList[currentMove]) SetFocus(commentDialog);
\r
1055 /* starts not with digit */
\r
1056 if(StrCaseStr(messageText, "illegal")) PlayIcsUnfinishedSound();
\r
1057 SayString(messageText, FALSE);
\r
1065 char buf1[50], buf2[50];
\r
1066 char *str1, *str2;
\r
1067 static long int lastWhiteTime, lastBlackTime;
\r
1069 suppressClocks = 1; // if user is using alt+T command, no reason to display them
\r
1070 if(abs(lastWhiteTime - whiteTimeRemaining) < 1000 && abs(lastBlackTime - blackTimeRemaining) < 1000)
\r
1071 suppressClocks = 0; // back on after two requests in rapid succession
\r
1072 sprintf(buf1, "%s", TimeString(whiteTimeRemaining));
\r
1074 SayString("White's remaining time is", FALSE);
\r
1075 SayString(str1, FALSE);
\r
1076 sprintf(buf2, "%s", TimeString(blackTimeRemaining));
\r
1078 SayString("Black's remaining time is", FALSE);
\r
1079 SayString(str2, FALSE);
\r
1080 lastWhiteTime = whiteTimeRemaining;
\r
1081 lastBlackTime = blackTimeRemaining;
\r
1085 Toggle(Boolean *b, char *mess)
\r
1088 SayString(mess, FALSE);
\r
1089 SayString("is now", FALSE);
\r
1090 SayString(*b ? "on" : "off", FALSE);
\r
1093 /* handles keyboard moves in a click-click fashion */
\r
1095 KeyboardMove(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
1097 ChessSquare currentpiece;
\r
1100 static BOOLEAN sameAgain = FALSE;
\r
1101 switch (message) {
\r
1103 sameAgain = FALSE;
\r
1104 if(oldFromX == fromX && oldFromY == fromY) {
\r
1106 /* click on same square */
\r
1109 else if(oldFromX != -1) {
\r
1111 ChessSquare pdown, pup;
\r
1112 pdown = boards[currentMove][oldFromY][oldFromX];
\r
1113 pup = boards[currentMove][fromY][fromX];
\r
1115 if (gameMode == EditPosition ||
\r
1116 !((WhitePawn <= pdown && pdown <= WhiteKing &&
\r
1117 WhitePawn <= pup && pup <= WhiteKing) ||
\r
1118 (BlackPawn <= pdown && pdown <= BlackKing &&
\r
1119 BlackPawn <= pup && pup <= BlackKing))) {
\r
1120 /* EditPosition, empty square, or different color piece;
\r
1121 click-click move is possible */
\r
1122 char promoChoice = NULLCHAR;
\r
1124 if (HasPromotionChoice(oldFromX, oldFromY, fromX, fromY, &promoChoice)) {
\r
1125 if (appData.alwaysPromoteToQueen) {
\r
1126 UserMoveEvent(oldFromX, oldFromY, fromX, fromY, 'q');
\r
1129 toX = fromX; toY = fromY; fromX = oldFromX; fromY = oldFromY;
\r
1130 PromotionPopup(hwnd);
\r
1131 fromX = toX; fromY = toY;
\r
1135 UserMoveEvent(oldFromX, oldFromY, fromX, fromY, promoChoice);
\r
1137 oldFromX = oldFromY = -1;
\r
1142 /* First downclick, or restart on a square with same color piece */
\r
1143 if (OKToStartUserMove(fromX, fromY)) {
\r
1146 currentpiece = boards[currentMove][fromY][fromX];
\r
1147 piece = PieceToName(currentpiece,1);
\r
1148 SayString(piece, FALSE);
\r
1149 SayString("selected", FALSE);
\r
1152 oldFromX = oldFromY = -1;
\r
1157 if (oldFromX == fromX && oldFromY == fromY) {
\r
1158 /* Upclick on same square */
\r
1160 /* Clicked same square twice: abort click-click move */
\r
1161 oldFromX = oldFromY = -1;
\r
1162 currentpiece = boards[currentMove][fromY][fromX];
\r
1163 piece = PieceToName(currentpiece,0);
\r
1164 SayString(piece, FALSE);
\r
1165 SayString("unselected", FALSE);
\r
1173 { // return TRUE for times we want to announce
\r
1175 x = (x+50)/100; // tenth of seconds
\r
1176 if(x <= 100) return (x%10 == 0);
\r
1177 if(x <= 600) return (x%100 == 0);
\r
1178 if(x <= 6000) return (x%600 == 0);
\r
1179 return (x%3000 == 0);
\r
1182 #define JAWS_ARGS \
\r
1183 { "beepOffBoard", ArgInt, (LPVOID) beeps, TRUE, (ArgIniType) 1 },\
\r
1184 { "beepEmpty", ArgInt, (LPVOID) (beeps+1), TRUE, (ArgIniType) 0 },\
\r
1185 { "beepWhite", ArgInt, (LPVOID) (beeps+2), TRUE, (ArgIniType) 0 },\
\r
1186 { "beepBlack", ArgInt, (LPVOID) (beeps+3), TRUE, (ArgIniType) 0 },\
\r
1187 { "beepHoldings", ArgInt, (LPVOID) (beeps+4), TRUE, (ArgIniType) 0 },\
\r
1189 #define JAWS_ALT_INTERCEPT \
\r
1190 if(suppressOneKey) {\
\r
1191 suppressOneKey = 0;\
\r
1192 if(GetKeyState(VK_MENU) < 0 && GetKeyState(VK_CONTROL) < 0) break;\
\r
1194 if ((char)wParam == 022 && gameMode == EditPosition) { /* <Ctl R>. Pop up piece menu */\
\r
1195 POINT pt; int x, y;\
\r
1196 SquareToPos(fromY, fromX, &x, &y);\
\r
1197 pt.x = x; pt.y = y;\
\r
1198 if(gameInfo.variant != VariantShogi)\
\r
1199 MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1);\
\r
1201 MenuPopup(hwnd, pt, LoadMenu(hInst, "ShogiPieceMenu"), -1);\
\r
1205 #define JAWS_REPLAY \
\r
1206 case '\020': /* ctrl P */\
\r
1207 { char buf[MSG_SIZ];\
\r
1208 if(GetWindowText(hwnd, buf, MSG_SIZ-1))\
\r
1209 SayString(buf, FALSE);\
\r
1213 #define JAWS_KB_NAVIGATION \
\r
1217 if(GetKeyState(VK_MENU) < 0 && GetKeyState(VK_CONTROL) < 0) {\
\r
1218 /* Control + Alt + letter used for speaking piece positions */\
\r
1219 static int lastTime; static char lastChar;\
\r
1220 int mine = 0, time = GetTickCount(); char c;\
\r
1222 if((char)wParam == lastChar && time-lastTime < 250) mine = 1;\
\r
1223 lastChar = wParam; lastTime = time;\
\r
1226 if(gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) mine = !mine;\
\r
1228 if(ToLower(c) == 'x') {\
\r
1229 SayPieces(mine ? WhitePlay : BlackPlay);\
\r
1230 suppressOneKey = 1;\
\r
1233 if(CharToPiece(c) != EmptySquare) {\
\r
1234 SayPieces(CharToPiece(mine ? ToUpper(c) : ToLower(c)));\
\r
1235 suppressOneKey = 1;\
\r
1240 switch (wParam) {\
\r
1245 KeyboardEvent(hwnd, message, wParam, lParam);\
\r
1248 KeyboardMove(hwnd, message, wParam, lParam);\
\r
1253 switch (wParam) {\
\r
1255 KeyboardMove(hwnd, message, wParam, lParam);\
\r
1260 #define JAWS_MENU_ITEMS \
\r
1261 case IDM_PossibleAttackMove: /*What can I possible attack from here */\
\r
1262 PossibleAttackMove();\
\r
1265 case IDM_PossibleAttacked: /*what can possible attack this square*/\
\r
1266 PossibleAttacked();\
\r
1269 case IDM_ReadRow: /* Read the current row of pieces */\
\r
1273 case IDM_ReadColumn: /* Read the current column of pieces */\
\r
1277 case IDM_SayCurrentPos: /* Say current position including color */\
\r
1281 case IDM_SayAllBoard: /* Say the whole board from bottom to top */\
\r
1285 case IDM_SayMachineMove: /* Say the last move made */\
\r
1287 SayMachineMove(1);\
\r
1290 case IDM_SayUpperDiagnols: /* Says the diagnol positions above you */\
\r
1291 SayUpperDiagnols();\
\r
1294 case IDM_SayLowerDiagnols: /* Say the diagnol positions below you */\
\r
1295 SayLowerDiagnols();\
\r
1298 case IDM_SayBlackPieces: /*Say the opponents pieces */\
\r
1299 SayPieces(BlackPlay);\
\r
1302 case IDM_SayWhitePieces: /*Say the opponents pieces */\
\r
1303 SayPieces(WhitePlay);\
\r
1306 case IDM_SayClockTime: /*Say the clock time */\
\r
1310 case IDM_SayWhosTurn: /* Say whos turn it its */\
\r
1314 case IDM_SayKnightMoves: /* Say Knights (L-shaped) move */\
\r
1315 SayKnightMoves();\
\r
1318 case OPT_PonderNextMove: /* Toggle option setting */\
\r
1319 Toggle(&appData.ponderNextMove, "ponder");\
\r
1322 case OPT_AnimateMoving: /* Toggle option setting */\
\r
1323 Toggle(&appData.animate, "animate moving");\
\r
1326 case OPT_AutoFlag: /* Toggle option setting */\
\r
1327 Toggle(&appData.autoCallFlag, "auto flag");\
\r
1330 case OPT_AlwaysQueen: /* Toggle option setting */\
\r
1331 Toggle(&appData.alwaysPromoteToQueen, "always promote to queen");\
\r
1334 case OPT_TestLegality: /* Toggle option setting */\
\r
1335 Toggle(&appData.testLegality, "legality testing");\
\r
1338 case OPT_HideThinkFromHuman: /* Toggle option setting */\
\r
1339 Toggle(&appData.hideThinkingFromHuman, "hide thinking");\
\r
1340 ShowThinkingEvent();\
\r
1343 case OPT_SaveExtPGN: /* Toggle option setting */\
\r
1344 Toggle(&appData.saveExtendedInfoInPGN, "extended P G N info");\
\r
1347 case OPT_ExtraInfoInMoveHistory: /* Toggle option setting */\
\r
1348 Toggle(&appData.showEvalInMoveHistory, "extra info in move histoty");\
\r
1353 #define JAWS_ACCEL \
\r
1354 !(!frozen && TranslateAccelerator(hwndMain, hAccelJAWS, &msg)) &&
\r
1356 #define JAWS_INIT if (!InitJAWS()) return (FALSE);
\r
1358 #define JAWS_DELETE(X)
\r
1360 #define JAWS_SILENCE if(suppressClocks) return;
\r
1362 #define JAWS_COPYRIGHT \
\r
1363 SetDlgItemText(hDlg, OPT_MESS, "Auditory/Keyboard Enhancements By: Ed Rodriguez (sort of)");
\r
1365 #define SAY(S) SayString((S), FALSE)
\r
1367 #define SAYMACHINEMOVE() SayMachineMove(0)
\r
1369 // After inclusion of this file somewhere early in winboard.c, the remaining part of the patch
\r
1370 // is scattered over winboard.c for actually calling the routines.
\r