~ubuntu-branches/ubuntu/warty/gnushogi/warty

« back to all changes in this revision

Viewing changes to xshogi/xshogi.c

  • Committer: Bazaar Package Importer
  • Author(s): Javier Fernandez-Sanguino Pen~a
  • Date: 2004-01-09 16:06:59 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040109160659-n26nu7009llm247p
Tags: 1.3-3.1
* NMU
 - Minimal testing done and looks quite OK (even if I don't know
   how to play the game...)
 - Build-Depends move from libxaw-dev to libxaw6-dev (Closes: #169975)
 - Included errno.h in gnushogi which makes the binary build properly
   now (and is usable with xshogi) (Closes: #226319)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * FILE: xshogi.c
 
3
 *
 
4
 *     Implementation of the X interface for GNU shogi (xshogi).
 
5
 *
 
6
 * ------------------------------------------------------------------------
 
7
 * xshogi is based on XBoard -- an Xt/Athena user interface for GNU Chess.
 
8
 *
 
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
 
15
 *
 
16
 * XShogi borrows its piece bitmaps from CRANES Shogi.
 
17
 *
 
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
 
22
 *
 
23
 * The following terms apply to Digital Equipment Corporation's copyright
 
24
 * interest in XBoard:
 
25
 * ------------------------------------------------------------------------
 
26
 * All Rights Reserved
 
27
 *
 
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.
 
35
 *
 
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
 
42
 * SOFTWARE.
 
43
 * ------------------------------------------------------------------------
 
44
 *
 
45
 * This file is part of GNU shogi.
 
46
 *
 
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.
 
50
 *
 
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.
 
55
 *
 
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.
 
59
 *
 
60
 * ------------------------------------------------------------------------
 
61
 *
 
62
 */
 
63
 
 
64
#include "config.h"
 
65
 
 
66
#ifdef X_DISPLAY_MISSING
 
67
#error You cannot compile xshogi if X windows is unavailable!
 
68
#endif
 
69
 
 
70
#include "sysdeps.h"
 
71
 
 
72
#define XBOARD_VERSION "2.0/2.1"
 
73
 
 
74
#include <stdio.h>
 
75
#include <ctype.h>
 
76
#include <signal.h>
 
77
#include <sys/ioctl.h>
 
78
 
 
79
#include <time.h>
 
80
#include <pwd.h>
 
81
 
 
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>
 
93
 
 
94
#include "../version.h"
 
95
#include "xshogi.h"
 
96
 
 
97
#define BUF_SIZE 1024
 
98
#define BOARD    1
 
99
#define MOVES    2
 
100
 
 
101
#include "bitmaps.h"  /* Piece bitmaps. */
 
102
#include "xshogifn.h" /* Forward declarations. */
 
103
 
 
104
#define off_board(x) (x < 2 || x > BOARD_SIZE + 1)
 
105
 
 
106
 
 
107
/**********************************************************************
 
108
 *
 
109
 * Global variables, structs etc.
 
110
 *
 
111
 **********************************************************************/
 
112
 
 
113
/*
 
114
 * NOTE: XShogi depends on Xt R4 or higher
 
115
 */
 
116
 
 
117
int xtVersion = XtSpecificationRelease;
 
118
 
 
119
XtIntervalId firstProgramXID = 0, secondProgramXID = 0,
 
120
    readGameXID = 0, timerXID = 0, blinkSquareXID = 0;
 
121
 
 
122
XtAppContext appContext;
 
123
 
 
124
Boolean (*fileProc) (char *name);
 
125
 
 
126
FILE *fromFirstProgFP, *toFirstProgFP, *fromSecondProgFP,
 
127
    *toSecondProgFP, *gameFileFP, *lastMsgFP;
 
128
 
 
129
int currentMove = 0, forwardMostMove = 0, backwardMostMove = 0,
 
130
    firstProgramPID = 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,
 
137
    filemodeUp = False;
 
138
 
 
139
int at_least_gnushogi_1_2p03 = False;
 
140
 
 
141
int firstSendTime = 2, secondSendTime = 2; /* 0 = don't, 1 = do,
 
142
                                              2 = test first */
 
143
 
 
144
MatchMode matchMode         = MatchFalse;
 
145
GameMode  gameMode          = BeginningOfGame;
 
146
GameMode  lastGameMode      = BeginningOfGame;
 
147
GameMode  pausePreviousMode = BeginningOfGame;
 
148
 
 
149
char moveList[MAX_MOVES][MOVE_LEN], parseList[MAX_MOVES][MOVE_LEN * 2],
 
150
    ptyname[24], *shogiDir, *programName;
 
151
 
 
152
char endMessage[MOVE_LEN * 4];
 
153
 
 
154
long blackTimeRemaining, whiteTimeRemaining, timeControl;
 
155
long timeRemaining[2][MAX_MOVES];
 
156
 
 
157
extern char currentMoveString[];
 
158
 
 
159
int updateRemotePlayer = False;
 
160
 
 
161
Catched catches[MAX_MOVES];
 
162
 
 
163
#define DIMENSION 100
 
164
 
 
165
Widget blackPieceMenu, whitePieceMenu, commentShell;
 
166
 
 
167
XSetWindowAttributes attr;
 
168
 
 
169
#define pawn      0
 
170
#define lance     1
 
171
#define knight    2
 
172
#define silver    3
 
173
#define gold      4
 
174
#define bishop    5
 
175
#define rook      6
 
176
#define king      7
 
177
#define no_piece  8
 
178
#define ppawn     9
 
179
#define plance   10
 
180
#define pknight  11
 
181
#define psilver  12
 
182
#define pbishop  13
 
183
 
 
184
#define NO_PIECES  15
 
185
#define NO_SQUARES 81
 
186
#define NO_COLS     9
 
187
#define NO_ROWS     9
 
188
 
 
189
 
 
190
char catchedIndexToChar[8] =
 
191
{
 
192
    'P', 'L', 'N', 'S', 'G', 'B', 'R', 'K'
 
193
};
 
194
 
 
195
ShogiSquare catchedIndexToPiece[2][8] =
 
196
{
 
197
    {
 
198
        BlackPawn, BlackLance, BlackKnight, BlackSilver, BlackGold,
 
199
        BlackBishop, BlackRook, BlackKing
 
200
    },
 
201
    {
 
202
        WhitePawn, WhiteLance, WhiteKnight, WhiteSilver, WhiteGold,
 
203
        WhiteBishop, WhiteRook, WhiteKing
 
204
    }
 
205
};
 
206
 
 
207
 
 
208
int pieceToCatchedIndex[] =
 
209
{
 
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,
 
214
    no_piece
 
215
};
 
216
 
 
217
 
 
218
 
 
219
Board boards[MAX_MOVES];
 
220
Board initialPosition =
 
221
{
 
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 }
 
240
};
 
241
 
 
242
String gnuButtonStrings[] =
 
243
{
 
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",
 
249
};
 
250
 
 
251
/* must be in same order as buttonStrings! */
 
252
XtActionProc gnuButtonProcs[] =
 
253
{
 
254
    QuitProc,       LoadGameProc,      MachineWhiteProc,  ForwardProc,
 
255
    ResetProc,      LoadPositionProc,  MachineBlackProc,  BackwardProc,
 
256
    FlipViewProc,   SaveGameProc,      ForceProc,         PauseProc,
 
257
    HintProc,       SavePositionProc,  TwoMachinesProc,   EditPositionProc,
 
258
    ChallengeProc,  SelectLevelProc,   MoveNowProc,
 
259
    NULL
 
260
};
 
261
 
 
262
 
 
263
String *buttonStrings;
 
264
XtActionProc *buttonProcs;
 
265
int buttonCount;
 
266
 
 
267
#define PIECE_MENU_SIZE 18
 
268
 
 
269
String pieceMenuStrings[PIECE_MENU_SIZE] =
 
270
{
 
271
    "----",     "Pawn",          "Lance",       "Knight", "Silver",
 
272
    "Gold",     "Bishop",        "Rook",
 
273
    "PPawn",    "PLance",        "PKnight",     "PSilver",
 
274
    "PBishop",  "PRook",         "King",
 
275
    "----",     "Empty square",  "Clear board"
 
276
};
 
277
 
 
278
/* must be in same order as PieceMenuStrings! */
 
279
ShogiSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] =
 
280
{
 
281
    {
 
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
 
287
    },
 
288
    {
 
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
 
294
    },
 
295
};
 
296
 
 
297
 
 
298
typedef struct
 
299
{
 
300
    Pixel blackPieceColor;
 
301
    Pixel whitePieceColor;
 
302
    Pixel lightSquareColor;
 
303
    Pixel darkSquareColor;
 
304
    Pixel charPieceColor;
 
305
    Pixel zeroColor;
 
306
    Pixel oneColor;
 
307
    Boolean westernPieceSet;
 
308
    int movesPerSession;
 
309
    String initString;
 
310
    String blackString;
 
311
    String whiteString;
 
312
    String firstShogiProgram;
 
313
    String secondShogiProgram;
 
314
    Boolean noShogiProgram;
 
315
    String firstHost;
 
316
    String secondHost;
 
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;
 
349
    String remoteShell;
 
350
    float  timeDelay;
 
351
    String timeControl;
 
352
    String gameIn;
 
353
 
 
354
    Boolean autoSaveGames;
 
355
    String loadGameFile;
 
356
    String loadPositionFile;
 
357
    String saveGameFile;
 
358
    String savePositionFile;
 
359
    String matchMode;
 
360
    String challengeDisplay;
 
361
    Boolean monoMode;
 
362
    Boolean debugMode;
 
363
    Boolean clockMode;
 
364
    String boardSize;
 
365
    Boolean Iconic;
 
366
    String searchTime;
 
367
    int searchDepth;
 
368
    Boolean showCoords;
 
369
    String mainFont;
 
370
    String coordFont;
 
371
    Boolean ringBellAfterMoves;
 
372
    Boolean autoCallFlag;
 
373
    int borderXoffset;
 
374
    int borderYoffset;
 
375
} AppData, *AppDataPtr;
 
376
 
 
377
 
 
378
XtResource clientResources[] =
 
379
{
 
380
    {
 
381
        "blackPieceColor", "BlackPieceColor", XtRPixel, sizeof(Pixel),
 
382
        XtOffset(AppDataPtr, blackPieceColor), XtRString,
 
383
        BLACK_PIECE_COLOR
 
384
    },
 
385
    {
 
386
        "whitePieceColor", "WhitePieceColor", XtRPixel, sizeof(Pixel),
 
387
        XtOffset(AppDataPtr, whitePieceColor), XtRString,
 
388
        WHITE_PIECE_COLOR
 
389
    },
 
390
    {
 
391
        "charPieceColor", "CharPieceColor", XtRPixel, sizeof(Pixel),
 
392
        XtOffset(AppDataPtr, charPieceColor), XtRString,
 
393
        CHAR_PIECE_COLOR
 
394
    },
 
395
    {
 
396
        "oneColor", "OneColor", XtRPixel, sizeof(Pixel),
 
397
        XtOffset(AppDataPtr, oneColor), XtRString,
 
398
        ONE_COLOR
 
399
    },
 
400
    {
 
401
        "zeroColor", "ZeroColor", XtRPixel, sizeof(Pixel),
 
402
        XtOffset(AppDataPtr, zeroColor), XtRString,
 
403
        ZERO_COLOR
 
404
    },
 
405
    {
 
406
        "lightSquareColor", "LightSquareColor", XtRPixel,
 
407
        sizeof(Pixel), XtOffset(AppDataPtr, lightSquareColor),
 
408
        XtRString, LIGHT_SQUARE_COLOR
 
409
    },
 
410
    {
 
411
        "darkSquareColor", "DarkSquareColor", XtRPixel, sizeof(Pixel),
 
412
        XtOffset(AppDataPtr, darkSquareColor), XtRString,
 
413
        DARK_SQUARE_COLOR
 
414
    },
 
415
    {
 
416
        "westernPieceSet", "WesternPieceSet", XtRBoolean, sizeof(Boolean),
 
417
        XtOffset(AppDataPtr, westernPieceSet), XtRString,
 
418
        (XtPointer) False
 
419
    },
 
420
    {
 
421
        "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
 
422
        XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
 
423
        (XtPointer) MOVES_PER_SESSION
 
424
    },
 
425
    {
 
426
        "initString", "initString", XtRString, sizeof(String),
 
427
        XtOffset(AppDataPtr, initString), XtRString, INIT_STRING
 
428
    },
 
429
    {
 
430
        "blackString", "blackString", XtRString, sizeof(String),
 
431
        XtOffset(AppDataPtr, blackString), XtRString, BLACK_STRING
 
432
    },
 
433
    {
 
434
        "whiteString", "whiteString", XtRString, sizeof(String),
 
435
        XtOffset(AppDataPtr, whiteString), XtRString, WHITE_STRING
 
436
    },
 
437
    {
 
438
        "firstShogiProgram", "firstShogiProgram", XtRString,
 
439
        sizeof(String), XtOffset(AppDataPtr, firstShogiProgram),
 
440
        XtRString, FIRST_SHOGI_PROGRAM
 
441
    },
 
442
    {
 
443
        "secondShogiProgram", "secondShogiProgram", XtRString,
 
444
        sizeof(String), XtOffset(AppDataPtr, secondShogiProgram),
 
445
        XtRString, SECOND_SHOGI_PROGRAM
 
446
    },
 
447
    {
 
448
        "noShogiProgram", "noShogiProgram", XtRBoolean,
 
449
        sizeof(Boolean), XtOffset(AppDataPtr, noShogiProgram),
 
450
        XtRImmediate, (XtPointer) False
 
451
    },
 
452
    {
 
453
        "firstHost", "firstHost", XtRString, sizeof(String),
 
454
        XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST
 
455
    },
 
456
    {
 
457
        "secondHost", "secondHost", XtRString, sizeof(String),
 
458
        XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST
 
459
    },
 
460
    {
 
461
        "reversePawnBitmap", "reversePawnBitmap", XtRString,
 
462
        sizeof(String), XtOffset(AppDataPtr, reversePawnBitmap),
 
463
        XtRString, NULL
 
464
    },
 
465
    {
 
466
        "reverseLanceBitmap", "reverseLanceBitmap", XtRString,
 
467
        sizeof(String), XtOffset(AppDataPtr, reverseLanceBitmap),
 
468
        XtRString, NULL
 
469
    },
 
470
    {
 
471
        "reverseKnightBitmap", "reverseKnightBitmap", XtRString,
 
472
        sizeof(String), XtOffset(AppDataPtr, reverseKnightBitmap),
 
473
        XtRString, NULL
 
474
    },
 
475
    {
 
476
        "reverseSilverBitmap", "reverseSilverBitmap", XtRString,
 
477
        sizeof(String), XtOffset(AppDataPtr, reverseSilverBitmap),
 
478
        XtRString, NULL
 
479
    },
 
480
    {
 
481
        "reverseGoldBitmap", "reverseGoldBitmap", XtRString,
 
482
        sizeof(String), XtOffset(AppDataPtr, reverseGoldBitmap),
 
483
        XtRString, NULL
 
484
    },
 
485
    {
 
486
        "reverseRookBitmap", "reverseRookBitmap", XtRString,
 
487
        sizeof(String), XtOffset(AppDataPtr, reverseRookBitmap),
 
488
        XtRString, NULL
 
489
    },
 
490
    {
 
491
        "reverseBishopBitmap", "reverseBishopBitmap", XtRString,
 
492
        sizeof(String), XtOffset(AppDataPtr, reverseBishopBitmap),
 
493
        XtRString, NULL
 
494
    },
 
495
    {
 
496
        "reversePPawnBitmap", "reversePPawnBitmap", XtRString,
 
497
        sizeof(String), XtOffset(AppDataPtr, reversePPawnBitmap),
 
498
        XtRString, NULL
 
499
    },
 
500
    {
 
501
        "reversePLanceBitmap", "reversePLanceBitmap", XtRString,
 
502
        sizeof(String), XtOffset(AppDataPtr, reversePLanceBitmap),
 
503
        XtRString, NULL
 
504
    },
 
505
    {
 
506
        "reversePKnightBitmap", "reversePKnightBitmap", XtRString,
 
507
        sizeof(String), XtOffset(AppDataPtr, reversePKnightBitmap),
 
508
        XtRString, NULL
 
509
    },
 
510
    {
 
511
        "reversePSilverBitmap", "reversePSilverBitmap", XtRString,
 
512
        sizeof(String), XtOffset(AppDataPtr, reversePSilverBitmap),
 
513
        XtRString, NULL
 
514
    },
 
515
    {
 
516
        "reversePRookBitmap", "reversePRookBitmap", XtRString,
 
517
        sizeof(String), XtOffset(AppDataPtr, reversePRookBitmap),
 
518
        XtRString, NULL
 
519
    },
 
520
    {
 
521
        "reversePBishopBitmap", "reversePBishopBitmap", XtRString,
 
522
        sizeof(String), XtOffset(AppDataPtr, reversePBishopBitmap),
 
523
        XtRString, NULL
 
524
    },
 
525
    {
 
526
        "reverseKingBitmap", "reverseKingBitmap", XtRString,
 
527
        sizeof(String), XtOffset(AppDataPtr, reverseKingBitmap),
 
528
        XtRString, NULL
 
529
    },
 
530
    {
 
531
        "normalPawnBitmap", "normalPawnBitmap", XtRString,
 
532
        sizeof(String), XtOffset(AppDataPtr, normalPawnBitmap),
 
533
        XtRString, NULL
 
534
    },
 
535
    {
 
536
        "normalLanceBitmap", "normalLanceBitmap", XtRString,
 
537
        sizeof(String), XtOffset(AppDataPtr, normalLanceBitmap),
 
538
        XtRString, NULL
 
539
    },
 
540
    {
 
541
        "normalKnightBitmap", "normalKnightBitmap", XtRString,
 
542
        sizeof(String), XtOffset(AppDataPtr, normalKnightBitmap),
 
543
        XtRString, NULL
 
544
    },
 
545
    {
 
546
        "normalSilverBitmap", "normalSilverBitmap", XtRString,
 
547
        sizeof(String), XtOffset(AppDataPtr, normalSilverBitmap),
 
548
        XtRString, NULL
 
549
    },
 
550
    {
 
551
        "normalGoldBitmap", "normalGoldBitmap", XtRString,
 
552
        sizeof(String), XtOffset(AppDataPtr, normalGoldBitmap),
 
553
        XtRString, NULL
 
554
    },
 
555
    {
 
556
        "normalBishopBitmap", "normalBishopBitmap", XtRString,
 
557
        sizeof(String), XtOffset(AppDataPtr, normalBishopBitmap),
 
558
        XtRString, NULL
 
559
    },
 
560
    {
 
561
        "normalRookBitmap", "normalRookBitmap", XtRString,
 
562
        sizeof(String), XtOffset(AppDataPtr, normalRookBitmap),
 
563
        XtRString, NULL
 
564
    },
 
565
    {
 
566
        "normalPPawnBitmap", "normalPPawnBitmap", XtRString,
 
567
        sizeof(String), XtOffset(AppDataPtr, normalPPawnBitmap),
 
568
        XtRString, NULL
 
569
    },
 
570
    {
 
571
        "normalPLanceBitmap", "normalPLanceBitmap", XtRString,
 
572
        sizeof(String), XtOffset(AppDataPtr, normalPLanceBitmap),
 
573
        XtRString, NULL
 
574
    },
 
575
    {
 
576
        "normalPKnightBitmap", "normalPKnightBitmap", XtRString,
 
577
        sizeof(String), XtOffset(AppDataPtr, normalPKnightBitmap),
 
578
        XtRString, NULL
 
579
    },
 
580
    {
 
581
        "normalPSilverBitmap", "normalPSilverBitmap", XtRString,
 
582
        sizeof(String), XtOffset(AppDataPtr, normalPSilverBitmap),
 
583
        XtRString, NULL
 
584
    },
 
585
    {
 
586
        "normalPBishopBitmap", "normalPBishopBitmap", XtRString,
 
587
        sizeof(String), XtOffset(AppDataPtr, normalPBishopBitmap),
 
588
        XtRString, NULL
 
589
    },
 
590
    {
 
591
        "normalPRookBitmap", "normalPRookBitmap", XtRString,
 
592
        sizeof(String), XtOffset(AppDataPtr, normalPRookBitmap),
 
593
        XtRString, NULL
 
594
    },
 
595
    {
 
596
        "normalKingBitmap", "normalKingBitmap", XtRString,
 
597
        sizeof(String), XtOffset(AppDataPtr, normalKingBitmap),
 
598
        XtRString, NULL
 
599
    },
 
600
    {
 
601
        "remoteShell", "remoteShell", XtRString, sizeof(String),
 
602
        XtOffset(AppDataPtr, remoteShell), XtRString, "rsh"
 
603
    },
 
604
    {
 
605
        "timeDelay", "timeDelay", XtRFloat, sizeof(float),
 
606
        XtOffset(AppDataPtr, timeDelay), XtRString,
 
607
        (XtPointer) TIME_DELAY
 
608
    },
 
609
    {
 
610
        "timeControl", "timeControl", XtRString, sizeof(String),
 
611
        XtOffset(AppDataPtr, timeControl), XtRString,
 
612
        (XtPointer) TIME_CONTROL
 
613
    },
 
614
    {
 
615
        "gameIn", "gameIn",
 
616
        XtRBoolean, sizeof(Boolean),
 
617
        XtOffset(AppDataPtr, gameIn), XtRImmediate,
 
618
        (XtPointer) False
 
619
    },
 
620
    {
 
621
        "autoSaveGames", "autoSaveGames", XtRBoolean,
 
622
        sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
 
623
        XtRImmediate, (XtPointer) False
 
624
    },
 
625
    {
 
626
        "loadGameFile", "loadGameFile", XtRString, sizeof(String),
 
627
        XtOffset(AppDataPtr, loadGameFile), XtRString, NULL
 
628
    },
 
629
    {
 
630
        "loadPositionFile", "loadPositionFile", XtRString,
 
631
        sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
 
632
        XtRString, NULL
 
633
    },
 
634
    {
 
635
        "saveGameFile", "saveGameFile", XtRString, sizeof(String),
 
636
        XtOffset(AppDataPtr, saveGameFile), XtRString, ""
 
637
    },
 
638
    {
 
639
        "savePositionFile", "savePositionFile", XtRString,
 
640
        sizeof(String), XtOffset(AppDataPtr, savePositionFile),
 
641
        XtRString, ""
 
642
    },
 
643
    {
 
644
        "challengeDisplay", "challengeDisplay", XtRString,
 
645
        sizeof(String), XtOffset(AppDataPtr, challengeDisplay),
 
646
        XtRString, NULL
 
647
    },
 
648
    {
 
649
        "matchMode", "matchMode", XtRString, sizeof(String),
 
650
        XtOffset(AppDataPtr, matchMode), XtRString, MATCH_MODE
 
651
    },
 
652
    {
 
653
        "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
 
654
        XtOffset(AppDataPtr, monoMode), XtRImmediate,
 
655
        (XtPointer) False
 
656
    },
 
657
    {
 
658
        "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
 
659
        XtOffset(AppDataPtr, debugMode), XtRImmediate,
 
660
        (XtPointer) False
 
661
    },
 
662
    {
 
663
        "Iconic", "Iconic", XtRBoolean, sizeof(Boolean),
 
664
        XtOffset(AppDataPtr, Iconic), XtRImmediate,
 
665
        (XtPointer) False
 
666
    },
 
667
    {
 
668
        "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
 
669
        XtOffset(AppDataPtr, clockMode), XtRImmediate,
 
670
        (XtPointer) True
 
671
    },
 
672
    {
 
673
        "autoCallFlag", "autoCallFlag", XtRBoolean,
 
674
        sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
 
675
        XtRImmediate, (XtPointer) False
 
676
    },
 
677
    {
 
678
        "boardSize", "boardSize", XtRString, sizeof(String),
 
679
        XtOffset(AppDataPtr, boardSize), XtRString, DEFAULT_SIZE
 
680
    },
 
681
    {
 
682
        "searchTime", "searchTime", XtRString, sizeof(String),
 
683
        XtOffset(AppDataPtr, searchTime), XtRString,
 
684
        (XtPointer) NULL
 
685
    },
 
686
    {
 
687
        "searchDepth", "searchDepth", XtRInt, sizeof(int),
 
688
        XtOffset(AppDataPtr, searchDepth), XtRImmediate,
 
689
        (XtPointer) 0
 
690
    },
 
691
    {
 
692
        "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
 
693
        XtOffset(AppDataPtr, showCoords), XtRImmediate,
 
694
        (XtPointer) False
 
695
    },
 
696
    {
 
697
        "mainFont", "mainFont", XtRString, sizeof(String),
 
698
        XtOffset(AppDataPtr, mainFont), XtRString, MAIN_FONT
 
699
    },
 
700
    {
 
701
        "coordFont", "coordFont", XtRString, sizeof(String),
 
702
        XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT
 
703
    },
 
704
    {
 
705
        "ringBellAfterMoves", "ringBellAfterMoves",
 
706
        XtRBoolean, sizeof(Boolean),
 
707
        XtOffset(AppDataPtr, ringBellAfterMoves),
 
708
        XtRImmediate, (XtPointer) False
 
709
    },
 
710
    {
 
711
        "borderXoffset", "borderXoffset", XtRInt, sizeof(int),
 
712
        XtOffset(AppDataPtr, borderXoffset), XtRImmediate,
 
713
        (XtPointer) BORDER_X_OFFSET
 
714
    },
 
715
    {
 
716
        "borderYoffset", "borderYOffset", XtRInt, sizeof(int),
 
717
        XtOffset(AppDataPtr, borderYoffset), XtRImmediate,
 
718
        (XtPointer) BORDER_Y_OFFSET
 
719
    }
 
720
};
 
721
 
 
722
 
 
723
struct DisplayData
 
724
{
 
725
 
 
726
    AppData appData;
 
727
 
 
728
    Arg shellArgs[6];
 
729
    Arg boardArgs[3];
 
730
    Arg commandsArgs[7];
 
731
    Arg messageArgs[3];
 
732
    Arg timerArgs[2];
 
733
    Arg titleArgs[2];
 
734
 
 
735
    Pixmap reversePawnBitmap, reverseLanceBitmap,   reverseKnightBitmap,
 
736
        reverseSilverBitmap,
 
737
        reverseGoldBitmap,    reverseBishopBitmap,  reverseRookBitmap,
 
738
        reversePPawnBitmap,   reversePLanceBitmap,  reversePKnightBitmap,
 
739
        reversePSilverBitmap, reversePBishopBitmap, reversePRookBitmap,
 
740
        reverseKingBitmap,
 
741
        reverseBigSolidBitmap, reverseSmallSolidBitmap,
 
742
        normalBigSolidBitmap,  normalSmallSolidBitmap,
 
743
        normalPawnBitmap,      normalLanceBitmap,   normalKnightBitmap,
 
744
        normalSilverBitmap,    normalGoldBitmap,
 
745
        normalBishopBitmap,    normalRookBitmap,
 
746
        normalPPawnBitmap,     normalPLanceBitmap,  normalPKnightBitmap,
 
747
        normalPSilverBitmap,   normalPBishopBitmap, normalPRookBitmap,
 
748
        normalKingBitmap,
 
749
        iconPixmap;
 
750
 
 
751
    Display *xDisplay;
 
752
    int xScreen;
 
753
    Window xBoardWindow;
 
754
 
 
755
    GC lightSquareGC, darkSquareGC, lineGC, wdPieceGC, wlPieceGC,
 
756
        woPieceGC, boPieceGC, bdPieceGC, blPieceGC, wbPieceGC,
 
757
        bwPieceGC, coordGC, dropPiece;
 
758
 
 
759
    GC charPieceGC;
 
760
 
 
761
    Font mainFontID, coordFontID;
 
762
    XFontStruct *mainFontStruct, *coordFontStruct;
 
763
 
 
764
    Widget shellWidget, formWidget, boardWidget,
 
765
        commandsWidget, messageWidget,
 
766
        blackTimerWidget, whiteTimerWidget,
 
767
        titleWidget, widgetList[6],
 
768
        promotionShell,
 
769
        filemodeShell, challengeWidget;
 
770
 
 
771
    XSegment gridSegments[(BOARD_SIZE + 1) * 2];
 
772
 
 
773
    Pixel timerForegroundPixel, timerBackgroundPixel;
 
774
 
 
775
    BoardSize boardSize;
 
776
    int squareSize;
 
777
    int black_pixel_is_zero;
 
778
    int flipView;
 
779
    int promotionUp;
 
780
 
 
781
    Boolean monoMode, showCoords, Iconic;
 
782
};
 
783
 
 
784
 
 
785
 
 
786
struct DisplayData localPlayer, remotePlayer;
 
787
 
 
788
 
 
789
typedef struct
 
790
{
 
791
    ShogiSquare piece;
 
792
    int to_x, to_y;
 
793
} PromotionMoveInfo;
 
794
 
 
795
static PromotionMoveInfo pmi;  /* making this global is gross */
 
796
 
 
797
 
 
798
Pixmap *pieceToReverse[2][28] =
 
799
{
 
800
    {
 
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
 
829
    },
 
830
    {
 
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
 
859
    }
 
860
};
 
861
 
 
862
 
 
863
 
 
864
Pixmap *pieceToNormal[2][28] =
 
865
{
 
866
    {
 
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
 
895
    },
 
896
    {
 
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
 
925
    }
 
926
};
 
927
 
 
928
 
 
929
 
 
930
Pixmap *pieceToReverseSolid[2][28] =
 
931
{
 
932
    {
 
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
 
961
    },
 
962
    {
 
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
 
991
    }
 
992
};
 
993
 
 
994
 
 
995
 
 
996
Pixmap *pieceToNormalSolid[2][28] =
 
997
{
 
998
    {
 
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
 
1027
    },
 
1028
    {
 
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
 
1057
    }
 
1058
};
 
1059
 
 
1060
 
 
1061
 
 
1062
int pieceIsPromoted[] =
 
1063
{
 
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,
 
1068
    False
 
1069
};
 
1070
 
 
1071
 
 
1072
int piecePromotable[] =
 
1073
{
 
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,
 
1078
    False
 
1079
};
 
1080
 
 
1081
 
 
1082
char pieceToChar[] =
 
1083
{
 
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',
 
1086
    '.'
 
1087
};
 
1088
 
 
1089
 
 
1090
int pieceisWhite[] =
 
1091
{
 
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,
 
1096
    False
 
1097
};
 
1098
 
 
1099
 
 
1100
 
 
1101
ShogiSquare pieceToPromoted[] =
 
1102
{
 
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
 
1111
};
 
1112
 
 
1113
 
 
1114
 
 
1115
XrmOptionDescRec shellOptions[] =
 
1116
{
 
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" }
 
1242
};
 
1243
 
 
1244
 
 
1245
 
 
1246
XtActionsRec boardActions[] =
 
1247
{
 
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 }
 
1262
};
 
1263
 
 
1264
 
 
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";
 
1288
 
 
1289
 
 
1290
char translationsTableReduced[] =
 
1291
"<Expose>: DrawPosition() \n \
 
1292
<Btn1Down>: HandleUserMove() \n \
 
1293
<Btn1Up>: HandleUserMove() \n \
 
1294
<Message>WM_PROTOCOLS: QuitProc() \n";
 
1295
 
 
1296
 
 
1297
char blackTranslations[] = "<BtnDown>: SetBlackToPlay()\n";
 
1298
char whiteTranslations[] = "<BtnDown>: SetWhiteToPlay()\n";
 
1299
 
 
1300
String xshogiResources[] =
 
1301
{
 
1302
    DEFAULT_FONT,
 
1303
    "*Dialog*value.translations: #override "
 
1304
    "\\n <Key>Return: FileNameAction()",
 
1305
    NULL
 
1306
};
 
1307
 
 
1308
 
 
1309
int global_argc;       /* number of command args */
 
1310
char *global_argv[10]; /* pointers to up to 10 command args */
 
1311
 
 
1312
 
 
1313
 
 
1314
static struct DisplayData *player;
 
1315
 
 
1316
 
 
1317
typedef struct
 
1318
{
 
1319
    char mode[2];
 
1320
    char name[100];
 
1321
} FileModeInfo;
 
1322
 
 
1323
static FileModeInfo fmi;
 
1324
 
 
1325
 
 
1326
/**********************************************************************
 
1327
 *
 
1328
 * End of globals.
 
1329
 *
 
1330
 **********************************************************************/
 
1331
 
 
1332
 
 
1333
void
 
1334
CreatePlayerWindow(void)
 
