|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T c
Length: 14330 (0x37fa) Types: TextFile Names: »comp.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/General/Hotel/comp.c«
/* * 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); };