[comp.sources.x] v09i021: xmahjongg, Part01/05

jsy@poplar.cray.com (Jeff Young) (09/12/90)

Submitted-by: jsy@poplar.cray.com (Jeff Young)
Posting-number: Volume 9, Issue 21
Archive-name: xmahjongg/part01

	Here is the first of 5 shar files for an updated xmahjongg.  It is
almost totally rewritten, so that I am just submitting sources instead of
patches.

Jeff Young
jsy@cray.com


#! /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
# If this archive is complete, you will see the following message at the end:
#		"End of archive 1 (of 5)."
#
# Contents:
#   draw.c event.c initial.c packet.c play.c random.c sysdep.c
#   variables.c xmahjongg.c
#
# Wrapped by jsy@cray.com on Sun Sep  9 12:43:56 1990
#
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f draw.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"draw.c\"
else
echo shar: Extracting \"draw.c\" \(7171 characters\)
sed "s/^X//" >draw.c <<'END_OF_draw.c'
X/*
X ******************************************************************************
X *									      *
X *	Copyright (c) 1990 by Jeff S. Young.  All rights reserved under the   *
X *	copyright laws of the United States.			      	      *
X *									      *
X ******************************************************************************
X */
X
X#include <stdio.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <sys/time.h>
X#include "xmahjongg.h"
X#include "variables.h"
X
X#define	DRAW_NAME(pp) {							\
X	int xpos = X_NAMES;						\
X									\
X	sprintf((char *)buffer, "%8.8s", pp->name);			\
X	draw_string((char *)buffer, xpos, pp->y, XGameTextGC[0]);	\
X}
X
X#define	DRAW_BOARD(pp, pos) {						\
X	int xpos = X_BOARD+50*pos;					\
X									\
X	sprintf((char *)buffer, "%5.5d", pp->board[pos]);		\
X	draw_string((char *)buffer, xpos, Y_BOARD, XGameTextGC[0]);	\
X}
X
X#define DRAW_SCORE(pp, pos) {						\
X	int itmp;							\
X	int xpos = pp->x+50*pos;					\
X	int score = pp->tiles[pos];					\
X									\
X	if (score < 0) score *= -1;					\
X	itmp = (pp->tiles[pos] > 0) ? 0 : 1;				\
X	sprintf((char *)buffer, " %3.3d ", score);			\
X	draw_string((char *)buffer, xpos, pp->y, XGameTextGC[itmp]);	\
X}
X
X#define DRAW_TOTAL(pp, pos) {						\
X	int itmp;							\
X	int xpos = X_BOARD+50*pos;					\
X									\
X	sprintf((char *)buffer, "TOTAL");				\
X	draw_string((char *)buffer, xpos, Y_BOARD, XGameTextGC[0]);	\
X	xpos = pp->x + 50*pos;						\
X	itmp = (pp->quit == 0) ? 0 : 1;					\
X	sprintf((char *)buffer, " %3.3d ", pp->total);			\
X	draw_string((char *)buffer, xpos, pp->y, XGameTextGC[itmp]);	\
X}
X
Xchar	copy[]   = "(c) 1990 by Jeff Young. ";
Xchar	rights[] = "All rights reserved.    ";
X
Xdraw_user(pp, type)
XPlayer *pp;
Xint type;
X{
X	int i;
X	char buffer[20];
X	GC userGC;
X
X	if (type == GAME_START) {
X		DRAW_NAME(pp);
X
X		for (i = 0; i < MAX_BOARDS; i++) {
X			if (pp->tiles[i] > TILES) break;
X			DRAW_BOARD(pp, i);
X			DRAW_SCORE(pp, i);
X		};
X
X		DRAW_TOTAL(pp, num_games);
X	} else if (type == GAME_PLAY) {
X		DRAW_BOARD(pp, pp->done);
X		DRAW_SCORE(pp, pp->done);
X		DRAW_TOTAL(pp, num_games);
X	} else if (type == GAME_DONE) {
X		DRAW_BOARD(pp, pp->done);
X		DRAW_SCORE(pp, pp->done);
X	} else if (type == GAME_QUIT) {
X		DRAW_BOARD(pp, pp->done);
X		DRAW_SCORE(pp, pp->done);
X		DRAW_TOTAL(pp, num_games);
X	} else {
X		fprintf(stderr, "bad draw_user type (%d)\n", type);
X		exit(1);
X	};
X
X	return(0);
X}
X
Xdraw_data()
X{
X	int i, j, x, y;
X	char string[2];
X
X/*
X *	Display the tiles on the screen before the start of the game.  Order:
X *	dragons, seasons, plants, directions, circles, bamboos, ideographs.
X *	The 'if' statement below is just a way to figure out the x and y 
X *	coordinates of the tiles.
X *
X */
X	for (i = 10; i <= 51; i++) {
X		if ((10 <= i) && (i <= 12)) {
X			j = 6;
X			x = 2*(i%9);
X			y = 198;
X		} else if ((13 <= i) && (i <= 16)) {
X			j = 5;
X			x = (2*i + 7)%8;
X			y = 278 + 80*((i-13)/4);
X		} else if ((17 <= i) && (i <= 20)) {
X			j = 4;
X			x = (2*i + 7)%8;
X			y = 278 + 80*((i-13)/4);
X		} else if ((21 <= i) && (i <= 24)) {
X			j = 3;
X			x = (2*i + 7)%8;
X			y = 278 + 80*((i-13)/4);
X		} else if ((25 <= i) && (i <= 33)) {
X			j = 1;
X			x = (i+2)%9;
X			y = 278 + 80*((i+2)/9);
X		} else if ((34 <= i) && (i <= 42)) {
X			j = 0;
X			x = (i+2)%9;
X			y = 278 + 80*((i+2)/9);
X		} else if ((43 <= i) && (i <= 51)) {
X			j = 2;
X			x = (i+2)%9;
X			y = 278 + 80*((i+2)/9);
X		};
X
X		x = 42 + 106*x;
X		string[0] = tile_data[i];
X		XDrawImageString(XGameDisplay, XGameWindow,
X			XGameTileGC[j][0], x, y, string, 1);
X	};
X
X	return(0);
X}
X
Xdraw_tiles()
X{
X	int i, j, k;
X	char string[2];
X	Tile *tp;
X
X	XClearWindow(XGameDisplay, XGamePlayWindow);
X
X	XCopyArea(XGameDisplay, XGamePlayWindow, XGamePixmap, XGameTextGC[0],
X		0, 0, PLAY_WIDTH, PLAY_HEIGHT, 0, 0);
X
X	for (i = 0, tp = order[0]; i < TILES; i++, tp = order[i]) {
X		if (tp == NULL) break;
X		if (tp->state != USED) continue;
X		string[0] = tp->data;
X		j = (tp != tile1p) ? 0 : 1;
X		k = (color_type == 0) ? tp->lev : (tp->data/16) - 1;
X		XDrawImageString(XGameDisplay, XGamePixmap,
X			XGameTileGC[k][j], tp->x, tp->y, string, 1);
X
X		draw_border(tp->x, tp->y);
X	};
X
X	XCopyArea(XGameDisplay, XGamePixmap, XGamePlayWindow, XGameTextGC[0],
X		0, 0, PLAY_WIDTH, PLAY_HEIGHT, 0, 0);
X
X	XFlush(XGameDisplay);
X
X	return(0);
X}
X
Xdraw_count()
X{
X	char string[4];
X	int count = (done_count != 0) ? done_count : tiles_remaining;
X
X	string[0] = count/100;
X	string[1] = (count/10)%10;
X	string[2] = count%10;
X
X	XDrawImageString(XGameDisplay, XGameCountWindow, XGameOtherGC[0],
X		0, 0, string, 3);
X
X	XFlush(XGameDisplay);
X
X	return(0);
X}
X
Xdraw_border(x, y)
Xint	x;
Xint	y;
X{
X	int i;
X
X	for (i = 0; i < 12; i++) {
X		XGamePoint[i].x += x;
X		XGamePoint[i].y += y;
X	};
X
X	XDrawLines(XGameDisplay, XGamePixmap, XGameBorderGC, XGamePoint,
X		12, CoordModeOrigin);
X
X	for (i = 0; i < 12; i++) {
X		XGamePoint[i].x -= x;
X		XGamePoint[i].y -= y;
X	};
X
X	return(0);
X}
X
Xdraw_letter(index, x, y)
Xint	index;
Xint	x;
Xint	y;
X{
X	char string[2];
X
X	string[0] = index;
X	string[1] = index+16;
X
X	XDrawImageString(XGameDisplay, XGameWindow, XGameOtherGC[0],
X		x, y+00, &string[0], 1);
X	XDrawImageString(XGameDisplay, XGameWindow, XGameOtherGC[0],
X		x, y+64, &string[1], 1);
X
X	XFlush(XGameDisplay);
X
X	return(0);
X}
X
Xdraw_window()
X{
X	int i, k, x, y;
X	char string[64];
X
X	k = XGameTextFont->ascent + XGameTextFont->descent + 1;
X	x = 55;
X	y = (Y_COUNT-4*k)/2;
X
X/*
X *	Print out the strings in the upper window
X */
X	XClearWindow(XGameDisplay, XGameWindow);
X
X	sprintf(string, "Board number: %5d", seed);
X	draw_string(copy,   x, y+0*k, XGameTextGC[1]);
X	draw_string(rights, x, y+1*k, XGameTextGC[1]);
X	draw_string(string, x, y+3*k, XGameTextGC[1]);
X
X	draw_matches();
X
X/*
X *	If in tournament mode, then reprint the current scores
X */
X	if (tourn_flag != 0) {
X		for (i = 0, pp = player; i < num_players; i++, pp++) {
X			pp->y = Y_SCORE+i*k;
X			draw_user(pp, GAME_START);
X		};
X	};
X
X	XFlush(XGameDisplay);
X
X	return(0);
X}
X
Xdraw_option(index, window)
Xint	index;
XWindow	window;
X{
X	int i;
X	char string[2];
X
X
X	string[0] = index;
X	i = ((window == XGameDoneWindow) && (done_count != 0)) ? 1 : 0;
X	XDrawImageString(XGameDisplay, window, XGameOtherGC[i],
X		0, 0, string, 1);
X	XFlush(XGameDisplay);
X
X	return(0);
X}
X
Xdraw_string(data, x, y, imageGC)
Xchar *data;
Xint x, y;
XGC imageGC;
X{
X
X	XDrawImageString(XGameDisplay, XGameWindow, imageGC,
X		x, y, data, strlen(data));
X
X	XFlush(XGameDisplay);
X
X	return(0);
X}
X
Xdraw_matches() {
X	int i, j, k;
X	int matches = 0;
X	char string[80];
X	Tile *t1p, *t2p;
X
X	if (done_count == 0) return(0);
X
X/*
X *	Count the number of matches remaining.
X */
X	for(i = 0, t1p = &tiles[0][0][0]; i < ROWS*COLS*LEVS-1; i++, t1p++) {
X		if (t1p->state != USED) continue;
X		if (not_free(t1p->row, t1p->col, t1p->lev)) continue;
X
X		for(j = i+1, t2p = t1p+1; j < ROWS*COLS*LEVS; j++, t2p++) {
X			if (t2p->state != USED) continue;
X			if (not_free(t2p->row, t2p->col, t2p->lev)) continue;
X			if (t1p->type == t2p->type) matches++;
X		};
X	};
X
X/*
X *	Display the number of matches.
X */
X	i = XGameTextFont->ascent;
X	j = XGameTextFont->descent;
X	k = (184-Y_DONE-OPTION_HEIGHT-i-j)/2;
X	sprintf(string, " Matches remaining = %3d ", matches);
X	draw_string(string, 800, Y_DONE+OPTION_HEIGHT+k+i, XGameTextGC[1]);
X	XFlush(XGameDisplay);
X
X	return(0);
X}
END_OF_draw.c
if test 7171 -ne `wc -c <draw.c`; then
    echo shar: \"draw.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f event.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"event.c\"