1335
{
 
1336
    int mainFontPxlSize, coordFontPxlSize;
 
1337
    int min, sec, matched;
 
1338
    XSetWindowAttributes window_attributes;
 
1339
    char buf[MSG_SIZ];
 
1340
    Arg args[10];
 
1341
    Dimension timerWidth, boardWidth, commandsWidth, w, h;
 
1342
    int local;
 
1343
    int fromRemotePlayer = (player == &remotePlayer);
 
1344
 
 
1345
    player->monoMode = player->appData.monoMode;
 
1346
    player->showCoords = player->appData.showCoords;
 
1347
 
 
1348
    /*
 
1349
     * Parse timeControl resource.
 
1350
     */
 
1351
 
 
1352
    if (player->appData.timeControl != NULL)
 
1353
    {
 
1354
        matched = sscanf(player->appData.timeControl, "%d:%d", &min, &sec);
 
1355
 
 
1356
        if (matched == 1)
 
1357
        {
 
1358
            timeControl = min * 60 * 1000;
 
1359
        }
 
1360
        else if (matched == 2)
 
1361
        {
 
1362
            timeControl = (min * 60 + sec) * 1000;
 
1363
        }
 
1364
        else
 
1365
        {
 
1366
            fprintf(stderr, "%s: bad timeControl option %s\n",
 
1367
                    programName, player->appData.timeControl);
 
1368
            Usage();
 
1369
        }
 
1370
    }
 
1371
 
 
1372
    /*
 
1373
     * Parse searchTime resource
 
1374
     */
 
1375
 
 
1376
    if (player->appData.searchTime != NULL)
 
1377
    {
 
1378
        matched = sscanf(player->appData.searchTime, "%d:%d", &min, &sec);
 
1379
 
 
1380
        if (matched == 1)
 
1381
        {
 
1382
            searchTime = min * 60;
 
1383
        }
 
1384
        else if (matched == 2)
 
1385
        {
 
1386
            searchTime = min * 60 + sec;
 
1387
        }
 
1388
        else
 
1389
        {
 
1390
            fprintf(stderr, "%s: bad searchTime option %s\n",
 
1391
                    programName, player->appData.searchTime);
 
1392
            Usage();
 
1393
        }
 
1394
    }
 
1395
 
 
1396
    if ((player->appData.searchTime != NULL)
 
1397
        || (player->appData.searchDepth > 0)
 
1398
        || player->appData.noShogiProgram)
 
1399
    {
 
1400
        player->appData.clockMode = False;
 
1401
    }
 
1402
 
 
1403
    player->Iconic = False;
 
1404
    player->boardSize = Small;
 
1405
    player->squareSize = SMALL_SQUARE_SIZE;
 
1406
    player->flipView = (player == &remotePlayer);
 
1407
    player->promotionUp = False;
 
1408
 
 
1409
    /*
 
1410
     * Determine boardSize.
 
1411
     */
 
1412
 
 
1413
    if (strcasecmp(player->appData.boardSize, "Large") == 0)
 
1414
    {
 
1415
        player->boardSize = Large;
 
1416
    }
 
1417
    else if (strcasecmp(player->appData.boardSize, "Medium") == 0)
 
1418
    {
 
1419
        player->boardSize = Medium;
 
1420
    }
 
1421
    else if (strcasecmp(player->appData.boardSize, "Small") == 0)
 
1422
    {
 
1423
        player->boardSize = Small;
 
1424
    }
 
1425
    else
 
1426
    {
 
1427
        fprintf(stderr, "%s: bad boardSize option %s\n",
 
1428
                programName, player->appData.boardSize);
 
1429
        Usage();
 
1430
    }
 
1431
 
 
1432
    if ((local = (player == &localPlayer)))
 
1433
    {
 
1434
        player->xDisplay = XtDisplay(player->shellWidget);
 
1435
        player->xScreen = DefaultScreen(player->xDisplay);
 
1436
    }
 
1437
 
 
1438
    if (((DisplayWidth(player->xDisplay, player->xScreen) < 800)
 
1439
         || (DisplayHeight(player->xDisplay, player->xScreen) < 800))
 
1440
        && (player->boardSize == Large))
 
1441
    {
 
1442
        player->boardSize = Medium;
 
1443
    }
 
1444
 
 
1445
    switch (player->boardSize)
 
1446
    {
 
1447
    case Small:
 
1448
        player->squareSize = SMALL_SQUARE_SIZE;
 
1449
        mainFontPxlSize    = 11;
 
1450
        coordFontPxlSize   = 10;
 
1451
        break;
 
1452
 
 
1453
    case Medium:
 
1454
        player->squareSize = MEDIUM_SQUARE_SIZE;
 
1455
        mainFontPxlSize    = 17;
 
1456
        coordFontPxlSize   = 12;
 
1457
        break;
 
1458
 
 
1459
    default:
 
1460
    case Large:
 
1461
        player->squareSize = LARGE_SQUARE_SIZE;
 
1462
        mainFontPxlSize    = 17;
 
1463
        coordFontPxlSize   = 14;
 
1464
        break;
 
1465
    }
 
1466
 
 
1467
    /*
 
1468
     * Detect if there are not enough colors are available and adapt.
 
1469
     */
 
1470
 
 
1471
    if (DefaultDepth(player->xDisplay, player->xScreen) <= 2)
 
1472
        player->monoMode = True;
 
1473
 
 
1474
    /*
 
1475
     * Determine what fonts to use.
 
1476
     */
 
1477
 
 
1478
    player->appData.mainFont
 
1479
        = FindFont(player->appData.mainFont, mainFontPxlSize);
 
1480
    player->mainFontID
 
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);
 
1486
    player->coordFontID
 
1487
        = XLoadFont(player->xDisplay, player->appData.coordFont);
 
1488
    player->coordFontStruct
 
1489
        = XQueryFont(player->xDisplay, player->coordFontID);
 
1490
 
 
1491
    /*
 
1492
     * Set default arguments.
 
1493
     */
 
1494
 
 
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);
 
1501
 
 
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));
 
1509
 
 
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);
 
1517
 
 
1518
    XtSetArg(player->messageArgs[0], XtNborderWidth, 0);
 
1519
    XtSetArg(player->messageArgs[1], XtNjustify, (XtArgVal) XtJustifyLeft);
 
1520
    XtSetArg(player->messageArgs[2], XtNlabel, (XtArgVal) "starting...");
 
1521
 
 
1522
    XtSetArg(player->timerArgs[0], XtNborderWidth, 0);
 
1523
    XtSetArg(player->timerArgs[1], XtNjustify, (XtArgVal) XtJustifyLeft);
 
1524
 
 
1525
    XtSetArg(player->titleArgs[0], XtNborderWidth, 0);
 
1526
    XtSetArg(player->titleArgs[1], XtNjustify, (XtArgVal) XtJustifyLeft);
 
1527
 
 
1528
    boardWidth = LINE_GAP
 
1529
        + (BOARD_SIZE + 4) * (player->squareSize + LINE_GAP);
 
1530
 
 
1531
    XtSetArg(player->boardArgs[1], XtNwidth, boardWidth);
 
1532
    XtSetArg(player->boardArgs[2], XtNheight,
 
1533
             LINE_GAP + BOARD_SIZE * (player->squareSize + LINE_GAP));
 
1534
 
 
1535
    /*
 
1536
     * widget hierarchy
 
1537
     */
 
1538
 
 
1539
    player->formWidget = XtCreateManagedWidget("form",
 
1540
                                               formWidgetClass,
 
1541
                                               player->shellWidget, NULL, 0);
 
1542
 
 
1543
    player->widgetList[0] = player->blackTimerWidget
 
1544
        = XtCreateWidget((local ? "black time:" : "rblack time:"),
 
1545
                         labelWidgetClass,
 
1546
                         player->formWidget, player->timerArgs,
 
1547
                         XtNumber(player->timerArgs));
 
1548
 
 
1549
    XtSetArg(args[0], XtNfont, player->mainFontStruct);
 
1550
    XtSetValues(player->blackTimerWidget, args, 1);
 
1551
 
 
1552
    player->widgetList[1] = player->whiteTimerWidget
 
1553
        = XtCreateWidget((local ? "white time:" : "rwhite time:"),
 
1554
                         labelWidgetClass,
 
1555
                         player->formWidget, player->timerArgs,
 
1556
                         XtNumber(player->timerArgs));
 
1557
 
 
1558
    XtSetArg(args[0], XtNfont, player->mainFontStruct);
 
1559
    XtSetValues(player->whiteTimerWidget, args, 1);
 
1560
 
 
1561
    player->widgetList[2] = player->titleWidget
 
1562
        = XtCreateWidget((local ? "" : "r"), labelWidgetClass,
 
1563
                         player->formWidget, player->titleArgs,
 
1564
                         XtNumber(player->titleArgs));
 
1565
 
 
1566
    XtSetArg(args[0], XtNfont, player->mainFontStruct);
 
1567
    XtSetValues(player->titleWidget, args, 1);
 
1568
 
 
1569
    player->widgetList[3] = player->messageWidget
 
1570
        = XtCreateWidget((local ? "message" : "rmessage"),
 
1571
                         labelWidgetClass, player->formWidget,
 
1572
                         player->messageArgs,
 
1573
                         XtNumber(player->messageArgs));
 
1574
 
 
1575
    XtSetArg(args[0], XtNfont, player->mainFontStruct);
 
1576
    XtSetValues(player->messageWidget, args, 1);
 
1577
 
 
1578
    player->widgetList[4] = player->commandsWidget
 
1579
        = XtCreateWidget((local ? "commands" : "rcommand"),
 
1580
                         listWidgetClass, player->formWidget,
 
1581
                         player->commandsArgs,
 
1582
                         XtNumber(player->commandsArgs));
 
1583
 
 
1584
    player->widgetList[5] = player->boardWidget
 
1585
        = XtCreateWidget((local ? "board" : "rboard"),
 
1586
                         widgetClass, player->formWidget,
 
1587
                         player->boardArgs,
 
1588
                         XtNumber(player->boardArgs));
 
1589
 
 
1590
    XtManageChildren(player->widgetList, XtNumber(player->widgetList));
 
1591
 
 
1592
    /*
 
1593
     * Calculate the width of the timer labels.
 
1594
     */
 
1595
 
 
1596
    XtSetArg(args[0], XtNfont, &player->mainFontStruct);
 
1597
    XtGetValues(player->blackTimerWidget, args, 1);
 
1598
 
 
1599
    if (player->appData.clockMode)
 
1600
    {
 
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);
 
1606
    }
 
1607
    else
 
1608
    {
 
1609
        timerWidth = XTextWidth(player->mainFontStruct, "Black  ", 7);
 
1610
    }
 
1611
 
 
1612
    XtSetArg(args[0], XtNwidth, timerWidth);
 
1613
    XtSetValues(player->blackTimerWidget, args, 1);
 
1614
    XtSetValues(player->whiteTimerWidget, args, 1);
 
1615
 
 
1616
    XtSetArg(args[0], XtNbackground, &player->timerForegroundPixel);
 
1617
    XtSetArg(args[1], XtNforeground, &player->timerBackgroundPixel);
 
1618
    XtGetValues(player->blackTimerWidget, args, 2);
 
1619
 
 
1620
    /*
 
1621
     * Calculate the width of the name and message labels.
 
1622
     */
 
1623
 
 
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);
 
1631
 
 
1632
    /*
 
1633
     * formWidget uses these constraints but they are stored
 
1634
     * in the children.
 
1635
     */
 
1636
 
 
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);
 
1647
 
 
1648
    XtRealizeWidget(player->shellWidget);
 
1649
 
 
1650
    player->xBoardWindow = XtWindow(player->boardWidget);
 
1651
 
 
1652
    /*
 
1653
     * Create an icon.
 
1654
     */
 
1655
 
 
1656
    player->iconPixmap =
 
1657
        XCreateBitmapFromData(player->xDisplay,
 
1658
                              XtWindow(player->shellWidget),
 
1659
                              icon_bits, icon_width, icon_height);
 
1660
 
 
1661
    XtSetArg(args[0], XtNiconPixmap, player->iconPixmap);
 
1662
    XtSetValues(player->shellWidget, args, 1);
 
1663
 
 
1664
    /*
 
1665
     * Create a cursor for the board widget.
 
1666
     */
 
1667
 
 
1668
    window_attributes.cursor = XCreateFontCursor(player->xDisplay, XC_hand2);
 
1669
    XChangeWindowAttributes(player->xDisplay, player->xBoardWindow,
 
1670
                            CWCursor, &window_attributes);
 
1671
 
 
1672
    /*
 
1673
     * Inhibit shell resizing.
 
1674
     */
 
1675
 
 
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);
 
1682
 
 
1683
    /*
 
1684
     * Determine value of black pixel.
 
1685
     */
 
1686
 
 
1687
    player->black_pixel_is_zero =
 
1688
        (XBlackPixel(player->xDisplay, player->xScreen) == 0);
 
1689
 
 
1690
    CreateGCs();
 
1691
    CreateGrid();
 
1692
    CreatePieces();
 
1693
 
 
1694
    if (!fromRemotePlayer)
 
1695
        CreatePieceMenus();
 
1696
 
 
1697
    XtAddCallback(player->commandsWidget, XtNcallback, SelectCommand,
 
1698
                  (XtPointer)fromRemotePlayer);
 
1699
 
 
1700
    if (!fromRemotePlayer)
 
1701
        XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
 
1702
 
 
1703
    if (fromRemotePlayer)
 
1704
    {
 
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);
 
1711
    }
 
1712
    else
 
1713
    {
 
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);
 
1723
    }
 
1724
 
 
1725
    XtAddEventHandler(player->boardWidget, ExposureMask | ButtonPressMask
 
1726
                      | ButtonReleaseMask | Button1MotionMask | KeyPressMask,
 
1727
                      False, (XtEventHandler)EventProc,
 
1728
                      (XtPointer)(player == &remotePlayer));
 
1729
 
 
1730
    sprintf(buf, "xshogi version %s, patchlevel %s based on "
 
1731
            "xboard version %s",
 
1732
            version, patchlevel, XBOARD_VERSION);
 
1733
 
 
1734
    /*
 
1735
     * If there is to be a machine match, set it up.
 
1736
     */
 
1737
 
 
1738
    if (matchMode != MatchFalse && player != &remotePlayer)
 
1739
    {
 
1740
        if (player->appData.noShogiProgram)
 
1741
        {
 
1742
            fprintf(stderr,
 
1743
                    "%s: can't have a match with no shogi programs!\n",
 
1744
                    programName);
 
1745
            exit(1);
 
1746
        }
 
1747
 
 
1748
        DisplayMessage(buf, fromRemotePlayer);
 
1749
        TwoMachinesProc(NULL, NULL, NULL, NULL);
 
1750
    }
 
1751
    else
 
1752
    {
 
1753
        Reset(True);
 
1754
        DisplayMessage(buf, fromRemotePlayer);
 
1755
    }
 
1756
}
 
1757
 
 
1758
 
 
1759
 
 
1760
 
 
1761
int
 
1762
main(int argc, char **argv)
 
1763
{
 
1764
    setbuf(stdout, NULL);
 
1765
    setbuf(stderr, NULL);
 
1766
 
 
1767
    /*
 
1768
     * Copy pointers to command line arguments and number of such pointers.
 
1769
     * (argc, argv will be destroyed by XtAppInitialize)
 
1770
     */
 
1771
 
 
1772
    for (global_argc = 0; global_argc < argc; global_argc++)
 
1773
        global_argv[global_argc] = argv[global_argc];
 
1774
 
 
1775
    programName = strrchr(argv[0], '/');
 
1776
 
 
1777
    if (programName == NULL)
 
1778
        programName = argv[0];
 
1779
    else
 
1780
        programName++;
 
1781
 
 
1782
    localPlayer.shellWidget
 
1783
        = XtAppInitialize(&appContext, "XShogi", shellOptions,
 
1784
                          XtNumber(shellOptions), &argc, argv,
 
1785
                          xshogiResources, NULL, 0);
 
1786
 
 
1787
    if (argc > 1)
 
1788
        Usage();
 
1789
 
 
1790
    if ((shogiDir = (char *)getenv("SHOGIDIR")) == NULL)
 
1791
    {
 
1792
        shogiDir = ".";
 
1793
    }
 
1794
    else
 
1795
    {
 
1796
        if (chdir(shogiDir) != 0)
 
1797
        {
 
1798
            fprintf(stderr, "%s: can't cd to SHOGIDIR\n",
 
1799
                    programName);
 
1800
            perror(shogiDir);
 
1801
            exit(1);
 
1802
        }
 
1803
    }
 
1804
 
 
1805
    XtGetApplicationResources(localPlayer.shellWidget,
 
1806
                              &localPlayer.appData, clientResources,
 
1807
                              XtNumber(clientResources), NULL, 0);
 
1808
 
 
1809
    xshogiDebug = localPlayer.appData.debugMode;
 
1810
 
 
1811
    /*
 
1812
     * Determine matchMode state -- poor man's resource converter
 
1813
     */
 
1814
 
 
1815
    if (strcasecmp(localPlayer.appData.matchMode, "Init") == 0)
 
1816
    {
 
1817
        matchMode = MatchInit;
 
1818
    }
 
1819
    else if (strcasecmp(localPlayer.appData.matchMode, "Position") == 0)
 
1820
    {
 
1821
        matchMode = MatchPosition;
 
1822
    }
 
1823
    else if (strcasecmp(localPlayer.appData.matchMode, "Opening") == 0)
 
1824
    {
 
1825
        matchMode = MatchOpening;
 
1826
    }
 
1827
    else if (strcasecmp(localPlayer.appData.matchMode, "False") == 0)
 
1828
    {
 
1829
        matchMode = MatchFalse;
 
1830
    }
 
1831
    else
 
1832
    {
 
1833
        fprintf(stderr, "%s: bad matchMode option %s\n",
 
1834
                programName, localPlayer.appData.matchMode);
 
1835
        Usage();
 
1836
    }
 
1837
 
 
1838
    buttonStrings = gnuButtonStrings;
 
1839
    buttonProcs = gnuButtonProcs;
 
1840
    buttonCount = XtNumber(gnuButtonStrings);
 
1841
 
 
1842
    player = &localPlayer;
 
1843
 
 
1844
    CreatePlayerWindow();
 
1845
 
 
1846
    XtAppMainLoop(appContext);
 
1847
 
 
1848
    return 0;
 
1849
}
 
1850
 
 
1851
 
 
1852
 
 
1853
/*
 
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
 
1860
 * longer needed.
 
1861
 */
 
1862
 
 
1863
char *
 
1864
FindFont(char *pattern, int targetPxlSize)
 
1865
{
 
1866
    char **fonts, *p, *best;
 
1867
    int i, j, nfonts, minerr, err, pxlSize;
 
1868
 
 
1869
    fonts = XListFonts(player->xDisplay, pattern, 999999, &nfonts);
 
1870
 
 
1871
    if (nfonts < 1)
 
1872
    {
 
1873
        fprintf(stderr, "%s: No fonts match pattern %s\n",
 
1874
                programName, pattern);
 
1875
        exit(1);
 
1876
    }
 
1877
 
 
1878
    best = "";
 
1879
    minerr = 999999;
 
1880
 
 
1881
    for (i = 0; i < nfonts; i++)
 
1882
    {
 
1883
        j = 0;
 
1884
        p = fonts[i];
 
1885
 
 
1886
        if (*p != '-')
 
1887
            continue;
 
1888
 
 
1889
        while (j < 7)
 
1890
        {
 
1891
            if (*p == NULLCHAR)
 
1892
                break;
 
1893
 
 
1894
            if (*p++ == '-')
 
1895
                j++;
 
1896
        }
 
1897
 
 
1898
        if (j < 7)
 
1899
            continue;
 
1900
 
 
1901
        pxlSize = atoi(p);
 
1902
 
 
1903
        if (pxlSize == targetPxlSize)
 
1904
        {
 
1905
            best = fonts[i];
 
1906
            break;
 
1907
        }
 
1908
 
 
1909
        err = pxlSize - targetPxlSize;
 
1910
 
 
1911
        if (abs(err) < abs(minerr)
 
1912
            || ((minerr > 0) && (err < 0) && (-err == minerr)))
 
1913
        {
 
1914
            best = fonts[i];
 
1915
            minerr = err;
 
1916
        }
 
1917
    }
 
1918
 
 
1919
    p = (char *)XtMalloc(strlen(best) + 1);
 
1920
    strcpy(p, best);
 
1921
    XFreeFontNames(fonts);
 
1922
    return p;
 
1923
}
 
1924
 
 
1925
 
 
1926
 
 
1927
 
 
1928
void
 
1929
CreateGCs(void)
 
1930
{
 
1931
    XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
 
1932
        | GCBackground | GCFunction | GCPlaneMask;
 
1933
    XGCValues gc_values;
 
1934
 
 
1935
    gc_values.plane_mask = AllPlanes;
 
1936
    gc_values.line_width = LINE_GAP;
 
1937
    gc_values.line_style = LineSolid;
 
1938
    gc_values.function = GXcopy;
 
1939
 
 
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);
 
1943
 
 
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);
 
1947
 
 
1948
    if (player->monoMode)
 
1949
    {
 
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);
 
1960
        player->bwPieceGC
 
1961
            = XtGetGC(player->shellWidget, value_mask, &gc_values);
 
1962
    }
 
1963
    else
 
1964
    {
 
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);
 
1970
        player->wbPieceGC
 
1971
            = XtGetGC(player->shellWidget, value_mask, &gc_values);
 
1972
 
 
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);
 
1978
        player->bwPieceGC
 
1979
            = XtGetGC(player->shellWidget, value_mask, &gc_values);
 
1980
 
 
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);
 
1988
 
 
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);
 
1996
 
 
1997
        /* black piece on dark square */
 
1998
        gc_values.background
 
1999
            = player->appData.blackPieceColor;
 
2000
        gc_values.foreground
 
2001
            = player->appData.darkSquareColor;
 
2002
        player->bdPieceGC
 
2003
            = XtGetGC(player->shellWidget, value_mask, &gc_values);
 
2004
 
 
2005
        /* black piece on light square */
 
2006
        gc_values.background
 
2007
            = player->appData.blackPieceColor;
 
2008
        gc_values.foreground
 
2009
            = player->appData.lightSquareColor;
 
2010
        player->blPieceGC
 
2011
            = XtGetGC(player->shellWidget, value_mask, &gc_values);
 
2012
 
 
2013
        /* white piece on dark square */
 
2014
        gc_values.background
 
2015
            = player->appData.whitePieceColor;
 
2016
        gc_values.foreground
 
2017
            = player->appData.darkSquareColor;
 
2018
        player->wdPieceGC
 
2019
            = XtGetGC(player->shellWidget,  value_mask, &gc_values);
 
2020
 
 
2021
        /* white piece on dark square */
 
2022
        gc_values.background
 
2023
            = player->appData.whitePieceColor;
 
2024
        gc_values.foreground
 
2025
            = player->appData.lightSquareColor;
 
2026
        player->wlPieceGC
 
2027
            = XtGetGC(player->shellWidget, value_mask, &gc_values);
 
2028
 
 
2029
        /* black piece off board */
 
2030
        gc_values.background
 
2031
            = player->appData.blackPieceColor;
 
2032
        gc_values.foreground
 
2033
            = XWhitePixel(player->xDisplay, player->xScreen);
 
2034
        player->boPieceGC
 
2035
            = XtGetGC(player->shellWidget, value_mask, &gc_values);
 
2036
 
 
2037
        /* white piece off board */
 
2038
        gc_values.background
 
2039
            = player->appData.whitePieceColor;
 
2040
        gc_values.foreground
 
2041
            = XWhitePixel(player->xDisplay, player->xScreen);
 
2042
        player->woPieceGC
 
2043
            = XtGetGC(player->shellWidget, value_mask, &gc_values);
 
2044
 
 
2045
        /* piece symbol */
 
2046
        gc_values.function = (player->black_pixel_is_zero ? GXand : GXor);
 
2047
 
 
2048
        gc_values.foreground
 
2049
            = XBlackPixel(player->xDisplay, player->xScreen);
 
2050
        gc_values.background
 
2051
            = XWhitePixel(player->xDisplay, player->xScreen);
 
2052
        player->charPieceGC
 
2053
            = XtGetGC(player->shellWidget, value_mask, &gc_values);
 
2054
    }
 
2055
}
 
2056
 
 
2057
 
 
2058
 
 
2059
 
 
2060
void
 
2061
CreatePieces(void)
 
