DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T c

⟦8596332bd⟧ TextFile

    Length: 14330 (0x37fa)
    Types: TextFile
    Names: »comp.c«

Derivation

└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
    └─⟦this⟧ »EUUGD18/General/Hotel/comp.c« 

TextFile

/*
 * This program (called "Hotel") is copyright 1989 to Scott R. Turner,
 * in both source code and executable form.  Permission is given to 
 * copy both the source code and the executable under the following
 * conditions:
 * 
 * COPYING POLICIES
 * 
 *   1. You may copy and distribute verbatim copies of Hotel code as you
 * receive it, in any medium, provided that you conspicuously and
 * appropriately publish on each file a valid copyright notice such as
 * "Copyright (C) 1989 Scott R. Turner", and keep intact the copyright
 * and license notices on all files.  You may charge a distribution fee for the
 * physical act of transferring a copy, but that fee may not exceed
 * your actual costs in creating and delivering the copy.
 * 
 *   2. You may modify your copy or copies of Hotel or any portion of it,
 * and copy and distribute such modifications under the terms of
 * Paragraph 1 above, provided that you also do the following:
 * 
 *     a) cause the modified files to carry prominent notices stating
 *     who last changed such files and the date of any change; and
 * 
 *     b) cause the whole of any work that you distribute or publish,
 *     that in whole or in part contains or is a derivative of Hotel
 *     or any part thereof, to be licensed at no charge to all third
 *     parties on terms identical to those contained in this License
 *     Agreement (except that you may choose to grant more extensive
 *     warranty protection to third parties, at your option).
 *
 *   3. You may not copy, sublicense, distribute or transfer Hotel
 * except as expressly provided under this License Agreement.  Any attempt
 * otherwise to copy, sublicense, distribute or transfer Hotel is void and
 * your rights to use Hotel under this License agreement shall be
 * automatically terminated.  However, parties who have received computer
 * software programs from you with this License Agreement will not have
 * their licenses terminated so long as such parties remain in full compliance.
 * 
 *   4.  Under no circumstances may you charge for copies of Hotel, for copies
 * of any program containing code from Hotel in whole or in part, or for 
 * any software package or collection of programs or code that contains Hotel
 * in whole or part.
 *
 */ 
/*
 *  comp.c
 *  Scott R. Turner
 *  Wed Nov  2 11:05:22 1988 -- Scott R. Turner
 *
 *  This file contains the routines that implement the computer
 *  player.
 *
 */
#include "defs.h"
extern int legal_play();
extern void print_board();
extern void update_cash();
extern int maj_bonus();
extern int mergecheck();
extern int adjacent();

/*
 *  Comp_play selects a tile to play.
 *
 *  (1) If you can sink a hotel that you have a majority
 *      interest in, do so.
 *  (1a) If you can sink a hotel that you do not have a 
 *	majority interest in to a hotel you do have a 
 *	majority interest in, do so.
 *  (2) If you can create a hotel, do so.
 *  (3) If you can extend the size of a hotel you
 *      have a majority interest in, do so.
 *  (4) If you can make an isolated play, do so.
 *  (5) Play randomly.
 * 
 *
 */

