home *** CD-ROM | disk | FTP | other *** search
- /* This is "graphics.c", a part of the pool (billiards)-program
-
- "ANOTHER POOL".
-
- "graphics.c" uses CBGRX 2.0 and includes most of the graphic-functions.
-
- 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. */
-
- /* ------------------------------ graphics.c ----------------------------- */
-
- #include "c:/djgpp/contrib.20/libgrx/include/grx20.h"
- #include <pc.h>
- #include <math.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <go32.h>
- #include "apool.h"
- /* unten: für die Kürzung der BitBlt-Routine */
- #include "c:/djgpp/contrib.20/libgrx/src/include/libgrx.h"
- #include "c:/djgpp/contrib.20/libgrx/src/include/clipping.h"
-
- #ifdef S3
- #define BitBlt_S3( dx, dy, x1)\
- bitblt( (x1)-Radius+64, 480+Radius ,(dx)-Radius, (dy)-Radius,\
- (Radius*2)+1, (Radius*2)+1 )
- #else
- #define BitBlt_S3( dx, dy, x1) (*(CURC->gc_driver->bltr2v))\
- ( curc_gc_frame, (dx) + curc_xoffset, (dy) + curc_yoffset,\
- cont_gc_frame, (x1) + cont_xoffset, cont_yoffset,\
- RADIUS + RADIUS + 1, RADIUS + RADIUS + 1, GrXOR )
- #endif
-
- #define CRTC_ADR 0x3d4
- #define CRTC_DATA 0x3d5
-
- #define CRT_REG_LOCK1 0x38
- #define CRT_REG_LOCK2 0x39
- #define CRT_SYS_CNFG 0x40
- #define GP_STAT 0x9ae8
-
- #define FRGD_MIX 0xbae8
- #define FRGD_COLOR 0xa6e8
- #define MULTIFUNC_CNTL 0xbee8
- #define CUR_X 0x86e8
- #define CUR_Y 0x82e8
- #define MAJ_AXIS_PCNT 0x96e8
- #define MIN_AXIS_PCNT 0xbee8
- #define DESTX_DIASTP 0x8ee8
- #define DESTY_AXSTP 0x8ae8
- #define ERR_TERM 0x92e8
- #define CMD 0x9ae8
-
- double oldalph=0.0, alph=0.0, spd=0.75, RADIUSL, e_winkel, old_min;
- int counter=0, oldx[BALLS], oldy[BALLS], olds[2] = {SPINPOSX,SPINPOSY};
- int old_ball, old_hole, old_paint=5;
- struct hole posl[6]; /* 6 Löcher */
- struct bande ban[18];
- GrCursor *cursor[5];
- GrMouseEvent me;
- GrFont *fontb, *fontm, *fonts;
- GrTextOption textopt = { NULL, {6}, {0}, GR_TEXT_DEFAULT, GR_BYTE_TEXT,
- GR_ALIGN_CENTER, GR_ALIGN_TOP };
- GrTextOption textleft = { NULL, {6}, {0}, GR_TEXT_DEFAULT, GR_BYTE_TEXT,
- GR_ALIGN_LEFT, GR_ALIGN_TOP };
- GrTextOption textcenter = { NULL, {6}, {0}, GR_TEXT_DEFAULT, GR_BYTE_TEXT,
- GR_ALIGN_CENTER, GR_ALIGN_TOP };
- #ifndef S3
- GrContext *context;
- GrFrame *cont_gc_frame, *curc_gc_frame;
- int curc_xoffset, curc_yoffset, cont_xoffset, cont_yoffset;
- #endif
-
- void init(void)
- {
- #ifdef S3
- outportb(CRTC_ADR,CRT_REG_LOCK1);
- outportb(CRTC_DATA,0x48);
- outportb(CRTC_ADR,CRT_REG_LOCK2);
- outportb(CRTC_DATA,0xa0);
- outportb(CRTC_ADR,CRT_SYS_CNFG);
- outportb(CRTC_ADR,CRT_SYS_CNFG);
- outportb(CRTC_DATA,inportb(CRTC_DATA)|1);
- #endif
- }
-
- void init_graphics( int a, int b, int c)
- { /* Öffnet Grafikschirm der Größe a*b, mit c Farben */
- if( !GrMouseDetect() ) { MSG; printf("Mouse required...\a\n\n"); exit( 0 ); }
- GrSetMode( GR_width_height_color_graphics, a, b, c );
- GrSetColor( 0, 0, 0, 0 );
- GrSetColor( 1, 0, 128, 0 );
- GrSetColor( 2, 0, 96, 0 );
- GrSetColor( 3, 96, 64, 32 );
- GrSetColor( 4, 255, 0, 0 );
- GrSetColor( 5, 255, 255, 255 );
- GrSetColor( 6, 118, 138, 168 );
- GrSetColor( 7, 192, 150, 64 );
- GrSetColor( 8, 128, 80, 20 );
- GrSetColor( 9, 54, 58, 62 );
- GrSetColor( 10, 0, 128, 255 );
- GrSetColor( 11, 255, 255, 0 );
- GrSetColor( 12, 0, 110, 150 );
- GrSetColor( 13, 255, 192, 192 );
- GrSetColor( 14, 0, 0, 127 );
- GrSetColor( 15, 0, 0, 255 );
- GrMouseEventMode( 0 ); /* Maus im "poll"-mode */
- GrMouseInit();
- GrMouseSetAccel( 50, 2 ); /* unten: Mausbeweg. auf Tischgröße reduzieren ! */
- GrMouseSetLimits(LEFT+RADIUS+1, UP+RADIUS+1, RIGHT-RADIUS-1, DOWN-RADIUS-1);
- init();
- make_mouse_cursor();
- fontb = GrLoadFont("ncen29b.fnt");
- textopt.txo_font = fontb;
- fontm = GrLoadFont("xm8x16.fnt");
- textleft.txo_font = fontm;
- fonts = GrLoadFont("xm7x14.fnt");
- textcenter.txo_font = fonts;
- }
-
- #ifdef S3
- void
- bitblt(int sx1,int sy1,int dx1,int dy1,int sx,int sy)
- {
- while(inportw(GP_STAT)&0xc0); /* wait for 2 FIFOs */
- outportw(MULTIFUNC_CNTL,0xa000);
- outportw(FRGD_MIX,0x65); /* use foreground color set in next line and
- just write (no and or or so) */
- while(inportw(GP_STAT)&0xfe); /* wait for 7 FIFOs */
- outportw(CUR_X,sx1);
- outportw(CUR_Y,sy1);
- outportw(DESTX_DIASTP,dx1);
- outportw(DESTY_AXSTP,dy1);
- outportw(MAJ_AXIS_PCNT,sx-1);
- outportw(MIN_AXIS_PCNT,sy-1);
- outportw(CMD,0xc0b3);
- }
- #endif
-
- void close_graphics( void )
- {
- GrMouseUnInit();
- GrSetMode(GR_default_text,0,0,0);
- }
-
- void msg( char *out )
- { /* Gibt einige Dinge unterhalb des Tisches aus */
- GrFilledBox( 0, DOWN+25, 480 + 60*(fonts==NULL), DOWN+41, 0 );
- GrDrawString( out, strlen(out), 240+30*(fonts==NULL), DOWN+25, &textcenter );
- }
-
- void plot_standings( void )
- {
- char out[15];
- sprintf(out,"%d : %d",(int)(ply[0].points)%10000+(int)(ply[1].points)/10000,
- (int)(ply[1].points)%10000 + (int)(ply[0].points)/10000 );
- GrDrawString(out, strlen(out), GrMaxX() - (15+strlen(out))*8, 10, &textleft);
- }
-
- void plot_table( void )
- /* Hier wird der Tisch neu initialisiert und gemalt, die Banden und Löcher
- werden aus der Datei "table.dat" ausgelesen und entsprechend gemalt.
- Gleichzeitig werden diese Daten für das Spiel aufbereitet... */
- {
- FILE *dat;
- int i, j, poly[4][2], counter = 0;
- double dummy, dummy2[4];
- struct vect n;
- char out[20];
- GrClearScreen( 0 );
- GrFilledBox( LEFT-10, UP-10, RIGHT+10, DOWN+10, 1 ); /* "Tuch" */
- if( !(dat = fopen("table.dat","r")) )
- {
- GrSetMode(GR_default_text,0,0,0);
- MSG;
- printf("error: can't find the file 'table.dat'. \n");
- printf("create this file using 'creatabl.e.xe' ...\n\n");
- exit(0);
- }
- fscanf(dat,"%lg",&RADIUSL );
- for(i=0;i<6;i++) /* Teilkreise der Taschen malen */
- {
- for(j=0;j<2;j++) fscanf(dat,"%lg",&dummy2[j]);
- GrFilledCircle( LEFT+dummy2[0], UP+dummy2[1], RADIUSL, 0 );
- posl[i].p.x = dummy2[0] / DIFFX;
- posl[i].p.y = dummy2[1] / DIFFX;
- }
- for(i=0;i<6;i++) /* Banden initialisieren und malen */
- {
- for(j=0;j<4;j++)
- {
- fscanf(dat,"%lg",&dummy); poly[j][0] = LEFT + (int)dummy;
- fscanf(dat,"%lg",&dummy); poly[j][1] = UP + (int)dummy;
- }
- for( j=1;j<4;j++) /* Punkte den Banden zuweisen und Norm.vektoren berech. */
- {
- ban[counter].p0.x = poly[j-1][0]-LEFT;
- ban[counter].p0.y = poly[j-1][1]-UP;
- ban[counter].p1.x = poly[j][0]-LEFT;
- ban[counter].p1.y = poly[j][1]-UP;
- /* "Den" zum "Richtungs-Vektor" der Bande senkrechten Vektor bestimmen */
- n.y = ban[counter].p1.x-ban[counter].p0.x;
- n.x = - ( ban[counter].p1.y-ban[counter].p0.y );
- /* Normieren */
- ban[counter].n.x = n.x / ( dummy = BETR( n ) );
- ban[counter].n.y = n.y / dummy;
- counter++;
- }
- GrFilledConvexPolygon( 4, poly, 2);
- }
- fclose(dat);
- /* dicke Banden wieder schmaler machen (optisch) */
- GrFilledBox( 0,0, GrMaxX(), UP-11, 0 );
- GrFilledBox( 0,DOWN+11, GrMaxX(), GrMaxY(), 0 );
- GrFilledBox( 0,0, LEFT-11, GrMaxY(), 0 );
- GrFilledBox( RIGHT+11,0, GrMaxX(), GrMaxY(), 0 );
- GrDrawString("ANOTHER POOL", 12, GrMaxX()/2, 0, &textopt );
- textcenter.txo_fgcolor.v = 9;
- sprintf(out,"V %s",VERSION);
- GrDrawString( out, strlen(out), 615, 0, &textcenter);
- textcenter.txo_fgcolor.v = 6;
- GrFilledCircle( SPINPOSX, SPINPOSY, 39, 5 );
- GrCircle( SPINPOSX, SPINPOSY, 39, 9 );
- calc_hot_spot();
- calc_e_winkel();
- plot_standings();
- }
-
- void speed( double p )
- { /* Gibt den Geschwindigkeitsbalken am unteren Ende des Screens aus */
- int mx = GrMaxX(), my = GrMaxY();
- GrFilledBox( 0, my - 9, mx, my, 14 );
- GrFilledBox( 0, my - 9, (int)(mx*p), my, 15 );
- }
-
- void plot_balls( void )
- { /* Zeichnet alle Bälle neu und löscht die alten */
- int i;
- for(i=0;i<BALLS;i++)
- if( !k[i].stat && !k[i].nopaint )
- {
- BitBlt_S3( oldx[i], oldy[i], (k[i].col)<<5 );
- oldx[i]=(LEFT+DIFFX*k[i].p.x+0.5);
- oldy[i]=(UP+DIFFX*k[i].p.y)+0.5;
- BitBlt_S3( oldx[i], oldy[i], (k[i].col)<<5 );
- }
- }
-
- void plot_one_ball( int i )
- { /* Malt im Gegensatz zu plot_balls() nur eine einzige Kugel neu */
- oldx[i]=(LEFT+DIFFX*k[i].p.x)+0.5;
- oldy[i]=(UP+DIFFX*k[i].p.y)+0.5;
- BitBlt_S3( oldx[i], oldy[i], (k[i].col)<<5 );
- }
-
- void set_spin( double sx, double sy, double sz )
- { /* hier wird der (lokale) Spin der Weißen am Anfang gesetzt und gemalt */
- GrFilledCircle( olds[0], olds[1], 7, 5 );
- k[WHITE].ez = sz; k[WHITE].e.y = sy; k[WHITE].e.x = sx;
- olds[0] = SPINPOSX + (31.0*k[WHITE].ez + 0.5);
- olds[1] = SPINPOSY + (31.0*k[WHITE].e.y + 0.5);
- GrFilledCircle( olds[0], olds[1], 7, 12 );
- }
-
- void test_spin( int x, int y )
- { /* Mouse-Abfrage für das Setzten des lokalen Spins... */
- int oldx=x, oldy=y;
- double sz, sp, dummy;
- do
- {
- GrMouseGetEvent( GR_M_KEYPRESS | GR_M_MOTION | GR_M_BUTTON_CHANGE, &me );
- if( me.flags & GR_M_MOTION )
- {
- /* sollte vielleicht umgerechnet werden in einen Winkel !!! !!! !!! ??? */
- sz = (me.x - oldx)/31.0; sp = (me.y - oldy)/31.0;
- GrMouseWarp( oldx, oldy );
- if( (k[WHITE].ez+sz)*(k[WHITE].ez+sz)+
- (k[WHITE].e.y+sp)*(k[WHITE].e.y+sp) < 1.0 )
- set_spin( 0.0, k[WHITE].e.y+sp, k[WHITE].ez+sz );
- else if( (k[WHITE].e.y+sp) || (k[WHITE].ez+sz) )
- {
- dummy = sqrt( (k[WHITE].ez+sz)*(k[WHITE].ez+sz) +
- (k[WHITE].e.y+sp)*(k[WHITE].e.y+sp) );
- set_spin( 0.0, (k[WHITE].e.y+sp)/dummy, (k[WHITE].ez+sz)/dummy );
- }
- }
- }
- while( !(me.flags & GR_M_KEYPRESS) && !(me.flags & GR_M_MIDDLE_UP) &&
- !(me.flags & GR_M_RIGHT_DOWN) );
- }
-
- void wait_for_click( void )
- /* wartet auf Mouse-Click oder Tasten-Druck */
- {
- GrMouseEvent mev;
- msg("press any key or mouse-button");
- do
- { GrMouseGetEvent( GR_M_BUTTON_CHANGE | GR_M_KEYPRESS, &mev ); }
- while( !(mev.flags & ( GR_M_BUTTON_DOWN | GR_M_KEYPRESS )) );
- if( (mev.flags & GR_M_KEYPRESS) && (mev.key == 27) ) stop_it();
- }
-
- void wink( double a ) /* Winkel zwischen Queue und Tisch darstellen */
- { /* Könnte mal einen dickeren Queue bekommen !!! !!! !!!*/
- double b = a*M_PI/180.0;
- GrFilledCircleArc( 480, 465, 4*RADIUS, 0, 900, GR_ARC_STYLE_CLOSE2, 5 );
- GrCircleArc( 480, 465, 4*RADIUS+1, 0, 900, GR_ARC_STYLE_OPEN, 9 );
- GrLine(480+4*(RADIUS+1)*cos( oldalph ),465-4*(RADIUS+1)*sin( oldalph ),
- 480+8*(RADIUS+1)*cos( oldalph ),465-8*(RADIUS+1)*sin( oldalph ), 0 );
- GrLine(480+4*(RADIUS+1)*cos( b ),465-4*(RADIUS+1)*sin( b ),
- 480+8*(RADIUS+1)*cos( b ),465-8*(RADIUS+1)*sin( oldalph = b ), 8 );
- }
-
- void err( char *out )
- { /* Ausgabe der normalen Texte während des Spiels */
- GrFilledBox( 0, 450, 400, 469, 0 );
- GrDrawString( out, strlen( out ), 0, 451, &textleft );
- }
-
- void err2( char *out, int col )
- { /* Ausgabe von z.B. Free- oder Extra-Ball ... */
- GrFilledBox( 0, 430, 440, 449, 0 );
- textleft.txo_fgcolor.v = col;
- GrDrawString(out, strlen(out), 0, 431, &textleft );
- textleft.txo_fgcolor.v = 6;
- }
-
- void debug( char *out )
- { /* Ausgabe der Kommentare beim Computer-Spieler */
- char o[80];
- sprintf(o,"%s",out);
- GrFilledBox( 0, 35, 540, 55, 0 );
- GrDrawString(out, strlen(out), 0, 35, &textleft );
- }
-
- void make_mouse_cursor( void )
- { /* erstellt die Bälle, die als Mouse-Cursor dienen */
- int i,j;
- long c_table[5][4] =
- {{3,6,4,4},{3,6,11,11},{3,6,4,11},{3,6,0,0},{3,5,5,5}};
- char curs[(int)((2*RADIUS+1)*(2*RADIUS+1))];
- #ifndef S3
- context = GrCreateContext( 256, 4*RADIUS, NULL, NULL );
- cont_gc_frame = &context->gc_frame;
- curc_gc_frame = &CURC->gc_frame;
- curc_xoffset = CURC->gc_xoffset - RADIUS;
- curc_yoffset = CURC->gc_yoffset - RADIUS;
- cont_xoffset = context->gc_xoffset - RADIUS + 64;
- cont_yoffset = context->gc_yoffset + RADIUS;
- #endif
- GrFilledCircle( 32, 2*RADIUS, RADIUS, 1 ); /* f. Mauszeiger */
- GrFilledCircleArc( 32, 2*RADIUS, 3, 2700, 900, GR_ARC_STYLE_CLOSE2, 2 );
- GrFilledCircleArc( 32, 2*RADIUS, 3, 900, 2700, GR_ARC_STYLE_CLOSE2, 3 );
- GrFilledCircle( 64, 2*RADIUS, RADIUS, 4 ); /* f. WEISS; KUGELN ... */
- GrFilledCircle( 96, 2*RADIUS, RADIUS, 5 ); /* f. ROT */
- GrFilledCircle( 128, 2*RADIUS, RADIUS, 10 ); /* f. GELB */
- GrFilledCircle( 160, 2*RADIUS, RADIUS, 1 ); /* f. SCHWARZ */
- GrFilledCircleArc(192, 2*RADIUS, RADIUS, 2700, 900, GR_ARC_STYLE_CLOSE2, 5);
- GrFilledCircleArc(192, 2*RADIUS, RADIUS, 900, 2700, GR_ARC_STYLE_CLOSE2, 10);
- #ifdef S3
- bitblt( 0, 0, 0, GrSizeY(), 256, 4*RADIUS );
- #else
- GrBitBltNC( context, 0, 0, NULL, 0, 0, 255, 4*RADIUS, GrWRITE);
- #endif
- for(j=0;j<2*RADIUS+1;j++) /* fünf neue Maus-"Zeiger" werden erstellt */
- for(i=0;i<2*RADIUS+1;i++)
- curs[(int)(j*(2*RADIUS+1)+i)] =
- GrPixel( 32-RADIUS+i, 2*RADIUS-RADIUS+j );
- for( i=0;i<5;i++ ) cursor[i] = GrBuildCursor( curs, 2*RADIUS+1, 2*RADIUS+1,
- 2*RADIUS+1, RADIUS, RADIUS, c_table[i] );
- }
-
- void mouse_on( void )
- { GrMouseDisplayCursor(); }
-
- void mouse_off( void )
- { GrMouseEraseCursor(); }
-
- void plot_act_player( int act )
- { /* gibt die kleine Kugel oben links und den akt. Spieler aus */
- char whois[20];
- GrFilledBox( 0, 0, 2*RADIUS+3, 2*RADIUS+3, 1 );
- if( !ply[act].col ) BitBlt_S3( 1 + RADIUS, 1 + RADIUS, 128);
- else BitBlt_S3( 1 + RADIUS, 1 + RADIUS, (ply[act].col)<<5);
- sprintf(whois,"player no: %d",act+1);
- GrDrawString( whois, strlen(whois), 3*RADIUS+1, 1, &textleft );
- }
-
- void set_white_ball( void )
- { /* Weiße Kugel am Anfang oder nach Foul neu positionieren */
- int i, j, ok;
- double old, old2;
- if( (c_player == -1) || (act != c_player ) )
- {
- msg("place cue-ball");
- set_spin( 0.0, 0.0, 0.0 );
- old2 = 0.25;
- i = 250;
- do
- {
- old = ((double)i) / 1000.0;
- ok = 1;
- for(j=0;j<WHITE;j++) /* Suche nach freiem Platz auf dem Tisch */
- if( DIFF2( old-k[j].p.x, old2-k[j].p.y ) < 5.0*RADIUS*RADIUS )
- {ok=0; break;}
- }
- while( !ok && (--i>50) );
- k[WHITE].p.x = old; k[WHITE].p.y = old2;
- GrMouseWarp( LEFT + old*DIFFX, UP + old2*DIFFX );
- GrMouseSetLimits( LEFT+RADIUS+1, UP+RADIUS+1, LEFT+DIFFX/4, DOWN-RADIUS-1 );
- do
- {
- GrMouseSetCursor( cursor[4] ); /* weißer Mouse-Cursor */
- GrMouseGetEvent( GR_M_KEYPRESS | GR_M_MOTION | GR_M_BUTTON_CHANGE, &me );
- ok = 1;
- if( me.flags & GR_M_MOTION )
- { /* Verschieben des Spielballs, aber nicht "auf" andere Kugeln */
- for(j=0;j<WHITE;j++)
- if((!(k[j].stat)) && (DIFF2( (me.x-LEFT)/DIFFX - k[j].p.x,
- (me.y-UP)/DIFFX - k[j].p.y ) < 5.0*RADIUS*RADIUS) )
- { ok = 0; break; }
- if( ok )
- {
- old = (double)(me.x-RIGHT+DIFFX)/DIFFX;
- old2 = (double)(me.y-DOWN+DIFFX/2)/DIFFX;
- k[WHITE].p.x = old; k[WHITE].p.y = old2;
- }
- else GrMouseWarp((double)LEFT + old * DIFFX, (double)UP + old2*DIFFX);
- }
- }
- while( !(me.flags & GR_M_KEYPRESS ) && (!(me.flags & GR_M_BUTTON_DOWN)) );
- if( (me.flags & GR_M_KEYPRESS) && (me.key == 27) ) stop_it();
- }
- else /* !!! !!! !!! !!! !!! !!! VERBESSERN! */
- {
- /* Computer kann Weiße legen ... */
- set_spin( 0.0, 0.0, 0.0 );
- old2 = 0.25;
- i = 250;
- do
- {
- old = ((double)i) / 1000.0;
- ok = 1;
- for(j=0;j<WHITE;j++) /* Suche nach freiem Platz auf dem Tisch */
- if( DIFF2( old-k[j].p.x, old2-k[j].p.y ) < 5.0*RADIUS*RADIUS )
- {ok=0; break;}
- }
- while( !ok && (--i>50) );
- k[WHITE].p.x = old; k[WHITE].p.y = old2;
- }
- k[WHITE].stat = 0; /* Weiße wieder auf dem Tisch */
- plot_one_ball( WHITE );
- }
-
- void calc_player_v( void )
- { /* brechnet die Richtung (zum Maus-Zeiger) der Geschwindigkeit und
- multipliziert diese mit dem "Power"-Faktor spd */
- struct vect v;
- double dummy;
- v.x = (double)(me.x - LEFT) - k[WHITE].p.x*DIFFX;
- v.y = (double)(me.y - UP) - k[WHITE].p.y*DIFFX;
- if( v.x || v.y )
- {
- v.x /= (dummy = sqrt(v.x*v.x+v.y*v.y));
- v.y /= dummy;
- }
- /* v multiplizieren mit Geschwindigkeitsfaktor (0 <= spd <= 1) */
- k[WHITE].v.x = spd * v.x / DIFFX * cos( alph * M_PI/180.0 );
- k[WHITE].v.y = spd * v.y / DIFFX * cos( alph * M_PI/180.0 );
- set_spin( k[WHITE].e.x*spd, k[WHITE].e.y*spd, k[WHITE].ez/* *spd!!! ??*/);
- err(" "); debug(" ");
- }
-
- void set_player_power( void )
- { /* zum Einstellen der Stoßstärke; Balken ganz unten im Bildschirm */
- int old, old2;
- msg("move mouse to increase / decrease power");
- old=me.y; old2=me.x;
- do
- {
- GrMouseGetEvent( GR_M_KEYPRESS | GR_M_MOTION | GR_M_BUTTON_CHANGE, &me);
- if( (me.flags & GR_M_MOTION))
- {
- spd += 1.0/GrSizeX() * (old-me.y - old2 + me.x);
- GrMouseWarp( old2, old );
- if( spd > 1.0 ) spd = 1.0;
- if( spd < 0.0 ) spd = 0.0;
- speed( spd );
- }
- }
- while( !(me.flags & GR_M_KEYPRESS) && !(me.flags & GR_M_RIGHT_UP) );
- MSG2;
- }
-
- void set_player_spin( void )
- { /* zum Einstellen des Spins; dicke Kugel rechts unten */
- int old, old2;
- msg("move mouse to change spin, press right button to change angle");
- test_spin(me.x, me.y);
- if( me.flags & (GR_M_MIDDLE_DOWN | GR_M_RIGHT_DOWN) )
- {
- old = me.x; old2 = me.y;
- msg("move mouse to change angle between queue an table");
- do
- {
- GrMouseGetEvent( GR_M_KEYPRESS|GR_M_MOTION|GR_M_BUTTON_CHANGE, &me);
- if( me.flags & GR_M_MOTION)
- {
- alph += 0.1 * (old -me.y +old2 -me.x);
- GrMouseWarp( old, old2 );
- if( alph > 85.0 ) alph = 85.0;
- if( alph < 0.0 ) alph = 0.0;
- wink( alph );
- }
- }
- while( !(me.flags & GR_M_KEYPRESS) &&
- (!( me.flags & (GR_M_MIDDLE_UP | GR_M_RIGHT_UP) )) );
- }
- MSG2;
- }
-
- void set_test_power( void )
- { /* Test-Prozedur, berechnet Geschw., die die Weisse haben muß, um zur akt.
- Maus-Position zu rollen */
- struct vect v;
- debug("press button, to play white to act.pos. !");
- do
- { GrMouseGetEvent( GR_M_KEYPRESS|GR_M_MOTION|GR_M_BUTTON_CHANGE, &me); }
- while( !(me.flags & GR_M_BUTTON_DOWN) );
- v.x = (me.x-LEFT)/DIFFX - k[WHITE].p.x;
- v.y = (me.y-UP)/DIFFX - k[WHITE].p.y;
- set_c_speed( SET_V(BETR( v ), 0), v );
- }
-
- int set_test_power2( void )
- { /* Test-Prozedur, berechnet die Geschw., die die Weisse benötigt, um ein
- best. Kugel in ein best. Loch zu schießen; ohne jeden Test, ob andere
- Kugeln im Weg liegen ... */
- int i, puffer_ball;
- struct vect v1, v2, v3, v4;
- double dum1, dummy;
- int dum2;
- char outtext[80];
- debug("ball ?");
- do
- { GrMouseGetEvent( GR_M_KEYPRESS|GR_M_MOTION|GR_M_BUTTON_CHANGE, &me); }
- while( !(me.flags & GR_M_BUTTON_DOWN) );
- v1.x = (me.x-LEFT) / DIFFX;
- v1.y = (me.y-UP) / DIFFX;
- dum1 = dum2 = 4;
- for( i=0;i<WHITE;i++ )
- if( DIFF( v1.x-k[i].p.x, v1.y-k[i].p.y ) < dum1 )
- { dum1 = DIFF( v1.x-k[i].p.x, v1.y-k[i].p.y ); dum2 = i; }
- v1.x = k[dum2].p.x; v1.y = k[dum2].p.y;
- puffer_ball = dum2;
- sprintf(outtext,"ball no: %d, hole ?", dum2 );
- debug(outtext);
- do
- { GrMouseGetEvent( GR_M_KEYPRESS|GR_M_MOTION|GR_M_BUTTON_CHANGE, &me); }
- while( !(me.flags & GR_M_BUTTON_DOWN) );
- v2.x = (me.x-LEFT) / DIFFX;
- v2.y = (me.y-UP) / DIFFX;
- dum1 = 1000.0; dum2 = 0;
- for( i=0;i<6;i++ )
- if( DIFF( v2.x-posl[i].m.x, v2.y-posl[i].m.y ) < dum1 )
- { dum1 = DIFF( v2.x-posl[i].m.x, v2.y-posl[i].m.y ); dum2 = i; }
- sprintf(outtext,"hole: %d",dum2);
- debug(outtext);
- v2.x = posl[dum2].m.x; v2.y = posl[dum2].m.y;
- v3 = calc_tp( v1, v2 );
- dummy = sqrt( DIFF( k[WHITE].p.x-v3.x, k[WHITE].p.y-v3.y ));
- /* geht so natürlich noch nicht wieder !!! */
- v4.x = v2.x - v3.x; v4.y = v2.y - v3.y;
- v1.x = v3.x - k[WHITE].p.x; v1.y = v3.y - k[WHITE].p.y;
- if( COSV( v1, v4 ) > 0.0 )
- {
- v2.x = posl[dum2].p.x - posl[dum2].m.x;
- v2.y = posl[dum2].p.y - posl[dum2].m.y;
- v3.x = posl[dum2].m.x - k[puffer_ball].p.x;
- v3.y = posl[dum2].m.y - k[puffer_ball].p.y;
- if( ((dum2 == 2 || dum2 == 5) && COSV( v2, v3 ) > COS(e_winkel))
- || (dum2 != 2 && dum2 != 5) )
- {
- if( (dum1=COSV( v1, v4 )) ) dummy += BETR(v4) / (dum1 * dum1);
- else dummy = 1000000.0; /* =infinity */
- set_c_speed( SET_V(dummy*sqrt(1.0/ROLL), 0), v1 );
- return 1;
- }
- else
- {
- char out[80];
- sprintf(out,"can't play this..(ew:%g/ pw:%g)", e_winkel,
- 180.0/M_PI * acos(COSV( v2, v3 )) );
- debug(out);
- return 0;
- }
- }
- debug("can't play this...");
- return 0;
- }
-
- /* steht nur wegen den Grafik-Befehlen und #defines in graphics.c */
- int menu( void )
- /* hier wird einiges geregelt, Mouse-Abfragen, die zum Stoßen, Spin u.
- Geschw. einstellen dienen und Tastaturabfragen, wie z.B. Computer-
- Gegner anschalten, Porgramm beenden ... */
- {
- int i, ok=0, ret_wert=0;
- plot_act_player( act );
- wink( alph = 0.0 );
- set_spin( 0.0, 0.0, 0.0 );
- for( i=0;i<BALLS;i++) /* alle Kugeln neu initialisieren */
- { k[i].v.x = k[i].v.y = k[i].e.x = k[i].e.y = k[i].ez = 0.0; }
- if( k[WHITE].stat ) set_white_ball(); /* Weiße neu setzen */
- if( ply[act].col == COL_WHITE ) GrMouseSetCursor( cursor[2] );
- else if( ply[act].col == COL_RED ) GrMouseSetCursor( cursor[0] );
- else if( ply[act].col == COL_YELLOW ) GrMouseSetCursor( cursor[1] );
- else GrMouseSetCursor( cursor[3] ); /* if ... COL_BLACK */
- if( act == c_player ) { computer_stoss(); return ret_wert; }
- GrMouseSetLimits(LEFT+RADIUS+1, UP+RADIUS+1, RIGHT-RADIUS-1, DOWN-RADIUS-1);
- ok = 0;
- MSG2;
- while( kbhit() ) getkey();
- do
- {
- mouse_on();
- do
- { GrMouseGetEvent( GR_M_KEYPRESS | GR_M_BUTTON_CHANGE, &me ); }
- while( !(me.flags & (GR_M_KEYPRESS | GR_M_BUTTON_CHANGE)) );
- if( (me.flags & GR_M_BUTTON_DOWN) )
- {
- GrMouseSetLimits( 0, 0, GrMaxX(), GrMaxY() );
- switch(me.buttons)
- {
- case GR_M_LEFT: /* Stoß: Geschw. berechnen */
- calc_player_v(); ok = 1; break;
- case GR_M_RIGHT: /* Geschwindigkeits (Power)-Faktor verstellen */
- set_player_power(); break;
- case GR_M_MIDDLE: /* Spin einstellen */
- set_player_spin(); break;
- default: {}
- }
- GrMouseSetLimits( LEFT+RADIUS+1, UP+RADIUS+1, RIGHT-RADIUS-1,
- DOWN-RADIUS-1);
- }
- else if( me.flags & GR_M_KEYPRESS )
- switch( me.key )
- {
- case 13: case ' ': calc_player_v(); ok = 1; break;
- case 'q': plot_statistics( 0, 0 );
- case 27: ok = ret_wert = 1; break;
- case 'n': /* new game */
- mouse_off();
- ply[1-act].points += 1;
- stats[act].losses += 1;
- act = 1 - act;
- init_table();
- ok = 1;
- break;
- case 'r': /* 'instant replay'-mode on/off */
- i = STEP;
- STEP = old_paint;
- old_paint = i;
- if( STEP < 6 ) debug("replay-mode on");
- else debug("replay-mode off");
- break;
- case 'u': /* undo last shot */
- undo(); debug("undo..."); break; /* akt ??? !!! !!! !!! */
- case 'd': demo = 1;
- msg("press any key to stop demo");
- c_player = act;
- computer_stoss();
- ok = 1;
- break;
- case 'c': /* computer plays every shot*/
- if( c_player == -1 ) c_player = act;
- else { c_player = -1; break; }
- case 'x': /* let computer play one shot */
- computer_stoss();
- ok = 1;
- break;
- #ifdef BANDEN
- case 'b': /* show shots 'through' 1 or 2 sides */
- mouse_off();
- banden_stoss();
- mouse_on();
- ok = 0;
- break;
- #endif
- case 'D':
- for( i=BLACK+1;i<WHITE;i++ ) delete_ball( i );
- for( i=0;i<BLACK;i++ ) delete_ball( i );
- break;
- case 'w': /* White --> akt-Mouse-Pos */
- /* computer soll Weiße bis zur akt. Mouse-Pos. rollen lassen !!! */
- set_test_power(); ok = 1; break;
- case 'W': /* shot ball (1) in hole (2) */
- ok = set_test_power2(); break;
- case 's': plot_statistics( 0, 1 ); break;
- case 315: help(); break; /* F1 */
- case 316: credits(); break; /* F2 */
- default: {}
- }
- }
- while( !ok );
- mouse_off();
- return ret_wert;
- }
-
- void ctrl_break_off( void ) /* stellt CTRL-BREAK AB ! */
- { _go32_want_ctrl_break( 1 ); }
-
- void plot_statistics( double time, int grx )
- {
- int add = 84;
- time_t oldt = clock();
- char out[80];
- GrContext *cont = NULL;
- mouse_off();
- if( grx ) cont = GrCreateContext( GrSizeX(), GrSizeY(), NULL, NULL );
- if( cont || !grx )
- {
- if( grx ) GrBitBltNC(cont, 0, 0, NULL, 0, 0, GrSizeX(), GrSizeY(), GrWRITE);
- GrClearScreen( 0 );
- GrDrawString( "STATISTICS", 10, GrMaxX()/2, 30, &textopt );
- sprintf(out," Player %5d %5d", 1, 2);
- GrDrawString( out, strlen(out), 1, add, &textleft );
- add += 32;
- sprintf(out,"standings %5d %5d",
- stats[0].wins+stats[1].losses, stats[1].wins+stats[0].losses);
- GrDrawString( out, strlen(out), 1, (add+=16), &textleft );
- sprintf(out,"-games won (correct play on black) %5d %5d",
- stats[0].wins, stats[1].wins);
- GrDrawString( out, strlen(out), 1, (add+=24), &textleft );
- sprintf(out,"-games lost ('direct' foul on black) %5d %5d",
- stats[0].losses, stats[1].losses );
- GrDrawString( out, strlen(out), 1, (add+=16), &textleft );
- sprintf(out,"number of pocketed balls %5d %5d",
- stats[0].pots, stats[1].pots );
- GrDrawString( out, strlen(out), 1, (add+=20), &textleft );
- sprintf(out,"no. of attempts without success %5d %5d",
- stats[0].nopots, stats[1].nopots );
- GrDrawString( out, strlen(out), 1, (add+=16), &textleft );
- sprintf(out,"fouls: wrong color touched %5d %5d",
- stats[0].fouls.wrongct, stats[1].fouls.wrongct );
- GrDrawString( out, strlen(out), 1, (add+=16), &textleft );
- sprintf(out,"fouls: wrong color pocketed %5d %5d",
- stats[0].fouls.wrongcp, stats[1].fouls.wrongcp );
- GrDrawString( out, strlen(out), 1, (add+=16), &textleft );
- sprintf(out,"fouls: white ball disappeared %5d %5d",
- stats[0].fouls.whited, stats[1].fouls.whited );
- GrDrawString( out, strlen(out), 1, (add+=16), &textleft );
- sprintf(out,"fouls: no ball or side touched %5d %5d",
- stats[0].fouls.notouch, stats[1].fouls.notouch );
- GrDrawString( out, strlen(out), 1, (add+=16), &textleft );
- if( time > 0 ) while( (double)(clock() - oldt)/CLOCKS_PER_SEC < time );
- else { wait_for_click(); mouse_off(); }
- if( grx )
- {
- GrBitBltNC( NULL, 0, 0, cont, 0, 0, GrSizeX(), GrSizeY(), GrWRITE);
- GrDestroyContext( cont );
- }
- }
- mouse_on();
- }
-
- void delete_ball( int n )
- /* Kugel "n" fällt in Tasche und wird gelöscht; außerdem wird geprüft, ob
- ein Foul durch das Versenken begangen wurde... Hatte der Spieler vor dem
- Versenken noch keine Farbe (Anfang des Spiels) so bekommt er hier diese */
- {
- k[n].stat = 1;
- k[n].p.x = k[n].p.y = 10000.0; /* eigentlich unnötig ! */
- BitBlt_S3( oldx[n], oldy[n], (k[n].col)<<5 );
- if( k[n].col == COL_WHITE ) ply[act].stat |= FOUL_WHITE_POCKETED;
- else if( (k[n].col == COL_BLACK) && (ply[act].col != COL_BLACK) )
- ply[act].stat |= FOUL_BLACK_ILLEGALY_POCKETED;
- else if( !ply[act].col && (k[n].col != COL_WHITE) )
- { /* falls noch kein Spieler-Farbe festgelegt ist */
- if( (k[n].col != COL_BLACK) && (ply[1-act].col != k[n].col) )
- ply[act].col = k[n].col;
- ply[1-act].col = 3 - k[n].col;
- ply[act].stat |= FOUL_CORRECT_POT;
- col_in = k[n].col;
- new_col |= NEW_COL_NEW;
- }
- else if( !freeball && (k[n].col != ply[act].col) ) /* falsche Farbe */
- {
- if( new_col & NEW_COL_NEW ) new_col |= NEW_COL_DOUBLE;
- else ply[act].stat |= FOUL_WRONG_COLOR_POCKETED;
- }
- else if( freeball || (k[n].col == ply[act].col)) /* OK */
- ply[act].stat |= FOUL_CORRECT_POT;
- bande_hit = 1;
- last_pocketed_balls++;
- }
-
- void print( char *out, int align, int x, int y )
- {
- int old_align = textleft.txo_xalign;
- textleft.txo_xalign = align;
- GrDrawString( out, strlen(out), x, y, &textleft );
- textleft.txo_xalign = old_align;
- }
-
- void print2( char *out, int align, int x, int y )
- {
- int old_align = textcenter.txo_xalign;
- textcenter.txo_xalign = align;
- GrDrawString( out, strlen(out), x, y, &textcenter );
- textcenter.txo_xalign = old_align;
- }
-
- void help( void )
- {
- GrContext *cont = NULL;
- int a=100;
- mouse_off();
- cont = GrCreateContext( GrSizeX(), GrSizeY(), NULL, NULL );
- if( cont )
- {
- GrBitBltNC(cont, 0, 0, NULL, 0, 0, GrSizeX(), GrSizeY(), GrWRITE);
- GrClearScreen( 0 );
- GrDrawString("HELP-Screen", 11, GrMaxX()/2, 30, &textopt );
- print("KEYS:",GR_ALIGN_LEFT, 30, 65);
- print(" 'c': activate/deactivate computer opponent",
- GR_ALIGN_LEFT, 30, a+=16);
- print(" 'x': computer plays only one shot", GR_ALIGN_LEFT, 30, a+=16 );
- print(" 'n': new game, actual game is lost", GR_ALIGN_LEFT, 30, a+=16 );
- print(" 'd': demo-mode on; any key to stop demo",
- GR_ALIGN_LEFT, 30, a+=16 );
- print(" 'w': ball rolls to actual mouse-position (test-procedure)",
- GR_ALIGN_LEFT, 30 , a+=16 );
- print(" 'W': some sort of computer help (test it)",
- GR_ALIGN_LEFT, 30, a+=16 );
- print(" 'u': undo last shot (no redo implemented)",
- GR_ALIGN_LEFT, 30 , a+=16 );
- print(" 'r': slow-motion-mode on/off", GR_ALIGN_LEFT, 30, a+=16 );
- print(" 's': show statistics", GR_ALIGN_LEFT, 30, a+=16 );
- print(" 'F1': this screen", GR_ALIGN_LEFT, 30, a+=16 );
- print(" 'F2': credits", GR_ALIGN_LEFT, 30, a+=16 );
- print("ENTER: or SPACE: same as left mouse-button",
- GR_ALIGN_LEFT, 30, a+=16 );
- print(" 'q': show statistics before quitting the game",
- GR_ALIGN_LEFT, 30, a+=16);
- print(" ESC: 'fast' quit game (works im allmost every situation)",
- GR_ALIGN_LEFT, 30, a+=16 );
- wait_for_click();
- GrBitBltNC( NULL, 0, 0, cont, 0, 0, GrSizeX(), GrSizeY(), GrWRITE);
- GrDestroyContext( cont );
- }
- else msg("no help available");
- mouse_on();
- }
-
- void credits( void )
- {
- /*#ifndef S3*/
- GrContext *cont = NULL;
- /*#endif*/
- int a=70;
- char out[90];
- mouse_off();
- /*#ifndef S3*/
- cont = GrCreateContext( GrSizeX(), GrSizeY(), NULL, NULL );
- if( cont )
- {
- GrBitBltNC(cont, 0, 0, NULL, 0, 0, GrSizeX(), GrSizeY(), GrWRITE);
- /*#else*/
- /* bitblt( 0, 0, 0, 700, 640, 480 );*/
- /*#endif*/
- GrClearScreen( 0 );
- sprintf(out,"Another Pool V %s, %s, copyright (c) by Gerrit Jahn",
- VERSION, DATE);
- print2(out, GR_ALIGN_CENTER, GrMaxX()/2, 20 );
- GrDrawString("CREDITS", 8, GrMaxX()/2, 40, &textopt );
- print2("'ANOTHER POOL' is free software; you can redistribute it",
- GR_ALIGN_LEFT, 90, a+=15);
- print2("and/or modify it under the terms of the GNU General Public License",
- GR_ALIGN_LEFT, 90, a+=15);
- print2("as published by the Free Software Foundation; either version 2 of",
- GR_ALIGN_LEFT, 90, a+=15);
- print2("the License, or (at your option) any later version.",
- GR_ALIGN_LEFT, 90, a+=15);a+=15;
- print2("Another Pool is distributed in the hope that it will be useful,",
- GR_ALIGN_LEFT, 90, a+=15);
- print2("but WITHOUT ANY WARRANTY; without even the implied warranty of",
- GR_ALIGN_LEFT, 90, a+=15);
- print2("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
- GR_ALIGN_LEFT, 90, a+=15);
- print2("GNU General Public License (see file COPYING) for more details.",
- GR_ALIGN_LEFT, 90, a+=15);a+=5;
- print2("------------------------------------------------------------------",
- GR_ALIGN_LEFT, 90, a+=15);a+=5;
- print("Special thanks to Achim Stremplat for helping me in",
- GR_ALIGN_LEFT, 90, a+=15);
- print("coding and talking about the physics of the game.",
- GR_ALIGN_LEFT, 90, a+=15);
- print("Also thanks to Jens Willibald, Martin Schmidt and Frank",
- GR_ALIGN_LEFT, 90, a+=15);
- print2("Schmithuesen for testing; Boris Postler for some corrections",
- GR_ALIGN_LEFT, 90, a+=15);
- print2("on the 'apool.doc'-file.", GR_ALIGN_LEFT, 90, a+=15);
- print2("... and the developers of GNU-C ...", GR_ALIGN_LEFT, 90, a+=15);
- a+=5;
- print2("------------------------------------------------------------------",
- GR_ALIGN_LEFT, 90, a+=15);a+=5;
- print2("If you have any problems, questions or suggestions, email to:",
- GR_ALIGN_LEFT, 90, a+=15);
- print2("ub1g@rz.uni-karlsruhe.de Gerrit",
- GR_ALIGN_LEFT, 90, a+=15);a+=15;
- wait_for_click();
- /* #ifndef S3*/
- GrBitBltNC( NULL, 0, 0, cont, 0, 0, GrSizeX(), GrSizeY(), GrWRITE);
- GrDestroyContext( cont );
- }
- else msg("no credits available");
- /*#else*/
- /* bitblt( 0, 700, 0, 0, 640, 480 );*/
- /*#endif*/
- mouse_on();
- }
-