2062
{
 
2063
    XSynchronize(player->xDisplay, True);   /* Work-around for xlib/xt
 
2064
                                               buffering bug */
 
2065
 
 
2066
    if (player->appData.westernPieceSet)
 
2067
    {
 
2068
        ReadBitmap(player->appData.reverseBigSolidBitmap,
 
2069
                   &player->reverseBigSolidBitmap,
 
2070
                   NULL,
 
2071
                   bigsolidR_bits, bigsolidR_bits, bigsolidR_bits);
 
2072
 
 
2073
        ReadBitmap(player->appData.reverseSmallSolidBitmap,
 
2074
                   &player->reverseSmallSolidBitmap,
 
2075
                   NULL,
 
2076
                   smallsolidR_bits, smallsolidR_bits, smallsolidR_bits);
 
2077
 
 
2078
        ReadBitmap(player->appData.normalBigSolidBitmap,
 
2079
                   &player->normalBigSolidBitmap,
 
2080
                   NULL,
 
2081
                   bigsolid_bits, bigsolid_bits, bigsolid_bits);
 
2082
 
 
2083
        ReadBitmap(player->appData.normalSmallSolidBitmap,
 
2084
                   &player->normalSmallSolidBitmap,
 
2085
                   NULL,
 
2086
                   smallsolid_bits, smallsolid_bits, smallsolid_bits);
 
2087
 
 
2088
        ReadBitmap(player->appData.reversePawnBitmap,
 
2089
                   &player->reversePawnBitmap,
 
2090
                   &player->reverseSmallSolidBitmap,
 
2091
                   pawnRW_bits, pawnRW_bits, pawnRW_bits);
 
2092
 
 
2093
        ReadBitmap(player->appData.reverseLanceBitmap,
 
2094
                   &player->reverseLanceBitmap,
 
2095
                   &player->reverseSmallSolidBitmap,
 
2096
                   lanceRW_bits, lanceRW_bits, lanceRW_bits);
 
2097
 
 
2098
        ReadBitmap(player->appData.reverseKnightBitmap,
 
2099
                   &player->reverseKnightBitmap,
 
2100
                   &player->reverseSmallSolidBitmap,
 
2101
                   knightRW_bits, knightRW_bits, knightRW_bits);
 
2102
 
 
2103
        ReadBitmap(player->appData.reverseSilverBitmap,
 
2104
                   &player->reverseSilverBitmap,
 
2105
                   &player->reverseBigSolidBitmap,
 
2106
                   silverRW_bits, silverRW_bits, silverRW_bits);
 
2107
 
 
2108
        ReadBitmap(player->appData.reverseGoldBitmap,
 
2109
                   &player->reverseGoldBitmap,
 
2110
                   &player->reverseBigSolidBitmap,
 
2111
                   goldRW_bits, goldRW_bits, goldRW_bits);
 
2112
 
 
2113
        ReadBitmap(player->appData.reverseRookBitmap,
 
2114
                   &player->reverseRookBitmap,
 
2115
                   &player->reverseBigSolidBitmap,
 
2116
                   rookRW_bits, rookRW_bits, rookRW_bits);
 
2117
 
 
2118
        ReadBitmap(player->appData.reverseBishopBitmap,
 
2119
                   &player->reverseBishopBitmap,
 
2120
                   &player->reverseBigSolidBitmap,
 
2121
                   bishopRW_bits, bishopRW_bits, bishopRW_bits);
 
2122
 
 
2123
        ReadBitmap(player->appData.reversePPawnBitmap,
 
2124
                   &player->reversePPawnBitmap,
 
2125
                   &player->reverseSmallSolidBitmap,
 
2126
                   pawnPRW_bits, pawnPRW_bits, pawnPRW_bits);
 
2127
 
 
2128
        ReadBitmap(player->appData.reversePLanceBitmap,
 
2129
                   &player->reversePLanceBitmap,
 
2130
                   &player->reverseSmallSolidBitmap,
 
2131
                   lancePRW_bits, lancePRW_bits, lancePRW_bits);
 
2132
 
 
2133
        ReadBitmap(player->appData.reversePKnightBitmap,
 
2134
                   &player->reversePKnightBitmap,
 
2135
                   &player->reverseSmallSolidBitmap,
 
2136
                   knightPRW_bits, knightPRW_bits, knightPRW_bits);
 
2137
 
 
2138
        ReadBitmap(player->appData.reversePSilverBitmap,
 
2139
                   &player->reversePSilverBitmap,
 
2140
                   &player->reverseBigSolidBitmap,
 
2141
                   silverPRW_bits, silverPRW_bits, silverPRW_bits);
 
2142
 
 
2143
        ReadBitmap(player->appData.reversePRookBitmap,
 
2144
                   &player->reversePRookBitmap,
 
2145
                   &player->reverseBigSolidBitmap,
 
2146
                   rookPRW_bits, rookPRW_bits, rookPRW_bits);
 
2147
 
 
2148
        ReadBitmap(player->appData.reversePBishopBitmap,
 
2149
                   &player->reversePBishopBitmap,
 
2150
                   &player->reverseBigSolidBitmap,
 
2151
                   bishopPRW_bits, bishopPRW_bits, bishopPRW_bits);
 
2152
 
 
2153
        ReadBitmap(player->appData.reverseKingBitmap,
 
2154
                   &player->reverseKingBitmap,
 
2155
                   &player->reverseBigSolidBitmap,
 
2156
                   kingRW_bits, kingRW_bits, kingRW_bits);
 
2157
 
 
2158
        ReadBitmap(player->appData.normalPawnBitmap,
 
2159
                   &player->normalPawnBitmap,
 
2160
                   &player->normalSmallSolidBitmap,
 
2161
                   pawnW_bits, pawnW_bits, pawnW_bits);
 
2162
 
 
2163
        ReadBitmap(player->appData.normalLanceBitmap,
 
2164
                   &player->normalLanceBitmap,
 
2165
                   &player->normalSmallSolidBitmap,
 
2166
                   lanceW_bits, lanceW_bits, lanceW_bits);
 
2167
 
 
2168
        ReadBitmap(player->appData.normalKnightBitmap,
 
2169
                   &player->normalKnightBitmap,
 
2170
                   &player->normalSmallSolidBitmap,
 
2171
                   knightW_bits, knightW_bits, knightW_bits);
 
2172
 
 
2173
        ReadBitmap(player->appData.normalSilverBitmap,
 
2174
                   &player->normalSilverBitmap,
 
2175
                   &player->normalBigSolidBitmap,
 
2176
                   silverW_bits, silverW_bits, silverW_bits);
 
2177
 
 
2178
        ReadBitmap(player->appData.normalGoldBitmap,
 
2179
                   &player->normalGoldBitmap,
 
2180
                   &player->normalBigSolidBitmap,
 
2181
                   goldW_bits, goldW_bits, goldW_bits);
 
2182
 
 
2183
        ReadBitmap(player->appData.normalRookBitmap,
 
2184
                   &player->normalRookBitmap,
 
2185
                   &player->normalBigSolidBitmap,
 
2186
                   rookW_bits, rookW_bits, rookW_bits);
 
2187
 
 
2188
        ReadBitmap(player->appData.normalBishopBitmap,
 
2189
                   &player->normalBishopBitmap,
 
2190
                   &player->normalBigSolidBitmap,
 
2191
                   bishopW_bits, bishopW_bits, bishopW_bits);
 
2192
 
 
2193
        ReadBitmap(player->appData.normalPPawnBitmap,
 
2194
                   &player->normalPPawnBitmap,
 
2195
                   &player->normalSmallSolidBitmap,
 
2196
                   pawnPW_bits, pawnPW_bits, pawnPW_bits);
 
2197
 
 
2198
        ReadBitmap(player->appData.normalPLanceBitmap,
 
2199
                   &player->normalPLanceBitmap,
 
2200
                   &player->normalSmallSolidBitmap,
 
2201
                   lancePW_bits, lancePW_bits, lancePW_bits);
 
2202
 
 
2203
        ReadBitmap(player->appData.normalPKnightBitmap,
 
2204
                   &player->normalPKnightBitmap,
 
2205
                   &player->normalSmallSolidBitmap,
 
2206
                   knightPW_bits, knightPW_bits, knightPW_bits);
 
2207
 
 
2208
        ReadBitmap(player->appData.normalPSilverBitmap,
 
2209
                   &player->normalPSilverBitmap,
 
2210
                   &player->normalBigSolidBitmap,
 
2211
                   silverPW_bits, silverPW_bits, silverPW_bits);
 
2212
 
 
2213
        ReadBitmap(player->appData.normalPRookBitmap,
 
2214
                   &player->normalPRookBitmap,
 
2215
                   &player->normalBigSolidBitmap,
 
2216
                   rookPW_bits, rookPW_bits, rookPW_bits);
 
2217
 
 
2218
        ReadBitmap(player->appData.normalPBishopBitmap,
 
2219
                   &player->normalPBishopBitmap,
 
2220
                   &player->normalBigSolidBitmap,
 
2221
                   bishopPW_bits, bishopPW_bits, bishopPW_bits);
 
2222
 
 
2223
        ReadBitmap(player->appData.normalKingBitmap,
 
2224
                   &player->normalKingBitmap,
 
2225
                   &player->normalBigSolidBitmap,
 
2226
                   kingW_bits, kingW_bits, kingW_bits);
 
2227
    }
 
2228
    else
 
2229
    {
 
2230
        ReadBitmap(player->appData.reverseBigSolidBitmap,
 
2231
                   &player->reverseBigSolidBitmap,
 
2232
                   NULL,
 
2233
                   bigsolidR_bits, bigsolidR_m_bits, bigsolidR_l_bits);
 
2234
 
 
2235
        ReadBitmap(player->appData.reverseSmallSolidBitmap,
 
2236
                   &player->reverseSmallSolidBitmap,
 
2237
                   NULL,
 
2238
                   smallsolidR_bits, smallsolidR_m_bits, smallsolidR_l_bits);
 
2239
 
 
2240
        ReadBitmap(player->appData.normalBigSolidBitmap,
 
2241
                   &player->normalBigSolidBitmap,
 
2242
                   NULL,
 
2243
                   bigsolid_bits, bigsolid_m_bits, bigsolid_l_bits);
 
2244
 
 
2245
        ReadBitmap(player->appData.normalSmallSolidBitmap,
 
2246
                   &player->normalSmallSolidBitmap,
 
2247
                   NULL,
 
2248
                   smallsolid_bits, smallsolid_m_bits, smallsolid_l_bits);
 
2249
 
 
2250
        ReadBitmap(player->appData.reversePawnBitmap,
 
2251
                   &player->reversePawnBitmap,
 
2252
                   &player->reverseSmallSolidBitmap,
 
2253
                   pawnR_bits, pawnR_m_bits, pawnR_l_bits);
 
2254
 
 
2255
        ReadBitmap(player->appData.reverseLanceBitmap,
 
2256
                   &player->reverseLanceBitmap,
 
2257
                   &player->reverseSmallSolidBitmap,
 
2258
                   lanceR_bits, lanceR_m_bits, lanceR_l_bits);
 
2259
 
 
2260
        ReadBitmap(player->appData.reverseKnightBitmap,
 
2261
                   &player->reverseKnightBitmap,
 
2262
                   &player->reverseSmallSolidBitmap,
 
2263
                   knightR_bits, knightR_m_bits, knightR_l_bits);
 
2264
 
 
2265
        ReadBitmap(player->appData.reverseSilverBitmap,
 
2266
                   &player->reverseSilverBitmap,
 
2267
                   &player->reverseBigSolidBitmap,
 
2268
                   silverR_bits, silverR_m_bits, silverR_l_bits);
 
2269
 
 
2270
        ReadBitmap(player->appData.reverseGoldBitmap,
 
2271
                   &player->reverseGoldBitmap,
 
2272
                   &player->reverseBigSolidBitmap,
 
2273
                   goldR_bits, goldR_m_bits, goldR_l_bits);
 
2274
 
 
2275
        ReadBitmap(player->appData.reverseRookBitmap,
 
2276
                   &player->reverseRookBitmap,
 
2277
                   &player->reverseBigSolidBitmap,
 
2278
                   rookR_bits, rookR_m_bits, rookR_l_bits);
 
2279
 
 
2280
        ReadBitmap(player->appData.reverseBishopBitmap,
 
2281
                   &player->reverseBishopBitmap,
 
2282
                   &player->reverseBigSolidBitmap,
 
2283
                   bishopR_bits, bishopR_m_bits, bishopR_l_bits);
 
2284
 
 
2285
        ReadBitmap(player->appData.reversePPawnBitmap,
 
2286
                   &player->reversePPawnBitmap,
 
2287
                   &player->reverseSmallSolidBitmap,
 
2288
                   pawnPR_bits, pawnPR_m_bits, pawnPR_l_bits);
 
2289
 
 
2290
        ReadBitmap(player->appData.reversePLanceBitmap,
 
2291
                   &player->reversePLanceBitmap,
 
2292
                   &player->reverseSmallSolidBitmap,
 
2293
                   lancePR_bits, lancePR_m_bits, lancePR_l_bits);
 
2294
 
 
2295
        ReadBitmap(player->appData.reversePKnightBitmap,
 
2296
                   &player->reversePKnightBitmap,
 
2297
                   &player->reverseSmallSolidBitmap,
 
2298
                   knightPR_bits, knightPR_m_bits, knightPR_l_bits);
 
2299
 
 
2300
        ReadBitmap(player->appData.reversePSilverBitmap,
 
2301
                   &player->reversePSilverBitmap,
 
2302
                   &player->reverseBigSolidBitmap,
 
2303
                   silverPR_bits, silverPR_m_bits, silverPR_l_bits);
 
2304
 
 
2305
        ReadBitmap(player->appData.reversePRookBitmap,
 
2306
                   &player->reversePRookBitmap,
 
2307
                   &player->reverseBigSolidBitmap,
 
2308
                   rookPR_bits, rookPR_m_bits, rookPR_l_bits);
 
2309
 
 
2310
        ReadBitmap(player->appData.reversePBishopBitmap,
 
2311
                   &player->reversePBishopBitmap,
 
2312
                   &player->reverseBigSolidBitmap,
 
2313
                   bishopPR_bits, bishopPR_m_bits, bishopPR_l_bits);
 
2314
 
 
2315
        ReadBitmap(player->appData.reverseKingBitmap,
 
2316
                   &player->reverseKingBitmap,
 
2317
                   &player->reverseBigSolidBitmap,
 
2318
                   kingR_bits, kingR_m_bits, kingR_l_bits);
 
2319
 
 
2320
        ReadBitmap(player->appData.normalPawnBitmap,
 
2321
                   &player->normalPawnBitmap,
 
2322
                   &player->normalSmallSolidBitmap,
 
2323
                   pawn_bits, pawn_m_bits, pawn_l_bits);
 
2324
 
 
2325
        ReadBitmap(player->appData.normalLanceBitmap,
 
2326
                   &player->normalLanceBitmap,
 
2327
                   &player->normalSmallSolidBitmap,
 
2328
                   lance_bits, lance_m_bits, lance_l_bits);
 
2329
 
 
2330
        ReadBitmap(player->appData.normalKnightBitmap,
 
2331
                   &player->normalKnightBitmap,
 
2332
                   &player->normalSmallSolidBitmap,
 
2333
                   knight_bits, knight_m_bits, knight_l_bits);
 
2334
 
 
2335
        ReadBitmap(player->appData.normalSilverBitmap,
 
2336
                   &player->normalSilverBitmap,
 
2337
                   &player->normalBigSolidBitmap,
 
2338
                   silver_bits, silver_m_bits, silver_l_bits);
 
2339
 
 
2340
        ReadBitmap(player->appData.normalGoldBitmap,
 
2341
                   &player->normalGoldBitmap,
 
2342
                   &player->normalBigSolidBitmap,
 
2343
                   gold_bits, gold_m_bits, gold_l_bits);
 
2344
 
 
2345
        ReadBitmap(player->appData.normalRookBitmap,
 
2346
                   &player->normalRookBitmap,
 
2347
                   &player->normalBigSolidBitmap,
 
2348
                   rook_bits, rook_m_bits, rook_l_bits);
 
2349
 
 
2350
        ReadBitmap(player->appData.normalBishopBitmap,
 
2351
                   &player->normalBishopBitmap,
 
2352
                   &player->normalBigSolidBitmap,
 
2353
                   bishop_bits, bishop_m_bits, bishop_l_bits);
 
2354
 
 
2355
        ReadBitmap(player->appData.normalPPawnBitmap,
 
2356
                   &player->normalPPawnBitmap,
 
2357
                   &player->normalSmallSolidBitmap,
 
2358
                   pawnP_bits, pawnP_m_bits, pawnP_l_bits);
 
2359
 
 
2360
        ReadBitmap(player->appData.normalPLanceBitmap,
 
2361
                   &player->normalPLanceBitmap,
 
2362
                   &player->normalSmallSolidBitmap,
 
2363
                   lanceP_bits, lanceP_m_bits, lanceP_l_bits);
 
2364
 
 
2365
        ReadBitmap(player->appData.normalPKnightBitmap,
 
2366
                   &player->normalPKnightBitmap,
 
2367
                   &player->normalSmallSolidBitmap,
 
2368
                   knightP_bits, knightP_m_bits, knightP_l_bits);
 
2369
 
 
2370
        ReadBitmap(player->appData.normalPSilverBitmap,
 
2371
                   &player->normalPSilverBitmap,
 
2372
                   &player->normalBigSolidBitmap,
 
2373
                   silverP_bits, silverP_m_bits, silverP_l_bits);
 
2374
 
 
2375
        ReadBitmap(player->appData.normalPRookBitmap,
 
2376
                   &player->normalPRookBitmap,
 
2377
                   &player->normalBigSolidBitmap,
 
2378
                   rookP_bits, rookP_m_bits, rookP_l_bits);
 
2379
 
 
2380
        ReadBitmap(player->appData.normalPBishopBitmap,
 
2381
                   &player->normalPBishopBitmap,
 
2382
                   &player->normalBigSolidBitmap,
 
2383
                   bishopP_bits, bishopP_m_bits, bishopP_l_bits);
 
2384
 
 
2385
        ReadBitmap(player->appData.normalKingBitmap,
 
2386
                   &player->normalKingBitmap,
 
2387
                   &player->normalBigSolidBitmap,
 
2388
                   king_bits, king_m_bits, king_l_bits);
 
2389
 
 
2390
    }
 
2391
 
 
2392
    XSynchronize(player->xDisplay, False);  /* Work-around for xlib/xt
 
2393
                                               buffering bug */
 
2394
}
 
2395
 
 
2396
 
 
2397
 
 
2398
 
 
2399
int
 
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)
 
2405
{
 
2406
    int n;
 
2407
 
 
2408
    if ((n = XReadBitmapFile(display, d, filename,
 
2409
                             width_return, height_return,
 
2410
                             bitmap_return, x_hot_return, y_hot_return))
 
2411
        != BitmapSuccess)
 
2412
    {
 
2413
        return n;
 
2414
    }
 
2415
    else
 
2416
    {
 
2417
        /* transform a 1 plane pixmap to a k plane pixmap */
 
2418
        return BitmapSuccess;
 
2419
    }
 
2420
}
 
2421
 
 
2422
 
 
2423
 
 
2424
 
 
2425
/*
 
2426
 * Create the X pixmap from .xbm file bitmap data.  This may
 
2427
 * have to be revised considerably.
 
2428
 */
 
2429
 
 
2430
void
 
2431
ReadBitmap(String name, Pixmap *pm, Pixmap *qm,
 
2432
           char *small_bits, char *medium_bits, char *large_bits)
 
2433
{
 
2434
    int x_hot, y_hot;
 
2435
    u_int w, h;
 
2436
 
 
2437
    if ((name == NULL)
 
2438
        || (ReadBitmapFile(player->xDisplay, player->xBoardWindow, name,
 
2439
                          &w, &h, pm, &x_hot, &y_hot) != BitmapSuccess)
 
2440
        || (w != player->squareSize)
 
2441
        || (h != player->squareSize))
 
2442
    {
 
2443
        unsigned long fg, bg;
 
2444
        unsigned int depth;
 
2445
 
 
2446
        depth = DisplayPlanes(player->xDisplay, player->xScreen);
 
2447
 
 
2448
        if (player->monoMode)
 
2449
        {
 
2450
            fg = XBlackPixel(player->xDisplay, player->xScreen);
 
2451
            bg = XWhitePixel(player->xDisplay, player->xScreen);
 
2452
        }
 
2453
        else if (qm == NULL)
 
2454
        {
 
2455
            fg = player->appData.oneColor;
 
2456
            bg = player->appData.zeroColor;
 
2457
        }
 
2458
        else
 
2459
        {
 
2460
            fg = (player->black_pixel_is_zero ? 0 : ~0);
 
2461
            bg = (player->black_pixel_is_zero ? ~0 : 0);
 
2462
        }
 
2463
 
 
2464
        switch (player->boardSize)
 
2465
        {
 
2466
        case Large:
 
2467
            *pm = XCreatePixmapFromBitmapData(player->xDisplay,
 
2468
                                              player->xBoardWindow,
 
2469
                                              large_bits,
 
2470
                                              player->squareSize,
 
2471
                                              player->squareSize,
 
2472
                                              fg, bg, depth);
 
2473
            break;
 
2474
 
 
2475
        case Medium:
 
2476
            *pm = XCreatePixmapFromBitmapData(player->xDisplay,
 
2477
                                              player->xBoardWindow,
 
2478
                                              medium_bits,
 
2479
                                              player->squareSize,
 
2480
                                              player->squareSize,
 
2481
                                              fg, bg, depth);
 
2482
            break;
 
2483
 
 
2484
        case Small:
 
2485
            *pm = XCreatePixmapFromBitmapData(player->xDisplay,
 
2486
                                              player->xBoardWindow,
 
2487
                                              small_bits,
 
2488
                                              player->squareSize,
 
2489
                                              player->squareSize,
 
2490
                                              fg, bg, depth);
 
2491
            break;
 
2492
        }
 
2493
    }
 
2494
}
 
2495
 
 
2496
 
 
2497
 
 
2498
 
 
2499
void
 
2500
CreateGrid(void)
 
2501
{
 
2502
    int i, offset;
 
2503
 
 
2504
    offset = 2 * (player->squareSize + LINE_GAP);
 
2505
 
 
2506
    for (i = 0; i < BOARD_SIZE + 1; i++)
 
2507
    {
 
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);
 
2519
    }
 
2520
}
 
2521
 
 
2522
 
 
2523
 
 
2524
 
 
2525
void
 
2526
CreatePieceMenus(void)
 
2527
{
 
2528
    int i;
 
2529
    Widget entry;
 
2530
    Arg args[1];
 
2531
    ShogiSquare selection;
 
2532
 
 
2533
    XtSetArg(args[0], XtNlabel, "Black");
 
2534
    blackPieceMenu = XtCreatePopupShell("menuW", simpleMenuWidgetClass,
 
2535
                                        localPlayer.boardWidget, args, 1);
 
2536
 
 
2537
    for (i = 0; i < PIECE_MENU_SIZE; i++)
 
2538
    {
 
2539
        String item = pieceMenuStrings[i];
 
2540
 
 
2541
        if (strcmp(item, "----") == 0)
 
2542
        {
 
2543
            entry = XtCreateManagedWidget(item, smeLineObjectClass,
 
2544
                                          blackPieceMenu, NULL, 0);
 
2545
        }
 
2546
        else
 
2547
        {
 
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);
 
2554
 
 
2555
            if (selection == BlackPawn)
 
2556
            {
 
2557
                XtSetArg(args[0], XtNpopupOnEntry, entry);
 
2558
                XtSetValues(blackPieceMenu, args, 1);
 
2559
            }
 
2560
        }
 
2561
    }
 
2562
 
 
2563
    XtSetArg(args[0], XtNlabel, "White");
 
2564
    whitePieceMenu = XtCreatePopupShell("menuB", simpleMenuWidgetClass,
 
2565
                                        localPlayer.boardWidget, args, 1);
 
2566
 
 
2567
    for (i = 0; i < PIECE_MENU_SIZE; i++)
 
2568
    {
 
2569
        String item = pieceMenuStrings[i];
 
2570
 
 
2571
        if (strcmp(item, "----") == 0)
 
2572
        {
 
2573
            entry = XtCreateManagedWidget(item, smeLineObjectClass,
 
2574
                                          whitePieceMenu, NULL, 0);
 
2575
        }
 
2576
        else
 
2577
        {
 
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);
 
2584
 
 
2585
            if (selection == WhitePawn)
 
2586
            {
 
2587
                XtSetArg(args[0], XtNpopupOnEntry, entry);
 
2588
                XtSetValues(whitePieceMenu, args, 1);
 
2589
            }
 
2590
        }
 
2591
    }
 
2592
 
 
2593
    XtRegisterGrabAction(PieceMenuPopup, True,
 
2594
                         (unsigned)(ButtonPressMask|ButtonReleaseMask),
 
2595
                         GrabModeAsync, GrabModeAsync);
 
2596
}
 
2597
 
 
2598
 
 
2599
 
 
2600
 
 
2601
void
 
2602
PieceMenuPopup(Widget w, XEvent *event, String *params, Cardinal *num_params)
 
2603
{
 
2604
    if (event->type != ButtonPress) 
 
2605
        return;
 
2606
 
 
2607
    if (gameMode != EditPosition) 
 
2608
        return;
 
2609
 
 
2610
    if (((pmFromX = EventToXSquare(event->xbutton.x)) < 1) 
 
2611
        || (pmFromX > BOARD_SIZE + 2) 
 
2612
        || ((pmFromY = EventToSquare(event->xbutton.y)) < 0))
 
2613
    {
 
2614
        pmFromX = pmFromY = -1;
 
2615
        return;
 
2616
    }
 
2617
 
 
2618
    if (localPlayer.flipView)
 
2619
        pmFromX = BOARD_SIZE + 3 - pmFromX;
 
2620
    else
 
2621
        pmFromY = BOARD_SIZE - 1 - pmFromY;
 
2622
 
 
2623
    XtPopupSpringLoaded(XtNameToWidget(localPlayer.boardWidget, params[0]));
 
2624
}
 
2625
 
 
2626
 
 
2627
 
 
2628
 
 
2629
static void
 
2630
PieceMenuSelect(Widget w, ShogiSquare piece, caddr_t junk)
 
2631
{
 
2632
    if ((pmFromX < 0) || (pmFromY < 0))
 
2633
        return;
 
2634
 
 
2635
    if (off_board(pmFromX))
 
2636
    {
 
2637
        int i, c;
 
2638
        switch (piece)
 
2639
        {
 
2640
        case ClearBoard:
 
2641
            break;
 
2642
 
 
2643
        case BlackPlay:
 
2644
            break;
 
2645
 
 
2646
        case WhitePlay:
 
2647
            break;
 
2648
 
 
2649
        default:
 
2650
            i = pieceToCatchedIndex[piece];
 
2651
            c = (piece >= WhitePawn);
 
2652
            catches[0][c][i]++;
 
2653
            DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
 
2654
            XSync(localPlayer.xDisplay, False);
 
2655
            return;
 
2656
        }
 
2657
    }
 
2658
 
 
2659
    pmFromX -= 2;
 
2660
 
 
2661
    switch (piece)
 
2662
    {
 
2663
    case ClearBoard:
 
2664
        for (pmFromY = 0; pmFromY < BOARD_SIZE; pmFromY++)
 
2665
            for (pmFromX = 0; pmFromX < BOARD_SIZE; pmFromX++)
 
2666
                boards[0][pmFromY][pmFromX] = EmptySquare;
 
2667
 
 
2668
        ClearCatches(catches[0]);
 
2669
        DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
 
2670
        break;
 
2671
 
 
2672
    case BlackPlay:  /* not currently on menu */
 
2673
        SetBlackToPlay();
 
2674
        break;
 
2675
 
 
2676
    case WhitePlay:  /* not currently on menu */
 
2677
        SetWhiteToPlay();
 
2678
        break;
 
2679
 
 
2680
    default:
 
2681
        boards[0][pmFromY][pmFromX] = piece;
 
2682
        DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
 
2683
        break;
 
2684
    }
 
2685
 
 
2686
    XSync(localPlayer.xDisplay, False);
 
2687
}
 
2688
 
 
2689
 
 
2690
 
 
2691
 
 
2692
static void
 
2693
SetBlackToPlay(void)
 
2694
{
 
2695
    int saveCM;
 
2696
 
 
2697
    if (gameMode != EditPosition) 
 
2698
        return;
 
2699
 
 
2700
    whitePlaysFirst = False;
 
2701
    saveCM = currentMove;
 
2702
    currentMove = 0;  /* kludge */
 
2703
    DisplayClocks(ReDisplayTimers);
 
2704
    currentMove = saveCM;
 
2705
}
 
2706
 
 
2707
 
 
2708
 
 
2709
 
 
2710
static void
 
2711
SetWhiteToPlay(void)
 
2712
{
 
2713
    int saveCM;
 
2714
 
 
2715
    if (gameMode != EditPosition) 
 
2716
        return;
 
2717
 
 
2718
    whitePlaysFirst = True;
 
2719
    saveCM = currentMove;
 
2720
    currentMove = 1;  /* kludge */
 
2721
    DisplayClocks(ReDisplayTimers);
 
2722
    currentMove = saveCM;
 
2723
}
 
2724
 
 
2725
 
 
2726
 
 
2727
 
 
2728
/*
 
2729
 * If the user selects on a border boundary or off the board, return failure.
 
2730
 * Otherwise map the event coordinate to the square.
 
2731
 */
 
2732
 
 
2733
int
 
2734
EventToSquare(int x)
 
2735
{
 
2736
    if (x < LINE_GAP)
 
2737
        return -1;
 
2738
 
 
2739
    x -= LINE_GAP;
 
2740
 
 
2741
    if ((x % (player->squareSize + LINE_GAP)) >= player->squareSize)
 
2742
        return -1;
 
2743
 
 
2744
    x /= (player->squareSize + LINE_GAP);
 
2745
 
 
2746
    if (x >= BOARD_SIZE)
 
2747
        return -1;
 
2748
 
 
2749
    return x;
 
2750
}
 
2751
 
 
2752
 
 
2753
 
 
2754
 
 
2755
int
 
2756
EventToXSquare(int x)
 
2757
{
 
2758
    if (x < LINE_GAP)
 
2759
        return -1;
 
2760
 
 
2761
    x -= LINE_GAP;
 
2762
 
 
2763
    if ((x % (player->squareSize + LINE_GAP)) >= player->squareSize)
 
2764
        return -1;
 
2765
 
 
2766
    x /= (player->squareSize + LINE_GAP);
 
2767
 
 
2768
    if (x >= BOARD_SIZE + 4)
 
2769
        return -1;
 
2770
 
 
2771
    return x;
 
2772
}
 
2773
 
 
2774
 
 
2775
 
 
2776
 
 
2777
ShogiSquare
 
2778
CharToPiece(int c, int p)
 
2779
{
 
2780
    if (p)
 
2781
    {
 
2782
        switch (c)
 
2783
        {
 
2784
        default:
 
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;
 
2802
        }
 
2803
    }
 
2804
    else
 
2805
    {
 
2806
        switch (c)
 
2807
        {
 
2808
        default:
 
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;
 
2826
        }
 
2827
    }
 
2828
}
 
2829
 
 
2830
 
 
2831
 
 
2832
 
 
2833
/*
 
2834
 * Convert coordinates to normal algebraic notation.
 
2835
 * promoPiece must be NULLCHAR if not a promotion.
 
2836
 */
 
2837
 
 
2838
ShogiMove
 
2839
MakeAlg(int fromX, int fromY, int toX, int toY,
 
2840
        char promoPiece, int currentBoardIndex, char *out)
 
2841
{
 
2842
    ShogiSquare piece;
 
2843
    char *outp = out;
 
2844
 
 
2845
    if (fromX > 80)
 
2846
    {
 
2847
        piece = (fromX - 81);
 
2848
        *outp++ = catchedIndexToChar[piece];
 
2849
        *outp++ = '*';
 
2850
        *outp++ = '9' - toX;
 
2851
        *outp++ = 'i' - toY;
 
2852
        *outp++ = NULLCHAR;
 
2853
        return (BlackOnMove(forwardMostMove) ? BlackDrop : WhiteDrop);
 
2854
    }
 
2855
    else
 
2856
    {
 
2857
        *outp++ = '9' - fromX;
 
2858
        *outp++ = 'i' - fromY;
 
2859
        *outp++ = '9' - toX;
 
2860
        *outp++ = 'i' - toY;
 
2861
        *outp++ = promoPiece;
 
2862
        *outp++ = NULLCHAR;
 
2863
 
 
2864
        if (promoPiece == NULLCHAR)
 
2865
        {
 
2866
            return NormalMove;
 
2867
        }
 
2868
        else
 
2869
        {
 
2870
            return (BlackOnMove(forwardMostMove)
 
2871
                    ? BlackPromotion : WhitePromotion);
 
2872
        }
 
2873
    }
 
2874
}
 
2875
 
 
2876
 
 
2877
 
 
2878
 
 
2879
void
 
2880
DrawSquare(int row, int column, ShogiSquare piece)
 
2881
{
 
2882
    int square_color, x, y, direction, font_ascent, font_descent;
 
2883
    char string[2];
 
2884
    XCharStruct overall;
 
2885
    struct DisplayData *player;
 
2886
 
 
2887
    for (player = &localPlayer; True; player = &remotePlayer)
 
2888
    {
 
2889
        int offset, remote;
 
2890
 
 
2891
        remote = (player == &remotePlayer);
 
2892
        offset = 2 * (player->squareSize + LINE_GAP);
 
2893
 
 
2894
        if (player->flipView)
 
2895
        {
 
2896
            x = LINE_GAP + ((BOARD_SIZE - 1) - column) *
 
2897
                (player->squareSize + LINE_GAP) + offset;
 
2898
            y = LINE_GAP + row * (player->squareSize + LINE_GAP);
 
2899
        }
 
2900
        else
 
2901
        {
 
2902
            x = LINE_GAP + column * (player->squareSize + LINE_GAP) + offset;
 
2903
            y = LINE_GAP + ((BOARD_SIZE - 1) - row) *
 
2904
                (player->squareSize + LINE_GAP);
 
2905
        }
 
2906
 
 
2907
        square_color = (((column + row) % 2) ? LIGHT : DARK);
 
2908
 
 
2909
        if (piece == EmptySquare)
 
2910
        {
 
2911
            if (column < 0 || column >= BOARD_SIZE)
 
2912
            {
 
2913
                /* empty square off board */
 
2914
                XFillRectangle(player->xDisplay, player->xBoardWindow,
 
2915
                               player->wbPieceGC,
 
2916
                               x, y, player->squareSize,
 
2917
                               player->squareSize);
 
2918
            }
 
2919
            else
 
2920
            {
 
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);
 
2928
            }
 
2929
        }
 
2930
        else if (player->monoMode)
 
2931
        {
 
2932
            /* in mono mode */
 
2933
            if (square_color == LIGHT)
 
2934
            {
 
2935
                XCopyArea(player->xDisplay,
 
2936
                          ((((((int)piece) < ((int)WhitePawn)))
 
2937
                            ^ player->flipView)
 
2938
                           ? *pieceToNormal[remote][(int)piece]
 
2939
                           : *pieceToReverse[remote][(int)piece]),
 
2940
                          player->xBoardWindow,
 
2941
                          (player->monoMode
 
2942
                           ? player->wbPieceGC
 
2943
                           : player->wlPieceGC),
 
2944
                          0, 0,
 
2945
                          player->squareSize, player->squareSize, x, y);
 
2946
            }
 
2947
            else
 
2948
            {
 
2949
                XCopyArea(player->xDisplay,
 
2950
                          ((((((int)piece) < ((int)WhitePawn))) 
 
2951
                            ^ player->flipView)
 
2952
                           ? *pieceToNormal[remote][(int)piece]
 
2953
                           : *pieceToReverse[remote][(int)piece]),
 
2954
                          player->xBoardWindow,
 
2955
                          (player->monoMode
 
2956
                           ? player->bwPieceGC
 
2957
                           : player->blPieceGC),
 
2958
                          0, 0,
 
2959
                          player->squareSize, player->squareSize, x, y);
 
2960
            }
 
2961
        }
 
2962
        else
 
2963
        {
 
2964
            /* in color mode */
 
2965
            if ((column < 0) || (column >= BOARD_SIZE))
 
2966
            {
 
2967
                /* off board */
 
2968
                XCopyPlane(player->xDisplay,
 
2969
                           ((((((int)piece) < ((int)WhitePawn)))
 
2970
                             ^ player->flipView)
 
2971
                            ? *pieceToNormalSolid[remote][(int)piece]
 
2972
                            : *pieceToReverseSolid[remote][(int)piece]),
 
2973
                           player->xBoardWindow,
 
2974
                           (pieceisWhite[(int)piece]
 
2975
                            ? player->woPieceGC
 
2976
                            : player->boPieceGC),
 
2977
                           0, 0,
 
2978
                           player->squareSize, player->squareSize, x, y, 1);
 
2979
 
 
2980
                XCopyArea(player->xDisplay,
 
2981
                          ((((((int)piece) < ((int)WhitePawn)))
 
2982
                            ^ player->flipView)
 
2983
                           ? *pieceToNormal[remote][(int)piece]
 
2984
                           : *pieceToReverse[remote][(int)piece]),
 
2985
                          player->xBoardWindow,
 
2986
                          player->charPieceGC,
 
2987
                          0, 0,
 
2988
                          player->squareSize, player->squareSize, x, y);
 
2989
            }
 
2990
            else if (square_color == LIGHT)
 
2991
            {
 
2992
                /* on board, light square */
 
2993
                XCopyPlane(player->xDisplay,
 
2994
                           ((((((int)piece) < ((int)WhitePawn)))
 
2995
                             ^ player->flipView)
 
2996
                            ? *pieceToNormalSolid[remote][(int)piece]
 
2997
                            : *pieceToReverseSolid[remote][(int)piece]),
 
2998
                           player->xBoardWindow,
 
2999
                           pieceisWhite[(int)piece]
 
3000
                           ? player->wlPieceGC
 
3001
                           : player->blPieceGC,
 
3002
                           0, 0,
 
3003
                           player->squareSize, player->squareSize, x, y, 1);
 
3004
 
 
3005
                XCopyArea(player->xDisplay,
 
3006
                          ((((((int)piece) < ((int)WhitePawn)))
 
3007
                            ^ player->flipView)
 
3008
                           ? *pieceToNormal[remote][(int)piece]
 
3009
                           : *pieceToReverse[remote][(int)piece]),
 
3010
                          player->xBoardWindow,
 
3011
                          player->charPieceGC,
 
3012
                          0, 0,
 
3013
                          player->squareSize, player->squareSize, x, y);
 
3014
            }
 
3015
            else
 
3016
            {
 
3017
                /* on board, dark square */
 
3018
                XCopyPlane(player->xDisplay,
 
3019
                           ((((((int)piece) < ((int)WhitePawn)))
 
3020
                             ^ player->flipView)
 
3021
                            ? *pieceToNormalSolid[remote][(int)piece]
 
3022
                            : *pieceToReverseSolid[remote][(int)piece]),
 
3023
                           player->xBoardWindow,
 
3024
                           (pieceisWhite[(int)piece]
 
3025
                            ? player->wdPieceGC
 
3026
                            : player->bdPieceGC),
 
3027
                           0, 0,
 
3028
                           player->squareSize, player->squareSize, x, y, 1);
 
3029
 
 
3030
                XCopyArea(player->xDisplay,
 
3031
                          ((((((int)piece) < ((int)WhitePawn)))
 
3032
                            ^ player->flipView)
 
3033
                           ? *pieceToNormal[remote][(int)piece]
 
3034
                           : *pieceToReverse[remote][(int)piece]),
 
3035
                          player->xBoardWindow,
 
3036
                          player->charPieceGC,
 
3037
                          0, 0,
 
3038
                          player->squareSize, player->squareSize, x, y);
 
3039
            }
 
3040
        }
 
3041
        string[1] = NULLCHAR;
 
3042
 
 
3043
        if (player->showCoords
 
3044
            && (column >= 0) && (column < 9)
 
3045
            && (row == (player->flipView ? 8 : 0)))
 
3046
        {
 
3047
            string[0] = '9' - column;
 
3048
            XTextExtents(player->coordFontStruct, string, 1, &direction,
 
3049
                         &font_ascent, &font_descent, &overall);
 
3050
 
 
3051
            if (player->monoMode)
 
3052
            {
 
3053
                XDrawImageString(player->xDisplay,
 
3054
                                 player->xBoardWindow, player->coordGC,
 
3055
                                 x + player->squareSize - overall.width - 2,
 
3056
                                 y + player->squareSize - font_descent - 1,
 
3057
                                 string, 1);
 
3058
            }
 
3059
            else
 
3060
            {
 
3061
                XDrawString(player->xDisplay, player->xBoardWindow,
 
3062
                            player->coordGC,
 
3063
                            x + player->squareSize - overall.width - 2,
 
3064
                            y + player->squareSize - font_descent - 1,
 
3065
                            string, 1);
 
3066
            }
 
3067
        }
 
3068
 
 
3069
        if (player->showCoords
 
3070
            && (row >= 0) && (row < 9)
 
3071
            && (column == (player->flipView ? 8 : 0)))
 
3072
        {
 
3073
            string[0] = 'i' - row;
 
3074
            XTextExtents(player->coordFontStruct, string, 1, &direction,
 
3075
                         &font_ascent, &font_descent, &overall);
 
3076
 
 
3077
            if (player->monoMode)
 
3078
            {
 
3079
                XDrawImageString(player->xDisplay,
 
3080
                                 player->xBoardWindow, player->coordGC,
 
3081
                                 x + 2, y + font_ascent + 1, string, 1);
 
3082
            }
 
3083
            else
 
3084
            {
 
3085
                XDrawString(player->xDisplay, player->xBoardWindow,
 
3086
                            player->coordGC,
 
3087
                            x + 2, y + font_ascent + 1, string, 1);
 
3088
            }
 
3089
        }
 
3090
 
 
3091
        if (!updateRemotePlayer || (player == &remotePlayer))
 
3092
            break;
 
3093
    }
 
