home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!news.tek.com!master!saab!billr
- From: billr@saab.CNA.TEK.COM (Bill Randle)
- Newsgroups: comp.sources.games
- Subject: v17i074: malawi - 2 players board game, Part01/01
- Message-ID: <4926@master.CNA.TEK.COM>
- Date: 19 Apr 93 02:19:52 GMT
- Sender: news@master.CNA.TEK.COM
- Lines: 1445
- Approved: billr@saab.CNA.TEK.COM
- Xref: uunet comp.sources.games:1753
-
- Submitted-by: Johannes Sixt <Johannes.Sixt@risc.uni-linz.ac.at>
- Posting-number: Volume 17, Issue 74
- Archive-name: malawi/Part01
- Environment: X11, Xaw
-
-
- [From the author...]
- [[This is malawi, version 0.1, a 2 players board game.
- You will require X11R4 or higher to compile and link.
- Check the man page for the rules of the game and how to play it.
-
- The initial version 0.0 of malawi was posted to alt.sources. The major
- improvement of 0.1 is that the opponents can play on different displays.
-
- Have fun!
-
- -- Hannes
-
- PS: I do not know whether it is coincidence or not that the name of this
- game is the same as that of an African republic, because I did not invent
- the name for the game.]]
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 1 (of 1)."
- # Contents: README malawi.man HISTORY Imakefile MANIFEST Makefile.std
- # Malawi.ad malawi.c patchlevel.h
- # Wrapped by jsixt@melmac on Tue Apr 13 09:33:58 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(1122 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- XThis is Malawi.
- X
- XMalawi is a 2 players board game modeled after PIATNIK game No. 6104 by
- XGerhard Kodys.
- X
- XThe sources are available from
- X
- X ftp.risc.uni-linz.ac.at:/pub/x11/malawi-0.1.tar.Z
- X
- X
- XInstallation:
- X
- XIf you have imake:
- X
- X csh> xmkmf
- X csh> make
- X csh> make install
- X csh> make install.man
- X
- XIf you don't have imake, try
- X
- X csh> make -f Makefile.std
- X
- XTo test the program
- X
- X csh> (setenv XFILESEARCHPATH ./%N.ad; ./malawi)
- X
- Xbecause the application defaults are mandatory for malawi to display correctly.
- X
- XThe program runs on the following platforms:
- X
- X Sequent, DYNIX/ptx 1.3.1 (SYSV 3.2), X11R5, gcc
- X Apollo, Domain/OS 10.3.4 (BSD 4.3), X11R4, cc
- X DEC 5000/240, Ultrix 4.2, X11R5, cc
- X IBM RS6000, AIX 3.2.2, X11R5, cc
- X
- XSince the program is fairly operating system independent, it should actually
- Xcompile under every environment with X11R4 or higher.
- X
- X
- XBug reports:
- X
- XDirect bug reports, bug fixes, enhancements, ... to
- XJohannes Sixt (jsixt@risc.uni-linz.ac.at)
- X
- XSince my native language is not English any comments on and improvements of
- XEnglish prose anywhere in the source and, most importantly, in the man page
- Xare welcome.
- END_OF_FILE
- if test 1122 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'malawi.man' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'malawi.man'\"
- else
- echo shar: Extracting \"'malawi.man'\" \(5154 characters\)
- sed "s/^X//" >'malawi.man' <<'END_OF_FILE'
- X.TH MALAWI 6 "Version 0.1"
- X.SH NAME
- Xmalawi - a computerized 2 players strategy board game
- X.SH SYNOPSIS
- X.B malawi
- X[-\fItoolkitoption\fP ...]
- X[-white \fIdisplay\fP]
- X[-black \fIdisplay\fP]
- X[-mto \fItime-out\fP]
- X.SH DESCRIPTION
- X.I malawi
- Xis a strategy board game for 2 players which has fairly simple rules.
- XIf played by somewhat experienced opponents a game can take one hour and
- Xmore.
- X.LP
- XThe board is a 6x6 raster.
- XEach player has a \fBbase line\fP on the board, 6 \fBsticks\fP, and 12
- X\fBeumels\fP.
- XInitially, the 6 sticks are positioned on the base line, each carrying 2
- Xeumels.
- XThe 2 players' base lines are opposite rows on the board.
- X.LP
- XThe goal of the game is to move a stick that carries at least one eumel onto
- Xthe opponent's base line such that the eumels carried by the stick can not be
- Xcaptured immediatly by the opponent. To achieve this goal the sticks can be
- Xmoved, eumels can be redistributed, and opponent's eumels can be captured.
- XThere are always 6 sticks per player in the game, but the number of eumels
- Xwill decrease (and never increase) as they get captured.
- X.LP
- XThe program watches the rules, so it is not possible for a player to do
- Xsomething against the rules.
- X.SH RULES
- XThe two opponents alternate their turns. White begins the game.
- XDuring his turn, a player must do one of three things:
- X.IP "Move a stick"
- XThe player moves one of his sticks. It can be moved only horizontally or
- Xvertically. It must be moved exactly as many fields as eumels are on the
- Xstick. (Hence, a stick without eumels or with 6 eumels cannot be moved.)
- XThe direction of the
- Xmovement must not be altered during the move. All fields on the path as well
- Xas the final field must be empty, i.e. no stick of either player may occupy
- Xsuch a field, not even a stick that carries no eumels.
- X.IP "Capture opponent's eumels"
- XThe player removes \fBall\fP eumels of one of the opponent's sticks. This stick
- Xmust occupy a field that could be reached, if it were empty, by a move of
- Xa stick of the player as described above. It is not allowed to "remove"
- Xzero eumels. The captured eumels are out of play and are never returned.
- X.IP "Distribute eumels"
- XThe player distributes \fBall\fP eumels of one of his sticks onto his other
- Xsticks. It is not allowed to "distribute" zero eumels. Each stick may receive
- Xat most one eumel. The stick which was emptied must not receive an eumel (it
- Xremains, therefore, empty). A stick can carry at most 6 eumels. If
- X6 eumels are to be distributed the superfluous eumel is removed from play
- Xand is lost. On the other hand, it is not allowed to remove eumels from play
- Xby not putting it on any stick if there are still sticks which can take an
- Xeumel (because they have not received one yet and they are not the stick
- Xthat is distributed).
- X.LP
- XThe game ends in two cases:
- X.IP "No eumels"
- XIf a player loses all eumels he has lost the game.
- X.IP "Eumel survives on enemy base line"
- XIf a player's eumel survives one opponent's turn on the opponent's base line
- Xthe player wins the game; that is, if the player gets his turn and still has
- Xa stick on the opponent's base line and this stick carries at least one eumel.
- X.SH USING THE PROGRAM
- XWhen a player's turn begins he selects one of his sticks. Then he chooses
- Xwhat to do with the stick by pressing one of the buttons "Move Stick",
- X"Distribute Eumels", or "Capture Eumels". Then he either selects the
- Xdestination
- Xfield(s) and presses "Execute Turn" or he selects "Cancel Turn" in which case
- Xhe again can choose a field.
- X.LP
- XA message line displays errors and gives hints on what a player can do.
- X.LP
- XThe buttons "New Game" and "Quit Game" have obvious functions. However, if
- Xone player presses the button only a request is issued: The button is
- Xhighlighted on both players' displays, but the function
- Xis not executed until the other player also presses the button and thus
- Xconfirms the request. A request can be withdrawn by the player who issued it
- Xbefore the other player confirms it by again pressing the button.
- X.SH OPTIONS
- XSince
- X.I malawi
- Xis built on top of the X Toolkit and the Athena Widget Set,
- Xall standard toolkit options are accepted. Additionally,
- X.I malawi
- Xunderstands the following command line options and application resources:
- X.PP
- X.TP 8
- X.B \-white \fIdisplay\fP
- X(Resource \fBwhite\fP) This option specifies on which display the white
- Xside player is.
- X.TP 8
- X.B \-black \fIdisplay\fP
- X(Resource \fBblack\fP) This option specifies on which display the black
- Xside player is.
- X.TP 8
- X.B \-mto \fItime-out\fP
- X(Resource \fBmessageTimeOut\fP) This option specifies how long error messages
- Xare displayed in the message line. \fItime-out\fP is in milli-seconds.
- XThe default is 4000.
- X.SH BUGS
- XThere's no possibility for the players to communicate unless they sit in the
- Xsame room where they can yell each other.
- X.LP
- XThere is no possibility to take back moves once they are "executed".
- X.LP
- XIt is planned that the game can be played against the computer.
- X.LP
- X.SH IDEA
- XThe idea for the game is stolen from PIATNIK game No. 6104 by Gerhard Kodys.
- X.SH COPYRIGHT
- XThe computerized version of the game is written by
- XJohannes Sixt (jsixt@risc.uni-linz.ac.at).
- X.LP
- XCopyright (c) 1993 Johannes Sixt
- END_OF_FILE
- if test 5154 -ne `wc -c <'malawi.man'`; then
- echo shar: \"'malawi.man'\" unpacked with wrong size!
- fi
- # end of 'malawi.man'
- fi
- if test -f 'HISTORY' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'HISTORY'\"
- else
- echo shar: Extracting \"'HISTORY'\" \(188 characters\)
- sed "s/^X//" >'HISTORY' <<'END_OF_FILE'
- XMalawi 0.1
- X
- X Data structures have been rewritten such that future extensions, like
- X computer as player are possible.
- X
- X Multiple displays are supported.
- X
- X
- XMalawi 0.0
- X
- X First implementation
- END_OF_FILE
- if test 188 -ne `wc -c <'HISTORY'`; then
- echo shar: \"'HISTORY'\" unpacked with wrong size!
- fi
- # end of 'HISTORY'
- fi
- if test -f 'Imakefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Imakefile'\"
- else
- echo shar: Extracting \"'Imakefile'\" \(102 characters\)
- sed "s/^X//" >'Imakefile' <<'END_OF_FILE'
- XLOCAL_LIBRARIES = XawClientLibs
- XMANSUFFIX = 6
- X
- XSimpleProgramTarget(malawi)
- XInstallAppDefaults(Malawi)
- END_OF_FILE
- if test 102 -ne `wc -c <'Imakefile'`; then
- echo shar: \"'Imakefile'\" unpacked with wrong size!
- fi
- # end of 'Imakefile'
- fi
- if test -f 'MANIFEST' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'MANIFEST'\"
- else
- echo shar: Extracting \"'MANIFEST'\" \(569 characters\)
- sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
- X File Name Archive # Description
- X-----------------------------------------------------------
- X README 1 Read this first
- X malawi.man 1 Unformatted man page
- X HISTORY 1 The evolution of the computerized game
- X Imakefile 1
- X MANIFEST 1 This shipping list
- X Makefile.std 1 Simple Makefile in case you don't have imake
- X Malawi.ad 1 Application defaults
- X malawi.c 1 Source of everything
- X patchlevel.h 1 Version information
- END_OF_FILE
- if test 569 -ne `wc -c <'MANIFEST'`; then
- echo shar: \"'MANIFEST'\" unpacked with wrong size!
- fi
- # end of 'MANIFEST'
- fi
- if test -f 'Makefile.std' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile.std'\"
- else
- echo shar: Extracting \"'Makefile.std'\" \(115 characters\)
- sed "s/^X//" >'Makefile.std' <<'END_OF_FILE'
- XOBJS = malawi.o
- XLIBS = -lXaw -lXmu -lXt -lXext -lX11
- XCFLAGS = -O
- X
- Xmalawi: $(OBJS)
- X $(CC) -o malawi $(OBJS) $(LIBS)
- END_OF_FILE
- if test 115 -ne `wc -c <'Makefile.std'`; then
- echo shar: \"'Makefile.std'\" unpacked with wrong size!
- fi
- # end of 'Makefile.std'
- fi
- if test -f 'Malawi.ad' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Malawi.ad'\"
- else
- echo shar: Extracting \"'Malawi.ad'\" \(340 characters\)
- sed "s/^X//" >'Malawi.ad' <<'END_OF_FILE'
- X*new.label: New Game
- X*quit.label: Quit Game
- X*quit.fromHoriz: new
- X
- X*move.label: Move Stick
- X*distribute.label: Distribute Eumels
- X*capture.label: Capture Eumels
- X*do.label: Execute Turn
- X*cancel.label: Cancel Turn
- X
- X*distribute.fromHoriz: move
- X*capture.fromHoriz: distribute
- X*do.fromVert: move
- X*cancel.fromHoriz: do
- X*cancel.fromVert: move
- END_OF_FILE
- if test 340 -ne `wc -c <'Malawi.ad'`; then
- echo shar: \"'Malawi.ad'\" unpacked with wrong size!
- fi
- # end of 'Malawi.ad'
- fi
- if test -f 'malawi.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'malawi.c'\"
- else
- echo shar: Extracting \"'malawi.c'\" \(29241 characters\)
- sed "s/^X//" >'malawi.c' <<'END_OF_FILE'
- X/*
- X * Copyright 1993 Johannes Sixt
- X *
- X * Permission to use, copy, modify and distribute this software and its
- X * documentation for any purpose other than its commercial exploitation
- X * is hereby granted without fee, provided that the above copyright
- X * notice appear in all copies and that both that copyright notice and
- X * this permission notice appear in supporting documentation. The author
- X * makes no representations about the suitability of this software for
- X * any purpose. It is provided "as is" without express or implied warranty.
- X *
- X * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- X * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
- X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- X * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
- X * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
- X * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- X * PERFORMANCE OF THIS SOFTWARE.
- X *
- X * Author: Johannes Sixt <jsixt@risc.uni-linz.ac.at>
- X */
- X
- X#include <stdio.h> /* also for sprintf */
- X
- X#include <X11/Intrinsic.h>
- X#include <X11/StringDefs.h>
- X#include <X11/Shell.h>
- X#include <X11/Xaw/Paned.h>
- X/* #include <X11/Xaw/Command.h> included by <X11/Xaw/Toggle.h> */
- X#include <X11/Xaw/Toggle.h>
- X#include <X11/Xaw/Form.h>
- X#include "patchlevel.h"
- X
- X#define BOARD_SIZE 6
- X#define INITIAL_EUMELS 2
- X#define MAX_EUMELS BOARD_SIZE
- X#define FIELD_WIDTH 80
- X#define FIELD_HEIGHT FIELD_WIDTH
- X#define WIN_WIDTH (FIELD_WIDTH * BOARD_SIZE)
- X#define WIN_HEIGHT (FIELD_HEIGHT * BOARD_SIZE)
- X#define MESS_TIME_OUT 4000
- X
- Xtypedef enum {
- X BlackSide, WhiteSide, Empty
- X } FieldType;
- X#define MAX_FIELD_TYPE ((int) Empty)
- X
- Xtypedef struct {
- X FieldType type; /* empty, black, white */
- X int count; /* number of Eumels */
- X int r, c; /* row, column of this field */
- X} Field;
- X
- Xtypedef struct {
- X FieldType side; /* whose turn is it? Empty is not allowed */
- X FieldType other_side; /* whose turn is it NOT? For ease of program */
- X#if BOARD_SIZE < 4
- X#define MAX_POSS 4
- X#else
- X#define MAX_POSS BOARD_SIZE
- X#endif
- X Field *possibility[MAX_POSS]; /* possible destinations */
- X int no_possibilities; /* number of possible destinations */
- X Field *source; /* field involved in this turn */
- X Field board[BOARD_SIZE][BOARD_SIZE];
- X int remain[MAX_FIELD_TYPE]; /* remaining eumels */
- X} MoveData;
- X
- Xtypedef struct {
- X Pixmap bitmap; /* bitmap to draw Field in */
- X Widget widget; /* the toggle widget */
- X} DisplayField;
- X
- Xtypedef struct {
- X Display *d;
- X GC cleargc, gc; /* Graphics Contexts for clearing and drawing */
- X Widget top_level; /* application shell of the display */
- X Widget new_game, quit;
- X Widget turnMove, turnDistr, turnCapture, turnDo, turnCancel;
- X Widget message;
- X XtIntervalId messTimeOut;
- X char *rulesHint;
- X DisplayField board[BOARD_SIZE][BOARD_SIZE];
- X} PerDisplay;
- X
- Xtypedef struct {
- X MoveData *move;
- X /* what is player going to do in this turn? */
- X#if NeedFunctionPrototypes
- X Boolean (*executeTurn)(void);
- X#else
- X Boolean (*executeTurn)();
- X#endif
- X PerDisplay pd[MAX_FIELD_TYPE]; /* don't provide for Empty */
- X FieldType requests_new, requests_quit;
- X} DisplayData;
- X
- Xstatic void CreateUserInterface();
- Xstatic void InitDrawing();
- Xstatic void DrawField();
- Xstatic void InitTurn();
- Xstatic void NewGame();
- Xstatic void InitGame();
- Xstatic void Quit();
- Xstatic void DoMove();
- Xstatic void DoDistribute();
- Xstatic void DoCapture();
- Xstatic void DoTurn();
- Xstatic void PrepareDoTurn();
- Xstatic void CancelTurn();
- Xstatic Boolean FindSingleSelected();
- Xstatic void FindPossibilities();
- Xstatic Boolean Move();
- Xstatic Boolean Distribute();
- Xstatic Boolean Capture();
- Xstatic Boolean IsSet();
- Xstatic Boolean GameEnds();
- X#define OtherSide(side) \
- X ((FieldType)(((int) BlackSide + (int) WhiteSide) - (int) side))
- Xstatic void BeepMessage();
- Xstatic void SetRulesHint();
- Xstatic void RestoreMessage();
- X
- Xstatic XtAppContext app_context;
- X
- Xstatic MoveData move_data; /* data of next move */
- Xstatic DisplayData dd = { &move_data }; /* data to display field */
- X
- Xstatic struct _app_res {
- X String black_side;
- X String white_side;
- X int message_time_out;
- X} app_res;
- X
- X#define offset(field) XtOffsetOf(struct _app_res, field)
- Xstatic XtResource resources[] = {
- X {"black", "Black", XtRString, sizeof(String),
- X offset(black_side), XtRImmediate, NULL},
- X {"white", "White", XtRString, sizeof(String),
- X offset(white_side), XtRImmediate, NULL},
- X {"messageTimeOut", "MessageTimeOut", XtRInt, sizeof(int),
- X offset(message_time_out), XtRImmediate,
- X (XtPointer) MESS_TIME_OUT},
- X};
- X
- Xstatic XrmOptionDescRec options[] = {
- X {"-black", ".black", XrmoptionSepArg, NULL},
- X {"-white", ".white", XrmoptionSepArg, NULL},
- X {"-mto", ".messageTimeOut", XrmoptionSepArg, NULL},
- X};
- X
- Xstatic String fallback_res[] = {
- X "*quit.fromHoriz: new",
- X "*distribute.fromHoriz: move",
- X "*capture.fromHoriz: distribute",
- X "*do.fromHoriz: capture",
- X "*cancel.fromHoriz: do",
- X NULL
- X};
- X
- Xstatic char app_class[] = "Malawi";
- X
- Xvoid main(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X Display *d;
- X Widget top_level;
- X Window w;
- X int i, j;
- X static char white_title[50], black_title[50];
- X Boolean top_level_used;
- X
- X (void) sprintf(white_title, "Malawi %s, White side", VERSION);
- X (void) sprintf(black_title, "Malawi %s, Black side", VERSION);
- X
- X XtToolkitInitialize();
- X app_context = XtCreateApplicationContext();
- X XtAppSetFallbackResources(app_context, fallback_res);
- X
- X d = XtOpenDisplay(app_context, NULL, argv[0], app_class,
- X options, XtNumber(options), &argc, argv);
- X if (d == NULL) {
- X fprintf(stderr, "Can't open display\n");
- X exit(1);
- X }
- X if (argc > 1) {
- X fprintf(stderr,
- X "Usage: %s [-black display] [-white display] [-mto time-out]\n",
- X argv[0]);
- X exit(1);
- X }
- X
- X top_level = XtVaAppCreateShell(NULL, app_class,
- X applicationShellWidgetClass, d,
- X NULL);
- X
- X XtGetApplicationResources(top_level, (XtPointer) &app_res,
- X resources, XtNumber(resources), NULL, 0);
- X
- X top_level_used = False;
- X /* find white side's display */
- X if (app_res.white_side == NULL) {
- X dd.pd[WhiteSide].d = d;
- X dd.pd[WhiteSide].top_level = top_level;
- X XtVaSetValues(top_level, XtNtitle, (XtArgVal) white_title, NULL);
- X top_level_used = True;
- X } else {
- X dd.pd[WhiteSide].d = XtOpenDisplay(app_context, app_res.white_side,
- X argv[0], app_class, NULL, 0, &argc, argv);
- X if (dd.pd[WhiteSide].d == NULL) {
- X fprintf(stderr, "Can't open display %s\n", app_res.white_side);
- X exit(1);
- X }
- X dd.pd[WhiteSide].top_level = XtVaAppCreateShell(NULL, app_class,
- X applicationShellWidgetClass, dd.pd[WhiteSide].d,
- X XtNtitle, (XtArgVal) white_title,
- X NULL);
- X }
- X CreateUserInterface(WhiteSide);
- X
- X /* find black side's display */
- X if (!top_level_used && app_res.black_side == NULL) {
- X dd.pd[BlackSide].d = d;
- X dd.pd[BlackSide].top_level = top_level;
- X XtVaSetValues(top_level, XtNtitle, (XtArgVal) black_title, NULL);
- X top_level_used = True;
- X } else {
- X dd.pd[BlackSide].d = XtOpenDisplay(app_context, app_res.black_side,
- X argv[0], app_class, NULL, 0, &argc, argv);
- X if (dd.pd[BlackSide].d == NULL) {
- X fprintf(stderr, "Can't open display %s\n", app_res.black_side);
- X exit(1);
- X }
- X dd.pd[BlackSide].top_level = XtVaAppCreateShell(NULL, app_class,
- X applicationShellWidgetClass, dd.pd[BlackSide].d,
- X XtNtitle, (XtArgVal) black_title,
- X NULL);
- X }
- X CreateUserInterface(BlackSide);
- X
- X XtRealizeWidget(dd.pd[WhiteSide].top_level);
- X XtRealizeWidget(dd.pd[BlackSide].top_level);
- X
- X /* draw board */
- X w = XtWindow(dd.pd[WhiteSide].top_level);
- X for (i = 0; i < BOARD_SIZE; i++) {
- X for (j = 0; j < BOARD_SIZE; j++) {
- X dd.pd[WhiteSide].board[i][j].bitmap =
- X XCreatePixmap(dd.pd[WhiteSide].d, w,
- X FIELD_WIDTH, FIELD_HEIGHT, 1);
- X }
- X }
- X
- X w = XtWindow(dd.pd[BlackSide].top_level);
- X for (i = 0; i < BOARD_SIZE; i++) {
- X for (j = 0; j < BOARD_SIZE; j++) {
- X dd.pd[BlackSide].board[i][j].bitmap =
- X XCreatePixmap(dd.pd[BlackSide].d, w,
- X FIELD_WIDTH, FIELD_HEIGHT, 1);
- X }
- X }
- X
- X InitDrawing(WhiteSide);
- X InitDrawing(BlackSide);
- X
- X InitGame(NULL, NULL, NULL);
- X
- X XtAppMainLoop(app_context);
- X /*NOTREACHED*/
- X}
- X
- X
- X#define HIGHTHICK 2
- X
- Xstatic void CreateUserInterface(side)
- XFieldType side;
- X{
- X Widget panel, game, form, turn;
- X int i, j;
- X
- X panel = XtVaCreateManagedWidget("panel", panedWidgetClass,
- X dd.pd[side].top_level, NULL);
- X
- X game = XtVaCreateManagedWidget("game", formWidgetClass, panel,
- X NULL);
- X
- X dd.pd[side].new_game = XtVaCreateManagedWidget("new",
- X toggleWidgetClass, game,
- X XtNstate, (XtArgVal) False,
- X NULL);
- X XtAddCallback(dd.pd[side].new_game, XtNcallback, NewGame, (XtPointer) side);
- X
- X dd.pd[side].quit = XtVaCreateManagedWidget("quit", toggleWidgetClass, game,
- X XtNstate, (XtArgVal) False,
- X NULL);
- X XtAddCallback(dd.pd[side].quit, XtNcallback, Quit, (XtPointer) side);
- X
- X dd.pd[side].message = XtVaCreateManagedWidget("message",
- X labelWidgetClass, panel,
- X XtNlabel, (XtArgVal) "",
- X NULL);
- X
- X dd.pd[side].messTimeOut = NULL;
- X
- X turn = XtVaCreateManagedWidget("turn", formWidgetClass, panel,
- X NULL);
- X dd.pd[side].turnMove = XtVaCreateManagedWidget("move",
- X commandWidgetClass, turn, NULL);
- X dd.pd[side].turnDistr = XtVaCreateManagedWidget("distribute",
- X commandWidgetClass, turn, NULL);
- X dd.pd[side].turnCapture = XtVaCreateManagedWidget("capture",
- X commandWidgetClass, turn, NULL);
- X dd.pd[side].turnDo = XtVaCreateManagedWidget("do",
- X commandWidgetClass, turn, NULL);
- X dd.pd[side].turnCancel = XtVaCreateManagedWidget("cancel",
- X commandWidgetClass, turn, NULL);
- X
- X XtAddCallback(dd.pd[side].turnMove, XtNcallback, DoMove, NULL);
- X XtAddCallback(dd.pd[side].turnDistr, XtNcallback, DoDistribute, NULL);
- X XtAddCallback(dd.pd[side].turnCapture, XtNcallback, DoCapture, NULL);
- X XtAddCallback(dd.pd[side].turnDo, XtNcallback, DoTurn, NULL);
- X XtAddCallback(dd.pd[side].turnCancel, XtNcallback, CancelTurn, NULL);
- X
- X form = XtVaCreateManagedWidget("form", formWidgetClass, panel,
- X NULL);
- X
- X /* create buttons for fields */
- X for (i = 0; i < BOARD_SIZE; i++) {
- X for (j = 0; j < BOARD_SIZE; j++) {
- X dd.pd[side].board[i][j].widget =
- X XtVaCreateManagedWidget("field", toggleWidgetClass, form,
- X XtNlabel, (XtArgVal) "",
- X XtNwidth, (XtArgVal) (FIELD_WIDTH+(2*HIGHTHICK)),
- X XtNheight, (XtArgVal) (FIELD_HEIGHT+(2*HIGHTHICK)),
- X XtNinternalWidth, (XtArgVal) 0,
- X XtNinternalHeight, (XtArgVal) 0,
- X XtNhighlightThickness, (XtArgVal) HIGHTHICK,
- X XtNfromVert, (XtArgVal) (i == 0 ?
- X NULL : dd.pd[side].board[i-1][0].widget),
- X XtNfromHoriz, (XtArgVal) (j == 0 ?
- X NULL : dd.pd[side].board[i][j-1].widget),
- X NULL);
- X }
- X }
- X}
- X
- X
- X#define SIDE_MARKER_THICK 8
- X
- Xstatic XRectangle rect[MAX_EUMELS + 1];
- X
- Xstatic void InitDrawing(side)
- XFieldType side;
- X{
- X XGCValues values;
- X unsigned long mask;
- X int i;
- X
- X values.function = GXcopy;
- X values.foreground = 1;
- X values.background = 0;
- X values.line_width = 0;
- X values.line_style = LineSolid;
- X values.fill_style = FillSolid;
- X mask = GCFunction | GCForeground | GCBackground |
- X GCLineWidth | GCLineStyle | GCFillStyle;
- X dd.pd[side].gc = XCreateGC(dd.pd[side].d,
- X dd.pd[side].board[0][0].bitmap, mask, &values);
- X
- X values.foreground = 0;
- X mask = GCFunction | GCForeground | GCBackground | GCFillStyle;
- X dd.pd[side].cleargc = XCreateGC(dd.pd[side].d,
- X dd.pd[side].board[0][0].bitmap, mask, &values);
- X
- X /* initialize rectangles array */
- X rect[0].x = SIDE_MARKER_THICK;
- X rect[0].y = FIELD_HEIGHT - ((3 * SIDE_MARKER_THICK) / 2);
- X rect[0].width = FIELD_WIDTH - 2 * SIDE_MARKER_THICK;
- X rect[0].height = SIDE_MARKER_THICK;
- X /* try hard to make the rects nicly aligned */
- X for (i = 1; i <= MAX_EUMELS; i++) {
- X rect[i].x = i * (FIELD_WIDTH / (MAX_EUMELS + 3));
- X rect[i].y = FIELD_HEIGHT - ((3 * SIDE_MARKER_THICK) / 2) -
- X i * ((FIELD_WIDTH - ((3 * SIDE_MARKER_THICK) / 2)) /
- X (MAX_EUMELS + 3));
- X rect[i].width = 2 * (FIELD_WIDTH / (MAX_EUMELS + 3));
- X rect[i].height = ((FIELD_WIDTH - ((3 * SIDE_MARKER_THICK) / 2)) /
- X (MAX_EUMELS + 3)) - 1;
- X }
- X}
- X
- X
- Xstatic void DrawField(r, c)
- Xint r, c;
- X{
- X#if NeedFunctionPrototypes
- X int (*fun)(Display *display, Drawable d, GC gc, XRectangle *rect, int c);
- X#else
- X int (*fun)();
- X#endif
- X
- X /* clear drawing area */
- X XFillRectangle(dd.pd[WhiteSide].d, dd.pd[WhiteSide].board[r][c].bitmap,
- X dd.pd[WhiteSide].cleargc,
- X 0, 0, FIELD_WIDTH, FIELD_HEIGHT);
- X XFillRectangle(dd.pd[BlackSide].d, dd.pd[BlackSide].board[r][c].bitmap,
- X dd.pd[BlackSide].cleargc,
- X 0, 0, FIELD_WIDTH, FIELD_HEIGHT);
- X if (dd.move->board[r][c].type == Empty) {
- X /* we're done */
- X XtVaSetValues(dd.pd[WhiteSide].board[r][c].widget,
- X XtNbitmap, (XtArgVal) dd.pd[WhiteSide].board[r][c].bitmap,
- X NULL);
- X XtVaSetValues(dd.pd[BlackSide].board[r][c].widget,
- X XtNbitmap, (XtArgVal) dd.pd[BlackSide].board[r][c].bitmap,
- X NULL);
- X return;
- X }
- X
- X switch (dd.move->board[r][c].type) {
- X case BlackSide:
- X fun = XFillRectangles;
- X break;
- X
- X case WhiteSide:
- X fun = XDrawRectangles;
- X break;
- X
- X default:
- X BeepMessage(BlackSide, "Default case must not occur. Call maintainer.");
- X BeepMessage(WhiteSide, "Default case must not occur. Call maintainer.");
- X return;
- X }
- X
- X (*fun)(dd.pd[WhiteSide].d, dd.pd[WhiteSide].board[r][c].bitmap,
- X dd.pd[WhiteSide].gc,
- X rect, dd.move->board[r][c].count + 1);
- X XtVaSetValues(dd.pd[WhiteSide].board[r][c].widget,
- X XtNbitmap, (XtArgVal) dd.pd[WhiteSide].board[r][c].bitmap,
- X NULL);
- X (*fun)(dd.pd[BlackSide].d, dd.pd[BlackSide].board[r][c].bitmap,
- X dd.pd[BlackSide].gc,
- X rect, dd.move->board[r][c].count + 1);
- X XtVaSetValues(dd.pd[BlackSide].board[r][c].widget,
- X XtNbitmap, (XtArgVal) dd.pd[BlackSide].board[r][c].bitmap,
- X NULL);
- X}
- X
- X
- X/*ARGSUSED*/
- Xstatic void NewGame(w, client_data, call_data)
- XWidget w;
- XXtPointer client_data, call_data;
- X{
- X FieldType side = (FieldType) client_data;
- X FieldType other_side = OtherSide(side);
- X static Arg arg = { XtNstate };
- X
- X arg.value = (XtArgVal) IsSet(w);
- X /* set button on opponent's display */
- X XtSetValues(dd.pd[other_side].new_game, &arg, 1);
- X
- X if (arg.value) { /* i.e. if (IsSet(w)) */
- X BeepMessage(other_side, "Opponent requests new game");
- X dd.requests_new = side;
- X } else {
- X if (dd.requests_new != side) {
- X /* request confirmed */
- X InitGame();
- X
- X /* withdraw quit requests; arg.value is False */
- X XtSetValues(dd.pd[WhiteSide].quit, &arg, 1);
- X XtSetValues(dd.pd[BlackSide].quit, &arg, 1);
- X }
- X }
- X}
- X
- X
- Xstatic void InitGame()
- X{
- X int i, j;
- X
- X dd.move->remain[BlackSide] = dd.move->remain[WhiteSide] =
- X BOARD_SIZE * INITIAL_EUMELS;
- X dd.move->side = WhiteSide;
- X dd.move->other_side = BlackSide;
- X
- X for (j = 0; j < BOARD_SIZE; j++) {
- X dd.move->board[0][j].type = BlackSide;
- X dd.move->board[0][j].count = INITIAL_EUMELS;
- X dd.move->board[0][j].r = 0;
- X dd.move->board[0][j].c = j;
- X dd.move->board[BOARD_SIZE - 1][j].type = WhiteSide;
- X dd.move->board[BOARD_SIZE - 1][j].count = INITIAL_EUMELS;
- X dd.move->board[BOARD_SIZE - 1][j].r = BOARD_SIZE - 1;
- X dd.move->board[BOARD_SIZE - 1][j].c = j;
- X }
- X for (i = 1; i < BOARD_SIZE - 1; i++) {
- X for (j = 0; j < BOARD_SIZE; j++) {
- X dd.move->board[i][j].type = Empty;
- X dd.move->board[i][j].count = 0;
- X dd.move->board[i][j].r = i;
- X dd.move->board[i][j].c = j;
- X }
- X }
- X
- X CancelTurn(NULL, NULL, NULL);
- X
- X for (i = 0; i < BOARD_SIZE; i++) {
- X for (j = 0; j < BOARD_SIZE; j++) {
- X DrawField(i, j);
- X }
- X }
- X}
- X
- X
- X/*ARGSUSED*/
- Xstatic void Quit(w, client_data, call_data)
- XWidget w;
- XXtPointer client_data, call_data;
- X{
- X FieldType side = (FieldType) client_data;
- X FieldType other_side = OtherSide(side);
- X
- X if (IsSet(w)) {
- X XtVaSetValues(dd.pd[other_side].quit,
- X XtNstate, (XtArgVal) True, NULL);
- X BeepMessage(other_side, "Opponent requests quitting");
- X dd.requests_quit = side;
- X } else {
- X XtVaSetValues(dd.pd[other_side].quit,
- X XtNstate, (XtArgVal) False, NULL);
- X if (dd.requests_quit != side) {
- X /* request confirmed */
- X exit(0);
- X }
- X }
- X}
- X
- X
- X/*ARGSUSED*/
- Xstatic void DoMove(w, clientData, notused)
- XWidget w;
- XXtPointer clientData, notused;
- X{
- X int i, j, k;
- X int r, c; /* position of source field */
- X int move_possibilities;
- X Field *source, *field;
- X Widget wid;
- X
- X /* prepare board for move */
- X dd.executeTurn = Move;
- X if (FindSingleSelected(&r, &c)) {
- X source = &dd.move->board[r][c];
- X if (source->count == 0) {
- X BeepMessage(dd.move->side, "This field cannot move, no eumels!");
- X return;
- X }
- X dd.move->source = source;
- X
- X FindPossibilities(dd.move, r, c);
- X
- X move_possibilities = dd.move->no_possibilities;
- X for (k = dd.move->no_possibilities; k > 0;) {
- X if (dd.move->possibility[--k]->type != Empty) {
- X move_possibilities--;
- X }
- X }
- X if (move_possibilities == 0) {
- X BeepMessage(dd.move->side, "These eumels cannot move: blocked!");
- X return;
- X }
- X
- X k = 0;
- X for (i = 0; i < BOARD_SIZE; i++) {
- X for (j = 0; j < BOARD_SIZE; j++) {
- X field = &dd.move->board[i][j];
- X wid = dd.pd[dd.move->side].board[i][j].widget;
- X XtVaSetValues(wid, XtNstate, (XtArgVal) False, NULL);
- X if (dd.move->possibility[k] == field) {
- X /* the field may or may not be empty;
- X FindPossibilities doesn't check for that */
- X XtSetSensitive(wid, field->type == Empty);
- X k++;
- X } else {
- X XtSetSensitive(wid, False);
- X }
- X }
- X }
- X
- X SetRulesHint(dd.move->side, "Select destination field");
- X PrepareDoTurn();
- X }
- X}
- X
- X
- X/*ARGSUSED*/
- Xstatic void DoDistribute(w, clientData, notused)
- XWidget w;
- XXtPointer clientData, notused;
- X{
- X int i, j;
- X int r, c; /* position of source field */
- X Field *source, *field;
- X Widget wid;
- X
- X /* prepare board for distribution */
- X dd.executeTurn = Distribute;
- X if (FindSingleSelected(&r, &c)) {
- X source = &dd.move->board[r][c];
- X if (source->count == 0) {
- X BeepMessage(dd.move->side, "This field has no eumels!");
- X return;
- X }
- X dd.move->source = source;
- X
- X dd.move->no_possibilities = 0;
- X for (i = 0; i < BOARD_SIZE; i++) {
- X for (j = 0; j < BOARD_SIZE; j++) {
- X field = &dd.move->board[i][j];
- X wid = dd.pd[dd.move->side].board[i][j].widget;
- X XtVaSetValues(wid, XtNstate, (XtArgVal) False, NULL);
- X if (field != source &&
- X field->type == dd.move->side &&
- X field->count < BOARD_SIZE) {
- X XtSetSensitive(wid, True);
- X dd.move->possibility[dd.move->no_possibilities++] = field;
- X } else {
- X XtSetSensitive(wid, False);
- X }
- X }
- X }
- X
- X SetRulesHint(dd.move->side,
- X "Select sticks onto which to distribute eumels");
- X PrepareDoTurn();
- X }
- X}
- X
- X
- X/*ARGSUSED*/
- Xstatic void DoCapture(w, clientData, notused)
- XWidget w;
- XXtPointer clientData, notused;
- X{
- X int i, j, k;
- X int r, c; /* position of source field */
- X int capture_possibilities;
- X Field *source, *field;
- X Widget wid;
- X
- X /* prepare board for capture */
- X dd.executeTurn = Capture;
- X if (FindSingleSelected(&r, &c)) {
- X source = &dd.move->board[r][c];
- X if (source->count == 0) {
- X BeepMessage(dd.move->side, "This stick has no eumels!");
- X return;
- X }
- X dd.move->source = source;
- X
- X FindPossibilities(dd.move, r, c);
- X
- X capture_possibilities = dd.move->no_possibilities;
- X for (k = dd.move->no_possibilities - 1; k >= 0; k--) {
- X if (dd.move->possibility[k]->count == 0 ||
- X dd.move->possibility[k]->type != dd.move->other_side) {
- X capture_possibilities--;
- X }
- X }
- X if (capture_possibilities == 0) {
- X BeepMessage(dd.move->side, "This stick cannot capture eumels!");
- X return;
- X }
- X
- X k = 0;
- X for (i = 0; i < BOARD_SIZE; i++) {
- X for (j = 0; j < BOARD_SIZE; j++) {
- X field = &dd.move->board[i][j];
- X wid = dd.pd[dd.move->side].board[i][j].widget;
- X XtVaSetValues(wid, XtNstate, (XtArgVal) False, NULL);
- X if (dd.move->possibility[k] == field) {
- X /* the field may or may not be removable;
- X FindPossibilities doesn't check for that */
- X XtSetSensitive(wid, field->count != 0 &&
- X field->type == dd.move->other_side);
- X k++;
- X } else {
- X XtSetSensitive(wid, False);
- X }
- X }
- X }
- X
- X SetRulesHint(dd.move->side,
- X "Select the field from which to capture eumels");
- X PrepareDoTurn();
- X }
- X}
- X
- X
- Xstatic void PrepareDoTurn()
- X{
- X PerDisplay *me = &dd.pd[dd.move->side];
- X
- X XtSetSensitive(me->turnMove, False);
- X XtSetSensitive(me->turnDistr, False);
- X XtSetSensitive(me->turnCapture, False);
- X XtSetSensitive(me->turnDo, True);
- X XtSetSensitive(me->turnCancel, True);
- X}
- X
- X
- X/*ARGSUSED*/
- Xstatic void DoTurn(w, client_data, unused)
- XWidget w;
- XXtPointer client_data, unused;
- X{
- X PerDisplay *me, *other;
- X FieldType won_by;
- X static char buf[100];
- X
- X if ((*dd.executeTurn)()) {
- X dd.move->other_side = dd.move->side;
- X dd.move->side = OtherSide(dd.move->side);
- X
- X if (GameEnds(dd.move, &won_by)) {
- X /* game ends */
- X BeepMessage(WhiteSide, "GAME OVER");
- X BeepMessage(BlackSide, "GAME OVER");
- X (void) sprintf(buf, "Game won by %s side",
- X won_by == BlackSide ? "Black" : "White");
- X dd.pd[WhiteSide].rulesHint = buf;
- X dd.pd[BlackSide].rulesHint = buf;
- X
- X me = &dd.pd[dd.move->side];
- X other = &dd.pd[dd.move->other_side];
- X XtSetSensitive(me->turnDo, False);
- X XtSetSensitive(me->turnCancel, False);
- X XtSetSensitive(other->turnDo, False);
- X XtSetSensitive(other->turnCancel, False);
- X } else {
- X CancelTurn(w, NULL, NULL);
- X }
- X }
- X}
- X
- X
- X/*ARGSUSED*/
- Xstatic void CancelTurn(w, client_data, unused)
- XWidget w;
- XXtPointer client_data, unused;
- X{
- X PerDisplay *me, *other;
- X
- X me = &dd.pd[dd.move->side];
- X other = &dd.pd[dd.move->other_side];
- X
- X XtSetSensitive(me->turnMove, True);
- X XtSetSensitive(me->turnDistr, True);
- X XtSetSensitive(me->turnCapture, True);
- X XtSetSensitive(me->turnDo, False);
- X XtSetSensitive(me->turnCancel, False);
- X XtSetSensitive(other->turnMove, False);
- X XtSetSensitive(other->turnDistr, False);
- X XtSetSensitive(other->turnCapture, False);
- X XtSetSensitive(other->turnDo, False);
- X XtSetSensitive(other->turnCancel, False);
- X InitTurn();
- X}
- X
- X
- X/* Initialize for new turn: Only the side's fields are sensitive. */
- Xstatic void InitTurn()
- X{
- X int i, j;
- X PerDisplay *me, *other;
- X
- X me = &dd.pd[dd.move->side];
- X other = &dd.pd[dd.move->other_side];
- X for (i = 0; i < BOARD_SIZE; i++) {
- X for (j = 0; j < BOARD_SIZE; j++) {
- X XtSetSensitive(me->board[i][j].widget,
- X dd.move->board[i][j].type == dd.move->side);
- X XtVaSetValues(me->board[i][j].widget,
- X XtNstate, (XtArgVal) False, NULL);
- X XtSetSensitive(other->board[i][j].widget, False);
- X XtVaSetValues(other->board[i][j].widget,
- X XtNstate, (XtArgVal) False, NULL);
- X }
- X }
- X
- X SetRulesHint(dd.move->side, "Select one stick");
- X SetRulesHint(dd.move->other_side, "Opponent's turn");
- X}
- X
- X
- Xstatic Boolean FindSingleSelected(r, c)
- Xint *r, *c;
- X{
- X int i, j;
- X Boolean found = False;
- X PerDisplay *me = &dd.pd[dd.move->side];
- X
- X for (i = 0; i < BOARD_SIZE; i++) {
- X for (j = 0; j < BOARD_SIZE; j++) {
- X if (IsSet(me->board[i][j].widget)) {
- X if (found) {
- X /* more than one field selected */
- X BeepMessage(dd.move->side,
- X "More than one field is selected!");
- X return False;
- X }
- X found = True;
- X *r = i;
- X *c = j;
- X }
- X }
- X }
- X if (!found) {
- X /* no field is selected */
- X BeepMessage(dd.move->side, "No field is selected!");
- X return False;
- X }
- X return True;
- X}
- X
- X
- X/**
- XFind the fields which can be reached from a given field.
- X*/
- Xstatic void FindPossibilities(move, r, c)
- XMoveData *move;
- Xint r, c; /* position of source field */
- X{
- X int i;
- X int dpr, dpc; /* positive row, column */
- X int dnr, dnc; /* negative row, coulmn */
- X Boolean north_ok, east_ok, south_ok, west_ok;
- X
- X north_ok = east_ok = south_ok = west_ok = True;
- X dpr = dnr = r, dpc = dnc = c;
- X
- X i = move->board[r][c].count;
- X if (i == 0) {
- X move->no_possibilities = 0;
- X return;
- X }
- X
- X /* check for occupied fields BETWEEN source and possible destinations */
- X for (i--; i; i--) {
- X ++dpr, ++dpc, --dnr, --dnc;
- X if (north_ok &&
- X (dnr < 0 || move->board[dnr][c].type != Empty))
- X north_ok = False;
- X if (west_ok &&
- X (dnc < 0 || move->board[r][dnc].type != Empty))
- X west_ok = False;
- X if (east_ok &&
- X (dpc>=BOARD_SIZE || move->board[r][dpc].type != Empty))
- X east_ok = False;
- X if (south_ok &&
- X (dpr>=BOARD_SIZE || move->board[dpr][c].type != Empty))
- X south_ok = False;
- X }
- X ++dpr, ++dpc, --dnr, --dnc;
- X
- X /* check that possible destinations don't fall off board */
- X if (dnr < 0)
- X north_ok = False;
- X if (dnc < 0)
- X west_ok = False;
- X if (dpc >= BOARD_SIZE)
- X east_ok = False;
- X if (dpr >= BOARD_SIZE)
- X south_ok = False;
- X
- X
- X /* ensure that the possiblities are stored in "increasing" order if
- X board is scanned with column index changing fastest */
- X i = 0;
- X if (north_ok)
- X move->possibility[i++] = &move->board[dnr][c];
- X if (west_ok)
- X move->possibility[i++] = &move->board[r][dnc];
- X if (east_ok)
- X move->possibility[i++] = &move->board[r][dpc];
- X if (south_ok)
- X move->possibility[i++] = &move->board[dpr][c];
- X move->no_possibilities = i;
- X
- X /* erase remaining array */
- X while (i < MAX_POSS)
- X move->possibility[i++] = NULL;
- X}
- X
- X
- Xstatic Boolean Move()
- X{
- X int i;
- X Field *field = NULL, *f;
- X PerDisplay *me = &dd.pd[dd.move->side];
- X
- X /* this should not occur */ if (dd.move->no_possibilities == 0) return True;
- X
- X for (i = dd.move->no_possibilities; i > 0;) {
- X f = dd.move->possibility[--i];
- X if (IsSet(me->board[f->r][f->c].widget)) {
- X if (field != NULL) {
- X BeepMessage(dd.move->side, "More than one field is selected!");
- X return False;
- X }
- X field = f;
- X }
- X }
- X if (field == NULL) {
- X BeepMessage(dd.move->side, "No field is selected!");
- X return False;
- X }
- X field->type = dd.move->source->type;
- X field->count = dd.move->source->count;
- X dd.move->source->type = Empty;
- X dd.move->source->count = 0;
- X DrawField(dd.move->source->r, dd.move->source->c);
- X DrawField(field->r, field->c);
- X return True;
- X}
- X
- X
- Xstatic Boolean Distribute()
- X{
- X int i;
- X int must_distribute; /* number of fields that must be selected */
- X int selected = 0;
- X Field *field;
- X PerDisplay *me = &dd.pd[dd.move->side];
- X
- X must_distribute = dd.move->source->count < dd.move->no_possibilities ?
- X dd.move->source->count : dd.move->no_possibilities;
- X
- X for (i = dd.move->no_possibilities; i > 0;) {
- X field = dd.move->possibility[--i];
- X if (IsSet(me->board[field->r][field->c].widget)) {
- X selected++;
- X }
- X }
- X
- X if (selected != must_distribute) {
- X char buf[100];
- X (void) sprintf(buf, "Exactly %d fields must be selected!",
- X must_distribute);
- X BeepMessage(dd.move->side, buf);
- X return False;
- X }
- X
- X for (i = dd.move->no_possibilities; i > 0;) {
- X field = dd.move->possibility[--i];
- X if (IsSet(me->board[field->r][field->c].widget)) {
- X field->count++;
- X dd.move->source->count--;
- X DrawField(field->r, field->c);
- X }
- X }
- X
- X /* remaining eumels are lost */
- X dd.move->remain[dd.move->side] -= dd.move->source->count;
- X dd.move->source->count = 0;
- X DrawField(dd.move->source->r, dd.move->source->c);
- X
- X /* This should not lead to end of game. Correct me if I'm wrong. */
- X
- X return True;
- X}
- X
- X
- Xstatic Boolean Capture()
- X{
- X int i;
- X Field *field = NULL, *f;
- X PerDisplay *me = &dd.pd[dd.move->side];
- X
- X /* this should not occur */ if (dd.move->no_possibilities == 0) return True;
- X
- X for (i = dd.move->no_possibilities; i > 0;) {
- X f = dd.move->possibility[--i];
- X if (IsSet(me->board[f->r][f->c].widget)) {
- X if (field != NULL) {
- X BeepMessage(dd.move->side, "More than one field is selected!");
- X return False;
- X }
- X field = f;
- X }
- X }
- X if (field == NULL) {
- X BeepMessage(dd.move->side, "No field is selected!");
- X return False;
- X }
- X dd.move->remain[field->type] -= field->count;
- X field->count = 0;
- X DrawField(field->r, field->c);
- X
- X return True;
- X}
- X
- X
- Xstatic Boolean IsSet(w)
- XWidget w;
- X{
- X Boolean state;
- X
- X XtVaGetValues(w, XtNstate, (XtArgVal) &state, NULL);
- X return state;
- X}
- X
- X
- Xstatic Boolean GameEnds(move, winning_side)
- XMoveData *move;
- XFieldType *winning_side;
- X{
- X int i, j;
- X
- X if (move->remain[move->side] == 0) {
- X *winning_side = move->other_side;
- X return True;
- X }
- X
- X i = move->side == BlackSide ? BOARD_SIZE - 1 : 0;
- X for (j = 0; j < BOARD_SIZE; j++) {
- X if (move->board[i][j].type == move->side &&
- X move->board[i][j].count != 0) {
- X *winning_side = move->side;
- X return True;
- X }
- X }
- X return False;
- X}
- X
- X
- Xstatic void BeepMessage(side, text)
- XFieldType side;
- Xchar *text;
- X{
- X PerDisplay *me = &dd.pd[side];
- X
- X XtVaSetValues(me->message, XtNlabel, (XtArgVal) text, NULL);
- X XBell(me->d, 0);
- X if (me->messTimeOut != NULL) {
- X XtRemoveTimeOut(me->messTimeOut);
- X }
- X me->messTimeOut =
- X XtAppAddTimeOut(app_context, app_res.message_time_out,
- X RestoreMessage, (XtPointer) side);
- X}
- X
- X
- Xstatic void SetRulesHint(side, text)
- XFieldType side;
- Xchar *text;
- X{
- X PerDisplay *me = &dd.pd[side];
- X
- X me->rulesHint = text;
- X XtVaSetValues(me->message, XtNlabel, (XtArgVal) text, NULL);
- X if (me->messTimeOut != NULL) {
- X XtRemoveTimeOut(me->messTimeOut);
- X }
- X}
- X
- X
- X/*ARGSUSED*/
- Xstatic void RestoreMessage(client_data, id)
- XXtPointer client_data;
- XXtIntervalId *id;
- X{
- X FieldType side = (FieldType) client_data;
- X PerDisplay *me = &dd.pd[side];
- X
- X XtVaSetValues(me->message, XtNlabel, (XtArgVal) me->rulesHint, NULL);
- X me->messTimeOut = NULL;
- X}
- END_OF_FILE
- if test 29241 -ne `wc -c <'malawi.c'`; then
- echo shar: \"'malawi.c'\" unpacked with wrong size!
- fi
- # end of 'malawi.c'
- fi
- if test -f 'patchlevel.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'patchlevel.h'\"
- else
- echo shar: Extracting \"'patchlevel.h'\" \(23 characters\)
- sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
- X#define VERSION "0.1"
- END_OF_FILE
- if test 23 -ne `wc -c <'patchlevel.h'`; then
- echo shar: \"'patchlevel.h'\" unpacked with wrong size!
- fi
- # end of 'patchlevel.h'
- fi
- echo shar: End of archive 1 \(of 1\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have the archive.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-