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 its piece bitmaps from CRANES Shogi.
18 * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.
19 * Enhancements Copyright 1992 Free Software Foundation, Inc.
20 * Enhancements for XShogi Copyright 1993, 1994, 1995 Matthias Mutz
21 * Copyright (c) 1999 Michael Vanier and the Free Software Foundation
23 * The following terms apply to Digital Equipment Corporation's copyright
25 * ------------------------------------------------------------------------
28 * Permission to use, copy, modify, and distribute this software and its
29 * documentation for any purpose and without fee is hereby granted,
30 * provided that the above copyright notice appear in all copies and that
31 * both that copyright notice and this permission notice appear in
32 * supporting documentation, and that the name of Digital not be
33 * used in advertising or publicity pertaining to distribution of the
34 * software without specific, written prior permission.
36 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
37 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
38 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
39 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
40 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
41 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43 * ------------------------------------------------------------------------
45 * This file is part of GNU shogi.
47 * GNU shogi is free software; you can redistribute it and/or modify
48 * it under the terms of the GNU General Public License as published by
49 * the Free Software Foundation.
51 * GNU shogi is distributed in the hope that it will be useful,
52 * but WITHOUT ANY WARRANTY; without even the implied warranty of
53 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
54 * GNU General Public License for more details.
56 * You should have received a copy of the GNU General Public License
57 * along with GNU shogi; see the file COPYING. If not, write to
58 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
60 * ------------------------------------------------------------------------
66 #ifdef X_DISPLAY_MISSING
67 #error You cannot compile xshogi if X windows is unavailable!
72 #define XBOARD_VERSION "2.0/2.1"
77 #include <sys/ioctl.h>
82 #include <X11/Intrinsic.h>
83 #include <X11/StringDefs.h>
84 #include <X11/Shell.h>
85 #include <X11/Xaw/Dialog.h>
86 #include <X11/Xaw/Form.h>
87 #include <X11/Xaw/List.h>
88 #include <X11/Xaw/Label.h>
89 #include <X11/Xaw/SimpleMenu.h>
90 #include <X11/Xaw/SmeBSB.h>
91 #include <X11/Xaw/SmeLine.h>
92 #include <X11/cursorfont.h>
94 #include "../version.h"
101 #include "bitmaps.h" /* Piece bitmaps. */
102 #include "xshogifn.h" /* Forward declarations. */
104 #define off_board(x) (x < 2 || x > BOARD_SIZE + 1)
107 /**********************************************************************
109 * Global variables, structs etc.
111 **********************************************************************/
114 * NOTE: XShogi depends on Xt R4 or higher
117 int xtVersion = XtSpecificationRelease;
119 XtIntervalId firstProgramXID = 0, secondProgramXID = 0,
120 readGameXID = 0, timerXID = 0, blinkSquareXID = 0;
122 XtAppContext appContext;
124 Boolean (*fileProc) (char *name);
126 FILE *fromFirstProgFP, *toFirstProgFP, *fromSecondProgFP,
127 *toSecondProgFP, *gameFileFP, *lastMsgFP;
129 int currentMove = 0, forwardMostMove = 0, backwardMostMove = 0,
131 secondProgramPID = 0, fromX = -1,
132 fromY = -1, firstMove = True, flipView = False,
133 xshogiDebug = True, commentUp = False, filenameUp = False,
134 whitePlaysFirst = False, startedFromSetupPosition = False,
135 searchTime = 0, pmFromX = -1, pmFromY = -1,
136 blackFlag = False, whiteFlag = False, maybeThinking = False,
139 int at_least_gnushogi_1_2p03 = False;
141 int firstSendTime = 2, secondSendTime = 2; /* 0 = don't, 1 = do,
144 MatchMode matchMode = MatchFalse;
145 GameMode gameMode = BeginningOfGame;
146 GameMode lastGameMode = BeginningOfGame;
147 GameMode pausePreviousMode = BeginningOfGame;
149 char moveList[MAX_MOVES][MOVE_LEN], parseList[MAX_MOVES][MOVE_LEN * 2],
150 ptyname[24], *shogiDir, *programName;
152 char endMessage[MOVE_LEN * 4];
154 long blackTimeRemaining, whiteTimeRemaining, timeControl;
155 long timeRemaining[2][MAX_MOVES];
157 extern char currentMoveString[];
159 int updateRemotePlayer = False;
161 Catched catches[MAX_MOVES];
163 #define DIMENSION 100
165 Widget blackPieceMenu, whitePieceMenu, commentShell;
167 XSetWindowAttributes attr;
185 #define NO_SQUARES 81
190 char catchedIndexToChar[8] =
192 'P', 'L', 'N', 'S', 'G', 'B', 'R', 'K'
195 ShogiSquare catchedIndexToPiece[2][8] =
198 BlackPawn, BlackLance, BlackKnight, BlackSilver, BlackGold,
199 BlackBishop, BlackRook, BlackKing
202 WhitePawn, WhiteLance, WhiteKnight, WhiteSilver, WhiteGold,
203 WhiteBishop, WhiteRook, WhiteKing
208 int pieceToCatchedIndex[] =
210 pawn, lance, knight, silver, gold, bishop, rook,
211 pawn, lance, knight, silver, bishop, rook, king,
212 pawn, lance, knight, silver, gold, bishop, rook,
213 pawn, lance, knight, silver, bishop, rook, king,
219 Board boards[MAX_MOVES];
220 Board initialPosition =
222 { BlackLance, BlackKnight, BlackSilver, BlackGold, BlackKing,
223 BlackGold, BlackSilver, BlackKnight, BlackLance },
224 { EmptySquare, BlackBishop, EmptySquare, EmptySquare, EmptySquare,
225 EmptySquare, EmptySquare, BlackRook, EmptySquare },
226 { BlackPawn, BlackPawn, BlackPawn, BlackPawn, BlackPawn,
227 BlackPawn, BlackPawn, BlackPawn, BlackPawn },
228 { EmptySquare, EmptySquare, EmptySquare, EmptySquare, EmptySquare,
229 EmptySquare, EmptySquare, EmptySquare, EmptySquare } ,
230 { EmptySquare, EmptySquare, EmptySquare, EmptySquare, EmptySquare,
231 EmptySquare, EmptySquare, EmptySquare, EmptySquare } ,
232 { EmptySquare, EmptySquare, EmptySquare, EmptySquare, EmptySquare,
233 EmptySquare, EmptySquare, EmptySquare, EmptySquare } ,
234 { WhitePawn, WhitePawn, WhitePawn, WhitePawn, WhitePawn,
235 WhitePawn, WhitePawn, WhitePawn, WhitePawn },
236 { EmptySquare, WhiteRook, EmptySquare, EmptySquare, EmptySquare,
237 EmptySquare, EmptySquare, WhiteBishop, EmptySquare },
238 { WhiteLance, WhiteKnight, WhiteSilver, WhiteGold, WhiteKing,
239 WhiteGold, WhiteSilver, WhiteKnight, WhiteLance }
242 String gnuButtonStrings[] =
244 "Quit", "Load Game", "Machine White", "Forward",
245 "Reset", "Load Position", "Machine Black", "Backward",
246 "Flip View", "Save Game", "Force Moves", "Pause",
247 "Hint", "Save Position", "Two Machines", "Edit Position",
248 "Challenge", "Select Level", "Move NOW",
251 /* must be in same order as buttonStrings! */
252 XtActionProc gnuButtonProcs[] =
254 QuitProc, LoadGameProc, MachineWhiteProc, ForwardProc,
255 ResetProc, LoadPositionProc, MachineBlackProc, BackwardProc,
256 FlipViewProc, SaveGameProc, ForceProc, PauseProc,
257 HintProc, SavePositionProc, TwoMachinesProc, EditPositionProc,
258 ChallengeProc, SelectLevelProc, MoveNowProc,
263 String *buttonStrings;
264 XtActionProc *buttonProcs;
267 #define PIECE_MENU_SIZE 18
269 String pieceMenuStrings[PIECE_MENU_SIZE] =
271 "----", "Pawn", "Lance", "Knight", "Silver",
272 "Gold", "Bishop", "Rook",
273 "PPawn", "PLance", "PKnight", "PSilver",
274 "PBishop", "PRook", "King",
275 "----", "Empty square", "Clear board"
278 /* must be in same order as PieceMenuStrings! */
279 ShogiSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] =
282 (ShogiSquare) 0, BlackPawn, BlackLance, BlackKnight,
283 BlackSilver, BlackGold, BlackBishop, BlackRook,
284 BlackPPawn, BlackPLance, BlackPKnight, BlackPSilver,
285 BlackPBishop, BlackPRook, BlackKing,
286 (ShogiSquare) 0, EmptySquare, ClearBoard
289 (ShogiSquare) 0, WhitePawn, WhiteLance, WhiteKnight,
290 WhiteSilver, WhiteGold, WhiteBishop, WhiteRook,
291 WhitePPawn, WhitePLance, WhitePKnight, WhitePSilver,
292 WhitePBishop, WhitePRook, WhiteKing,
293 (ShogiSquare) 0, EmptySquare, ClearBoard
300 Pixel blackPieceColor;
301 Pixel whitePieceColor;
302 Pixel lightSquareColor;
303 Pixel darkSquareColor;
304 Pixel charPieceColor;
307 Boolean westernPieceSet;
312 String firstShogiProgram;
313 String secondShogiProgram;
314 Boolean noShogiProgram;
317 String reverseBigSolidBitmap;
318 String reverseSmallSolidBitmap;
319 String normalBigSolidBitmap;
320 String normalSmallSolidBitmap;
321 String reversePawnBitmap;
322 String reverseLanceBitmap;
323 String reverseKnightBitmap;
324 String reverseSilverBitmap;
325 String reverseGoldBitmap;
326 String reverseRookBitmap;
327 String reverseBishopBitmap;
328 String reversePPawnBitmap;
329 String reversePLanceBitmap;
330 String reversePKnightBitmap;
331 String reversePSilverBitmap;
332 String reversePBishopBitmap;
333 String reversePRookBitmap;
334 String reverseKingBitmap;
335 String normalPawnBitmap;
336 String normalLanceBitmap;
337 String normalKnightBitmap;
338 String normalSilverBitmap;
339 String normalGoldBitmap;
340 String normalRookBitmap;
341 String normalBishopBitmap;
342 String normalPPawnBitmap;
343 String normalPLanceBitmap;
344 String normalPKnightBitmap;
345 String normalPSilverBitmap;
346 String normalPBishopBitmap;
347 String normalPRookBitmap;
348 String normalKingBitmap;
354 Boolean autoSaveGames;
356 String loadPositionFile;
358 String savePositionFile;
360 String challengeDisplay;
371 Boolean ringBellAfterMoves;
372 Boolean autoCallFlag;
375 } AppData, *AppDataPtr;
378 XtResource clientResources[] =
381 "blackPieceColor", "BlackPieceColor", XtRPixel, sizeof(Pixel),
382 XtOffset(AppDataPtr, blackPieceColor), XtRString,
386 "whitePieceColor", "WhitePieceColor", XtRPixel, sizeof(Pixel),
387 XtOffset(AppDataPtr, whitePieceColor), XtRString,
391 "charPieceColor", "CharPieceColor", XtRPixel, sizeof(Pixel),
392 XtOffset(AppDataPtr, charPieceColor), XtRString,
396 "oneColor", "OneColor", XtRPixel, sizeof(Pixel),
397 XtOffset(AppDataPtr, oneColor), XtRString,
401 "zeroColor", "ZeroColor", XtRPixel, sizeof(Pixel),
402 XtOffset(AppDataPtr, zeroColor), XtRString,
406 "lightSquareColor", "LightSquareColor", XtRPixel,
407 sizeof(Pixel), XtOffset(AppDataPtr, lightSquareColor),
408 XtRString, LIGHT_SQUARE_COLOR
411 "darkSquareColor", "DarkSquareColor", XtRPixel, sizeof(Pixel),
412 XtOffset(AppDataPtr, darkSquareColor), XtRString,
416 "westernPieceSet", "WesternPieceSet", XtRBoolean, sizeof(Boolean),
417 XtOffset(AppDataPtr, westernPieceSet), XtRString,
421 "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
422 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
423 (XtPointer) MOVES_PER_SESSION
426 "initString", "initString", XtRString, sizeof(String),
427 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING
430 "blackString", "blackString", XtRString, sizeof(String),
431 XtOffset(AppDataPtr, blackString), XtRString, BLACK_STRING
434 "whiteString", "whiteString", XtRString, sizeof(String),
435 XtOffset(AppDataPtr, whiteString), XtRString, WHITE_STRING
438 "firstShogiProgram", "firstShogiProgram", XtRString,
439 sizeof(String), XtOffset(AppDataPtr, firstShogiProgram),
440 XtRString, FIRST_SHOGI_PROGRAM
443 "secondShogiProgram", "secondShogiProgram", XtRString,
444 sizeof(String), XtOffset(AppDataPtr, secondShogiProgram),
445 XtRString, SECOND_SHOGI_PROGRAM
448 "noShogiProgram", "noShogiProgram", XtRBoolean,
449 sizeof(Boolean), XtOffset(AppDataPtr, noShogiProgram),
450 XtRImmediate, (XtPointer) False
453 "firstHost", "firstHost", XtRString, sizeof(String),
454 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST
457 "secondHost", "secondHost", XtRString, sizeof(String),
458 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST
461 "reversePawnBitmap", "reversePawnBitmap", XtRString,
462 sizeof(String), XtOffset(AppDataPtr, reversePawnBitmap),
466 "reverseLanceBitmap", "reverseLanceBitmap", XtRString,
467 sizeof(String), XtOffset(AppDataPtr, reverseLanceBitmap),
471 "reverseKnightBitmap", "reverseKnightBitmap", XtRString,
472 sizeof(String), XtOffset(AppDataPtr, reverseKnightBitmap),
476 "reverseSilverBitmap", "reverseSilverBitmap", XtRString,
477 sizeof(String), XtOffset(AppDataPtr, reverseSilverBitmap),
481 "reverseGoldBitmap", "reverseGoldBitmap", XtRString,
482 sizeof(String), XtOffset(AppDataPtr, reverseGoldBitmap),
486 "reverseRookBitmap", "reverseRookBitmap", XtRString,
487 sizeof(String), XtOffset(AppDataPtr, reverseRookBitmap),
491 "reverseBishopBitmap", "reverseBishopBitmap", XtRString,
492 sizeof(String), XtOffset(AppDataPtr, reverseBishopBitmap),
496 "reversePPawnBitmap", "reversePPawnBitmap", XtRString,
497 sizeof(String), XtOffset(AppDataPtr, reversePPawnBitmap),
501 "reversePLanceBitmap", "reversePLanceBitmap", XtRString,
502 sizeof(String), XtOffset(AppDataPtr, reversePLanceBitmap),
506 "reversePKnightBitmap", "reversePKnightBitmap", XtRString,
507 sizeof(String), XtOffset(AppDataPtr, reversePKnightBitmap),
511 "reversePSilverBitmap", "reversePSilverBitmap", XtRString,
512 sizeof(String), XtOffset(AppDataPtr, reversePSilverBitmap),
516 "reversePRookBitmap", "reversePRookBitmap", XtRString,
517 sizeof(String), XtOffset(AppDataPtr, reversePRookBitmap),
521 "reversePBishopBitmap", "reversePBishopBitmap", XtRString,
522 sizeof(String), XtOffset(AppDataPtr, reversePBishopBitmap),
526 "reverseKingBitmap", "reverseKingBitmap", XtRString,
527 sizeof(String), XtOffset(AppDataPtr, reverseKingBitmap),
531 "normalPawnBitmap", "normalPawnBitmap", XtRString,
532 sizeof(String), XtOffset(AppDataPtr, normalPawnBitmap),
536 "normalLanceBitmap", "normalLanceBitmap", XtRString,
537 sizeof(String), XtOffset(AppDataPtr, normalLanceBitmap),
541 "normalKnightBitmap", "normalKnightBitmap", XtRString,
542 sizeof(String), XtOffset(AppDataPtr, normalKnightBitmap),
546 "normalSilverBitmap", "normalSilverBitmap", XtRString,
547 sizeof(String), XtOffset(AppDataPtr, normalSilverBitmap),
551 "normalGoldBitmap", "normalGoldBitmap", XtRString,
552 sizeof(String), XtOffset(AppDataPtr, normalGoldBitmap),
556 "normalBishopBitmap", "normalBishopBitmap", XtRString,
557 sizeof(String), XtOffset(AppDataPtr, normalBishopBitmap),
561 "normalRookBitmap", "normalRookBitmap", XtRString,
562 sizeof(String), XtOffset(AppDataPtr, normalRookBitmap),
566 "normalPPawnBitmap", "normalPPawnBitmap", XtRString,
567 sizeof(String), XtOffset(AppDataPtr, normalPPawnBitmap),
571 "normalPLanceBitmap", "normalPLanceBitmap", XtRString,
572 sizeof(String), XtOffset(AppDataPtr, normalPLanceBitmap),
576 "normalPKnightBitmap", "normalPKnightBitmap", XtRString,
577 sizeof(String), XtOffset(AppDataPtr, normalPKnightBitmap),
581 "normalPSilverBitmap", "normalPSilverBitmap", XtRString,
582 sizeof(String), XtOffset(AppDataPtr, normalPSilverBitmap),
586 "normalPBishopBitmap", "normalPBishopBitmap", XtRString,
587 sizeof(String), XtOffset(AppDataPtr, normalPBishopBitmap),
591 "normalPRookBitmap", "normalPRookBitmap", XtRString,
592 sizeof(String), XtOffset(AppDataPtr, normalPRookBitmap),
596 "normalKingBitmap", "normalKingBitmap", XtRString,
597 sizeof(String), XtOffset(AppDataPtr, normalKingBitmap),
601 "remoteShell", "remoteShell", XtRString, sizeof(String),
602 XtOffset(AppDataPtr, remoteShell), XtRString, "rsh"
605 "timeDelay", "timeDelay", XtRFloat, sizeof(float),
606 XtOffset(AppDataPtr, timeDelay), XtRString,
607 (XtPointer) TIME_DELAY
610 "timeControl", "timeControl", XtRString, sizeof(String),
611 XtOffset(AppDataPtr, timeControl), XtRString,
612 (XtPointer) TIME_CONTROL
616 XtRBoolean, sizeof(Boolean),
617 XtOffset(AppDataPtr, gameIn), XtRImmediate,
621 "autoSaveGames", "autoSaveGames", XtRBoolean,
622 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
623 XtRImmediate, (XtPointer) False
626 "loadGameFile", "loadGameFile", XtRString, sizeof(String),
627 XtOffset(AppDataPtr, loadGameFile), XtRString, NULL
630 "loadPositionFile", "loadPositionFile", XtRString,
631 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
635 "saveGameFile", "saveGameFile", XtRString, sizeof(String),
636 XtOffset(AppDataPtr, saveGameFile), XtRString, ""
639 "savePositionFile", "savePositionFile", XtRString,
640 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
644 "challengeDisplay", "challengeDisplay", XtRString,
645 sizeof(String), XtOffset(AppDataPtr, challengeDisplay),
649 "matchMode", "matchMode", XtRString, sizeof(String),
650 XtOffset(AppDataPtr, matchMode), XtRString, MATCH_MODE
653 "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
654 XtOffset(AppDataPtr, monoMode), XtRImmediate,
658 "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
659 XtOffset(AppDataPtr, debugMode), XtRImmediate,
663 "Iconic", "Iconic", XtRBoolean, sizeof(Boolean),
664 XtOffset(AppDataPtr, Iconic), XtRImmediate,
668 "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
669 XtOffset(AppDataPtr, clockMode), XtRImmediate,
673 "autoCallFlag", "autoCallFlag", XtRBoolean,
674 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
675 XtRImmediate, (XtPointer) False
678 "boardSize", "boardSize", XtRString, sizeof(String),
679 XtOffset(AppDataPtr, boardSize), XtRString, DEFAULT_SIZE
682 "searchTime", "searchTime", XtRString, sizeof(String),
683 XtOffset(AppDataPtr, searchTime), XtRString,
687 "searchDepth", "searchDepth", XtRInt, sizeof(int),
688 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
692 "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
693 XtOffset(AppDataPtr, showCoords), XtRImmediate,
697 "mainFont", "mainFont", XtRString, sizeof(String),
698 XtOffset(AppDataPtr, mainFont), XtRString, MAIN_FONT
701 "coordFont", "coordFont", XtRString, sizeof(String),
702 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT
705 "ringBellAfterMoves", "ringBellAfterMoves",
706 XtRBoolean, sizeof(Boolean),
707 XtOffset(AppDataPtr, ringBellAfterMoves),
708 XtRImmediate, (XtPointer) False
711 "borderXoffset", "borderXoffset", XtRInt, sizeof(int),
712 XtOffset(AppDataPtr, borderXoffset), XtRImmediate,
713 (XtPointer) BORDER_X_OFFSET
716 "borderYoffset", "borderYOffset", XtRInt, sizeof(int),
717 XtOffset(AppDataPtr, borderYoffset), XtRImmediate,
718 (XtPointer) BORDER_Y_OFFSET
735 Pixmap reversePawnBitmap, reverseLanceBitmap, reverseKnightBitmap,
737 reverseGoldBitmap, reverseBishopBitmap, reverseRookBitmap,
738 reversePPawnBitmap, reversePLanceBitmap, reversePKnightBitmap,
739 reversePSilverBitmap, reversePBishopBitmap, reversePRookBitmap,
741 reverseBigSolidBitmap, reverseSmallSolidBitmap,
742 normalBigSolidBitmap, normalSmallSolidBitmap,
743 normalPawnBitmap, normalLanceBitmap, normalKnightBitmap,
744 normalSilverBitmap, normalGoldBitmap,
745 normalBishopBitmap, normalRookBitmap,
746 normalPPawnBitmap, normalPLanceBitmap, normalPKnightBitmap,
747 normalPSilverBitmap, normalPBishopBitmap, normalPRookBitmap,
755 GC lightSquareGC, darkSquareGC, lineGC, wdPieceGC, wlPieceGC,
756 woPieceGC, boPieceGC, bdPieceGC, blPieceGC, wbPieceGC,
757 bwPieceGC, coordGC, dropPiece;
761 Font mainFontID, coordFontID;
762 XFontStruct *mainFontStruct, *coordFontStruct;
764 Widget shellWidget, formWidget, boardWidget,
765 commandsWidget, messageWidget,
766 blackTimerWidget, whiteTimerWidget,
767 titleWidget, widgetList[6],
769 filemodeShell, challengeWidget;
771 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
773 Pixel timerForegroundPixel, timerBackgroundPixel;
777 int black_pixel_is_zero;
781 Boolean monoMode, showCoords, Iconic;
786 struct DisplayData localPlayer, remotePlayer;
795 static PromotionMoveInfo pmi; /* making this global is gross */
798 Pixmap *pieceToReverse[2][28] =
801 &localPlayer.reversePawnBitmap,
802 &localPlayer.reverseLanceBitmap,
803 &localPlayer.reverseKnightBitmap,
804 &localPlayer.reverseSilverBitmap,
805 &localPlayer.reverseGoldBitmap,
806 &localPlayer.reverseBishopBitmap,
807 &localPlayer.reverseRookBitmap,
808 &localPlayer.reversePPawnBitmap,
809 &localPlayer.reversePLanceBitmap,
810 &localPlayer.reversePKnightBitmap,
811 &localPlayer.reversePSilverBitmap,
812 &localPlayer.reversePBishopBitmap,
813 &localPlayer.reversePRookBitmap,
814 &localPlayer.reverseKingBitmap,
815 &localPlayer.reversePawnBitmap,
816 &localPlayer.reverseLanceBitmap,
817 &localPlayer.reverseKnightBitmap,
818 &localPlayer.reverseSilverBitmap,
819 &localPlayer.reverseGoldBitmap,
820 &localPlayer.reverseBishopBitmap,
821 &localPlayer.reverseRookBitmap,
822 &localPlayer.reversePPawnBitmap,
823 &localPlayer.reversePLanceBitmap,
824 &localPlayer.reversePKnightBitmap,
825 &localPlayer.reversePSilverBitmap,
826 &localPlayer.reversePBishopBitmap,
827 &localPlayer.reversePRookBitmap,
828 &localPlayer.reverseKingBitmap
831 &remotePlayer.reversePawnBitmap,
832 &remotePlayer.reverseLanceBitmap,
833 &remotePlayer.reverseKnightBitmap,
834 &remotePlayer.reverseSilverBitmap,
835 &remotePlayer.reverseGoldBitmap,
836 &remotePlayer.reverseBishopBitmap,
837 &remotePlayer.reverseRookBitmap,
838 &remotePlayer.reversePPawnBitmap,
839 &remotePlayer.reversePLanceBitmap,
840 &remotePlayer.reversePKnightBitmap,
841 &remotePlayer.reversePSilverBitmap,
842 &remotePlayer.reversePBishopBitmap,
843 &remotePlayer.reversePRookBitmap,
844 &remotePlayer.reverseKingBitmap,
845 &remotePlayer.reversePawnBitmap,
846 &remotePlayer.reverseLanceBitmap,
847 &remotePlayer.reverseKnightBitmap,
848 &remotePlayer.reverseSilverBitmap,
849 &remotePlayer.reverseGoldBitmap,
850 &remotePlayer.reverseBishopBitmap,
851 &remotePlayer.reverseRookBitmap,
852 &remotePlayer.reversePPawnBitmap,
853 &remotePlayer.reversePLanceBitmap,
854 &remotePlayer.reversePKnightBitmap,
855 &remotePlayer.reversePSilverBitmap,
856 &remotePlayer.reversePBishopBitmap,
857 &remotePlayer.reversePRookBitmap,
858 &remotePlayer.reverseKingBitmap
864 Pixmap *pieceToNormal[2][28] =
867 &localPlayer.normalPawnBitmap,
868 &localPlayer.normalLanceBitmap,
869 &localPlayer.normalKnightBitmap,
870 &localPlayer.normalSilverBitmap,
871 &localPlayer.normalGoldBitmap,
872 &localPlayer.normalBishopBitmap,
873 &localPlayer.normalRookBitmap,
874 &localPlayer.normalPPawnBitmap,
875 &localPlayer.normalPLanceBitmap,
876 &localPlayer.normalPKnightBitmap,
877 &localPlayer.normalPSilverBitmap,
878 &localPlayer.normalPBishopBitmap,
879 &localPlayer.normalPRookBitmap,
880 &localPlayer.normalKingBitmap,
881 &localPlayer.normalPawnBitmap,
882 &localPlayer.normalLanceBitmap,
883 &localPlayer.normalKnightBitmap,
884 &localPlayer.normalSilverBitmap,
885 &localPlayer.normalGoldBitmap,
886 &localPlayer.normalBishopBitmap,
887 &localPlayer.normalRookBitmap,
888 &localPlayer.normalPPawnBitmap,
889 &localPlayer.normalPLanceBitmap,
890 &localPlayer.normalPKnightBitmap,
891 &localPlayer.normalPSilverBitmap,
892 &localPlayer.normalPBishopBitmap,
893 &localPlayer.normalPRookBitmap,
894 &localPlayer.normalKingBitmap
897 &remotePlayer.normalPawnBitmap,
898 &remotePlayer.normalLanceBitmap,
899 &remotePlayer.normalKnightBitmap,
900 &remotePlayer.normalSilverBitmap,
901 &remotePlayer.normalGoldBitmap,
902 &remotePlayer.normalBishopBitmap,
903 &remotePlayer.normalRookBitmap,
904 &remotePlayer.normalPPawnBitmap,
905 &remotePlayer.normalPLanceBitmap,
906 &remotePlayer.normalPKnightBitmap,
907 &remotePlayer.normalPSilverBitmap,
908 &remotePlayer.normalPBishopBitmap,
909 &remotePlayer.normalPRookBitmap,
910 &remotePlayer.normalKingBitmap,
911 &remotePlayer.normalPawnBitmap,
912 &remotePlayer.normalLanceBitmap,
913 &remotePlayer.normalKnightBitmap,
914 &remotePlayer.normalSilverBitmap,
915 &remotePlayer.normalGoldBitmap,
916 &remotePlayer.normalBishopBitmap,
917 &remotePlayer.normalRookBitmap,
918 &remotePlayer.normalPPawnBitmap,
919 &remotePlayer.normalPLanceBitmap,
920 &remotePlayer.normalPKnightBitmap,
921 &remotePlayer.normalPSilverBitmap,
922 &remotePlayer.normalPBishopBitmap,
923 &remotePlayer.normalPRookBitmap,
924 &remotePlayer.normalKingBitmap
930 Pixmap *pieceToReverseSolid[2][28] =
933 &localPlayer.reverseSmallSolidBitmap,
934 &localPlayer.reverseSmallSolidBitmap,
935 &localPlayer.reverseSmallSolidBitmap,
936 &localPlayer.reverseBigSolidBitmap,
937 &localPlayer.reverseBigSolidBitmap,
938 &localPlayer.reverseBigSolidBitmap,
939 &localPlayer.reverseBigSolidBitmap,
940 &localPlayer.reverseSmallSolidBitmap,
941 &localPlayer.reverseSmallSolidBitmap,
942 &localPlayer.reverseSmallSolidBitmap,
943 &localPlayer.reverseBigSolidBitmap,
944 &localPlayer.reverseBigSolidBitmap,
945 &localPlayer.reverseBigSolidBitmap,
946 &localPlayer.reverseBigSolidBitmap,
947 &localPlayer.reverseSmallSolidBitmap,
948 &localPlayer.reverseSmallSolidBitmap,
949 &localPlayer.reverseSmallSolidBitmap,
950 &localPlayer.reverseBigSolidBitmap,
951 &localPlayer.reverseBigSolidBitmap,
952 &localPlayer.reverseBigSolidBitmap,
953 &localPlayer.reverseBigSolidBitmap,
954 &localPlayer.reverseSmallSolidBitmap,
955 &localPlayer.reverseSmallSolidBitmap,
956 &localPlayer.reverseSmallSolidBitmap,
957 &localPlayer.reverseBigSolidBitmap,
958 &localPlayer.reverseBigSolidBitmap,
959 &localPlayer.reverseBigSolidBitmap,
960 &localPlayer.reverseBigSolidBitmap
963 &remotePlayer.reverseSmallSolidBitmap,
964 &remotePlayer.reverseSmallSolidBitmap,
965 &remotePlayer.reverseSmallSolidBitmap,
966 &remotePlayer.reverseBigSolidBitmap,
967 &remotePlayer.reverseBigSolidBitmap,
968 &remotePlayer.reverseBigSolidBitmap,
969 &remotePlayer.reverseBigSolidBitmap,
970 &remotePlayer.reverseSmallSolidBitmap,
971 &remotePlayer.reverseSmallSolidBitmap,
972 &remotePlayer.reverseSmallSolidBitmap,
973 &remotePlayer.reverseBigSolidBitmap,
974 &remotePlayer.reverseBigSolidBitmap,
975 &remotePlayer.reverseBigSolidBitmap,
976 &remotePlayer.reverseBigSolidBitmap,
977 &remotePlayer.reverseSmallSolidBitmap,
978 &remotePlayer.reverseSmallSolidBitmap,
979 &remotePlayer.reverseSmallSolidBitmap,
980 &remotePlayer.reverseBigSolidBitmap,
981 &remotePlayer.reverseBigSolidBitmap,
982 &remotePlayer.reverseBigSolidBitmap,
983 &remotePlayer.reverseBigSolidBitmap,
984 &remotePlayer.reverseSmallSolidBitmap,
985 &remotePlayer.reverseSmallSolidBitmap,
986 &remotePlayer.reverseSmallSolidBitmap,
987 &remotePlayer.reverseBigSolidBitmap,
988 &remotePlayer.reverseBigSolidBitmap,
989 &remotePlayer.reverseBigSolidBitmap,
990 &remotePlayer.reverseBigSolidBitmap
996 Pixmap *pieceToNormalSolid[2][28] =
999 &localPlayer.normalSmallSolidBitmap,
1000 &localPlayer.normalSmallSolidBitmap,
1001 &localPlayer.normalSmallSolidBitmap,
1002 &localPlayer.normalBigSolidBitmap,
1003 &localPlayer.normalBigSolidBitmap,
1004 &localPlayer.normalBigSolidBitmap,
1005 &localPlayer.normalBigSolidBitmap,
1006 &localPlayer.normalSmallSolidBitmap,
1007 &localPlayer.normalSmallSolidBitmap,
1008 &localPlayer.normalSmallSolidBitmap,
1009 &localPlayer.normalBigSolidBitmap,
1010 &localPlayer.normalBigSolidBitmap,
1011 &localPlayer.normalBigSolidBitmap,
1012 &localPlayer.normalBigSolidBitmap,
1013 &localPlayer.normalSmallSolidBitmap,
1014 &localPlayer.normalSmallSolidBitmap,
1015 &localPlayer.normalSmallSolidBitmap,
1016 &localPlayer.normalBigSolidBitmap,
1017 &localPlayer.normalBigSolidBitmap,
1018 &localPlayer.normalBigSolidBitmap,
1019 &localPlayer.normalBigSolidBitmap,
1020 &localPlayer.normalSmallSolidBitmap,
1021 &localPlayer.normalSmallSolidBitmap,
1022 &localPlayer.normalSmallSolidBitmap,
1023 &localPlayer.normalBigSolidBitmap,
1024 &localPlayer.normalBigSolidBitmap,
1025 &localPlayer.normalBigSolidBitmap,
1026 &localPlayer.normalBigSolidBitmap
1029 &remotePlayer.normalSmallSolidBitmap,
1030 &remotePlayer.normalSmallSolidBitmap,
1031 &remotePlayer.normalSmallSolidBitmap,
1032 &remotePlayer.normalBigSolidBitmap,
1033 &remotePlayer.normalBigSolidBitmap,
1034 &remotePlayer.normalBigSolidBitmap,
1035 &remotePlayer.normalBigSolidBitmap,
1036 &remotePlayer.normalSmallSolidBitmap,
1037 &remotePlayer.normalSmallSolidBitmap,
1038 &remotePlayer.normalSmallSolidBitmap,
1039 &remotePlayer.normalBigSolidBitmap,
1040 &remotePlayer.normalBigSolidBitmap,
1041 &remotePlayer.normalBigSolidBitmap,
1042 &remotePlayer.normalBigSolidBitmap,
1043 &remotePlayer.normalSmallSolidBitmap,
1044 &remotePlayer.normalSmallSolidBitmap,
1045 &remotePlayer.normalSmallSolidBitmap,
1046 &remotePlayer.normalBigSolidBitmap,
1047 &remotePlayer.normalBigSolidBitmap,
1048 &remotePlayer.normalBigSolidBitmap,
1049 &remotePlayer.normalBigSolidBitmap,
1050 &remotePlayer.normalSmallSolidBitmap,
1051 &remotePlayer.normalSmallSolidBitmap,
1052 &remotePlayer.normalSmallSolidBitmap,
1053 &remotePlayer.normalBigSolidBitmap,
1054 &remotePlayer.normalBigSolidBitmap,
1055 &remotePlayer.normalBigSolidBitmap,
1056 &remotePlayer.normalBigSolidBitmap
1062 int pieceIsPromoted[] =
1064 False, False, False, False, False, False, False,
1065 True, True, True, True, True, True, False,
1066 False, False, False, False, False, False, False,
1067 True, True, True, True, True, True, False,
1072 int piecePromotable[] =
1074 True, True, True, True, False, True, True,
1075 False, False, False, False, False, False, False,
1076 True, True, True, True, False, True, True,
1077 False, False, False, False, False, False, False,
1082 char pieceToChar[] =
1084 'P', 'L', 'N', 'S', 'G', 'B', 'R', 'P', 'L', 'N', 'S', 'B', 'R', 'K',
1085 'p', 'l', 'n', 's', 'g', 'b', 'r', 'p', 'l', 'n', 's', 'b', 'r', 'k',
1090 int pieceisWhite[] =
1092 False, False, False, False, False, False, False,
1093 False, False, False, False, False, False, False,
1094 True, True, True, True, True, True, True,
1095 True, True, True, True, True, True, True,
1101 ShogiSquare pieceToPromoted[] =
1103 BlackPPawn, BlackPLance, BlackPKnight, BlackPSilver, BlackGold,
1104 BlackPBishop, BlackPRook,
1105 BlackPPawn, BlackPLance, BlackPKnight, BlackPSilver,
1106 BlackPBishop, BlackPRook, BlackKing,
1107 WhitePPawn, WhitePLance, WhitePKnight, WhitePSilver, WhiteGold,
1108 WhitePBishop, WhitePRook,
1109 WhitePPawn, WhitePLance, WhitePKnight, WhitePSilver,
1110 WhitePBishop, WhitePRook, WhiteKing
1115 XrmOptionDescRec shellOptions[] =
1117 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1118 { "-bpc", "blackPieceColor", XrmoptionSepArg, NULL },
1119 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1120 { "-wpc", "whitePieceColor", XrmoptionSepArg, NULL },
1121 { "-charPieceColor", "charPieceColor", XrmoptionSepArg, NULL },
1122 { "-cpc", "charPieceColor", XrmoptionSepArg, NULL },
1123 { "-zeroColor", "zeroColor", XrmoptionSepArg, NULL },
1124 { "-zc", "zeroColor", XrmoptionSepArg, NULL },
1125 { "-oneColor", "oneColor", XrmoptionSepArg, NULL },
1126 { "-oc", "oneColor", XrmoptionSepArg, NULL },
1127 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1128 { "-lsc", "lightSquareColor", XrmoptionSepArg, NULL },
1129 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1130 { "-dsc", "darkSquareColor", XrmoptionSepArg, NULL },
1131 { "-westernPieceSet", "westernPieceSet", XrmoptionSepArg, NULL },
1132 { "-wps", "westernPieceSet", XrmoptionSepArg, NULL },
1133 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1134 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1135 { "-firstShogiProgram", "firstShogiProgram", XrmoptionSepArg, NULL },
1136 { "-fsp", "firstShogiProgram", XrmoptionSepArg, NULL },
1137 { "-secondShogiProgram", "secondShogiProgram", XrmoptionSepArg, NULL },
1138 { "-ssp", "secondShogiProgram", XrmoptionSepArg, NULL },
1139 { "-noShogiProgram", "noShogiProgram", XrmoptionSepArg, NULL },
1140 { "-nsp", "noShogiProgram", XrmoptionSepArg, NULL },
1141 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1142 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1143 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1144 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1145 { "-reversePawnBitmap", "reversePawnBitmap", XrmoptionSepArg, NULL },
1146 { "-rpb", "reversePawnBitmap", XrmoptionSepArg, NULL },
1147 { "-reverseLanceBitmap", "reverseLanceBitmap", XrmoptionSepArg, NULL },
1148 { "-rlb", "reverseLanceBitmap", XrmoptionSepArg, NULL },
1149 { "-reverseKnightBitmap", "reverseKnightBitmap", XrmoptionSepArg, NULL },
1150 { "-rnb", "reverseKnightBitmap", XrmoptionSepArg, NULL },
1151 { "-reverseSilverBitmap", "reverseSilverBitmap", XrmoptionSepArg, NULL },
1152 { "-rsb", "reverseSilverBitmap", XrmoptionSepArg, NULL },
1153 { "-reverseGoldBitmap", "reverseGoldBitmap", XrmoptionSepArg, NULL },
1154 { "-rgb", "reverseGoldBitmap", XrmoptionSepArg, NULL },
1155 { "-reverseRookBitmap", "reverseRookBitmap", XrmoptionSepArg, NULL },
1156 { "-rrb", "reverseRookBitmap", XrmoptionSepArg, NULL },
1157 { "-reverseBishopBitmap", "reverseBishopBitmap", XrmoptionSepArg, NULL },
1158 { "-rbb", "reverseBishopBitmap", XrmoptionSepArg, NULL },
1159 { "-reversePPawnBitmap", "reversePPawnBitmap",
1160 XrmoptionSepArg, NULL },
1161 { "-rppb", "reversePPawnBitmap", XrmoptionSepArg, NULL },
1162 { "-reversePLanceBitmap", "reversePLanceBitmap",
1163 XrmoptionSepArg, NULL },
1164 { "-rplb", "reversePLanceBitmap", XrmoptionSepArg, NULL },
1165 { "-reversePKnightBitmap", "reversePKnightBitmap",
1166 XrmoptionSepArg, NULL },
1167 { "-rpnb", "reversePKnightBitmap", XrmoptionSepArg, NULL },
1168 { "-reversePSilverBitmap", "reversePSilverBitmap",
1169 XrmoptionSepArg, NULL },
1170 { "-rpsb", "reversePSilverBitmap", XrmoptionSepArg, NULL },
1171 { "-reversePRookBitmap", "reversePRookBitmap",
1172 XrmoptionSepArg, NULL },
1173 { "-rprb", "reversePRookBitmap", XrmoptionSepArg, NULL },
1174 { "-reversePBishopBitmap", "reversePBishopBitmap",
1175 XrmoptionSepArg, NULL },
1176 { "-rpbb", "reversePBishopBitmap", XrmoptionSepArg, NULL },
1177 { "-reverseKingBitmap", "reverseKingBitmap", XrmoptionSepArg, NULL },
1178 { "-rkb", "reverseKingBitmap", XrmoptionSepArg, NULL },
1179 { "-outlinePawnBitmap", "outlinePawnBitmap", XrmoptionSepArg, NULL },
1180 { "-opb", "normalPawnBitmap", XrmoptionSepArg, NULL },
1181 { "-normalLanceBitmap", "normalLanceBitmap", XrmoptionSepArg, NULL },
1182 { "-olb", "normalLanceBitmap", XrmoptionSepArg, NULL },
1183 { "-normalKnightBitmap", "normalKnightBitmap", XrmoptionSepArg, NULL },
1184 { "-onb", "normalKnightBitmap", XrmoptionSepArg, NULL },
1185 { "-normalSilverBitmap", "normalSilverBitmap", XrmoptionSepArg, NULL },
1186 { "-osb", "normalSilverBitmap", XrmoptionSepArg, NULL },
1187 { "-normalGoldBitmap", "normalGoldBitmap", XrmoptionSepArg, NULL },
1188 { "-ogb", "normalGoldBitmap", XrmoptionSepArg, NULL },
1189 { "-normalRookBitmap", "normalRookBitmap", XrmoptionSepArg, NULL },
1190 { "-orb", "normalRookBitmap", XrmoptionSepArg, NULL },
1191 { "-normalBishopBitmap", "normalBishopBitmap", XrmoptionSepArg, NULL },
1192 { "-obb", "normalBishopBitmap", XrmoptionSepArg, NULL },
1193 { "-normalPPawnBitmap", "normalPPawnBitmap", XrmoptionSepArg, NULL },
1194 { "-oppb", "normalPPawnBitmap", XrmoptionSepArg, NULL },
1195 { "-normalPLanceBitmap", "normalPLanceBitmap", XrmoptionSepArg, NULL },
1196 { "-oplb", "normalPLanceBitmap", XrmoptionSepArg, NULL },
1197 { "-normalPKnightBitmap", "normalPKnightBitmap", XrmoptionSepArg, NULL },
1198 { "-opnb", "normalPKnightBitmap", XrmoptionSepArg, NULL },
1199 { "-normalPSilverBitmap", "normalPSilverBitmap", XrmoptionSepArg, NULL },
1200 { "-opsb", "normalPSilverBitmap", XrmoptionSepArg, NULL },
1201 { "-normalPRookBitmap", "normalPRookBitmap", XrmoptionSepArg, NULL },
1202 { "-oprb", "normalPRookBitmap", XrmoptionSepArg, NULL },
1203 { "-normalPBishopBitmap", "normalPBishopBitmap", XrmoptionSepArg, NULL },
1204 { "-opbb", "normalPBishopBitmap", XrmoptionSepArg, NULL },
1205 { "-normalKingBitmap", "normalKingBitmap", XrmoptionSepArg, NULL },
1206 { "-okb", "outlineKingBitmap", XrmoptionSepArg, NULL },
1207 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1208 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1209 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1210 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1211 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1212 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1213 { "-gameIn", "gameIn", XrmoptionSepArg, NULL },
1214 { "-gi", "gameIn", XrmoptionSepArg, NULL },
1215 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1216 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1217 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1218 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1219 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1220 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1221 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1222 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1223 { "-challengeDisplay", "challengeDisplay", XrmoptionSepArg, NULL },
1224 { "-cd", "challengeDisplay", XrmoptionSepArg, NULL },
1225 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1226 { "-mm", "matchMode", XrmoptionSepArg, NULL },
1227 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1228 { "-mono", "monoMode", XrmoptionSepArg, NULL },
1229 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1230 { "-debug", "debugMode", XrmoptionSepArg, NULL },
1231 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1232 { "-clock", "clockMode", XrmoptionSepArg, NULL },
1233 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1234 { "-size", "boardSize", XrmoptionSepArg, NULL },
1235 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1236 { "-st", "searchTime", XrmoptionSepArg, NULL },
1237 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1238 { "-sd", "searchDepth", XrmoptionSepArg, NULL },
1239 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1240 { "-coords", "showCoords", XrmoptionSepArg, NULL },
1241 { "-iconic", "Iconic", XrmoptionNoArg, "True" }
1246 XtActionsRec boardActions[] =
1248 { "DrawPosition", (XtActionProc) DrawPosition },
1249 { "HandleUserMove", (XtActionProc) HandleUserMove },
1250 { "ResetProc", (XtActionProc) ResetProc },
1251 { "ResetFileProc", (XtActionProc) ResetFileProc },
1252 { "LoadGameProc", (XtActionProc) LoadGameProc },
1253 { "QuitProc", (XtActionProc) QuitProc },
1254 { "ForwardProc", (XtActionProc) ForwardProc },
1255 { "BackwardProc", (XtActionProc) BackwardProc },
1256 { "PauseProc", (XtActionProc) PauseProc },
1257 { "Iconify", (XtActionProc) Iconify },
1258 { "FileNameAction", (XtActionProc) FileNameAction },
1259 { "PieceMenuPopup", (XtActionProc) PieceMenuPopup },
1260 { "SetBlackToPlay", (XtActionProc) SetBlackToPlay },
1261 { "SetWhiteToPlay", (XtActionProc) SetWhiteToPlay }
1265 char translationsTable[] =
1266 "<Expose>: DrawPosition() \n \
1267 <Btn1Down>: HandleUserMove() \n \
1268 <Btn1Up>: HandleUserMove() \n \
1269 <Btn2Down>: XawPositionSimpleMenu(menuW) PieceMenuPopup(menuW) \n \
1270 <Btn3Down>: XawPositionSimpleMenu(menuB) PieceMenuPopup(menuB) \n \
1271 <Key>r: ResetFileProc() ResetProc() \n \
1272 <Key>R: ResetFileProc() ResetProc() \n \
1273 <Key>g: LoadGameProc() \n \
1274 <Key>G: LoadGameProc() \n \
1275 <Key>q: QuitProc() \n \
1276 <Key>Q: QuitProc() \n \
1277 <Message>WM_PROTOCOLS: QuitProc() \n \
1278 <Key>f: ForwardProc() \n \
1279 <Key>F: ForwardProc() \n \
1280 <Key>b: BackwardProc() \n \
1281 <Key>B: BackwardProc() \n \
1282 <Key>p: PauseProc() \n \
1283 <Key>P: PauseProc() \n \
1284 <Key>i: Iconify() \n \
1285 <Key>I: Iconify() \n \
1286 <Key>c: Iconify() \n \
1287 <Key>C: Iconify() \n";
1290 char translationsTableReduced[] =
1291 "<Expose>: DrawPosition() \n \
1292 <Btn1Down>: HandleUserMove() \n \
1293 <Btn1Up>: HandleUserMove() \n \
1294 <Message>WM_PROTOCOLS: QuitProc() \n";
1297 char blackTranslations[] = "<BtnDown>: SetBlackToPlay()\n";
1298 char whiteTranslations[] = "<BtnDown>: SetWhiteToPlay()\n";
1300 String xshogiResources[] =
1303 "*Dialog*value.translations: #override "
1304 "\\n <Key>Return: FileNameAction()",
1309 int global_argc; /* number of command args */
1310 char *global_argv[10]; /* pointers to up to 10 command args */
1314 static struct DisplayData *player;
1323 static FileModeInfo fmi;
1326 /**********************************************************************
1330 **********************************************************************/
1334 CreatePlayerWindow(void)
1336 int mainFontPxlSize, coordFontPxlSize;
1337 int min, sec, matched;
1338 XSetWindowAttributes window_attributes;
1341 Dimension timerWidth, boardWidth, commandsWidth, w, h;
1343 int fromRemotePlayer = (player == &remotePlayer);
1345 player->monoMode = player->appData.monoMode;
1346 player->showCoords = player->appData.showCoords;
1349 * Parse timeControl resource.
1352 if (player->appData.timeControl != NULL)
1354 matched = sscanf(player->appData.timeControl, "%d:%d", &min, &sec);
1358 timeControl = min * 60 * 1000;
1360 else if (matched == 2)
1362 timeControl = (min * 60 + sec) * 1000;
1366 fprintf(stderr, "%s: bad timeControl option %s\n",
1367 programName, player->appData.timeControl);
1373 * Parse searchTime resource
1376 if (player->appData.searchTime != NULL)
1378 matched = sscanf(player->appData.searchTime, "%d:%d", &min, &sec);
1382 searchTime = min * 60;
1384 else if (matched == 2)
1386 searchTime = min * 60 + sec;
1390 fprintf(stderr, "%s: bad searchTime option %s\n",
1391 programName, player->appData.searchTime);
1396 if ((player->appData.searchTime != NULL)
1397 || (player->appData.searchDepth > 0)
1398 || player->appData.noShogiProgram)
1400 player->appData.clockMode = False;
1403 player->Iconic = False;
1404 player->boardSize = Small;
1405 player->squareSize = SMALL_SQUARE_SIZE;
1406 player->flipView = (player == &remotePlayer);
1407 player->promotionUp = False;
1410 * Determine boardSize.
1413 if (strcasecmp(player->appData.boardSize, "Large") == 0)
1415 player->boardSize = Large;
1417 else if (strcasecmp(player->appData.boardSize, "Medium") == 0)
1419 player->boardSize = Medium;
1421 else if (strcasecmp(player->appData.boardSize, "Small") == 0)
1423 player->boardSize = Small;
1427 fprintf(stderr, "%s: bad boardSize option %s\n",
1428 programName, player->appData.boardSize);
1432 if ((local = (player == &localPlayer)))
1434 player->xDisplay = XtDisplay(player->shellWidget);
1435 player->xScreen = DefaultScreen(player->xDisplay);
1438 if (((DisplayWidth(player->xDisplay, player->xScreen) < 800)
1439 || (DisplayHeight(player->xDisplay, player->xScreen) < 800))
1440 && (player->boardSize == Large))
1442 player->boardSize = Medium;
1445 switch (player->boardSize)
1448 player->squareSize = SMALL_SQUARE_SIZE;
1449 mainFontPxlSize = 11;
1450 coordFontPxlSize = 10;
1454 player->squareSize = MEDIUM_SQUARE_SIZE;
1455 mainFontPxlSize = 17;
1456 coordFontPxlSize = 12;
1461 player->squareSize = LARGE_SQUARE_SIZE;
1462 mainFontPxlSize = 17;
1463 coordFontPxlSize = 14;
1468 * Detect if there are not enough colors are available and adapt.
1471 if (DefaultDepth(player->xDisplay, player->xScreen) <= 2)
1472 player->monoMode = True;
1475 * Determine what fonts to use.
1478 player->appData.mainFont
1479 = FindFont(player->appData.mainFont, mainFontPxlSize);
1481 = XLoadFont(player->xDisplay, player->appData.mainFont);
1482 player->mainFontStruct
1483 = XQueryFont(player->xDisplay, player->mainFontID);
1484 player->appData.coordFont
1485 = FindFont(player->appData.coordFont, coordFontPxlSize);
1487 = XLoadFont(player->xDisplay, player->appData.coordFont);
1488 player->coordFontStruct
1489 = XQueryFont(player->xDisplay, player->coordFontID);
1492 * Set default arguments.
1495 XtSetArg(player->shellArgs[0], XtNwidth, 0);
1496 XtSetArg(player->shellArgs[1], XtNheight, 0);
1497 XtSetArg(player->shellArgs[2], XtNminWidth, 0);
1498 XtSetArg(player->shellArgs[3], XtNminHeight, 0);
1499 XtSetArg(player->shellArgs[4], XtNmaxWidth, 0);
1500 XtSetArg(player->shellArgs[5], XtNmaxHeight, 0);
1502 XtSetArg(player->boardArgs[0], XtNborderWidth, 0);
1503 XtSetArg(player->boardArgs[1], XtNwidth,
1504 LINE_GAP + (BOARD_SIZE + 4)
1505 * (SMALL_SQUARE_SIZE + LINE_GAP));
1506 XtSetArg(player->boardArgs[2], XtNheight,
1507 LINE_GAP + BOARD_SIZE
1508 * (SMALL_SQUARE_SIZE + LINE_GAP));
1510 XtSetArg(player->commandsArgs[0], XtNborderWidth, 0);
1511 XtSetArg(player->commandsArgs[1], XtNdefaultColumns, 4);
1512 XtSetArg(player->commandsArgs[2], XtNforceColumns, True);
1513 XtSetArg(player->commandsArgs[3], XtNcolumnSpacing, 12);
1514 XtSetArg(player->commandsArgs[4], XtNlist, (XtArgVal) buttonStrings);
1515 XtSetArg(player->commandsArgs[5], XtNnumberStrings, buttonCount);
1516 XtSetArg(player->commandsArgs[6], XtNfont, player->mainFontStruct);
1518 XtSetArg(player->messageArgs[0], XtNborderWidth, 0);
1519 XtSetArg(player->messageArgs[1], XtNjustify, (XtArgVal) XtJustifyLeft);
1520 XtSetArg(player->messageArgs[2], XtNlabel, (XtArgVal) "starting...");
1522 XtSetArg(player->timerArgs[0], XtNborderWidth, 0);
1523 XtSetArg(player->timerArgs[1], XtNjustify, (XtArgVal) XtJustifyLeft);
1525 XtSetArg(player->titleArgs[0], XtNborderWidth, 0);
1526 XtSetArg(player->titleArgs[1], XtNjustify, (XtArgVal) XtJustifyLeft);
1528 boardWidth = LINE_GAP
1529 + (BOARD_SIZE + 4) * (player->squareSize + LINE_GAP);
1531 XtSetArg(player->boardArgs[1], XtNwidth, boardWidth);
1532 XtSetArg(player->boardArgs[2], XtNheight,
1533 LINE_GAP + BOARD_SIZE * (player->squareSize + LINE_GAP));
1539 player->formWidget = XtCreateManagedWidget("form",
1541 player->shellWidget, NULL, 0);
1543 player->widgetList[0] = player->blackTimerWidget
1544 = XtCreateWidget((local ? "black time:" : "rblack time:"),
1546 player->formWidget, player->timerArgs,
1547 XtNumber(player->timerArgs));
1549 XtSetArg(args[0], XtNfont, player->mainFontStruct);
1550 XtSetValues(player->blackTimerWidget, args, 1);
1552 player->widgetList[1] = player->whiteTimerWidget
1553 = XtCreateWidget((local ? "white time:" : "rwhite time:"),
1555 player->formWidget, player->timerArgs,
1556 XtNumber(player->timerArgs));
1558 XtSetArg(args[0], XtNfont, player->mainFontStruct);
1559 XtSetValues(player->whiteTimerWidget, args, 1);
1561 player->widgetList[2] = player->titleWidget
1562 = XtCreateWidget((local ? "" : "r"), labelWidgetClass,
1563 player->formWidget, player->titleArgs,
1564 XtNumber(player->titleArgs));
1566 XtSetArg(args[0], XtNfont, player->mainFontStruct);
1567 XtSetValues(player->titleWidget, args, 1);
1569 player->widgetList[3] = player->messageWidget
1570 = XtCreateWidget((local ? "message" : "rmessage"),
1571 labelWidgetClass, player->formWidget,
1572 player->messageArgs,
1573 XtNumber(player->messageArgs));
1575 XtSetArg(args[0], XtNfont, player->mainFontStruct);
1576 XtSetValues(player->messageWidget, args, 1);
1578 player->widgetList[4] = player->commandsWidget
1579 = XtCreateWidget((local ? "commands" : "rcommand"),
1580 listWidgetClass, player->formWidget,
1581 player->commandsArgs,
1582 XtNumber(player->commandsArgs));
1584 player->widgetList[5] = player->boardWidget
1585 = XtCreateWidget((local ? "board" : "rboard"),
1586 widgetClass, player->formWidget,
1588 XtNumber(player->boardArgs));
1590 XtManageChildren(player->widgetList, XtNumber(player->widgetList));
1593 * Calculate the width of the timer labels.
1596 XtSetArg(args[0], XtNfont, &player->mainFontStruct);
1597 XtGetValues(player->blackTimerWidget, args, 1);
1599 if (player->appData.clockMode)
1601 /* sprintf(buf, "Black: %s ", TimeString(timeControl));
1602 timerWidth = XTextWidth(player->mainFontStruct,
1603 buf, strlen(buf)); */
1604 timerWidth = XTextWidth(player->mainFontStruct,
1605 "Black: 8:88:88 ", 15);
1609 timerWidth = XTextWidth(player->mainFontStruct, "Black ", 7);
1612 XtSetArg(args[0], XtNwidth, timerWidth);
1613 XtSetValues(player->blackTimerWidget, args, 1);
1614 XtSetValues(player->whiteTimerWidget, args, 1);
1616 XtSetArg(args[0], XtNbackground, &player->timerForegroundPixel);
1617 XtSetArg(args[1], XtNforeground, &player->timerBackgroundPixel);
1618 XtGetValues(player->blackTimerWidget, args, 2);
1621 * Calculate the width of the name and message labels.
1624 XtSetArg(args[0], XtNwidth, &commandsWidth);
1625 XtGetValues(player->commandsWidget, args, 1);
1626 w = ((commandsWidth > boardWidth) ? commandsWidth : boardWidth);
1627 XtSetArg(args[0], XtNwidth, w - timerWidth*2 - 12);
1628 XtSetValues(player->titleWidget, args, 1);
1629 XtSetArg(args[0], XtNwidth, w - 8);
1630 XtSetValues(player->messageWidget, args, 1);
1633 * formWidget uses these constraints but they are stored
1637 XtSetArg(args[0], XtNfromHoriz, player->blackTimerWidget);
1638 XtSetValues(player->whiteTimerWidget, args, 1);
1639 XtSetArg(args[0], XtNfromHoriz, player->whiteTimerWidget);
1640 XtSetValues(player->titleWidget, args, 1);
1641 XtSetArg(args[0], XtNfromVert, player->blackTimerWidget);
1642 XtSetValues(player->messageWidget, args, 1);
1643 XtSetArg(args[0], XtNfromVert, player->messageWidget);
1644 XtSetValues(player->commandsWidget, args, 1);
1645 XtSetArg(args[0], XtNfromVert, player->commandsWidget);
1646 XtSetValues(player->boardWidget, args, 1);
1648 XtRealizeWidget(player->shellWidget);
1650 player->xBoardWindow = XtWindow(player->boardWidget);
1656 player->iconPixmap =
1657 XCreateBitmapFromData(player->xDisplay,
1658 XtWindow(player->shellWidget),
1659 icon_bits, icon_width, icon_height);
1661 XtSetArg(args[0], XtNiconPixmap, player->iconPixmap);
1662 XtSetValues(player->shellWidget, args, 1);
1665 * Create a cursor for the board widget.
1668 window_attributes.cursor = XCreateFontCursor(player->xDisplay, XC_hand2);
1669 XChangeWindowAttributes(player->xDisplay, player->xBoardWindow,
1670 CWCursor, &window_attributes);
1673 * Inhibit shell resizing.
1676 player->shellArgs[0].value = (XtArgVal) &w;
1677 player->shellArgs[1].value = (XtArgVal) &h;
1678 XtGetValues(player->shellWidget, player->shellArgs, 2);
1679 player->shellArgs[4].value = player->shellArgs[2].value = w;
1680 player->shellArgs[5].value = player->shellArgs[3].value = h;
1681 XtSetValues(player->shellWidget, &player->shellArgs[2], 4);
1684 * Determine value of black pixel.
1687 player->black_pixel_is_zero =
1688 (XBlackPixel(player->xDisplay, player->xScreen) == 0);
1694 if (!fromRemotePlayer)
1697 XtAddCallback(player->commandsWidget, XtNcallback, SelectCommand,
1698 (XtPointer)fromRemotePlayer);
1700 if (!fromRemotePlayer)
1701 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
1703 if (fromRemotePlayer)
1705 XtSetArg(args[0], XtNtranslations,
1706 XtParseTranslationTable(translationsTableReduced));
1707 /* Disable key commands because often keys are pressed
1708 in the board window if using another talk window. */
1709 XtSetValues(player->boardWidget, &args[0], 1);
1710 XtSetValues(localPlayer.boardWidget, &args[0], 1);
1714 XtSetArg(args[0], XtNtranslations,
1715 XtParseTranslationTable(translationsTable));
1716 XtSetValues(player->boardWidget, &args[0], 1);
1717 XtSetArg(args[0], XtNtranslations,
1718 XtParseTranslationTable(blackTranslations));
1719 XtSetValues(player->blackTimerWidget, &args[0], 1);
1720 XtSetArg(args[0], XtNtranslations,
1721 XtParseTranslationTable(whiteTranslations));
1722 XtSetValues(player->whiteTimerWidget, &args[0], 1);
1725 XtAddEventHandler(player->boardWidget, ExposureMask | ButtonPressMask
1726 | ButtonReleaseMask | Button1MotionMask | KeyPressMask,
1727 False, (XtEventHandler)EventProc,
1728 (XtPointer)(player == &remotePlayer));
1730 sprintf(buf, "xshogi version %s, patchlevel %s based on "
1731 "xboard version %s",
1732 version, patchlevel, XBOARD_VERSION);
1735 * If there is to be a machine match, set it up.
1738 if (matchMode != MatchFalse && player != &remotePlayer)
1740 if (player->appData.noShogiProgram)
1743 "%s: can't have a match with no shogi programs!\n",
1748 DisplayMessage(buf, fromRemotePlayer);
1749 TwoMachinesProc(NULL, NULL, NULL, NULL);
1754 DisplayMessage(buf, fromRemotePlayer);
1762 main(int argc, char **argv)
1764 setbuf(stdout, NULL);
1765 setbuf(stderr, NULL);
1768 * Copy pointers to command line arguments and number of such pointers.
1769 * (argc, argv will be destroyed by XtAppInitialize)
1772 for (global_argc = 0; global_argc < argc; global_argc++)
1773 global_argv[global_argc] = argv[global_argc];
1775 programName = strrchr(argv[0], '/');
1777 if (programName == NULL)
1778 programName = argv[0];
1782 localPlayer.shellWidget
1783 = XtAppInitialize(&appContext, "XShogi", shellOptions,
1784 XtNumber(shellOptions), &argc, argv,
1785 xshogiResources, NULL, 0);
1790 if ((shogiDir = (char *)getenv("SHOGIDIR")) == NULL)
1796 if (chdir(shogiDir) != 0)
1798 fprintf(stderr, "%s: can't cd to SHOGIDIR\n",
1805 XtGetApplicationResources(localPlayer.shellWidget,
1806 &localPlayer.appData, clientResources,
1807 XtNumber(clientResources), NULL, 0);
1809 xshogiDebug = localPlayer.appData.debugMode;
1812 * Determine matchMode state -- poor man's resource converter
1815 if (strcasecmp(localPlayer.appData.matchMode, "Init") == 0)
1817 matchMode = MatchInit;
1819 else if (strcasecmp(localPlayer.appData.matchMode, "Position") == 0)
1821 matchMode = MatchPosition;
1823 else if (strcasecmp(localPlayer.appData.matchMode, "Opening") == 0)
1825 matchMode = MatchOpening;
1827 else if (strcasecmp(localPlayer.appData.matchMode, "False") == 0)
1829 matchMode = MatchFalse;
1833 fprintf(stderr, "%s: bad matchMode option %s\n",
1834 programName, localPlayer.appData.matchMode);
1838 buttonStrings = gnuButtonStrings;
1839 buttonProcs = gnuButtonProcs;
1840 buttonCount = XtNumber(gnuButtonStrings);
1842 player = &localPlayer;
1844 CreatePlayerWindow();
1846 XtAppMainLoop(appContext);
1854 * Find a font that matches "pattern" that is as close as
1855 * possible to the targetPxlSize. Prefer fonts that are k
1856 * pixels smaller to fonts that are k pixels larger. The
1857 * pattern must be in the X Consortium standard format,
1858 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
1859 * The return value should be freed with XtFree when no
1864 FindFont(char *pattern, int targetPxlSize)
1866 char **fonts, *p, *best;
1867 int i, j, nfonts, minerr, err, pxlSize;
1869 fonts = XListFonts(player->xDisplay, pattern, 999999, &nfonts);
1873 fprintf(stderr, "%s: No fonts match pattern %s\n",
1874 programName, pattern);
1881 for (i = 0; i < nfonts; i++)
1903 if (pxlSize == targetPxlSize)
1909 err = pxlSize - targetPxlSize;
1911 if (abs(err) < abs(minerr)
1912 || ((minerr > 0) && (err < 0) && (-err == minerr)))
1919 p = (char *)XtMalloc(strlen(best) + 1);
1921 XFreeFontNames(fonts);
1931 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
1932 | GCBackground | GCFunction | GCPlaneMask;
1933 XGCValues gc_values;
1935 gc_values.plane_mask = AllPlanes;
1936 gc_values.line_width = LINE_GAP;
1937 gc_values.line_style = LineSolid;
1938 gc_values.function = GXcopy;
1940 gc_values.foreground = XBlackPixel(player->xDisplay, player->xScreen);
1941 gc_values.background = XBlackPixel(player->xDisplay, player->xScreen);
1942 player->lineGC = XtGetGC(player->shellWidget, value_mask, &gc_values);
1944 gc_values.background = XWhitePixel(player->xDisplay, player->xScreen);
1945 player->coordGC = XtGetGC(player->shellWidget, value_mask, &gc_values);
1946 XSetFont(player->xDisplay, player->coordGC, player->coordFontID);
1948 if (player->monoMode)
1950 gc_values.foreground
1951 = XWhitePixel(player->xDisplay, player->xScreen);
1952 gc_values.background
1953 = XBlackPixel(player->xDisplay, player->xScreen);
1954 player->lightSquareGC = player->darkSquareGC = player->wbPieceGC
1955 = XtGetGC(player->shellWidget, value_mask, &gc_values);
1956 gc_values.foreground
1957 = XBlackPixel(player->xDisplay, player->xScreen);
1958 gc_values.background
1959 = XWhitePixel(player->xDisplay, player->xScreen);
1961 = XtGetGC(player->shellWidget, value_mask, &gc_values);
1965 /* white piece black background */
1966 gc_values.foreground
1967 = XWhitePixel(player->xDisplay, player->xScreen);
1968 gc_values.background
1969 = XBlackPixel(player->xDisplay, player->xScreen);
1971 = XtGetGC(player->shellWidget, value_mask, &gc_values);
1973 /* black piece white background */
1974 gc_values.foreground
1975 = XBlackPixel(player->xDisplay, player->xScreen);
1976 gc_values.background
1977 = XWhitePixel(player->xDisplay, player->xScreen);
1979 = XtGetGC(player->shellWidget, value_mask, &gc_values);
1981 /* light empty square */
1982 gc_values.foreground
1983 = player->appData.lightSquareColor;
1984 gc_values.background
1985 = player->appData.darkSquareColor;
1986 player->lightSquareGC
1987 = XtGetGC(player->shellWidget, value_mask, &gc_values);
1989 /* dark empty square */
1990 gc_values.foreground
1991 = player->appData.darkSquareColor;
1992 gc_values.background
1993 = player->appData.lightSquareColor;
1994 player->darkSquareGC
1995 = XtGetGC(player->shellWidget, value_mask, &gc_values);
1997 /* black piece on dark square */
1998 gc_values.background
1999 = player->appData.blackPieceColor;
2000 gc_values.foreground
2001 = player->appData.darkSquareColor;
2003 = XtGetGC(player->shellWidget, value_mask, &gc_values);
2005 /* black piece on light square */
2006 gc_values.background
2007 = player->appData.blackPieceColor;
2008 gc_values.foreground
2009 = player->appData.lightSquareColor;
2011 = XtGetGC(player->shellWidget, value_mask, &gc_values);
2013 /* white piece on dark square */
2014 gc_values.background
2015 = player->appData.whitePieceColor;
2016 gc_values.foreground
2017 = player->appData.darkSquareColor;
2019 = XtGetGC(player->shellWidget, value_mask, &gc_values);
2021 /* white piece on dark square */
2022 gc_values.background
2023 = player->appData.whitePieceColor;
2024 gc_values.foreground
2025 = player->appData.lightSquareColor;
2027 = XtGetGC(player->shellWidget, value_mask, &gc_values);
2029 /* black piece off board */
2030 gc_values.background
2031 = player->appData.blackPieceColor;
2032 gc_values.foreground
2033 = XWhitePixel(player->xDisplay, player->xScreen);
2035 = XtGetGC(player->shellWidget, value_mask, &gc_values);
2037 /* white piece off board */
2038 gc_values.background
2039 = player->appData.whitePieceColor;
2040 gc_values.foreground
2041 = XWhitePixel(player->xDisplay, player->xScreen);
2043 = XtGetGC(player->shellWidget, value_mask, &gc_values);
2046 gc_values.function = (player->black_pixel_is_zero ? GXand : GXor);
2048 gc_values.foreground
2049 = XBlackPixel(player->xDisplay, player->xScreen);
2050 gc_values.background
2051 = XWhitePixel(player->xDisplay, player->xScreen);
2053 = XtGetGC(player->shellWidget, value_mask, &gc_values);
2063 XSynchronize(player->xDisplay, True); /* Work-around for xlib/xt
2066 if (player->appData.westernPieceSet)
2068 ReadBitmap(player->appData.reverseBigSolidBitmap,
2069 &player->reverseBigSolidBitmap,
2071 bigsolidR_bits, bigsolidR_bits, bigsolidR_bits);
2073 ReadBitmap(player->appData.reverseSmallSolidBitmap,
2074 &player->reverseSmallSolidBitmap,
2076 smallsolidR_bits, smallsolidR_bits, smallsolidR_bits);
2078 ReadBitmap(player->appData.normalBigSolidBitmap,
2079 &player->normalBigSolidBitmap,
2081 bigsolid_bits, bigsolid_bits, bigsolid_bits);
2083 ReadBitmap(player->appData.normalSmallSolidBitmap,
2084 &player->normalSmallSolidBitmap,
2086 smallsolid_bits, smallsolid_bits, smallsolid_bits);
2088 ReadBitmap(player->appData.reversePawnBitmap,
2089 &player->reversePawnBitmap,
2090 &player->reverseSmallSolidBitmap,
2091 pawnRW_bits, pawnRW_bits, pawnRW_bits);
2093 ReadBitmap(player->appData.reverseLanceBitmap,
2094 &player->reverseLanceBitmap,
2095 &player->reverseSmallSolidBitmap,
2096 lanceRW_bits, lanceRW_bits, lanceRW_bits);
2098 ReadBitmap(player->appData.reverseKnightBitmap,
2099 &player->reverseKnightBitmap,
2100 &player->reverseSmallSolidBitmap,
2101 knightRW_bits, knightRW_bits, knightRW_bits);
2103 ReadBitmap(player->appData.reverseSilverBitmap,
2104 &player->reverseSilverBitmap,
2105 &player->reverseBigSolidBitmap,
2106 silverRW_bits, silverRW_bits, silverRW_bits);
2108 ReadBitmap(player->appData.reverseGoldBitmap,
2109 &player->reverseGoldBitmap,
2110 &player->reverseBigSolidBitmap,
2111 goldRW_bits, goldRW_bits, goldRW_bits);
2113 ReadBitmap(player->appData.reverseRookBitmap,
2114 &player->reverseRookBitmap,
2115 &player->reverseBigSolidBitmap,
2116 rookRW_bits, rookRW_bits, rookRW_bits);
2118 ReadBitmap(player->appData.reverseBishopBitmap,
2119 &player->reverseBishopBitmap,
2120 &player->reverseBigSolidBitmap,
2121 bishopRW_bits, bishopRW_bits, bishopRW_bits);
2123 ReadBitmap(player->appData.reversePPawnBitmap,
2124 &player->reversePPawnBitmap,
2125 &player->reverseSmallSolidBitmap,
2126 pawnPRW_bits, pawnPRW_bits, pawnPRW_bits);
2128 ReadBitmap(player->appData.reversePLanceBitmap,
2129 &player->reversePLanceBitmap,
2130 &player->reverseSmallSolidBitmap,
2131 lancePRW_bits, lancePRW_bits, lancePRW_bits);
2133 ReadBitmap(player->appData.reversePKnightBitmap,
2134 &player->reversePKnightBitmap,
2135 &player->reverseSmallSolidBitmap,
2136 knightPRW_bits, knightPRW_bits, knightPRW_bits);
2138 ReadBitmap(player->appData.reversePSilverBitmap,
2139 &player->reversePSilverBitmap,
2140 &player->reverseBigSolidBitmap,
2141 silverPRW_bits, silverPRW_bits, silverPRW_bits);
2143 ReadBitmap(player->appData.reversePRookBitmap,
2144 &player->reversePRookBitmap,
2145 &player->reverseBigSolidBitmap,
2146 rookPRW_bits, rookPRW_bits, rookPRW_bits);
2148 ReadBitmap(player->appData.reversePBishopBitmap,
2149 &player->reversePBishopBitmap,
2150 &player->reverseBigSolidBitmap,
2151 bishopPRW_bits, bishopPRW_bits, bishopPRW_bits);
2153 ReadBitmap(player->appData.reverseKingBitmap,
2154 &player->reverseKingBitmap,
2155 &player->reverseBigSolidBitmap,
2156 kingRW_bits, kingRW_bits, kingRW_bits);
2158 ReadBitmap(player->appData.normalPawnBitmap,
2159 &player->normalPawnBitmap,
2160 &player->normalSmallSolidBitmap,
2161 pawnW_bits, pawnW_bits, pawnW_bits);
2163 ReadBitmap(player->appData.normalLanceBitmap,
2164 &player->normalLanceBitmap,
2165 &player->normalSmallSolidBitmap,
2166 lanceW_bits, lanceW_bits, lanceW_bits);
2168 ReadBitmap(player->appData.normalKnightBitmap,
2169 &player->normalKnightBitmap,
2170 &player->normalSmallSolidBitmap,
2171 knightW_bits, knightW_bits, knightW_bits);
2173 ReadBitmap(player->appData.normalSilverBitmap,
2174 &player->normalSilverBitmap,
2175 &player->normalBigSolidBitmap,
2176 silverW_bits, silverW_bits, silverW_bits);
2178 ReadBitmap(player->appData.normalGoldBitmap,
2179 &player->normalGoldBitmap,
2180 &player->normalBigSolidBitmap,
2181 goldW_bits, goldW_bits, goldW_bits);
2183 ReadBitmap(player->appData.normalRookBitmap,
2184 &player->normalRookBitmap,
2185 &player->normalBigSolidBitmap,
2186 rookW_bits, rookW_bits, rookW_bits);
2188 ReadBitmap(player->appData.normalBishopBitmap,
2189 &player->normalBishopBitmap,
2190 &player->normalBigSolidBitmap,
2191 bishopW_bits, bishopW_bits, bishopW_bits);
2193 ReadBitmap(player->appData.normalPPawnBitmap,
2194 &player->normalPPawnBitmap,
2195 &player->normalSmallSolidBitmap,
2196 pawnPW_bits, pawnPW_bits, pawnPW_bits);
2198 ReadBitmap(player->appData.normalPLanceBitmap,
2199 &player->normalPLanceBitmap,
2200 &player->normalSmallSolidBitmap,
2201 lancePW_bits, lancePW_bits, lancePW_bits);
2203 ReadBitmap(player->appData.normalPKnightBitmap,
2204 &player->normalPKnightBitmap,
2205 &player->normalSmallSolidBitmap,
2206 knightPW_bits, knightPW_bits, knightPW_bits);
2208 ReadBitmap(player->appData.normalPSilverBitmap,
2209 &player->normalPSilverBitmap,
2210 &player->normalBigSolidBitmap,
2211 silverPW_bits, silverPW_bits, silverPW_bits);
2213 ReadBitmap(player->appData.normalPRookBitmap,
2214 &player->normalPRookBitmap,
2215 &player->normalBigSolidBitmap,
2216 rookPW_bits, rookPW_bits, rookPW_bits);
2218 ReadBitmap(player->appData.normalPBishopBitmap,
2219 &player->normalPBishopBitmap,
2220 &player->normalBigSolidBitmap,
2221 bishopPW_bits, bishopPW_bits, bishopPW_bits);
2223 ReadBitmap(player->appData.normalKingBitmap,
2224 &player->normalKingBitmap,
2225 &player->normalBigSolidBitmap,
2226 kingW_bits, kingW_bits, kingW_bits);
2230 ReadBitmap(player->appData.reverseBigSolidBitmap,
2231 &player->reverseBigSolidBitmap,
2233 bigsolidR_bits, bigsolidR_m_bits, bigsolidR_l_bits);
2235 ReadBitmap(player->appData.reverseSmallSolidBitmap,
2236 &player->reverseSmallSolidBitmap,
2238 smallsolidR_bits, smallsolidR_m_bits, smallsolidR_l_bits);
2240 ReadBitmap(player->appData.normalBigSolidBitmap,
2241 &player->normalBigSolidBitmap,
2243 bigsolid_bits, bigsolid_m_bits, bigsolid_l_bits);
2245 ReadBitmap(player->appData.normalSmallSolidBitmap,
2246 &player->normalSmallSolidBitmap,
2248 smallsolid_bits, smallsolid_m_bits, smallsolid_l_bits);
2250 ReadBitmap(player->appData.reversePawnBitmap,
2251 &player->reversePawnBitmap,
2252 &player->reverseSmallSolidBitmap,
2253 pawnR_bits, pawnR_m_bits, pawnR_l_bits);
2255 ReadBitmap(player->appData.reverseLanceBitmap,
2256 &player->reverseLanceBitmap,
2257 &player->reverseSmallSolidBitmap,
2258 lanceR_bits, lanceR_m_bits, lanceR_l_bits);
2260 ReadBitmap(player->appData.reverseKnightBitmap,
2261 &player->reverseKnightBitmap,
2262 &player->reverseSmallSolidBitmap,
2263 knightR_bits, knightR_m_bits, knightR_l_bits);
2265 ReadBitmap(player->appData.reverseSilverBitmap,
2266 &player->reverseSilverBitmap,
2267 &player->reverseBigSolidBitmap,
2268 silverR_bits, silverR_m_bits, silverR_l_bits);
2270 ReadBitmap(player->appData.reverseGoldBitmap,
2271 &player->reverseGoldBitmap,
2272 &player->reverseBigSolidBitmap,
2273 goldR_bits, goldR_m_bits, goldR_l_bits);
2275 ReadBitmap(player->appData.reverseRookBitmap,
2276 &player->reverseRookBitmap,
2277 &player->reverseBigSolidBitmap,
2278 rookR_bits, rookR_m_bits, rookR_l_bits);
2280 ReadBitmap(player->appData.reverseBishopBitmap,
2281 &player->reverseBishopBitmap,
2282 &player->reverseBigSolidBitmap,
2283 bishopR_bits, bishopR_m_bits, bishopR_l_bits);
2285 ReadBitmap(player->appData.reversePPawnBitmap,
2286 &player->reversePPawnBitmap,
2287 &player->reverseSmallSolidBitmap,
2288 pawnPR_bits, pawnPR_m_bits, pawnPR_l_bits);
2290 ReadBitmap(player->appData.reversePLanceBitmap,
2291 &player->reversePLanceBitmap,
2292 &player->reverseSmallSolidBitmap,
2293 lancePR_bits, lancePR_m_bits, lancePR_l_bits);
2295 ReadBitmap(player->appData.reversePKnightBitmap,
2296 &player->reversePKnightBitmap,
2297 &player->reverseSmallSolidBitmap,
2298 knightPR_bits, knightPR_m_bits, knightPR_l_bits);
2300 ReadBitmap(player->appData.reversePSilverBitmap,
2301 &player->reversePSilverBitmap,
2302 &player->reverseBigSolidBitmap,
2303 silverPR_bits, silverPR_m_bits, silverPR_l_bits);
2305 ReadBitmap(player->appData.reversePRookBitmap,
2306 &player->reversePRookBitmap,
2307 &player->reverseBigSolidBitmap,
2308 rookPR_bits, rookPR_m_bits, rookPR_l_bits);
2310 ReadBitmap(player->appData.reversePBishopBitmap,
2311 &player->reversePBishopBitmap,
2312 &player->reverseBigSolidBitmap,
2313 bishopPR_bits, bishopPR_m_bits, bishopPR_l_bits);
2315 ReadBitmap(player->appData.reverseKingBitmap,
2316 &player->reverseKingBitmap,
2317 &player->reverseBigSolidBitmap,
2318 kingR_bits, kingR_m_bits, kingR_l_bits);
2320 ReadBitmap(player->appData.normalPawnBitmap,
2321 &player->normalPawnBitmap,
2322 &player->normalSmallSolidBitmap,
2323 pawn_bits, pawn_m_bits, pawn_l_bits);
2325 ReadBitmap(player->appData.normalLanceBitmap,
2326 &player->normalLanceBitmap,
2327 &player->normalSmallSolidBitmap,
2328 lance_bits, lance_m_bits, lance_l_bits);
2330 ReadBitmap(player->appData.normalKnightBitmap,
2331 &player->normalKnightBitmap,
2332 &player->normalSmallSolidBitmap,
2333 knight_bits, knight_m_bits, knight_l_bits);
2335 ReadBitmap(player->appData.normalSilverBitmap,
2336 &player->normalSilverBitmap,
2337 &player->normalBigSolidBitmap,
2338 silver_bits, silver_m_bits, silver_l_bits);
2340 ReadBitmap(player->appData.normalGoldBitmap,
2341 &player->normalGoldBitmap,
2342 &player->normalBigSolidBitmap,
2343 gold_bits, gold_m_bits, gold_l_bits);
2345 ReadBitmap(player->appData.normalRookBitmap,
2346 &player->normalRookBitmap,
2347 &player->normalBigSolidBitmap,
2348 rook_bits, rook_m_bits, rook_l_bits);
2350 ReadBitmap(player->appData.normalBishopBitmap,
2351 &player->normalBishopBitmap,
2352 &player->normalBigSolidBitmap,
2353 bishop_bits, bishop_m_bits, bishop_l_bits);
2355 ReadBitmap(player->appData.normalPPawnBitmap,
2356 &player->normalPPawnBitmap,
2357 &player->normalSmallSolidBitmap,
2358 pawnP_bits, pawnP_m_bits, pawnP_l_bits);
2360 ReadBitmap(player->appData.normalPLanceBitmap,
2361 &player->normalPLanceBitmap,
2362 &player->normalSmallSolidBitmap,
2363 lanceP_bits, lanceP_m_bits, lanceP_l_bits);
2365 ReadBitmap(player->appData.normalPKnightBitmap,
2366 &player->normalPKnightBitmap,
2367 &player->normalSmallSolidBitmap,
2368 knightP_bits, knightP_m_bits, knightP_l_bits);
2370 ReadBitmap(player->appData.normalPSilverBitmap,
2371 &player->normalPSilverBitmap,
2372 &player->normalBigSolidBitmap,
2373 silverP_bits, silverP_m_bits, silverP_l_bits);
2375 ReadBitmap(player->appData.normalPRookBitmap,
2376 &player->normalPRookBitmap,
2377 &player->normalBigSolidBitmap,
2378 rookP_bits, rookP_m_bits, rookP_l_bits);
2380 ReadBitmap(player->appData.normalPBishopBitmap,
2381 &player->normalPBishopBitmap,
2382 &player->normalBigSolidBitmap,
2383 bishopP_bits, bishopP_m_bits, bishopP_l_bits);
2385 ReadBitmap(player->appData.normalKingBitmap,
2386 &player->normalKingBitmap,
2387 &player->normalBigSolidBitmap,
2388 king_bits, king_m_bits, king_l_bits);
2392 XSynchronize(player->xDisplay, False); /* Work-around for xlib/xt
2400 ReadBitmapFile(Display *display, Drawable d, char *filename,
2401 unsigned int *width_return,
2402 unsigned int *height_return,
2403 Pixmap *bitmap_return,
2404 int *x_hot_return, int *y_hot_return)
2408 if ((n = XReadBitmapFile(display, d, filename,
2409 width_return, height_return,
2410 bitmap_return, x_hot_return, y_hot_return))
2417 /* transform a 1 plane pixmap to a k plane pixmap */
2418 return BitmapSuccess;
2426 * Create the X pixmap from .xbm file bitmap data. This may
2427 * have to be revised considerably.
2431 ReadBitmap(String name, Pixmap *pm, Pixmap *qm,
2432 char *small_bits, char *medium_bits, char *large_bits)
2438 || (ReadBitmapFile(player->xDisplay, player->xBoardWindow, name,
2439 &w, &h, pm, &x_hot, &y_hot) != BitmapSuccess)
2440 || (w != player->squareSize)
2441 || (h != player->squareSize))
2443 unsigned long fg, bg;
2446 depth = DisplayPlanes(player->xDisplay, player->xScreen);
2448 if (player->monoMode)
2450 fg = XBlackPixel(player->xDisplay, player->xScreen);
2451 bg = XWhitePixel(player->xDisplay, player->xScreen);
2453 else if (qm == NULL)
2455 fg = player->appData.oneColor;
2456 bg = player->appData.zeroColor;
2460 fg = (player->black_pixel_is_zero ? 0 : ~0);
2461 bg = (player->black_pixel_is_zero ? ~0 : 0);
2464 switch (player->boardSize)
2467 *pm = XCreatePixmapFromBitmapData(player->xDisplay,
2468 player->xBoardWindow,
2476 *pm = XCreatePixmapFromBitmapData(player->xDisplay,
2477 player->xBoardWindow,
2485 *pm = XCreatePixmapFromBitmapData(player->xDisplay,
2486 player->xBoardWindow,
2504 offset = 2 * (player->squareSize + LINE_GAP);
2506 for (i = 0; i < BOARD_SIZE + 1; i++)
2508 player->gridSegments[i].x1 = offset;
2509 player->gridSegments[i + BOARD_SIZE + 1].y1 = 0;
2510 player->gridSegments[i].y1 = player->gridSegments[i].y2
2511 = LINE_GAP / 2 + (i * (player->squareSize + LINE_GAP));
2512 player->gridSegments[i].x2 = LINE_GAP + BOARD_SIZE *
2513 (player->squareSize + LINE_GAP) + offset;
2514 player->gridSegments[i + BOARD_SIZE + 1].x1
2515 = player->gridSegments[i + BOARD_SIZE + 1].x2 = LINE_GAP / 2
2516 + (i * (player->squareSize + LINE_GAP)) + offset;
2517 player->gridSegments[i + BOARD_SIZE + 1].y2
2518 = BOARD_SIZE * (player->squareSize + LINE_GAP);
2526 CreatePieceMenus(void)
2531 ShogiSquare selection;
2533 XtSetArg(args[0], XtNlabel, "Black");
2534 blackPieceMenu = XtCreatePopupShell("menuW", simpleMenuWidgetClass,
2535 localPlayer.boardWidget, args, 1);
2537 for (i = 0; i < PIECE_MENU_SIZE; i++)
2539 String item = pieceMenuStrings[i];
2541 if (strcmp(item, "----") == 0)
2543 entry = XtCreateManagedWidget(item, smeLineObjectClass,
2544 blackPieceMenu, NULL, 0);
2548 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
2549 blackPieceMenu, NULL, 0);
2550 selection = pieceMenuTranslation[0][i];
2551 XtAddCallback(entry, XtNcallback,
2552 (XtCallbackProc) PieceMenuSelect,
2553 (caddr_t)selection);
2555 if (selection == BlackPawn)
2557 XtSetArg(args[0], XtNpopupOnEntry, entry);
2558 XtSetValues(blackPieceMenu, args, 1);
2563 XtSetArg(args[0], XtNlabel, "White");
2564 whitePieceMenu = XtCreatePopupShell("menuB", simpleMenuWidgetClass,
2565 localPlayer.boardWidget, args, 1);
2567 for (i = 0; i < PIECE_MENU_SIZE; i++)
2569 String item = pieceMenuStrings[i];
2571 if (strcmp(item, "----") == 0)
2573 entry = XtCreateManagedWidget(item, smeLineObjectClass,
2574 whitePieceMenu, NULL, 0);
2578 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
2579 whitePieceMenu, NULL, 0);
2580 selection = pieceMenuTranslation[1][i];
2581 XtAddCallback(entry, XtNcallback,
2582 (XtCallbackProc) PieceMenuSelect,
2583 (caddr_t)selection);
2585 if (selection == WhitePawn)
2587 XtSetArg(args[0], XtNpopupOnEntry, entry);
2588 XtSetValues(whitePieceMenu, args, 1);
2593 XtRegisterGrabAction(PieceMenuPopup, True,
2594 (unsigned)(ButtonPressMask|ButtonReleaseMask),
2595 GrabModeAsync, GrabModeAsync);
2602 PieceMenuPopup(Widget w, XEvent *event, String *params, Cardinal *num_params)
2604 if (event->type != ButtonPress)
2607 if (gameMode != EditPosition)
2610 if (((pmFromX = EventToXSquare(event->xbutton.x)) < 1)
2611 || (pmFromX > BOARD_SIZE + 2)
2612 || ((pmFromY = EventToSquare(event->xbutton.y)) < 0))
2614 pmFromX = pmFromY = -1;
2618 if (localPlayer.flipView)
2619 pmFromX = BOARD_SIZE + 3 - pmFromX;
2621 pmFromY = BOARD_SIZE - 1 - pmFromY;
2623 XtPopupSpringLoaded(XtNameToWidget(localPlayer.boardWidget, params[0]));
2630 PieceMenuSelect(Widget w, ShogiSquare piece, caddr_t junk)
2632 if ((pmFromX < 0) || (pmFromY < 0))
2635 if (off_board(pmFromX))
2650 i = pieceToCatchedIndex[piece];
2651 c = (piece >= WhitePawn);
2653 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
2654 XSync(localPlayer.xDisplay, False);
2664 for (pmFromY = 0; pmFromY < BOARD_SIZE; pmFromY++)
2665 for (pmFromX = 0; pmFromX < BOARD_SIZE; pmFromX++)
2666 boards[0][pmFromY][pmFromX] = EmptySquare;
2668 ClearCatches(catches[0]);
2669 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
2672 case BlackPlay: /* not currently on menu */
2676 case WhitePlay: /* not currently on menu */
2681 boards[0][pmFromY][pmFromX] = piece;
2682 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
2686 XSync(localPlayer.xDisplay, False);
2693 SetBlackToPlay(void)
2697 if (gameMode != EditPosition)
2700 whitePlaysFirst = False;
2701 saveCM = currentMove;
2702 currentMove = 0; /* kludge */
2703 DisplayClocks(ReDisplayTimers);
2704 currentMove = saveCM;
2711 SetWhiteToPlay(void)
2715 if (gameMode != EditPosition)
2718 whitePlaysFirst = True;
2719 saveCM = currentMove;
2720 currentMove = 1; /* kludge */
2721 DisplayClocks(ReDisplayTimers);
2722 currentMove = saveCM;
2729 * If the user selects on a border boundary or off the board, return failure.
2730 * Otherwise map the event coordinate to the square.
2734 EventToSquare(int x)
2741 if ((x % (player->squareSize + LINE_GAP)) >= player->squareSize)
2744 x /= (player->squareSize + LINE_GAP);
2746 if (x >= BOARD_SIZE)
2756 EventToXSquare(int x)
2763 if ((x % (player->squareSize + LINE_GAP)) >= player->squareSize)
2766 x /= (player->squareSize + LINE_GAP);
2768 if (x >= BOARD_SIZE + 4)
2778 CharToPiece(int c, int p)
2785 case '.': return EmptySquare;
2786 case 'P': return BlackPPawn;
2787 case 'L': return BlackPLance;
2788 case 'N': return BlackPKnight;
2789 case 'S': return BlackPSilver;
2790 case 'G': return BlackGold;
2791 case 'R': return BlackPRook;
2792 case 'B': return BlackPBishop;
2793 case 'K': return BlackKing;
2794 case 'p': return WhitePPawn;
2795 case 'l': return WhitePLance;
2796 case 'n': return WhitePKnight;
2797 case 's': return WhitePSilver;
2798 case 'g': return WhiteGold;
2799 case 'r': return WhitePRook;
2800 case 'b': return WhitePBishop;
2801 case 'k': return WhiteKing;
2809 case '.': return EmptySquare;
2810 case 'P': return BlackPawn;
2811 case 'L': return BlackLance;
2812 case 'N': return BlackKnight;
2813 case 'S': return BlackSilver;
2814 case 'G': return BlackGold;
2815 case 'R': return BlackRook;
2816 case 'B': return BlackBishop;
2817 case 'K': return BlackKing;
2818 case 'p': return WhitePawn;
2819 case 'l': return WhiteLance;
2820 case 'n': return WhiteKnight;
2821 case 's': return WhiteSilver;
2822 case 'g': return WhiteGold;
2823 case 'r': return WhiteRook;
2824 case 'b': return WhiteBishop;
2825 case 'k': return WhiteKing;
2834 * Convert coordinates to normal algebraic notation.
2835 * promoPiece must be NULLCHAR if not a promotion.
2839 MakeAlg(int fromX, int fromY, int toX, int toY,
2840 char promoPiece, int currentBoardIndex, char *out)
2847 piece = (fromX - 81);
2848 *outp++ = catchedIndexToChar[piece];
2850 *outp++ = '9' - toX;
2851 *outp++ = 'i' - toY;
2853 return (BlackOnMove(forwardMostMove) ? BlackDrop : WhiteDrop);
2857 *outp++ = '9' - fromX;
2858 *outp++ = 'i' - fromY;
2859 *outp++ = '9' - toX;
2860 *outp++ = 'i' - toY;
2861 *outp++ = promoPiece;
2864 if (promoPiece == NULLCHAR)
2870 return (BlackOnMove(forwardMostMove)
2871 ? BlackPromotion : WhitePromotion);
2880 DrawSquare(int row, int column, ShogiSquare piece)
2882 int square_color, x, y, direction, font_ascent, font_descent;
2884 XCharStruct overall;
2885 struct DisplayData *player;
2887 for (player = &localPlayer; True; player = &remotePlayer)
2891 remote = (player == &remotePlayer);
2892 offset = 2 * (player->squareSize + LINE_GAP);
2894 if (player->flipView)
2896 x = LINE_GAP + ((BOARD_SIZE - 1) - column) *
2897 (player->squareSize + LINE_GAP) + offset;
2898 y = LINE_GAP + row * (player->squareSize + LINE_GAP);
2902 x = LINE_GAP + column * (player->squareSize + LINE_GAP) + offset;
2903 y = LINE_GAP + ((BOARD_SIZE - 1) - row) *
2904 (player->squareSize + LINE_GAP);
2907 square_color = (((column + row) % 2) ? LIGHT : DARK);
2909 if (piece == EmptySquare)
2911 if (column < 0 || column >= BOARD_SIZE)
2913 /* empty square off board */
2914 XFillRectangle(player->xDisplay, player->xBoardWindow,
2916 x, y, player->squareSize,
2917 player->squareSize);
2921 /* empty square on board */
2922 XFillRectangle(player->xDisplay, player->xBoardWindow,
2923 ((square_color == LIGHT)
2924 ? player->lightSquareGC
2925 : player->darkSquareGC),
2926 x, y, player->squareSize,
2927 player->squareSize);
2930 else if (player->monoMode)
2933 if (square_color == LIGHT)
2935 XCopyArea(player->xDisplay,
2936 ((((((int)piece) < ((int)WhitePawn)))
2938 ? *pieceToNormal[remote][(int)piece]
2939 : *pieceToReverse[remote][(int)piece]),
2940 player->xBoardWindow,
2943 : player->wlPieceGC),
2945 player->squareSize, player->squareSize, x, y);
2949 XCopyArea(player->xDisplay,
2950 ((((((int)piece) < ((int)WhitePawn)))
2952 ? *pieceToNormal[remote][(int)piece]
2953 : *pieceToReverse[remote][(int)piece]),
2954 player->xBoardWindow,
2957 : player->blPieceGC),
2959 player->squareSize, player->squareSize, x, y);
2965 if ((column < 0) || (column >= BOARD_SIZE))
2968 XCopyPlane(player->xDisplay,
2969 ((((((int)piece) < ((int)WhitePawn)))
2971 ? *pieceToNormalSolid[remote][(int)piece]
2972 : *pieceToReverseSolid[remote][(int)piece]),
2973 player->xBoardWindow,
2974 (pieceisWhite[(int)piece]
2976 : player->boPieceGC),
2978 player->squareSize, player->squareSize, x, y, 1);
2980 XCopyArea(player->xDisplay,
2981 ((((((int)piece) < ((int)WhitePawn)))
2983 ? *pieceToNormal[remote][(int)piece]
2984 : *pieceToReverse[remote][(int)piece]),
2985 player->xBoardWindow,
2986 player->charPieceGC,
2988 player->squareSize, player->squareSize, x, y);
2990 else if (square_color == LIGHT)
2992 /* on board, light square */
2993 XCopyPlane(player->xDisplay,
2994 ((((((int)piece) < ((int)WhitePawn)))
2996 ? *pieceToNormalSolid[remote][(int)piece]
2997 : *pieceToReverseSolid[remote][(int)piece]),
2998 player->xBoardWindow,
2999 pieceisWhite[(int)piece]
3001 : player->blPieceGC,
3003 player->squareSize, player->squareSize, x, y, 1);
3005 XCopyArea(player->xDisplay,
3006 ((((((int)piece) < ((int)WhitePawn)))
3008 ? *pieceToNormal[remote][(int)piece]
3009 : *pieceToReverse[remote][(int)piece]),
3010 player->xBoardWindow,
3011 player->charPieceGC,
3013 player->squareSize, player->squareSize, x, y);
3017 /* on board, dark square */
3018 XCopyPlane(player->xDisplay,
3019 ((((((int)piece) < ((int)WhitePawn)))
3021 ? *pieceToNormalSolid[remote][(int)piece]
3022 : *pieceToReverseSolid[remote][(int)piece]),
3023 player->xBoardWindow,
3024 (pieceisWhite[(int)piece]
3026 : player->bdPieceGC),
3028 player->squareSize, player->squareSize, x, y, 1);
3030 XCopyArea(player->xDisplay,
3031 ((((((int)piece) < ((int)WhitePawn)))
3033 ? *pieceToNormal[remote][(int)piece]
3034 : *pieceToReverse[remote][(int)piece]),
3035 player->xBoardWindow,
3036 player->charPieceGC,
3038 player->squareSize, player->squareSize, x, y);
3041 string[1] = NULLCHAR;
3043 if (player->showCoords
3044 && (column >= 0) && (column < 9)
3045 && (row == (player->flipView ? 8 : 0)))
3047 string[0] = '9' - column;
3048 XTextExtents(player->coordFontStruct, string, 1, &direction,
3049 &font_ascent, &font_descent, &overall);
3051 if (player->monoMode)
3053 XDrawImageString(player->xDisplay,
3054 player->xBoardWindow, player->coordGC,
3055 x + player->squareSize - overall.width - 2,
3056 y + player->squareSize - font_descent - 1,
3061 XDrawString(player->xDisplay, player->xBoardWindow,
3063 x + player->squareSize - overall.width - 2,
3064 y + player->squareSize - font_descent - 1,
3069 if (player->showCoords
3070 && (row >= 0) && (row < 9)
3071 && (column == (player->flipView ? 8 : 0)))
3073 string[0] = 'i' - row;
3074 XTextExtents(player->coordFontStruct, string, 1, &direction,
3075 &font_ascent, &font_descent, &overall);
3077 if (player->monoMode)
3079 XDrawImageString(player->xDisplay,
3080 player->xBoardWindow, player->coordGC,
3081 x + 2, y + font_ascent + 1, string, 1);
3085 XDrawString(player->xDisplay, player->xBoardWindow,
3087 x + 2, y + font_ascent + 1, string, 1);
3091 if (!updateRemotePlayer || (player == &remotePlayer))
3100 EventProc(Widget widget, caddr_t client_data, XEvent *event)
3102 if (event->type == MappingNotify)
3104 XRefreshKeyboardMapping((XMappingEvent *) event);
3108 if (!XtIsRealized(widget))
3111 if ((event->type == ButtonPress) || (event->type == ButtonRelease))
3113 if (event->xbutton.button != Button1)
3117 switch (event->type)
3120 DrawPosition(widget, event, NULL, NULL);
3132 * event handler for redrawing the board
3136 DrawPosition(Widget w, XEvent *event, String *prms, Cardinal *nprms)
3140 static Board lastBoard;
3141 static Catched lastCatches;
3142 static int lastBoardValid = 0;
3143 static int lastFlipView = 0, lastRemoteFlipView = 1;
3145 if (!player->Iconic)
3147 XtSetArg(args[0], XtNiconic, False);
3148 XtSetValues(localPlayer.shellWidget, args, 1);
3152 * It would be simpler to clear the window with XClearWindow()
3153 * but this causes a very distracting flicker.
3156 if ((w == localPlayer.boardWidget)
3159 && (lastFlipView == localPlayer.flipView)
3160 && (!updateRemotePlayer
3161 || (lastRemoteFlipView == remotePlayer.flipView)))
3163 for (i = 0; i < BOARD_SIZE; i++)
3165 for (j = 0; j < BOARD_SIZE; j++)
3167 if (boards[currentMove][i][j] != lastBoard[i][j])
3168 DrawSquare(i, j, boards[currentMove][i][j]);
3172 for (i = 0; i < 2; i++)
3174 for (j = 0; j < 8; j++)
3176 if (catches[currentMove][i][j] != lastCatches[i][j])
3178 UpdateCatched(i, 0, False, True, currentMove);
3186 XDrawSegments(localPlayer.xDisplay,
3187 localPlayer.xBoardWindow, localPlayer.lineGC,
3188 localPlayer.gridSegments, (BOARD_SIZE + 1) * 2);
3190 if (updateRemotePlayer)
3192 XDrawSegments(remotePlayer.xDisplay,
3193 remotePlayer.xBoardWindow, remotePlayer.lineGC,
3194 remotePlayer.gridSegments, (BOARD_SIZE + 1) * 2);
3197 for (i = 0; i < BOARD_SIZE; i++)
3198 for (j = 0; j < BOARD_SIZE; j++)
3199 DrawSquare(i, j, boards[currentMove][i][j]);
3201 UpdateCatched(0, 0, False, True, currentMove);
3202 UpdateCatched(1, 0, False, True, currentMove);
3205 CopyBoard(lastBoard, boards[currentMove]);
3206 CopyCatches(lastCatches, catches[currentMove]);
3208 lastFlipView = localPlayer.flipView;
3210 if (updateRemotePlayer)
3211 lastRemoteFlipView = remotePlayer.flipView;
3213 XSync(localPlayer.xDisplay, False);
3215 if (updateRemotePlayer)
3216 XSync(remotePlayer.xDisplay, False);
3223 InitPosition(int redraw)
3225 currentMove = forwardMostMove = backwardMostMove = 0;
3226 CopyBoard(boards[0], initialPosition);
3227 ClearCatches(catches[0]);
3230 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
3237 CopyBoard(Board to, Board from)
3241 for (i = 0; i < BOARD_SIZE; i++)
3242 for (j = 0; j < BOARD_SIZE; j++)
3243 to[i][j] = from[i][j];
3250 CopyCatches(Catched to, Catched from)
3254 for (i = 0; i < 2; i++)
3255 for (j = 0; j < 8; j++)
3256 to[i][j] = from[i][j];
3263 SendCurrentBoard(FILE *fp)
3265 SendBoard(fp, boards[currentMove], catches[currentMove]);
3272 SendBoard(FILE *fp, Board board, Catched catches)
3274 char message[MSG_SIZ];
3278 SendToProgram("edit\n", fp);
3279 SendToProgram("#\n", fp);
3281 for (i = BOARD_SIZE - 1; i >= 0; i--)
3285 for (j = 0; j < BOARD_SIZE; j++, bp++)
3287 if (((int) *bp) < (int)WhitePawn)
3289 sprintf(message, "%c%c%c%s\n",
3290 pieceToChar[(int) *bp],
3292 (pieceIsPromoted[(int) *bp] ? "+" : ""));
3293 SendToProgram(message, fp);
3298 for (i = 0; i <= 7; i++)
3302 for (n = catches[0][i]; n > 0; n--)
3304 sprintf(message, "%c*\n",
3305 catchedIndexToChar[i]);
3306 SendToProgram(message, fp);
3310 SendToProgram("c\n", fp);
3312 for (i = BOARD_SIZE - 1; i >= 0; i--)
3316 for (j = 0; j < BOARD_SIZE; j++, bp++)
3318 if ((((int) *bp) != ((int)EmptySquare))
3319 && (((int) *bp) >= ((int)WhitePawn)))
3321 sprintf(message, "%c%c%c%s\n",
3322 pieceToChar[((int) *bp) - ((int)WhitePawn)],
3324 (pieceIsPromoted[(int) *bp] ? "+" : ""));
3325 SendToProgram(message, fp);
3330 for (i = 0; i <= 7; i++)
3334 for (n = catches[1][i]; n > 0; n--)
3336 sprintf(message, "%c*\n",
3337 catchedIndexToChar[i]);
3338 SendToProgram(message, fp);
3342 SendToProgram(".\n", fp);
3349 PromotionPossible(int fromY, int toY, ShogiSquare piece)
3351 if (((int)piece) < ((int)WhitePawn))
3353 if ((fromY < 6) && (toY < 6))
3358 if ((fromY > 2) && (toY > 2))
3362 return piecePromotable[(int)piece];
3370 ShowCount(int row, int column, int n)
3372 int offset = 2 * (player->squareSize + LINE_GAP);
3373 int x, y, direction, font_ascent, font_descent;
3375 XCharStruct overall;
3376 struct DisplayData *player;
3378 DrawSquare(row, column, EmptySquare);
3383 for (player = &localPlayer; True; player = &remotePlayer)
3385 if (player->flipView)
3387 x = LINE_GAP + ((BOARD_SIZE - 1) - column) *
3388 (player->squareSize + LINE_GAP) + offset;
3389 y = LINE_GAP + row * (player->squareSize + LINE_GAP);
3393 x = LINE_GAP + column * (player->squareSize + LINE_GAP) + offset;
3394 y = LINE_GAP + ((BOARD_SIZE - 1) - row) *
3395 (player->squareSize + LINE_GAP);
3398 x -= player->squareSize / 2;
3400 string[1] = NULLCHAR;
3405 string[0] = '0' + n;
3407 XTextExtents(player->coordFontStruct, string, 1, &direction,
3408 &font_ascent, &font_descent, &overall);
3410 if (player->monoMode)
3412 XDrawImageString(player->xDisplay, player->xBoardWindow,
3414 x + player->squareSize - overall.width - 2,
3415 y + player->squareSize - font_descent - 1,
3420 XDrawString(player->xDisplay, player->xBoardWindow,
3422 x + player->squareSize - overall.width - 2,
3423 y + player->squareSize - font_descent - 1,
3427 if (!updateRemotePlayer || (player == &remotePlayer))
3436 UpdateCatched(int Color, int Figure, int Drop, int DropAll, int currentMove)
3441 /* Determine first row and column. */
3457 n = catches[currentMove][Color][Figure];
3459 /* Update the display for captured pieces
3460 if no piece of the dropped type is there (Drop && n==1)
3461 or if a piece type is removed (NOT Drop && n==0).
3462 In the other cases update only the count. */
3464 if (DropAll || (Drop && (n == 1)) || (!Drop && (n == 0)))
3466 /* show all captured pieces */
3469 for (F = pawn; F <= king; F++)
3473 if ((c = catches[currentMove][Color][F]) > 0)
3476 DrawSquare(y, x, catchedIndexToPiece[Color][F]);
3477 ShowCount(y, (Color ? (x - 1) : (x + 1)), c);
3490 DrawSquare(y, x, EmptySquare);
3491 ShowCount(y, (Color ? (x - 1) : (x + 1)), 0);
3501 /* remove one line! */
3502 DrawSquare(y, x, EmptySquare);
3503 ShowCount(y, (Color ? (x - 1) : (x + 1)), 0);
3508 /* show the actual count */
3509 for (F = pawn; F <= Figure - 1; F++)
3511 if (catches[currentMove][Color][F] > 0)
3520 ShowCount(y, (Color ? (x - 1) : (x + 1)), n);
3529 static int BlinkCount = 0;
3530 static int BlinkRow, BlinkCol;
3531 static ShogiSquare BlinkPiece;
3535 BlinkSquareProc(void)
3540 DrawSquare (BlinkRow, BlinkCol,
3541 ((BlinkCount & 1) ? EmptySquare : BlinkPiece));
3546 = XtAppAddTimeOut(appContext,
3548 (XtTimerCallbackProc)BlinkSquareProc,
3562 BlinkSquare(int row, int col, ShogiSquare piece)
3564 BlinkCount = 2 * BLINK_COUNT + 1;
3572 #endif /* BLINK_COUNT */
3578 PieceOfCatched(int color, int x, int y, int currentMove)
3595 for (F = pawn, n = 0; F <= king; F++)
3597 if (catches[currentMove][color][F] > 0)
3613 * event handler for parsing user moves
3617 HandleUserMove(Widget w, XEvent *event)
3619 ShogiMove move_type;
3620 ShogiSquare from_piece;
3621 int to_x, to_y, fromRemotePlayer;
3623 if (updateRemotePlayer)
3625 if (((w != localPlayer.boardWidget)
3626 && (w != remotePlayer.boardWidget))
3627 || (matchMode != MatchFalse))
3632 fromRemotePlayer = (w == remotePlayer.boardWidget);
3636 if ((w != localPlayer.boardWidget) || (matchMode != MatchFalse))
3639 fromRemotePlayer = False;
3642 player = (fromRemotePlayer ? &remotePlayer : &localPlayer);
3644 if (player->promotionUp)
3646 XtPopdown(player->promotionShell);
3647 XtDestroyWidget(player->promotionShell);
3648 player->promotionUp = False;
3655 case PlayFromGameFile:
3656 case TwoMachinesPlay:
3659 case MachinePlaysBlack:
3660 if (BlackOnMove(forwardMostMove))
3662 DisplayMessage("It is not your turn", fromRemotePlayer);
3668 case MachinePlaysWhite:
3669 if (!BlackOnMove(forwardMostMove))
3671 DisplayMessage("It is not your turn", fromRemotePlayer);
3678 forwardMostMove = currentMove;
3685 if (currentMove != forwardMostMove)
3687 DisplayMessage("Displayed position is not current",
3692 switch (event->type)
3695 if ((fromX >= 0) || (fromY >= 0))
3698 if (((fromX = EventToXSquare(event->xbutton.x)) < 1)
3699 || (fromX > BOARD_SIZE + 2)
3700 || ((fromY = EventToSquare(event->xbutton.y)) < 0))
3706 if (player->flipView)
3707 fromX = BOARD_SIZE + 3 - fromX;
3709 fromY = BOARD_SIZE - 1 - fromY;
3714 if ((fromX < 0) || (fromY < 0))
3717 if (((to_x = EventToXSquare(event->xbutton.x)) < 1)
3718 || (to_x > BOARD_SIZE + 2)
3719 || ((to_y = EventToSquare(event->xbutton.y)) < 0))
3721 if (gameMode == EditPosition && !off_board(fromX))
3724 boards[0][fromY][fromX] = EmptySquare;
3725 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
3726 XSync(localPlayer.xDisplay, False);
3728 if (updateRemotePlayer)
3729 XSync(remotePlayer.xDisplay, False);
3736 if (player->flipView)
3737 to_x = BOARD_SIZE + 3 - to_x;
3739 to_y = BOARD_SIZE - 1 - to_y;
3741 if ((fromX == to_x) && (fromY == to_y))
3747 if (gameMode == EditPosition)
3751 if (off_board(fromX))
3753 /* Remove a catched piece */
3755 c = ((fromX < 5) ^ player->flipView);
3756 i = PieceOfCatched(c, fromX, fromY, 0);
3765 piece = catchedIndexToPiece[c][i];
3771 /* remove piece from board field */
3773 piece = boards[0][fromY][fromX];
3774 boards[0][fromY][fromX] = EmptySquare;
3777 if (!off_board(to_x))
3779 /* drop piece to board field */
3780 ShogiSquare catched_piece;
3782 catched_piece = boards[0][to_y][to_x];
3784 if (catched_piece != EmptySquare)
3786 /* put piece to catched pieces */
3787 int i = pieceToCatchedIndex[catched_piece];
3788 int c = (catched_piece < WhitePawn);
3792 /* place moved piece */
3793 boards[0][to_y][to_x] = piece;
3797 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
3798 XSync(localPlayer.xDisplay, False);
3800 if (updateRemotePlayer)
3801 XSync(remotePlayer.xDisplay, False);
3806 if (off_board(fromX))
3808 int c = (BlackOnMove(forwardMostMove) ? 0 : 1);
3809 int piece = PieceOfCatched(c, fromX, fromY, currentMove);
3811 if (piece == no_piece)
3818 if (updateRemotePlayer
3819 && (BlackOnMove(forwardMostMove) == fromRemotePlayer))
3821 DisplayMessage("do not drop opponent pieces",
3827 fromX = fromY = piece + 81;
3829 move_type = (BlackOnMove(forwardMostMove)
3830 ? BlackDrop : WhiteDrop);
3831 MakeMove(&move_type, fromX, fromY, to_x, to_y);
3834 if (updateRemotePlayer)
3835 BlinkSquare(to_y, to_x, boards[currentMove][to_y][to_x]);
3838 FinishUserMove(move_type, to_x, to_y);
3842 else if (off_board(to_x))
3851 from_piece = boards[currentMove][fromY][fromX];
3853 if ((from_piece != EmptySquare)
3854 && updateRemotePlayer
3855 && ((from_piece < WhitePawn) == fromRemotePlayer))
3857 DisplayMessage("do not move opponent pieces",
3863 if (PromotionPossible(fromY, to_y, from_piece))
3865 PromotionPopUp(from_piece, to_x, to_y, fromRemotePlayer);
3869 move_type = NormalMove;
3870 MakeMove(&move_type, fromX, fromY, to_x, to_y);
3873 if (updateRemotePlayer)
3874 BlinkSquare(to_y, to_x, boards[currentMove][to_y][to_x]);
3877 FinishUserMove(move_type, to_x, to_y);
3887 FinishUserMove(ShogiMove move_type, int to_x, int to_y)
3889 char user_move[MSG_SIZ];
3891 /* output move for gnushogi */
3894 case BlackPromotion:
3895 case WhitePromotion:
3896 sprintf(user_move, "%c%c%c%c+\n",
3897 '9' - fromX, 'i' - fromY, '9' - to_x, 'i' - to_y);
3902 sprintf(user_move, "%c*%c%c\n",
3903 catchedIndexToChar[fromX - 81], '9' - to_x, 'i' - to_y);
3907 sprintf(user_move, "%c%c%c%c\n",
3908 '9' - fromX, 'i' - fromY, '9' - to_x, 'i' - to_y);
3912 fprintf(stderr, "%s: internal error; bad move_type\n",
3913 (char *)programName);
3917 Attention(firstProgramPID);
3920 SendTimeRemaining(toFirstProgFP);
3922 SendToProgram(user_move, toFirstProgFP);
3923 strcpy(moveList[currentMove - 1], user_move);
3927 if (gameMode == PauseGame)
3929 /* a user move restarts a paused game*/
3930 PauseProc(NULL, NULL, NULL, NULL);
3938 case BeginningOfGame:
3939 if (localPlayer.appData.noShogiProgram)
3940 lastGameMode = gameMode = ForceMoves;
3942 lastGameMode = gameMode = MachinePlaysWhite;
3947 case MachinePlaysWhite:
3948 case MachinePlaysBlack:
3957 /* Simple parser for moves from gnushogi. */
3959 ParseMachineMove(char *machine_move, ShogiMove *move_type,
3960 int *from_x, int *from_y, int *to_x, int *to_y)
3962 #define no_digit(c) (c < '0' || c > '9')
3964 if (no_digit(machine_move[0]))
3966 switch (machine_move[0])
4005 *to_x = '9' - machine_move[2];
4006 *to_y = 'i' - machine_move[3];
4010 *from_x = '9' - machine_move[0] ;
4011 *from_y = 'i' - machine_move[1];
4012 *to_x = '9' - machine_move[2];
4013 *to_y = 'i' - machine_move[3];
4015 switch (machine_move[4])
4018 *move_type = (BlackOnMove(forwardMostMove)
4019 ? BlackPromotion : WhitePromotion);
4023 *move_type = NormalMove;
4034 SkipString(char **mpr)
4036 while (**mpr == ' ')
4039 while ((**mpr != ' ') && (**mpr != NULLCHAR) && (**mpr != '\n'))
4042 while (**mpr == ' ')
4050 HandleMachineMove(char *message, FILE *fp)
4052 char machine_move[MSG_SIZ], buf1[MSG_SIZ], buf2[MSG_SIZ];
4053 int from_x, from_y, to_x, to_y;
4054 ShogiMove move_type;
4058 long time_remaining;
4061 maybeThinking = False;
4063 if (strncmp(message, "warning:", 8) == 0)
4065 DisplayMessage(message, False);
4067 if (updateRemotePlayer)
4068 DisplayMessage(message, True);
4074 * If shogi program startup fails, exit with an error message.
4075 * Attempts to recover here are futile.
4078 if ((strstr(message, "unknown host") != NULL)
4079 || (strstr(message, "No remote directory") != NULL)
4080 || (strstr(message, "not found") != NULL)
4081 || (strstr(message, "No such file") != NULL)
4082 || (strstr(message, "Permission denied") != NULL))
4085 "%s: failed to start shogi program %s on %s: %s\n",
4087 ((fp == fromFirstProgFP)
4088 ? localPlayer.appData.firstShogiProgram
4089 : localPlayer.appData.secondShogiProgram),
4090 ((fp == fromFirstProgFP)
4091 ? localPlayer.appData.firstHost
4092 : localPlayer.appData.secondHost),
4094 ShutdownShogiPrograms(message);
4099 * If the move is illegal, cancel it and redraw the board.
4102 if (strncmp(message, "Illegal move", 12) == 0)
4104 if (fp == fromFirstProgFP && firstSendTime == 2)
4106 /* First program doesn't have the "time" command */
4110 else if (fp == fromSecondProgFP && secondSendTime == 2)
4112 /* Second program doesn't have the "time" command */
4117 if (forwardMostMove <= backwardMostMove)
4120 if (gameMode == PauseGame)
4121 PauseProc(NULL, NULL, NULL, NULL);
4123 if (gameMode == PlayFromGameFile)
4125 /* Stop reading this game file */
4126 gameMode = ForceMoves;
4130 currentMove = --forwardMostMove;
4132 if ((gameMode == PlayFromGameFile)
4133 || (gameMode == ForceMoves))
4134 DisplayClocks(ReDisplayTimers);
4136 DisplayClocks(SwitchTimers);
4138 sprintf(buf1, "Illegal move: %s", parseList[currentMove]);
4139 DisplayMessage(buf1, False);
4141 if (updateRemotePlayer)
4142 DisplayMessage(buf1, True);
4146 * Disable blinking of the target square.
4151 /* If BlinkCount is even, the piece is currently displayed. */
4152 if (!(BlinkCount & 1))
4153 DrawSquare (BlinkRow, BlinkCol, EmptySquare);
4155 /* BlinkCount = 0 will force the next blink timeout
4161 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
4163 XSync(localPlayer.xDisplay, False);
4165 if (updateRemotePlayer)
4166 XSync(remotePlayer.xDisplay, False);
4171 if (strstr(message, "GNU Shogi") != NULL)
4173 at_least_gnushogi_1_2p03 = True;
4177 if (strncmp(message, "Hint:", 5) == 0)
4180 sscanf(message, "Hint: %s", machine_move);
4181 ParseMachineMove(machine_move, &move_type,
4182 &from_x, &from_y, &to_x, &to_y);
4184 if (move_type == WhitePromotion || move_type == BlackPromotion)
4187 promoPiece = NULLCHAR;
4189 move_type = MakeAlg(from_x, from_y, to_x, to_y, promoPiece,
4191 sprintf(buf2, "Hint: %s", buf1);
4192 DisplayMessage(buf2, False);
4194 if (updateRemotePlayer)
4195 DisplayMessage(buf2, True);
4200 if (strncmp(message, "Clocks:", 7) == 0)
4202 sscanf(message, "Clocks: %ld %ld",
4203 &blackTimeRemaining, &whiteTimeRemaining);
4204 DisplayClocks(ReDisplayTimers);
4213 if (strncmp(message, "Black", 5) == 0)
4215 ShutdownShogiPrograms("Black wins");
4218 else if (strncmp(message, "White", 5) == 0)
4220 ShutdownShogiPrograms("White wins");
4223 else if (strncmp(message, "Repetition", 10) == 0)
4225 ShutdownShogiPrograms("Repetition");
4228 else if (strncmp(message, "opponent mates!", 15) == 0)
4230 switch ((gameMode == PauseGame) ? pausePreviousMode : gameMode)
4232 case MachinePlaysWhite:
4233 ShutdownShogiPrograms("Black wins");
4236 case MachinePlaysBlack:
4237 ShutdownShogiPrograms("White wins");
4240 case TwoMachinesPlay:
4241 ShutdownShogiPrograms((fp == fromFirstProgFP)
4242 ? "Black wins" : "White wins");
4252 else if (strncmp(message, "computer mates!", 15) == 0)
4254 switch ((gameMode == PauseGame) ? pausePreviousMode : gameMode)
4256 case MachinePlaysWhite:
4257 ShutdownShogiPrograms("White wins");
4260 case MachinePlaysBlack:
4261 ShutdownShogiPrograms("Black wins");
4264 case TwoMachinesPlay:
4265 ShutdownShogiPrograms((fp == fromFirstProgFP)
4266 ? "White wins" : "Black wins");
4276 else if (strncmp(message, "Draw", 4) == 0)
4278 ShutdownShogiPrograms("Draw");
4283 * normal machine reply move
4285 maybeThinking = True;
4287 if (strstr(message, "...") != NULL)
4289 sscanf(message, "%s %s %s", buf1, buf2, machine_move);
4293 SkipString(&mpr); /* skip move number */
4294 SkipString(&mpr); /* skip ... */
4295 SkipString(&mpr); /* skip move */
4297 if ((gameMode != TwoMachinesPlay) && (gameMode != ForceMoves)
4298 && ((*mpr == '-') || ((*mpr >= '0') && (*mpr <= '9'))))
4300 /* synchronize with shogi program clock */
4301 sscanf(mpr, "%ld", &time_remaining);
4305 printf("from '%s' synchronize %s clock %ld\n",
4307 (BlackOnMove(forwardMostMove)
4313 if (BlackOnMove(forwardMostMove))
4314 blackTimeRemaining = time_remaining;
4316 whiteTimeRemaining = time_remaining;
4320 if (machine_move[0] == NULLCHAR)
4328 if (strstr(message, "time") == NULL)
4330 /* remaining time will be determined from move */
4331 SkipString(&mpr); /* skip move number */
4332 SkipString(&mpr); /* skip move */
4335 if ((gameMode != TwoMachinesPlay) && (gameMode != ForceMoves)
4336 && ((*mpr == '-') || ((*mpr >= '0') && (*mpr <= '9'))))
4338 /* synchronize with shogi program clock */
4339 sscanf(mpr, "%ld", &time_remaining);
4343 printf("from '%s' synchronize %s clock %ld\n",
4345 ((!BlackOnMove(forwardMostMove))
4346 ? "Black's" : "White's"),
4350 if (!BlackOnMove(forwardMostMove))
4351 blackTimeRemaining = time_remaining;
4353 whiteTimeRemaining = time_remaining;
4359 printf("ignore noise: '%s'\n", message);
4361 return; /* ignore noise */
4364 strcpy(moveList[forwardMostMove], machine_move);
4366 ParseMachineMove(machine_move, &move_type, &from_x, &from_y,
4369 if (gameMode != PauseGame)
4370 currentMove = forwardMostMove; /* display latest move */
4372 MakeMove(&move_type, from_x, from_y, to_x, to_y);
4375 if (gameMode != TwoMachinesPlay)
4376 BlinkSquare(to_y, to_x, boards[currentMove][to_y][to_x]);
4379 if ((gameMode != PauseGame) && localPlayer.appData.ringBellAfterMoves)
4380 putc(BELLCHAR, stderr);
4382 if ((gameMode == TwoMachinesPlay)
4383 || ((gameMode == PauseGame)
4384 && (pausePreviousMode == TwoMachinesPlay)))
4386 strcat(machine_move, "\n");
4388 if (BlackOnMove(forwardMostMove))
4390 Attention(secondProgramPID);
4393 SendTimeRemaining(toSecondProgFP);
4395 SendToProgram(machine_move, toSecondProgFP);
4400 SendToProgram(localPlayer.appData.blackString,
4406 Attention(firstProgramPID);
4409 SendTimeRemaining(toFirstProgFP);
4411 SendToProgram(machine_move, toFirstProgFP);
4416 SendToProgram(localPlayer.appData.blackString,
4431 if (!ReadGameFileProc())
4434 if (matchMode == MatchOpening)
4438 = XtAppAddTimeOut(appContext,
4439 (int)(1000 * localPlayer.appData.timeDelay),
4440 (XtTimerCallbackProc) ReadGameFile, NULL);
4448 * FIXME: there is a naming inconsistency: here ReadGameFileProc() is
4449 * called by ReadGameFile() while in other places XXXProc() calls XXX().
4453 ReadGameFileProc(void)
4455 ShogiMove move_type;
4456 char move[MSG_SIZ], buf[MSG_SIZ];
4458 if (gameFileFP == NULL)
4461 if (gameMode == PauseGame)
4464 if (gameMode != PlayFromGameFile)
4473 XtPopdown(commentShell);
4474 XtDestroyWidget(commentShell);
4478 fgets(move, MSG_SIZ, gameFileFP);
4479 move[strlen(move) - 1] = NULLCHAR;
4480 sprintf(buf, "# %s game file", programName);
4482 if (strncmp(move, buf, strlen(buf)))
4484 strcat(move, ": no xshogi game file");
4485 DisplayMessage(move, False);
4494 move_type = (ShogiMove)0;
4496 lastGameMode = gameMode;
4497 gameMode = ForceMoves;
4499 DisplayMessage("End of game file", False);
4501 if (readGameXID != 0)
4503 XtRemoveTimeOut(readGameXID);
4517 * Apply a move to the given board. Oddity: move_type is ignored on input
4518 * unless the move is seen to be a pawn promotion, in which case move_type
4519 * tells us what to promote to.
4523 ApplyMove(ShogiMove *move_type, int from_x, int from_y,
4524 int to_x, int to_y, int currentMove)
4526 ShogiSquare piece, cpiece;
4533 c = (BlackOnMove(currentMove) ? 1 : 0);
4534 cpiece = catchedIndexToPiece[c][i];
4535 boards[currentMove][to_y][to_x] = cpiece;
4536 catches[currentMove][c][i]--;
4538 else if (PromotionPossible(from_y, to_y,
4539 piece = boards[currentMove][from_y][from_x]))
4541 cpiece = boards[currentMove][to_y][to_x];
4543 if (cpiece != EmptySquare)
4545 i = pieceToCatchedIndex[cpiece];
4546 c = (cpiece < WhitePawn);
4547 catches[currentMove][c][i]++;
4550 if (*move_type == NormalMove)
4552 boards[currentMove][to_y][to_x] = piece;
4556 boards[currentMove][to_y][to_x] = piece = pieceToPromoted[piece];
4560 boards[currentMove][from_y][from_x] = EmptySquare;
4564 ShogiSquare piece = boards[currentMove][to_y][to_x];
4566 if (piece != EmptySquare)
4568 i = pieceToCatchedIndex[piece];
4569 c = (piece < WhitePawn);
4570 catches[currentMove][c][i]++;
4573 *move_type = NormalMove;
4574 boards[currentMove][to_y][to_x] =
4575 boards[currentMove][from_y][from_x];
4576 boards[currentMove][from_y][from_x] = EmptySquare;
4584 * MakeMove() displays moves. If they are illegal, GNU shogi will detect
4585 * this and send an Illegal move message. XShogi will then retract the move.
4586 * The clockMode False case is tricky because it displays the player on move.
4590 MakeMove(ShogiMove *move_type, int from_x, int from_y, int to_x, int to_y)
4592 char message[MSG_SIZ], movestr[MSG_SIZ];
4593 char promoPiece = NULLCHAR;
4597 CopyBoard(boards[forwardMostMove], boards[forwardMostMove - 1]);
4598 CopyCatches(catches[forwardMostMove], catches[forwardMostMove - 1]);
4600 ApplyMove(move_type, from_x, from_y, to_x, to_y, forwardMostMove);
4602 endMessage[0] = NULLCHAR;
4604 timeRemaining[0][forwardMostMove] = blackTimeRemaining;
4605 timeRemaining[1][forwardMostMove] = whiteTimeRemaining;
4607 if ((gameMode == PauseGame) && (pausePreviousMode != PlayFromGameFile))
4610 currentMove = forwardMostMove;
4612 if (gameMode == PlayFromGameFile)
4614 sprintf(message, "%d. %s%s",
4615 ((currentMove + 1) / 2),
4616 (BlackOnMove(currentMove) ? "... " : ""),
4618 strcpy(parseList[currentMove - 1], currentMoveString);
4622 if ((*move_type == WhitePromotion) || (*move_type == BlackPromotion))
4625 promoPiece = NULLCHAR;
4627 MakeAlg(from_x, from_y, to_x, to_y, promoPiece,
4628 currentMove - 1, movestr);
4629 sprintf(message, "%d. %s%s",
4630 ((currentMove + 1) / 2),
4631 (BlackOnMove(currentMove) ? "... " : ""),
4633 strcpy(parseList[currentMove - 1], movestr);
4636 DisplayMessage(message, False);
4638 if ((gameMode == PlayFromGameFile) || (gameMode == ForceMoves)
4639 || ((gameMode == PauseGame)
4640 && (pausePreviousMode == PlayFromGameFile)))
4642 DisplayClocks(ReDisplayTimers);
4646 DisplayClocks(SwitchTimers);
4649 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
4651 XSync(localPlayer.xDisplay, False);
4653 if (updateRemotePlayer)
4655 DisplayMessage(message, True);
4656 XSync(remotePlayer.xDisplay, False);
4664 InitShogiProgram(char *host_name, char *program_name, int *pid,
4665 FILE **to, FILE **from, XtIntervalId *xid, int *sendTime)
4669 int to_prog[2], from_prog[2];
4670 FILE *from_fp, *to_fp;
4674 if (localPlayer.appData.noShogiProgram)
4677 signal(SIGPIPE, CatchPipeSignal);
4681 if ((*pid = fork()) == 0)
4683 signal(SIGPIPE, CatchPipeSignal);
4685 dup2(to_prog[0], 0);
4686 dup2(from_prog[1], 1);
4689 close(from_prog[0]);
4690 close(from_prog[1]);
4691 dup2(1, fileno(stderr)); /* force stderr to the pipe */
4693 if (localPlayer.appData.searchTime != NULL)
4695 sprintf(arg_buf, "%d", searchTime);
4697 arg2 = (char *)NULL;
4699 else if (localPlayer.appData.searchDepth > 0)
4701 sprintf(arg_buf, "%d", localPlayer.appData.searchDepth);
4707 sprintf(arg_buf, "%d", localPlayer.appData.movesPerSession);
4709 arg2 = localPlayer.appData.timeControl;
4712 if (strcmp(host_name, "localhost") == 0)
4714 execlp(program_name, program_name, arg1, arg2,
4719 execlp(localPlayer.appData.remoteShell,
4720 localPlayer.appData.remoteShell,
4721 host_name, program_name, arg1, arg2,
4725 perror(program_name);
4730 close(from_prog[1]);
4732 *from = from_fp = fdopen(from_prog[0], "r");
4733 *to = to_fp = fdopen(to_prog[1], "w");
4734 setbuf(from_fp, NULL);
4735 setbuf(to_fp, NULL);
4737 ReceiveFromProgram(from_fp, &dummy_source, &dummy_id); /* "GNU Shogi"*/
4739 if (!at_least_gnushogi_1_2p03)
4741 fprintf(stderr, "you must have at least gnushogi-1.2p03\n");
4748 *xid = XtAppAddInput(appContext, fileno(from_fp),
4749 (XtPointer)XtInputReadMask,
4750 (XtInputCallbackProc)ReceiveFromProgram,
4751 (XtPointer)from_fp);
4753 SendToProgram(localPlayer.appData.initString, *to);
4755 if (localPlayer.appData.gameIn)
4756 SendToProgram("gamein\n", *to);
4758 SendSearchDepth(*to);
4762 /* Does program have "time" command? */
4765 sprintf(buf, "time %ld\n", blackTimeRemaining / 10);
4766 SendToProgram(buf, to_fp);
4767 ReceiveFromProgram(from_fp, &dummy_source, &dummy_id);
4771 *sendTime = 1; /* yes! */
4772 sprintf(buf, "otime %ld\n", whiteTimeRemaining / 10);
4773 SendToProgram(buf, to_fp);
4774 ReceiveFromProgram(from_fp, &dummy_source, &dummy_id);
4783 ShutdownShogiPrograms(char *why)
4785 lastGameMode = gameMode;
4786 gameMode = EndOfGame;
4788 CopyBoard(boards[currentMove + 1], boards[currentMove]);
4789 CopyCatches(catches[currentMove + 1], catches[currentMove]);
4790 strncpy(parseList[currentMove], why, MOVE_LEN);
4791 parseList[currentMove][MOVE_LEN - 1] = NULLCHAR;
4793 DisplayMessage(why, False);
4795 if (readGameXID != 0)
4796 XtRemoveTimeOut(readGameXID);
4800 if (firstProgramPID != 0)
4802 fclose(fromFirstProgFP);
4803 fclose(toFirstProgFP);
4804 fromFirstProgFP = toFirstProgFP = NULL;
4806 if (kill(firstProgramPID, SIGTERM) == 0)
4810 firstProgramPID = 0;
4812 if (firstProgramXID != 0)
4813 XtRemoveInput(firstProgramXID);
4815 firstProgramXID = 0;
4817 if (secondProgramPID != 0)
4819 fclose(fromSecondProgFP);
4820 fclose(toSecondProgFP);
4821 fromSecondProgFP = toSecondProgFP = NULL;
4823 if (kill(secondProgramPID, SIGTERM) == 0)
4827 secondProgramPID = 0;
4829 if (secondProgramXID != 0)
4830 XtRemoveInput(secondProgramXID);
4832 secondProgramXID = 0;
4834 DisplayClocks(StopTimers);
4836 if (matchMode != MatchFalse)
4838 if (localPlayer.appData.saveGameFile[0] != NULLCHAR)
4839 SaveGame(localPlayer.appData.saveGameFile);
4849 CommentPopUp(char *label)
4853 Dimension bw_width, pw_width;
4857 XtPopdown(commentShell);
4858 XtDestroyWidget(commentShell);
4862 DisplayMessage("Comment", False);
4864 XtSetArg(args[0], XtNwidth, &bw_width);
4865 XtGetValues(localPlayer.formWidget, args, 1);
4867 XtSetArg(args[0], XtNresizable, True);
4868 XtSetArg(args[1], XtNwidth, bw_width - 8);
4870 commentShell = XtCreatePopupShell("Comment",
4871 transientShellWidgetClass,
4872 localPlayer.commandsWidget, args, 2);
4874 XtSetArg(args[0], XtNlabel, label);
4876 (void)XtCreateManagedWidget("commentLabel", labelWidgetClass,
4877 commentShell, args, 1);
4879 XtRealizeWidget(commentShell);
4881 XtSetArg(args[0], XtNwidth, &pw_width);
4882 XtGetValues(commentShell, args, 1);
4884 XtTranslateCoords(localPlayer.shellWidget,
4885 (bw_width - pw_width) / 2, -50, &x, &y);
4887 XtSetArg(args[0], XtNx, x);
4888 XtSetArg(args[1], XtNy, y);
4889 XtSetValues(commentShell, args, 2);
4891 XtPopup(commentShell, XtGrabNone);
4899 FileNamePopUp(char *label, Boolean (*proc) (char *))
4902 Widget popup, dialog;
4904 Dimension bw_width, pw_width;
4908 XtSetArg(args[0], XtNwidth, &bw_width);
4909 XtGetValues(localPlayer.boardWidget, args, 1);
4911 XtSetArg(args[0], XtNresizable, True);
4912 XtSetArg(args[1], XtNwidth, DIALOG_SIZE);
4914 popup = XtCreatePopupShell("File Name Prompt",
4915 transientShellWidgetClass,
4916 localPlayer.commandsWidget, args, 2);
4918 XtSetArg(args[0], XtNlabel, label);
4919 XtSetArg(args[1], XtNvalue, "");
4921 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
4924 XawDialogAddButton(dialog, "ok", FileNameCallback, (XtPointer) dialog);
4925 XawDialogAddButton(dialog, "cancel", FileNameCallback,
4926 (XtPointer) dialog);
4928 XtRealizeWidget(popup);
4930 XtSetArg(args[0], XtNwidth, &pw_width);
4931 XtGetValues(popup, args, 1);
4933 XtTranslateCoords(localPlayer.boardWidget,
4934 (bw_width - pw_width) / 2, 10, &x, &y);
4936 XtSetArg(args[0], XtNx, x);
4937 XtSetArg(args[1], XtNy, y);
4938 XtSetValues(popup, args, 2);
4940 XtPopup(popup, XtGrabExclusive);
4943 XtSetKeyboardFocus(localPlayer.shellWidget, popup);
4950 FileNameCallback(Widget w, XtPointer client_data, XtPointer call_data)
4955 XtSetArg(args[0], XtNlabel, &name);
4956 XtGetValues(w, args, 1);
4958 if (strcmp(name, "cancel") == 0)
4960 XtPopdown(w = XtParent(XtParent(w)));
4967 FileNameAction(w, NULL, NULL, NULL);
4974 FileNameAction(Widget w, XEvent *event, String *prms, Cardinal *nprms)
4979 name = XawDialogGetValueString(w = XtParent(w));
4981 if ((name != NULL) && (*name != NULLCHAR))
4984 XtPopdown(w = XtParent(w));
4987 (*fileProc)(buf); /* I can't see a way not
4988 to use a global here */
4993 XtPopdown(w = XtParent(w));
5003 PromotionPopUp(ShogiSquare piece, int to_x, int to_y, int fromRemotePlayer)
5008 Dimension bw_width, bw_height, pw_width, pw_height;
5010 player = (fromRemotePlayer ? &remotePlayer : &localPlayer);
5016 XtSetArg(args[0], XtNwidth, &bw_width);
5017 XtSetArg(args[1], XtNheight, &bw_height);
5018 XtGetValues(player->boardWidget, args, 2);
5020 XtSetArg(args[0], XtNresizable, True);
5022 player->promotionShell
5023 = XtCreatePopupShell("Promotion",
5024 transientShellWidgetClass,
5025 player->commandsWidget, args, 1);
5027 XtSetArg(args[0], XtNlabel, "Promote piece?");
5028 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5029 player->promotionShell, args, 1);
5031 XawDialogAddButton(dialog, "Yes", PromotionCallback,
5032 (XtPointer) dialog);
5033 XawDialogAddButton(dialog, "No", PromotionCallback,
5034 (XtPointer) dialog);
5035 XawDialogAddButton(dialog, "cancel", PromotionCallback,
5036 (XtPointer) dialog);
5038 XtRealizeWidget(player->promotionShell);
5040 XtSetArg(args[0], XtNwidth, &pw_width);
5041 XtSetArg(args[1], XtNheight, &pw_height);
5042 XtGetValues(player->promotionShell, args, 2);
5044 XtTranslateCoords(player->boardWidget,
5045 ((bw_width - pw_width) / 2),
5047 + player->squareSize / 3
5048 + (((piece == BlackPawn) ^ (player->flipView))
5050 : (6 * (player->squareSize + LINE_GAP)))),
5053 XtSetArg(args[0], XtNx, x);
5054 XtSetArg(args[1], XtNy, y);
5055 XtSetValues(player->promotionShell, args, 2);
5057 XtPopup(player->promotionShell, XtGrabNone);
5059 player->promotionUp = True;
5066 PromotionCallback(Widget w, XtPointer client_data, XtPointer call_data)
5070 ShogiMove move_type;
5071 struct DisplayData *player;
5073 XtSetArg(args[0], XtNlabel, &name);
5074 XtGetValues(w, args, 1);
5076 w = XtParent(XtParent(w));
5077 player = ((w == remotePlayer.promotionShell)
5078 ? &remotePlayer : &localPlayer);
5081 player->promotionUp = False;
5086 if (strcmp(name, "Yes") == 0)
5088 if ((int)pmi.piece < (int)WhitePawn)
5089 move_type = BlackPromotion;
5091 move_type = WhitePromotion;
5093 else if (strcmp(name, "No") == 0)
5095 move_type = NormalMove;
5097 else /* strcmp(name, "cancel") == 0 */
5103 MakeMove(&move_type, fromX, fromY, pmi.to_x, pmi.to_y);
5106 if (updateRemotePlayer)
5108 BlinkSquare(pmi.to_y, pmi.to_x,
5109 boards[currentMove][pmi.to_y][pmi.to_x]);
5113 FinishUserMove(move_type, pmi.to_x, pmi.to_y);
5120 FileModePopUp(char *name)
5125 Dimension bw_width, bw_height, pw_width, pw_height;
5127 struct DisplayData *player = &localPlayer;
5129 strcpy(fmi.name, name);
5131 XtSetArg(args[0], XtNwidth, &bw_width);
5132 XtSetArg(args[1], XtNheight, &bw_height);
5133 XtGetValues(player->boardWidget, args, 2);
5135 XtSetArg(args[0], XtNresizable, True);
5136 player->filemodeShell
5137 = XtCreatePopupShell("FileMode",
5138 transientShellWidgetClass,
5139 player->commandsWidget, args, 1);
5141 XtSetArg(args[0], XtNlabel, "Append to existing file?");
5142 dialog = XtCreateManagedWidget("filemode", dialogWidgetClass,
5143 player->filemodeShell, args, 1);
5145 XawDialogAddButton(dialog, "Yes", FileModeCallback,
5146 (XtPointer) dialog);
5147 XawDialogAddButton(dialog, "No", FileModeCallback,
5148 (XtPointer) dialog);
5149 XawDialogAddButton(dialog, "cancel", FileModeCallback,
5150 (XtPointer) dialog);
5152 XtRealizeWidget(player->filemodeShell);
5154 XtSetArg(args[0], XtNwidth, &pw_width);
5155 XtSetArg(args[1], XtNheight, &pw_height);
5156 XtGetValues(player->filemodeShell, args, 2);
5158 XtTranslateCoords(player->boardWidget, (bw_width - pw_width) / 2,
5159 LINE_GAP + player->squareSize/3 +
5160 (6*(player->squareSize + LINE_GAP)),
5163 XtSetArg(args[0], XtNx, x);
5164 XtSetArg(args[1], XtNy, y);
5165 XtSetValues(player->filemodeShell, args, 2);
5167 XtPopup(player->filemodeShell, XtGrabNone);
5176 FileModeCallback(Widget w, XtPointer client_data, XtPointer call_data)
5181 XtSetArg(args[0], XtNlabel, &name);
5182 XtGetValues(w, args, 1);
5184 XtPopdown(w = XtParent(XtParent(w)));
5187 if (strcmp(name, "Yes") == 0)
5189 strcpy(fmi.mode, "a");
5191 else if (strcmp(name, "No") == 0)
5193 strcpy(fmi.mode, "w");
5195 else /* strcmp(name, "cancel") == 0 */
5201 XtPopdown(localPlayer.filemodeShell);
5202 XtDestroyWidget(localPlayer.filemodeShell);
5213 SelectCommand(Widget w, XtPointer client_data, XtPointer call_data)
5215 Cardinal fromRemotePlayer = (Cardinal)client_data;
5217 XawListReturnStruct *list_return = XawListShowCurrent(w);
5219 player = fromRemotePlayer ? &remotePlayer : &localPlayer;
5223 if (player->promotionUp)
5225 XtPopdown(player->promotionShell);
5226 XtDestroyWidget(player->promotionShell);
5227 player->promotionUp = False;
5230 (*buttonProcs[list_return->list_index])
5231 (w, NULL, NULL, &fromRemotePlayer);
5241 HighlightProcButton(XtActionProc proc)
5247 XawListUnhighlight(localPlayer.commandsWidget);
5249 if (updateRemotePlayer)
5250 XawListUnhighlight(remotePlayer.commandsWidget);
5257 if (buttonProcs[i] == NULL)
5259 XawListUnhighlight(localPlayer.commandsWidget);
5261 if (updateRemotePlayer)
5262 XawListUnhighlight(remotePlayer.commandsWidget);
5267 if (buttonProcs[i] == proc)
5269 XawListHighlight(localPlayer.commandsWidget, i);
5271 if (updateRemotePlayer)
5272 XawListHighlight(remotePlayer.commandsWidget, i);
5289 case BeginningOfGame:
5290 if (localPlayer.appData.noShogiProgram)
5291 HighlightProcButton(ForceProc);
5293 HighlightProcButton(MachineBlackProc);
5297 case MachinePlaysBlack:
5298 HighlightProcButton(MachineBlackProc);
5301 case MachinePlaysWhite:
5302 HighlightProcButton(MachineWhiteProc);
5305 case TwoMachinesPlay:
5306 HighlightProcButton(TwoMachinesProc);
5310 HighlightProcButton(ForceProc);
5314 case PlayFromGameFile:
5315 HighlightProcButton(LoadGameProc);
5319 HighlightProcButton(PauseProc);
5323 HighlightProcButton(EditPositionProc);
5328 HighlightProcButton(NULL);
5341 QuitRemotePlayerProc(void)
5343 /* This should be modified... */
5344 XCloseDisplay(remotePlayer.xDisplay);
5345 /* XtDestroyWidget(remotePlayer.shellWidget); */
5346 updateRemotePlayer = False;
5347 DisplayMessage("Remote player has pressed Quit", False);
5354 QuitProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5356 if (updateRemotePlayer)
5357 QuitRemotePlayerProc();
5359 ShutdownShogiPrograms("Quitting");
5366 LoadGameProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5368 int fromRemotePlayer = *nprms;
5370 if (fromRemotePlayer)
5372 DisplayMessage("only opponent may load game", fromRemotePlayer);
5376 if (gameMode != BeginningOfGame)
5378 DisplayMessage("Press Reset first", False);
5382 if (localPlayer.appData.loadGameFile == NULL)
5383 FileNamePopUp("Game file name?", LoadGame);
5385 (void) LoadGame(localPlayer.appData.loadGameFile);
5392 LoadGame(char *name)
5396 if (gameMode != BeginningOfGame)
5398 DisplayMessage("Press Reset first", False);
5402 if (localPlayer.appData.loadGameFile != name)
5404 if (localPlayer.appData.loadGameFile)
5405 XtFree(localPlayer.appData.loadGameFile);
5407 localPlayer.appData.loadGameFile = XtMalloc(strlen(name) + 1);
5408 strcpy(localPlayer.appData.loadGameFile, name);
5411 if ((gameFileFP = fopen(name, "r")) == NULL)
5413 sprintf(buf, "Can't open %s", name);
5414 DisplayMessage(buf, False);
5415 XtFree(localPlayer.appData.loadGameFile);
5416 localPlayer.appData.loadGameFile = NULL;
5420 lastGameMode = gameMode = PlayFromGameFile;
5423 DisplayClocks(StopTimers);
5425 if (firstProgramXID == 0)
5427 InitShogiProgram(localPlayer.appData.firstHost,
5428 localPlayer.appData.firstShogiProgram,
5429 &firstProgramPID, &toFirstProgFP,
5430 &fromFirstProgFP, &firstProgramXID,
5434 SendToProgram(localPlayer.appData.initString, toFirstProgFP);
5435 SendSearchDepth(toFirstProgFP);
5436 SendToProgram("force\n", toFirstProgFP);
5438 currentMove = forwardMostMove = backwardMostMove = 0;
5449 * Restart the shogi program and feed it all the moves made so far.
5450 * Used when the user wants to back up from end of game, when gnushogi
5451 * has already exited. Assumes gameMode == EndOfGame.
5455 ResurrectShogiProgram(void)
5460 if (currentMove > 0)
5461 currentMove--; /* delete "Black wins" or the like */
5463 InitShogiProgram(localPlayer.appData.firstHost,
5464 localPlayer.appData.firstShogiProgram,
5465 &firstProgramPID, &toFirstProgFP, &fromFirstProgFP,
5466 &firstProgramXID, &firstSendTime);
5468 SendToProgram(localPlayer.appData.initString, toFirstProgFP);
5469 SendSearchDepth(toFirstProgFP);
5470 SendToProgram("force\n", toFirstProgFP);
5471 gameMode = lastGameMode = ForceMoves;
5474 i = (whitePlaysFirst ? 1 : 0);
5476 if (startedFromSetupPosition)
5477 SendBoard(toFirstProgFP, boards[i], catches[i]);
5479 for (; i < currentMove; i++)
5481 strcpy(buf, moveList[i]);
5482 SendToProgram(buf, toFirstProgFP);
5487 /* can't tell gnushogi what its clock should read,
5488 so we bow to its notion. */
5489 DisplayClocks(ResetTimers);
5490 timeRemaining[0][currentMove] = blackTimeRemaining;
5491 timeRemaining[1][currentMove] = whiteTimeRemaining;
5499 MachineWhiteProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5501 int fromRemotePlayer = *nprms;
5503 if (updateRemotePlayer)
5505 DisplayMessage("no machine moves in challenge mode",
5511 if (gameMode == PauseGame)
5512 PauseProc(w, event, prms, nprms);
5514 if (gameMode == PlayFromGameFile)
5515 ForceProc(w, event, prms, nprms);
5517 if (gameMode == EditPosition)
5520 if ((gameMode == EndOfGame)
5521 || (gameMode == PlayFromGameFile)
5522 || (gameMode == TwoMachinesPlay)
5523 || localPlayer.appData.noShogiProgram
5524 || (gameMode == MachinePlaysWhite))
5529 if (BlackOnMove((gameMode == ForceMoves)
5533 DisplayMessage("It is not White's turn", False);
5537 if (gameMode == ForceMoves)
5538 forwardMostMove = currentMove;
5540 lastGameMode = gameMode = MachinePlaysWhite;
5542 SendToProgram(localPlayer.appData.whiteString, toFirstProgFP);
5543 DisplayClocks(StartTimers);
5550 MachineBlackProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5552 int fromRemotePlayer = *nprms;
5554 if (updateRemotePlayer)
5556 DisplayMessage("no machine moves in challenge mode",
5561 if (gameMode == PauseGame)
5562 PauseProc(w, event, prms, nprms);
5564 if (gameMode == PlayFromGameFile)
5565 ForceProc(w, event, prms, nprms);
5567 if (gameMode == EditPosition)
5570 if ((gameMode == EndOfGame)
5571 || (gameMode == PlayFromGameFile)
5572 || (gameMode == TwoMachinesPlay)
5573 || localPlayer.appData.noShogiProgram
5574 || (gameMode == MachinePlaysBlack))
5579 if (!BlackOnMove((gameMode == ForceMoves)
5583 DisplayMessage("It is not Black's turn", False);
5587 if (gameMode == ForceMoves)
5588 forwardMostMove = currentMove;
5590 lastGameMode = gameMode = MachinePlaysBlack;
5592 SendToProgram(localPlayer.appData.blackString, toFirstProgFP);
5593 DisplayClocks(StartTimers);
5600 ForwardProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5606 int fromRemotePlayer = *nprms;
5608 if (updateRemotePlayer)
5610 DisplayMessage("Forward button disabled", fromRemotePlayer);
5614 if ((gameMode == EndOfGame) || (gameMode == EditPosition))
5617 if (gameMode == PlayFromGameFile)
5618 PauseProc(w, event, prms, nprms);
5620 if (currentMove >= forwardMostMove)
5629 XQueryPointer(localPlayer.xDisplay, localPlayer.xBoardWindow,
5630 &root, &child, &root_x, &root_y,
5631 &win_x, &win_y, &state);
5635 state = event->xkey.state;
5638 if (state & ShiftMask)
5639 target = forwardMostMove;
5641 target = currentMove + 1;
5643 if (gameMode == ForceMoves)
5645 while (currentMove < target)
5647 strcpy(buf, moveList[currentMove++]);
5648 SendToProgram(buf, toFirstProgFP);
5653 currentMove = target;
5656 if (gameMode == ForceMoves)
5658 blackTimeRemaining = timeRemaining[0][currentMove];
5659 whiteTimeRemaining = timeRemaining[1][currentMove];
5662 DisplayClocks(ReDisplayTimers);
5663 DisplayMove(currentMove - 1);
5664 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
5675 if (updateRemotePlayer)
5678 if (localPlayer.appData.loadGameFile)
5679 XtFree(localPlayer.appData.loadGameFile);
5681 if (localPlayer.appData.loadPositionFile)
5682 XtFree(localPlayer.appData.loadPositionFile);
5684 localPlayer.appData.loadGameFile
5685 = localPlayer.appData.loadPositionFile = NULL;
5688 if (gameFileFP != NULL)
5699 ResetChallenge(void)
5703 if (localPlayer.appData.challengeDisplay)
5704 XtFree(localPlayer.appData.challengeDisplay);
5706 localPlayer.appData.challengeDisplay = NULL;
5714 ResetProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5716 int fromRemotePlayer = *nprms;
5718 if (fromRemotePlayer)
5720 DisplayMessage("only your opponent may reset the game",
5732 Reset(int redraw) /* Boolean */
5737 localPlayer.flipView = False;
5738 remotePlayer.flipView = True;
5739 startedFromSetupPosition = whitePlaysFirst = False;
5740 matchMode = MatchFalse;
5742 blackFlag = whiteFlag = False;
5743 maybeThinking = False;
5745 endMessage[0] = NULLCHAR;
5747 ShutdownShogiPrograms("");
5748 lastGameMode = gameMode = BeginningOfGame;
5750 InitPosition(redraw);
5751 DisplayClocks(ResetTimers);
5752 timeRemaining[0][0] = blackTimeRemaining;
5753 timeRemaining[1][0] = whiteTimeRemaining;
5754 InitShogiProgram(localPlayer.appData.firstHost,
5755 localPlayer.appData.firstShogiProgram,
5756 &firstProgramPID, &toFirstProgFP,
5757 &fromFirstProgFP, &firstProgramXID,
5762 XtPopdown(commentShell);
5763 XtDestroyWidget(commentShell);
5767 if (localPlayer.promotionUp)
5769 XtPopdown(localPlayer.promotionShell);
5770 XtDestroyWidget(localPlayer.promotionShell);
5771 localPlayer.promotionUp = False;
5774 if (updateRemotePlayer && remotePlayer.promotionUp)
5776 XtPopdown(remotePlayer.promotionShell);
5777 XtDestroyWidget(remotePlayer.promotionShell);
5778 remotePlayer.promotionUp = False;
5786 ClearCatches(int (*catches)[8])
5790 for (c = 0; c <= 1; c++)
5791 for (p = 0; p <= 7; p++)
5799 Challenge(char *name)
5804 XrmDatabase database;
5806 if (gameMode != BeginningOfGame)
5808 DisplayMessage("Press Reset first", False);
5812 if (localPlayer.appData.challengeDisplay != name)
5814 if (localPlayer.appData.challengeDisplay)
5815 XtFree(localPlayer.appData.challengeDisplay);
5817 localPlayer.appData.challengeDisplay = XtMalloc(strlen(name) + 1);
5818 strcpy(localPlayer.appData.challengeDisplay, name);
5821 sprintf(buf, "trying to connect to %s.....", name);
5822 DisplayMessage(buf, False);
5827 if ((remotePlayer.xDisplay
5828 = XtOpenDisplay(appContext, name, "XShogi",
5829 "XShogi", 0, 0, &argc, argv)) == NULL)
5831 sprintf(buf, "Can't open display %s", name);
5832 DisplayMessage(buf, False);
5833 XtFree(localPlayer.appData.challengeDisplay);
5834 localPlayer.appData.challengeDisplay = NULL;
5838 DisplayMessage("connected! creating remote window...", False);
5840 remotePlayer.xScreen = DefaultScreen(remotePlayer.xDisplay);
5842 remotePlayer.shellWidget
5843 = XtAppCreateShell(NULL, "XShogi",
5844 applicationShellWidgetClass,
5845 remotePlayer.xDisplay, NULL, 0);
5847 database = XtDatabase(remotePlayer.xDisplay);
5849 XrmParseCommand(&database,
5850 shellOptions, XtNumber(shellOptions),
5851 "XShogi", &argc, argv);
5853 XtGetApplicationResources(remotePlayer.shellWidget,
5854 &remotePlayer.appData, clientResources,
5855 XtNumber(clientResources), NULL, 0);
5857 player = &remotePlayer;
5859 CreatePlayerWindow();
5861 updateRemotePlayer = True;
5863 DisplayName("REMOTE");
5864 DrawPosition(remotePlayer.boardWidget, NULL, NULL, NULL);
5865 DisplayClocks(ReDisplayTimers);
5867 DisplayMessage("ready to play", False);
5868 DisplayMessage("ready to play", True);
5877 ChallengeProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5879 int fromRemotePlayer = *nprms;
5881 if (updateRemotePlayer)
5883 DisplayMessage("you are already in challenge mode",
5888 if (gameMode != BeginningOfGame)
5890 DisplayMessage("Press Reset first", False);
5894 if (localPlayer.appData.challengeDisplay == NULL)
5895 FileNamePopUp("Challenge display?", Challenge);
5897 (void) Challenge(localPlayer.appData.challengeDisplay);
5904 SelectLevel(char *command)
5908 sprintf(buf, "level %s\n", command);
5909 SendToProgram(buf, toFirstProgFP);
5918 SelectLevelProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5920 if ((BlackOnMove(forwardMostMove) && (gameMode == MachinePlaysBlack))
5921 || (!BlackOnMove(forwardMostMove) && (gameMode == MachinePlaysWhite)))
5923 DisplayMessage("Wait until your turn", False);
5927 FileNamePopUp("#moves #minutes", SelectLevel);
5935 MoveNowProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5937 if ((!BlackOnMove(forwardMostMove) && (gameMode == MachinePlaysBlack))
5938 || (BlackOnMove(forwardMostMove) && (gameMode == MachinePlaysWhite)))
5940 DisplayMessage("Wait until machines turn", False);
5944 Attention(firstProgramPID);
5952 LoadPositionProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
5954 int fromRemotePlayer = *nprms;
5956 if (fromRemotePlayer)
5958 DisplayMessage("only opponent may load position", fromRemotePlayer);
5962 if (gameMode != BeginningOfGame)
5964 DisplayMessage("Press Reset first", False);
5968 FileNamePopUp("Position file name?", LoadPosition);
5975 LoadPosition(char *name)
5977 char *p, line[MSG_SIZ], buf[MSG_SIZ];
5978 Board initial_position;
5979 Catched initial_catches;
5983 if (gameMode != BeginningOfGame)
5985 DisplayMessage("Press Reset first", False);
5989 if (localPlayer.appData.loadPositionFile != name)
5991 if (localPlayer.appData.loadPositionFile)
5992 XtFree(localPlayer.appData.loadPositionFile);
5994 localPlayer.appData.loadPositionFile = XtMalloc(strlen(name) + 1);
5995 strcpy(localPlayer.appData.loadPositionFile, name);
5998 if ((fp = fopen(name, "r")) == NULL)
6000 sprintf(buf, "Can't open %s", name);
6001 DisplayMessage(buf, False);
6002 XtFree(localPlayer.appData.loadPositionFile);
6003 localPlayer.appData.loadPositionFile = NULL;
6007 lastGameMode = gameMode = ForceMoves;
6009 startedFromSetupPosition = True;
6011 if (firstProgramXID == 0)
6013 InitShogiProgram(localPlayer.appData.firstHost,
6014 localPlayer.appData.firstShogiProgram,
6015 &firstProgramPID, &toFirstProgFP,
6016 &fromFirstProgFP, &firstProgramXID,
6021 * Check and skip header information in position file.
6024 fgets(line, MSG_SIZ, fp);
6025 line[strlen(line) - 1] = NULLCHAR;
6026 sprintf(buf, "# %s position file", programName);
6028 if (strncmp(line, buf, strlen(buf)))
6030 strcat(line, ": no xshogi position file");
6031 DisplayMessage(line, False);
6036 fgets(line, MSG_SIZ, fp); /* skip opponents */
6038 for (i = BOARD_SIZE - 1; i >= 0; i--)
6040 fgets(line, MSG_SIZ, fp);
6042 for (p = line, j = 0; j < BOARD_SIZE; p++)
6044 int promoted = False; /* CHECKME: is this valid? */
6053 initial_position[i][j++] = CharToPiece(*p, promoted);
6060 for (color = 0; color <= 1; color++)
6062 fscanf(fp, "%i%i%i%i%i%i%i%i\n",
6063 &initial_catches[color][pawn],
6064 &initial_catches[color][lance],
6065 &initial_catches[color][knight],
6066 &initial_catches[color][silver],
6067 &initial_catches[color][gold],
6068 &initial_catches[color][bishop],
6069 &initial_catches[color][rook],
6070 &initial_catches[color][king]);
6074 whitePlaysFirst = False;
6078 fgets(line, MSG_SIZ, fp);
6080 if (strncmp(line, "white", strlen("white")) == 0)
6081 whitePlaysFirst = True;
6086 if (whitePlaysFirst)
6088 CopyBoard(boards[0], initial_position);
6089 CopyCatches(catches[0], initial_catches);
6090 strcpy(moveList[0], " ...\n");
6091 strcpy(parseList[0], " ...\n");
6092 currentMove = forwardMostMove = backwardMostMove = 1;
6093 CopyBoard(boards[1], initial_position);
6094 CopyCatches(catches[1], initial_catches);
6095 SendToProgram("white\n", toFirstProgFP);
6096 SendToProgram("force\n", toFirstProgFP);
6097 SendCurrentBoard(toFirstProgFP);
6098 DisplayMessage("White to play", False);
6102 currentMove = forwardMostMove = backwardMostMove = 0;
6103 CopyBoard(boards[0], initial_position);
6104 CopyCatches(catches[0], initial_catches);
6105 SendCurrentBoard(toFirstProgFP);
6106 SendToProgram("force\n", toFirstProgFP);
6107 DisplayMessage("Black to play", False);
6110 DisplayClocks(ResetTimers);
6111 timeRemaining[0][1] = blackTimeRemaining;
6112 timeRemaining[1][1] = whiteTimeRemaining;
6114 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
6122 EditPositionProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6124 int fromRemotePlayer = *nprms;
6126 if (updateRemotePlayer)
6128 DisplayMessage("Edit button disabled", fromRemotePlayer);
6132 if (gameMode == EditPosition)
6135 ForceProc(w, event, prms, nprms);
6137 if (gameMode != ForceMoves)
6140 DisplayName("<-- Press to set side to play next");
6141 DisplayMessage("Mouse: 1=drag, 2=black, 3=white", False);
6143 lastGameMode = gameMode = EditPosition;
6146 if (currentMove > 0)
6147 CopyBoard(boards[0], boards[currentMove]);
6149 whitePlaysFirst = !BlackOnMove(forwardMostMove);
6150 currentMove = forwardMostMove = backwardMostMove = 0;
6157 EditPositionDone(void)
6159 startedFromSetupPosition = True;
6160 SendToProgram(localPlayer.appData.initString, toFirstProgFP);
6161 SendSearchDepth(toFirstProgFP);
6163 if (whitePlaysFirst)
6165 strcpy(moveList[0], " ...\n");
6166 strcpy(parseList[0], " ...\n");
6167 currentMove = forwardMostMove = backwardMostMove = 1;
6168 CopyBoard(boards[1], boards[0]);
6169 CopyCatches(catches[1], catches[0]);
6170 SendToProgram("force\n", toFirstProgFP);
6171 SendCurrentBoard(toFirstProgFP);
6173 DisplayMessage("White to play", False);
6177 currentMove = forwardMostMove = backwardMostMove = 0;
6178 SendCurrentBoard(toFirstProgFP);
6179 SendToProgram("force\n", toFirstProgFP);
6181 DisplayMessage("Black to play", False);
6184 lastGameMode = gameMode = ForceMoves;
6194 * This function executes when undoing a move.
6195 * FIXME: this function is totally hosed!!!
6209 BackwardProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6214 int fromRemotePlayer = *nprms;
6216 if (updateRemotePlayer)
6218 DisplayMessage("Backward button disabled", fromRemotePlayer);
6223 * Why do we need this here?
6226 ForceProc(w, event, prms, nprms);
6228 if ((currentMove <= backwardMostMove) || (gameMode == EditPosition))
6231 if (gameMode == EndOfGame)
6232 ResurrectShogiProgram();
6234 if (gameMode == PlayFromGameFile)
6235 PauseProc(w, event, prms, nprms);
6244 XQueryPointer(localPlayer.xDisplay, localPlayer.xBoardWindow,
6245 &root, &child, &root_x, &root_y,
6246 &win_x, &win_y, &state);
6250 state = event->xkey.state;
6253 if (state & ShiftMask)
6255 target = backwardMostMove;
6259 target = currentMove - 1;
6262 if (gameMode == ForceMoves)
6264 Attention(firstProgramPID);
6266 while (currentMove > target)
6268 SendToProgram("undo\n", toFirstProgFP);
6274 currentMove = target;
6277 if (gameMode == ForceMoves)
6279 whiteTimeRemaining = timeRemaining[0][currentMove];
6280 blackTimeRemaining = timeRemaining[1][currentMove];
6283 DisplayClocks(ReDisplayTimers);
6284 DisplayMove(currentMove - 1);
6285 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
6292 FlipViewProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6294 struct DisplayData *player = (*nprms ? &remotePlayer : &localPlayer);
6296 player->flipView = !player->flipView;
6297 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
6304 SaveGameProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6308 int fromRemotePlayer = *nprms;
6310 if (fromRemotePlayer)
6312 DisplayMessage("only opponent may save game", fromRemotePlayer);
6318 FileNamePopUp("Filename for saved game?", SaveGame);
6325 SaveGame(char *name)
6328 int i, len, move = 0;
6331 if (!filemodeUp) /* if called via FileModeCallback avoid recursion */
6333 if ((gameFileFP = fopen(name, "r")) == NULL)
6335 strcpy(fmi.mode, "w");
6340 FileModePopUp(name);
6341 return False; /* CHECKME: what should the return value be? */
6345 if ((gameFileFP = fopen(name, fmi.mode)) == NULL)
6347 sprintf(buf, "Can't open %s (mode %s)", name, fmi.mode);
6348 DisplayMessage(buf, False);
6352 tm = time((time_t *) NULL);
6354 fprintf(gameFileFP, "# %s game file -- %s", programName, ctime(&tm));
6355 PrintOpponents(gameFileFP);
6357 for (i = 0; i < currentMove;)
6360 fprintf(gameFileFP, "\n");
6362 fprintf(gameFileFP, "%d. %s ", ++move, parseList[i++]);
6364 if (i >= currentMove)
6366 fprintf(gameFileFP, "\n");
6370 if ((len = strlen(parseList[i])) == 0)
6373 fprintf(gameFileFP, "%s ", parseList[i++]);
6376 fprintf(gameFileFP, "\n");
6388 SwitchProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6390 if (localPlayer.appData.noShogiProgram)
6398 case MachinePlaysBlack:
6399 if (BlackOnMove(forwardMostMove))
6401 DisplayMessage("Wait until your turn", False);
6405 lastGameMode = gameMode = MachinePlaysWhite;
6409 case BeginningOfGame:
6411 case MachinePlaysWhite:
6412 if (!BlackOnMove(forwardMostMove))
6414 DisplayMessage("Wait until your turn", False);
6418 if (forwardMostMove == 0)
6420 MachineBlackProc(w, event, prms, nprms);
6424 lastGameMode = gameMode = MachinePlaysBlack;
6429 Attention(firstProgramPID);
6430 SendToProgram("switch\n", toFirstProgFP);
6437 ForceProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6443 case MachinePlaysBlack:
6444 if (BlackOnMove(forwardMostMove))
6446 DisplayMessage("Wait until your turn", False);
6450 Attention(firstProgramPID);
6451 SendToProgram("force\n", toFirstProgFP);
6454 case MachinePlaysWhite:
6455 if (!BlackOnMove(forwardMostMove))
6457 DisplayMessage("Wait until your turn", False);
6461 Attention(firstProgramPID);
6462 SendToProgram("force\n", toFirstProgFP);
6465 case BeginningOfGame:
6466 SendToProgram("force\n", toFirstProgFP);
6469 case PlayFromGameFile:
6470 if (readGameXID != 0)
6472 XtRemoveTimeOut(readGameXID);
6476 if (gameFileFP != NULL)
6485 ResurrectShogiProgram();
6492 case TwoMachinesPlay:
6493 ShutdownShogiPrograms("");
6494 ResurrectShogiProgram();
6501 if ((gameMode == MachinePlaysWhite)
6502 || (gameMode == MachinePlaysBlack)
6503 || (gameMode == TwoMachinesPlay)
6504 || (gameMode == PlayFromGameFile))
6506 i = forwardMostMove;
6508 while (i > currentMove)
6510 SendToProgram("undo\n", toFirstProgFP);
6514 blackTimeRemaining = timeRemaining[0][currentMove];
6515 whiteTimeRemaining = timeRemaining[1][currentMove];
6517 if (whiteFlag || blackFlag)
6519 whiteFlag = blackFlag = 0;
6525 lastGameMode = gameMode = ForceMoves;
6527 DisplayClocks(StopTimers);
6533 HintProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6535 int fromRemotePlayer = *nprms;
6537 if (updateRemotePlayer)
6539 DisplayMessage("no hints in challenge mode", fromRemotePlayer);
6543 if (localPlayer.appData.noShogiProgram)
6548 case MachinePlaysBlack:
6549 if (BlackOnMove(forwardMostMove))
6551 DisplayMessage("Wait until your turn", False);
6557 case BeginningOfGame:
6558 case MachinePlaysWhite:
6559 if (!BlackOnMove(forwardMostMove))
6561 DisplayMessage("Wait until your turn", False);
6568 DisplayMessage("No hint available", False);
6572 Attention(firstProgramPID);
6573 SendToProgram("hint\n", toFirstProgFP);
6580 PrintPosition(FILE *fp, int move)
6584 for (i = BOARD_SIZE - 1; i >= 0; i--)
6586 for (j = 0; j < BOARD_SIZE; j++)
6588 if (pieceIsPromoted[(int)boards[currentMove][i][j]])
6589 fprintf(fp, "%c", '+');
6591 fprintf(fp, "%c", ' ');
6594 pieceToChar[(int)boards[currentMove][i][j]]);
6596 if (j == BOARD_SIZE - 1)
6601 for (color = 0; color <= 1; color++)
6603 fprintf(fp, "%i %i %i %i %i %i %i %i\n",
6604 catches[currentMove][color][pawn],
6605 catches[currentMove][color][lance],
6606 catches[currentMove][color][knight],
6607 catches[currentMove][color][silver],
6608 catches[currentMove][color][gold],
6609 catches[currentMove][color][bishop],
6610 catches[currentMove][color][rook],
6611 catches[currentMove][color][king]);
6614 if ((gameMode == EditPosition)
6616 : BlackOnMove(forwardMostMove))
6618 fprintf(fp, "black to play\n");
6622 fprintf(fp, "white to play\n");
6630 PrintOpponents(FILE *fp)
6632 char host_name[MSG_SIZ];
6634 #ifdef HAVE_GETHOSTNAME
6635 gethostname(host_name, MSG_SIZ);
6637 strncpy(host_name, "hostname not available", MSG_SIZ);
6640 switch (lastGameMode)
6642 case MachinePlaysWhite:
6643 fprintf(fp, "# %s@%s vs. %s@%s\n",
6644 localPlayer.appData.firstShogiProgram,
6645 localPlayer.appData.firstHost,
6646 getpwuid(getuid())->pw_name,
6650 case MachinePlaysBlack:
6651 fprintf(fp, "# %s@%s vs. %s@%s\n",
6652 getpwuid(getuid())->pw_name,
6654 localPlayer.appData.firstShogiProgram,
6655 localPlayer.appData.firstHost);
6658 case TwoMachinesPlay:
6659 fprintf(fp, "# %s@%s vs. %s@%s\n",
6660 localPlayer.appData.secondShogiProgram,
6661 localPlayer.appData.secondHost,
6662 localPlayer.appData.firstShogiProgram,
6663 localPlayer.appData.firstHost);
6676 SavePositionProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6680 int fromRemotePlayer = *nprms;
6682 if (fromRemotePlayer)
6684 DisplayMessage("only opponent may save game", fromRemotePlayer);
6690 FileNamePopUp("Filename for saved position?", SavePosition);
6697 SavePosition(char *name)
6703 if ((fp = fopen(name, "w")) == NULL)
6705 sprintf(buf, "Can't open %s", name);
6706 DisplayMessage(buf, False);
6710 tm = time((time_t *) NULL);
6712 fprintf(fp, "# %s position file -- %s", programName, ctime(&tm));
6714 PrintPosition(fp, currentMove);
6724 TwoMachinesProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6727 MatchMode matchKind;
6729 int fromRemotePlayer = *nprms;
6731 if (updateRemotePlayer)
6733 DisplayMessage("no machine moves in challenge mode",
6738 if (gameMode == PauseGame)
6739 PauseProc(w, event, prms, nprms);
6741 if (gameMode == PlayFromGameFile)
6742 ForceProc(w, event, prms, nprms);
6744 if ((gameMode == EndOfGame)
6745 || (gameMode == TwoMachinesPlay)
6746 || localPlayer.appData.noShogiProgram)
6751 if (matchMode == MatchFalse)
6756 case PlayFromGameFile:
6759 case MachinePlaysBlack:
6760 case MachinePlaysWhite:
6761 ForceProc(w, event, prms, nprms);
6763 if (gameMode != ForceMoves)
6766 matchKind = MatchOpening;
6770 matchKind = MatchOpening;
6775 matchKind = MatchPosition;
6778 case BeginningOfGame:
6780 matchKind = MatchInit;
6786 matchKind = matchMode;
6789 forwardMostMove = currentMove;
6791 localPlayer.flipView = False;
6792 remotePlayer.flipView = True;
6794 DisplayClocks(ResetTimers);
6795 DisplayClocks(StartTimers);
6800 if (firstProgramXID == 0)
6802 if (localPlayer.appData.loadGameFile == NULL)
6804 DisplayMessage("Select game file first", False);
6808 InitShogiProgram(localPlayer.appData.firstHost,
6809 localPlayer.appData.firstShogiProgram,
6810 &firstProgramPID, &toFirstProgFP,
6811 &fromFirstProgFP, &firstProgramXID,
6814 if (!LoadGame(localPlayer.appData.loadGameFile))
6816 ShutdownShogiPrograms("Bad game file");
6820 DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
6823 InitShogiProgram(localPlayer.appData.secondHost,
6824 localPlayer.appData.secondShogiProgram,
6825 &secondProgramPID, &toSecondProgFP,
6826 &fromSecondProgFP, &secondProgramXID,
6829 if (startedFromSetupPosition)
6831 if (whitePlaysFirst)
6834 SendToProgram("force\n", toSecondProgFP);
6835 SendBoard(toSecondProgFP, boards[i], catches[i]);
6840 SendBoard(toSecondProgFP, boards[i], catches[i]);
6841 SendToProgram("force\n", toSecondProgFP);
6847 SendToProgram("force\n", toSecondProgFP);
6850 for (i = backwardMostMove; i < forwardMostMove; i++)
6851 SendToProgram(moveList[i], toSecondProgFP);
6853 lastGameMode = gameMode = TwoMachinesPlay;
6857 if (BlackOnMove(forwardMostMove))
6858 SendToProgram(localPlayer.appData.blackString, toSecondProgFP);
6860 SendToProgram(localPlayer.appData.whiteString, toFirstProgFP);
6865 if (firstProgramXID == 0)
6867 if (localPlayer.appData.loadPositionFile == NULL)
6869 DisplayMessage("Select position file first", False);
6873 InitShogiProgram(localPlayer.appData.firstHost,
6874 localPlayer.appData.firstShogiProgram,
6875 &firstProgramPID, &toFirstProgFP,
6876 &fromFirstProgFP, &firstProgramXID,
6879 if (!LoadPosition(localPlayer.appData.loadPositionFile))
6883 InitShogiProgram(localPlayer.appData.secondHost,
6884 localPlayer.appData.secondShogiProgram,
6885 &secondProgramPID, &toSecondProgFP,
6886 &fromSecondProgFP, &secondProgramXID,
6889 if (whitePlaysFirst)
6890 SendToProgram("force\n", toSecondProgFP);
6892 SendCurrentBoard(toSecondProgFP);
6893 lastGameMode = gameMode = TwoMachinesPlay;
6897 if (BlackOnMove(forwardMostMove))
6898 SendToProgram(localPlayer.appData.blackString, toSecondProgFP);
6900 SendToProgram(localPlayer.appData.whiteString, toFirstProgFP);
6907 if (firstProgramXID == 0)
6909 InitShogiProgram(localPlayer.appData.firstHost,
6910 localPlayer.appData.firstShogiProgram,
6911 &firstProgramPID, &toFirstProgFP,
6912 &fromFirstProgFP, &firstProgramXID,
6916 InitShogiProgram(localPlayer.appData.secondHost,
6917 localPlayer.appData.secondShogiProgram,
6918 &secondProgramPID, &toSecondProgFP,
6919 &fromSecondProgFP, &secondProgramXID,
6922 lastGameMode = gameMode = TwoMachinesPlay;
6924 SendToProgram(localPlayer.appData.blackString, toSecondProgFP);
6930 if (!firstSendTime || !secondSendTime)
6932 DisplayClocks(ResetTimers);
6933 timeRemaining[0][forwardMostMove] = blackTimeRemaining;
6934 timeRemaining[1][forwardMostMove] = whiteTimeRemaining;
6937 DisplayClocks(StartTimers);
6944 PauseProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
6946 static GameMode previous_mode = PauseGame;
6957 gameMode = previous_mode;
6959 previous_mode = PauseGame;
6960 DisplayClocks(StartTimers);
6961 DisplayMessage("", False);
6963 if (updateRemotePlayer)
6964 DisplayMessage("", True);
6967 case PlayFromGameFile:
6968 if (readGameXID == 0)
6971 XtAppAddTimeOut(appContext,
6972 (int)(1000 * localPlayer.appData.timeDelay),
6973 (XtTimerCallbackProc) ReadGameFile, NULL);
6977 XtRemoveTimeOut(readGameXID);
6981 DisplayMessage("Pausing", False);
6983 if (updateRemotePlayer)
6984 DisplayMessage("Pausing", True);
6988 case BeginningOfGame:
6989 case MachinePlaysBlack:
6990 case MachinePlaysWhite:
6991 case TwoMachinesPlay:
6992 if (forwardMostMove == 0) /* Don't pause if no one has moved. */
6995 if (((gameMode == MachinePlaysWhite)
6996 && !BlackOnMove(forwardMostMove))
6997 || ((gameMode == MachinePlaysBlack) &&
6998 BlackOnMove(forwardMostMove)))
7000 DisplayClocks(StopTimers);
7003 previous_mode = gameMode;
7004 gameMode = PauseGame;
7006 DisplayClocks(StopTimers);
7007 DisplayMessage("Pausing", False);
7009 if (updateRemotePlayer)
7010 DisplayMessage("Pausing", True);
7020 Iconify(Widget w, XEvent *event, String *prms, Cardinal *nprms)
7026 XtSetArg(args[0], XtNiconic, True);
7027 XtSetValues(localPlayer.shellWidget, args, 1);
7034 SendToProgram(char *message, FILE *fp)
7043 fprintf(stderr, "Sending to %s: %s\n",
7044 ((fp == toFirstProgFP) ? "first" : "second"), message);
7047 if (message[strlen(message) - 1] != '\n')
7048 fprintf(fp, "\n%s\n", message);
7059 ReceiveFromProgram(FILE *fp, int *source, XtInputId *id)
7061 char message[MSG_SIZ], *end_str, *number, *name;
7062 extern const char *const sys_errlist[];
7064 if (fgets(message, MSG_SIZ, fp) == NULL)
7066 if (fp == fromFirstProgFP)
7069 name = localPlayer.appData.firstShogiProgram;
7071 else if (fp == fromSecondProgFP)
7074 name = localPlayer.appData.secondShogiProgram;
7081 if (ferror(fp) == 0)
7083 sprintf(message, "%s shogi program (%s) exited unexpectedly",
7085 fprintf(stderr, "%s: %s\n", programName, message);
7090 "error reading from %s shogi program (%s): %s",
7091 number, name, sys_errlist[ferror(fp)]);
7092 fprintf(stderr, "%s: %s\n", programName, message);
7098 if ((end_str = (char *)strchr(message, '\r')) != NULL)
7099 *end_str = NULLCHAR;
7101 if ((end_str = (char *)strchr(message, '\n')) != NULL)
7102 *end_str = NULLCHAR;
7104 if (xshogiDebug || localPlayer.appData.debugMode)
7106 fprintf(stderr, "Received from %s: %s\n",
7107 ((fp == fromFirstProgFP) ? "first" : "second"), message);
7110 HandleMachineMove(message, fp);
7117 SendSearchDepth(FILE *fp)
7119 char message[MSG_SIZ];
7121 if (localPlayer.appData.searchDepth <= 0)
7124 sprintf(message, "depth\n%d\nhelp\n", localPlayer.appData.searchDepth);
7125 /* Note kludge: "help" command forces gnushogi to print
7126 * out something that ends with a newline. */
7127 SendToProgram(message, fp);
7134 DisplayMessage(char *message, int toRemotePlayer)
7138 XtSetArg(arg, XtNlabel, message);
7140 if (!toRemotePlayer)
7141 XtSetValues(localPlayer.messageWidget, &arg, 1);
7143 if (updateRemotePlayer && toRemotePlayer)
7144 XtSetValues(remotePlayer.messageWidget, &arg, 1);
7151 DisplayName(char *name)
7155 XtSetArg(arg, XtNlabel, name);
7156 XtSetValues(localPlayer.titleWidget, &arg, 1);
7158 if (updateRemotePlayer)
7159 XtSetValues(remotePlayer.titleWidget, &arg, 1);
7165 void SendTimeRemaining(FILE *fp)
7167 char message[MSG_SIZ];
7168 long comtime, opptime;
7170 if (BlackOnMove(forwardMostMove) == (fp == toFirstProgFP))
7172 comtime = blackTimeRemaining;
7173 opptime = whiteTimeRemaining;
7177 comtime = whiteTimeRemaining;
7178 opptime = blackTimeRemaining;
7187 sprintf(message, "time %ld\n", comtime / 10);
7188 SendToProgram(message, fp);
7189 sprintf(message, "otime %ld\n", opptime / 10);
7190 SendToProgram(message, fp);
7196 void DisplayMove(int moveNumber)
7198 char message[MSG_SIZ];
7202 if (moveNumber == forwardMostMove - 1)
7203 DisplayMessage(endMessage, False);
7205 DisplayMessage("", False);
7209 sprintf(message, "%d. %s%s %s",
7210 (moveNumber / 2 + 1),
7211 (BlackOnMove(moveNumber) ? "" : "... "),
7212 parseList[moveNumber],
7213 (moveNumber == (forwardMostMove - 1)) ? endMessage : "");
7214 DisplayMessage(message, False);
7221 void DisplayTitle(char *title)
7225 XtSetArg(arg, XtNlabel, title);
7226 XtSetValues(localPlayer.titleWidget, &arg, 1);
7232 /* CHECKME: does this work?
7233 * This routine sends a SIGINT (^C interrupt) to gnushogi to awaken it
7234 * if it might be busy thinking on our time. This normally isn't needed,
7235 * but is useful on systems where the FIONREAD ioctl doesn't work since
7236 * on those systems the gnushogi feature that lets you interrupt its thinking
7237 * just by typing a command does not work.
7239 * In the future, similar code could be used to stop gnushogi and make
7240 * it move immediately when it is thinking about its own move; this could
7241 * be useful if we want to make Backward or ForceMoves work while gnushogi
7248 #if !defined(FIONREAD)
7249 if (localPlayer.appData.noShogiProgram || (pid == 0))
7254 case MachinePlaysBlack:
7255 case MachinePlaysWhite:
7256 case TwoMachinesPlay:
7257 if ((forwardMostMove > backwardMostMove + 1) && maybeThinking)
7259 if (xshogiDebug || localPlayer.appData.debugMode)
7261 fprintf(stderr, "Sending SIGINT to %s\n",
7262 ((pid == firstProgramPID) ? "first" : "second"));
7265 (void)kill(pid, SIGINT); /* stop it thinking */
7270 break; /* CHECKME: is this OK? */
7272 #endif /* !defined(FIONREAD) */
7281 if (blackTimeRemaining <= 0)
7288 DisplayName(" Both flags have fallen");
7290 DisplayName(" Black's flag has fallen");
7294 if (whiteTimeRemaining <= 0)
7301 DisplayName(" Both flags have fallen");
7303 DisplayName(" White's flag has fallen");
7312 CheckTimeControl(void)
7314 if (!localPlayer.appData.clockMode)
7317 if (forwardMostMove == 0)
7321 * Add time to clocks when time control is achieved.
7324 if ((forwardMostMove % (localPlayer.appData.movesPerSession * 2)) == 0)
7326 blackTimeRemaining += timeControl;
7327 whiteTimeRemaining += timeControl;
7337 DisplayTimerLabel(localPlayer.blackTimerWidget, "Black",
7338 blackTimeRemaining);
7339 DisplayTimerLabel(localPlayer.whiteTimerWidget, "White",
7340 whiteTimeRemaining);
7342 if (updateRemotePlayer)
7344 DisplayTimerLabel(remotePlayer.blackTimerWidget, "Black",
7345 blackTimeRemaining);
7346 DisplayTimerLabel(remotePlayer.whiteTimerWidget, "White",
7347 whiteTimeRemaining);
7354 #ifdef HAVE_GETTIMEOFDAY
7355 static struct timeval tickStartTV;
7356 static int tickLength;
7359 PartialTickLength(void)
7365 gettimeofday(&tv, &tz);
7366 ptl = ((tv.tv_sec - tickStartTV.tv_sec) * 1000000 +
7367 (tv.tv_usec - tickStartTV.tv_usec) + 500) / 1000;
7369 if (ptl > tickLength)
7374 #else /* !HAVE_GETTIMEOFDAY */
7375 #define tickLength 1000
7376 #endif /* HAVE_GETTIMEOFDAY */
7382 * DisplayClocks manages the game clocks.
7384 * In tournament play, white starts the clock and then black makes a move.
7385 * We give the human user a slight advantage if he is playing black---the
7386 * clocks don't run until he makes his first move, so it takes zero time.
7387 * Also, DisplayClocks doesn't account for network lag so it could get out
7388 * of sync with GNU Shogi's clock -- but then, referees are always right.
7392 DisplayClocks(int clock_mode)
7394 #ifdef HAVE_GETTIMEOFDAY
7396 #endif /* HAVE_GETTIMEOFDAY */
7403 /* Stop clocks and reset to a fresh time control */
7406 XtRemoveTimeOut(timerXID);
7410 blackTimeRemaining = timeControl;
7411 whiteTimeRemaining = timeControl;
7413 if (blackFlag || whiteFlag)
7416 blackFlag = whiteFlag = False;
7422 case DecrementTimers:
7423 /* Decrement running clock to next 1-second boundary */
7424 if (gameMode == PauseGame)
7429 if (!localPlayer.appData.clockMode)
7432 if (BlackOnMove(forwardMostMove))
7434 timeRemaining = (blackTimeRemaining -= tickLength);
7438 timeRemaining = (whiteTimeRemaining -= tickLength);
7444 #ifdef HAVE_GETTIMEOFDAY
7445 tickLength = (((timeRemaining <= 1000) && (timeRemaining > 0))
7447 gettimeofday(&tickStartTV, &tz);
7448 #endif /* HAVE_GETTIMEOFDAY */
7451 XtAppAddTimeOut(appContext, tickLength,
7452 (XtTimerCallbackProc) DisplayClocks,
7453 (XtPointer) DecrementTimers);
7457 /* A player has just moved, so stop the previously running
7458 clock and start the other one. */
7462 XtRemoveTimeOut(timerXID);
7465 #ifdef HAVE_GETTIMEOFDAY
7466 if (localPlayer.appData.clockMode)
7468 if (BlackOnMove(forwardMostMove))
7469 whiteTimeRemaining -= PartialTickLength();
7471 blackTimeRemaining -= PartialTickLength();
7474 #endif /* HAVE_GETTIMEOFDAY */
7480 if (!localPlayer.appData.clockMode)
7483 if ((gameMode == PauseGame)
7484 && ((pausePreviousMode == MachinePlaysBlack)
7485 || (pausePreviousMode == MachinePlaysWhite)))
7490 timeRemaining = (BlackOnMove(forwardMostMove)
7491 ? blackTimeRemaining : whiteTimeRemaining);
7493 #ifdef HAVE_GETTIMEOFDAY
7494 tickLength = (((timeRemaining <= 1000) && (timeRemaining > 0))
7495 ? (((timeRemaining - 1) % 100) + 1)
7496 : (((timeRemaining - 1) % 1000) + 1));
7498 if (tickLength <= 0)
7501 gettimeofday(&tickStartTV, &tz);
7503 #endif /* HAVE_GETTIMEOFDAY */
7505 XtAppAddTimeOut(appContext, tickLength,
7506 (XtTimerCallbackProc) DisplayClocks,
7507 (XtPointer) DecrementTimers);
7510 case ReDisplayTimers:
7511 /* Display current clock values */
7516 /* Stop both clocks */
7520 XtRemoveTimeOut(timerXID);
7523 if (!localPlayer.appData.clockMode)
7526 #ifdef HAVE_GETTIMEOFDAY
7527 if (BlackOnMove(forwardMostMove))
7528 blackTimeRemaining -= PartialTickLength();
7530 whiteTimeRemaining -= PartialTickLength();
7533 #endif /* HAVE_GETTIMEOFDAY */
7537 /* Start clock of player on move, if not already running. */
7543 if (!localPlayer.appData.clockMode)
7546 timeRemaining = (BlackOnMove(forwardMostMove)
7547 ? blackTimeRemaining : whiteTimeRemaining);
7549 if (timeRemaining == 0)
7552 #ifdef HAVE_GETTIMEOFDAY
7553 tickLength = (((timeRemaining <= 1000) && (timeRemaining > 0))
7554 ? (((timeRemaining - 1) % 100) + 1)
7555 : (((timeRemaining - 1) % 1000) + 1));
7557 if (tickLength <= 0)
7560 gettimeofday(&tickStartTV, &tz);
7561 #endif /* HAVE_GETTIMEOFDAY */
7564 XtAppAddTimeOut(appContext, tickLength,
7565 (XtTimerCallbackProc) DisplayClocks,
7566 (XtPointer)DecrementTimers);
7575 DisplayTimerLabel(Widget w, char *color, long int timer)
7579 struct DisplayData *player;
7581 player = (((w == localPlayer.blackTimerWidget)
7582 || (w == localPlayer.whiteTimerWidget))
7583 ? &localPlayer : &remotePlayer);
7585 if (localPlayer.appData.clockMode)
7587 sprintf(buf, "%s: %s", color, TimeString(timer));
7588 XtSetArg(args[0], XtNlabel, buf);
7592 XtSetArg(args[0], XtNlabel, color);
7595 if (((color[0] == 'W') && BlackOnMove(forwardMostMove))
7596 || ((color[0] == 'B') && !BlackOnMove(forwardMostMove)))
7598 XtSetArg(args[1], XtNbackground, player->timerForegroundPixel);
7599 XtSetArg(args[2], XtNforeground, player->timerBackgroundPixel);
7603 XtSetArg(args[1], XtNbackground, player->timerBackgroundPixel);
7604 XtSetArg(args[2], XtNforeground, player->timerForegroundPixel);
7607 XtSetValues(w, args, 3);
7616 int second, minute, hour, day;
7618 static char buf[32];
7620 if ((tm > 0) && (tm <= 900))
7622 /* convert milliseconds to tenths, rounding up */
7623 sprintf(buf, " 0.%1ld ", (tm + 99) / 100);
7627 /* convert milliseconds to seconds, rounding up */
7628 tm = (tm + 999) / 1000;
7636 if (tm >= (60 * 60 * 24))
7638 day = (int)(tm / (60 * 60 * 24));
7639 tm -= day * 60 * 60 * 24;
7646 if (tm >= (60 * 60))
7648 hour = (int)(tm / (60 * 60));
7649 tm -= hour * 60 * 60;
7658 minute = (int)(tm / 60);
7670 sprintf(buf, " %s%d:%02d:%02d:%02d ",
7671 sign, day, hour, minute, second);
7675 sprintf(buf, " %s%d:%02d:%02d ",
7676 sign, hour, minute, second);
7680 sprintf(buf, " %s%2d:%02d ",
7681 sign, minute, second);
7693 fprintf(stderr, "Usage: %s\n", programName);
7694 fprintf(stderr, "\tstandard Xt options\n");
7695 fprintf(stderr, "\t-iconic\n");
7696 fprintf(stderr, "\t-tc or -timeControl minutes[:seconds]\n");
7697 fprintf(stderr, "\t-gi or -gameIn (True | False)\n");
7698 fprintf(stderr, "\t-mps or -movesPerSession moves\n");
7699 fprintf(stderr, "\t-st or -searchTime minutes[:seconds]\n");
7700 fprintf(stderr, "\t-sd or -searchDepth number\n");
7701 fprintf(stderr, "\t-clock or -clockMode (True | False)\n");
7702 fprintf(stderr, "\t-td or -timeDelay seconds\n");
7704 fprintf(stderr, "\t-nsp or -noShogiProgram (True | False)\n");
7705 fprintf(stderr, "\t-fsp or -firstShogiProgram program_name\n");
7706 fprintf(stderr, "\t-ssp or -secondShogiProgram program_name\n");
7707 fprintf(stderr, "\t-fh or -firstHost host_name\n");
7708 fprintf(stderr, "\t-sh or -secondHost host_name\n");
7709 fprintf(stderr, "\t-rsh or -remoteShell shell_name\n");
7711 "\t-mm or -matchMode (False | Init | Position | Opening)\n");
7712 fprintf(stderr, "\t-lgf or -loadGameFile file_name\n");
7713 fprintf(stderr, "\t-lpf or -loadPositionFile file_name\n");
7714 fprintf(stderr, "\t-sgf or -saveGameFile file_name\n");
7715 fprintf(stderr, "\t-spf or -savePositionFile file_name\n");
7716 fprintf(stderr, "\t-size or -boardSize (Large | Medium | Small)\n");
7717 fprintf(stderr, "\t-coords or -showCoords (True | False)\n");
7718 fprintf(stderr, "\t-mono or -monoMode (True | False)\n");
7719 fprintf(stderr, "\t-bpc or -blackPieceColor color\n");
7720 fprintf(stderr, "\t-wpc or -whitePieceColor color\n");
7721 fprintf(stderr, "\t-lsc or -lightSquareColor color\n");
7722 fprintf(stderr, "\t-dsc or -darkSquareColor color\n");
7723 fprintf(stderr, "\t-wps or -westernPieceSet (True | False)\n");
7724 fprintf(stderr, "\t-debug or -debugMode (True | False)\n");
7731 CatchPipeSignal(int dummy)
7733 char message[MSG_SIZ];
7736 "%s shogi program (%s) exited unexpectedly",
7737 ((lastMsgFP == toFirstProgFP) ? "first" : "second"),
7738 ((lastMsgFP == toFirstProgFP)
7739 ? localPlayer.appData.firstShogiProgram
7740 : localPlayer.appData.secondShogiProgram));
7741 fprintf(stderr, "%s: %s\n", programName, message);
7742 ShutdownShogiPrograms(message);