3094
}
 
3095
 
 
3096
 
 
3097
 
 
3098
 
 
3099
void
 
3100
EventProc(Widget widget, caddr_t client_data, XEvent *event)
 
3101
{
 
3102
    if (event->type == MappingNotify)
 
3103
    {
 
3104
        XRefreshKeyboardMapping((XMappingEvent *) event);
 
3105
        return;
 
3106
    }
 
3107
 
 
3108
    if (!XtIsRealized(widget))
 
3109
        return;
 
3110
 
 
3111
    if ((event->type == ButtonPress) || (event->type == ButtonRelease))
 
3112
    {
 
3113
        if (event->xbutton.button != Button1)
 
3114
            return;
 
3115
    }
 
3116
 
 
3117
    switch (event->type)
 
3118
    {
 
3119
    case Expose:
 
3120
        DrawPosition(widget, event, NULL, NULL);
 
3121
        break;
 
3122
 
 
3123
    default:
 
3124
        return;
 
3125
    }
 
3126
}
 
3127
 
 
3128
 
 
3129
 
 
3130
 
 
3131
/*
 
3132
 * event handler for redrawing the board
 
3133
 */
 
3134
 
 
3135
void
 
3136
DrawPosition(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
3137
{
 
3138
    Arg args[1];
 
3139
    int i, j;
 
3140
    static Board lastBoard;
 
3141
    static Catched lastCatches;
 
3142
    static int lastBoardValid = 0;
 
3143
    static int lastFlipView = 0, lastRemoteFlipView = 1;
 
3144
 
 
3145
    if (!player->Iconic)
 
3146
    {
 
3147
        XtSetArg(args[0], XtNiconic, False);
 
3148
        XtSetValues(localPlayer.shellWidget, args, 1);
 
3149
    }
 
3150
 
 
3151
    /*
 
3152
     * It would be simpler to clear the window with XClearWindow()
 
3153
     * but this causes a very distracting flicker.
 
3154
     */
 
3155
 
 
3156
    if ((w == localPlayer.boardWidget)
 
3157
        && (event == NULL)
 
3158
        && lastBoardValid
 
3159
        && (lastFlipView == localPlayer.flipView)
 
3160
        && (!updateRemotePlayer
 
3161
            || (lastRemoteFlipView == remotePlayer.flipView)))
 
3162
    {
 
3163
        for (i = 0; i < BOARD_SIZE; i++)
 
3164
        {
 
3165
            for (j = 0; j < BOARD_SIZE; j++)
 
3166
            {
 
3167
                if (boards[currentMove][i][j] != lastBoard[i][j])
 
3168
                    DrawSquare(i, j, boards[currentMove][i][j]);
 
3169
            }
 
3170
        }
 
3171
 
 
3172
        for (i = 0; i < 2; i++)
 
3173
        {
 
3174
            for (j = 0; j < 8; j++)
 
3175
            {
 
3176
                if (catches[currentMove][i][j] != lastCatches[i][j])
 
3177
                {
 
3178
                    UpdateCatched(i, 0, False, True, currentMove);
 
3179
                    break;
 
3180
                }
 
3181
            }
 
3182
        }
 
3183
    }
 
3184
    else
 
3185
    {
 
3186
        XDrawSegments(localPlayer.xDisplay,
 
3187
                      localPlayer.xBoardWindow, localPlayer.lineGC,
 
3188
                      localPlayer.gridSegments, (BOARD_SIZE + 1) * 2);
 
3189
 
 
3190
        if (updateRemotePlayer)
 
3191
        {
 
3192
            XDrawSegments(remotePlayer.xDisplay,
 
3193
                          remotePlayer.xBoardWindow, remotePlayer.lineGC,
 
3194
                          remotePlayer.gridSegments, (BOARD_SIZE + 1) * 2);
 
3195
        }
 
3196
 
 
3197
        for (i = 0; i < BOARD_SIZE; i++)
 
3198
            for (j = 0; j < BOARD_SIZE; j++)
 
3199
                DrawSquare(i, j, boards[currentMove][i][j]);
 
3200
 
 
3201
        UpdateCatched(0, 0, False, True, currentMove);
 
3202
        UpdateCatched(1, 0, False, True, currentMove);
 
3203
    }
 
3204
 
 
3205
    CopyBoard(lastBoard, boards[currentMove]);
 
3206
    CopyCatches(lastCatches, catches[currentMove]);
 
3207
    lastBoardValid = 1;
 
3208
    lastFlipView = localPlayer.flipView;
 
3209
 
 
3210
    if (updateRemotePlayer)
 
3211
        lastRemoteFlipView = remotePlayer.flipView;
 
3212
 
 
3213
    XSync(localPlayer.xDisplay, False);
 
3214
 
 
3215
    if (updateRemotePlayer)
 
3216
        XSync(remotePlayer.xDisplay, False);
 
3217
}
 
3218
 
 
3219
 
 
3220
 
 
3221
 
 
3222
void
 
3223
InitPosition(int redraw)
 
3224
{
 
3225
    currentMove = forwardMostMove = backwardMostMove = 0;
 
3226
    CopyBoard(boards[0], initialPosition);
 
3227
    ClearCatches(catches[0]);
 
3228
 
 
3229
    if (redraw)
 
3230
        DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
 
3231
}
 
3232
 
 
3233
 
 
3234
 
 
3235
 
 
3236
void
 
3237
CopyBoard(Board to, Board from)
 
3238
{
 
3239
    int i, j;
 
3240
 
 
3241
    for (i = 0; i < BOARD_SIZE; i++)
 
3242
        for (j = 0; j < BOARD_SIZE; j++)
 
3243
            to[i][j] = from[i][j];
 
3244
}
 
3245
 
 
3246
 
 
3247
 
 
3248
 
 
3249
void
 
3250
CopyCatches(Catched to, Catched from)
 
3251
{
 
3252
    int i, j;
 
3253
 
 
3254
    for (i = 0; i < 2; i++)
 
3255
        for (j = 0; j < 8; j++)
 
3256
            to[i][j] = from[i][j];
 
3257
}
 
3258
 
 
3259
 
 
3260
 
 
3261
 
 
3262
void
 
3263
SendCurrentBoard(FILE *fp)
 
3264
{
 
3265
    SendBoard(fp, boards[currentMove], catches[currentMove]);
 
3266
}
 
3267
 
 
3268
 
 
3269
 
 
3270
 
 
3271
void
 
3272
SendBoard(FILE *fp, Board board, Catched catches)
 
3273
{
 
3274
    char message[MSG_SIZ];
 
3275
    ShogiSquare *bp;
 
3276
    int i, j;
 
3277
 
 
3278
    SendToProgram("edit\n", fp);
 
3279
    SendToProgram("#\n", fp);
 
3280
 
 
3281
    for (i = BOARD_SIZE - 1; i >= 0; i--)
 
3282
    {
 
3283
        bp = &board[i][0];
 
3284
 
 
3285
        for (j = 0; j < BOARD_SIZE; j++, bp++)
 
3286
        {
 
3287
            if (((int) *bp) < (int)WhitePawn)
 
3288
            {
 
3289
                sprintf(message, "%c%c%c%s\n",
 
3290
                        pieceToChar[(int) *bp],
 
3291
                        '9' - j, 'i' - i,
 
3292
                        (pieceIsPromoted[(int) *bp] ? "+" : ""));
 
3293
                SendToProgram(message, fp);
 
3294
            }
 
3295
        }
 
3296
    }
 
3297
 
 
3298
    for (i = 0; i <= 7; i++)
 
3299
    {
 
3300
        int n;
 
3301
 
 
3302
        for (n = catches[0][i]; n > 0; n--)
 
3303
        {
 
3304
            sprintf(message, "%c*\n",
 
3305
                    catchedIndexToChar[i]);
 
3306
            SendToProgram(message, fp);
 
3307
        }
 
3308
    }
 
3309
 
 
3310
    SendToProgram("c\n", fp);
 
3311
 
 
3312
    for (i = BOARD_SIZE - 1; i >= 0; i--)
 
3313
    {
 
3314
        bp = &board[i][0];
 
3315
 
 
3316
        for (j = 0; j < BOARD_SIZE; j++, bp++)
 
3317
        {
 
3318
            if ((((int) *bp) != ((int)EmptySquare))
 
3319
                && (((int) *bp) >= ((int)WhitePawn)))
 
3320
            {
 
3321
                sprintf(message, "%c%c%c%s\n",
 
3322
                        pieceToChar[((int) *bp) - ((int)WhitePawn)],
 
3323
                        '9' - j, 'i' - i,
 
3324
                        (pieceIsPromoted[(int) *bp] ? "+" : ""));
 
3325
                SendToProgram(message, fp);
 
3326
            }
 
3327
        }
 
3328
    }
 
3329
 
 
3330
    for (i = 0; i <= 7; i++)
 
3331
    {
 
3332
        int n;
 
3333
 
 
3334
        for (n = catches[1][i]; n > 0; n--)
 
3335
        {
 
3336
            sprintf(message, "%c*\n",
 
3337
                    catchedIndexToChar[i]);
 
3338
            SendToProgram(message, fp);
 
3339
        }
 
3340
    }
 
3341
 
 
3342
    SendToProgram(".\n", fp);
 
3343
}
 
3344
 
 
3345
 
 
3346
 
 
3347
 
 
3348
static int
 
3349
PromotionPossible(int fromY, int toY, ShogiSquare piece)
 
3350
{
 
3351
    if (((int)piece) < ((int)WhitePawn))
 
3352
    {
 
3353
        if ((fromY < 6) && (toY < 6))
 
3354
            return False;
 
3355
    }
 
3356
    else
 
3357
    {
 
3358
        if ((fromY > 2) && (toY > 2))
 
3359
            return False;
 
3360
    }
 
3361
 
 
3362
    return piecePromotable[(int)piece];
 
3363
 
 
3364
}
 
3365
 
 
3366
 
 
3367
 
 
3368
 
 
3369
static void
 
3370
ShowCount(int row, int column, int n)
 
3371
{
 
3372
    int offset = 2 * (player->squareSize + LINE_GAP);
 
3373
    int x, y, direction, font_ascent, font_descent;
 
3374
    char string[2];
 
3375
    XCharStruct overall;
 
3376
    struct DisplayData *player;
 
3377
 
 
3378
    DrawSquare(row, column, EmptySquare);
 
3379
 
 
3380
    if (n <= 1)
 
3381
        return;
 
3382
 
 
3383
    for (player = &localPlayer; True; player = &remotePlayer)
 
3384
    {
 
3385
        if (player->flipView)
 
3386
        {
 
3387
            x = LINE_GAP + ((BOARD_SIZE - 1) - column) *
 
3388
                (player->squareSize + LINE_GAP) + offset;
 
3389
            y = LINE_GAP + row * (player->squareSize + LINE_GAP);
 
3390
        }
 
3391
        else
 
3392
        {
 
3393
            x = LINE_GAP + column * (player->squareSize + LINE_GAP) + offset;
 
3394
            y = LINE_GAP + ((BOARD_SIZE - 1) - row) *
 
3395
                (player->squareSize + LINE_GAP);
 
3396
        }
 
3397
 
 
3398
        x -= player->squareSize / 2;
 
3399
 
 
3400
        string[1] = NULLCHAR;
 
3401
 
 
3402
        if (n > 9)
 
3403
            string[0] = '*';
 
3404
        else
 
3405
            string[0] = '0' + n;
 
3406
 
 
3407
        XTextExtents(player->coordFontStruct, string, 1, &direction,
 
3408
                     &font_ascent, &font_descent, &overall);
 
3409
 
 
3410
        if (player->monoMode)
 
3411
        {
 
3412
            XDrawImageString(player->xDisplay, player->xBoardWindow,
 
3413
                             player->coordGC,
 
3414
                             x + player->squareSize - overall.width - 2,
 
3415
                             y + player->squareSize - font_descent - 1,
 
3416
                             string, 1);
 
3417
        }
 
3418
        else
 
3419
        {
 
3420
            XDrawString(player->xDisplay, player->xBoardWindow,
 
3421
                        player->coordGC,
 
3422
                        x + player->squareSize - overall.width - 2,
 
3423
                        y + player->squareSize - font_descent - 1,
 
3424
                        string, 1);
 
3425
        }
 
3426
 
 
3427
        if (!updateRemotePlayer || (player == &remotePlayer))
 
3428
            break;
 
3429
    }
 
3430
}
 
3431
 
 
3432
 
 
3433
 
 
3434
 
 
3435
void
 
3436
UpdateCatched(int Color, int Figure, int Drop, int DropAll, int currentMove)
 
3437
{
 
3438
    int n, F;
 
3439
    int x, y;
 
3440
 
 
3441
    /* Determine first row and column. */
 
3442
 
 
3443
    if (Color)
 
3444
    {
 
3445
        x = -1;
 
3446
        y = BOARD_SIZE - 1;
 
3447
    }
 
3448
    else
 
3449
    {
 
3450
        x = BOARD_SIZE;
 
3451
        y = 0;
 
3452
    }
 
3453
 
 
3454
    if (DropAll)
 
3455
        n = 0;
 
3456
    else
 
3457
        n = catches[currentMove][Color][Figure];
 
3458
 
 
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. */
 
3463
 
 
3464
    if (DropAll || (Drop && (n == 1)) || (!Drop && (n == 0)))
 
3465
    {
 
3466
        /* show all captured pieces */
 
3467
        n = 0;
 
3468
 
 
3469
        for (F = pawn; F <= king; F++)
 
3470
        {
 
3471
            int c;
 
3472
 
 
3473
            if ((c = catches[currentMove][Color][F]) > 0)
 
3474
            {
 
3475
                n++;
 
3476
                DrawSquare(y, x, catchedIndexToPiece[Color][F]);
 
3477
                ShowCount(y, (Color ? (x - 1) : (x + 1)), c);
 
3478
 
 
3479
                if (Color) 
 
3480
                    y--;
 
3481
                else
 
3482
                    y++;
 
3483
            }
 
3484
        }
 
3485
 
 
3486
        if (DropAll)
 
3487
        {
 
3488
            for (; n < 9; n++)
 
3489
            {
 
3490
                DrawSquare(y, x, EmptySquare);
 
3491
                ShowCount(y, (Color ? (x - 1) : (x + 1)), 0);
 
3492
 
 
3493
                if (Color) 
 
3494
                    y--;
 
3495
                else
 
3496
                    y++;
 
3497
            }
 
3498
        }
 
3499
        else if (!Drop)
 
3500
        {
 
3501
            /* remove one line! */
 
3502
            DrawSquare(y, x, EmptySquare);
 
3503
            ShowCount(y, (Color ? (x - 1) : (x + 1)), 0);
 
3504
        }
 
3505
    }
 
3506
    else
 
3507
    {
 
3508
        /* show the actual count */
 
3509
        for (F = pawn; F <= Figure - 1; F++)
 
3510
        {
 
3511
            if (catches[currentMove][Color][F] > 0)
 
3512
            {
 
3513
                if (Color) 
 
3514
                    y--;
 
3515
                else 
 
3516
                    y++;
 
3517
            }
 
3518
        }
 
3519
 
 
3520
        ShowCount(y, (Color ? (x - 1) : (x + 1)), n);
 
3521
    }
 
3522
}
 
3523
 
 
3524
 
 
3525
 
 
3526
 
 
3527
#ifdef BLINK_COUNT
 
3528
 
 
3529
static int BlinkCount = 0;
 
3530
static int BlinkRow, BlinkCol;
 
3531
static ShogiSquare BlinkPiece;
 
3532
 
 
3533
 
 
3534
void
 
3535
BlinkSquareProc(void)
 
3536
{
 
3537
    if (BlinkCount > 0)
 
3538
    {
 
3539
        BlinkCount--;
 
3540
        DrawSquare (BlinkRow, BlinkCol,
 
3541
                    ((BlinkCount & 1) ? EmptySquare : BlinkPiece));
 
3542
 
 
3543
        if (BlinkCount > 0)
 
3544
        {
 
3545
            blinkSquareXID
 
3546
                = XtAppAddTimeOut(appContext,
 
3547
                                  150,
 
3548
                                  (XtTimerCallbackProc)BlinkSquareProc,
 
3549
                                  NULL);
 
3550
        }
 
3551
    }
 
3552
    else
 
3553
    {
 
3554
        BlinkCount = 0;
 
3555
    }
 
3556
}
 
3557
 
 
3558
 
 
3559
 
 
3560
 
 
3561
void
 
3562
BlinkSquare(int row, int col, ShogiSquare piece)
 
3563
{
 
3564
    BlinkCount = 2 * BLINK_COUNT + 1;
 
3565
    BlinkRow = row;
 
3566
    BlinkCol = col;
 
3567
    BlinkPiece = piece;
 
3568
    BlinkSquareProc();
 
3569
}
 
3570
 
 
3571
 
 
3572
#endif /* BLINK_COUNT */
 
3573
 
 
3574
 
 
3575
 
 
3576
 
 
3577
static int
 
3578
PieceOfCatched(int color, int x, int y, int currentMove)
 
3579
{
 
3580
    int F, n;
 
3581
 
 
3582
    if (color)
 
3583
    {
 
3584
        if (x != 1) 
 
3585
            return (no_piece);
 
3586
 
 
3587
        y = 8 - y;
 
3588
    }
 
3589
    else
 
3590
    {
 
3591
        if (x != 11) 
 
3592
            return no_piece;
 
3593
    }
 
3594
 
 
3595
    for (F = pawn, n = 0; F <= king; F++)
 
3596
    {
 
3597
        if (catches[currentMove][color][F] > 0)
 
3598
        {
 
3599
            if (n == y) 
 
3600
                return F;
 
3601
 
 
3602
            n++;
 
3603
        }
 
3604
    }
 
3605
 
 
3606
    return no_piece;
 
3607
}
 
3608
 
 
3609
 
 
3610
 
 
3611
 
 
3612
/*
 
3613
 * event handler for parsing user moves
 
3614
 */
 
3615
 
 
3616
void
 
3617
HandleUserMove(Widget w, XEvent *event)
 
3618
{
 
3619
    ShogiMove move_type;
 
3620
    ShogiSquare from_piece;
 
3621
    int to_x, to_y, fromRemotePlayer;
 
3622
 
 
3623
    if (updateRemotePlayer)
 
3624
    {
 
3625
        if (((w != localPlayer.boardWidget)
 
3626
             && (w != remotePlayer.boardWidget))
 
3627
            || (matchMode != MatchFalse))
 
3628
        {
 
3629
            return;
 
3630
        }
 
3631
 
 
3632
        fromRemotePlayer = (w == remotePlayer.boardWidget);
 
3633
    }
 
3634
    else
 
3635
    {
 
3636
        if ((w != localPlayer.boardWidget) || (matchMode != MatchFalse))
 
3637
            return;
 
3638
 
 
3639
        fromRemotePlayer = False;
 
3640
    }
 
3641
 
 
3642
    player = (fromRemotePlayer ? &remotePlayer : &localPlayer);
 
3643
 
 
3644
    if (player->promotionUp)
 
3645
    {
 
3646
        XtPopdown(player->promotionShell);
 
3647
        XtDestroyWidget(player->promotionShell);
 
3648
        player->promotionUp = False;
 
3649
        fromX = fromY = -1;
 
3650
    }
 
3651
 
 
3652
    switch (gameMode)
 
3653
    {
 
3654
    case EndOfGame:
 
3655
    case PlayFromGameFile:
 
3656
    case TwoMachinesPlay:
 
3657
        return;
 
3658
 
 
3659
    case MachinePlaysBlack:
 
3660
        if (BlackOnMove(forwardMostMove))
 
3661
        {
 
3662
            DisplayMessage("It is not your turn", fromRemotePlayer);
 
3663
            return;
 
3664
        }
 
3665
 
 
3666
        break;
 
3667
 
 
3668
    case MachinePlaysWhite:
 
3669
        if (!BlackOnMove(forwardMostMove))
 
3670
        {
 
3671
            DisplayMessage("It is not your turn", fromRemotePlayer);
 
3672
            return;
 
3673
        }
 
3674
 
 
3675
        break;
 
3676
 
 
3677
    case ForceMoves:
 
3678
        forwardMostMove = currentMove;
 
3679
        break;
 
3680
 
 
3681
    default:
 
3682
        break;
 
3683
    }
 
3684
 
 
3685
    if (currentMove != forwardMostMove)
 
3686
    {
 
3687
        DisplayMessage("Displayed position is not current",
 
3688
                       fromRemotePlayer);
 
3689
        return;
 
3690
    }
 
3691
 
 
3692
    switch (event->type)
 
3693
    {
 
3694
    case ButtonPress:
 
3695
        if ((fromX >= 0) || (fromY >= 0))
 
3696
            return;
 
3697
 
 
3698
        if (((fromX = EventToXSquare(event->xbutton.x)) < 1)
 
3699
            || (fromX > BOARD_SIZE + 2)
 
3700
            || ((fromY = EventToSquare(event->xbutton.y)) < 0))
 
3701
        {
 
3702
            fromX = fromY = -1;
 
3703
            return;
 
3704
        }
 
3705
 
 
3706
        if (player->flipView)
 
3707
            fromX = BOARD_SIZE + 3 - fromX;
 
3708
        else
 
3709
            fromY = BOARD_SIZE - 1 - fromY;
 
3710
 
 
3711
        break;
 
3712
 
 
3713
    case ButtonRelease:
 
3714
        if ((fromX < 0) || (fromY < 0)) 
 
3715
            return;
 
3716
 
 
3717
        if (((to_x = EventToXSquare(event->xbutton.x)) < 1)
 
3718
            || (to_x > BOARD_SIZE + 2)
 
3719
            || ((to_y = EventToSquare(event->xbutton.y)) < 0))
 
3720
        {
 
3721
            if (gameMode == EditPosition && !off_board(fromX))
 
3722
            {
 
3723
                fromX -= 2;
 
3724
                boards[0][fromY][fromX] = EmptySquare;
 
3725
                DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
 
3726
                XSync(localPlayer.xDisplay, False);
 
3727
 
 
3728
                if (updateRemotePlayer)
 
3729
                    XSync(remotePlayer.xDisplay, False);
 
3730
            }
 
3731
 
 
3732
            fromX = fromY = -1;
 
3733
            return;
 
3734
        }
 
3735
 
 
3736
        if (player->flipView)
 
3737
            to_x = BOARD_SIZE + 3 - to_x;
 
3738
        else
 
3739
            to_y = BOARD_SIZE - 1 - to_y;
 
3740
 
 
3741
        if ((fromX == to_x) && (fromY == to_y))
 
3742
        {
 
3743
            fromX = fromY = -1;
 
3744
            return;
 
3745
        }
 
3746
 
 
3747
        if (gameMode == EditPosition)
 
3748
        {
 
3749
            ShogiSquare piece;
 
3750
 
 
3751
            if (off_board(fromX))
 
3752
            {
 
3753
                /* Remove a catched piece */
 
3754
                int i, c;
 
3755
                c = ((fromX < 5) ^ player->flipView);
 
3756
                i = PieceOfCatched(c, fromX, fromY, 0);
 
3757
 
 
3758
                if (i == no_piece)
 
3759
                {
 
3760
                    fromX = fromY = -1;
 
3761
                    return;
 
3762
                }
 
3763
                else
 
3764
                {
 
3765
                    piece = catchedIndexToPiece[c][i];
 
3766
                    catches[0][c][i]--;
 
3767
                }
 
3768
            }
 
3769
            else
 
3770
            {
 
3771
                /* remove piece from board field */
 
3772
                fromX -= 2;
 
3773
                piece = boards[0][fromY][fromX];
 
3774
                boards[0][fromY][fromX] = EmptySquare;
 
3775
            }
 
3776
 
 
3777
            if (!off_board(to_x))
 
3778
            {
 
3779
                /* drop piece to board field */
 
3780
                ShogiSquare catched_piece;
 
3781
                to_x -= 2;
 
3782
                catched_piece = boards[0][to_y][to_x];
 
3783
 
 
3784
                if (catched_piece != EmptySquare)
 
3785
                {
 
3786
                    /* put piece to catched pieces */
 
3787
                    int i = pieceToCatchedIndex[catched_piece];
 
3788
                    int c = (catched_piece < WhitePawn);
 
3789
                    catches[0][c][i]++;
 
3790
                }
 
3791
 
 
3792
                /* place moved piece */
 
3793
                boards[0][to_y][to_x] = piece;
 
3794
            }
 
3795
 
 
3796
            fromX = fromY = -1;
 
3797
            DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
 
3798
            XSync(localPlayer.xDisplay, False);
 
3799
 
 
3800
            if (updateRemotePlayer)
 
3801
                XSync(remotePlayer.xDisplay, False);
 
3802
 
 
3803
            return;
 
3804
        }
 
3805
 
 
3806
        if (off_board(fromX))
 
3807
        {
 
3808
            int c     = (BlackOnMove(forwardMostMove) ? 0 : 1);
 
3809
            int piece = PieceOfCatched(c, fromX, fromY, currentMove);
 
3810
 
 
3811
            if (piece == no_piece)
 
3812
            {
 
3813
                fromX = fromY = -1;
 
3814
                return;
 
3815
            }
 
3816
            else
 
3817
            {
 
3818
                if (updateRemotePlayer
 
3819
                    && (BlackOnMove(forwardMostMove) == fromRemotePlayer))
 
3820
                {
 
3821
                    DisplayMessage("do not drop opponent pieces",
 
3822
                                   fromRemotePlayer);
 
3823
                    fromX = fromY = -1;
 
3824
                    return;
 
3825
                }
 
3826
 
 
3827
                fromX = fromY = piece + 81;
 
3828
                to_x -= 2;
 
3829
                move_type = (BlackOnMove(forwardMostMove)
 
3830
                             ? BlackDrop : WhiteDrop);
 
3831
                MakeMove(&move_type, fromX, fromY, to_x, to_y);
 
3832
 
 
3833
#ifdef BLINK_COUNT
 
3834
                if (updateRemotePlayer)
 
3835
                    BlinkSquare(to_y, to_x, boards[currentMove][to_y][to_x]);
 
3836
#endif
 
3837
 
 
3838
                FinishUserMove(move_type, to_x, to_y);
 
3839
                break;
 
3840
            }
 
3841
        }
 
3842
        else if (off_board(to_x))
 
3843
        {
 
3844
            fromX = fromY = -1;
 
3845
            return;
 
3846
        }
 
3847
        else
 
3848
        {
 
3849
            fromX -= 2;
 
3850
            to_x -= 2;
 
3851
            from_piece = boards[currentMove][fromY][fromX];
 
3852
 
 
3853
            if ((from_piece != EmptySquare)
 
3854
                && updateRemotePlayer
 
3855
                && ((from_piece < WhitePawn) == fromRemotePlayer))
 
3856
            {
 
3857
                DisplayMessage("do not move opponent pieces",
 
3858
                               fromRemotePlayer);
 
3859
                fromX = fromY = -1;
 
3860
                return;
 
3861
            }
 
3862
 
 
3863
            if (PromotionPossible(fromY, to_y, from_piece))
 
3864
            {
 
3865
                PromotionPopUp(from_piece, to_x, to_y, fromRemotePlayer);
 
3866
                return;
 
3867
            }
 
3868
 
 
3869
            move_type = NormalMove;
 
3870
            MakeMove(&move_type, fromX, fromY, to_x, to_y);
 
3871
 
 
3872
#ifdef BLINK_COUNT
 
3873
            if (updateRemotePlayer)
 
3874
                BlinkSquare(to_y, to_x, boards[currentMove][to_y][to_x]);
 
3875
#endif
 
3876
 
 
3877
            FinishUserMove(move_type, to_x, to_y);
 
3878
            break;
 
3879
        }
 
3880
    }
 
3881
}
 
3882
 
 
3883
 
 
3884
 
 
3885
 
 
3886
void
 
3887
FinishUserMove(ShogiMove move_type, int to_x, int to_y)
 
3888
{
 
3889
    char user_move[MSG_SIZ];
 
3890
 
 
3891
    /* output move for gnushogi */
 
3892
    switch (move_type)
 
3893
    {
 
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);
 
3898
        break;
 
3899
        
 
3900
    case BlackDrop:
 
3901
    case WhiteDrop:
 
3902
        sprintf(user_move, "%c*%c%c\n",
 
3903
                catchedIndexToChar[fromX - 81], '9' - to_x, 'i' - to_y);
 
3904
        break;
 
3905
        
 
3906
    case NormalMove:
 
3907
        sprintf(user_move, "%c%c%c%c\n",
 
3908
                '9' - fromX, 'i' - fromY, '9' - to_x, 'i' - to_y);
 
3909
        break;
 
3910
        
 
3911
    default:
 
3912
        fprintf(stderr, "%s: internal error; bad move_type\n",
 
3913
                (char *)programName);
 
3914
        break;
 
3915
    }
 
3916
 
 
3917
    Attention(firstProgramPID);
 
3918
 
 
3919
    if (firstSendTime)
 
3920
        SendTimeRemaining(toFirstProgFP);
 
3921
 
 
3922
    SendToProgram(user_move, toFirstProgFP);
 
3923
    strcpy(moveList[currentMove - 1], user_move);
 
3924
 
 
3925
    fromX = fromY = -1;
 
3926
 
 
3927
    if (gameMode == PauseGame)
 
3928
    {
 
3929
        /* a user move restarts a paused game*/
 
3930
        PauseProc(NULL, NULL, NULL, NULL);
 
3931
    }
 
3932
 
 
3933
    switch (gameMode)
 
3934
    {
 
3935
    case ForceMoves:
 
3936
        break;
 
3937
 
 
3938
    case BeginningOfGame:
 
3939
        if (localPlayer.appData.noShogiProgram)
 
3940
            lastGameMode = gameMode = ForceMoves;
 
3941
        else
 
3942
            lastGameMode = gameMode = MachinePlaysWhite;
 
3943
 
 
3944
        ModeHighlight();
 
3945
        break;
 
3946
 
 
3947
    case MachinePlaysWhite:
 
3948
    case MachinePlaysBlack:
 
3949
    default:
 
3950
        break;
 
3951
    }
 
3952
}
 
3953
 
 
3954
 
 
3955
 
 
3956
 
 
3957
/* Simple parser for moves from gnushogi. */
 
3958
void
 
3959
ParseMachineMove(char *machine_move, ShogiMove *move_type,
 
3960
                 int *from_x, int *from_y, int *to_x, int *to_y)
 
