[comp.sources.games] v04i029: mahjongg - game of mahjongg for B&W and Color Suns, Part03/03

games@tekred.TEK.COM (06/01/88)

Submitted by: tektronix!tessi!exc!markh (Mark Holm)
Comp.sources.games: Volume 4, Issue 29
Archive-name: mahjongg/Part03

#! /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 3 (of 3)."
# Contents:  event.c mahjongg.c
# Wrapped by billr@saab on Tue May 31 11:44:04 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
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\" \(20252 characters\)
sed "s/^X//" >event.c <<'END_OF_event.c'
X/*
X *	Copyright 1988, Mark Holm
X *			Exceptions
X *
X *	Acknowledgments to Dorothy Robinson for her artistic
X *	 abilities in drawing the icons and to Jim Batch for
X *	 technical support and graphical concepts (which I abandoned in favor
X *       of the easy way out).
X *
X *	Permission is given to copy and distribute for non-profit purposes.
X *
X */
X
X/*      This file has the event handlers for the background and
X *       tiles in the play panel
X */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <suntool/sunview.h>
X#include <suntool/panel.h>
X#include <sunwindow/notify.h>
X#include <pixrect/pixrect.h>
X
X#include "mahjongg.h"
X
X/* external definitions */
X
Xextern Frame		main_frame;
Xextern Panel		play_panel, message_panel;
Xextern Panel_item	TL_hundred;
Xextern Panel_item	TL_ten;
Xextern Panel_item	TL_one;
Xextern Panel_item	message;
Xextern Panel_item	tile[144];
Xextern Panel_item	tiles_left[3];
Xextern Panel_item	board_num;
Xextern Cursor		play_cursor;
X
Xextern boolean		BandW;
Xextern Tiles		*board[144];
Xextern int		tile_count;
Xextern int		seed;
Xextern Selected		last_item;
Xextern Selected		selected[2];
X
X/* local globals */
X
XSelected		undo_tiles[144][2];
Xint			undo_count;
Xboolean			help_mode = FALSE;
X
X/*******************************************/
X
Xvoid help_proc(item, event)
XPanel_item	item;
XEvent		*event;
X
X{
Xint 		i;
XTiles 		*data[2];
Xstatic int	parse[2];
X
X    if(!(selected[0].filled)) {
X	if(!(help_mode)) { /* Just starting. init and recall */
X
X	    help_mode = TRUE;
X	    parse[0] = 143;
X	    parse[1] = 142;
X	    help_proc(item, event);
X
X	} else { /* find next match */
X	    for(; parse[0] >= 0; parse[0]--) {
X	    	if (!((board[parse[0]]->top_free &&		    /* uncovered */
X		    (board[parse[0]]->left_free || board[parse[0]]->right_free) && /* open */
X		    (!(board[parse[0]]->removed)))))  /* not already used */
X		    continue; /* not available go to next */
X
X		for(; parse[1] >= 0; parse[1]--) { /* check for second tile */
X	    	    if ((board[parse[0]]->value == board[parse[1]]->value) && /* right value */
X			(parse[0] != parse[1]) &&    /* different item */
X			(board[parse[1]]->top_free &&		    /* uncovered */
X			(board[parse[1]]->left_free || board[parse[1]]->right_free) && /* open */
X			(!(board[parse[1]]->removed)))) { /* not already used */
X
X			/* Found a match, show it */
X
X			/* flag found items */
X			selected[0].filled = TRUE;
X			selected[1].filled = TRUE;
X
X			/* fake in some data */
X			selected[0].item = tile[parse[0]];
X			selected[0].event.ie_locx = ((int) panel_get(tile[parse[0]], PANEL_ITEM_X) + 10);
X			selected[0].event.ie_locy = ((int) panel_get(tile[parse[0]], PANEL_ITEM_Y) + 10);
X			selected[0].event.ie_time.tv_sec = event->ie_time.tv_sec;
X			selected[0].event.ie_time.tv_usec = event->ie_time.tv_usec;
X
X			selected[1].item = tile[parse[1]];
X			selected[1].event.ie_locx = ((int) panel_get(tile[parse[1]], PANEL_ITEM_X) + 10);
X			selected[1].event.ie_locy = ((int) panel_get(tile[parse[1]], PANEL_ITEM_Y) + 10);
X			selected[1].event.ie_time.tv_sec = event->ie_time.tv_sec;
X			selected[1].event.ie_time.tv_usec = event->ie_time.tv_usec;
X
X			/* Muppet news flash */
X			panel_begin_preview(selected[0].item, selected[0].event);
X			panel_begin_preview(selected[1].item, selected[1].event);
X
X    			/* show next move message */
X	    		panel_set(message, PANEL_LABEL_STRING,
X					    "Show next move? [Y] [] [N]",
X					   PANEL_SHOW_ITEM,
X					    TRUE, 0);
X
X       	    		window_set(message_panel, WIN_IGNORE_PICK_EVENTS,
X						   WIN_MOUSE_BUTTONS, 0, 0);
X       	    		window_set(message_panel, WIN_IGNORE_KBD_EVENT,
X					           WIN_ASCII_EVENTS, 0, 0);
X   	    		cursor_set(play_cursor, CURSOR_IMAGE, &confirm, 0);
X   	    		window_set(play_panel, WIN_CURSOR, play_cursor, 0);
X
X			parse[1]--; /* do loop step */
X			return; /* all done this rotation */
X
X		    }
X		} /* else go to next */
X		     
X		parse[1] = parse[0] - 2; /* going around again */
X
X	    }
X
X	    /* no more moves beep and show message */
X
X	    window_bell(main_frame);
X
X	    panel_set(message, PANEL_LABEL_STRING,
X			    "No more moves. [DONE] [] []",
X			   PANEL_SHOW_ITEM,
X			    TRUE, 0);
X
X       	    window_set(message_panel, WIN_IGNORE_PICK_EVENTS,
X				   WIN_MOUSE_BUTTONS, 0, 0);
X       	    window_set(message_panel, WIN_IGNORE_KBD_EVENT,
X			           WIN_ASCII_EVENTS, 0, 0);
X   	    cursor_set(play_cursor, CURSOR_IMAGE, &confirm, 0);
X   	    window_set(play_panel, WIN_CURSOR, play_cursor, 0);
X
X        }
X
X    } else { /* search for available match */
X
X	data[0] = (Tiles *) panel_get(selected[0].item, PANEL_CLIENT_DATA);
X
X	for(i = 143; i >= 0; i--) {
X	    if ((board[i]->value == data[0]->value) && /* right value */
X		(tile[i] != selected[0].item) &&    /* different item */
X		(board[i]->top_free &&		    /* uncovered */
X		(board[i]->left_free || board[i]->right_free) && /* open */
X		(!(board[i]->removed)))) { /* not already used */
X
X		/* found one */
X
X		/* fake in some selected data */
X
X		selected[1].item = tile[i];
X		selected[1].event.ie_locx = ((int) panel_get(tile[i], PANEL_ITEM_X) + 10);
X		selected[1].event.ie_locy = ((int) panel_get(tile[i], PANEL_ITEM_Y) + 10);
X		selected[1].event.ie_time.tv_sec = 10; /*sounds good */
X		selected[1].event.ie_time.tv_usec = 10; /*sounds good */
X
X		selected[1].filled = TRUE;
X
X		/* turn on preview */
X
X		panel_begin_preview(selected[1].item, selected[1].event);
X
X		/* set confirm message */
X
X		panel_set(message, PANEL_LABEL_STRING,
X				    "Please confirm. [Y] [] [N]",
X				   PANEL_SHOW_ITEM,
X				    TRUE, 0);
X
X       		window_set(message_panel, WIN_IGNORE_PICK_EVENTS,
X					   WIN_MOUSE_BUTTONS, 0, 0);
X       		window_set(message_panel, WIN_IGNORE_KBD_EVENT,
X				           WIN_ASCII_EVENTS, 0, 0);
X   		cursor_set(play_cursor, CURSOR_IMAGE, &confirm, 0);
X   		window_set(play_panel, WIN_CURSOR, play_cursor, 0);
X
X		/* return to sender */
X
X		return;
X
X	    }
X	}
X
X        selected[0].filled = FALSE;
X	panel_cancel_preview(selected[0].item, selected[0].event);
X	window_bell(main_frame);
X
X    }
X}
X
Xvoid remove_tiles(REMOVE)
Xboolean	REMOVE;
X
X{
XTiles	*data[2];
Xint	 i;
Xint	 tiles_left_hun;
Xint	 tiles_left_ten;
Xint	 tiles_left_one;
XPixwin  *pw;
XRect    *r;
X
X    if (REMOVE) {
X	/* get data from items to be removed */
X	data[0] = (Tiles *) panel_get(selected[0].item, PANEL_CLIENT_DATA);
X	data[1] = (Tiles *) panel_get(selected[1].item, PANEL_CLIENT_DATA);
X
X    } else {
X	/* get data from items to be replaced */
X	data[0] = (Tiles *) panel_get(undo_tiles[undo_count][0].item, PANEL_CLIENT_DATA);
X	data[1] = (Tiles *) panel_get(undo_tiles[undo_count][1].item, PANEL_CLIENT_DATA);
X    }
X
X    /* adjust adjacent tiles */
X    for(i = 0; i < 2 && data[0]->left_next[i] != 999; board[data[0]->left_next[i]]->right_free = REMOVE, i++);
X    for(i = 0; i < 2 && data[1]->left_next[i] != 999; board[data[1]->left_next[i]]->right_free = REMOVE, i++);
X    for(i = 0; i < 2 && data[0]->right_next[i] != 999; board[data[0]->right_next[i]]->left_free = REMOVE, i++);
X    for(i = 0; i < 2 && data[1]->right_next[i] != 999; board[data[1]->right_next[i]]->left_free = REMOVE, i++);
X    for(i = 0; i < 4 && data[0]->covered[i] != 999; board[data[0]->covered[i]]->top_free = REMOVE, i++);
X    for(i = 0; i < 4 && data[1]->covered[i] != 999; board[data[1]->covered[i]]->top_free = REMOVE, i++);
X
X    /* set removed flags */
X    data[0]->removed = REMOVE;
X    data[1]->removed = REMOVE;
X
X    if (REMOVE) {
X	/* turn off preview */
X	panel_cancel_preview(selected[0].item, selected[0].event);
X	panel_cancel_preview(selected[1].item, selected[1].event);
X    } else  /* check to see if previewing an item and un-preview and select */
X	if (selected[0].filled) {
X	    panel_cancel_preview(selected[0].item, selected[0].event);
X	    selected[0].filled = FALSE;
X	}
X
X    /* fix playing field */
X    pw = (Pixwin *) window_get(play_panel, WIN_PIXWIN);
X    r  = (Rect *)   window_get(play_panel, WIN_RECT);
X    pw_batch_on(pw);
X    pw_lock(pw, r);
X    panel_paint(play_panel, PANEL_NONE);
X    panel_set((REMOVE) ? selected[0].item : undo_tiles[undo_count][0].item, PANEL_SHOW_ITEM, !REMOVE, 0);
X    panel_set((REMOVE) ? selected[1].item : undo_tiles[undo_count][1].item, PANEL_SHOW_ITEM, !REMOVE, 0);
X    panel_paint(play_panel, PANEL_NO_CLEAR);
X    pw_unlock(pw);
X    pw_batch_off(pw);
X
X    /* deselect tiles */
X    selected[0].filled = FALSE;
X    selected[1].filled = FALSE;
X
X    /* fix tile counter */
X    tile_count += (REMOVE) ? -2 : 2;
X
X    tiles_left_hun = tile_count / 100;
X    tiles_left_ten = (tile_count - (tiles_left_hun * 100)) / 10;
X    tiles_left_one = tile_count - (tiles_left_hun * 100) - (tiles_left_ten * 10);
X
X    /* display hundreds tile by own status */
X    panel_set(TL_hundred, PANEL_SHOW_ITEM, tiles_left_hun, 0);
X
X    /* display tens tile by own status ored with hundreds status */
X    panel_set(TL_ten, PANEL_SHOW_ITEM, tiles_left_hun || tiles_left_ten, 0);
X
X    switch(tiles_left_ten) {
X	case 0:
X		panel_set(TL_ten, PANEL_LABEL_IMAGE, (BandW) ? &NUM0 : &cNUM0, 0);
X		break;
X	case 1:
X		panel_set(TL_ten, PANEL_LABEL_IMAGE, (BandW) ? &NUM1 : &cNUM1, 0);
X		break;
X	case 2:
X		panel_set(TL_ten, PANEL_LABEL_IMAGE, (BandW) ? &NUM2 : &cNUM2, 0);
X		break;
X	case 3:
X		panel_set(TL_ten, PANEL_LABEL_IMAGE, (BandW) ? &NUM3 : &cNUM3, 0);
X		break;
X	case 4:
X		panel_set(TL_ten, PANEL_LABEL_IMAGE, (BandW) ? &NUM4 : &cNUM4, 0);
X		break;
X	case 5:
X		panel_set(TL_ten, PANEL_LABEL_IMAGE, (BandW) ? &NUM5 : &cNUM5, 0);
X		break;
X	case 6:
X		panel_set(TL_ten, PANEL_LABEL_IMAGE, (BandW) ? &NUM6 : &cNUM6, 0);
X		break;
X	case 7:
X		panel_set(TL_ten, PANEL_LABEL_IMAGE, (BandW) ? &NUM7 : &cNUM7, 0);
X		break;
X	case 8:
X		panel_set(TL_ten, PANEL_LABEL_IMAGE, (BandW) ? &NUM8 : &cNUM8, 0);
X		break;
X	case 9:
X		panel_set(TL_ten, PANEL_LABEL_IMAGE, (BandW) ? &NUM9 : &cNUM9, 0);
X		break;
X	}
X
X    switch(tiles_left_one) { /* only need even tiles */
X	case 0:
X		panel_set(TL_one, PANEL_LABEL_IMAGE, (BandW) ? &NUM0 : &cNUM0, 0);
X		break;
X	case 2:
X		panel_set(TL_one, PANEL_LABEL_IMAGE, (BandW) ? &NUM2 : &cNUM2, 0);
X		break;
X	case 4:
X		panel_set(TL_one, PANEL_LABEL_IMAGE, (BandW) ? &NUM4 : &cNUM4, 0);
X		break;
X	case 6:
X		panel_set(TL_one, PANEL_LABEL_IMAGE, (BandW) ? &NUM6 : &cNUM6, 0);
X		break;
X	case 8:
X		panel_set(TL_one, PANEL_LABEL_IMAGE, (BandW) ? &NUM8 : &cNUM8, 0);
X		break;
X	}
X
X    if (REMOVE) {
X
X	/* update undo_count */
X	undo_count++;
X
X	/* update removed array */
X	undo_tiles[undo_count][0].item = selected[0].item;
X	undo_tiles[undo_count][0].event.ie_locx = selected[0].event.ie_locx;
X	undo_tiles[undo_count][0].event.ie_locy = selected[0].event.ie_locy;
X	undo_tiles[undo_count][0].event.ie_time.tv_sec = selected[0].event.ie_time.tv_sec;
X	undo_tiles[undo_count][0].event.ie_time.tv_usec = selected[0].event.ie_time.tv_usec;
X	undo_tiles[undo_count][0].filled = TRUE;
X
X	undo_tiles[undo_count][1].item = selected[1].item;
X	undo_tiles[undo_count][1].event.ie_locx = selected[1].event.ie_locx;
X	undo_tiles[undo_count][1].event.ie_locy = selected[1].event.ie_locy;
X	undo_tiles[undo_count][1].event.ie_time.tv_sec = selected[1].event.ie_time.tv_sec;
X	undo_tiles[undo_count][1].event.ie_time.tv_usec = selected[1].event.ie_time.tv_usec;
X	undo_tiles[undo_count][1].filled = TRUE;
X
X	/* remove confirm message */
X
X	panel_set(message,PANEL_SHOW_ITEM, FALSE, 0);
X
X	window_set(message_panel, WIN_CONSUME_PICK_EVENTS,
X			       WIN_MOUSE_BUTTONS, 0,
X			       0);
X	window_set(message_panel, WIN_CONSUME_KBD_EVENT,
X			       WIN_ASCII_EVENTS, 0, 0);
X    
X	cursor_set(play_cursor, CURSOR_IMAGE, &stick, 0);
X	window_set(play_panel, WIN_CURSOR, play_cursor, 0);
X
X	/* check for clean board and congrat them */
X
X	if ( tiles_left_hun == 0 && tiles_left_ten == 0 && tiles_left_one == 0) 
X		panel_set(message, PANEL_LABEL_STRING,
X			    "Congratulations!! Press 'AGAIN' or 'NEW'",
X			   PANEL_SHOW_ITEM,
X			    TRUE, 0);
X
X    } else { /* decrement undo_count */
X	undo_tiles[undo_count][0].filled = FALSE;
X	undo_tiles[undo_count][1].filled = FALSE;
X	undo_count--;
X    }
X}
X
Xvoid play_back_proc(where, event)
XPanel		 where;
XEvent		*event;
X{
X    
X    if (!(selected[0].filled) && help_mode) { /* stop helping */
X	if (event_id(event) == MS_LEFT) { /* all done */
X
X    	    /* remove message */
X
X    	    panel_set(message,PANEL_SHOW_ITEM, FALSE, 0);
X   	    window_set(message_panel, WIN_CONSUME_PICK_EVENTS,
X					   WIN_MOUSE_BUTTONS, 0,
X					  0);
X   	    window_set(message_panel, WIN_CONSUME_KBD_EVENT,
X					   WIN_ASCII_EVENTS, 0, 0);
X   	    cursor_set(play_cursor, CURSOR_IMAGE, &stick, 0);
X   	    window_set(play_panel, WIN_CURSOR, play_cursor, 0);
X
X	    /* exit help_mode */
X
X	    help_mode = FALSE;
X
X	}
X    } else { /* doing confirm or next help */
X
X    if (selected[1].filled) { /* doing confirm  or next help */
X
X        switch (event_id(event)) {
X
X	    case MS_LEFT:
X		    /* confirmed selection */
X		    if (event_is_up(event)) {
X			if (help_mode) { /* do next help */
X
X			    /* cancel preview of selected tiles */
X			    panel_cancel_preview(selected[0].item, selected[0].event);
X			    panel_cancel_preview(selected[1].item, selected[1].event);
X			    /* Clean up selected's variables */
X			    selected[0].filled = FALSE;
X			    selected[1].filled = FALSE;
X
X    			    /* remove confirm message */
X    			    panel_set(message,PANEL_SHOW_ITEM, FALSE, 0);
X
X			    /* do next help */
X			    help_proc();
X
X			} else { /* confirmed selection. remove them */
X			    remove_tiles(TRUE);
X			}
X		    }
X		    break;
X
X	    case MS_RIGHT:
X		    /* refused selection */
X		    if (event_is_down(event)) {
X			    /* cancel preview of selected tiles */
X			    panel_cancel_preview(selected[0].item, selected[0].event);
X			    panel_cancel_preview(selected[1].item, selected[1].event);
X			    /* Clean up selected's variables */
X			    selected[0].filled = FALSE;
X			    selected[1].filled = FALSE;
X
X    			    /* remove confirm message */
X
X    			    panel_set(message,PANEL_SHOW_ITEM, FALSE, 0);
X   			    window_set(message_panel, WIN_CONSUME_PICK_EVENTS,
X						       WIN_MOUSE_BUTTONS, 0,
X						       0);
X   			    window_set(message_panel, WIN_CONSUME_KBD_EVENT,
X						       WIN_ASCII_EVENTS, 0, 0);
X   			    cursor_set(play_cursor, CURSOR_IMAGE, &stick, 0);
X   			    window_set(play_panel, WIN_CURSOR, play_cursor, 0);
X
X			    /* if in help mode toggle out */
X			    if (help_mode) help_mode = FALSE; 
X
X		    }
X		    break;
X	}
X    } else {
X
X        /* check for help requests */
X
X	if ((event_id(event) == MS_MIDDLE) && event_is_up(event) && selected[0].filled) {
X
X	    help_proc();
X
X	} else  /* or MS_LEFT up outside of playing area */
X	    if ((event_id(event) == MS_LEFT) && event_is_up(event) &&
X		 last_item.filled) { /* went down on something */ 
X
X		window_bell(main_frame);
X		last_item.filled = FALSE;
X
X		if (!selected[0].filled || (selected[0].item != last_item.item)) {
X		    /* not aborting deselection */
X		    panel_cancel_preview(last_item.item, last_item.event);
X		}
X	    }
X    }
X   }
X}
X
Xvoid play_event_proc(item, event)
XPanel_item		 item;
XEvent			*event;
X
X{
XTiles	*data;
Xint	value;
Xint	i;
Xint	x;
Xint	y;
X
X    /* check to see if in help_mode */
X
X    if (help_mode) {
X	play_back_proc(play_panel, event);
X	return;
X    }
X
X    /* check to see if just confirming */
X
X    if (selected[1].filled) {
X	play_back_proc(play_panel, event);
X	return;
X    }
X
X    /* translate item to top level available */
X
X    if ( (event_id(event) == MS_LEFT) &&
X         ((ROW2 - B_TILE_SHADOW) <= event->ie_locy) &&
X         (event->ie_locy <= (ROW2 - B_TILE_SHADOW + (6 * W_BASE_TILE))) &&
X         ((COL5 - S_TILE_SHADOW) <= event->ie_locx) &&
X	 (event->ie_locx <= (COL5 - S_TILE_SHADOW + (6 * H_BASE_TILE))) ) { /* in overlap area, check for stacks */
X
X	for(i = 143; i > 86 ; i--) { /* check from top to bottom */
X
X	    x = (int) panel_get(tile[i], PANEL_ITEM_X);
X	    y = (int) panel_get(tile[i], PANEL_ITEM_Y);
X
X	    if ( (x <= event->ie_locx) &&
X		 (event->ie_locx <= x + W_BASE_TILE) &&
X		 (y <= event->ie_locy) &&
X		 (event->ie_locy <= y + H_BASE_TILE) ) { /* right spot */
X
X	        if ( !(board[i]->removed) ) {
X
X		   item = tile[i]; /* got it */
X		   break;
X
X		} else { /* look on next layer down */
X		   /* take first covered tile and add 1 for loop */
X		   if (i != 143) i = board[i]->covered[0] + 1;
X		}
X	    } /* wrong location. try again */
X	} /* next loop */
X    }
X
X    /* get data from item selected */
X
X    data = (Tiles *) panel_get(item, PANEL_CLIENT_DATA);
X    value = data->value;
X
X    switch(event_id(event)) {
X
X	case MS_LEFT: 
X	    /* Left button down begin selection */
X		if (event_is_down(event)) {
X    		    if ( data->top_free && (data->left_free || data->right_free)) {
X
X			if ( !(selected[0].filled) || (last_item.item != item) ) { /* don't double up */
X		            panel_begin_preview(item, event);
X			}
X
X		        /* file last_item slected for future reference */
X		        last_item.item = item;
X		        last_item.event.ie_locx = event->ie_locx;
X		        last_item.event.ie_locy = event->ie_locy;
X		        last_item.event.ie_time.tv_sec = event->ie_time.tv_sec;
X		        last_item.event.ie_time.tv_usec = event->ie_time.tv_usec;
X
X		        last_item.filled = TRUE;
X
X		    } else { /* beep at them */
X
X			window_bell(main_frame);
X
X		    }
X
X		} else {
X
X		/* button went up, check same item as down and grab it */
X
X		    if ((last_item.filled)) { /* else ignore it */
X
X			if (item != last_item.item) { /* beep at them */
X
X			    last_item.filled = FALSE;
X			    window_bell(main_frame);
X			    if (!selected[0].filled || (selected[0].item != last_item.item)) {
X				/* not aborting deselect */
X				panel_cancel_preview(last_item.item, last_item.event);
X
X			    }
X
X		        } else {
X
X			    if (!(selected[0].filled)) {
X
X				/* fill first selection if empty */
X				selected[0].item = item;
X				selected[0].event.ie_locx = event->ie_locx;
X				selected[0].event.ie_locy = event->ie_locy;
X				selected[0].event.ie_time.tv_sec = event->ie_time.tv_sec;
X				selected[0].event.ie_time.tv_usec = event->ie_time.tv_usec;
X
X				selected[0].filled = TRUE;
X
X				/* clear last item */
X
X				last_item.filled = FALSE;
X
X		    	    } else {
X
X				if (item == selected[0].item) { /* deselect item */
X
X				    panel_cancel_preview(selected[0].item, selected[0].event);
X
X				    /* clear last item and selected[0] */
X
X				    selected[0].filled = FALSE;
X				    last_item.filled   = FALSE;
X
X				} else {
X    				    data = (Tiles *) panel_get(selected[0].item, PANEL_CLIENT_DATA);
X				    if ( value == data->value) {
X				        /* fill second and show confirm message */
X
X				        selected[1].item = item;
X				        selected[1].event.ie_locx = event->ie_locx;
X				        selected[1].event.ie_locy = event->ie_locy;
X				        selected[1].event.ie_time.tv_sec = event->ie_time.tv_sec;
X				        selected[1].event.ie_time.tv_usec = event->ie_time.tv_usec;
X
X				        selected[1].filled = TRUE;
X
X				        /* clear last item */
X
X				        last_item.filled = FALSE;
X
X					panel_set(message, PANEL_LABEL_STRING,
X							    "Please confirm. [Y] [] [N]",
X							   PANEL_SHOW_ITEM,
X							    TRUE, 0);
X
X       					window_set(message_panel, WIN_IGNORE_PICK_EVENTS,
X								   WIN_MOUSE_BUTTONS, 0, 0);
X       					window_set(message_panel, WIN_IGNORE_KBD_EVENT,
X								   WIN_ASCII_EVENTS, 0, 0);
X
X   					cursor_set(play_cursor, CURSOR_IMAGE, &confirm, 0);
X   					window_set(play_panel, WIN_CURSOR, play_cursor, 0);
X
X				    } else { /* beep at them */
X
X			    	        panel_cancel_preview(last_item.item, last_item.event);
X			    	        panel_cancel_preview(selected[0].item, selected[0].event);
X			    		last_item.filled = FALSE;
X			    		selected[0].filled = FALSE;
X				        window_bell(main_frame);
X
X				    }
X				}
X			    }
X		    	}
X		    }
X		}
X		break;
X
X	    case MS_MIDDLE:
X
X		if (event_is_up(event) && selected[0].filled) { /* request for help */
X
X			help_proc();
X		}
X
X		break;
X
X		/* and all else shall pass */
X    }
X}
X
Xvoid quit_proc()
X{
X    window_destroy(main_frame);
X}
X
Xvoid new_proc()
X{
X
X    seed = random() % 20011;
X    build_image(FALSE);
X    place_tiles(FALSE);
X}
X
Xvoid again_proc()
X{
X    build_image(TRUE);
X    place_tiles(FALSE);
X}
X
Xvoid undo_proc()
X
X{
X    if(undo_count < 0)
X	window_bell(main_frame);
X    else
X	remove_tiles(FALSE);
X}
X
Xvoid board_num_proc()
X{
X    sscanf((char *) panel_get(board_num, PANEL_VALUE), "%d", &seed);
X    build_image(FALSE);
X    place_tiles(FALSE);
X}
END_OF_event.c
if test 20252 -ne `wc -c <event.c`; then
    echo shar: \"event.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f mahjongg.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"mahjongg.c\"