void  comp_play(n,px,py)
     int n;
     int *px,*py;
{
  int i,j,k,legl,plays[20][2],numplays;
  int possibles[MAXHOTELS],mhotel,mvalue,mx,my,p;
  int hotel1a,x1a,y1a;
  

  /*  The computer may not have a legal play.  */

  legl = 0;
    for(i=1;i<=boardsize;i++)
      for(j=1;j<=boardsize;j++) 
	if(board[i][j] == -n && legal_play(i,j)) {
	  legl=1;
	  goto done;
	}
 done:

  if (!legl) {
    printw("%s has no legal moves.\n",players[n].name);
    refresh();
    *px = -1;
    *py = -1;
    return;
  };

  /*
   *  Decide the computer's play.
   *
   */

  /*  (1) Look for hotels to sink
   *
   *    (a) find all the possibles merges for each play.
   *    (b) pick out the biggest merge that you have a share in.
   *
   */

  mx = 0;
  my = 0;
  mhotel = 0;
  mvalue = 0;
  hotel1a = 0;
  for(i=1;i<=boardsize;i++)
    for(j=1;j<=boardsize;j++) 
      if(board[i][j] == -n && legal_play(i,j) && mergecheck(i,j,possibles))
	for (p = 1;p<=numhotels;p++) {
	  /*  This is looking for (1) */
	  if (possibles[p] && (maj_bonus(n,p) > mvalue)) {
	    mvalue = maj_bonus(n,p);
	    mhotel = p;
	    mx = i;
	    my = j;
	  };
	  /*  This is looking for (1a) */
	  if (possibles[p] && stock_differential(n,p) > 3 && 
	      maj_in_merge(p,i,j)) {
	        hotel1a = p;
	        x1a = i;
	        y1a = j;
	    };
 	};

  if (mhotel) {
    /*  We are going to play mx,my to sink hotel #p. */
    if (debug) printw("%s plays %d,%d sinking %c.\n",players[n].name,mx,my,('A'+mhotel-1));
    *px = mx;
    *py = my;
    return;
  };

  if (hotel1a) {
    /*  We are going to play mx,my to sink hotel #p. */
    if (debug) printw("%s plays %d,%d sinking %c.\n",players[n].name,mx,my,('A'+hotel1a-1));
    *px = x1a;
    *py = y1a;
    return;
  };
  
  /*
   *  (2) Create a new hotel if possible.
   *
   */

  numplays = 0;
  for(i=1;i<=boardsize;i++)
    for(j=1;j<=boardsize;j++) 
      if(board[i][j] == -n && legal_play(i,j) && new_hotel(i,j)) {
	numplays++;
	plays[numplays][0] = i;
	plays[numplays][1] = j;
      };

  if (numplays) {
    k = randum(1,numplays);
    *px = plays[k][0];
    *py = plays[k][1];
    if (debug) printw("%s plays %d,%d to create a new hotel.\n",players[n].name,*px,*py); 
    return;
  };

  /*
   *  (3) Extend hotels that I own stock in.
   *
   */

  mhotel = 0;
  mvalue = 0;
  for(i=1;i<=boardsize;i++)
    for(j=1;j<=boardsize;j++) 
      if(board[i][j] == -n && legal_play(i,j) && !mergecheck(i,j,possibles)
	 && adjacent(i,j,&k) && players[n].shares[k] > mvalue) {
	mhotel = k;
	mvalue = players[n].shares[k];
      };
  numplays = 0;
  for(i=1;i<=boardsize;i++)
    for(j=1;j<=boardsize;j++) 
      if(board[i][j] == -n && legal_play(i,j) && !mergecheck(i,j,possibles)
	 && adjacent(i,j,&k) && k == mhotel) {
	numplays++;
	plays[numplays][0] = i;
	plays[numplays][1] = j;
      };
  
  if (numplays) {
    k = randum(1,numplays);
    *px = plays[k][0];
    *py = plays[k][1];
    if (debug) printw("%s plays %d,%d to extend a hotel.\n",players[n].name,*px,*py);
    return;
  };

  /*
   *  (4) Make an isolated play.
   *
   */

  numplays = 0;
  for(i=1;i<=boardsize;i++)
    for(j=1;j<=boardsize;j++)
      if(board[i][j] == -n && legal_play(i,j) && !mergecheck(i,j,possibles)
	 && !adjacent(i,j,&k)) {
	numplays++;
	plays[numplays][0] = i;
	plays[numplays][1] = j;
      };

  if (numplays) {
    k = randum(1,numplays);
    *px = plays[k][0];
    *py = plays[k][1];
    if (debug) printw("%s plays %d,%d (isolated).\n",players[n].name,*px,*py);
    return;
  };

  /*
   *  (5) Play randomly.
   *
   */

  numplays = 0;
  for(i=1;i<=boardsize;i++)
    for(j=1;j<=boardsize;j++)
      if(board[i][j] == -n && legal_play(i,j)){
	numplays++;
	plays[numplays][0] = i;
	plays[numplays][1] = j;
      };

  if (numplays) {
    k = randum(1,numplays);
    *px = plays[k][0];
    *py = plays[k][1];
    if (debug) printw("%s plays %d,%d (randomly).\n",players[n].name,*px,*py);
    return;
  };

  /*  Otherwise, give up. */
  if (debug) printw("%s couldn't find a play.\n",players[n].name);
  return;

};

/*
 *  Buying Strategies (General Notes)
 *
 *  (1) Theoretically, you could keep track in your head of all the
 *      stocks sold (and the stocks available), so comp_buy is free
 *      to rummage through other player's stock holdings.
 *
 */

