/* evaluate_move.c ** ** evaluate moves for dfferent gametypes ** Copyright (C) 2001 Florian Berger ** Email: harpin_floh@yahoo.de, florian.berger@jk.uni-linz.ac.at ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License Version 2 as ** published by the Free Software Foundation; ** ** 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 this program; if not, write to the Free Software ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ** */ #include #include #include #define EVALUATE_MOVE_C #include "evaluate_move.h" #define MAX(x,y) ((x)>(y)?(x):(y)); typedef enum { SN_PLAY_RED, SN_PLAY_ANY_COLOR, SN_PLAY_YELLOW, SN_PLAY_GREEN, SN_PLAY_BROWN, SN_PLAY_BLUE, SN_PLAY_PINK, SN_PLAY_BLACK, SN_DONE } SnookerBallToPlay; typedef struct { SnookerBallToPlay to_play; } SnookerState; void spot_snooker_ball(BallsType *balls,int nr); void (* evaluate_last_move)( struct Player * player, int * pact_player, BallsType * pballs, int * pqueue_view, float * pXque ) = evaluate_last_move_8ball; /*static void white_free_place(double x0, double y0, double * xd, double *yd, BallsType * pballs) { int i,exitloop; double x,y, r,phi; x=x0; y=y0; phi=0.0; do{ exitloop=1; phi+=0.01; r=floor(phi/2.0/M_PI)*0.01; x=x0+r*cos(phi); y=y0+r*sin(phi); if(x<(TABLE_W-pballs->ball[0].d)/2.0 && x>(-TABLE_W+pballs->ball[0].d)/2.0 && y<-TABLE_L/4.0 && y>(-TABLE_L+pballs->ball[0].d)/2.0 ) { } else exitloop=0; for(i=1;inr;i++){ if ( vec_abs(vec_diff(vec_xyz(x,y,0),pballs->ball[i].r)) < (pballs->ball[0].d+pballs->ball[i].d)/2.0 ) { exitloop=0; break; } } } while(!exitloop); *xd=x; *yd=y; }*/ static int in_strafraum(VMvect pos) { return(pos.y<-TABLE_L/4.0); } void evaluate_last_move_8ball( struct Player * player, int * pact_player, BallsType * pballs, int * pqueue_view, float * pXque ) { #define act_player (*pact_player) #define balls (*pballs) int out_half=0; int out_full=0; int nextplayer=1; int foul=0; int first_ball_hit; /* if balls_out_half!=balls_out_full && human_full_half==BALL_ANY then */ out_half = BM_get_balls_out_half(); out_full = BM_get_balls_out_full(); nextplayer=1; foul=0; /* wenn fremde kugel zuerst angespielt -> foul */ first_ball_hit=BM_get_1st_ball_hit(); if( player[act_player].half_full == BALL_FULL ){ if ( first_ball_hit>8 && first_ball_hit<16 ) foul=1; } if( player[act_player].half_full == BALL_HALF ){ if ( first_ball_hit>0 && first_ball_hit<8 ) foul=1; } /* erst an 2. stelle, da oben kein foul bei break */ if( player[act_player].half_full == BALL_ANY ){ if(out_half>out_full){ player[act_player].half_full=BALL_HALF; player[!act_player].half_full=BALL_FULL; nextplayer=0; } if(out_half foul */ if ( first_ball_hit==8 ){ int i, eigene_da; eigene_da=0; if( player[act_player].half_full==BALL_FULL ){ for(i=0;inr;i++){ if( pballs->ball[i].in_game && pballs->ball[i].nr>0 && pballs->ball[i].nr<8 ){ eigene_da=1; break; } } } else if( player[act_player].half_full==BALL_HALF ){ for(i=0;inr;i++){ if( pballs->ball[i].in_game && pballs->ball[i].nr>8 && pballs->ball[i].nr<16 ){ eigene_da=1; break; } } } if(eigene_da) foul=1; } /* wenn angespielte kugel im strafraum */ if ( player[act_player].place_cue_ball && in_strafraum(BM_get_1st_ball_hit_pos()) && !BM_get_non_strafraum_wall_hit_before_1st_ball(in_strafraum) ){ foul=1; } /* wenn eigene rein naechster */ if( player[act_player].half_full==BALL_HALF && out_half!=0 ){ nextplayer=0; } if( player[act_player].half_full==BALL_FULL && out_full!=0 ){ nextplayer=0; } /* at break */ if( player[act_player].half_full==BALL_ANY && (out_half!=0 || out_full!=0) ){ nextplayer=0; } if( BM_get_balls_hit()==0 ) foul=1; /* wenn weisse rein */ if( BM_get_white_out() ){ nextplayer=1; foul=1; balls.ball[0].in_game=1; balls.ball[0].in_hole=0; } /* wenn foul */ if( foul ){ // double x,y; /* this is done now for all balls in billard3d.c after evaluate_last_move */ /* white_free_place(0, -TABLE_L/4.0, &x, &y, pballs); */ balls.ball[0].v=vec_xyz(0.0,0.0,0.0); balls.ball[0].w=vec_xyz(0.0,0.0,0.0); balls.ball[0].r=vec_xyz(0.0,-TABLE_L/4.0,0.0); // balls.ball[0].r=vec_xyz(x,y,0.0); } /* if 8 out */ if( BM_get_ball_out(8) ){ int (* get_balls_out_own)(void); int in_own,i; if( player[act_player].half_full==BALL_HALF ){ get_balls_out_own=BM_get_balls_out_half; } else { get_balls_out_own=BM_get_balls_out_full; } /* count own balls in game */ in_own=0; for(i=0;inr;i++){ if( player[act_player].half_full==BALL_FULL && pballs->ball[i].nr>0 && pballs->ball[i].nr<8 && pballs->ball[i].in_game ) in_own++; if( player[act_player].half_full==BALL_HALF && pballs->ball[i].nr>8 && pballs->ball[i].nr<16 && pballs->ball[i].in_game ) in_own++; } /* only one and last one */ if( !foul && get_balls_out_own()==0 && in_own==0 && player[act_player].half_full!=BALL_ANY /* potting 8 at break caused a win (this should fix it) */ ) { player[act_player].winner=1; } else { player[(act_player==1)?0:1].winner=1; } } BM_reset_move_info(); if( player[act_player].place_cue_ball ) player[act_player].place_cue_ball=0; if(foul) nextplayer=1; if(nextplayer){ // Xque=player[act_player].Xque; // player[act_player].Zque=Zque; player[act_player].queue_view=*pqueue_view; act_player = (act_player==1) ? 0 : 1 ; if( foul ) player[act_player].place_cue_ball=1; // Xque=player[act_player].Xque; *pXque=player[act_player].Xque; *pqueue_view=player[act_player].queue_view; } #undef balls #undef act_player } void evaluate_last_move_9ball( struct Player * player, int * pact_player, BallsType * pballs, int * pqueue_view, float * pXque ) { #define act_player (*pact_player) int nextplayer=1; int i, minball, dummy, foul; /* if balls_out_half!=balls_out_full && human_full_half==BALL_ANY then */ nextplayer=1; foul=0; minball=15; for(i=0;inr;i++){ if( pballs->ball[i].nr!=0 && pballs->ball[i].nrball[i].in_game ){ minball=pballs->ball[i].nr; } } dummy=BM_get_min_ball_out(); if ( dummy 0 && !BM_get_white_out() ){ nextplayer=0; } if( BM_get_balls_hit()==0 ) foul=1; if( BM_get_1st_ball_hit()!=minball ) foul=1; /* wenn weisse rein */ if( BM_get_white_out() ){ foul=1; nextplayer=1; pballs->ball[0].in_game=1; pballs->ball[0].in_hole=0; } /* wenn foul - weisse platzieren */ if( foul ){ // double x,y; /* this is done now for all balls in billard3d.c after evaluate_last_move */ /*white_free_place(0, -TABLE_L/4.0, &x, &y, pballs);*/ pballs->ball[0].v=vec_xyz(0.0,0.0,0.0); pballs->ball[0].w=vec_xyz(0.0,0.0,0.0); pballs->ball[0].r=vec_xyz(0,-TABLE_L/4.0,0.0); } fprintf(stderr,"foul:%d, nextplayer:%d, BM_get_ball_out(9):%d\n",foul,nextplayer,BM_get_ball_out(9)); if( !foul && !nextplayer && BM_get_ball_out(9) ){ player[act_player].winner=1; } if( foul && BM_get_ball_out(9) ){ player[(act_player==1)?0:1].winner=1; } BM_reset_move_info(); if( player[act_player].place_cue_ball ) player[act_player].place_cue_ball=0; if(nextplayer){ // Xque=player[act_player].Xque; // player[act_player].Zque=Zque; player[act_player].queue_view=*pqueue_view; act_player = (act_player==1) ? 0 : 1 ; if( foul ) player[act_player].place_cue_ball=1; // Xque=player[act_player].Xque; *pXque=player[act_player].Xque; *pqueue_view=player[act_player].queue_view; } #undef act_player } void evaluate_last_move_carambol( struct Player * player, int * pact_player, BallsType * pballs, int * pqueue_view, float * pXque ) { #define act_player (*pact_player) #define CUE_BALL_IND (player[act_player].cue_ball) int nextplayer=1; int bhit1, bhit2, i; int other_player; other_player=(act_player==1)?0:1; nextplayer=1; bhit1=BM_get_nth_ball_hit_by_ind(CUE_BALL_IND,1); for( i=2 ; (bhit2=BM_get_nth_ball_hit_by_ind(CUE_BALL_IND,i))!=-1 && bhit2==bhit1 ; i++ ); fprintf(stderr,"cueball=%d,%d\n",CUE_BALL_IND, pballs->ball[CUE_BALL_IND].nr); fprintf(stderr,"bhit1=%d\n",bhit1); fprintf(stderr,"bhit2=%d\n",bhit2); if( bhit2!=-1 && bhit1!=-1 && bhit2!=bhit1 ){ nextplayer=0; player[act_player].score++; } BM_reset_move_info(); if(nextplayer){ // Xque=player[act_player].Xque; // player[act_player].Zque=Zque; player[act_player].queue_view=*pqueue_view; fprintf(stderr, "score of %s: %d\n", player[act_player].name, player[act_player].score ); fprintf(stderr, "score of %s: %d\n", player[other_player].name, player[other_player].score ); act_player = (act_player==1) ? 0 : 1 ; // if( foul ) player[act_player].place_cue_ball=1; // Xque=player[act_player].Xque; *pXque=player[act_player].Xque; *pqueue_view=player[act_player].queue_view; } #undef CUE_BALL_IND #undef act_player } void evaluate_last_move_snooker( struct Player * player, int * pact_player, BallsType * pballs, int * pqueue_view, float * pXque ) { #define act_player (*pact_player) #define IS_RED(x) ( x==1 || x>=8 ) int red_balls_are_in_game=0; static SnookerState st={SN_PLAY_RED}; int color_to_pot; int i; int act_score=0; int act_penalty=0; int foul=0; int ball_out; int other_player=(act_player==1)?0:1; int b1hit = BM_get_1st_ball_hit(); if (b1hit>=8) b1hit=1; if( player[act_player].place_cue_ball ) player[act_player].place_cue_ball=0; printf("EVAL start\n"); printf("EVAL to_play=%d\n",st.to_play); printf("EVAL b1hit=%d\n",b1hit); for(i=0;inr;i++){ if( IS_RED(pballs->ball[i].nr) && pballs->ball[i].in_game ){ red_balls_are_in_game=1; break; } } /* wenn weisse rein */ if( BM_get_white_out() ){ foul=1; printf("EVAL foul 7\n"); act_penalty =MAX(act_penalty,(BM_get_1st_ball_hit()<=7?BM_get_1st_ball_hit():4)); spot_snooker_ball(pballs,0); player[act_player].place_cue_ball=1; } switch(st.to_play) { case SN_PLAY_RED: color_to_pot=1; if(b1hit!=1) { foul=1; act_penalty=MAX(act_penalty,b1hit); printf("EVAL foul 1\n"); } i=1; while((ball_out=BM_get_nth_ball_out(i++))>=0) { printf("EVAL ball out:%d\n",ball_out); if(IS_RED(ball_out)) { act_score+=1; } else { act_penalty=MAX(act_penalty,ball_out); foul=1; printf("EVAL foul 2\n"); } } for(i=2;i<8;i++) { if( BM_get_ball_out(i)) spot_snooker_ball(pballs,i); } st.to_play=SN_PLAY_ANY_COLOR; break; case SN_PLAY_ANY_COLOR: if(b1hit==1) { foul=1; printf("EVAL foul 3\n"); act_penalty=MAX(act_penalty,7); } color_to_pot=b1hit; i=1; while((ball_out=BM_get_nth_ball_out(i++))>=0) { printf("EVAL ball out:%d\n",ball_out); if(ball_out==color_to_pot) { act_score+=ball_out; } else { foul=1; printf("EVAL foul 4\n"); act_penalty=MAX(act_penalty,ball_out==1?7:ball_out); } } if(red_balls_are_in_game) st.to_play=SN_PLAY_RED; else st.to_play=SN_PLAY_YELLOW; for(i=2;i<8;i++) { if( BM_get_ball_out(i)) spot_snooker_ball(pballs,i); } break; case SN_PLAY_YELLOW: case SN_PLAY_GREEN: case SN_PLAY_BROWN: case SN_PLAY_BLUE: case SN_PLAY_PINK: case SN_PLAY_BLACK: color_to_pot=st.to_play; if(b1hit!=color_to_pot) { foul=1; printf("EVAL foul 5\n"); act_penalty=MAX(act_penalty,b1hit); act_penalty=MAX(act_penalty,color_to_pot); } i=1; while((ball_out=BM_get_nth_ball_out(i++))>=0) { printf("EVAL ball out:%d\n",ball_out); if(ball_out==color_to_pot) { act_score+=ball_out; } else { foul=1; printf("EVAL foul 6\n"); act_penalty=MAX(act_penalty,b1hit); act_penalty=MAX(act_penalty,color_to_pot); } } if(!foul && act_score>0) st.to_play++; for(i=st.to_play;i<8;i++) { if( BM_get_ball_out(i)) spot_snooker_ball(pballs,i); } break; } if(foul) { act_penalty =MAX(act_penalty,4); player[other_player].score += act_penalty ; printf("EVAL foul\n"); } else { player[act_player].score += act_score ; printf("EVAL no foul\n"); } if(act_score==0 || foul) { printf("EVAL next player\n"); if(red_balls_are_in_game) { st.to_play=SN_PLAY_RED; } else { if(st.to_play<=SN_PLAY_ANY_COLOR) { st.to_play=SN_PLAY_YELLOW; } } player[act_player].queue_view=*pqueue_view; act_player = other_player; *pXque=player[act_player].Xque; *pqueue_view=player[act_player].queue_view; } player[act_player].snooker_on_red=st.to_play==SN_PLAY_RED; player[act_player].snooker_next_color=st.to_play; printf("EVAL to_play=%d\n",st.to_play); if(st.to_play==SN_DONE) { int other_player; other_player = (act_player+1)%2; if(player[act_player].score>player[other_player].score){ player[act_player].winner=1; player[other_player].winner=0; } if(player[act_player].score