[comp.sources.games] v07i015: hotel - boardgame of hotel development, Part01/02

billr@saab.CNA.TEK.COM (Bill Randle) (07/12/89)

Submitted-by: srt@aerospace.aero.org
Posting-number: Volume 7, Issue 15
Archive-name: hotel/Part01


#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 2)."
# Contents:  README MANIFEST comp.c hotel.c human.c init.c
# Wrapped by billr@saab on Wed Jul 12 07:06:46 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1531 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X			A Note From the Author
X
X	Over the years the games that have wandered across the net
Xhave given me a lot of enjoyment.  Hack, Moria, and all the others.
XIn part to pay back that debt and to increase the general public
Xwealth, I've written Hotel.
X
X	Hotel is a boardgame of hotel development, played on a 10x10
Xboard.  Players take turns placing tiles on the board and buying stock
Xin the hotels they create.  As hotels are merged together, the
Xstockholders receive merger bonuses, and the winner is the player who
Xaccumulates the most money.  Full instructions are available in the
Xprogram.
X
X	The program itself is written in C and has been compiled on a
XVax 750 running 4.3, on a Sun running whatever it is that Suns run
Xnow-a-days, and on a PC clone using Turbo C 2.0.  There are some
Xdependencies in the code, primarily to account for minor differences
Xbetween the Vax and PC versions of curses.
X
X	Hotel also uses Hung Le's "my_wgetstr" function, which adds 
Xediting capabilities to the curses "wgetstr" function.
X
X	For those of you interested in modifying the code, the
Xcomputer players' strategy resides primarily in the file "comp.c".
XThis code is fairly straightforward and commented, so you should have
Xno problems in tweaking in your latest and greatest strategy ideas.
X
X	Hotel in both source code and executable forms is Copyright
X1989 to Scott R. Turner.  However, most non-commercial uses of Hotel
Xare acceptable.  See the file "Notice" for full details.
X
X	Have fun.
X
X						-- Scott R. Turner
X						   srt@cs.ucla.edu
END_OF_FILE
if test 1531 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(579 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X MANIFEST                   1	This shipping list
X Notice                     2	
X README                     1	
X comp.c                     1	
X costs.c                    2	
X defs.h                     2	
X help.c                     2	
X hotel.c                    1	
X human.c                    1	
X init.c                     1	
X makefile                   2	
X my_wgets.c                 2	
X my_wgets.h                 2	
X pcdisp.c                   2	
X utils.c                    2	
END_OF_FILE
if test 579 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'comp.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'comp.c'\"
else
echo shar: Extracting \"'comp.c'\" \(14330 characters\)
sed "s/^X//" >'comp.c' <<'END_OF_FILE'
X/*
X * This program (called "Hotel") is copyright 1989 to Scott R. Turner,
X * in both source code and executable form.  Permission is given to 
X * copy both the source code and the executable under the following
X * conditions:
X * 
X * COPYING POLICIES
X * 
X *   1. You may copy and distribute verbatim copies of Hotel code as you
X * receive it, in any medium, provided that you conspicuously and
X * appropriately publish on each file a valid copyright notice such as
X * "Copyright (C) 1989 Scott R. Turner", and keep intact the copyright
X * and license notices on all files.  You may charge a distribution fee for the
X * physical act of transferring a copy, but that fee may not exceed
X * your actual costs in creating and delivering the copy.
X * 
X *   2. You may modify your copy or copies of Hotel or any portion of it,
X * and copy and distribute such modifications under the terms of
X * Paragraph 1 above, provided that you also do the following:
X * 
X *     a) cause the modified files to carry prominent notices stating
X *     who last changed such files and the date of any change; and
X * 
X *     b) cause the whole of any work that you distribute or publish,
X *     that in whole or in part contains or is a derivative of Hotel
X *     or any part thereof, to be licensed at no charge to all third
X *     parties on terms identical to those contained in this License
X *     Agreement (except that you may choose to grant more extensive
X *     warranty protection to third parties, at your option).
X *
X *   3. You may not copy, sublicense, distribute or transfer Hotel
X * except as expressly provided under this License Agreement.  Any attempt
X * otherwise to copy, sublicense, distribute or transfer Hotel is void and
X * your rights to use Hotel under this License agreement shall be
X * automatically terminated.  However, parties who have received computer
X * software programs from you with this License Agreement will not have
X * their licenses terminated so long as such parties remain in full compliance.
X * 
X *   4.  Under no circumstances may you charge for copies of Hotel, for copies
X * of any program containing code from Hotel in whole or in part, or for 
X * any software package or collection of programs or code that contains Hotel
X * in whole or part.
X *
X */ 
X/*
X *  comp.c
X *  Scott R. Turner
X *  Wed Nov  2 11:05:22 1988 -- Scott R. Turner
X *
X *  This file contains the routines that implement the computer
X *  player.
X *
X */
X#include "defs.h"
Xextern int legal_play();
Xextern void print_board();
Xextern void update_cash();
Xextern int maj_bonus();
Xextern int mergecheck();
Xextern int adjacent();
X
X/*
X *  Comp_play selects a tile to play.
X *
X *  (1) If you can sink a hotel that you have a majority
X *      interest in, do so.
X *  (1a) If you can sink a hotel that you do not have a 
X *	majority interest in to a hotel you do have a 
X *	majority interest in, do so.
X *  (2) If you can create a hotel, do so.
X *  (3) If you can extend the size of a hotel you
X *      have a majority interest in, do so.
X *  (4) If you can make an isolated play, do so.
X *  (5) Play randomly.
X * 
X *
X */
X
Xvoid  comp_play(n,px,py)
X     int n;
X     int *px,*py;
X{
X  int i,j,k,legl,plays[20][2],numplays;
X  int possibles[MAXHOTELS],mhotel,mvalue,mx,my,p;
X  int hotel1a,x1a,y1a;
X  
X
X  /*  The computer may not have a legal play.  */
X
X  legl = 0;
X    for(i=1;i<=boardsize;i++)
X      for(j=1;j<=boardsize;j++) 
X	if(board[i][j] == -n && legal_play(i,j)) {
X	  legl=1;
X	  goto done;
X	}
X done:
X
X  if (!legl) {
X    printw("%s has no legal moves.\n",players[n].name);
X    refresh();
X    *px = -1;
X    *py = -1;
X    return;
X  };
X
X  /*
X   *  Decide the computer's play.
X   *
X   */
X
X  /*  (1) Look for hotels to sink
X   *
X   *    (a) find all the possibles merges for each play.
X   *    (b) pick out the biggest merge that you have a share in.
X   *
X   */
X
X  mx = 0;
X  my = 0;
X  mhotel = 0;
X  mvalue = 0;
X  hotel1a = 0;
X  for(i=1;i<=boardsize;i++)
X    for(j=1;j<=boardsize;j++) 
X      if(board[i][j] == -n && legal_play(i,j) && mergecheck(i,j,possibles))
X	for (p = 1;p<=numhotels;p++) {
X	  /*  This is looking for (1) */
X	  if (possibles[p] && (maj_bonus(n,p) > mvalue)) {
X	    mvalue = maj_bonus(n,p);
X	    mhotel = p;
X	    mx = i;
X	    my = j;
X	  };
X	  /*  This is looking for (1a) */
X	  if (possibles[p] && stock_differential(n,p) > 3 && 
X	      maj_in_merge(p,i,j)) {
X	        hotel1a = p;
X	        x1a = i;
X	        y1a = j;
X	    };
X 	};
X
X  if (mhotel) {
X    /*  We are going to play mx,my to sink hotel #p. */
X    if (debug) printw("%s plays %d,%d sinking %c.\n",players[n].name,mx,my,('A'+mhotel-1));
X    *px = mx;
X    *py = my;
X    return;
X  };
X
X  if (hotel1a) {
X    /*  We are going to play mx,my to sink hotel #p. */
X    if (debug) printw("%s plays %d,%d sinking %c.\n",players[n].name,mx,my,('A'+hotel1a-1));
X    *px = x1a;
X    *py = y1a;
X    return;
X  };
X  
X  /*
X   *  (2) Create a new hotel if possible.
X   *
X   */
X
X  numplays = 0;
X  for(i=1;i<=boardsize;i++)
X    for(j=1;j<=boardsize;j++) 
X      if(board[i][j] == -n && legal_play(i,j) && new_hotel(i,j)) {
X	numplays++;
X	plays[numplays][0] = i;
X	plays[numplays][1] = j;
X      };
X
X  if (numplays) {
X    k = randum(1,numplays);
X    *px = plays[k][0];
X    *py = plays[k][1];
X    if (debug) printw("%s plays %d,%d to create a new hotel.\n",players[n].name,*px,*py); 
X    return;
X  };
X
X  /*
X   *  (3) Extend hotels that I own stock in.
X   *
X   */
X
X  mhotel = 0;
X  mvalue = 0;
X  for(i=1;i<=boardsize;i++)
X    for(j=1;j<=boardsize;j++) 
X      if(board[i][j] == -n && legal_play(i,j) && !mergecheck(i,j,possibles)
X	 && adjacent(i,j,&k) && players[n].shares[k] > mvalue) {
X	mhotel = k;
X	mvalue = players[n].shares[k];
X      };
X  numplays = 0;
X  for(i=1;i<=boardsize;i++)
X    for(j=1;j<=boardsize;j++) 
X      if(board[i][j] == -n && legal_play(i,j) && !mergecheck(i,j,possibles)
X	 && adjacent(i,j,&k) && k == mhotel) {
X	numplays++;
X	plays[numplays][0] = i;
X	plays[numplays][1] = j;
X      };
X  
X  if (numplays) {
X    k = randum(1,numplays);
X    *px = plays[k][0];
X    *py = plays[k][1];
X    if (debug) printw("%s plays %d,%d to extend a hotel.\n",players[n].name,*px,*py);
X    return;
X  };
X
X  /*
X   *  (4) Make an isolated play.
X   *
X   */
X
X  numplays = 0;
X  for(i=1;i<=boardsize;i++)
X    for(j=1;j<=boardsize;j++)
X      if(board[i][j] == -n && legal_play(i,j) && !mergecheck(i,j,possibles)
X	 && !adjacent(i,j,&k)) {
X	numplays++;
X	plays[numplays][0] = i;
X	plays[numplays][1] = j;
X      };
X
X  if (numplays) {
X    k = randum(1,numplays);
X    *px = plays[k][0];
X    *py = plays[k][1];
X    if (debug) printw("%s plays %d,%d (isolated).\n",players[n].name,*px,*py);
X    return;
X  };
X
X  /*
X   *  (5) Play randomly.
X   *
X   */
X
X  numplays = 0;
X  for(i=1;i<=boardsize;i++)
X    for(j=1;j<=boardsize;j++)
X      if(board[i][j] == -n && legal_play(i,j)){
X	numplays++;
X	plays[numplays][0] = i;
X	plays[numplays][1] = j;
X      };
X
X  if (numplays) {
X    k = randum(1,numplays);
X    *px = plays[k][0];
X    *py = plays[k][1];
X    if (debug) printw("%s plays %d,%d (randomly).\n",players[n].name,*px,*py);
X    return;
X  };
X
X  /*  Otherwise, give up. */
X  if (debug) printw("%s couldn't find a play.\n",players[n].name);
X  return;
X
X};
X
X/*
X *  Buying Strategies (General Notes)
X *
X *  (1) Theoretically, you could keep track in your head of all the
X *      stocks sold (and the stocks available), so comp_buy is free
X *      to rummage through other player's stock holdings.
X *
X */
X
X/*
X *  Get Majorities
X *
X *  The "Get Majorities" strategy attempts to gain and maintain
X *  majorities in as many hotels as possible.
X *
X */
X
X get_maj_strategy(p,purchases)
X     int p, purchases[MAXHOTELS];
X{
X  extern int share_cost();
X  int i,j,ok[MAXHOTELS],max[MAXHOTELS],spread[MAXHOTELS],numok,pick;
X  int order[MAXHOTELS],numorder,numbought,tmp;
X
X  /* Which hotels should be considered? */
X
X  numok = 0;
X  for(i=1;i<=numhotels;i++) {
X    purchases[i] = 0;
X    max[i] = 0;
X    spread[i] = 0;
X    if (hotels[i].shares > 0 && hotels[i].size > 0 &&
X	players[p].cash > share_cost(i)) {
X      ok[i] = 1;
X      numok++;
X    } else {
X      ok[i] = 0;
X    };
X  };
X
X  if(!numok) return;
X  
X  /* What's my share situation in each re other players? */
X
X  for(i=1;i<=numhotels;i++)
X    if (ok[i])
X      for(j=1;j<=numplayers;j++) {
X        if (j != p && players[j].shares[i]) spread[i]++;
X	if (j != p && players[j].shares[i] > max[i])
X	  max[i] = players[j].shares[i];
X	};
X	
X  /*
X   *  We can ignore hotels that we already have a 4 advantage
X   *  in.
X   *
X   */
X   
X  for(i=1;i<=numhotels;i++)
X    if (ok[i] && (players[p].shares[i] - max[i]) > 3) ok[i] = 0;
X	  
X  /*
X   * Rank the ok hotels according to the following cost
X   * equation:
X   * 
X   *  cost(i) = share_cost(i) * (needed_for_max + num_competing*3)
X   *
X   *  We do this with a rather inefficient bubble sort, but
X   *  computing cost isn't really an issue.
X   *
X   */
X  
X  numorder = 0;
X  for(i=1;i<=numhotels;i++) 
X    if (ok[i]) {
X    	numorder++;
X        order[numorder] = i;
X    };
X   
X  for(i=1;i<=numorder;i++)
X    for(j=1;j<=(numorder-1);j++)
X      if ((share_cost(order[j]) *
X             ((4-(players[p].shares[order[j]] - max[order[j]])) +
X              (spread[order[j]]*3))) >
X          (share_cost(order[j+1]) *
X             ((4-(players[p].shares[order[j+1]] - max[order[j+1]])) +
X              (spread[order[j+1]]*3)))) {
X	  tmp = order[j];
X	  order[j] = order[j+1];
X	  order[j+1] = tmp;
X	};
X              
X/*   printw("Stock order is: ");
X   for(i=1;i<=numorder;i++) printw("%d ",order[i]);
X   printw("\n");
X   print_board(1);
X   refresh();
X   any_key();
X*/	
X  /*
X   *  If we've just gotten the free share in something, buy 
X   *  some more.
X   *
X   */
X  
X  for(i=1;i<=numhotels;i++)
X    if(ok[i] && players[p].shares[i] == 1 && max[i] == 0) {
X    	pick = i;
X	purchases[pick] = num_shares(p,i,3);
X	return;
X    };
X    
X   /*
X    *  Otherwise, buy off the top.
X    *
X    */
X   
X   if (numorder) {
X     purchases[order[1]] = num_shares(p,order[1],3);
X   };
X   return;     
X
X};
X
X/*
X *  comp_liquidate is called when a hotel chain is sunk and a player might
X *  have stock to get rid of.
X *
X */
X
Xvoid  comp_liquidate(p,maxhot,sunk,sell,trade)
X     int p, *sell, *trade, maxhot,sunk;
X{
X  int i,j,maxtrade,num,mshares;
X  float coverage;
X
X  num = 0;
X  for(i=1;i<=boardsize;i++)
X    for(j=1;j<=boardsize;j++)
X      if (board[i][j] > 0) num++;
X  coverage = (num + 0.0) / (boardsize * boardsize);
X
X  /* If game is young, hold all stock. */
X  
X  if (coverage < .40) {
X    *sell = 0;
X    *trade = 0;
X    return;
X  };
X
X  /* Figure the maximum you can trade. */
X
X  if ((int) players[p].shares[sunk]/2 > hotels[sunk].shares)
X    maxtrade = hotels[sunk].shares * 2;
X  else
X    maxtrade = players[p].shares[sunk];
X  
X  /* If game is old, trade all possible. */
X
X  if (coverage > .60) {
X    *trade = maxtrade;
X    *sell = (players[p].shares[sunk] - maxtrade);
X    return;
X  };
X
X  /* Trade if the trade makes financial sense or
X   * if it will pull you within 3 of the maximum stockholder
X   * in maxhot.
X   */
X
X  if (share_cost(sunk)*2 <= share_cost(maxhot)) {
X    *trade = maxtrade;
X    *sell = (players[p].shares[sunk] - maxtrade);
X    return;
X  };
X
X  mshares = 0;
X  for(i=1;i<=numplayers;i++)
X    if (i != p && players[i].shares[maxhot] > mshares)
X      mshares = players[i].shares[maxhot];
X      
X  if (players[p].shares[maxhot] + (maxtrade / 2) + 3 >= mshares) {
X    *trade = maxtrade;
X    *sell = (players[p].shares[sunk] - maxtrade);
X    return;
X  };
X
X  /*
X   *  Otherwise, trade a random number.
X   *
X   */
X
X  *trade = randum(maxtrade);
X  *sell = randum(players[p].shares[sunk] - *trade);
X  return;
X  
X};
X
Xint  comp_new(n,x,y)
X     int n,x,y;
X{
X  int i,max,hot;
X
X  /*
X   *  Picks the hotel it holds the most stock in.
X   */
X
X  max = -1;
X  for(i=1;i<=numhotels;i++) {
X    if (hotels[i].size == 0 && players[n].shares[i] == max && randum(10) > 5) {
X        max = players[n].shares[i];
X	hot = i;
X    };
X    if (hotels[i].size == 0 && players[n].shares[i] > max) {
X        max = players[n].shares[i];
X	hot = i;
X    };
X  };
X  	
X  printw("%s creates hotel %c.\n",players[n].name,'A' + hot - 1);
X  return(hot);
X
X};
X
X/*
X *  comp_save is a routine for asking the player which of N
X *  equal size hotels they'd like to save.
X *
X *  Save the hotel you have the most stock in.
X *
X */
X
Xint  comp_save(p,max,adj)
X     int p,max,adj[MAXHOTELS+1];
X{
X  int num,i,choice,top;
X
X  top = -1;
X  choice = 0;
X  for(i=1;i<=numhotels;i++)
X    if (adj[i] == max && players[p].shares[i] > top) {
X    	top = players[p].shares[i];
X    	choice = i;
X    };
X
X  return(choice);
X};
X
X /*
X  *  This function returns the stock differential between
X  *  "player" and the top holder in the hotel.
X  *
X  */
X
Xint stock_differential(p,h)
X    int p,h;
X{
X  int i,diff;
X  
X  diff = 0;
X  for(i=1;i<=numplayers;i++)
X    if (i != p &&
X      (players[i].shares[h]-players[p].shares[h]) > diff)
X        diff = (players[i].shares[h]-players[p].shares[h]);
X  return(diff);
X  
X};
X	
X/*
X *  Maj_in_merge returns true if playing x,y would merge h
X *  into another h that the player has a majority interest
X *  in.  (Whew!)
X *
X */
X
Xint maj_in_merge(p,x,y)
X    int p,x,y;
X{
X    
X  int i,lsize,mergeh;
X  int j,k,max1,max2,first,second;
X
X  lsize = 0;
X  mergeh = 0;
X  for(i= -1;i<2;i++)
X    for(j= -1;j<2;j++)
X      if ( i*j == 0 && (i != 0 || j != 0) &&
X	  ((x+i) > 0) && ((y+j) > 0) &&
X	  ((x+i) <= boardsize) && ((y+j) <= boardsize) &&
X	  (board[x+i][y+j] != UNUSED) &&
X	  (board[x+i][y+j] > 0)) {
X	if (hotels[board[x+i][y+j]].size > lsize) {
X            mergeh = board[x+i][y+j];
X        };
X    };
X
X  max1 = 0;
X  max2 = 0;
X  for(j=1;j<=numplayers;j++) {
X    if (players[j].shares[mergeh] > max1) {
X      max2 = max1;
X      max1 = players[j].shares[mergeh];
X    } else if (players[j].shares[mergeh] > max2) {
X      max2 = players[j].shares[mergeh];
X    };
X  };
X
X  if (players[p].shares[mergeh] > max2) {
X    return(1);
X  } else {
X    return(0);
X  };
X  
X};
X
X/*
X *  Num shares finds the maximum number of shares you can 
X *  afford within the given range.
X *
X */
X 
Xint num_shares(p,hot,max)
X    int p,hot,max;
X{        
X   int num;
X   /* How many can we afford to buy? */
X
X   num = players[p].cash / share_cost(hot);
X   if (num > 3) num = 3;
X   if (num > hotels[hot].shares)
X     num = hotels[hot].shares;
X
X   printw("%s purchased %d shares of Hotel %c.\n",players[p].name,
X	 num,('A' + hot - 1));
X   return(num);
X};
X    
X        
END_OF_FILE
if test 14330 -ne `wc -c <'comp.c'`; then
    echo shar: \"'comp.c'\" unpacked with wrong size!
fi
# end of 'comp.c'
fi
if test -f 'hotel.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hotel.c'\"
else
echo shar: Extracting \"'hotel.c'\" \(17784 characters\)
sed "s/^X//" >'hotel.c' <<'END_OF_FILE'
X/*
X * This program (called "Hotel") is copyright 1989 to Scott R. Turner,
X * in both source code and executable form.  Permission is given to 
X * copy both the source code and the executable under the following
X * conditions:
X * 
X * COPYING POLICIES
X * 
X *   1. You may copy and distribute verbatim copies of Hotel code as you
X * receive it, in any medium, provided that you conspicuously and
X * appropriately publish on each file a valid copyright notice such as
X * "Copyright (C) 1989 Scott R. Turner", and keep intact the copyright
X * and license notices on all files.  You may charge a distribution fee for the
X * physical act of transferring a copy, but that fee may not exceed
X * your actual costs in creating and delivering the copy.
X * 
X *   2. You may modify your copy or copies of Hotel or any portion of it,
X * and copy and distribute such modifications under the terms of
X * Paragraph 1 above, provided that you also do the following:
X * 
X *     a) cause the modified files to carry prominent notices stating
X *     who last changed such files and the date of any change; and
X * 
X *     b) cause the whole of any work that you distribute or publish,
X *     that in whole or in part contains or is a derivative of Hotel
X *     or any part thereof, to be licensed at no charge to all third
X *     parties on terms identical to those contained in this License
X *     Agreement (except that you may choose to grant more extensive
X *     warranty protection to third parties, at your option).
X *
X *   3. You may not copy, sublicense, distribute or transfer Hotel
X * except as expressly provided under this License Agreement.  Any attempt
X * otherwise to copy, sublicense, distribute or transfer Hotel is void and
X * your rights to use Hotel under this License agreement shall be
X * automatically terminated.  However, parties who have received computer
X * software programs from you with this License Agreement will not have
X * their licenses terminated so long as such parties remain in full compliance.
X * 
X *   4.  Under no circumstances may you charge for copies of Hotel, for copies
X * of any program containing code from Hotel in whole or in part, or for 
X * any software package or collection of programs or code that contains Hotel
X * in whole or part.
X *
X */ 
X/*
X *  hotel.c
X *  Scott R. Turner
X *  9/7/88
X *
X *  The main program and declarations for Hotel.
X *
X */
X
X#include "defs.h"
X#include <signal.h>
X
X#ifdef TURBO
X#include <stdlib.h>
X#include <time.h>
X#endif
X
X/* Hotels Array */
X
Xhotel hotels[MAXHOTELS+1];
X
X/* Players Array */
X
Xplayer players[MAXPLAYERS+1];
X
X/* Board */
X
Xint board[MAXBOARD+1][MAXBOARD+1];
X
X/* Run-time variables */
X
Xint numplayers, numhotels, boardsize, numshares, numtiles, startcash;
Xint turn, maxbuy, debug, pnum;
X
X/* Externals */
X
Xextern int share_cost();
Xextern void majority_bonus();
Xextern void print_board();
Xextern int new_hotel();
Xextern void anykey_help();
X
Xvoid endgame()
X{
X  nocrmode();
X  echo();
X  endwin();
X  printf("\n");
X  exit(1);
X};
X
X/*
X *  Quit - a little subroutine to handle the quit key.
X *
X */
X
Xvoid quit()
X{
X  char ans;
X  
X  printw("\nAre you sure you want to quit? (Y/N) ");
X  refresh();
X  ans = getch();
X  if (ans == 'Y' || ans == 'y') {
X    echo();
X    nocrmode();
X    endwin();
X    exit(1);
X  };
X};
X
Xmain ()
X{
X  int i,j,k,x,y,hotelchoice,played;
X  int purchases[MAXHOTELS];
X  extern long time();
X#ifdef UNIX
X  extern void srandom();
X#endif
X  extern void  human_play();
X  extern int  human_new();
X  extern int  human_save();
X  extern void  human_buy();
X  extern void  human_liquidate();
X  extern void  comp_play();
X  extern int  comp_new();
X  extern int  comp_save();
X  extern void  get_maj_strategy();
X  extern void  comp_liquidate();
X
X  /* Debug flag. */
X  
X  debug = 0;
X  
X  /* Initialize random number generator. */
X
X#ifdef UNIX
X  srandom((int) time(0));
X#else
X  randomize();
X#endif
X
X  /*
X     Curses Initialization.
X   */
X   
X  initscr();
X#ifdef UNIX
X  nonl();
X#endif UNIX
X  crmode();
X
X  /* Initialize game. */
X
X  init();
X  noecho();
X
X  signal(SIGINT,endgame);
X#ifdef UNIX
X  signal(SIGQUIT,endgame);
X#endif
X
X  /* Game Cycle:
X
X        For each player in the game, execute their "play" and "buy"
X	behaviors.
X  */
X  
X  turn = 1;
X
X  while(!game_over()) {
X
X    for (i=1;i<=numplayers;i++) {
X    
X       /*
X        *  If a player has a tile that is permanently unplayable because
X        *  it would cause the merger of two safe hotel chains, then he
X        *  is allowed to discard that tile and draw a new one.  We do this
X        *  automatically for each player at the beginning of each round.
X        *
X        */
X
X      for(k=1;k<=boardsize;k++)
X        for(j=1;j<=boardsize;j++)
X	  if (unplayable(k,j)) {
X	    if (board[k][j] < 0 && board[k][j] != UNPLAYABLE) 
X	    	newtile(-board[k][j]);
X	    board[k][j] = UNPLAYABLE;
X	  };
X	  
X      pnum = i;
X      move((boardsize+5),0);
X      clrtobot();
X      played = 0;
X
X      /*
X       *  The "play" behavior returns (in &x and &y) the location of
X       *  the tile the player would like to play this round.
X       *
X       */
X
X      if (players[i].strategy) {
X	 /*  A computer player. */
X	comp_play(i,&x,&y);
X	printw("%s played (%d,%d).\n",players[i].name,x,y);
X      } else {
X      	/*  Human player. */
X      	human_play(i,&x,&y);
X      };
X
X      /*
X       *  If the move is legal and on the board and owned by the player,
X       *  then make the move.
X       *
X       */
X      
X      if (x > 0 && y > 0 && x <= boardsize && y <= boardsize && legal_play(x,y) &&
X	  board[x][y] == -i) {
X	
X	/*  Place the tile on the board. */
X	
X	board[x][y] = UNUSED;
X	
X	/* Check to see if the play merged two hotel chains, or added to a hotel. */
X
X	hotel_merge(x,y,i);
X
X	/* Check to see if the play created a new hotel chain. */
X
X	if (new_hotel(x,y)) {
X
X	  /* It did, so let him choose the hotel chain. */
X	  
X	  if (players[i].strategy) {
X	    hotelchoice = comp_new(i,x,y);
X	  } else {
X	    hotelchoice = human_new(i,x,y);
X          };
X	  make_new_hotel(hotelchoice,x,y,i);
X	};
X	played = 1;
X	
X      };
X
X      /*
X       *  The player is done placing his tile.  Now execute his buy
X       *  behavior, which returns (in purchases) the stocks he chooses
X       *  to buy.
X       *
X       */
X	
X      if (players[i].strategy) {
X        get_maj_strategy(i,purchases);
X	print_board(human_player);
X	refresh();
X	any_key();
X      } else {
X        human_buy(i,purchases);
X      };
X      /*
X       *  Actually make the purchases, checking to see that the
X       *  the shares are available, the hotel exists, and he has the money.
X       *
X       */
X
X      for (j=1;j<=numhotels;j++)
X	if (purchases[j] != 0 && hotels[j].size > 0 &&
X	    purchases[j] <= hotels[j].shares &&
X	    purchases[j]*share_cost(j) <= players[i].cash) {
X
X	  hotels[j].shares -= purchases[j];
X	  players[i].shares[j] += purchases[j];
X	  players[i].cash -= purchases[j]*share_cost(j);
X	};
X
X      /*  Give the player a new tile to replace the one just played. */
X
X      if (played==1) newtile(i);
X	  
X    };
X    turn++;
X  };
X  standings();
X  endwin();
X  exit(1);
X};
X
X/*
X *  game_over checks to see whether or not the end conditions
X *  have become satisfied.
X *
X */
X
Xgame_over()
X{
X  int i,x,y;
X  int done = 1, any = 0, available = 0;
X  
X  /* Game is over if all the hotels on the board are safe,
X   * or any chain is >  42% of the board, or if no one has
X   * a legal play.
X   */
X  
X  /*
X   *  No legal plays...?
X   *
X   */
X
X  for(x=1;x<=boardsize;x++)
X    for(y=1;y<=boardsize;y++)
X      if (board[x][y] <= 0 && board[x][y] != UNPLAYABLE &&
X          !unplayable(x,y)) available++;
X      
X  if (!available) return(1);
X
X  /*
X   *  Big hotel?
X   *
X   */
X  for(i=1;i<=numhotels;i++)
X    if(hotels[i].size > (.42 * boardsize * boardsize)) return(1);
X  /*
X   *  Just started?
X   *
X   */
X  for(i=1;i<=numhotels;i++)
X    if(hotels[i].size > 0) {
X    	any = 1;
X	break;
X    };
X  if (!any) return(0);
X  for(i=1;i<=numhotels;i++)
X    if(hotels[i].size > 0 && !safe(i)) {
X      done = 0;
X      break;
X    };
X  return(done);
X  
X};
X 
X/*
X *  make_new_hotel makes a new hotel (hotel #n) around x,y.
X *
X */
X  
Xmake_new_hotel(n,x,y,pl)
X     int n,x,y,pl;
X{
X  int change,i,j;
X  
X  board[x][y] = n;
X  hotels[n].size++;
X  spread_hotel(n,x,y);
X
X  /*  Give the player one free share, if available. */
X
X  if (hotels[n].shares > 0) {
X    hotels[n].shares -= 1;
X    players[pl].shares[n] += 1;
X  };
X
X};
X		
X/*
X *  hotel_merge checks to see if the newly placed tile at (x,y) merges two 
X *  hotel chains.
X * 
X */  
X	   
Xhotel_merge(x,y,p)
X  int x,y,p;
X{
X  int adj[MAXHOTELS+1],shares[MAXHOTELS+1];
X  int i, j, k, count, max, dup, winner, hot, maxhot;
X  int hold, sell, trade, numtraded, cp;
X  int max1, max2, num1, num2, first, second;
X
X  /*
X   *  Start by making a list of all the hotels that this 
X   *  new play is adjacent to.
X   * 
X   */
X
X  for(i=1;i<=numhotels;i++) {
X    adj[i] = 0;
X    shares[i] = 0;
X  };
X  count = 0;
X  max =  0;
X  dup = 0;
X
X  for(i= -1;i<2;i++)
X    for(j= -1;j<2;j++) {
X	hot = board[x+i][y+j];
X	if ((i*j == 0) && (i != 0 || j != 0) &&
X	    ((x+i) > 0) && ((y+j) > 0) &&
X	    ((x+i) <= boardsize) && ((y+j) <= boardsize) &&
X	    (hot > 0) && (hot != UNUSED)) {
X	  if (!adj[hot]) count++;
X	  adj[hot] = hotels[hot].size;
X	  shares[hot] = share_cost(hot);
X	};
X      };
X
X  for(i=1;i<=numhotels;i++) 
X    if (adj[i] == max) {
X      dup++;
X    } else if (adj[i] > max) {
X      dup = 0;
X      max = adj[i];
X      maxhot = i;
X    };
X      
X  /*  If count = 0, we weren't adjacent to anything.  */
X
X  if (count == 0) return(0);
X                                                                                                 
X  /*  If count = 1, we were adjacent to a single hotel, so spread that hotel. */
X
X  if (count == 1) {
X	 spread_hotel(maxhot,x,y);
X	 return(1);
X       };
X  
X  /* If count > 1, then we are merging two or more chains. */      
X
X  /* If dup > 0, then we have two chains of the same size,
X   * so the player gets to choose which to dump.  If dup = 0,
X   * then there is a clear winner, and we find it.
X   */
X
X  if (dup > 0) 
X    if (players[p].strategy) {
X        maxhot = comp_save(p,max,adj);
X    } else {
X        maxhot = human_save(p,max,adj);
X    };
X
X  /*
X   *  Hand out the majority bonuses for all the sunken hotels.
X   *
X   */
X
X  for(i=1;i<=numhotels;i++)
X    if(i != maxhot && adj[i] != 0) do_maj_bonuses(i);
X
X  /*
X   *  After the other chains have been sunk, we need to give people
X   *  a chance to liquidate, starting with the current player and 
X   *  continuing in play order.
X   *
X   */
X
X  for(j=1;j<=numhotels;j++)
X    if(adj[j] && j != maxhot)
X      for(i=0;i<numplayers;i++){
X	cp = ((p+i)%numplayers) + 1;
X	if (players[cp].shares[j] > 0) {
X
X          if (players[cp].strategy) {
X            comp_liquidate(cp,maxhot,j,&sell,&trade);
X	  } else {
X            human_liquidate(cp,maxhot,j,&sell,&trade);
X	  };
X
X	  /* Sell as many as he asked. */
X
X	  if (sell <= players[cp].shares[j] && sell > 0) {
X	    players[cp].cash += sell*share_cost(j);
X	    players[cp].shares[j] -= sell;
X	    hotels[j].shares += sell;
X	  };
X	  
X	  /* Trade as many as possible. */
X
X	  if (trade <= players[cp].shares[j] && trade > 0) {
X	    numtraded = (hotels[maxhot].shares <= (int) (trade / 2)) ? (hotels[maxhot].shares * 2) :
X	      trade;
X	    players[cp].shares[j] -= numtraded;
X	    hotels[j].shares += numtraded;
X	    players[cp].shares[maxhot] += round(numtraded / 2);
X	    hotels[maxhot].shares -= round(numtraded / 2);
X	  };
X
X	  /* Everything left gets held. */
X	};
X	
X      };
X
X  /*
X   *  Merge all the chains other than the winner into the winner.
X   *
X   */
X
X  for(i=1;i<=numhotels;i++)
X   if(i != maxhot && adj[i] != 0)
X     for(x=1;x<=boardsize;x++)   
X        for(y=1;y<=boardsize;y++)
X          if (board[x][y] == i) {
X             board[x][y] = maxhot;
X             hotels[i].size--;
X             hotels[maxhot].size++;
X          };
X
X  /*
X   *  Finally, spread the winning hotel, in case the new tile also
X   *  touched some unused tiles.
X   *
X   */
X  
X  spread_hotel(maxhot,x,y);
X  
X};
X
X/*
X *  Spread_hotel iteratively changes unused tiles into the hotel
X *  they are next to. 
X *
X */
X
Xspread_hotel(n,x,y)
X  int n,x,y;
X{
X  int i,j,change;
X  
X  change = 1;
X
X  while(change){
X    change = 0;
X    for(x=1;x<=boardsize;x++)
X      for(y=1;y<=boardsize;y++)
X	if(board[x][y] == n)
X	  for(i= -1;i<2;i++)
X	    for(j= -1;j<2;j++)
X	      if((i*j == 0) && (i != 0 || j != 0) && (x+i) > 0 && (x+i) <= boardsize &&
X		 (y+j) > 0 && (y+j) <= boardsize &&
X		 board[x+i][y+j] == UNUSED) {
X		board[x+i][y+j] = n;
X		hotels[n].size++;
X		change = 1;
X	      };
X  };
X
X};
X 
X/*
X *  safe returns true if a hotel is safe, i.e., > 10
X *
X */
X
Xsafe(hot)
X     int hot;
X{
X  if (hotels[hot].size > 10) return(1);
X  else return(0);
X};
X
X/*
X *  legal_play returns false if the play would create a (numhotels + 1) hotel
X *
X */
X
Xlegal_play(x,y)
X     int x,y;
X{
X  int i,j,new;
X
X  /* Is the new tile adjacent to an existing hotel? */
X
X  new = 1;
X  for(i= -1;i<2;i++)
X    for(j= -1;j<2;j++)
X      if ( i*j == 0 && (i != 0 || j != 0) &&
X	  ((x+i) > 0) && ((y+j) > 0) &&
X	  ((x+i) <= boardsize) && ((y+j) <= boardsize) &&
X	  (board[x+i][y+j] > 0) && (board[x+i][y+j] < UNUSED)) {
X        new = 0;
X	break;
X      };
X
X  if (new == 0) return(1);
X
X  /* Is there an UNUSED adjacent? */
X
X  new = 0;
X  for(i= -1;i<2;i++)
X    for(j= -1;j<2;j++)
X      if ( i*j == 0 && (i != 0 || j != 0) &&
X	  ((x+i) > 0) && ((y+j) > 0) &&
X	  ((x+i) <= boardsize) && ((y+j) <= boardsize) &&
X	  (board[x+i][y+j] == UNUSED)) {
X	new = 1;
X	goto done;
X      };
X  
X done:
X
X  if (new == 0) return(1);
X  
X  /* Is there an available hotel? */
X
X  new = 0;
X  for(i=1;i<=numhotels;i++)
X    if(hotels[i].size == 0) {
X     new = 1;
X     break;
X   };
X
X  return(new);
X
X};
X
X/*
X *  unplayable returns true if the play would merge two "safe" hotels.
X *
X */
X
Xunplayable(x,y)
X     int x,y;
X{
X  
X  int i,j,count,adj[MAXHOTELS+1];
X
X  for(i=1;i<=numhotels;i++)
X    adj[i] = 0;
X
X  for(i= -1;i<2;i++)
X    for(j= -1;j<2;j++)
X      if (i*j == 0 && (i != 0 || j != 0) &&
X	  ((x+i) > 0) && ((y+j) > 0) &&
X	  ((x+i) <= boardsize) && ((y+j) <= boardsize) &&
X	  (board[x+i][y+j] != UNUSED) &&
X	  (board[x+i][y+j] > 0) &&
X	  safe(board[x+i][y+j]))
X	adj[board[x+i][y+j]] = 1;
X
X  count = 0;
X  for(i=1;i<=numhotels;i++)
X    if(adj[i]) count++;
X    
X  if (count > 1 && debug) {
X  	printw("(%d, %d): ",x,y);
X  	for(i=1;i<=numhotels;i++)
X    	  if(adj[i]) printw("%c ",'A'+i-1);
X  	printw("%d\n",count);
X	refresh();
X	any_key();
X  };
X 
X  if (count > 1) return(1);
X  else return(0);
X
X};
X
X/*
X *  standings calculates and  prints the value of everyone at the endgame.
X *
X */
X
Xstandings()
X{
X  int i,j,order[MAXPLAYERS+1],tmp;
X
X  clear();
X  printw("The game is over!.\n\n");
X  for(i=1;i<=numhotels;i++)
X    if(hotels[i].size > 0) do_maj_bonuses(i);
X
X  for(i=1;i<=numplayers;i++)
X    for(j=1;j<=numhotels;j++)
X      if (hotels[j].size > 0) players[i].cash += players[i].shares[j] * share_cost(j);
X
X  /*  Sort  */
X  
X  for(i=1;i<=numplayers;i++) order[i] = i;
X
X  for(j=1;j<=numplayers;j++)
X    for(i=1;i<=(numplayers-1);i++)
X      if (players[order[i]].cash < players[order[i+1]].cash) {
X	tmp = order[i];
X	order[i] = order[i+1];
X	order[i+1] = tmp;
X      };
X
X  clear();
X  printw("Here are the final standings:\n");
X  for(i=1;i<=numplayers;i++)
X    printw("  (%d) %s:  $%ld\n",i,players[order[i]].name,
X      				players[order[i]].cash);
X  refresh();
X  any_key();
X  
X};
X
Xany_key()
X
X{
X  char ans;
X  int y,x;
X
X  clrtoeol();
X  printw("--- Hit any Key to Continue ---");
X  getyx(stdscr,y,x);
X  refresh();
Xtopofanykey:
X  ans = getch();
X  if (islower(ans)) ans = toupper(ans);
X/*
X *  Removed in production version...
X *
X 
X  if (ans == 'D') {
X  	if (!debug) debug = 1;
X	else debug = 0;
X	goto topofanykey;
X  };
X 
X *
X */
X 
X  if (ans == REFRESHKEY) {
X    wrefresh(curscr);
X    goto topofanykey;
X  };
X  if (ans == HELPKEY) {
X    anykey_help();
X    goto topofanykey;
X  };
X  if (ans == QUITKEY) {
X    quit();
X  };
X  move(y,0);
X  clrtoeol();
X};
X
X
X
Xdo_maj_bonuses(i)
X  int i;
X{
X  int j,k,max1,num1,max2,num2,first,second;
X
X  max1 = 0;
X  num1 = 0;
X  max2 = 0;
X  num2 = 0;
X
X  for(j=1;j<=numplayers;j++) {
X    if (players[j].shares[i] > max1) {
X      max2 = max1;
X      num2 = num1;
X      max1 = players[j].shares[i];
X      num1 = 1;
X    } else if (players[j].shares[i] == max1) {
X      num1++;
X    } else if (players[j].shares[i] > max2) {
X      max2 = players[j].shares[i];
X      num2 = 1;
X    } else if (players[j].shares[i] == max2) {
X      num2++;
X    };
X  };
X
X  majority_bonus(i,&first,&second);
X
X  if (max2 == 0 || num1 > 1) {
X
X    /*
X     *  The top dogs split both.
X     *
X     */
X     
X    for(k=1;k<=numplayers;k++)
X      if (players[k].shares[i] == max1) {
X        if (players[k].strategy == 0) {
X	    printw("%s get $%d Majority Bonus for %s\n",
X	       players[k].name, round((first + second) / num1), hotels[i].name);
X	} else {
X	    printw("%s gets $%d Majority Bonus for %s\n",
X	       players[k].name, round((first + second) / num1), hotels[i].name);
X	};
X	players[k].cash += round((first + second) / num1);
X      };
X  } else
X    for (k=1;k<=numplayers;k++)
X      if (players[k].shares[i] == max1) {
X        if (players[k].strategy == 0) {
X	    printw("%s get %d Majority Bonus (First) for %s\n",
X	       players[k].name, first, hotels[i].name);
X	} else {
X	    printw("%s gets %d Majority Bonus (First) for %s\n",
X	       players[k].name, first, hotels[i].name);
X	};
X	players[k].cash += round(first);
X      } else if (players[k].shares[i] == max2) {
X        if (players[k].strategy == 0) {
X	printw("%s get %d Majority Bonus (Second) for %s\n",
X	       players[k].name, round(second/num2), hotels[i].name);
X	} else {
X	    printw("%s gets %d Majority Bonus (Second) for %s\n",
X	       players[k].name, round(second/num2), hotels[i].name);
X	};
X	players[k].cash += round(second/num2);
X      };
X  refresh();
X  any_key();
X
X};
X
END_OF_FILE
if test 17784 -ne `wc -c <'hotel.c'`; then
    echo shar: \"'hotel.c'\" unpacked with wrong size!
fi
# end of 'hotel.c'
fi
if test -f 'human.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'human.c'\"
else
echo shar: Extracting \"'human.c'\" \(9962 characters\)
sed "s/^X//" >'human.c' <<'END_OF_FILE'
X/*
X * This program (called "Hotel") is copyright 1989 to Scott R. Turner,
X * in both source code and executable form.  Permission is given to 
X * copy both the source code and the executable under the following
X * conditions:
X * 
X * COPYING POLICIES
X * 
X *   1. You may copy and distribute verbatim copies of Hotel code as you
X * receive it, in any medium, provided that you conspicuously and
X * appropriately publish on each file a valid copyright notice such as
X * "Copyright (C) 1989 Scott R. Turner", and keep intact the copyright
X * and license notices on all files.  You may charge a distribution fee for the
X * physical act of transferring a copy, but that fee may not exceed
X * your actual costs in creating and delivering the copy.
X * 
X *   2. You may modify your copy or copies of Hotel or any portion of it,
X * and copy and distribute such modifications under the terms of
X * Paragraph 1 above, provided that you also do the following:
X * 
X *     a) cause the modified files to carry prominent notices stating
X *     who last changed such files and the date of any change; and
X * 
X *     b) cause the whole of any work that you distribute or publish,
X *     that in whole or in part contains or is a derivative of Hotel
X *     or any part thereof, to be licensed at no charge to all third
X *     parties on terms identical to those contained in this License
X *     Agreement (except that you may choose to grant more extensive
X *     warranty protection to third parties, at your option).
X *
X *   3. You may not copy, sublicense, distribute or transfer Hotel
X * except as expressly provided under this License Agreement.  Any attempt
X * otherwise to copy, sublicense, distribute or transfer Hotel is void and
X * your rights to use Hotel under this License agreement shall be
X * automatically terminated.  However, parties who have received computer
X * software programs from you with this License Agreement will not have
X * their licenses terminated so long as such parties remain in full compliance.
X * 
X *   4.  Under no circumstances may you charge for copies of Hotel, for copies
X * of any program containing code from Hotel in whole or in part, or for 
X * any software package or collection of programs or code that contains Hotel
X * in whole or part.
X *
X */ 
X/*
X *  human.c
X *  Scott R. Turner
X *  9/7/88
X *
X *  This file contains the "play", "buy" and "liquidate" strategies
X *  for human players.
X *
X */
X#include "defs.h"
X#include "my_wgets.h"
Xextern int legal_play();
Xextern void print_board();
Xextern void update_cash();
Xextern void getnum_help();
Xextern void buy_help();
Xextern void newhotel_help();
Xextern void save_help();
Xextern void quit();
X
X/*
X *  human_play queries the player to find out which of his tiles
X *  he would like to play.
X *
X */
X
Xvoid  human_play(n,px,py)
X     int n;
X     int *px,*py;
X{
X  int tile,i,j,legl;
X
X  print_board(n);
X  move((boardsize+5),0);
X  clrtobot();
X  printw("Cash: $%d\n",players[n].cash);
X  printw("Holdings: ");
X  for(i=1;i<=numhotels;i++)
X    if(players[n].shares[i] > 0)
X      printw("(%c) %d  ",(i + 'A' - 1),players[n].shares[i]);
X  printw("\n");
X
X  /*  The player may not have a legal play.  */
X
X  legl = 0;
X    for(i=1;i<=boardsize;i++)
X      for(j=1;j<=boardsize;j++)
X	if(board[i][j] == -n && legal_play(i,j)) {
X	  legl=1;
X	  goto done;
X	}
X done:
X
X  if (!legl) {
X    printw("Sorry, you have no legal moves.\n");
X    refresh();
X    *px = -1;
X    *py = -1;
X    return;
X  };
X
X  /* Else get his play. */
X
X  do {
X    legl = 0;
X    printw("Which tile to play? ");
X    refresh();
X    tile = getnum(1,numtiles);
X
X    /* Is this legitimate? */
X
X    if(tile > numtiles || tile < 1) {
X      printw("That is not a valid tile number.\n");
X    } else {
X
X      /* Figure out where it is */
X
X      for(i=1;i<=boardsize;i++)
X	for(j=1;j<=boardsize;j++)
X	  if(board[i][j] == -n) {
X	    tile--;
X	    if (tile == 0) {
X	      *px = i;
X	      *py = j;
X	      goto finished;
X	    };
X	  };
X      
X    finished:
X      
X      legl = legal_play(*px,*py);
X      if (!legl) {
X        move((boardsize+8),0);
X	clrtobot();
X	printw("You cannot create another hotel.\n");
X	refresh();
X      };
X    };
X  } while (!legl);
X  
X};
X
X/*
X *  human_buy queries the player and asks what shares he would
X *  like to purchase, and returns the answer in purchases.
X *
X */
Xbeep2()
X{
X  printf("%c",7);
X};
X
Xvoid  human_buy(p,purchases)
X     int p, purchases[MAXHOTELS];
X{
X  extern int share_cost();
X  int i,j,tot,cashtot,goahead;
X  char ans;
X
X  for(i=1;i<=numhotels;i++) purchases[i] = 0;
X
X  goahead = 0;
X  for(j=1;j<=numhotels;j++)
X    if(hotels[j].shares>0 &&
X       hotels[j].size>0 && players[p].cash >= share_cost(j))
X      goahead = 1;
X
X  if (!goahead) return;
X
X  /*  Query the user about each available hotel. */
X
X  print_board(p);
X  move((boardsize+5),0);
X  clrtobot();
X  printw("What to buy?\n");
X  printw("(Hit letter once for each stock, Space to finish.) ");
X  refresh();
X
X  tot = 0;
X  cashtot = players[p].cash;
X
X  do {
X    ans = getch();
X    if (islower(ans)) ans = toupper(ans);
X    if (ans == REFRESHKEY) {
X      wrefresh(curscr);
X      continue;
X    }
X    if (ans == QUITKEY) {
X      quit();
X    };
X    if (ans == HELPKEY) {
X        buy_help();
X	continue;
X    };
X    if (ans == 32) break;
X    clrtobot();
X    i = (ans - 'A' + 1);
X    if (i < 1 || i > numhotels || hotels[i].size == 0 ||
X	hotels[i].shares == 0) {
X      /* An invalid choice, so beep. */
X      beep2();
X      continue;
X    };
X    /* Can he afford this? */
X    if (share_cost(i) > cashtot) {
X      beep2();
X      continue;
X    };
X    purchases[i]++;
X    tot++;
X    cashtot -= share_cost(i);
X  } while (tot != maxbuy);
X  move((boardsize+10),0);
X  clrtobot();
X  refresh();
X};
X
X/*
X *  human_liquidate is called when a hotel chain is sunk and a player might
X *  have stock to get rid of.
X *
X */
X
Xvoid  human_liquidate(p,maxhot,sunk,sell,trade)
X     int p, *sell, *trade, maxhot,sunk;
X{
X  int i;
X
X  print_board(p);
X  refresh();
X  if(players[p].shares[sunk]) {
X      *sell = MAXSHARES + 1;
X      while(*sell+*trade > players[p].shares[sunk]) {
X	move((boardsize+5),0);
X	clrtobot();
X	*sell = 0;
X	*trade = 0;
Xagain:	  
X	printw("You have %d shares of (%d) %s.\n",
X	       players[p].shares[sunk],sunk,hotels[sunk].name);
X	if (hotels[maxhot].shares != 0) {
X	  printw("There are %d shares of %s available.\n",hotels[maxhot].shares,
X		 hotels[maxhot].name);
X	  printw("How many shares would you like to trade in (2 for 1)? ");
X	  refresh();
X	  echo();
X#ifdef UNIX
X	  nl(); 
X#endif UNIX
X        /*	  scanw("%d",trade);  */
X        /*  Trying getint. */
X        *trade = getint();
X#ifdef UNIX
X	  nonl(); 
X#endif UNIX
X	  noecho();
X	  printw("\n");
X
X	  if (*trade % 2) {
X	    move((boardsize+5),0);
X	    clrtobot();
X	    printw("Trading an odd number of shares is wasteful.\n");
X	    refresh();
X	    (void) any_key();
X	    goto again;
X	  };
X	  if ((*trade / 2) > hotels[maxhot].shares) {
X	    move((boardsize+5),0);
X	    clrtobot();
X	    printw("No point in trading for more shares than available.");
X	    refresh();
X	    (void) any_key();
X	    goto again;
X	  };
X	};
X	if (players[p].shares[sunk] > *trade) {
X	  printw("How many shares would you like to sell at %d? ",share_cost(sunk));
X	  refresh();
X	  echo();
X#ifdef UNIX
X	  nl(); 
X#endif UNIX
X	  /*  scanw("%d",sell); */
X	  *sell = getint();
X#ifdef UNIX
X	  nonl(); 
X#endif UNIX
X	  noecho();
X	  printw("\n");
X        };
X	if (*sell+*trade > players[p].shares[sunk]) {
X	  printw("That's too many.  You only have %d shares.\n",
X		 players[p].shares[sunk]);
X          refresh();
X          (void) any_key();
X	};
X     };
X   };
X};
X
Xint  human_new(n,x,y)
X     int n,x,y;
X{
X  int i;
X  char ans;
X
X  print_board(n);
X  do {
Xtopofselect:
X    move((boardsize + 5), 0);
X    clrtobot();
X    printw("You have created a new hotel.\n");
X    printw("Available hotels:\n");
X    for(i=1;i<=numhotels;i++)
X      if (hotels[i].size == 0)
X        printw("%c ",hotels[i].name[0]);
X    printw("\nSelect a hotel: ");
X    refresh();
Xnextinput:
X    ans = getch();
X    if (islower(ans)) ans = toupper(ans);
X    if (ans == REFRESHKEY) {
X      wrefresh(curscr);
X      goto nextinput;
X    }
X    if (ans == QUITKEY) {
X      quit();
X    };
X    if (ans == HELPKEY) {
X        newhotel_help();
X        goto topofselect;
X    };
X    clrtobot();
X    i = (ans - 'A' + 1);
X    if (i < 1 || i > numhotels || hotels[i].size != 0) {
X#ifdef UNIX
X       printw("\n");
X#endif UNIX       
X       printw("That is not a legal selection.\n");
X       refresh();
X       goto topofselect;
X    };
X  } while (0);
X  move((boardsize+10),0);
X  clrtobot();
X  refresh();
X  return(i);
X};
X
X/*
X *  human_save is a routine for asking the player which of N
X *  equal size hotels they'd like to save.
X *
X */
X
Xint  human_save(p,max,adj)
X     int p,adj[MAXHOTELS+1];
X{
X  int j,i;
X  char ans;
X
X  print_board(p);
X  printw("Save which hotel: ");
X  for(j=1;j<=MAXHOTELS;j++)
X    if (adj[j] == max) printw(" %c",hotels[j].name[0]);
X  printw("?");
X  refresh();
X  i = 0;
X  do {
X    ans = getch();
X    if (islower(ans)) ans = toupper(ans);
X    if (ans == REFRESHKEY) {
X      wrefresh(curscr);
X      continue;
X    }
X    if (ans == QUITKEY) {
X      quit();
X    };
X    if (ans == HELPKEY) {
X        save_help();
X	continue;
X    };
X    clrtobot();
X    i = (ans - 'A' + 1);
X  } while (i < 1 || i > numhotels || adj[i] != max);
X  printw("\n");
X  move((boardsize+10),0);
X  clrtobot();
X  refresh();
X  return(i);
X
X};
X
X/*
X *  getnum does the input processing to get a number in the
X *  range [low,high] inclusive.
X *
X *  Should put hooks in here for clear and help, etc.
X */
X
Xgetnum(low,high)
X     int low,high;
X{
X  char ch;
X  int ans,y,x;
X
X  ans = low - 1;
X  do {
X    ch = getch();
X    if (islower(ch)) ch = toupper(ch);
X    if (ch == REFRESHKEY) {
X      wrefresh(curscr);
X      continue;
X    };
X    if (ch == HELPKEY) {
X        getnum_help();
X	continue;
X    };
X    if (ch == QUITKEY) {
X      quit();
X    };
X    clrtobot();
X    ans = ch - '0';
X  } while (ans < low || ans > high);
X  printw("%d\n",ans);
X  return(ans);
X};
END_OF_FILE
if test 9962 -ne `wc -c <'human.c'`; then
    echo shar: \"'human.c'\" unpacked with wrong size!
fi
# end of 'human.c'
fi
if test -f 'init.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'init.c'\"
else
echo shar: Extracting \"'init.c'\" \(5669 characters\)
sed "s/^X//" >'init.c' <<'END_OF_FILE'
X/*
X * This program (called "Hotel") is copyright 1989 to Scott R. Turner,
X * in both source code and executable form.  Permission is given to 
X * copy both the source code and the executable under the following
X * conditions:
X * 
X * COPYING POLICIES
X * 
X *   1. You may copy and distribute verbatim copies of Hotel code as you
X * receive it, in any medium, provided that you conspicuously and
X * appropriately publish on each file a valid copyright notice such as
X * "Copyright (C) 1989 Scott R. Turner", and keep intact the copyright
X * and license notices on all files.  You may charge a distribution fee for the
X * physical act of transferring a copy, but that fee may not exceed
X * your actual costs in creating and delivering the copy.
X * 
X *   2. You may modify your copy or copies of Hotel or any portion of it,
X * and copy and distribute such modifications under the terms of
X * Paragraph 1 above, provided that you also do the following:
X * 
X *     a) cause the modified files to carry prominent notices stating
X *     who last changed such files and the date of any change; and
X * 
X *     b) cause the whole of any work that you distribute or publish,
X *     that in whole or in part contains or is a derivative of Hotel
X *     or any part thereof, to be licensed at no charge to all third
X *     parties on terms identical to those contained in this License
X *     Agreement (except that you may choose to grant more extensive
X *     warranty protection to third parties, at your option).
X *
X *   3. You may not copy, sublicense, distribute or transfer Hotel
X * except as expressly provided under this License Agreement.  Any attempt
X * otherwise to copy, sublicense, distribute or transfer Hotel is void and
X * your rights to use Hotel under this License agreement shall be
X * automatically terminated.  However, parties who have received computer
X * software programs from you with this License Agreement will not have
X * their licenses terminated so long as such parties remain in full compliance.
X * 
X *   4.  Under no circumstances may you charge for copies of Hotel, for copies
X * of any program containing code from Hotel in whole or in part, or for 
X * any software package or collection of programs or code that contains Hotel
X * in whole or part.
X *
X */ 
X/*
X *  init.c
X *  Scott R. Turner
X *  9/7/88
X *
X *  init.c contains the routines to initialize the game and to 
X *  ask the initial questions of the user (number of players, etc.)
X *
X */
X#include "defs.h"
Xextern void newtile();
Xextern void help();
Xextern int getnum();
Xextern void any_key();
Xint human_player;
X
Xinit()
X{
X  int i,j,x,y;
X  char ans[80], ch;
X
X
X/* Initialize run-time variables.  These will probably be modified
X   or set to new values by the function that will read the startup
X   file. 
X*/
X
X  numhotels = 7;
X  boardsize = 10;
X  numshares = 30;
X  startcash = 6000;
X  numtiles = 6;
X  maxbuy = 3;
X
X/*   At this point, read the initialization file. */
X  
X/* Initialize the board */
X
X  for(i=1;i<=MAXBOARD;i++)
X    for(j=1;j<=MAXBOARD;j++)
X      board[i][j] = 0;
X  
X/* Initialize the hotels */
X
X  for(i=1;i<=MAXHOTELS;i++)
X    {
X      hotels[i].size = 0;
X      hotels[i].shares = numshares;
X
X      /*  Class and Name will probably be set in the initialization file. */
X
X    };
X
X  strcpy(hotels[1].name,"American Motel");
X  hotels[1].class = 0;
X  strcpy(hotels[2].name,"Bedford Arms");
X  hotels[2].class = 0;
X  strcpy(hotels[3].name,"Century Plaza");
X  hotels[3].class = 1;
X  strcpy(hotels[4].name,"Danford Arms");
X  hotels[4].class = 1;
X  strcpy(hotels[5].name,"Eagle Overnight");
X  hotels[5].class = 1;
X  strcpy(hotels[6].name,"Fawlty Towers");
X  hotels[6].class = 2;
X  strcpy(hotels[7].name,"Girabaldi Deluxe");
X  hotels[7].class = 2;
X
X  /*  Give the players various names, if they turn out to be computer */
X
X  strcpy(players[1].name,"Andrew");
X  strcpy(players[2].name,"Betty");
X  strcpy(players[3].name,"Charley");
X  strcpy(players[4].name,"Darlene");
X  strcpy(players[5].name,"Edmond");
X  strcpy(players[6].name,"Freddy");
X  strcpy(players[7].name,"Gertrude");
X
X  for(i=1;i<=MAXPLAYERS;i++)
X    {
X      players[i].cash = startcash;
X      for(j=1;j<=MAXHOTELS;j++)
X	players[i].shares[j] = 0;
X    };
X    
X  /* Copyright Screen */
X  clear();
X  move(3,0);
X  printw("                                   H*O*T*E*L\n");
X  printw("                       Copyright 1989 by Scott R. Turner\n");
X  refresh();
X  sleep(1);
X  clear();
X
X  /* Time to query the user. */
X
X  printw("Welcome to the game of Hotel.\n\n");
X  printw("Instructions? (Y/N) ");
X  refresh();
X  noecho();
X  crmode();
X  ch = getch();
X  if (ch == 'Y' || ch == 'y') help();
X  printw("\nHow many players? (2 to %d) ",MAXPLAYERS);
X  refresh();
X  numplayers = getnum(2,MAXPLAYERS);
X  for(i=1;i<=numplayers;i++){
X  	players[i].strategy = 1;
X  };
X  human_player = randum(numplayers);
X  players[human_player].strategy = 0;
X  strcpy(players[human_player].name,"You");
X  printw("You will be the ");
X  switch (human_player) {
X  	case 1: printw("first");
X  		break;
X  	case 2: printw("second");
X  		break;
X  	case 3: printw("third");
X  		break;
X  	case 4: printw("fourth");
X  		break;
X  	case 5: printw("fifth");
X  		break;
X  	case 6: printw("sixth");
X  		break;
X  	case 7: printw("seventh");
X  		break;
X  	};
X  printw(" player.\n");
X  any_key();
X  clear();
X  
X/* Give every player some initial tiles. */
X
X  for(i=1;i<=numplayers;i++)
X    for(j=1;j<=numtiles;j++)
X      newtile(i);
X
X/* Place one tile for each player. */
X
X  for(i=1;i<=numplayers;i++) {
X    x = randum(boardsize);
X    y = randum(boardsize);
X    while(board[x][y] != 0) {
X      x = randum(boardsize);
X      y = randum(boardsize);
X    };
X    board[x][y] = UNUSED;
X  };
X};
END_OF_FILE
if test 5669 -ne `wc -c <'init.c'`; then
    echo shar: \"'init.c'\" unpacked with wrong size!
fi
# end of 'init.c'
fi
echo shar: End of archive 1 \(of 2\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both 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