/*
 *  Get Majorities
 *
 *  The "Get Majorities" strategy attempts to gain and maintain
 *  majorities in as many hotels as possible.
 *
 */

 get_maj_strategy(p,purchases)
     int p, purchases[MAXHOTELS];
{
  extern int share_cost();
  int i,j,ok[MAXHOTELS],max[MAXHOTELS],spread[MAXHOTELS],numok,pick;
  int order[MAXHOTELS],numorder,numbought,tmp;

  /* Which hotels should be considered? */

  numok = 0;
  for(i=1;i<=numhotels;i++) {
    purchases[i] = 0;
    max[i] = 0;
    spread[i] = 0;
    if (hotels[i].shares > 0 && hotels[i].size > 0 &&
	players[p].cash > share_cost(i)) {
      ok[i] = 1;
      numok++;
    } else {
      ok[i] = 0;
    };
  };

  if(!numok) return;
  
  /* What's my share situation in each re other players? */

  for(i=1;i<=numhotels;i++)
    if (ok[i])
      for(j=1;j<=numplayers;j++) {
        if (j != p && players[j].shares[i]) spread[i]++;
	if (j != p && players[j].shares[i] > max[i])
	  max[i] = players[j].shares[i];
	};
	
  /*
   *  We can ignore hotels that we already have a 4 advantage
   *  in.
   *
   */
   
  for(i=1;i<=numhotels;i++)
    if (ok[i] && (players[p].shares[i] - max[i]) > 3) ok[i] = 0;
	  
  /*
   * Rank the ok hotels according to the following cost
   * equation:
   * 
   *  cost(i) = share_cost(i) * (needed_for_max + num_competing*3)
   *
   *  We do this with a rather inefficient bubble sort, but
   *  computing cost isn't really an issue.
   *
   */
  
  numorder = 0;
  for(i=1;i<=numhotels;i++) 
    if (ok[i]) {
    	numorder++;
        order[numorder] = i;
    };
   
  for(i=1;i<=numorder;i++)
    for(j=1;j<=(numorder-1);j++)
      if ((share_cost(order[j]) *
             ((4-(players[p].shares[order[j]] - max[order[j]])) +
              (spread[order[j]]*3))) >
          (share_cost(order[j+1]) *
             ((4-(players[p].shares[order[j+1]] - max[order[j+1]])) +
              (spread[order[j+1]]*3)))) {
	  tmp = order[j];
	  order[j] = order[j+1];
	  order[j+1] = tmp;
	};
              
/*   printw("Stock order is: ");
   for(i=1;i<=numorder;i++) printw("%d ",order[i]);
   printw("\n");
   print_board(1);
   refresh();
   any_key();
*/	
  /*
   *  If we've just gotten the free share in something, buy 
   *  some more.
   *
   */
  
  for(i=1;i<=numhotels;i++)
    if(ok[i] && players[p].shares[i] == 1 && max[i] == 0) {
    	pick = i;
	purchases[pick] = num_shares(p,i,3);
	return;
    };
    
   /*
    *  Otherwise, buy off the top.
    *
    */
   
   if (numorder) {
     purchases[order[1]] = num_shares(p,order[1],3);
   };
   return;     

};

/*
 *  comp_liquidate is called when a hotel chain is sunk and a player might
 *  have stock to get rid of.
 *
 */

void  comp_liquidate(p,maxhot,sunk,sell,trade)
     int p, *sell, *trade, maxhot,sunk;
{
  int i,j,maxtrade,num,mshares;
  float coverage;

  num = 0;
  for(i=1;i<=boardsize;i++)
    for(j=1;j<=boardsize;j++)
      if (board[i][j] > 0) num++;
  coverage = (num + 0.0) / (boardsize * boardsize);

  /* If game is young, hold all stock. */
  
  if (coverage < .40) {
    *sell = 0;
    *trade = 0;
    return;
  };

  /* Figure the maximum you can trade. */

  if ((int) players[p].shares[sunk]/2 > hotels[sunk].shares)
    maxtrade = hotels[sunk].shares * 2;
  else
    maxtrade = players[p].shares[sunk];
  
  /* If game is old, trade all possible. */

  if (coverage > .60) {
    *trade = maxtrade;
    *sell = (players[p].shares[sunk] - maxtrade);
    return;
  };

  /* Trade if the trade makes financial sense or
   * if it will pull you within 3 of the maximum stockholder
   * in maxhot.
   */

  if (share_cost(sunk)*2 <= share_cost(maxhot)) {
    *trade = maxtrade;
    *sell = (players[p].shares[sunk] - maxtrade);
    return;
  };

  mshares = 0;
  for(i=1;i<=numplayers;i++)
    if (i != p && players[i].shares[maxhot] > mshares)
      mshares = players[i].shares[maxhot];
      
  if (players[p].shares[maxhot] + (maxtrade / 2) + 3 >= mshares) {
    *trade = maxtrade;
    *sell = (players[p].shares[sunk] - maxtrade);
    return;
  };

  /*
   *  Otherwise, trade a random number.
   *
   */

  *trade = randum(maxtrade);
  *sell = randum(players[p].shares[sunk] - *trade);
  return;
  
};

