home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Kinjite Games 1996 November
/
SENTINEL.img
/
dosgames
/
sports
/
apool098
/
src
/
apool.c
next >
Wrap
C/C++ Source or Header
|
1995-05-26
|
11KB
|
341 lines
/* This is "apool.c", main-fragment of the pool (billiards)-program
"ANOTHER POOL".
Copyright (C) 1995 by Gerrit Jahn (email: ub1g@rz.uni-karlsruhe.de)
"ANOTHER POOL" is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------ apool.c -------------------------------- */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <random.h>
#include "apool.h"
#include <pc.h>
double ALPHA, BETA, GAMMA, DELTA, ETA, BANDES, BANDEREF,
SPINC, MASS_WHITE; /* eigentlich Konstanten, werden es später wieder !!! */
double CURVES, CURVEP;
int TIME_STEP;
int first_hit, bande_hit, col_in, last_foul, freeball, extra_shot,ende,
STEP, CLEV, act=1, new_col, c_player=-1, anstoss, demo = 0,
undo_freeball, undo_extra_shot, undo_act, undo_color, last_anstoss=0,
last_pocketed_balls;
double undo_spd, undo_wink, undo_ez;
struct vect undo_e;
struct ball k[BALLS];
struct player ply[2];
FILE *datei;
struct vect old_pos[BALLS]; int old_stat[BALLS]; /* f. undo().. */
struct statistic stats[2] = {{{0,0,0,0},0,0,0,0},{{0,0,0,0},0,0,0,-1}};
void init_table( void )
/* Hier wird alles, was es so an Variablen bezüglich Lage der Kugeln gibt,
neu initialisiert. init_table() wird immer beim Neustart aufgerufen */
{
int i, j, l=0;
for(i=0;i<5;i++)
for(j=-i;j<=i;j+=2) /* Lage der Kugeln am Anfang */
{
k[l].p.x = 0.75+((i/*-2*/)*XAB/DIFFX) + 0.25 * RND / DIFFX;
k[l].p.y = 0.25+j/2.0*((2*RADIUS+2))/DIFFX + 0.25 * RND / DIFFX;
k[l].v.x = k[l].v.y = k[l].e.x = k[l].e.y = k[l].ez = k[l].col = 0.0;
k[l].stat = 0; k[l++].m = 1.0;
}
k[4].col = COL_BLACK; l = 0;
do /* Farbe der Kugeln, zufallsgesteuert */
{
while( (i = 15.0*rand()/(RAND_MAX+1) ) == BLACK );
if( !k[i].col ) { k[i].col = COL_RED; l++; }
}
while( l < (BALLS-2)/2 );
for( i=0;i<WHITE;i++ ) if( !k[i].col ) k[i].col = COL_YELLOW;
k[WHITE].stat = 1; /* Weiße ist anfangs NICHT auf dem Tisch */
k[WHITE].m = MASS_WHITE;
k[WHITE].col = COL_WHITE;
for( i=0;i<2;i++)
{ ply[i].stat = ply[i].wait = ply[i].col = ply[i].hole_black = 0; }
first_hit = bande_hit = anstoss = 1;
plot_table(); /* oben: damit nicht VOR dem Anfang bereits gefoult wurde */
ply[0].speed = ply[1].speed = spd = 0.75; speed( spd );
wink( alph );
for( i=0;i<WHITE;i++) plot_one_ball( i );
freeball = extra_shot = last_foul = col_in = 0;
if( demo ) msg("press any key to stop demo");
}
void save_actual_position( void )
{ /* sichert die aktuelle Position der Kugeln, für undo() */
int i;
for( i=0;i<BALLS;i++ ) { old_pos[i].x = k[i].p.x; old_pos[i].y = k[i].p.y;
old_stat[i] = k[i].stat; }
undo_act = act;
undo_freeball = freeball;
undo_extra_shot = extra_shot;
undo_color = ply[act].col;
undo_spd = spd;
undo_wink = alph;
undo_e.x = k[WHITE].e.x;
undo_e.y = k[WHITE].e.y;
undo_ez = k[WHITE].ez;
}
void undo( void )
{ /* naja, was wohl */
int i;
mouse_off();
for( i=0;i<BALLS;i++ )
{
if( !k[i].stat ) plot_one_ball( i );
k[i].p.x = old_pos[i].x;
k[i].p.y = old_pos[i].y;
k[i].stat = old_stat[i];
if( !k[i].stat ) plot_one_ball( i );
}
act = undo_act;
freeball = undo_freeball;
extra_shot = undo_extra_shot;
ply[act].col = undo_color;
plot_act_player( act );
if( ply[act].col == COL_RED ) i = 4;
else if( ply[act].col == COL_YELLOW ) i = 11;
else i = 6;
if( freeball ) err2("free-ball", i);
else if( extra_shot) err2("extra_shot", i);
else err2(" ", 0);
speed( spd = undo_spd );
wink( alph = undo_wink );
set_spin( undo_e.x, undo_e.y, undo_ez );
mouse_on();
}
void test_for_play_on_black( void )
/* Wenn alle Kugeln einer Farbe verschwinden sind, wird auf die Schwarze
gespielt. Wann das der Fall ist, und wer Schwarz spielen muß, ermittelt
dies Prozedur */
{
int i, j;
for( j=0;j<2;j++ )
if( (ply[j].col != COL_BLACK) && (ply[j].col) )
{
ply[j].hole_black = 0;
for(i=0;i<WHITE;i++)
if( k[i].stat && (k[i].col == ply[j].col) ) ply[j].hole_black++;
if( ply[j].hole_black == (BALLS-2)/2 )
{
ply[j].col = COL_BLACK;
/* ply[j].hole_black = last_hole gegenüber; */ /* SPÄTER !!! */
}
}
}
char *str_player( char *out2, int act )
{
sprintf(out2, "Player %d%s", act+1, (c_player==act) ? " (Computer)" : "");
return out2;
}
int test_if_game_is_over( void )
{ /* Wie der Name schon sagt, testet, ob Spiel zu Ende */
char out[80], out2[30];
int loser;
if( k[BLACK].stat )
{
if( !(ply[act].stat & FOUL_ANY_FOUL) )
{ /* Schwarze wurde KORREKT eingelocht */
loser = 1 - act;
sprintf(out,"%s wins!", str_player( out2, act) );
ply[act].points += 1;
stats[act].wins += 1;
stats[act].pots += 1;
}
else
{
loser = act;
sprintf(out,"black ball illegaly pocketed; %s loses!",
str_player( out2, act ) );
ply[act].points += 10000;
stats[act].losses += 1;
act = 1 - act;
}
err(out);
if( loser != last_anstoss ) last_anstoss = loser;
if( demo || c_player == loser ) { msg("wait..."); wait_user_time( 5.0 ); }
else wait_for_click();
init_table();
return 1;
}
return 0;
}
void rules( void )
/* Die Regeln, nach einem Stoß wird überprüft, ob keine Fouls aufgetreten
sind. Sollte dies so sein, so erfolgen die "Strafen". Ruft die obigen
Test-Prozeduren, das Menu und den Stoß auf ... */
{
int spielende=0, color;
mouse_off();
init_table();
ply[0].points = ply[0].points = 0;
do
{
first_hit = bande_hit = 0;
if( ply[act].stat & FOUL_WHITE_POCKETED ) /* hier kommen die Fouls... */
{
err("white ball pocketed, foul!");
last_foul = 1;
stats[act].fouls.whited += 1;
}
else if( ply[act].stat & FOUL_NO_TOUCH )
{
err("no ball or no side touched, foul!");
last_foul = 1;
stats[act].fouls.notouch += 1;
}
else if( ply[act].stat & FOUL_WRONG_COLOR_POCKETED)
{
if( !freeball )
{
err("wrong color pocketed, foul!");
last_foul = 1;
stats[act].fouls.wrongcp += 1;
}
else { ply[1-act].wait = 1; }
}
else if( ply[act].stat & FOUL_WRONG_COLOR_TOUCHED )
{
if( !freeball )
{
err("wrong color touched first, foul!");
last_foul = 1;
stats[act].fouls.wrongct += 1;
}
else { extra_shot = 1; }
}
else if( !(ply[act].stat & FOUL_ANY_FOUL) ) /* kein Foul gemacht */
{
if( ply[act].stat & FOUL_CORRECT_POT )
{
last_foul = 0;
stats[act].pots += last_pocketed_balls;
err("OK!"); /* Kugel eingelocht */
}
else /* keine Kugel eingelocht */
{
stats[act].nopots += 1;
if( ply[1-act].wait == 1 ) { extra_shot = 1; ply[1-act].wait = 0; }
else act = 1 - act;
}
}
if( col_in && last_foul ) { ply[act].col = ply[1-act].col = 0; }
if( last_foul )
{
ply[act].wait = 1; act = 1 - act;
if( ply[act].col == COL_RED ) color = 4;
else if( ply[act].col == COL_YELLOW ) color = 11;
else color = 6;
err2("free-ball", color );
freeball = 1;
}
else if( extra_shot )
{
ply[act].wait = 0;
freeball = 0;
if( ply[act].col == COL_RED ) color = 4;
else if( ply[act].col == COL_YELLOW ) color = 11;
else color = 6;
err2("extra-shot", color);
}
else freeball = 0;
if( !freeball && !extra_shot) err2(" ", 0);
new_col = col_in = last_foul = extra_shot = last_pocketed_balls = 0;
ply[0].stat = ply[1].stat = 0; /* eigentlich nur ply[act].stat */
if( demo ) c_player = act;
if( c_player != act ) speed( spd = ply[act].speed );
if( !( spielende = menu() ) ) stoss(); /*HIER ROLLEN ERST D. KUGELN*/
if( !test_if_game_is_over() ) test_for_play_on_black();
if( new_col & NEW_COL_NEW )
{
if( (new_col & NEW_COL_DOUBLE) /*&& (ply[act].stat & FOUL_CORRECT_POT)*/ )
ply[0].col = ply[1].col = 0;
}
if( (!first_hit) || (!bande_hit) ) ply[act].stat |= FOUL_NO_TOUCH;
}
while( !spielende );
}
void stop_it( void )
{ /* beendet Programm und gibt Statistiken und Stand aus */
int i;
close_graphics();
if( datei ) fclose(datei);
MSG;
for( i=0;i<2;i++ )
printf("\n Player %d has won %d and lost %d game%s",i+1,
(int)(ply[i].points)%10000, (int)(ply[i].points)/10000,
( ((int)(ply[i].points)/10000) !=1 ) ? "s" : "");
printf("\n\n");
exit( 0 );
}
void main( int argc, char *argv[])
{
time_t sys_time;
if( !(datei = fopen("konst.dat","r") ) )
{ /* Datei für die (phys.) Konstanten */
printf("can't open file 'konst.dat'\n");
exit( 0 );
}
fscanf(datei,"%lg%*[^\n]%lg%*[^\n]%lg%*[^\n]%lg%*[^\n]%lg%*[^\n]",
&ALPHA, &BETA, &GAMMA, &DELTA, &ETA);
fscanf(datei,"%lg%*[^\n]%lg%*[^\n]%lg%*[^\n]",
&BANDES, &BANDEREF, &MASS_WHITE);
fscanf(datei,"%d%*[^\n]%d%*[^\n]", &STEP, &CLEV);
fscanf(datei,"%*[^\n]%lg%*[^\n]%lg%*[^\n]%d",&CURVES, &CURVEP, &TIME_STEP);
if( CLEV > 15 ) CLEV = 15; /* Computer-Level max 15 */
fclose(datei);
/*if(argc>=4) init_graphics( atoi(argv[1]), atoi(argv[2]), atoi(argv[3]) );*/
if( argc >= 3 && !strcmp( argv[1], "-init") )
{
create_table( atoi( argv[2] ) );
MSG; printf("file 'table.dat' created.\n\n");
init_graphics( 640, 480, 256 );
}
else if( argc >= 2 ) init_graphics( 640, 480, 16 );
else init_graphics( 640, 480, 256 );
datei = NULL;
/* datei = fopen("xxx.xxx","w"); */
init_timer();
sys_time = time( NULL );
srand( sys_time % RAND_MAX );
rules(); /* Start des Spiels */
stop_it();
}
void calc_e_winkel( void )
/* Als nächstes wird der "Einschußwinkel" der Mittellöcher berechnet, also
der Winkel, "oberhalb dem cos( diese Winkels )" die Kugeln noch ins
Mittelloch versenkt werden können*/
{
double dummy;
dummy = (300 - ban[8].p0.x) - 0;
e_winkel = 90-180.0 / M_PI *
atan( ((ban[8].p0.y+RADIUS+2) - posl[2].m.y*DIFFX) / dummy );
}