4 * Implementation of the X interface for GNU shogi (xshogi).
6 * ------------------------------------------------------------------------
7 * xshogi is based on XBoard -- an Xt/Athena user interface for GNU Chess.
9 * Original authors: Dan Sears, Chris Sears
10 * Enhancements (Version 2.0 and following): Tim Mann
11 * Modifications to XShogi (Version 1.0): Matthias Mutz
12 * Enhancements to XShogi (Version 1.1): Matthias Mutz
13 * Modified implementation of ISS mode for XShogi: Matthias Mutz
14 * Current maintainer: Michael C. Vanier
16 * XShogi borrows some of its piece bitmaps from CRANES Shogi.
18 * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.
19 * Enhancements Copyright 1992 Free Software Foundation, Inc.
20 * Enhancements for XShogi Copyright 1993, 1994, 1995 Matthias Mutz
21 * Copyright (c) 1999 Michael Vanier and the Free Software Foundation
23 * The following terms apply to Digital Equipment Corporation's copyright
25 * ------------------------------------------------------------------------
28 * Permission to use, copy, modify, and distribute this software and its
29 * documentation for any purpose and without fee is hereby granted,
30 * provided that the above copyright notice appear in all copies and that
31 * both that copyright notice and this permission notice appear in
32 * supporting documentation, and that the name of Digital not be
33 * used in advertising or publicity pertaining to distribution of the
34 * software without specific, written prior permission.
36 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
37 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
38 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
39 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
40 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
41 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43 * ------------------------------------------------------------------------
45 * This file is part of GNU shogi.
47 * GNU shogi is free software; you can redistribute it and/or modify
48 * it under the terms of the GNU General Public License as published by
49 * the Free Software Foundation.
51 * GNU shogi is distributed in the hope that it will be useful,
52 * but WITHOUT ANY WARRANTY; without even the implied warranty of
53 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
54 * GNU General Public License for more details.
56 * You should have received a copy of the GNU General Public License
57 * along with GNU shogi; see the file COPYING. If not, write to
58 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
60 * ------------------------------------------------------------------------
66 #ifdef X_DISPLAY_MISSING
67 #error You cannot compile xshogi if X windows is unavailable!
72 #define XBOARD_VERSION "2.0/2.1"
77 #include <sys/ioctl.h>
82 #include <X11/Intrinsic.h>
83 #include <X11/StringDefs.h>
84 #include <X11/Shell.h>
85 #include <X11/Xaw/Dialog.h>
86 #include <X11/Xaw/Form.h>
87 #include <X11/Xaw/List.h>
88 #include <X11/Xaw/Label.h>
89 #include <X11/Xaw/SimpleMenu.h>
90 #include <X11/Xaw/SmeBSB.h>
91 #include <X11/Xaw/SmeLine.h>
92 #include <X11/cursorfont.h>
94 #include "../version.h"
101 #include "bitmaps.h" /* Piece bitmaps. */
102 #include "xshogifn.h" /* Forward declarations. */
104 #define off_board(x) ((x < 2) || (x > BOARD_SIZE + 1))
107 /**********************************************************************
109 * Global variables, structs etc.
111 **********************************************************************/
114 * NOTE: XShogi depends on Xt R4 or higher
117 int xtVersion = XtSpecificationRelease;
119 XtIntervalId firstProgramXID = 0, secondProgramXID = 0,
120 readGameXID = 0, timerXID = 0, blinkSquareXID = 0;
122 XtAppContext appContext;
124 Boolean (*fileProc) (char *name);
126 FILE *fromFirstProgFP, *toFirstProgFP, *fromSecondProgFP,
127 *toSecondProgFP, *gameFileFP, *lastMsgFP;
129 int currentMove = 0, forwardMostMove = 0, backwardMostMove = 0,
131 secondProgramPID = 0, fromX = -1,
132 fromY = -1, firstMove = True, flipView = False,
133 xshogiDebug = True, commentUp = False, filenameUp = False,
134 whitePlaysFirst = False, startedFromSetupPosition = False,
135 searchTime = 0, pmFromX = -1, pmFromY = -1,
136 blackFlag = False, whiteFlag = False, maybeThinking = False,
139 int at_least_gnushogi_1_2p03 = False;
141 int firstSendTime = 2, secondSendTime = 2; /* 0 = don't, 1 = do,
144 MatchMode matchMode = MatchFalse;
145 GameMode gameMode = BeginningOfGame;
146 GameMode lastGameMode = BeginningOfGame;
147 GameMode pausePreviousMode = BeginningOfGame;
149 char moveList[MAX_MOVES][MOVE_LEN], parseList[MAX_MOVES][MOVE_LEN * 2],
150 ptyname[24], *shogiDir, *programName;
152 char endMessage[MOVE_LEN * 4];
154 long blackTimeRemaining, whiteTimeRemaining, timeControl;
155 long timeRemaining[2][MAX_MOVES];
157 extern char currentMoveString[];
159 int updateRemotePlayer = False;
161 Catched catches[MAX_MOVES];
163 #define DIMENSION 100
165 Widget blackPieceMenu, whitePieceMenu, commentShell;
167 XSetWindowAttributes attr;
185 #define NO_SQUARES 81
190 char catchedIndexToChar[8] =
192 'P', 'L', 'N', 'S', 'G', 'B', 'R', 'K'
195 ShogiSquare catchedIndexToPiece[2][8] =
198 BlackPawn, BlackLance, BlackKnight, BlackSilver, BlackGold,
199 BlackBishop, BlackRook, BlackKing
202 WhitePawn, WhiteLance, WhiteKnight, WhiteSilver, WhiteGold,
203 WhiteBishop, WhiteRook, WhiteKing
208 int pieceToCatchedIndex[] =
210 pawn, lance, knight, silver, gold, bishop, rook,
211 pawn, lance, knight, silver, bishop, rook, king,
212 pawn, lance, knight, silver, gold, bishop, rook,
213 pawn, lance, knight, silver, bishop, rook, king,
219 Board boards[MAX_MOVES];
220 Board initialPosition =
222 { BlackLance, BlackKnight, BlackSilver, BlackGold, BlackKing,
223 BlackGold, BlackSilver, BlackKnight, BlackLance },
224 { EmptySquare, BlackBishop, EmptySquare, EmptySquare, EmptySquare,
225 EmptySquare, EmptySquare, BlackRook, EmptySquare },
226 { BlackPawn, BlackPawn, BlackPawn, BlackPawn, BlackPawn,
227 BlackPawn, BlackPawn, BlackPawn, BlackPawn },
228 { EmptySquare, EmptySquare, EmptySquare, EmptySquare, EmptySquare,
229 EmptySquare, EmptySquare, EmptySquare, EmptySquare } ,
230 { EmptySquare, EmptySquare, EmptySquare, EmptySquare, EmptySquare,
231 EmptySquare, EmptySquare, EmptySquare, EmptySquare } ,
232 { EmptySquare, EmptySquare, EmptySquare, EmptySquare, EmptySquare,
233 EmptySquare, EmptySquare, EmptySquare, EmptySquare } ,
234 { WhitePawn, WhitePawn, WhitePawn, WhitePawn, WhitePawn,
235 WhitePawn, WhitePawn, WhitePawn, WhitePawn },
236 { EmptySquare, WhiteRook, EmptySquare, EmptySquare, EmptySquare,
237 EmptySquare, EmptySquare, WhiteBishop, EmptySquare },
238 { WhiteLance, WhiteKnight, WhiteSilver, WhiteGold, WhiteKing,
239 WhiteGold, WhiteSilver, WhiteKnight, WhiteLance }
242 String gnuButtonStrings[] =
244 "Quit", "Load Game", "Machine White", "Forward",
245 "Reset", "Load Position", "Machine Black", "Backward",
246 "Flip View", "Save Game", "Force Moves", "Pause",
247 "Hint", "Save Position", "Two Machines", "Edit Position",
248 "Challenge", "Select Level", "Move NOW",
251 /* must be in same order as buttonStrings! */
252 XtActionProc gnuButtonProcs[] =
254 QuitProc, LoadGameProc, MachineWhiteProc, ForwardProc,
255 ResetProc, LoadPositionProc, MachineBlackProc, BackwardProc,
256 FlipViewProc, SaveGameProc, ForceProc, PauseProc,
257 HintProc, SavePositionProc, TwoMachinesProc, EditPositionProc,
258 ChallengeProc, SelectLevelProc, MoveNowProc,
263 String *buttonStrings;
264 XtActionProc *buttonProcs;
267 #define PIECE_MENU_SIZE 18
269 String pieceMenuStrings[PIECE_MENU_SIZE] =
271 "----", "Pawn", "Lance", "Knight", "Silver",
272 "Gold", "Bishop", "Rook",
273 "PPawn", "PLance", "PKnight", "PSilver",
274 "PBishop", "PRook", "King",
275 "----", "Empty square", "Clear board"
278 /* must be in same order as PieceMenuStrings! */
279 ShogiSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] =
282 (ShogiSquare) 0, BlackPawn, BlackLance, BlackKnight,
283 BlackSilver, BlackGold, BlackBishop, BlackRook,
284 BlackPPawn, BlackPLance, BlackPKnight, BlackPSilver,
285 BlackPBishop, BlackPRook, BlackKing,
286 (ShogiSquare) 0, EmptySquare, ClearBoard
289 (ShogiSquare) 0, WhitePawn, WhiteLance, WhiteKnight,
290 WhiteSilver, WhiteGold, WhiteBishop, WhiteRook,
291 WhitePPawn, WhitePLance, WhitePKnight, WhitePSilver,
292 WhitePBishop, WhitePRook, WhiteKing,
293 (ShogiSquare) 0, EmptySquare, ClearBoard
302 Pixel charPieceColor;
305 Boolean westernPieceSet;
310 String firstShogiProgram;
311 String secondShogiProgram;
312 Boolean noShogiProgram;
315 String reverseBigSolidBitmap;
316 String reverseSmallSolidBitmap;
317 String normalBigSolidBitmap;
318 String normalSmallSolidBitmap;
319 String reversePawnBitmap;
320 String reverseLanceBitmap;
321 String reverseKnightBitmap;
322 String reverseSilverBitmap;
323 String reverseGoldBitmap;
324 String reverseRookBitmap;
325 String reverseBishopBitmap;
326 String reversePPawnBitmap;
327 String reversePLanceBitmap;
328 String reversePKnightBitmap;
329 String reversePSilverBitmap;
330 String reversePBishopBitmap;
331 String reversePRookBitmap;
332 String reverseKingBitmap;
333 String normalPawnBitmap;
334 String normalLanceBitmap;
335 String normalKnightBitmap;
336 String normalSilverBitmap;
337 String normalGoldBitmap;
338 String normalRookBitmap;
339 String normalBishopBitmap;
340 String normalPPawnBitmap;
341 String normalPLanceBitmap;
342 String normalPKnightBitmap;
343 String normalPSilverBitmap;
344 String normalPBishopBitmap;
345 String normalPRookBitmap;
346 String normalKingBitmap;
352 Boolean autoSaveGames;
354 String loadPositionFile;
356 String savePositionFile;
358 String challengeDisplay;
369 Boolean ringBellAfterMoves;
370 Boolean autoCallFlag;
373 } AppData, *AppDataPtr;
376 XtResource clientResources[] =
379 "pieceColor", "pieceColor", XtRPixel, sizeof(Pixel),
380 XtOffset(AppDataPtr, pieceColor), XtRString,
384 "charPieceColor", "CharPieceColor", XtRPixel, sizeof(Pixel),
385 XtOffset(AppDataPtr, charPieceColor), XtRString,
389 "oneColor", "OneColor", XtRPixel, sizeof(Pixel),
390 XtOffset(AppDataPtr, oneColor), XtRString,
394 "zeroColor", "ZeroColor", XtRPixel, sizeof(Pixel),
395 XtOffset(AppDataPtr, zeroColor), XtRString,
399 "squareColor", "squareColor", XtRPixel,
400 sizeof(Pixel), XtOffset(AppDataPtr, squareColor),
401 XtRString, SQUARE_COLOR
404 "westernPieceSet", "WesternPieceSet", XtRBoolean, sizeof(Boolean),
405 XtOffset(AppDataPtr, westernPieceSet), XtRString,
409 "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
410 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
411 (XtPointer) MOVES_PER_SESSION
414 "initString", "initString", XtRString, sizeof(String),
415 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING
418 "blackString", "blackString", XtRString, sizeof(String),
419 XtOffset(AppDataPtr, blackString), XtRString, BLACK_STRING
422 "whiteString", "whiteString", XtRString, sizeof(String),
423 XtOffset(AppDataPtr, whiteString), XtRString, WHITE_STRING
426 "firstShogiProgram", "firstShogiProgram", XtRString,
427 sizeof(String), XtOffset(AppDataPtr, firstShogiProgram),
428 XtRString, FIRST_SHOGI_PROGRAM
431 "secondShogiProgram", "secondShogiProgram", XtRString,
432 sizeof(String), XtOffset(AppDataPtr, secondShogiProgram),
433 XtRString, SECOND_SHOGI_PROGRAM
436 "noShogiProgram", "noShogiProgram", XtRBoolean,
437 sizeof(Boolean), XtOffset(AppDataPtr, noShogiProgram),
438 XtRImmediate, (XtPointer) False
441 "firstHost", "firstHost", XtRString, sizeof(String),
442 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST
445 "secondHost", "secondHost", XtRString, sizeof(String),
446 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST
449 "reversePawnBitmap", "reversePawnBitmap", XtRString,
450 sizeof(String), XtOffset(AppDataPtr, reversePawnBitmap),
454 "reverseLanceBitmap", "reverseLanceBitmap", XtRString,
455 sizeof(String), XtOffset(AppDataPtr, reverseLanceBitmap),
459 "reverseKnightBitmap", "reverseKnightBitmap", XtRString,
460 sizeof(String), XtOffset(AppDataPtr, reverseKnightBitmap),
464 "reverseSilverBitmap", "reverseSilverBitmap", XtRString,
465 sizeof(String), XtOffset(AppDataPtr, reverseSilverBitmap),
469 "reverseGoldBitmap", "reverseGoldBitmap", XtRString,
470 sizeof(String), XtOffset(AppDataPtr, reverseGoldBitmap),
474 "reverseRookBitmap", "reverseRookBitmap", XtRString,
475 sizeof(String), XtOffset(AppDataPtr, reverseRookBitmap),
479 "reverseBishopBitmap", "reverseBishopBitmap", XtRString,
480 sizeof(String), XtOffset(AppDataPtr, reverseBishopBitmap),
484 "reversePPawnBitmap", "reversePPawnBitmap", XtRString,
485 sizeof(String), XtOffset(AppDataPtr, reversePPawnBitmap),
489 "reversePLanceBitmap", "reversePLanceBitmap", XtRString,
490 sizeof(String), XtOffset(AppDataPtr, reversePLanceBitmap),
494 "reversePKnightBitmap", "reversePKnightBitmap", XtRString,
495 sizeof(String), XtOffset(AppDataPtr, reversePKnightBitmap),
499 "reversePSilverBitmap", "reversePSilverBitmap", XtRString,
500 sizeof(String), XtOffset(AppDataPtr, reversePSilverBitmap),
504 "reversePRookBitmap", "reversePRookBitmap", XtRString,
505 sizeof(String), XtOffset(AppDataPtr, reversePRookBitmap),
509 "reversePBishopBitmap", "reversePBishopBitmap", XtRString,
510 sizeof(String), XtOffset(AppDataPtr, reversePBishopBitmap),
514 "reverseKingBitmap", "reverseKingBitmap", XtRString,
515 sizeof(String), XtOffset(AppDataPtr, reverseKingBitmap),
519 "normalPawnBitmap", "normalPawnBitmap", XtRString,
520 sizeof(String), XtOffset(AppDataPtr, normalPawnBitmap),
524 "normalLanceBitmap", "normalLanceBitmap", XtRString,
525 sizeof(String), XtOffset(AppDataPtr, normalLanceBitmap),
529 "normalKnightBitmap", "normalKnightBitmap", XtRString,
530 sizeof(String), XtOffset(AppDataPtr, normalKnightBitmap),
534 "normalSilverBitmap", "normalSilverBitmap", XtRString,
535 sizeof(String), XtOffset(AppDataPtr, normalSilverBitmap),
539 "normalGoldBitmap", "normalGoldBitmap", XtRString,
540 sizeof(String), XtOffset(AppDataPtr, normalGoldBitmap),
544 "normalBishopBitmap", "normalBishopBitmap", XtRString,
545 sizeof(String), XtOffset(AppDataPtr, normalBishopBitmap),
549 "normalRookBitmap", "normalRookBitmap", XtRString,
550 sizeof(String), XtOffset(AppDataPtr, normalRookBitmap),
554 "normalPPawnBitmap", "normalPPawnBitmap", XtRString,
555 sizeof(String), XtOffset(AppDataPtr, normalPPawnBitmap),
559 "normalPLanceBitmap", "normalPLanceBitmap", XtRString,
560 sizeof(String), XtOffset(AppDataPtr, normalPLanceBitmap),
564 "normalPKnightBitmap", "normalPKnightBitmap", XtRString,
565 sizeof(String), XtOffset(AppDataPtr, normalPKnightBitmap),
569 "normalPSilverBitmap", "normalPSilverBitmap", XtRString,
570 sizeof(String), XtOffset(AppDataPtr, normalPSilverBitmap),
574 "normalPBishopBitmap", "normalPBishopBitmap", XtRString,
575 sizeof(String), XtOffset(AppDataPtr, normalPBishopBitmap),
579 "normalPRookBitmap", "normalPRookBitmap", XtRString,
580 sizeof(String), XtOffset(AppDataPtr, normalPRookBitmap),
584 "normalKingBitmap", "normalKingBitmap", XtRString,
585 sizeof(String), XtOffset(AppDataPtr, normalKingBitmap),
589 "remoteShell", "remoteShell", XtRString, sizeof(String),
590 XtOffset(AppDataPtr, remoteShell), XtRString, "rsh"
593 "timeDelay", "timeDelay", XtRFloat, sizeof(float),
594 XtOffset(AppDataPtr, timeDelay), XtRString,
595 (XtPointer) TIME_DELAY
598 "timeControl", "timeControl", XtRString, sizeof(String),
599 XtOffset(AppDataPtr, timeControl), XtRString,
600 (XtPointer) TIME_CONTROL
604 XtRBoolean, sizeof(Boolean),
605 XtOffset(AppDataPtr, gameIn), XtRImmediate,
609 "autoSaveGames", "autoSaveGames", XtRBoolean,
610 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
611 XtRImmediate, (XtPointer) False
614 "loadGameFile", "loadGameFile", XtRString, sizeof(String),
615 XtOffset(AppDataPtr, loadGameFile), XtRString, NULL
618 "loadPositionFile", "loadPositionFile", XtRString,
619 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
623 "saveGameFile", "saveGameFile", XtRString, sizeof(String),
624 XtOffset(AppDataPtr, saveGameFile), XtRString, ""
627 "savePositionFile", "savePositionFile", XtRString,
628 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
632 "challengeDisplay", "challengeDisplay", XtRString,
633 sizeof(String), XtOffset(AppDataPtr, challengeDisplay),
637 "matchMode", "matchMode", XtRString, sizeof(String),
638 XtOffset(AppDataPtr, matchMode), XtRString, MATCH_MODE
641 "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
642 XtOffset(AppDataPtr, monoMode), XtRImmediate,
646 "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
647 XtOffset(AppDataPtr, debugMode), XtRImmediate,
651 "Iconic", "Iconic", XtRBoolean, sizeof(Boolean),
652 XtOffset(AppDataPtr, Iconic), XtRImmediate,
656 "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
657 XtOffset(AppDataPtr, clockMode), XtRImmediate,
661 "autoCallFlag", "autoCallFlag", XtRBoolean,
662 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
663 XtRImmediate, (XtPointer) False
666 "boardSize", "boardSize", XtRString, sizeof(String),
667 XtOffset(AppDataPtr, boardSize), XtRString, DEFAULT_SIZE
670 "searchTime", "searchTime", XtRString, sizeof(String),
671 XtOffset(AppDataPtr, searchTime), XtRString,
675 "searchDepth", "searchDepth", XtRInt, sizeof(int),
676 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
680 "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
681 XtOffset(AppDataPtr, showCoords), XtRImmediate,
685 "mainFont", "mainFont", XtRString, sizeof(String),
686 XtOffset(AppDataPtr, mainFont), XtRString, MAIN_FONT
689 "coordFont", "coordFont", XtRString, sizeof(String),
690 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT
693 "ringBellAfterMoves", "ringBellAfterMoves",
694 XtRBoolean, sizeof(Boolean),
695 XtOffset(AppDataPtr, ringBellAfterMoves),
696 XtRImmediate, (XtPointer) False
699 "borderXoffset", "borderXoffset", XtRInt, sizeof(int),
700 XtOffset(AppDataPtr, borderXoffset), XtRImmediate,
701 (XtPointer) BORDER_X_OFFSET
704 "borderYoffset", "borderYOffset", XtRInt, sizeof(int),
705 XtOffset(AppDataPtr, borderYoffset), XtRImmediate,
706 (XtPointer) BORDER_Y_OFFSET
722 Pixmap reversePawnBitmap, reverseLanceBitmap, reverseKnightBitmap,
724 reverseGoldBitmap, reverseBishopBitmap, reverseRookBitmap,
725 reversePPawnBitmap, reversePLanceBitmap, reversePKnightBitmap,
726 reversePSilverBitmap, reversePBishopBitmap, reversePRookBitmap,
728 reverseBigSolidBitmap, reverseSmallSolidBitmap,
729 normalBigSolidBitmap, normalSmallSolidBitmap,
730 normalPawnBitmap, normalLanceBitmap, normalKnightBitmap,
731 normalSilverBitmap, normalGoldBitmap,
732 normalBishopBitmap, normalRookBitmap,
733 normalPPawnBitmap, normalPLanceBitmap, normalPKnightBitmap,
734 normalPSilverBitmap, normalPBishopBitmap, normalPRookBitmap,
742 GC squareGC, lineGC, pieceGC, oPieceGC, charPieceGC,
743 squareOffBoardGC, coordGC, dropPiece;
745 Font mainFontID, coordFontID;
746 XFontStruct *mainFontStruct, *coordFontStruct;
748 Widget shellWidget, formWidget, boardWidget,
749 commandsWidget, messageWidget,
750 blackTimerWidget, whiteTimerWidget,
751 titleWidget, widgetList[6],
753 filemodeShell, challengeWidget;
755 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
757 Pixel timerForegroundPixel, timerBackgroundPixel;
761 int black_pixel_is_zero;
765 Boolean monoMode, showCoords, Iconic;
770 struct DisplayData localPlayer, remotePlayer;
779 static PromotionMoveInfo pmi; /* making this global is gross */
782 Pixmap *pieceToReverse[2][28] =
785 &localPlayer.reversePawnBitmap,
786 &localPlayer.reverseLanceBitmap,
787 &localPlayer.reverseKnightBitmap,
788 &localPlayer.reverseSilverBitmap,
789 &localPlayer.reverseGoldBitmap,
790 &localPlayer.reverseBishopBitmap,
791 &localPlayer.reverseRookBitmap,
792 &localPlayer.reversePPawnBitmap,
793 &localPlayer.reversePLanceBitmap,
794 &localPlayer.reversePKnightBitmap,
795 &localPlayer.reversePSilverBitmap,
796 &localPlayer.reversePBishopBitmap,
797 &localPlayer.reversePRookBitmap,
798 &localPlayer.reverseKingBitmap,
799 &localPlayer.reversePawnBitmap,
800 &localPlayer.reverseLanceBitmap,
801 &localPlayer.reverseKnightBitmap,
802 &localPlayer.reverseSilverBitmap,
803 &localPlayer.reverseGoldBitmap,
804 &localPlayer.reverseBishopBitmap,
805 &localPlayer.reverseRookBitmap,
806 &localPlayer.reversePPawnBitmap,
807 &localPlayer.reversePLanceBitmap,
808 &localPlayer.reversePKnightBitmap,
809 &localPlayer.reversePSilverBitmap,
810 &localPlayer.reversePBishopBitmap,
811 &localPlayer.reversePRookBitmap,
812 &localPlayer.reverseKingBitmap
815 &remotePlayer.reversePawnBitmap,
816 &remotePlayer.reverseLanceBitmap,
817 &remotePlayer.reverseKnightBitmap,
818 &remotePlayer.reverseSilverBitmap,
819 &remotePlayer.reverseGoldBitmap,
820 &remotePlayer.reverseBishopBitmap,
821 &remotePlayer.reverseRookBitmap,
822 &remotePlayer.reversePPawnBitmap,
823 &remotePlayer.reversePLanceBitmap,
824 &remotePlayer.reversePKnightBitmap,
825 &remotePlayer.reversePSilverBitmap,
826 &remotePlayer.reversePBishopBitmap,
827 &remotePlayer.reversePRookBitmap,
828 &remotePlayer.reverseKingBitmap,
829 &remotePlayer.reversePawnBitmap,
830 &remotePlayer.reverseLanceBitmap,
831 &remotePlayer.reverseKnightBitmap,
832 &remotePlayer.reverseSilverBitmap,
833 &remotePlayer.reverseGoldBitmap,
834 &remotePlayer.reverseBishopBitmap,
835 &remotePlayer.reverseRookBitmap,
836 &remotePlayer.reversePPawnBitmap,
837 &remotePlayer.reversePLanceBitmap,
838 &remotePlayer.reversePKnightBitmap,
839 &remotePlayer.reversePSilverBitmap,
840 &remotePlayer.reversePBishopBitmap,
841 &remotePlayer.reversePRookBitmap,
842 &remotePlayer.reverseKingBitmap
848 Pixmap *pieceToNormal[2][28] =
851 &localPlayer.normalPawnBitmap,
852 &localPlayer.normalLanceBitmap,
853 &localPlayer.normalKnightBitmap,
854 &localPlayer.normalSilverBitmap,
855 &localPlayer.normalGoldBitmap,
856 &localPlayer.normalBishopBitmap,
857 &localPlayer.normalRookBitmap,
858 &localPlayer.normalPPawnBitmap,
859 &localPlayer.normalPLanceBitmap,
860 &localPlayer.normalPKnightBitmap,
861 &localPlayer.normalPSilverBitmap,
862 &localPlayer.normalPBishopBitmap,
863 &localPlayer.normalPRookBitmap,
864 &localPlayer.normalKingBitmap,
865 &localPlayer.normalPawnBitmap,
866 &localPlayer.normalLanceBitmap,
867 &localPlayer.normalKnightBitmap,
868 &localPlayer.normalSilverBitmap,
869 &localPlayer.normalGoldBitmap,
870 &localPlayer.normalBishopBitmap,
871 &localPlayer.normalRookBitmap,
872 &localPlayer.normalPPawnBitmap,
873 &localPlayer.normalPLanceBitmap,
874 &localPlayer.normalPKnightBitmap,
875 &localPlayer.normalPSilverBitmap,
876 &localPlayer.normalPBishopBitmap,
877 &localPlayer.normalPRookBitmap,
878 &localPlayer.normalKingBitmap
881 &remotePlayer.normalPawnBitmap,
882 &remotePlayer.normalLanceBitmap,
883 &remotePlayer.normalKnightBitmap,
884 &remotePlayer.normalSilverBitmap,
885 &remotePlayer.normalGoldBitmap,
886 &remotePlayer.normalBishopBitmap,
887 &remotePlayer.normalRookBitmap,
888 &remotePlayer.normalPPawnBitmap,
889 &remotePlayer.normalPLanceBitmap,
890 &remotePlayer.normalPKnightBitmap,
891 &remotePlayer.normalPSilverBitmap,
892 &remotePlayer.normalPBishopBitmap,
893 &remotePlayer.normalPRookBitmap,
894 &remotePlayer.normalKingBitmap,
895 &remotePlayer.normalPawnBitmap,
896 &remotePlayer.normalLanceBitmap,
897 &remotePlayer.normalKnightBitmap,
898 &remotePlayer.normalSilverBitmap,
899 &remotePlayer.normalGoldBitmap,
900 &remotePlayer.normalBishopBitmap,
901 &remotePlayer.normalRookBitmap,
902 &remotePlayer.normalPPawnBitmap,
903 &remotePlayer.normalPLanceBitmap,
904 &remotePlayer.normalPKnightBitmap,
905 &remotePlayer.normalPSilverBitmap,
906 &remotePlayer.normalPBishopBitmap,
907 &remotePlayer.normalPRookBitmap,
908 &remotePlayer.normalKingBitmap
914 Pixmap *pieceToReverseSolid[2][28] =
917 &localPlayer.reverseSmallSolidBitmap,
918 &localPlayer.reverseSmallSolidBitmap,
919 &localPlayer.reverseSmallSolidBitmap,
920 &localPlayer.reverseBigSolidBitmap,
921 &localPlayer.reverseBigSolidBitmap,
922 &localPlayer.reverseBigSolidBitmap,
923 &localPlayer.reverseBigSolidBitmap,
924 &localPlayer.reverseSmallSolidBitmap,
925 &localPlayer.reverseSmallSolidBitmap,
926 &localPlayer.reverseSmallSolidBitmap,
927 &localPlayer.reverseBigSolidBitmap,
928 &localPlayer.reverseBigSolidBitmap,
929 &localPlayer.reverseBigSolidBitmap,
930 &localPlayer.reverseBigSolidBitmap,
931 &localPlayer.reverseSmallSolidBitmap,
932 &localPlayer.reverseSmallSolidBitmap,
933 &localPlayer.reverseSmallSolidBitmap,
934 &localPlayer.reverseBigSolidBitmap,
935 &localPlayer.reverseBigSolidBitmap,
936 &localPlayer.reverseBigSolidBitmap,
937 &localPlayer.reverseBigSolidBitmap,
938 &localPlayer.reverseSmallSolidBitmap,
939 &localPlayer.reverseSmallSolidBitmap,
940 &localPlayer.reverseSmallSolidBitmap,
941 &localPlayer.reverseBigSolidBitmap,
942 &localPlayer.reverseBigSolidBitmap,
943 &localPlayer.reverseBigSolidBitmap,
944 &localPlayer.reverseBigSolidBitmap
947 &remotePlayer.reverseSmallSolidBitmap,
948 &remotePlayer.reverseSmallSolidBitmap,
949 &remotePlayer.reverseSmallSolidBitmap,
950 &remotePlayer.reverseBigSolidBitmap,
951 &remotePlayer.reverseBigSolidBitmap,
952 &remotePlayer.reverseBigSolidBitmap,
953 &remotePlayer.reverseBigSolidBitmap,
954 &remotePlayer.reverseSmallSolidBitmap,
955 &remotePlayer.reverseSmallSolidBitmap,
956 &remotePlayer.reverseSmallSolidBitmap,
957 &remotePlayer.reverseBigSolidBitmap,
958 &remotePlayer.reverseBigSolidBitmap,
959 &remotePlayer.reverseBigSolidBitmap,
960 &remotePlayer.reverseBigSolidBitmap,
961 &remotePlayer.reverseSmallSolidBitmap,
962 &remotePlayer.reverseSmallSolidBitmap,
963 &remotePlayer.reverseSmallSolidBitmap,
964 &remotePlayer.reverseBigSolidBitmap,
965 &remotePlayer.reverseBigSolidBitmap,
966 &remotePlayer.reverseBigSolidBitmap,
967 &remotePlayer.reverseBigSolidBitmap,
968 &remotePlayer.reverseSmallSolidBitmap,
969 &remotePlayer.reverseSmallSolidBitmap,
970 &remotePlayer.reverseSmallSolidBitmap,
971 &remotePlayer.reverseBigSolidBitmap,
972 &remotePlayer.reverseBigSolidBitmap,
973 &remotePlayer.reverseBigSolidBitmap,
974 &remotePlayer.reverseBigSolidBitmap
980 Pixmap *pieceToNormalSolid[2][28] =
983 &localPlayer.normalSmallSolidBitmap,
984 &localPlayer.normalSmallSolidBitmap,
985 &localPlayer.normalSmallSolidBitmap,
986 &localPlayer.normalBigSolidBitmap,
987 &localPlayer.normalBigSolidBitmap,
988 &localPlayer.normalBigSolidBitmap,
989 &localPlayer.normalBigSolidBitmap,
990 &localPlayer.normalSmallSolidBitmap,
991 &localPlayer.normalSmallSolidBitmap,
992 &localPlayer.normalSmallSolidBitmap,
993 &localPlayer.normalBigSolidBitmap,
994 &localPlayer.normalBigSolidBitmap,
995 &localPlayer.normalBigSolidBitmap,
996 &localPlayer.normalBigSolidBitmap,
997 &localPlayer.normalSmallSolidBitmap,
998 &localPlayer.normalSmallSolidBitmap,
999 &localPlayer.normalSmallSolidBitmap,
1000 &localPlayer.normalBigSolidBitmap,
1001 &localPlayer.normalBigSolidBitmap,
1002 &localPlayer.normalBigSolidBitmap,
1003 &localPlayer.normalBigSolidBitmap,
1004 &localPlayer.normalSmallSolidBitmap,
1005 &localPlayer.normalSmallSolidBitmap,
1006 &localPlayer.normalSmallSolidBitmap,
1007 &localPlayer.normalBigSolidBitmap,
1008 &localPlayer.normalBigSolidBitmap,
1009 &localPlayer.normalBigSolidBitmap,
1010 &localPlayer.normalBigSolidBitmap
1013 &remotePlayer.normalSmallSolidBitmap,
1014 &remotePlayer.normalSmallSolidBitmap,
1015 &remotePlayer.normalSmallSolidBitmap,
1016 &remotePlayer.normalBigSolidBitmap,
1017 &remotePlayer.normalBigSolidBitmap,
1018 &remotePlayer.normalBigSolidBitmap,
1019 &remotePlayer.normalBigSolidBitmap,
1020 &remotePlayer.normalSmallSolidBitmap,
1021 &remotePlayer.normalSmallSolidBitmap,
1022 &remotePlayer.normalSmallSolidBitmap,
1023 &remotePlayer.normalBigSolidBitmap,
1024 &remotePlayer.normalBigSolidBitmap,
1025 &remotePlayer.normalBigSolidBitmap,
1026 &remotePlayer.normalBigSolidBitmap,
1027 &remotePlayer.normalSmallSolidBitmap,
1028 &remotePlayer.normalSmallSolidBitmap,
1029 &remotePlayer.normalSmallSolidBitmap,
1030 &remotePlayer.normalBigSolidBitmap,
1031 &remotePlayer.normalBigSolidBitmap,
1032 &remotePlayer.normalBigSolidBitmap,
1033 &remotePlayer.normalBigSolidBitmap,
1034 &remotePlayer.normalSmallSolidBitmap,
1035 &remotePlayer.normalSmallSolidBitmap,
1036 &remotePlayer.normalSmallSolidBitmap,
1037 &remotePlayer.normalBigSolidBitmap,
1038 &remotePlayer.normalBigSolidBitmap,
1039 &remotePlayer.normalBigSolidBitmap,
1040 &remotePlayer.normalBigSolidBitmap
1046 int pieceIsPromoted[] =
1048 False, False, False, False, False, False, False,
1049 True, True, True, True, True, True, False,
1050 False, False, False, False, False, False, False,
1051 True, True, True, True, True, True, False,
1056 int piecePromotable[] =
1058 True, True, True, True, False, True, True,
1059 False, False, False, False, False, False, False,
1060 True, True, True, True, False, True, True,
1061 False, False, False, False, False, False, False,
1066 char pieceToChar[] =
1068 'P', 'L', 'N', 'S', 'G', 'B', 'R', 'P', 'L', 'N', 'S', 'B', 'R', 'K',
1069 'p', 'l', 'n', 's', 'g', 'b', 'r', 'p', 'l', 'n', 's', 'b', 'r', 'k',
1074 ShogiSquare pieceToPromoted[] =
1076 BlackPPawn, BlackPLance, BlackPKnight, BlackPSilver, BlackGold,
1077 BlackPBishop, BlackPRook,
1078 BlackPPawn, BlackPLance, BlackPKnight, BlackPSilver,
1079 BlackPBishop, BlackPRook, BlackKing,
1080 WhitePPawn, WhitePLance, WhitePKnight, WhitePSilver, WhiteGold,
1081 WhitePBishop, WhitePRook,
1082 WhitePPawn, WhitePLance, WhitePKnight, WhitePSilver,
1083 WhitePBishop, WhitePRook, WhiteKing
1088 XrmOptionDescRec shellOptions[] =
1090 { "-pieceColor", "pieceColor", XrmoptionSepArg, NULL },
1091 { "-pc", "pieceColor", XrmoptionSepArg, NULL },
1092 { "-charPieceColor", "charPieceColor", XrmoptionSepArg, NULL },
1093 { "-cpc", "charPieceColor", XrmoptionSepArg, NULL },
1094 { "-zeroColor", "zeroColor", XrmoptionSepArg, NULL },
1095 { "-zc", "zeroColor", XrmoptionSepArg, NULL },
1096 { "-oneColor", "oneColor", XrmoptionSepArg, NULL },
1097 { "-oc", "oneColor", XrmoptionSepArg, NULL },
1098 { "-squareColor", "squareColor", XrmoptionSepArg, NULL },
1099 { "-sc", "squareColor", XrmoptionSepArg, NULL },
1100 { "-westernPieceSet", "westernPieceSet", XrmoptionSepArg, NULL },
1101 { "-wps", "westernPieceSet", XrmoptionSepArg, NULL },
1102 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1103 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1104 { "-firstShogiProgram", "firstShogiProgram", XrmoptionSepArg, NULL },
1105 { "-fsp", "firstShogiProgram", XrmoptionSepArg, NULL },
1106 { "-secondShogiProgram", "secondShogiProgram", XrmoptionSepArg, NULL },
1107 { "-ssp", "secondShogiProgram", XrmoptionSepArg, NULL },
1108 { "-noShogiProgram", "noShogiProgram", XrmoptionSepArg, NULL },
1109 { "-nsp", "noShogiProgram", XrmoptionSepArg, NULL },
1110 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1111 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1112 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1113 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1114 { "-reversePawnBitmap", "reversePawnBitmap", XrmoptionSepArg, NULL },
1115 { "-rpb", "reversePawnBitmap", XrmoptionSepArg, NULL },
1116 { "-reverseLanceBitmap", "reverseLanceBitmap", XrmoptionSepArg, NULL },
1117 { "-rlb", "reverseLanceBitmap", XrmoptionSepArg, NULL },
1118 { "-reverseKnightBitmap", "reverseKnightBitmap", XrmoptionSepArg, NULL },
1119 { "-rnb", "reverseKnightBitmap", XrmoptionSepArg, NULL },
1120 { "-reverseSilverBitmap", "reverseSilverBitmap", XrmoptionSepArg, NULL },
1121 { "-rsb", "reverseSilverBitmap", XrmoptionSepArg, NULL },
1122 { "-reverseGoldBitmap", "reverseGoldBitmap", XrmoptionSepArg, NULL },
1123 { "-rgb", "reverseGoldBitmap", XrmoptionSepArg, NULL },
1124 { "-reverseRookBitmap", "reverseRookBitmap", XrmoptionSepArg, NULL },
1125 { "-rrb", "reverseRookBitmap", XrmoptionSepArg, NULL },
1126 { "-reverseBishopBitmap", "reverseBishopBitmap", XrmoptionSepArg, NULL },
1127 { "-rbb", "reverseBishopBitmap", XrmoptionSepArg, NULL },
1128 { "-reversePPawnBitmap", "reversePPawnBitmap",
1129 XrmoptionSepArg, NULL },
1130 { "-rppb", "reversePPawnBitmap", XrmoptionSepArg, NULL },
1131 { "-reversePLanceBitmap", "reversePLanceBitmap",
1132 XrmoptionSepArg, NULL },
1133 { "-rplb", "reversePLanceBitmap", XrmoptionSepArg, NULL },
1134 { "-reversePKnightBitmap", "reversePKnightBitmap",
1135 XrmoptionSepArg, NULL },
1136 { "-rpnb", "reversePKnightBitmap", XrmoptionSepArg, NULL },
1137 { "-reversePSilverBitmap", "reversePSilverBitmap",
1138 XrmoptionSepArg, NULL },
1139 { "-rpsb", "reversePSilverBitmap", XrmoptionSepArg, NULL },
1140 { "-reversePRookBitmap", "reversePRookBitmap",
1141 XrmoptionSepArg, NULL },
1142 { "-rprb", "reversePRookBitmap", XrmoptionSepArg, NULL },
1143 { "-reversePBishopBitmap", "reversePBishopBitmap",
1144 XrmoptionSepArg, NULL },
1145 { "-rpbb", "reversePBishopBitmap", XrmoptionSepArg, NULL },
1146 { "-reverseKingBitmap", "reverseKingBitmap", XrmoptionSepArg, NULL },
1147 { "-rkb", "reverseKingBitmap", XrmoptionSepArg, NULL },
1148 { "-outlinePawnBitmap", "outlinePawnBitmap", XrmoptionSepArg, NULL },
1149 { "-opb", "normalPawnBitmap", XrmoptionSepArg, NULL },
1150 { "-normalLanceBitmap", "normalLanceBitmap", XrmoptionSepArg, NULL },
1151 { "-olb", "normalLanceBitmap", XrmoptionSepArg, NULL },
1152 { "-normalKnightBitmap", "normalKnightBitmap", XrmoptionSepArg, NULL },
1153 { "-onb", "normalKnightBitmap", XrmoptionSepArg, NULL },
1154 { "-normalSilverBitmap", "normalSilverBitmap", XrmoptionSepArg, NULL },
1155 { "-osb", "normalSilverBitmap", XrmoptionSepArg, NULL },
1156 { "-normalGoldBitmap", "normalGoldBitmap", XrmoptionSepArg, NULL },
1157 { "-ogb", "normalGoldBitmap", XrmoptionSepArg, NULL },
1158 { "-normalRookBitmap", "normalRookBitmap", XrmoptionSepArg, NULL },
1159 { "-orb", "normalRookBitmap", XrmoptionSepArg, NULL },
1160 { "-normalBishopBitmap", "normalBishopBitmap", XrmoptionSepArg, NULL },
1161 { "-obb", "normalBishopBitmap", XrmoptionSepArg, NULL },
1162 { "-normalPPawnBitmap", "normalPPawnBitmap", XrmoptionSepArg, NULL },
1163 { "-oppb", "normalPPawnBitmap", XrmoptionSepArg, NULL },
1164 { "-normalPLanceBitmap", "normalPLanceBitmap", XrmoptionSepArg, NULL },
1165 { "-oplb", "normalPLanceBitmap", XrmoptionSepArg, NULL },
1166 { "-normalPKnightBitmap", "normalPKnightBitmap", XrmoptionSepArg, NULL },
1167 { "-opnb", "normalPKnightBitmap", XrmoptionSepArg, NULL },
1168 { "-normalPSilverBitmap", "normalPSilverBitmap", XrmoptionSepArg, NULL },
1169 { "-opsb", "normalPSilverBitmap", XrmoptionSepArg, NULL },
1170 { "-normalPRookBitmap", "normalPRookBitmap", XrmoptionSepArg, NULL },
1171 { "-oprb", "normalPRookBitmap", XrmoptionSepArg, NULL },
1172 { "-normalPBishopBitmap", "normalPBishopBitmap", XrmoptionSepArg, NULL },
1173 { "-opbb", "normalPBishopBitmap", XrmoptionSepArg, NULL },
1174 { "-normalKingBitmap", "normalKingBitmap", XrmoptionSepArg, NULL },
1175 { "-okb", "outlineKingBitmap", XrmoptionSepArg, NULL },
1176 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1177 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1178 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1179 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1180 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1181 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1182 { "-gameIn", "gameIn", XrmoptionSepArg, NULL },
1183 { "-gi", "gameIn", XrmoptionSepArg, NULL },
1184 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1185 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1186 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1187 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1188 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1189 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1190 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1191 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1192 { "-challengeDisplay", "challengeDisplay", XrmoptionSepArg, NULL },
1193 { "-cd", "challengeDisplay", XrmoptionSepArg, NULL },
1194 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1195 { "-mm", "matchMode", XrmoptionSepArg, NULL },
1196 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1197 { "-mono", "monoMode", XrmoptionSepArg, NULL },
1198 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1199 { "-debug", "debugMode", XrmoptionSepArg, NULL },
1200 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1201 { "-clock", "clockMode", XrmoptionSepArg, NULL },
1202 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1203 { "-size", "boardSize", XrmoptionSepArg, NULL },
1204 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1205 { "-st", "searchTime", XrmoptionSepArg, NULL },
1206 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1207 { "-sd", "searchDepth", XrmoptionSepArg, NULL },
1208 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1209 { "-coords", "showCoords", XrmoptionSepArg, NULL },
1210 { "-iconic", "Iconic", XrmoptionNoArg, "True" }
1215 XtActionsRec boardActions[] =
1217 { "DrawPosition", (XtActionProc) DrawPosition },
1218 { "HandleUserMove", (XtActionProc) HandleUserMove },
1219 { "ResetProc", (XtActionProc) ResetProc },
1220 { "ResetFileProc", (XtActionProc) ResetFileProc },
1221 { "LoadGameProc", (XtActionProc) LoadGameProc },
1222 { "QuitProc", (XtActionProc) QuitProc },
1223 { "ForwardProc", (XtActionProc) ForwardProc },
1224 { "BackwardProc", (XtActionProc) BackwardProc },
1225 { "PauseProc", (XtActionProc) PauseProc },
1226 { "Iconify", (XtActionProc) Iconify },
1227 { "FileNameAction", (XtActionProc) FileNameAction },
1228 { "PieceMenuPopup", (XtActionProc) PieceMenuPopup },
1229 { "SetBlackToPlay", (XtActionProc) SetBlackToPlay },
1230 { "SetWhiteToPlay", (XtActionProc) SetWhiteToPlay }
1234 char translationsTable[] =
1235 "<Expose>: DrawPosition() \n \
1236 <Btn1Down>: HandleUserMove() \n \
1237 <Btn1Up>: HandleUserMove() \n \
1238 <Btn2Down>: XawPositionSimpleMenu(menuW) PieceMenuPopup(menuW) \n \
1239 <Btn3Down>: XawPositionSimpleMenu(menuB) PieceMenuPopup(menuB) \n \
1240 <Key>r: ResetFileProc() ResetProc() \n \
1241 <Key>R: ResetFileProc() ResetProc() \n \
1242 <Key>g: LoadGameProc() \n \
1243 <Key>G: LoadGameProc() \n \
1244 <Key>q: QuitProc() \n \
1245 <Key>Q: QuitProc() \n \
1246 <Message>WM_PROTOCOLS: QuitProc() \n \
1247 <Key>f: ForwardProc() \n \
1248 <Key>F: ForwardProc() \n \
1249 <Key>b: BackwardProc() \n \
1250 <Key>B: BackwardProc() \n \
1251 <Key>p: PauseProc() \n \
1252 <Key>P: PauseProc() \n \
1253 <Key>i: Iconify() \n \
1254 <Key>I: Iconify() \n \
1255 <Key>c: Iconify() \n \
1256 <Key>C: Iconify() \n";
1259 char translationsTableReduced[] =
1260 "<Expose>: DrawPosition() \n \
1261 <Btn1Down>: HandleUserMove() \n \
1262 <Btn1Up>: HandleUserMove() \n \
1263 <Message>WM_PROTOCOLS: QuitProc() \n";
1266 char blackTranslations[] = "<BtnDown>: SetBlackToPlay()\n";
1267 char whiteTranslations[] = "<BtnDown>: SetWhiteToPlay()\n";
1269 String xshogiResources[] =
1272 "*Dialog*value.translations: #override "
1273 "\\n <Key>Return: FileNameAction()",
1278 int global_argc; /* number of command args */
1279 char *global_argv[10]; /* pointers to up to 10 command args */
1283 static struct DisplayData *player;
1292 static FileModeInfo fmi;
1296 * This is a hack that allows the parser to tell the program
1297 * that the game it's loading has ended.
1300 int loaded_game_finished = 0;
1303 /**********************************************************************
1307 **********************************************************************/
1311 CreatePlayerWindow(void)
1313 int mainFontPxlSize, coordFontPxlSize;
1314 int min, sec, matched;
1315 XSetWindowAttributes window_attributes;
1318 Dimension timerWidth, boardWidth, commandsWidth, w, h;
1320 int fromRemotePlayer = (player == &remotePlayer);
1322 player->monoMode = player->appData.monoMode;
1323 player->showCoords = player->appData.showCoords;
1326 * Parse timeControl resource.
1329 if (player->appData.timeControl != NULL)
1331 matched = sscanf(player->appData.timeControl, "%d:%d", &min, &sec);
1335 timeControl = min * 60 * 1000;
1337 else if (matched == 2)
1339 timeControl = (min * 60 + sec) * 1000;
1343 fprintf(stderr, "%s: bad timeControl option %s\n",
1344 programName, player->appData.timeControl);
1350 * Parse searchTime resource
1353 if (player->appData.searchTime != NULL)
1355 matched = sscanf(player->appData.searchTime, "%d:%d", &min, &sec);
1359 searchTime = min * 60;
1361 else if (matched == 2)
1363 searchTime = min * 60 + sec;
1367 fprintf(stderr, "%s: bad searchTime option %s\n",
1368 programName, player->appData.searchTime);
1373 if ((player->appData.searchTime != NULL)
1374 || (player->appData.searchDepth > 0)
1375 || player->appData.noShogiProgram)
1377 player->appData.clockMode = False;
1380 player->Iconic = False;
1381 player->boardSize = Small;
1382 player->squareSize = SMALL_SQUARE_SIZE;
1383 player->flipView = (player == &remotePlayer);
1384 player->promotionUp = False;
1387 * Determine boardSize.
1390 if (strcasecmp(player->appData.boardSize, "Large") == 0)
1392 player->boardSize = Large;
1394 else if (strcasecmp(player->appData.boardSize, "Medium") == 0)
1396 player->boardSize = Medium;
1398 else if (strcasecmp(player->appData.boardSize, "Small") == 0)
1400 player->boardSize = Small;
1404 fprintf(stderr, "%s: bad boardSize option %s\n",
1405 programName, player->appData.boardSize);
1409 if ((local = (player == &localPlayer)))
1411 player->xDisplay = XtDisplay(player->shellWidget);
1412 player->xScreen = DefaultScreen(player->xDisplay);
1415 #undef DONT_ADJUST_BOARDSIZE
1416 #ifndef DONT_ADJUST_BOARDSIZE
1417 if (((DisplayWidth(player->xDisplay, player->xScreen) < 800)
1418 || (DisplayHeight(player->xDisplay, player->xScreen) < 800))
1419 && (player->boardSize == Large))
1421 player->boardSize = Medium;
1425 switch (player->boardSize)
1428 player->squareSize = SMALL_SQUARE_SIZE;
1429 mainFontPxlSize = 11;
1430 coordFontPxlSize = 10;
1434 player->squareSize = MEDIUM_SQUARE_SIZE;
1435 mainFontPxlSize = 17;
1436 coordFontPxlSize = 12;
1441 player->squareSize = LARGE_SQUARE_SIZE;
1442 mainFontPxlSize = 17;
1443 coordFontPxlSize = 14;
1448 * Detect if there are not enough colors are available and adapt.
1451 if (DefaultDepth(player->xDisplay, player->xScreen) <= 2)
1452 player->monoMode = True;
1455 * Determine what fonts to use.
1458 player->appData.mainFont
1459 = FindFont(player->appData.mainFont, mainFontPxlSize);
1461 = XLoadFont(player->xDisplay, player->appData.mainFont);
1462 player->mainFontStruct
1463 = XQueryFont(player->xDisplay, player->mainFontID);
1464 player->appData.coordFont
1465 = FindFont(player->appData.coordFont, coordFontPxlSize);
1467 = XLoadFont(player->xDisplay, player->appData.coordFont);
1468 player->coordFontStruct
1469 = XQueryFont(player->xDisplay, player->coordFontID);
1472 * Set default arguments.
1475 XtSetArg(player->shellArgs[0], XtNwidth, 0);
1476 XtSetArg(player->shellArgs[1], XtNheight, 0);
1477 XtSetArg(player->shellArgs[2], XtNminWidth, 0);
1478 XtSetArg(player->shellArgs[3], XtNminHeight, 0);
1479 XtSetArg(player->shellArgs[4], XtNmaxWidth, 0);
1480 XtSetArg(player->shellArgs[5], XtNmaxHeight, 0);
1482 XtSetArg(player->boardArgs[0], XtNborderWidth, 0);
1483 XtSetArg(player->boardArgs[1], XtNwidth,
1484 LINE_GAP + (BOARD_SIZE + 4)
1485 * (SMALL_SQUARE_SIZE + LINE_GAP));
1486 XtSetArg(player->boardArgs[2], XtNheight,
1487 LINE_GAP + BOARD_SIZE
1488 * (SMALL_SQUARE_SIZE + LINE_GAP));
1490 XtSetArg(player->commandsArgs[0], XtNborderWidth, 0);
1491 XtSetArg(player->commandsArgs[1], XtNdefaultColumns, 4);
1492 XtSetArg(player->commandsArgs[2], XtNforceColumns, True);
1493 XtSetArg(player->commandsArgs[3], XtNcolumnSpacing, 12);
1494 XtSetArg(player->commandsArgs[4], XtNlist, (XtArgVal) buttonStrings);
1495 XtSetArg(player->commandsArgs[5], XtNnumberStrings, buttonCount);
1496 XtSetArg(player->commandsArgs[6], XtNfont, player->mainFontStruct);
1498 XtSetArg(player->messageArgs[0], XtNborderWidth, 0);
1499 XtSetArg(player->messageArgs[1], XtNjustify, (XtArgVal) XtJustifyLeft);
1500 XtSetArg(player->messageArgs[2], XtNlabel, (XtArgVal) "starting...");
1502 XtSetArg(player->timerArgs[0], XtNborderWidth, 0);
1503 XtSetArg(player->timerArgs[1], XtNjustify, (XtArgVal) XtJustifyLeft);
1505 XtSetArg(player->titleArgs[0], XtNborderWidth, 0);
1506 XtSetArg(player->titleArgs[1], XtNjustify, (XtArgVal) XtJustifyLeft);
1508 boardWidth = LINE_GAP
1509 + (BOARD_SIZE + 4) * (player->squareSize + LINE_GAP);
1511 XtSetArg(player->boardArgs[1], XtNwidth, boardWidth);
1512 XtSetArg(player->boardArgs[2], XtNheight,
1513 LINE_GAP + BOARD_SIZE * (player->squareSize + LINE_GAP));
1519 player->formWidget = XtCreateManagedWidget("form",
1521 player->shellWidget, NULL, 0);
1523 player->widgetList[0] = player->blackTimerWidget
1524 = XtCreateWidget((local ? "black time:" : "rblack time:"),
1526 player->formWidget, player->timerArgs,
1527 XtNumber(player->timerArgs));
1529 XtSetArg(args[0], XtNfont, player->mainFontStruct);
1530 XtSetValues(player->blackTimerWidget, args, 1);
1532 player->widgetList[1] = player->whiteTimerWidget
1533 = XtCreateWidget((local ? "white time:" : "rwhite time:"),
1535 player->formWidget, player->timerArgs,
1536 XtNumber(player->timerArgs));
1538 XtSetArg(args[0], XtNfont, player->mainFontStruct);
1539 XtSetValues(player->whiteTimerWidget, args, 1);
1541 player->widgetList[2] = player->titleWidget
1542 = XtCreateWidget((local ? "" : "r"), labelWidgetClass,
1543 player->formWidget, player->titleArgs,
1544 XtNumber(player->titleArgs));
1546 XtSetArg(args[0], XtNfont, player->mainFontStruct);
1547 XtSetValues(player->titleWidget, args, 1);
1549 player->widgetList[3] = player->messageWidget
1550 = XtCreateWidget((local ? "message" : "rmessage"),
1551 labelWidgetClass, player->formWidget,
1552 player->messageArgs,
1553 XtNumber(player->messageArgs));
1555 XtSetArg(args[0], XtNfont, player->mainFontStruct);
1556 XtSetValues(player->messageWidget, args, 1);
1558 player->widgetList[4] = player->commandsWidget
1559 = XtCreateWidget((local ? "commands" : "rcommand"),
1560 listWidgetClass, player->formWidget,
1561 player->commandsArgs,
1562 XtNumber(player->commandsArgs));
1564 player->widgetList[5] = player->boardWidget
1565 = XtCreateWidget((local ? "board" : "rboard"),
1566 widgetClass, player->formWidget,
1568 XtNumber(player->boardArgs));
1570 XtManageChildren(player->widgetList, XtNumber(player->widgetList));
1573 * Calculate the width of the timer labels.
1576 XtSetArg(args[0], XtNfont, &player->mainFontStruct);
1577 XtGetValues(player->blackTimerWidget, args, 1);
1579 if (player->appData.clockMode)
1581 timerWidth = XTextWidth(player->mainFontStruct,
1582 "Black: 8:88:88 ", 15);
1586 timerWidth = XTextWidth(player->mainFontStruct, "Black ", 7);
1589 XtSetArg(args[0], XtNwidth, timerWidth);
1590 XtSetValues(player->blackTimerWidget, args, 1);
1591 XtSetValues(player->whiteTimerWidget, args, 1);
1593 XtSetArg(args[0], XtNbackground, &player->timerForegroundPixel);
1594 XtSetArg(args[1], XtNforeground, &player->timerBackgroundPixel);
1595 XtGetValues(player->blackTimerWidget, args, 2);
1598 * Calculate the width of the name and message labels.
1601 XtSetArg(args[0], XtNwidth, &commandsWidth);
1602 XtGetValues(player->commandsWidget, args, 1);
1603 w = ((commandsWidth > boardWidth) ? commandsWidth : boardWidth);
1604 XtSetArg(args[0], XtNwidth, w - timerWidth * 2 - 12);
1605 XtSetValues(player->titleWidget, args, 1);
1606 XtSetArg(args[0], XtNwidth, w - 8);
1607 XtSetValues(player->messageWidget, args, 1);
1610 * 'formWidget' uses these constraints but they are stored
1614 XtSetArg(args[0], XtNfromHoriz, player->blackTimerWidget);
1615 XtSetValues(player->whiteTimerWidget, args, 1);
1616 XtSetArg(args[0], XtNfromHoriz, player->whiteTimerWidget);
1617 XtSetValues(player->titleWidget, args, 1);
1618 XtSetArg(args[0], XtNfromVert, player->blackTimerWidget);
1619 XtSetValues(player->messageWidget, args, 1);
1620 XtSetArg(args[0], XtNfromVert, player->messageWidget);
1621 XtSetValues(player->commandsWidget, args, 1);
1622 XtSetArg(args[0], XtNfromVert, player->commandsWidget);
1623 XtSetValues(player->boardWidget, args, 1);
1625 XtRealizeWidget(player->shellWidget);
1627 player->xBoardWindow = XtWindow(player->boardWidget);
1633 player->iconPixmap =
1634 XCreateBitmapFromData(player->xDisplay,
1635 XtWindow(player->shellWidget),
1636 (char *)icon_bits, icon_width, icon_height);
1638 XtSetArg(args[0], XtNiconPixmap, player->iconPixmap);
1639 XtSetValues(player->shellWidget, args, 1);
1642 * Create a cursor for the board widget.
1645 window_attributes.cursor = XCreateFontCursor(player->xDisplay, XC_hand2);
1646 XChangeWindowAttributes(player->xDisplay, player->xBoardWindow,
1647 CWCursor, &window_attributes);
1650 * Inhibit shell resizing.
1653 player->shellArgs[0].value = (XtArgVal) &w;
1654 player->shellArgs[1].value = (XtArgVal) &h;
1655 XtGetValues(player->shellWidget, player->shellArgs, 2);
1656 player->shellArgs[4].value = player->shellArgs[2].value = w;
1657 player->shellArgs[5].value = player->shellArgs[3].value = h;
1658 XtSetValues(player->shellWidget, &player->shellArgs[2], 4);
1661 * Determine value of black pixel.
1664 player->black_pixel_is_zero =
1665 (XBlackPixel(player->xDisplay, player->xScreen) == 0);
1671 if (!fromRemotePlayer)
1674 XtAddCallback(player->commandsWidget, XtNcallback, SelectCommand,
1675 (XtPointer)fromRemotePlayer);
1677 if (!fromRemotePlayer)
1678 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
1680 if (fromRemotePlayer)
1682 XtSetArg(args[0], XtNtranslations,
1683 XtParseTranslationTable(translationsTableReduced));
1684 /* Disable key commands because often keys are pressed
1685 in the board window if using another talk window. */
1686 XtSetValues(player->boardWidget, &args[0], 1);
1687 XtSetValues(localPlayer.boardWidget, &args[0], 1);
1691 XtSetArg(args[0], XtNtranslations,
1692 XtParseTranslationTable(translationsTable));
1693 XtSetValues(player->boardWidget, &args[0], 1);
1694 XtSetArg(args[0], XtNtranslations,
1695 XtParseTranslationTable(blackTranslations));
1696 XtSetValues(player->blackTimerWidget, &args[0], 1);
1697 XtSetArg(args[0], XtNtranslations,
1698 XtParseTranslationTable(whiteTranslations));
1699 XtSetValues(player->whiteTimerWidget, &args[0], 1);
1702 XtAddEventHandler(player->boardWidget, ExposureMask | ButtonPressMask
1703 | ButtonReleaseMask | Button1MotionMask | KeyPressMask,
1704 False, (XtEventHandler)EventProc,
1705 (XtPointer)(player == &remotePlayer));
1707 sprintf(buf, "xshogi version %s, patchlevel %s based on "
1708 "xboard version %s",
1709 version, patchlevel, XBOARD_VERSION);
1712 * If there is to be a machine match, set it up.
1715 if (matchMode != MatchFalse && player != &remotePlayer)
1717 if (player->appData.noShogiProgram)
1720 "%s: can't have a match with no shogi programs!\n",
1725 DisplayMessage(buf, fromRemotePlayer);
1726 TwoMachinesProc(NULL, NULL, NULL, NULL);
1731 DisplayMessage(buf, fromRemotePlayer);
1739 main(int argc, char **argv)
1741 setbuf(stdout, NULL);
1742 setbuf(stderr, NULL);
1745 * Copy pointers to command line arguments and number of such pointers.
1746 * (argc, argv will be destroyed by XtAppInitialize)
1749 for (global_argc = 0; global_argc < argc; global_argc++)
1750 global_argv[global_argc] = argv[global_argc];
1752 programName = strrchr(argv[0], '/');
1754 if (programName == NULL)
1755 programName = argv[0];
1759 localPlayer.shellWidget
1760 = XtAppInitialize(&appContext, "XShogi", shellOptions,
1761 XtNumber(shellOptions), &argc, argv,
1762 xshogiResources, NULL, 0);
1767 if ((shogiDir = (char *)getenv("SHOGIDIR")) == NULL)
1773 if (chdir(shogiDir) != 0)
1775 fprintf(stderr, "%s: can't cd to SHOGIDIR\n",
1782 XtGetApplicationResources(localPlayer.shellWidget,
1783 &localPlayer.appData, clientResources,
1784 XtNumber(clientResources), NULL, 0);
1786 xshogiDebug = localPlayer.appData.debugMode;
1789 * Determine matchMode state -- poor man's resource converter.
1792 if (strcasecmp(localPlayer.appData.matchMode, "Init") == 0)
1794 matchMode = MatchInit;
1796 else if (strcasecmp(localPlayer.appData.matchMode, "Position") == 0)
1798 matchMode = MatchPosition;
1800 else if (strcasecmp(localPlayer.appData.matchMode, "Opening") == 0)
1802 matchMode = MatchOpening;
1804 else if (strcasecmp(localPlayer.appData.matchMode, "False") == 0)
1806 matchMode = MatchFalse;
1810 fprintf(stderr, "%s: bad matchMode option %s\n",
1811 programName, localPlayer.appData.matchMode);
1815 buttonStrings = gnuButtonStrings;
1816 buttonProcs = gnuButtonProcs;
1817 buttonCount = XtNumber(gnuButtonStrings);
1819 player = &localPlayer;
1821 CreatePlayerWindow();
1823 XtAppMainLoop(appContext);
1831 * Find a font that matches "pattern" that is as close as
1832 * possible to the targetPxlSize. Prefer fonts that are k
1833 * pixels smaller to fonts that are k pixels larger. The
1834 * pattern must be in the X Consortium standard format,
1835 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
1836 * The return value should be freed with XtFree when no
1841 FindFont(char *pattern, int targetPxlSize)
1843 char **fonts, *p, *best;
1844 int i, j, nfonts, minerr, err, pxlSize;
1846 fonts = XListFonts(player->xDisplay, pattern, 999999, &nfonts);
1850 fprintf(stderr, "%s: No fonts match pattern %s\n",
1851 programName, pattern);
1858 for (i = 0; i < nfonts; i++)
1880 if (pxlSize == targetPxlSize)
1886 err = pxlSize - targetPxlSize;
1888 if (abs(err) < abs(minerr)
1889 || ((minerr > 0) && (err < 0) && (-err == minerr)))
1896 p = (char *)XtMalloc(strlen(best) + 1);
1898 XFreeFontNames(fonts);
1908 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
1909 | GCBackground | GCFunction | GCPlaneMask;
1910 XGCValues gc_values;
1912 gc_values.plane_mask = AllPlanes;
1913 gc_values.line_width = LINE_GAP;
1914 gc_values.line_style = LineSolid;
1915 gc_values.function = GXcopy;
1917 gc_values.foreground = XBlackPixel(player->xDisplay, player->xScreen);
1918 gc_values.background = XBlackPixel(player->xDisplay, player->xScreen);
1919 player->lineGC = XtGetGC(player->shellWidget, value_mask, &gc_values);
1921 gc_values.background = XWhitePixel(player->xDisplay, player->xScreen);
1922 player->coordGC = XtGetGC(player->shellWidget, value_mask, &gc_values);
1923 XSetFont(player->xDisplay, player->coordGC, player->coordFontID);
1925 if (player->monoMode)
1927 gc_values.foreground
1928 = XWhitePixel(player->xDisplay, player->xScreen);
1929 gc_values.background
1930 = XWhitePixel(player->xDisplay, player->xScreen);
1932 /* empty square off board */
1933 player->squareOffBoardGC
1934 = XtGetGC(player->shellWidget, value_mask, &gc_values);
1936 /* empty square on board */
1938 = XtGetGC(player->shellWidget, value_mask, &gc_values);
1942 Pixel bg; /* background color */
1945 /* Get background color. */
1946 XtSetArg(args[0], XtNbackground, &bg);
1947 XtGetValues(player->shellWidget, args, 1);
1949 /* empty square off board */
1950 gc_values.foreground = gc_values.background = bg;
1951 player->squareOffBoardGC
1952 = XtGetGC(player->shellWidget, value_mask, &gc_values);
1954 /* empty square on board */
1955 gc_values.foreground
1956 = player->appData.squareColor;
1957 gc_values.background
1958 = player->appData.squareColor;
1960 = XtGetGC(player->shellWidget, value_mask, &gc_values);
1962 /* piece off board */
1963 gc_values.foreground
1964 = player->appData.pieceColor;
1965 gc_values.background = bg;
1967 = XtGetGC(player->shellWidget, value_mask, &gc_values);
1969 /* piece on board */
1970 gc_values.foreground
1971 = player->appData.pieceColor;
1972 gc_values.background
1973 = player->appData.squareColor;
1975 = XtGetGC(player->shellWidget, value_mask, &gc_values);
1979 * FIXME: charPieceColor seems to have no effect;
1980 * the bitmap is *always* black.
1982 gc_values.function = (player->black_pixel_is_zero ? GXand : GXor);
1984 gc_values.foreground
1985 = player->appData.charPieceColor;
1986 gc_values.background
1987 = player->appData.charPieceColor;
1990 = XtGetGC(player->shellWidget, value_mask, &gc_values);
2000 XSynchronize(player->xDisplay, True); /* Work-around for xlib/xt
2003 if (player->appData.westernPieceSet)
2005 ReadBitmap(player->appData.reverseBigSolidBitmap,
2006 &player->reverseBigSolidBitmap,
2008 bigsolidR_bits, bigsolidR_m_bits, bigsolidR_l_bits);
2010 ReadBitmap(player->appData.reverseSmallSolidBitmap,
2011 &player->reverseSmallSolidBitmap,
2013 smallsolidR_bits, smallsolidR_m_bits, smallsolidR_l_bits);
2015 ReadBitmap(player->appData.normalBigSolidBitmap,
2016 &player->normalBigSolidBitmap,
2018 bigsolid_bits, bigsolid_m_bits, bigsolid_l_bits);
2020 ReadBitmap(player->appData.normalSmallSolidBitmap,
2021 &player->normalSmallSolidBitmap,
2023 smallsolid_bits, smallsolid_m_bits, smallsolid_l_bits);
2025 ReadBitmap(player->appData.reversePawnBitmap,
2026 &player->reversePawnBitmap,
2027 &player->reverseSmallSolidBitmap,
2028 pawnRW_bits, pawnRW_bits, pawnRW_bits);
2030 ReadBitmap(player->appData.reverseLanceBitmap,
2031 &player->reverseLanceBitmap,
2032 &player->reverseSmallSolidBitmap,
2033 lanceRW_bits, lanceRW_bits, lanceRW_bits);
2035 ReadBitmap(player->appData.reverseKnightBitmap,
2036 &player->reverseKnightBitmap,
2037 &player->reverseSmallSolidBitmap,
2038 knightRW_bits, knightRW_bits, knightRW_bits);
2040 ReadBitmap(player->appData.reverseSilverBitmap,
2041 &player->reverseSilverBitmap,
2042 &player->reverseBigSolidBitmap,
2043 silverRW_bits, silverRW_bits, silverRW_bits);
2045 ReadBitmap(player->appData.reverseGoldBitmap,
2046 &player->reverseGoldBitmap,
2047 &player->reverseBigSolidBitmap,
2048 goldRW_bits, goldRW_bits, goldRW_bits);
2050 ReadBitmap(player->appData.reverseRookBitmap,
2051 &player->reverseRookBitmap,
2052 &player->reverseBigSolidBitmap,
2053 rookRW_bits, rookRW_bits, rookRW_bits);
2055 ReadBitmap(player->appData.reverseBishopBitmap,
2056 &player->reverseBishopBitmap,
2057 &player->reverseBigSolidBitmap,
2058 bishopRW_bits, bishopRW_bits, bishopRW_bits);
2060 ReadBitmap(player->appData.reversePPawnBitmap,
2061 &player->reversePPawnBitmap,
2062 &player->reverseSmallSolidBitmap,
2063 pawnPRW_bits, pawnPRW_bits, pawnPRW_bits);
2065 ReadBitmap(player->appData.reversePLanceBitmap,
2066 &player->reversePLanceBitmap,
2067 &player->reverseSmallSolidBitmap,
2068 lancePRW_bits, lancePRW_bits, lancePRW_bits);
2070 ReadBitmap(player->appData.reversePKnightBitmap,
2071 &player->reversePKnightBitmap,
2072 &player->reverseSmallSolidBitmap,
2073 knightPRW_bits, knightPRW_bits, knightPRW_bits);
2075 ReadBitmap(player->appData.reversePSilverBitmap,
2076 &player->reversePSilverBitmap,
2077 &player->reverseBigSolidBitmap,
2078 silverPRW_bits, silverPRW_bits, silverPRW_bits);
2080 ReadBitmap(player->appData.reversePRookBitmap,
2081 &player->reversePRookBitmap,
2082 &player->reverseBigSolidBitmap,
2083 rookPRW_bits, rookPRW_bits, rookPRW_bits);
2085 ReadBitmap(player->appData.reversePBishopBitmap,
2086 &player->reversePBishopBitmap,
2087 &player->reverseBigSolidBitmap,
2088 bishopPRW_bits, bishopPRW_bits, bishopPRW_bits);
2090 ReadBitmap(player->appData.reverseKingBitmap,
2091 &player->reverseKingBitmap,
2092 &player->reverseBigSolidBitmap,
2093 kingRW_bits, kingRW_bits, kingRW_bits);
2095 ReadBitmap(player->appData.normalPawnBitmap,
2096 &player->normalPawnBitmap,
2097 &player->normalSmallSolidBitmap,
2098 pawnW_bits, pawnW_bits, pawnW_bits);
2100 ReadBitmap(player->appData.normalLanceBitmap,
2101 &player->normalLanceBitmap,
2102 &player->normalSmallSolidBitmap,
2103 lanceW_bits, lanceW_bits, lanceW_bits);
2105 ReadBitmap(player->appData.normalKnightBitmap,
2106 &player->normalKnightBitmap,
2107 &player->normalSmallSolidBitmap,
2108 knightW_bits, knightW_bits, knightW_bits);
2110 ReadBitmap(player->appData.normalSilverBitmap,
2111 &player->normalSilverBitmap,
2112 &player->normalBigSolidBitmap,
2113 silverW_bits, silverW_bits, silverW_bits);
2115 ReadBitmap(player->appData.normalGoldBitmap,
2116 &player->normalGoldBitmap,
2117 &player->normalBigSolidBitmap,
2118 goldW_bits, goldW_bits, goldW_bits);
2120 ReadBitmap(player->appData.normalRookBitmap,
2121 &player->normalRookBitmap,
2122 &player->normalBigSolidBitmap,
2123 rookW_bits, rookW_bits, rookW_bits);
2125 ReadBitmap(player->appData.normalBishopBitmap,
2126 &player->normalBishopBitmap,
2127 &player->normalBigSolidBitmap,
2128 bishopW_bits, bishopW_bits, bishopW_bits);
2130 ReadBitmap(player->appData.normalPPawnBitmap,
2131 &player->normalPPawnBitmap,
2132 &player->normalSmallSolidBitmap,
2133 pawnPW_bits, pawnPW_bits, pawnPW_bits);
2135 ReadBitmap(player->appData.normalPLanceBitmap,
2136 &player->normalPLanceBitmap,
2137 &player->normalSmallSolidBitmap,
2138 lancePW_bits, lancePW_bits, lancePW_bits);
2140 ReadBitmap(player->appData.normalPKnightBitmap,
2141 &player->normalPKnightBitmap,
2142 &player->normalSmallSolidBitmap,
2143 knightPW_bits, knightPW_bits, knightPW_bits);
2145 ReadBitmap(player->appData.normalPSilverBitmap,
2146 &player->normalPSilverBitmap,
2147 &player->normalBigSolidBitmap,
2148 silverPW_bits, silverPW_bits, silverPW_bits);
2150 ReadBitmap(player->appData.normalPRookBitmap,
2151 &player->normalPRookBitmap,
2152 &player->normalBigSolidBitmap,
2153 rookPW_bits, rookPW_bits, rookPW_bits);
2155 ReadBitmap(player->appData.normalPBishopBitmap,
2156 &player->normalPBishopBitmap,
2157 &player->normalBigSolidBitmap,
2158 bishopPW_bits, bishopPW_bits, bishopPW_bits);
2160 ReadBitmap(player->appData.normalKingBitmap,
2161 &player->normalKingBitmap,
2162 &player->normalBigSolidBitmap,
2163 kingW_bits, kingW_bits, kingW_bits);
2167 ReadBitmap(player->appData.reverseBigSolidBitmap,
2168 &player->reverseBigSolidBitmap,
2170 bigsolidR_bits, bigsolidR_m_bits, bigsolidR_l_bits);
2172 ReadBitmap(player->appData.reverseSmallSolidBitmap,
2173 &player->reverseSmallSolidBitmap,
2175 smallsolidR_bits, smallsolidR_m_bits, smallsolidR_l_bits);
2177 ReadBitmap(player->appData.normalBigSolidBitmap,
2178 &player->normalBigSolidBitmap,
2180 bigsolid_bits, bigsolid_m_bits, bigsolid_l_bits);
2182 ReadBitmap(player->appData.normalSmallSolidBitmap,
2183 &player->normalSmallSolidBitmap,
2185 smallsolid_bits, smallsolid_m_bits, smallsolid_l_bits);
2187 ReadBitmap(player->appData.reversePawnBitmap,
2188 &player->reversePawnBitmap,
2189 &player->reverseSmallSolidBitmap,
2190 pawnR_bits, pawnR_m_bits, pawnR_l_bits);
2192 ReadBitmap(player->appData.reverseLanceBitmap,
2193 &player->reverseLanceBitmap,
2194 &player->reverseSmallSolidBitmap,
2195 lanceR_bits, lanceR_m_bits, lanceR_l_bits);
2197 ReadBitmap(player->appData.reverseKnightBitmap,
2198 &player->reverseKnightBitmap,
2199 &player->reverseSmallSolidBitmap,
2200 knightR_bits, knightR_m_bits, knightR_l_bits);
2202 ReadBitmap(player->appData.reverseSilverBitmap,
2203 &player->reverseSilverBitmap,
2204 &player->reverseBigSolidBitmap,
2205 silverR_bits, silverR_m_bits, silverR_l_bits);
2207 ReadBitmap(player->appData.reverseGoldBitmap,
2208 &player->reverseGoldBitmap,
2209 &player->reverseBigSolidBitmap,
2210 goldR_bits, goldR_m_bits, goldR_l_bits);
2212 ReadBitmap(player->appData.reverseRookBitmap,
2213 &player->reverseRookBitmap,
2214 &player->reverseBigSolidBitmap,
2215 rookR_bits, rookR_m_bits, rookR_l_bits);
2217 ReadBitmap(player->appData.reverseBishopBitmap,
2218 &player->reverseBishopBitmap,
2219 &player->reverseBigSolidBitmap,
2220 bishopR_bits, bishopR_m_bits, bishopR_l_bits);
2222 ReadBitmap(player->appData.reversePPawnBitmap,
2223 &player->reversePPawnBitmap,
2224 &player->reverseSmallSolidBitmap,
2225 pawnPR_bits, pawnPR_m_bits, pawnPR_l_bits);
2227 ReadBitmap(player->appData.reversePLanceBitmap,
2228 &player->reversePLanceBitmap,
2229 &player->reverseSmallSolidBitmap,
2230 lancePR_bits, lancePR_m_bits, lancePR_l_bits);
2232 ReadBitmap(player->appData.reversePKnightBitmap,
2233 &player->reversePKnightBitmap,
2234 &player->reverseSmallSolidBitmap,
2235 knightPR_bits, knightPR_m_bits, knightPR_l_bits);
2237 ReadBitmap(player->appData.reversePSilverBitmap,
2238 &player->reversePSilverBitmap,
2239 &player->reverseBigSolidBitmap,
2240 silverPR_bits, silverPR_m_bits, silverPR_l_bits);
2242 ReadBitmap(player->appData.reversePRookBitmap,
2243 &player->reversePRookBitmap,
2244 &player->reverseBigSolidBitmap,
2245 rookPR_bits, rookPR_m_bits, rookPR_l_bits);
2247 ReadBitmap(player->appData.reversePBishopBitmap,
2248 &player->reversePBishopBitmap,
2249 &player->reverseBigSolidBitmap,
2250 bishopPR_bits, bishopPR_m_bits, bishopPR_l_bits);
2252 ReadBitmap(player->appData.reverseKingBitmap,
2253 &player->reverseKingBitmap,
2254 &player->reverseBigSolidBitmap,
2255 kingR_bits, kingR_m_bits, kingR_l_bits);
2257 ReadBitmap(player->appData.normalPawnBitmap,
2258 &player->normalPawnBitmap,
2259 &player->normalSmallSolidBitmap,
2260 pawn_bits, pawn_m_bits, pawn_l_bits);
2262 ReadBitmap(player->appData.normalLanceBitmap,
2263 &player->normalLanceBitmap,
2264 &player->normalSmallSolidBitmap,
2265 lance_bits, lance_m_bits, lance_l_bits);
2267 ReadBitmap(player->appData.normalKnightBitmap,
2268 &player->normalKnightBitmap,
2269 &player->normalSmallSolidBitmap,
2270 knight_bits, knight_m_bits, knight_l_bits);
2272 ReadBitmap(player->appData.normalSilverBitmap,
2273 &player->normalSilverBitmap,
2274 &player->normalBigSolidBitmap,
2275 silver_bits, silver_m_bits, silver_l_bits);
2277 ReadBitmap(player->appData.normalGoldBitmap,
2278 &player->normalGoldBitmap,
2279 &player->normalBigSolidBitmap,
2280 gold_bits, gold_m_bits, gold_l_bits);
2282 ReadBitmap(player->appData.normalRookBitmap,
2283 &player->normalRookBitmap,
2284 &player->normalBigSolidBitmap,
2285 rook_bits, rook_m_bits, rook_l_bits);
2287 ReadBitmap(player->appData.normalBishopBitmap,
2288 &player->normalBishopBitmap,
2289 &player->normalBigSolidBitmap,
2290 bishop_bits, bishop_m_bits, bishop_l_bits);
2292 ReadBitmap(player->appData.normalPPawnBitmap,
2293 &player->normalPPawnBitmap,
2294 &player->normalSmallSolidBitmap,
2295 pawnP_bits, pawnP_m_bits, pawnP_l_bits);
2297 ReadBitmap(player->appData.normalPLanceBitmap,
2298 &player->normalPLanceBitmap,
2299 &player->normalSmallSolidBitmap,
2300 lanceP_bits, lanceP_m_bits, lanceP_l_bits);
2302 ReadBitmap(player->appData.normalPKnightBitmap,
2303 &player->normalPKnightBitmap,
2304 &player->normalSmallSolidBitmap,
2305 knightP_bits, knightP_m_bits, knightP_l_bits);
2307 ReadBitmap(player->appData.normalPSilverBitmap,
2308 &player->normalPSilverBitmap,
2309 &player->normalBigSolidBitmap,
2310 silverP_bits, silverP_m_bits, silverP_l_bits);
2312 ReadBitmap(player->appData.normalPRookBitmap,
2313 &player->normalPRookBitmap,
2314 &player->normalBigSolidBitmap,
2315 rookP_bits, rookP_m_bits, rookP_l_bits);
2317 ReadBitmap(player->appData.normalPBishopBitmap,
2318 &player->normalPBishopBitmap,
2319 &player->normalBigSolidBitmap,
2320 bishopP_bits, bishopP_m_bits, bishopP_l_bits);
2322 ReadBitmap(player->appData.normalKingBitmap,
2323 &player->normalKingBitmap,
2324 &player->normalBigSolidBitmap,
2325 king_bits, king_m_bits, king_l_bits);
2329 XSynchronize(player->xDisplay, False); /* Work-around for xlib/xt
2337 ReadBitmapFile(Display *display, Drawable d, char *filename,
2338 unsigned int *width_return,
2339 unsigned int *height_return,
2340 Pixmap *bitmap_return,
2341 int *x_hot_return, int *y_hot_return)
2345 if ((n = XReadBitmapFile(display, d, filename,
2346 width_return, height_return,
2347 bitmap_return, x_hot_return, y_hot_return))
2354 /* transform a 1 plane pixmap to a k plane pixmap */
2355 return BitmapSuccess;
2363 * Create the X pixmap from .xbm file bitmap data. This may
2364 * have to be revised considerably.
2368 ReadBitmap(String name, Pixmap *pm, Pixmap *qm,
2369 unsigned char *small_bits,
2370 unsigned char *medium_bits,
2371 unsigned char *large_bits)
2377 || (ReadBitmapFile(player->xDisplay, player->xBoardWindow, name,
2378 &w, &h, pm, &x_hot, &y_hot) != BitmapSuccess)
2379 || (w != player->squareSize)
2380 || (h != player->squareSize))
2382 unsigned long fg, bg;
2385 depth = DisplayPlanes(player->xDisplay, player->xScreen);
2387 if (player->monoMode)
2389 fg = XBlackPixel(player->xDisplay, player->xScreen);
2390 bg = XWhitePixel(player->xDisplay, player->xScreen);
2392 else if (qm == NULL)
2394 fg = player->appData.oneColor;
2395 bg = player->appData.zeroColor;
2399 fg = (player->black_pixel_is_zero ? 0 : ~0);
2400 bg = (player->black_pixel_is_zero ? ~0 : 0);
2403 switch (player->boardSize)
2406 *pm = XCreatePixmapFromBitmapData(player->xDisplay,
2407 player->xBoardWindow,
2415 *pm = XCreatePixmapFromBitmapData(player->xDisplay,
2416 player->xBoardWindow,
2417 (char *)medium_bits,
2424 *pm = XCreatePixmapFromBitmapData(player->xDisplay,
2425 player->xBoardWindow,
2443 offset = 2 * (player->squareSize + LINE_GAP);
2445 for (i = 0; i < BOARD_SIZE + 1; i++)
2447 player->gridSegments[i].x1 = offset;
2448 player->gridSegments[i + BOARD_SIZE + 1].y1 = 0;
2449 player->gridSegments[i].y1 = player->gridSegments[i].y2
2450 = LINE_GAP / 2 + (i * (player->squareSize + LINE_GAP));
2451 player->gridSegments[i].x2 = LINE_GAP + BOARD_SIZE *
2452 (player->squareSize + LINE_GAP) + offset;
2453 player->gridSegments[i + BOARD_SIZE + 1].x1
2454 = player->gridSegments[i + BOARD_SIZE + 1].x2 = LINE_GAP / 2
2455 + (i * (player->squareSize + LINE_GAP)) + offset;
2456 player->gridSegments[i + BOARD_SIZE + 1].y2
2457 = BOARD_SIZE * (player->squareSize + LINE_GAP);
2465 CreatePieceMenus(void)
2470 ShogiSquare selection;
2472 XtSetArg(args[0], XtNlabel, "Black");
2473 blackPieceMenu = XtCreatePopupShell("menuW", simpleMenuWidgetClass,
2474 localPlayer.boardWidget, args, 1);
2476 for (i = 0; i < PIECE_MENU_SIZE; i++)
2478 String item = pieceMenuStrings[i];
2480 if (strcmp(item, "----") == 0)
2482 entry = XtCreateManagedWidget(item, smeLineObjectClass,
2483 blackPieceMenu, NULL, 0);
2487 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
2488 blackPieceMenu, NULL, 0);
2489 selection = pieceMenuTranslation[0][i];
2490 XtAddCallback(entry, XtNcallback,
2491 (XtCallbackProc)PieceMenuSelect,
2492 (XtPointer)selection);
2494 if (selection == BlackPawn)
2496 XtSetArg(args[0], XtNpopupOnEntry, entry);
2497 XtSetValues(blackPieceMenu, args, 1);
2502 XtSetArg(args[0], XtNlabel, "White");
2503 whitePieceMenu = XtCreatePopupShell("menuB", simpleMenuWidgetClass,
2504 localPlayer.boardWidget, args, 1);
2506 for (i = 0; i < PIECE_MENU_SIZE; i++)
2508 String item = pieceMenuStrings[i];
2510 if (strcmp(item, "----") == 0)
2512 entry = XtCreateManagedWidget(item, smeLineObjectClass,
2513 whitePieceMenu, NULL, 0);
2517 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
2518 whitePieceMenu, NULL, 0);
2519 selection = pieceMenuTranslation[1][i];
2520 XtAddCallback(entry, XtNcallback,
2521 (XtCallbackProc)PieceMenuSelect,
2522 (XtPointer)selection);
2524 if (selection == WhitePawn)
2526 XtSetArg(args[0], XtNpopupOnEntry, entry);
2527 XtSetValues(whitePieceMenu, args, 1);
2532 XtRegisterGrabAction(PieceMenuPopup, True,
2533 (unsigned)(ButtonPressMask|ButtonReleaseMask),
2534 GrabModeAsync, GrabModeAsync);
2541 PieceMenuPopup(Widget w, XEvent *event, String *params, Cardinal *num_params)
2543 if (event->type != ButtonPress)
2546 if (gameMode != EditPosition)
2549 if (((pmFromX = EventToXSquare(event->xbutton.x)) < 1)
2550 || (pmFromX > BOARD_SIZE + 2)
2551 || ((pmFromY = EventToSquare(event->xbutton.y)) < 0))
2553 pmFromX = pmFromY = -1;
2557 if (localPlayer.flipView)
2558 pmFromX = BOARD_SIZE + 3 - pmFromX;
2560 pmFromY = BOARD_SIZE - 1 - pmFromY;
2562 XtPopupSpringLoaded(XtNameToWidget(localPlayer.boardWidget, params[0]));
2569 PieceMenuSelect(Widget w, ShogiSquare piece, char *junk)
2571 if ((pmFromX < 0) || (pmFromY < 0))
2574 if (off_board(pmFromX))
2589 i = pieceToCatchedIndex[piece];
2590 c = (piece >= WhitePawn);
2592 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
2593 XSync(localPlayer.xDisplay, False);
2603 for (pmFromY = 0; pmFromY < BOARD_SIZE; pmFromY++)
2604 for (pmFromX = 0; pmFromX < BOARD_SIZE; pmFromX++)
2605 boards[0][pmFromY][pmFromX] = EmptySquare;
2607 ClearCatches(catches[0]);
2608 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
2611 case BlackPlay: /* not currently on menu */
2615 case WhitePlay: /* not currently on menu */
2620 boards[0][pmFromY][pmFromX] = piece;
2621 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
2625 XSync(localPlayer.xDisplay, False);
2632 SetBlackToPlay(void)
2636 if (gameMode != EditPosition)
2639 whitePlaysFirst = False;
2640 saveCM = currentMove;
2641 currentMove = 0; /* kludge */
2642 DisplayClocks(ReDisplayTimers);
2643 currentMove = saveCM;
2650 SetWhiteToPlay(void)
2654 if (gameMode != EditPosition)
2657 whitePlaysFirst = True;
2658 saveCM = currentMove;
2659 currentMove = 1; /* kludge */
2660 DisplayClocks(ReDisplayTimers);
2661 currentMove = saveCM;
2668 * If the user selects on a border boundary or off the board, return failure.
2669 * Otherwise map the event coordinate to the square.
2673 EventToSquare(int x)
2680 if ((x % (player->squareSize + LINE_GAP)) >= player->squareSize)
2683 x /= (player->squareSize + LINE_GAP);
2685 if (x >= BOARD_SIZE)
2695 EventToXSquare(int x)
2702 if ((x % (player->squareSize + LINE_GAP)) >= player->squareSize)
2705 x /= (player->squareSize + LINE_GAP);
2707 if (x >= BOARD_SIZE + 4)
2717 CharToPiece(int c, int p)
2724 case '.': return EmptySquare;
2725 case 'P': return BlackPPawn;
2726 case 'L': return BlackPLance;
2727 case 'N': return BlackPKnight;
2728 case 'S': return BlackPSilver;
2729 case 'G': return BlackGold;
2730 case 'R': return BlackPRook;
2731 case 'B': return BlackPBishop;
2732 case 'K': return BlackKing;
2733 case 'p': return WhitePPawn;
2734 case 'l': return WhitePLance;
2735 case 'n': return WhitePKnight;
2736 case 's': return WhitePSilver;
2737 case 'g': return WhiteGold;
2738 case 'r': return WhitePRook;
2739 case 'b': return WhitePBishop;
2740 case 'k': return WhiteKing;
2748 case '.': return EmptySquare;
2749 case 'P': return BlackPawn;
2750 case 'L': return BlackLance;
2751 case 'N': return BlackKnight;
2752 case 'S': return BlackSilver;
2753 case 'G': return BlackGold;
2754 case 'R': return BlackRook;
2755 case 'B': return BlackBishop;
2756 case 'K': return BlackKing;
2757 case 'p': return WhitePawn;
2758 case 'l': return WhiteLance;
2759 case 'n': return WhiteKnight;
2760 case 's': return WhiteSilver;
2761 case 'g': return WhiteGold;
2762 case 'r': return WhiteRook;
2763 case 'b': return WhiteBishop;
2764 case 'k': return WhiteKing;
2773 * Convert coordinates to normal algebraic notation.
2774 * promoPiece must be NULLCHAR if not a promotion.
2778 MakeAlg(int fromX, int fromY, int toX, int toY,
2779 char promoPiece, int currentBoardIndex, char *out)
2786 piece = (fromX - 81);
2787 *outp++ = catchedIndexToChar[piece];
2789 *outp++ = '9' - toX;
2790 *outp++ = 'i' - toY;
2792 return (BlackOnMove(forwardMostMove) ? BlackDrop : WhiteDrop);
2796 *outp++ = '9' - fromX;
2797 *outp++ = 'i' - fromY;
2798 *outp++ = '9' - toX;
2799 *outp++ = 'i' - toY;
2800 *outp++ = promoPiece;
2803 if (promoPiece == NULLCHAR)
2809 return (BlackOnMove(forwardMostMove)
2810 ? BlackPromotion : WhitePromotion);
2819 DrawSquare(int row, int column, ShogiSquare piece)
2821 int square_color, x, y, direction, font_ascent, font_descent;
2823 XCharStruct overall;
2824 struct DisplayData *player;
2826 for (player = &localPlayer; True; player = &remotePlayer)
2830 remote = (player == &remotePlayer);
2831 offset = 2 * (player->squareSize + LINE_GAP);
2833 if (player->flipView)
2835 x = LINE_GAP + ((BOARD_SIZE - 1) - column) *
2836 (player->squareSize + LINE_GAP) + offset;
2837 y = LINE_GAP + row * (player->squareSize + LINE_GAP);
2841 x = LINE_GAP + column * (player->squareSize + LINE_GAP) + offset;
2842 y = LINE_GAP + ((BOARD_SIZE - 1) - row) *
2843 (player->squareSize + LINE_GAP);
2846 square_color = (((column + row) % 2) ? LIGHT : DARK);
2848 if (piece == EmptySquare)
2850 if (column < 0 || column >= BOARD_SIZE)
2852 /* empty square off board */
2853 XFillRectangle(player->xDisplay, player->xBoardWindow,
2854 player->squareOffBoardGC,
2855 x, y, player->squareSize,
2856 player->squareSize);
2860 /* empty square on board */
2861 XFillRectangle(player->xDisplay,
2862 player->xBoardWindow,
2866 player->squareSize);
2869 else if (player->monoMode) /* Draw a piece in mono mode. */
2871 XCopyArea(player->xDisplay,
2872 ((((((int)piece) < ((int)WhitePawn)))
2874 ? *pieceToNormal[remote][(int)piece]
2875 : *pieceToReverse[remote][(int)piece]),
2876 player->xBoardWindow,
2878 ? player->squareOffBoardGC /* ??? FIXME? */
2881 player->squareSize, player->squareSize, x, y);
2883 else /* Draw a piece in color mode. */
2885 if ((column < 0) || (column >= BOARD_SIZE)) /* off board */
2887 /* draw piece background */
2889 XCopyPlane(player->xDisplay,
2890 ((((((int)piece) < ((int)WhitePawn)))
2892 ? *pieceToNormalSolid[remote][(int)piece]
2893 : *pieceToReverseSolid[remote][(int)piece]),
2894 player->xBoardWindow,
2897 player->squareSize, player->squareSize, x, y, 1);
2899 /* draw piece bitmap */
2901 XCopyArea(player->xDisplay,
2902 ((((((int)piece) < ((int)WhitePawn)))
2904 ? *pieceToNormal[remote][(int)piece]
2905 : *pieceToReverse[remote][(int)piece]),
2906 player->xBoardWindow,
2907 player->charPieceGC,
2909 player->squareSize, player->squareSize, x, y);
2913 /* draw piece background */
2915 XCopyPlane(player->xDisplay,
2916 ((((((int)piece) < ((int)WhitePawn)))
2918 ? *pieceToNormalSolid[remote][(int)piece]
2919 : *pieceToReverseSolid[remote][(int)piece]),
2920 player->xBoardWindow,
2923 player->squareSize, player->squareSize, x, y, 1);
2925 /* draw piece bitmap */
2927 XCopyArea(player->xDisplay,
2928 ((((((int)piece) < ((int)WhitePawn)))
2930 ? *pieceToNormal[remote][(int)piece]
2931 : *pieceToReverse[remote][(int)piece]),
2932 player->xBoardWindow,
2933 player->charPieceGC,
2935 player->squareSize, player->squareSize, x, y);
2939 string[1] = NULLCHAR;
2941 if (player->showCoords
2942 && (column >= 0) && (column < 9)
2943 && (row == (player->flipView ? 8 : 0)))
2945 string[0] = '9' - column;
2946 XTextExtents(player->coordFontStruct, string, 1, &direction,
2947 &font_ascent, &font_descent, &overall);
2949 if (player->monoMode)
2951 XDrawImageString(player->xDisplay,
2952 player->xBoardWindow, player->coordGC,
2953 x + player->squareSize - overall.width - 2,
2954 y + player->squareSize - font_descent - 1,
2959 XDrawString(player->xDisplay, player->xBoardWindow,
2961 x + player->squareSize - overall.width - 2,
2962 y + player->squareSize - font_descent - 1,
2967 if (player->showCoords
2968 && (row >= 0) && (row < 9)
2969 && (column == (player->flipView ? 8 : 0)))
2971 string[0] = 'i' - row;
2972 XTextExtents(player->coordFontStruct, string, 1, &direction,
2973 &font_ascent, &font_descent, &overall);
2975 if (player->monoMode)
2977 XDrawImageString(player->xDisplay,
2978 player->xBoardWindow, player->coordGC,
2979 x + 2, y + font_ascent + 1, string, 1);
2983 XDrawString(player->xDisplay, player->xBoardWindow,
2985 x + 2, y + font_ascent + 1, string, 1);
2989 if (!updateRemotePlayer || (player == &remotePlayer))
2998 EventProc(Widget widget, XtPointer client_data, XEvent *event)
3000 if (event->type == MappingNotify)
3002 XRefreshKeyboardMapping((XMappingEvent *) event);
3006 if (!XtIsRealized(widget))
3009 if ((event->type == ButtonPress) || (event->type == ButtonRelease))
3011 if (event->xbutton.button != Button1)
3015 switch (event->type)
3018 DrawPosition(widget, event, NULL, NULL);
3030 * event handler for redrawing the board
3034 DrawPosition(Widget w, XEvent *event, String *prms, Cardinal *nprms)
3038 static Board lastBoard;
3039 static Catched lastCatches;
3040 static int lastBoardValid = 0;
3041 static int lastFlipView = 0, lastRemoteFlipView = 1;
3043 if (!player->Iconic)
3045 XtSetArg(args[0], XtNiconic, False);
3046 XtSetValues(localPlayer.shellWidget, args, 1);
3050 * It would be simpler to clear the window with XClearWindow()
3051 * but this causes a very distracting flicker.
3054 if ((w == localPlayer.boardWidget)
3057 && (lastFlipView == localPlayer.flipView)
3058 && (!updateRemotePlayer
3059 || (lastRemoteFlipView == remotePlayer.flipView)))
3061 for (i = 0; i < BOARD_SIZE; i++)
3063 for (j = 0; j < BOARD_SIZE; j++)
3065 if (boards[currentMove][i][j] != lastBoard[i][j])
3066 DrawSquare(i, j, boards[currentMove][i][j]);
3070 for (i = 0; i < 2; i++)
3072 for (j = 0; j < 8; j++)
3074 if (catches[currentMove][i][j] != lastCatches[i][j])
3076 UpdateCatched(i, 0, False, True, currentMove);
3084 XDrawSegments(localPlayer.xDisplay,
3085 localPlayer.xBoardWindow, localPlayer.lineGC,
3086 localPlayer.gridSegments, (BOARD_SIZE + 1) * 2);
3088 if (updateRemotePlayer)
3090 XDrawSegments(remotePlayer.xDisplay,
3091 remotePlayer.xBoardWindow, remotePlayer.lineGC,
3092 remotePlayer.gridSegments, (BOARD_SIZE + 1) * 2);
3095 for (i = 0; i < BOARD_SIZE; i++)
3096 for (j = 0; j < BOARD_SIZE; j++)
3097 DrawSquare(i, j, boards[currentMove][i][j]);
3099 UpdateCatched(0, 0, False, True, currentMove);
3100 UpdateCatched(1, 0, False, True, currentMove);
3103 CopyBoard(lastBoard, boards[currentMove]);
3104 CopyCatches(lastCatches, catches[currentMove]);
3106 lastFlipView = localPlayer.flipView;
3108 if (updateRemotePlayer)
3109 lastRemoteFlipView = remotePlayer.flipView;
3111 XSync(localPlayer.xDisplay, False);
3113 if (updateRemotePlayer)
3114 XSync(remotePlayer.xDisplay, False);
3121 InitPosition(int redraw)
3123 currentMove = forwardMostMove = backwardMostMove = 0;
3124 CopyBoard(boards[0], initialPosition);
3125 ClearCatches(catches[0]);
3128 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
3135 CopyBoard(Board to, Board from)
3139 for (i = 0; i < BOARD_SIZE; i++)
3140 for (j = 0; j < BOARD_SIZE; j++)
3141 to[i][j] = from[i][j];
3148 CopyCatches(Catched to, Catched from)
3152 for (i = 0; i < 2; i++)
3153 for (j = 0; j < 8; j++)
3154 to[i][j] = from[i][j];
3161 SendCurrentBoard(FILE *fp)
3163 SendBoard(fp, boards[currentMove], catches[currentMove]);
3170 SendBoard(FILE *fp, Board board, Catched catches)
3172 char message[MSG_SIZ];
3176 SendToProgram("edit\n", fp);
3177 SendToProgram("#\n", fp);
3179 for (i = BOARD_SIZE - 1; i >= 0; i--)
3183 for (j = 0; j < BOARD_SIZE; j++, bp++)
3185 if (((int) *bp) < (int)WhitePawn)
3187 sprintf(message, "%c%c%c%s\n",
3188 pieceToChar[(int) *bp],
3190 (pieceIsPromoted[(int) *bp] ? "+" : ""));
3191 SendToProgram(message, fp);
3196 for (i = 0; i <= 7; i++)
3200 for (n = catches[0][i]; n > 0; n--)
3202 sprintf(message, "%c*\n",
3203 catchedIndexToChar[i]);
3204 SendToProgram(message, fp);
3208 SendToProgram("c\n", fp);
3210 for (i = BOARD_SIZE - 1; i >= 0; i--)
3214 for (j = 0; j < BOARD_SIZE; j++, bp++)
3216 if ((((int) *bp) != ((int)EmptySquare))
3217 && (((int) *bp) >= ((int)WhitePawn)))
3219 sprintf(message, "%c%c%c%s\n",
3220 pieceToChar[((int) *bp) - ((int)WhitePawn)],
3222 (pieceIsPromoted[(int) *bp] ? "+" : ""));
3223 SendToProgram(message, fp);
3228 for (i = 0; i <= 7; i++)
3232 for (n = catches[1][i]; n > 0; n--)
3234 sprintf(message, "%c*\n",
3235 catchedIndexToChar[i]);
3236 SendToProgram(message, fp);
3240 SendToProgram(".\n", fp);
3247 PromotionPossible(int fromY, int toY, ShogiSquare piece)
3249 if (((int)piece) < ((int)WhitePawn))
3251 if ((fromY < 6) && (toY < 6))
3256 if ((fromY > 2) && (toY > 2))
3260 return piecePromotable[(int)piece];
3268 ShowCount(int row, int column, int n)
3270 int offset = 2 * (player->squareSize + LINE_GAP);
3271 int x, y, direction, font_ascent, font_descent;
3273 XCharStruct overall;
3274 struct DisplayData *player;
3276 DrawSquare(row, column, EmptySquare);
3281 for (player = &localPlayer; True; player = &remotePlayer)
3283 if (player->flipView)
3285 x = LINE_GAP + ((BOARD_SIZE - 1) - column) *
3286 (player->squareSize + LINE_GAP) + offset;
3287 y = LINE_GAP + row * (player->squareSize + LINE_GAP);
3291 x = LINE_GAP + column * (player->squareSize + LINE_GAP) + offset;
3292 y = LINE_GAP + ((BOARD_SIZE - 1) - row) *
3293 (player->squareSize + LINE_GAP);
3296 x -= player->squareSize / 2;
3298 string[1] = NULLCHAR;
3303 string[0] = '0' + n;
3305 XTextExtents(player->coordFontStruct, string, 1, &direction,
3306 &font_ascent, &font_descent, &overall);
3308 if (player->monoMode)
3310 XDrawImageString(player->xDisplay, player->xBoardWindow,
3312 x + player->squareSize - overall.width - 2,
3313 y + player->squareSize - font_descent - 1,
3318 XDrawString(player->xDisplay, player->xBoardWindow,
3320 x + player->squareSize - overall.width - 2,
3321 y + player->squareSize - font_descent - 1,
3325 if (!updateRemotePlayer || (player == &remotePlayer))
3334 UpdateCatched(int Color, int Figure, int Drop, int DropAll, int currentMove)
3339 /* Determine first row and column. */
3355 n = catches[currentMove][Color][Figure];
3357 /* Update the display for captured pieces
3358 if no piece of the dropped type is there (Drop && n==1)
3359 or if a piece type is removed (NOT Drop && n==0).
3360 In the other cases update only the count. */
3362 if (DropAll || (Drop && (n == 1)) || (!Drop && (n == 0)))
3364 /* show all captured pieces */
3367 for (F = pawn; F <= king; F++)
3371 if ((c = catches[currentMove][Color][F]) > 0)
3374 DrawSquare(y, x, catchedIndexToPiece[Color][F]);
3375 ShowCount(y, (Color ? (x - 1) : (x + 1)), c);
3388 DrawSquare(y, x, EmptySquare);
3389 ShowCount(y, (Color ? (x - 1) : (x + 1)), 0);
3399 /* remove one line! */
3400 DrawSquare(y, x, EmptySquare);
3401 ShowCount(y, (Color ? (x - 1) : (x + 1)), 0);
3406 /* show the actual count */
3407 for (F = pawn; F <= Figure - 1; F++)
3409 if (catches[currentMove][Color][F] > 0)
3418 ShowCount(y, (Color ? (x - 1) : (x + 1)), n);
3427 static int BlinkCount = 0;
3428 static int BlinkRow, BlinkCol;
3429 static ShogiSquare BlinkPiece;
3433 BlinkSquareProc(void)
3438 DrawSquare (BlinkRow, BlinkCol,
3439 ((BlinkCount & 1) ? EmptySquare : BlinkPiece));
3444 = XtAppAddTimeOut(appContext,
3446 (XtTimerCallbackProc)BlinkSquareProc,
3460 BlinkSquare(int row, int col, ShogiSquare piece)
3462 BlinkCount = 2 * BLINK_COUNT + 1;
3470 #endif /* BLINK_COUNT */
3476 PieceOfCatched(int color, int x, int y, int currentMove)
3493 for (F = pawn, n = 0; F <= king; F++)
3495 if (catches[currentMove][color][F] > 0)
3511 * event handler for parsing user moves
3515 HandleUserMove(Widget w, XEvent *event)
3517 ShogiMove move_type;
3518 ShogiSquare from_piece;
3519 int to_x, to_y, fromRemotePlayer;
3521 if (updateRemotePlayer)
3523 if (((w != localPlayer.boardWidget)
3524 && (w != remotePlayer.boardWidget))
3525 || (matchMode != MatchFalse))
3530 fromRemotePlayer = (w == remotePlayer.boardWidget);
3534 if ((w != localPlayer.boardWidget) || (matchMode != MatchFalse))
3537 fromRemotePlayer = False;
3540 player = (fromRemotePlayer ? &remotePlayer : &localPlayer);
3542 if (player->promotionUp)
3544 XtPopdown(player->promotionShell);
3545 XtDestroyWidget(player->promotionShell);
3546 player->promotionUp = False;
3553 case PlayFromGameFile:
3554 case TwoMachinesPlay:
3557 case MachinePlaysBlack:
3558 if (BlackOnMove(forwardMostMove))
3560 DisplayMessage("It is not your turn", fromRemotePlayer);
3566 case MachinePlaysWhite:
3567 if (!BlackOnMove(forwardMostMove))
3569 DisplayMessage("It is not your turn", fromRemotePlayer);
3576 forwardMostMove = currentMove;
3583 if (currentMove != forwardMostMove)
3585 DisplayMessage("Displayed position is not current",
3590 switch (event->type)
3593 if ((fromX >= 0) || (fromY >= 0))
3596 if (((fromX = EventToXSquare(event->xbutton.x)) < 1)
3597 || (fromX > BOARD_SIZE + 2)
3598 || ((fromY = EventToSquare(event->xbutton.y)) < 0))
3604 if (player->flipView)
3605 fromX = BOARD_SIZE + 3 - fromX;
3607 fromY = BOARD_SIZE - 1 - fromY;
3612 if ((fromX < 0) || (fromY < 0))
3615 if (((to_x = EventToXSquare(event->xbutton.x)) < 1)
3616 || (to_x > BOARD_SIZE + 2)
3617 || ((to_y = EventToSquare(event->xbutton.y)) < 0))
3619 if (gameMode == EditPosition && !off_board(fromX))
3622 boards[0][fromY][fromX] = EmptySquare;
3623 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
3624 XSync(localPlayer.xDisplay, False);
3626 if (updateRemotePlayer)
3627 XSync(remotePlayer.xDisplay, False);
3634 if (player->flipView)
3635 to_x = BOARD_SIZE + 3 - to_x;
3637 to_y = BOARD_SIZE - 1 - to_y;
3639 if ((fromX == to_x) && (fromY == to_y))
3645 if (gameMode == EditPosition)
3649 if (off_board(fromX))
3651 /* Remove a catched piece */
3653 c = ((fromX < 5) ^ player->flipView);
3654 i = PieceOfCatched(c, fromX, fromY, 0);
3663 piece = catchedIndexToPiece[c][i];
3669 /* remove piece from board field */
3671 piece = boards[0][fromY][fromX];
3672 boards[0][fromY][fromX] = EmptySquare;
3675 if (!off_board(to_x))
3677 /* drop piece to board field */
3678 ShogiSquare catched_piece;
3680 catched_piece = boards[0][to_y][to_x];
3682 if (catched_piece != EmptySquare)
3684 /* put piece to catched pieces */
3685 int i = pieceToCatchedIndex[catched_piece];
3686 int c = (catched_piece < WhitePawn);
3690 /* place moved piece */
3691 boards[0][to_y][to_x] = piece;
3695 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
3696 XSync(localPlayer.xDisplay, False);
3698 if (updateRemotePlayer)
3699 XSync(remotePlayer.xDisplay, False);
3704 if (off_board(fromX))
3706 int c = (BlackOnMove(forwardMostMove) ? 0 : 1);
3707 int piece = PieceOfCatched(c, fromX, fromY, currentMove);
3709 if (piece == no_piece)
3716 if (updateRemotePlayer
3717 && (BlackOnMove(forwardMostMove) == fromRemotePlayer))
3719 DisplayMessage("Do not try to drop your opponent's pieces!",
3725 fromX = fromY = piece + 81;
3727 move_type = (BlackOnMove(forwardMostMove)
3728 ? BlackDrop : WhiteDrop);
3729 MakeMove(&move_type, fromX, fromY, to_x, to_y);
3732 if (updateRemotePlayer)
3733 BlinkSquare(to_y, to_x, boards[currentMove][to_y][to_x]);
3736 FinishUserMove(move_type, to_x, to_y);
3740 else if (off_board(to_x))
3749 from_piece = boards[currentMove][fromY][fromX];
3751 if ((from_piece != EmptySquare)
3752 && updateRemotePlayer
3753 && ((from_piece < WhitePawn) == fromRemotePlayer))
3755 DisplayMessage("Do not try to move your opponent's pieces!",
3761 if (PromotionPossible(fromY, to_y, from_piece))
3763 PromotionPopUp(from_piece, to_x, to_y, fromRemotePlayer);
3767 move_type = NormalMove;
3768 MakeMove(&move_type, fromX, fromY, to_x, to_y);
3771 if (updateRemotePlayer)
3772 BlinkSquare(to_y, to_x, boards[currentMove][to_y][to_x]);
3775 FinishUserMove(move_type, to_x, to_y);
3785 FinishUserMove(ShogiMove move_type, int to_x, int to_y)
3787 char user_move[MSG_SIZ];
3789 /* output move for gnushogi */
3792 case BlackPromotion:
3793 case WhitePromotion:
3794 sprintf(user_move, "%c%c%c%c+\n",
3795 '9' - fromX, 'i' - fromY, '9' - to_x, 'i' - to_y);
3800 sprintf(user_move, "%c*%c%c\n",
3801 catchedIndexToChar[fromX - 81], '9' - to_x, 'i' - to_y);
3805 sprintf(user_move, "%c%c%c%c\n",
3806 '9' - fromX, 'i' - fromY, '9' - to_x, 'i' - to_y);
3810 fprintf(stderr, "%s: internal error; bad move_type\n",
3811 (char *)programName);
3815 Attention(firstProgramPID);
3818 SendTimeRemaining(toFirstProgFP);
3820 SendToProgram(user_move, toFirstProgFP);
3821 strcpy(moveList[currentMove - 1], user_move);
3825 if (gameMode == PauseGame)
3827 /* a user move restarts a paused game*/
3828 PauseProc(NULL, NULL, NULL, NULL);
3836 case BeginningOfGame:
3837 if (localPlayer.appData.noShogiProgram)
3838 lastGameMode = gameMode = ForceMoves;
3840 lastGameMode = gameMode = MachinePlaysWhite;
3845 case MachinePlaysWhite:
3846 case MachinePlaysBlack:
3855 /* Simple parser for moves from gnushogi. */
3857 ParseMachineMove(char *machine_move, ShogiMove *move_type,
3858 int *from_x, int *from_y, int *to_x, int *to_y)
3860 #define no_digit(c) (c < '0' || c > '9')
3862 if (no_digit(machine_move[0]))
3864 switch (machine_move[0])
3903 *to_x = '9' - machine_move[2];
3904 *to_y = 'i' - machine_move[3];
3908 *from_x = '9' - machine_move[0] ;
3909 *from_y = 'i' - machine_move[1];
3910 *to_x = '9' - machine_move[2];
3911 *to_y = 'i' - machine_move[3];
3913 switch (machine_move[4])
3916 *move_type = (BlackOnMove(forwardMostMove)
3917 ? BlackPromotion : WhitePromotion);
3921 *move_type = NormalMove;
3932 SkipString(char **mpr)
3934 while (**mpr == ' ')
3937 while ((**mpr != ' ') && (**mpr != NULLCHAR) && (**mpr != '\n'))
3940 while (**mpr == ' ')
3948 HandleMachineMove(char *message, FILE *fp)
3950 char machine_move[MSG_SIZ], buf1[MSG_SIZ], buf2[MSG_SIZ];
3951 int from_x, from_y, to_x, to_y;
3952 ShogiMove move_type;
3956 long time_remaining;
3959 maybeThinking = False;
3961 if (strncmp(message, "warning:", 8) == 0)
3963 DisplayMessage(message, False);
3965 if (updateRemotePlayer)
3966 DisplayMessage(message, True);
3972 * If shogi program startup fails, exit with an error message.
3973 * Attempts to recover here are futile.
3976 if ((strstr(message, "unknown host") != NULL)
3977 || (strstr(message, "No remote directory") != NULL)
3978 || (strstr(message, "not found") != NULL)
3979 || (strstr(message, "No such file") != NULL)
3980 || (strstr(message, "Permission denied") != NULL))
3983 "%s: failed to start shogi program %s on %s: %s\n",
3985 ((fp == fromFirstProgFP)
3986 ? localPlayer.appData.firstShogiProgram
3987 : localPlayer.appData.secondShogiProgram),
3988 ((fp == fromFirstProgFP)
3989 ? localPlayer.appData.firstHost
3990 : localPlayer.appData.secondHost),
3992 ShutdownShogiPrograms(message);
3997 * If the move is illegal, cancel it and redraw the board.
4000 if (strncmp(message, "Illegal move", 12) == 0)
4002 if (fp == fromFirstProgFP && firstSendTime == 2)
4004 /* First program doesn't have the "time" command */
4008 else if (fp == fromSecondProgFP && secondSendTime == 2)
4010 /* Second program doesn't have the "time" command */
4015 if (forwardMostMove <= backwardMostMove)
4018 if (gameMode == PauseGame)
4019 PauseProc(NULL, NULL, NULL, NULL);
4021 if (gameMode == PlayFromGameFile)
4023 /* Stop reading this game file */
4024 gameMode = ForceMoves;
4028 currentMove = --forwardMostMove;
4030 if ((gameMode == PlayFromGameFile)
4031 || (gameMode == ForceMoves))
4032 DisplayClocks(ReDisplayTimers);
4034 DisplayClocks(SwitchTimers);
4036 sprintf(buf1, "Illegal move: %s", parseList[currentMove]);
4037 DisplayMessage(buf1, False);
4039 if (updateRemotePlayer)
4040 DisplayMessage(buf1, True);
4044 * Disable blinking of the target square.
4049 /* If BlinkCount is even, the piece is currently displayed. */
4050 if (!(BlinkCount & 1))
4051 DrawSquare (BlinkRow, BlinkCol, EmptySquare);
4053 /* BlinkCount = 0 will force the next blink timeout
4059 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
4061 XSync(localPlayer.xDisplay, False);
4063 if (updateRemotePlayer)
4064 XSync(remotePlayer.xDisplay, False);
4069 if (strstr(message, "GNU Shogi") != NULL)
4071 at_least_gnushogi_1_2p03 = True;
4075 if (strncmp(message, "Hint:", 5) == 0)
4078 sscanf(message, "Hint: %s", machine_move);
4079 ParseMachineMove(machine_move, &move_type,
4080 &from_x, &from_y, &to_x, &to_y);
4082 if (move_type == WhitePromotion || move_type == BlackPromotion)
4085 promoPiece = NULLCHAR;
4087 move_type = MakeAlg(from_x, from_y, to_x, to_y, promoPiece,
4089 sprintf(buf2, "Hint: %s", buf1);
4090 DisplayMessage(buf2, False);
4092 if (updateRemotePlayer)
4093 DisplayMessage(buf2, True);
4098 if (strncmp(message, "Clocks:", 7) == 0)
4100 sscanf(message, "Clocks: %ld %ld",
4101 &blackTimeRemaining, &whiteTimeRemaining);
4102 DisplayClocks(ReDisplayTimers);
4111 if (strncmp(message, "Black", 5) == 0)
4113 ShutdownShogiPrograms("Black wins");
4116 else if (strncmp(message, "White", 5) == 0)
4118 ShutdownShogiPrograms("White wins");
4121 else if (strncmp(message, "Repetition", 10) == 0)
4123 ShutdownShogiPrograms("Repetition");
4126 else if (strncmp(message, "opponent mates!", 15) == 0)
4128 switch ((gameMode == PauseGame) ? pausePreviousMode : gameMode)
4130 case MachinePlaysWhite:
4131 ShutdownShogiPrograms("Black wins");
4134 case MachinePlaysBlack:
4135 ShutdownShogiPrograms("White wins");
4138 case TwoMachinesPlay:
4139 ShutdownShogiPrograms((fp == fromFirstProgFP)
4140 ? "Black wins" : "White wins");
4150 else if (strncmp(message, "computer mates!", 15) == 0)
4152 switch ((gameMode == PauseGame) ? pausePreviousMode : gameMode)
4154 case MachinePlaysWhite:
4155 ShutdownShogiPrograms("White wins");
4158 case MachinePlaysBlack:
4159 ShutdownShogiPrograms("Black wins");
4162 case TwoMachinesPlay:
4163 ShutdownShogiPrograms((fp == fromFirstProgFP)
4164 ? "White wins" : "Black wins");
4174 else if (strncmp(message, "Draw", 4) == 0)
4176 ShutdownShogiPrograms("Draw");
4181 * normal machine reply move
4183 maybeThinking = True;
4185 if (strstr(message, "...") != NULL)
4187 sscanf(message, "%s %s %s", buf1, buf2, machine_move);
4191 SkipString(&mpr); /* skip move number */
4192 SkipString(&mpr); /* skip ... */
4193 SkipString(&mpr); /* skip move */
4195 if ((gameMode != TwoMachinesPlay) && (gameMode != ForceMoves)
4196 && ((*mpr == '-') || ((*mpr >= '0') && (*mpr <= '9'))))
4198 /* synchronize with shogi program clock */
4199 sscanf(mpr, "%ld", &time_remaining);
4203 printf("from '%s' synchronize %s clock %ld\n",
4205 (BlackOnMove(forwardMostMove)
4211 if (BlackOnMove(forwardMostMove))
4212 blackTimeRemaining = time_remaining;
4214 whiteTimeRemaining = time_remaining;
4218 if (machine_move[0] == NULLCHAR)
4226 if (strstr(message, "time") == NULL)
4228 /* remaining time will be determined from move */
4229 SkipString(&mpr); /* skip move number */
4230 SkipString(&mpr); /* skip move */
4233 if ((gameMode != TwoMachinesPlay) && (gameMode != ForceMoves)
4234 && ((*mpr == '-') || ((*mpr >= '0') && (*mpr <= '9'))))
4236 /* synchronize with shogi program clock */
4237 sscanf(mpr, "%ld", &time_remaining);
4241 printf("from '%s' synchronize %s clock %ld\n",
4243 ((!BlackOnMove(forwardMostMove))
4244 ? "Black's" : "White's"),
4248 if (!BlackOnMove(forwardMostMove))
4249 blackTimeRemaining = time_remaining;
4251 whiteTimeRemaining = time_remaining;
4257 printf("ignore noise: '%s'\n", message);
4259 return; /* ignore noise */
4262 strcpy(moveList[forwardMostMove], machine_move);
4264 ParseMachineMove(machine_move, &move_type, &from_x, &from_y,
4267 if (gameMode != PauseGame)
4268 currentMove = forwardMostMove; /* display latest move */
4270 MakeMove(&move_type, from_x, from_y, to_x, to_y);
4273 if (gameMode != TwoMachinesPlay)
4274 BlinkSquare(to_y, to_x, boards[currentMove][to_y][to_x]);
4277 if ((gameMode != PauseGame) && localPlayer.appData.ringBellAfterMoves)
4278 putc(BELLCHAR, stderr);
4280 if ((gameMode == TwoMachinesPlay)
4281 || ((gameMode == PauseGame)
4282 && (pausePreviousMode == TwoMachinesPlay)))
4284 strcat(machine_move, "\n");
4286 if (BlackOnMove(forwardMostMove))
4288 Attention(secondProgramPID);
4291 SendTimeRemaining(toSecondProgFP);
4293 SendToProgram(machine_move, toSecondProgFP);
4298 SendToProgram(localPlayer.appData.blackString,
4304 Attention(firstProgramPID);
4307 SendTimeRemaining(toFirstProgFP);
4309 SendToProgram(machine_move, toFirstProgFP);
4314 SendToProgram(localPlayer.appData.blackString,
4329 if (!ReadGameFileProc())
4332 if (matchMode == MatchOpening)
4336 = XtAppAddTimeOut(appContext,
4337 (int)(1000 * localPlayer.appData.timeDelay),
4338 (XtTimerCallbackProc) ReadGameFile, NULL);
4346 * FIXME: there is a naming inconsistency: here ReadGameFileProc() is
4347 * called by ReadGameFile() while in other places XXXProc() calls XXX().
4351 ReadGameFileProc(void)
4353 ShogiMove move_type;
4354 char move[MSG_SIZ], buf[MSG_SIZ];
4356 if (gameFileFP == NULL)
4359 if (gameMode == PauseGame)
4362 if (gameMode != PlayFromGameFile)
4371 XtPopdown(commentShell);
4372 XtDestroyWidget(commentShell);
4376 fgets(move, MSG_SIZ, gameFileFP);
4377 move[strlen(move) - 1] = NULLCHAR;
4378 sprintf(buf, "# %s game file", programName);
4380 if (strncmp(move, buf, strlen(buf)))
4382 strcat(move, ": no xshogi game file");
4383 DisplayMessage(move, False);
4392 move_type = (ShogiMove)0;
4394 lastGameMode = gameMode;
4395 gameMode = ForceMoves;
4398 if (!loaded_game_finished)
4399 DisplayMessage("End of game file", False);
4401 if (readGameXID != 0)
4403 XtRemoveTimeOut(readGameXID);
4417 * Apply a move to the given board. Oddity: move_type is ignored on input
4418 * unless the move is seen to be a pawn promotion, in which case move_type
4419 * tells us what to promote to.
4423 ApplyMove(ShogiMove *move_type, int from_x, int from_y,
4424 int to_x, int to_y, int currentMove)
4426 ShogiSquare piece, cpiece;
4433 c = (BlackOnMove(currentMove) ? 1 : 0);
4434 cpiece = catchedIndexToPiece[c][i];
4435 boards[currentMove][to_y][to_x] = cpiece;
4436 catches[currentMove][c][i]--;
4438 else if (PromotionPossible(from_y, to_y,
4439 piece = boards[currentMove][from_y][from_x]))
4441 cpiece = boards[currentMove][to_y][to_x];
4443 if (cpiece != EmptySquare)
4445 i = pieceToCatchedIndex[cpiece];
4446 c = (cpiece < WhitePawn);
4447 catches[currentMove][c][i]++;
4450 if (*move_type == NormalMove)
4452 boards[currentMove][to_y][to_x] = piece;
4456 boards[currentMove][to_y][to_x] = piece = pieceToPromoted[piece];
4460 boards[currentMove][from_y][from_x] = EmptySquare;
4464 ShogiSquare piece = boards[currentMove][to_y][to_x];
4466 if (piece != EmptySquare)
4468 i = pieceToCatchedIndex[piece];
4469 c = (piece < WhitePawn);
4470 catches[currentMove][c][i]++;
4473 *move_type = NormalMove;
4474 boards[currentMove][to_y][to_x] =
4475 boards[currentMove][from_y][from_x];
4476 boards[currentMove][from_y][from_x] = EmptySquare;
4484 * MakeMove() displays moves. If they are illegal, GNU shogi will detect
4485 * this and send an Illegal move message. XShogi will then retract the move.
4486 * The clockMode False case is tricky because it displays the player on move.
4490 MakeMove(ShogiMove *move_type, int from_x, int from_y, int to_x, int to_y)
4492 char message[MSG_SIZ], movestr[MSG_SIZ];
4493 char promoPiece = NULLCHAR;
4497 CopyBoard(boards[forwardMostMove], boards[forwardMostMove - 1]);
4498 CopyCatches(catches[forwardMostMove], catches[forwardMostMove - 1]);
4500 ApplyMove(move_type, from_x, from_y, to_x, to_y, forwardMostMove);
4502 endMessage[0] = NULLCHAR;
4504 timeRemaining[0][forwardMostMove] = blackTimeRemaining;
4505 timeRemaining[1][forwardMostMove] = whiteTimeRemaining;
4507 if ((gameMode == PauseGame) && (pausePreviousMode != PlayFromGameFile))
4510 currentMove = forwardMostMove;
4512 if (gameMode == PlayFromGameFile)
4514 sprintf(message, "%d. %s%s",
4515 ((currentMove + 1) / 2),
4516 (BlackOnMove(currentMove) ? "... " : ""),
4518 strcpy(parseList[currentMove - 1], currentMoveString);
4522 if ((*move_type == WhitePromotion) || (*move_type == BlackPromotion))
4525 promoPiece = NULLCHAR;
4527 MakeAlg(from_x, from_y, to_x, to_y, promoPiece,
4528 currentMove - 1, movestr);
4529 sprintf(message, "%d. %s%s",
4530 ((currentMove + 1) / 2),
4531 (BlackOnMove(currentMove) ? "... " : ""),
4533 strcpy(parseList[currentMove - 1], movestr);
4536 DisplayMessage(message, False);
4538 if ((gameMode == PlayFromGameFile) || (gameMode == ForceMoves)
4539 || ((gameMode == PauseGame)
4540 && (pausePreviousMode == PlayFromGameFile)))
4542 DisplayClocks(ReDisplayTimers);
4546 DisplayClocks(SwitchTimers);
4549 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
4551 XSync(localPlayer.xDisplay, False);
4553 if (updateRemotePlayer)
4555 DisplayMessage(message, True);
4556 XSync(remotePlayer.xDisplay, False);
4564 InitShogiProgram(char *host_name, char *program_name, int *pid,
4565 FILE **to, FILE **from, XtIntervalId *xid, int *sendTime)
4569 int to_prog[2], from_prog[2];
4570 FILE *from_fp, *to_fp;
4574 if (localPlayer.appData.noShogiProgram)
4577 signal(SIGPIPE, CatchPipeSignal);
4581 if ((*pid = fork()) == 0)
4583 signal(SIGPIPE, CatchPipeSignal);
4585 dup2(to_prog[0], 0);
4586 dup2(from_prog[1], 1);
4589 close(from_prog[0]);
4590 close(from_prog[1]);
4591 dup2(1, fileno(stderr)); /* force stderr to the pipe */
4593 if (localPlayer.appData.searchTime != NULL)
4595 sprintf(arg_buf, "%d", searchTime);
4597 arg2 = (char *)NULL;
4599 else if (localPlayer.appData.searchDepth > 0)
4601 sprintf(arg_buf, "%d", localPlayer.appData.searchDepth);
4607 sprintf(arg_buf, "%d", localPlayer.appData.movesPerSession);
4609 arg2 = localPlayer.appData.timeControl;
4612 if (strcmp(host_name, "localhost") == 0)
4614 execlp(program_name, program_name, arg1, arg2,
4619 execlp(localPlayer.appData.remoteShell,
4620 localPlayer.appData.remoteShell,
4621 host_name, program_name, arg1, arg2,
4625 perror(program_name);
4630 close(from_prog[1]);
4632 *from = from_fp = fdopen(from_prog[0], "r");
4633 *to = to_fp = fdopen(to_prog[1], "w");
4634 setbuf(from_fp, NULL);
4635 setbuf(to_fp, NULL);
4637 ReceiveFromProgram(from_fp, &dummy_source, &dummy_id); /* "GNU Shogi"*/
4639 if (!at_least_gnushogi_1_2p03)
4641 fprintf(stderr, "you must have at least gnushogi-1.2p03\n");
4648 *xid = XtAppAddInput(appContext, fileno(from_fp),
4649 (XtPointer)XtInputReadMask,
4650 (XtInputCallbackProc)ReceiveFromProgram,
4651 (XtPointer)from_fp);
4653 SendToProgram(localPlayer.appData.initString, *to);
4655 if (localPlayer.appData.gameIn)
4656 SendToProgram("gamein\n", *to);
4658 SendSearchDepth(*to);
4662 /* Does program have "time" command? */
4665 sprintf(buf, "time %ld\n", blackTimeRemaining / 10);
4666 SendToProgram(buf, to_fp);
4667 ReceiveFromProgram(from_fp, &dummy_source, &dummy_id);
4671 *sendTime = 1; /* yes! */
4672 sprintf(buf, "otime %ld\n", whiteTimeRemaining / 10);
4673 SendToProgram(buf, to_fp);
4674 ReceiveFromProgram(from_fp, &dummy_source, &dummy_id);
4683 ShutdownShogiPrograms(char *why)
4685 lastGameMode = gameMode;
4686 gameMode = EndOfGame;
4688 CopyBoard(boards[currentMove + 1], boards[currentMove]);
4689 CopyCatches(catches[currentMove + 1], catches[currentMove]);
4690 strncpy(parseList[currentMove], why, MOVE_LEN);
4691 parseList[currentMove][MOVE_LEN - 1] = NULLCHAR;
4693 DisplayMessage(why, False);
4695 if (readGameXID != 0)
4696 XtRemoveTimeOut(readGameXID);
4700 if (firstProgramPID != 0)
4702 fclose(fromFirstProgFP);
4703 fclose(toFirstProgFP);
4704 fromFirstProgFP = toFirstProgFP = NULL;
4706 if (kill(firstProgramPID, SIGTERM) == 0)
4710 firstProgramPID = 0;
4712 if (firstProgramXID != 0)
4713 XtRemoveInput(firstProgramXID);
4715 firstProgramXID = 0;
4717 if (secondProgramPID != 0)
4719 fclose(fromSecondProgFP);
4720 fclose(toSecondProgFP);
4721 fromSecondProgFP = toSecondProgFP = NULL;
4723 if (kill(secondProgramPID, SIGTERM) == 0)
4727 secondProgramPID = 0;
4729 if (secondProgramXID != 0)
4730 XtRemoveInput(secondProgramXID);
4732 secondProgramXID = 0;
4734 DisplayClocks(StopTimers);
4736 if (matchMode != MatchFalse)
4738 if (localPlayer.appData.saveGameFile[0] != NULLCHAR)
4739 SaveGame(localPlayer.appData.saveGameFile);
4749 CommentPopUp(char *label)
4753 Dimension bw_width, pw_width;
4757 XtPopdown(commentShell);
4758 XtDestroyWidget(commentShell);
4762 DisplayMessage("Comment", False);
4764 XtSetArg(args[0], XtNwidth, &bw_width);
4765 XtGetValues(localPlayer.formWidget, args, 1);
4767 XtSetArg(args[0], XtNresizable, True);
4768 XtSetArg(args[1], XtNwidth, bw_width - 8);
4770 commentShell = XtCreatePopupShell("Comment",
4771 transientShellWidgetClass,
4772 localPlayer.commandsWidget, args, 2);
4774 XtSetArg(args[0], XtNlabel, label);
4776 (void)XtCreateManagedWidget("commentLabel", labelWidgetClass,
4777 commentShell, args, 1);
4779 XtRealizeWidget(commentShell);
4781 XtSetArg(args[0], XtNwidth, &pw_width);
4782 XtGetValues(commentShell, args, 1);
4784 XtTranslateCoords(localPlayer.shellWidget,
4785 (bw_width - pw_width) / 2, -50, &x, &y);
4787 XtSetArg(args[0], XtNx, x);
4788 XtSetArg(args[1], XtNy, y);
4789 XtSetValues(commentShell, args, 2);
4791 XtPopup(commentShell, XtGrabNone);
4799 FileNamePopUp(char *label, Boolean (*proc) (char *))
4802 Widget popup, dialog;
4804 Dimension bw_width, pw_width;
4808 XtSetArg(args[0], XtNwidth, &bw_width);
4809 XtGetValues(localPlayer.boardWidget, args, 1);
4811 XtSetArg(args[0], XtNresizable, True);
4812 XtSetArg(args[1], XtNwidth, DIALOG_SIZE);
4814 popup = XtCreatePopupShell("File Name Prompt",
4815 transientShellWidgetClass,
4816 localPlayer.commandsWidget, args, 2);
4818 XtSetArg(args[0], XtNlabel, label);
4819 XtSetArg(args[1], XtNvalue, "");
4821 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
4824 XawDialogAddButton(dialog, "ok", FileNameCallback, (XtPointer) dialog);
4825 XawDialogAddButton(dialog, "cancel", FileNameCallback,
4826 (XtPointer) dialog);
4828 XtRealizeWidget(popup);
4830 XtSetArg(args[0], XtNwidth, &pw_width);
4831 XtGetValues(popup, args, 1);
4833 XtTranslateCoords(localPlayer.boardWidget,
4834 (bw_width - pw_width) / 2, 10, &x, &y);
4836 XtSetArg(args[0], XtNx, x);
4837 XtSetArg(args[1], XtNy, y);
4838 XtSetValues(popup, args, 2);
4840 XtPopup(popup, XtGrabExclusive);
4843 XtSetKeyboardFocus(localPlayer.shellWidget, popup);
4850 FileNameCallback(Widget w, XtPointer client_data, XtPointer call_data)
4855 XtSetArg(args[0], XtNlabel, &name);
4856 XtGetValues(w, args, 1);
4858 if (strcmp(name, "cancel") == 0)
4860 XtPopdown(w = XtParent(XtParent(w)));
4867 FileNameAction(w, NULL, NULL, NULL);
4874 FileNameAction(Widget w, XEvent *event, String *prms, Cardinal *nprms)
4879 name = XawDialogGetValueString(w = XtParent(w));
4881 if ((name != NULL) && (*name != NULLCHAR))
4884 XtPopdown(w = XtParent(w));
4887 (*fileProc)(buf); /* I can't see a way not
4888 to use a global here */
4893 XtPopdown(w = XtParent(w));
4903 PromotionPopUp(ShogiSquare piece, int to_x, int to_y, int fromRemotePlayer)
4908 Dimension bw_width, bw_height, pw_width, pw_height;
4910 player = (fromRemotePlayer ? &remotePlayer : &localPlayer);
4916 XtSetArg(args[0], XtNwidth, &bw_width);
4917 XtSetArg(args[1], XtNheight, &bw_height);
4918 XtGetValues(player->boardWidget, args, 2);
4920 XtSetArg(args[0], XtNresizable, True);
4922 player->promotionShell
4923 = XtCreatePopupShell("Promotion",
4924 transientShellWidgetClass,
4925 player->commandsWidget, args, 1);
4927 XtSetArg(args[0], XtNlabel, "Promote piece?");
4928 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4929 player->promotionShell, args, 1);
4931 XawDialogAddButton(dialog, "Yes", PromotionCallback,
4932 (XtPointer) dialog);
4933 XawDialogAddButton(dialog, "No", PromotionCallback,
4934 (XtPointer) dialog);
4935 XawDialogAddButton(dialog, "cancel", PromotionCallback,
4936 (XtPointer) dialog);
4938 XtRealizeWidget(player->promotionShell);
4940 XtSetArg(args[0], XtNwidth, &pw_width);
4941 XtSetArg(args[1], XtNheight, &pw_height);
4942 XtGetValues(player->promotionShell, args, 2);
4944 XtTranslateCoords(player->boardWidget,
4945 ((bw_width - pw_width) / 2),
4947 + player->squareSize / 3
4948 + (((piece == BlackPawn) ^ (player->flipView))
4950 : (6 * (player->squareSize + LINE_GAP)))),
4953 XtSetArg(args[0], XtNx, x);
4954 XtSetArg(args[1], XtNy, y);
4955 XtSetValues(player->promotionShell, args, 2);
4957 XtPopup(player->promotionShell, XtGrabNone);
4959 player->promotionUp = True;
4966 PromotionCallback(Widget w, XtPointer client_data, XtPointer call_data)
4970 ShogiMove move_type;
4971 struct DisplayData *player;
4973 XtSetArg(args[0], XtNlabel, &name);
4974 XtGetValues(w, args, 1);
4976 w = XtParent(XtParent(w));
4977 player = ((w == remotePlayer.promotionShell)
4978 ? &remotePlayer : &localPlayer);
4981 player->promotionUp = False;
4986 if (strcmp(name, "Yes") == 0)
4988 if ((int)pmi.piece < (int)WhitePawn)
4989 move_type = BlackPromotion;
4991 move_type = WhitePromotion;
4993 else if (strcmp(name, "No") == 0)
4995 move_type = NormalMove;
4997 else /* strcmp(name, "cancel") == 0 */
5003 MakeMove(&move_type, fromX, fromY, pmi.to_x, pmi.to_y);
5006 if (updateRemotePlayer)
5008 BlinkSquare(pmi.to_y, pmi.to_x,
5009 boards[currentMove][pmi.to_y][pmi.to_x]);
5013 FinishUserMove(move_type, pmi.to_x, pmi.to_y);
5020 FileModePopUp(char *name)
5025 Dimension bw_width, bw_height, pw_width, pw_height;
5027 struct DisplayData *player = &localPlayer;
5029 strcpy(fmi.name, name);
5031 XtSetArg(args[0], XtNwidth, &bw_width);
5032 XtSetArg(args[1], XtNheight, &bw_height);
5033 XtGetValues(player->boardWidget, args, 2);
5035 XtSetArg(args[0], XtNresizable, True);
5036 player->filemodeShell
5037 = XtCreatePopupShell("FileMode",
5038 transientShellWidgetClass,
5039 player->commandsWidget, args, 1);
5041 XtSetArg(args[0], XtNlabel, "Append to existing file?");
5042 dialog = XtCreateManagedWidget("filemode", dialogWidgetClass,
5043 player->filemodeShell, args, 1);
5045 XawDialogAddButton(dialog, "Yes", FileModeCallback,
5046 (XtPointer) dialog);
5047 XawDialogAddButton(dialog, "No", FileModeCallback,
5048 (XtPointer) dialog);
5049 XawDialogAddButton(dialog, "cancel", FileModeCallback,
5050 (XtPointer) dialog);
5052 XtRealizeWidget(player->filemodeShell);
5054 XtSetArg(args[0], XtNwidth, &pw_width);
5055 XtSetArg(args[1], XtNheight, &pw_height);
5056 XtGetValues(player->filemodeShell, args, 2);
5058 XtTranslateCoords(player->boardWidget, (bw_width - pw_width) / 2,
5059 LINE_GAP + player->squareSize/3 +
5060 (6*(player->squareSize + LINE_GAP)),
5063 XtSetArg(args[0], XtNx, x);
5064 XtSetArg(args[1], XtNy, y);
5065 XtSetValues(player->filemodeShell, args, 2);
5067 XtPopup(player->filemodeShell, XtGrabNone);
5076 FileModeCallback(Widget w, XtPointer client_data, XtPointer call_data)
5081 XtSetArg(args[0], XtNlabel, &name);
5082 XtGetValues(w, args, 1);
5084 XtPopdown(w = XtParent(XtParent(w)));
5087 if (strcmp(name, "Yes") == 0)
5089 strcpy(fmi.mode, "a");
5091 else if (strcmp(name, "No") == 0)
5093 strcpy(fmi.mode, "w");
5095 else /* strcmp(name, "cancel") == 0 */
5101 XtPopdown(localPlayer.filemodeShell);
5102 XtDestroyWidget(localPlayer.filemodeShell);
5113 SelectCommand(Widget w, XtPointer client_data, XtPointer call_data)
5115 Cardinal fromRemotePlayer = (Cardinal)client_data;
5117 XawListReturnStruct *list_return = XawListShowCurrent(w);
5119 player = fromRemotePlayer ? &remotePlayer : &localPlayer;
5123 if (player->promotionUp)
5125 XtPopdown(player->promotionShell);
5126 XtDestroyWidget(player->promotionShell);
5127 player->promotionUp = False;
5130 (*buttonProcs[list_return->list_index])
5131 (w, NULL, NULL, &fromRemotePlayer);
5141 HighlightProcButton(XtActionProc proc)
5147 XawListUnhighlight(localPlayer.commandsWidget);
5149 if (updateRemotePlayer)
5150 XawListUnhighlight(remotePlayer.commandsWidget);
5157 if (buttonProcs[i] == NULL)
5159 XawListUnhighlight(localPlayer.commandsWidget);
5161 if (updateRemotePlayer)
5162 XawListUnhighlight(remotePlayer.commandsWidget);
5167 if (buttonProcs[i] == proc)
5169 XawListHighlight(localPlayer.commandsWidget, i);
5171 if (updateRemotePlayer)
5172 XawListHighlight(remotePlayer.commandsWidget, i);
5189 case BeginningOfGame:
5190 if (localPlayer.appData.noShogiProgram)
5191 HighlightProcButton(ForceProc);
5193 HighlightProcButton(MachineBlackProc);
5197 case MachinePlaysBlack:
5198 HighlightProcButton(MachineBlackProc);
5201 case MachinePlaysWhite:
5202 HighlightProcButton(MachineWhiteProc);
5205 case TwoMachinesPlay:
5206 HighlightProcButton(TwoMachinesProc);
5210 HighlightProcButton(ForceProc);
5214 case PlayFromGameFile:
5215 HighlightProcButton(LoadGameProc);
5219 HighlightProcButton(PauseProc);
5223 HighlightProcButton(EditPositionProc);
5228 HighlightProcButton(NULL);
5241 QuitRemotePlayerProc(void)
5243 /* This should be modified... */
5244 XCloseDisplay(remotePlayer.xDisplay);
5245 /* XtDestroyWidget(remotePlayer.shellWidget); */
5246 updateRemotePlayer = False;
5247 DisplayMessage("Remote player has pressed Quit", False);
5254 QuitProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5256 if (updateRemotePlayer)
5257 QuitRemotePlayerProc();
5259 ShutdownShogiPrograms("Quitting");
5266 LoadGameProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5268 int fromRemotePlayer = *nprms;
5270 if (fromRemotePlayer)
5272 DisplayMessage("only opponent may load game", fromRemotePlayer);
5276 if (gameMode != BeginningOfGame)
5278 DisplayMessage("Press Reset first.", False);
5282 if (localPlayer.appData.loadGameFile == NULL)
5283 FileNamePopUp("Game file name?", LoadGame);
5285 (void) LoadGame(localPlayer.appData.loadGameFile);
5292 LoadGame(char *name)
5296 loaded_game_finished = 0;
5298 if (gameMode != BeginningOfGame)
5300 DisplayMessage("Press Reset first", False);
5304 if (localPlayer.appData.loadGameFile != name)
5306 if (localPlayer.appData.loadGameFile)
5307 XtFree(localPlayer.appData.loadGameFile);
5309 localPlayer.appData.loadGameFile = XtMalloc(strlen(name) + 1);
5310 strcpy(localPlayer.appData.loadGameFile, name);
5313 if ((gameFileFP = fopen(name, "r")) == NULL)
5315 sprintf(buf, "Can't open %s", name);
5316 DisplayMessage(buf, False);
5317 XtFree(localPlayer.appData.loadGameFile);
5318 localPlayer.appData.loadGameFile = NULL;
5322 lastGameMode = gameMode = PlayFromGameFile;
5325 DisplayClocks(StopTimers);
5327 if (firstProgramXID == 0)
5329 InitShogiProgram(localPlayer.appData.firstHost,
5330 localPlayer.appData.firstShogiProgram,
5331 &firstProgramPID, &toFirstProgFP,
5332 &fromFirstProgFP, &firstProgramXID,
5336 SendToProgram(localPlayer.appData.initString, toFirstProgFP);
5337 SendSearchDepth(toFirstProgFP);
5338 SendToProgram("force\n", toFirstProgFP);
5340 currentMove = forwardMostMove = backwardMostMove = 0;
5351 * Restart the shogi program and feed it all the moves made so far.
5352 * Used when the user wants to back up from end of game, when gnushogi
5353 * has already exited. Assumes gameMode == EndOfGame.
5357 ResurrectShogiProgram(void)
5362 if (currentMove > 0)
5363 currentMove--; /* delete "Black wins" or the like */
5365 InitShogiProgram(localPlayer.appData.firstHost,
5366 localPlayer.appData.firstShogiProgram,
5367 &firstProgramPID, &toFirstProgFP, &fromFirstProgFP,
5368 &firstProgramXID, &firstSendTime);
5370 SendToProgram(localPlayer.appData.initString, toFirstProgFP);
5371 SendSearchDepth(toFirstProgFP);
5372 SendToProgram("force\n", toFirstProgFP);
5373 gameMode = lastGameMode = ForceMoves;
5376 i = (whitePlaysFirst ? 1 : 0);
5378 if (startedFromSetupPosition)
5379 SendBoard(toFirstProgFP, boards[i], catches[i]);
5381 for (; i < currentMove; i++)
5383 strcpy(buf, moveList[i]);
5384 SendToProgram(buf, toFirstProgFP);
5389 /* can't tell gnushogi what its clock should read,
5390 so we bow to its notion. */
5391 DisplayClocks(ResetTimers);
5392 timeRemaining[0][currentMove] = blackTimeRemaining;
5393 timeRemaining[1][currentMove] = whiteTimeRemaining;
5401 MachineWhiteProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5403 int fromRemotePlayer = *nprms;
5405 if (updateRemotePlayer)
5407 DisplayMessage("no machine moves in challenge mode",
5413 if (gameMode == PauseGame)
5414 PauseProc(w, event, prms, nprms);
5416 if (gameMode == PlayFromGameFile)
5417 ForceProc(w, event, prms, nprms);
5419 if (gameMode == EditPosition)
5422 if ((gameMode == EndOfGame)
5423 || (gameMode == PlayFromGameFile)
5424 || (gameMode == TwoMachinesPlay)
5425 || localPlayer.appData.noShogiProgram
5426 || (gameMode == MachinePlaysWhite))
5431 if (BlackOnMove((gameMode == ForceMoves)
5435 DisplayMessage("It is not White's turn.", False);
5439 if (gameMode == ForceMoves)
5440 forwardMostMove = currentMove;
5442 lastGameMode = gameMode = MachinePlaysWhite;
5444 SendToProgram(localPlayer.appData.whiteString, toFirstProgFP);
5445 DisplayClocks(StartTimers);
5452 MachineBlackProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5454 int fromRemotePlayer = *nprms;
5456 if (updateRemotePlayer)
5458 DisplayMessage("no machine moves in challenge mode",
5463 if (gameMode == PauseGame)
5464 PauseProc(w, event, prms, nprms);
5466 if (gameMode == PlayFromGameFile)
5467 ForceProc(w, event, prms, nprms);
5469 if (gameMode == EditPosition)
5472 if ((gameMode == EndOfGame)
5473 || (gameMode == PlayFromGameFile)
5474 || (gameMode == TwoMachinesPlay)
5475 || localPlayer.appData.noShogiProgram
5476 || (gameMode == MachinePlaysBlack))
5481 if (!BlackOnMove((gameMode == ForceMoves)
5485 DisplayMessage("It is not Black's turn.", False);
5489 if (gameMode == ForceMoves)
5490 forwardMostMove = currentMove;
5492 lastGameMode = gameMode = MachinePlaysBlack;
5494 SendToProgram(localPlayer.appData.blackString, toFirstProgFP);
5495 DisplayClocks(StartTimers);
5502 ForwardProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5508 int fromRemotePlayer = *nprms;
5510 if (updateRemotePlayer)
5512 DisplayMessage("Forward button disabled.", fromRemotePlayer);
5516 if ((gameMode == EndOfGame) || (gameMode == EditPosition))
5519 if (gameMode == PlayFromGameFile)
5520 PauseProc(w, event, prms, nprms);
5522 if (currentMove >= forwardMostMove)
5531 XQueryPointer(localPlayer.xDisplay, localPlayer.xBoardWindow,
5532 &root, &child, &root_x, &root_y,
5533 &win_x, &win_y, &state);
5537 state = event->xkey.state;
5540 if (state & ShiftMask)
5541 target = forwardMostMove;
5543 target = currentMove + 1;
5545 if (gameMode == ForceMoves)
5547 while (currentMove < target)
5549 strcpy(buf, moveList[currentMove++]);
5550 SendToProgram(buf, toFirstProgFP);
5555 currentMove = target;
5558 if (gameMode == ForceMoves)
5560 blackTimeRemaining = timeRemaining[0][currentMove];
5561 whiteTimeRemaining = timeRemaining[1][currentMove];
5564 DisplayClocks(ReDisplayTimers);
5565 DisplayMove(currentMove - 1);
5566 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
5577 if (updateRemotePlayer)
5580 if (localPlayer.appData.loadGameFile)
5581 XtFree(localPlayer.appData.loadGameFile);
5583 if (localPlayer.appData.loadPositionFile)
5584 XtFree(localPlayer.appData.loadPositionFile);
5586 localPlayer.appData.loadGameFile
5587 = localPlayer.appData.loadPositionFile = NULL;
5590 if (gameFileFP != NULL)
5601 ResetChallenge(void)
5605 if (localPlayer.appData.challengeDisplay)
5606 XtFree(localPlayer.appData.challengeDisplay);
5608 localPlayer.appData.challengeDisplay = NULL;
5616 ResetProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5618 int fromRemotePlayer = *nprms;
5620 if (fromRemotePlayer)
5622 DisplayMessage("Only your opponent may reset the game.",
5634 Reset(int redraw) /* Boolean */
5639 localPlayer.flipView = False;
5640 remotePlayer.flipView = True;
5641 startedFromSetupPosition = whitePlaysFirst = False;
5642 matchMode = MatchFalse;
5644 blackFlag = whiteFlag = False;
5645 maybeThinking = False;
5647 endMessage[0] = NULLCHAR;
5649 ShutdownShogiPrograms("");
5650 lastGameMode = gameMode = BeginningOfGame;
5652 InitPosition(redraw);
5653 DisplayClocks(ResetTimers);
5654 timeRemaining[0][0] = blackTimeRemaining;
5655 timeRemaining[1][0] = whiteTimeRemaining;
5656 InitShogiProgram(localPlayer.appData.firstHost,
5657 localPlayer.appData.firstShogiProgram,
5658 &firstProgramPID, &toFirstProgFP,
5659 &fromFirstProgFP, &firstProgramXID,
5664 XtPopdown(commentShell);
5665 XtDestroyWidget(commentShell);
5669 if (localPlayer.promotionUp)
5671 XtPopdown(localPlayer.promotionShell);
5672 XtDestroyWidget(localPlayer.promotionShell);
5673 localPlayer.promotionUp = False;
5676 if (updateRemotePlayer && remotePlayer.promotionUp)
5678 XtPopdown(remotePlayer.promotionShell);
5679 XtDestroyWidget(remotePlayer.promotionShell);
5680 remotePlayer.promotionUp = False;
5688 ClearCatches(int (*catches)[8])
5692 for (c = 0; c <= 1; c++)
5693 for (p = 0; p <= 7; p++)
5701 Challenge(char *name)
5706 XrmDatabase database;
5708 if (gameMode != BeginningOfGame)
5710 DisplayMessage("Press Reset first.", False);
5714 if (localPlayer.appData.challengeDisplay != name)
5716 if (localPlayer.appData.challengeDisplay)
5717 XtFree(localPlayer.appData.challengeDisplay);
5719 localPlayer.appData.challengeDisplay = XtMalloc(strlen(name) + 1);
5720 strcpy(localPlayer.appData.challengeDisplay, name);
5723 sprintf(buf, "trying to connect to %s.....", name);
5724 DisplayMessage(buf, False);
5729 if ((remotePlayer.xDisplay
5730 = XtOpenDisplay(appContext, name, "XShogi",
5731 "XShogi", 0, 0, &argc, argv)) == NULL)
5733 sprintf(buf, "Can't open display %s", name);
5734 DisplayMessage(buf, False);
5735 XtFree(localPlayer.appData.challengeDisplay);
5736 localPlayer.appData.challengeDisplay = NULL;
5740 DisplayMessage("connected! creating remote window...", False);
5742 remotePlayer.xScreen = DefaultScreen(remotePlayer.xDisplay);
5744 remotePlayer.shellWidget
5745 = XtAppCreateShell(NULL, "XShogi",
5746 applicationShellWidgetClass,
5747 remotePlayer.xDisplay, NULL, 0);
5749 database = XtDatabase(remotePlayer.xDisplay);
5751 XrmParseCommand(&database,
5752 shellOptions, XtNumber(shellOptions),
5753 "XShogi", &argc, argv);
5755 XtGetApplicationResources(remotePlayer.shellWidget,
5756 &remotePlayer.appData, clientResources,
5757 XtNumber(clientResources), NULL, 0);
5759 player = &remotePlayer;
5761 CreatePlayerWindow();
5763 updateRemotePlayer = True;
5765 DisplayName("REMOTE");
5766 DrawPosition(remotePlayer.boardWidget, NULL, NULL, NULL);
5767 DisplayClocks(ReDisplayTimers);
5769 DisplayMessage("ready to play", False);
5770 DisplayMessage("ready to play", True);
5779 ChallengeProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5781 int fromRemotePlayer = *nprms;
5783 if (updateRemotePlayer)
5785 DisplayMessage("You are already in challenge mode.",
5790 if (gameMode != BeginningOfGame)
5792 DisplayMessage("Press Reset first.", False);
5796 if (localPlayer.appData.challengeDisplay == NULL)
5797 FileNamePopUp("Challenge display?", Challenge);
5799 (void) Challenge(localPlayer.appData.challengeDisplay);
5806 SelectLevel(char *command)
5810 sprintf(buf, "level %s\n", command);
5811 SendToProgram(buf, toFirstProgFP);
5820 SelectLevelProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5822 if ((BlackOnMove(forwardMostMove) && (gameMode == MachinePlaysBlack))
5823 || (!BlackOnMove(forwardMostMove) && (gameMode == MachinePlaysWhite)))
5825 DisplayMessage("Wait until your turn.", False);
5829 FileNamePopUp("#moves #minutes", SelectLevel);
5837 MoveNowProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5839 if ((!BlackOnMove(forwardMostMove) && (gameMode == MachinePlaysBlack))
5840 || (BlackOnMove(forwardMostMove) && (gameMode == MachinePlaysWhite)))
5842 DisplayMessage("Wait until machine's turn.", False);
5846 Attention(firstProgramPID);
5854 LoadPositionProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5856 int fromRemotePlayer = *nprms;
5858 if (fromRemotePlayer)
5860 DisplayMessage("only opponent may load position", fromRemotePlayer);
5864 if (gameMode != BeginningOfGame)
5866 DisplayMessage("Press Reset first.", False);
5870 FileNamePopUp("Position file name?", LoadPosition);
5877 LoadPosition(char *name)
5879 char *p, line[MSG_SIZ], buf[MSG_SIZ];
5880 Board initial_position;
5881 Catched initial_catches;
5885 if (gameMode != BeginningOfGame)
5887 DisplayMessage("Press Reset first.", False);
5891 if (localPlayer.appData.loadPositionFile != name)
5893 if (localPlayer.appData.loadPositionFile)
5894 XtFree(localPlayer.appData.loadPositionFile);
5896 localPlayer.appData.loadPositionFile = XtMalloc(strlen(name) + 1);
5897 strcpy(localPlayer.appData.loadPositionFile, name);
5900 if ((fp = fopen(name, "r")) == NULL)
5902 sprintf(buf, "Can't open %s", name);
5903 DisplayMessage(buf, False);
5904 XtFree(localPlayer.appData.loadPositionFile);
5905 localPlayer.appData.loadPositionFile = NULL;
5909 lastGameMode = gameMode = ForceMoves;
5911 startedFromSetupPosition = True;
5913 if (firstProgramXID == 0)
5915 InitShogiProgram(localPlayer.appData.firstHost,
5916 localPlayer.appData.firstShogiProgram,
5917 &firstProgramPID, &toFirstProgFP,
5918 &fromFirstProgFP, &firstProgramXID,
5923 * Check and skip header information in position file.
5926 fgets(line, MSG_SIZ, fp);
5927 line[strlen(line) - 1] = NULLCHAR;
5928 sprintf(buf, "# %s position file", programName);
5930 if (strncmp(line, buf, strlen(buf)))
5932 strcat(line, ": no xshogi position file");
5933 DisplayMessage(line, False);
5938 fgets(line, MSG_SIZ, fp); /* skip opponents */
5940 for (i = BOARD_SIZE - 1; i >= 0; i--)
5942 fgets(line, MSG_SIZ, fp);
5944 for (p = line, j = 0; j < BOARD_SIZE; p++)
5946 int promoted = False; /* CHECKME: is this valid? */
5955 initial_position[i][j++] = CharToPiece(*p, promoted);
5962 for (color = 0; color <= 1; color++)
5964 fscanf(fp, "%i%i%i%i%i%i%i%i\n",
5965 &initial_catches[color][pawn],
5966 &initial_catches[color][lance],
5967 &initial_catches[color][knight],
5968 &initial_catches[color][silver],
5969 &initial_catches[color][gold],
5970 &initial_catches[color][bishop],
5971 &initial_catches[color][rook],
5972 &initial_catches[color][king]);
5976 whitePlaysFirst = False;
5980 fgets(line, MSG_SIZ, fp);
5982 if (strncmp(line, "white", strlen("white")) == 0)
5983 whitePlaysFirst = True;
5988 if (whitePlaysFirst)
5990 CopyBoard(boards[0], initial_position);
5991 CopyCatches(catches[0], initial_catches);
5992 strcpy(moveList[0], " ...\n");
5993 strcpy(parseList[0], " ...\n");
5994 currentMove = forwardMostMove = backwardMostMove = 1;
5995 CopyBoard(boards[1], initial_position);
5996 CopyCatches(catches[1], initial_catches);
5997 SendToProgram("white\n", toFirstProgFP);
5998 SendToProgram("force\n", toFirstProgFP);
5999 SendCurrentBoard(toFirstProgFP);
6000 DisplayMessage("White to play", False);
6004 currentMove = forwardMostMove = backwardMostMove = 0;
6005 CopyBoard(boards[0], initial_position);
6006 CopyCatches(catches[0], initial_catches);
6007 SendCurrentBoard(toFirstProgFP);
6008 SendToProgram("force\n", toFirstProgFP);
6009 DisplayMessage("Black to play", False);
6012 DisplayClocks(ResetTimers);
6013 timeRemaining[0][1] = blackTimeRemaining;
6014 timeRemaining[1][1] = whiteTimeRemaining;
6016 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
6024 EditPositionProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6026 int fromRemotePlayer = *nprms;
6028 if (updateRemotePlayer)
6030 DisplayMessage("Edit button disabled", fromRemotePlayer);
6034 if (gameMode == EditPosition)
6037 ForceProc(w, event, prms, nprms);
6039 if (gameMode != ForceMoves)
6042 DisplayName("<-- Press to set side to play next");
6043 DisplayMessage("Mouse: 1=drag, 2=black, 3=white", False);
6045 lastGameMode = gameMode = EditPosition;
6048 if (currentMove > 0)
6049 CopyBoard(boards[0], boards[currentMove]);
6051 whitePlaysFirst = !BlackOnMove(forwardMostMove);
6052 currentMove = forwardMostMove = backwardMostMove = 0;
6059 EditPositionDone(void)
6061 startedFromSetupPosition = True;
6062 SendToProgram(localPlayer.appData.initString, toFirstProgFP);
6063 SendSearchDepth(toFirstProgFP);
6065 if (whitePlaysFirst)
6067 strcpy(moveList[0], " ...\n");
6068 strcpy(parseList[0], " ...\n");
6069 currentMove = forwardMostMove = backwardMostMove = 1;
6070 CopyBoard(boards[1], boards[0]);
6071 CopyCatches(catches[1], catches[0]);
6072 SendToProgram("force\n", toFirstProgFP);
6073 SendCurrentBoard(toFirstProgFP);
6075 DisplayMessage("White to play", False);
6079 currentMove = forwardMostMove = backwardMostMove = 0;
6080 SendCurrentBoard(toFirstProgFP);
6081 SendToProgram("force\n", toFirstProgFP);
6083 DisplayMessage("Black to play", False);
6086 lastGameMode = gameMode = ForceMoves;
6096 * This function executes when undoing a move.
6097 * FIXME: this function is totally hosed!!!
6111 BackwardProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6116 int fromRemotePlayer = *nprms;
6118 if (updateRemotePlayer)
6120 DisplayMessage("Backward button disabled", fromRemotePlayer);
6125 * Why do we need this here?
6128 ForceProc(w, event, prms, nprms);
6130 if ((currentMove <= backwardMostMove) || (gameMode == EditPosition))
6133 if (gameMode == EndOfGame)
6134 ResurrectShogiProgram();
6136 if (gameMode == PlayFromGameFile)
6137 PauseProc(w, event, prms, nprms);
6146 XQueryPointer(localPlayer.xDisplay, localPlayer.xBoardWindow,
6147 &root, &child, &root_x, &root_y,
6148 &win_x, &win_y, &state);
6152 state = event->xkey.state;
6155 if (state & ShiftMask)
6157 target = backwardMostMove;
6161 target = currentMove - 1;
6164 if (gameMode == ForceMoves)
6166 Attention(firstProgramPID);
6168 while (currentMove > target)
6170 SendToProgram("undo\n", toFirstProgFP);
6176 currentMove = target;
6179 if (gameMode == ForceMoves)
6181 whiteTimeRemaining = timeRemaining[0][currentMove];
6182 blackTimeRemaining = timeRemaining[1][currentMove];
6185 DisplayClocks(ReDisplayTimers);
6186 DisplayMove(currentMove - 1);
6187 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
6194 FlipViewProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6196 struct DisplayData *player = (*nprms ? &remotePlayer : &localPlayer);
6198 player->flipView = !player->flipView;
6199 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
6206 SaveGameProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6210 int fromRemotePlayer = *nprms;
6212 if (fromRemotePlayer)
6214 DisplayMessage("only opponent may save game", fromRemotePlayer);
6220 FileNamePopUp("Filename for saved game?", SaveGame);
6227 SaveGame(char *name)
6230 int i, len, move = 0;
6233 if (!filemodeUp) /* if called via FileModeCallback avoid recursion */
6235 if ((gameFileFP = fopen(name, "r")) == NULL)
6237 strcpy(fmi.mode, "w");
6242 FileModePopUp(name);
6243 return False; /* CHECKME: what should the return value be? */
6247 if ((gameFileFP = fopen(name, fmi.mode)) == NULL)
6249 sprintf(buf, "Can't open %s (mode %s)", name, fmi.mode);
6250 DisplayMessage(buf, False);
6254 tm = time((time_t *) NULL);
6256 fprintf(gameFileFP, "# %s game file -- %s", programName, ctime(&tm));
6257 PrintOpponents(gameFileFP);
6259 for (i = 0; i < currentMove;)
6262 fprintf(gameFileFP, "\n");
6264 fprintf(gameFileFP, "%d. %s ", ++move, parseList[i++]);
6266 if (i >= currentMove)
6268 fprintf(gameFileFP, "\n");
6272 if ((len = strlen(parseList[i])) == 0)
6275 fprintf(gameFileFP, "%s ", parseList[i++]);
6278 fprintf(gameFileFP, "\n");
6290 SwitchProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6292 if (localPlayer.appData.noShogiProgram)
6300 case MachinePlaysBlack:
6301 if (BlackOnMove(forwardMostMove))
6303 DisplayMessage("Wait until your turn", False);
6307 lastGameMode = gameMode = MachinePlaysWhite;
6311 case BeginningOfGame:
6313 case MachinePlaysWhite:
6314 if (!BlackOnMove(forwardMostMove))
6316 DisplayMessage("Wait until your turn", False);
6320 if (forwardMostMove == 0)
6322 MachineBlackProc(w, event, prms, nprms);
6326 lastGameMode = gameMode = MachinePlaysBlack;
6331 Attention(firstProgramPID);
6332 SendToProgram("switch\n", toFirstProgFP);
6339 ForceProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6345 case MachinePlaysBlack:
6346 if (BlackOnMove(forwardMostMove))
6348 DisplayMessage("Wait until your turn", False);
6352 Attention(firstProgramPID);
6353 SendToProgram("force\n", toFirstProgFP);
6356 case MachinePlaysWhite:
6357 if (!BlackOnMove(forwardMostMove))
6359 DisplayMessage("Wait until your turn", False);
6363 Attention(firstProgramPID);
6364 SendToProgram("force\n", toFirstProgFP);
6367 case BeginningOfGame:
6368 SendToProgram("force\n", toFirstProgFP);
6371 case PlayFromGameFile:
6372 if (readGameXID != 0)
6374 XtRemoveTimeOut(readGameXID);
6378 if (gameFileFP != NULL)
6387 ResurrectShogiProgram();
6394 case TwoMachinesPlay:
6395 ShutdownShogiPrograms("");
6396 ResurrectShogiProgram();
6403 if ((gameMode == MachinePlaysWhite)
6404 || (gameMode == MachinePlaysBlack)
6405 || (gameMode == TwoMachinesPlay)
6406 || (gameMode == PlayFromGameFile))
6408 i = forwardMostMove;
6410 while (i > currentMove)
6412 SendToProgram("undo\n", toFirstProgFP);
6416 blackTimeRemaining = timeRemaining[0][currentMove];
6417 whiteTimeRemaining = timeRemaining[1][currentMove];
6419 if (whiteFlag || blackFlag)
6421 whiteFlag = blackFlag = 0;
6427 lastGameMode = gameMode = ForceMoves;
6429 DisplayClocks(StopTimers);
6435 HintProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6437 int fromRemotePlayer = *nprms;
6439 if (updateRemotePlayer)
6441 DisplayMessage("no hints in challenge mode", fromRemotePlayer);
6445 if (localPlayer.appData.noShogiProgram)
6450 case MachinePlaysBlack:
6451 if (BlackOnMove(forwardMostMove))
6453 DisplayMessage("Wait until your turn", False);
6459 case BeginningOfGame:
6460 case MachinePlaysWhite:
6461 if (!BlackOnMove(forwardMostMove))
6463 DisplayMessage("Wait until your turn", False);
6470 DisplayMessage("No hint available", False);
6474 Attention(firstProgramPID);
6475 SendToProgram("hint\n", toFirstProgFP);
6482 PrintPosition(FILE *fp, int move)
6486 for (i = BOARD_SIZE - 1; i >= 0; i--)
6488 for (j = 0; j < BOARD_SIZE; j++)
6490 if (pieceIsPromoted[(int)boards[currentMove][i][j]])
6491 fprintf(fp, "%c", '+');
6493 fprintf(fp, "%c", ' ');
6496 pieceToChar[(int)boards[currentMove][i][j]]);
6498 if (j == BOARD_SIZE - 1)
6503 for (color = 0; color <= 1; color++)
6505 fprintf(fp, "%i %i %i %i %i %i %i %i\n",
6506 catches[currentMove][color][pawn],
6507 catches[currentMove][color][lance],
6508 catches[currentMove][color][knight],
6509 catches[currentMove][color][silver],
6510 catches[currentMove][color][gold],
6511 catches[currentMove][color][bishop],
6512 catches[currentMove][color][rook],
6513 catches[currentMove][color][king]);
6516 if ((gameMode == EditPosition)
6518 : BlackOnMove(forwardMostMove))
6520 fprintf(fp, "black to play\n");
6524 fprintf(fp, "white to play\n");
6532 PrintOpponents(FILE *fp)
6534 char host_name[MSG_SIZ];
6536 #ifdef HAVE_GETHOSTNAME
6537 gethostname(host_name, MSG_SIZ);
6539 strncpy(host_name, "hostname not available", MSG_SIZ);
6542 switch (lastGameMode)
6544 case MachinePlaysWhite:
6545 fprintf(fp, "# %s@%s vs. %s@%s\n",
6546 localPlayer.appData.firstShogiProgram,
6547 localPlayer.appData.firstHost,
6548 getpwuid(getuid())->pw_name,
6552 case MachinePlaysBlack:
6553 fprintf(fp, "# %s@%s vs. %s@%s\n",
6554 getpwuid(getuid())->pw_name,
6556 localPlayer.appData.firstShogiProgram,
6557 localPlayer.appData.firstHost);
6560 case TwoMachinesPlay:
6561 fprintf(fp, "# %s@%s vs. %s@%s\n",
6562 localPlayer.appData.secondShogiProgram,
6563 localPlayer.appData.secondHost,
6564 localPlayer.appData.firstShogiProgram,
6565 localPlayer.appData.firstHost);
6578 SavePositionProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6582 int fromRemotePlayer = *nprms;
6584 if (fromRemotePlayer)
6586 DisplayMessage("only opponent may save game", fromRemotePlayer);
6592 FileNamePopUp("Filename for saved position?", SavePosition);
6599 SavePosition(char *name)
6605 if ((fp = fopen(name, "w")) == NULL)
6607 sprintf(buf, "Can't open %s", name);
6608 DisplayMessage(buf, False);
6612 tm = time((time_t *) NULL);
6614 fprintf(fp, "# %s position file -- %s", programName, ctime(&tm));
6616 PrintPosition(fp, currentMove);
6626 TwoMachinesProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6629 MatchMode matchKind;
6631 int fromRemotePlayer = *nprms;
6633 if (updateRemotePlayer)
6635 DisplayMessage("no machine moves in challenge mode",
6640 if (gameMode == PauseGame)
6641 PauseProc(w, event, prms, nprms);
6643 if (gameMode == PlayFromGameFile)
6644 ForceProc(w, event, prms, nprms);
6646 if ((gameMode == EndOfGame)
6647 || (gameMode == TwoMachinesPlay)
6648 || localPlayer.appData.noShogiProgram)
6653 if (matchMode == MatchFalse)
6658 case PlayFromGameFile:
6661 case MachinePlaysBlack:
6662 case MachinePlaysWhite:
6663 ForceProc(w, event, prms, nprms);
6665 if (gameMode != ForceMoves)
6668 matchKind = MatchOpening;
6672 matchKind = MatchOpening;
6677 matchKind = MatchPosition;
6680 case BeginningOfGame:
6682 matchKind = MatchInit;
6688 matchKind = matchMode;
6691 forwardMostMove = currentMove;
6693 localPlayer.flipView = False;
6694 remotePlayer.flipView = True;
6696 DisplayClocks(ResetTimers);
6697 DisplayClocks(StartTimers);
6702 if (firstProgramXID == 0)
6704 if (localPlayer.appData.loadGameFile == NULL)
6706 DisplayMessage("Select game file first", False);
6710 InitShogiProgram(localPlayer.appData.firstHost,
6711 localPlayer.appData.firstShogiProgram,
6712 &firstProgramPID, &toFirstProgFP,
6713 &fromFirstProgFP, &firstProgramXID,
6716 if (!LoadGame(localPlayer.appData.loadGameFile))
6718 ShutdownShogiPrograms("Bad game file");
6722 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
6725 InitShogiProgram(localPlayer.appData.secondHost,
6726 localPlayer.appData.secondShogiProgram,
6727 &secondProgramPID, &toSecondProgFP,
6728 &fromSecondProgFP, &secondProgramXID,
6731 if (startedFromSetupPosition)
6733 if (whitePlaysFirst)
6736 SendToProgram("force\n", toSecondProgFP);
6737 SendBoard(toSecondProgFP, boards[i], catches[i]);
6742 SendBoard(toSecondProgFP, boards[i], catches[i]);
6743 SendToProgram("force\n", toSecondProgFP);
6749 SendToProgram("force\n", toSecondProgFP);
6752 for (i = backwardMostMove; i < forwardMostMove; i++)
6753 SendToProgram(moveList[i], toSecondProgFP);
6755 lastGameMode = gameMode = TwoMachinesPlay;
6759 if (BlackOnMove(forwardMostMove))
6760 SendToProgram(localPlayer.appData.blackString, toSecondProgFP);
6762 SendToProgram(localPlayer.appData.whiteString, toFirstProgFP);
6767 if (firstProgramXID == 0)
6769 if (localPlayer.appData.loadPositionFile == NULL)
6771 DisplayMessage("Select position file first", False);
6775 InitShogiProgram(localPlayer.appData.firstHost,
6776 localPlayer.appData.firstShogiProgram,
6777 &firstProgramPID, &toFirstProgFP,
6778 &fromFirstProgFP, &firstProgramXID,
6781 if (!LoadPosition(localPlayer.appData.loadPositionFile))
6785 InitShogiProgram(localPlayer.appData.secondHost,
6786 localPlayer.appData.secondShogiProgram,
6787 &secondProgramPID, &toSecondProgFP,
6788 &fromSecondProgFP, &secondProgramXID,
6791 if (whitePlaysFirst)
6792 SendToProgram("force\n", toSecondProgFP);
6794 SendCurrentBoard(toSecondProgFP);
6795 lastGameMode = gameMode = TwoMachinesPlay;
6799 if (BlackOnMove(forwardMostMove))
6800 SendToProgram(localPlayer.appData.blackString, toSecondProgFP);
6802 SendToProgram(localPlayer.appData.whiteString, toFirstProgFP);
6809 if (firstProgramXID == 0)
6811 InitShogiProgram(localPlayer.appData.firstHost,
6812 localPlayer.appData.firstShogiProgram,
6813 &firstProgramPID, &toFirstProgFP,
6814 &fromFirstProgFP, &firstProgramXID,
6818 InitShogiProgram(localPlayer.appData.secondHost,
6819 localPlayer.appData.secondShogiProgram,
6820 &secondProgramPID, &toSecondProgFP,
6821 &fromSecondProgFP, &secondProgramXID,
6824 lastGameMode = gameMode = TwoMachinesPlay;
6826 SendToProgram(localPlayer.appData.blackString, toSecondProgFP);
6832 if (!firstSendTime || !secondSendTime)
6834 DisplayClocks(ResetTimers);
6835 timeRemaining[0][forwardMostMove] = blackTimeRemaining;
6836 timeRemaining[1][forwardMostMove] = whiteTimeRemaining;
6839 DisplayClocks(StartTimers);
6846 PauseProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6848 static GameMode previous_mode = PauseGame;
6859 gameMode = previous_mode;
6861 previous_mode = PauseGame;
6862 DisplayClocks(StartTimers);
6863 DisplayMessage("", False);
6865 if (updateRemotePlayer)
6866 DisplayMessage("", True);
6869 case PlayFromGameFile:
6870 if (readGameXID == 0)
6873 XtAppAddTimeOut(appContext,
6874 (int)(1000 * localPlayer.appData.timeDelay),
6875 (XtTimerCallbackProc) ReadGameFile, NULL);
6879 XtRemoveTimeOut(readGameXID);
6883 DisplayMessage("Pausing", False);
6885 if (updateRemotePlayer)
6886 DisplayMessage("Pausing", True);
6890 case BeginningOfGame:
6891 case MachinePlaysBlack:
6892 case MachinePlaysWhite:
6893 case TwoMachinesPlay:
6894 if (forwardMostMove == 0) /* Don't pause if no one has moved. */
6897 if (((gameMode == MachinePlaysWhite)
6898 && !BlackOnMove(forwardMostMove))
6899 || ((gameMode == MachinePlaysBlack) &&
6900 BlackOnMove(forwardMostMove)))
6902 DisplayClocks(StopTimers);
6905 previous_mode = gameMode;
6906 gameMode = PauseGame;
6908 DisplayClocks(StopTimers);
6909 DisplayMessage("Pausing", False);
6911 if (updateRemotePlayer)
6912 DisplayMessage("Pausing", True);
6922 Iconify(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6928 XtSetArg(args[0], XtNiconic, True);
6929 XtSetValues(localPlayer.shellWidget, args, 1);
6936 SendToProgram(char *message, FILE *fp)
6945 fprintf(stderr, "Sending to %s: %s\n",
6946 ((fp == toFirstProgFP) ? "first" : "second"), message);
6949 if (message[strlen(message) - 1] != '\n')
6950 fprintf(fp, "\n%s\n", message);
6961 ReceiveFromProgram(FILE *fp, int *source, XtInputId *id)
6963 char message[MSG_SIZ], *end_str, *number, *name;
6965 if (fgets(message, MSG_SIZ, fp) == NULL)
6967 if (fp == fromFirstProgFP)
6970 name = localPlayer.appData.firstShogiProgram;
6972 else if (fp == fromSecondProgFP)
6975 name = localPlayer.appData.secondShogiProgram;
6982 if (ferror(fp) == 0)
6984 sprintf(message, "%s shogi program (%s) exited unexpectedly",
6986 fprintf(stderr, "%s: %s\n", programName, message);
6991 "error reading from %s shogi program (%s): %s",
6992 number, name, strerror(ferror(fp)));
6993 fprintf(stderr, "%s: %s\n", programName, message);
6999 if ((end_str = (char *)strchr(message, '\r')) != NULL)
7000 *end_str = NULLCHAR;
7002 if ((end_str = (char *)strchr(message, '\n')) != NULL)
7003 *end_str = NULLCHAR;
7005 if (xshogiDebug || localPlayer.appData.debugMode)
7007 fprintf(stderr, "Received from %s: %s\n",
7008 ((fp == fromFirstProgFP) ? "first" : "second"), message);
7011 HandleMachineMove(message, fp);
7018 SendSearchDepth(FILE *fp)
7020 char message[MSG_SIZ];
7022 if (localPlayer.appData.searchDepth <= 0)
7025 sprintf(message, "depth\n%d\nhelp\n", localPlayer.appData.searchDepth);
7026 /* Note kludge: "help" command forces gnushogi to print
7027 * out something that ends with a newline. */
7028 SendToProgram(message, fp);
7035 DisplayMessage(char *message, int toRemotePlayer)
7039 XtSetArg(arg, XtNlabel, message);
7041 if (!toRemotePlayer)
7042 XtSetValues(localPlayer.messageWidget, &arg, 1);
7044 if (updateRemotePlayer && toRemotePlayer)
7045 XtSetValues(remotePlayer.messageWidget, &arg, 1);
7052 DisplayName(char *name)
7056 XtSetArg(arg, XtNlabel, name);
7057 XtSetValues(localPlayer.titleWidget, &arg, 1);
7059 if (updateRemotePlayer)
7060 XtSetValues(remotePlayer.titleWidget, &arg, 1);
7066 void SendTimeRemaining(FILE *fp)
7068 char message[MSG_SIZ];
7069 long comtime, opptime;
7071 if (BlackOnMove(forwardMostMove) == (fp == toFirstProgFP))
7073 comtime = blackTimeRemaining;
7074 opptime = whiteTimeRemaining;
7078 comtime = whiteTimeRemaining;
7079 opptime = blackTimeRemaining;
7088 sprintf(message, "time %ld\n", comtime / 10);
7089 SendToProgram(message, fp);
7090 sprintf(message, "otime %ld\n", opptime / 10);
7091 SendToProgram(message, fp);
7097 void DisplayMove(int moveNumber)
7099 char message[MSG_SIZ];
7103 if (moveNumber == forwardMostMove - 1)
7104 DisplayMessage(endMessage, False);
7106 DisplayMessage("", False);
7110 sprintf(message, "%d. %s%s %s",
7111 (moveNumber / 2 + 1),
7112 (BlackOnMove(moveNumber) ? "" : "... "),
7113 parseList[moveNumber],
7114 (moveNumber == (forwardMostMove - 1)) ? endMessage : "");
7115 DisplayMessage(message, False);
7122 void DisplayTitle(char *title)
7126 XtSetArg(arg, XtNlabel, title);
7127 XtSetValues(localPlayer.titleWidget, &arg, 1);
7134 * This routine used to send a SIGINT (^C interrupt) to gnushogi to awaken it
7135 * if it might be busy thinking on our time. This normally isn't needed,
7136 * but is useful on systems where the FIONREAD ioctl doesn't work since
7137 * on those systems the gnushogi feature that lets you interrupt its thinking
7138 * just by typing a command does not work.
7140 * Now gnushogi periodically checks for user input without a need for
7148 if (localPlayer.appData.noShogiProgram || (pid == 0))
7153 case MachinePlaysBlack:
7154 case MachinePlaysWhite:
7155 case TwoMachinesPlay:
7156 if ((forwardMostMove > backwardMostMove + 1) && maybeThinking)
7158 if (xshogiDebug || localPlayer.appData.debugMode)
7160 fprintf(stderr, "Sending SIGINT to %s\n",
7161 ((pid == firstProgramPID) ? "first" : "second"));
7164 (void)kill(pid, SIGINT); /* stop it thinking */
7169 break; /* CHECKME: is this OK? */
7171 #endif /* !defined(FIONREAD) */
7180 if (blackTimeRemaining <= 0)
7187 DisplayName(" Both flags have fallen");
7189 DisplayName(" Black's flag has fallen");
7193 if (whiteTimeRemaining <= 0)
7200 DisplayName(" Both flags have fallen");
7202 DisplayName(" White's flag has fallen");
7211 CheckTimeControl(void)
7213 if (!localPlayer.appData.clockMode)
7216 if (forwardMostMove == 0)
7220 * Add time to clocks when time control is achieved.
7223 if ((forwardMostMove % (localPlayer.appData.movesPerSession * 2)) == 0)
7225 blackTimeRemaining += timeControl;
7226 whiteTimeRemaining += timeControl;
7236 DisplayTimerLabel(localPlayer.blackTimerWidget, "Black",
7237 blackTimeRemaining);
7238 DisplayTimerLabel(localPlayer.whiteTimerWidget, "White",
7239 whiteTimeRemaining);
7241 if (updateRemotePlayer)
7243 DisplayTimerLabel(remotePlayer.blackTimerWidget, "Black",
7244 blackTimeRemaining);
7245 DisplayTimerLabel(remotePlayer.whiteTimerWidget, "White",
7246 whiteTimeRemaining);
7253 #ifdef HAVE_GETTIMEOFDAY
7254 static struct timeval tickStartTV;
7255 static int tickLength;
7258 PartialTickLength(void)
7263 gettimeofday(&tv, NULL);
7264 ptl = ((tv.tv_sec - tickStartTV.tv_sec) * 1000000 +
7265 (tv.tv_usec - tickStartTV.tv_usec) + 500) / 1000;
7267 if (ptl > tickLength)
7272 #else /* !HAVE_GETTIMEOFDAY */
7273 #define tickLength 1000
7274 #endif /* HAVE_GETTIMEOFDAY */
7280 * DisplayClocks manages the game clocks.
7282 * In tournament play, white starts the clock and then black makes a move.
7283 * We give the human user a slight advantage if he is playing black---the
7284 * clocks don't run until he makes his first move, so it takes zero time.
7285 * Also, DisplayClocks doesn't account for network lag so it could get out
7286 * of sync with GNU Shogi's clock -- but then, referees are always right.
7290 DisplayClocks(int clock_mode)
7297 /* Stop clocks and reset to a fresh time control */
7300 XtRemoveTimeOut(timerXID);
7304 blackTimeRemaining = timeControl;
7305 whiteTimeRemaining = timeControl;
7307 if (blackFlag || whiteFlag)
7310 blackFlag = whiteFlag = False;
7316 case DecrementTimers:
7317 /* Decrement running clock to next 1-second boundary */
7318 if (gameMode == PauseGame)
7323 if (!localPlayer.appData.clockMode)
7326 if (BlackOnMove(forwardMostMove))
7328 timeRemaining = (blackTimeRemaining -= tickLength);
7332 timeRemaining = (whiteTimeRemaining -= tickLength);
7338 #ifdef HAVE_GETTIMEOFDAY
7339 tickLength = (((timeRemaining <= 1000) && (timeRemaining > 0))
7341 gettimeofday(&tickStartTV, NULL);
7342 #endif /* HAVE_GETTIMEOFDAY */
7345 XtAppAddTimeOut(appContext, tickLength,
7346 (XtTimerCallbackProc) DisplayClocks,
7347 (XtPointer) DecrementTimers);
7351 /* A player has just moved, so stop the previously running
7352 clock and start the other one. */
7356 XtRemoveTimeOut(timerXID);
7359 #ifdef HAVE_GETTIMEOFDAY
7360 if (localPlayer.appData.clockMode)
7362 if (BlackOnMove(forwardMostMove))
7363 whiteTimeRemaining -= PartialTickLength();
7365 blackTimeRemaining -= PartialTickLength();
7368 #endif /* HAVE_GETTIMEOFDAY */
7374 if (!localPlayer.appData.clockMode)
7377 if ((gameMode == PauseGame)
7378 && ((pausePreviousMode == MachinePlaysBlack)
7379 || (pausePreviousMode == MachinePlaysWhite)))
7384 timeRemaining = (BlackOnMove(forwardMostMove)
7385 ? blackTimeRemaining : whiteTimeRemaining);
7387 #ifdef HAVE_GETTIMEOFDAY
7388 tickLength = (((timeRemaining <= 1000) && (timeRemaining > 0))
7389 ? (((timeRemaining - 1) % 100) + 1)
7390 : (((timeRemaining - 1) % 1000) + 1));
7392 if (tickLength <= 0)
7395 gettimeofday(&tickStartTV, NULL);
7397 #endif /* HAVE_GETTIMEOFDAY */
7399 XtAppAddTimeOut(appContext, tickLength,
7400 (XtTimerCallbackProc) DisplayClocks,
7401 (XtPointer) DecrementTimers);
7404 case ReDisplayTimers:
7405 /* Display current clock values */
7410 /* Stop both clocks */
7414 XtRemoveTimeOut(timerXID);
7417 if (!localPlayer.appData.clockMode)
7420 #ifdef HAVE_GETTIMEOFDAY
7421 if (BlackOnMove(forwardMostMove))
7422 blackTimeRemaining -= PartialTickLength();
7424 whiteTimeRemaining -= PartialTickLength();
7427 #endif /* HAVE_GETTIMEOFDAY */
7431 /* Start clock of player on move, if not already running. */
7437 if (!localPlayer.appData.clockMode)
7440 timeRemaining = (BlackOnMove(forwardMostMove)
7441 ? blackTimeRemaining : whiteTimeRemaining);
7443 if (timeRemaining == 0)
7446 #ifdef HAVE_GETTIMEOFDAY
7447 tickLength = (((timeRemaining <= 1000) && (timeRemaining > 0))
7448 ? (((timeRemaining - 1) % 100) + 1)
7449 : (((timeRemaining - 1) % 1000) + 1));
7451 if (tickLength <= 0)
7454 gettimeofday(&tickStartTV, NULL);
7455 #endif /* HAVE_GETTIMEOFDAY */
7458 XtAppAddTimeOut(appContext, tickLength,
7459 (XtTimerCallbackProc) DisplayClocks,
7460 (XtPointer)DecrementTimers);
7469 DisplayTimerLabel(Widget w, char *color, long int timer)
7473 struct DisplayData *player;
7475 player = (((w == localPlayer.blackTimerWidget)
7476 || (w == localPlayer.whiteTimerWidget))
7477 ? &localPlayer : &remotePlayer);
7479 if (localPlayer.appData.clockMode)
7481 sprintf(buf, "%s: %s", color, TimeString(timer));
7482 XtSetArg(args[0], XtNlabel, buf);
7486 XtSetArg(args[0], XtNlabel, color);
7489 if (((color[0] == 'W') && BlackOnMove(forwardMostMove))
7490 || ((color[0] == 'B') && !BlackOnMove(forwardMostMove)))
7492 XtSetArg(args[1], XtNbackground, player->timerForegroundPixel);
7493 XtSetArg(args[2], XtNforeground, player->timerBackgroundPixel);
7497 XtSetArg(args[1], XtNbackground, player->timerBackgroundPixel);
7498 XtSetArg(args[2], XtNforeground, player->timerForegroundPixel);
7501 XtSetValues(w, args, 3);
7510 int second, minute, hour, day;
7512 static char buf[32];
7514 if ((tm > 0) && (tm <= 900))
7516 /* convert milliseconds to tenths, rounding up */
7517 sprintf(buf, " 0.%1ld ", (tm + 99) / 100);
7521 /* convert milliseconds to seconds, rounding up */
7522 tm = (tm + 999) / 1000;
7530 if (tm >= (60 * 60 * 24))
7532 day = (int)(tm / (60 * 60 * 24));
7533 tm -= day * 60 * 60 * 24;
7540 if (tm >= (60 * 60))
7542 hour = (int)(tm / (60 * 60));
7543 tm -= hour * 60 * 60;
7552 minute = (int)(tm / 60);
7564 sprintf(buf, " %s%d:%02d:%02d:%02d ",
7565 sign, day, hour, minute, second);
7569 sprintf(buf, " %s%d:%02d:%02d ",
7570 sign, hour, minute, second);
7574 sprintf(buf, " %s%2d:%02d ",
7575 sign, minute, second);
7587 fprintf(stderr, "Usage: %s\n", programName);
7588 fprintf(stderr, "\tstandard Xt options\n");
7589 fprintf(stderr, "\t-iconic\n");
7590 fprintf(stderr, "\t-tc or -timeControl minutes[:seconds]\n");
7591 fprintf(stderr, "\t-gi or -gameIn (True | False)\n");
7592 fprintf(stderr, "\t-mps or -movesPerSession moves\n");
7593 fprintf(stderr, "\t-st or -searchTime minutes[:seconds]\n");
7594 fprintf(stderr, "\t-sd or -searchDepth number\n");
7595 fprintf(stderr, "\t-clock or -clockMode (True | False)\n");
7596 fprintf(stderr, "\t-td or -timeDelay seconds\n");
7598 fprintf(stderr, "\t-nsp or -noShogiProgram (True | False)\n");
7599 fprintf(stderr, "\t-fsp or -firstShogiProgram program_name\n");
7600 fprintf(stderr, "\t-ssp or -secondShogiProgram program_name\n");
7601 fprintf(stderr, "\t-fh or -firstHost host_name\n");
7602 fprintf(stderr, "\t-sh or -secondHost host_name\n");
7603 fprintf(stderr, "\t-rsh or -remoteShell shell_name\n");
7605 "\t-mm or -matchMode (False | Init | Position | Opening)\n");
7606 fprintf(stderr, "\t-lgf or -loadGameFile file_name\n");
7607 fprintf(stderr, "\t-lpf or -loadPositionFile file_name\n");
7608 fprintf(stderr, "\t-sgf or -saveGameFile file_name\n");
7609 fprintf(stderr, "\t-spf or -savePositionFile file_name\n");
7610 fprintf(stderr, "\t-size or -boardSize (Large | Medium | Small)\n");
7611 fprintf(stderr, "\t-coords or -showCoords (True | False)\n");
7612 fprintf(stderr, "\t-mono or -monoMode (True | False)\n");
7613 fprintf(stderr, "\t-pc or -pieceColor color\n");
7614 fprintf(stderr, "\t-sc or -squareColor color\n");
7615 fprintf(stderr, "\t-wps or -westernPieceSet (True | False)\n");
7616 fprintf(stderr, "\t-debug or -debugMode (True | False)\n");
7623 CatchPipeSignal(int dummy)
7625 char message[MSG_SIZ];
7628 "%s shogi program (%s) exited unexpectedly",
7629 ((lastMsgFP == toFirstProgFP) ? "first" : "second"),
7630 ((lastMsgFP == toFirstProgFP)
7631 ? localPlayer.appData.firstShogiProgram
7632 : localPlayer.appData.secondShogiProgram));
7633 fprintf(stderr, "%s: %s\n", programName, message);
7634 ShutdownShogiPrograms(message);