3961
{
 
3962
#define no_digit(c) (c < '0' || c > '9')
 
3963
    {
 
3964
        if (no_digit(machine_move[0]))
 
3965
        {
 
3966
            switch (machine_move[0])
 
3967
            {
 
3968
            case 'P': 
 
3969
                *from_x = 81;
 
3970
                break;
 
3971
 
 
3972
            case 'L': 
 
3973
                *from_x = 82;
 
3974
                break;
 
3975
 
 
3976
            case 'N': 
 
3977
                *from_x = 83;
 
3978
                break;
 
3979
 
 
3980
            case 'S': 
 
3981
                *from_x = 84;
 
3982
                break;
 
3983
 
 
3984
            case 'G': 
 
3985
                *from_x = 85;
 
3986
                break;
 
3987
 
 
3988
            case 'B': 
 
3989
                *from_x = 86;
 
3990
                break;
 
3991
 
 
3992
            case 'R': 
 
3993
                *from_x = 87;
 
3994
                break;
 
3995
 
 
3996
            case 'K': 
 
3997
                *from_x = 88;
 
3998
                break;
 
3999
 
 
4000
            default: 
 
4001
                *from_x = -1;
 
4002
            }
 
4003
 
 
4004
            *from_y = *from_x;
 
4005
            *to_x   = '9' - machine_move[2];
 
4006
            *to_y   = 'i' - machine_move[3];
 
4007
        }
 
4008
        else
 
4009
        {
 
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];
 
4014
 
 
4015
            switch (machine_move[4])
 
4016
            {
 
4017
            case '+':
 
4018
                *move_type = (BlackOnMove(forwardMostMove) 
 
4019
                    ? BlackPromotion : WhitePromotion);
 
4020
                break;
 
4021
 
 
4022
            default:
 
4023
                *move_type = NormalMove;
 
4024
                break;
 
4025
            }
 
4026
        }
 
4027
    }
 
4028
}
 
4029
 
 
4030
 
 
4031
 
 
4032
 
 
4033
void
 
4034
SkipString(char **mpr)
 
4035
{
 
4036
    while (**mpr == ' ')
 
4037
        (*mpr)++;
 
4038
 
 
4039
    while ((**mpr != ' ') && (**mpr != NULLCHAR) && (**mpr != '\n'))
 
4040
        (*mpr)++;
 
4041
 
 
4042
    while (**mpr == ' ')
 
4043
        (*mpr)++;
 
4044
}
 
4045
 
 
4046
 
 
4047
 
 
4048
 
 
4049
void
 
4050
HandleMachineMove(char *message, FILE *fp)
 
4051
{
 
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;
 
4055
    char *mpr;
 
4056
 
 
4057
#ifdef SYNCHTIME
 
4058
    long time_remaining;
 
4059
#endif
 
4060
 
 
4061
    maybeThinking = False;
 
4062
 
 
4063
    if (strncmp(message, "warning:", 8) == 0)
 
4064
    {
 
4065
        DisplayMessage(message, False);
 
4066
 
 
4067
        if (updateRemotePlayer)
 
4068
            DisplayMessage(message, True);
 
4069
 
 
4070
        return;
 
4071
    }
 
4072
 
 
4073
    /*
 
4074
     * If shogi program startup fails, exit with an error message.
 
4075
     * Attempts to recover here are futile.
 
4076
     */
 
4077
 
 
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))
 
4083
    {
 
4084
        fprintf(stderr,
 
4085
                "%s: failed to start shogi program %s on %s: %s\n",
 
4086
                programName,
 
4087
                ((fp == fromFirstProgFP) 
 
4088
                 ? localPlayer.appData.firstShogiProgram
 
4089
                 : localPlayer.appData.secondShogiProgram),
 
4090
                ((fp == fromFirstProgFP)
 
4091
                 ? localPlayer.appData.firstHost
 
4092
                 : localPlayer.appData.secondHost),
 
4093
                message);
 
4094
        ShutdownShogiPrograms(message);
 
4095
        exit(1);
 
4096
    }
 
4097
 
 
4098
    /*
 
4099
     * If the move is illegal, cancel it and redraw the board.
 
4100
     */
 
4101
 
 
4102
    if (strncmp(message, "Illegal move", 12) == 0)
 
4103
    {
 
4104
        if (fp == fromFirstProgFP && firstSendTime == 2)
 
4105
        {
 
4106
            /* First program doesn't have the "time" command */
 
4107
            firstSendTime = 0;
 
4108
            return;
 
4109
        }
 
4110
        else if (fp == fromSecondProgFP && secondSendTime == 2)
 
4111
        {
 
4112
            /* Second program doesn't have the "time" command */
 
4113
            secondSendTime = 0;
 
4114
            return;
 
4115
        }
 
4116
 
 
4117
        if (forwardMostMove <= backwardMostMove) 
 
4118
            return;
 
4119
 
 
4120
        if (gameMode == PauseGame) 
 
4121
            PauseProc(NULL, NULL, NULL, NULL);
 
4122
 
 
4123
        if (gameMode == PlayFromGameFile)
 
4124
        {
 
4125
            /* Stop reading this game file */
 
4126
            gameMode = ForceMoves;
 
4127
            ModeHighlight();
 
4128
        }
 
4129
 
 
4130
        currentMove = --forwardMostMove;
 
4131
 
 
4132
        if ((gameMode == PlayFromGameFile) 
 
4133
            || (gameMode == ForceMoves))
 
4134
            DisplayClocks(ReDisplayTimers);
 
4135
        else
 
4136
            DisplayClocks(SwitchTimers);
 
4137
 
 
4138
        sprintf(buf1, "Illegal move: %s", parseList[currentMove]);
 
4139
        DisplayMessage(buf1, False);
 
4140
 
 
4141
        if (updateRemotePlayer)
 
4142
            DisplayMessage(buf1, True);
 
4143
 
 
4144
#ifdef BLINK_COUNT
 
4145
        /*
 
4146
         * Disable blinking of the target square.
 
4147
         */
 
4148
 
 
4149
        if (BlinkCount > 0)
 
4150
        {
 
4151
            /* If BlinkCount is even, the piece is currently displayed. */
 
4152
            if (!(BlinkCount & 1))
 
4153
                DrawSquare (BlinkRow, BlinkCol, EmptySquare);
 
4154
 
 
4155
            /* BlinkCount = 0 will force the next blink timeout
 
4156
             * to do nothing. */
 
4157
            BlinkCount = 0;
 
4158
        }
 
4159
#endif
 
4160
 
 
4161
        DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
 
4162
 
 
4163
        XSync(localPlayer.xDisplay, False);
 
4164
 
 
4165
        if (updateRemotePlayer)
 
4166
            XSync(remotePlayer.xDisplay, False);
 
4167
 
 
4168
        return;
 
4169
    }
 
4170
 
 
4171
    if (strstr(message, "GNU Shogi") != NULL)
 
4172
    {
 
4173
        at_least_gnushogi_1_2p03 = True;
 
4174
        return;
 
4175
    }
 
4176
 
 
4177
    if (strncmp(message, "Hint:", 5) == 0)
 
4178
    {
 
4179
        char promoPiece;
 
4180
        sscanf(message, "Hint: %s", machine_move);
 
4181
        ParseMachineMove(machine_move, &move_type,
 
4182
                         &from_x, &from_y, &to_x, &to_y);
 
4183
 
 
4184
        if (move_type == WhitePromotion || move_type == BlackPromotion)
 
4185
            promoPiece = '+';
 
4186
        else
 
4187
            promoPiece = NULLCHAR;
 
4188
 
 
4189
        move_type = MakeAlg(from_x, from_y, to_x, to_y, promoPiece,
 
4190
                            currentMove, buf1);
 
4191
        sprintf(buf2, "Hint: %s", buf1);
 
4192
        DisplayMessage(buf2, False);
 
4193
 
 
4194
        if (updateRemotePlayer)
 
4195
            DisplayMessage(buf2, True);
 
4196
 
 
4197
        return;
 
4198
    }
 
4199
 
 
4200
    if (strncmp(message, "Clocks:", 7) == 0)
 
4201
    {
 
4202
        sscanf(message, "Clocks: %ld %ld",
 
4203
               &blackTimeRemaining, &whiteTimeRemaining);
 
4204
        DisplayClocks(ReDisplayTimers);
 
4205
 
 
4206
        return;
 
4207
    }
 
4208
 
 
4209
    /*
 
4210
     * win, lose or draw
 
4211
     */
 
4212
 
 
4213
    if (strncmp(message, "Black", 5) == 0)
 
4214
    {
 
4215
        ShutdownShogiPrograms("Black wins");
 
4216
        return;
 
4217
    }
 
4218
    else if (strncmp(message, "White", 5) == 0)
 
4219
    {
 
4220
        ShutdownShogiPrograms("White wins");
 
4221
        return;
 
4222
    }
 
4223
    else if (strncmp(message, "Repetition", 10) == 0)
 
4224
    {
 
4225
        ShutdownShogiPrograms("Repetition");
 
4226
        return;
 
4227
    }
 
4228
    else if (strncmp(message, "opponent mates!", 15) == 0)
 
4229
    {
 
4230
        switch ((gameMode == PauseGame) ? pausePreviousMode : gameMode)
 
4231
        {
 
4232
        case MachinePlaysWhite:
 
4233
            ShutdownShogiPrograms("Black wins");
 
4234
            break;
 
4235
 
 
4236
        case MachinePlaysBlack:
 
4237
            ShutdownShogiPrograms("White wins");
 
4238
            break;
 
4239
 
 
4240
        case TwoMachinesPlay:
 
4241
            ShutdownShogiPrograms((fp == fromFirstProgFP)
 
4242
                                  ? "Black wins" : "White wins");
 
4243
            break;
 
4244
 
 
4245
        default:
 
4246
            /* can't happen */
 
4247
            break;
 
4248
        }
 
4249
 
 
4250
        return;
 
4251
    }
 
4252
    else if (strncmp(message, "computer mates!", 15) == 0)
 
4253
    {
 
4254
        switch ((gameMode == PauseGame) ? pausePreviousMode : gameMode)
 
4255
        {
 
4256
        case MachinePlaysWhite:
 
4257
            ShutdownShogiPrograms("White wins");
 
4258
            break;
 
4259
 
 
4260
        case MachinePlaysBlack:
 
4261
            ShutdownShogiPrograms("Black wins");
 
4262
            break;
 
4263
 
 
4264
        case TwoMachinesPlay:
 
4265
            ShutdownShogiPrograms((fp == fromFirstProgFP)
 
4266
                                  ? "White wins" : "Black wins");
 
4267
            break;
 
4268
 
 
4269
        default:
 
4270
            /* can't happen */
 
4271
            break;
 
4272
        }
 
4273
 
 
4274
        return;
 
4275
    }
 
4276
    else if (strncmp(message, "Draw", 4) == 0)
 
4277
    {
 
4278
        ShutdownShogiPrograms("Draw");
 
4279
        return;
 
4280
    }
 
4281
 
 
4282
    /*
 
4283
     * normal machine reply move
 
4284
     */
 
4285
    maybeThinking = True;
 
4286
 
 
4287
    if (strstr(message, "...") != NULL)
 
4288
    {
 
4289
        sscanf(message, "%s %s %s", buf1, buf2, machine_move);
 
4290
 
 
4291
#ifdef SYNCHTIME
 
4292
        mpr = message;
 
4293
        SkipString(&mpr); /* skip move number */
 
4294
        SkipString(&mpr); /* skip ... */
 
4295
        SkipString(&mpr); /* skip move */
 
4296
 
 
4297
        if ((gameMode != TwoMachinesPlay) && (gameMode != ForceMoves)
 
4298
            && ((*mpr == '-') || ((*mpr >= '0') && (*mpr <= '9'))))
 
4299
        {
 
4300
            /* synchronize with shogi program clock */
 
4301
            sscanf(mpr, "%ld", &time_remaining);
 
4302
 
 
4303
            if (xshogiDebug)
 
4304
            {
 
4305
                printf("from '%s' synchronize %s clock %ld\n",
 
4306
                       message, 
 
4307
                       (BlackOnMove(forwardMostMove)
 
4308
                        ? "Black's" 
 
4309
                        : "White's"), 
 
4310
                       time_remaining);
 
4311
            }
 
4312
 
 
4313
            if (BlackOnMove(forwardMostMove))
 
4314
                blackTimeRemaining = time_remaining;
 
4315
            else
 
4316
                whiteTimeRemaining = time_remaining;
 
4317
        }
 
4318
#endif
 
4319
 
 
4320
        if (machine_move[0] == NULLCHAR)
 
4321
            return;
 
4322
    }
 
4323
    else
 
4324
    {
 
4325
        mpr = message;
 
4326
 
 
4327
#ifdef SYNCHTIME
 
4328
        if (strstr(message, "time") == NULL)
 
4329
        {
 
4330
            /* remaining time will be determined from move */
 
4331
            SkipString(&mpr); /* skip move number */
 
4332
            SkipString(&mpr); /* skip move */
 
4333
        }
 
4334
 
 
4335
        if ((gameMode != TwoMachinesPlay) && (gameMode != ForceMoves)
 
4336
            && ((*mpr == '-') || ((*mpr >= '0') && (*mpr <= '9'))))
 
4337
        {
 
4338
            /* synchronize with shogi program clock */
 
4339
            sscanf(mpr, "%ld", &time_remaining);
 
4340
 
 
4341
            if (xshogiDebug)
 
4342
            {
 
4343
                printf("from '%s' synchronize %s clock %ld\n",
 
4344
                       message, 
 
4345
                       ((!BlackOnMove(forwardMostMove))
 
4346
                        ? "Black's" : "White's"), 
 
4347
                       time_remaining);
 
4348
            }
 
4349
 
 
4350
            if (!BlackOnMove(forwardMostMove))
 
4351
                blackTimeRemaining = time_remaining;
 
4352
            else
 
4353
                whiteTimeRemaining = time_remaining;
 
4354
        }
 
4355
        else
 
4356
#endif
 
4357
 
 
4358
            if (xshogiDebug)
 
4359
                printf("ignore noise: '%s'\n", message);
 
4360
 
 
4361
        return; /* ignore noise */
 
4362
    }
 
4363
 
 
4364
    strcpy(moveList[forwardMostMove], machine_move);
 
4365
 
 
4366
    ParseMachineMove(machine_move, &move_type, &from_x, &from_y,
 
4367
                     &to_x, &to_y);
 
4368
 
 
4369
    if (gameMode != PauseGame)
 
4370
        currentMove = forwardMostMove;  /* display latest move */
 
4371
 
 
4372
    MakeMove(&move_type, from_x, from_y, to_x, to_y);
 
4373
 
 
4374
#ifdef BLINK_COUNT
 
4375
    if (gameMode != TwoMachinesPlay)
 
4376
        BlinkSquare(to_y, to_x, boards[currentMove][to_y][to_x]);
 
4377
#endif
 
4378
 
 
4379
    if ((gameMode != PauseGame) && localPlayer.appData.ringBellAfterMoves)
 
4380
        putc(BELLCHAR, stderr);
 
4381
 
 
4382
    if ((gameMode == TwoMachinesPlay)
 
4383
        || ((gameMode == PauseGame) 
 
4384
            && (pausePreviousMode == TwoMachinesPlay)))
 
4385
    {
 
4386
        strcat(machine_move, "\n");
 
4387
 
 
4388
        if (BlackOnMove(forwardMostMove))
 
4389
        {
 
4390
            Attention(secondProgramPID);
 
4391
 
 
4392
            if (secondSendTime)
 
4393
                SendTimeRemaining(toSecondProgFP);
 
4394
 
 
4395
            SendToProgram(machine_move, toSecondProgFP);
 
4396
 
 
4397
            if (firstMove)
 
4398
            {
 
4399
                firstMove = False;
 
4400
                SendToProgram(localPlayer.appData.blackString,
 
4401
                              toSecondProgFP);
 
4402
            }
 
4403
        }
 
4404
        else
 
4405
        {
 
4406
            Attention(firstProgramPID);
 
4407
 
 
4408
            if (firstSendTime)
 
4409
                SendTimeRemaining(toFirstProgFP);
 
4410
 
 
4411
            SendToProgram(machine_move, toFirstProgFP);
 
4412
 
 
4413
            if (firstMove)
 
4414
            {
 
4415
                firstMove = False;
 
4416
                SendToProgram(localPlayer.appData.blackString,
 
4417
                              toFirstProgFP);
 
4418
            }
 
4419
        }
 
4420
    }
 
4421
}
 
4422
 
 
4423
 
 
4424
 
 
4425
 
 
4426
void
 
4427
ReadGameFile(void)
 
4428
{
 
4429
    for (;;)
 
4430
    {
 
4431
        if (!ReadGameFileProc())
 
4432
            return;
 
4433
 
 
4434
        if (matchMode == MatchOpening)
 
4435
            continue;
 
4436
 
 
4437
        readGameXID
 
4438
            = XtAppAddTimeOut(appContext,
 
4439
                              (int)(1000 * localPlayer.appData.timeDelay),
 
4440
                              (XtTimerCallbackProc) ReadGameFile, NULL);
 
4441
        break;
 
4442
    }
 
4443
}
 
4444
 
 
4445
 
 
4446
 
 
4447
/*
 
4448
 * FIXME: there is a naming inconsistency: here ReadGameFileProc() is
 
4449
 * called by ReadGameFile() while in other places XXXProc() calls XXX().
 
4450
 */
 
4451
 
 
4452
int
 
4453
ReadGameFileProc(void)
 
4454
{
 
4455
    ShogiMove move_type;
 
4456
    char move[MSG_SIZ], buf[MSG_SIZ];
 
4457
 
 
4458
    if (gameFileFP == NULL)
 
4459
        return (int)False;
 
4460
 
 
4461
    if (gameMode == PauseGame) 
 
4462
        return True;
 
4463
 
 
4464
    if (gameMode != PlayFromGameFile)
 
4465
    {
 
4466
        fclose(gameFileFP);
 
4467
        gameFileFP = NULL;
 
4468
        return (int)False;
 
4469
    }
 
4470
 
 
4471
    if (commentUp)
 
4472
    {
 
4473
        XtPopdown(commentShell);
 
4474
        XtDestroyWidget(commentShell);
 
4475
        commentUp = False;
 
4476
    }
 
4477
 
 
4478
    fgets(move, MSG_SIZ, gameFileFP);
 
4479
    move[strlen(move) - 1] = NULLCHAR;
 
4480
    sprintf(buf, "# %s game file", programName);
 
4481
 
 
4482
    if (strncmp(move, buf, strlen(buf)))
 
4483
    {
 
4484
        strcat(move, ": no xshogi game file");
 
4485
        DisplayMessage(move, False);
 
4486
        return (int)False;
 
4487
    }
 
4488
 
 
4489
    DisplayName(move);
 
4490
    rewind(gameFileFP);
 
4491
 
 
4492
    parseGameFile();
 
4493
 
 
4494
    move_type = (ShogiMove)0;
 
4495
 
 
4496
    lastGameMode = gameMode;
 
4497
    gameMode = ForceMoves;
 
4498
    ModeHighlight();
 
4499
    DisplayMessage("End of game file", False);
 
4500
 
 
4501
    if (readGameXID != 0)
 
4502
    {
 
4503
        XtRemoveTimeOut(readGameXID);
 
4504
        readGameXID = 0;
 
4505
    }
 
4506
 
 
4507
    fclose(gameFileFP);
 
4508
    gameFileFP = NULL;
 
4509
 
 
4510
    return (int)False;
 
4511
}
 
4512
 
 
4513
 
 
4514
 
 
4515
 
 
4516
/* 
 
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.
 
4520
 */
 
4521
 
 
4522
void
 
4523
ApplyMove(ShogiMove *move_type, int from_x, int from_y,
 
4524
          int to_x, int to_y, int currentMove)
 
4525
{
 
4526
    ShogiSquare piece, cpiece;
 
4527
    char pieceChar;
 
4528
    int  i, c;
 
4529
 
 
4530
    if (from_x > 80)
 
4531
    {
 
4532
        i = from_x - 81;
 
4533
        c = (BlackOnMove(currentMove) ? 1 : 0);
 
4534
        cpiece = catchedIndexToPiece[c][i];
 
4535
        boards[currentMove][to_y][to_x] = cpiece;
 
4536
        catches[currentMove][c][i]--;
 
4537
    }
 
4538
    else if (PromotionPossible(from_y, to_y,
 
4539
                               piece = boards[currentMove][from_y][from_x]))
 
4540
    {
 
4541
        cpiece = boards[currentMove][to_y][to_x];
 
4542
 
 
4543
        if (cpiece != EmptySquare)
 
4544
        {
 
4545
            i = pieceToCatchedIndex[cpiece];
 
4546
            c = (cpiece < WhitePawn);
 
4547
            catches[currentMove][c][i]++;
 
4548
        }
 
4549
 
 
4550
        if (*move_type == NormalMove)
 
4551
        {
 
4552
            boards[currentMove][to_y][to_x] = piece;
 
4553
        }
 
4554
        else
 
4555
        {
 
4556
            boards[currentMove][to_y][to_x] = piece = pieceToPromoted[piece];
 
4557
            pieceChar = '+';
 
4558
        }
 
4559
 
 
4560
        boards[currentMove][from_y][from_x] = EmptySquare;
 
4561
    }
 
4562
    else
 
4563
    {
 
4564
        ShogiSquare piece = boards[currentMove][to_y][to_x];
 
4565
 
 
4566
        if (piece != EmptySquare)
 
4567
        {
 
4568
            i = pieceToCatchedIndex[piece];
 
4569
            c = (piece < WhitePawn);
 
4570
            catches[currentMove][c][i]++;
 
4571
        }
 
4572
 
 
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;
 
4577
    }
 
4578
}
 
4579
 
 
4580
 
 
4581
 
 
4582
 
 
4583
/*
 
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.
 
4587
 */
 
4588
 
 
4589
void
 
4590
MakeMove(ShogiMove *move_type, int from_x, int from_y, int to_x, int to_y)
 
4591
{
 
4592
    char message[MSG_SIZ], movestr[MSG_SIZ];
 
4593
    char promoPiece = NULLCHAR;
 
4594
 
 
4595
    forwardMostMove++;
 
4596
 
 
4597
    CopyBoard(boards[forwardMostMove], boards[forwardMostMove - 1]);
 
4598
    CopyCatches(catches[forwardMostMove], catches[forwardMostMove - 1]);
 
4599
 
 
4600
    ApplyMove(move_type, from_x, from_y, to_x, to_y, forwardMostMove);
 
4601
 
 
4602
    endMessage[0] = NULLCHAR;
 
4603
 
 
4604
    timeRemaining[0][forwardMostMove] = blackTimeRemaining;
 
4605
    timeRemaining[1][forwardMostMove] = whiteTimeRemaining;
 
4606
 
 
4607
    if ((gameMode == PauseGame) && (pausePreviousMode != PlayFromGameFile))
 
4608
        return;
 
4609
 
 
4610
    currentMove = forwardMostMove;
 
4611
 
 
4612
    if (gameMode == PlayFromGameFile)
 
4613
    {
 
4614
        sprintf(message, "%d. %s%s", 
 
4615
                ((currentMove + 1) / 2),
 
4616
                (BlackOnMove(currentMove) ? "... " : ""), 
 
4617
                currentMoveString);
 
4618
        strcpy(parseList[currentMove - 1], currentMoveString);
 
4619
    }
 
4620
    else
 
4621
    {
 
4622
        if ((*move_type == WhitePromotion) || (*move_type == BlackPromotion))
 
4623
            promoPiece = '+';
 
4624
        else
 
4625
            promoPiece = NULLCHAR;
 
4626
 
 
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) ? "... " : ""), 
 
4632
                movestr);
 
4633
        strcpy(parseList[currentMove - 1], movestr);
 
4634
    }
 
4635
 
 
4636
    DisplayMessage(message, False);
 
4637
 
 
4638
    if ((gameMode == PlayFromGameFile) || (gameMode == ForceMoves) 
 
4639
        || ((gameMode == PauseGame) 
 
4640
            && (pausePreviousMode == PlayFromGameFile)))
 
4641
    {
 
4642
        DisplayClocks(ReDisplayTimers);
 
4643
    }
 
4644
    else
 
4645
    {
 
4646
        DisplayClocks(SwitchTimers);
 
4647
    }
 
4648
 
 
4649
    DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
 
4650
 
 
4651
    XSync(localPlayer.xDisplay, False);
 
4652
 
 
4653
    if (updateRemotePlayer)
 
4654
    {
 
4655
        DisplayMessage(message, True);
 
4656
        XSync(remotePlayer.xDisplay, False);
 
4657
    }
 
4658
}
 
4659
 
 
4660
 
 
4661
 
 
4662
 
 
4663
void
 
4664
InitShogiProgram(char *host_name, char *program_name, int *pid,
 
4665
                 FILE **to, FILE **from, XtIntervalId *xid, int *sendTime)
 
4666
{
 
4667
    char  arg_buf[10];
 
4668
    char *arg1, *arg2;
 
4669
    int   to_prog[2], from_prog[2];
 
4670
    FILE *from_fp, *to_fp;
 
4671
    int   dummy_source;
 
4672
    XtInputId dummy_id;
 
4673
 
 
4674
    if (localPlayer.appData.noShogiProgram) 
 
4675
        return;
 
4676
 
 
4677
    signal(SIGPIPE, CatchPipeSignal);
 
4678
    pipe(to_prog);
 
4679
    pipe(from_prog);
 
4680
 
 
4681
    if ((*pid = fork()) == 0)
 
4682
    {
 
4683
        signal(SIGPIPE, CatchPipeSignal);
 
4684
 
 
4685
        dup2(to_prog[0], 0);
 
4686
        dup2(from_prog[1], 1);
 
4687
        close(to_prog[0]);
 
4688
        close(to_prog[1]);
 
4689
        close(from_prog[0]);
 
4690
        close(from_prog[1]);
 
4691
        dup2(1, fileno(stderr));    /* force stderr to the pipe */
 
4692
 
 
4693
        if (localPlayer.appData.searchTime != NULL)
 
4694
        {
 
4695
            sprintf(arg_buf, "%d", searchTime);
 
4696
            arg1 = arg_buf;
 
4697
            arg2 = (char *)NULL;
 
4698
        }
 
4699
        else if (localPlayer.appData.searchDepth > 0)
 
4700
        {
 
4701
            sprintf(arg_buf, "%d", localPlayer.appData.searchDepth);
 
4702
            arg1 = "1";
 
4703
            arg2 = "9999";
 
4704
        }
 
4705
        else
 
4706
        {
 
4707
            sprintf(arg_buf, "%d", localPlayer.appData.movesPerSession);
 
4708
            arg1 = arg_buf;
 
4709
            arg2 = localPlayer.appData.timeControl;
 
4710
        }
 
4711
 
 
4712
        if (strcmp(host_name, "localhost") == 0)
 
4713
        {
 
4714
            execlp(program_name, program_name, arg1, arg2,
 
4715
                   (char *)NULL);
 
4716
        }
 
4717
        else
 
4718
        {
 
4719
            execlp(localPlayer.appData.remoteShell,
 
4720
                   localPlayer.appData.remoteShell,
 
4721
                   host_name, program_name, arg1, arg2,
 
4722
                   (char *)NULL);
 
4723
        }
 
4724
 
 
4725
        perror(program_name);
 
4726
        exit(1);
 
4727
    }
 
4728
 
 
4729
    close(to_prog[0]);
 
4730
    close(from_prog[1]);
 
4731
 
 
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);
 
4736
 
 
4737
    ReceiveFromProgram(from_fp, &dummy_source, &dummy_id); /* "GNU Shogi"*/
 
4738
 
 
4739
    if (!at_least_gnushogi_1_2p03)
 
4740
    {
 
4741
        fprintf(stderr, "you must have at least gnushogi-1.2p03\n");
 
4742
        exit(1);
 
4743
    }
 
4744
 
 
4745
    if (*pid == 0)
 
4746
        return;
 
4747
 
 
4748
    *xid = XtAppAddInput(appContext, fileno(from_fp),
 
4749
                         (XtPointer)XtInputReadMask,
 
4750
                         (XtInputCallbackProc)ReceiveFromProgram,
 
4751
                         (XtPointer)from_fp);
 
4752
 
 
4753
    SendToProgram(localPlayer.appData.initString, *to);
 
4754
 
 
4755
    if (localPlayer.appData.gameIn)
 
4756
        SendToProgram("gamein\n", *to);
 
4757
 
 
4758
    SendSearchDepth(*to);
 
4759
 
 
4760
    if (*sendTime == 2)
 
4761
    {
 
4762
        /* Does program have "time" command? */
 
4763
        char buf[MSG_SIZ];
 
4764
 
 
4765
        sprintf(buf, "time %ld\n", blackTimeRemaining / 10);
 
4766
        SendToProgram(buf, to_fp);
 
4767
        ReceiveFromProgram(from_fp, &dummy_source, &dummy_id);
 
4768
 
 
4769
        if (*sendTime == 2)
 
4770
        {
 
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);
 
4775
        }
 
4776
    }
 
4777
}
 
4778
 
 
4779
 
 
4780
 
 
4781
 
 
4782
void
 
4783
ShutdownShogiPrograms(char *why)
 
4784
{
 
4785
    lastGameMode = gameMode;
 
4786
    gameMode = EndOfGame;
 
4787
    ModeHighlight();
 
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;
 
4792
    currentMove++;
 
4793
    DisplayMessage(why, False);
 
4794
 
 
4795
    if (readGameXID != 0)
 
4796
        XtRemoveTimeOut(readGameXID);
 
4797
 
 
4798
    readGameXID = 0;
 
4799
 
 
4800
    if (firstProgramPID != 0)
 
4801
    {
 
4802
        fclose(fromFirstProgFP);
 
4803
        fclose(toFirstProgFP);
 
4804
        fromFirstProgFP = toFirstProgFP = NULL;
 
4805
 
 
4806
        if (kill(firstProgramPID, SIGTERM) == 0)
 
4807
            WAIT0;
 
4808
    }
 
4809
 
 
4810
    firstProgramPID = 0;
 
4811
 
 
4812
    if (firstProgramXID != 0)
 
4813
        XtRemoveInput(firstProgramXID);
 
4814
 
 
4815
    firstProgramXID = 0;
 
4816
 
 
4817
    if (secondProgramPID != 0)
 
4818
    {
 
4819
        fclose(fromSecondProgFP);
 
4820
        fclose(toSecondProgFP);
 
4821
        fromSecondProgFP = toSecondProgFP = NULL;
 
4822
 
 
4823
        if (kill(secondProgramPID, SIGTERM) == 0)
 
4824
            WAIT0;
 
4825
    }
 
4826
 
 
4827
    secondProgramPID = 0;
 
4828
 
 
4829
    if (secondProgramXID != 0)
 
4830
        XtRemoveInput(secondProgramXID);
 
4831
 
 
4832
    secondProgramXID = 0;
 
4833
 
 
4834
    DisplayClocks(StopTimers);
 
4835
 
 
4836
    if (matchMode != MatchFalse)
 
4837
    {
 
4838
        if (localPlayer.appData.saveGameFile[0] != NULLCHAR)
 
4839
            SaveGame(localPlayer.appData.saveGameFile);
 
4840
 
 
4841
        exit(0);
 
4842
    }
 
4843
}
 
4844
 
 
4845
 
 
4846
 
 
4847
 
 
4848
void
 
4849
CommentPopUp(char *label)
 
4850
{
 
4851
    Arg args[2];
 
4852
    Position x, y;
 
4853
    Dimension bw_width, pw_width;
 
4854
 
 
4855
    if (commentUp)
 
4856
    {
 
4857
        XtPopdown(commentShell);
 
4858
        XtDestroyWidget(commentShell);
 
4859
        commentUp = False;
 
4860
    }
 
4861
 
 
4862
    DisplayMessage("Comment", False);
 
4863
 
 
4864
    XtSetArg(args[0], XtNwidth, &bw_width);
 
4865
    XtGetValues(localPlayer.formWidget, args, 1);
 
4866
 
 
4867
    XtSetArg(args[0], XtNresizable, True);
 
4868
    XtSetArg(args[1], XtNwidth, bw_width - 8);
 
4869
 
 
4870
    commentShell = XtCreatePopupShell("Comment",
 
4871
                                      transientShellWidgetClass,
 
4872
                                      localPlayer.commandsWidget, args, 2);
 
4873
 
 
4874
    XtSetArg(args[0], XtNlabel, label);
 
4875
 
 
4876
    (void)XtCreateManagedWidget("commentLabel", labelWidgetClass,
 
4877
                                commentShell, args, 1);
 
4878
 
 
4879
    XtRealizeWidget(commentShell);
 
4880
 
 
4881
    XtSetArg(args[0], XtNwidth, &pw_width);
 
4882
    XtGetValues(commentShell, args, 1);
 
4883
 
 
4884
    XtTranslateCoords(localPlayer.shellWidget,
 
4885
                      (bw_width - pw_width) / 2, -50, &x, &y);
 
4886
 
 
4887
    XtSetArg(args[0], XtNx, x);
 
4888
    XtSetArg(args[1], XtNy, y);
 
4889
    XtSetValues(commentShell, args, 2);
 
4890
 
 
4891
    XtPopup(commentShell, XtGrabNone);
 
4892
    commentUp = True;
 
4893
}
 
