PageRenderTime 22ms CodeModel.GetById 11ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/Code/src/com/game/AI/CalculateCirclePathTask.java

https://bitbucket.org/DeveloperUX/behaviortree
Java | 239 lines | 146 code | 36 blank | 57 comment | 29 complexity | e75170f545edf4b8caf5fdcf483cbf33 MD5 | raw file
  1package com.game.AI;
  2
  3import java.util.Iterator;
  4import java.util.Vector;
  5
  6import com.game.Constants;
  7import com.game.Cursor;
  8import com.game.Map;
  9import com.game.Tile;
 10import com.game.Vec2;
 11
 12/**
 13 * Task to calculate a path along the border of the nearest enemy
 14 * army.
 15 * @author Ying
 16 *
 17 */
 18public class CalculateCirclePathTask extends LeafTask 
 19{
 20	/**
 21	 * Max length of the path we want
 22	 */
 23	private static final int pathLen = 10;
 24	
 25	/**
 26	 * Minimum distance at which we attempt to circle
 27	 * TODO: Calculate from map size.
 28	 */
 29	private static final float minDistance = 40;
 30
 31	/**
 32	 * Creates a new instance of the CalculateCirclePathTask class 
 33	 * @param blackboard Reference to the AI Blackboard data
 34	 */
 35	public CalculateCirclePathTask(Blackboard blackboard) 
 36	{
 37		super(blackboard);
 38	}
 39
 40	/**
 41	 * Creates a new instance of the CalculateCirclePathTask class 
 42	 * @param blackboard Reference to the AI Blackboard data
 43	 * @param name Name of the class, used for debugging
 44	 */
 45	public CalculateCirclePathTask(Blackboard blackboard, String name) 
 46	{
 47		super(blackboard, name);
 48	}
 49
 50	/**
 51	 * Confirms the data we need exists and that we are not
 52	 * too far away to circle.
 53	 */
 54	@Override
 55	public boolean CheckConditions()
 56	{
 57		LogTask("Checking conditions");
 58		if(bb.path == null && bb.closestEnemyCursor == null)
 59		{
 60			return false;
 61		}
 62		
 63		float distanceToEnemy = (float) bb.player.GetCursor().GetPosition().GetVectorTo(bb.closestEnemyCursor.GetPosition()).Length();
 64		if(distanceToEnemy > minDistance)
 65		{
 66			return false;
 67		}
 68		
 69		return true;
 70	}
 71
 72	/**
 73	 * Calculates a path of tiles around the enemy army
 74	 * and stores it in the Blackboard
 75	 */
 76	@Override
 77	public void DoAction() 
 78	{
 79		LogTask("Doing action");
 80		
 81		
 82		Cursor chosenEnemy = bb.closestEnemyCursor;
 83		Vec2 lineToEnemy = bb.player.GetCursor().GetPosition().GetVectorTo(chosenEnemy.GetPosition());
 84		
 85		//Log.i("CircleStrategy", "Start: Selected enemy " + chosenEnemy.GetID());
 86		
 87		// Get the last empty tile before the cursor density
 88		Map mapRef = Blackboard.map;
 89		Tile curTile = mapRef.AtWorld(
 90				(int)chosenEnemy.GetPosition().X(), 
 91				(int)chosenEnemy.GetPosition().Y());
 92		
 93		lineToEnemy.Normalize();
 94		lineToEnemy.Scale(Constants.TileWidth);
 95		
 96		// If no starting tile, we're done here.
 97		if(curTile == null)
 98		{
 99			LogTask("Not found initial tile, bailing out");
100			this.control.FinishWithFailure();
101			return;
102		}
103		
104		//curTile.GetPos().Print("CircleStrategy", "Start: Enemy cursor closest tile is ");
105		//lineToEnemy.Print("CircleStrategy", "Start: Line to enemy is ");
106		
107		while( curTile != null && curTile.GetMaxCapacity() > 0 && !curTile.HasEnemyDensity(chosenEnemy.GetPlayer().GetID()))
108		{
109			//curTile.GetPos().Print("CircleStrategy", "Start: Checking tile ");
110			
111			int x = (int)Math.round((curTile.GetRealPos().X()-lineToEnemy.X() ));
112			int y = (int)Math.round((curTile.GetRealPos().Y()-lineToEnemy.Y()) );
113			
114			//curTile.GetRealPos().Print("CircleStrategy", "Start: (" + x+", " +y +") Checking tile ");
115			Tile nextTile = mapRef.AtWorld( x , y);
116			
117			// To avoid infinite loops caused by float precision, if we're stuck on the same tile twice
118			// Just jump to the closest in that direction.
119			if(curTile == nextTile)
120			{
121				curTile = mapRef.AtWorld( 
122						(int)(curTile.GetRealPos().X()-(Math.signum(lineToEnemy.X()) * Constants.TileWidth) ) , 
123						(int)(curTile.GetRealPos().Y()-(Math.signum(lineToEnemy.Y()) * Constants.TileWidth) ));
124			}
125			else
126			{
127				curTile = nextTile;
128			}
129					
130		}
131		//Log.i("CircleStrategy", "Start: Finished looking for initial tile");
132		
133		
134		// If no starting tile, we're done here.
135		if(curTile == null)
136		{
137			LogTask("Not found initial tile, bailing out");
138			this.control.FinishWithFailure();
139			return;
140		}	
141		
142		//curTile.GetPos().Print("CircleStrategy", "Start: Initial selected tile is ");
143		
144		// In the direction of the cursor, find the emptiest tile of the surrounding ones		
145		Vector<Tile> path= new Vector<Tile>();
146		path.add(curTile);		
147		//Log.i("CircleStrategy", "Start: Looking for tile path");
148		for(int i = 0; i < pathLen; i++)
149		{		
150			Tile toAdd = null;
151			curTile = mapRef.AtWorld(
152					(int)(path.lastElement().GetRealPos().X()+lineToEnemy.X()), 
153					(int)(path.lastElement().GetRealPos().Y()+lineToEnemy.Y()));
154			
155			for(int j = 0; j < 9; j++)
156			{
157				Tile next = Blackboard.map.GetNeighbour(curTile, j);
158				if(next != null)
159				{
160					if(toAdd == null)
161					{
162						if(next.GetCurrentCapacity() > 0)
163						{
164							if(NotInPath(next,path))
165							{
166								toAdd = next;
167							}
168						}
169					}
170					else
171					{
172						if(next.GetCurrentCapacity() > toAdd.GetCurrentCapacity())
173						{
174							if(NotInPath(next,path))
175							{
176								toAdd = next;
177							}
178						}
179					}
180				}
181			}
182			
183			if(toAdd != null)
184			{
185				//toAdd.GetPos().Print("CircleStrategy", "Start: -- Adding tile ");
186				path.add(toAdd);
187			}
188			else
189			{
190				//Log.i("CircleStrategy", "Start: No more tiles to add. Path ended");
191				break;
192			}
193		}
194		
195		bb.path = path;
196		this.control.FinishWithSuccess();
197		
198	}
199
200	/**
201	 * Ends the task
202	 */
203	@Override
204	public void End() 
205	{
206		LogTask("Ending");
207
208	}
209
210	/**
211	 * Starts the task
212	 */
213	@Override
214	public void Start() 
215	{
216		LogTask("Starting");
217
218	}
219	
220	/**
221	 * Checks if a said tile is not in the path so far
222	 * @param tile Tile to check against.
223	 * @return True if it's not on the path, false if it is
224	 */
225	private boolean NotInPath(Tile tile, Vector<Tile> path)
226	{
227		boolean found = false;
228		for (Iterator<Tile> iterator = path.iterator(); iterator.hasNext();) 
229		{
230			if(tile == (Tile) iterator.next())
231			{
232				found = true;
233				break;
234			}			
235		}
236		
237		return !found;
238	}
239}