int  comp_new(n,x,y)
     int n,x,y;
{
  int i,max,hot;

  /*
   *  Picks the hotel it holds the most stock in.
   */

  max = -1;
  for(i=1;i<=numhotels;i++) {
    if (hotels[i].size == 0 && players[n].shares[i] == max && randum(10) > 5) {
        max = players[n].shares[i];
	hot = i;
    };
    if (hotels[i].size == 0 && players[n].shares[i] > max) {
        max = players[n].shares[i];
	hot = i;
    };
  };
  	
  printw("%s creates hotel %c.\n",players[n].name,'A' + hot - 1);
  return(hot);

};

/*
 *  comp_save is a routine for asking the player which of N
 *  equal size hotels they'd like to save.
 *
 *  Save the hotel you have the most stock in.
 *
 */

int  comp_save(p,max,adj)
     int p,max,adj[MAXHOTELS+1];
{
  int num,i,choice,top;

  top = -1;
  choice = 0;
  for(i=1;i<=numhotels;i++)
    if (adj[i] == max && players[p].shares[i] > top) {
    	top = players[p].shares[i];
    	choice = i;
    };

  return(choice);
};

 /*
  *  This function returns the stock differential between
  *  "player" and the top holder in the hotel.
  *
  */

int stock_differential(p,h)
    int p,h;
{
  int i,diff;
  
  diff = 0;
  for(i=1;i<=numplayers;i++)
    if (i != p &&
      (players[i].shares[h]-players[p].shares[h]) > diff)
        diff = (players[i].shares[h]-players[p].shares[h]);
  return(diff);
  
};
	
/*
 *  Maj_in_merge returns true if playing x,y would merge h
 *  into another h that the player has a majority interest
 *  in.  (Whew!)
 *
 */

int maj_in_merge(p,x,y)
    int p,x,y;
{
    
  int i,lsize,mergeh;
  int j,k,max1,max2,first,second;

  lsize = 0;
  mergeh = 0;
  for(i= -1;i<2;i++)
    for(j= -1;j<2;j++)
      if ( i*j == 0 && (i != 0 || j != 0) &&
	  ((x+i) > 0) && ((y+j) > 0) &&
	  ((x+i) <= boardsize) && ((y+j) <= boardsize) &&
	  (board[x+i][y+j] != UNUSED) &&
	  (board[x+i][y+j] > 0)) {
	if (hotels[board[x+i][y+j]].size > lsize) {
            mergeh = board[x+i][y+j];
        };
    };

  max1 = 0;
  max2 = 0;
  for(j=1;j<=numplayers;j++) {
    if (players[j].shares[mergeh] > max1) {
      max2 = max1;
      max1 = players[j].shares[mergeh];
    } else if (players[j].shares[mergeh] > max2) {
      max2 = players[j].shares[mergeh];
    };
  };

  if (players[p].shares[mergeh] > max2) {
    return(1);
  } else {
    return(0);
  };
  
};

/*
 *  Num shares finds the maximum number of shares you can 
 *  afford within the given range.
 *
 */
 
int num_shares(p,hot,max)
    int p,hot,max;
{        
   int num;
   /* How many can we afford to buy? */

   num = players[p].cash / share_cost(hot);
   if (num > 3) num = 3;
   if (num > hotels[hot].shares)
     num = hotels[hot].shares;

   printw("%s purchased %d shares of Hotel %c.\n",players[p].name,
	 num,('A' + hot - 1));
   return(num);
};