else
echo shar: Extracting \"event.c\" \(8545 characters\)
sed "s/^X//" >event.c <<'END_OF_event.c'
X/*
X ******************************************************************************
X *									      *
X *	Copyright (c) 1990 by Jeff S. Young.  All rights reserved under the   *
X *	copyright laws of the United States.			      	      *
X *									      *
X ******************************************************************************
X */
X
X#include <stdio.h>
X#include <signal.h>
X#include <sys/time.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include "xmahjongg.h"
X#include "variables.h"
X
Xevent_process() {
X	int readfds;
X
X/*
X *	Wait for an event and then process it.
X */
X	event_wait();
X
Xnext_event:
X	XNextEvent(XGameDisplay, &XGameEvent);
X	switch (XGameEvent.type) {
X		case Expose:
X			if (XGameEvent.xexpose.count != 0) goto next_event;
X			event_expose();
X			break;
X		case ButtonPress:
X			event_button();
X			break;
X		default:
X			break;
X	};
X
X	return(0);
X}
X
Xevent_packet(readfds)
Xint readfds;
X{
X	int i;
X
X	for (i = 0, pp = player; i < num_players; i++, pp++) {
X		if (pp->type == 'M') continue;
X		if ((readfds & (1 << pp->fd)) != 0) {
X			packet_recv(pp->fd);
X		};
X	};
X
X	return(0);
X}
X
Xevent_expose() {
X
X	if (XGameEvent.xexpose.window == XGameWindow) {
X		draw_window();
X	} else if (XGameEvent.xexpose.window == XGameNewWindow) {
X		draw_option(INDEX_NEW, XGameNewWindow);
X	} else if (XGameEvent.xexpose.window == XGameDoneWindow) {
X		draw_option(INDEX_DONE, XGameDoneWindow);
X	} else if (XGameEvent.xexpose.window == XGameQuitWindow) {
X		draw_option(INDEX_QUIT, XGameQuitWindow);
X	} else if (XGameEvent.xexpose.window == XGameSameWindow) {
X		draw_option(INDEX_SAME, XGameSameWindow);
X	} else if (XGameEvent.xexpose.window == XGamePlayWindow) {
X		draw_tiles();
X	} else if (XGameEvent.xexpose.window == XGameCountWindow) {
X		draw_count();
X	};
X
X	return(0);
X}
X
Xevent_button() {
X	int i, j, k;
X
X	if (XGameEvent.xbutton.window == XGameNewWindow) {
X		event_new();
X	} else if (XGameEvent.xbutton.window == XGameDoneWindow) {
X		event_done();
X	} else if (XGameEvent.xbutton.window == XGameSameWindow) {
X		event_same();
X	} else if (XGameEvent.xbutton.window == XGameQuitWindow) {
X		event_quit();
X	} else if (XGameEvent.xbutton.window == XGamePlayWindow) {
X		event_play();
X	};
X
X	return(0);
X}
X
Xevent_new() {
X	int i, j, k;
X
X/*
X *	If this is a tournament, the the user can't go to a new board
X *	unless this is not the last game in the series.
X */
X	if ((tourn_flag != 0) && (mypp->done == num_games-1)) {
X		XBell(XGameDisplay, 100);
X		XFlush(XGameDisplay);
X		return(0);
X	};
X
X/*
X *	If this is setup mode, then clear all of the tiles.
X */
X	if (setup_flag != 0) {
X		for (i = 0; i < TILES; i++) {
X			order[i] = NULL;
X		};
X
X		for (i = 0; i < ROWS; i++) {
X			for (j = 0; j < COLS; j++) {
X				for (k = 0; k < LEVS; k++) {
X					tiles[i][j][k].state = FREE;
X				};
X			};
X		};
X	};
X
X/*
X *	Clear all the windows.
X */
X	keep_playing = 0;
X	packet_send(GAME_DONE);
X	XClearArea(XGameDisplay, XGameWindow, 0, 0, 0, 0, True);
X	XClearArea(XGameDisplay, XGameNewWindow, 0, 0, 0, 0, True);
X	XClearArea(XGameDisplay, XGameDoneWindow, 0, 0, 0, 0, True);
X	XClearArea(XGameDisplay, XGameSameWindow, 0, 0, 0, 0, True);
X	XClearArea(XGameDisplay, XGameQuitWindow, 0, 0, 0, 0, True);
X	XClearArea(XGameDisplay, XGamePlayWindow, 0, 0, 0, 0, True);
X	XClearArea(XGameDisplay, XGameCountWindow, 0, 0, 0, 0, True);
X	XFlush(XGameDisplay);
X
X	return(0);
X}
X
Xevent_same() {
X
X/*
X *	If this is a tournament, then the user can't play the same board
X *	twice.  If this is setup mode, then do nothing;
X */
X	if ((num_games != 0) || (setup_flag != 0)) {
X		XBell(XGameDisplay, 100);
X		XFlush(XGameDisplay);
X	} else {
X		seed = -seed;
X		keep_playing = 0;
X		XClearArea(XGameDisplay, XGameWindow, 0, 0, 0, 0, True);
X		XClearArea(XGameDisplay, XGameNewWindow, 0, 0, 0, 0, True);
X		XClearArea(XGameDisplay, XGameDoneWindow, 0, 0, 0, 0, True);
X		XClearArea(XGameDisplay, XGameSameWindow, 0, 0, 0, 0, True);
X		XClearArea(XGameDisplay, XGameQuitWindow, 0, 0, 0, 0, True);
X		XClearArea(XGameDisplay, XGamePlayWindow, 0, 0, 0, 0, True);
X		XClearArea(XGameDisplay, XGameCountWindow, 0, 0, 0, 0, True);
X		XFlush(XGameDisplay);
X	};
X
X	return(0);
X}
X
Xevent_done() {
X	int i;
X	FILE *stdconf;
X
X/*
X *	If this is not setup mode, then mark the game as done and display
X *	the matches remaining.
X */
X	if (setup_flag == 0) {
X		if (done_count == 0) {
X			done_count = tiles_remaining;
X			packet_send(GAME_DONE);
X		};
X
X		draw_option(INDEX_DONE, XGameDoneWindow);
X		draw_matches();
X		return(0);
X	};
X
X/*
X *	For setup mode, we must check to be sure that all the tiles have
X *	been placed.  If they have, then write out the configuration file.
X */
X	if (tiles_remaining != 0) {
X		XBell(XGameDisplay, 100);
X		XFlush(XGameDisplay);
X		return(0);
X	};
X
X/*
X *	Open the configuration file.
X */
X	if (layout != NULL) {
X		if ((stdconf = fopen(layout, "w")) == NULL) {
X			fprintf(stderr, "can't open layout file\n");
X			exit(1);
X		};
X	} else {
X		stdconf = stdout;
X	};
X
X/*
X *	Dump out the configuration.
X */
X	for (i = 0; i < TILES; i++) {
X		fprintf(stdconf, "%3d  %3d  %3d\n",
X		order[i]->row, order[i]->col, order[i]->lev);
X	};
X
X	fclose(stdconf);
X	event_quit();
X
X	return(0);
X}
X
Xevent_quit() {
X	int i;
X
X	packet_send(GAME_QUIT);
X
X/*
X *	Free all of the X resources which we grabbed.
X */
X	XUnloadFont(XGameDisplay, XGameTextFont->fid);
X	XUnloadFont(XGameDisplay, XGameTileFont->fid);
X
X	XFreeGC(XGameDisplay, XGameBorderGC);
X	XFreeGC(XGameDisplay, XGameTextGC[0]);
X	XFreeGC(XGameDisplay, XGameTextGC[1]);
X	XFreeGC(XGameDisplay, XGameOtherGC[0]);
X	XFreeGC(XGameDisplay, XGameOtherGC[1]);
X
X	for (i = 0; i < LEVS; i++) {
X		XFreeGC(XGameDisplay, XGameTileGC[i][0]);
X		XFreeGC(XGameDisplay, XGameTileGC[i][1]);
X	};
X
X	XFreeCursor(XGameDisplay, XGameCursor);
X	XFreePixmap(XGameDisplay, XGamePixmap);
X
X	XCloseDisplay(XGameDisplay);
X
X	exit(0);
X}
X
Xevent_play() {
X	int i, j, k;
X	int x, y;
X
X	x_coor = XGameEvent.xbutton.x;
X	y_coor = XGameEvent.xbutton.y;
X
X/*
X *	If we are in setup mode, then call the routine which will create a 
X *	new tile or delete one from the board.
X */
X	if (setup_flag != 0) {
X		if (XGameEvent.xbutton.button == Button1) {
X			event_create();
X		} else {
X			event_delete();
X		};
X
X		return(0);
X	};
X
X/*
X *	We are in play mode.  Check the make sure the button was pushed on a 
X *	tile.
X */
X	for (k = LEVS-1; k >= 0; k--) {
X		x = (y_coor - Y_TILE + (4*k))/(TILE_SIDE/2);
X		y = (x_coor - X_TILE - (4*k))/(TILE_SIDE/2);
X
X		for (i = 0; i < 2; i++) {
X			for (j = 0; j < 2; j++) {
X				if (in_bounds(x-i, y-j)) {
X					if (tiles[x-i][y-j][k].state == USED) {
X						play_tile(&tiles[x-i][y-j][k]);
X						return(0);
X					};
X				};
X			};
X		};
X	};
X
X/*
X *	The button was pushed in a bad area.  We beep the bell and continue.
X */
X	XBell(XGameDisplay, 100);
X	XFlush(XGameDisplay);
X
X	return(0);
X}
X
Xevent_create() {
X	int i, j, k;
X	int x, y;
X
X	if (tiles_remaining == 0) {
X		XBell(XGameDisplay, 100);
X		XFlush(XGameDisplay);
X		return(0);
X	} else if (x_coor < X_TILE) {
X		XBell(XGameDisplay, 100);
X		XFlush(XGameDisplay);
X		return(0);
X	} else if (y_coor < Y_TILE) {
X		XBell(XGameDisplay, 100);
X		XFlush(XGameDisplay);
X		return(0);
X	};
X
X/*
X *	Check the make sure the button was pushed on a tile.
X */
X	for (k = 0; k < LEVS; k++) {
X		x = (y_coor - Y_TILE + (4*k))/(TILE_SIDE/2);
X		y = (x_coor - X_TILE - (4*k))/(TILE_SIDE/2);
X
X		for (i = 0; i < 2; i++) {
X			for (j = 0; j < 2; j++) {
X				if (in_bounds(x-i, y-j) == 0) continue;
X				if (ok_below(x-i, y-j, k) != 0) continue;
X				if (tiles[x-i][y-j][k].state == USED) continue;
X				create_tile(&tiles[x-i][y-j][k]);
X				return(0);
X			};
X		};
X	};
X
X/*
X *	The button was pushed in a bad area.  We beep the bell and continue.
X */
X	XBell(XGameDisplay, 100);
X	XFlush(XGameDisplay);
X
X	return(0);
X}
X
Xevent_delete() {
X	int i, j, k;
X	int x, y;
X
X	if (tiles_remaining == TILES) {
X		XBell(XGameDisplay, 100);
X		XFlush(XGameDisplay);
X		return(0);
X	} else if (x_coor < X_TILE) {
X		XBell(XGameDisplay, 100);
X		XFlush(XGameDisplay);
X		return(0);
X	} else if (y_coor < Y_TILE) {
X		XBell(XGameDisplay, 100);
X		XFlush(XGameDisplay);
X		return(0);
X	};
X
X/*
X *	Check the make sure the button was pushed on a tile.
X */
X	for (k = LEVS-1; k >= 0; k--) {
X		x = (y_coor - Y_TILE + (4*k))/(TILE_SIDE/2);
X		y = (x_coor - X_TILE - (4*k))/(TILE_SIDE/2);
X
X		for (i = 0; i < 2; i++) {
X			for (j = 0; j < 2; j++) {
X				if (in_bounds(x-i, y-j) == 0) continue;
X				if (ok_above(x-i, y-j, k) != 0) continue;
X				if (tiles[x-i][y-j][k].state == FREE) continue;
X				delete_tile(&tiles[x-i][y-j][k]);
X				return(0);
X			};
X		};
X	};
X
X/*
X *	The button was pushed in a bad area.  We beep the bell and continue.
X */
X	XBell(XGameDisplay, 100);
X	XFlush(XGameDisplay);
X
X	return(0);
X}
END_OF_event.c
if test 8545 -ne `wc -c <event.c`; then
    echo shar: \"event.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f initial.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"initial.c\"
