39f5d418eebfd07e3673ebe351a9642253f3449f
[applet-bots.git] / src / appletbots / gatherers / Gatherer.java
1 /*
2  * Copyright (c) 2002 Erik Rasmussen - All Rights Reserverd
3  */
4 package appletbots.gatherers;
5
6 import appletbots.CarriableObject;
7 import appletbots.CarrierAgent;
8 import appletbots.CollisionException;
9 import appletbots.WorldObject;
10 import appletbots.geometry.Vector;
11
12 import java.awt.*;
13 import java.util.ArrayList;
14 import java.util.List;
15
16 /**
17  * A gatherer agent chooses the closest visible piece of food
18  * that is currently not being carried by anyone (and is not
19  * already in the agent's home base) and accelerates towards it.
20  * If no "uncarried" food can be found, the agent tries to find
21  * food carried by a member of the opposing team to accelerate
22  * towards.  If no food is visible the agent sets his acceleration
23  * to a random vector to search for food.  When it gets close
24  * enough to pick up a piece of food, it picks it up and carries
25  * it towards its home base corner for 20 time cycles, and drops
26  * it again.  The gatherer must then rest for 10 time cycles
27  * before picking up another piece of food.  During these 10
28  * time cycles, the "exhausted" agent does not accelerate.
29  *
30  * @author Erik Rasmussen
31  */
32 public class Gatherer extends CarrierAgent
33 {
34         /**
35          * Whether or not the agent is on the team with the home base in the
36          * bottom right-hand corner of the world
37          */
38         protected boolean bottomRightTeam;
39         /**
40          * The amount of time the gatherer has been carrying a piece of food
41          */
42         protected int timeCarried;
43         /**
44          * The the amount of time needed to rest
45          */
46         protected int timeToRest;
47         /**
48          * The vector pointing in the direction of the agent's home base
49          */
50         protected Vector towardsHome;
51
52         /**
53          * Constructs a new Gatherer with the given parameters
54          *
55          * @param pickupDistance  The distance from an object the agent must be to
56          *                        pick up the object
57          * @param bottomRightTeam Whether or not this agent is on the team moving
58          *                        food to the bottom right corner of the world
59          * @param size            The agent's radius
60          * @param sight           The distance the agent can see
61          * @param maxSpeed        The maximum speed the agent can travel
62          * @param maxAcceleration The maximum acceleration for this agent
63          */
64         public Gatherer(final int pickupDistance, final boolean bottomRightTeam, final int size, final int sight, final double maxSpeed, final double maxAcceleration)
65         {
66                 super(pickupDistance, size, sight, maxSpeed, maxAcceleration);
67                 this.bottomRightTeam = bottomRightTeam;
68                 if (bottomRightTeam)
69                 {
70                         this.color = Color.cyan;
71                         towardsHome = new Vector(1, 1);
72                         towardsHome = towardsHome.setLength(maxAcceleration);
73                 }
74                 else
75                 {
76                         this.color = Color.pink;
77                         towardsHome = new Vector(-1, -1);
78                         towardsHome = towardsHome.setLength(maxAcceleration);
79                 }
80         }
81
82         /**
83          * Observes the world, and follows the Gatherer Algorithm.
84          */
85         public void observeWorld()
86         {
87                 timeToRest--;
88                 if (hasItems())
89                 {
90                         timeCarried--;
91                         setAcceleration(towardsHome);
92                         if (timeCarried < 0)
93                                 dropFood();
94                 }
95                 else if (timeToRest <= 0)
96                 {
97                         Food food = chooseFood(false);
98                         // if no uncarried food found, search for carried food
99                         if (food == null)
100                                 food = chooseFood(true);
101                         if (food == null)
102                                 setAcceleration(Vector.getRandom(maxAcceleration));
103                         else if (world.getVectorToObject(this, food).getLength() <= getPickUpDistance() &&
104                                  food.getCarriedBy() == null)
105                         {
106                                 pickUp(food);
107                                 setAcceleration(towardsHome);
108                         }
109                         else
110                                 setAcceleration(world.getVectorToObject(this, food));
111                 }
112                 else
113                         setAcceleration(new Vector(0, 0));
114         }
115
116         /**
117          * Selects closest visible food not already in home base
118          *
119          * @param carried Whether or not the food we are looking for is being
120          *                carried
121          * @return The closest visible food not already in home base
122          */
123         protected Food chooseFood(final boolean carried)
124         {
125                 final List seenObjects = world.getSeenObjects(this);
126                 final List foods = new ArrayList();
127                 for (int i = 0; i < seenObjects.size(); i++)
128                 {
129                         final WorldObject object = (WorldObject) seenObjects.get(i);
130                         if (object instanceof Food)
131                         {
132                                 final Food food = (Food) object;
133                                 if ((carried && food.getCarriedBy() != null && ((Gatherer) food.getCarriedBy()).isBottomRightTeam() != bottomRightTeam) ||
134                                     (!carried && food.getCarriedBy() == null && !((GatherersWorld) world).isInHome(object, bottomRightTeam)))
135                                         foods.add(object);
136                         }
137                 }
138                 if (!foods.isEmpty())
139                 {
140                         // choose closest piece of food
141                         double minDistance = Double.MAX_VALUE;
142                         Food closestFood = null;
143                         for (int i = 0; i < foods.size(); i++)
144                         {
145                                 final Food food = (Food) foods.get(i);
146                                 final double distance = world.getVectorToObject(this, food).getLength();
147                                 if (distance < minDistance)
148                                 {
149                                         minDistance = distance;
150                                         closestFood = food;
151                                 }
152                         }
153                         return closestFood;
154                 }
155                 else
156                         return null;
157         }
158
159         /**
160          * Returns the nearest visible gatherer
161          *
162          * @param opponent If true will return nearest visible opponent, otherwise nearest teammate
163          * @return The nearest visible gatherer
164          */
165         protected Gatherer getNearestGatherer(final boolean opponent)
166         {
167                 final List seenObjects = world.getSeenObjects(this);
168                 final List gatherers = new ArrayList();
169                 for (int i = 0; i < seenObjects.size(); i++)
170                 {
171                         final WorldObject object = (WorldObject) seenObjects.get(i);
172                         if (object instanceof Gatherer &&
173                             ((opponent && ((Gatherer) object).bottomRightTeam != bottomRightTeam) ||
174                              (!opponent && ((Gatherer) object).bottomRightTeam == bottomRightTeam)))
175                                 gatherers.add(object);
176                 }
177                 if (!gatherers.isEmpty())
178                 {
179                         // choose nearest opponent
180                         double minDistance = Double.MAX_VALUE;
181                         Gatherer nearestGatherer = null;
182                         for (int i = 0; i < gatherers.size(); i++)
183                         {
184                                 final Gatherer gatherer = (Gatherer) gatherers.get(i);
185                                 final double distance = world.getVectorToObject(this, gatherer).getLength();
186                                 if (distance < minDistance)
187                                 {
188                                         minDistance = distance;
189                                         nearestGatherer = gatherer;
190                                 }
191                         }
192                         return nearestGatherer;
193                 }
194                 else
195                         return null;
196         }
197
198         /**
199          * Returns whether or not the agent is on the team with the home base in
200          * the bottom right-hand corner of the world
201          *
202          * @return Whether or not the agent is on the team with the home base in the
203          *         bottom right-hand corner of the world
204          */
205         public boolean isBottomRightTeam()
206         {
207                 return bottomRightTeam;
208         }
209
210         /**
211          * Attempts to drop any carried food
212          */
213         protected void dropFood()
214         {
215                 if (hasItems())
216                 {
217                         try
218                         {
219                                 drop(getInventory()[0]);
220                                 timeToRest = 10;
221                         }
222                         catch (CollisionException e)
223                         {
224                         }
225                 }
226         }
227
228         /**
229          * Picks up an object
230          *
231          * @param item The object to pick up
232          */
233         protected void pickUp(final CarriableObject item)
234         {
235                 super.pickUp(item);
236                 timeCarried = 20;
237         }
238 }