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
167 safeStrCpy(buf, mess, sizeof(buf)/sizeof(buf[0]));
\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 snprintf(buf, MSG_SIZ, "%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 snprintf(buf, MSG_SIZ,"%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 snprintf(buf, MSG_SIZ, "%s %s %s", xchar, ynum, piece);
\r
354 } else snprintf(buf, MSG_SIZ, "%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 snprintf(buf, sizeof(buf)/sizeof(buf[0]),"%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
838 SayString("white holds", FALSE);
\r
839 currentpiece = boards[currentMove][Ypos][BOARD_WIDTH-1];
\r
840 piece = PieceToName(currentpiece,0);
\r
841 snprintf(buf, MSG_SIZ,"%d %s%s", n, piece, (n==1 ? "" : "s") );
\r
842 SayString(buf, FALSE);
\r
846 for(Ypos=BOARD_HEIGHT-1; Ypos>=BOARD_HEIGHT - gameInfo.holdingsSize; Ypos--) {
\r
847 int n = boards[currentMove][Ypos][1];
\r
851 SayString("black holds", FALSE);
\r
852 currentpiece = boards[currentMove][Ypos][0];
\r
853 piece = PieceToName(currentpiece,0);
\r
854 snprintf(buf, MSG_SIZ, "%d %s%s", n, piece, (n==1 ? "" : "s") );
\r
855 SayString(buf, FALSE);
\r
860 for(Ypos=BOARD_HEIGHT-1; Ypos>=0; Ypos--) {
\r
861 ynum = ordinals[Ypos + (gameInfo.boardHeight < 10)];
\r
862 SayString(ynum, FALSE);
\r
863 SayString("rank", FALSE);
\r
864 for(Xpos=BOARD_LEFT; Xpos<BOARD_RGHT; Xpos++) {
\r
865 currentpiece = boards[currentMove][Ypos][Xpos];
\r
866 if(currentpiece != EmptySquare) {
\r
869 piece = PieceToName(currentpiece,1);
\r
870 while(Xpos < BOARD_RGHT && boards[currentMove][Ypos][Xpos] == currentpiece)
\r
873 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%d %ss", count, piece);
\r
875 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s", piece);
\r
877 SayString(buf, FALSE);
\r
879 int count = 0, oldX = Xpos;
\r
880 while(Xpos < BOARD_RGHT && boards[currentMove][Ypos][Xpos] == EmptySquare)
\r
882 if(Xpos == BOARD_RGHT && oldX == BOARD_LEFT)
\r
883 SayString("all", FALSE);
\r
887 snprintf(buf, sizeof(buf)/sizeof(buf[0]),"%d", count);
\r
888 SayString(buf, FALSE);
\r
892 SayString("empty", FALSE);
\r
902 if(gameMode == MachinePlaysBlack || gameMode == IcsPlayingWhite) {
\r
903 if(WhiteOnMove(currentMove))
\r
904 SayString("It is your turn", FALSE);
\r
905 else SayString("It is your opponents turn", FALSE);
\r
906 } else if(gameMode == MachinePlaysWhite || gameMode == IcsPlayingBlack) {
\r
907 if(WhiteOnMove(currentMove))
\r
908 SayString("It is your opponents turn", FALSE);
\r
909 else SayString("It is your turn", FALSE);
\r
911 if(WhiteOnMove(currentMove))
\r
912 SayString("White is on move here", FALSE);
\r
913 else SayString("Black is on move here", FALSE);
\r
917 extern char *commentList[];
\r
920 SayMachineMove(int evenIfDuplicate)
\r
922 int len, xPos, yPos, moveNr, secondSpace = 0, castle = 0, n;
\r
923 ChessSquare currentpiece;
\r
924 char *piece, *xchar, *ynum, *p, checkMark = 0;
\r
925 char c, buf[MSG_SIZ], comment[MSG_SIZ];
\r
926 static char disambiguation[2];
\r
927 static int previousMove = 0;
\r
929 if(appData.debugMode) fprintf(debugFP, "Message = '%s'\n", messageText);
\r
930 if(gameMode == BeginningOfGame) return;
\r
931 if(messageText[0] == '[') return;
\r
933 if(isdigit(messageText[0])) { // message is move, possibly with thinking output
\r
934 int dotCount = 0, spaceCount = 0;
\r
935 sscanf(messageText, "%d", &moveNr);
\r
937 // [HGM] show: better extraction of move
\r
938 while (messageText[len] != NULLCHAR) {
\r
939 if(messageText[len] == '.' && spaceCount == 0) dotCount++;
\r
940 if(messageText[len] == ' ') { if(++spaceCount == 2) secondSpace = len; }
\r
941 if(messageText[len] == '{') { // we detected a comment
\r
942 if(isalpha(messageText[len+1]) ) sscanf(messageText+len, "{%[^}]}", comment);
\r
945 if(messageText[len] == '[') { // we detected thinking output
\r
946 int depth; float score=0; char c, lastMover = (dotCount == 3 ? 'B' : 'W');
\r
947 if(sscanf(messageText+len+1, "%d]%c%f", &depth, &c, &score) > 1) {
\r
948 if(c == ' ') { // if not explicitly specified, figure out source of thinking output
\r
950 case MachinePlaysWhite:
\r
951 case IcsPlayingWhite:
\r
953 case IcsPlayingBlack:
\r
954 case MachinePlaysBlack:
\r
960 if(c != lastMover && !evenIfDuplicate) return; // line is thinking output of future move, ignore.
\r
961 if(2*moveNr - (dotCount < 2) == previousMove)
\r
962 return; // do not repeat same move; likely ponder output
\r
963 snprintf(buf, MSG_SIZ, "score %s %d at %d ply",
\r
964 score > 0 ? "plus" : score < 0 ? "minus" : "",
\r
965 (int) (fabs(score)*100+0.5),
\r
967 SayString(buf, FALSE); // move + thinking output describing it; say it.
\r
969 while(messageText[len-1] == ' ') len--; // position just behind move;
\r
972 if(messageText[len] == '(') { // ICS time printed behind move
\r
973 while(messageText[len+1] && messageText[len] != ')') len++; // skip it
\r
977 if(secondSpace) len = secondSpace; // position behind move
\r
978 if(messageText[len-1] == '+' || messageText[len-1] == '#') { /* you are in checkmate */
\r
979 len--; // strip off check or mate indicator
\r
980 checkMark = messageText[len]; // make sure still seen after we stip off promo piece
\r
982 if(messageText[len-2] == '=') { /* promotion */
\r
983 len-=2; // strip off promotion piece
\r
984 SayString("promotion", FALSE);
\r
987 n = 2*moveNr - (dotCount < 2);
\r
989 if(previousMove != 2*moveNr + (dotCount > 1) || evenIfDuplicate) {
\r
991 previousMove = 2*moveNr + (dotCount > 1); // remember move nr of move last spoken
\r
992 snprintf(number, sizeof(number)/sizeof(number[0]),"%d", moveNr);
\r
994 yPos = CoordToNum(messageText[len-1]); /* turn char coords to ints */
\r
995 xPos = CoordToNum(messageText[len-2]);
\r
996 if(xPos < 0 || xPos > 11) return; // prevent crashes if no coord string available to speak
\r
997 if(yPos < 0 || yPos > 9) return;
\r
998 currentpiece = boards[n][yPos][xPos];
\r
999 piece = PieceToName(currentpiece,0);
\r
1000 ynum = SquareToNum(yPos);
\r
1001 xchar = SquareToChar(xPos);
\r
1002 c = messageText[len-3];
\r
1003 if(c == 'x') c = messageText[len-4];
\r
1004 if(!isdigit(c) && c < 'a' && c != '@') c = 0;
\r
1005 disambiguation[0] = c;
\r
1006 SayString(WhiteOnMove(n) ? "Black" : "White", FALSE);
\r
1007 SayString("move", FALSE);
\r
1008 SayString(number, FALSE);
\r
1009 // if(c==0 || c=='@') SayString("a", FALSE);
\r
1010 // intercept castling moves
\r
1011 p = StrStr(messageText, "O-O-O");
\r
1012 if(p && p-messageText < len) {
\r
1013 SayString("queen side castling",FALSE);
\r
1016 p = StrStr(messageText, "O-O");
\r
1017 if(p && p-messageText < len) {
\r
1018 SayString("king side castling",FALSE);
\r
1023 SayString(piece, FALSE);
\r
1024 if(c == '@') SayString("dropped on", FALSE); else
\r
1025 if(c) SayString(disambiguation, FALSE);
\r
1026 SayString("to", FALSE);
\r
1027 SayString(xchar, FALSE);
\r
1028 SayString(ynum, FALSE);
\r
1029 if(messageText[len-3] == 'x') {
\r
1030 currentpiece = boards[n-1][yPos][xPos];
\r
1031 if(currentpiece != EmptySquare) {
\r
1032 piece = PieceToName(currentpiece,0);
\r
1033 SayString("Capturing a",FALSE);
\r
1034 SayString(piece, FALSE);
\r
1035 } else SayString("Capturing onn passann",FALSE);
\r
1038 if(checkMark == '+') SayString("check", FALSE); else
\r
1039 if(checkMark == '#') {
\r
1040 SayString("finishing off", FALSE);
\r
1041 SayString(WhiteOnMove(n) ? "White" : "Black", FALSE);
\r
1045 /* say comment after move, possibly with result */
\r
1047 if(StrStr(messageText, " 1-0")) p = "white wins"; else
\r
1048 if(StrStr(messageText, " 0-1")) p = "black wins"; else
\r
1049 if(StrStr(messageText, " 1/2-1/2")) p = "game ends in a draw";
\r
1052 if(!StrCaseStr(comment, "draw") &&
\r
1053 !StrCaseStr(comment, "white") &&
\r
1054 !StrCaseStr(comment, "black") ) {
\r
1055 SayString(p, FALSE);
\r
1056 SayString("due to", FALSE);
\r
1059 SayString(comment, FALSE); // alphabetic comment (usually game end)
\r
1060 } else if(p) SayString(p, FALSE);
\r
1062 if(commentDialog && commentList[currentMove]) SetFocus(commentDialog);
\r
1065 /* starts not with digit */
\r
1066 if(StrCaseStr(messageText, "illegal")) PlayIcsUnfinishedSound();
\r
1067 SayString(messageText, FALSE);
\r
1075 char buf1[50], buf2[50];
\r
1076 char *str1, *str2;
\r
1077 static long int lastWhiteTime, lastBlackTime;
\r
1079 suppressClocks = 1; // if user is using alt+T command, no reason to display them
\r
1080 if(abs(lastWhiteTime - whiteTimeRemaining) < 1000 && abs(lastBlackTime - blackTimeRemaining) < 1000)
\r
1081 suppressClocks = 0; // back on after two requests in rapid succession
\r
1082 snprintf(buf1, sizeof(buf1)/sizeof(buf1[0]),"%s", TimeString(whiteTimeRemaining));
\r
1084 SayString("White clock", FALSE);
\r
1085 SayString(str1, FALSE);
\r
1086 snprintf(buf2, sizeof(buf2)/sizeof(buf2[0]), "%s", TimeString(blackTimeRemaining));
\r
1088 SayString("Black clock", FALSE);
\r
1089 SayString(str2, FALSE);
\r
1090 lastWhiteTime = whiteTimeRemaining;
\r
1091 lastBlackTime = blackTimeRemaining;
\r
1095 Toggle(Boolean *b, char *mess)
\r
1098 SayString(mess, FALSE);
\r
1099 SayString("is now", FALSE);
\r
1100 SayString(*b ? "on" : "off", FALSE);
\r
1103 /* handles keyboard moves in a click-click fashion */
\r
1105 KeyboardMove(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
1107 ChessSquare currentpiece;
\r
1110 static BOOLEAN sameAgain = FALSE;
\r
1111 switch (message) {
\r
1113 sameAgain = FALSE;
\r
1114 if(oldFromX == fromX && oldFromY == fromY) {
\r
1116 /* click on same square */
\r
1119 else if(oldFromX != -1) {
\r
1121 ChessSquare pdown, pup;
\r
1122 pdown = boards[currentMove][oldFromY][oldFromX];
\r
1123 pup = boards[currentMove][fromY][fromX];
\r
1125 if (gameMode == EditPosition ||
\r
1126 !((WhitePawn <= pdown && pdown <= WhiteKing &&
\r
1127 WhitePawn <= pup && pup <= WhiteKing) ||
\r
1128 (BlackPawn <= pdown && pdown <= BlackKing &&
\r
1129 BlackPawn <= pup && pup <= BlackKing))) {
\r
1130 /* EditPosition, empty square, or different color piece;
\r
1131 click-click move is possible */
\r
1132 char promoChoice = NULLCHAR;
\r
1134 if (HasPromotionChoice(oldFromX, oldFromY, fromX, fromY, &promoChoice)) {
\r
1135 if (appData.alwaysPromoteToQueen) {
\r
1136 UserMoveEvent(oldFromX, oldFromY, fromX, fromY, 'q');
\r
1139 toX = fromX; toY = fromY; fromX = oldFromX; fromY = oldFromY;
\r
1140 PromotionPopup(hwnd);
\r
1141 fromX = toX; fromY = toY;
\r
1145 UserMoveEvent(oldFromX, oldFromY, fromX, fromY, promoChoice);
\r
1147 oldFromX = oldFromY = -1;
\r
1152 /* First downclick, or restart on a square with same color piece */
\r
1153 if (OKToStartUserMove(fromX, fromY)) {
\r
1156 currentpiece = boards[currentMove][fromY][fromX];
\r
1157 piece = PieceToName(currentpiece,1);
\r
1158 SayString(piece, FALSE);
\r
1159 SayString("selected", FALSE);
\r
1162 oldFromX = oldFromY = -1;
\r
1167 if (oldFromX == fromX && oldFromY == fromY) {
\r
1168 /* Upclick on same square */
\r
1170 /* Clicked same square twice: abort click-click move */
\r
1171 oldFromX = oldFromY = -1;
\r
1172 currentpiece = boards[currentMove][fromY][fromX];
\r
1173 piece = PieceToName(currentpiece,0);
\r
1174 SayString(piece, FALSE);
\r
1175 SayString("unselected", FALSE);
\r
1183 { // return TRUE for times we want to announce
\r
1185 x = (x+50)/100; // tenth of seconds
\r
1186 if(x <= 100) return (x%10 == 0);
\r
1187 if(x <= 600) return (x%100 == 0);
\r
1188 if(x <= 6000) return (x%600 == 0);
\r
1189 return (x%3000 == 0);
\r
1192 #define JAWS_ARGS \
\r
1193 { "beepOffBoard", ArgInt, (LPVOID) beeps, TRUE, (ArgIniType) 1 },\
\r
1194 { "beepEmpty", ArgInt, (LPVOID) (beeps+1), TRUE, (ArgIniType) 0 },\
\r
1195 { "beepWhite", ArgInt, (LPVOID) (beeps+2), TRUE, (ArgIniType) 0 },\
\r
1196 { "beepBlack", ArgInt, (LPVOID) (beeps+3), TRUE, (ArgIniType) 0 },\
\r
1197 { "beepHoldings", ArgInt, (LPVOID) (beeps+4), TRUE, (ArgIniType) 0 },\
\r
1199 #define JAWS_ALT_INTERCEPT \
\r
1200 if(suppressOneKey) {\
\r
1201 suppressOneKey = 0;\
\r
1202 if(GetKeyState(VK_MENU) < 0 && GetKeyState(VK_CONTROL) < 0) break;\
\r
1204 if ((char)wParam == 022 && gameMode == EditPosition) { /* <Ctl R>. Pop up piece menu */\
\r
1205 POINT pt; int x, y;\
\r
1206 SquareToPos(fromY, fromX, &x, &y);\
\r
1207 dropX = fromX; dropY = fromY;\
\r
1208 pt.x = x; pt.y = y;\
\r
1209 if(gameInfo.variant != VariantShogi)\
\r
1210 MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1);\
\r
1212 MenuPopup(hwnd, pt, LoadMenu(hInst, "ShogiPieceMenu"), -1);\
\r
1216 #define JAWS_REPLAY \
\r
1217 case '\020': /* ctrl P */\
\r
1218 { char buf[MSG_SIZ];\
\r
1219 if(GetWindowText(hwnd, buf, MSG_SIZ-1))\
\r
1220 SayString(buf, FALSE);\
\r
1224 #define JAWS_KB_NAVIGATION \
\r
1228 if(GetKeyState(VK_MENU) < 0 && GetKeyState(VK_CONTROL) < 0) {\
\r
1229 /* Control + Alt + letter used for speaking piece positions */\
\r
1230 static int lastTime; static char lastChar;\
\r
1231 int mine = 0, time = GetTickCount(); char c;\
\r
1233 if((char)wParam == lastChar && time-lastTime < 250) mine = 1;\
\r
1234 lastChar = wParam; lastTime = time;\
\r
1237 if(gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) mine = !mine;\
\r
1239 if(ToLower(c) == 'x') {\
\r
1240 SayPieces(mine ? WhitePlay : BlackPlay);\
\r
1241 suppressOneKey = 1;\
\r
1244 if(CharToPiece(c) != EmptySquare) {\
\r
1245 SayPieces(CharToPiece(mine ? ToUpper(c) : ToLower(c)));\
\r
1246 suppressOneKey = 1;\
\r
1251 switch (wParam) {\
\r
1256 KeyboardEvent(hwnd, message, wParam, lParam);\
\r
1259 KeyboardMove(hwnd, message, wParam, lParam);\
\r
1264 switch (wParam) {\
\r
1266 KeyboardMove(hwnd, message, wParam, lParam);\
\r
1271 #define JAWS_MENU_ITEMS \
\r
1272 case IDM_PossibleAttackMove: /*What can I possible attack from here */\
\r
1273 PossibleAttackMove();\
\r
1276 case IDM_PossibleAttacked: /*what can possible attack this square*/\
\r
1277 PossibleAttacked();\
\r
1280 case IDM_ReadRow: /* Read the current row of pieces */\
\r
1284 case IDM_ReadColumn: /* Read the current column of pieces */\
\r
1288 case IDM_SayCurrentPos: /* Say current position including color */\
\r
1292 case IDM_SayAllBoard: /* Say the whole board from bottom to top */\
\r
1296 case IDM_SayMachineMove: /* Say the last move made */\
\r
1298 SayMachineMove(1);\
\r
1301 case IDM_SayUpperDiagnols: /* Says the diagnol positions above you */\
\r
1302 SayUpperDiagnols();\
\r
1305 case IDM_SayLowerDiagnols: /* Say the diagnol positions below you */\
\r
1306 SayLowerDiagnols();\
\r
1309 case IDM_SayBlackPieces: /*Say the opponents pieces */\
\r
1310 SayPieces(BlackPlay);\
\r
1313 case IDM_SayWhitePieces: /*Say the opponents pieces */\
\r
1314 SayPieces(WhitePlay);\
\r
1317 case IDM_SayClockTime: /*Say the clock time */\
\r
1321 case IDM_SayWhosTurn: /* Say whos turn it its */\
\r
1325 case IDM_SayKnightMoves: /* Say Knights (L-shaped) move */\
\r
1326 SayKnightMoves();\
\r
1329 case OPT_PonderNextMove: /* Toggle option setting */\
\r
1330 Toggle(&appData.ponderNextMove, "ponder");\
\r
1333 case OPT_AnimateMoving: /* Toggle option setting */\
\r
1334 Toggle(&appData.animate, "animate moving");\
\r
1337 case OPT_AutoFlag: /* Toggle option setting */\
\r
1338 Toggle(&appData.autoCallFlag, "auto flag");\
\r
1341 case OPT_AlwaysQueen: /* Toggle option setting */\
\r
1342 Toggle(&appData.alwaysPromoteToQueen, "always promote to queen");\
\r
1345 case OPT_TestLegality: /* Toggle option setting */\
\r
1346 Toggle(&appData.testLegality, "legality testing");\
\r
1349 case OPT_HideThinkFromHuman: /* Toggle option setting */\
\r
1350 Toggle(&appData.hideThinkingFromHuman, "hide thinking");\
\r
1351 ShowThinkingEvent();\
\r
1354 case OPT_SaveExtPGN: /* Toggle option setting */\
\r
1355 Toggle(&appData.saveExtendedInfoInPGN, "extended P G N info");\
\r
1358 case OPT_ExtraInfoInMoveHistory: /* Toggle option setting */\
\r
1359 Toggle(&appData.showEvalInMoveHistory, "extra info in move histoty");\
\r
1364 #define JAWS_ACCEL \
\r
1365 !(!frozen && TranslateAccelerator(hwndMain, hAccelJAWS, &msg)) &&
\r
1367 #define JAWS_INIT if (!InitJAWS()) return (FALSE);
\r
1369 #define JAWS_DELETE(X)
\r
1371 #define JAWS_SILENCE if(suppressClocks) return;
\r
1373 #define JAWS_COPYRIGHT \
\r
1374 SetDlgItemText(hDlg, OPT_MESS, "Auditory/Keyboard Enhancements By: Ed Rodriguez (sort of)");
\r
1376 #define SAY(S) SayString((S), FALSE)
\r
1378 #define SAYMACHINEMOVE() SayMachineMove(0)
\r
1380 // After inclusion of this file somewhere early in winboard.c, the remaining part of the patch
\r
1381 // is scattered over winboard.c for actually calling the routines.
\r