else
echo shar: Extracting \"initial.c\" \(19579 characters\)
sed "s/^X//" >initial.c <<'END_OF_initial.c'
X/*
X ******************************************************************************
X *									      *
X *	Copyright (c) 1990 by Jeff S. Young.  All rights reserved under the   *
X *	copyright laws of the United States.			      	      *
X *									      *
X ******************************************************************************
X */
X
X#include <netdb.h>
X#include <stdio.h>
X#include <signal.h>
X#include <sys/time.h>
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/cursorfont.h>
X#include "xmahjongg.h"
X#include "variables.h"
X#include "icon.h"
X
Xint	initial_flag = 0;
Xchar copyright[] = " Copyright (c) 1990 by Jeff Young (exceptions).  All rights reserved. ";
X
Xinitialize() {
X
X	initialize_conf();
X	initialize_data();
X	initialize_pool();
X	initialize_tiles();
X	initialize_socket();
X	initialize_window();
X
X	return(0);
X}
X
Xinitialize_conf() {
X	int i, j, k;
X	int cnt, row, col, lev;
X	char line[128], file[128];
X	FILE *stdconf;
X
X	if (initial_flag != 0) return(0);
X	if (setup_flag != 0) return(0);
X
X/*
X *	Set all tiles to FREE before reading in the configuration.
X */
X	for (i = 0; i < ROWS; i++) {
X		for (j = 0; j < COLS; j++) {
X			for (k = 0; k < LEVS; k++) {
X				tiles[i][j][k].init = FREE;
X				tiles[i][j][k].state = FREE;
X			};
X		};
X	};
X
X/*
X *	Open the file containing the specified layout.
X */
X	cnt = 0;
X	if (layout == NULL) {
X		sprintf(file, "%s/default", LAYOUT);
X	} else if ((layout[0] != '/') && (layout[0] != '.')) {
X		sprintf(file, "%s/%s", LAYOUT, layout);
X	} else {
X		strcpy(file, layout);
X	};
X
X	if ((stdconf = fopen(file, "r")) == NULL) {
X		fprintf(stderr, "can't open layout file \n");
X		exit(1);
X	};
X
X/*
X *	Read in the row, col, lev lines
X */
X	while (fgets(line, 127, stdconf) != NULL) {
X		if (line[0] == '#') continue;
X
X		sscanf(line, "%d %d %d", &row, &col, &lev);
X		tiles[row][col][lev].init = USED;
X		tiles[row][col][lev].state = USED;
X		order[cnt++] = &tiles[row][col][lev];
X	};
X
X	fclose(stdconf);
X
X/*
X *	Do a rudimentary check on the number of tiles read
X */
X	if (cnt != TILES) {
X		fprintf(stderr, "invalid layout file (%d)\n", cnt);
X		exit(1);
X	};
X
X	return(0);
X}
X
Xinitialize_data() {
X	int i, j, k, l;
X	int dx, dy, dz;
X	Tile *tp, *temp;
X
X	done_count = 0;
X	tiles_remaining = TILES;
X	if (initial_flag != 0) return(0);
X
X/*
X *	Initialize the bitmap pointers for shuffling into the pool.
X */
X	tile_data[ 0] = INDEX_NUMBER + 0;
X	tile_data[ 1] = INDEX_NUMBER + 1;
X	tile_data[ 2] = INDEX_NUMBER + 2;
X	tile_data[ 3] = INDEX_NUMBER + 3;
X	tile_data[ 4] = INDEX_NUMBER + 4;
X	tile_data[ 5] = INDEX_NUMBER + 5;
X	tile_data[ 6] = INDEX_NUMBER + 6;
X	tile_data[ 7] = INDEX_NUMBER + 7;
X	tile_data[ 8] = INDEX_NUMBER + 8;
X	tile_data[ 9] = INDEX_NUMBER + 9;
X	tile_data[10] = INDEX_DRAGON + 0;
X	tile_data[11] = INDEX_DRAGON + 1;
X	tile_data[12] = INDEX_DRAGON + 2;
X	tile_data[13] = INDEX_SEASON + 0;
X	tile_data[14] = INDEX_SEASON + 1;
X	tile_data[15] = INDEX_SEASON + 2;
X	tile_data[16] = INDEX_SEASON + 3;
X	tile_data[17] = INDEX_PLANT + 0;
X	tile_data[18] = INDEX_PLANT + 1;
X	tile_data[19] = INDEX_PLANT + 2;
X	tile_data[20] = INDEX_PLANT + 3;
X	tile_data[21] = INDEX_DIRECTION + 0;
X	tile_data[22] = INDEX_DIRECTION + 1;
X	tile_data[23] = INDEX_DIRECTION + 2;
X	tile_data[24] = INDEX_DIRECTION + 3;
X	tile_data[25] = INDEX_CIRCLE + 0;
X	tile_data[26] = INDEX_CIRCLE + 1;
X	tile_data[27] = INDEX_CIRCLE + 2;
X	tile_data[28] = INDEX_CIRCLE + 3;
X	tile_data[29] = INDEX_CIRCLE + 4;
X	tile_data[30] = INDEX_CIRCLE + 5;
X	tile_data[31] = INDEX_CIRCLE + 6;
X	tile_data[32] = INDEX_CIRCLE + 7;
X	tile_data[33] = INDEX_CIRCLE + 8;
X	tile_data[34] = INDEX_BAMBOO + 0;
X	tile_data[35] = INDEX_BAMBOO + 1;
X	tile_data[36] = INDEX_BAMBOO + 2;
X	tile_data[37] = INDEX_BAMBOO + 3;
X	tile_data[38] = INDEX_BAMBOO + 4;
X	tile_data[39] = INDEX_BAMBOO + 5;
X	tile_data[40] = INDEX_BAMBOO + 6;
X	tile_data[41] = INDEX_BAMBOO + 7;
X	tile_data[42] = INDEX_BAMBOO + 8;
X	tile_data[43] = INDEX_IDEOGRAPH + 0;
X	tile_data[44] = INDEX_IDEOGRAPH + 1;
X	tile_data[45] = INDEX_IDEOGRAPH + 2;
X	tile_data[46] = INDEX_IDEOGRAPH + 3;
X	tile_data[47] = INDEX_IDEOGRAPH + 4;
X	tile_data[48] = INDEX_IDEOGRAPH + 5;
X	tile_data[49] = INDEX_IDEOGRAPH + 6;
X	tile_data[50] = INDEX_IDEOGRAPH + 7;
X	tile_data[51] = INDEX_IDEOGRAPH + 8;
X
X/*
X *	Initialize the coordinates for all the tiles.
X */
X	l = TILE_SIDE/2;
X	for (i = 0; i < ROWS; i++) {
X		for (j = 0; j < COLS; j++) {
X			for (k = 0; k < LEVS; k++) {
X				tiles[i][j][k].row = i;
X				tiles[i][j][k].col = j;
X				tiles[i][j][k].lev = k;
X				tiles[i][j][k].x = X_TILE+(j*l)+(4*k);
X				tiles[i][j][k].y = Y_TILE+(i*l)-(4*k);
X				if (setup_flag != 0) {
X					tiles[i][j][k].state = FREE;
X				};
X			};
X		};
X	};
X
X/*
X *	Put the randomized images into the tiles and sort them according
X *	to the drawing order.
X */
X	if (setup_flag == 0) {
X		for (i = 0; i < TILES-1; i++) {
X			for (j = i+1; j < TILES; j++) {
X				dx = order[i]->row - order[j]->row;
X				dy = order[i]->col - order[j]->col;
X				dz = order[i]->lev - order[j]->lev;
X
X				if (dz < 0) continue;
X
X				if (dz > 0) {
X					temp = order[i];
X					order[i] = order[j];
X					order[j] = temp;
X				} else if (dy < dx) {
X					temp = order[i];
X					order[i] = order[j];
X					order[j] = temp;
X				} else if ((dy == dx) && (dy > 0)) {
X					temp = order[i];
X					order[i] = order[j];
X					order[j] = temp;
X				};
X			};
X
X			order[i]->value = i;
X		};
X
X		order[TILES-1]->value = TILES-1;
X	};
X
X	return(0);
X}
X
Xinitialize_pool() {
X	int i, j, k;
X	int seed1, seed2;
X	long save;
X
X	if (setup_flag != 0) return(0);
X
X/*
X *	Set up the randomness for the game
X */
X	get_seed();
X	random_init(seed);
X
X/*
X *	Place the circle, bamboo, and ideograph tiles in the pool
X */
X	for (j = 0, k = 0; j < 4; j++) {
X		for (i = 21; i <= 51; i++) {
X			buffer[k++] = i;
X		};
X	};
X
X/*
X *	Place the dragon tiles in the pool
X */
X	for (j = 0; j < 4; j++) {
X		for (i = 10; i <= 12; i++) {
X			buffer[k++] = i;
X		};
X	};
X
X/*
X *	Place the season and plant tiles in the pool
X */
X	for (i = 13; i <= 20; i++) {
X		buffer[k++] = i;
X	};
X
X/* 
X *	Shuffle the pool of tiles
X */
X	for (i = 0; i < 16384; i++) {
X		seed1 = (random_next() & 0xfffffff)%TILES;
X		seed2 = (random_next() & 0xfffffff)%TILES;
X		save = buffer[seed1];
X		buffer[seed1] = buffer[seed2];
X		buffer[seed2] = save;
X	};
X
X	return(0);
X}
X
Xinitialize_tiles() {
X	int i;
X	int s1_tile = tile_data[13];
X	int s2_tile = tile_data[16];
X	int p1_tile = tile_data[17];
X	int p2_tile = tile_data[20];
X	Tile *tp;
X
X	if (setup_flag != 0) return(0);
X
X/*
X *	Put the randomized images into the tiles and sort them according
X *	to the drawing order.
X */
X	for (i = 0, tp = order[0]; i < TILES; i++, tp = order[i]) {
X		tp->state = tp->init;
X		tp->data = tile_data[get_tile()];
X		if ((s1_tile <= tp->data) && (tp->data <= s2_tile)) {
X			tp->type = s1_tile;
X		} else if ((p1_tile <= tp->data) && (tp->data <= p2_tile)) {
X			tp->type = p1_tile;
X		} else {
X			tp->type = tp->data;
X		};
X
X	};
X
X/*
X *	Set the tile pointers to NULL for starters.
X */
X	tile1p = NULL;
X	tile2p = NULL;
X
X	return(0);
X}
X
Xinitialize_socket() {
X	int i, s;
X	int sizeon;
X	int namelen;
X	int on = 1;
X	struct sockaddr_in name;
X	struct hostent *hp, *gethostbyname();
X
X	if (setup_flag != 0) return(0);
X	if (tourn_flag != 1) return(0);
X	printf("attempting connections\n");
X
X/*
X *	Attempt connects
X */
X	i = 0;
X	for (pp = &player[num_players-1]; pp >= player; pp--, i++) {
X		if (pp->type != 'C') continue;
X
X		namelen = sizeof(name);
X		name.sin_family = AF_INET;
X		name.sin_port = htons(pp->port);
X		hp = gethostbyname(pp->machine);
X		bcopy(hp->h_addr, (char *)&name.sin_addr, hp->h_length);
X
X		while (1) {
X			if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
X				sleep(1);
X			} else if (connect(s, (char *)&name, namelen) < 0) {
X				close(s);
X				sleep(1);
X			} else {
X				pp->fd = s;
X				break;
X			};
X		};
X	};
X
X/*
X *	Attempt accepts
X */
X	name.sin_family = AF_INET;
X	name.sin_port = htons(mypp->port);
X	name.sin_addr.s_addr = 0;
X	namelen = sizeof(name);
X	sizeon = sizeof(on);
X
X	if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
X		perror("can't open socket");
X		exit(1);
X	} else if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeon) < 0) {
X		perror("can't reset socket");
X		exit(1);
X	} else if (bind(s, (char *)&name, namelen) < 0) {
X		perror("can't bind socket");
X		exit(1);
X	} else if (listen(s, 5) < 0) {
X		perror("can't listen socket");
X		exit(1);
X	};
X
X	for (i = 0, pp = player; i < num_players; i++, pp++) {
X		if (pp->type != 'A') continue;
X		namelen = sizeof(name);
X
X		if ((pp->fd = accept(s, (char *)&name, &namelen)) < 0) {
X			sleep(1);
X		};
X	};
X
X	for (i = 0, pp = player; i < num_players; i++, pp++) {
X		if (pp->type != 'M') playfds |= (1 << pp->fd);
X	};
X
X	tourn_flag = 2;
X	printf("connections established\n");
X
X	return(0);
X}
X
Xinitialize_window() {
X	int color[9];
X	int i, j, k, x, y;
X	int init_x, init_y;
X	int other_fore_color;
X	int other_back_color;
X	int window_fore_color;
X	int window_back_color;
X	int border_fore_color;
X	int border_back_color;
X	XWMHints XGameWMHints;
X
X/*
X *	Only initialize the window if the initial_flag is zero
X */
X	if (initial_flag != 0) return(0);
X
X/*
X *	Open up the display.
X */
X	if ((XGameDisplay = XOpenDisplay(display_name)) == NULL) {
X		fprintf(stderr, "can't connect to display\n");
X		exit(1);
X	};
X
X/*
X *	Set some default variables from the server.
X */
X	XGameScreen = DefaultScreen(XGameDisplay);
X	XGameColormap = DefaultColormap(XGameDisplay, XGameScreen);
X	XGameVisual = DefaultVisual(XGameDisplay, XGameScreen);
X	XGameDepth = DefaultDepth(XGameDisplay, XGameScreen);
X	XGameFD = ConnectionNumber(XGameDisplay);
X
X/*
X *	Get the colors that we need.
X */
X	if (XGameDepth > 1) {
X		XGameBlack = setup_color(0x0000, 0x0000, 0x0000);
X		XGameWhite = setup_color(0xffff, 0xffff, 0xffff);
X		XGameGrey  = setup_color(0x7fff, 0x7fff, 0x7fff);
X
X		color[0] = setup_color(0x0000, 0x8fff, 0xffff);
X		color[1] = setup_color(0x0000, 0xffff, 0xffff);
X		color[2] = setup_color(0x0000, 0xffff, 0x0000);
X		color[3] = setup_color(0xffff, 0xffff, 0x0000);
X		color[4] = setup_color(0xffff, 0x7fff, 0x0000);
X		color[5] = setup_color(0xffff, 0x0000, 0x0000);
X		color[6] = setup_color(0xffff, 0x0000, 0xafff);
X
X		for (i = 0; i < LEVS; i++) {
X			fore_colors[i] = XGameBlack;
X			back_colors[i] = color[i];
X		};
X
X		if (reverse_video == 0) {
X			other_fore_color = XGameBlack;
X			other_back_color = XGameWhite;
X			border_fore_color = XGameGrey;
X			border_back_color = XGameGrey;
X			window_fore_color = XGameBlack;
X			window_back_color = XGameWhite;
X		} else {
X			other_fore_color = XGameWhite;
X			other_back_color = XGameBlack;
X			border_fore_color = XGameGrey;
X			border_back_color = XGameGrey;
X			window_fore_color = XGameWhite;
X			window_back_color = XGameBlack;
X		};
X	} else {
X		XGameBlack  = BlackPixel(XGameDisplay, XGameScreen);
X		XGameWhite  = WhitePixel(XGameDisplay, XGameScreen);
X
X		if (reverse_video == 0) {
X			for (i = 0; i < LEVS; i++) {
X				fore_colors[i] = XGameBlack;
X				back_colors[i] = XGameWhite;
X			};
X
X			other_fore_color = XGameBlack;
X			other_back_color = XGameWhite;
X			border_fore_color = XGameWhite;
X			border_back_color = XGameBlack;
X			window_fore_color = XGameBlack;
X			window_back_color = XGameWhite;
X		} else {
X			for (i = 0; i < LEVS; i++) {
X				fore_colors[i] = XGameWhite;
X				back_colors[i] = XGameBlack;
X			};
X
X			other_fore_color = XGameWhite;
X			other_back_color = XGameBlack;
X			border_fore_color = XGameBlack;
X			border_back_color = XGameWhite;
X			window_fore_color = XGameWhite;
X			window_back_color = XGameBlack;
X		};
X
X		color_type = 0;
X	};
X
X/*
X *	Get the font for text printing and tile printing.
X */
X	if ((XGameTextFont = XLoadQueryFont(XGameDisplay, TEXT_FONT)) == NULL) {
X		fprintf(stderr, "can't load text font %s\n", TEXT_FONT);
X		exit(1);
X	};
X
X	if ((XGameTileFont = XLoadQueryFont(XGameDisplay, tile_font)) == NULL) {
X		fprintf(stderr, "can't load tile font %s\n", tile_font);
X		exit(1);
X	};
X
X/*
X *	Define an icon for the game
X */
X	XGameIcon = XCreateBitmapFromData(
X		XGameDisplay, DefaultRootWindow(XGameDisplay),
X		icon_tiles_bits, ICON_WIDTH, ICON_HEIGHT);
X
X/*
X *	Open the main window.
X */
X	init_x = (DisplayWidth(XGameDisplay, XGameScreen)-WINDOW_WIDTH)/2;
X	init_y = (DisplayHeight(XGameDisplay, XGameScreen)-WINDOW_HEIGHT)/2;
X
X	XGameWindow = XCreateSimpleWindow(
X		XGameDisplay, DefaultRootWindow(XGameDisplay),
X		init_x, init_y, WINDOW_WIDTH, WINDOW_HEIGHT,
X		BORDER_WIDTH, window_fore_color, window_back_color);
X
X	if (XGameWindow == 0) {
X		fprintf(stderr, "can't open main window");
X		exit(1);
X	};
X
X/*
X *	Open the subwindows
X */
X	XGameCountWindow = XCreateSimpleWindow(
X		XGameDisplay, XGameWindow,
X		X_COUNT, Y_COUNT, COUNT_WIDTH, COUNT_HEIGHT,
X		BORDER_WIDTH, window_fore_color, window_back_color);
X
X	if (XGameCountWindow == 0) {
X		fprintf(stderr, "can't open COUNT window");
X		exit(1);
X	};
X
X	XGamePlayWindow = XCreateSimpleWindow(
X		XGameDisplay, XGameWindow,
X		X_PLAY, Y_PLAY, PLAY_WIDTH, PLAY_HEIGHT,
X		BORDER_WIDTH, window_fore_color, window_back_color);
X
X	if (XGamePlayWindow == 0) {
X		fprintf(stderr, "can't open PLAY window");
X		exit(1);
X	};
X
X	XGameDoneWindow = XCreateSimpleWindow(
X		XGameDisplay, XGameWindow,
X		X_DONE, Y_DONE, OPTION_WIDTH, OPTION_HEIGHT,
X		BORDER_WIDTH, window_fore_color, window_back_color);
X
X	if (XGameDoneWindow == 0) {
X		fprintf(stderr, "can't open DONE window");
X		exit(1);
X	};
X
X	XGameQuitWindow = XCreateSimpleWindow(
X		XGameDisplay, XGameWindow,
X		X_QUIT, Y_QUIT, OPTION_WIDTH, OPTION_HEIGHT,
X		BORDER_WIDTH, window_fore_color, window_back_color);
X
X	if (XGameQuitWindow == 0) {
X		fprintf(stderr, "can't open QUIT window");
X		exit(1);
X	};
X
X	XGameSameWindow = XCreateSimpleWindow(
X		XGameDisplay, XGameWindow,
X		X_SAME, Y_SAME, OPTION_WIDTH, OPTION_HEIGHT,
X		BORDER_WIDTH, window_fore_color, window_back_color);
X
X	if (XGameSameWindow == 0) {
X		fprintf(stderr, "can't open SAME window");
X		exit(1);
X	};
X
X	XGameNewWindow = XCreateSimpleWindow(
X		XGameDisplay, XGameWindow,
X		X_NEW, Y_NEW, OPTION_WIDTH, OPTION_HEIGHT,
X		BORDER_WIDTH, window_fore_color, window_back_color);
X
X	if (XGameNewWindow == 0) {
X		fprintf(stderr, "can't open NEW window");
X		exit(1);
X	};
X
X/*
X *	Tell the window manager about us
X */
X	XSetStandardProperties(
X		XGameDisplay, XGameWindow,
X		"xmahjongg", NULL,
X		XGameIcon, NULL, 0,
X		&XGameHints);
X
X	XGameWMHints.flags = IconPixmapHint | StateHint;
X	XGameWMHints.icon_pixmap = XGameIcon;
X	XGameWMHints.initial_state = (iconic_start) ? IconicState : NormalState;
X	XSetWMHints(XGameDisplay, XGameWindow, &XGameWMHints);
X
X/*
X *	Create a pixmap for tile image copying.
X */
X	XGamePixmap = XCreatePixmap(XGameDisplay, XGameWindow,
X		PLAY_WIDTH, PLAY_HEIGHT, XGameDepth);
X
X/*
X *	Setup the offsets for the border drawing.
X */
X	XGamePoint[ 0].x = -1;	XGamePoint[ 0].y = 1;
X	XGamePoint[ 1].x = -1;	XGamePoint[ 1].y = 64;
X	XGamePoint[ 2].x = 62;	XGamePoint[ 2].y = 64;
X	XGamePoint[ 3].x = 61;	XGamePoint[ 3].y = 65;
X	XGamePoint[ 4].x = -2;	XGamePoint[ 4].y = 65;
X	XGamePoint[ 5].x = -2;	XGamePoint[ 5].y = 2;
X	XGamePoint[ 6].x = -3;	XGamePoint[ 6].y = 3;
X	XGamePoint[ 7].x = -3;	XGamePoint[ 7].y = 66;
X	XGamePoint[ 8].x = 60;	XGamePoint[ 8].y = 66;
X	XGamePoint[ 9].x = 59;	XGamePoint[ 9].y = 67;
X	XGamePoint[10].x = -4;	XGamePoint[10].y = 67;
X	XGamePoint[11].x = -4;	XGamePoint[11].y = 4;
X
X/*
X *	Setup the GCs for the text and tiles
X */
X	XGameBorderGC = XCreateGC(XGameDisplay, XGameWindow, 0, 0);
X	XSetForeground(XGameDisplay, XGameBorderGC, border_back_color);
X	XSetBackground(XGameDisplay, XGameBorderGC, border_fore_color);
X	XSetFont(XGameDisplay, XGameBorderGC, XGameTileFont->fid);
X
X	XGameTextGC[0] = XCreateGC(XGameDisplay, XGameWindow, 0, 0);
X	XSetForeground(XGameDisplay, XGameTextGC[0], other_fore_color);
X	XSetBackground(XGameDisplay, XGameTextGC[0], other_back_color);
X	XSetFont(XGameDisplay, XGameTextGC[0], XGameTextFont->fid);
X
X	XGameTextGC[1] = XCreateGC(XGameDisplay, XGameWindow, 0, 0);
X	XSetForeground(XGameDisplay, XGameTextGC[1], other_back_color);
X	XSetBackground(XGameDisplay, XGameTextGC[1], other_fore_color);
X	XSetFont(XGameDisplay, XGameTextGC[1], XGameTextFont->fid);
X
X	XGameOtherGC[0] = XCreateGC(XGameDisplay, XGameWindow, 0, 0);
X	XSetForeground(XGameDisplay, XGameOtherGC[0], other_fore_color);
X	XSetBackground(XGameDisplay, XGameOtherGC[0], other_back_color);
X	XSetFont(XGameDisplay, XGameOtherGC[0], XGameTileFont->fid);
X
X	XGameOtherGC[1] = XCreateGC(XGameDisplay, XGameWindow, 0, 0);
X	XSetForeground(XGameDisplay, XGameOtherGC[1], other_back_color);
X	XSetBackground(XGameDisplay, XGameOtherGC[1], other_fore_color);
X	XSetFont(XGameDisplay, XGameOtherGC[1], XGameTileFont->fid);
X
X	for (i = 0; i < LEVS; i++) {
X		XGameTileGC[i][0] = XCreateGC(XGameDisplay, XGameWindow, 0, 0);
X		XSetForeground(XGameDisplay, XGameTileGC[i][0], fore_colors[i]);
X		XSetBackground(XGameDisplay, XGameTileGC[i][0], back_colors[i]);
X		XSetFont(XGameDisplay, XGameTileGC[i][0], XGameTileFont->fid);
X
X		XGameTileGC[i][1] = XCreateGC(XGameDisplay, XGameWindow, 0, 0);
X		XSetForeground(XGameDisplay, XGameTileGC[i][1], back_colors[i]);
X		XSetBackground(XGameDisplay, XGameTileGC[i][1], fore_colors[i]);
X		XSetFont(XGameDisplay, XGameTileGC[i][1], XGameTileFont->fid);
X	};
X
X/*
X *	Define the cursor for the game
X */
X	XGameCursor = XCreateFontCursor(XGameDisplay, XC_left_ptr);
X	XDefineCursor(XGameDisplay, XGameWindow, XGameCursor);
X
X/*
X *	Select window exposure events to see if the contents of the window
X *	have been erased or altered.
X */
X	XSelectInput(XGameDisplay, XGameWindow, XGameEvents);
X	XSelectInput(XGameDisplay, XGameNewWindow, XGameEvents);
X	XSelectInput(XGameDisplay, XGameDoneWindow, XGameEvents);
X	XSelectInput(XGameDisplay, XGameQuitWindow, XGameEvents);
X	XSelectInput(XGameDisplay, XGameSameWindow, XGameEvents);
X	XSelectInput(XGameDisplay, XGamePlayWindow, XGameEvents);
X	XSelectInput(XGameDisplay, XGameCountWindow, XGameEvents);
X
X/*
X *	Map the game window to the screen.
X */
X	XMapRaised(XGameDisplay, XGameWindow);
X	while (1) {
X		XNextEvent(XGameDisplay, &XGameEvent);
X		if (XGameEvent.type == Expose) break;
X	};
X
X/*
X *	Display the game name.
X */
X	XDrawLine(XGameDisplay, XGameWindow, XGameTextGC[0], 0, 184, 1000, 184);
X
X	draw_letter(INDEX_X,  42, 50);
X	draw_letter(INDEX_M, 148, 50);
X	draw_letter(INDEX_A, 254, 50);
X	draw_letter(INDEX_H, 360, 50);
X	draw_letter(INDEX_J, 466, 50);
X	draw_letter(INDEX_O, 572, 50);
X	draw_letter(INDEX_N, 678, 50);
X	draw_letter(INDEX_G, 784, 50);
X	draw_letter(INDEX_G, 890, 50);
X
X/*
X *	Display the copyright notice
X */
X	i = strlen(copyright);
X	j = XGameTextFont->max_bounds.width;
X	k = XGameTextFont->ascent;
X
X	j = (WINDOW_WIDTH - i*j)/2;
X	k = (174 - k);
X	draw_string(copyright, j, k, XGameTextGC[1]);
X
X/*
X *	Display the tiles on the screen before the start of the game.  Order:
X *	dragons, seasons, plants, directions, circles, bamboos, ideographs
X */
X	draw_data();
X
X	XFlush(XGameDisplay);
X	sleep(5);
X
X/*
X *	Find the maximum file descriptor for the select system call and set
X *	the initialization flag.
X */
X	initial_flag++;
X	maxfds = 31;
X
X/*
X *	Map the subwindows
X */
X	XClearArea(XGameDisplay, XGameWindow, 0, 0, 0, 0, True);
X	XMapSubwindows(XGameDisplay, XGameWindow);
X	XFlush(XGameDisplay);
X	return(0);
X}
X
Xsetup_color(r, g, b)
Xint	r;
Xint	g;
Xint	b;
X{
X	XColor XGameColor;
X
X	XGameColor.red = r;
X	XGameColor.green = g;
X	XGameColor.blue = b;
X
X	if (XAllocColor(XGameDisplay,XGameColormap, &XGameColor) == 0) {
X		fprintf(stderr, "can't allocate color\n");
X		exit(1);
X	};
X
X	return(XGameColor.pixel);
X}
X
Xget_tile() {
X	int i, j;
X
X	i = random_next()%TILES;
X	j = ((random_next()%2) == 0) ? 1 : -1;
X
X/*
X *	Walk through the tile pool looking for an unused tile
X */
X	while (buffer[i] == 0) {
X		i = (i+j)%TILES;
X		if (i < 0) i = TILES-1;
X	};
X
X	j = buffer[i];
X	buffer[i] = 0;
X
X	return(j);
X}
X
END_OF_initial.c
if test 19579 -ne `wc -c <initial.c`; then
    echo shar: \"initial.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f packet.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"packet.c\"