else
echo shar: Extracting \"mahjongg.c\" \(26139 characters\)
sed "s/^X//" >mahjongg.c <<'END_OF_mahjongg.c'
X/*
X *	Copyright 1988, Mark Holm
X *			Exceptions
X *
X *	Acknowledgments to Dorothy Robinson for her artistic
X *	 abilities in drawing the icons and to Jim Batch for
X *	 technical support and graphical concepts (which I abandoned in favor
X *       of the easy way out).
X *
X *	Permission is given to copy and distribute for non-profit purposes.
X *
X */
X
X#ifndef lint
Xstatic char *rcs = "$header$ Copyright 1988 Mark Holm";
X#endif !lint
X
X/*
X * $log$
X */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/time.h>
X#include <sys/ioctl.h>
X#include <sys/file.h>
X#include <sun/fbio.h>
X#include <suntool/sunview.h>
X#include <suntool/panel.h>
X#include <suntool/canvas.h>
X#include <suntool/icon.h>
X#include <sunwindow/notify.h>
X#include <pixrect/pixrect.h>
X
X#include "mahjongg.h"
X
Xvoid			die();
Xvoid			build_image();
Xvoid			place_tiles();
XPixrect			*color_button();
X
X
X/* Black and white closed icon image */
X
Xstatic short		icon_image[] = {
X#include "mahjongg.icon"
X};
XDEFINE_ICON_FROM_IMAGE(icon, icon_image); /* Black and white icon */
Xstruct icon	*cicon;			  /* storage for color icon */
X
X/* externals */
X
Xextern void		quit_proc();
Xextern void		undo_proc();
Xextern void		new_proc();
Xextern void		again_proc();
Xextern void		help_proc();
Xextern void		board_num_proc();
Xextern void		play_back_proc();
Xextern void		play_event_proc();
X
Xextern short		stick_image[];
Xextern int		undo_count;
X
X/* overlap globals */
X
X
XFrame			main_frame;
XPanel			play_panel, message_panel;
XPanel_item		TL_hundred;
XPanel_item		TL_ten;
XPanel_item		TL_one;
XPanel_item		message;
XPanel_item		tile[144];
XPanel_item		tiles_left[3];
XCursor			play_cursor;
Xboolean			BandW = FALSE;
XTiles			*board[144];
XSelected		selected[2];
XSelected		last_item;
Xint			tile_count;
Xchar			state[256];
X
X/* local globals */
X
XPixwin			*frame_pw;
XPanel_item		tile_message;
XPanel_item		cp1;
XPanel_item		cp2;
XPanel_item		cp3;
XPanel_item		cp4;
XPanel_item		help;
XPanel_item		again;
XPanel_item		new;
XPanel_item		quit;
XPanel_item		undo;
XPanel_item		board_num;
Xstruct timeval		*tp;
Xstruct timezone		*tz;
Xint			seed;
X
X/* define color map */
X
X#include "color.h"
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X    struct pixfont	*panel_font;
X    struct pixfont	*dummy_font;
X	   int		 i;
X	   int		 middle;
X    struct fbtype	 fb;
X	   int		 open_stat;
X
X    /* determine type of frame buffer and set BandW accordingly */
X
X    open_stat = open("/dev/fb", O_RDONLY);
X    (void) ioctl(open_stat, FBIOGTYPE, &fb);
X
X    if ( (fb.fb_type == FBTYPE_SUN1BW) ||
X	 (fb.fb_type == FBTYPE_SUN2BW) ||
X	 (fb.fb_type == FBTYPE_SUN3BW) ||
X	 (fb.fb_type == FBTYPE_SUN4BW) )
X		BandW = TRUE;
X
X    /* initialize random number generator seed */
X
X    tp = (struct timeval *) malloc(sizeof(struct timeval));
X    tz = (struct timezone *) malloc(sizeof(struct timezone));
X    gettimeofday(tp, tz);
X    (void) initstate((unsigned) (tp->tv_sec % 255), state, 256); /* initialize random state array */
X    seed = RANDOM(20011);
X    free(tp);
X    free(tz);
X
X    /* create main frame */
X   
X    main_frame = window_create(NULL, FRAME,
X			       FRAME_SHOW_LABEL, FALSE,
X			       FRAME_SUBWINDOWS_ADJUSTABLE, FALSE,
X			       FRAME_ICON, &icon,
X			       FRAME_ARGC_PTR_ARGV, &argc, argv,
X			       WIN_HEIGHT, FRAME_Y_MAX,
X			       WIN_WIDTH, FRAME_X_MAX,
X			       0);
X
X    /* parse arguments */
X    for(argc--, argv++; argc > 0; argc--, argv++)
X	if (argv[0][0] = '-')
X	    switch (argv[0][1]) {
X	    case 'c': /* force color */
X		BandW = FALSE;
X		break;
X	    case 'b': /* force black and white */
X		BandW = TRUE;
X		break;
X	    case 'n': /* set board number */
X		if(argc-- == 0)
X		    die("Usage: mahjongg [-b] [-c] [-n #]\n", 0);
X		argv++;
X    		sscanf(argv[0] , "%d", &seed);
X		if (seed > 20011) {
X		    printf("Board numbers must be < 20011");
X		    seed %= 20011;
X		}
X		break;
X	    default:
X		die("Usage: mahjongg [-b] [-c] [-n #]\n", 0);
X		break;
X	    }
X	else
X	    die("Usage: mahjongg [-b] [-c] [-n #]\n", 0);
X	    
X    /* if color then apply color icon to window icon */
X
X    if(!BandW) {
X	cicon = (struct icon *) window_get(main_frame, FRAME_ICON);
X	cicon->ic_mpr = &cicon_image;
X     }
X
X    /* get pixwin to apply color maps */
X
X    frame_pw  = (Pixwin *) window_get(main_frame, WIN_PIXWIN, 0);
X
X    /* apply color maps to frame pixwin */
X
X    pw_setcmsname(frame_pw, "mahjongg");
X    pw_putcolormap(frame_pw, 0, MAX_COLORS+1, red, green, blue);
X    if (BandW)
X    	pw_putcolormap(frame_pw, 0, 1, &(red[WHITE]), &(green[WHITE]), &(blue[WHITE]));
X
X    /* set inheritable colors */
X
X    window_set(main_frame, FRAME_INHERIT_COLORS, TRUE, 0);
X
X    /* set up the panel on the right hand side */
X    
X    dummy_font = pf_open("/usr/lib/fonts/fixedwidthfonts/screen.r.7");
X    panel_font = pf_open("/usr/lib/fonts/fixedwidthfonts/screen.b.14");
X    message_panel = window_create(main_frame, PANEL,
X			  WIN_HEIGHT, MESS_Y_MAX,
X			  WIN_WIDTH, MESS_X_MAX,
X			  WIN_X, 0,
X			  WIN_Y, 0,
X			  WIN_FONT, dummy_font,
X			  0);
X
X    /* determine middle of panel */
X
X    middle = (MESS_X_MAX / 2);
X
X    /* create tile counters */
X
X    TL_hundred = panel_create_item(message_panel, PANEL_MESSAGE,
X				 PANEL_LABEL_IMAGE,
X				   (BandW) ? &NUM1 : &cNUM1,
X				 PANEL_ITEM_Y, ATTR_ROW(7),
X				 PANEL_ITEM_X, X_LOC,
X				 0);
X    TL_ten = panel_create_item(message_panel, PANEL_MESSAGE,
X				 PANEL_LABEL_IMAGE,
X				   (BandW) ? &NUM4 : &cNUM4,
X				 PANEL_ITEM_Y, ATTR_ROW(7),
X				 PANEL_ITEM_X, X_LOC +  W_BASE_TILE,
X				 0);
X    TL_one = panel_create_item(message_panel, PANEL_MESSAGE,
X				 PANEL_LABEL_IMAGE,
X				   (BandW) ? &NUM4 : &cNUM4,
X				 PANEL_ITEM_Y, ATTR_ROW(7),
X				 PANEL_ITEM_X, X_LOC + (W_BASE_TILE * 2),
X				 0);
X
X    /* create game label messages */
X
X    cp1 = panel_create_item(message_panel, PANEL_MESSAGE,
X			     PANEL_LABEL_FONT, panel_font,
X			     PANEL_LABEL_STRING, "MAHJONGG",
X			     PANEL_ITEM_Y, ATTR_ROW(1) - 11,
X			     PANEL_ITEM_X, middle - 65,
X			     0);
X    cp2 = panel_create_item(message_panel, PANEL_MESSAGE,
X			     PANEL_LABEL_FONT, dummy_font,
X			     PANEL_LABEL_STRING, "Copyright 1988",
X			     PANEL_ITEM_Y, ATTR_ROW(2),
X			     PANEL_ITEM_X, middle - 70,
X			     0);
X    cp3 = panel_create_item(message_panel, PANEL_MESSAGE,
X			     PANEL_LABEL_FONT, dummy_font,
X			     PANEL_LABEL_STRING, "Mark A. Holm",
X			     PANEL_ITEM_Y, ATTR_ROW(3),
X			     PANEL_ITEM_X, middle - 65,
X			     0);
X    cp3 = panel_create_item(message_panel, PANEL_MESSAGE,
X			     PANEL_LABEL_FONT, dummy_font,
X			     PANEL_LABEL_STRING, "Exceptions",
X			     PANEL_ITEM_Y, ATTR_ROW(4),
X			     PANEL_ITEM_X, middle - 60,
X			     0);
X    tile_message = panel_create_item(message_panel, PANEL_MESSAGE,
X                                     PANEL_LABEL_FONT, panel_font,
X                                     PANEL_LABEL_STRING, "Tiles Remaining",
X                                     PANEL_ITEM_Y, ATTR_ROW(5),
X                                     PANEL_ITEM_X,  X_LOC + 20,
X                                     0);
X
X    /* create seed item */
X
X    board_num = panel_create_item(message_panel, PANEL_TEXT,
X                                     PANEL_LABEL_FONT, panel_font,
X                                     PANEL_VALUE_FONT, panel_font,
X                                     PANEL_LABEL_STRING, "Board Number : ",
X				     PANEL_VALUE, "",
X                                     PANEL_ITEM_Y, ATTR_ROW(6),
X                                     PANEL_ITEM_X,  middle,
X				     PANEL_NOTIFY_PROC, board_num_proc,
X                                     0);
X
X    /* create control buttons */
X
X    help = panel_create_item(message_panel, PANEL_BUTTON,
X				 PANEL_ITEM_Y, ATTR_ROW(8),
X				 PANEL_ITEM_X, middle,
X                                 PANEL_LABEL_IMAGE,
X                                   color_button(panel_button_image(message_panel,
X								  "HELP",
X								  6,
X                                     			          panel_font),
X						CYAN),
X				 PANEL_NOTIFY_PROC, help_proc,
X				 0);
X
X    again = panel_create_item(message_panel, PANEL_BUTTON,
X                                 PANEL_LABEL_IMAGE,
X                                   color_button(panel_button_image(message_panel,
X								  "AGAIN",
X								  6,
X                                     			          panel_font),
X						YELLOW),
X				 PANEL_NOTIFY_PROC, again_proc,
X				 0);
X
X    new = panel_create_item(message_panel, PANEL_BUTTON,
X                                 PANEL_LABEL_IMAGE,
X                                   color_button(panel_button_image(message_panel,
X								  "NEW",
X								  6,
X                                     			          panel_font),
X						GREEN),
X				 PANEL_NOTIFY_PROC, new_proc,
X				 0);
X
X    undo = panel_create_item(message_panel, PANEL_BUTTON,
X                                 PANEL_LABEL_IMAGE,
X                                   color_button(panel_button_image(message_panel,
X								  "UNDO",
X								  6,
X                                     			          panel_font),
X						MAGENTA),
X				 PANEL_NOTIFY_PROC, undo_proc,
X				 PANEL_SHOW_ITEM, TRUE,
X				 0);
X
X    quit = panel_create_item(message_panel, PANEL_BUTTON,
X                                 PANEL_LABEL_IMAGE,
X                                   color_button(panel_button_image(message_panel,
X								  "QUIT",
X								  6,
X                                     			          panel_font),
X						RED),
X				 PANEL_NOTIFY_PROC, quit_proc,
X				 0);
X
X    /* place conceled message */
X
X    message = panel_create_item(message_panel, PANEL_MESSAGE,
X                                 PANEL_LABEL_FONT, panel_font,
X                                 PANEL_ITEM_Y, ATTR_ROW(10),
X				 PANEL_ITEM_X, middle,
X				 PANEL_LABEL_STRING, "",
X				 PANEL_SHOW_ITEM, FALSE,
X				 0);
X
X     /* create cursor for play panel*/
X
X    play_cursor = cursor_create(CURSOR_IMAGE, &stick,
X				CURSOR_XHOT, 8,
X				CURSOR_YHOT, 8,
X				0);
X
X    if (!BandW) {
X
X    /* invert the icon because we are reverse video */
X        for (i = 0; i < sizeof(stick_image)/sizeof(short); i++)
X            stick_image[i] ^= 0xFFFF;
X
X	cursor_set(play_cursor, CURSOR_OP,
X				 (PIX_SRC^PIX_DST) | PIX_COLOR( YELLOW ),
X				0);
X     }
X
X    /* set up panel for the play */
X    
X    play_panel = window_create(main_frame, PANEL,
X			   WIN_CONSUME_PICK_EVENTS,
X			    WIN_NO_EVENTS, WIN_MOUSE_BUTTONS, WIN_UP_EVENTS, WIN_LEFT_KEYS, 0,
X			   WIN_HEIGHT, PLAY_Y_MAX,
X			   WIN_WIDTH, PLAY_X_MAX,
X			   WIN_X, 0,
X			   WIN_Y, MESS_Y_MAX + BORDER,
X			   WIN_CURSOR, play_cursor,
X			   PANEL_PAINT, PANEL_NONE,
X			   PANEL_BACKGROUND_PROC, play_back_proc,
X			   PANEL_EVENT_PROC, play_event_proc,
X			   CANVAS_RETAINED, TRUE,
X			   0);
X
X	window_set(message_panel, WIN_INPUT_DESIGNEE,
X			   window_get(play_panel, WIN_DEVICE_NUMBER),
X			   0);
X
X    /* build board image */
X
X    build_image(FALSE);
X    place_tiles(TRUE);
X
X    /* start main processing */
X    		  
X    window_main_loop(main_frame);
X    exit(0);
X}
X
X
X/* die because of some UNIX error */
Xvoid die(message, pperr)
Xchar *message;
Xint pperr;
X{
X    fprintf(stderr, message);
X    if (pperr)
X	perror("mahjongg");
X    exit(1);
X}
X
Xvoid place_tiles(newboard)
Xboolean		newboard;
X
X{
X    int 	i;
X    int 	j;
X    int 	k;
X    int 	x_loc;
X    int 	y_loc;
X
X    /* check if not new and destroy existing panel buttons */
X
X    if (!newboard)
X	for(i = 0; i < 144; i++)
X		panel_destroy_item(tile[i]);
X
X    /* place tiles */
X
X        /* row 1 level 1 */
X
X	for(i = 0,
X	    x_loc = COL2;
X	    i < 12;
X	    i++,
X	    x_loc += W_BASE_TILE) 
X
X    		tile[i] = panel_create_item(play_panel, PANEL_BUTTON,
X						PANEL_LABEL_IMAGE,
X						 board[i]->image,
X						PANEL_ITEM_X,
X						 x_loc,
X				 		PANEL_ITEM_Y,
X						 ROW1,
X						PANEL_SHOW_ITEM,
X						 TRUE,
X						PANEL_CLIENT_DATA,
X						 (caddr_t) board[i],
X				 		0);
X
X	/* row 2 level 1 */
X
X	for(x_loc = COL4,
X	    j = 0;
X	    j < 8;
X	    j++,
X	    i++,
X	    x_loc += W_BASE_TILE) 
X
X    		tile[i] = panel_create_item(play_panel, PANEL_BUTTON,
X						PANEL_LABEL_IMAGE,
X						 board[i]->image,
X						PANEL_ITEM_X,
X						 x_loc,
X				 		PANEL_ITEM_Y,
X						 ROW2,
X						PANEL_SHOW_ITEM,
X						 TRUE,
X						PANEL_CLIENT_DATA,
X						 (caddr_t) board[i],
X				 		0);
X
X	/* row 3 level 1 */
X
X	for(x_loc = COL3,
X	    j = 0;
X	    j < 10;
X	    j++,
X	    i++,
X	    x_loc += W_BASE_TILE) 
X
X    		tile[i] = panel_create_item(play_panel, PANEL_BUTTON,
X						PANEL_LABEL_IMAGE,
X						 board[i]->image,
X						PANEL_ITEM_X,
X						 x_loc,
X				 		PANEL_ITEM_Y,
X						 ROW3,
X						PANEL_SHOW_ITEM,
X						 TRUE,
X						PANEL_CLIENT_DATA,
X						 (caddr_t) board[i],
X				 		0);
X
X	/* row 4 1/2 level 1 */
X
X	/* Left */
X
X    		tile[i] = panel_create_item(play_panel, PANEL_BUTTON,
X						PANEL_LABEL_IMAGE,
X						 board[i]->image,
X						PANEL_ITEM_X,
X						 COL1,
X				 		PANEL_ITEM_Y,
X						 ROW4pt5,
X						PANEL_SHOW_ITEM,
X						 TRUE,
X						PANEL_CLIENT_DATA,
X						 (caddr_t) board[i],
X				 		0);
X
X		i++; /* increment tile counter */
X
X	/* row 4 level 1 */
X
X	for(x_loc = COL2,
X	    j = 0;
X	    j < 12;
X	    j++,
X	    i++,
X	    x_loc += W_BASE_TILE) 
X
X    		tile[i] = panel_create_item(play_panel, PANEL_BUTTON,
X						PANEL_LABEL_IMAGE,
X						 board[i]->image,
X						PANEL_ITEM_X,
X						 x_loc,
X				 		PANEL_ITEM_Y,
X						 ROW4,
X						PANEL_SHOW_ITEM,
X						 TRUE,
X						PANEL_CLIENT_DATA,
X						 (caddr_t) board[i],
X				 		0);
X
X	/* row 5 level 1 */
X
X	for(x_loc = COL2,
X	    j = 0;
X	    j < 12;
X	    j++,
X	    i++,
X	    x_loc += W_BASE_TILE) 
X
X    		tile[i] = panel_create_item(play_panel, PANEL_BUTTON,
X						PANEL_LABEL_IMAGE,
X						 board[i]->image,
X						PANEL_ITEM_X,
X						 x_loc,
X				 		PANEL_ITEM_Y,
X						 ROW5,
X						PANEL_SHOW_ITEM,
X						 TRUE,
X						PANEL_CLIENT_DATA,
X						 (caddr_t) board[i],
X				 		0);
X	/* row 4 1/2 level 1 */
X
X	/* Right */
X
X    		tile[i] = panel_create_item(play_panel, PANEL_BUTTON,
X						PANEL_LABEL_IMAGE,
X						 board[i]->image,
X						PANEL_ITEM_X,
X						 COL14,
X				 		PANEL_ITEM_Y,
X						 ROW4pt5,
X						PANEL_SHOW_ITEM,
X						 TRUE,
X						PANEL_CLIENT_DATA,
X						 (caddr_t) board[i],
X				 		0);
X
X		i++; /* increment tile counter */
X
X    		tile[i] = panel_create_item(play_panel, PANEL_BUTTON,
X						PANEL_LABEL_IMAGE,
X						 board[i]->image,
X						PANEL_ITEM_X,
X						 COL15,
X				 		PANEL_ITEM_Y,
X						 ROW4pt5,
X						PANEL_SHOW_ITEM,
X						 TRUE,
X						PANEL_CLIENT_DATA,
X						 (caddr_t) board[i],
X				 		0);
X
X		i++; /* increment tile counter */
X
X	/* row 6 level 1 */
X
X	for(x_loc = COL3,
X	    j = 0;
X	    j < 10;
X	    j++,
X	    i++,
X	    x_loc += W_BASE_TILE) 
X
X    		tile[i] = panel_create_item(play_panel, PANEL_BUTTON,
X						PANEL_LABEL_IMAGE,
X						 board[i]->image,
X						PANEL_ITEM_X,
X						 x_loc,
X				 		PANEL_ITEM_Y,
X						 ROW6,
X						PANEL_SHOW_ITEM,
X						 TRUE,
X						PANEL_CLIENT_DATA,
X						 (caddr_t) board[i],
X				 		0);
X
X	/* row 7 level 1 */
X
X	for(x_loc = COL4,
X	    j = 0;
X	    j < 8;
X	    j++,
X	    i++,
X	    x_loc += W_BASE_TILE) 
X
X    		tile[i] = panel_create_item(play_panel, PANEL_BUTTON,
X						PANEL_LABEL_IMAGE,
X						 board[i]->image,
X						PANEL_ITEM_X,
X						 x_loc,
X				 		PANEL_ITEM_Y,
X						 ROW7,
X						PANEL_SHOW_ITEM,
X						 TRUE,
X						PANEL_CLIENT_DATA,
X						 (caddr_t) board[i],
X				 		0);
X
X        /* row 8 level 1 */
X
X	for(j = 0,
X	    x_loc = COL2;
X	    j < 12;
X	    j++,
X	    i++,
X	    x_loc += W_BASE_TILE) 
X
X    		tile[i] = panel_create_item(play_panel, PANEL_BUTTON,
X						PANEL_LABEL_IMAGE,
X						 board[i]->image,
X						PANEL_ITEM_X,
X						 x_loc,
X				 		PANEL_ITEM_Y,
X						 ROW8,
X						PANEL_SHOW_ITEM,
X						 TRUE,
X						PANEL_CLIENT_DATA,
X						 (caddr_t) board[i],
X				 		0);
X
X	/* rows 1-6 level 2 */
X
X	for(y_loc = ROW2 - B_TILE_SHADOW,
X	    j = 0;
X	    j < 6;
X	    j++,
X	    y_loc += H_BASE_TILE) 
X
X		for(x_loc = COL5 - S_TILE_SHADOW,
X		    k = 0;
X		    k < 6;
X		    i++,
X		    k++,
X		    x_loc += W_BASE_TILE) 
X
X    			tile[i] = panel_create_item(play_panel, PANEL_BUTTON,
X							PANEL_LABEL_IMAGE,
X							 board[i]->image,
X							PANEL_ITEM_X,
X							 x_loc,
X				 			PANEL_ITEM_Y,
X							 y_loc,
X							PANEL_SHOW_ITEM,
X							 TRUE,
X							PANEL_CLIENT_DATA,
X							 (caddr_t) board[i],
X				 			0);
X
X	/* rows 1-4 level 3 */
X
X	for(y_loc = ROW3 - (B_TILE_SHADOW * 2),
X	    j = 0;
X	    j < 4;
X	    j++,
X	    y_loc += H_BASE_TILE) 
X
X		for(x_loc = COL6 - (S_TILE_SHADOW * 2),
X		    k = 0;
X		    k < 4;
X		    i++,
X		    k++,
X		    x_loc += W_BASE_TILE) 
X
X    			tile[i] = panel_create_item(play_panel, PANEL_BUTTON,
X							PANEL_LABEL_IMAGE,
X							 board[i]->image,
X							PANEL_ITEM_X,
X							 x_loc,
X				 			PANEL_ITEM_Y,
X							 y_loc,
X							PANEL_SHOW_ITEM,
X							 TRUE,
X							PANEL_CLIENT_DATA,
X							 (caddr_t) board[i],
X				 			0);
X
X	/* rows 1-2 level 4 */
X	/* special case make messages instead of buttons */
X
X	for(y_loc = ROW4 - (B_TILE_SHADOW * 3),
X	    j = 0;
X	    j < 2;
X	    j++,
X	    y_loc += H_BASE_TILE) 
X
X		for(x_loc = COL7 - (S_TILE_SHADOW * 3),
X		    k = 0;
X		    k < 2;
X		    i++,
X		    k++,
X		    x_loc += W_BASE_TILE) 
X
X    			tile[i] = panel_create_item(play_panel, PANEL_BUTTON,
X							PANEL_LABEL_IMAGE,
X							 board[i]->image,
X							PANEL_ITEM_X,
X							 x_loc,
X				 			PANEL_ITEM_Y,
X							 y_loc,
X							PANEL_SHOW_ITEM,
X							 TRUE,
X							PANEL_CLIENT_DATA,
X							 (caddr_t) board[i],
X				 			0);
X
X	/* Cap tile */
X
X    		tile[i] = panel_create_item(play_panel, PANEL_BUTTON,
X						PANEL_LABEL_IMAGE,
X						 board[i]->image,
X						PANEL_ITEM_X,
X						 COL7pt5 - (S_TILE_SHADOW * 4),
X				 		PANEL_ITEM_Y,
X						 ROW4pt5 - (B_TILE_SHADOW * 4),
X						PANEL_SHOW_ITEM,
X						 TRUE,
X						PANEL_CLIENT_DATA,
X						 (caddr_t) board[i],
X				 		0);
X
X    /* paint panel */
X
X    panel_paint(play_panel, PANEL_NO_CLEAR);
X
X   /* clear stand_by message  and release input mask */
X
X   panel_set(message,   PANEL_SHOW_ITEM,
X	       		  FALSE,
X			 0);
X
X   window_set(message_panel, WIN_CONSUME_PICK_EVENTS,
X			      WIN_MOUSE_BUTTONS, 0,
X			      0);
X   window_set(message_panel, WIN_CONSUME_KBD_EVENT,
X			      WIN_ASCII_EVENTS, 0, 0);
X
X   cursor_set(play_cursor, CURSOR_IMAGE, &stick, 0);
X   window_set(play_panel, WIN_CURSOR, play_cursor, 0);
X
X}
X
Xvoid build_image(oldimage)
Xboolean oldimage;
X
X{
Xint 	i;
Xint 	j;
Xint	pool[42];
Xboolean ok;
Xboolean dir;
Xchar	seed_text[80];
X
X	/* initialize selected structures */
X
X        selected[0].filled = FALSE;
X        selected[1].filled = FALSE;
X        last_item.filled   = FALSE;
X        undo_count   	   = -1;
X
X        panel_set(message,   PANEL_SHOW_ITEM,
X			       FALSE,
X			      0);
X        panel_set(TL_hundred, PANEL_LABEL_IMAGE,
X			       (BandW) ? &NUM1 : &cNUM1,
X			      PANEL_SHOW_ITEM,
X			       TRUE,
X			      0);
X        panel_set(TL_ten    , PANEL_LABEL_IMAGE,
X			       (BandW) ? &NUM4 : &cNUM4,
X			      PANEL_SHOW_ITEM,
X			       TRUE,
X			      0);
X        panel_set(TL_one    , PANEL_LABEL_IMAGE,
X			       (BandW) ? &NUM4 : &cNUM4,
X			      0);
X
X	/* display current seed in text item */
X
X    	sprintf(seed_text, "%d", seed);
X    	panel_set(board_num, PANEL_VALUE, seed_text, 0);
X
X	/* show stand_by message while building image  and grab all input */
X
X	panel_set(message, PANEL_LABEL_STRING,
X			    "Building board. Please wait.",
X			   PANEL_SHOW_ITEM,
X			    TRUE, 0);
X
X       window_set(message_panel, WIN_IGNORE_PICK_EVENTS,
X			      WIN_MOUSE_BUTTONS, 0, 0);
X       window_set(message_panel, WIN_IGNORE_KBD_EVENT,
X			      WIN_ASCII_EVENTS, 0, 0);
X       cursor_set(play_cursor, CURSOR_IMAGE, &wait, 0);
X       window_set(play_panel, WIN_CURSOR, play_cursor, 0);
X
X	/* initialize random number counter */
X
X	(void) srandom(seed);
X
X	tile_count = 144;
X
X	/* initialize tile pool */
X	for(i = 0; i < 34; i++) pool[i] = 4;
X	for(; i < 42; i++) pool[i] = 1;
X
X	/* assign values to each location. Board is built from upper left *
X	 * to lower right, bottom to top. Exception are left tile for row *
X	 * 4pt5 is before rows 4 and 5, and right tiles for row 4.5 are   *
X	 * after rows 4 and 5                                             */
X
X	for(j = 0; j < 144; j++) {
X	    if (board[j] == NULL) /* intialize array */
X		board[j] = (Tiles *) malloc(sizeof(Tiles));
X
X	    if (!oldimage) { /* not repeating last board */
X
X		/* Randomly seed index into pool. Randomly *
X		 *  run up or down list until unused tile  *
X		 *  is found or end of list. If end of     *
X		 *  list reseed and run in opposite        *
X		 *  direction in list until unused tile is *
X		 *  found. If beginning of list found,     *
X		 *  start over. 			   */
X
X		ok = FALSE;
X		while (ok == FALSE) {
X			i = RANDOM(41);
X			/* Up, up, up! */
X			dir = random()&01;
X			while ((i < 42 || i >=0) && pool[i] == 0) (dir) ? i++ : i--;
X			if (i == 42 || i < 0) { /* Thud! Reverse march! */
X				i = RANDOM(41);
X				while ((i < 42 || i >= 0) && pool[i] == 0) (dir) ? i-- : i++;
X			}
X			if (i == 42 || i < 0) continue; /* Missed! try again */
X			pool[i]--;
X			ok = TRUE;
X		}
X
X		/* all flowers and all seasons */
X
X		board[j]->value = (i >= 34) ? ((i >= 38) ? 35 : 34) : i;
X		switch(i) {
X
X		case 0: board[j]->image = (BandW) ? &DOT1 : &cDOT1;
X			break;
X		case 1: board[j]->image = (BandW) ? &DOT2 : &cDOT2;
X			break;
X		case 2: board[j]->image = (BandW) ? &DOT3 : &cDOT3;
X			break;
X		case 3: board[j]->image = (BandW) ? &DOT4 : &cDOT4;
X			break;
X		case 4: board[j]->image = (BandW) ? &DOT5 : &cDOT5;
X			break;
X		case 5: board[j]->image = (BandW) ? &DOT6 : &cDOT6;
X			break;
X		case 6: board[j]->image = (BandW) ? &DOT7 : &cDOT7;
X			break;
X		case 7: board[j]->image = (BandW) ? &DOT8 : &cDOT8;
X			break;
X		case 8: board[j]->image = (BandW) ? &DOT9 : &cDOT9;
X			break;
X		case 9: board[j]->image = (BandW) ? &BAM1 : &cBAM1;
X			break;
X		case 10: board[j]->image = (BandW) ? &BAM2 : &cBAM2;
X			break;
X		case 11: board[j]->image = (BandW) ? &BAM3 : &cBAM3;
X			break;
X		case 12: board[j]->image = (BandW) ? &BAM4 : &cBAM4;
X			break;
X		case 13: board[j]->image = (BandW) ? &BAM5 : &cBAM5;
X			break;
X		case 14: board[j]->image = (BandW) ? &BAM6 : &cBAM6;
X			break;
X		case 15: board[j]->image = (BandW) ? &BAM7 : &cBAM7;
X			break;
X		case 16: board[j]->image = (BandW) ? &BAM8 : &cBAM8;
X			break;
X		case 17: board[j]->image = (BandW) ? &BAM9 : &cBAM9;
X			break;
X		case 18: board[j]->image = (BandW) ? &CHA1 : &cCHA1;
X			break;
X		case 19: board[j]->image = (BandW) ? &CHA2 : &cCHA2;
X			break;
X		case 20: board[j]->image = (BandW) ? &CHA3 : &cCHA3;
X			break;
X		case 21: board[j]->image = (BandW) ? &CHA4 : &cCHA4;
X			break;
X		case 22: board[j]->image = (BandW) ? &CHA5 : &cCHA5;
X			break;
X		case 23: board[j]->image = (BandW) ? &CHA6 : &cCHA6;
X			break;
X		case 24: board[j]->image = (BandW) ? &CHA7 : &cCHA7;
X			break;
X		case 25: board[j]->image = (BandW) ? &CHA8 : &cCHA8;
X			break;
X		case 26: board[j]->image = (BandW) ? &CHA9 : &cCHA9;
X			break;
X		case 27: board[j]->image = (BandW) ? &GRED : &cGRED;
X			break;
X		case 28: board[j]->image = (BandW) ? &REDD : &cREDD;
X			break;
X		case 29: board[j]->image = (BandW) ? &WHTD : &cWHTD;
X			break;
X		case 30: board[j]->image = (BandW) ? &EAST : &cEAST;
X			break;
X		case 31: board[j]->image = (BandW) ? &WEST : &cWEST;
X			break;
X		case 32: board[j]->image = (BandW) ? &SOUT : &cSOUT;
X			break;
X		case 33: board[j]->image = (BandW) ? &NORT : &cNORT;
X			break;
X		case 34: board[j]->image = (BandW) ? &AUT : &cAUT;
X			break;
X		case 35: board[j]->image = (BandW) ? &SUM : &cSUM;
X			break;
X		case 36: board[j]->image = (BandW) ? &SPR : &cSPR;
X			break;
X		case 37: board[j]->image = (BandW) ? &WIN : &cWIN;
X			break;
X		case 38: board[j]->image = (BandW) ? &ORC : &cORC;
X			break;
X		case 39: board[j]->image = (BandW) ? &MUM : &cMUM;
X			break;
X		case 40: board[j]->image = (BandW) ? &BAM : &cBAM;
X			break;
X		case 41: board[j]->image = (BandW) ? &PLM : &cPLM;
X			break;
X		}
X
X	}
X	/* establish default values */
X
X		board[j]->left_free     = FALSE;
X		board[j]->right_free    = FALSE;
X		board[j]->top_free      = TRUE;
X		board[j]->left_next[0]  = j - 1;
X		board[j]->left_next[1]  = 999;
X		board[j]->right_next[0] = j + 1;
X		board[j]->right_next[1] = 999;
X		board[j]->covered[0]    = 999;
X		board[j]->covered[1]    = 999;
X		board[j]->covered[2]    = 999;
X		board[j]->covered[3]    = 999;
X		board[j]->removed       = FALSE;
X
X	/* setup special cases */
X
X		switch (j) {
X		case 139:
X		case 141: 
X			board[j]->top_free = FALSE;
X		case 0:
X		case 12:
X		case 20:
X		case 30:
X		case 57:
X		case 67:
X		case 75:
X		case 87:
X		case 93:
X		case 99:
X		case 105:
X		case 111:
X		case 117:
X		case 123:
X		case 127:
X		case 131:
X		case 135:
X			board[j]->left_free = TRUE;
X			board[j]->left_next[0] = 999;
X			break;
X		case 140:
X		case 142:
X			board[j]->top_free = FALSE;
X		case 11:
X		case 19:
X		case 29:
X		case 56:
X		case 66:
X		case 74:
X		case 86:
X		case 92:
X		case 98:
X		case 104:
X		case 110:
X		case 116:
X		case 122:
X		case 126:
X		case 130:
X		case 134:
X		case 138:
X			board[j]->right_free = TRUE;
X			board[j]->right_next[0] = 999;
X			break;
X		case 143:
X			board[j]->right_free = TRUE;
X			board[j]->left_next[0] = 999;
X			board[j]->left_free = TRUE;
X			board[j]->right_next[0] = 999;
X			board[j]->covered[0] = 139;
X			board[j]->covered[1] = 140;
X			board[j]->covered[2] = 141;
X			board[j]->covered[3] = 142;
X			break;
X		case 42:
X			board[j]->right_next[0] = 55;
X			break;
X		case 43:
X			board[j]->left_next[0] = 30;
X			break;
X		case 55:
X			board[j]->left_next[1] = 42;
X			break;
X		}
X			
X	}
X
X	/* special case (did not fit in above) */
X
X	board[30]->right_next[1] = 43;
X
X	/* set top_free flags  and covered pointers */
X
X	for(i = 87, j = 13; i < 143; i++, j++) {
X		board[i]->covered[0] = j;
X		board[j]->top_free = FALSE;
X		switch(j) {
X			case 97:
X			case 103:
X			case 109:
X			case 129:
X				 j += 2;
X				 break;
X			case 18:
X			case 64:
X				 j += 3;
X				 break;
X			case 27:
X			case 39:
X				 j += 6;
X				 break;
X			case 51:
X				 j += 7;
X				 break;
X			case 73:
X				 j += 20;
X				 break;
X			case 115:
X				 j += 12;
X				 break;
X		}
X	}
X}
X
X/* This is the routine that returns the colored button image */
X
XPixrect *color_button(pr,color)
X  struct pixrect *pr;
X  int color;
X{
X  struct pixrect *color_pr;
X
X  if(pr == NULL)
X        return(NULL);
X
X  /* if running in b/w mode return same pixrect */
X  if (BandW)
X        return(pr);
X
X  /* make new pixrect */
X  color_pr = mem_create(pr->pr_size.x, pr->pr_size.y, 8);
X
X  /* copy pr to color_pr with color added */
X  pr_rop(color_pr, 0, 0, pr->pr_size.x, pr->pr_size.y,
X        PIX_SRC | PIX_COLOR( color ),
X        pr,0,0);
X
X  return(color_pr);
X}
END_OF_mahjongg.c
if test 26139 -ne `wc -c <mahjongg.c`; then
    echo shar: \"mahjongg.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 3 \(of 3\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 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