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>
100 #include "bitmaps.h" /* Piece bitmaps. */
101 #include "xshogifn.h" /* Forward declarations. */
103 #define off_board(x) ((x < 2) || (x > BOARD_SIZE + 1))
106 /**********************************************************************
108 * Global variables, structs etc.
110 **********************************************************************/
113 * NOTE: XShogi depends on Xt R4 or higher
116 int xtVersion = XtSpecificationRelease;
118 XtIntervalId firstProgramXID = 0, secondProgramXID = 0,
119 readGameXID = 0, timerXID = 0, blinkSquareXID = 0;
121 XtAppContext appContext;
123 Boolean (*fileProc) (char *name);
125 FILE *fromFirstProgFP, *toFirstProgFP, *fromSecondProgFP,
126 *toSecondProgFP, *gameFileFP, *lastMsgFP;
128 int currentMove = 0, forwardMostMove = 0, backwardMostMove = 0,
130 secondProgramPID = 0, fromX = -1,
131 fromY = -1, firstMove = True, flipView = False,
132 xshogiDebug = True, commentUp = False, filenameUp = False,
133 whitePlaysFirst = False, startedFromSetupPosition = False,
134 searchTime = 0, pmFromX = -1, pmFromY = -1,
135 blackFlag = False, whiteFlag = False, maybeThinking = False,
138 int at_least_gnushogi_1_2p03 = False;
140 int firstSendTime = 2, secondSendTime = 2; /* 0 = don't, 1 = do,
143 MatchMode matchMode = MatchFalse;
144 GameMode gameMode = BeginningOfGame;
145 GameMode lastGameMode = BeginningOfGame;
146 GameMode pausePreviousMode = BeginningOfGame;
148 char moveList[MAX_MOVES][MOVE_LEN], parseList[MAX_MOVES][MOVE_LEN * 2],
149 ptyname[24], *shogiDir, *programName;
151 char endMessage[MOVE_LEN * 4];
153 long blackTimeRemaining, whiteTimeRemaining, timeControl;
154 long timeRemaining[2][MAX_MOVES];
156 extern char currentMoveString[];
158 int updateRemotePlayer = False;
160 Catched catches[MAX_MOVES];
162 #define DIMENSION 100
164 Widget blackPieceMenu, whitePieceMenu, commentShell;
166 XSetWindowAttributes attr;
184 #define NO_SQUARES 81
189 char catchedIndexToChar[8] =
191 'P', 'L', 'N', 'S', 'G', 'B', 'R', 'K'
194 ShogiSquare catchedIndexToPiece[2][8] =
197 BlackPawn, BlackLance, BlackKnight, BlackSilver, BlackGold,
198 BlackBishop, BlackRook, BlackKing
201 WhitePawn, WhiteLance, WhiteKnight, WhiteSilver, WhiteGold,
202 WhiteBishop, WhiteRook, WhiteKing
207 int pieceToCatchedIndex[] =
209 pawn, lance, knight, silver, gold, bishop, rook,
210 pawn, lance, knight, silver, bishop, rook, king,
211 pawn, lance, knight, silver, gold, bishop, rook,
212 pawn, lance, knight, silver, bishop, rook, king,
218 Board boards[MAX_MOVES];
219 Board initialPosition =
221 { BlackLance, BlackKnight, BlackSilver, BlackGold, BlackKing,
222 BlackGold, BlackSilver, BlackKnight, BlackLance },
223 { EmptySquare, BlackBishop, EmptySquare, EmptySquare, EmptySquare,
224 EmptySquare, EmptySquare, BlackRook, EmptySquare },
225 { BlackPawn, BlackPawn, BlackPawn, BlackPawn, BlackPawn,
226 BlackPawn, BlackPawn, BlackPawn, BlackPawn },
227 { EmptySquare, EmptySquare, EmptySquare, EmptySquare, EmptySquare,
228 EmptySquare, EmptySquare, EmptySquare, EmptySquare } ,
229 { EmptySquare, EmptySquare, EmptySquare, EmptySquare, EmptySquare,
230 EmptySquare, EmptySquare, EmptySquare, EmptySquare } ,
231 { EmptySquare, EmptySquare, EmptySquare, EmptySquare, EmptySquare,
232 EmptySquare, EmptySquare, EmptySquare, EmptySquare } ,
233 { WhitePawn, WhitePawn, WhitePawn, WhitePawn, WhitePawn,
234 WhitePawn, WhitePawn, WhitePawn, WhitePawn },
235 { EmptySquare, WhiteRook, EmptySquare, EmptySquare, EmptySquare,
236 EmptySquare, EmptySquare, WhiteBishop, EmptySquare },
237 { WhiteLance, WhiteKnight, WhiteSilver, WhiteGold, WhiteKing,
238 WhiteGold, WhiteSilver, WhiteKnight, WhiteLance }
241 String gnuButtonStrings[] =
243 "Quit", "Load Game", "Machine White", "Forward",
244 "Reset", "Load Position", "Machine Black", "Backward",
245 "Flip View", "Save Game", "Force Moves", "Pause",
246 "Hint", "Save Position", "Two Machines", "Edit Position",
247 "Challenge", "Select Level", "Move NOW",
250 /* must be in same order as buttonStrings! */
251 XtActionProc gnuButtonProcs[] =
253 QuitProc, LoadGameProc, MachineWhiteProc, ForwardProc,
254 ResetProc, LoadPositionProc, MachineBlackProc, BackwardProc,
255 FlipViewProc, SaveGameProc, ForceProc, PauseProc,
256 HintProc, SavePositionProc, TwoMachinesProc, EditPositionProc,
257 ChallengeProc, SelectLevelProc, MoveNowProc,
262 String *buttonStrings;
263 XtActionProc *buttonProcs;
266 #define PIECE_MENU_SIZE 18
268 String pieceMenuStrings[PIECE_MENU_SIZE] =
270 "----", "Pawn", "Lance", "Knight", "Silver",
271 "Gold", "Bishop", "Rook",
272 "PPawn", "PLance", "PKnight", "PSilver",
273 "PBishop", "PRook", "King",
274 "----", "Empty square", "Clear board"
277 /* must be in same order as PieceMenuStrings! */
278 ShogiSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] =
281 (ShogiSquare) 0, BlackPawn, BlackLance, BlackKnight,
282 BlackSilver, BlackGold, BlackBishop, BlackRook,
283 BlackPPawn, BlackPLance, BlackPKnight, BlackPSilver,
284 BlackPBishop, BlackPRook, BlackKing,
285 (ShogiSquare) 0, EmptySquare, ClearBoard
288 (ShogiSquare) 0, WhitePawn, WhiteLance, WhiteKnight,
289 WhiteSilver, WhiteGold, WhiteBishop, WhiteRook,
290 WhitePPawn, WhitePLance, WhitePKnight, WhitePSilver,
291 WhitePBishop, WhitePRook, WhiteKing,
292 (ShogiSquare) 0, EmptySquare, ClearBoard
301 Pixel charPieceColor;
304 Boolean westernPieceSet;
309 String firstShogiProgram;
310 String secondShogiProgram;
311 Boolean noShogiProgram;
314 String reverseBigSolidBitmap;
315 String reverseSmallSolidBitmap;
316 String normalBigSolidBitmap;
317 String normalSmallSolidBitmap;
318 String reversePawnBitmap;
319 String reverseLanceBitmap;
320 String reverseKnightBitmap;
321 String reverseSilverBitmap;
322 String reverseGoldBitmap;
323 String reverseRookBitmap;
324 String reverseBishopBitmap;
325 String reversePPawnBitmap;
326 String reversePLanceBitmap;
327 String reversePKnightBitmap;
328 String reversePSilverBitmap;
329 String reversePBishopBitmap;
330 String reversePRookBitmap;
331 String reverseKingBitmap;
332 String normalPawnBitmap;
333 String normalLanceBitmap;
334 String normalKnightBitmap;
335 String normalSilverBitmap;
336 String normalGoldBitmap;
337 String normalRookBitmap;
338 String normalBishopBitmap;
339 String normalPPawnBitmap;
340 String normalPLanceBitmap;
341 String normalPKnightBitmap;
342 String normalPSilverBitmap;
343 String normalPBishopBitmap;
344 String normalPRookBitmap;
345 String normalKingBitmap;
351 Boolean autoSaveGames;
353 String loadPositionFile;
355 String savePositionFile;
357 String challengeDisplay;
368 Boolean ringBellAfterMoves;
369 Boolean autoCallFlag;
372 } AppData, *AppDataPtr;
375 XtResource clientResources[] =
378 "pieceColor", "pieceColor", XtRPixel, sizeof(Pixel),
379 XtOffset(AppDataPtr, pieceColor), XtRString,
383 "charPieceColor", "CharPieceColor", XtRPixel, sizeof(Pixel),
384 XtOffset(AppDataPtr, charPieceColor), XtRString,
388 "oneColor", "OneColor", XtRPixel, sizeof(Pixel),
389 XtOffset(AppDataPtr, oneColor), XtRString,
393 "zeroColor", "ZeroColor", XtRPixel, sizeof(Pixel),
394 XtOffset(AppDataPtr, zeroColor), XtRString,
398 "squareColor", "squareColor", XtRPixel,
399 sizeof(Pixel), XtOffset(AppDataPtr, squareColor),
400 XtRString, SQUARE_COLOR
403 "westernPieceSet", "WesternPieceSet", XtRBoolean, sizeof(Boolean),
404 XtOffset(AppDataPtr, westernPieceSet), XtRString,
408 "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
409 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
410 (XtPointer) MOVES_PER_SESSION
413 "initString", "initString", XtRString, sizeof(String),
414 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING
417 "blackString", "blackString", XtRString, sizeof(String),
418 XtOffset(AppDataPtr, blackString), XtRString, BLACK_STRING
421 "whiteString", "whiteString", XtRString, sizeof(String),
422 XtOffset(AppDataPtr, whiteString), XtRString, WHITE_STRING
425 "firstShogiProgram", "firstShogiProgram", XtRString,
426 sizeof(String), XtOffset(AppDataPtr, firstShogiProgram),
427 XtRString, FIRST_SHOGI_PROGRAM
430 "secondShogiProgram", "secondShogiProgram", XtRString,
431 sizeof(String), XtOffset(AppDataPtr, secondShogiProgram),
432 XtRString, SECOND_SHOGI_PROGRAM
435 "noShogiProgram", "noShogiProgram", XtRBoolean,
436 sizeof(Boolean), XtOffset(AppDataPtr, noShogiProgram),
437 XtRImmediate, (XtPointer) False
440 "firstHost", "firstHost", XtRString, sizeof(String),
441 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST
444 "secondHost", "secondHost", XtRString, sizeof(String),
445 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST
448 "reversePawnBitmap", "reversePawnBitmap", XtRString,
449 sizeof(String), XtOffset(AppDataPtr, reversePawnBitmap),
453 "reverseLanceBitmap", "reverseLanceBitmap", XtRString,
454 sizeof(String), XtOffset(AppDataPtr, reverseLanceBitmap),
458 "reverseKnightBitmap", "reverseKnightBitmap", XtRString,
459 sizeof(String), XtOffset(AppDataPtr, reverseKnightBitmap),
463 "reverseSilverBitmap", "reverseSilverBitmap", XtRString,
464 sizeof(String), XtOffset(AppDataPtr, reverseSilverBitmap),
468 "reverseGoldBitmap", "reverseGoldBitmap", XtRString,
469 sizeof(String), XtOffset(AppDataPtr, reverseGoldBitmap),
473 "reverseRookBitmap", "reverseRookBitmap", XtRString,
474 sizeof(String), XtOffset(AppDataPtr, reverseRookBitmap),
478 "reverseBishopBitmap", "reverseBishopBitmap", XtRString,
479 sizeof(String), XtOffset(AppDataPtr, reverseBishopBitmap),
483 "reversePPawnBitmap", "reversePPawnBitmap", XtRString,
484 sizeof(String), XtOffset(AppDataPtr, reversePPawnBitmap),
488 "reversePLanceBitmap", "reversePLanceBitmap", XtRString,
489 sizeof(String), XtOffset(AppDataPtr, reversePLanceBitmap),
493 "reversePKnightBitmap", "reversePKnightBitmap", XtRString,
494 sizeof(String), XtOffset(AppDataPtr, reversePKnightBitmap),
498 "reversePSilverBitmap", "reversePSilverBitmap", XtRString,
499 sizeof(String), XtOffset(AppDataPtr, reversePSilverBitmap),
503 "reversePRookBitmap", "reversePRookBitmap", XtRString,
504 sizeof(String), XtOffset(AppDataPtr, reversePRookBitmap),
508 "reversePBishopBitmap", "reversePBishopBitmap", XtRString,
509 sizeof(String), XtOffset(AppDataPtr, reversePBishopBitmap),
513 "reverseKingBitmap", "reverseKingBitmap", XtRString,
514 sizeof(String), XtOffset(AppDataPtr, reverseKingBitmap),
518 "normalPawnBitmap", "normalPawnBitmap", XtRString,
519 sizeof(String), XtOffset(AppDataPtr, normalPawnBitmap),
523 "normalLanceBitmap", "normalLanceBitmap", XtRString,
524 sizeof(String), XtOffset(AppDataPtr, normalLanceBitmap),
528 "normalKnightBitmap", "normalKnightBitmap", XtRString,
529 sizeof(String), XtOffset(AppDataPtr, normalKnightBitmap),
533 "normalSilverBitmap", "normalSilverBitmap", XtRString,
534 sizeof(String), XtOffset(AppDataPtr, normalSilverBitmap),
538 "normalGoldBitmap", "normalGoldBitmap", XtRString,
539 sizeof(String), XtOffset(AppDataPtr, normalGoldBitmap),
543 "normalBishopBitmap", "normalBishopBitmap", XtRString,
544 sizeof(String), XtOffset(AppDataPtr, normalBishopBitmap),
548 "normalRookBitmap", "normalRookBitmap", XtRString,
549 sizeof(String), XtOffset(AppDataPtr, normalRookBitmap),
553 "normalPPawnBitmap", "normalPPawnBitmap", XtRString,
554 sizeof(String), XtOffset(AppDataPtr, normalPPawnBitmap),
558 "normalPLanceBitmap", "normalPLanceBitmap", XtRString,
559 sizeof(String), XtOffset(AppDataPtr, normalPLanceBitmap),
563 "normalPKnightBitmap", "normalPKnightBitmap", XtRString,
564 sizeof(String), XtOffset(AppDataPtr, normalPKnightBitmap),
568 "normalPSilverBitmap", "normalPSilverBitmap", XtRString,
569 sizeof(String), XtOffset(AppDataPtr, normalPSilverBitmap),
573 "normalPBishopBitmap", "normalPBishopBitmap", XtRString,
574 sizeof(String), XtOffset(AppDataPtr, normalPBishopBitmap),
578 "normalPRookBitmap", "normalPRookBitmap", XtRString,
579 sizeof(String), XtOffset(AppDataPtr, normalPRookBitmap),
583 "normalKingBitmap", "normalKingBitmap", XtRString,
584 sizeof(String), XtOffset(AppDataPtr, normalKingBitmap),
588 "remoteShell", "remoteShell", XtRString, sizeof(String),
589 XtOffset(AppDataPtr, remoteShell), XtRString, "rsh"
592 "timeDelay", "timeDelay", XtRFloat, sizeof(float),
593 XtOffset(AppDataPtr, timeDelay), XtRString,
594 (XtPointer) TIME_DELAY
597 "timeControl", "timeControl", XtRString, sizeof(String),
598 XtOffset(AppDataPtr, timeControl), XtRString,
599 (XtPointer) TIME_CONTROL
603 XtRBoolean, sizeof(Boolean),
604 XtOffset(AppDataPtr, gameIn), XtRImmediate,
608 "autoSaveGames", "autoSaveGames", XtRBoolean,
609 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
610 XtRImmediate, (XtPointer) False
613 "loadGameFile", "loadGameFile", XtRString, sizeof(String),
614 XtOffset(AppDataPtr, loadGameFile), XtRString, NULL
617 "loadPositionFile", "loadPositionFile", XtRString,
618 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
622 "saveGameFile", "saveGameFile", XtRString, sizeof(String),
623 XtOffset(AppDataPtr, saveGameFile), XtRString, ""
626 "savePositionFile", "savePositionFile", XtRString,
627 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
631 "challengeDisplay", "challengeDisplay", XtRString,
632 sizeof(String), XtOffset(AppDataPtr, challengeDisplay),
636 "matchMode", "matchMode", XtRString, sizeof(String),
637 XtOffset(AppDataPtr, matchMode), XtRString, MATCH_MODE
640 "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
641 XtOffset(AppDataPtr, monoMode), XtRImmediate,
645 "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
646 XtOffset(AppDataPtr, debugMode), XtRImmediate,
650 "Iconic", "Iconic", XtRBoolean, sizeof(Boolean),
651 XtOffset(AppDataPtr, Iconic), XtRImmediate,
655 "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
656 XtOffset(AppDataPtr, clockMode), XtRImmediate,
660 "autoCallFlag", "autoCallFlag", XtRBoolean,
661 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
662 XtRImmediate, (XtPointer) False
665 "boardSize", "boardSize", XtRString, sizeof(String),
666 XtOffset(AppDataPtr, boardSize), XtRString, DEFAULT_SIZE
669 "searchTime", "searchTime", XtRString, sizeof(String),
670 XtOffset(AppDataPtr, searchTime), XtRString,
674 "searchDepth", "searchDepth", XtRInt, sizeof(int),
675 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
679 "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
680 XtOffset(AppDataPtr, showCoords), XtRImmediate,
684 "mainFont", "mainFont", XtRString, sizeof(String),
685 XtOffset(AppDataPtr, mainFont), XtRString, MAIN_FONT
688 "coordFont", "coordFont", XtRString, sizeof(String),
689 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT
692 "ringBellAfterMoves", "ringBellAfterMoves",
693 XtRBoolean, sizeof(Boolean),
694 XtOffset(AppDataPtr, ringBellAfterMoves),
695 XtRImmediate, (XtPointer) False
698 "borderXoffset", "borderXoffset", XtRInt, sizeof(int),
699 XtOffset(AppDataPtr, borderXoffset), XtRImmediate,
700 (XtPointer) BORDER_X_OFFSET
703 "borderYoffset", "borderYOffset", XtRInt, sizeof(int),
704 XtOffset(AppDataPtr, borderYoffset), XtRImmediate,
705 (XtPointer) BORDER_Y_OFFSET
721 Pixmap reversePawnBitmap, reverseLanceBitmap, reverseKnightBitmap,
723 reverseGoldBitmap, reverseBishopBitmap, reverseRookBitmap,
724 reversePPawnBitmap, reversePLanceBitmap, reversePKnightBitmap,
725 reversePSilverBitmap, reversePBishopBitmap, reversePRookBitmap,
727 reverseBigSolidBitmap, reverseSmallSolidBitmap,
728 normalBigSolidBitmap, normalSmallSolidBitmap,
729 normalPawnBitmap, normalLanceBitmap, normalKnightBitmap,
730 normalSilverBitmap, normalGoldBitmap,
731 normalBishopBitmap, normalRookBitmap,
732 normalPPawnBitmap, normalPLanceBitmap, normalPKnightBitmap,
733 normalPSilverBitmap, normalPBishopBitmap, normalPRookBitmap,
741 GC squareGC, lineGC, pieceGC, oPieceGC, charPieceGC,
742 squareOffBoardGC, coordGC, dropPiece;
744 Font mainFontID, coordFontID;
745 XFontStruct *mainFontStruct, *coordFontStruct;
747 Widget shellWidget, formWidget, boardWidget,
748 commandsWidget, messageWidget,
749 blackTimerWidget, whiteTimerWidget,
750 titleWidget, widgetList[6],
752 filemodeShell, challengeWidget;
754 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
756 Pixel timerForegroundPixel, timerBackgroundPixel;
760 int black_pixel_is_zero;
764 Boolean monoMode, showCoords, Iconic;
769 struct DisplayData localPlayer, remotePlayer;
778 static PromotionMoveInfo pmi; /* making this global is gross */
781 Pixmap *pieceToReverse[2][28] =
784 &localPlayer.reversePawnBitmap,
785 &localPlayer.reverseLanceBitmap,
786 &localPlayer.reverseKnightBitmap,
787 &localPlayer.reverseSilverBitmap,
788 &localPlayer.reverseGoldBitmap,
789 &localPlayer.reverseBishopBitmap,
790 &localPlayer.reverseRookBitmap,
791 &localPlayer.reversePPawnBitmap,
792 &localPlayer.reversePLanceBitmap,
793 &localPlayer.reversePKnightBitmap,
794 &localPlayer.reversePSilverBitmap,
795 &localPlayer.reversePBishopBitmap,
796 &localPlayer.reversePRookBitmap,
797 &localPlayer.reverseKingBitmap,
798 &localPlayer.reversePawnBitmap,
799 &localPlayer.reverseLanceBitmap,
800 &localPlayer.reverseKnightBitmap,
801 &localPlayer.reverseSilverBitmap,
802 &localPlayer.reverseGoldBitmap,
803 &localPlayer.reverseBishopBitmap,
804 &localPlayer.reverseRookBitmap,
805 &localPlayer.reversePPawnBitmap,
806 &localPlayer.reversePLanceBitmap,
807 &localPlayer.reversePKnightBitmap,
808 &localPlayer.reversePSilverBitmap,
809 &localPlayer.reversePBishopBitmap,
810 &localPlayer.reversePRookBitmap,
811 &localPlayer.reverseKingBitmap
814 &remotePlayer.reversePawnBitmap,
815 &remotePlayer.reverseLanceBitmap,
816 &remotePlayer.reverseKnightBitmap,
817 &remotePlayer.reverseSilverBitmap,
818 &remotePlayer.reverseGoldBitmap,
819 &remotePlayer.reverseBishopBitmap,
820 &remotePlayer.reverseRookBitmap,
821 &remotePlayer.reversePPawnBitmap,
822 &remotePlayer.reversePLanceBitmap,
823 &remotePlayer.reversePKnightBitmap,
824 &remotePlayer.reversePSilverBitmap,
825 &remotePlayer.reversePBishopBitmap,
826 &remotePlayer.reversePRookBitmap,
827 &remotePlayer.reverseKingBitmap,
828 &remotePlayer.reversePawnBitmap,
829 &remotePlayer.reverseLanceBitmap,
830 &remotePlayer.reverseKnightBitmap,
831 &remotePlayer.reverseSilverBitmap,
832 &remotePlayer.reverseGoldBitmap,
833 &remotePlayer.reverseBishopBitmap,
834 &remotePlayer.reverseRookBitmap,
835 &remotePlayer.reversePPawnBitmap,
836 &remotePlayer.reversePLanceBitmap,
837 &remotePlayer.reversePKnightBitmap,
838 &remotePlayer.reversePSilverBitmap,
839 &remotePlayer.reversePBishopBitmap,
840 &remotePlayer.reversePRookBitmap,
841 &remotePlayer.reverseKingBitmap
847 Pixmap *pieceToNormal[2][28] =
850 &localPlayer.normalPawnBitmap,
851 &localPlayer.normalLanceBitmap,
852 &localPlayer.normalKnightBitmap,
853 &localPlayer.normalSilverBitmap,
854 &localPlayer.normalGoldBitmap,
855 &localPlayer.normalBishopBitmap,
856 &localPlayer.normalRookBitmap,
857 &localPlayer.normalPPawnBitmap,
858 &localPlayer.normalPLanceBitmap,
859 &localPlayer.normalPKnightBitmap,
860 &localPlayer.normalPSilverBitmap,
861 &localPlayer.normalPBishopBitmap,
862 &localPlayer.normalPRookBitmap,
863 &localPlayer.normalKingBitmap,
864 &localPlayer.normalPawnBitmap,
865 &localPlayer.normalLanceBitmap,
866 &localPlayer.normalKnightBitmap,
867 &localPlayer.normalSilverBitmap,
868 &localPlayer.normalGoldBitmap,
869 &localPlayer.normalBishopBitmap,
870 &localPlayer.normalRookBitmap,
871 &localPlayer.normalPPawnBitmap,
872 &localPlayer.normalPLanceBitmap,
873 &localPlayer.normalPKnightBitmap,
874 &localPlayer.normalPSilverBitmap,
875 &localPlayer.normalPBishopBitmap,
876 &localPlayer.normalPRookBitmap,
877 &localPlayer.normalKingBitmap
880 &remotePlayer.normalPawnBitmap,
881 &remotePlayer.normalLanceBitmap,
882 &remotePlayer.normalKnightBitmap,
883 &remotePlayer.normalSilverBitmap,
884 &remotePlayer.normalGoldBitmap,
885 &remotePlayer.normalBishopBitmap,
886 &remotePlayer.normalRookBitmap,
887 &remotePlayer.normalPPawnBitmap,
888 &remotePlayer.normalPLanceBitmap,
889 &remotePlayer.normalPKnightBitmap,
890 &remotePlayer.normalPSilverBitmap,
891 &remotePlayer.normalPBishopBitmap,
892 &remotePlayer.normalPRookBitmap,
893 &remotePlayer.normalKingBitmap,
894 &remotePlayer.normalPawnBitmap,
895 &remotePlayer.normalLanceBitmap,
896 &remotePlayer.normalKnightBitmap,
897 &remotePlayer.normalSilverBitmap,
898 &remotePlayer.normalGoldBitmap,
899 &remotePlayer.normalBishopBitmap,
900 &remotePlayer.normalRookBitmap,
901 &remotePlayer.normalPPawnBitmap,
902 &remotePlayer.normalPLanceBitmap,
903 &remotePlayer.normalPKnightBitmap,
904 &remotePlayer.normalPSilverBitmap,
905 &remotePlayer.normalPBishopBitmap,
906 &remotePlayer.normalPRookBitmap,
907 &remotePlayer.normalKingBitmap
913 Pixmap *pieceToReverseSolid[2][28] =
916 &localPlayer.reverseSmallSolidBitmap,
917 &localPlayer.reverseSmallSolidBitmap,
918 &localPlayer.reverseSmallSolidBitmap,
919 &localPlayer.reverseBigSolidBitmap,
920 &localPlayer.reverseBigSolidBitmap,
921 &localPlayer.reverseBigSolidBitmap,
922 &localPlayer.reverseBigSolidBitmap,
923 &localPlayer.reverseSmallSolidBitmap,
924 &localPlayer.reverseSmallSolidBitmap,
925 &localPlayer.reverseSmallSolidBitmap,
926 &localPlayer.reverseBigSolidBitmap,
927 &localPlayer.reverseBigSolidBitmap,
928 &localPlayer.reverseBigSolidBitmap,
929 &localPlayer.reverseBigSolidBitmap,
930 &localPlayer.reverseSmallSolidBitmap,
931 &localPlayer.reverseSmallSolidBitmap,
932 &localPlayer.reverseSmallSolidBitmap,
933 &localPlayer.reverseBigSolidBitmap,
934 &localPlayer.reverseBigSolidBitmap,
935 &localPlayer.reverseBigSolidBitmap,
936 &localPlayer.reverseBigSolidBitmap,
937 &localPlayer.reverseSmallSolidBitmap,
938 &localPlayer.reverseSmallSolidBitmap,
939 &localPlayer.reverseSmallSolidBitmap,
940 &localPlayer.reverseBigSolidBitmap,
941 &localPlayer.reverseBigSolidBitmap,
942 &localPlayer.reverseBigSolidBitmap,
943 &localPlayer.reverseBigSolidBitmap
946 &remotePlayer.reverseSmallSolidBitmap,
947 &remotePlayer.reverseSmallSolidBitmap,
948 &remotePlayer.reverseSmallSolidBitmap,
949 &remotePlayer.reverseBigSolidBitmap,
950 &remotePlayer.reverseBigSolidBitmap,
951 &remotePlayer.reverseBigSolidBitmap,
952 &remotePlayer.reverseBigSolidBitmap,
953 &remotePlayer.reverseSmallSolidBitmap,
954 &remotePlayer.reverseSmallSolidBitmap,
955 &remotePlayer.reverseSmallSolidBitmap,
956 &remotePlayer.reverseBigSolidBitmap,
957 &remotePlayer.reverseBigSolidBitmap,
958 &remotePlayer.reverseBigSolidBitmap,
959 &remotePlayer.reverseBigSolidBitmap,
960 &remotePlayer.reverseSmallSolidBitmap,
961 &remotePlayer.reverseSmallSolidBitmap,
962 &remotePlayer.reverseSmallSolidBitmap,
963 &remotePlayer.reverseBigSolidBitmap,
964 &remotePlayer.reverseBigSolidBitmap,
965 &remotePlayer.reverseBigSolidBitmap,
966 &remotePlayer.reverseBigSolidBitmap,
967 &remotePlayer.reverseSmallSolidBitmap,
968 &remotePlayer.reverseSmallSolidBitmap,
969 &remotePlayer.reverseSmallSolidBitmap,
970 &remotePlayer.reverseBigSolidBitmap,
971 &remotePlayer.reverseBigSolidBitmap,
972 &remotePlayer.reverseBigSolidBitmap,
973 &remotePlayer.reverseBigSolidBitmap
979 Pixmap *pieceToNormalSolid[2][28] =
982 &localPlayer.normalSmallSolidBitmap,
983 &localPlayer.normalSmallSolidBitmap,
984 &localPlayer.normalSmallSolidBitmap,
985 &localPlayer.normalBigSolidBitmap,
986 &localPlayer.normalBigSolidBitmap,
987 &localPlayer.normalBigSolidBitmap,
988 &localPlayer.normalBigSolidBitmap,
989 &localPlayer.normalSmallSolidBitmap,
990 &localPlayer.normalSmallSolidBitmap,
991 &localPlayer.normalSmallSolidBitmap,
992 &localPlayer.normalBigSolidBitmap,
993 &localPlayer.normalBigSolidBitmap,
994 &localPlayer.normalBigSolidBitmap,
995 &localPlayer.normalBigSolidBitmap,
996 &localPlayer.normalSmallSolidBitmap,
997 &localPlayer.normalSmallSolidBitmap,
998 &localPlayer.normalSmallSolidBitmap,
999 &localPlayer.normalBigSolidBitmap,
1000 &localPlayer.normalBigSolidBitmap,
1001 &localPlayer.normalBigSolidBitmap,
1002 &localPlayer.normalBigSolidBitmap,
1003 &localPlayer.normalSmallSolidBitmap,
1004 &localPlayer.normalSmallSolidBitmap,
1005 &localPlayer.normalSmallSolidBitmap,
1006 &localPlayer.normalBigSolidBitmap,
1007 &localPlayer.normalBigSolidBitmap,
1008 &localPlayer.normalBigSolidBitmap,
1009 &localPlayer.normalBigSolidBitmap
1012 &remotePlayer.normalSmallSolidBitmap,
1013 &remotePlayer.normalSmallSolidBitmap,
1014 &remotePlayer.normalSmallSolidBitmap,
1015 &remotePlayer.normalBigSolidBitmap,
1016 &remotePlayer.normalBigSolidBitmap,
1017 &remotePlayer.normalBigSolidBitmap,
1018 &remotePlayer.normalBigSolidBitmap,
1019 &remotePlayer.normalSmallSolidBitmap,
1020 &remotePlayer.normalSmallSolidBitmap,
1021 &remotePlayer.normalSmallSolidBitmap,
1022 &remotePlayer.normalBigSolidBitmap,
1023 &remotePlayer.normalBigSolidBitmap,
1024 &remotePlayer.normalBigSolidBitmap,
1025 &remotePlayer.normalBigSolidBitmap,
1026 &remotePlayer.normalSmallSolidBitmap,
1027 &remotePlayer.normalSmallSolidBitmap,
1028 &remotePlayer.normalSmallSolidBitmap,
1029 &remotePlayer.normalBigSolidBitmap,
1030 &remotePlayer.normalBigSolidBitmap,
1031 &remotePlayer.normalBigSolidBitmap,
1032 &remotePlayer.normalBigSolidBitmap,
1033 &remotePlayer.normalSmallSolidBitmap,
1034 &remotePlayer.normalSmallSolidBitmap,
1035 &remotePlayer.normalSmallSolidBitmap,
1036 &remotePlayer.normalBigSolidBitmap,
1037 &remotePlayer.normalBigSolidBitmap,
1038 &remotePlayer.normalBigSolidBitmap,
1039 &remotePlayer.normalBigSolidBitmap
1045 int pieceIsPromoted[] =
1047 False, False, False, False, False, False, False,
1048 True, True, True, True, True, True, False,
1049 False, False, False, False, False, False, False,
1050 True, True, True, True, True, True, False,
1055 int piecePromotable[] =
1057 True, True, True, True, False, True, True,
1058 False, False, False, False, False, False, False,
1059 True, True, True, True, False, True, True,
1060 False, False, False, False, False, False, False,
1065 char pieceToChar[] =
1067 'P', 'L', 'N', 'S', 'G', 'B', 'R', 'P', 'L', 'N', 'S', 'B', 'R', 'K',
1068 'p', 'l', 'n', 's', 'g', 'b', 'r', 'p', 'l', 'n', 's', 'b', 'r', 'k',
1073 ShogiSquare pieceToPromoted[] =
1075 BlackPPawn, BlackPLance, BlackPKnight, BlackPSilver, BlackGold,
1076 BlackPBishop, BlackPRook,
1077 BlackPPawn, BlackPLance, BlackPKnight, BlackPSilver,
1078 BlackPBishop, BlackPRook, BlackKing,
1079 WhitePPawn, WhitePLance, WhitePKnight, WhitePSilver, WhiteGold,
1080 WhitePBishop, WhitePRook,
1081 WhitePPawn, WhitePLance, WhitePKnight, WhitePSilver,
1082 WhitePBishop, WhitePRook, WhiteKing
1087 XrmOptionDescRec shellOptions[] =
1089 { "-pieceColor", "pieceColor", XrmoptionSepArg, NULL },
1090 { "-pc", "pieceColor", XrmoptionSepArg, NULL },
1091 { "-charPieceColor", "charPieceColor", XrmoptionSepArg, NULL },
1092 { "-cpc", "charPieceColor", XrmoptionSepArg, NULL },
1093 { "-zeroColor", "zeroColor", XrmoptionSepArg, NULL },
1094 { "-zc", "zeroColor", XrmoptionSepArg, NULL },
1095 { "-oneColor", "oneColor", XrmoptionSepArg, NULL },
1096 { "-oc", "oneColor", XrmoptionSepArg, NULL },
1097 { "-squareColor", "squareColor", XrmoptionSepArg, NULL },
1098 { "-sc", "squareColor", XrmoptionSepArg, NULL },
1099 { "-westernPieceSet", "westernPieceSet", XrmoptionSepArg, NULL },
1100 { "-wps", "westernPieceSet", XrmoptionSepArg, NULL },
1101 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1102 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1103 { "-firstShogiProgram", "firstShogiProgram", XrmoptionSepArg, NULL },
1104 { "-fsp", "firstShogiProgram", XrmoptionSepArg, NULL },
1105 { "-secondShogiProgram", "secondShogiProgram", XrmoptionSepArg, NULL },
1106 { "-ssp", "secondShogiProgram", XrmoptionSepArg, NULL },
1107 { "-noShogiProgram", "noShogiProgram", XrmoptionSepArg, NULL },
1108 { "-nsp", "noShogiProgram", XrmoptionSepArg, NULL },
1109 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1110 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1111 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1112 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1113 { "-reversePawnBitmap", "reversePawnBitmap", XrmoptionSepArg, NULL },
1114 { "-rpb", "reversePawnBitmap", XrmoptionSepArg, NULL },
1115 { "-reverseLanceBitmap", "reverseLanceBitmap", XrmoptionSepArg, NULL },
1116 { "-rlb", "reverseLanceBitmap", XrmoptionSepArg, NULL },
1117 { "-reverseKnightBitmap", "reverseKnightBitmap", XrmoptionSepArg, NULL },
1118 { "-rnb", "reverseKnightBitmap", XrmoptionSepArg, NULL },
1119 { "-reverseSilverBitmap", "reverseSilverBitmap", XrmoptionSepArg, NULL },
1120 { "-rsb", "reverseSilverBitmap", XrmoptionSepArg, NULL },
1121 { "-reverseGoldBitmap", "reverseGoldBitmap", XrmoptionSepArg, NULL },
1122 { "-rgb", "reverseGoldBitmap", XrmoptionSepArg, NULL },
1123 { "-reverseRookBitmap", "reverseRookBitmap", XrmoptionSepArg, NULL },
1124 { "-rrb", "reverseRookBitmap", XrmoptionSepArg, NULL },
1125 { "-reverseBishopBitmap", "reverseBishopBitmap", XrmoptionSepArg, NULL },
1126 { "-rbb", "reverseBishopBitmap", XrmoptionSepArg, NULL },
1127 { "-reversePPawnBitmap", "reversePPawnBitmap",
1128 XrmoptionSepArg, NULL },
1129 { "-rppb", "reversePPawnBitmap", XrmoptionSepArg, NULL },
1130 { "-reversePLanceBitmap", "reversePLanceBitmap",
1131 XrmoptionSepArg, NULL },
1132 { "-rplb", "reversePLanceBitmap", XrmoptionSepArg, NULL },
1133 { "-reversePKnightBitmap", "reversePKnightBitmap",
1134 XrmoptionSepArg, NULL },
1135 { "-rpnb", "reversePKnightBitmap", XrmoptionSepArg, NULL },
1136 { "-reversePSilverBitmap", "reversePSilverBitmap",
1137 XrmoptionSepArg, NULL },
1138 { "-rpsb", "reversePSilverBitmap", XrmoptionSepArg, NULL },
1139 { "-reversePRookBitmap", "reversePRookBitmap",
1140 XrmoptionSepArg, NULL },
1141 { "-rprb", "reversePRookBitmap", XrmoptionSepArg, NULL },
1142 { "-reversePBishopBitmap", "reversePBishopBitmap",
1143 XrmoptionSepArg, NULL },
1144 { "-rpbb", "reversePBishopBitmap", XrmoptionSepArg, NULL },
1145 { "-reverseKingBitmap", "reverseKingBitmap", XrmoptionSepArg, NULL },
1146 { "-rkb", "reverseKingBitmap", XrmoptionSepArg, NULL },
1147 { "-outlinePawnBitmap", "outlinePawnBitmap", XrmoptionSepArg, NULL },
1148 { "-opb", "normalPawnBitmap", XrmoptionSepArg, NULL },
1149 { "-normalLanceBitmap", "normalLanceBitmap", XrmoptionSepArg, NULL },
1150 { "-olb", "normalLanceBitmap", XrmoptionSepArg, NULL },
1151 { "-normalKnightBitmap", "normalKnightBitmap", XrmoptionSepArg, NULL },
1152 { "-onb", "normalKnightBitmap", XrmoptionSepArg, NULL },
1153 { "-normalSilverBitmap", "normalSilverBitmap", XrmoptionSepArg, NULL },
1154 { "-osb", "normalSilverBitmap", XrmoptionSepArg, NULL },
1155 { "-normalGoldBitmap", "normalGoldBitmap", XrmoptionSepArg, NULL },
1156 { "-ogb", "normalGoldBitmap", XrmoptionSepArg, NULL },
1157 { "-normalRookBitmap", "normalRookBitmap", XrmoptionSepArg, NULL },
1158 { "-orb", "normalRookBitmap", XrmoptionSepArg, NULL },
1159 { "-normalBishopBitmap", "normalBishopBitmap", XrmoptionSepArg, NULL },
1160 { "-obb", "normalBishopBitmap", XrmoptionSepArg, NULL },
1161 { "-normalPPawnBitmap", "normalPPawnBitmap", XrmoptionSepArg, NULL },
1162 { "-oppb", "normalPPawnBitmap", XrmoptionSepArg, NULL },
1163 { "-normalPLanceBitmap", "normalPLanceBitmap", XrmoptionSepArg, NULL },
1164 { "-oplb", "normalPLanceBitmap", XrmoptionSepArg, NULL },
1165 { "-normalPKnightBitmap", "normalPKnightBitmap", XrmoptionSepArg, NULL },
1166 { "-opnb", "normalPKnightBitmap", XrmoptionSepArg, NULL },
1167 { "-normalPSilverBitmap", "normalPSilverBitmap", XrmoptionSepArg, NULL },
1168 { "-opsb", "normalPSilverBitmap", XrmoptionSepArg, NULL },
1169 { "-normalPRookBitmap", "normalPRookBitmap", XrmoptionSepArg, NULL },
1170 { "-oprb", "normalPRookBitmap", XrmoptionSepArg, NULL },
1171 { "-normalPBishopBitmap", "normalPBishopBitmap", XrmoptionSepArg, NULL },
1172 { "-opbb", "normalPBishopBitmap", XrmoptionSepArg, NULL },
1173 { "-normalKingBitmap", "normalKingBitmap", XrmoptionSepArg, NULL },
1174 { "-okb", "outlineKingBitmap", XrmoptionSepArg, NULL },
1175 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1176 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1177 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1178 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1179 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1180 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1181 { "-gameIn", "gameIn", XrmoptionSepArg, NULL },
1182 { "-gi", "gameIn", XrmoptionSepArg, NULL },
1183 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1184 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1185 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1186 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1187 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1188 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1189 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1190 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1191 { "-challengeDisplay", "challengeDisplay", XrmoptionSepArg, NULL },
1192 { "-cd", "challengeDisplay", XrmoptionSepArg, NULL },
1193 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1194 { "-mm", "matchMode", XrmoptionSepArg, NULL },
1195 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1196 { "-mono", "monoMode", XrmoptionSepArg, NULL },
1197 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1198 { "-debug", "debugMode", XrmoptionSepArg, NULL },
1199 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1200 { "-clock", "clockMode", XrmoptionSepArg, NULL },
1201 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1202 { "-size", "boardSize", XrmoptionSepArg, NULL },
1203 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1204 { "-st", "searchTime", XrmoptionSepArg, NULL },
1205 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1206 { "-sd", "searchDepth", XrmoptionSepArg, NULL },
1207 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1208 { "-coords", "showCoords", XrmoptionSepArg, NULL },
1209 { "-iconic", "Iconic", XrmoptionNoArg, "True" }
1214 XtActionsRec boardActions[] =
1216 { "DrawPosition", (XtActionProc) DrawPosition },
1217 { "HandleUserMove", (XtActionProc) HandleUserMove },
1218 { "ResetProc", (XtActionProc) ResetProc },
1219 { "ResetFileProc", (XtActionProc) ResetFileProc },
1220 { "LoadGameProc", (XtActionProc) LoadGameProc },
1221 { "QuitProc", (XtActionProc) QuitProc },
1222 { "ForwardProc", (XtActionProc) ForwardProc },
1223 { "BackwardProc", (XtActionProc) BackwardProc },
1224 { "PauseProc", (XtActionProc) PauseProc },
1225 { "Iconify", (XtActionProc) Iconify },
1226 { "FileNameAction", (XtActionProc) FileNameAction },
1227 { "PieceMenuPopup", (XtActionProc) PieceMenuPopup },
1228 { "SetBlackToPlay", (XtActionProc) SetBlackToPlay },
1229 { "SetWhiteToPlay", (XtActionProc) SetWhiteToPlay }
1233 char translationsTable[] =
1234 "<Expose>: DrawPosition() \n \
1235 <Btn1Down>: HandleUserMove() \n \
1236 <Btn1Up>: HandleUserMove() \n \
1237 <Btn2Down>: XawPositionSimpleMenu(menuW) PieceMenuPopup(menuW) \n \
1238 <Btn3Down>: XawPositionSimpleMenu(menuB) PieceMenuPopup(menuB) \n \
1239 <Key>r: ResetFileProc() ResetProc() \n \
1240 <Key>R: ResetFileProc() ResetProc() \n \
1241 <Key>g: LoadGameProc() \n \
1242 <Key>G: LoadGameProc() \n \
1243 <Key>q: QuitProc() \n \
1244 <Key>Q: QuitProc() \n \
1245 <Message>WM_PROTOCOLS: QuitProc() \n \
1246 <Key>f: ForwardProc() \n \
1247 <Key>F: ForwardProc() \n \
1248 <Key>b: BackwardProc() \n \
1249 <Key>B: BackwardProc() \n \
1250 <Key>p: PauseProc() \n \
1251 <Key>P: PauseProc() \n \
1252 <Key>i: Iconify() \n \
1253 <Key>I: Iconify() \n \
1254 <Key>c: Iconify() \n \
1255 <Key>C: Iconify() \n";
1258 char translationsTableReduced[] =
1259 "<Expose>: DrawPosition() \n \
1260 <Btn1Down>: HandleUserMove() \n \
1261 <Btn1Up>: HandleUserMove() \n \
1262 <Message>WM_PROTOCOLS: QuitProc() \n";
1265 char blackTranslations[] = "<BtnDown>: SetBlackToPlay()\n";
1266 char whiteTranslations[] = "<BtnDown>: SetWhiteToPlay()\n";
1268 String xshogiResources[] =
1271 "*Dialog*value.translations: #override "
1272 "\\n <Key>Return: FileNameAction()",
1277 int global_argc; /* number of command args */
1278 char *global_argv[10]; /* pointers to up to 10 command args */
1282 static struct DisplayData *player;
1291 static FileModeInfo fmi;
1295 * This is a hack that allows the parser to tell the program
1296 * that the game it's loading has ended.
1299 int loaded_game_finished = 0;
1302 /**********************************************************************
1306 **********************************************************************/
1310 CreatePlayerWindow(void)
1312 int mainFontPxlSize, coordFontPxlSize;
1313 int min, sec, matched;
1314 XSetWindowAttributes window_attributes;
1317 Dimension timerWidth, boardWidth, commandsWidth, w, h;
1319 int fromRemotePlayer = (player == &remotePlayer);
1321 player->monoMode = player->appData.monoMode;
1322 player->showCoords = player->appData.showCoords;
1325 * Parse timeControl resource.
1328 if (player->appData.timeControl != NULL)
1330 matched = sscanf(player->appData.timeControl, "%d:%d", &min, &sec);
1334 timeControl = min * 60 * 1000;
1336 else if (matched == 2)
1338 timeControl = (min * 60 + sec) * 1000;
1342 fprintf(stderr, "%s: bad timeControl option %s\n",
1343 programName, player->appData.timeControl);
1349 * Parse searchTime resource
1352 if (player->appData.searchTime != NULL)
1354 matched = sscanf(player->appData.searchTime, "%d:%d", &min, &sec);
1358 searchTime = min * 60;
1360 else if (matched == 2)
1362 searchTime = min * 60 + sec;
1366 fprintf(stderr, "%s: bad searchTime option %s\n",
1367 programName, player->appData.searchTime);
1372 if ((player->appData.searchTime != NULL)
1373 || (player->appData.searchDepth > 0)
1374 || player->appData.noShogiProgram)
1376 player->appData.clockMode = False;
1379 player->Iconic = False;
1380 player->boardSize = Small;
1381 player->squareSize = SMALL_SQUARE_SIZE;
1382 player->flipView = (player == &remotePlayer);
1383 player->promotionUp = False;
1386 * Determine boardSize.
1389 if (strcasecmp(player->appData.boardSize, "Large") == 0)
1391 player->boardSize = Large;
1393 else if (strcasecmp(player->appData.boardSize, "Medium") == 0)
1395 player->boardSize = Medium;
1397 else if (strcasecmp(player->appData.boardSize, "Small") == 0)
1399 player->boardSize = Small;
1403 fprintf(stderr, "%s: bad boardSize option %s\n",
1404 programName, player->appData.boardSize);
1408 if ((local = (player == &localPlayer)))
1410 player->xDisplay = XtDisplay(player->shellWidget);
1411 player->xScreen = DefaultScreen(player->xDisplay);
1414 #undef DONT_ADJUST_BOARDSIZE
1415 #ifndef DONT_ADJUST_BOARDSIZE
1416 if (((DisplayWidth(player->xDisplay, player->xScreen) < 800)
1417 || (DisplayHeight(player->xDisplay, player->xScreen) < 800))
1418 && (player->boardSize == Large))
1420 player->boardSize = Medium;
1424 switch (player->boardSize)
1427 player->squareSize = SMALL_SQUARE_SIZE;
1428 mainFontPxlSize = 11;
1429 coordFontPxlSize = 10;
1433 player->squareSize = MEDIUM_SQUARE_SIZE;
1434 mainFontPxlSize = 17;
1435 coordFontPxlSize = 12;
1440 player->squareSize = LARGE_SQUARE_SIZE;
1441 mainFontPxlSize = 17;
1442 coordFontPxlSize = 14;
1447 * Detect if there are not enough colors are available and adapt.
1450 if (DefaultDepth(player->xDisplay, player->xScreen) <= 2)
1451 player->monoMode = True;
1454 * Determine what fonts to use.
1457 player->appData.mainFont
1458 = FindFont(player->appData.mainFont, mainFontPxlSize);
1460 = XLoadFont(player->xDisplay, player->appData.mainFont);
1461 player->mainFontStruct
1462 = XQueryFont(player->xDisplay, player->mainFontID);
1463 player->appData.coordFont
1464 = FindFont(player->appData.coordFont, coordFontPxlSize);
1466 = XLoadFont(player->xDisplay, player->appData.coordFont);
1467 player->coordFontStruct
1468 = XQueryFont(player->xDisplay, player->coordFontID);
1471 * Set default arguments.
1474 XtSetArg(player->shellArgs[0], XtNwidth, 0);
1475 XtSetArg(player->shellArgs[1], XtNheight, 0);
1476 XtSetArg(player->shellArgs[2], XtNminWidth, 0);
1477 XtSetArg(player->shellArgs[3], XtNminHeight, 0);
1478 XtSetArg(player->shellArgs[4], XtNmaxWidth, 0);
1479 XtSetArg(player->shellArgs[5], XtNmaxHeight, 0);
1481 XtSetArg(player->boardArgs[0], XtNborderWidth, 0);
1482 XtSetArg(player->boardArgs[1], XtNwidth,
1483 LINE_GAP + (BOARD_SIZE + 4)
1484 * (SMALL_SQUARE_SIZE + LINE_GAP));
1485 XtSetArg(player->boardArgs[2], XtNheight,
1486 LINE_GAP + BOARD_SIZE
1487 * (SMALL_SQUARE_SIZE + LINE_GAP));
1489 XtSetArg(player->commandsArgs[0], XtNborderWidth, 0);
1490 XtSetArg(player->commandsArgs[1], XtNdefaultColumns, 4);
1491 XtSetArg(player->commandsArgs[2], XtNforceColumns, True);
1492 XtSetArg(player->commandsArgs[3], XtNcolumnSpacing, 12);
1493 XtSetArg(player->commandsArgs[4], XtNlist, (XtArgVal) buttonStrings);
1494 XtSetArg(player->commandsArgs[5], XtNnumberStrings, buttonCount);
1495 XtSetArg(player->commandsArgs[6], XtNfont, player->mainFontStruct);
1497 XtSetArg(player->messageArgs[0], XtNborderWidth, 0);
1498 XtSetArg(player->messageArgs[1], XtNjustify, (XtArgVal) XtJustifyLeft);
1499 XtSetArg(player->messageArgs[2], XtNlabel, (XtArgVal) "starting...");
1501 XtSetArg(player->timerArgs[0], XtNborderWidth, 0);
1502 XtSetArg(player->timerArgs[1], XtNjustify, (XtArgVal) XtJustifyLeft);
1504 XtSetArg(player->titleArgs[0], XtNborderWidth, 0);
1505 XtSetArg(player->titleArgs[1], XtNjustify, (XtArgVal) XtJustifyLeft);
1507 boardWidth = LINE_GAP
1508 + (BOARD_SIZE + 4) * (player->squareSize + LINE_GAP);
1510 XtSetArg(player->boardArgs[1], XtNwidth, boardWidth);
1511 XtSetArg(player->boardArgs[2], XtNheight,
1512 LINE_GAP + BOARD_SIZE * (player->squareSize + LINE_GAP));
1518 player->formWidget = XtCreateManagedWidget("form",
1520 player->shellWidget, NULL, 0);
1522 player->widgetList[0] = player->blackTimerWidget
1523 = XtCreateWidget((local ? "black time:" : "rblack time:"),
1525 player->formWidget, player->timerArgs,
1526 XtNumber(player->timerArgs));
1528 XtSetArg(args[0], XtNfont, player->mainFontStruct);
1529 XtSetValues(player->blackTimerWidget, args, 1);
1531 player->widgetList[1] = player->whiteTimerWidget
1532 = XtCreateWidget((local ? "white time:" : "rwhite time:"),
1534 player->formWidget, player->timerArgs,
1535 XtNumber(player->timerArgs));
1537 XtSetArg(args[0], XtNfont, player->mainFontStruct);
1538 XtSetValues(player->whiteTimerWidget, args, 1);
1540 player->widgetList[2] = player->titleWidget
1541 = XtCreateWidget((local ? "" : "r"), labelWidgetClass,
1542 player->formWidget, player->titleArgs,
1543 XtNumber(player->titleArgs));
1545 XtSetArg(args[0], XtNfont, player->mainFontStruct);
1546 XtSetValues(player->titleWidget, args, 1);
1548 player->widgetList[3] = player->messageWidget
1549 = XtCreateWidget((local ? "message" : "rmessage"),
1550 labelWidgetClass, player->formWidget,
1551 player->messageArgs,
1552 XtNumber(player->messageArgs));
1554 XtSetArg(args[0], XtNfont, player->mainFontStruct);
1555 XtSetValues(player->messageWidget, args, 1);
1557 player->widgetList[4] = player->commandsWidget
1558 = XtCreateWidget((local ? "commands" : "rcommand"),
1559 listWidgetClass, player->formWidget,
1560 player->commandsArgs,
1561 XtNumber(player->commandsArgs));
1563 player->widgetList[5] = player->boardWidget
1564 = XtCreateWidget((local ? "board" : "rboard"),
1565 widgetClass, player->formWidget,
1567 XtNumber(player->boardArgs));
1569 XtManageChildren(player->widgetList, XtNumber(player->widgetList));
1572 * Calculate the width of the timer labels.
1575 XtSetArg(args[0], XtNfont, &player->mainFontStruct);
1576 XtGetValues(player->blackTimerWidget, args, 1);
1578 if (player->appData.clockMode)
1580 timerWidth = XTextWidth(player->mainFontStruct,
1581 "Black: 8:88:88 ", 15);
1585 timerWidth = XTextWidth(player->mainFontStruct, "Black ", 7);
1588 XtSetArg(args[0], XtNwidth, timerWidth);
1589 XtSetValues(player->blackTimerWidget, args, 1);
1590 XtSetValues(player->whiteTimerWidget, args, 1);
1592 XtSetArg(args[0], XtNbackground, &player->timerForegroundPixel);
1593 XtSetArg(args[1], XtNforeground, &player->timerBackgroundPixel);
1594 XtGetValues(player->blackTimerWidget, args, 2);
1597 * Calculate the width of the name and message labels.
1600 XtSetArg(args[0], XtNwidth, &commandsWidth);
1601 XtGetValues(player->commandsWidget, args, 1);
1602 w = ((commandsWidth > boardWidth) ? commandsWidth : boardWidth);
1603 XtSetArg(args[0], XtNwidth, w - timerWidth * 2 - 12);
1604 XtSetValues(player->titleWidget, args, 1);
1605 XtSetArg(args[0], XtNwidth, w - 8);
1606 XtSetValues(player->messageWidget, args, 1);
1609 * 'formWidget' uses these constraints but they are stored
1613 XtSetArg(args[0], XtNfromHoriz, player->blackTimerWidget);
1614 XtSetValues(player->whiteTimerWidget, args, 1);
1615 XtSetArg(args[0], XtNfromHoriz, player->whiteTimerWidget);
1616 XtSetValues(player->titleWidget, args, 1);
1617 XtSetArg(args[0], XtNfromVert, player->blackTimerWidget);
1618 XtSetValues(player->messageWidget, args, 1);
1619 XtSetArg(args[0], XtNfromVert, player->messageWidget);
1620 XtSetValues(player->commandsWidget, args, 1);
1621 XtSetArg(args[0], XtNfromVert, player->commandsWidget);
1622 XtSetValues(player->boardWidget, args, 1);
1624 XtRealizeWidget(player->shellWidget);
1626 player->xBoardWindow = XtWindow(player->boardWidget);
1632 player->iconPixmap =
1633 XCreateBitmapFromData(player->xDisplay,
1634 XtWindow(player->shellWidget),
1635 (char *)icon_bits, icon_width, icon_height);
1637 XtSetArg(args[0], XtNiconPixmap, player->iconPixmap);
1638 XtSetValues(player->shellWidget, args, 1);
1641 * Create a cursor for the board widget.
1644 window_attributes.cursor = XCreateFontCursor(player->xDisplay, XC_hand2);
1645 XChangeWindowAttributes(player->xDisplay, player->xBoardWindow,
1646 CWCursor, &window_attributes);
1649 * Inhibit shell resizing.
1652 player->shellArgs[0].value = (XtArgVal) &w;
1653 player->shellArgs[1].value = (XtArgVal) &h;
1654 XtGetValues(player->shellWidget, player->shellArgs, 2);
1655 player->shellArgs[4].value = player->shellArgs[2].value = w;
1656 player->shellArgs[5].value = player->shellArgs[3].value = h;
1657 XtSetValues(player->shellWidget, &player->shellArgs[2], 4);
1660 * Determine value of black pixel.
1663 player->black_pixel_is_zero =
1664 (XBlackPixel(player->xDisplay, player->xScreen) == 0);
1670 if (!fromRemotePlayer)
1673 XtAddCallback(player->commandsWidget, XtNcallback, SelectCommand,
1674 (XtPointer)fromRemotePlayer);
1676 if (!fromRemotePlayer)
1677 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
1679 if (fromRemotePlayer)
1681 XtSetArg(args[0], XtNtranslations,
1682 XtParseTranslationTable(translationsTableReduced));
1683 /* Disable key commands because often keys are pressed
1684 in the board window if using another talk window. */
1685 XtSetValues(player->boardWidget, &args[0], 1);
1686 XtSetValues(localPlayer.boardWidget, &args[0], 1);
1690 XtSetArg(args[0], XtNtranslations,
1691 XtParseTranslationTable(translationsTable));
1692 XtSetValues(player->boardWidget, &args[0], 1);
1693 XtSetArg(args[0], XtNtranslations,
1694 XtParseTranslationTable(blackTranslations));
1695 XtSetValues(player->blackTimerWidget, &args[0], 1);
1696 XtSetArg(args[0], XtNtranslations,
1697 XtParseTranslationTable(whiteTranslations));
1698 XtSetValues(player->whiteTimerWidget, &args[0], 1);
1701 XtAddEventHandler(player->boardWidget, ExposureMask | ButtonPressMask
1702 | ButtonReleaseMask | Button1MotionMask | KeyPressMask,
1703 False, (XtEventHandler)EventProc,
1704 (XtPointer)(player == &remotePlayer));
1706 sprintf(buf, "xshogi version %s based on "
1707 "xboard version %s",
1708 PACKAGE_VERSION, XBOARD_VERSION);
1711 * If there is to be a machine match, set it up.
1714 if (matchMode != MatchFalse && player != &remotePlayer)
1716 if (player->appData.noShogiProgram)
1719 "%s: can't have a match with no shogi programs!\n",
1724 DisplayMessage(buf, fromRemotePlayer);
1725 TwoMachinesProc(NULL, NULL, NULL, NULL);
1730 DisplayMessage(buf, fromRemotePlayer);
1738 main(int argc, char **argv)
1740 setbuf(stdout, NULL);
1741 setbuf(stderr, NULL);
1744 * Copy pointers to command line arguments and number of such pointers.
1745 * (argc, argv will be destroyed by XtAppInitialize)
1748 for (global_argc = 0; global_argc < argc; global_argc++)
1749 global_argv[global_argc] = argv[global_argc];
1751 programName = strrchr(argv[0], '/');
1753 if (programName == NULL)
1754 programName = argv[0];
1758 localPlayer.shellWidget
1759 = XtAppInitialize(&appContext, "XShogi", shellOptions,
1760 XtNumber(shellOptions), &argc, argv,
1761 xshogiResources, NULL, 0);
1766 if ((shogiDir = (char *)getenv("SHOGIDIR")) == NULL)
1772 if (chdir(shogiDir) != 0)
1774 fprintf(stderr, "%s: can't cd to SHOGIDIR\n",
1781 XtGetApplicationResources(localPlayer.shellWidget,
1782 &localPlayer.appData, clientResources,
1783 XtNumber(clientResources), NULL, 0);
1785 xshogiDebug = localPlayer.appData.debugMode;
1788 * Determine matchMode state -- poor man's resource converter.
1791 if (strcasecmp(localPlayer.appData.matchMode, "Init") == 0)
1793 matchMode = MatchInit;
1795 else if (strcasecmp(localPlayer.appData.matchMode, "Position") == 0)
1797 matchMode = MatchPosition;
1799 else if (strcasecmp(localPlayer.appData.matchMode, "Opening") == 0)
1801 matchMode = MatchOpening;
1803 else if (strcasecmp(localPlayer.appData.matchMode, "False") == 0)
1805 matchMode = MatchFalse;
1809 fprintf(stderr, "%s: bad matchMode option %s\n",
1810 programName, localPlayer.appData.matchMode);
1814 buttonStrings = gnuButtonStrings;
1815 buttonProcs = gnuButtonProcs;
1816 buttonCount = XtNumber(gnuButtonStrings);
1818 player = &localPlayer;
1820 CreatePlayerWindow();
1822 XtAppMainLoop(appContext);
1830 * Find a font that matches "pattern" that is as close as
1831 * possible to the targetPxlSize. Prefer fonts that are k
1832 * pixels smaller to fonts that are k pixels larger. The
1833 * pattern must be in the X Consortium standard format,
1834 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
1835 * The return value should be freed with XtFree when no
1840 FindFont(char *pattern, int targetPxlSize)
1842 char **fonts, *p, *best;
1843 int i, j, nfonts, minerr, err, pxlSize;
1845 fonts = XListFonts(player->xDisplay, pattern, 999999, &nfonts);
1849 fprintf(stderr, "%s: No fonts match pattern %s\n",
1850 programName, pattern);
1857 for (i = 0; i < nfonts; i++)
1879 if (pxlSize == targetPxlSize)
1885 err = pxlSize - targetPxlSize;
1887 if (abs(err) < abs(minerr)
1888 || ((minerr > 0) && (err < 0) && (-err == minerr)))
1895 p = (char *)XtMalloc(strlen(best) + 1);
1897 XFreeFontNames(fonts);
1907 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
1908 | GCBackground | GCFunction | GCPlaneMask;
1909 XGCValues gc_values;
1911 gc_values.plane_mask = AllPlanes;
1912 gc_values.line_width = LINE_GAP;
1913 gc_values.line_style = LineSolid;
1914 gc_values.function = GXcopy;
1916 gc_values.foreground = XBlackPixel(player->xDisplay, player->xScreen);
1917 gc_values.background = XBlackPixel(player->xDisplay, player->xScreen);
1918 player->lineGC = XtGetGC(player->shellWidget, value_mask, &gc_values);
1920 gc_values.background = XWhitePixel(player->xDisplay, player->xScreen);
1921 player->coordGC = XtGetGC(player->shellWidget, value_mask, &gc_values);
1922 XSetFont(player->xDisplay, player->coordGC, player->coordFontID);
1924 if (player->monoMode)
1926 gc_values.foreground
1927 = XWhitePixel(player->xDisplay, player->xScreen);
1928 gc_values.background
1929 = XWhitePixel(player->xDisplay, player->xScreen);
1931 /* empty square off board */
1932 player->squareOffBoardGC
1933 = XtGetGC(player->shellWidget, value_mask, &gc_values);
1935 /* empty square on board */
1937 = XtGetGC(player->shellWidget, value_mask, &gc_values);
1941 Pixel bg; /* background color */
1944 /* Get background color. */
1945 XtSetArg(args[0], XtNbackground, &bg);
1946 XtGetValues(player->shellWidget, args, 1);
1948 /* empty square off board */
1949 gc_values.foreground = gc_values.background = bg;
1950 player->squareOffBoardGC
1951 = XtGetGC(player->shellWidget, value_mask, &gc_values);
1953 /* empty square on board */
1954 gc_values.foreground
1955 = player->appData.squareColor;
1956 gc_values.background
1957 = player->appData.squareColor;
1959 = XtGetGC(player->shellWidget, value_mask, &gc_values);
1961 /* piece off board */
1962 gc_values.foreground
1963 = player->appData.pieceColor;
1964 gc_values.background = bg;
1966 = XtGetGC(player->shellWidget, value_mask, &gc_values);
1968 /* piece on board */
1969 gc_values.foreground
1970 = player->appData.pieceColor;
1971 gc_values.background
1972 = player->appData.squareColor;
1974 = XtGetGC(player->shellWidget, value_mask, &gc_values);
1978 * FIXME: charPieceColor seems to have no effect;
1979 * the bitmap is *always* black.
1981 gc_values.function = (player->black_pixel_is_zero ? GXand : GXor);
1983 gc_values.foreground
1984 = player->appData.charPieceColor;
1985 gc_values.background
1986 = player->appData.charPieceColor;
1989 = XtGetGC(player->shellWidget, value_mask, &gc_values);
1999 XSynchronize(player->xDisplay, True); /* Work-around for xlib/xt
2002 if (player->appData.westernPieceSet)
2004 ReadBitmap(player->appData.reverseBigSolidBitmap,
2005 &player->reverseBigSolidBitmap,
2007 bigsolidR_bits, bigsolidR_m_bits, bigsolidR_l_bits);
2009 ReadBitmap(player->appData.reverseSmallSolidBitmap,
2010 &player->reverseSmallSolidBitmap,
2012 smallsolidR_bits, smallsolidR_m_bits, smallsolidR_l_bits);
2014 ReadBitmap(player->appData.normalBigSolidBitmap,
2015 &player->normalBigSolidBitmap,
2017 bigsolid_bits, bigsolid_m_bits, bigsolid_l_bits);
2019 ReadBitmap(player->appData.normalSmallSolidBitmap,
2020 &player->normalSmallSolidBitmap,
2022 smallsolid_bits, smallsolid_m_bits, smallsolid_l_bits);
2024 ReadBitmap(player->appData.reversePawnBitmap,
2025 &player->reversePawnBitmap,
2026 &player->reverseSmallSolidBitmap,
2027 pawnRW_bits, pawnRW_bits, pawnRW_bits);
2029 ReadBitmap(player->appData.reverseLanceBitmap,
2030 &player->reverseLanceBitmap,
2031 &player->reverseSmallSolidBitmap,
2032 lanceRW_bits, lanceRW_bits, lanceRW_bits);
2034 ReadBitmap(player->appData.reverseKnightBitmap,
2035 &player->reverseKnightBitmap,
2036 &player->reverseSmallSolidBitmap,
2037 knightRW_bits, knightRW_bits, knightRW_bits);
2039 ReadBitmap(player->appData.reverseSilverBitmap,
2040 &player->reverseSilverBitmap,
2041 &player->reverseBigSolidBitmap,
2042 silverRW_bits, silverRW_bits, silverRW_bits);
2044 ReadBitmap(player->appData.reverseGoldBitmap,
2045 &player->reverseGoldBitmap,
2046 &player->reverseBigSolidBitmap,
2047 goldRW_bits, goldRW_bits, goldRW_bits);
2049 ReadBitmap(player->appData.reverseRookBitmap,
2050 &player->reverseRookBitmap,
2051 &player->reverseBigSolidBitmap,
2052 rookRW_bits, rookRW_bits, rookRW_bits);
2054 ReadBitmap(player->appData.reverseBishopBitmap,
2055 &player->reverseBishopBitmap,
2056 &player->reverseBigSolidBitmap,
2057 bishopRW_bits, bishopRW_bits, bishopRW_bits);
2059 ReadBitmap(player->appData.reversePPawnBitmap,
2060 &player->reversePPawnBitmap,
2061 &player->reverseSmallSolidBitmap,
2062 pawnPRW_bits, pawnPRW_bits, pawnPRW_bits);
2064 ReadBitmap(player->appData.reversePLanceBitmap,
2065 &player->reversePLanceBitmap,
2066 &player->reverseSmallSolidBitmap,
2067 lancePRW_bits, lancePRW_bits, lancePRW_bits);
2069 ReadBitmap(player->appData.reversePKnightBitmap,
2070 &player->reversePKnightBitmap,
2071 &player->reverseSmallSolidBitmap,
2072 knightPRW_bits, knightPRW_bits, knightPRW_bits);
2074 ReadBitmap(player->appData.reversePSilverBitmap,
2075 &player->reversePSilverBitmap,
2076 &player->reverseBigSolidBitmap,
2077 silverPRW_bits, silverPRW_bits, silverPRW_bits);
2079 ReadBitmap(player->appData.reversePRookBitmap,
2080 &player->reversePRookBitmap,
2081 &player->reverseBigSolidBitmap,
2082 rookPRW_bits, rookPRW_bits, rookPRW_bits);
2084 ReadBitmap(player->appData.reversePBishopBitmap,
2085 &player->reversePBishopBitmap,
2086 &player->reverseBigSolidBitmap,
2087 bishopPRW_bits, bishopPRW_bits, bishopPRW_bits);
2089 ReadBitmap(player->appData.reverseKingBitmap,
2090 &player->reverseKingBitmap,
2091 &player->reverseBigSolidBitmap,
2092 kingRW_bits, kingRW_bits, kingRW_bits);
2094 ReadBitmap(player->appData.normalPawnBitmap,
2095 &player->normalPawnBitmap,
2096 &player->normalSmallSolidBitmap,
2097 pawnW_bits, pawnW_bits, pawnW_bits);
2099 ReadBitmap(player->appData.normalLanceBitmap,
2100 &player->normalLanceBitmap,
2101 &player->normalSmallSolidBitmap,
2102 lanceW_bits, lanceW_bits, lanceW_bits);
2104 ReadBitmap(player->appData.normalKnightBitmap,
2105 &player->normalKnightBitmap,
2106 &player->normalSmallSolidBitmap,
2107 knightW_bits, knightW_bits, knightW_bits);
2109 ReadBitmap(player->appData.normalSilverBitmap,
2110 &player->normalSilverBitmap,
2111 &player->normalBigSolidBitmap,
2112 silverW_bits, silverW_bits, silverW_bits);
2114 ReadBitmap(player->appData.normalGoldBitmap,
2115 &player->normalGoldBitmap,
2116 &player->normalBigSolidBitmap,
2117 goldW_bits, goldW_bits, goldW_bits);
2119 ReadBitmap(player->appData.normalRookBitmap,
2120 &player->normalRookBitmap,
2121 &player->normalBigSolidBitmap,
2122 rookW_bits, rookW_bits, rookW_bits);
2124 ReadBitmap(player->appData.normalBishopBitmap,
2125 &player->normalBishopBitmap,
2126 &player->normalBigSolidBitmap,
2127 bishopW_bits, bishopW_bits, bishopW_bits);
2129 ReadBitmap(player->appData.normalPPawnBitmap,
2130 &player->normalPPawnBitmap,
2131 &player->normalSmallSolidBitmap,
2132 pawnPW_bits, pawnPW_bits, pawnPW_bits);
2134 ReadBitmap(player->appData.normalPLanceBitmap,
2135 &player->normalPLanceBitmap,
2136 &player->normalSmallSolidBitmap,
2137 lancePW_bits, lancePW_bits, lancePW_bits);
2139 ReadBitmap(player->appData.normalPKnightBitmap,
2140 &player->normalPKnightBitmap,
2141 &player->normalSmallSolidBitmap,
2142 knightPW_bits, knightPW_bits, knightPW_bits);
2144 ReadBitmap(player->appData.normalPSilverBitmap,
2145 &player->normalPSilverBitmap,
2146 &player->normalBigSolidBitmap,
2147 silverPW_bits, silverPW_bits, silverPW_bits);
2149 ReadBitmap(player->appData.normalPRookBitmap,
2150 &player->normalPRookBitmap,
2151 &player->normalBigSolidBitmap,
2152 rookPW_bits, rookPW_bits, rookPW_bits);
2154 ReadBitmap(player->appData.normalPBishopBitmap,
2155 &player->normalPBishopBitmap,
2156 &player->normalBigSolidBitmap,
2157 bishopPW_bits, bishopPW_bits, bishopPW_bits);
2159 ReadBitmap(player->appData.normalKingBitmap,
2160 &player->normalKingBitmap,
2161 &player->normalBigSolidBitmap,
2162 kingW_bits, kingW_bits, kingW_bits);
2166 ReadBitmap(player->appData.reverseBigSolidBitmap,
2167 &player->reverseBigSolidBitmap,
2169 bigsolidR_bits, bigsolidR_m_bits, bigsolidR_l_bits);
2171 ReadBitmap(player->appData.reverseSmallSolidBitmap,
2172 &player->reverseSmallSolidBitmap,
2174 smallsolidR_bits, smallsolidR_m_bits, smallsolidR_l_bits);
2176 ReadBitmap(player->appData.normalBigSolidBitmap,
2177 &player->normalBigSolidBitmap,
2179 bigsolid_bits, bigsolid_m_bits, bigsolid_l_bits);
2181 ReadBitmap(player->appData.normalSmallSolidBitmap,
2182 &player->normalSmallSolidBitmap,
2184 smallsolid_bits, smallsolid_m_bits, smallsolid_l_bits);
2186 ReadBitmap(player->appData.reversePawnBitmap,
2187 &player->reversePawnBitmap,
2188 &player->reverseSmallSolidBitmap,
2189 pawnR_bits, pawnR_m_bits, pawnR_l_bits);
2191 ReadBitmap(player->appData.reverseLanceBitmap,
2192 &player->reverseLanceBitmap,
2193 &player->reverseSmallSolidBitmap,
2194 lanceR_bits, lanceR_m_bits, lanceR_l_bits);
2196 ReadBitmap(player->appData.reverseKnightBitmap,
2197 &player->reverseKnightBitmap,
2198 &player->reverseSmallSolidBitmap,
2199 knightR_bits, knightR_m_bits, knightR_l_bits);
2201 ReadBitmap(player->appData.reverseSilverBitmap,
2202 &player->reverseSilverBitmap,
2203 &player->reverseBigSolidBitmap,
2204 silverR_bits, silverR_m_bits, silverR_l_bits);
2206 ReadBitmap(player->appData.reverseGoldBitmap,
2207 &player->reverseGoldBitmap,
2208 &player->reverseBigSolidBitmap,
2209 goldR_bits, goldR_m_bits, goldR_l_bits);
2211 ReadBitmap(player->appData.reverseRookBitmap,
2212 &player->reverseRookBitmap,
2213 &player->reverseBigSolidBitmap,
2214 rookR_bits, rookR_m_bits, rookR_l_bits);
2216 ReadBitmap(player->appData.reverseBishopBitmap,
2217 &player->reverseBishopBitmap,
2218 &player->reverseBigSolidBitmap,
2219 bishopR_bits, bishopR_m_bits, bishopR_l_bits);
2221 ReadBitmap(player->appData.reversePPawnBitmap,
2222 &player->reversePPawnBitmap,
2223 &player->reverseSmallSolidBitmap,
2224 pawnPR_bits, pawnPR_m_bits, pawnPR_l_bits);
2226 ReadBitmap(player->appData.reversePLanceBitmap,
2227 &player->reversePLanceBitmap,
2228 &player->reverseSmallSolidBitmap,
2229 lancePR_bits, lancePR_m_bits, lancePR_l_bits);
2231 ReadBitmap(player->appData.reversePKnightBitmap,
2232 &player->reversePKnightBitmap,
2233 &player->reverseSmallSolidBitmap,
2234 knightPR_bits, knightPR_m_bits, knightPR_l_bits);
2236 ReadBitmap(player->appData.reversePSilverBitmap,
2237 &player->reversePSilverBitmap,
2238 &player->reverseBigSolidBitmap,
2239 silverPR_bits, silverPR_m_bits, silverPR_l_bits);
2241 ReadBitmap(player->appData.reversePRookBitmap,
2242 &player->reversePRookBitmap,
2243 &player->reverseBigSolidBitmap,
2244 rookPR_bits, rookPR_m_bits, rookPR_l_bits);
2246 ReadBitmap(player->appData.reversePBishopBitmap,
2247 &player->reversePBishopBitmap,
2248 &player->reverseBigSolidBitmap,
2249 bishopPR_bits, bishopPR_m_bits, bishopPR_l_bits);
2251 ReadBitmap(player->appData.reverseKingBitmap,
2252 &player->reverseKingBitmap,
2253 &player->reverseBigSolidBitmap,
2254 kingR_bits, kingR_m_bits, kingR_l_bits);
2256 ReadBitmap(player->appData.normalPawnBitmap,
2257 &player->normalPawnBitmap,
2258 &player->normalSmallSolidBitmap,
2259 pawn_bits, pawn_m_bits, pawn_l_bits);
2261 ReadBitmap(player->appData.normalLanceBitmap,
2262 &player->normalLanceBitmap,
2263 &player->normalSmallSolidBitmap,
2264 lance_bits, lance_m_bits, lance_l_bits);
2266 ReadBitmap(player->appData.normalKnightBitmap,
2267 &player->normalKnightBitmap,
2268 &player->normalSmallSolidBitmap,
2269 knight_bits, knight_m_bits, knight_l_bits);
2271 ReadBitmap(player->appData.normalSilverBitmap,
2272 &player->normalSilverBitmap,
2273 &player->normalBigSolidBitmap,
2274 silver_bits, silver_m_bits, silver_l_bits);
2276 ReadBitmap(player->appData.normalGoldBitmap,
2277 &player->normalGoldBitmap,
2278 &player->normalBigSolidBitmap,
2279 gold_bits, gold_m_bits, gold_l_bits);
2281 ReadBitmap(player->appData.normalRookBitmap,
2282 &player->normalRookBitmap,
2283 &player->normalBigSolidBitmap,
2284 rook_bits, rook_m_bits, rook_l_bits);
2286 ReadBitmap(player->appData.normalBishopBitmap,
2287 &player->normalBishopBitmap,
2288 &player->normalBigSolidBitmap,
2289 bishop_bits, bishop_m_bits, bishop_l_bits);
2291 ReadBitmap(player->appData.normalPPawnBitmap,
2292 &player->normalPPawnBitmap,
2293 &player->normalSmallSolidBitmap,
2294 pawnP_bits, pawnP_m_bits, pawnP_l_bits);
2296 ReadBitmap(player->appData.normalPLanceBitmap,
2297 &player->normalPLanceBitmap,
2298 &player->normalSmallSolidBitmap,
2299 lanceP_bits, lanceP_m_bits, lanceP_l_bits);
2301 ReadBitmap(player->appData.normalPKnightBitmap,
2302 &player->normalPKnightBitmap,
2303 &player->normalSmallSolidBitmap,
2304 knightP_bits, knightP_m_bits, knightP_l_bits);
2306 ReadBitmap(player->appData.normalPSilverBitmap,
2307 &player->normalPSilverBitmap,
2308 &player->normalBigSolidBitmap,
2309 silverP_bits, silverP_m_bits, silverP_l_bits);
2311 ReadBitmap(player->appData.normalPRookBitmap,
2312 &player->normalPRookBitmap,
2313 &player->normalBigSolidBitmap,
2314 rookP_bits, rookP_m_bits, rookP_l_bits);
2316 ReadBitmap(player->appData.normalPBishopBitmap,
2317 &player->normalPBishopBitmap,
2318 &player->normalBigSolidBitmap,
2319 bishopP_bits, bishopP_m_bits, bishopP_l_bits);
2321 ReadBitmap(player->appData.normalKingBitmap,
2322 &player->normalKingBitmap,
2323 &player->normalBigSolidBitmap,
2324 king_bits, king_m_bits, king_l_bits);
2328 XSynchronize(player->xDisplay, False); /* Work-around for xlib/xt
2336 ReadBitmapFile(Display *display, Drawable d, char *filename,
2337 unsigned int *width_return,
2338 unsigned int *height_return,
2339 Pixmap *bitmap_return,
2340 int *x_hot_return, int *y_hot_return)
2344 if ((n = XReadBitmapFile(display, d, filename,
2345 width_return, height_return,
2346 bitmap_return, x_hot_return, y_hot_return))
2353 /* transform a 1 plane pixmap to a k plane pixmap */
2354 return BitmapSuccess;
2362 * Create the X pixmap from .xbm file bitmap data. This may
2363 * have to be revised considerably.
2367 ReadBitmap(String name, Pixmap *pm, Pixmap *qm,
2368 unsigned char *small_bits,
2369 unsigned char *medium_bits,
2370 unsigned char *large_bits)
2376 || (ReadBitmapFile(player->xDisplay, player->xBoardWindow, name,
2377 &w, &h, pm, &x_hot, &y_hot) != BitmapSuccess)
2378 || (w != player->squareSize)
2379 || (h != player->squareSize))
2381 unsigned long fg, bg;
2384 depth = DisplayPlanes(player->xDisplay, player->xScreen);
2386 if (player->monoMode)
2388 fg = XBlackPixel(player->xDisplay, player->xScreen);
2389 bg = XWhitePixel(player->xDisplay, player->xScreen);
2391 else if (qm == NULL)
2393 fg = player->appData.oneColor;
2394 bg = player->appData.zeroColor;
2398 fg = (player->black_pixel_is_zero ? 0 : ~0);
2399 bg = (player->black_pixel_is_zero ? ~0 : 0);
2402 switch (player->boardSize)
2405 *pm = XCreatePixmapFromBitmapData(player->xDisplay,
2406 player->xBoardWindow,
2414 *pm = XCreatePixmapFromBitmapData(player->xDisplay,
2415 player->xBoardWindow,
2416 (char *)medium_bits,
2423 *pm = XCreatePixmapFromBitmapData(player->xDisplay,
2424 player->xBoardWindow,
2442 offset = 2 * (player->squareSize + LINE_GAP);
2444 for (i = 0; i < BOARD_SIZE + 1; i++)
2446 player->gridSegments[i].x1 = offset;
2447 player->gridSegments[i + BOARD_SIZE + 1].y1 = 0;
2448 player->gridSegments[i].y1 = player->gridSegments[i].y2
2449 = LINE_GAP / 2 + (i * (player->squareSize + LINE_GAP));
2450 player->gridSegments[i].x2 = LINE_GAP + BOARD_SIZE *
2451 (player->squareSize + LINE_GAP) + offset;
2452 player->gridSegments[i + BOARD_SIZE + 1].x1
2453 = player->gridSegments[i + BOARD_SIZE + 1].x2 = LINE_GAP / 2
2454 + (i * (player->squareSize + LINE_GAP)) + offset;
2455 player->gridSegments[i + BOARD_SIZE + 1].y2
2456 = BOARD_SIZE * (player->squareSize + LINE_GAP);
2464 CreatePieceMenus(void)
2469 ShogiSquare selection;
2471 XtSetArg(args[0], XtNlabel, "Black");
2472 blackPieceMenu = XtCreatePopupShell("menuW", simpleMenuWidgetClass,
2473 localPlayer.boardWidget, args, 1);
2475 for (i = 0; i < PIECE_MENU_SIZE; i++)
2477 String item = pieceMenuStrings[i];
2479 if (strcmp(item, "----") == 0)
2481 entry = XtCreateManagedWidget(item, smeLineObjectClass,
2482 blackPieceMenu, NULL, 0);
2486 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
2487 blackPieceMenu, NULL, 0);
2488 selection = pieceMenuTranslation[0][i];
2489 XtAddCallback(entry, XtNcallback,
2490 (XtCallbackProc)PieceMenuSelect,
2491 (XtPointer)selection);
2493 if (selection == BlackPawn)
2495 XtSetArg(args[0], XtNpopupOnEntry, entry);
2496 XtSetValues(blackPieceMenu, args, 1);
2501 XtSetArg(args[0], XtNlabel, "White");
2502 whitePieceMenu = XtCreatePopupShell("menuB", simpleMenuWidgetClass,
2503 localPlayer.boardWidget, args, 1);
2505 for (i = 0; i < PIECE_MENU_SIZE; i++)
2507 String item = pieceMenuStrings[i];
2509 if (strcmp(item, "----") == 0)
2511 entry = XtCreateManagedWidget(item, smeLineObjectClass,
2512 whitePieceMenu, NULL, 0);
2516 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
2517 whitePieceMenu, NULL, 0);
2518 selection = pieceMenuTranslation[1][i];
2519 XtAddCallback(entry, XtNcallback,
2520 (XtCallbackProc)PieceMenuSelect,
2521 (XtPointer)selection);
2523 if (selection == WhitePawn)
2525 XtSetArg(args[0], XtNpopupOnEntry, entry);
2526 XtSetValues(whitePieceMenu, args, 1);
2531 XtRegisterGrabAction(PieceMenuPopup, True,
2532 (unsigned)(ButtonPressMask|ButtonReleaseMask),
2533 GrabModeAsync, GrabModeAsync);
2540 PieceMenuPopup(Widget w, XEvent *event, String *params, Cardinal *num_params)
2542 if (event->type != ButtonPress)
2545 if (gameMode != EditPosition)
2548 if (((pmFromX = EventToXSquare(event->xbutton.x)) < 1)
2549 || (pmFromX > BOARD_SIZE + 2)
2550 || ((pmFromY = EventToSquare(event->xbutton.y)) < 0))
2552 pmFromX = pmFromY = -1;
2556 if (localPlayer.flipView)
2557 pmFromX = BOARD_SIZE + 3 - pmFromX;
2559 pmFromY = BOARD_SIZE - 1 - pmFromY;
2561 XtPopupSpringLoaded(XtNameToWidget(localPlayer.boardWidget, params[0]));
2568 PieceMenuSelect(Widget w, ShogiSquare piece, char *junk)
2570 if ((pmFromX < 0) || (pmFromY < 0))
2573 if (off_board(pmFromX))
2588 i = pieceToCatchedIndex[piece];
2589 c = (piece >= WhitePawn);
2591 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
2592 XSync(localPlayer.xDisplay, False);
2602 for (pmFromY = 0; pmFromY < BOARD_SIZE; pmFromY++)
2603 for (pmFromX = 0; pmFromX < BOARD_SIZE; pmFromX++)
2604 boards[0][pmFromY][pmFromX] = EmptySquare;
2606 ClearCatches(catches[0]);
2607 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
2610 case BlackPlay: /* not currently on menu */
2614 case WhitePlay: /* not currently on menu */
2619 boards[0][pmFromY][pmFromX] = piece;
2620 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
2624 XSync(localPlayer.xDisplay, False);
2631 SetBlackToPlay(void)
2635 if (gameMode != EditPosition)
2638 whitePlaysFirst = False;
2639 saveCM = currentMove;
2640 currentMove = 0; /* kludge */
2641 DisplayClocks(ReDisplayTimers);
2642 currentMove = saveCM;
2649 SetWhiteToPlay(void)
2653 if (gameMode != EditPosition)
2656 whitePlaysFirst = True;
2657 saveCM = currentMove;
2658 currentMove = 1; /* kludge */
2659 DisplayClocks(ReDisplayTimers);
2660 currentMove = saveCM;
2667 * If the user selects on a border boundary or off the board, return failure.
2668 * Otherwise map the event coordinate to the square.
2672 EventToSquare(int x)
2679 if ((x % (player->squareSize + LINE_GAP)) >= player->squareSize)
2682 x /= (player->squareSize + LINE_GAP);
2684 if (x >= BOARD_SIZE)
2694 EventToXSquare(int x)
2701 if ((x % (player->squareSize + LINE_GAP)) >= player->squareSize)
2704 x /= (player->squareSize + LINE_GAP);
2706 if (x >= BOARD_SIZE + 4)
2716 CharToPiece(int c, int p)
2723 case '.': return EmptySquare;
2724 case 'P': return BlackPPawn;
2725 case 'L': return BlackPLance;
2726 case 'N': return BlackPKnight;
2727 case 'S': return BlackPSilver;
2728 case 'G': return BlackGold;
2729 case 'R': return BlackPRook;
2730 case 'B': return BlackPBishop;
2731 case 'K': return BlackKing;
2732 case 'p': return WhitePPawn;
2733 case 'l': return WhitePLance;
2734 case 'n': return WhitePKnight;
2735 case 's': return WhitePSilver;
2736 case 'g': return WhiteGold;
2737 case 'r': return WhitePRook;
2738 case 'b': return WhitePBishop;
2739 case 'k': return WhiteKing;
2747 case '.': return EmptySquare;
2748 case 'P': return BlackPawn;
2749 case 'L': return BlackLance;
2750 case 'N': return BlackKnight;
2751 case 'S': return BlackSilver;
2752 case 'G': return BlackGold;
2753 case 'R': return BlackRook;
2754 case 'B': return BlackBishop;
2755 case 'K': return BlackKing;
2756 case 'p': return WhitePawn;
2757 case 'l': return WhiteLance;
2758 case 'n': return WhiteKnight;
2759 case 's': return WhiteSilver;
2760 case 'g': return WhiteGold;
2761 case 'r': return WhiteRook;
2762 case 'b': return WhiteBishop;
2763 case 'k': return WhiteKing;
2772 * Convert coordinates to normal algebraic notation.
2773 * promoPiece must be NULLCHAR if not a promotion.
2777 MakeAlg(int fromX, int fromY, int toX, int toY,
2778 char promoPiece, int currentBoardIndex, char *out)
2785 piece = (fromX - 81);
2786 *outp++ = catchedIndexToChar[piece];
2788 *outp++ = '9' - toX;
2789 *outp++ = 'i' - toY;
2791 return (BlackOnMove(forwardMostMove) ? BlackDrop : WhiteDrop);
2795 *outp++ = '9' - fromX;
2796 *outp++ = 'i' - fromY;
2797 *outp++ = '9' - toX;
2798 *outp++ = 'i' - toY;
2799 *outp++ = promoPiece;
2802 if (promoPiece == NULLCHAR)
2808 return (BlackOnMove(forwardMostMove)
2809 ? BlackPromotion : WhitePromotion);
2818 DrawSquare(int row, int column, ShogiSquare piece)
2820 int square_color, x, y, direction, font_ascent, font_descent;
2822 XCharStruct overall;
2823 struct DisplayData *player;
2825 for (player = &localPlayer; True; player = &remotePlayer)
2829 remote = (player == &remotePlayer);
2830 offset = 2 * (player->squareSize + LINE_GAP);
2832 if (player->flipView)
2834 x = LINE_GAP + ((BOARD_SIZE - 1) - column) *
2835 (player->squareSize + LINE_GAP) + offset;
2836 y = LINE_GAP + row * (player->squareSize + LINE_GAP);
2840 x = LINE_GAP + column * (player->squareSize + LINE_GAP) + offset;
2841 y = LINE_GAP + ((BOARD_SIZE - 1) - row) *
2842 (player->squareSize + LINE_GAP);
2845 square_color = (((column + row) % 2) ? LIGHT : DARK);
2847 if (piece == EmptySquare)
2849 if (column < 0 || column >= BOARD_SIZE)
2851 /* empty square off board */
2852 XFillRectangle(player->xDisplay, player->xBoardWindow,
2853 player->squareOffBoardGC,
2854 x, y, player->squareSize,
2855 player->squareSize);
2859 /* empty square on board */
2860 XFillRectangle(player->xDisplay,
2861 player->xBoardWindow,
2865 player->squareSize);
2868 else if (player->monoMode) /* Draw a piece in mono mode. */
2870 XCopyArea(player->xDisplay,
2871 ((((((int)piece) < ((int)WhitePawn)))
2873 ? *pieceToNormal[remote][(int)piece]
2874 : *pieceToReverse[remote][(int)piece]),
2875 player->xBoardWindow,
2877 ? player->squareOffBoardGC /* ??? FIXME? */
2880 player->squareSize, player->squareSize, x, y);
2882 else /* Draw a piece in color mode. */
2884 if ((column < 0) || (column >= BOARD_SIZE)) /* off board */
2886 /* draw piece background */
2888 XCopyPlane(player->xDisplay,
2889 ((((((int)piece) < ((int)WhitePawn)))
2891 ? *pieceToNormalSolid[remote][(int)piece]
2892 : *pieceToReverseSolid[remote][(int)piece]),
2893 player->xBoardWindow,
2896 player->squareSize, player->squareSize, x, y, 1);
2898 /* draw piece bitmap */
2900 XCopyArea(player->xDisplay,
2901 ((((((int)piece) < ((int)WhitePawn)))
2903 ? *pieceToNormal[remote][(int)piece]
2904 : *pieceToReverse[remote][(int)piece]),
2905 player->xBoardWindow,
2906 player->charPieceGC,
2908 player->squareSize, player->squareSize, x, y);
2912 /* draw piece background */
2914 XCopyPlane(player->xDisplay,
2915 ((((((int)piece) < ((int)WhitePawn)))
2917 ? *pieceToNormalSolid[remote][(int)piece]
2918 : *pieceToReverseSolid[remote][(int)piece]),
2919 player->xBoardWindow,
2922 player->squareSize, player->squareSize, x, y, 1);
2924 /* draw piece bitmap */
2926 XCopyArea(player->xDisplay,
2927 ((((((int)piece) < ((int)WhitePawn)))
2929 ? *pieceToNormal[remote][(int)piece]
2930 : *pieceToReverse[remote][(int)piece]),
2931 player->xBoardWindow,
2932 player->charPieceGC,
2934 player->squareSize, player->squareSize, x, y);
2938 string[1] = NULLCHAR;
2940 if (player->showCoords
2941 && (column >= 0) && (column < 9)
2942 && (row == (player->flipView ? 8 : 0)))
2944 string[0] = '9' - column;
2945 XTextExtents(player->coordFontStruct, string, 1, &direction,
2946 &font_ascent, &font_descent, &overall);
2948 if (player->monoMode)
2950 XDrawImageString(player->xDisplay,
2951 player->xBoardWindow, player->coordGC,
2952 x + player->squareSize - overall.width - 2,
2953 y + player->squareSize - font_descent - 1,
2958 XDrawString(player->xDisplay, player->xBoardWindow,
2960 x + player->squareSize - overall.width - 2,
2961 y + player->squareSize - font_descent - 1,
2966 if (player->showCoords
2967 && (row >= 0) && (row < 9)
2968 && (column == (player->flipView ? 8 : 0)))
2970 string[0] = 'i' - row;
2971 XTextExtents(player->coordFontStruct, string, 1, &direction,
2972 &font_ascent, &font_descent, &overall);
2974 if (player->monoMode)
2976 XDrawImageString(player->xDisplay,
2977 player->xBoardWindow, player->coordGC,
2978 x + 2, y + font_ascent + 1, string, 1);
2982 XDrawString(player->xDisplay, player->xBoardWindow,
2984 x + 2, y + font_ascent + 1, string, 1);
2988 if (!updateRemotePlayer || (player == &remotePlayer))
2997 EventProc(Widget widget, XtPointer client_data, XEvent *event)
2999 if (event->type == MappingNotify)
3001 XRefreshKeyboardMapping((XMappingEvent *) event);
3005 if (!XtIsRealized(widget))
3008 if ((event->type == ButtonPress) || (event->type == ButtonRelease))
3010 if (event->xbutton.button != Button1)
3014 switch (event->type)
3017 DrawPosition(widget, event, NULL, NULL);
3029 * event handler for redrawing the board
3033 DrawPosition(Widget w, XEvent *event, String *prms, Cardinal *nprms)
3037 static Board lastBoard;
3038 static Catched lastCatches;
3039 static int lastBoardValid = 0;
3040 static int lastFlipView = 0, lastRemoteFlipView = 1;
3042 if (!player->Iconic)
3044 XtSetArg(args[0], XtNiconic, False);
3045 XtSetValues(localPlayer.shellWidget, args, 1);
3049 * It would be simpler to clear the window with XClearWindow()
3050 * but this causes a very distracting flicker.
3053 if ((w == localPlayer.boardWidget)
3056 && (lastFlipView == localPlayer.flipView)
3057 && (!updateRemotePlayer
3058 || (lastRemoteFlipView == remotePlayer.flipView)))
3060 for (i = 0; i < BOARD_SIZE; i++)
3062 for (j = 0; j < BOARD_SIZE; j++)
3064 if (boards[currentMove][i][j] != lastBoard[i][j])
3065 DrawSquare(i, j, boards[currentMove][i][j]);
3069 for (i = 0; i < 2; i++)
3071 for (j = 0; j < 8; j++)
3073 if (catches[currentMove][i][j] != lastCatches[i][j])
3075 UpdateCatched(i, 0, False, True, currentMove);
3083 XDrawSegments(localPlayer.xDisplay,
3084 localPlayer.xBoardWindow, localPlayer.lineGC,
3085 localPlayer.gridSegments, (BOARD_SIZE + 1) * 2);
3087 if (updateRemotePlayer)
3089 XDrawSegments(remotePlayer.xDisplay,
3090 remotePlayer.xBoardWindow, remotePlayer.lineGC,
3091 remotePlayer.gridSegments, (BOARD_SIZE + 1) * 2);
3094 for (i = 0; i < BOARD_SIZE; i++)
3095 for (j = 0; j < BOARD_SIZE; j++)
3096 DrawSquare(i, j, boards[currentMove][i][j]);
3098 UpdateCatched(0, 0, False, True, currentMove);
3099 UpdateCatched(1, 0, False, True, currentMove);
3102 CopyBoard(lastBoard, boards[currentMove]);
3103 CopyCatches(lastCatches, catches[currentMove]);
3105 lastFlipView = localPlayer.flipView;
3107 if (updateRemotePlayer)
3108 lastRemoteFlipView = remotePlayer.flipView;
3110 XSync(localPlayer.xDisplay, False);
3112 if (updateRemotePlayer)
3113 XSync(remotePlayer.xDisplay, False);
3120 InitPosition(int redraw)
3122 currentMove = forwardMostMove = backwardMostMove = 0;
3123 CopyBoard(boards[0], initialPosition);
3124 ClearCatches(catches[0]);
3127 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
3134 CopyBoard(Board to, Board from)
3138 for (i = 0; i < BOARD_SIZE; i++)
3139 for (j = 0; j < BOARD_SIZE; j++)
3140 to[i][j] = from[i][j];
3147 CopyCatches(Catched to, Catched from)
3151 for (i = 0; i < 2; i++)
3152 for (j = 0; j < 8; j++)
3153 to[i][j] = from[i][j];
3160 SendCurrentBoard(FILE *fp)
3162 SendBoard(fp, boards[currentMove], catches[currentMove]);
3169 SendBoard(FILE *fp, Board board, Catched catches)
3171 char message[MSG_SIZ];
3175 SendToProgram("edit\n", fp);
3176 SendToProgram("#\n", fp);
3178 for (i = BOARD_SIZE - 1; i >= 0; i--)
3182 for (j = 0; j < BOARD_SIZE; j++, bp++)
3184 if (((int) *bp) < (int)WhitePawn)
3186 sprintf(message, "%c%c%c%s\n",
3187 pieceToChar[(int) *bp],
3189 (pieceIsPromoted[(int) *bp] ? "+" : ""));
3190 SendToProgram(message, fp);
3195 for (i = 0; i <= 7; i++)
3199 for (n = catches[0][i]; n > 0; n--)
3201 sprintf(message, "%c*\n",
3202 catchedIndexToChar[i]);
3203 SendToProgram(message, fp);
3207 SendToProgram("c\n", fp);
3209 for (i = BOARD_SIZE - 1; i >= 0; i--)
3213 for (j = 0; j < BOARD_SIZE; j++, bp++)
3215 if ((((int) *bp) != ((int)EmptySquare))
3216 && (((int) *bp) >= ((int)WhitePawn)))
3218 sprintf(message, "%c%c%c%s\n",
3219 pieceToChar[((int) *bp) - ((int)WhitePawn)],
3221 (pieceIsPromoted[(int) *bp] ? "+" : ""));
3222 SendToProgram(message, fp);
3227 for (i = 0; i <= 7; i++)
3231 for (n = catches[1][i]; n > 0; n--)
3233 sprintf(message, "%c*\n",
3234 catchedIndexToChar[i]);
3235 SendToProgram(message, fp);
3239 SendToProgram(".\n", fp);
3246 PromotionPossible(int fromY, int toY, ShogiSquare piece)
3248 if (((int)piece) < ((int)WhitePawn))
3250 if ((fromY < 6) && (toY < 6))
3255 if ((fromY > 2) && (toY > 2))
3259 return piecePromotable[(int)piece];
3267 ShowCount(int row, int column, int n)
3269 int offset = 2 * (player->squareSize + LINE_GAP);
3270 int x, y, direction, font_ascent, font_descent;
3272 XCharStruct overall;
3273 struct DisplayData *player;
3275 DrawSquare(row, column, EmptySquare);
3280 for (player = &localPlayer; True; player = &remotePlayer)
3282 if (player->flipView)
3284 x = LINE_GAP + ((BOARD_SIZE - 1) - column) *
3285 (player->squareSize + LINE_GAP) + offset;
3286 y = LINE_GAP + row * (player->squareSize + LINE_GAP);
3290 x = LINE_GAP + column * (player->squareSize + LINE_GAP) + offset;
3291 y = LINE_GAP + ((BOARD_SIZE - 1) - row) *
3292 (player->squareSize + LINE_GAP);
3295 x -= player->squareSize / 2;
3297 string[1] = NULLCHAR;
3302 string[0] = '0' + n;
3304 XTextExtents(player->coordFontStruct, string, 1, &direction,
3305 &font_ascent, &font_descent, &overall);
3307 if (player->monoMode)
3309 XDrawImageString(player->xDisplay, player->xBoardWindow,
3311 x + player->squareSize - overall.width - 2,
3312 y + player->squareSize - font_descent - 1,
3317 XDrawString(player->xDisplay, player->xBoardWindow,
3319 x + player->squareSize - overall.width - 2,
3320 y + player->squareSize - font_descent - 1,
3324 if (!updateRemotePlayer || (player == &remotePlayer))
3333 UpdateCatched(int Color, int Figure, int Drop, int DropAll, int currentMove)
3338 /* Determine first row and column. */
3354 n = catches[currentMove][Color][Figure];
3356 /* Update the display for captured pieces
3357 if no piece of the dropped type is there (Drop && n==1)
3358 or if a piece type is removed (NOT Drop && n==0).
3359 In the other cases update only the count. */
3361 if (DropAll || (Drop && (n == 1)) || (!Drop && (n == 0)))
3363 /* show all captured pieces */
3366 for (F = pawn; F <= king; F++)
3370 if ((c = catches[currentMove][Color][F]) > 0)
3373 DrawSquare(y, x, catchedIndexToPiece[Color][F]);
3374 ShowCount(y, (Color ? (x - 1) : (x + 1)), c);
3387 DrawSquare(y, x, EmptySquare);
3388 ShowCount(y, (Color ? (x - 1) : (x + 1)), 0);
3398 /* remove one line! */
3399 DrawSquare(y, x, EmptySquare);
3400 ShowCount(y, (Color ? (x - 1) : (x + 1)), 0);
3405 /* show the actual count */
3406 for (F = pawn; F <= Figure - 1; F++)
3408 if (catches[currentMove][Color][F] > 0)
3417 ShowCount(y, (Color ? (x - 1) : (x + 1)), n);
3426 static int BlinkCount = 0;
3427 static int BlinkRow, BlinkCol;
3428 static ShogiSquare BlinkPiece;
3432 BlinkSquareProc(void)
3437 DrawSquare (BlinkRow, BlinkCol,
3438 ((BlinkCount & 1) ? EmptySquare : BlinkPiece));
3443 = XtAppAddTimeOut(appContext,
3445 (XtTimerCallbackProc)BlinkSquareProc,
3459 BlinkSquare(int row, int col, ShogiSquare piece)
3461 BlinkCount = 2 * BLINK_COUNT + 1;
3469 #endif /* BLINK_COUNT */
3475 PieceOfCatched(int color, int x, int y, int currentMove)
3492 for (F = pawn, n = 0; F <= king; F++)
3494 if (catches[currentMove][color][F] > 0)
3510 * event handler for parsing user moves
3514 HandleUserMove(Widget w, XEvent *event)
3516 ShogiMove move_type;
3517 ShogiSquare from_piece;
3518 int to_x, to_y, fromRemotePlayer;
3520 if (updateRemotePlayer)
3522 if (((w != localPlayer.boardWidget)
3523 && (w != remotePlayer.boardWidget))
3524 || (matchMode != MatchFalse))
3529 fromRemotePlayer = (w == remotePlayer.boardWidget);
3533 if ((w != localPlayer.boardWidget) || (matchMode != MatchFalse))
3536 fromRemotePlayer = False;
3539 player = (fromRemotePlayer ? &remotePlayer : &localPlayer);
3541 if (player->promotionUp)
3543 XtPopdown(player->promotionShell);
3544 XtDestroyWidget(player->promotionShell);
3545 player->promotionUp = False;
3552 case PlayFromGameFile:
3553 case TwoMachinesPlay:
3556 case MachinePlaysBlack:
3557 if (BlackOnMove(forwardMostMove))
3559 DisplayMessage("It is not your turn", fromRemotePlayer);
3565 case MachinePlaysWhite:
3566 if (!BlackOnMove(forwardMostMove))
3568 DisplayMessage("It is not your turn", fromRemotePlayer);
3575 forwardMostMove = currentMove;
3582 if (currentMove != forwardMostMove)
3584 DisplayMessage("Displayed position is not current",
3589 switch (event->type)
3592 if ((fromX >= 0) || (fromY >= 0))
3595 if (((fromX = EventToXSquare(event->xbutton.x)) < 1)
3596 || (fromX > BOARD_SIZE + 2)
3597 || ((fromY = EventToSquare(event->xbutton.y)) < 0))
3603 if (player->flipView)
3604 fromX = BOARD_SIZE + 3 - fromX;
3606 fromY = BOARD_SIZE - 1 - fromY;
3611 if ((fromX < 0) || (fromY < 0))
3614 if (((to_x = EventToXSquare(event->xbutton.x)) < 1)
3615 || (to_x > BOARD_SIZE + 2)
3616 || ((to_y = EventToSquare(event->xbutton.y)) < 0))
3618 if (gameMode == EditPosition && !off_board(fromX))
3621 boards[0][fromY][fromX] = EmptySquare;
3622 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
3623 XSync(localPlayer.xDisplay, False);
3625 if (updateRemotePlayer)
3626 XSync(remotePlayer.xDisplay, False);
3633 if (player->flipView)
3634 to_x = BOARD_SIZE + 3 - to_x;
3636 to_y = BOARD_SIZE - 1 - to_y;
3638 if ((fromX == to_x) && (fromY == to_y))
3644 if (gameMode == EditPosition)
3648 if (off_board(fromX))
3650 /* Remove a catched piece */
3652 c = ((fromX < 5) ^ player->flipView);
3653 i = PieceOfCatched(c, fromX, fromY, 0);
3662 piece = catchedIndexToPiece[c][i];
3668 /* remove piece from board field */
3670 piece = boards[0][fromY][fromX];
3671 boards[0][fromY][fromX] = EmptySquare;
3674 if (!off_board(to_x))
3676 /* drop piece to board field */
3677 ShogiSquare catched_piece;
3679 catched_piece = boards[0][to_y][to_x];
3681 if (catched_piece != EmptySquare)
3683 /* put piece to catched pieces */
3684 int i = pieceToCatchedIndex[catched_piece];
3685 int c = (catched_piece < WhitePawn);
3689 /* place moved piece */
3690 boards[0][to_y][to_x] = piece;
3694 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
3695 XSync(localPlayer.xDisplay, False);
3697 if (updateRemotePlayer)
3698 XSync(remotePlayer.xDisplay, False);
3703 if (off_board(fromX))
3705 int c = (BlackOnMove(forwardMostMove) ? 0 : 1);
3706 int piece = PieceOfCatched(c, fromX, fromY, currentMove);
3708 if (piece == no_piece)
3715 if (updateRemotePlayer
3716 && (BlackOnMove(forwardMostMove) == fromRemotePlayer))
3718 DisplayMessage("Do not try to drop your opponent's pieces!",
3724 fromX = fromY = piece + 81;
3726 move_type = (BlackOnMove(forwardMostMove)
3727 ? BlackDrop : WhiteDrop);
3728 MakeMove(&move_type, fromX, fromY, to_x, to_y);
3731 if (updateRemotePlayer)
3732 BlinkSquare(to_y, to_x, boards[currentMove][to_y][to_x]);
3735 FinishUserMove(move_type, to_x, to_y);
3739 else if (off_board(to_x))
3748 from_piece = boards[currentMove][fromY][fromX];
3750 if ((from_piece != EmptySquare)
3751 && updateRemotePlayer
3752 && ((from_piece < WhitePawn) == fromRemotePlayer))
3754 DisplayMessage("Do not try to move your opponent's pieces!",
3760 if (PromotionPossible(fromY, to_y, from_piece))
3762 PromotionPopUp(from_piece, to_x, to_y, fromRemotePlayer);
3766 move_type = NormalMove;
3767 MakeMove(&move_type, fromX, fromY, to_x, to_y);
3770 if (updateRemotePlayer)
3771 BlinkSquare(to_y, to_x, boards[currentMove][to_y][to_x]);
3774 FinishUserMove(move_type, to_x, to_y);
3784 FinishUserMove(ShogiMove move_type, int to_x, int to_y)
3786 char user_move[MSG_SIZ];
3788 /* output move for gnushogi */
3791 case BlackPromotion:
3792 case WhitePromotion:
3793 sprintf(user_move, "%c%c%c%c+\n",
3794 '9' - fromX, 'i' - fromY, '9' - to_x, 'i' - to_y);
3799 sprintf(user_move, "%c*%c%c\n",
3800 catchedIndexToChar[fromX - 81], '9' - to_x, 'i' - to_y);
3804 sprintf(user_move, "%c%c%c%c\n",
3805 '9' - fromX, 'i' - fromY, '9' - to_x, 'i' - to_y);
3809 fprintf(stderr, "%s: internal error; bad move_type\n",
3810 (char *)programName);
3814 Attention(firstProgramPID);
3817 SendTimeRemaining(toFirstProgFP);
3819 SendToProgram(user_move, toFirstProgFP);
3820 strcpy(moveList[currentMove - 1], user_move);
3824 if (gameMode == PauseGame)
3826 /* a user move restarts a paused game*/
3827 PauseProc(NULL, NULL, NULL, NULL);
3835 case BeginningOfGame:
3836 if (localPlayer.appData.noShogiProgram)
3837 lastGameMode = gameMode = ForceMoves;
3839 lastGameMode = gameMode = MachinePlaysWhite;
3844 case MachinePlaysWhite:
3845 case MachinePlaysBlack:
3854 /* Simple parser for moves from gnushogi. */
3856 ParseMachineMove(char *machine_move, ShogiMove *move_type,
3857 int *from_x, int *from_y, int *to_x, int *to_y)
3859 #define no_digit(c) (c < '0' || c > '9')
3861 if (no_digit(machine_move[0]))
3863 switch (machine_move[0])
3902 *to_x = '9' - machine_move[2];
3903 *to_y = 'i' - machine_move[3];
3907 *from_x = '9' - machine_move[0] ;
3908 *from_y = 'i' - machine_move[1];
3909 *to_x = '9' - machine_move[2];
3910 *to_y = 'i' - machine_move[3];
3912 switch (machine_move[4])
3915 *move_type = (BlackOnMove(forwardMostMove)
3916 ? BlackPromotion : WhitePromotion);
3920 *move_type = NormalMove;
3931 SkipString(char **mpr)
3933 while (**mpr == ' ')
3936 while ((**mpr != ' ') && (**mpr != NULLCHAR) && (**mpr != '\n'))
3939 while (**mpr == ' ')
3947 HandleMachineMove(char *message, FILE *fp)
3949 char machine_move[MSG_SIZ], buf1[MSG_SIZ], buf2[MSG_SIZ];
3950 int from_x, from_y, to_x, to_y;
3951 ShogiMove move_type;
3955 long time_remaining;
3958 maybeThinking = False;
3960 if (strncmp(message, "warning:", 8) == 0)
3962 DisplayMessage(message, False);
3964 if (updateRemotePlayer)
3965 DisplayMessage(message, True);
3971 * If shogi program startup fails, exit with an error message.
3972 * Attempts to recover here are futile.
3975 if ((strstr(message, "unknown host") != NULL)
3976 || (strstr(message, "No remote directory") != NULL)
3977 || (strstr(message, "not found") != NULL)
3978 || (strstr(message, "No such file") != NULL)
3979 || (strstr(message, "Permission denied") != NULL))
3982 "%s: failed to start shogi program %s on %s: %s\n",
3984 ((fp == fromFirstProgFP)
3985 ? localPlayer.appData.firstShogiProgram
3986 : localPlayer.appData.secondShogiProgram),
3987 ((fp == fromFirstProgFP)
3988 ? localPlayer.appData.firstHost
3989 : localPlayer.appData.secondHost),
3991 ShutdownShogiPrograms(message);
3996 * If the move is illegal, cancel it and redraw the board.
3999 if (strncmp(message, "Illegal move", 12) == 0)
4001 if (fp == fromFirstProgFP && firstSendTime == 2)
4003 /* First program doesn't have the "time" command */
4007 else if (fp == fromSecondProgFP && secondSendTime == 2)
4009 /* Second program doesn't have the "time" command */
4014 if (forwardMostMove <= backwardMostMove)
4017 if (gameMode == PauseGame)
4018 PauseProc(NULL, NULL, NULL, NULL);
4020 if (gameMode == PlayFromGameFile)
4022 /* Stop reading this game file */
4023 gameMode = ForceMoves;
4027 currentMove = --forwardMostMove;
4029 if ((gameMode == PlayFromGameFile)
4030 || (gameMode == ForceMoves))
4031 DisplayClocks(ReDisplayTimers);
4033 DisplayClocks(SwitchTimers);
4035 sprintf(buf1, "Illegal move: %s", parseList[currentMove]);
4036 DisplayMessage(buf1, False);
4038 if (updateRemotePlayer)
4039 DisplayMessage(buf1, True);
4043 * Disable blinking of the target square.
4048 /* If BlinkCount is even, the piece is currently displayed. */
4049 if (!(BlinkCount & 1))
4050 DrawSquare (BlinkRow, BlinkCol, EmptySquare);
4052 /* BlinkCount = 0 will force the next blink timeout
4058 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
4060 XSync(localPlayer.xDisplay, False);
4062 if (updateRemotePlayer)
4063 XSync(remotePlayer.xDisplay, False);
4068 if (strstr(message, "GNU Shogi") != NULL)
4070 at_least_gnushogi_1_2p03 = True;
4074 if (strncmp(message, "Hint:", 5) == 0)
4077 sscanf(message, "Hint: %s", machine_move);
4078 ParseMachineMove(machine_move, &move_type,
4079 &from_x, &from_y, &to_x, &to_y);
4081 if (move_type == WhitePromotion || move_type == BlackPromotion)
4084 promoPiece = NULLCHAR;
4086 move_type = MakeAlg(from_x, from_y, to_x, to_y, promoPiece,
4088 sprintf(buf2, "Hint: %s", buf1);
4089 DisplayMessage(buf2, False);
4091 if (updateRemotePlayer)
4092 DisplayMessage(buf2, True);
4097 if (strncmp(message, "Clocks:", 7) == 0)
4099 sscanf(message, "Clocks: %ld %ld",
4100 &blackTimeRemaining, &whiteTimeRemaining);
4101 DisplayClocks(ReDisplayTimers);
4110 if (strncmp(message, "Black", 5) == 0)
4112 ShutdownShogiPrograms("Black wins");
4115 else if (strncmp(message, "White", 5) == 0)
4117 ShutdownShogiPrograms("White wins");
4120 else if (strncmp(message, "Repetition", 10) == 0)
4122 ShutdownShogiPrograms("Repetition");
4125 else if (strncmp(message, "opponent mates!", 15) == 0)
4127 switch ((gameMode == PauseGame) ? pausePreviousMode : gameMode)
4129 case MachinePlaysWhite:
4130 ShutdownShogiPrograms("Black wins");
4133 case MachinePlaysBlack:
4134 ShutdownShogiPrograms("White wins");
4137 case TwoMachinesPlay:
4138 ShutdownShogiPrograms((fp == fromFirstProgFP)
4139 ? "Black wins" : "White wins");
4149 else if (strncmp(message, "computer mates!", 15) == 0)
4151 switch ((gameMode == PauseGame) ? pausePreviousMode : gameMode)
4153 case MachinePlaysWhite:
4154 ShutdownShogiPrograms("White wins");
4157 case MachinePlaysBlack:
4158 ShutdownShogiPrograms("Black wins");
4161 case TwoMachinesPlay:
4162 ShutdownShogiPrograms((fp == fromFirstProgFP)
4163 ? "White wins" : "Black wins");
4173 else if (strncmp(message, "Draw", 4) == 0)
4175 ShutdownShogiPrograms("Draw");
4180 * normal machine reply move
4182 maybeThinking = True;
4184 if (strstr(message, "...") != NULL)
4186 sscanf(message, "%s %s %s", buf1, buf2, machine_move);
4190 SkipString(&mpr); /* skip move number */
4191 SkipString(&mpr); /* skip ... */
4192 SkipString(&mpr); /* skip move */
4194 if ((gameMode != TwoMachinesPlay) && (gameMode != ForceMoves)
4195 && ((*mpr == '-') || ((*mpr >= '0') && (*mpr <= '9'))))
4197 /* synchronize with shogi program clock */
4198 sscanf(mpr, "%ld", &time_remaining);
4202 printf("from '%s' synchronize %s clock %ld\n",
4204 (BlackOnMove(forwardMostMove)
4210 if (BlackOnMove(forwardMostMove))
4211 blackTimeRemaining = time_remaining;
4213 whiteTimeRemaining = time_remaining;
4217 if (machine_move[0] == NULLCHAR)
4225 if (strstr(message, "time") == NULL)
4227 /* remaining time will be determined from move */
4228 SkipString(&mpr); /* skip move number */
4229 SkipString(&mpr); /* skip move */
4232 if ((gameMode != TwoMachinesPlay) && (gameMode != ForceMoves)
4233 && ((*mpr == '-') || ((*mpr >= '0') && (*mpr <= '9'))))
4235 /* synchronize with shogi program clock */
4236 sscanf(mpr, "%ld", &time_remaining);
4240 printf("from '%s' synchronize %s clock %ld\n",
4242 ((!BlackOnMove(forwardMostMove))
4243 ? "Black's" : "White's"),
4247 if (!BlackOnMove(forwardMostMove))
4248 blackTimeRemaining = time_remaining;
4250 whiteTimeRemaining = time_remaining;
4256 printf("ignore noise: '%s'\n", message);
4258 return; /* ignore noise */
4261 strcpy(moveList[forwardMostMove], machine_move);
4263 ParseMachineMove(machine_move, &move_type, &from_x, &from_y,
4266 if (gameMode != PauseGame)
4267 currentMove = forwardMostMove; /* display latest move */
4269 MakeMove(&move_type, from_x, from_y, to_x, to_y);
4272 if (gameMode != TwoMachinesPlay)
4273 BlinkSquare(to_y, to_x, boards[currentMove][to_y][to_x]);
4276 if ((gameMode != PauseGame) && localPlayer.appData.ringBellAfterMoves)
4277 putc(BELLCHAR, stderr);
4279 if ((gameMode == TwoMachinesPlay)
4280 || ((gameMode == PauseGame)
4281 && (pausePreviousMode == TwoMachinesPlay)))
4283 strcat(machine_move, "\n");
4285 if (BlackOnMove(forwardMostMove))
4287 Attention(secondProgramPID);
4290 SendTimeRemaining(toSecondProgFP);
4292 SendToProgram(machine_move, toSecondProgFP);
4297 SendToProgram(localPlayer.appData.blackString,
4303 Attention(firstProgramPID);
4306 SendTimeRemaining(toFirstProgFP);
4308 SendToProgram(machine_move, toFirstProgFP);
4313 SendToProgram(localPlayer.appData.blackString,
4328 if (!ReadGameFileProc())
4331 if (matchMode == MatchOpening)
4335 = XtAppAddTimeOut(appContext,
4336 (int)(1000 * localPlayer.appData.timeDelay),
4337 (XtTimerCallbackProc) ReadGameFile, NULL);
4345 * FIXME: there is a naming inconsistency: here ReadGameFileProc() is
4346 * called by ReadGameFile() while in other places XXXProc() calls XXX().
4350 ReadGameFileProc(void)
4352 ShogiMove move_type;
4353 char move[MSG_SIZ], buf[MSG_SIZ];
4355 if (gameFileFP == NULL)
4358 if (gameMode == PauseGame)
4361 if (gameMode != PlayFromGameFile)
4370 XtPopdown(commentShell);
4371 XtDestroyWidget(commentShell);
4375 fgets(move, MSG_SIZ, gameFileFP);
4376 move[strlen(move) - 1] = NULLCHAR;
4377 sprintf(buf, "# %s game file", programName);
4379 if (strncmp(move, buf, strlen(buf)))
4381 strcat(move, ": no xshogi game file");
4382 DisplayMessage(move, False);
4391 move_type = (ShogiMove)0;
4393 lastGameMode = gameMode;
4394 gameMode = ForceMoves;
4397 if (!loaded_game_finished)
4398 DisplayMessage("End of game file", False);
4400 if (readGameXID != 0)
4402 XtRemoveTimeOut(readGameXID);
4416 * Apply a move to the given board. Oddity: move_type is ignored on input
4417 * unless the move is seen to be a pawn promotion, in which case move_type
4418 * tells us what to promote to.
4422 ApplyMove(ShogiMove *move_type, int from_x, int from_y,
4423 int to_x, int to_y, int currentMove)
4425 ShogiSquare piece, cpiece;
4432 c = (BlackOnMove(currentMove) ? 1 : 0);
4433 cpiece = catchedIndexToPiece[c][i];
4434 boards[currentMove][to_y][to_x] = cpiece;
4435 catches[currentMove][c][i]--;
4437 else if (PromotionPossible(from_y, to_y,
4438 piece = boards[currentMove][from_y][from_x]))
4440 cpiece = boards[currentMove][to_y][to_x];
4442 if (cpiece != EmptySquare)
4444 i = pieceToCatchedIndex[cpiece];
4445 c = (cpiece < WhitePawn);
4446 catches[currentMove][c][i]++;
4449 if (*move_type == NormalMove)
4451 boards[currentMove][to_y][to_x] = piece;
4455 boards[currentMove][to_y][to_x] = piece = pieceToPromoted[piece];
4459 boards[currentMove][from_y][from_x] = EmptySquare;
4463 ShogiSquare piece = boards[currentMove][to_y][to_x];
4465 if (piece != EmptySquare)
4467 i = pieceToCatchedIndex[piece];
4468 c = (piece < WhitePawn);
4469 catches[currentMove][c][i]++;
4472 *move_type = NormalMove;
4473 boards[currentMove][to_y][to_x] =
4474 boards[currentMove][from_y][from_x];
4475 boards[currentMove][from_y][from_x] = EmptySquare;
4483 * MakeMove() displays moves. If they are illegal, GNU shogi will detect
4484 * this and send an Illegal move message. XShogi will then retract the move.
4485 * The clockMode False case is tricky because it displays the player on move.
4489 MakeMove(ShogiMove *move_type, int from_x, int from_y, int to_x, int to_y)
4491 char message[MSG_SIZ], movestr[MSG_SIZ];
4492 char promoPiece = NULLCHAR;
4496 CopyBoard(boards[forwardMostMove], boards[forwardMostMove - 1]);
4497 CopyCatches(catches[forwardMostMove], catches[forwardMostMove - 1]);
4499 ApplyMove(move_type, from_x, from_y, to_x, to_y, forwardMostMove);
4501 endMessage[0] = NULLCHAR;
4503 timeRemaining[0][forwardMostMove] = blackTimeRemaining;
4504 timeRemaining[1][forwardMostMove] = whiteTimeRemaining;
4506 if ((gameMode == PauseGame) && (pausePreviousMode != PlayFromGameFile))
4509 currentMove = forwardMostMove;
4511 if (gameMode == PlayFromGameFile)
4513 sprintf(message, "%d. %s%s",
4514 ((currentMove + 1) / 2),
4515 (BlackOnMove(currentMove) ? "... " : ""),
4517 strcpy(parseList[currentMove - 1], currentMoveString);
4521 if ((*move_type == WhitePromotion) || (*move_type == BlackPromotion))
4524 promoPiece = NULLCHAR;
4526 MakeAlg(from_x, from_y, to_x, to_y, promoPiece,
4527 currentMove - 1, movestr);
4528 sprintf(message, "%d. %s%s",
4529 ((currentMove + 1) / 2),
4530 (BlackOnMove(currentMove) ? "... " : ""),
4532 strcpy(parseList[currentMove - 1], movestr);
4535 DisplayMessage(message, False);
4537 if ((gameMode == PlayFromGameFile) || (gameMode == ForceMoves)
4538 || ((gameMode == PauseGame)
4539 && (pausePreviousMode == PlayFromGameFile)))
4541 DisplayClocks(ReDisplayTimers);
4545 DisplayClocks(SwitchTimers);
4548 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
4550 XSync(localPlayer.xDisplay, False);
4552 if (updateRemotePlayer)
4554 DisplayMessage(message, True);
4555 XSync(remotePlayer.xDisplay, False);
4563 InitShogiProgram(char *host_name, char *program_name, int *pid,
4564 FILE **to, FILE **from, XtIntervalId *xid, int *sendTime)
4568 int to_prog[2], from_prog[2];
4569 FILE *from_fp, *to_fp;
4573 if (localPlayer.appData.noShogiProgram)
4576 signal(SIGPIPE, CatchPipeSignal);
4580 if ((*pid = fork()) == 0)
4582 signal(SIGPIPE, CatchPipeSignal);
4584 dup2(to_prog[0], 0);
4585 dup2(from_prog[1], 1);
4588 close(from_prog[0]);
4589 close(from_prog[1]);
4590 dup2(1, fileno(stderr)); /* force stderr to the pipe */
4592 if (localPlayer.appData.searchTime != NULL)
4594 sprintf(arg_buf, "%d", searchTime);
4596 arg2 = (char *)NULL;
4598 else if (localPlayer.appData.searchDepth > 0)
4600 sprintf(arg_buf, "%d", localPlayer.appData.searchDepth);
4606 sprintf(arg_buf, "%d", localPlayer.appData.movesPerSession);
4608 arg2 = localPlayer.appData.timeControl;
4611 if (strcmp(host_name, "localhost") == 0)
4613 execlp(program_name, program_name, arg1, arg2,
4618 execlp(localPlayer.appData.remoteShell,
4619 localPlayer.appData.remoteShell,
4620 host_name, program_name, arg1, arg2,
4624 perror(program_name);
4629 close(from_prog[1]);
4631 *from = from_fp = fdopen(from_prog[0], "r");
4632 *to = to_fp = fdopen(to_prog[1], "w");
4633 setbuf(from_fp, NULL);
4634 setbuf(to_fp, NULL);
4636 ReceiveFromProgram(from_fp, &dummy_source, &dummy_id); /* "GNU Shogi"*/
4638 if (!at_least_gnushogi_1_2p03)
4640 fprintf(stderr, "you must have at least gnushogi-1.2p03\n");
4647 *xid = XtAppAddInput(appContext, fileno(from_fp),
4648 (XtPointer)XtInputReadMask,
4649 (XtInputCallbackProc)ReceiveFromProgram,
4650 (XtPointer)from_fp);
4652 SendToProgram(localPlayer.appData.initString, *to);
4654 if (localPlayer.appData.gameIn)
4655 SendToProgram("gamein\n", *to);
4657 SendSearchDepth(*to);
4661 /* Does program have "time" command? */
4664 sprintf(buf, "time %ld\n", blackTimeRemaining / 10);
4665 SendToProgram(buf, to_fp);
4666 ReceiveFromProgram(from_fp, &dummy_source, &dummy_id);
4670 *sendTime = 1; /* yes! */
4671 sprintf(buf, "otime %ld\n", whiteTimeRemaining / 10);
4672 SendToProgram(buf, to_fp);
4673 ReceiveFromProgram(from_fp, &dummy_source, &dummy_id);
4682 ShutdownShogiPrograms(char *why)
4684 lastGameMode = gameMode;
4685 gameMode = EndOfGame;
4687 CopyBoard(boards[currentMove + 1], boards[currentMove]);
4688 CopyCatches(catches[currentMove + 1], catches[currentMove]);
4689 strncpy(parseList[currentMove], why, MOVE_LEN);
4690 parseList[currentMove][MOVE_LEN - 1] = NULLCHAR;
4692 DisplayMessage(why, False);
4694 if (readGameXID != 0)
4695 XtRemoveTimeOut(readGameXID);
4699 if (firstProgramPID != 0)
4701 fclose(fromFirstProgFP);
4702 fclose(toFirstProgFP);
4703 fromFirstProgFP = toFirstProgFP = NULL;
4705 if (kill(firstProgramPID, SIGTERM) == 0)
4709 firstProgramPID = 0;
4711 if (firstProgramXID != 0)
4712 XtRemoveInput(firstProgramXID);
4714 firstProgramXID = 0;
4716 if (secondProgramPID != 0)
4718 fclose(fromSecondProgFP);
4719 fclose(toSecondProgFP);
4720 fromSecondProgFP = toSecondProgFP = NULL;
4722 if (kill(secondProgramPID, SIGTERM) == 0)
4726 secondProgramPID = 0;
4728 if (secondProgramXID != 0)
4729 XtRemoveInput(secondProgramXID);
4731 secondProgramXID = 0;
4733 DisplayClocks(StopTimers);
4735 if (matchMode != MatchFalse)
4737 if (localPlayer.appData.saveGameFile[0] != NULLCHAR)
4738 SaveGame(localPlayer.appData.saveGameFile);
4748 CommentPopUp(char *label)
4752 Dimension bw_width, pw_width;
4756 XtPopdown(commentShell);
4757 XtDestroyWidget(commentShell);
4761 DisplayMessage("Comment", False);
4763 XtSetArg(args[0], XtNwidth, &bw_width);
4764 XtGetValues(localPlayer.formWidget, args, 1);
4766 XtSetArg(args[0], XtNresizable, True);
4767 XtSetArg(args[1], XtNwidth, bw_width - 8);
4769 commentShell = XtCreatePopupShell("Comment",
4770 transientShellWidgetClass,
4771 localPlayer.commandsWidget, args, 2);
4773 XtSetArg(args[0], XtNlabel, label);
4775 (void)XtCreateManagedWidget("commentLabel", labelWidgetClass,
4776 commentShell, args, 1);
4778 XtRealizeWidget(commentShell);
4780 XtSetArg(args[0], XtNwidth, &pw_width);
4781 XtGetValues(commentShell, args, 1);
4783 XtTranslateCoords(localPlayer.shellWidget,
4784 (bw_width - pw_width) / 2, -50, &x, &y);
4786 XtSetArg(args[0], XtNx, x);
4787 XtSetArg(args[1], XtNy, y);
4788 XtSetValues(commentShell, args, 2);
4790 XtPopup(commentShell, XtGrabNone);
4798 FileNamePopUp(char *label, Boolean (*proc) (char *))
4801 Widget popup, dialog;
4803 Dimension bw_width, pw_width;
4807 XtSetArg(args[0], XtNwidth, &bw_width);
4808 XtGetValues(localPlayer.boardWidget, args, 1);
4810 XtSetArg(args[0], XtNresizable, True);
4811 XtSetArg(args[1], XtNwidth, DIALOG_SIZE);
4813 popup = XtCreatePopupShell("File Name Prompt",
4814 transientShellWidgetClass,
4815 localPlayer.commandsWidget, args, 2);
4817 XtSetArg(args[0], XtNlabel, label);
4818 XtSetArg(args[1], XtNvalue, "");
4820 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
4823 XawDialogAddButton(dialog, "ok", FileNameCallback, (XtPointer) dialog);
4824 XawDialogAddButton(dialog, "cancel", FileNameCallback,
4825 (XtPointer) dialog);
4827 XtRealizeWidget(popup);
4829 XtSetArg(args[0], XtNwidth, &pw_width);
4830 XtGetValues(popup, args, 1);
4832 XtTranslateCoords(localPlayer.boardWidget,
4833 (bw_width - pw_width) / 2, 10, &x, &y);
4835 XtSetArg(args[0], XtNx, x);
4836 XtSetArg(args[1], XtNy, y);
4837 XtSetValues(popup, args, 2);
4839 XtPopup(popup, XtGrabExclusive);
4842 XtSetKeyboardFocus(localPlayer.shellWidget, popup);
4849 FileNameCallback(Widget w, XtPointer client_data, XtPointer call_data)
4854 XtSetArg(args[0], XtNlabel, &name);
4855 XtGetValues(w, args, 1);
4857 if (strcmp(name, "cancel") == 0)
4859 XtPopdown(w = XtParent(XtParent(w)));
4866 FileNameAction(w, NULL, NULL, NULL);
4873 FileNameAction(Widget w, XEvent *event, String *prms, Cardinal *nprms)
4878 name = XawDialogGetValueString(w = XtParent(w));
4880 if ((name != NULL) && (*name != NULLCHAR))
4883 XtPopdown(w = XtParent(w));
4886 (*fileProc)(buf); /* I can't see a way not
4887 to use a global here */
4892 XtPopdown(w = XtParent(w));
4902 PromotionPopUp(ShogiSquare piece, int to_x, int to_y, int fromRemotePlayer)
4907 Dimension bw_width, bw_height, pw_width, pw_height;
4909 player = (fromRemotePlayer ? &remotePlayer : &localPlayer);
4915 XtSetArg(args[0], XtNwidth, &bw_width);
4916 XtSetArg(args[1], XtNheight, &bw_height);
4917 XtGetValues(player->boardWidget, args, 2);
4919 XtSetArg(args[0], XtNresizable, True);
4921 player->promotionShell
4922 = XtCreatePopupShell("Promotion",
4923 transientShellWidgetClass,
4924 player->commandsWidget, args, 1);
4926 XtSetArg(args[0], XtNlabel, "Promote piece?");
4927 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4928 player->promotionShell, args, 1);
4930 XawDialogAddButton(dialog, "Yes", PromotionCallback,
4931 (XtPointer) dialog);
4932 XawDialogAddButton(dialog, "No", PromotionCallback,
4933 (XtPointer) dialog);
4934 XawDialogAddButton(dialog, "cancel", PromotionCallback,
4935 (XtPointer) dialog);
4937 XtRealizeWidget(player->promotionShell);
4939 XtSetArg(args[0], XtNwidth, &pw_width);
4940 XtSetArg(args[1], XtNheight, &pw_height);
4941 XtGetValues(player->promotionShell, args, 2);
4943 XtTranslateCoords(player->boardWidget,
4944 ((bw_width - pw_width) / 2),
4946 + player->squareSize / 3
4947 + (((piece == BlackPawn) ^ (player->flipView))
4949 : (6 * (player->squareSize + LINE_GAP)))),
4952 XtSetArg(args[0], XtNx, x);
4953 XtSetArg(args[1], XtNy, y);
4954 XtSetValues(player->promotionShell, args, 2);
4956 XtPopup(player->promotionShell, XtGrabNone);
4958 player->promotionUp = True;
4965 PromotionCallback(Widget w, XtPointer client_data, XtPointer call_data)
4969 ShogiMove move_type;
4970 struct DisplayData *player;
4972 XtSetArg(args[0], XtNlabel, &name);
4973 XtGetValues(w, args, 1);
4975 w = XtParent(XtParent(w));
4976 player = ((w == remotePlayer.promotionShell)
4977 ? &remotePlayer : &localPlayer);
4980 player->promotionUp = False;
4985 if (strcmp(name, "Yes") == 0)
4987 if ((int)pmi.piece < (int)WhitePawn)
4988 move_type = BlackPromotion;
4990 move_type = WhitePromotion;
4992 else if (strcmp(name, "No") == 0)
4994 move_type = NormalMove;
4996 else /* strcmp(name, "cancel") == 0 */
5002 MakeMove(&move_type, fromX, fromY, pmi.to_x, pmi.to_y);
5005 if (updateRemotePlayer)
5007 BlinkSquare(pmi.to_y, pmi.to_x,
5008 boards[currentMove][pmi.to_y][pmi.to_x]);
5012 FinishUserMove(move_type, pmi.to_x, pmi.to_y);
5019 FileModePopUp(char *name)
5024 Dimension bw_width, bw_height, pw_width, pw_height;
5026 struct DisplayData *player = &localPlayer;
5028 strcpy(fmi.name, name);
5030 XtSetArg(args[0], XtNwidth, &bw_width);
5031 XtSetArg(args[1], XtNheight, &bw_height);
5032 XtGetValues(player->boardWidget, args, 2);
5034 XtSetArg(args[0], XtNresizable, True);
5035 player->filemodeShell
5036 = XtCreatePopupShell("FileMode",
5037 transientShellWidgetClass,
5038 player->commandsWidget, args, 1);
5040 XtSetArg(args[0], XtNlabel, "Append to existing file?");
5041 dialog = XtCreateManagedWidget("filemode", dialogWidgetClass,
5042 player->filemodeShell, args, 1);
5044 XawDialogAddButton(dialog, "Yes", FileModeCallback,
5045 (XtPointer) dialog);
5046 XawDialogAddButton(dialog, "No", FileModeCallback,
5047 (XtPointer) dialog);
5048 XawDialogAddButton(dialog, "cancel", FileModeCallback,
5049 (XtPointer) dialog);
5051 XtRealizeWidget(player->filemodeShell);
5053 XtSetArg(args[0], XtNwidth, &pw_width);
5054 XtSetArg(args[1], XtNheight, &pw_height);
5055 XtGetValues(player->filemodeShell, args, 2);
5057 XtTranslateCoords(player->boardWidget, (bw_width - pw_width) / 2,
5058 LINE_GAP + player->squareSize/3 +
5059 (6*(player->squareSize + LINE_GAP)),
5062 XtSetArg(args[0], XtNx, x);
5063 XtSetArg(args[1], XtNy, y);
5064 XtSetValues(player->filemodeShell, args, 2);
5066 XtPopup(player->filemodeShell, XtGrabNone);
5075 FileModeCallback(Widget w, XtPointer client_data, XtPointer call_data)
5080 XtSetArg(args[0], XtNlabel, &name);
5081 XtGetValues(w, args, 1);
5083 XtPopdown(w = XtParent(XtParent(w)));
5086 if (strcmp(name, "Yes") == 0)
5088 strcpy(fmi.mode, "a");
5090 else if (strcmp(name, "No") == 0)
5092 strcpy(fmi.mode, "w");
5094 else /* strcmp(name, "cancel") == 0 */
5100 XtPopdown(localPlayer.filemodeShell);
5101 XtDestroyWidget(localPlayer.filemodeShell);
5112 SelectCommand(Widget w, XtPointer client_data, XtPointer call_data)
5114 Cardinal fromRemotePlayer = (Cardinal)client_data;
5116 XawListReturnStruct *list_return = XawListShowCurrent(w);
5118 player = fromRemotePlayer ? &remotePlayer : &localPlayer;
5122 if (player->promotionUp)
5124 XtPopdown(player->promotionShell);
5125 XtDestroyWidget(player->promotionShell);
5126 player->promotionUp = False;
5129 (*buttonProcs[list_return->list_index])
5130 (w, NULL, NULL, &fromRemotePlayer);
5140 HighlightProcButton(XtActionProc proc)
5146 XawListUnhighlight(localPlayer.commandsWidget);
5148 if (updateRemotePlayer)
5149 XawListUnhighlight(remotePlayer.commandsWidget);
5156 if (buttonProcs[i] == NULL)
5158 XawListUnhighlight(localPlayer.commandsWidget);
5160 if (updateRemotePlayer)
5161 XawListUnhighlight(remotePlayer.commandsWidget);
5166 if (buttonProcs[i] == proc)
5168 XawListHighlight(localPlayer.commandsWidget, i);
5170 if (updateRemotePlayer)
5171 XawListHighlight(remotePlayer.commandsWidget, i);
5188 case BeginningOfGame:
5189 if (localPlayer.appData.noShogiProgram)
5190 HighlightProcButton(ForceProc);
5192 HighlightProcButton(MachineBlackProc);
5196 case MachinePlaysBlack:
5197 HighlightProcButton(MachineBlackProc);
5200 case MachinePlaysWhite:
5201 HighlightProcButton(MachineWhiteProc);
5204 case TwoMachinesPlay:
5205 HighlightProcButton(TwoMachinesProc);
5209 HighlightProcButton(ForceProc);
5213 case PlayFromGameFile:
5214 HighlightProcButton(LoadGameProc);
5218 HighlightProcButton(PauseProc);
5222 HighlightProcButton(EditPositionProc);
5227 HighlightProcButton(NULL);
5240 QuitRemotePlayerProc(void)
5242 /* This should be modified... */
5243 XCloseDisplay(remotePlayer.xDisplay);
5244 /* XtDestroyWidget(remotePlayer.shellWidget); */
5245 updateRemotePlayer = False;
5246 DisplayMessage("Remote player has pressed Quit", False);
5253 QuitProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5255 if (updateRemotePlayer)
5256 QuitRemotePlayerProc();
5258 ShutdownShogiPrograms("Quitting");
5265 LoadGameProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5267 int fromRemotePlayer = *nprms;
5269 if (fromRemotePlayer)
5271 DisplayMessage("only opponent may load game", fromRemotePlayer);
5275 if (gameMode != BeginningOfGame)
5277 DisplayMessage("Press Reset first.", False);
5281 if (localPlayer.appData.loadGameFile == NULL)
5282 FileNamePopUp("Game file name?", LoadGame);
5284 (void) LoadGame(localPlayer.appData.loadGameFile);
5291 LoadGame(char *name)
5295 loaded_game_finished = 0;
5297 if (gameMode != BeginningOfGame)
5299 DisplayMessage("Press Reset first", False);
5303 if (localPlayer.appData.loadGameFile != name)
5305 if (localPlayer.appData.loadGameFile)
5306 XtFree(localPlayer.appData.loadGameFile);
5308 localPlayer.appData.loadGameFile = XtMalloc(strlen(name) + 1);
5309 strcpy(localPlayer.appData.loadGameFile, name);
5312 if ((gameFileFP = fopen(name, "r")) == NULL)
5314 sprintf(buf, "Can't open %s", name);
5315 DisplayMessage(buf, False);
5316 XtFree(localPlayer.appData.loadGameFile);
5317 localPlayer.appData.loadGameFile = NULL;
5321 lastGameMode = gameMode = PlayFromGameFile;
5324 DisplayClocks(StopTimers);
5326 if (firstProgramXID == 0)
5328 InitShogiProgram(localPlayer.appData.firstHost,
5329 localPlayer.appData.firstShogiProgram,
5330 &firstProgramPID, &toFirstProgFP,
5331 &fromFirstProgFP, &firstProgramXID,
5335 SendToProgram(localPlayer.appData.initString, toFirstProgFP);
5336 SendSearchDepth(toFirstProgFP);
5337 SendToProgram("force\n", toFirstProgFP);
5339 currentMove = forwardMostMove = backwardMostMove = 0;
5350 * Restart the shogi program and feed it all the moves made so far.
5351 * Used when the user wants to back up from end of game, when gnushogi
5352 * has already exited. Assumes gameMode == EndOfGame.
5356 ResurrectShogiProgram(void)
5361 if (currentMove > 0)
5362 currentMove--; /* delete "Black wins" or the like */
5364 InitShogiProgram(localPlayer.appData.firstHost,
5365 localPlayer.appData.firstShogiProgram,
5366 &firstProgramPID, &toFirstProgFP, &fromFirstProgFP,
5367 &firstProgramXID, &firstSendTime);
5369 SendToProgram(localPlayer.appData.initString, toFirstProgFP);
5370 SendSearchDepth(toFirstProgFP);
5371 SendToProgram("force\n", toFirstProgFP);
5372 gameMode = lastGameMode = ForceMoves;
5375 i = (whitePlaysFirst ? 1 : 0);
5377 if (startedFromSetupPosition)
5378 SendBoard(toFirstProgFP, boards[i], catches[i]);
5380 for (; i < currentMove; i++)
5382 strcpy(buf, moveList[i]);
5383 SendToProgram(buf, toFirstProgFP);
5388 /* can't tell gnushogi what its clock should read,
5389 so we bow to its notion. */
5390 DisplayClocks(ResetTimers);
5391 timeRemaining[0][currentMove] = blackTimeRemaining;
5392 timeRemaining[1][currentMove] = whiteTimeRemaining;
5400 MachineWhiteProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5402 int fromRemotePlayer = *nprms;
5404 if (updateRemotePlayer)
5406 DisplayMessage("no machine moves in challenge mode",
5412 if (gameMode == PauseGame)
5413 PauseProc(w, event, prms, nprms);
5415 if (gameMode == PlayFromGameFile)
5416 ForceProc(w, event, prms, nprms);
5418 if (gameMode == EditPosition)
5421 if ((gameMode == EndOfGame)
5422 || (gameMode == PlayFromGameFile)
5423 || (gameMode == TwoMachinesPlay)
5424 || localPlayer.appData.noShogiProgram
5425 || (gameMode == MachinePlaysWhite))
5430 if (BlackOnMove((gameMode == ForceMoves)
5434 DisplayMessage("It is not White's turn.", False);
5438 if (gameMode == ForceMoves)
5439 forwardMostMove = currentMove;
5441 lastGameMode = gameMode = MachinePlaysWhite;
5443 SendToProgram(localPlayer.appData.whiteString, toFirstProgFP);
5444 DisplayClocks(StartTimers);
5451 MachineBlackProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5453 int fromRemotePlayer = *nprms;
5455 if (updateRemotePlayer)
5457 DisplayMessage("no machine moves in challenge mode",
5462 if (gameMode == PauseGame)
5463 PauseProc(w, event, prms, nprms);
5465 if (gameMode == PlayFromGameFile)
5466 ForceProc(w, event, prms, nprms);
5468 if (gameMode == EditPosition)
5471 if ((gameMode == EndOfGame)
5472 || (gameMode == PlayFromGameFile)
5473 || (gameMode == TwoMachinesPlay)
5474 || localPlayer.appData.noShogiProgram
5475 || (gameMode == MachinePlaysBlack))
5480 if (!BlackOnMove((gameMode == ForceMoves)
5484 DisplayMessage("It is not Black's turn.", False);
5488 if (gameMode == ForceMoves)
5489 forwardMostMove = currentMove;
5491 lastGameMode = gameMode = MachinePlaysBlack;
5493 SendToProgram(localPlayer.appData.blackString, toFirstProgFP);
5494 DisplayClocks(StartTimers);
5501 ForwardProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5507 int fromRemotePlayer = *nprms;
5509 if (updateRemotePlayer)
5511 DisplayMessage("Forward button disabled.", fromRemotePlayer);
5515 if ((gameMode == EndOfGame) || (gameMode == EditPosition))
5518 if (gameMode == PlayFromGameFile)
5519 PauseProc(w, event, prms, nprms);
5521 if (currentMove >= forwardMostMove)
5530 XQueryPointer(localPlayer.xDisplay, localPlayer.xBoardWindow,
5531 &root, &child, &root_x, &root_y,
5532 &win_x, &win_y, &state);
5536 state = event->xkey.state;
5539 if (state & ShiftMask)
5540 target = forwardMostMove;
5542 target = currentMove + 1;
5544 if (gameMode == ForceMoves)
5546 while (currentMove < target)
5548 strcpy(buf, moveList[currentMove++]);
5549 SendToProgram(buf, toFirstProgFP);
5554 currentMove = target;
5557 if (gameMode == ForceMoves)
5559 blackTimeRemaining = timeRemaining[0][currentMove];
5560 whiteTimeRemaining = timeRemaining[1][currentMove];
5563 DisplayClocks(ReDisplayTimers);
5564 DisplayMove(currentMove - 1);
5565 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
5576 if (updateRemotePlayer)
5579 if (localPlayer.appData.loadGameFile)
5580 XtFree(localPlayer.appData.loadGameFile);
5582 if (localPlayer.appData.loadPositionFile)
5583 XtFree(localPlayer.appData.loadPositionFile);
5585 localPlayer.appData.loadGameFile
5586 = localPlayer.appData.loadPositionFile = NULL;
5589 if (gameFileFP != NULL)
5600 ResetChallenge(void)
5604 if (localPlayer.appData.challengeDisplay)
5605 XtFree(localPlayer.appData.challengeDisplay);
5607 localPlayer.appData.challengeDisplay = NULL;
5615 ResetProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5617 int fromRemotePlayer = *nprms;
5619 if (fromRemotePlayer)
5621 DisplayMessage("Only your opponent may reset the game.",
5633 Reset(int redraw) /* Boolean */
5638 localPlayer.flipView = False;
5639 remotePlayer.flipView = True;
5640 startedFromSetupPosition = whitePlaysFirst = False;
5641 matchMode = MatchFalse;
5643 blackFlag = whiteFlag = False;
5644 maybeThinking = False;
5646 endMessage[0] = NULLCHAR;
5648 ShutdownShogiPrograms("");
5649 lastGameMode = gameMode = BeginningOfGame;
5651 InitPosition(redraw);
5652 DisplayClocks(ResetTimers);
5653 timeRemaining[0][0] = blackTimeRemaining;
5654 timeRemaining[1][0] = whiteTimeRemaining;
5655 InitShogiProgram(localPlayer.appData.firstHost,
5656 localPlayer.appData.firstShogiProgram,
5657 &firstProgramPID, &toFirstProgFP,
5658 &fromFirstProgFP, &firstProgramXID,
5663 XtPopdown(commentShell);
5664 XtDestroyWidget(commentShell);
5668 if (localPlayer.promotionUp)
5670 XtPopdown(localPlayer.promotionShell);
5671 XtDestroyWidget(localPlayer.promotionShell);
5672 localPlayer.promotionUp = False;
5675 if (updateRemotePlayer && remotePlayer.promotionUp)
5677 XtPopdown(remotePlayer.promotionShell);
5678 XtDestroyWidget(remotePlayer.promotionShell);
5679 remotePlayer.promotionUp = False;
5687 ClearCatches(int (*catches)[8])
5691 for (c = 0; c <= 1; c++)
5692 for (p = 0; p <= 7; p++)
5700 Challenge(char *name)
5705 XrmDatabase database;
5707 if (gameMode != BeginningOfGame)
5709 DisplayMessage("Press Reset first.", False);
5713 if (localPlayer.appData.challengeDisplay != name)
5715 if (localPlayer.appData.challengeDisplay)
5716 XtFree(localPlayer.appData.challengeDisplay);
5718 localPlayer.appData.challengeDisplay = XtMalloc(strlen(name) + 1);
5719 strcpy(localPlayer.appData.challengeDisplay, name);
5722 sprintf(buf, "trying to connect to %s.....", name);
5723 DisplayMessage(buf, False);
5728 if ((remotePlayer.xDisplay
5729 = XtOpenDisplay(appContext, name, "XShogi",
5730 "XShogi", 0, 0, &argc, argv)) == NULL)
5732 sprintf(buf, "Can't open display %s", name);
5733 DisplayMessage(buf, False);
5734 XtFree(localPlayer.appData.challengeDisplay);
5735 localPlayer.appData.challengeDisplay = NULL;
5739 DisplayMessage("connected! creating remote window...", False);
5741 remotePlayer.xScreen = DefaultScreen(remotePlayer.xDisplay);
5743 remotePlayer.shellWidget
5744 = XtAppCreateShell(NULL, "XShogi",
5745 applicationShellWidgetClass,
5746 remotePlayer.xDisplay, NULL, 0);
5748 database = XtDatabase(remotePlayer.xDisplay);
5750 XrmParseCommand(&database,
5751 shellOptions, XtNumber(shellOptions),
5752 "XShogi", &argc, argv);
5754 XtGetApplicationResources(remotePlayer.shellWidget,
5755 &remotePlayer.appData, clientResources,
5756 XtNumber(clientResources), NULL, 0);
5758 player = &remotePlayer;
5760 CreatePlayerWindow();
5762 updateRemotePlayer = True;
5764 DisplayName("REMOTE");
5765 DrawPosition(remotePlayer.boardWidget, NULL, NULL, NULL);
5766 DisplayClocks(ReDisplayTimers);
5768 DisplayMessage("ready to play", False);
5769 DisplayMessage("ready to play", True);
5778 ChallengeProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5780 int fromRemotePlayer = *nprms;
5782 if (updateRemotePlayer)
5784 DisplayMessage("You are already in challenge mode.",
5789 if (gameMode != BeginningOfGame)
5791 DisplayMessage("Press Reset first.", False);
5795 if (localPlayer.appData.challengeDisplay == NULL)
5796 FileNamePopUp("Challenge display?", Challenge);
5798 (void) Challenge(localPlayer.appData.challengeDisplay);
5805 SelectLevel(char *command)
5809 sprintf(buf, "level %s\n", command);
5810 SendToProgram(buf, toFirstProgFP);
5819 SelectLevelProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5821 if ((BlackOnMove(forwardMostMove) && (gameMode == MachinePlaysBlack))
5822 || (!BlackOnMove(forwardMostMove) && (gameMode == MachinePlaysWhite)))
5824 DisplayMessage("Wait until your turn.", False);
5828 FileNamePopUp("#moves #minutes", SelectLevel);
5836 MoveNowProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5838 if ((!BlackOnMove(forwardMostMove) && (gameMode == MachinePlaysBlack))
5839 || (BlackOnMove(forwardMostMove) && (gameMode == MachinePlaysWhite)))
5841 DisplayMessage("Wait until machine's turn.", False);
5845 Attention(firstProgramPID);
5853 LoadPositionProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5855 int fromRemotePlayer = *nprms;
5857 if (fromRemotePlayer)
5859 DisplayMessage("only opponent may load position", fromRemotePlayer);
5863 if (gameMode != BeginningOfGame)
5865 DisplayMessage("Press Reset first.", False);
5869 FileNamePopUp("Position file name?", LoadPosition);
5876 LoadPosition(char *name)
5878 char *p, line[MSG_SIZ], buf[MSG_SIZ];
5879 Board initial_position;
5880 Catched initial_catches;
5884 if (gameMode != BeginningOfGame)
5886 DisplayMessage("Press Reset first.", False);
5890 if (localPlayer.appData.loadPositionFile != name)
5892 if (localPlayer.appData.loadPositionFile)
5893 XtFree(localPlayer.appData.loadPositionFile);
5895 localPlayer.appData.loadPositionFile = XtMalloc(strlen(name) + 1);
5896 strcpy(localPlayer.appData.loadPositionFile, name);
5899 if ((fp = fopen(name, "r")) == NULL)
5901 sprintf(buf, "Can't open %s", name);
5902 DisplayMessage(buf, False);
5903 XtFree(localPlayer.appData.loadPositionFile);
5904 localPlayer.appData.loadPositionFile = NULL;
5908 lastGameMode = gameMode = ForceMoves;
5910 startedFromSetupPosition = True;
5912 if (firstProgramXID == 0)
5914 InitShogiProgram(localPlayer.appData.firstHost,
5915 localPlayer.appData.firstShogiProgram,
5916 &firstProgramPID, &toFirstProgFP,
5917 &fromFirstProgFP, &firstProgramXID,
5922 * Check and skip header information in position file.
5925 fgets(line, MSG_SIZ, fp);
5926 line[strlen(line) - 1] = NULLCHAR;
5927 sprintf(buf, "# %s position file", programName);
5929 if (strncmp(line, buf, strlen(buf)))
5931 strcat(line, ": no xshogi position file");
5932 DisplayMessage(line, False);
5937 fgets(line, MSG_SIZ, fp); /* skip opponents */
5939 for (i = BOARD_SIZE - 1; i >= 0; i--)
5941 fgets(line, MSG_SIZ, fp);
5943 for (p = line, j = 0; j < BOARD_SIZE; p++)
5945 int promoted = False; /* CHECKME: is this valid? */
5954 initial_position[i][j++] = CharToPiece(*p, promoted);
5961 for (color = 0; color <= 1; color++)
5963 fscanf(fp, "%i%i%i%i%i%i%i%i\n",
5964 &initial_catches[color][pawn],
5965 &initial_catches[color][lance],
5966 &initial_catches[color][knight],
5967 &initial_catches[color][silver],
5968 &initial_catches[color][gold],
5969 &initial_catches[color][bishop],
5970 &initial_catches[color][rook],
5971 &initial_catches[color][king]);
5975 whitePlaysFirst = False;
5979 fgets(line, MSG_SIZ, fp);
5981 if (strncmp(line, "white", strlen("white")) == 0)
5982 whitePlaysFirst = True;
5987 if (whitePlaysFirst)
5989 CopyBoard(boards[0], initial_position);
5990 CopyCatches(catches[0], initial_catches);
5991 strcpy(moveList[0], " ...\n");
5992 strcpy(parseList[0], " ...\n");
5993 currentMove = forwardMostMove = backwardMostMove = 1;
5994 CopyBoard(boards[1], initial_position);
5995 CopyCatches(catches[1], initial_catches);
5996 SendToProgram("white\n", toFirstProgFP);
5997 SendToProgram("force\n", toFirstProgFP);
5998 SendCurrentBoard(toFirstProgFP);
5999 DisplayMessage("White to play", False);
6003 currentMove = forwardMostMove = backwardMostMove = 0;
6004 CopyBoard(boards[0], initial_position);
6005 CopyCatches(catches[0], initial_catches);
6006 SendCurrentBoard(toFirstProgFP);
6007 SendToProgram("force\n", toFirstProgFP);
6008 DisplayMessage("Black to play", False);
6011 DisplayClocks(ResetTimers);
6012 timeRemaining[0][1] = blackTimeRemaining;
6013 timeRemaining[1][1] = whiteTimeRemaining;
6015 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
6023 EditPositionProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6025 int fromRemotePlayer = *nprms;
6027 if (updateRemotePlayer)
6029 DisplayMessage("Edit button disabled", fromRemotePlayer);
6033 if (gameMode == EditPosition)
6036 ForceProc(w, event, prms, nprms);
6038 if (gameMode != ForceMoves)
6041 DisplayName("<-- Press to set side to play next");
6042 DisplayMessage("Mouse: 1=drag, 2=black, 3=white", False);
6044 lastGameMode = gameMode = EditPosition;
6047 if (currentMove > 0)
6048 CopyBoard(boards[0], boards[currentMove]);
6050 whitePlaysFirst = !BlackOnMove(forwardMostMove);
6051 currentMove = forwardMostMove = backwardMostMove = 0;
6058 EditPositionDone(void)
6060 startedFromSetupPosition = True;
6061 SendToProgram(localPlayer.appData.initString, toFirstProgFP);
6062 SendSearchDepth(toFirstProgFP);
6064 if (whitePlaysFirst)
6066 strcpy(moveList[0], " ...\n");
6067 strcpy(parseList[0], " ...\n");
6068 currentMove = forwardMostMove = backwardMostMove = 1;
6069 CopyBoard(boards[1], boards[0]);
6070 CopyCatches(catches[1], catches[0]);
6071 SendToProgram("force\n", toFirstProgFP);
6072 SendCurrentBoard(toFirstProgFP);
6074 DisplayMessage("White to play", False);
6078 currentMove = forwardMostMove = backwardMostMove = 0;
6079 SendCurrentBoard(toFirstProgFP);
6080 SendToProgram("force\n", toFirstProgFP);
6082 DisplayMessage("Black to play", False);
6085 lastGameMode = gameMode = ForceMoves;
6095 * This function executes when undoing a move.
6096 * FIXME: this function is totally hosed!!!
6110 BackwardProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6115 int fromRemotePlayer = *nprms;
6117 if (updateRemotePlayer)
6119 DisplayMessage("Backward button disabled", fromRemotePlayer);
6124 * Why do we need this here?
6127 ForceProc(w, event, prms, nprms);
6129 if ((currentMove <= backwardMostMove) || (gameMode == EditPosition))
6132 if (gameMode == EndOfGame)
6133 ResurrectShogiProgram();
6135 if (gameMode == PlayFromGameFile)
6136 PauseProc(w, event, prms, nprms);
6145 XQueryPointer(localPlayer.xDisplay, localPlayer.xBoardWindow,
6146 &root, &child, &root_x, &root_y,
6147 &win_x, &win_y, &state);
6151 state = event->xkey.state;
6154 if (state & ShiftMask)
6156 target = backwardMostMove;
6160 target = currentMove - 1;
6163 if (gameMode == ForceMoves)
6165 Attention(firstProgramPID);
6167 while (currentMove > target)
6169 SendToProgram("undo\n", toFirstProgFP);
6175 currentMove = target;
6178 if (gameMode == ForceMoves)
6180 whiteTimeRemaining = timeRemaining[0][currentMove];
6181 blackTimeRemaining = timeRemaining[1][currentMove];
6184 DisplayClocks(ReDisplayTimers);
6185 DisplayMove(currentMove - 1);
6186 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
6193 FlipViewProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6195 struct DisplayData *player = (*nprms ? &remotePlayer : &localPlayer);
6197 player->flipView = !player->flipView;
6198 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
6205 SaveGameProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6209 int fromRemotePlayer = *nprms;
6211 if (fromRemotePlayer)
6213 DisplayMessage("only opponent may save game", fromRemotePlayer);
6219 FileNamePopUp("Filename for saved game?", SaveGame);
6226 SaveGame(char *name)
6229 int i, len, move = 0;
6232 if (!filemodeUp) /* if called via FileModeCallback avoid recursion */
6234 if ((gameFileFP = fopen(name, "r")) == NULL)
6236 strcpy(fmi.mode, "w");
6241 FileModePopUp(name);
6242 return False; /* CHECKME: what should the return value be? */
6246 if ((gameFileFP = fopen(name, fmi.mode)) == NULL)
6248 sprintf(buf, "Can't open %s (mode %s)", name, fmi.mode);
6249 DisplayMessage(buf, False);
6253 tm = time((time_t *) NULL);
6255 fprintf(gameFileFP, "# %s game file -- %s", programName, ctime(&tm));
6256 PrintOpponents(gameFileFP);
6258 for (i = 0; i < currentMove;)
6261 fprintf(gameFileFP, "\n");
6263 fprintf(gameFileFP, "%d. %s ", ++move, parseList[i++]);
6265 if (i >= currentMove)
6267 fprintf(gameFileFP, "\n");
6271 if ((len = strlen(parseList[i])) == 0)
6274 fprintf(gameFileFP, "%s ", parseList[i++]);
6277 fprintf(gameFileFP, "\n");
6289 SwitchProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6291 if (localPlayer.appData.noShogiProgram)
6299 case MachinePlaysBlack:
6300 if (BlackOnMove(forwardMostMove))
6302 DisplayMessage("Wait until your turn", False);
6306 lastGameMode = gameMode = MachinePlaysWhite;
6310 case BeginningOfGame:
6312 case MachinePlaysWhite:
6313 if (!BlackOnMove(forwardMostMove))
6315 DisplayMessage("Wait until your turn", False);
6319 if (forwardMostMove == 0)
6321 MachineBlackProc(w, event, prms, nprms);
6325 lastGameMode = gameMode = MachinePlaysBlack;
6330 Attention(firstProgramPID);
6331 SendToProgram("switch\n", toFirstProgFP);
6338 ForceProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6344 case MachinePlaysBlack:
6345 if (BlackOnMove(forwardMostMove))
6347 DisplayMessage("Wait until your turn", False);
6351 Attention(firstProgramPID);
6352 SendToProgram("force\n", toFirstProgFP);
6355 case MachinePlaysWhite:
6356 if (!BlackOnMove(forwardMostMove))
6358 DisplayMessage("Wait until your turn", False);
6362 Attention(firstProgramPID);
6363 SendToProgram("force\n", toFirstProgFP);
6366 case BeginningOfGame:
6367 SendToProgram("force\n", toFirstProgFP);
6370 case PlayFromGameFile:
6371 if (readGameXID != 0)
6373 XtRemoveTimeOut(readGameXID);
6377 if (gameFileFP != NULL)
6386 ResurrectShogiProgram();
6393 case TwoMachinesPlay:
6394 ShutdownShogiPrograms("");
6395 ResurrectShogiProgram();
6402 if ((gameMode == MachinePlaysWhite)
6403 || (gameMode == MachinePlaysBlack)
6404 || (gameMode == TwoMachinesPlay)
6405 || (gameMode == PlayFromGameFile))
6407 i = forwardMostMove;
6409 while (i > currentMove)
6411 SendToProgram("undo\n", toFirstProgFP);
6415 blackTimeRemaining = timeRemaining[0][currentMove];
6416 whiteTimeRemaining = timeRemaining[1][currentMove];
6418 if (whiteFlag || blackFlag)
6420 whiteFlag = blackFlag = 0;
6426 lastGameMode = gameMode = ForceMoves;
6428 DisplayClocks(StopTimers);
6434 HintProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6436 int fromRemotePlayer = *nprms;
6438 if (updateRemotePlayer)
6440 DisplayMessage("no hints in challenge mode", fromRemotePlayer);
6444 if (localPlayer.appData.noShogiProgram)
6449 case MachinePlaysBlack:
6450 if (BlackOnMove(forwardMostMove))
6452 DisplayMessage("Wait until your turn", False);
6458 case BeginningOfGame:
6459 case MachinePlaysWhite:
6460 if (!BlackOnMove(forwardMostMove))
6462 DisplayMessage("Wait until your turn", False);
6469 DisplayMessage("No hint available", False);
6473 Attention(firstProgramPID);
6474 SendToProgram("hint\n", toFirstProgFP);
6481 PrintPosition(FILE *fp, int move)
6485 for (i = BOARD_SIZE - 1; i >= 0; i--)
6487 for (j = 0; j < BOARD_SIZE; j++)
6489 if (pieceIsPromoted[(int)boards[currentMove][i][j]])
6490 fprintf(fp, "%c", '+');
6492 fprintf(fp, "%c", ' ');
6495 pieceToChar[(int)boards[currentMove][i][j]]);
6497 if (j == BOARD_SIZE - 1)
6502 for (color = 0; color <= 1; color++)
6504 fprintf(fp, "%i %i %i %i %i %i %i %i\n",
6505 catches[currentMove][color][pawn],
6506 catches[currentMove][color][lance],
6507 catches[currentMove][color][knight],
6508 catches[currentMove][color][silver],
6509 catches[currentMove][color][gold],
6510 catches[currentMove][color][bishop],
6511 catches[currentMove][color][rook],
6512 catches[currentMove][color][king]);
6515 if ((gameMode == EditPosition)
6517 : BlackOnMove(forwardMostMove))
6519 fprintf(fp, "black to play\n");
6523 fprintf(fp, "white to play\n");
6531 PrintOpponents(FILE *fp)
6533 char host_name[MSG_SIZ];
6535 #ifdef HAVE_GETHOSTNAME
6536 gethostname(host_name, MSG_SIZ);
6538 strncpy(host_name, "hostname not available", MSG_SIZ);
6541 switch (lastGameMode)
6543 case MachinePlaysWhite:
6544 fprintf(fp, "# %s@%s vs. %s@%s\n",
6545 localPlayer.appData.firstShogiProgram,
6546 localPlayer.appData.firstHost,
6547 getpwuid(getuid())->pw_name,
6551 case MachinePlaysBlack:
6552 fprintf(fp, "# %s@%s vs. %s@%s\n",
6553 getpwuid(getuid())->pw_name,
6555 localPlayer.appData.firstShogiProgram,
6556 localPlayer.appData.firstHost);
6559 case TwoMachinesPlay:
6560 fprintf(fp, "# %s@%s vs. %s@%s\n",
6561 localPlayer.appData.secondShogiProgram,
6562 localPlayer.appData.secondHost,
6563 localPlayer.appData.firstShogiProgram,
6564 localPlayer.appData.firstHost);
6577 SavePositionProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6581 int fromRemotePlayer = *nprms;
6583 if (fromRemotePlayer)
6585 DisplayMessage("only opponent may save game", fromRemotePlayer);
6591 FileNamePopUp("Filename for saved position?", SavePosition);
6598 SavePosition(char *name)
6604 if ((fp = fopen(name, "w")) == NULL)
6606 sprintf(buf, "Can't open %s", name);
6607 DisplayMessage(buf, False);
6611 tm = time((time_t *) NULL);
6613 fprintf(fp, "# %s position file -- %s", programName, ctime(&tm));
6615 PrintPosition(fp, currentMove);
6625 TwoMachinesProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6628 MatchMode matchKind;
6630 int fromRemotePlayer = *nprms;
6632 if (updateRemotePlayer)
6634 DisplayMessage("no machine moves in challenge mode",
6639 if (gameMode == PauseGame)
6640 PauseProc(w, event, prms, nprms);
6642 if (gameMode == PlayFromGameFile)
6643 ForceProc(w, event, prms, nprms);
6645 if ((gameMode == EndOfGame)
6646 || (gameMode == TwoMachinesPlay)
6647 || localPlayer.appData.noShogiProgram)
6652 if (matchMode == MatchFalse)
6657 case PlayFromGameFile:
6660 case MachinePlaysBlack:
6661 case MachinePlaysWhite:
6662 ForceProc(w, event, prms, nprms);
6664 if (gameMode != ForceMoves)
6667 matchKind = MatchOpening;
6671 matchKind = MatchOpening;
6676 matchKind = MatchPosition;
6679 case BeginningOfGame:
6681 matchKind = MatchInit;
6687 matchKind = matchMode;
6690 forwardMostMove = currentMove;
6692 localPlayer.flipView = False;
6693 remotePlayer.flipView = True;
6695 DisplayClocks(ResetTimers);
6696 DisplayClocks(StartTimers);
6701 if (firstProgramXID == 0)
6703 if (localPlayer.appData.loadGameFile == NULL)
6705 DisplayMessage("Select game file first", False);
6709 InitShogiProgram(localPlayer.appData.firstHost,
6710 localPlayer.appData.firstShogiProgram,
6711 &firstProgramPID, &toFirstProgFP,
6712 &fromFirstProgFP, &firstProgramXID,
6715 if (!LoadGame(localPlayer.appData.loadGameFile))
6717 ShutdownShogiPrograms("Bad game file");
6721 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
6724 InitShogiProgram(localPlayer.appData.secondHost,
6725 localPlayer.appData.secondShogiProgram,
6726 &secondProgramPID, &toSecondProgFP,
6727 &fromSecondProgFP, &secondProgramXID,
6730 if (startedFromSetupPosition)
6732 if (whitePlaysFirst)
6735 SendToProgram("force\n", toSecondProgFP);
6736 SendBoard(toSecondProgFP, boards[i], catches[i]);
6741 SendBoard(toSecondProgFP, boards[i], catches[i]);
6742 SendToProgram("force\n", toSecondProgFP);
6748 SendToProgram("force\n", toSecondProgFP);
6751 for (i = backwardMostMove; i < forwardMostMove; i++)
6752 SendToProgram(moveList[i], toSecondProgFP);
6754 lastGameMode = gameMode = TwoMachinesPlay;
6758 if (BlackOnMove(forwardMostMove))
6759 SendToProgram(localPlayer.appData.blackString, toSecondProgFP);
6761 SendToProgram(localPlayer.appData.whiteString, toFirstProgFP);
6766 if (firstProgramXID == 0)
6768 if (localPlayer.appData.loadPositionFile == NULL)
6770 DisplayMessage("Select position file first", False);
6774 InitShogiProgram(localPlayer.appData.firstHost,
6775 localPlayer.appData.firstShogiProgram,
6776 &firstProgramPID, &toFirstProgFP,
6777 &fromFirstProgFP, &firstProgramXID,
6780 if (!LoadPosition(localPlayer.appData.loadPositionFile))
6784 InitShogiProgram(localPlayer.appData.secondHost,
6785 localPlayer.appData.secondShogiProgram,
6786 &secondProgramPID, &toSecondProgFP,
6787 &fromSecondProgFP, &secondProgramXID,
6790 if (whitePlaysFirst)
6791 SendToProgram("force\n", toSecondProgFP);
6793 SendCurrentBoard(toSecondProgFP);
6794 lastGameMode = gameMode = TwoMachinesPlay;
6798 if (BlackOnMove(forwardMostMove))
6799 SendToProgram(localPlayer.appData.blackString, toSecondProgFP);
6801 SendToProgram(localPlayer.appData.whiteString, toFirstProgFP);
6808 if (firstProgramXID == 0)
6810 InitShogiProgram(localPlayer.appData.firstHost,
6811 localPlayer.appData.firstShogiProgram,
6812 &firstProgramPID, &toFirstProgFP,
6813 &fromFirstProgFP, &firstProgramXID,
6817 InitShogiProgram(localPlayer.appData.secondHost,
6818 localPlayer.appData.secondShogiProgram,
6819 &secondProgramPID, &toSecondProgFP,
6820 &fromSecondProgFP, &secondProgramXID,
6823 lastGameMode = gameMode = TwoMachinesPlay;
6825 SendToProgram(localPlayer.appData.blackString, toSecondProgFP);
6831 if (!firstSendTime || !secondSendTime)
6833 DisplayClocks(ResetTimers);
6834 timeRemaining[0][forwardMostMove] = blackTimeRemaining;
6835 timeRemaining[1][forwardMostMove] = whiteTimeRemaining;
6838 DisplayClocks(StartTimers);
6845 PauseProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6847 static GameMode previous_mode = PauseGame;
6858 gameMode = previous_mode;
6860 previous_mode = PauseGame;
6861 DisplayClocks(StartTimers);
6862 DisplayMessage("", False);
6864 if (updateRemotePlayer)
6865 DisplayMessage("", True);
6868 case PlayFromGameFile:
6869 if (readGameXID == 0)
6872 XtAppAddTimeOut(appContext,
6873 (int)(1000 * localPlayer.appData.timeDelay),
6874 (XtTimerCallbackProc) ReadGameFile, NULL);
6878 XtRemoveTimeOut(readGameXID);
6882 DisplayMessage("Pausing", False);
6884 if (updateRemotePlayer)
6885 DisplayMessage("Pausing", True);
6889 case BeginningOfGame:
6890 case MachinePlaysBlack:
6891 case MachinePlaysWhite:
6892 case TwoMachinesPlay:
6893 if (forwardMostMove == 0) /* Don't pause if no one has moved. */
6896 if (((gameMode == MachinePlaysWhite)
6897 && !BlackOnMove(forwardMostMove))
6898 || ((gameMode == MachinePlaysBlack) &&
6899 BlackOnMove(forwardMostMove)))
6901 DisplayClocks(StopTimers);
6904 previous_mode = gameMode;
6905 gameMode = PauseGame;
6907 DisplayClocks(StopTimers);
6908 DisplayMessage("Pausing", False);
6910 if (updateRemotePlayer)
6911 DisplayMessage("Pausing", True);
6921 Iconify(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6927 XtSetArg(args[0], XtNiconic, True);
6928 XtSetValues(localPlayer.shellWidget, args, 1);
6935 SendToProgram(char *message, FILE *fp)
6944 fprintf(stderr, "Sending to %s: %s\n",
6945 ((fp == toFirstProgFP) ? "first" : "second"), message);
6948 if (message[strlen(message) - 1] != '\n')
6949 fprintf(fp, "\n%s\n", message);
6960 ReceiveFromProgram(FILE *fp, int *source, XtInputId *id)
6962 char message[MSG_SIZ], *end_str, *number, *name;
6964 if (fgets(message, MSG_SIZ, fp) == NULL)
6966 if (fp == fromFirstProgFP)
6969 name = localPlayer.appData.firstShogiProgram;
6971 else if (fp == fromSecondProgFP)
6974 name = localPlayer.appData.secondShogiProgram;
6981 if (ferror(fp) == 0)
6983 sprintf(message, "%s shogi program (%s) exited unexpectedly",
6985 fprintf(stderr, "%s: %s\n", programName, message);
6990 "error reading from %s shogi program (%s): %s",
6991 number, name, strerror(ferror(fp)));
6992 fprintf(stderr, "%s: %s\n", programName, message);
6998 if ((end_str = (char *)strchr(message, '\r')) != NULL)
6999 *end_str = NULLCHAR;
7001 if ((end_str = (char *)strchr(message, '\n')) != NULL)
7002 *end_str = NULLCHAR;
7004 if (xshogiDebug || localPlayer.appData.debugMode)
7006 fprintf(stderr, "Received from %s: %s\n",
7007 ((fp == fromFirstProgFP) ? "first" : "second"), message);
7010 HandleMachineMove(message, fp);
7017 SendSearchDepth(FILE *fp)
7019 char message[MSG_SIZ];
7021 if (localPlayer.appData.searchDepth <= 0)
7024 sprintf(message, "depth\n%d\nhelp\n", localPlayer.appData.searchDepth);
7025 /* Note kludge: "help" command forces gnushogi to print
7026 * out something that ends with a newline. */
7027 SendToProgram(message, fp);
7034 DisplayMessage(char *message, int toRemotePlayer)
7038 XtSetArg(arg, XtNlabel, message);
7040 if (!toRemotePlayer)
7041 XtSetValues(localPlayer.messageWidget, &arg, 1);
7043 if (updateRemotePlayer && toRemotePlayer)
7044 XtSetValues(remotePlayer.messageWidget, &arg, 1);
7051 DisplayName(char *name)
7055 XtSetArg(arg, XtNlabel, name);
7056 XtSetValues(localPlayer.titleWidget, &arg, 1);
7058 if (updateRemotePlayer)
7059 XtSetValues(remotePlayer.titleWidget, &arg, 1);
7065 void SendTimeRemaining(FILE *fp)
7067 char message[MSG_SIZ];
7068 long comtime, opptime;
7070 if (BlackOnMove(forwardMostMove) == (fp == toFirstProgFP))
7072 comtime = blackTimeRemaining;
7073 opptime = whiteTimeRemaining;
7077 comtime = whiteTimeRemaining;
7078 opptime = blackTimeRemaining;
7087 sprintf(message, "time %ld\n", comtime / 10);
7088 SendToProgram(message, fp);
7089 sprintf(message, "otime %ld\n", opptime / 10);
7090 SendToProgram(message, fp);
7096 void DisplayMove(int moveNumber)
7098 char message[MSG_SIZ];
7102 if (moveNumber == forwardMostMove - 1)
7103 DisplayMessage(endMessage, False);
7105 DisplayMessage("", False);
7109 sprintf(message, "%d. %s%s %s",
7110 (moveNumber / 2 + 1),
7111 (BlackOnMove(moveNumber) ? "" : "... "),
7112 parseList[moveNumber],
7113 (moveNumber == (forwardMostMove - 1)) ? endMessage : "");
7114 DisplayMessage(message, False);
7121 void DisplayTitle(char *title)
7125 XtSetArg(arg, XtNlabel, title);
7126 XtSetValues(localPlayer.titleWidget, &arg, 1);
7133 * This routine used to send a SIGINT (^C interrupt) to gnushogi to awaken it
7134 * if it might be busy thinking on our time. This normally isn't needed,
7135 * but is useful on systems where the FIONREAD ioctl doesn't work since
7136 * on those systems the gnushogi feature that lets you interrupt its thinking
7137 * just by typing a command does not work.
7139 * Now gnushogi periodically checks for user input without a need for
7147 if (localPlayer.appData.noShogiProgram || (pid == 0))
7152 case MachinePlaysBlack:
7153 case MachinePlaysWhite:
7154 case TwoMachinesPlay:
7155 if ((forwardMostMove > backwardMostMove + 1) && maybeThinking)
7157 if (xshogiDebug || localPlayer.appData.debugMode)
7159 fprintf(stderr, "Sending SIGINT to %s\n",
7160 ((pid == firstProgramPID) ? "first" : "second"));
7163 (void)kill(pid, SIGINT); /* stop it thinking */
7168 break; /* CHECKME: is this OK? */
7170 #endif /* !defined(FIONREAD) */
7179 if (blackTimeRemaining <= 0)
7186 DisplayName(" Both flags have fallen");
7188 DisplayName(" Black's flag has fallen");
7192 if (whiteTimeRemaining <= 0)
7199 DisplayName(" Both flags have fallen");
7201 DisplayName(" White's flag has fallen");
7210 CheckTimeControl(void)
7212 if (!localPlayer.appData.clockMode)
7215 if (forwardMostMove == 0)
7219 * Add time to clocks when time control is achieved.
7222 if ((forwardMostMove % (localPlayer.appData.movesPerSession * 2)) == 0)
7224 blackTimeRemaining += timeControl;
7225 whiteTimeRemaining += timeControl;
7235 DisplayTimerLabel(localPlayer.blackTimerWidget, "Black",
7236 blackTimeRemaining);
7237 DisplayTimerLabel(localPlayer.whiteTimerWidget, "White",
7238 whiteTimeRemaining);
7240 if (updateRemotePlayer)
7242 DisplayTimerLabel(remotePlayer.blackTimerWidget, "Black",
7243 blackTimeRemaining);
7244 DisplayTimerLabel(remotePlayer.whiteTimerWidget, "White",
7245 whiteTimeRemaining);
7252 #ifdef HAVE_GETTIMEOFDAY
7253 static struct timeval tickStartTV;
7254 static int tickLength;
7257 PartialTickLength(void)
7262 gettimeofday(&tv, NULL);
7263 ptl = ((tv.tv_sec - tickStartTV.tv_sec) * 1000000 +
7264 (tv.tv_usec - tickStartTV.tv_usec) + 500) / 1000;
7266 if (ptl > tickLength)
7271 #else /* !HAVE_GETTIMEOFDAY */
7272 #define tickLength 1000
7273 #endif /* HAVE_GETTIMEOFDAY */
7279 * DisplayClocks manages the game clocks.
7281 * In tournament play, white starts the clock and then black makes a move.
7282 * We give the human user a slight advantage if he is playing black---the
7283 * clocks don't run until he makes his first move, so it takes zero time.
7284 * Also, DisplayClocks doesn't account for network lag so it could get out
7285 * of sync with GNU Shogi's clock -- but then, referees are always right.
7289 DisplayClocks(int clock_mode)
7296 /* Stop clocks and reset to a fresh time control */
7299 XtRemoveTimeOut(timerXID);
7303 blackTimeRemaining = timeControl;
7304 whiteTimeRemaining = timeControl;
7306 if (blackFlag || whiteFlag)
7309 blackFlag = whiteFlag = False;
7315 case DecrementTimers:
7316 /* Decrement running clock to next 1-second boundary */
7317 if (gameMode == PauseGame)
7322 if (!localPlayer.appData.clockMode)
7325 if (BlackOnMove(forwardMostMove))
7327 timeRemaining = (blackTimeRemaining -= tickLength);
7331 timeRemaining = (whiteTimeRemaining -= tickLength);
7337 #ifdef HAVE_GETTIMEOFDAY
7338 tickLength = (((timeRemaining <= 1000) && (timeRemaining > 0))
7340 gettimeofday(&tickStartTV, NULL);
7341 #endif /* HAVE_GETTIMEOFDAY */
7344 XtAppAddTimeOut(appContext, tickLength,
7345 (XtTimerCallbackProc) DisplayClocks,
7346 (XtPointer) DecrementTimers);
7350 /* A player has just moved, so stop the previously running
7351 clock and start the other one. */
7355 XtRemoveTimeOut(timerXID);
7358 #ifdef HAVE_GETTIMEOFDAY
7359 if (localPlayer.appData.clockMode)
7361 if (BlackOnMove(forwardMostMove))
7362 whiteTimeRemaining -= PartialTickLength();
7364 blackTimeRemaining -= PartialTickLength();
7367 #endif /* HAVE_GETTIMEOFDAY */
7373 if (!localPlayer.appData.clockMode)
7376 if ((gameMode == PauseGame)
7377 && ((pausePreviousMode == MachinePlaysBlack)
7378 || (pausePreviousMode == MachinePlaysWhite)))
7383 timeRemaining = (BlackOnMove(forwardMostMove)
7384 ? blackTimeRemaining : whiteTimeRemaining);
7386 #ifdef HAVE_GETTIMEOFDAY
7387 tickLength = (((timeRemaining <= 1000) && (timeRemaining > 0))
7388 ? (((timeRemaining - 1) % 100) + 1)
7389 : (((timeRemaining - 1) % 1000) + 1));
7391 if (tickLength <= 0)
7394 gettimeofday(&tickStartTV, NULL);
7396 #endif /* HAVE_GETTIMEOFDAY */
7398 XtAppAddTimeOut(appContext, tickLength,
7399 (XtTimerCallbackProc) DisplayClocks,
7400 (XtPointer) DecrementTimers);
7403 case ReDisplayTimers:
7404 /* Display current clock values */
7409 /* Stop both clocks */
7413 XtRemoveTimeOut(timerXID);
7416 if (!localPlayer.appData.clockMode)
7419 #ifdef HAVE_GETTIMEOFDAY
7420 if (BlackOnMove(forwardMostMove))
7421 blackTimeRemaining -= PartialTickLength();
7423 whiteTimeRemaining -= PartialTickLength();
7426 #endif /* HAVE_GETTIMEOFDAY */
7430 /* Start clock of player on move, if not already running. */
7436 if (!localPlayer.appData.clockMode)
7439 timeRemaining = (BlackOnMove(forwardMostMove)
7440 ? blackTimeRemaining : whiteTimeRemaining);
7442 if (timeRemaining == 0)
7445 #ifdef HAVE_GETTIMEOFDAY
7446 tickLength = (((timeRemaining <= 1000) && (timeRemaining > 0))
7447 ? (((timeRemaining - 1) % 100) + 1)
7448 : (((timeRemaining - 1) % 1000) + 1));
7450 if (tickLength <= 0)
7453 gettimeofday(&tickStartTV, NULL);
7454 #endif /* HAVE_GETTIMEOFDAY */
7457 XtAppAddTimeOut(appContext, tickLength,
7458 (XtTimerCallbackProc) DisplayClocks,
7459 (XtPointer)DecrementTimers);
7468 DisplayTimerLabel(Widget w, char *color, long int timer)
7472 struct DisplayData *player;
7474 player = (((w == localPlayer.blackTimerWidget)
7475 || (w == localPlayer.whiteTimerWidget))
7476 ? &localPlayer : &remotePlayer);
7478 if (localPlayer.appData.clockMode)
7480 sprintf(buf, "%s: %s", color, TimeString(timer));
7481 XtSetArg(args[0], XtNlabel, buf);
7485 XtSetArg(args[0], XtNlabel, color);
7488 if (((color[0] == 'W') && BlackOnMove(forwardMostMove))
7489 || ((color[0] == 'B') && !BlackOnMove(forwardMostMove)))
7491 XtSetArg(args[1], XtNbackground, player->timerForegroundPixel);
7492 XtSetArg(args[2], XtNforeground, player->timerBackgroundPixel);
7496 XtSetArg(args[1], XtNbackground, player->timerBackgroundPixel);
7497 XtSetArg(args[2], XtNforeground, player->timerForegroundPixel);
7500 XtSetValues(w, args, 3);
7509 int second, minute, hour, day;
7511 static char buf[32];
7513 if ((tm > 0) && (tm <= 900))
7515 /* convert milliseconds to tenths, rounding up */
7516 sprintf(buf, " 0.%1ld ", (tm + 99) / 100);
7520 /* convert milliseconds to seconds, rounding up */
7521 tm = (tm + 999) / 1000;
7529 if (tm >= (60 * 60 * 24))
7531 day = (int)(tm / (60 * 60 * 24));
7532 tm -= day * 60 * 60 * 24;
7539 if (tm >= (60 * 60))
7541 hour = (int)(tm / (60 * 60));
7542 tm -= hour * 60 * 60;
7551 minute = (int)(tm / 60);
7563 sprintf(buf, " %s%d:%02d:%02d:%02d ",
7564 sign, day, hour, minute, second);
7568 sprintf(buf, " %s%d:%02d:%02d ",
7569 sign, hour, minute, second);
7573 sprintf(buf, " %s%2d:%02d ",
7574 sign, minute, second);
7586 fprintf(stderr, "Usage: %s\n", programName);
7587 fprintf(stderr, "\tstandard Xt options\n");
7588 fprintf(stderr, "\t-iconic\n");
7589 fprintf(stderr, "\t-tc or -timeControl minutes[:seconds]\n");
7590 fprintf(stderr, "\t-gi or -gameIn (True | False)\n");
7591 fprintf(stderr, "\t-mps or -movesPerSession moves\n");
7592 fprintf(stderr, "\t-st or -searchTime minutes[:seconds]\n");
7593 fprintf(stderr, "\t-sd or -searchDepth number\n");
7594 fprintf(stderr, "\t-clock or -clockMode (True | False)\n");
7595 fprintf(stderr, "\t-td or -timeDelay seconds\n");
7597 fprintf(stderr, "\t-nsp or -noShogiProgram (True | False)\n");
7598 fprintf(stderr, "\t-fsp or -firstShogiProgram program_name\n");
7599 fprintf(stderr, "\t-ssp or -secondShogiProgram program_name\n");
7600 fprintf(stderr, "\t-fh or -firstHost host_name\n");
7601 fprintf(stderr, "\t-sh or -secondHost host_name\n");
7602 fprintf(stderr, "\t-rsh or -remoteShell shell_name\n");
7604 "\t-mm or -matchMode (False | Init | Position | Opening)\n");
7605 fprintf(stderr, "\t-lgf or -loadGameFile file_name\n");
7606 fprintf(stderr, "\t-lpf or -loadPositionFile file_name\n");
7607 fprintf(stderr, "\t-sgf or -saveGameFile file_name\n");
7608 fprintf(stderr, "\t-spf or -savePositionFile file_name\n");
7609 fprintf(stderr, "\t-size or -boardSize (Large | Medium | Small)\n");
7610 fprintf(stderr, "\t-coords or -showCoords (True | False)\n");
7611 fprintf(stderr, "\t-mono or -monoMode (True | False)\n");
7612 fprintf(stderr, "\t-pc or -pieceColor color\n");
7613 fprintf(stderr, "\t-sc or -squareColor color\n");
7614 fprintf(stderr, "\t-wps or -westernPieceSet (True | False)\n");
7615 fprintf(stderr, "\t-debug or -debugMode (True | False)\n");
7622 CatchPipeSignal(int dummy)
7624 char message[MSG_SIZ];
7627 "%s shogi program (%s) exited unexpectedly",
7628 ((lastMsgFP == toFirstProgFP) ? "first" : "second"),
7629 ((lastMsgFP == toFirstProgFP)
7630 ? localPlayer.appData.firstShogiProgram
7631 : localPlayer.appData.secondShogiProgram));
7632 fprintf(stderr, "%s: %s\n", programName, message);
7633 ShutdownShogiPrograms(message);