else
echo shar: Extracting \"packet.c\" \(3553 characters\)
sed "s/^X//" >packet.c <<'END_OF_packet.c'
X/*
X ******************************************************************************
X *									      *
X *	Copyright (c) 1990 by Jeff S. Young.  All rights reserved under the   *
X *	copyright laws of the United States.			      	      *
X *									      *
X ******************************************************************************
X */
X
X#include <stdio.h>
X#include <signal.h>
X#include <sys/time.h>
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <netinet/in.h>
X#include "xmahjongg.h"
X#include "variables.h"
X
Xpacket_send(type)
Xint type;
X{
X	int i;
X	int packetlen = sizeof(Packet);
X	char ascii[24];
X
X	if (tourn_flag == 0) return(0);
X	i = mypp->done;
X
X/*
X *	Update the information on my board
X */
X	if (type == GAME_START) {
X		mypp->done++;
X		mypp->tiles[mypp->done] = TILES;
X		mypp->board[mypp->done] = seed;
X		if ((i >= 0) && (mypp->tiles[i] > 0)) mypp->tiles[i] *= -1;
X		draw_user(mypp, GAME_START);
X	} else if (type == GAME_PLAY) {
X		mypp->total -= 2;
X		mypp->tiles[i] = tiles_remaining;
X		draw_user(mypp, GAME_PLAY);
X	} else if (type == GAME_DONE) {
X		if (mypp->tiles[i] > 0) mypp->tiles[i] *= -1;
X		draw_user(mypp, GAME_DONE);
X	} else if (type == GAME_QUIT) {
X		draw_user(mypp, GAME_QUIT);
X	} else {
X		fprintf(stderr, "bad packet type = %d\n", type);
X		exit(1);
X	};
X
X/*
X *	Send the information to the other players
X */
X	packet.type = htons(type);
X	packet.port = htons(mypp->port);
X	packet.tiles = htons(tiles_remaining);
X	packet.board = htonl(seed);
X	strcpy(packet.name, mypp->name);
X
X	for (i = 0, pp = player; i < num_players; i++, pp++) {
X		if ((pp->fd < 0) || (pp->type == 'M')) continue;
X		if (write(pp->fd, (char *)&packet, packetlen) != packetlen) {
X			fprintf(stderr, "can't send to %s\n", pp->name);
X			playfds ^= (1 << pp->fd);
X			close(pp->fd);
X			pp->fd = -1;
X		};
X	};
X
X	return(0);
X}
X
Xpacket_recv(fd)
Xint fd;
X{
X	int i;
X	int readfds = 1 << fd;
X	int packetlen = sizeof(Packet);
X	struct timeval timeout;
X	char ascii[32];
X	char *cp;
X
X/*
X *	Read in the packet which is waiting for us.
X */
X	timeout.tv_sec = 0L;
X	timeout.tv_usec = 0L;
X
X	if (select(maxfds, &readfds, NULL, NULL, &timeout) <= 0) {
X		return(0);
X	} else if ((i = read(fd, (char *)&packet, packetlen)) != packetlen) {
X		fprintf(stderr, "can't read from %s\n", pp->name);
X		playfds ^= (1 << pp->fd);
X		close(pp->fd);
X		pp->fd = -1;
X		return(0);
X	};
X
X/*
X *	Find this players structure.
X */
X	packet.type = ntohs(packet.type);
X	packet.port = ntohs(packet.port);
X	packet.tiles = ntohs(packet.tiles);
X	packet.board = ntohl(packet.board);
X
X	for (i = 0, pp = player; i < num_players; i++, pp++) {
X		if (pp->port == packet.port) break;
X	};
X
X	if (i == num_players) {
X		fprintf(stderr, "****** BAD PACKET ******\n");
X		fprintf(stderr, "packet name = %s   port=%d\n",
X			packet.name, packet.port);
X		return(0);
X	};
X
X	i = pp->done;
X
X	switch (packet.type) {
X		case GAME_START:
X			pp->done++;
X			pp->board[i+1] = packet.board;
X			pp->tiles[i+1] = packet.tiles;
X			if ((i >= 0) && (pp->tiles[i] > 0)) pp->tiles[i] *= -1;
X			draw_user(pp, GAME_START);
X			break;
X		case GAME_PLAY:
X			pp->total -= 2;
X			pp->tiles[i] = packet.tiles;
X			draw_user(pp, GAME_PLAY);
X			break;
X		case GAME_DONE:
X			if (pp->tiles[i] > 0) pp->tiles[i] *= -1;
X			draw_user(pp, GAME_DONE);
X			break;
X		case GAME_QUIT:
X			pp->tiles[i] = -packet.tiles;
X			pp->quit = 1;
X			draw_user(pp, GAME_QUIT);
X			playfds ^= (1 << pp->fd);
X			close(pp->fd);
X			pp->fd = -1;
X			break;
X		default:
X			fprintf(stderr, "bad switch (%d)\n", packet.type);
X			exit(1);
X			break;
X	};
X
X	return(0);
X}
END_OF_packet.c
if test 3553 -ne `wc -c <packet.c`; then
    echo shar: \"packet.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f play.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"play.c\"
