From decwrl!wyse!mips!zaphod.mps.ohio-state.edu!usc!cs.utexas.edu!rice!uw-beaver!zephyr.ens.tek.com!tekred!saab!billr Sat May 19 13:03:33 PDT 1990
Article 900 of comp.sources.games:
Path: decwrl!wyse!mips!zaphod.mps.ohio-state.edu!usc!cs.utexas.edu!rice!uw-beaver!zephyr.ens.tek.com!tekred!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v09i076:  umoria3 - single player dungeon simulation (ver. 5.2), Part21/31
Message-ID: <5611@tekred.CNA.TEK.COM>
Date: 17 May 90 16:25:23 GMT
Sender: news@tekred.CNA.TEK.COM
Lines: 2969
Approved: billr@saab.CNA.TEK.COM

Submitted-by: wilson@ernie.Berkeley.EDU (Jim Wilson)
Posting-number: Volume 9, Issue 76
Archive-name: umoria3/Part21
Supersedes: umoria2: Volume 5, Issue 32-37,41-52,87



#! /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 21 (of 31)."
# Contents:  mac/mac.c source/store2.c util/mc/attribut.txt
# Wrapped by billr@saab on Wed May 16 11:54:36 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'mac/mac.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mac/mac.c'\"
else
echo shar: Extracting \"'mac/mac.c'\" \(29254 characters\)
sed "s/^X//" >'mac/mac.c' <<'END_OF_FILE'
X/* Stuff for the Macintosh to make Moria work */
X/* Needs to be better organized:  Maybe split into several files */
X/* Contains some used routines from 4.87 */
X
X#include <types.h>
X#include <controls.h>
X#include <dialogs.h>
X#include <memory.h>
X#include <resources.h>
X#include <files.h>
X#include <segload.h>
X#include <packages.h>
X#include <menus.h>
X#include <osutils.h>
X#include <sysequ.h>
X
X#include <scrnmgr.h>
X#include <dumpres.h>
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <strings.h>
X#include <setjmp.h>
X
X#include "constant.h"
X#include "config.h"
X#include "types.h"
X#include "externs.h"
X#include "macrsrc.h"
X
Xint GetCommandSet(Handle theData);
Xint GetTextEditor(Handle theData);
X
Xvoid DoMacHelp(void), DoKillsDlg(void);
X
Xstatic int game_flag;
Xstatic int exit_code;
X
Xstatic short savedir, applvrefnum;
X
Xstatic char **save_chars, **save_attrs;
Xstatic int save_cursor_h, save_cursor_v;
X
X/* global flags */
Xextern int search_flag;		/* Player is searching	*/
X
X#define PATHLEN					256
X
X#define CODE_IGNORE				0
X#define CODE_PASSTHRU			1
X#define CODE_KEYPAD				2
X#define CODE_ARROW				3
X#define CODE_ENTER				4
X
Xstatic unsigned char codetable[0x80] = {
X	/*				0	1	2	3	4	5	6	7	8	9	A	B	C	D	E	F	*/
X	/*				-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	*/
X	/* [00] */		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,
X	/* [10] */		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,
X	/* [20] */		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,
X	/* [30] */		0,	1,	1,	1,	1,	1,	1,	0,	0,	0,	0,	0,	0,	0,	0,	1,
X	/* [40] */		1,	1,	3,	1,	1,	1,	3,	1,	3,	1,	1,	1,	4,	3,	1,	1,
X	/* [50] */		1,	1,	1,	2,	2,	2,	2,	2,	2,	2,	1,	2,	2,	1,	1,	1,
X	/* [60] */		0,	0,	0,	0,	0,	0,	1,	0,	1,	0,	1,	0,	1,	0,	1,	0,
X	/* [70] */		1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	3,	3,	3,	3,	1
X};
X
X#define ARROW_UP_1				0x4D
X#define ARROW_DOWN_1			0x48
X#define ARROW_LEFT_1			0x46
X#define ARROW_RIGHT_1			0x42
X
X#define ARROW_UP_2				0x7E
X#define ARROW_DOWN_2			0x7D
X#define ARROW_LEFT_2			0x7B
X#define ARROW_RIGHT_2			0x7C
X
X#define CMDSET_TYPE				'CNFG'
X#define CMDSET_ID				256
X
X#define TE_TYPE					'CNFG'
X#define TE_ID					257
X
X#define SPIN_TICKS				15
X
Xstatic int editor, cmdsetopt;
X
Xstatic jmp_buf jb;
X
X#define FM_NEW					1
X#define FM_OPEN					2
X#define FM_SAVE					4
X#define FM_SAVE_AS				5
X#define FM_QUIT					7
X
X#define AM_HELP					1
X#define AM_CMD_SET				2
X#define AM_TEXT_ED				3
X#define AM_SCORES				5
X
X#define KEY_UNKNOWN				0xFF
X#define KEY_DIR					0x90
X#define KEY_DIR_SHIFT			0xA0
X#define KEY_DIR_CONTROL			0xB0
X
X#define NEXT_FINDER				1
X#define NEXT_NEW				2
X#define NEXT_OPEN				3
X#define NEXT_WAIT				4
X#define NEXT_QUIT				5
X
Xint savefileset;
Xchar savefilename[64];
Xshort savefilevol;
X
X#define sqc_dlg_id				258
X#define sqc_save_item			1
X#define sqc_quit_item			2
X#define sqc_cancel_item			3
X#define sqc_defbrd_item			4
X
X#define code_enter				0x03
X#define code_return				0x0D
X
X#define errAlrtID				1024
X
Xstatic short sqcdefault_item;
Xstatic Handle sqcdefault_handle;
X
Xstatic int save_cmd_level, file_menu_level, app_menu_level;
Xstatic int save_cmd_enabled, file_menu_enabled, app_menu_enabled;
X
X#if 0
X/* this stuff is no longer used */
X
X#define malloc_zone_size		0x1000
X
Xstatic THz malloc_zone;
X
Xvoid init_malloc_zone()
X
X{
X	THz theOldZone;
X	
X	theOldZone = GetZone();
X	
X	InitZone(NULL, 64, (Ptr)((int) malloc_zone + malloc_zone_size), (Ptr) malloc_zone);
X	
X	SetZone(theOldZone);
X	
X	return;
X}
X
Xvoid *mac_malloc(n)
Xunsigned n;
X
X{
X	THz theOldZone;
X	void *theNewPtr;
X	
X	theOldZone = GetZone();
X	SetZone(malloc_zone);
X	
X	theNewPtr = (void *) NewPtrClear((Size) n);
X	
X	SetZone(theOldZone);
X	
X	return(theNewPtr);
X}
X
Xvoid mac_free(p)
Xvoid *p;
X
X{
X#if 0
X	THz theOldZone;
X	
X	theOldZone = GetZone();
X	SetZone(malloc_zone);
X	
X	DisposPtr((Ptr) p);
X	
X	SetZone(theOldZone);
X#else
X#pragma unused(p)
X#endif
X	
X	return;
X}
X
X#endif
X
Xint mac_time()
X
X{
X	int now;
X	
X	GetDateTime((unsigned int *) &now);
X	return(now);
X}
X
Xvoid alert_error(message)
Xchar *message;
X
X{
X	Str255 pstr;
X	
X	strncpy(pstr, message, 255);
X	pstr[255] = '\0';
X	(void) c2pstr(pstr);
X	
X	ParamText(pstr, NULL, NULL, NULL);
X	
X	DoScreenALRT(errAlrtID, akStop, fixHalf, fixHalf);
X	
X	return;
X}
X
Xvoid fatal_error(message)
Xchar *message;
X
X{
X	alert_error(message);
X	exit(0);
X}
X
Xchar *truncstr(pstr, wid)
Xchar *pstr;
Xshort wid;
X
X{
X	unsigned char len;
X	
X	if (StringWidth(pstr) > wid) {
X		len = (unsigned char) pstr[0];
X		if (len > 0) pstr[len] = '\311';
X		while ( (len > 1) && (StringWidth(pstr) > wid) ) {
X			pstr[0] = (char) --len;
X			pstr[len] = '\311';
X		}
X	}
X	
X	return(pstr);
X}
X
Xvoid idle()
X
X{
X	int redraw;
X	
X	redraw = FALSE;
X	
X	if ((!save_cmd_enabled) && (save_cmd_level > 0)) {
X		EnableItem((MenuHandle) GetFileMHandle(), FM_SAVE);
X		EnableItem((MenuHandle) GetFileMHandle(), FM_SAVE_AS);
X		save_cmd_enabled = TRUE;
X	}
X	else if ((save_cmd_enabled) && (save_cmd_level <= 0)) {
X		DisableItem((MenuHandle) GetFileMHandle(), FM_SAVE);
X		DisableItem((MenuHandle) GetFileMHandle(), FM_SAVE_AS);
X		save_cmd_enabled = FALSE;
X	}
X	
X	if ((!file_menu_enabled) && (file_menu_level > 0)) {
X		EnableItem((MenuHandle) GetFileMHandle(), 0);
X		file_menu_enabled = TRUE;
X		redraw = TRUE;
X	}
X	else if ((file_menu_enabled) && (file_menu_level <= 0)) {
X		DisableItem((MenuHandle) GetFileMHandle(), 0);
X		file_menu_enabled = FALSE;
X		redraw = TRUE;
X	}
X	
X	if ((!app_menu_enabled) && (app_menu_level > 0)) {
X		EnableItem((MenuHandle) GetAppMHandle(), 0);
X		app_menu_enabled = TRUE;
X		redraw = TRUE;
X	}
X	else if ((app_menu_enabled) && (app_menu_level <= 0)) {
X		DisableItem((MenuHandle) GetAppMHandle(), 0);
X		app_menu_enabled = FALSE;
X		redraw = TRUE;
X	}
X	
X	if (redraw)
X		DrawMenuBar();
X		
X	IdleScreenMgr();
X}
X
Xint macgetkey(ch, nowait)
Xchar *ch;
Xint nowait;
X
X{
X	char keycode, modifiers, ascii;
X	int h, v;
X	
X	do {
X	
X		if (nowait) {
X			idle();
X			if (!GetScreenKeys(&keycode, &modifiers, &ascii, &h, &v)) return(FALSE);
X		}
X		else {
X			do {
X				idle();
X			} while (!GetScreenKeys(&keycode, &modifiers, &ascii, &h, &v));
X		}
X		
X	} while ( (modifiers & maskModMouse) || (codetable[keycode] == CODE_IGNORE) );
X	
X	if (ascii > 0x7F) ascii = KEY_UNKNOWN;
X	
X	switch (codetable[keycode]) {
X	
X		case CODE_KEYPAD:
X			if ((ascii >= '1') && (ascii <= '9')) {
X				ascii -= '0';
X				if (modifiers & maskModControl)
X					ascii += KEY_DIR_CONTROL;
X				else if (modifiers & maskModShift)
X					ascii += KEY_DIR_SHIFT;
X				else
X					ascii += KEY_DIR;
X			}
X			break;
X			
X		case CODE_ARROW:
X			switch (keycode) {
X				case ARROW_UP_1: case ARROW_UP_2:
X					ascii = 8;
X					break;
X				case ARROW_DOWN_1: case ARROW_DOWN_2:
X					ascii = 2;
X					break;
X				case ARROW_LEFT_1: case ARROW_LEFT_2:
X					ascii = 4;
X					break;
X				case ARROW_RIGHT_1: case ARROW_RIGHT_2:
X					ascii = 6;
X					break;
X				default:
X					ascii = 5;
X					break;
X			}
X			if (modifiers & maskModControl)
X				ascii += KEY_DIR_CONTROL;
X			else if (modifiers & maskModShift)
X				ascii += KEY_DIR_SHIFT;
X			else
X				ascii += KEY_DIR;
X			break;
X			
X		case CODE_ENTER:
X			ascii = '\r';
X			break;
X			
X	}
X	
X	if (ch != NULL) *ch = ascii;
X	
X	return(TRUE);
X}
X
Xint extractdir(ch, shift_flag, ctrl_flag)
Xchar ch;
Xint *shift_flag;
Xint *ctrl_flag;
X
X{
X	int rc;
X	
X	if ((ch & 0xF0) == KEY_DIR) {
X		*shift_flag = FALSE;
X		*ctrl_flag = FALSE;
X		rc = ch & 0x0F;
X	}
X	else if ((ch & 0xF0) == KEY_DIR_SHIFT) {
X		*shift_flag = TRUE;
X		*ctrl_flag = FALSE;
X		rc = ch & 0x0F;
X	}
X	else if ((ch & 0xF0) == KEY_DIR_CONTROL) {
X		*shift_flag = FALSE;
X		*ctrl_flag = TRUE;
X		rc = ch & 0x0F;
X	}
X	else
X		rc = -1;
X		
X	return(rc);
X}
X
Xvoid mac_save_screen()
X
X{
X	Rect screen;
X	
X	screen.left = screen.top = 0;
X	screen.right = SCRN_COLS;
X	screen.bottom = SCRN_ROWS;
X	
X	HLock((Handle) save_chars);
X	HLock((Handle) save_attrs);
X	
X	GetScreenImage(*save_chars, *save_attrs, SCRN_COLS, &screen, 0, 0);
X	GetScreenCursor(&save_cursor_h, &save_cursor_v);
X	
X	HUnlock((Handle) save_chars);
X	HUnlock((Handle) save_attrs);
X	
X	return;
X}
X
X/* This restore routine only touches as much of the screen as necessary. */
X
Xvoid mac_restore_screen()
X
X{
X	Rect screen;
X	int v;
X	char chars[SCRN_COLS], attrs[SCRN_COLS];
X	char *c, *a, *c1, *c2, *a1, *a2;
X	
X	HLock((Handle) save_chars);
X	HLock((Handle) save_attrs);
X	
X	c = *save_chars;
X	a = *save_attrs;
X	
X	screen.top = 0;
X	screen.bottom = 1;
X	
X	for (v = 0; v < SCRN_ROWS; v++) {
X	
X		screen.left = 0;
X		screen.right = SCRN_COLS;
X		
X		GetScreenImage(chars, attrs, SCRN_COLS, &screen, 0, v);
X		
X		c1 = chars;
X		c2 = c;
X		
X		a1 = attrs;
X		a2 = a;
X		
X		while (screen.left < SCRN_COLS) {
X			if (*c1++ != *c2++) break;
X			if (*a1++ != *a2++) break;
X			++screen.left;
X		}
X		
X		c1 = chars + SCRN_COLS;
X		c2 = c + SCRN_COLS;
X		
X		a1 = attrs + SCRN_COLS;
X		a2 = a + SCRN_COLS;
X		
X		while (screen.right > screen.left) {
X			if (*--c1 != *--c2) break;
X			if (*--a1 != *--a2) break;
X			--screen.right;
X		}
X		
X		if (screen.right > screen.left)
X			DSetScreenImage(c, a, SCRN_COLS, &screen, screen.left, v);
X			
X		c += SCRN_COLS;
X		a += SCRN_COLS;
X		
X	}
X	
X	DSetScreenCursor(save_cursor_h, save_cursor_v);
X	
X	HUnlock((Handle) save_chars);
X	HUnlock((Handle) save_attrs);
X	
X	return;
X}
X
Xvoid mac_beep()
X
X{
X	SysBeep(15);
X	return;
X}
X
Xvoid macbeginwait()
X
X{
X	BeginScreenWait(SPIN_TICKS);
X	return;
X}
X
Xvoid macendwait()
X
X{
X	EndScreenWait();
X	return;
X}
X
XOSErr GetDirID(wdVRefNum, vRefNum, dirID)
Xshort wdVRefNum;
Xshort *vRefNum;
Xint *dirID;
X
X{
X	OSErr err;
X	WDPBRec wdpb;
X	
X	wdpb.ioNamePtr = NULL;
X	wdpb.ioVRefNum = wdVRefNum;
X	wdpb.ioWDIndex = 0;
X	wdpb.ioWDProcID = 0;
X	wdpb.ioWDVRefNum = 0;
X	err = PBGetWDInfo(&wdpb, false);
X	
X	if (!err) {
X		*vRefNum = wdpb.ioWDVRefNum;
X		*dirID = wdpb.ioWDDirID;
X	}
X	
X	return(err);
X}
X
XOSErr MakePath(vRefNum, dirID, fName, pathName)
Xshort vRefNum;
Xint dirID;
Xchar *fName;
Xchar *pathName;
X
X{
X	char buf[PATHLEN], *bufptr;
X	int len;
X	OSErr err;
X	Str255 vNameBuf;
X	CInfoPBRec cipb;
X	
X	bufptr = buf + PATHLEN;
X	
X	*--bufptr = '\0';
X	
X	if (fName != NULL) {
X		len = strlen(fName);
X		strncpy(bufptr -= len, fName, len);
X	}
X	
X	cipb.dirInfo.ioNamePtr = vNameBuf;
X	cipb.dirInfo.ioVRefNum = vRefNum;
X	cipb.dirInfo.ioFDirIndex = -1;
X	
X	do {
X		cipb.dirInfo.ioDrDirID = dirID;
X		err = PBGetCatInfo(&cipb, false);
X		if (!err) {
X			*--bufptr = ':';
X			len = strlen(p2cstr(vNameBuf));
X			strncpy(bufptr -= len, vNameBuf, len);
X			dirID = cipb.dirInfo.ioDrParID;
X		}
X	} while ( (!err) && (dirID != fsRtParID) );
X	
X	strcpy(pathName, bufptr);
X	
X	return(err);
X}
X
Xvoid checkdebugger()
X
X{
X	if (((char *) KeyMapLM)[6] & 0x80) Debugger();			/* if command key is down */
X	
X	return;
X}
X
Xvoid getstack(request)
Xint request;
X
X{
X	int cursize;
X	int newlimit;
X	
X	cursize = (*((int *) CurStackBase) - *((int *) ApplLimit)) - 8;
X	if (cursize < request) {
X		newlimit = (*((int *) CurStackBase) - request) - 8;
X		if (newlimit > *((int *) HeapEnd)) *((int *) ApplLimit) = newlimit;
X	}
X	
X	return;
X}
X
Xvoid sfposition(vrefnum)
Xshort vrefnum;
X
X{
X	short v;
X	int d;
X	
X	GetDirID(vrefnum, &v, &d);
X	*((short *) SFSaveDisk) = -v;
X	*((int *) CurDirStore) = d;
X	
X	return;
X}
X
Xint doputfile(prompt, fname, vrefnum)
Xchar *prompt;
Xchar *fname;
Xshort *vrefnum;
X
X{
X	char p[256], f[256];
X	SFReply reply;
X	Point loc;
X	int h, v;
X	
X	CenterScreenDLOG(putDlgID, fixHalf, fixThird, &h, &v);
X	
X	loc.h = (short) h;
X	loc.v = (short) v;
X	
X	strncpy(p, prompt, 255);
X	strncpy(f, fname, 255);
X	p[255] = '\0';
X	f[255] = '\0';
X	c2pstr(p);
X	c2pstr(f);
X	
X	SFPutFile(loc, p, f, NULL, &reply);
X	
X	if (reply.good) {
X		p2cstr(reply.fName);
X		strcpy(fname, reply.fName);
X		*vrefnum = reply.vRefNum;
X	}
X	
X	return(reply.good);
X}
X
Xint asksavegame(ask)
Xint ask;
X
X{
X	int rc;
X	
X	if (!ask && savefileset)
X		rc = TRUE;
X		
X	else {
X		rc = doputfile("Save game as:", savefilename, &savefilevol);
X		if (rc) savefileset = TRUE;
X	}
X	
X	return(rc);
X}
X
Xstatic pascal Boolean savefilefilter(pb)
XParmBlkPtr pb;
X
X{
X	OSType fdtype, fdcreator;
X	
X	fdtype = pb->fileParam.ioFlFndrInfo.fdType;
X	fdcreator = pb->fileParam.ioFlFndrInfo.fdCreator;
X	
X	return(!((fdcreator == MORIA_FCREATOR) && (fdtype == SAVE_FTYPE)));
X}
X
Xint dogetfile(fname, vrefnum)
Xchar *fname;
Xshort *vrefnum;
X
X{
X	SFTypeList types;
X	SFReply reply;
X	Point loc;
X	int h, v;
X	
X	CenterScreenDLOG(getDlgID, fixHalf, fixThird, &h, &v);
X	
X	loc.h = (short) h;
X	loc.v = (short) v;
X	
X	types[0] = SAVE_FTYPE;
X	
X	SFGetFile(loc, NULL, savefilefilter, 1, types, NULL, &reply);
X	
X	if (reply.good) {
X		p2cstr(reply.fName);
X		strcpy(fname, reply.fName);
X		*vrefnum = reply.vRefNum;
X	}
X	
X	return(reply.good);
X}
X
Xstatic pascal Boolean sqcfilter(dlg, evt, item)
XDialogPtr dlg;
XEventRecord *evt;
Xshort *item;
X
X{
X#pragma unused(dlg)
X	Boolean rc;
X	char key;
X	
X	rc = FALSE;
X	
X	if (evt->what == keyDown) {
X		key = evt->message & charCodeMask;
X		if ( (key == code_enter) || (key == code_return) ) {
X			rc = TRUE;
X			HiliteControl((ControlHandle) sqcdefault_handle, inButton);
X			*item = sqcdefault_item;
X		}
X	}
X	
X	return(rc);
X}
X
Xshort currentdirectory()
X
X{
X	short vrefnum;
X	
X	(void) GetVol(NULL, &vrefnum);
X	return(vrefnum);
X}
X
Xvoid changedirectory(vrefnum)
Xshort vrefnum;
X
X{
X	(void) GetVol(NULL, &savedir);
X	(void) SetVol(NULL, vrefnum);
X	return;
X}
X
Xvoid appldirectory()
X
X{
X	(void) GetVol(NULL, &savedir);
X	(void) SetVol(NULL, applvrefnum);
X	return;
X}
X
Xvoid restoredirectory()
X
X{
X	(void) SetVol(NULL, savedir);
X	return;
X}
X
Xvoid mac_helpfile(filename, wait)
Xchar *filename;
Xint wait;
X
X{
X	Str255 temp;
X	short apRefNum;
X	Handle apParam;
X	FILE *file;
X	int i, done;
X	char ch;
X	Rect area;
X	
X	GetAppParms(temp, &apRefNum, &apParam);
X	
X	appldirectory();
X	file = fopen(p2cstr(temp), "r");
X	restoredirectory();
X	
X	if (file != NULL) {
X	
X		while (!feof(file))
X			if (fgets (temp, 255, file) != NULL)
X				if (temp[0] == '#')
X					if (strstr(temp, filename) != NULL)
X						break;
X						
X		if (feof(file)) {
X			(void) fclose(file);
X			file = NULL;
X		}
X		
X	}
X	
X	if (file == NULL) {
X		sprintf(temp, "Cannot find text file: %s", filename);
X		alert_error(temp);
X	}
X	
X	else {
X	
X		area.left = area.top = 0;
X		area.right = SCRN_COLS;
X		area.bottom = SCRN_ROWS;
X		
X		if (wait)
X			mac_save_screen();
X		
X		done = FALSE;
X		
X		while ((!done) && (!feof(file))) {
X			DEraseScreen(&area);
X			for (i = 0; (!done) && (i < SCRN_ROWS - 1); i++)
X				if ((fgets(temp, 255, file) != NULL) && (temp[0] != '#'))
X					DSetScreenString(temp, 0, i);
X				else
X					done = TRUE;
X			if (wait) {
X				DSetScreenCursor(20, SCRN_ROWS - 1);
X				DWriteScreenString(
X					done ? 
X						"[Press any key to continue.]" :
X						"[Press any key for next page or ESC to abort.]");
X				macgetkey(&ch, FALSE);
X				if (ch == ESCAPE)
X					done = TRUE;
X			}
X		}
X		
X		if (wait)
X			mac_restore_screen();
X		
X		fclose(file);
X		
X	}
X	
X	return;
X}
X
Xchar *nextstring(loc)
Xchar **loc;
X
X{
X	char *str;
X	unsigned char len;
X	
X	len = *((unsigned char *) (*loc));
X	str = p2cstr(*loc);
X	*loc += len + 1;
X	
X	return(str);
X}
X
X#if 0
X/* no longer used */
Xint allocmalloczone(restart)
Xint restart;
X
X{
X	int rc;
X	
X	if (!restart) {
X		malloc_zone = (THz) NewPtr(malloc_zone_size);
X		rc = malloc_zone != NULL;
X	}
X	else
X		rc = TRUE;
X		
X	if (rc && !restart)
X		init_malloc_zone();
X		
X	return(rc);
X}
X#endif
X
Xint allocsavearea(restart)
Xint restart;
X
X{
X	int rc;
X	
X	if (!restart) {
X		save_chars = (char **) NewHandle(SCRN_ROWS * SCRN_COLS);
X		save_attrs = (char **) NewHandle(SCRN_ROWS * SCRN_COLS);
X		rc = (save_chars != NULL) && (save_attrs != NULL);
X	}
X	else
X		rc = TRUE;
X		
X	return(rc);
X}
X
Xint setupmem(restart)
Xint restart;
X
X{
X	int i;
X	memtable_type *m;
X	
X	for (i = 0, m = memtable; i < MAX_PTRS; i++, m++) {
X	
X		if (!restart) {
X			*m->memPtr = (char *) NewPtrClear(m->elemCnt * m->elemSiz);
X			if (*m->memPtr == NULL) return(FALSE);
X		}
X		
X		else if (m->restartFlag) {
X			memset(*m->memPtr, 0, m->elemCnt * m->elemSiz);
X		}
X		
X	}
X	
X	return(TRUE);
X}
X
Xint getresources(restart)
Xint restart;
X
X{
X	int i, rc;
X	restable_type *r;
X	
X	for (i = 0, r = restable; i < MAX_RESOURCES; i++, r++) {
X	
X		if (!restart) *r->memPtr = NULL;
X		
X		if ( (!restart) || (r->restartFlag) ) {
X		
X			rc = LoadRes(
X				r->memPtr,
X				r->resType, r->resID,
X				r->elemCnt, r->elemSiz,
X				r->strProc);
X				
X			if (!rc) return(FALSE);
X			
X		}
X		
X	}
X	
X	return(TRUE);
X}
X
Xint getrestart(restart)
Xint restart;
X
X{
X	int i, rc;
X	unsigned size;
X	char *p, *q;
X	
X	if (restart) {
X	
X		size = 0;
X		for (i = 0; i < MAX_RESTART; i++) size += restart_vars[i].size;
X		
X		p = NULL;
X		
X		rc = LoadRes(
X			&p,
X			restartRsrc, restart_id,
X			1, size,
X			NULL);
X			
X		if (!rc) return(FALSE);
X		
X		q = p;
X		for (i = 0; i < MAX_RESTART; i++) {
X			BlockMove(q, restart_vars[i].ptr, restart_vars[i].size);
X			q += restart_vars[i].size;
X		}
X		
X		DisposPtr(p);
X		
X	}
X	
X	return(TRUE);
X}
X
Xint clearvars(restart)
Xint restart;
X
X{
X	int i;
X	clrtable_type *c;
X	
X	if (restart)
X		for (i = 0, c = clrtable; i < MAX_CLRS; i++, c++)
X			memset(c->ptr, 0, c->size);
X	
X	return(TRUE);
X}
X
Xunsigned sleep(time)
Xunsigned time;
X
X{
X#pragma unused(time)
X	idle();
X	return(0);
X}
X
Xchar *makefilename(buffer, suffix, append)
Xchar *buffer, *suffix;
Xint append;
X
X
X{
X	int len;
X	char *p;
X	
X	len = strlen(py.misc.name) + ((append) ? strlen(suffix)+3 : 0);
X	
X	if ( (strlen(py.misc.name) == 0) || (len > 31) )
X		strcpy(buffer, suffix);
X		
X	else {
X		strcpy(buffer, py.misc.name);
X		if (append) {
X			strcat(buffer, "'s ");
X			strcat(buffer, suffix);
X		}
X		for (p = buffer; *p; p++)
X			if (*p == ':') *p = '.';
X	}
X	
X	return(buffer);
X}
X
Xvoid initsavedefaults()
X
X{
X	savefileset = FALSE;
X	
X	(void) makefilename(savefilename, "Save File", FALSE);
X	savefilevol = currentdirectory();
X	
X	return;
X}
X
Xvoid setsavedefaults(name, vol)
Xchar *name;
Xshort vol;
X
X{
X	savefileset = TRUE;
X	
X	strncpy(savefilename, name, 63);
X	savefilename[63] = '\0';
X	
X	savefilevol = vol;
X	
X	return;
X}
X
Xint getsavedefaults(name, vol)
Xchar *name;
Xshort *vol;
X
X{
X	strcpy(name, savefilename);
X	*vol = savefilevol;
X	
X	return(savefileset);
X}
X
Xint getfinderfile()
X
X{
X	short message, count, i;
X	AppFile appfile;
X	
X	CountAppFiles(&message, &count);
X	
X	for (i = 1; i <= count; i++) {
X		GetAppFiles(i, &appfile);
X		if (appfile.fType == SAVE_FTYPE) break;
X	}
X	
X	if (i <= count) {
X		setsavedefaults(p2cstr(appfile.fName), appfile.vRefNum);
X	}
X	
X	return(i <= count);
X}
X
Xint setfileinfo(fname, vrefnum, ftype)
Xchar *fname;
Xshort vrefnum;
Xint ftype;
X
X{
X	int fcreator;
X	char temp[64];
X	FileParam pb;
X	OSErr err;
X	
X	fcreator = (ftype != INFO_FTYPE) ? MORIA_FCREATOR : editor;
X	
X	strcpy(temp, fname);
X	(void) c2pstr(temp);
X	
X	pb.ioCompletion = NULL;
X	pb.ioNamePtr = temp;
X	pb.ioVRefNum = vrefnum;
X	pb.ioFVersNum = 0;
X	pb.ioFDirIndex = 0;
X	
X	err = PBGetFInfo((ParmBlkPtr) &pb, FALSE);
X	
X	if (err == noErr) {
X		pb.ioFlFndrInfo.fdType = ftype;
X		pb.ioFlFndrInfo.fdCreator = fcreator;
X		err = PBSetFInfo((ParmBlkPtr) &pb, FALSE);
X	}
X	
X	return(err == noErr);
X}
X
X#if 0
Xint getfileage(fname, vrefnum)
Xchar *fname;
Xshort vrefnum;
X
X{
X	char temp[64];
X	FileParam pb;
X	OSErr err;
X	int age;
X	
X	strcpy(temp, fname);
X	(void) c2pstr(temp);
X	
X	pb.ioCompletion = NULL;
X	pb.ioNamePtr = temp;
X	pb.ioVRefNum = vrefnum;
X	pb.ioFVersNum = 0;
X	pb.ioFDirIndex = 0;
X	
X	err = PBGetFInfo((ParmBlkPtr) &pb, FALSE);
X	
X	if (err == noErr) {
X		GetDateTime((unsigned int *) &age);
X		age -= pb.ioFlMdDat;
X	}
X	else
X		age = 0;
X	
X	return(age);
X}
X#endif
X
Xvoid benediction()
X
X{
X	Rect scrn;
X	
X	scrn.left = 0;
X	scrn.top = SCRN_ROWS-1;
X	scrn.right = SCRN_COLS;
X	scrn.bottom = SCRN_ROWS;
X	
X	EraseScreen(&scrn);
X	
X	SetScreenCursor(0, SCRN_ROWS-1);
X	WriteScreenString("Please select a command from the file menu...");
X	
X	return;
X}
X
Xvoid setsavecmdstatus(val, init)
Xint val, init;
X
X{
X	save_cmd_level = val;
X	
X	if (init)
X		save_cmd_enabled = val > 0;
X		
X	return;
X}
X
Xvoid enablesavecmd(flag)
Xint flag;
X
X{
X	save_cmd_level += flag ? 1 : -1;
X	return;
X}
X
Xvoid setfilemenustatus(val, init)
Xint val, init;
X
X{
X	file_menu_level = val;
X	
X	if (init)
X		file_menu_enabled = val > 0;
X		
X	return;
X}
X
Xvoid enablefilemenu(flag)
Xint flag;
X
X{
X	file_menu_level += flag ? 1 : -1;
X	return;
X}
X
Xvoid setappmenustatus(val, init)
Xint val, init;
X
X{
X	app_menu_level = val;
X	
X	if (init)
X		app_menu_enabled = val > 0;
X		
X	return;
X}
X
Xvoid enableappmenu(flag)
Xint flag;
X
X{
X	app_menu_level += flag ? 1 : -1;
X	return;
X}
X
Xvoid savequitorcancel(next)
Xint next;
X
X{
X	DialogPtr thedialog;
X	short itemhit;
X	short itstype;
X	Rect itsrect;
X	int h, v;
X	int saveOk, dialogFinished;
X	
X	thedialog = GetNewDialog(sqc_dlg_id, nil, (WindowPtr) -1);
X	
X	CenterScreenDLOG(sqc_dlg_id, fixHalf, fixThird, &h, &v);
X	MoveWindow((WindowPtr) thedialog, (short) h, (short) v, false);
X	
X	if ((save_cmd_level > 0) && !total_winner) {
X		sqcdefault_item = sqc_save_item;
X		saveOk = true;
X	}
X	else {
X		sqcdefault_item = sqc_quit_item;
X		saveOk = false;
X	}
X	
X	GetDItem(thedialog, sqcdefault_item, &itstype, &sqcdefault_handle, &itsrect);
X	InsetRect(&itsrect, -4, -4);
X	
X	SetDItem(thedialog, sqc_defbrd_item, userItem, (Handle) DrawDefaultBorder, &itsrect);
X	
X	ShowWindow((WindowPtr) thedialog);
X
X	do {
X		ModalDialog(sqcfilter, &itemhit);
X		if ( (!saveOk) && (itemhit == sqc_save_item) ) {
X			if (total_winner)
X				alert_error("Sorry.  Since you are a total winner, you cannot save this game.  Your character must be retired.");
X			else
X				alert_error("Sorry.  You cannot save at this point in the game.  It must be your turn to move in order to save.");
X			dialogFinished = false;
X		}
X		else
X			dialogFinished = (itemhit == sqc_save_item) ||
X						(itemhit == sqc_quit_item) ||
X						(itemhit == sqc_cancel_item);
X	} while (!dialogFinished);
X	
X	DisposDialog(thedialog);
X	
X	switch (itemhit) {
X	
X		case sqc_save_item:
X			if (asksavegame(FALSE)) {
X				HiliteMenu(0);
X				(void) strcpy (died_from, "(saved)");
X				exit_code = next;
X				if (save_char(FALSE))
X					exit_game();
X				/* Should only get here if save_char fails */
X				UnloadSeg(save_char);
X				UnloadSeg(exit_game);
X				exit_code = NEXT_WAIT;
X				(void) strcpy (died_from, "(alive and well)");
X			}
X			break;
X			
X		case sqc_quit_item:
X			HiliteMenu(0);
X			death = TRUE;
X			(void) strcpy(died_from, "Quitting.");
X			exit_code = next;
X			exit_game();
X			/* Should never get here */
X			UnloadSeg(exit_game);
X			exit_code = NEXT_WAIT;
X			(void) strcpy (died_from, "(alive and well)");
X			death = FALSE;
X			break;
X			
X		default:
X			HiliteMenu(0);
X			break;
X			
X	}
X	
X	return;
X}
X
Xvoid loaddata(restart)
X
X{
X	if (
X#if 0
X	    		(!allocmalloczone(restart))	||
X#endif
X			(!allocsavearea(restart))	||
X			(!setupmem(restart))		||
X			(!getresources(restart))	||
X			(!getrestart(restart))		||
X			(!clearvars(restart))			)
X			
X				fatal_error("Insufficient memory to play Moria.  Sorry.");
X	
X	return;
X}
X
Xvoid goback()
X
X{
X	longjmp(jb, exit_code);
X}
X
Xint startfinder()
X
X{
X	int next;
X	int argc;
X	int local_cmdsetopt;
X	char *argv[2];
X	
X	if ((next = setjmp(jb)) != 0) return(next);
X	
X	clear_screen();
X	
X	local_cmdsetopt = cmdsetopt;
X	
X	argc = 0;
X	argv[argc++] = NULL;
X	argv[argc++] = (char *) &local_cmdsetopt;
X	
X	game_flag = TRUE;
X	exit_code = NEXT_WAIT;
X	
X	moria_main(argc, argv);
X	
X	/* should never get here */
X	return(NEXT_WAIT);
X}
X
Xint startnew()
X
X{
X	int next;
X	int argc;
X	int local_cmdsetopt, local_newgameopt;
X	char *argv[3];
X	
X	if ((next = setjmp(jb)) != 0) return(next);
X	
X	clear_screen();
X	
X	local_cmdsetopt = cmdsetopt;
X	local_newgameopt = '-n\0\0';
X	
X	argc = 0;
X	argv[argc++] = NULL;
X	argv[argc++] = (char *) &local_cmdsetopt;
X	argv[argc++] = (char *) &local_newgameopt;
X	
X	game_flag = TRUE;
X	exit_code = NEXT_WAIT;
X	
X	moria_main(argc, argv);
X	
X	/* should never get here */
X	return(NEXT_WAIT);
X}
X
Xint startopen()
X
X{
X	int next;
X	int argc;
X	int local_cmdsetopt;
X	char *argv[2];
X	
X	if ((next = setjmp(jb)) != 0) return(next);
X	
X	clear_screen();
X	
X	if (dogetfile(savefilename, &savefilevol)) {
X	
X		savefileset = TRUE;
X	
X		local_cmdsetopt = cmdsetopt;
X		
X		argc = 0;
X		argv[argc++] = NULL;
X		argv[argc++] = (char *) &local_cmdsetopt;
X		
X		game_flag = TRUE;
X		exit_code = NEXT_WAIT;
X		
X		moria_main(argc, argv);
X		
X	}
X	
X	/* should not get here unless user cancels standard file dialog */
X	return(NEXT_WAIT);
X}
X
Xint waitforchoice()
X
X{
X	int next;
X	
X	if ((next = setjmp(jb)) != 0) return(next);
X	
X	game_flag = FALSE;
X	
X	benediction();
X	
X	do {
X		idle();
X	} while(TRUE);
X	
X	return(NEXT_WAIT);
X}
X
Xvoid dofmnew()
X
X{
X	if (game_flag && character_generated)
X		savequitorcancel(NEXT_NEW);
X	
X	else {
X		HiliteMenu(0);
X		exit_code = NEXT_NEW;
X		goback();
X	}
X	
X	return;
X}
X
Xvoid dofmopen()
X
X{
X	if (game_flag && character_generated)
X		savequitorcancel(NEXT_OPEN);
X	
X	else {
X		HiliteMenu(0);
X		exit_code = NEXT_OPEN;
X		goback();
X	}
X	
X	return;
X}
X
Xvoid dofmsave(ask)
Xint ask;
X
X{
X	if (game_flag && character_generated && total_winner) {
X		alert_error("Sorry.  Since you are a total winner, you cannot save this game.  Your character must be retired.");
X		HiliteMenu(0);
X	}
X	else if (game_flag && character_generated && asksavegame(ask)) {
X		HiliteMenu(0);
X		(void) strcpy (died_from, "(saved)");
X		if (save_char(FALSE))
X			exit_game();
X		/* Should only get here if save_char fails */
X		UnloadSeg(save_char);
X		UnloadSeg(exit_game);
X		(void) strcpy (died_from, "(alive and well)");
X	}
X	else
X		HiliteMenu(0);
X		
X	return;
X}
X
Xvoid dofmquit()
X
X{
X	if (game_flag && character_generated)
X		savequitorcancel(NEXT_QUIT);
X	
X	else {
X		HiliteMenu(0);
X		exit_code = NEXT_QUIT;
X		goback();
X	}
X	
X	return;
X}
X
Xvoid dofilemenu(item)
Xint item;
X
X{
X	switch (item) {
X	
X		case FM_NEW:		dofmnew();
X							break;
X							
X		case FM_OPEN:		dofmopen();
X							break;
X							
X		case FM_SAVE:		dofmsave(FALSE);
X							break;
X							
X		case FM_SAVE_AS:	dofmsave(TRUE);
X							break;
X							
X		case FM_QUIT:		dofmquit();
X							break;
X							
X		case closeBoxItem:	if (file_menu_level > 0) dofmquit();
X							break;
X							
X		default:			HiliteMenu(0);
X							break;
X							
X	}
X	
X	return;
X}
X
Xvoid doappmenu(item)
Xint item;
X
X{
X	switch (item) {
X	
X		case AM_HELP:		DoMacHelp();
X							UnloadSeg(DoMacHelp);
X							break;
X							
X		case AM_CMD_SET:	ConfigScreenMgr(TRUE, CMDSET_TYPE, CMDSET_ID, GetCommandSet);
X							UnloadSeg(GetCommandSet);
X							cmdsetopt = **((int **) GetResource(CMDSET_TYPE, CMDSET_ID));
X							HiliteMenu(0);
X							break;
X							
X		case AM_TEXT_ED:	ConfigScreenMgr(TRUE, TE_TYPE, TE_ID, GetTextEditor);
X							UnloadSeg(GetTextEditor);
X							editor = **((int **) GetResource(TE_TYPE, TE_ID));
X							HiliteMenu(0);
X							break;
X							
X		case AM_SCORES:		DoScoresDlg();
X							UnloadSeg(DoScoresDlg);
X							break;
X							
X		default:			HiliteMenu(0);
X							break;
X							
X	}
X	
X	return;
X}
X
Xvoid unloadsegments()
X
X{
X	extern void create_character(),
X		creatures(),
X		exit_game(),
X		eat(),
X		file_character(),
X		generate_cave(),
X		ident_char(),
X		cast(),
X		pray(),
X		quaff(),
X		roff_recall(),
X		save_char(),
X		read_scroll(),
X		use(),
X		store_init(),
X		aim(),
X		wizard_light();
X		
X	UnloadSeg(create_character);			/* Create			*/
X	UnloadSeg(creatures);					/* Creature			*/
X	UnloadSeg(exit_game);					/* Death			*/
X	UnloadSeg(eat);							/* Eat				*/
X	UnloadSeg(file_character);				/* Files			*/
X	UnloadSeg(generate_cave);				/* Generate			*/
X	UnloadSeg(ident_char);					/* Help				*/
X	UnloadSeg(cast);						/* Magic			*/
X	UnloadSeg(pray);						/* Prayer			*/
X	UnloadSeg(quaff);						/* Potions			*/
X	UnloadSeg(roff_recall);					/* Recall			*/
X	UnloadSeg(save_char);					/* Save				*/
X	UnloadSeg(read_scroll);					/* Scrolls			*/
X	UnloadSeg(use);							/* Staffs			*/
X	UnloadSeg(store_init);					/* Store			*/
X	UnloadSeg(aim);							/* Wands			*/
X	UnloadSeg(wizard_light);				/* Wizard			*/
X	
X	return;
X}	
X
Xvoid salutation()
X
X{
X	mac_helpfile(MORIA_MOR, FALSE);
X}
X
Xint main()
X
X{
X	int next, savedgame, restart_flag;
X	extern void _DataInit();
X	
X	checkdebugger();
X	
X	UnloadSeg(_DataInit);
X	
X	getstack(0x7000);
X	
X  	MaxApplZone();
X	
X	/* Do this early to prevent fragmentation */
X	loaddata(FALSE);
X	
X	InitScreenMgr(SCRN_COLS, SCRN_ROWS,
X		"Moria", "Moria Config",
X		MORIA_FCREATOR, CONFIG_FTYPE,
X		dofilemenu, doappmenu,
X		twoColor);
X		
X	/* Get permanently set options */
X	/* If user has not set them yet, a dialog will be invoked */
X	/* Otherwise, they will be loaded from the preferences file */
X	
X	ConfigScreenMgr(FALSE, CMDSET_TYPE, CMDSET_ID, GetCommandSet);
X	UnloadSeg(GetCommandSet);
X	cmdsetopt = **((int **) GetResource(CMDSET_TYPE, CMDSET_ID));
X	
X	ConfigScreenMgr(FALSE, TE_TYPE, TE_ID, GetTextEditor);
X	UnloadSeg(GetTextEditor);
X	editor = **((int **) GetResource(TE_TYPE, TE_ID));
X		
X	DefineScreenCursor(attrColorFore, 2, GetCaretTime());
X	ShowScreenCursor();
X	
X	/* Save the application volume */
X	GetVol(NULL, &applvrefnum);
X	
X	/* These should be based up the menu resources */
X	setsavecmdstatus(0, TRUE);
X	setfilemenustatus(1, TRUE);
X	setappmenustatus(1, TRUE);
X	
X	restart_flag = FALSE;
X	
X	/* Find out if user has started from a saved game */
X	savedgame = getfinderfile();
X	
X	if (savedgame) {
X		enablefilemenu(FALSE);
X		salutation();
X		pause_line(23);
X		enablefilemenu(TRUE);
X		next = NEXT_FINDER;
X	}
X	else {
X		salutation();
X		next = NEXT_WAIT;
X	}
X	
X	do {
X		setsavecmdstatus(0, FALSE);
X		setfilemenustatus(1, FALSE);
X		setappmenustatus(1, FALSE);
X		switch (next) {
X			case NEXT_FINDER:
X				if (restart_flag) loaddata(TRUE);
X				next = startfinder();
X				unloadsegments();
X				restart_flag = TRUE;
X				break;
X			case NEXT_NEW:
X				if (restart_flag) loaddata(TRUE);
X				next = startnew();
X				unloadsegments();
X				restart_flag = TRUE;
X				break;
X			case NEXT_OPEN:
X				if (restart_flag) loaddata(TRUE);
X				next = startopen();
X				unloadsegments();
X				restart_flag = TRUE;
X				break;
X			case NEXT_WAIT:
X				next = waitforchoice();
X				break;
X		}
X	} while (next != NEXT_QUIT);
X	
X	CloseScreenMgr();
X	
X	/* That's all, folks... */
X	return(0);
X}
END_OF_FILE
if test 29254 -ne `wc -c <'mac/mac.c'`; then
    echo shar: \"'mac/mac.c'\" unpacked with wrong size!
