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

  1. /*
  2.  * This program (called "Hotel") is copyright 1989 to Scott R. Turner,
  3.  * in both source code and executable form.  Permission is given to 
  4.  * copy both the source code and the executable under the following
  5.  * conditions:
  6.  * 
  7.  * COPYING POLICIES
  8.  * 
  9.  *   1. You may copy and distribute verbatim copies of Hotel code as you
  10.  * receive it, in any medium, provided that you conspicuously and
  11.  * appropriately publish on each file a valid copyright notice such as
  12.  * "Copyright (C) 1989 Scott R. Turner", and keep intact the copyright
  13.  * and license notices on all files.  You may charge a distribution fee for the
  14.  * physical act of transferring a copy, but that fee may not exceed
  15.  * your actual costs in creating and delivering the copy.
  16.  * 
  17.  *   2. You may modify your copy or copies of Hotel or any portion of it,
  18.  * and copy and distribute such modifications under the terms of
  19.  * Paragraph 1 above, provided that you also do the following:
  20.  * 
  21.  *     a) cause the modified files to carry prominent notices stating
  22.  *     who last changed such files and the date of any change; and
  23.  * 
  24.  *     b) cause the whole of any work that you distribute or publish,
  25.  *     that in whole or in part contains or is a derivative of Hotel
  26.  *     or any part thereof, to be licensed at no charge to all third
  27.  *     parties on terms identical to those contained in this License
  28.  *     Agreement (except that you may choose to grant more extensive
  29.  *     warranty protection to third parties, at your option).
  30.  *
  31.  *   3. You may not copy, sublicense, distribute or transfer Hotel
  32.  * except as expressly provided under this License Agreement.  Any attempt
  33.  * otherwise to copy, sublicense, distribute or transfer Hotel is void and
  34.  * your rights to use Hotel under this License agreement shall be
  35.  * automatically terminated.  However, parties who have received computer
  36.  * software programs from you with this License Agreement will not have
  37.  * their licenses terminated so long as such parties remain in full compliance.
  38.  * 
  39.  *   4.  Under no circumstances may you charge for copies of Hotel, for copies
  40.  * of any program containing code from Hotel in whole or in part, or for 
  41.  * any software package or collection of programs or code that contains Hotel
  42.  * in whole or part.
  43.  *
  44.  */ 
  45. /*
  46.  *  comp.c
  47.  *  Scott R. Turner
  48.  *  Wed Nov  2 11:05:22 1988 -- Scott R. Turner
  49.  *
  50.  *  This file contains the routines that implement the computer
  51.  *  player.
  52.  *
  53.  */
  54. #include "defs.h"
  55. extern int legal_play();
  56. extern void print_board();
  57. extern void update_cash();
  58. extern int maj_bonus();
  59. extern int mergecheck();
  60. extern int adjacent();
  61.  
  62. /*
  63.  *  Comp_play selects a tile to play.
  64.  *
  65.  *  (1) If you can sink a hotel that you have a majority
  66.  *      interest in, do so.
  67.  *  (1a) If you can sink a hotel that you do not have a 
  68.  *    majority interest in to a hotel you do have a 
  69.  *    majority interest in, do so.
  70.  *  (2) If you can create a hotel, do so.
  71.  *  (3) If you can extend the size of a hotel you
  72.  *      have a majority interest in, do so.
  73.  *  (4) If you can make an isolated play, do so.
  74.  *  (5) Play randomly.
  75.  * 
  76.  *
  77.  */
  78.  
  79. void  comp_play(n,px,py)
  80.      int n;
  81.      int *px,*py;
  82. {
  83.   int i,j,k,legl,plays[20][2],numplays;
  84.   int possibles[MAXHOTELS],mhotel,mvalue,mx,my,p;
  85.   int hotel1a,x1a,y1a;
  86.   
  87.  
  88.   /*  The computer may not have a legal play.  */
  89.  
  90.   legl = 0;
  91.     for(i=1;i<=boardsize;i++)
  92.       for(j=1;j<=boardsize;j++) 
  93.     if(board[i][j] == -n && legal_play(i,j)) {
  94.       legl=1;
  95.       goto done;
  96.     }
  97.  done:
  98.  
  99.   if (!legl) {
  100.     printw("%s has no legal moves.\n",players[n].name);
  101.     refresh();
  102.     *px = -1;
  103.     *py = -1;
  104.     return;
  105.   };
  106.  
  107.   /*
  108.    *  Decide the computer's play.
  109.    *
  110.    */
  111.  
  112.   /*  (1) Look for hotels to sink
  113.    *
  114.    *    (a) find all the possibles merges for each play.
  115.    *    (b) pick out the biggest merge that you have a share in.
  116.    *
  117.    */
  118.  
  119.   mx = 0;
  120.   my = 0;
  121.   mhotel = 0;
  122.   mvalue = 0;
  123.   hotel1a = 0;
  124.   for(i=1;i<=boardsize;i++)
  125.     for(j=1;j<=boardsize;j++) 
  126.       if(board[i][j] == -n && legal_play(i,j) && mergecheck(i,j,possibles))
  127.     for (p = 1;p<=numhotels;p++) {
  128.       /*  This is looking for (1) */
  129.       if (possibles[p] && (maj_bonus(n,p) > mvalue)) {
  130.         mvalue = maj_bonus(n,p);
  131.         mhotel = p;
  132.         mx = i;
  133.         my = j;
  134.       };
  135.       /*  This is looking for (1a) */
  136.       if (possibles[p] && stock_differential(n,p) > 3 && 
  137.           maj_in_merge(p,i,j)) {
  138.             hotel1a = p;
  139.             x1a = i;
  140.             y1a = j;
  141.         };
  142.      };
  143.  
  144.   if (mhotel) {
  145.     /*  We are going to play mx,my to sink hotel #p. */
  146.     if (debug) printw("%s plays %d,%d sinking %c.\n",players[n].name,mx,my,('A'+mhotel-1));
  147.     *px = mx;
  148.     *py = my;
  149.     return;
  150.   };
  151.  
  152.   if (hotel1a) {
  153.     /*  We are going to play mx,my to sink hotel #p. */
  154.     if (debug) printw("%s plays %d,%d sinking %c.\n",players[n].name,mx,my,('A'+hotel1a-1));
  155.     *px = x1a;
  156.     *py = y1a;
  157.     return;
  158.   };
  159.   
  160.   /*
  161.    *  (2) Create a new hotel if possible.
  162.    *
  163.    */
  164.  
  165.   numplays = 0;
  166.   for(i=1;i<=boardsize;i++)
  167.     for(j=1;j<=boardsize;j++) 
  168.       if(board[i][j] == -n && legal_play(i,j) && new_hotel(i,j)) {
  169.     numplays++;
  170.     plays[numplays][0] = i;
  171.     plays[numplays][1] = j;
  172.       };
  173.  
  174.   if (numplays) {
  175.     k = randum(1,numplays);
  176.     *px = plays[k][0];
  177.     *py = plays[k][1];
  178.     if (debug) printw("%s plays %d,%d to create a new hotel.\n",players[n].name,*px,*py); 
  179.     return;
  180.   };
  181.  
  182.   /*
  183.    *  (3) Extend hotels that I own stock in.
  184.    *
  185.    */
  186.  
  187.   mhotel = 0;
  188.   mvalue = 0;
  189.   for(i=1;i<=boardsize;i++)
  190.     for(j=1;j<=boardsize;j++) 
  191.       if(board[i][j] == -n && legal_play(i,j) && !mergecheck(i,j,possibles)
  192.      && adjacent(i,j,&k) && players[n].shares[k] > mvalue) {
  193.     mhotel = k;
  194.     mvalue = players[n].shares[k];
  195.       };
  196.   numplays = 0;
  197.   for(i=1;i<=boardsize;i++)
  198.     for(j=1;j<=boardsize;j++) 
  199.       if(board[i][j] == -n && legal_play(i,j) && !mergecheck(i,j,possibles)
  200.      && adjacent(i,j,&k) && k == mhotel) {
  201.     numplays++;
  202.     plays[numplays][0] = i;
  203.     plays[numplays][1] = j;
  204.       };
  205.   
  206.   if (numplays) {
  207.     k = randum(1,numplays);
  208.     *px = plays[k][0];
  209.     *py = plays[k][1];
  210.     if (debug) printw("%s plays %d,%d to extend a hotel.\n",players[n].name,*px,*py);
  211.     return;
  212.   };
  213.  
  214.   /*
  215.    *  (4) Make an isolated play.
  216.    *
  217.    */
  218.  
  219.   numplays = 0;
  220.   for(i=1;i<=boardsize;i++)
  221.     for(j=1;j<=boardsize;j++)
  222.       if(board[i][j] == -n && legal_play(i,j) && !mergecheck(i,j,possibles)
  223.      && !adjacent(i,j,&k)) {
  224.     numplays++;
  225.     plays[numplays][0] = i;
  226.     plays[numplays][1] = j;
  227.       };
  228.  
  229.   if (numplays) {
  230.     k = randum(1,numplays);
  231.     *px = plays[k][0];
  232.     *py = plays[k][1];
  233.     if (debug) printw("%s plays %d,%d (isolated).\n",players[n].name,*px,*py);
  234.     return;
  235.   };
  236.  
  237.   /*
  238.    *  (5) Play randomly.
  239.    *
  240.    */
  241.  
  242.   numplays = 0;
  243.   for(i=1;i<=boardsize;i++)
  244.     for(j=1;j<=boardsize;j++)
  245.       if(board[i][j] == -n && legal_play(i,j)){
  246.     numplays++;
  247.     plays[numplays][0] = i;
  248.     plays[numplays][1] = j;
  249.       };
  250.  
  251.   if (numplays) {
  252.     k = randum(1,numplays);
  253.     *px = plays[k][0];
  254.     *py = plays[k][1];
  255.     if (debug) printw("%s plays %d,%d (randomly).\n",players[n].name,*px,*py);
  256.     return;
  257.   };
  258.  
  259.   /*  Otherwise, give up. */
  260.   if (debug) printw("%s couldn't find a play.\n",players[n].name);
  261.   return;
  262.  
  263. };
  264.  
  265. /*
  266.  *  Buying Strategies (General Notes)
  267.  *
  268.  *  (1) Theoretically, you could keep track in your head of all the
  269.  *      stocks sold (and the stocks available), so comp_buy is free
  270.  *      to rummage through other player's stock holdings.
  271.  *
  272.  */
  273.  
  274. /*
  275.  *  Get Majorities
  276.  *
  277.  *  The "Get Majorities" strategy attempts to gain and maintain
  278.  *  majorities in as many hotels as possible.
  279.  *
  280.  */
  281.  
  282.  get_maj_strategy(p,purchases)
  283.      int p, purchases[MAXHOTELS];
  284. {
  285.   extern int share_cost();
  286.   int i,j,ok[MAXHOTELS],max[MAXHOTELS],spread[MAXHOTELS],numok,pick;
  287.   int order[MAXHOTELS],numorder,numbought,tmp;
  288.  
  289.   /* Which hotels should be considered? */
  290.  
  291.   numok = 0;
  292.   for(i=1;i<=numhotels;i++) {
  293.     purchases[i] = 0;
  294.     max[i] = 0;
  295.     spread[i] = 0;
  296.     if (hotels[i].shares > 0 && hotels[i].size > 0 &&
  297.     players[p].cash > share_cost(i)) {
  298.       ok[i] = 1;
  299.       numok++;
  300.     } else {
  301.       ok[i] = 0;
  302.     };
  303.   };
  304.  
  305.   if(!numok) return;
  306.   
  307.   /* What's my share situation in each re other players? */
  308.  
  309.   for(i=1;i<=numhotels;i++)
  310.     if (ok[i])
  311.       for(j=1;j<=numplayers;j++) {
  312.         if (j != p && players[j].shares[i]) spread[i]++;
  313.     if (j != p && players[j].shares[i] > max[i])
  314.       max[i] = players[j].shares[i];
  315.     };
  316.     
  317.   /*
  318.    *  We can ignore hotels that we already have a 4 advantage
  319.    *  in.
  320.    *
  321.    */
  322.    
  323.   for(i=1;i<=numhotels;i++)
  324.     if (ok[i] && (players[p].shares[i] - max[i]) > 3) ok[i] = 0;
  325.       
  326.   /*
  327.    * Rank the ok hotels according to the following cost
  328.    * equation:
  329.    * 
  330.    *  cost(i) = share_cost(i) * (needed_for_max + num_competing*3)
  331.    *
  332.    *  We do this with a rather inefficient bubble sort, but
  333.    *  computing cost isn't really an issue.
  334.    *
  335.    */
  336.   
  337.   numorder = 0;
  338.   for(i=1;i<=numhotels;i++) 
  339.     if (ok[i]) {
  340.         numorder++;
  341.         order[numorder] = i;
  342.     };
  343.    
  344.   for(i=1;i<=numorder;i++)
  345.     for(j=1;j<=(numorder-1);j++)
  346.       if ((share_cost(order[j]) *
  347.              ((4-(players[p].shares[order[j]] - max[order[j]])) +
  348.               (spread[order[j]]*3))) >
  349.           (share_cost(order[j+1]) *
  350.              ((4-(players[p].shares[order[j+1]] - max[order[j+1]])) +
  351.               (spread[order[j+1]]*3)))) {
  352.       tmp = order[j];
  353.       order[j] = order[j+1];
  354.       order[j+1] = tmp;
  355.     };
  356.               
  357. /*   printw("Stock order is: ");
  358.    for(i=1;i<=numorder;i++) printw("%d ",order[i]);
  359.    printw("\n");
  360.    print_board(1);
  361.    refresh();
  362.    any_key();
  363. */    
  364.   /*
  365.    *  If we've just gotten the free share in something, buy 
  366.    *  some more.
  367.    *
  368.    */
  369.   
  370.   for(i=1;i<=numhotels;i++)
  371.     if(ok[i] && players[p].shares[i] == 1 && max[i] == 0) {
  372.         pick = i;
  373.     purchases[pick] = num_shares(p,i,3);
  374.     return;
  375.     };
  376.     
  377.    /*
  378.     *  Otherwise, buy off the top.
  379.     *
  380.     */
  381.    
  382.    if (numorder) {
  383.      purchases[order[1]] = num_shares(p,order[1],3);
  384.    };
  385.    return;     
  386.  
  387. };
  388.  
  389. /*
  390.  *  comp_liquidate is called when a hotel chain is sunk and a player might
  391.  *  have stock to get rid of.
  392.  *
  393.  */
  394.  
  395. void  comp_liquidate(p,maxhot,sunk,sell,trade)
  396.      int p, *sell, *trade, maxhot,sunk;
  397. {
  398.   int i,j,maxtrade,num,mshares;
  399.   float coverage;
  400.  
  401.   num = 0;
  402.   for(i=1;i<=boardsize;i++)
  403.     for(j=1;j<=boardsize;j++)
  404.       if (board[i][j] > 0) num++;
  405.   coverage = (num + 0.0) / (boardsize * boardsize);
  406.  
  407.   /* If game is young, hold all stock. */
  408.   
  409.   if (coverage < .40) {
  410.     *sell = 0;
  411.     *trade = 0;
  412.     return;
  413.   };
  414.  
  415.   /* Figure the maximum you can trade. */
  416.  
  417.   if ((int) players[p].shares[sunk]/2 > hotels[sunk].shares)
  418.     maxtrade = hotels[sunk].shares * 2;
  419.   else
  420.     maxtrade = players[p].shares[sunk];
  421.   
  422.   /* If game is old, trade all possible. */
  423.  
  424.   if (coverage > .60) {
  425.     *trade = maxtrade;
  426.     *sell = (players[p].shares[sunk] - maxtrade);
  427.     return;
  428.   };
  429.  
  430.   /* Trade if the trade makes financial sense or
  431.    * if it will pull you within 3 of the maximum stockholder
  432.    * in maxhot.
  433.    */
  434.  
  435.   if (share_cost(sunk)*2 <= share_cost(maxhot)) {
  436.     *trade = maxtrade;
  437.     *sell = (players[p].shares[sunk] - maxtrade);
  438.     return;
  439.   };
  440.  
  441.   mshares = 0;
  442.   for(i=1;i<=numplayers;i++)
  443.     if (i != p && players[i].shares[maxhot] > mshares)
  444.       mshares = players[i].shares[maxhot];
  445.       
  446.   if (players[p].shares[maxhot] + (maxtrade / 2) + 3 >= mshares) {
  447.     *trade = maxtrade;
  448.     *sell = (players[p].shares[sunk] - maxtrade);
  449.     return;
  450.   };
  451.  
  452.   /*
  453.    *  Otherwise, trade a random number.
  454.    *
  455.    */
  456.  
  457.   *trade = randum(maxtrade);
  458.   *sell = randum(players[p].shares[sunk] - *trade);
  459.   return;
  460.   
  461. };
  462.  
  463. int  comp_new(n,x,y)
  464.      int n,x,y;
  465. {
  466.   int i,max,hot;
  467.  
  468.   /*
  469.    *  Picks the hotel it holds the most stock in.
  470.    */
  471.  
  472.   max = -1;
  473.   for(i=1;i<=numhotels;i++) {
  474.     if (hotels[i].size == 0 && players[n].shares[i] == max && randum(10) > 5) {
  475.         max = players[n].shares[i];
  476.     hot = i;
  477.     };
  478.     if (hotels[i].size == 0 && players[n].shares[i] > max) {
  479.         max = players[n].shares[i];
  480.     hot = i;
  481.     };
  482.   };
  483.       
  484.   printw("%s creates hotel %c.\n",players[n].name,'A' + hot - 1);
  485.   return(hot);
  486.  
  487. };
  488.  
  489. /*
  490.  *  comp_save is a routine for asking the player which of N
  491.  *  equal size hotels they'd like to save.
  492.  *
  493.  *  Save the hotel you have the most stock in.
  494.  *
  495.  */
  496.  
  497. int  comp_save(p,max,adj)
  498.      int p,max,adj[MAXHOTELS+1];
  499. {
  500.   int num,i,choice,top;
  501.  
  502.   top = -1;
  503.   choice = 0;
  504.   for(i=1;i<=numhotels;i++)
  505.     if (adj[i] == max && players[p].shares[i] > top) {
  506.         top = players[p].shares[i];
  507.         choice = i;
  508.     };
  509.  
  510.   return(choice);
  511. };
  512.  
  513.  /*
  514.   *  This function returns the stock differential between
  515.   *  "player" and the top holder in the hotel.
  516.   *
  517.   */
  518.  
  519. int stock_differential(p,h)
  520.     int p,h;
  521. {
  522.   int i,diff;
  523.   
  524.   diff = 0;
  525.   for(i=1;i<=numplayers;i++)
  526.     if (i != p &&
  527.       (players[i].shares[h]-players[p].shares[h]) > diff)
  528.         diff = (players[i].shares[h]-players[p].shares[h]);
  529.   return(diff);
  530.   
  531. };
  532.     
  533. /*
  534.  *  Maj_in_merge returns true if playing x,y would merge h
  535.  *  into another h that the player has a majority interest
  536.  *  in.  (Whew!)
  537.  *
  538.  */
  539.  
  540. int maj_in_merge(p,x,y)
  541.     int p,x,y;
  542. {
  543.     
  544.   int i,lsize,mergeh;
  545.   int j,k,max1,max2,first,second;
  546.  
  547.   lsize = 0;
  548.   mergeh = 0;
  549.   for(i= -1;i<2;i++)
  550.     for(j= -1;j<2;j++)
  551.       if ( i*j == 0 && (i != 0 || j != 0) &&
  552.       ((x+i) > 0) && ((y+j) > 0) &&
  553.       ((x+i) <= boardsize) && ((y+j) <= boardsize) &&
  554.       (board[x+i][y+j] != UNUSED) &&
  555.       (board[x+i][y+j] > 0)) {
  556.     if (hotels[board[x+i][y+j]].size > lsize) {
  557.             mergeh = board[x+i][y+j];
  558.         };
  559.     };
  560.  
  561.   max1 = 0;
  562.   max2 = 0;
  563.   for(j=1;j<=numplayers;j++) {
  564.     if (players[j].shares[mergeh] > max1) {
  565.       max2 = max1;
  566.       max1 = players[j].shares[mergeh];
  567.     } else if (players[j].shares[mergeh] > max2) {
  568.       max2 = players[j].shares[mergeh];
  569.     };
  570.   };
  571.  
  572.   if (players[p].shares[mergeh] > max2) {
  573.     return(1);
  574.   } else {
  575.     return(0);
  576.   };
  577.   
  578. };
  579.  
  580. /*
  581.  *  Num shares finds the maximum number of shares you can 
  582.  *  afford within the given range.
  583.  *
  584.  */
  585.  
  586. int num_shares(p,hot,max)
  587.     int p,hot,max;
  588. {        
  589.    int num;
  590.    /* How many can we afford to buy? */
  591.  
  592.    num = players[p].cash / share_cost(hot);
  593.    if (num > 3) num = 3;
  594.    if (num > hotels[hot].shares)
  595.      num = hotels[hot].shares;
  596.  
  597.    printw("%s purchased %d shares of Hotel %c.\n",players[p].name,
  598.      num,('A' + hot - 1));
  599.    return(num);
  600. };
  601.     
  602.         
  603.