else
echo shar: Extracting \"play.c\" \(7196 characters\)
sed "s/^X//" >play.c <<'END_OF_play.c'
X/*
X ******************************************************************************
X *									      *
X *	Copyright (c) 1990 by Jeff S. Young.  All rights reserved under the   *
X *	copyright laws of the United States.			      	      *
X *									      *
X ******************************************************************************
X */
X
X#include <stdio.h>
X#include <sys/time.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include "xmahjongg.h"
X#include "variables.h"
X
Xextern int initial_flag;
Xint x_dist[] = {  0, -1,  1,  0, -1,  1, -1,  0,  1, -1,  0,  1, -1,  0,  1};
Xint y_dist[] = {  2,  2,  2, -2, -2, -2, -1, -1, -1,  0,  0,  0,  1,  1,  1};
Xint z_dist[] = {  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1};
X
Xplay_tile(tp)
XTile *tp;
X{
X
X	if (not_free(tp->row, tp->col, tp->lev)) {
X		XBell(XGameDisplay, 100);
X		XFlush(XGameDisplay);
X	} else if (tile1p == NULL) {
X		invert_tile(tp, 1);
X		tile1p = tp;
X	} else if (tp == tile1p) {
X		invert_tile(tp, 0);
X		tile1p = NULL;
X	} else if (tp->type == tile1p->type) {
X		tiles_remaining -= 2;
X		remove_tile(tile1p);
X		remove_tile(tp);
X		tile1p = NULL;
X		draw_count();
X		draw_matches();
X		if (done_count == 0) packet_send(GAME_PLAY);
X	} else {
X		XBell(XGameDisplay, 100);
X		XFlush(XGameDisplay);
X	};
X
X	return(0);
X}
X
Xinvert_tile(tp, type)
XTile *tp;
Xint type;
X{
X
X	redraw_tile(tp, type);
X	XFlush(XGameDisplay);
X
X	return(0);
X}
X
Xremove_tile(tp)
XTile *tp;
X{
X
X	tp->state = FREE;
X	redraw_tile(tp, 0);
X	XFlush(XGameDisplay);
X
X	return(0);
X}
X
Xcreate_tile(tp)
XTile *tp;
X{
X	int i, j;
X	int dx, dy, dz;
X
X	for (i = 0; i < TILES; i++) {
X		if (order[i] == NULL) break;
X
X		dx = order[i]->row - tp->row;
X		dy = order[i]->col - tp->col;
X		dz = order[i]->lev - tp->lev;
X
X		if (dz < 0) continue;
X
X		if (dz > 0) break;
X		if (dy < dx) break;
X		if ((dy == dx) && (dy > 0)) break;
X	};
X
X	for (j = TILES - tiles_remaining; j > i; j--) {
X		order[j] = order[j-1];
X	};
X
X	order[i] = tp;
X	tiles_remaining--;
X	draw_count();
X
X	tp->data = tp->lev;
X	tp->state = USED;
X	redraw_tile(tp, 0);
X	XFlush(XGameDisplay);
X
X	return(0);
X}
X
Xdelete_tile(tp)
XTile *tp;
X{
X	int i, j;
X
X	for (i = 0; i < TILES; i++) {
X		if (order[i] == NULL) break;
X		if (order[i]->row != tp->row) continue;
X		if (order[i]->col != tp->col) continue;
X		if (order[i]->lev != tp->lev) continue;
X
X		for (j = i; j < TILES-1; j++) {
X			order[j] = order[j+1];
X		};
X
X		order[TILES-1] = 0;
X		break;
X	};
X
X	tiles_remaining++;
X	draw_count();
X
X	tp->state = FREE;
X	redraw_tile(tp, 0);
X	XFlush(XGameDisplay);
X
X	return(0);
X}
X
Xredraw_tile(tp, type)
XTile	*tp;
Xint	type;
X{
X	int x_src, y_src;
X	int x_dst, y_dst;
X	int row, col, lev;
X	int i, j, k, l, x, y, rv;
X	char string[4];
X	Tile *xp[144];
X	GC gc;
X
X/*
X *	Copy the tiles into the pixmap and then dump the pixmap into
X *	the window.
X */
X	row = tp->row;
X	col = tp->col;
X	lev = tp->lev;
X
X	string[0] = 127;
X	string[1] = 127;
X	string[2] = 127;
X	XDrawImageString(XGameDisplay, XGamePixmap, XGameOtherGC[0],
X		0, 0*TILE_SIDE, string, 3);
X	XDrawImageString(XGameDisplay, XGamePixmap, XGameOtherGC[0],
X		0, 1*TILE_SIDE, string, 3);
X	XDrawImageString(XGameDisplay, XGamePixmap, XGameOtherGC[0],
X		0, 2*TILE_SIDE, string, 3);
X
X	l = load_tiles(xp, row, col);
X
X	for (i = 0; i < l; i++) {
X		rv = (xp[i] == tp) ? type : 0;
X		k = (color_type == 0) ? xp[i]->lev : (xp[i]->data/16) - 1;
X
X		string[0] = xp[i]->data;
X		x = (xp[i]->col + 2-col)*(TILE_SIDE/2) + 4*xp[i]->lev;
X		y = (xp[i]->row + 2-row)*(TILE_SIDE/2) - 4*xp[i]->lev;
X		XDrawImageString(XGameDisplay, XGamePixmap,
X			XGameTileGC[k][rv], x, y, string, 1);
X
X		draw_border(x, y);
X	};
X
X	x_src = TILE_SIDE + 4*(lev-1);
X	y_src = TILE_SIDE - 4*(lev-0);
X	x_dst = tp->x - 4;
X	y_dst = tp->y + 0;
X
X	XCopyArea(XGameDisplay, XGamePixmap, XGamePlayWindow, XGameTextGC[0],
X		x_src, y_src, TILE_SIDE+4, TILE_SIDE+4, x_dst, y_dst);
X
X	return(0);
X}
X
Xnot_free(row, col, lev) 
Xint row, col, lev;
X{
X	int i, mask;
X	int r1, c1, l1;
X
X	for (i = 0, mask = 0; i < 15; i++) {
X		r1 = row+x_dist[i];
X		c1 = col+y_dist[i];
X		l1 = lev+z_dist[i];
X		if ((r1 < 0) || (r1 >=  ROWS)) continue;
X		if ((c1 < 0) || (c1 >=  COLS)) continue;
X		if ((l1 < 0) || (l1 >=  LEVS)) continue;
X
X		if (tiles[r1][c1][l1].state == USED) {
X			mask |= (1 << i);
X		};
X	};
X
X	if ((mask & 077700) != 0) {
X		return(1);
X	} else if ((mask & 000070) == 0) {
X		return(0);
X	} else if ((mask & 000007) != 0) {
X		return(1);
X	} else {
X		return(0);
X	};
X}
X
Xload_tiles(xp, row, col)
XTile	*xp[];
Xint	row;
Xint	col;
X{
X	register int i, m;
X	register int dx, dy;
X	register Tile *tp;
X
X	m = 0;
X
X	for (i = 0, tp = order[0]; i < TILES; i++, tp = order[i]) {
X		if (tp == NULL) break;
X		if (tp->state != USED) continue;
X
X		dx = tp->row - row;
X		dy = tp->col - col;
X
X		if (dx < 0) dx = -dx;
X		if (dy < 0) dy = -dy;
X
X		if ((dx <= 2) && (dy <= 2)) xp[m++] = tp;
X	};
X
X	return(m);
X}
X
Xok_below(x, y, z)
Xint	x;
Xint	y;
Xint	z;
X{
X	int i, j, k;
X
X/*
X *	Check this level to be sure that this tile will not overlap another
X *	tile.
X */
X	for (i = x-1; i <= x+1; i++) {
X		for (j = y-1; j <= y+1; j++) {
X			if ((i < 0) || (i >= ROWS)) continue;
X			if ((j < 0) || (j >= COLS)) continue;
X			if ((i == x) && (j == y)) continue;
X			if (tiles[i][j][z].state == USED) return(-1);
X		};
X	};
X
X	if (z == 0) return(0);
X
X/*
X *	Check the level below this tile to be sure that all four quadrants are
X *	covered.
X */
Xquadrant1:
X	if (tiles[x-1][y-1][z-1].state == USED) goto quadrant2;
X	if (tiles[x-1][y-0][z-1].state == USED) goto quadrant2;
X	if (tiles[x-0][y-1][z-1].state == USED) goto quadrant2;
X	if (tiles[x-0][y-0][z-1].state == USED) goto quadrant2;
X	return(-1);
X
Xquadrant2:
X	if (tiles[x-1][y-0][z-1].state == USED) goto quadrant3;
X	if (tiles[x-1][y+1][z-1].state == USED) goto quadrant3;
X	if (tiles[x-0][y-0][z-1].state == USED) goto quadrant3;
X	if (tiles[x-0][y+1][z-1].state == USED) goto quadrant3;
X	return(-1);
X
Xquadrant3:
X	if (tiles[x-0][y-1][z-1].state == USED) goto quadrant4;
X	if (tiles[x-0][y-0][z-1].state == USED) goto quadrant4;
X	if (tiles[x+1][y-1][z-1].state == USED) goto quadrant4;
X	if (tiles[x+1][y-0][z-1].state == USED) goto quadrant4;
X	return(-1);
X
Xquadrant4:
X	if (tiles[x-0][y-0][z-1].state == USED) goto quadrant5;
X	if (tiles[x-0][y+1][z-1].state == USED) goto quadrant5;
X	if (tiles[x+1][y-0][z-1].state == USED) goto quadrant5;
X	if (tiles[x+1][y+1][z-1].state == USED) goto quadrant5;
X	return(-1);
X
Xquadrant5:
X	return(0);
X}
X
Xok_above(x, y, z)
Xint	x;
Xint	y;
Xint	z;
X{
X	int i, j, k;
X
X	if (z == (LEVS-1)) return(0);
X
X/*
X *	Check the level above this tile to be sure that all four quadrants are
X *	free.
X */
X	for (i = -1; i <= 1; i++) {
X		for (j = -1; j <= 1; j++) {
X			if (((x+i) < 0) || ((x+i) >= ROWS)) continue;
X			if (((y+j) < 0) || ((y+j) >= COLS)) continue;
X			if (tiles[x+i][y+i][z+1].state == USED) return(-1);
X		};
X	};
X
X/*
X	if (tiles[x-1][y-1][z+1].state == USED) return(-1);
X	if (tiles[x-1][y-0][z+1].state == USED) return(-1);
X	if (tiles[x-1][y+1][z+1].state == USED) return(-1);
X
X	if (tiles[x-0][y-1][z+1].state == USED) return(-1);
X	if (tiles[x-0][y-0][z+1].state == USED) return(-1);
X	if (tiles[x-0][y+1][z+1].state == USED) return(-1);
X
X	if (tiles[x+1][y-1][z+1].state == USED) return(-1);
X	if (tiles[x+1][y-0][z+1].state == USED) return(-1);
X	if (tiles[x+1][y+1][z+1].state == USED) return(-1);
X*/
X
X	return(0);
X}
END_OF_play.c
if test 7196 -ne `wc -c <play.c`; then
    echo shar: \"play.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f random.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"random.c\"