4894
 
 
4895
 
 
4896
 
 
4897
 
 
4898
void
 
4899
FileNamePopUp(char *label, Boolean (*proc) (char *))
 
4900
{
 
4901
    Arg args[2];
 
4902
    Widget popup, dialog;
 
4903
    Position x, y;
 
4904
    Dimension bw_width, pw_width;
 
4905
 
 
4906
    fileProc = proc;
 
4907
 
 
4908
    XtSetArg(args[0], XtNwidth, &bw_width);
 
4909
    XtGetValues(localPlayer.boardWidget, args, 1);
 
4910
 
 
4911
    XtSetArg(args[0], XtNresizable, True);
 
4912
    XtSetArg(args[1], XtNwidth, DIALOG_SIZE);
 
4913
 
 
4914
    popup = XtCreatePopupShell("File Name Prompt",
 
4915
                               transientShellWidgetClass,
 
4916
                               localPlayer.commandsWidget, args, 2);
 
4917
 
 
4918
    XtSetArg(args[0], XtNlabel, label);
 
4919
    XtSetArg(args[1], XtNvalue, "");
 
4920
 
 
4921
    dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
 
4922
                                   popup, args, 2);
 
4923
 
 
4924
    XawDialogAddButton(dialog, "ok", FileNameCallback, (XtPointer) dialog);
 
4925
    XawDialogAddButton(dialog, "cancel", FileNameCallback,
 
4926
                       (XtPointer) dialog);
 
4927
 
 
4928
    XtRealizeWidget(popup);
 
4929
 
 
4930
    XtSetArg(args[0], XtNwidth, &pw_width);
 
4931
    XtGetValues(popup, args, 1);
 
4932
 
 
4933
    XtTranslateCoords(localPlayer.boardWidget,
 
4934
                      (bw_width - pw_width) / 2, 10, &x, &y);
 
4935
 
 
4936
    XtSetArg(args[0], XtNx, x);
 
4937
    XtSetArg(args[1], XtNy, y);
 
4938
    XtSetValues(popup, args, 2);
 
4939
 
 
4940
    XtPopup(popup, XtGrabExclusive);
 
4941
    filenameUp = True;
 
4942
 
 
4943
    XtSetKeyboardFocus(localPlayer.shellWidget, popup);
 
4944
}
 
4945
 
 
4946
 
 
4947
 
 
4948
 
 
4949
void
 
4950
FileNameCallback(Widget w, XtPointer client_data, XtPointer call_data)
 
4951
{
 
4952
    String name;
 
4953
    Arg args[1];
 
4954
 
 
4955
    XtSetArg(args[0], XtNlabel, &name);
 
4956
    XtGetValues(w, args, 1);
 
4957
 
 
4958
    if (strcmp(name, "cancel") == 0)
 
4959
    {
 
4960
        XtPopdown(w = XtParent(XtParent(w)));
 
4961
        XtDestroyWidget(w);
 
4962
        filenameUp = False;
 
4963
        ModeHighlight();
 
4964
        return;
 
4965
    }
 
4966
 
 
4967
    FileNameAction(w, NULL, NULL, NULL);
 
4968
}
 
4969
 
 
4970
 
 
4971
 
 
4972
 
 
4973
void
 
4974
FileNameAction(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
4975
{
 
4976
    char buf[MSG_SIZ];
 
4977
    String name;
 
4978
 
 
4979
    name = XawDialogGetValueString(w = XtParent(w));
 
4980
 
 
4981
    if ((name != NULL) && (*name != NULLCHAR))
 
4982
    {
 
4983
        strcpy(buf, name);
 
4984
        XtPopdown(w = XtParent(w));
 
4985
        XtDestroyWidget(w);
 
4986
        filenameUp = False;
 
4987
        (*fileProc)(buf);  /* I can't see a way not
 
4988
                              to use a global here */
 
4989
        ModeHighlight();
 
4990
        return;
 
4991
    }
 
4992
 
 
4993
    XtPopdown(w = XtParent(w));
 
4994
    XtDestroyWidget(w);
 
4995
    filenameUp = False;
 
4996
    ModeHighlight();
 
4997
}
 
4998
 
 
4999
 
 
5000
 
 
5001
 
 
5002
void
 
5003
PromotionPopUp(ShogiSquare piece, int to_x, int to_y, int fromRemotePlayer)
 
5004
{
 
5005
    Arg args[2];
 
5006
    Widget dialog;
 
5007
    Position x, y;
 
5008
    Dimension bw_width, bw_height, pw_width, pw_height;
 
5009
 
 
5010
    player = (fromRemotePlayer ? &remotePlayer : &localPlayer);
 
5011
 
 
5012
    pmi.piece = piece;
 
5013
    pmi.to_x = to_x;
 
5014
    pmi.to_y = to_y;
 
5015
 
 
5016
    XtSetArg(args[0], XtNwidth, &bw_width);
 
5017
    XtSetArg(args[1], XtNheight, &bw_height);
 
5018
    XtGetValues(player->boardWidget, args, 2);
 
5019
 
 
5020
    XtSetArg(args[0], XtNresizable, True);
 
5021
 
 
5022
    player->promotionShell
 
5023
        = XtCreatePopupShell("Promotion",
 
5024
                             transientShellWidgetClass,
 
5025
                             player->commandsWidget, args, 1);
 
5026
 
 
5027
    XtSetArg(args[0], XtNlabel, "Promote piece?");
 
5028
    dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
 
5029
                                   player->promotionShell, args, 1);
 
5030
 
 
5031
    XawDialogAddButton(dialog, "Yes", PromotionCallback,
 
5032
                       (XtPointer) dialog);
 
5033
    XawDialogAddButton(dialog, "No", PromotionCallback,
 
5034
                       (XtPointer) dialog);
 
5035
    XawDialogAddButton(dialog, "cancel", PromotionCallback,
 
5036
                       (XtPointer) dialog);
 
5037
 
 
5038
    XtRealizeWidget(player->promotionShell);
 
5039
 
 
5040
    XtSetArg(args[0], XtNwidth, &pw_width);
 
5041
    XtSetArg(args[1], XtNheight, &pw_height);
 
5042
    XtGetValues(player->promotionShell, args, 2);
 
5043
 
 
5044
    XtTranslateCoords(player->boardWidget, 
 
5045
                      ((bw_width - pw_width) / 2),
 
5046
                      (LINE_GAP 
 
5047
                       + player->squareSize / 3 
 
5048
                       + (((piece == BlackPawn) ^ (player->flipView)) 
 
5049
                          ? 0 
 
5050
                          : (6 * (player->squareSize + LINE_GAP)))),
 
5051
                      &x, &y);
 
5052
 
 
5053
    XtSetArg(args[0], XtNx, x);
 
5054
    XtSetArg(args[1], XtNy, y);
 
5055
    XtSetValues(player->promotionShell, args, 2);
 
5056
 
 
5057
    XtPopup(player->promotionShell, XtGrabNone);
 
5058
 
 
5059
    player->promotionUp = True;
 
5060
}
 
5061
 
 
5062
 
 
5063
 
 
5064
 
 
5065
void
 
5066
PromotionCallback(Widget w, XtPointer client_data, XtPointer call_data)
 
5067
{
 
5068
    String name;
 
5069
    Arg args[1];
 
5070
    ShogiMove move_type;
 
5071
    struct DisplayData *player;
 
5072
 
 
5073
    XtSetArg(args[0], XtNlabel, &name);
 
5074
    XtGetValues(w, args, 1);
 
5075
 
 
5076
    w = XtParent(XtParent(w));
 
5077
    player = ((w == remotePlayer.promotionShell)
 
5078
              ? &remotePlayer : &localPlayer);
 
5079
    XtPopdown(w);
 
5080
    XtDestroyWidget(w);
 
5081
    player->promotionUp = False;
 
5082
 
 
5083
    if (fromX == -1) 
 
5084
        return;
 
5085
 
 
5086
    if (strcmp(name, "Yes") == 0)
 
5087
    {
 
5088
        if ((int)pmi.piece < (int)WhitePawn)
 
5089
            move_type = BlackPromotion;
 
5090
        else
 
5091
            move_type = WhitePromotion;
 
5092
    }
 
5093
    else if (strcmp(name, "No") == 0)
 
5094
    {
 
5095
        move_type = NormalMove;
 
5096
    }
 
5097
    else /* strcmp(name, "cancel") == 0 */
 
5098
    {
 
5099
        fromX = fromY = -1;
 
5100
        return;
 
5101
    }
 
5102
 
 
5103
    MakeMove(&move_type, fromX, fromY, pmi.to_x, pmi.to_y);
 
5104
 
 
5105
#ifdef BLINK_COUNT
 
5106
    if (updateRemotePlayer)
 
5107
    {
 
5108
        BlinkSquare(pmi.to_y, pmi.to_x,
 
5109
                    boards[currentMove][pmi.to_y][pmi.to_x]);
 
5110
    }
 
5111
#endif
 
5112
 
 
5113
    FinishUserMove(move_type, pmi.to_x, pmi.to_y);
 
5114
}
 
5115
 
 
5116
 
 
5117
 
 
5118
 
 
5119
void
 
5120
FileModePopUp(char *name)
 
5121
{
 
5122
    Arg args[2];
 
5123
    Widget dialog;
 
5124
    Position x, y;
 
5125
    Dimension bw_width, bw_height, pw_width, pw_height;
 
5126
 
 
5127
    struct DisplayData *player = &localPlayer;
 
5128
 
 
5129
    strcpy(fmi.name, name);
 
5130
 
 
5131
    XtSetArg(args[0], XtNwidth, &bw_width);
 
5132
    XtSetArg(args[1], XtNheight, &bw_height);
 
5133
    XtGetValues(player->boardWidget, args, 2);
 
5134
 
 
5135
    XtSetArg(args[0], XtNresizable, True);
 
5136
    player->filemodeShell
 
5137
        = XtCreatePopupShell("FileMode",
 
5138
                             transientShellWidgetClass,
 
5139
                             player->commandsWidget, args, 1);
 
5140
 
 
5141
    XtSetArg(args[0], XtNlabel, "Append to existing file?");
 
5142
    dialog = XtCreateManagedWidget("filemode", dialogWidgetClass,
 
5143
                                   player->filemodeShell, args, 1);
 
5144
 
 
5145
    XawDialogAddButton(dialog, "Yes", FileModeCallback,
 
5146
                       (XtPointer) dialog);
 
5147
    XawDialogAddButton(dialog, "No", FileModeCallback,
 
5148
                       (XtPointer) dialog);
 
5149
    XawDialogAddButton(dialog, "cancel", FileModeCallback,
 
5150
                       (XtPointer) dialog);
 
5151
 
 
5152
    XtRealizeWidget(player->filemodeShell);
 
5153
 
 
5154
    XtSetArg(args[0], XtNwidth, &pw_width);
 
5155
    XtSetArg(args[1], XtNheight, &pw_height);
 
5156
    XtGetValues(player->filemodeShell, args, 2);
 
5157
 
 
5158
    XtTranslateCoords(player->boardWidget, (bw_width - pw_width) / 2,
 
5159
                      LINE_GAP + player->squareSize/3 +
 
5160
                      (6*(player->squareSize + LINE_GAP)),
 
5161
                      &x, &y);
 
5162
 
 
5163
    XtSetArg(args[0], XtNx, x);
 
5164
    XtSetArg(args[1], XtNy, y);
 
5165
    XtSetValues(player->filemodeShell, args, 2);
 
5166
 
 
5167
    XtPopup(player->filemodeShell, XtGrabNone);
 
5168
 
 
5169
    filemodeUp = True;
 
5170
}
 
5171
 
 
5172
 
 
5173
 
 
5174
 
 
5175
void
 
5176
FileModeCallback(Widget w, XtPointer client_data, XtPointer call_data)
 
5177
{
 
5178
    String name;
 
5179
    Arg args[1];
 
5180
 
 
5181
    XtSetArg(args[0], XtNlabel, &name);
 
5182
    XtGetValues(w, args, 1);
 
5183
 
 
5184
    XtPopdown(w = XtParent(XtParent(w)));
 
5185
    XtDestroyWidget(w);
 
5186
 
 
5187
    if (strcmp(name, "Yes") == 0)
 
5188
    {
 
5189
        strcpy(fmi.mode, "a");
 
5190
    }
 
5191
    else if (strcmp(name, "No") == 0)
 
5192
    {
 
5193
        strcpy(fmi.mode, "w");
 
5194
    }
 
5195
    else /* strcmp(name, "cancel") == 0 */
 
5196
    {
 
5197
        filemodeUp = False;
 
5198
        return;
 
5199
    }
 
5200
 
 
5201
    XtPopdown(localPlayer.filemodeShell);
 
5202
    XtDestroyWidget(localPlayer.filemodeShell);
 
5203
 
 
5204
    SaveGame(fmi.name);
 
5205
 
 
5206
    filemodeUp = False;
 
5207
}
 
5208
 
 
5209
 
 
5210
 
 
5211
 
 
5212
void
 
5213
SelectCommand(Widget w, XtPointer client_data, XtPointer call_data)
 
5214
{
 
5215
    Cardinal fromRemotePlayer = (Cardinal)client_data;
 
5216
 
 
5217
    XawListReturnStruct *list_return = XawListShowCurrent(w);
 
5218
 
 
5219
    player = fromRemotePlayer ? &remotePlayer : &localPlayer;
 
5220
 
 
5221
    fromX = fromY = -1;
 
5222
 
 
5223
    if (player->promotionUp)
 
5224
    {
 
5225
        XtPopdown(player->promotionShell);
 
5226
        XtDestroyWidget(player->promotionShell);
 
5227
        player->promotionUp = False;
 
5228
    }
 
5229
 
 
5230
    (*buttonProcs[list_return->list_index])
 
5231
        (w, NULL, NULL, &fromRemotePlayer);
 
5232
 
 
5233
    if (!filenameUp) 
 
5234
        ModeHighlight();
 
5235
}
 
5236
 
 
5237
 
 
5238
 
 
5239
 
 
5240
void
 
5241
HighlightProcButton(XtActionProc proc)
 
5242
{
 
5243
    int i = 0;
 
5244
 
 
5245
    if (proc == NULL)
 
5246
    {
 
5247
        XawListUnhighlight(localPlayer.commandsWidget);
 
5248
 
 
5249
        if (updateRemotePlayer)
 
5250
            XawListUnhighlight(remotePlayer.commandsWidget);
 
5251
 
 
5252
        return;
 
5253
    }
 
5254
 
 
5255
    for (;;)
 
5256
    {
 
5257
        if (buttonProcs[i] == NULL)
 
5258
        {
 
5259
            XawListUnhighlight(localPlayer.commandsWidget);
 
5260
 
 
5261
            if (updateRemotePlayer)
 
5262
                XawListUnhighlight(remotePlayer.commandsWidget);
 
5263
 
 
5264
            return;
 
5265
        }
 
5266
 
 
5267
        if (buttonProcs[i] == proc)
 
5268
        {
 
5269
            XawListHighlight(localPlayer.commandsWidget, i);
 
5270
 
 
5271
            if (updateRemotePlayer)
 
5272
                XawListHighlight(remotePlayer.commandsWidget, i);
 
5273
 
 
5274
            return;
 
5275
        }
 
5276
 
 
5277
        i++;
 
5278
    }
 
5279
}
 
5280
 
 
5281
 
 
5282
 
 
5283
 
 
5284
void
 
5285
ModeHighlight(void)
 
5286
{
 
5287
    switch (gameMode)
 
5288
    {
 
5289
    case BeginningOfGame:
 
5290
        if (localPlayer.appData.noShogiProgram)
 
5291
            HighlightProcButton(ForceProc);
 
5292
        else
 
5293
            HighlightProcButton(MachineBlackProc);
 
5294
 
 
5295
        break;
 
5296
 
 
5297
    case MachinePlaysBlack:
 
5298
        HighlightProcButton(MachineBlackProc);
 
5299
        break;
 
5300
 
 
5301
    case MachinePlaysWhite:
 
5302
        HighlightProcButton(MachineWhiteProc);
 
5303
        break;
 
5304
 
 
5305
    case TwoMachinesPlay:
 
5306
        HighlightProcButton(TwoMachinesProc);
 
5307
        break;
 
5308
 
 
5309
    case ForceMoves:
 
5310
        HighlightProcButton(ForceProc);
 
5311
 
 
5312
        break;
 
5313
 
 
5314
    case PlayFromGameFile:
 
5315
        HighlightProcButton(LoadGameProc);
 
5316
        break;
 
5317
 
 
5318
    case PauseGame:
 
5319
        HighlightProcButton(PauseProc);
 
5320
        break;
 
5321
 
 
5322
    case EditPosition:
 
5323
        HighlightProcButton(EditPositionProc);
 
5324
        break;
 
5325
 
 
5326
    case EndOfGame:
 
5327
    default:
 
5328
        HighlightProcButton(NULL);
 
5329
        break;
 
5330
    }
 
5331
}
 
5332
 
 
5333
 
 
5334
 
 
5335
 
 
5336
/*
 
5337
 * Button procedures
 
5338
 */
 
5339
 
 
5340
void
 
5341
QuitRemotePlayerProc(void)
 
5342
{
 
5343
    /* This should be modified... */
 
5344
    XCloseDisplay(remotePlayer.xDisplay);
 
5345
    /* XtDestroyWidget(remotePlayer.shellWidget); */
 
5346
    updateRemotePlayer = False;
 
5347
    DisplayMessage("Remote player has pressed Quit", False);
 
5348
    fromX = fromY = -1;
 
5349
}
 
5350
 
 
5351
 
 
5352
 
 
5353
void
 
5354
QuitProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
5355
{
 
5356
    if (updateRemotePlayer)
 
5357
        QuitRemotePlayerProc();
 
5358
 
 
5359
    ShutdownShogiPrograms("Quitting");
 
5360
    exit(0);
 
5361
}
 
5362
 
 
5363
 
 
5364
 
 
5365
void
 
5366
LoadGameProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
5367
{
 
5368
    int fromRemotePlayer = *nprms;
 
5369
 
 
5370
    if (fromRemotePlayer)
 
5371
    {
 
5372
        DisplayMessage("only opponent may load game", fromRemotePlayer);
 
5373
        return;
 
5374
    }
 
5375
 
 
5376
    if (gameMode != BeginningOfGame)
 
5377
    {
 
5378
        DisplayMessage("Press Reset first", False);
 
5379
        return;
 
5380
    }
 
5381
 
 
5382
    if (localPlayer.appData.loadGameFile == NULL)
 
5383
        FileNamePopUp("Game file name?", LoadGame);
 
5384
    else
 
5385
        (void) LoadGame(localPlayer.appData.loadGameFile);
 
5386
}
 
5387
 
 
5388
 
 
5389
 
 
5390
 
 
5391
Boolean
 
5392
LoadGame(char *name)
 
5393
{
 
5394
    char buf[MSG_SIZ];
 
5395
 
 
5396
    if (gameMode != BeginningOfGame)
 
5397
    {
 
5398
        DisplayMessage("Press Reset first", False);
 
5399
        return (int)False;
 
5400
    }
 
5401
 
 
5402
    if (localPlayer.appData.loadGameFile != name)
 
5403
    {
 
5404
        if (localPlayer.appData.loadGameFile)
 
5405
            XtFree(localPlayer.appData.loadGameFile);
 
5406
 
 
5407
        localPlayer.appData.loadGameFile = XtMalloc(strlen(name) + 1);
 
5408
        strcpy(localPlayer.appData.loadGameFile, name);
 
5409
    }
 
5410
 
 
5411
    if ((gameFileFP = fopen(name, "r")) == NULL)
 
5412
    {
 
5413
        sprintf(buf, "Can't open %s", name);
 
5414
        DisplayMessage(buf, False);
 
5415
        XtFree(localPlayer.appData.loadGameFile);
 
5416
        localPlayer.appData.loadGameFile = NULL;
 
5417
        return (int)False;
 
5418
    }
 
5419
 
 
5420
    lastGameMode = gameMode = PlayFromGameFile;
 
5421
    ModeHighlight();
 
5422
    InitPosition(True);
 
5423
    DisplayClocks(StopTimers);
 
5424
 
 
5425
    if (firstProgramXID == 0)
 
5426
    {
 
5427
        InitShogiProgram(localPlayer.appData.firstHost,
 
5428
                         localPlayer.appData.firstShogiProgram,
 
5429
                         &firstProgramPID, &toFirstProgFP,
 
5430
                         &fromFirstProgFP, &firstProgramXID,
 
5431
                         &firstSendTime);
 
5432
    }
 
5433
 
 
5434
    SendToProgram(localPlayer.appData.initString, toFirstProgFP);
 
5435
    SendSearchDepth(toFirstProgFP);
 
5436
    SendToProgram("force\n", toFirstProgFP);
 
5437
 
 
5438
    currentMove = forwardMostMove = backwardMostMove = 0;
 
5439
 
 
5440
    ReadGameFile();
 
5441
 
 
5442
    return True;
 
5443
}
 
5444
 
 
5445
 
 
5446
 
 
5447
 
 
5448
/* 
 
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. 
 
5452
 */
 
5453
 
 
5454
void
 
5455
ResurrectShogiProgram(void)
 
5456
{
 
5457
    char buf[MSG_SIZ];
 
5458
    int i;
 
5459
 
 
5460
    if (currentMove > 0)
 
5461
        currentMove--;  /* delete "Black wins" or the like */
 
5462
 
 
5463
    InitShogiProgram(localPlayer.appData.firstHost,
 
5464
                     localPlayer.appData.firstShogiProgram,
 
5465
                     &firstProgramPID, &toFirstProgFP, &fromFirstProgFP,
 
5466
                     &firstProgramXID, &firstSendTime);
 
5467
 
 
5468
    SendToProgram(localPlayer.appData.initString, toFirstProgFP);
 
5469
    SendSearchDepth(toFirstProgFP);
 
5470
    SendToProgram("force\n", toFirstProgFP);
 
5471
    gameMode = lastGameMode = ForceMoves;
 
5472
    ModeHighlight();
 
5473
 
 
5474
    i = (whitePlaysFirst ? 1 : 0);
 
5475
 
 
5476
    if (startedFromSetupPosition)
 
5477
        SendBoard(toFirstProgFP, boards[i], catches[i]);
 
5478
 
 
5479
    for (; i < currentMove; i++)
 
5480
    {
 
5481
        strcpy(buf, moveList[i]);
 
5482
        SendToProgram(buf, toFirstProgFP);
 
5483
    }
 
5484
 
 
5485
    if (!firstSendTime)
 
5486
    {
 
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;
 
5492
    }
 
5493
}
 
5494
 
 
5495
 
 
5496
 
 
5497
 
 
5498
void
 
5499
MachineWhiteProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
5500
{
 
5501
    int fromRemotePlayer = *nprms;
 
5502
 
 
5503
    if (updateRemotePlayer)
 
5504
    {
 
5505
        DisplayMessage("no machine moves in challenge mode",
 
5506
                       fromRemotePlayer);
 
5507
 
 
5508
        return;
 
5509
    }
 
5510
 
 
5511
    if (gameMode == PauseGame)
 
5512
        PauseProc(w, event, prms, nprms);
 
5513
 
 
5514
    if (gameMode == PlayFromGameFile)
 
5515
        ForceProc(w, event, prms, nprms);
 
5516
 
 
5517
    if (gameMode == EditPosition)
 
5518
        EditPositionDone();
 
5519
 
 
5520
    if ((gameMode == EndOfGame)
 
5521
        || (gameMode == PlayFromGameFile)
 
5522
        || (gameMode == TwoMachinesPlay)
 
5523
        || localPlayer.appData.noShogiProgram
 
5524
        || (gameMode == MachinePlaysWhite))
 
5525
    {
 
5526
        return;
 
5527
    }
 
5528
 
 
5529
    if (BlackOnMove((gameMode == ForceMoves)
 
5530
                    ? currentMove 
 
5531
                    : forwardMostMove))
 
5532
    {
 
5533
        DisplayMessage("It is not White's turn", False);
 
5534
        return;
 
5535
    }
 
5536
 
 
5537
    if (gameMode == ForceMoves) 
 
5538
        forwardMostMove = currentMove;
 
5539
 
 
5540
    lastGameMode = gameMode = MachinePlaysWhite;
 
5541
    ModeHighlight();
 
5542
    SendToProgram(localPlayer.appData.whiteString, toFirstProgFP);
 
5543
    DisplayClocks(StartTimers);
 
5544
}
 
5545
 
 
5546
 
 
5547
 
 
5548
 
 
5549
void
 
5550
MachineBlackProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
5551
{
 
5552
    int fromRemotePlayer = *nprms;
 
5553
 
 
5554
    if (updateRemotePlayer)
 
5555
    {
 
5556
        DisplayMessage("no machine moves in challenge mode",
 
5557
                       fromRemotePlayer);
 
5558
        return;
 
5559
    }
 
5560
 
 
5561
    if (gameMode == PauseGame)
 
5562
        PauseProc(w, event, prms, nprms);
 
5563
 
 
5564
    if (gameMode == PlayFromGameFile)
 
5565
        ForceProc(w, event, prms, nprms);
 
5566
 
 
5567
    if (gameMode == EditPosition)
 
5568
        EditPositionDone();
 
5569
 
 
5570
    if ((gameMode == EndOfGame)
 
5571
        || (gameMode == PlayFromGameFile)
 
5572
        || (gameMode == TwoMachinesPlay)
 
5573
        || localPlayer.appData.noShogiProgram
 
5574
        || (gameMode == MachinePlaysBlack))
 
5575
    {
 
5576
        return;
 
5577
    }
 
5578
 
 
5579
    if (!BlackOnMove((gameMode == ForceMoves)
 
5580
                     ? currentMove 
 
5581
                     : forwardMostMove))
 
5582
    {
 
5583
        DisplayMessage("It is not Black's turn", False);
 
5584
        return;
 
5585
    }
 
5586
 
 
5587
    if (gameMode == ForceMoves) 
 
5588
        forwardMostMove = currentMove;
 
5589
 
 
5590
    lastGameMode = gameMode = MachinePlaysBlack;
 
5591
    ModeHighlight();
 
5592
    SendToProgram(localPlayer.appData.blackString, toFirstProgFP);
 
5593
    DisplayClocks(StartTimers);
 
5594
}
 
5595
 
 
5596
 
 
5597
 
 
5598
 
 
5599
void
 
5600
ForwardProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
5601
{
 
5602
    char buf[MSG_SIZ];
 
5603
    int target;
 
5604
    unsigned int state;
 
5605
 
 
5606
    int fromRemotePlayer = *nprms;
 
5607
 
 
5608
    if (updateRemotePlayer)
 
5609
    {
 
5610
        DisplayMessage("Forward button disabled", fromRemotePlayer);
 
5611
        return;
 
5612
    }
 
5613
 
 
5614
    if ((gameMode == EndOfGame) || (gameMode == EditPosition))
 
5615
        return;
 
5616
 
 
5617
    if (gameMode == PlayFromGameFile)
 
5618
        PauseProc(w, event, prms, nprms);
 
5619
 
 
5620
    if (currentMove >= forwardMostMove)
 
5621
        return;
 
5622
 
 
5623
    if (event == NULL)
 
5624
    {
 
5625
        /* Kludge */
 
5626
        Window root, child;
 
5627
        int root_x, root_y;
 
5628
        int win_x, win_y;
 
5629
        XQueryPointer(localPlayer.xDisplay, localPlayer.xBoardWindow,
 
5630
                      &root, &child, &root_x, &root_y,
 
5631
                      &win_x, &win_y, &state);
 
5632
    }
 
5633
    else
 
5634
    {
 
5635
        state = event->xkey.state;
 
5636
    }
 
5637
 
 
5638
    if (state & ShiftMask)
 
5639
        target = forwardMostMove;
 
5640
    else
 
5641
        target = currentMove + 1;
 
5642
 
 
5643
    if (gameMode == ForceMoves)
 
5644
    {
 
5645
        while (currentMove < target)
 
5646
        {
 
5647
            strcpy(buf, moveList[currentMove++]);
 
5648
            SendToProgram(buf, toFirstProgFP);
 
5649
        }
 
5650
    }
 
5651
    else
 
5652
    {
 
5653
        currentMove = target;
 
5654
    }
 
5655
 
 
5656
    if (gameMode == ForceMoves)
 
5657
    {
 
5658
        blackTimeRemaining = timeRemaining[0][currentMove];
 
5659
        whiteTimeRemaining = timeRemaining[1][currentMove];
 
5660
    }
 
5661
 
 
5662
    DisplayClocks(ReDisplayTimers);
 
5663
    DisplayMove(currentMove - 1);
 
5664
    DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
 
5665
}
 
5666
 
 
5667
 
 
5668
 
 
5669
 
 
5670
void
 
5671
ResetFileProc(void)
 
5672
{
 
5673
    char *buf = "";
 
5674
 
 
5675
    if (updateRemotePlayer)
 
5676
        return;
 
5677
 
 
5678
    if (localPlayer.appData.loadGameFile)
 
5679
        XtFree(localPlayer.appData.loadGameFile);
 
5680
 
 
5681
    if (localPlayer.appData.loadPositionFile)
 
5682
        XtFree(localPlayer.appData.loadPositionFile);
 
5683
 
 
5684
    localPlayer.appData.loadGameFile
 
5685
        = localPlayer.appData.loadPositionFile = NULL;
 
5686
    DisplayName(buf);
 
5687
 
 
5688
    if (gameFileFP != NULL)
 
5689
    {
 
5690
        fclose(gameFileFP);
 
5691
        gameFileFP = NULL;
 
5692
    }
 
5693
}
 
5694
 
 
5695
 
 
5696
 
 
5697
 
 
5698
void
 
5699
ResetChallenge(void)
 
5700
{
 
5701
    char *buf = "";
 
5702
 
 
5703
    if (localPlayer.appData.challengeDisplay)
 
5704
        XtFree(localPlayer.appData.challengeDisplay);
 
5705
 
 
5706
    localPlayer.appData.challengeDisplay = NULL;
 
5707
    DisplayName(buf);
 
5708
}
 
5709
 
 
5710
 
 
5711
 
 
5712
 
 
5713
void
 
5714
ResetProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
5715
{
 
5716
    int fromRemotePlayer = *nprms;
 
5717
 
 
5718
    if (fromRemotePlayer)
 
5719
    {
 
5720
        DisplayMessage("only your opponent may reset the game",
 
5721
                       fromRemotePlayer);
 
5722
        return;
 
5723
    }
 
5724
 
 
5725
    Reset(True);
 
5726
}
 
5727
 
 
5728
 
 
5729
 
 
5730
 
 
5731
void
 
5732
Reset(int redraw)  /* Boolean */
 
5733
{
 
5734
    ResetFileProc();
 
5735
    ResetChallenge();
 
5736
 
 
5737
    localPlayer.flipView = False;
 
5738
    remotePlayer.flipView = True;
 
5739
    startedFromSetupPosition = whitePlaysFirst = False;
 
5740
    matchMode = MatchFalse;
 
5741
    firstMove = True;
 
5742
    blackFlag = whiteFlag = False;
 
5743
    maybeThinking = False;
 
5744
 
 
5745
    endMessage[0] = NULLCHAR;
 
5746
 
 
5747
    ShutdownShogiPrograms("");
 
5748
    lastGameMode = gameMode = BeginningOfGame;
 
5749
    ModeHighlight();
 
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,
 
5758
                     &firstSendTime);
 
5759
 
 
5760
    if (commentUp)
 
5761
    {
 
5762
        XtPopdown(commentShell);
 
5763
        XtDestroyWidget(commentShell);
 
5764
        commentUp = False;
 
5765
    }
 
5766
 
 
5767
    if (localPlayer.promotionUp)
 
5768
    {
 
5769
        XtPopdown(localPlayer.promotionShell);
 
5770
        XtDestroyWidget(localPlayer.promotionShell);
 
5771
        localPlayer.promotionUp = False;
 
5772
    }
 
5773
 
 
5774
    if (updateRemotePlayer && remotePlayer.promotionUp)
 
5775
    {
 
5776
        XtPopdown(remotePlayer.promotionShell);
 
5777
        XtDestroyWidget(remotePlayer.promotionShell);
 
5778
        remotePlayer.promotionUp = False;
 
5779
    }
 
