1 /* $Id: ComTrainingPenAttack.cpp,v 1.12 2003/07/13 15:29:43 nan Exp $ */
2 
3 // Copyright (C) 2000, 2003  $B?@Fn(B $B5H9((B(Kanna Yoshihiro)
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 
19 #include "ttinc.h"
20 #include "ComTrainingPenAttack.h"
21 #include "Ball.h"
22 #include "Player.h"
23 #include "Control.h"
24 #include "PlayGame.h"
25 #include "Training.h"
26 
27 extern Ball   theBall;
28 
ComTrainingPenAttack()29 ComTrainingPenAttack::ComTrainingPenAttack() : ComPenAttack() {
30 }
31 
ComTrainingPenAttack(long side)32 ComTrainingPenAttack::ComTrainingPenAttack(long side) :
33   ComPenAttack(side) {
34 }
35 
ComTrainingPenAttack(long playerType,long side,double x,double y,double z,double vx,double vy,double vz,long status,long swing,long swingType,bool swingSide,long afterSwing,long swingError,double targetX,double targetY,double eyeX,double eyeY,double eyeZ,long pow,double spin,double stamina,long statusMax)36 ComTrainingPenAttack::ComTrainingPenAttack( long playerType, long side,
37 					    double x, double y, double z,
38 					    double vx, double vy, double vz,
39 					    long status, long swing,
40 					    long swingType, bool swingSide,
41 					    long afterSwing, long swingError,
42 					    double targetX, double targetY,
43 					    double eyeX, double eyeY,
44 					    double eyeZ,
45 					    long pow, double spin,
46 					    double stamina, long statusMax ) :
47   ComPenAttack( playerType, side, x, y, z, vx, vy, vz, status, swing,
48 		swingType, swingSide, afterSwing, swingError, targetX, targetY,
49 		eyeX, eyeY, eyeZ, pow, spin, stamina, statusMax ) {
50 }
51 
~ComTrainingPenAttack()52 ComTrainingPenAttack::~ComTrainingPenAttack() {
53 }
54 
55 bool
Think()56 ComTrainingPenAttack::Think() {
57   double hitTX, hitTY;	// estimation time until ball reaches _hitX, _hitY
58   double mx;
59 
60   // If the ball status changes, change _hitX, _hitY
61   if ( _prevBallstatus != theBall.GetStatus() && m_swing == 0 ){
62     Hitarea( _hitX, _hitY );
63 
64     _prevBallstatus = theBall.GetStatus();
65   }
66 
67   if ( theBall.GetVX() != 0.0 )
68     hitTX = (_hitX - theBall.GetX())/theBall.GetVX();
69   else
70     hitTX = -1.0;
71 
72   if ( theBall.GetVY() != 0.0 )
73     hitTY = (_hitY - theBall.GetY())/theBall.GetVY();
74   else
75     hitTY = -1.0;
76 
77   if ( fabs( _hitX-(m_x+m_side*0.3) ) < fabs( _hitX-(m_x-m_side*0.3) ) ||
78        theBall.GetStatus() == 8 || _hitX*m_side > 0 )
79     mx = m_x+m_side*0.3;
80   else
81     mx = m_x-m_side*0.3;
82 
83   if ( hitTX > 0.0 ) {
84     if ( m_vx > 0 && mx + m_vx*hitTX < _hitX )
85       m_vx += 0.1;
86     else if ( m_vx < 0 && mx + m_vx*hitTX > _hitX )
87       m_vx -= 0.1;
88     else if ( m_vx*fabs(m_vx*0.1)/2 < _hitX - mx )
89       m_vx += 0.1;
90     else
91       m_vx -= 0.1;
92   } else {
93     if ( m_vx*fabs(m_vx*0.1)/2 < _hitX - mx )
94       m_vx += 0.1;
95     else
96       m_vx -= 0.1;
97   }
98 
99   if ( hitTY > 0.0 ) {
100     if ( m_vy > 0 && m_y + m_vy*hitTY < _hitY )
101       m_vy += 0.1;
102     else if ( m_vy < 0 && m_y + m_vy*hitTY > _hitY )
103       m_vy -= 0.1;
104     else if ( m_vy*fabs(m_vy*0.1)/2 < _hitY - m_y )
105       m_vy += 0.1;
106     else
107       m_vy -= 0.1;
108   } else {
109     if ( m_vy*fabs(m_vy*0.1)/2 < _hitY - m_y )
110       m_vy += 0.1;
111     else
112       m_vy -= 0.1;
113   }
114 
115   if ( m_vx > 5.0 )
116     m_vx = 5.0;
117   else if ( m_vx < -5.0 )
118     m_vx = -5.0;
119   if ( m_vy > 5.0 )
120     m_vy = 5.0;
121   else if ( m_vy < -5.0 )
122     m_vy = -5.0;
123 
124   // Toss
125   if ( theBall.GetStatus() == 8 &&
126        ((PlayGame *)Control::TheControl())->GetService() == GetSide() &&
127        fabs(m_vx) < 0.1 && fabs(m_vy) < 0.1 &&
128        fabs(m_x+m_side*0.3-_hitX) < 0.1 && fabs(m_y-_hitY) < 0.1 &&
129        m_swing == 0 ){
130     theBall.Toss( this, 2 );
131     StartSwing( 3 );
132     m_targetY = TABLELENGTH/8*m_side;
133 
134     return true;
135   }
136 
137   // Calc the ball location of 0.1 second later.
138   // This part seems to be the same as Swing(). Consider again.
139   Ball *tmpBall;
140 
141   tmpBall = new Ball( theBall.GetX(), theBall.GetY(), theBall.GetZ(),
142 		      theBall.GetVX(), theBall.GetVY(), theBall.GetVZ(),
143 		      theBall.GetSpin(), theBall.GetStatus() );
144 
145   for ( int i = 0 ; i < 10 ; i++ )
146     tmpBall->Move();
147 
148   if ( ((tmpBall->GetStatus() == 3 && m_side == 1) ||
149 	(tmpBall->GetStatus() == 1 && m_side == -1)) &&
150        fabs(m_y-tmpBall->GetY()) < 0.1 ){
151     _hitX = tmpBall->GetX();
152     _hitY = tmpBall->GetY();
153 
154     m_targetX = -TABLEWIDTH/5*2*m_side;
155     Swing( 3 );
156   }
157   delete tmpBall;
158 
159   return true;
160 }
161 
162 bool
HitBall()163 ComTrainingPenAttack::HitBall() {
164   double vx, vy, vz;
165   double level;
166 
167   // Serve
168   if ( ( (m_side == 1 && theBall.GetStatus() == 6) ||
169          (m_side ==-1 && theBall.GetStatus() == 7) ) &&
170        fabs( m_x-theBall.GetX() ) < 0.6 && fabs( m_y-theBall.GetY() ) < 0.3 ){
171     PenAttack::HitBall();
172   } else {
173     if ( ((m_side == 1 && theBall.GetStatus() == 3) ||
174 	  (m_side ==-1 && theBall.GetStatus() == 1)) ) {
175       ((Training *)Control::TheControl())->AddTrainingCount();
176 
177       level = 1.0 -
178 	1.0/((double)((Training *)Control::TheControl())->GetTrainingCount()/10.0+1.5);
179       theBall.TargetToV( -TABLEWIDTH/5*m_side, TABLELENGTH/16*4*m_side,
180 			 level, m_spin, vx, vy, vz, 0.1, 20.0 );
181 
182       theBall.Hit( vx, vy, vz, m_spin, this );
183     } else
184       m_swingError = SWING_MISS;
185   }
186 
187   return true;
188 }
189 
190 // Calc hit point
191 // (1) If the ball haven't bound, calc bound point
192 // (2) Calc hit point from current ball location or bound location
193 bool
Hitarea(double & hitX,double & hitY)194 ComTrainingPenAttack::Hitarea( double &hitX, double &hitY ) {
195   Ball *tmpBall;
196 
197   if ( (theBall.GetStatus() == 3 && m_side == 1) ||
198        (theBall.GetStatus() == 2 && m_side == 1) ||
199        (theBall.GetStatus() == 0 && m_side == -1) ||
200        (theBall.GetStatus() == 1 && m_side == -1) ||
201        (theBall.GetStatus() == 4 && m_side == -1) ||
202        (theBall.GetStatus() == 5 && m_side == 1) ) {
203     tmpBall = new Ball( theBall.GetX(), theBall.GetY(), theBall.GetZ(),
204 			theBall.GetVX(), theBall.GetVY(), theBall.GetVZ(),
205 			theBall.GetSpin(), theBall.GetStatus() );
206 
207     while ( tmpBall->GetStatus() != -1 ) {
208       if ( (tmpBall->GetStatus() == 3 && m_side == 1) ||
209 	   (tmpBall->GetStatus() == 1 && m_side == -1) ) {
210 	if ( fabs(tmpBall->GetY()) > TABLELENGTH/2 ) {
211 	  hitX = tmpBall->GetX();
212 	  hitY = tmpBall->GetY();
213 	  break;
214 	}
215       }
216       tmpBall->Move();
217     }
218 
219     delete tmpBall;
220 
221   } else if ( theBall.GetStatus() == 8 ) {
222     if ( ((PlayGame *)Control::TheControl())->GetService() == GetSide() ) {
223     if ( RAND(2) )
224       hitX = m_targetX;
225     else
226       hitX = -m_targetX;
227     } else
228       hitX = 0.0;
229     hitY = -(TABLELENGTH/2+0.2)*m_side;
230   }
231 
232   return true;
233 }
234