else
echo shar: Extracting \"random.c\" \(1155 characters\)
sed "s/^X//" >random.c <<'END_OF_random.c'
X/*
X ******************************************************************************
X *									      *
X *	Copyright (c) 1990 by Jeff S. Young.  All rights reserved under the   *
X *	copyright laws of the United States.			      	      *
X *									      *
X ******************************************************************************
X */
X
X#include <stdio.h>
X#include <sys/time.h>
X
X#define	POLY_SIZE	31
X#define	TAP_1		0
X#define	TAP_2		3
X#define	TAP_3		POLY_SIZE
X
Xlong	poly[POLY_SIZE+1];
Xlong	*p1 = &poly[TAP_1];
Xlong	*p2 = &poly[TAP_2];
Xlong	*p3 = &poly[TAP_3];
X
Xlong random_init(x)
Xint x;
X{
X	int i;
X
X	poly[0] = x;
X	for (i = 1; i < POLY_SIZE; i++) {
X		poly[i] = 3234846615*poly[i-1] + 47027;
X	};
X
X	p1 = &poly[TAP_1];
X	p2 = &poly[TAP_2];
X	p3 = &poly[TAP_3];
X
X	for (i = 0; i < 2*POLY_SIZE; i++) {
X		random();
X	};
X
X	return(0L);
X}
X
Xlong random_next()
X{
X	long x;
X
X	*p3 = (*p2 + *p1);
X	x = (*p3 >> 1) & 0x7fffffff;
X
X	if (p3 == &poly[POLY_SIZE]) {
X		p3 = poly;
X		p2++;
X		p1++;
X	} else if (p2 == &poly[POLY_SIZE]) {
X		p3++;
X		p2 = poly;
X		p1++;
X	} else if (p1 == &poly[POLY_SIZE]) {
X		p3++;
X		p2++;
X		p1 = poly;
X	} else {
X		p3++;
X		p2++;
X		p1++;
X	};
X
X	return(x);
X}
END_OF_random.c
if test 1155 -ne `wc -c <random.c`; then
    echo shar: \"random.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f sysdep.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"sysdep.c\"
