home *** CD-ROM | disk | FTP | other *** search
/ Kinjite Games 1996 November / SENTINEL.img / dosgames / sports / apool098 / src / apool.c next >
C/C++ Source or Header  |  1995-05-26  |  11KB  |  341 lines

  1. /* This is "apool.c", main-fragment of the pool (billiards)-program
  2.                    
  3.                      "ANOTHER POOL".
  4.  
  5.    Copyright (C) 1995 by Gerrit Jahn (email: ub1g@rz.uni-karlsruhe.de)
  6.  
  7.    "ANOTHER POOL" is free software; you can redistribute it 
  8.    and/or modify it under the terms of the GNU General Public License 
  9.    as published by the Free Software Foundation; either version 2 of 
  10.    the License, or (at your option) any later version.
  11.  
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with GNU CC; see the file COPYING.  If not, write to
  19.    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. /* ------------------------------ apool.c -------------------------------- */
  22.  
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <time.h>
  26. #include <math.h>
  27. #include <random.h>
  28. #include "apool.h"
  29. #include <pc.h>
  30.  
  31. double ALPHA, BETA, GAMMA, DELTA, ETA, BANDES, BANDEREF,
  32.  SPINC, MASS_WHITE; /* eigentlich Konstanten, werden es später wieder !!! */
  33. double CURVES, CURVEP;
  34. int TIME_STEP;
  35. int first_hit, bande_hit, col_in, last_foul, freeball, extra_shot,ende,
  36.  STEP, CLEV, act=1, new_col, c_player=-1, anstoss, demo = 0,
  37.  undo_freeball, undo_extra_shot, undo_act, undo_color, last_anstoss=0,
  38.  last_pocketed_balls;
  39. double undo_spd, undo_wink, undo_ez;
  40. struct vect undo_e;
  41.  
  42. struct ball k[BALLS];
  43. struct player ply[2];
  44. FILE *datei;
  45. struct vect old_pos[BALLS]; int old_stat[BALLS]; /* f. undo().. */
  46. struct statistic stats[2] = {{{0,0,0,0},0,0,0,0},{{0,0,0,0},0,0,0,-1}};
  47.  
  48. void init_table( void ) 
  49. /* Hier wird alles, was es so an Variablen bezüglich Lage der Kugeln gibt, 
  50.    neu initialisiert. init_table() wird immer beim Neustart aufgerufen */
  51.  { 
  52.   int i, j, l=0;
  53.   for(i=0;i<5;i++) 
  54.    for(j=-i;j<=i;j+=2)        /* Lage der Kugeln am Anfang */
  55.     { 
  56.      k[l].p.x = 0.75+((i/*-2*/)*XAB/DIFFX) + 0.25 * RND / DIFFX;
  57.      k[l].p.y = 0.25+j/2.0*((2*RADIUS+2))/DIFFX + 0.25 * RND / DIFFX;
  58.      k[l].v.x = k[l].v.y = k[l].e.x = k[l].e.y = k[l].ez = k[l].col = 0.0; 
  59.      k[l].stat = 0; k[l++].m = 1.0;
  60.     }
  61.   k[4].col = COL_BLACK; l = 0;
  62.   do            /* Farbe der Kugeln, zufallsgesteuert */
  63.    { 
  64.     while( (i = 15.0*rand()/(RAND_MAX+1) ) == BLACK );
  65.     if( !k[i].col ) { k[i].col = COL_RED; l++; }
  66.    }
  67.   while( l < (BALLS-2)/2 );
  68.   for( i=0;i<WHITE;i++ ) if( !k[i].col ) k[i].col = COL_YELLOW;
  69.   k[WHITE].stat = 1; /* Weiße ist anfangs NICHT auf dem Tisch */
  70.   k[WHITE].m = MASS_WHITE;
  71.   k[WHITE].col = COL_WHITE;
  72.   for( i=0;i<2;i++)
  73.    { ply[i].stat = ply[i].wait = ply[i].col = ply[i].hole_black = 0; }
  74.   first_hit = bande_hit = anstoss = 1;
  75.   plot_table();     /* oben: damit nicht VOR dem Anfang bereits gefoult wurde */
  76.   ply[0].speed = ply[1].speed = spd = 0.75; speed( spd );
  77.   wink( alph );
  78.   for( i=0;i<WHITE;i++) plot_one_ball( i );
  79.   freeball = extra_shot = last_foul = col_in = 0;
  80.   if( demo ) msg("press any key to stop demo");
  81.  }
  82.  
  83. void save_actual_position( void )
  84.  { /* sichert die aktuelle Position der Kugeln, für undo() */
  85.   int i;
  86.   for( i=0;i<BALLS;i++ ) { old_pos[i].x = k[i].p.x; old_pos[i].y = k[i].p.y; 
  87.    old_stat[i] = k[i].stat; }
  88.   undo_act = act;
  89.   undo_freeball = freeball;
  90.   undo_extra_shot = extra_shot;
  91.   undo_color = ply[act].col;
  92.   undo_spd = spd;
  93.   undo_wink = alph;
  94.   undo_e.x = k[WHITE].e.x;
  95.   undo_e.y = k[WHITE].e.y;
  96.   undo_ez = k[WHITE].ez;
  97.  }
  98.  
  99. void undo( void )
  100.  { /* naja, was wohl */
  101.   int i;
  102.   mouse_off();
  103.   for( i=0;i<BALLS;i++ )
  104.    {
  105.     if( !k[i].stat ) plot_one_ball( i );
  106.     k[i].p.x = old_pos[i].x; 
  107.     k[i].p.y = old_pos[i].y; 
  108.     k[i].stat = old_stat[i]; 
  109.     if( !k[i].stat ) plot_one_ball( i );
  110.    }
  111.   act = undo_act;
  112.   freeball = undo_freeball;
  113.   extra_shot = undo_extra_shot;
  114.   ply[act].col = undo_color;
  115.   plot_act_player( act );
  116.   if( ply[act].col == COL_RED ) i = 4;
  117.   else if( ply[act].col == COL_YELLOW ) i = 11;
  118.   else i = 6;
  119.   if( freeball ) err2("free-ball", i);
  120.   else if( extra_shot) err2("extra_shot", i);
  121.   else err2(" ", 0);
  122.   speed( spd = undo_spd );
  123.   wink( alph = undo_wink );
  124.   set_spin( undo_e.x, undo_e.y, undo_ez );
  125.   mouse_on();
  126.  }
  127.  
  128. void test_for_play_on_black( void )
  129. /* Wenn alle Kugeln einer Farbe verschwinden sind, wird auf die Schwarze
  130.    gespielt. Wann das der Fall ist, und wer Schwarz spielen muß, ermittelt
  131.    dies Prozedur */
  132.  {
  133.   int i, j;
  134.   for( j=0;j<2;j++ )
  135.    if( (ply[j].col != COL_BLACK) && (ply[j].col) ) 
  136.     {
  137.      ply[j].hole_black = 0;
  138.      for(i=0;i<WHITE;i++)
  139.       if( k[i].stat && (k[i].col == ply[j].col) ) ply[j].hole_black++;
  140.      if( ply[j].hole_black == (BALLS-2)/2 ) 
  141.       {
  142.        ply[j].col = COL_BLACK;
  143.         /* ply[j].hole_black = last_hole gegenüber; */ /* SPÄTER !!! */
  144.       }
  145.     }
  146.  } 
  147.  
  148. char *str_player( char *out2, int act )
  149.  { 
  150.   sprintf(out2, "Player %d%s", act+1, (c_player==act) ? " (Computer)" : "");
  151.   return out2;
  152.  }
  153.  
  154. int test_if_game_is_over( void ) 
  155.  { /* Wie der Name schon sagt, testet, ob Spiel zu Ende */
  156.  char out[80], out2[30];
  157.  int loser;
  158.  if( k[BLACK].stat )
  159.   {
  160.    if( !(ply[act].stat & FOUL_ANY_FOUL) ) 
  161.     {        /* Schwarze wurde KORREKT eingelocht */
  162.      loser = 1 - act;
  163.      sprintf(out,"%s wins!", str_player( out2, act) );
  164.      ply[act].points += 1;
  165.      stats[act].wins += 1;
  166.      stats[act].pots += 1;
  167.     }
  168.    else
  169.     { 
  170.      loser = act;
  171.      sprintf(out,"black ball illegaly pocketed; %s loses!",
  172.       str_player( out2, act ) );
  173.      ply[act].points += 10000;
  174.      stats[act].losses += 1;
  175.      act = 1 - act;
  176.     }
  177.    err(out);
  178.    if( loser != last_anstoss ) last_anstoss = loser;
  179.    if( demo || c_player == loser ) { msg("wait..."); wait_user_time( 5.0 ); }
  180.    else wait_for_click();
  181.    init_table();
  182.    return 1;
  183.   }
  184.  return 0;
  185. }
  186.  
  187. void rules( void )
  188. /* Die Regeln, nach einem Stoß wird überprüft, ob keine Fouls aufgetreten
  189.    sind. Sollte dies so sein, so erfolgen die "Strafen". Ruft die obigen
  190.    Test-Prozeduren, das Menu und den Stoß auf ... */
  191.  {
  192.  int spielende=0, color; 
  193.  mouse_off();
  194.  init_table();
  195.  ply[0].points = ply[0].points = 0;
  196.  do
  197.   {
  198.    first_hit = bande_hit =  0;
  199.    if( ply[act].stat & FOUL_WHITE_POCKETED ) /* hier kommen die Fouls... */
  200.     {
  201.      err("white ball pocketed, foul!");
  202.      last_foul = 1;
  203.      stats[act].fouls.whited += 1;
  204.     }
  205.    else if( ply[act].stat & FOUL_NO_TOUCH )
  206.     {
  207.      err("no ball or no side touched, foul!");
  208.      last_foul = 1;
  209.      stats[act].fouls.notouch += 1;
  210.     }
  211.    else if( ply[act].stat & FOUL_WRONG_COLOR_POCKETED)
  212.     {
  213.      if( !freeball )
  214.       {
  215.        err("wrong color pocketed, foul!");
  216.        last_foul = 1;
  217.        stats[act].fouls.wrongcp += 1;
  218.       }
  219.      else { ply[1-act].wait = 1; }
  220.     }
  221.    else if( ply[act].stat & FOUL_WRONG_COLOR_TOUCHED )
  222.     {
  223.      if( !freeball )
  224.       {
  225.        err("wrong color touched first, foul!");
  226.        last_foul = 1;
  227.        stats[act].fouls.wrongct += 1;
  228.       }
  229.      else { extra_shot = 1; }
  230.     }
  231.    else if( !(ply[act].stat & FOUL_ANY_FOUL) ) /* kein Foul gemacht */
  232.     {
  233.     if( ply[act].stat & FOUL_CORRECT_POT )
  234.      {
  235.       last_foul = 0;
  236.       stats[act].pots += last_pocketed_balls;
  237.       err("OK!"); /* Kugel eingelocht */
  238.      }
  239.     else /* keine Kugel eingelocht */
  240.      {
  241.       stats[act].nopots += 1;
  242.       if( ply[1-act].wait == 1 ) { extra_shot = 1; ply[1-act].wait = 0; }
  243.       else act = 1 - act;
  244.      }
  245.     }
  246.    if( col_in && last_foul ) { ply[act].col = ply[1-act].col = 0; }
  247.    if( last_foul ) 
  248.     { 
  249.      ply[act].wait = 1; act = 1 - act;
  250.      if( ply[act].col == COL_RED ) color = 4;
  251.      else if( ply[act].col == COL_YELLOW ) color = 11;
  252.      else color = 6;
  253.      err2("free-ball", color ); 
  254.      freeball = 1; 
  255.     }
  256.    else if( extra_shot )
  257.     {
  258.      ply[act].wait = 0;
  259.      freeball = 0;
  260.      if( ply[act].col == COL_RED ) color = 4;
  261.      else if( ply[act].col == COL_YELLOW ) color = 11;
  262.      else color = 6;
  263.      err2("extra-shot", color);
  264.     }
  265.    else freeball = 0;
  266.    if( !freeball && !extra_shot) err2(" ", 0);
  267.    new_col = col_in = last_foul = extra_shot = last_pocketed_balls = 0;
  268.    ply[0].stat = ply[1].stat = 0;  /* eigentlich nur ply[act].stat */
  269.    if( demo ) c_player = act; 
  270.    if( c_player != act ) speed( spd = ply[act].speed );
  271.    if( !( spielende = menu() ) ) stoss(); /*HIER ROLLEN ERST D. KUGELN*/
  272.    if( !test_if_game_is_over() ) test_for_play_on_black();   
  273.    if( new_col & NEW_COL_NEW )
  274.     {
  275.     if( (new_col & NEW_COL_DOUBLE) /*&& (ply[act].stat & FOUL_CORRECT_POT)*/ )
  276.      ply[0].col = ply[1].col = 0;
  277.     }
  278.    if( (!first_hit) || (!bande_hit) ) ply[act].stat |= FOUL_NO_TOUCH;
  279.   }
  280.  while( !spielende );
  281.  }
  282.  
  283. void stop_it( void )
  284.  { /* beendet Programm und gibt Statistiken und Stand aus */
  285.  int i;
  286.  close_graphics();
  287.  if( datei ) fclose(datei);
  288.  MSG;
  289.  for( i=0;i<2;i++ )
  290.   printf("\n    Player %d has won %d and lost %d game%s",i+1, 
  291.    (int)(ply[i].points)%10000, (int)(ply[i].points)/10000,
  292.    ( ((int)(ply[i].points)/10000) !=1 ) ? "s" : "");
  293.  printf("\n\n");
  294.  exit( 0 );
  295.  }
  296.  
  297. void main( int argc, char *argv[])
  298.  {
  299.  time_t sys_time;
  300.  if( !(datei = fopen("konst.dat","r") ) ) 
  301.   { /* Datei für die (phys.) Konstanten */
  302.   printf("can't open file 'konst.dat'\n");
  303.   exit( 0 ); 
  304.   }
  305.  fscanf(datei,"%lg%*[^\n]%lg%*[^\n]%lg%*[^\n]%lg%*[^\n]%lg%*[^\n]",
  306.   &ALPHA, &BETA, &GAMMA, &DELTA, &ETA);
  307.  fscanf(datei,"%lg%*[^\n]%lg%*[^\n]%lg%*[^\n]",
  308.   &BANDES, &BANDEREF, &MASS_WHITE);
  309.  fscanf(datei,"%d%*[^\n]%d%*[^\n]", &STEP, &CLEV);
  310.  fscanf(datei,"%*[^\n]%lg%*[^\n]%lg%*[^\n]%d",&CURVES, &CURVEP, &TIME_STEP);
  311.  if( CLEV > 15 ) CLEV = 15; /* Computer-Level max 15 */
  312.  fclose(datei);
  313.  /*if(argc>=4) init_graphics( atoi(argv[1]), atoi(argv[2]), atoi(argv[3]) );*/
  314.  if( argc >= 3 && !strcmp( argv[1], "-init") )
  315.   {
  316.   create_table( atoi( argv[2] ) );
  317.   MSG; printf("file 'table.dat' created.\n\n");
  318.   init_graphics( 640, 480, 256 );
  319.   }
  320.  else if( argc >= 2 ) init_graphics( 640, 480, 16 );
  321.  else init_graphics( 640, 480, 256 );
  322.  datei = NULL;
  323. /* datei = fopen("xxx.xxx","w"); */
  324.  init_timer();
  325.  sys_time = time( NULL );
  326.  srand( sys_time % RAND_MAX );
  327.  rules(); /* Start des Spiels */
  328.  stop_it();
  329. }
  330.  
  331. void calc_e_winkel( void )
  332.  /* Als nächstes wird der "Einschußwinkel" der Mittellöcher berechnet, also
  333.     der Winkel, "oberhalb dem cos( diese Winkels )" die Kugeln noch ins 
  334.     Mittelloch versenkt werden können*/
  335.  {
  336.  double dummy;
  337.  dummy = (300 - ban[8].p0.x) - 0;
  338.  e_winkel = 90-180.0 / M_PI * 
  339.   atan( ((ban[8].p0.y+RADIUS+2) - posl[2].m.y*DIFFX) / dummy );
  340.  }
  341.