/*************************************************************************** * Copyright (C) 2004 by Samuele Catuzzi * * samuele_catuzzi@yahoo.it * * * * This program 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 this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "aiplayer.h" #include #include #include #include #include using namespace std; AIplayer::AIplayer(Kbilliards *kb, QCanvas * canvas):QObject( (QObject *)kb, "aiplayer" ) { kbill=kb; error_factor=1.4 ; //absolute error parameter to add when calculate trajectory show_trajectory=false; line1 = new QCanvasLine(canvas); line2 = new QCanvasLine(canvas); line3 = new QCanvasLine(canvas); } AIplayer::~AIplayer() { delete (line1); delete (line2); delete (line3); } /*! \fn AIplayer::stroke() */ void AIplayer::stroke() { int min=16; double nearest, tmp; Ball *nextBallseq=0; Ball *it; QList valid_balls,clone ; if ( kbill->gamestatus == 0 ) return; clone=kbill->ingameballs ; clone.remove(kbill->whiteball); if ( clone.isEmpty() ) return; // determine ball to hit switch ( kbill->actualgameoptions.game ) { case 1: case 2: //first choice: select minor ball number for(it=clone.first(); it != 0; it=clone.next()) { if ( it->ballnumber < min ){ min=it->ballnumber; nextBallseq=it; } } clone.remove(nextBallseq); valid_balls.prepend(nextBallseq); //cout<<"nextBallseq="<ballnumber<vect_Pos - kbill->whiteball->vect_Pos).abs(); if ( tmp < nearest ){ nearest=tmp; nextBallseq=it; } } clone.remove(nextBallseq); valid_balls.append(nextBallseq); } break; default: cout<<"actualgameoptions.game = "<actualgameoptions.game<vect_Pos) ; if ( isPathFree(it,it,temp) ) { temp = it->vect_Pos - ((temp.unit())*(Ball_Physics::diameter)) ; tr = temp - kbill->whiteball->vect_Pos ; if ( tr.abs() < ((it->vect_Pos - kbill->whiteball->vect_Pos).abs() - (Ball_Physics::diameter)*0.5) ) if ( isPathFree(kbill->whiteball,it,tr) && ( temp.abs() < nearest ) ) { to_hole=v_HOLE - (it->vect_Pos); //determine approximate power power1 = sqrtl( 2*(kbill->actualconfig.decel)* tr.abs() ) ; power = power1 ; cos=tr.unit()*to_hole.unit(); v2=sqrtl( 2*(kbill->actualconfig.decel)*to_hole.abs() ) ; if ( cos != 0 ) { power2 = v2/cos ; power = power1 + power2 ; if ( power2 != v2 ) { reflex = tr.unit()*power2 - to_hole.unit()*v2 ; v1 = reflex.x*reflex.x + reflex.y*reflex.y ; reflex = reflex.unit()*(v1/(2*kbill->actualconfig.decel)); reflex = reflex*2 ; //approximate //v1 = v2*(sqrt(1 - cos*cos)/cos) ; //v1 = sqrt(power2*power2 - v2*v2) ; //v1 = power2 - v2 ; //reflex = reflex.unit()*((v1*v1)/(2*kbill->actualconfig.decel)); //reflex = reflex.unit()*((v1/v2)*(to_hole.abs())); } else reflex.null() ; /* cout<<"kbill->MaxThrowPower="<<(kbill->MaxThrowPower)<<" MaxDist="<<(((kbill->MaxThrowPower)*(kbill->MaxThrowPower))/(2*kbill->actualconfig.decel))<vect_Pos - kbill->whiteball->vect_Pos ; // add an error err_vect.set((trajectory.unit()).y,-((trajectory.unit()).x),0.0); err_vect = err_vect*(curr_error - error_factor/2);// -error_val/2 <= curr_error <= +error_val/2 trajectory= trajectory + err_vect; power = kbill->MaxThrowPower ; trajectory = trajectory.unit() * power ; } else { //power=ceil(power); if ( power > kbill->MaxThrowPower ) { power = kbill->MaxThrowPower; //cout<<"too power"<whiteball->vect_Pos, kbill->whiteball->vect_Pos + trajectory, QColor(255,0,0) ); drawLine(2,nextBallseq->vect_Pos, nextBallseq->vect_Pos + to_hole, QColor(255,0,0) ); drawLine(3,kbill->whiteball->vect_Pos + trajectory, kbill->whiteball->vect_Pos + trajectory + reflex, QColor(0,0,255) ); //******end DEBUG******* // add an error err_vect.set((trajectory.unit()).y,-((trajectory.unit()).x),0.0); err_vect = err_vect*(curr_error - error_factor/2);// -error_val/2 <= curr_error <= +error_val/2 trajectory= trajectory + err_vect; trajectory = trajectory.unit() * power ; } kbill->Music->OneShot("shot"); kbill->whiteball->setVelocity(trajectory.x,trajectory.y); } /*! \fn AIplayer::isPathFree() */ bool AIplayer::isPathFree(Ball *from,Ball *exclude,samuele::Vector v) { Ball *k; QList clone ; double diameter; samuele::Vector a,j; bool ret_value=true; a=from->vect_Pos ; diameter= Ball_Physics::diameter ; clone=kbill->ingameballs; //cout<<"-isPathFree-"<ballnumber != 0)) { j=k->vect_Pos; if ( ( (fabs(v.y*j.x - v.x*j.y + (v.x*a.y - v.y*a.x))/v.abs() < diameter) && (0 < (v.x*j.x + v.y*j.y - v.x*a.x - v.y*a.y)) && ( (v.x*j.x + v.y*j.y - v.x*a.x - v.y*a.y) < (v.x*v.x + v.y*v.y)) ) || ( (a - j).abs() < diameter ) || ( (a + v - j).abs() < diameter ) ) { //cout<<" si scontra con la "<ballnumber< 0 )&&( y2 > 0 ) ) { line->setPen( QPen( color, 1, Qt::DotLine ) ); line->setPoints(x1,y1,x2,y2); line->setZ(1); line->show(); } else { line->hide(); } } /*! \fn AIplayer::slotShowTrajectory(bool flag) */ void AIplayer::slotShowTrajectory(bool flag) { show_trajectory = flag; if ( !show_trajectory ) hideTrajectories() ; } /*! \fn AIplayer::hideTrajectories() */ void AIplayer::hideTrajectories() { line1->hide(); line2->hide(); line3->hide(); } #include "aiplayer.moc"