else
echo shar: Extracting \"sysdep.c\" \(2001 characters\)
sed "s/^X//" >sysdep.c <<'END_OF_sysdep.c'
X/*
X ******************************************************************************
X *									      *
X *	Copyright (c) 1990 by Jeff S. Young.  All rights reserved under the   *
X *	copyright laws of the United States.			      	      *
X *									      *
X ******************************************************************************
X */
X
X#ifndef	VMS
X
X#include <pwd.h>
X#include <stdio.h>
X#include <string.h>
X#include <sys/time.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include "xmahjongg.h"
X#include "variables.h"
X
Xget_user(name)
Xchar	*name;
X{
X	struct passwd *pwp;
X
X	if ((pwp = getpwuid(getuid())) == NULL) {
X		fprintf(stderr, "can't getpwuid\n");
X		exit(1);
X	} else {
X		strcpy(name, pwp->pw_name);
X	};
X
X	return(0);
X}
X
Xget_seed()
X{
X	struct timeval tv;
X	struct timezone tz;
X
X	if (seed == 0) {
X		gettimeofday(&tv, &tz);
X		seed = 1 + (tv.tv_sec%100000);
X	} else if (seed < 0) {
X		seed = (-seed)%100000;
X	} else {
X		seed = 1 + (random_next(seed)%100000);
X	};
X
X	return(0);
X}
X
Xevent_wait()
X{
X	int readfds;
X
X/*
X *	If there are no events pending, then sleep until one occurs.
X */
X	while (XEventsQueued(XGameDisplay, QueuedAfterReading) == 0) {
X		readfds = (1 << XGameFD) | playfds;
X		select(maxfds, &readfds, NULL, NULL, NULL);
X
X		if ((readfds & playfds) != 0) {
X			event_packet(readfds);
X		};
X	};
X
X	return(0);
X}
X
X#else
X
X#include <stdio.h>
X#include <string.h>
X#include <sys/time.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include "xmahjongg.h"
X#include "variables.h"
X
X
Xget_user(name)
Xchar	*name;
X{
X
X	if (cuserid(name) == NULL) {
X		fprintf(stderr, "can't cuserid\n");
X		exit(1);
X	};
X
X	return(0);
X}
X
Xget_seed()
X{
X	struct tm *tv;
X	time_t clock_time;
X
X	if (seed == 0) {
X		time(&clock_time);
X		tv = localtime(&clock_time);
X		seed = 1 + (tv->tm_sec%100000);
X	} else if (seed < 0) {
X		seed = (-seed)%100000;
X	} else {
X		seed = 1 + (random_next(seed)%100000);
X	};
X
X	return(0);
X}
X
Xevent_wait()
X{
X
X/*
X *	Since VMS doesn't have tournament mode, this is really a dummy 
X *	routine.
X */
X
X	return(0);
X}
X
X#endif
END_OF_sysdep.c
if test 2001 -ne `wc -c <sysdep.c`; then
    echo shar: \"sysdep.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f variables.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"variables.c\"