fi
# end of 'mac/mac.c'
fi
if test -f 'source/store2.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'source/store2.c'\"
else
echo shar: Extracting \"'source/store2.c'\" \(25842 characters\)
sed "s/^X//" >'source/store2.c' <<'END_OF_FILE'
X/* store2.c: store code, entering, command interpreter, buying, selling
X
X   Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
X
X   This software may be copied and distributed for educational, research, and
X   not for profit purposes provided that this copyright and statement are
X   included in all such copies. */
X
X#include "constant.h"
X#include "config.h"
X#include "types.h"
X#include "externs.h"
X
X#ifdef USG
X#ifndef ATARIST_MWC
X#include <string.h>
X#endif
X#else
X#ifndef VMS
X#include <strings.h>
X#endif
X#endif
X
X#if defined(LINT_ARGS)
Xstatic void prt_comment1(void);
Xstatic void prt_comment2(int32, int32, int);
Xstatic void prt_comment3(int32, int32, int);
Xstatic void prt_comment4(void);
Xstatic void prt_comment5(void);
Xstatic void prt_comment6(void);
Xstatic void display_commands(void);
Xstatic void haggle_commands(int);
Xstatic void display_inventory(int, int);
Xstatic void display_cost(int, int);
Xstatic void store_prt_gold(void);
Xstatic void display_store(int, int);
Xstatic int get_store_item(int *, char *, int, int);
Xstatic int increase_insults(int);
Xstatic void decrease_insults(int);
Xstatic int haggle_insults(int);
Xstatic int get_haggle(char *, int32 *, int);
Xstatic int receive_offer(int, char *, int32 *, int32, int, int);
Xstatic int purchase_haggle(int, int32 *, struct inven_type *);
Xstatic int sell_haggle(int, int32 *, struct inven_type *);
Xstatic int store_purchase(int, int *);
Xstatic int store_sell(int, int *);
X#endif
X
Xlong atol();
X
Xstatic char *comment1[14] = {
X  "Done!",  "Accepted!",  "Fine.",  "Agreed!",  "Ok.",  "Taken!",
X  "You drive a hard bargain, but taken.",
X  "You'll force me bankrupt, but it's a deal.",  "Sigh.  I'll take it.",
X  "My poor sick children may starve, but done!",  "Finally!  I accept.",
X  "Robbed again.",  "A pleasure to do business with you!",
X  "My spouse will skin me, but accepted."
X  };
X
Xstatic char *comment2a[3] = {
X  "%A2 is my final offer; take it or leave it.",
X  "I'll give you no more than %A2.",
X  "My patience grows thin.  %A2 is final."
X  };
X
Xstatic char *comment2b[16] = {
X  "%A1 for such a fine item?  HA!  No less than %A2.",
X  "%A1 is an insult!  Try %A2 gold pieces.",
X  "%A1?!?  You would rob my poor starving children?",
X  "Why, I'll take no less than %A2 gold pieces.",
X  "Ha!  No less than %A2 gold pieces.",
X  "Thou knave!  No less than %A2 gold pieces.",
X  "%A1 is far too little, how about %A2?",
X  "I paid more than %A1 for it myself, try %A2.",
X  "%A1?  Are you mad?!?  How about %A2 gold pieces?",
X  "As scrap this would bring %A1.  Try %A2 in gold.",
X  "May the fleas of 1000 orcs molest you.  I want %A2.",
X  "My mother you can get for %A1, this costs %A2.",
X  "May your chickens grow lips.  I want %A2 in gold!",
X  "Sell this for such a pittance?  Give me %A2 gold.",
X  "May the Balrog find you tasty!  %A2 gold pieces?",
X  "Your mother was a Troll!  %A2 or I'll tell."
X  };
X
Xstatic char *comment3a[3] = {
X  "I'll pay no more than %A1; take it or leave it.",
X  "You'll get no more than %A1 from me.",
X  "%A1 and that's final."
X  };
X
Xstatic char *comment3b[15] = {
X  "%A2 for that piece of junk?  No more than %A1.",
X  "For %A2 I could own ten of those.  Try %A1.",
X  "%A2?  NEVER!  %A1 is more like it.",
X  "Let's be reasonable. How about %A1 gold pieces?",
X  "%A1 gold for that junk, no more.",
X  "%A1 gold pieces and be thankful for it!",
X  "%A1 gold pieces and not a copper more.",
X  "%A2 gold?  HA!  %A1 is more like it.",  "Try about %A1 gold.",
X  "I wouldn't pay %A2 for your children, try %A1.",
X  "*CHOKE* For that!?  Let's say %A1.",  "How about %A1?",
X  "That looks war surplus!  Say %A1 gold.",
X  "I'll buy it as scrap for %A1.",
X  "%A2 is too much, let us say %A1 gold."
X  };
X
Xstatic char *comment4a[5] = {
X  "ENOUGH!  You have abused me once too often!",
X  "THAT DOES IT!  You shall waste my time no more!",
X  "This is getting nowhere.  I'm going home!",
X  "BAH!  No more shall you insult me!",
X  "Begone!  I have had enough abuse for one day."
X  };
X
Xstatic char *comment4b[5] = {
X  "Out of my place!",  "out... Out... OUT!!!",  "Come back tomorrow.",
X  "Leave my place.  Begone!",  "Come back when thou art richer."
X  };
X
Xstatic char *comment5[10] = {
X  "You will have to do better than that!",  "That's an insult!",
X  "Do you wish to do business or not?",  "Hah!  Try again.",
X  "Ridiculous!",  "You've got to be kidding!",  "You'd better be kidding!",
X  "You try my patience.",  "I don't hear you.",
X  "Hmmm, nice weather we're having."
X  };
X
Xstatic char *comment6[5] = {
X  "I must have heard you wrong.",  "What was that?",
X  "I'm sorry, say that again.",  "What did you say?",
X  "Sorry, what was that again?"
X  };
X
X
X/* Comments vary.					-RAK-	*/
X/* Comment one : Finished haggling				*/
Xstatic void prt_comment1()
X{
X  msg_print(comment1[randint(14)-1]);
X}
X
X
X/* %A1 is offer, %A2 is asking.		*/
Xstatic void prt_comment2(offer, asking, final)
Xint32 offer, asking; int final;
X{
X  vtype comment;
X
X  if (final > 0)
X    (void) strcpy(comment, comment2a[randint(3)-1]);
X  else
X    (void) strcpy(comment, comment2b[randint(16)-1]);
X
X  insert_lnum(comment, "%A1", offer, FALSE);
X  insert_lnum(comment, "%A2", asking, FALSE);
X  msg_print(comment);
X}
X
X
Xstatic void prt_comment3(offer, asking, final)
Xint32 offer, asking; int final;
X{
X  vtype comment;
X
X  if (final > 0)
X    (void) strcpy (comment, comment3a[randint(3)-1]);
X  else
X    (void) strcpy (comment, comment3b[randint(15)-1]);
X
X  insert_lnum(comment, "%A1", offer, FALSE);
X  insert_lnum(comment, "%A2", asking, FALSE);
X  msg_print(comment);
X}
X
X
X/* Kick 'da bum out.					-RAK-	*/
Xstatic void prt_comment4()
X{
X  register int tmp;
X
X  tmp = randint(5) - 1;
X  msg_print(comment4a[tmp]);
X  msg_print(comment4b[tmp]);
X}
X
X
Xstatic void prt_comment5()
X{
X  msg_print(comment5[randint(10)-1]);
X}
X
X
Xstatic void prt_comment6()
X{
X  msg_print (comment6[randint(5)-1]);
X}
X
X
X/* Displays the set of commands				-RAK-	*/
Xstatic void display_commands()
X{
X  prt("You may:", 20, 0);
X  prt(" p) Purchase an item.           b) Browse store's inventory.", 21, 0);
X  prt(" s) Sell an item.               i/e/t/w/x) Inventory/Equipment Lists.",
X      22, 0);
X  prt("ESC) Exit from Building.        ^R) Redraw the screen.", 23, 0);
X}
X
X
X/* Displays the set of commands				-RAK-	*/
Xstatic void haggle_commands(typ)
Xint typ;
X{
X  if (typ == -1)
X    prt("Specify an asking-price in gold pieces.", 21, 0);
X  else
X    prt("Specify an offer in gold pieces.", 21, 0);
X  prt("ESC) Quit Haggling.", 22, 0);
X  erase_line (23, 0);	/* clear last line */
X}
X
X
X/* Displays a store's inventory				-RAK-	*/
Xstatic void display_inventory(store_num, start)
Xint store_num, start;
X{
X  register store_type *s_ptr;
X  register inven_type *i_ptr;
X  register int i, j, stop;
X  bigvtype out_val1, out_val2;
X  int32 x;
X
X  s_ptr = &store[store_num];
X  i = (start % 12);
X  stop = ((start / 12) + 1) * 12;
X  if (stop > s_ptr->store_ctr)	stop = s_ptr->store_ctr;
X  while (start < stop)
X    {
X      i_ptr = &s_ptr->store_inven[start].sitem;
X      x = i_ptr->number;
X      if ((i_ptr->subval >= ITEM_SINGLE_STACK_MIN)
X	  && (i_ptr->subval <= ITEM_SINGLE_STACK_MAX))
X	i_ptr->number = 1;
X      objdes(out_val1, i_ptr, TRUE);
X      i_ptr->number = x;
X      (void) sprintf(out_val2, "%c) %s", 'a'+i, out_val1);
X      prt(out_val2, i+5, 0);
X      x = s_ptr->store_inven[start].scost;
X      if (x <= 0)
X	{
X	  int32 value = -x;
X	  value = value * chr_adj() / 100;
X	  if (value <= 0)
X	    value = 1;
X	  (void) sprintf(out_val2, "%9ld", value);
X	}
X      else
X	(void) sprintf(out_val2,"%9ld [Fixed]", x);
X      prt(out_val2, i+5, 59);
X      i++;
X      start++;
X    }
X  if (i < 12)
X    for (j = 0; j < (11 - i + 1); j++)
X      erase_line (j+i+5, 0); /* clear remaining lines */
X  if (s_ptr->store_ctr > 12)
X    put_buffer("- cont. -", 17, 60);
X  else
X    erase_line (17, 60);
X}
X
X
X/* Re-displays only a single cost			-RAK-	*/
Xstatic void display_cost(store_num, pos)
Xint store_num, pos;
X{
X  register int i;
X  register int32 j;
X  vtype out_val;
X  register store_type *s_ptr;
X
X  s_ptr = &store[store_num];
X  i = (pos % 12);
X  if (s_ptr->store_inven[pos].scost < 0)
X    {
X      j = - s_ptr->store_inven[pos].scost;
X      j = j * chr_adj() / 100;
X      (void) sprintf(out_val, "%ld", j);
X    }
X  else
X    (void) sprintf(out_val, "%9ld [Fixed]", s_ptr->store_inven[pos].scost);
X  prt(out_val, i+5, 59);
X}
X
X
X/* Displays players gold					-RAK-	*/
Xstatic void store_prt_gold()
X{
X  vtype out_val;
X
X  (void) sprintf(out_val, "Gold Remaining : %ld", py.misc.au);
X  prt(out_val, 18, 17);
X}
X
X
X/* Displays store					-RAK-	*/
Xstatic void display_store(store_num, cur_top)
Xint store_num, cur_top;
X{
X  register store_type *s_ptr;
X
X  s_ptr = &store[store_num];
X  clear_screen();
X  put_buffer(owners[s_ptr->owner].owner_name, 3, 9);
X  put_buffer("Item", 4, 3);
X  put_buffer("Asking Price", 4, 60);
X  store_prt_gold();
X  display_commands();
X  display_inventory(store_num, cur_top);
X}
X
X
X/* Get the ID of a store item and return it's value	-RAK-	*/
Xstatic int get_store_item(com_val, pmt, i, j)
Xint *com_val;
Xchar *pmt;
Xregister int i, j;
X{
X  char command;
X  vtype out_val;
X  register int flag;
X
X  *com_val = -1;
X  flag = FALSE;
X  (void) sprintf(out_val, "(Items %c-%c, ESC to exit) %s", i+'a', j+'a', pmt);
X  while (get_com(out_val, &command))
X    {
X      command -= 'a';
X      if (command >= i && command <= j)
X	{
X	  flag = TRUE;
X	  *com_val = command;
X	  break;
X	}
X      bell();
X    }
X  erase_line(MSG_LINE, 0);
X  return(flag);
X}
X
X
X/* Increase the insult counter and get angry if too many -RAK-	*/
Xstatic int increase_insults(store_num)
Xint store_num;
X{
X  register int increase;
X  register store_type *s_ptr;
X
X  increase = FALSE;
X  s_ptr = &store[store_num];
X  s_ptr->insult_cur++;
X  if (s_ptr->insult_cur > owners[s_ptr->owner].insult_max)
X    {
X      prt_comment4();
X      s_ptr->insult_cur = 0;
X      s_ptr->good_buy = 0;
X      s_ptr->bad_buy = 0;
X      s_ptr->store_open = turn + 2500 + randint(2500);
X      increase = TRUE;
X    }
X  return(increase);
X}
X
X
X/* Decrease insults					-RAK-	*/
Xstatic void decrease_insults(store_num)
Xint store_num;
X{
X  register store_type *s_ptr;
X
X  s_ptr = &store[store_num];
X  if (s_ptr->insult_cur != 0)
X    s_ptr->insult_cur--;
X}
X
X
X/* Have insulted while haggling				-RAK-	*/
Xstatic int haggle_insults(store_num)
Xint store_num;
X{
X  register int haggle;
X
X  haggle = FALSE;
X  if (increase_insults(store_num))
X    haggle = TRUE;
X  else
X    prt_comment5();
X  return(haggle);
X}
X
X
Xstatic int get_haggle(comment, new_offer, num_offer)
Xchar *comment;
Xint32 *new_offer;
Xint num_offer;
X{
X  register int32 i;
X  vtype out_val;
X  register int flag, clen;
X  register char *p;
X
X  flag = TRUE;
X  clen = strlen(comment);
X  i = 0;
X  do
X    {
X      prt(comment, 0, 0);
X      if (!get_string(out_val, 0, clen, 40))
X	flag = FALSE;
X      i = atol(out_val);
X      /* don't allow incremental haggling, if player has not made an offer
X	 yet */
X      for (p = out_val; *p == ' '; p++)
X	;
X      if (flag && num_offer == 0 && (*p == '+' || *p == '-'))
X	{
X	  msg_print("You haven't even made your first offer yet!");
X	  i = 0;
X	}
X    }
X  while (flag && (i == 0));
X  if (flag)
X    {
X      for (p = out_val; *p == ' '; p++)
X	;
X      if (*p == '+' || *p == '-')
X	*new_offer += i;
X      else
X	*new_offer = i;
X    }
X  else
X    erase_line (0, 0);
X  return(flag);
X}
X
X
Xstatic int receive_offer(store_num, comment, new_offer, last_offer,
X			 num_offer, factor)
Xint store_num;
Xchar *comment;
Xregister int32 *new_offer, last_offer;
Xint num_offer, factor;
X{
X  register int flag;
X  register int receive;
X
X  receive = 0;
X  flag = FALSE;
X  do
X    {
X      if (get_haggle(comment, new_offer, num_offer))
X	{
X	  if (*new_offer*factor >= last_offer*factor)
X	    flag = TRUE;
X	  else if (haggle_insults(store_num))
X	    {
X	      receive = 2;
X	      flag = TRUE;
X	    }
X	  else
X	    /* new_offer rejected, reset new_offer so that incremental
X	       haggling works correctly */
X	    *new_offer = last_offer;
X	}
X      else
X	{
X	  receive = 1;
X	  flag = TRUE;
X	}
X    }
X  while (!flag);
X  return(receive);
X}
X
X
X/* Haggling routine					-RAK-	*/
Xstatic int purchase_haggle(store_num, price, item)
Xint store_num;
Xint32 *price;
Xinven_type *item;
X{
X  int32 max_sell, min_sell, max_buy;
X  int32 cost, cur_ask, final_ask, min_offer;
X  int32 last_offer, new_offer;
X  int32 x1, x2, x3;
X  int32 min_per, max_per;
X  register int flag, loop_flag;
X  char *comment;
X  vtype out_val;
X  int purchase, num_offer, final_flag;
X  register store_type *s_ptr;
X  register owner_type *o_ptr;
X
X  flag = FALSE;
X  purchase = 0;
X  *price = 0;
X  final_flag = 0;
X  s_ptr = &store[store_num];
X  o_ptr = &owners[s_ptr->owner];
X  cost = sell_price(store_num, &max_sell, &min_sell, item);
X  max_sell = max_sell * chr_adj() / 100;
X  if (max_sell <= 0)  max_sell = 1;
X  min_sell = min_sell * chr_adj() / 100;
X  if (min_sell <= 0)  min_sell = 1;
X  /* cast max_inflate to signed so that subtraction works correctly */
X  max_buy  = cost * (200 - (int)o_ptr->max_inflate) / 100;
X  if (max_buy <= 0) max_buy = 1;
X  min_per  = o_ptr->haggle_per;
X  max_per  = min_per * 3;
X  haggle_commands(1);
X  cur_ask   = max_sell;
X  final_ask = min_sell;
X  min_offer = max_buy;
X  last_offer = min_offer;
X  new_offer = 0;
X  num_offer = 0; /* this prevents incremental haggling on first try */
X  comment = "Asking";
X
X  /* go right to final price if player has bargained well */
X  if (noneedtobargain(store_num, final_ask))
X    {
X      msg_print("After a long bargaining session, you agree upon the price.");
X      cur_ask = min_sell;
X    }
X
X  do
X    {
X      do
X	{
X	  loop_flag = TRUE;
X	  (void) sprintf(out_val, "%s :  %ld", comment, cur_ask);
X	  put_buffer(out_val, 1, 0);
X	  purchase = receive_offer(store_num, "What do you offer? ",
X				   &new_offer, last_offer, num_offer, 1);
X	  if (purchase != 0)
X	    flag = TRUE;
X	  else
X	    {
X	      if (new_offer > cur_ask)
X		{
X		  prt_comment6();
X		  /* rejected, reset new_offer for incremental haggling */
X		  new_offer = last_offer;
X		}
X	      else if (new_offer == cur_ask)
X		{
X		  flag = TRUE;
X		  *price = new_offer;
X		}
X	      else
X		loop_flag = FALSE;
X	    }
X	}
X      while (!flag && loop_flag);
X      if (!flag)
X	{
X	  x1 = (new_offer - last_offer) * 100 / (cur_ask - last_offer);
X	  if (x1 < min_per)
X	    {
X	      flag = haggle_insults(store_num);
X	      if (flag)	 purchase = 2;
X	    }
X	  else if (x1 > max_per)
X	    {
X	      x1 = x1 * 75 / 100;
X	      if (x1 < max_per)	 x1 = max_per;
X	    }
X	  x2 = x1 + randint(5) - 3;
X	  x3 = ((cur_ask - new_offer) * x2 / 100) + 1;
X	  /* don't let the price go up */
X	  if (x3 < 0)
X	    x3 = 0;
X	  cur_ask -= x3;
X	  if (cur_ask < final_ask)
X	    {
X	      cur_ask = final_ask;
X	      comment = "Final Offer";
X	      final_flag++;
X	      if (final_flag > 3)
X		{
X		  if (increase_insults(store_num))
X		    purchase = 2;
X		  else
X		    purchase = 1;
X		  flag = TRUE;
X		}
X	    }
X	  else if (new_offer >= cur_ask)
X	    {
X	      flag = TRUE;
X	      *price = new_offer;
X	    }
X	  if (!flag)
X	    {
X	      last_offer = new_offer;
X	      num_offer++; /* enable incremental haggling */
X	      erase_line (1, 0);
X	      (void) sprintf(out_val, "Your last offer : %ld", last_offer);
X	      put_buffer(out_val, 1, 39);
X	      prt_comment2(last_offer, cur_ask, final_flag);
X	    }
X	}
X    }
X  while (!flag);
X
X  /* update bargaining info */
X  if (purchase == 0)
X    updatebargain(store_num, *price, final_ask);
X
X  return(purchase);
X}
X
X
X/* Haggling routine					-RAK-	*/
Xstatic int sell_haggle(store_num, price, item)
Xint store_num;
Xint32 *price;
Xinven_type *item;
X{
X  int32 max_sell, max_buy, min_buy;
X  int32 cost, cur_ask, final_ask, min_offer;
X  int32 last_offer, new_offer;
X  int32 max_gold;
X  int32 x1, x2, x3;
X  int32 min_per, max_per;
X  register int flag, loop_flag;
X  char *comment;
X  vtype out_val;
X  register store_type *s_ptr;
X  register owner_type *o_ptr;
X  int sell, num_offer, final_flag;
X
X  flag = FALSE;
X  sell = 0;
X  *price = 0;
X  final_flag = 0;
X  s_ptr = &store[store_num];
X  cost = item_value(item);
X  if (cost < 1)
X    {
X      sell = 3;
X      flag = TRUE;
X    }
X  else
X    {
X      o_ptr = &owners[s_ptr->owner];
X      cost = cost * (200 - chr_adj()) / 100;
X      cost = cost * (200 - rgold_adj[o_ptr->owner_race][py.misc.prace]) / 100;
X      if (cost < 1)  cost = 1;
X      max_sell = cost * o_ptr->max_inflate / 100;
X      /* cast max_inflate to signed so that subtraction works correctly */
X      max_buy  = cost * (200 - (int)o_ptr->max_inflate) / 100;
X      min_buy  = cost * (200 - o_ptr->min_inflate) / 100;
X      if (min_buy < 1) min_buy = 1;
X      if (max_buy < 1) max_buy = 1;
X      if (min_buy < max_buy)  min_buy = max_buy;
X      min_per  = o_ptr->haggle_per;
X      max_per  = min_per * 3;
X      max_gold = o_ptr->max_cost;
X    }
X  if (!flag)
X    {
X      haggle_commands(-1);
X      if (max_buy > max_gold)
X	{
X	  final_flag= 1;
X	  comment = "Final Offer";
X	  cur_ask   = max_gold;
X	  final_ask = max_gold;
X msg_print("I am sorry, but I have not the money to afford such a fine item.");
X	}
X      else
X	{
X	  cur_ask   = max_buy;
X	  final_ask = min_buy;
X	  if (final_ask > max_gold)
X	    final_ask = max_gold;
X	  comment = "Offer";
X
X	  /* go right to final price if player has bargained well */
X          if (noneedtobargain(store_num, final_ask))
X	    {
X       msg_print("After a long bargaining session, you agree upon the price.");
X              cur_ask = final_ask;
X            }
X	}
X      min_offer = max_sell;
X      last_offer = min_offer;
X      new_offer = 0;
X      num_offer = 0; /* this prevents incremental haggling on first try */
X      if (cur_ask < 1)	cur_ask = 1;
X      do
X	{
X	  do
X	    {
X	      loop_flag = TRUE;
X	      (void) sprintf(out_val, "%s :  %ld", comment, cur_ask);
X	      put_buffer(out_val, 1, 0);
X	      sell = receive_offer(store_num, "What price do you ask? ",
X				 &new_offer, last_offer, num_offer, -1);
X	      if (sell != 0)
X		flag   = TRUE;
X	      else
X		{
X		  if (new_offer < cur_ask)
X		    {
X		      prt_comment6();
X		      /* rejected, reset new_offer for incremental haggling */
X		      new_offer = last_offer;
X		    }
X		  else if (new_offer == cur_ask)
X		    {
X		      flag = TRUE;
X		      *price = new_offer;
X		    }
X		  else
X		    loop_flag = FALSE;
X		}
X	    }
X	  while (!flag && loop_flag);
X	  if (!flag)
X	    {
X	      x1 = (last_offer - new_offer) * 100 / (last_offer - cur_ask);
X	      if (x1 < min_per)
X		{
X		  flag = haggle_insults(store_num);
X		  if (flag)  sell = 2;
X		}
X	      else if (x1 > max_per)
X		{
X		  x1 = x1 * 75 / 100;
X		  if (x1 < max_per)  x1 = max_per;
X		}
X	      x2 = x1 + randint(5) - 3;
X	      x3 = ((new_offer - cur_ask) * x2 / 100) + 1;
X	      /* don't let the price go down */
X	      if (x3 < 0)
X		x3 = 0;
X	      cur_ask += x3;
X	      if (cur_ask > final_ask)
X		{
X		  cur_ask = final_ask;
X		  comment = "Final Offer";
X		  final_flag++;
X		  if (final_flag > 3)
X		    {
X		      if (increase_insults(store_num))
X			sell = 2;
X		      else
X			sell = 1;
X		      flag = TRUE;
X		    }
X		}
X	      else if (new_offer <= cur_ask)
X		{
X		  flag = TRUE;
X		  *price = new_offer;
X		}
X	      if (!flag)
X		{
X		  last_offer = new_offer;
X		  num_offer++; /* enable incremental haggling */
X		  erase_line (1, 0);
X		  (void) sprintf(out_val, "Your last bid %ld", last_offer);
X		  put_buffer(out_val, 1, 39);
X		  prt_comment3(cur_ask, last_offer, final_flag);
X		}
X	    }
X	}
X      while (!flag);
X    }
X
X  /* update bargaining info */
X  if (sell == 0)
X    updatebargain(store_num, *price, final_ask);
X
X  return(sell);
X}
X
X
X/* Buy an item from a store				-RAK-	*/
Xstatic int store_purchase(store_num, cur_top)
Xint store_num;
Xint *cur_top;
X{
X  int32 price;
X  register int i, choice;
X  bigvtype out_val, tmp_str;
X  register store_type *s_ptr;
X  inven_type sell_obj;
X  register inven_record *r_ptr;
X  int item_val, item_new, purchase;
X
X  purchase = FALSE;
X  s_ptr = &store[store_num];
X  /* i == number of objects shown on screen	*/
X  if (*cur_top == 12)
X    i = s_ptr->store_ctr - 1 - 12;
X  else if (s_ptr->store_ctr > 11)
X    i = 11;
X  else
X    i = s_ptr->store_ctr - 1;
X  if (s_ptr->store_ctr < 1)
X    msg_print("I am currently out of stock.");
X      /* Get the item number to be bought		*/
X  else if (get_store_item(&item_val,
X			  "Which item are you interested in? ", 0, i))
X    {
X      item_val = item_val + *cur_top;	/* TRUE item_val	*/
X      take_one_item(&sell_obj, &s_ptr->store_inven[item_val].sitem);
X      if (inven_check_num(&sell_obj))
X	{
X	  if (s_ptr->store_inven[item_val].scost > 0)
X	    {
X	      price = s_ptr->store_inven[item_val].scost;
X	      choice = 0;
X	    }
X	  else
X	    choice = purchase_haggle(store_num, &price, &sell_obj);
X	  if (choice == 0)
X	    {
X	      if (py.misc.au >= price)
X		{
X		  prt_comment1();
X		  decrease_insults(store_num);
X		  py.misc.au -= price;
X		  item_new = inven_carry(&sell_obj);
X		  i = s_ptr->store_ctr;
X		  store_destroy(store_num, item_val, TRUE);
X		  objdes(tmp_str, &inventory[item_new], TRUE);
X		  (void) sprintf(out_val, "You have %s (%c)",
X				   tmp_str, item_new+'a');
X		  prt(out_val, 0, 0);
X		  check_strength();
X		  if (*cur_top >= s_ptr->store_ctr)
X		    {
X		      *cur_top = 0;
X		      display_inventory(store_num, *cur_top);
X		    }
X		  else
X		    {
X		      r_ptr = &s_ptr->store_inven[item_val];
X		      if (i == s_ptr->store_ctr)
X			{
X			  if (r_ptr->scost < 0)
X			    {
X			      r_ptr->scost = price;
X			      display_cost(store_num, item_val);
X			    }
X			}
X		      else
X			display_inventory(store_num, item_val);
X		      store_prt_gold();
X		    }
X		}
X	      else
X		{
X		  if (increase_insults(store_num))
X		    purchase = TRUE;
X		  else
X		    {
X		      prt_comment1();
X		      msg_print("Liar!  You have not the gold!");
X		    }
X		}
X	    }
X	  else if (choice == 2)
X	    purchase = TRUE;
X
X	  /* Less intuitive, but looks better here than in purchase_haggle. */
X	  display_commands();
X	  erase_line (1, 0);
X	}
X      else
X	prt("You cannot carry that many different items.", 0, 0);
X    }
X  return(purchase);
X}
X
X
X/* Sell an item to the store				-RAK-	*/
Xstatic int store_sell(store_num, cur_top)
Xint store_num, *cur_top;
X{
X  int item_val, item_pos;
X  int32 price;
X  bigvtype out_val, tmp_str;
X  inven_type sold_obj;
X  register int sell, choice;
X
X  sell = FALSE;
X  if (get_item(&item_val, "Which one? ", 0, inven_ctr-1))
X    {
X      take_one_item(&sold_obj, &inventory[item_val]);
X      objdes(tmp_str, &sold_obj, TRUE);
X      (void) sprintf(out_val, "Selling %s (%c)", tmp_str, item_val+'a');
X      msg_print(out_val);
X#ifdef MAC
X      /* MPW limitations force a subroutine call, see sets.c */
X      if (store_buy(store_num, sold_obj.tval))
X#else
X      if ((*store_buy[store_num])(sold_obj.tval))
X#endif
X	if (store_check_num(&sold_obj, store_num))
X	  {
X	    choice = sell_haggle(store_num, &price, &sold_obj);
X	    if (choice == 0)
X	      {
X		prt_comment1();
X		decrease_insults(store_num);
X		py.misc.au += price;
X		/* identify object in inventory to set object_ident */
X		identify(&item_val);
X		/* retake sold_obj so that it will be identified */
X		take_one_item(&sold_obj, &inventory[item_val]);
X		/* call known2 for store item, so charges/pluses are known */
X		known2(&sold_obj);
X		inven_destroy(item_val);
X		objdes(tmp_str, &sold_obj, TRUE);
X		(void) sprintf(out_val, "You've sold %s", tmp_str);
X		msg_print(out_val);
X		store_carry(store_num, &item_pos, &sold_obj);
X		check_strength();
X		if (item_pos >= 0)
X		  {
X		    if (item_pos < 12)
X		      if (*cur_top < 12)
X			display_inventory(store_num, item_pos);
X		      else
X			{
X			  *cur_top = 0;
X			  display_inventory(store_num, *cur_top);
X			}
X		    else if (*cur_top > 11)
X		      display_inventory(store_num, item_pos);
X		    else
X		      {
X			*cur_top = 12;
X			display_inventory(store_num, *cur_top);
X		      }
X		  }
X		store_prt_gold();
X	      }
X	    else if (choice == 2)
X	      sell = TRUE;
X	    else if (choice == 3)
X	      {
X		msg_print("How dare you!");
X		msg_print("I will not buy that!");
X		sell = increase_insults(store_num);
X	      }
X	    /* Less intuitive, but looks better here than in sell_haggle. */
X	    erase_line (1, 0);
X	    display_commands();
X	  }
X	else
X	  msg_print("I have not the room in my store to keep it.");
X      else
X	msg_print("I do not buy such items.");
X    }
X  return(sell);
X}
X
X
X/* Entering a store					-RAK-	*/
Xvoid enter_store(store_num)
Xint store_num;
X{
X  int cur_top, tmp_chr;
X  char command;
X  register int exit_flag;
X  register store_type *s_ptr;
X
X  s_ptr = &store[store_num];
X  if (s_ptr->store_open < turn)
X    {
X      exit_flag = FALSE;
X      cur_top = 0;
X      display_store(store_num, cur_top);
X      do
X	{
X	  move_cursor (20, 9);
X	  /* clear the msg flag just like we do in dungeon.c */
X	  msg_flag = FALSE;
X	  if (get_com(NULL, &command))
X	    {
X	      switch(command)
X		{
X		case 'b':
X		  if (cur_top == 0)
X		    if (s_ptr->store_ctr > 12)
X		      {
X			cur_top = 12;
X			display_inventory(store_num, cur_top);
X		      }
X		    else
X		      msg_print("Entire inventory is shown.");
X		  else
X		    {
X		      cur_top = 0;
X		      display_inventory(store_num, cur_top);
X		    }
X		  break;
X		case 'E': case 'e':	 /* Equipment List	*/
X		case 'I': case 'i':	 /* Inventory		*/
X		case 'T': case 't':	 /* Take off		*/
X		case 'W': case 'w':	/* Wear			*/
X		case 'X': case 'x':	/* Switch weapon		*/
X		  tmp_chr = py.stats.use_stat[A_CHR];
X		  do
X		    {
X		      inven_command(command);
X		      command = doing_inven;
X		    }
X		  while (command);
X		  /* redisplay store prices if charisma changes */
X		  if (tmp_chr != py.stats.use_stat[A_CHR])
X		    display_inventory(store_num, cur_top);
X		  free_turn_flag = FALSE;	/* No free moves here. -CJS- */
X		  break;
X		case 'p':
X		  exit_flag = store_purchase(store_num, &cur_top);
X		  break;
X		case 's':
X		  exit_flag = store_sell(store_num, &cur_top);
X		  break;
X		default:
X		  bell();
X		  break;
X		}
X	    }
X	  else
X	    exit_flag = TRUE;
X	}
X      while (!exit_flag);
X      /* Can't save and restore the screen, because inven_command does that. */
X      draw_cave();
X    }
X  else
X    msg_print("The doors are locked.");
X}
END_OF_FILE
if test 25842 -ne `wc -c <'source/store2.c'`; then
    echo shar: \"'source/store2.c'\" unpacked with wrong size!