5780
}
 
5781
 
 
5782
 
 
5783
 
 
5784
 
 
5785
void
 
5786
ClearCatches(int (*catches)[8])
 
5787
{
 
5788
    int c, p;
 
5789
 
 
5790
    for (c = 0; c <= 1; c++)
 
5791
        for (p = 0; p <= 7; p++)
 
5792
            catches[c][p] = 0;
 
5793
}
 
5794
 
 
5795
 
 
5796
 
 
5797
 
 
5798
Boolean
 
5799
Challenge(char *name)
 
5800
{
 
5801
    char buf[MSG_SIZ];
 
5802
    int argc;
 
5803
    char **argv;
 
5804
    XrmDatabase database;
 
5805
 
 
5806
    if (gameMode != BeginningOfGame)
 
5807
    {
 
5808
        DisplayMessage("Press Reset first", False);
 
5809
        return (int)False;
 
5810
    }
 
5811
 
 
5812
    if (localPlayer.appData.challengeDisplay != name)
 
5813
    {
 
5814
        if (localPlayer.appData.challengeDisplay)
 
5815
            XtFree(localPlayer.appData.challengeDisplay);
 
5816
 
 
5817
        localPlayer.appData.challengeDisplay = XtMalloc(strlen(name) + 1);
 
5818
        strcpy(localPlayer.appData.challengeDisplay, name);
 
5819
    }
 
5820
 
 
5821
    sprintf(buf, "trying to connect to %s.....", name);
 
5822
    DisplayMessage(buf, False);
 
5823
 
 
5824
    argc = global_argc;
 
5825
    argv = global_argv;
 
5826
 
 
5827
    if ((remotePlayer.xDisplay
 
5828
         = XtOpenDisplay(appContext, name, "XShogi",
 
5829
                         "XShogi", 0, 0, &argc, argv)) == NULL)
 
5830
    {
 
5831
        sprintf(buf, "Can't open display %s", name);
 
5832
        DisplayMessage(buf, False);
 
5833
        XtFree(localPlayer.appData.challengeDisplay);
 
5834
        localPlayer.appData.challengeDisplay = NULL;
 
5835
        return (int)False;
 
5836
    }
 
5837
 
 
5838
    DisplayMessage("connected! creating remote window...", False);
 
5839
 
 
5840
    remotePlayer.xScreen = DefaultScreen(remotePlayer.xDisplay);
 
5841
 
 
5842
    remotePlayer.shellWidget
 
5843
        = XtAppCreateShell(NULL, "XShogi",
 
5844
                           applicationShellWidgetClass,
 
5845
                           remotePlayer.xDisplay, NULL, 0);
 
5846
 
 
5847
    database = XtDatabase(remotePlayer.xDisplay);
 
5848
 
 
5849
    XrmParseCommand(&database,
 
5850
                    shellOptions, XtNumber(shellOptions),
 
5851
                    "XShogi", &argc, argv);
 
5852
 
 
5853
    XtGetApplicationResources(remotePlayer.shellWidget,
 
5854
                              &remotePlayer.appData, clientResources,
 
5855
                              XtNumber(clientResources), NULL, 0);
 
5856
 
 
5857
    player = &remotePlayer;
 
5858
 
 
5859
    CreatePlayerWindow();
 
5860
 
 
5861
    updateRemotePlayer = True;
 
5862
 
 
5863
    DisplayName("REMOTE");
 
5864
    DrawPosition(remotePlayer.boardWidget, NULL, NULL, NULL);
 
5865
    DisplayClocks(ReDisplayTimers);
 
5866
 
 
5867
    DisplayMessage("ready to play", False);
 
5868
    DisplayMessage("ready to play", True);
 
5869
 
 
5870
    return True;
 
5871
}
 
5872
 
 
5873
 
 
5874
 
 
5875
 
 
5876
void
 
5877
ChallengeProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
5878
{
 
5879
    int fromRemotePlayer = *nprms;
 
5880
 
 
5881
    if (updateRemotePlayer)
 
5882
    {
 
5883
        DisplayMessage("you are already in challenge mode",
 
5884
                       fromRemotePlayer);
 
5885
        return;
 
5886
    }
 
5887
 
 
5888
    if (gameMode != BeginningOfGame)
 
5889
    {
 
5890
        DisplayMessage("Press Reset first", False);
 
5891
        return;
 
5892
    }
 
5893
 
 
5894
    if (localPlayer.appData.challengeDisplay == NULL)
 
5895
        FileNamePopUp("Challenge display?", Challenge);
 
5896
    else
 
5897
        (void) Challenge(localPlayer.appData.challengeDisplay);
 
5898
}
 
5899
 
 
5900
 
 
5901
 
 
5902
 
 
5903
Boolean
 
5904
SelectLevel(char *command)
 
5905
{
 
5906
    char buf[MSG_SIZ];
 
5907
 
 
5908
    sprintf(buf, "level %s\n", command);
 
5909
    SendToProgram(buf, toFirstProgFP);
 
5910
 
 
5911
    return True;
 
5912
}
 
5913
 
 
5914
 
 
5915
 
 
5916
 
 
5917
void
 
5918
SelectLevelProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
5919
{
 
5920
    if ((BlackOnMove(forwardMostMove) && (gameMode == MachinePlaysBlack))
 
5921
        || (!BlackOnMove(forwardMostMove) && (gameMode == MachinePlaysWhite)))
 
5922
    {
 
5923
        DisplayMessage("Wait until your turn", False);
 
5924
    }
 
5925
    else
 
5926
    {
 
5927
        FileNamePopUp("#moves #minutes", SelectLevel);
 
5928
    }
 
5929
}
 
5930
 
 
5931
 
 
5932
 
 
5933
 
 
5934
void
 
5935
MoveNowProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
5936
{
 
5937
    if ((!BlackOnMove(forwardMostMove) && (gameMode == MachinePlaysBlack))
 
5938
        || (BlackOnMove(forwardMostMove) && (gameMode == MachinePlaysWhite)))
 
5939
    {
 
5940
        DisplayMessage("Wait until machines turn", False);
 
5941
    }
 
5942
    else
 
5943
    {
 
5944
        Attention(firstProgramPID);
 
5945
    }
 
5946
}
 
5947
 
 
5948
 
 
5949
 
 
5950
 
 
5951
void
 
5952
LoadPositionProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
5953
{
 
5954
    int fromRemotePlayer = *nprms;
 
5955
 
 
5956
    if (fromRemotePlayer)
 
5957
    {
 
5958
        DisplayMessage("only opponent may load position", fromRemotePlayer);
 
5959
        return;
 
5960
    }
 
5961
 
 
5962
    if (gameMode != BeginningOfGame)
 
5963
    {
 
5964
        DisplayMessage("Press Reset first", False);
 
5965
        return;
 
5966
    }
 
5967
 
 
5968
    FileNamePopUp("Position file name?", LoadPosition);
 
5969
}
 
5970
 
 
5971
 
 
5972
 
 
5973
 
 
5974
Boolean
 
5975
LoadPosition(char *name)
 
5976
{
 
5977
    char *p, line[MSG_SIZ], buf[MSG_SIZ];
 
5978
    Board initial_position;
 
5979
    Catched initial_catches;
 
5980
    FILE *fp;
 
5981
    int i, j;
 
5982
 
 
5983
    if (gameMode != BeginningOfGame)
 
5984
    {
 
5985
        DisplayMessage("Press Reset first", False);
 
5986
        return False;
 
5987
    }
 
5988
 
 
5989
    if (localPlayer.appData.loadPositionFile != name)
 
5990
    {
 
5991
        if (localPlayer.appData.loadPositionFile)
 
5992
            XtFree(localPlayer.appData.loadPositionFile);
 
5993
 
 
5994
        localPlayer.appData.loadPositionFile = XtMalloc(strlen(name) + 1);
 
5995
        strcpy(localPlayer.appData.loadPositionFile, name);
 
5996
    }
 
5997
 
 
5998
    if ((fp = fopen(name, "r")) == NULL)
 
5999
    {
 
6000
        sprintf(buf, "Can't open %s", name);
 
6001
        DisplayMessage(buf, False);
 
6002
        XtFree(localPlayer.appData.loadPositionFile);
 
6003
        localPlayer.appData.loadPositionFile = NULL;
 
6004
        return False;
 
6005
    }
 
6006
 
 
6007
    lastGameMode = gameMode = ForceMoves;
 
6008
    ModeHighlight();
 
6009
    startedFromSetupPosition = True;
 
6010
 
 
6011
    if (firstProgramXID == 0)
 
6012
    {
 
6013
        InitShogiProgram(localPlayer.appData.firstHost,
 
6014
                         localPlayer.appData.firstShogiProgram,
 
6015
                         &firstProgramPID, &toFirstProgFP,
 
6016
                         &fromFirstProgFP, &firstProgramXID,
 
6017
                         &firstSendTime);
 
6018
    }
 
6019
 
 
6020
    /*
 
6021
     * Check and skip header information in position file.
 
6022
     */
 
6023
 
 
6024
    fgets(line, MSG_SIZ, fp);
 
6025
    line[strlen(line) - 1] = NULLCHAR;
 
6026
    sprintf(buf, "# %s position file", programName);
 
6027
 
 
6028
    if (strncmp(line, buf, strlen(buf)))
 
6029
    {
 
6030
        strcat(line, ": no xshogi position file");
 
6031
        DisplayMessage(line, False);
 
6032
        return False;
 
6033
    }
 
6034
 
 
6035
    DisplayName(line);
 
6036
    fgets(line, MSG_SIZ, fp); /* skip opponents */
 
6037
 
 
6038
    for (i = BOARD_SIZE - 1; i >= 0; i--)
 
6039
    {
 
6040
        fgets(line, MSG_SIZ, fp);
 
6041
 
 
6042
        for (p = line, j = 0; j < BOARD_SIZE; p++)
 
6043
        {
 
6044
            int promoted = False;  /* CHECKME: is this valid? */
 
6045
 
 
6046
            if (*p == '+')
 
6047
                promoted = True;
 
6048
 
 
6049
            if (*p == ' ')
 
6050
                promoted = False;
 
6051
 
 
6052
            p++;
 
6053
            initial_position[i][j++] = CharToPiece(*p, promoted);
 
6054
        }
 
6055
    }
 
6056
 
 
6057
    {
 
6058
        int color;
 
6059
 
 
6060
        for (color = 0; color <= 1; color++)
 
6061
        {
 
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]);
 
6071
        }
 
6072
    }
 
6073
 
 
6074
    whitePlaysFirst = False;
 
6075
 
 
6076
    if (!feof(fp))
 
6077
    {
 
6078
        fgets(line, MSG_SIZ, fp);
 
6079
 
 
6080
        if (strncmp(line, "white", strlen("white")) == 0)
 
6081
            whitePlaysFirst = True;
 
6082
    }
 
6083
 
 
6084
    fclose(fp);
 
6085
 
 
6086
    if (whitePlaysFirst)
 
6087
    {
 
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);
 
6099
    }
 
6100
    else
 
6101
    {
 
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);
 
6108
    }
 
6109
 
 
6110
    DisplayClocks(ResetTimers);
 
6111
    timeRemaining[0][1] = blackTimeRemaining;
 
6112
    timeRemaining[1][1] = whiteTimeRemaining;
 
6113
 
 
6114
    DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
 
6115
    return True;
 
6116
}
 
6117
 
 
6118
 
 
6119
 
 
6120
 
 
6121
void
 
6122
EditPositionProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
6123
{
 
6124
    int fromRemotePlayer = *nprms;
 
6125
 
 
6126
    if (updateRemotePlayer)
 
6127
    {
 
6128
        DisplayMessage("Edit button disabled", fromRemotePlayer);
 
6129
        return;
 
6130
    }
 
6131
 
 
6132
    if (gameMode == EditPosition) 
 
6133
        return;
 
6134
 
 
6135
    ForceProc(w, event, prms, nprms);
 
6136
 
 
6137
    if (gameMode != ForceMoves) 
 
6138
        return;
 
6139
 
 
6140
    DisplayName("<-- Press to set side to play next");
 
6141
    DisplayMessage("Mouse: 1=drag, 2=black, 3=white", False);
 
6142
 
 
6143
    lastGameMode = gameMode = EditPosition;
 
6144
    ModeHighlight();
 
6145
 
 
6146
    if (currentMove > 0)
 
6147
        CopyBoard(boards[0], boards[currentMove]);
 
6148
 
 
6149
    whitePlaysFirst = !BlackOnMove(forwardMostMove);
 
6150
    currentMove = forwardMostMove = backwardMostMove = 0;
 
6151
}
 
6152
 
 
6153
 
 
6154
 
 
6155
 
 
6156
void
 
6157
EditPositionDone(void)
 
6158
{
 
6159
    startedFromSetupPosition = True;
 
6160
    SendToProgram(localPlayer.appData.initString, toFirstProgFP);
 
6161
    SendSearchDepth(toFirstProgFP);
 
6162
 
 
6163
    if (whitePlaysFirst)
 
6164
    {
 
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);
 
6172
        DisplayName(" ");
 
6173
        DisplayMessage("White to play", False);
 
6174
    }
 
6175
    else
 
6176
    {
 
6177
        currentMove = forwardMostMove = backwardMostMove = 0;
 
6178
        SendCurrentBoard(toFirstProgFP);
 
6179
        SendToProgram("force\n", toFirstProgFP);
 
6180
        DisplayName(" ");
 
6181
        DisplayMessage("Black to play", False);
 
6182
    }
 
6183
 
 
6184
    lastGameMode = gameMode = ForceMoves;
 
6185
}
 
6186
 
 
6187
 
 
6188
 
 
6189
/*
 
6190
 * FUNCTION
 
6191
 *     BackwardProc
 
6192
 *
 
6193
 * DESCRIPTION
 
6194
 *     This function executes when undoing a move.
 
6195
 *     FIXME: this function is totally hosed!!!
 
6196
 *
 
6197
 * ARGUMENTS
 
6198
 *     Widget w
 
6199
 *     XEvent *event
 
6200
 *     String *prms
 
6201
 *     Cardinal *nprms 
 
6202
 *
 
6203
 * RETURN VALUE
 
6204
 *     void
 
6205
 *
 
6206
 */
 
6207
 
 
6208
void
 
6209
BackwardProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
6210
{
 
6211
    int target;
 
6212
    unsigned int state;
 
6213
 
 
6214
    int fromRemotePlayer = *nprms;
 
6215
 
 
6216
    if (updateRemotePlayer)
 
6217
    {
 
6218
        DisplayMessage("Backward button disabled", fromRemotePlayer);
 
6219
        return;
 
6220
    }
 
6221
 
 
6222
    /* 
 
6223
     * Why do we need this here?
 
6224
     */
 
6225
 
 
6226
    ForceProc(w, event, prms, nprms);
 
6227
 
 
6228
    if ((currentMove <= backwardMostMove) || (gameMode == EditPosition))
 
6229
        return;
 
6230
 
 
6231
    if (gameMode == EndOfGame)
 
6232
        ResurrectShogiProgram();
 
6233
 
 
6234
    if (gameMode == PlayFromGameFile)
 
6235
        PauseProc(w, event, prms, nprms);
 
6236
 
 
6237
    if (event == NULL)
 
6238
    {
 
6239
        /* Kludge */
 
6240
        Window root, child;
 
6241
        int root_x, root_y;
 
6242
        int win_x, win_y;
 
6243
 
 
6244
        XQueryPointer(localPlayer.xDisplay, localPlayer.xBoardWindow,
 
6245
                      &root, &child, &root_x, &root_y,
 
6246
                      &win_x, &win_y, &state);
 
6247
    }
 
6248
    else
 
6249
    {
 
6250
        state = event->xkey.state;
 
6251
    }
 
6252
 
 
6253
    if (state & ShiftMask)
 
6254
    {
 
6255
        target = backwardMostMove;
 
6256
    }
 
6257
    else
 
6258
    {
 
6259
        target = currentMove - 1;
 
6260
    }
 
6261
 
 
6262
    if (gameMode == ForceMoves)
 
6263
    {
 
6264
        Attention(firstProgramPID);
 
6265
 
 
6266
        while (currentMove > target)
 
6267
        {
 
6268
            SendToProgram("undo\n", toFirstProgFP);
 
6269
            currentMove--;
 
6270
        }
 
6271
    }
 
6272
    else
 
6273
    {
 
6274
        currentMove = target;
 
6275
    }
 
6276
 
 
6277
    if (gameMode == ForceMoves)
 
6278
    {
 
6279
        whiteTimeRemaining = timeRemaining[0][currentMove];
 
6280
        blackTimeRemaining = timeRemaining[1][currentMove];
 
6281
    }
 
6282
 
 
6283
    DisplayClocks(ReDisplayTimers);
 
6284
    DisplayMove(currentMove - 1);
 
6285
    DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
 
6286
}
 
6287
 
 
6288
 
 
6289
 
 
6290
 
 
6291
void
 
6292
FlipViewProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
6293
{
 
6294
    struct DisplayData *player = (*nprms ? &remotePlayer : &localPlayer);
 
6295
 
 
6296
    player->flipView = !player->flipView;
 
6297
    DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
 
6298
}
 
6299
 
 
6300
 
 
6301
 
 
6302
 
 
6303
void
 
6304
SaveGameProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
6305
{
 
6306
    char def[MSG_SIZ];
 
6307
 
 
6308
    int fromRemotePlayer = *nprms;
 
6309
 
 
6310
    if (fromRemotePlayer)
 
6311
    {
 
6312
        DisplayMessage("only opponent may save game", fromRemotePlayer);
 
6313
        return;
 
6314
    }
 
6315
 
 
6316
    def[0] = NULLCHAR;
 
6317
 
 
6318
    FileNamePopUp("Filename for saved game?", SaveGame);
 
6319
}
 
6320
 
 
6321
 
 
6322
 
 
6323
 
 
6324
Boolean
 
6325
SaveGame(char *name)
 
6326
{
 
6327
    char buf[MSG_SIZ];
 
6328
    int i, len, move = 0;
 
6329
    time_t tm;
 
6330
 
 
6331
    if (!filemodeUp) /* if called via FileModeCallback avoid recursion */
 
6332
    {
 
6333
        if ((gameFileFP = fopen(name, "r")) == NULL)
 
6334
        {
 
6335
            strcpy(fmi.mode, "w");
 
6336
        }
 
6337
        else
 
6338
        {
 
6339
            fclose(gameFileFP);
 
6340
            FileModePopUp(name);
 
6341
            return False; /* CHECKME: what should the return value be? */
 
6342
        }
 
6343
    }
 
6344
 
 
6345
    if ((gameFileFP = fopen(name, fmi.mode)) == NULL)
 
6346
    {
 
6347
        sprintf(buf, "Can't open %s (mode %s)", name, fmi.mode);
 
6348
        DisplayMessage(buf, False);
 
6349
        return False;
 
6350
    }
 
6351
 
 
6352
    tm = time((time_t *) NULL);
 
6353
 
 
6354
    fprintf(gameFileFP, "# %s game file -- %s", programName, ctime(&tm));
 
6355
    PrintOpponents(gameFileFP);
 
6356
 
 
6357
    for (i = 0; i < currentMove;)
 
6358
    {
 
6359
        if ((i % 5) == 0)
 
6360
            fprintf(gameFileFP, "\n");
 
6361
 
 
6362
        fprintf(gameFileFP, "%d. %s ", ++move, parseList[i++]);
 
6363
 
 
6364
        if (i >= currentMove)
 
6365
        {
 
6366
            fprintf(gameFileFP, "\n");
 
6367
            break;
 
6368
        }
 
6369
 
 
6370
        if ((len = strlen(parseList[i])) == 0)
 
6371
            break;
 
6372
 
 
6373
        fprintf(gameFileFP, "%s ", parseList[i++]);
 
6374
    }
 
6375
 
 
6376
    fprintf(gameFileFP, "\n");
 
6377
 
 
6378
    fclose(gameFileFP);
 
6379
    gameFileFP = NULL;
 
6380
 
 
6381
    return True;
 
6382
}
 
6383
 
 
6384
 
 
6385
 
 
6386
 
 
6387
void
 
6388
SwitchProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
6389
{
 
6390
    if (localPlayer.appData.noShogiProgram)
 
6391
        return;
 
6392
 
 
6393
    switch (gameMode)
 
6394
    {
 
6395
    default:
 
6396
        return;
 
6397
 
 
6398
    case MachinePlaysBlack:
 
6399
        if (BlackOnMove(forwardMostMove))
 
6400
        {
 
6401
            DisplayMessage("Wait until your turn", False);
 
6402
            return;
 
6403
        }
 
6404
 
 
6405
        lastGameMode = gameMode = MachinePlaysWhite;
 
6406
        ModeHighlight();
 
6407
        break;
 
6408
 
 
6409
    case BeginningOfGame:
 
6410
 
 
6411
    case MachinePlaysWhite:
 
6412
        if (!BlackOnMove(forwardMostMove))
 
6413
        {
 
6414
            DisplayMessage("Wait until your turn", False);
 
6415
            return;
 
6416
        }
 
6417
 
 
6418
        if (forwardMostMove == 0)
 
6419
        {
 
6420
            MachineBlackProc(w, event, prms, nprms);
 
6421
            return;
 
6422
        }
 
6423
 
 
6424
        lastGameMode = gameMode = MachinePlaysBlack;
 
6425
        ModeHighlight();
 
6426
        break;
 
6427
    }
 
6428
 
 
6429
    Attention(firstProgramPID);
 
6430
    SendToProgram("switch\n", toFirstProgFP);
 
6431
}
 
6432
 
 
6433
 
 
6434
 
 
6435
 
 
6436
void
 
6437
ForceProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
6438
{
 
6439
    int i;
 
6440
 
 
6441
    switch (gameMode)
 
6442
    {
 
6443
    case MachinePlaysBlack:
 
6444
        if (BlackOnMove(forwardMostMove))
 
6445
        {
 
6446
            DisplayMessage("Wait until your turn", False);
 
6447
            return;
 
6448
        }
 
6449
 
 
6450
        Attention(firstProgramPID);
 
6451
        SendToProgram("force\n", toFirstProgFP);
 
6452
        break;
 
6453
 
 
6454
    case MachinePlaysWhite:
 
6455
        if (!BlackOnMove(forwardMostMove))
 
6456
        {
 
6457
            DisplayMessage("Wait until your turn", False);
 
6458
            return;
 
6459
        }
 
6460
 
 
6461
        Attention(firstProgramPID);
 
6462
        SendToProgram("force\n", toFirstProgFP);
 
6463
        break;
 
6464
 
 
6465
    case BeginningOfGame:
 
6466
        SendToProgram("force\n", toFirstProgFP);
 
6467
        break;
 
6468
 
 
6469
    case PlayFromGameFile:
 
6470
        if (readGameXID != 0)
 
6471
        {
 
6472
            XtRemoveTimeOut(readGameXID);
 
6473
            readGameXID = 0;
 
6474
        }
 
6475
 
 
6476
        if (gameFileFP != NULL)
 
6477
        {
 
6478
            fclose(gameFileFP);
 
6479
            gameFileFP = NULL;
 
6480
        }
 
6481
 
 
6482
        break;
 
6483
 
 
6484
    case EndOfGame:
 
6485
        ResurrectShogiProgram();
 
6486
        break;
 
6487
 
 
6488
    case EditPosition:
 
6489
        EditPositionDone();
 
6490
        break;
 
6491
 
 
6492
    case TwoMachinesPlay:
 
6493
        ShutdownShogiPrograms("");
 
6494
        ResurrectShogiProgram();
 
6495
        return;
 
6496
 
 
6497
    default:
 
6498
        return;
 
6499
    }
 
6500
 
 
6501
    if ((gameMode == MachinePlaysWhite)
 
6502
        || (gameMode == MachinePlaysBlack)
 
6503
        || (gameMode == TwoMachinesPlay)
 
6504
        || (gameMode == PlayFromGameFile))
 
6505
    {
 
6506
        i = forwardMostMove;
 
6507
 
 
6508
        while (i > currentMove)
 
6509
        {
 
6510
            SendToProgram("undo\n", toFirstProgFP);
 
6511
            i--;
 
6512
        }
 
6513
 
 
6514
        blackTimeRemaining = timeRemaining[0][currentMove];
 
6515
        whiteTimeRemaining = timeRemaining[1][currentMove];
 
6516
 
 
6517
        if (whiteFlag || blackFlag)
 
6518
        {
 
6519
            whiteFlag = blackFlag = 0;
 
6520
        }
 
6521
 
 
6522
        DisplayTitle("");
 
6523
    }
 
6524
 
 
6525
    lastGameMode = gameMode = ForceMoves;
 
6526
    ModeHighlight();
 
6527
    DisplayClocks(StopTimers);
 
6528
}
 
6529
 
 
6530
 
 
6531
 
 
6532
void
 
6533
HintProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
6534
{
 
6535
    int fromRemotePlayer = *nprms;
 
6536
 
 
6537
    if (updateRemotePlayer)
 
6538
    {
 
6539
        DisplayMessage("no hints in challenge mode", fromRemotePlayer);
 
6540
        return;
 
6541
    }
 
6542
 
 
6543
    if (localPlayer.appData.noShogiProgram) 
 
6544
        return;
 
6545
 
 
6546
    switch (gameMode)
 
6547
    {
 
6548
    case MachinePlaysBlack:
 
6549
        if (BlackOnMove(forwardMostMove))
 
6550
        {
 
6551
            DisplayMessage("Wait until your turn", False);
 
6552
            return;
 
6553
        }
 
6554
 
 
6555
        break;
 
6556
 
 
6557
    case BeginningOfGame:
 
6558
    case MachinePlaysWhite:
 
6559
        if (!BlackOnMove(forwardMostMove))
 
6560
        {
 
6561
            DisplayMessage("Wait until your turn", False);
 
6562
            return;
 
6563
        }
 
6564
 
 
6565
        break;
 
6566
 
 
6567
    default:
 
6568
        DisplayMessage("No hint available", False);
 
6569
        return;
 
6570
    }
 
6571
 
 
6572
    Attention(firstProgramPID);
 
6573
    SendToProgram("hint\n", toFirstProgFP);
 
6574
}
 
6575
 
 
6576
 
 
6577
 
 
6578
 
 
6579
void
 
6580
PrintPosition(FILE *fp, int move)
 
6581
{
 
6582
    int i, j, color;
 
6583
 
 
6584
    for (i = BOARD_SIZE - 1; i >= 0; i--)
 
6585
    {
 
6586
        for (j = 0; j < BOARD_SIZE; j++)
 
6587
        {
 
6588
            if (pieceIsPromoted[(int)boards[currentMove][i][j]])
 
6589
                fprintf(fp, "%c", '+');
 
6590
            else
 
6591
                fprintf(fp, "%c", ' ');
 
6592
 
 
6593
            fprintf(fp, "%c",
 
6594
                    pieceToChar[(int)boards[currentMove][i][j]]);
 
6595
 
 
6596
            if (j == BOARD_SIZE - 1)
 
6597
                fputc('\n', fp);
 
6598
        }
 
6599
    }
 
6600
 
 
6601
    for (color = 0; color <= 1; color++)
 
6602
    {
 
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]);
 
6612
    }
 
6613
 
 
6614
    if ((gameMode == EditPosition)
 
6615
        ? !whitePlaysFirst
 
6616
        : BlackOnMove(forwardMostMove))
 
6617
    {
 
6618
        fprintf(fp, "black to play\n");
 
6619
    }
 
6620
    else
 
6621
    {
 
6622
        fprintf(fp, "white to play\n");
 
6623
    }
 
6624
}
 
6625
 
 
6626
 
 
6627
 
 
6628
 
 
6629
void
 
6630
PrintOpponents(FILE *fp)
 
6631
{
 
6632
    char host_name[MSG_SIZ];
 
6633
 
 
6634
#ifdef HAVE_GETHOSTNAME
 
6635
    gethostname(host_name, MSG_SIZ);
 
6636
#else
 
6637
    strncpy(host_name, "hostname not available", MSG_SIZ);
 
6638
#endif
 
6639
 
 
6640
    switch (lastGameMode)
 
6641
    {
 
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,
 
6647
                host_name);
 
6648
        break;
 
6649
 
 
6650
    case MachinePlaysBlack:
 
6651
        fprintf(fp, "# %s@%s vs. %s@%s\n",
 
6652
                getpwuid(getuid())->pw_name,
 
6653
                host_name,
 
6654
                localPlayer.appData.firstShogiProgram,
 
6655
                localPlayer.appData.firstHost);
 
6656
        break;
 
6657
 
 
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);
 
6664
        break;
 
6665
 
 
6666
    default:
 
6667
        fprintf(fp, "#\n");
 
6668
        break;
 
6669
    }
 
6670
}
 
6671
 
 
6672
 
 
6673
 
 
6674
 
 
6675
void
 
6676
SavePositionProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
6677
{
 
6678
    char def[MSG_SIZ];
 
6679
 
 
6680
    int fromRemotePlayer = *nprms;
 
6681
 
 
6682
    if (fromRemotePlayer)
 
6683
    {
 
6684
        DisplayMessage("only opponent may save game", fromRemotePlayer);
 
6685
        return;
 
6686
    }
 
6687
 
 
6688
    def[0] = NULLCHAR;
 
6689
 
 
6690
    FileNamePopUp("Filename for saved position?", SavePosition);
 
6691
}
 
6692
 
 
6693
 
 
6694
 
 
6695
 
 
6696
Boolean
 
6697
SavePosition(char *name)
 
6698
{
 
6699
    char buf[MSG_SIZ];
 
6700
    FILE *fp;
 
6701
    time_t tm;
 
6702
 
 
6703
    if ((fp = fopen(name, "w")) == NULL)
 
6704
    {
 
6705
        sprintf(buf, "Can't open %s", name);
 
6706
        DisplayMessage(buf, False);
 
6707
        return False;
 
6708
    }
 
6709
 
 
6710
    tm = time((time_t *) NULL);
 
6711
 
 
6712
    fprintf(fp, "# %s position file -- %s", programName, ctime(&tm));
 
6713
    PrintOpponents(fp);
 
6714
    PrintPosition(fp, currentMove);
 
6715
    fclose(fp);
 
6716
 
 
6717
    return True;
 
6718
}
 
6719
 
 
6720
 
 
6721
 
 
6722
 
 
6723
void
 
