home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
games
/
volume7
/
hotel
/
part01
/
comp.c
next >
Wrap
C/C++ Source or Header
|
1989-07-13
|
14KB
|
603 lines
/*
* 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);
};