fi
# end of 'source/store2.c'
fi
if test -f 'util/mc/attribut.txt' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'util/mc/attribut.txt'\"
else
echo shar: Extracting \"'util/mc/attribut.txt'\" \(1179 characters\)
sed "s/^X//" >'util/mc/attribut.txt' <<'END_OF_FILE'
X
XDEFENSE attributes:
X
X	dragon
X	animal
X	evil
X	undead
X	frost
X	fire
X	poison
X	acid
X	light
X	stone
X	bit_9
X	bit_10
X	no_sleep
X	infra
X	max_hp
X	bit_15
X
XMOVE attributes:
X
X	attack_only
X	move_normal
X	bit_2
X	random_20
X	random_40
X	random_75
X
XSPECIAL attributes:
X
X	invisible
X	open_door
X	phase
X	eats_other
X	picks_up
X	multiply
X	win_creature
X
XTREASURE attributes:
X
X	carry_obj
X	carry_gold
X	has_random_60
X	has_random_90
X	has_1d2_obj
X	has_2d2_obj
X	has_4d2_obj
X
XSPELL attributes:
X
X	tel_short
X	tel_long
X	tel_to
X	lght_wnd
X	ser_wnd
X	hold_per
X	blind
X	confuse
X	fear
X	summon_mon
X	summon_und
X	slow_per
X	drain_mana
X	bit_17
X	bit_18
X
XBREATH attributes:
X
X	light
X	gas
X	acid
X	frost
X	fire
X
XATTACK TYPES:
X
X	normal_damage
X	lose_str
X	confusion
X	cause_fear
X	fire_damage
X	acid_damage
X	cold_damage
X	lightning_damage
X	corrosion
X	cause_blindness
X	cause_paralysis
X	steal_money
X	steal_obj
X	poison
X	lose_dex
X	lose_con
X	lose_int
X	lose_wis
X	lose_exp
X	aggravation
X	disenchant
X	eat_food
X	eat_light
X	eat_charges
X	blank
X
XATTACK DESCRIPTIONS:
X
X	hits
X	bites
X	claws
X	stings
X	touches
X	kicks
X	gazes
X	breathes
X	spits
X	wails
X	embraces
X	crawls_on
X	releases_spores
X	begs_for_money
X	slimes
X	crushes
X	tramples
X	drools_on
X	insults
X	is_repelled
X
END_OF_FILE
if test 1179 -ne `wc -c <'util/mc/attribut.txt'`; then
    echo shar: \"'util/mc/attribut.txt'\" unpacked with wrong size!
fi
# end of 'util/mc/attribut.txt'
fi
echo shar: End of archive 21 \(of 31\).
cp /dev/null ark21isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 31 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0