6724
TwoMachinesProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
6725
{
 
6726
    int i;
 
6727
    MatchMode matchKind;
 
6728
 
 
6729
    int fromRemotePlayer = *nprms;
 
6730
 
 
6731
    if (updateRemotePlayer)
 
6732
    {
 
6733
        DisplayMessage("no machine moves in challenge mode",
 
6734
                       fromRemotePlayer);
 
6735
        return;
 
6736
    }
 
6737
 
 
6738
    if (gameMode == PauseGame) 
 
6739
        PauseProc(w, event, prms, nprms);
 
6740
 
 
6741
    if (gameMode == PlayFromGameFile) 
 
6742
        ForceProc(w, event, prms, nprms);
 
6743
 
 
6744
    if ((gameMode == EndOfGame) 
 
6745
        || (gameMode == TwoMachinesPlay)
 
6746
        || localPlayer.appData.noShogiProgram)
 
6747
    {
 
6748
        return;
 
6749
    }
 
6750
 
 
6751
    if (matchMode == MatchFalse)
 
6752
    {
 
6753
        switch (gameMode)
 
6754
        {
 
6755
        case PauseGame:
 
6756
        case PlayFromGameFile:
 
6757
            return;
 
6758
 
 
6759
        case MachinePlaysBlack:
 
6760
        case MachinePlaysWhite:
 
6761
            ForceProc(w, event, prms, nprms);
 
6762
 
 
6763
            if (gameMode != ForceMoves) 
 
6764
                return;
 
6765
 
 
6766
            matchKind = MatchOpening;
 
6767
            break;
 
6768
 
 
6769
        case ForceMoves:
 
6770
            matchKind = MatchOpening;
 
6771
            break;
 
6772
 
 
6773
        case EditPosition:
 
6774
            EditPositionDone();
 
6775
            matchKind = MatchPosition;
 
6776
            break;
 
6777
 
 
6778
        case BeginningOfGame:
 
6779
        default:
 
6780
            matchKind = MatchInit;
 
6781
            break;
 
6782
        }
 
6783
    }
 
6784
    else
 
6785
    {
 
6786
        matchKind = matchMode;
 
6787
    }
 
6788
 
 
6789
    forwardMostMove = currentMove;
 
6790
 
 
6791
    localPlayer.flipView = False;
 
6792
    remotePlayer.flipView = True;
 
6793
    firstMove = False;
 
6794
    DisplayClocks(ResetTimers);
 
6795
    DisplayClocks(StartTimers);
 
6796
 
 
6797
    switch (matchKind)
 
6798
    {
 
6799
    case MatchOpening:
 
6800
        if (firstProgramXID == 0)
 
6801
        {
 
6802
            if (localPlayer.appData.loadGameFile == NULL)
 
6803
            {
 
6804
                DisplayMessage("Select game file first", False);
 
6805
                return;
 
6806
            }
 
6807
 
 
6808
            InitShogiProgram(localPlayer.appData.firstHost,
 
6809
                             localPlayer.appData.firstShogiProgram,
 
6810
                             &firstProgramPID, &toFirstProgFP,
 
6811
                             &fromFirstProgFP, &firstProgramXID,
 
6812
                             &firstSendTime);
 
6813
 
 
6814
            if (!LoadGame(localPlayer.appData.loadGameFile))
 
6815
            {
 
6816
                ShutdownShogiPrograms("Bad game file");
 
6817
                return;
 
6818
            }
 
6819
 
 
6820
            DrawPosition(localPlayer.boardWidget, NULL, NULL, NULL);
 
6821
        }
 
6822
 
 
6823
        InitShogiProgram(localPlayer.appData.secondHost,
 
6824
                         localPlayer.appData.secondShogiProgram,
 
6825
                         &secondProgramPID, &toSecondProgFP,
 
6826
                         &fromSecondProgFP, &secondProgramXID,
 
6827
                         &secondSendTime);
 
6828
 
 
6829
        if (startedFromSetupPosition)
 
6830
        {
 
6831
            if (whitePlaysFirst)
 
6832
            {
 
6833
                i = 1;
 
6834
                SendToProgram("force\n", toSecondProgFP);
 
6835
                SendBoard(toSecondProgFP, boards[i], catches[i]);
 
6836
            }
 
6837
            else
 
6838
            {
 
6839
                i = 0;
 
6840
                SendBoard(toSecondProgFP, boards[i], catches[i]);
 
6841
                SendToProgram("force\n", toSecondProgFP);
 
6842
            }
 
6843
        }
 
6844
        else
 
6845
        {
 
6846
            i = 0;
 
6847
            SendToProgram("force\n", toSecondProgFP);
 
6848
        }
 
6849
 
 
6850
        for (i = backwardMostMove; i < forwardMostMove; i++)
 
6851
            SendToProgram(moveList[i], toSecondProgFP);
 
6852
 
 
6853
        lastGameMode = gameMode = TwoMachinesPlay;
 
6854
        ModeHighlight();
 
6855
        firstMove = True;
 
6856
 
 
6857
        if (BlackOnMove(forwardMostMove))
 
6858
            SendToProgram(localPlayer.appData.blackString, toSecondProgFP);
 
6859
        else
 
6860
            SendToProgram(localPlayer.appData.whiteString, toFirstProgFP);
 
6861
 
 
6862
        break;
 
6863
 
 
6864
    case MatchPosition:
 
6865
        if (firstProgramXID == 0)
 
6866
        {
 
6867
            if (localPlayer.appData.loadPositionFile == NULL)
 
6868
            {
 
6869
                DisplayMessage("Select position file first", False);
 
6870
                return;
 
6871
            }
 
6872
 
 
6873
            InitShogiProgram(localPlayer.appData.firstHost,
 
6874
                             localPlayer.appData.firstShogiProgram,
 
6875
                             &firstProgramPID, &toFirstProgFP,
 
6876
                             &fromFirstProgFP, &firstProgramXID,
 
6877
                             &firstSendTime);
 
6878
 
 
6879
            if (!LoadPosition(localPlayer.appData.loadPositionFile))
 
6880
                return;
 
6881
        }
 
6882
 
 
6883
        InitShogiProgram(localPlayer.appData.secondHost,
 
6884
                         localPlayer.appData.secondShogiProgram,
 
6885
                         &secondProgramPID, &toSecondProgFP,
 
6886
                         &fromSecondProgFP, &secondProgramXID,
 
6887
                         &secondSendTime);
 
6888
 
 
6889
        if (whitePlaysFirst)
 
6890
            SendToProgram("force\n", toSecondProgFP);
 
6891
 
 
6892
        SendCurrentBoard(toSecondProgFP);
 
6893
        lastGameMode = gameMode = TwoMachinesPlay;
 
6894
        ModeHighlight();
 
6895
        firstMove = True;
 
6896
 
 
6897
        if (BlackOnMove(forwardMostMove))
 
6898
            SendToProgram(localPlayer.appData.blackString, toSecondProgFP);
 
6899
        else
 
6900
            SendToProgram(localPlayer.appData.whiteString, toFirstProgFP);
 
6901
 
 
6902
        break;
 
6903
 
 
6904
    case MatchInit:
 
6905
        InitPosition(True);
 
6906
 
 
6907
        if (firstProgramXID == 0)
 
6908
        {
 
6909
            InitShogiProgram(localPlayer.appData.firstHost,
 
6910
                             localPlayer.appData.firstShogiProgram,
 
6911
                             &firstProgramPID, &toFirstProgFP,
 
6912
                             &fromFirstProgFP, &firstProgramXID,
 
6913
                             &firstSendTime);
 
6914
        }
 
6915
 
 
6916
        InitShogiProgram(localPlayer.appData.secondHost,
 
6917
                         localPlayer.appData.secondShogiProgram,
 
6918
                         &secondProgramPID, &toSecondProgFP,
 
6919
                         &fromSecondProgFP, &secondProgramXID,
 
6920
                         &secondSendTime);
 
6921
 
 
6922
        lastGameMode = gameMode = TwoMachinesPlay;
 
6923
        ModeHighlight();
 
6924
        SendToProgram(localPlayer.appData.blackString, toSecondProgFP);
 
6925
 
 
6926
    default:
 
6927
        break;
 
6928
    }
 
6929
 
 
6930
    if (!firstSendTime || !secondSendTime)
 
6931
    {
 
6932
        DisplayClocks(ResetTimers);
 
6933
        timeRemaining[0][forwardMostMove] = blackTimeRemaining;
 
6934
        timeRemaining[1][forwardMostMove] = whiteTimeRemaining;
 
6935
    }
 
6936
 
 
6937
    DisplayClocks(StartTimers);
 
6938
}
 
6939
 
 
6940
 
 
6941
 
 
6942
 
 
6943
void
 
6944
PauseProc(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
6945
{
 
6946
    static GameMode previous_mode = PauseGame;
 
6947
 
 
6948
    switch (gameMode)
 
6949
    {
 
6950
    case ForceMoves:
 
6951
    case EndOfGame:
 
6952
    case EditPosition:
 
6953
    default:
 
6954
        return;
 
6955
 
 
6956
    case PauseGame:
 
6957
        gameMode = previous_mode;
 
6958
        ModeHighlight();
 
6959
        previous_mode = PauseGame;
 
6960
        DisplayClocks(StartTimers);
 
6961
        DisplayMessage("", False);
 
6962
 
 
6963
        if (updateRemotePlayer)
 
6964
            DisplayMessage("", True);
 
6965
        break;
 
6966
 
 
6967
    case PlayFromGameFile:
 
6968
        if (readGameXID == 0)
 
6969
        {
 
6970
            readGameXID =
 
6971
                XtAppAddTimeOut(appContext,
 
6972
                                (int)(1000 * localPlayer.appData.timeDelay),
 
6973
                                (XtTimerCallbackProc) ReadGameFile, NULL);
 
6974
        }
 
6975
        else
 
6976
        {
 
6977
            XtRemoveTimeOut(readGameXID);
 
6978
            readGameXID = 0;
 
6979
        }
 
6980
 
 
6981
        DisplayMessage("Pausing", False);
 
6982
 
 
6983
        if (updateRemotePlayer)
 
6984
            DisplayMessage("Pausing", True);
 
6985
 
 
6986
        break;
 
6987
 
 
6988
    case BeginningOfGame:
 
6989
    case MachinePlaysBlack:
 
6990
    case MachinePlaysWhite:
 
6991
    case TwoMachinesPlay:
 
6992
        if (forwardMostMove == 0)   /* Don't pause if no one has moved. */
 
6993
            return;
 
6994
 
 
6995
        if (((gameMode == MachinePlaysWhite)
 
6996
             && !BlackOnMove(forwardMostMove)) 
 
6997
            || ((gameMode == MachinePlaysBlack) &&
 
6998
                BlackOnMove(forwardMostMove)))
 
6999
        {
 
7000
            DisplayClocks(StopTimers);
 
7001
        }
 
7002
 
 
7003
        previous_mode = gameMode;
 
7004
        gameMode = PauseGame;
 
7005
        ModeHighlight();
 
7006
        DisplayClocks(StopTimers);
 
7007
        DisplayMessage("Pausing", False);
 
7008
 
 
7009
        if (updateRemotePlayer)
 
7010
            DisplayMessage("Pausing", True);
 
7011
 
 
7012
        break;
 
7013
    }
 
7014
}
 
7015
 
 
7016
 
 
7017
 
 
7018
 
 
7019
void
 
7020
Iconify(Widget w, XEvent *event, String *prms, Cardinal *nprms)
 
7021
{
 
7022
    Arg args[1];
 
7023
 
 
7024
    fromX = fromY = -1;
 
7025
 
 
7026
    XtSetArg(args[0], XtNiconic, True);
 
7027
    XtSetValues(localPlayer.shellWidget, args, 1);
 
7028
}
 
7029
 
 
7030
 
 
7031
 
 
7032
 
 
7033
void
 
7034
SendToProgram(char *message, FILE *fp)
 
7035
{
 
7036
    if (fp == NULL) 
 
7037
        return;
 
7038
 
 
7039
    lastMsgFP = fp;
 
7040
 
 
7041
    if (xshogiDebug)
 
7042
    {
 
7043
        fprintf(stderr, "Sending to %s: %s\n",
 
7044
                ((fp == toFirstProgFP) ? "first" : "second"), message);
 
7045
    }
 
7046
 
 
7047
    if (message[strlen(message) - 1] != '\n')
 
7048
        fprintf(fp, "\n%s\n", message);
 
7049
    else
 
7050
        fputs(message, fp);
 
7051
 
 
7052
    fflush(fp);
 
7053
}
 
7054
 
 
7055
 
 
7056
 
 
7057
 
 
7058
void
 
7059
ReceiveFromProgram(FILE *fp, int *source, XtInputId *id)
 
7060
{
 
7061
    char message[MSG_SIZ], *end_str, *number, *name;
 
7062
    extern const char *const sys_errlist[];
 
7063
 
 
7064
    if (fgets(message, MSG_SIZ, fp) == NULL)
 
7065
    {
 
7066
        if (fp == fromFirstProgFP)
 
7067
        {
 
7068
            number = "first";
 
7069
            name = localPlayer.appData.firstShogiProgram;
 
7070
        }
 
7071
        else if (fp == fromSecondProgFP)
 
7072
        {
 
7073
            number = "second";
 
7074
            name = localPlayer.appData.secondShogiProgram;
 
7075
        }
 
7076
        else
 
7077
        {
 
7078
            return;
 
7079
        }
 
7080
 
 
7081
        if (ferror(fp) == 0)
 
7082
        {
 
7083
            sprintf(message, "%s shogi program (%s) exited unexpectedly",
 
7084
                    number, name);
 
7085
            fprintf(stderr, "%s: %s\n", programName, message);
 
7086
        }
 
7087
        else
 
7088
        {
 
7089
            sprintf(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);
 
7093
        }
 
7094
 
 
7095
        return;
 
7096
    }
 
7097
 
 
7098
    if ((end_str = (char *)strchr(message, '\r')) != NULL)
 
7099
        *end_str = NULLCHAR;
 
7100
 
 
7101
    if ((end_str = (char *)strchr(message, '\n')) != NULL)
 
7102
        *end_str = NULLCHAR;
 
7103
 
 
7104
    if (xshogiDebug || localPlayer.appData.debugMode)
 
7105
    {
 
7106
        fprintf(stderr, "Received from %s: %s\n",
 
7107
                ((fp == fromFirstProgFP) ? "first" : "second"), message);
 
7108
    }
 
7109
 
 
7110
    HandleMachineMove(message, fp);
 
7111
}
 
7112
 
 
7113
 
 
7114
 
 
7115
 
 
7116
void
 
7117
SendSearchDepth(FILE *fp)
 
7118
{
 
7119
    char message[MSG_SIZ];
 
7120
 
 
7121
    if (localPlayer.appData.searchDepth <= 0) 
 
7122
        return;
 
7123
 
 
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);
 
7128
}
 
7129
 
 
7130
 
 
7131
 
 
7132
 
 
7133
void
 
7134
DisplayMessage(char *message, int toRemotePlayer)
 
7135
{
 
7136
    Arg arg;
 
7137
 
 
7138
    XtSetArg(arg, XtNlabel, message);
 
7139
 
 
7140
    if (!toRemotePlayer)
 
7141
        XtSetValues(localPlayer.messageWidget, &arg, 1);
 
7142
 
 
7143
    if (updateRemotePlayer && toRemotePlayer)
 
7144
        XtSetValues(remotePlayer.messageWidget, &arg, 1);
 
7145
}
 
7146
 
 
7147
 
 
7148
 
 
7149
 
 
7150
void
 
7151
DisplayName(char *name)
 
7152
{
 
7153
    Arg arg;
 
7154
 
 
7155
    XtSetArg(arg, XtNlabel, name);
 
7156
    XtSetValues(localPlayer.titleWidget, &arg, 1);
 
7157
 
 
7158
    if (updateRemotePlayer)
 
7159
        XtSetValues(remotePlayer.titleWidget, &arg, 1);
 
7160
}
 
7161
 
 
7162
 
 
7163
 
 
7164
 
 
7165
void SendTimeRemaining(FILE *fp)
 
7166
{
 
7167
    char message[MSG_SIZ];
 
7168
    long comtime, opptime;
 
7169
 
 
7170
    if (BlackOnMove(forwardMostMove) == (fp == toFirstProgFP))
 
7171
    {
 
7172
        comtime = blackTimeRemaining;
 
7173
        opptime = whiteTimeRemaining;
 
7174
    }
 
7175
    else
 
7176
    {
 
7177
        comtime = whiteTimeRemaining;
 
7178
        opptime = blackTimeRemaining;
 
7179
    }
 
7180
 
 
7181
    if (comtime <= 0) 
 
7182
        comtime = 1000;
 
7183
 
 
7184
    if (opptime <= 0) 
 
7185
        opptime = 1000;
 
7186
 
 
7187
    sprintf(message, "time %ld\n",  comtime / 10);
 
7188
    SendToProgram(message, fp);
 
7189
    sprintf(message, "otime %ld\n", opptime / 10);
 
7190
    SendToProgram(message, fp);
 
7191
}
 
7192
 
 
7193
 
 
7194
 
 
7195
 
 
7196
void DisplayMove(int moveNumber)
 
7197
{
 
7198
    char message[MSG_SIZ];
 
7199
 
 
7200
    if (moveNumber < 0)
 
7201
    {
 
7202
        if (moveNumber == forwardMostMove - 1)
 
7203
            DisplayMessage(endMessage, False);
 
7204
        else
 
7205
            DisplayMessage("", False);
 
7206
    }
 
7207
    else
 
7208
    {
 
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);
 
7215
    }
 
7216
}
 
7217
 
 
7218
 
 
7219
 
 
7220
 
 
7221
void DisplayTitle(char *title)
 
7222
{
 
7223
    Arg arg;
 
7224
 
 
7225
    XtSetArg(arg, XtNlabel, title);
 
7226
    XtSetValues(localPlayer.titleWidget, &arg, 1);
 
7227
}
 
7228
 
 
7229
 
 
7230
 
 
7231
 
 
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.
 
7238
 *
 
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
 
7242
 * is thinking.
 
7243
 */
 
7244
 
 
7245
void
 
7246
Attention(int pid)
 
7247
{
 
7248
#if !defined(FIONREAD)
 
7249
    if (localPlayer.appData.noShogiProgram || (pid == 0))
 
7250
        return;
 
7251
 
 
7252
    switch (gameMode)
 
7253
    {
 
7254
    case MachinePlaysBlack:
 
7255
    case MachinePlaysWhite:
 
7256
    case TwoMachinesPlay:
 
7257
        if ((forwardMostMove > backwardMostMove + 1) && maybeThinking)
 
7258
        {
 
7259
            if (xshogiDebug || localPlayer.appData.debugMode)
 
7260
            {
 
7261
                fprintf(stderr, "Sending SIGINT to %s\n",
 
7262
                        ((pid == firstProgramPID) ? "first" : "second"));
 
7263
            }
 
7264
 
 
7265
            (void)kill(pid, SIGINT); /* stop it thinking */
 
7266
        }
 
7267
        break;
 
7268
 
 
7269
    default:
 
7270
        break;  /* CHECKME: is this OK? */
 
7271
    }
 
7272
#endif /* !defined(FIONREAD) */
 
7273
}
 
7274
 
 
7275
 
 
7276
 
 
7277
 
 
7278
void
 
7279
CheckFlags(void)
 
7280
{
 
7281
    if (blackTimeRemaining <= 0)
 
7282
    {
 
7283
        if (!blackFlag)
 
7284
        {
 
7285
            blackFlag = True;
 
7286
 
 
7287
            if (whiteFlag)
 
7288
                DisplayName("  Both flags have fallen");
 
7289
            else
 
7290
                DisplayName("  Black's flag has fallen");
 
7291
        }
 
7292
    }
 
7293
 
 
7294
    if (whiteTimeRemaining <= 0)
 
7295
    {
 
7296
        if (!whiteFlag)
 
7297
        {
 
7298
            whiteFlag = True;
 
7299
 
 
7300
            if (blackFlag)
 
7301
                DisplayName("  Both flags have fallen");
 
7302
            else
 
7303
                DisplayName("  White's flag has fallen");
 
7304
        }
 
7305
    }
 
7306
}
 
7307
 
 
7308
 
 
7309
 
 
7310
 
 
7311
void
 
7312
CheckTimeControl(void)
 
7313
{
 
7314
    if (!localPlayer.appData.clockMode)
 
7315
        return;
 
7316
 
 
7317
    if (forwardMostMove == 0) 
 
7318
        return;
 
7319
 
 
7320
    /*
 
7321
     * Add time to clocks when time control is achieved.
 
7322
     */
 
7323
 
 
7324
    if ((forwardMostMove % (localPlayer.appData.movesPerSession * 2)) == 0)
 
7325
    {
 
7326
        blackTimeRemaining += timeControl;
 
7327
        whiteTimeRemaining += timeControl;
 
7328
    }
 
7329
}
 
7330
 
 
7331
 
 
7332
 
 
7333
 
 
7334
void
 
7335
DisplayLabels(void)
 
7336
{
 
7337
    DisplayTimerLabel(localPlayer.blackTimerWidget, "Black",
 
7338
                      blackTimeRemaining);
 
7339
    DisplayTimerLabel(localPlayer.whiteTimerWidget, "White",
 
7340
                      whiteTimeRemaining);
 
7341
 
 
7342
    if (updateRemotePlayer)
 
7343
    {
 
7344
        DisplayTimerLabel(remotePlayer.blackTimerWidget, "Black",
 
7345
                          blackTimeRemaining);
 
7346
        DisplayTimerLabel(remotePlayer.whiteTimerWidget, "White",
 
7347
                          whiteTimeRemaining);
 
7348
    }
 
7349
}
 
7350
 
 
7351
 
 
7352
 
 
7353
 
 
7354
#ifdef HAVE_GETTIMEOFDAY
 
7355
static struct timeval tickStartTV;
 
7356
static int tickLength;
 
7357
 
 
7358
int
 
7359
PartialTickLength(void)
 
7360
{
 
7361
    struct timeval tv;
 
7362
    struct timezone tz;
 
7363
    int ptl;
 
7364
 
 
7365
    gettimeofday(&tv, &tz);
 
7366
    ptl = ((tv.tv_sec - tickStartTV.tv_sec) * 1000000 +
 
7367
           (tv.tv_usec - tickStartTV.tv_usec) + 500) / 1000;
 
7368
 
 
7369
    if (ptl > tickLength) 
 
7370
        ptl = tickLength;
 
7371
 
 
7372
    return ptl;
 
7373
}
 
7374
#else /* !HAVE_GETTIMEOFDAY */
 
7375
#define tickLength 1000
 
7376
#endif /* HAVE_GETTIMEOFDAY */
 
7377
 
 
7378
 
 
7379
 
 
7380
 
 
7381
/*
 
7382
 * DisplayClocks manages the game clocks.
 
7383
 *
 
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.  
 
7389
 */
 
7390
 
 
7391
void
 
7392
DisplayClocks(int clock_mode)
 
7393
{
 
7394
#ifdef HAVE_GETTIMEOFDAY
 
7395
    struct timezone tz;
 
7396
#endif /* HAVE_GETTIMEOFDAY */
 
7397
 
 
7398
    long timeRemaining;
 
7399
 
 
7400
    switch (clock_mode)
 
7401
    {
 
7402
    case ResetTimers:
 
7403
        /* Stop clocks and reset to a fresh time control */
 
7404
        if (timerXID != 0)
 
7405
        {
 
7406
            XtRemoveTimeOut(timerXID);
 
7407
            timerXID = 0;
 
7408
        }
 
7409
 
 
7410
        blackTimeRemaining = timeControl;
 
7411
        whiteTimeRemaining = timeControl;
 
7412
 
 
7413
        if (blackFlag || whiteFlag)
 
7414
        {
 
7415
            DisplayName("");
 
7416
            blackFlag = whiteFlag = False;
 
7417
        }
 
7418
 
 
7419
        DisplayLabels();
 
7420
        break;
 
7421
 
 
7422
    case DecrementTimers:
 
7423
        /* Decrement running clock to next 1-second boundary */
 
7424
        if (gameMode == PauseGame) 
 
7425
            return;
 
7426
 
 
7427
        timerXID = 0;
 
7428
 
 
7429
        if (!localPlayer.appData.clockMode) 
 
7430
            return;
 
7431
 
 
7432
        if (BlackOnMove(forwardMostMove))
 
7433
        {
 
7434
            timeRemaining = (blackTimeRemaining -= tickLength);
 
7435
        }
 
7436
        else
 
7437
        {
 
7438
            timeRemaining = (whiteTimeRemaining -= tickLength);
 
7439
        }
 
7440
 
 
7441
        DisplayLabels();
 
7442
        CheckFlags();
 
7443
 
 
7444
#ifdef HAVE_GETTIMEOFDAY
 
7445
        tickLength = (((timeRemaining <= 1000) && (timeRemaining > 0))
 
7446
                      ? 100 : 1000);
 
7447
        gettimeofday(&tickStartTV, &tz);
 
7448
#endif /* HAVE_GETTIMEOFDAY */
 
7449
 
 
7450
        timerXID =
 
7451
            XtAppAddTimeOut(appContext, tickLength,
 
7452
                            (XtTimerCallbackProc) DisplayClocks,
 
7453
                            (XtPointer) DecrementTimers);
 
7454
        break;
 
7455
 
 
7456
    case SwitchTimers:
 
7457
        /* A player has just moved, so stop the previously running
 
7458
           clock and start the other one. */
 
7459
 
 
7460
        if (timerXID != 0)
 
7461
        {
 
7462
            XtRemoveTimeOut(timerXID);
 
7463
            timerXID = 0;
 
7464
 
 
7465
#ifdef HAVE_GETTIMEOFDAY
 
7466
            if (localPlayer.appData.clockMode)
 
7467
            {
 
7468
                if (BlackOnMove(forwardMostMove))
 
7469
                    whiteTimeRemaining -= PartialTickLength();
 
7470
                else
 
7471
                    blackTimeRemaining -= PartialTickLength();
 
7472
                CheckFlags();
 
7473
            }
 
7474
#endif /* HAVE_GETTIMEOFDAY */
 
7475
        }
 
7476
 
 
7477
        CheckTimeControl();
 
7478
        DisplayLabels();
 
7479
 
 
7480
        if (!localPlayer.appData.clockMode) 
 
7481
            return;
 
7482
 
 
7483
        if ((gameMode == PauseGame)
 
7484
            && ((pausePreviousMode == MachinePlaysBlack) 
 
7485
                || (pausePreviousMode == MachinePlaysWhite)))
 
7486
        {
 
7487
            return;
 
7488
        }
 
7489
 
 
7490
        timeRemaining = (BlackOnMove(forwardMostMove) 
 
7491
                         ? blackTimeRemaining : whiteTimeRemaining);
 
7492
 
 
7493
#ifdef HAVE_GETTIMEOFDAY
 
7494
        tickLength = (((timeRemaining <= 1000) && (timeRemaining > 0))
 
7495
                      ? (((timeRemaining - 1) % 100) + 1) 
 
7496
                      : (((timeRemaining - 1) % 1000) + 1));
 
7497
 
 
7498
        if (tickLength <= 0) 
 
7499
            tickLength += 1000;
 
7500
 
 
7501
        gettimeofday(&tickStartTV, &tz);
 
7502
 
 
7503
#endif /* HAVE_GETTIMEOFDAY */
 
7504
        timerXID =
 
7505
            XtAppAddTimeOut(appContext, tickLength,
 
7506
                            (XtTimerCallbackProc) DisplayClocks,
 
7507
                            (XtPointer) DecrementTimers);
 
7508
        break;
 
7509
 
 
7510
    case ReDisplayTimers:
 
7511
        /* Display current clock values */
 
7512
        DisplayLabels();
 
7513
        break;
 
7514
 
 
7515
    case StopTimers:
 
7516
        /* Stop both clocks */
 
7517
        if (timerXID == 0)
 
7518
            return;
 
7519
 
 
7520
        XtRemoveTimeOut(timerXID);
 
7521
        timerXID = 0;
 
7522
 
 
7523
        if (!localPlayer.appData.clockMode) 
 
7524
            return;
 
7525
 
 
7526
#ifdef HAVE_GETTIMEOFDAY
 
7527
        if (BlackOnMove(forwardMostMove))
 
7528
            blackTimeRemaining -= PartialTickLength();
 
7529
        else
 
7530
            whiteTimeRemaining -= PartialTickLength();
 
7531
        CheckFlags();
 
7532
        DisplayLabels();
 
7533
#endif /* HAVE_GETTIMEOFDAY */
 
7534
        break;
 
7535
 
 
7536
    case StartTimers:
 
7537
        /* Start clock of player on move, if not already running. */
 
7538
        if (timerXID != 0)
 
7539
            return;
 
7540
 
 
7541
        DisplayLabels();
 
7542
 
 
7543
        if (!localPlayer.appData.clockMode) 
 
7544
            return;
 
7545
 
 
7546
        timeRemaining = (BlackOnMove(forwardMostMove) 
 
7547
                         ? blackTimeRemaining : whiteTimeRemaining);
 
7548
 
 
7549
        if (timeRemaining == 0) 
 
7550
            return;
 
7551
 
 
7552
#ifdef HAVE_GETTIMEOFDAY
 
7553
        tickLength = (((timeRemaining <= 1000) && (timeRemaining > 0)) 
 
7554
                      ? (((timeRemaining - 1) % 100) + 1)
 
7555
                      : (((timeRemaining - 1) % 1000) + 1));
 
7556
 
 
7557
        if (tickLength <= 0) 
 
7558
            tickLength += 1000;
 
7559
 
 
7560
        gettimeofday(&tickStartTV, &tz);
 
7561
#endif /* HAVE_GETTIMEOFDAY */
 
7562
 
 
7563
        timerXID =
 
7564
            XtAppAddTimeOut(appContext, tickLength,
 
7565
                            (XtTimerCallbackProc) DisplayClocks,
 
7566
                            (XtPointer)DecrementTimers);
 
7567
        break;
 
7568
    }
 
7569
}
 
7570
 
 
7571
 
 
7572
 
 
7573
 
 
7574
void
 
7575
DisplayTimerLabel(Widget w, char *color, long int timer)
 
7576
{
 
7577
    char buf[MSG_SIZ];
 
7578
    Arg args[3];
 
7579
    struct DisplayData *player;
 
7580
 
 
7581
    player = (((w == localPlayer.blackTimerWidget)
 
7582
               || (w == localPlayer.whiteTimerWidget))
 
7583
              ? &localPlayer : &remotePlayer);
 
7584
 
 
7585
    if (localPlayer.appData.clockMode)
 
7586
    {
 
7587
        sprintf(buf, "%s: %s", color, TimeString(timer));
 
7588
        XtSetArg(args[0], XtNlabel, buf);
 
7589
    }
 
7590
    else
 
7591
    {
 
7592
        XtSetArg(args[0], XtNlabel, color);
 
7593
    }
 
7594
 
 
7595
    if (((color[0] == 'W') && BlackOnMove(forwardMostMove))
 
7596
        || ((color[0] == 'B') && !BlackOnMove(forwardMostMove)))
 
7597
    {
 
7598
        XtSetArg(args[1], XtNbackground, player->timerForegroundPixel);
 
7599
        XtSetArg(args[2], XtNforeground, player->timerBackgroundPixel);
 
7600
    }
 
7601
    else
 
7602
    {
 
7603
        XtSetArg(args[1], XtNbackground, player->timerBackgroundPixel);
 
7604
        XtSetArg(args[2], XtNforeground, player->timerForegroundPixel);
 
7605
    }
 
7606
 
 
7607
    XtSetValues(w, args, 3);
 
7608
}
 
7609
 
 
7610
 
 
7611
 
 
7612
 
 
7613
char *
 
7614
TimeString(long tm)
 
7615
{
 
7616
    int second, minute, hour, day;
 
7617
    char *sign = "";
 
7618
    static char buf[32];
 
7619
 
 
7620
    if ((tm > 0) && (tm <= 900))
 
7621
    {
 
7622
        /* convert milliseconds to tenths, rounding up */
 
7623
        sprintf(buf, " 0.%1ld ", (tm + 99) / 100);
 
7624
        return buf;
 
7625
    }
 
7626
 
 
7627
    /* convert milliseconds to seconds, rounding up */
 
7628
    tm = (tm + 999) / 1000;
 
7629
 
 
7630
    if (tm < 0)
 
7631
    {
 
7632
        sign = "-";
 
7633
        tm = -tm;
 
7634
    }
 
7635
 
 
7636
    if (tm >= (60 * 60 * 24))
 
7637
    {
 
7638
        day = (int)(tm / (60 * 60 * 24));
 
7639
        tm -= day * 60 * 60 * 24;
 
7640
    }
 
7641
    else
 
7642
    {
 
7643
        day = 0;
 
7644
    }
 
7645
 
 
7646
    if (tm >= (60 * 60))
 
7647
    {
 
7648
        hour = (int)(tm / (60 * 60));
 
7649
        tm -= hour * 60 * 60;
 
7650
    }
 
7651
    else
 
7652
    {
 
7653
        hour = 0;
 
7654
    }
 
7655
 
 
7656
    if (tm >= 60)
 
7657
    {
 
7658
        minute = (int)(tm / 60);
 
7659
        tm -= minute * 60;
 
7660
    }
 
7661
    else
 
7662
    {
 
7663
        minute = 0;
 
7664
    }
 
7665
 
 
7666
    second = tm % 60;
 
7667
 
 
7668
    if (day > 0)
 
7669
    {
 
7670
        sprintf(buf, " %s%d:%02d:%02d:%02d ",
 
7671
                sign, day, hour, minute, second);
 
7672
    }
 
7673
    else if (hour > 0)
 
7674
    {
 
7675
        sprintf(buf, " %s%d:%02d:%02d ",
 
7676
                sign, hour, minute, second);
 
7677
    }
 
7678
    else
 
7679
    {
 
7680
        sprintf(buf, " %s%2d:%02d ",
 
7681
                sign, minute, second);
 
7682
    }
 
7683
 
 
7684
    return buf;
 
7685
}
 
7686
 
 
7687
 
 
7688
 
 
7689
 
 
7690
void
 
7691
Usage(void)
 
7692
{
 
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");
 
7703
 
 
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");
 
7710
    fprintf(stderr,
 
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");
 
7725
    exit(2);
 
7726
}
 
7727
 
 
7728
 
 
7729
 
 
7730
void
 
7731
CatchPipeSignal(int dummy)
 
7732
{
 
7733
    char message[MSG_SIZ];
 
7734
    
 
7735
    sprintf(message,
 
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);
 
7743
    return;
 
7744
}
 
7745