001         package com.croftsoft.apps.mars.ai;
002    
003         import java.io.Serializable;
004         import java.util.*;
005    
006         import com.croftsoft.core.ai.astar.AStar;
007         import com.croftsoft.core.lang.NullArgumentException;
008         import com.croftsoft.core.math.geom.Circle;
009         import com.croftsoft.core.math.geom.Point2DD;
010         import com.croftsoft.core.math.geom.PointXY;
011         import com.croftsoft.core.math.geom.ShapeLib;
012    
013         /*********************************************************************
014         * Default TankOperator implementation.
015         *
016         * @version
017         *   2003-05-10
018         * @since
019         *   2003-03-21
020         * @author
021         *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
022         *********************************************************************/
023    
024         public final class  DefaultTankOperator
025           implements TankOperator, Serializable
026         //////////////////////////////////////////////////////////////////////
027         //////////////////////////////////////////////////////////////////////
028         {
029    
030         private static final long  serialVersionUID = 0L;
031    
032         /** Probability of firing during one second of time. */
033         private static final double  FIRING_PROBABILITY = 1.0;
034    
035         /** Probability of drifting during one second of time. */
036         private static final double  DRIFT_PROBABILITY  = 0.1;
037    
038         private static final int     A_STAR_LOOPS = 100;
039    
040         private static final double  STEP_SIZE = 10.0;
041    
042         private static final int     DIRECTIONS = 8;
043    
044         //
045    
046         private final Point2DD          center;
047    
048         private final Point2DD          destination;
049    
050         private final Random            random;
051    
052         private final AStar             aStar;
053    
054         private final TankCartographer  tankCartographer;
055    
056         private final StateSpaceNode    startStateSpaceNode;
057    
058         //
059    
060         private TankConsole  tankConsole;
061    
062         private PointXY      enemyCenter;
063    
064         //////////////////////////////////////////////////////////////////////
065         //////////////////////////////////////////////////////////////////////
066    
067         public  DefaultTankOperator ( Random  random )
068         //////////////////////////////////////////////////////////////////////
069         {
070           NullArgumentException.check ( this.random = random );
071    
072           center      = new Point2DD ( );
073    
074           destination = new Point2DD ( );
075    
076           tankCartographer = new TankCartographer ( STEP_SIZE, DIRECTIONS );
077    
078           aStar = new AStar ( tankCartographer );
079    
080           startStateSpaceNode = new StateSpaceNode ( );
081         }
082    
083         //////////////////////////////////////////////////////////////////////
084         //////////////////////////////////////////////////////////////////////
085    
086         public void  fire ( )
087         //////////////////////////////////////////////////////////////////////
088         {
089    // do something here
090         }
091    
092         public void  go ( PointXY  destination )
093         //////////////////////////////////////////////////////////////////////
094         {
095    // do something here
096         }
097    
098         public void  setTankConsole ( TankConsole  tankConsole )
099         //////////////////////////////////////////////////////////////////////
100         {
101           NullArgumentException.check ( this.tankConsole = tankConsole );
102    
103           tankCartographer.setTankConsole ( tankConsole );
104         }
105    
106         public void  update ( double  timeDelta )
107         //////////////////////////////////////////////////////////////////////
108         {
109           ShapeLib.getCenter ( tankConsole.getShape ( ), center );
110    
111           enemyCenter = tankConsole.getClosestEnemyTankCenter ( );
112    
113           tankConsole.rotateTurret ( enemyCenter );
114    
115           if ( tankConsole.getAmmo ( ) < 1.0 )
116           {
117             PointXY  ammoDumpCenter
118               = tankConsole.getClosestAmmoDumpCenter ( );
119    
120             if ( ammoDumpCenter != null )
121             {
122               tankConsole.go ( getFirstStep ( ammoDumpCenter ) );
123             }
124    
125             return;
126           }
127    
128           if ( enemyCenter != null )
129           {         
130             tankConsole.go ( getFirstStep ( enemyCenter ) );
131    
132             if ( random.nextDouble ( ) < timeDelta * FIRING_PROBABILITY )
133             {
134               tankConsole.fire ( );
135             }
136    
137             return;
138           }
139    
140           if ( random.nextDouble ( ) < timeDelta * DRIFT_PROBABILITY )
141           {
142             destination.setXY (
143               center.x + 2 * random.nextDouble ( ) - 1,
144               center.y + 2 * random.nextDouble ( ) - 1 );
145             
146             tankConsole.go ( destination );
147           }
148    
149           if ( random.nextDouble ( ) < timeDelta * FIRING_PROBABILITY )
150           {
151             tankConsole.fire ( );
152           }
153         }
154    
155         public Iterator  getPath ( ) { return aStar.getPath ( ); }
156    
157         //////////////////////////////////////////////////////////////////////
158         //////////////////////////////////////////////////////////////////////
159    
160         private PointXY  getFirstStep ( PointXY  destination )
161         //////////////////////////////////////////////////////////////////////
162         {
163           NullArgumentException.check ( destination );
164    
165           startStateSpaceNode.setPointXY ( center );
166    
167           startStateSpaceNode.setHeading ( tankConsole.getBodyHeading ( ) );
168    
169           tankCartographer.setStartStateSpaceNode ( startStateSpaceNode );
170    
171           aStar.reset ( startStateSpaceNode );
172    
173           tankCartographer.setGoalPointXY ( destination );
174    
175           for ( int  i = 0; i < A_STAR_LOOPS; i++ )
176           {
177             if ( !aStar.loop ( ) )
178             {
179               break;
180             }
181           }
182    
183           if ( !aStar.isGoalFound ( ) )
184           {
185             return destination;
186           }
187    
188           StateSpaceNode  stateSpaceNode
189             = ( StateSpaceNode ) aStar.getFirstStep ( );
190    
191           if ( stateSpaceNode == null )
192           {
193             return destination;
194           }
195    
196           return stateSpaceNode.getPointXY ( );
197         }
198    
199         //////////////////////////////////////////////////////////////////////
200         //////////////////////////////////////////////////////////////////////
201         }