else
echo shar: Extracting \"variables.c\" \(567 characters\)
sed "s/^X//" >variables.c <<'END_OF_variables.c'
X/*
X ******************************************************************************
X *									      *
X *	Copyright (c) 1990 by Jeff S. Young.  All rights reserved under the   *
X *	copyright laws of the United States.			      	      *
X *									      *
X ******************************************************************************
X */
X
X#ifdef	GLOBAL
X#undef	GLOBAL
X#endif
X#define	GLOBAL 
X
X#include <pwd.h>
X#include <stdio.h>
X#include <string.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include "xmahjongg.h"
X#include "variables.h"
X
Xvariables()
X{
X
X	return(0);
X}
END_OF_variables.c
if test 567 -ne `wc -c <variables.c`; then
    echo shar: \"variables.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f xmahjongg.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"xmahjongg.c\"
else
echo shar: Extracting \"xmahjongg.c\" \(3724 characters\)
sed "s/^X//" >xmahjongg.c <<'END_OF_xmahjongg.c'
X/*
X ******************************************************************************
X *									      *
X *	Copyright (c) 1990 by Jeff S. Young.  All rights reserved under the   *
X *	copyright laws of the United States.			      	      *
X *									      *
X ******************************************************************************
X */
X
X#include <stdio.h>
X#include <string.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include "xmahjongg.h"
X#include "variables.h"
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X
X	get_parameters(argc, argv);
X
X	while(1) {
X		initialize();
X		keep_playing = 1;
X		packet_send(GAME_START);
X
X		while(keep_playing != 0) {
X			event_process();
X		};
X	};
X}
X
Xget_parameters(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int i, j, c;
X	char username[32];
X	char *cp, hostname[HOSTNAMELEN];
X	Player tmp, *pp = player;
X
X/*
X *	Parse the arguments.
X */
X	layout = NULL;
X	tile_font = TILE_FONT;
X
X	while ((c = getopt(argc, argv, "icrsb:d:f:l:n:p:")) != EOF) {
X		switch (c) {
X			case 'b':
X				seed = -atoi(optarg);
X				break;
X			case 'c':
X				color_type = 1;
X				break;
X			case 'd':
X				display_name = optarg;
X				break;
X			case 'f':
X				tile_font = optarg;
X				break;
X			case 'i':
X				iconic_start = 1;
X				break;
X			case 'l':
X				layout = optarg;
X				break;
X			case 'n':
X				num_games = atoi(optarg);
X				break;
X			case 'p':
X				tourn_flag = 1;
X				cp = strchr(optarg, '@');
X				if (cp == NULL) usage(BAD_USERNAME);
X				strncpy(pp->name, optarg, cp-optarg);
X				strcpy(pp->machine, cp+1);
X				num_players++;
X				pp++;
X				break;
X			case 'r':
X				reverse_video = 1;
X				break;
X			case 's':
X				setup_flag = 1;
X				break;
X			default:
X				usage(NULL);
X				break;
X		};
X	};
X
X/*
X *	Check to see if we are in setup mode.  If we are only certain param-
X *	eters are valid.
X */
X	if (setup_flag != 0) {
X		if (seed < 0) usage(BAD_SEED);
X		if (num_games != 0) usage(BAD_GAMES);
X		if (tourn_flag != 0) usage(BAD_TOURN);
X		if (color_type != 0) usage(BAD_COLOR);
X
X		return(0);
X	};
X
X/*
X *	Set up the tournament if requested.
X */
X	if (num_players == 0) return(0);
X	if (num_games == 0) num_games = 3;
X
X	get_user(username);
X	gethostname(hostname, sizeof(hostname));
X	mypp = &player[num_players++];
X	strcpy(mypp->name, username);
X	strcpy(mypp->machine, hostname);
X
X	for (i = 0; i < num_players-1; i++) {
X		for (j = i+1; j < num_players; j++) {
X			if (strcmp(player[i].name, player[j].name) > 0) {
X				tmp = player[i];
X				player[i] = player[j];
X				player[j] = tmp;
X			};
X		};
X		
X	};
X
X	for (i = 0; i < num_players; i++) {
X		player[i].x = X_SCORE;
X		player[i].y = Y_SCORE+15*i;
X		player[i].port = XPORT+i;
X		player[i].done = -1;
X		player[i].total = 144*num_games;
X
X		for (j = 0; j < MAX_BOARDS; j++) {
X			player[i].tiles[j] = 2*TILES;
X		};
X
X		if (strcmp(player[i].name, username) < 0) {
X			player[i].type = 'C';
X		} else if (strcmp(player[i].name, username) > 0) {
X			player[i].type = 'A';
X		} else {
X			mypp = &player[i];
X			player[i].type = 'M';
X		};
X	};
X
X	return(0);
X}
X
Xusage(s)
Xchar	*s;
X{
X
X	if (s != NULL) fprintf(stderr, "xmahjongg: %s\n\n", s);
X
X	fprintf(stderr, "xmahjongg \n");
X	fprintf(stderr, "          [-b #]        - board number\n");
X	fprintf(stderr, "          [-c]          - color tiles by group\n");
X	fprintf(stderr, "          [-d display]  - display name\n");
X	fprintf(stderr, "          [-f fontname] - font name\n");
X	fprintf(stderr, "          [-i]          - iconic start\n");
X	fprintf(stderr, "          [-l file]     - board layout file\n");
X	fprintf(stderr, "          [-n #]        - # of games (tournament)\n");
X	fprintf(stderr, "          [-p nx@mx]    - another player\n");
X	fprintf(stderr, "          [-r]          - reverse video\n");
X	fprintf(stderr, "          [-s]          - setup mode\n");
X	exit(1);
X}
END_OF_xmahjongg.c
if test 3724 -ne `wc -c <xmahjongg.c`; then
    echo shar: \"xmahjongg.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 1 \(of 5\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 4 5 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 5 archives.
    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

dan
----------------------------------------------------
O'Reilly && Associates   argv@sun.com / argv@ora.com
Opinions expressed reflect those of the author only.