1   import java.awt.*;
2   import java.applet.*;
3   import javax.swing.*;
4   import java.awt.image.*;
5   import java.awt.geom.*;
6   import java.net.*;
7   import java.util.*;
8   /**
9    * Class used to move a NPC around the Grid.
10   * 
11   * @see People
12   * @see Person
13   * @see Trainer
14   * @see Grid
15   */
16  public class PersonAI implements Runnable
17  {
18      /**
19       * The name of the last person fought
20       */
21      private String lastPerson = "";
22      /**
23       * The grid
24       */
25      private Grid grid;
26      /**
27       * The person moving
28       */
29      private Person p;
30      /**
31       * RNG
32       */
33      private Random r = new Random(System.currentTimeMillis());
34      /**
35       * My Row
36       */
37      private int pi; // ROW
38      /**
39       * My Column
40       */
41      private int pj; // COL
42      /**
43       * The Number of Battles, and th Number of Moves
44       */
45      private int numBattles, numMoves; // Needed to prevent livelock with n-People gathered in a square
46      /**
47       * How far to be able to see in the direction I am facing
48       */
49      protected static final int los = 5;
50      /**
51       * My Thread
52       */
53      private Thread t;
54  
55  
56      /**
57       * Tie this to a Person to control.
58       * 
59       * @param p the Person to control
60       */
61      public PersonAI(Person p)
62      {
63          this.p = p;
64          numBattles = 0;
65          numMoves = 0;
66      }
67  
68      /**
69       * Get the people near my Location, one space any direction.
70       * 
71       * @param i the row
72       * @param j the column
73       */
74      private MapObject[] peopleNextTo(int i, int j)
75      {
76          MapObject mp[] = new MapObject[9], mptemp;
77          int k = 0;
78          for (int x = pi - 1; x <= pi + 1; x++) 
79          {
80              for (int y = pj - 1; y <= pj + 1; y++) 
81              {
82                  if (x != pi || y != pj) 
83                  {
84                      if ( grid.isValidLocation(x, y) )
85                      {
86                          try
87                          {
88                              mptemp = grid.mapObjectAt(x, y);
89                              if(mptemp.getType() == MapObject.PERSON || mptemp.getType() == MapObject.PLAYER)
90                              {
91                                  if( !( ((People)mptemp).getName().equals(p.getName()) ) && !( ((People)mptemp).isBattling() ) )
92                                  {
93                                      mp[k] = mptemp;
94                                      k++;
95                                  }
96                              }
97                          }
98                          catch(InvalidLocationException e) { }
99                          catch(EmptyLocationException e) { } // Normal to have happen
100                     }
101                 }
102             }
103         }
104         if(k != 0)
105             return mp;
106         return null;
107     }
108     /**
109      * Move the Person in the direction specified.
110      * 
111      * @param dir the Direction to move
112      */
113     protected void move(int dir) throws NonEmptyException, InvalidLocationException, EmptyLocationException
114     {
115         numBattles = 0;
116         numMoves++;
117         if(dir == grid.LEFT) // Left
118         {
119             if(grid.canMove(pi, pj-1))
120             {
121                 p.setDirection(grid.LEFT);
122                 grid.moveMapObjectTo(pi, pj, pi, pj-1);
123                 pj--;
124                 return;
125             }
126         } 
127         else if(dir == grid.RIGHT) // Right
128         {
129             if(grid.canMove(pi, pj+1))
130             {
131                 p.setDirection(grid.RIGHT);
132                 grid.moveMapObjectTo(pi, pj, pi, pj+1);
133                 pj++;
134                 return;
135             }
136         }
137         else if(dir == grid.UP) // Up
138         {
139             if(grid.canMove(pi-1, pj))
140             {
141                 p.setDirection(grid.UP);
142                 grid.moveMapObjectTo(pi, pj, pi-1, pj);
143                 pi--;
144                 return;
145             }
146         }
147         else // Down
148         {
149             if(grid.canMove(pi+1, pj))
150             {
151                 p.setDirection(grid.DOWN);
152                 grid.moveMapObjectTo(pi, pj, pi+1, pj);
153                 pi++;
154                 return;
155             }
156         }
157         if(grid.canMove(pi, pj-1) || grid.canMove(pi, pj+1)|| grid.canMove(pi-1, pj) || grid.canMove(pi+1, pj))
158                  move(r.nextInt(4));
159         else
160             return;
161     }
162     /**
163      * Handle the actual Moving, based on a RNG
164      */
165     protected void moveMe()
166     {
167         if(p.isBattling())
168             return;
169         try
170         {
171             MapObject[] mp = peopleNextTo(pi, pj);
172             int dir = r.nextInt(4);
173             boolean b = false;
174             int k = 0;
175             String advis = "";
176             MapObject qr = grid.isPeopleInDirection(pi, pj, p.getDirection(), los);
177 
178             if(mp != null)
179             {
180                 int i = 0;
181                 for(i = 0; i < mp.length && mp[i] != null; i++)
182                 {
183                     advis = ((People)mp[i]).getName();
184                     if(!(advis.equals(lastPerson)) || mp[i].getType() == MapObject.PLAYER)
185                     {
186                         b = true;
187                         break;
188                     }
189                 }
190                 if(b && numBattles == 0 && numMoves >= 4)
191                 {
192                     synchronized(mp[i])
193                     {
194                         numBattles++;
195                         numMoves = 0;
196                         if(((People)mp[i]).isBattling())
197                             return;
198                         p.battle();
199                         if(mp[i].getType() == MapObject.PLAYER)
200                         {
201                             grid.beginBattleWithPlayer(p);
202                             lastPerson = "";
203                         }
204                         else
205                         {
206                             lastPerson = advis;
207                             ((Person)mp[i]).battle();
208                         }
209                         return;
210                     }
211                 }
212             }
213             else if(qr != null)
214             {
215                 if( !( ((People)qr).getName().equals(lastPerson) ) )
216                 {
217                     move(p.getDirection()); // Move toward if not lastPerson
218                     return;
219                 }
220             }
221             move(dir);
222         }
223         catch(Exception e) { }
224     }
225     /**
226      * Set the Grid, set to null to kill the thread.
227      * 
228      * @param the Grid to move on, set to null to kill this thread
229      * @see Grid
230      */
231     public void setGrid(Grid g)
232     {
233         boolean b = false;
234         if(this.grid != null)
235             b = true;
236         this.grid = g;
237         try
238         {
239             Location l = grid.locationOf(p);
240             pi = l.getI();
241             pj = l.getJ();
242             if(!b)
243             {
244                 t = new Thread(this);
245                 t.start();
246             }
247         }
248         catch(Exception e) { }
249     }
250     /**
251      * Move this around the Grid, and sleep a random
252      * amount of time.
253      */
254     public void run()
255     {
256         while(grid != null && !p.isBeaten())
257         {
258             try
259             {
260                 int time = 0;
261                 synchronized(grid)
262                 {
263                     if(!p.isBattling())
264                     {
265                         moveMe();
266                         int count = 0;
267                         do
268                         {
269                             time = (int)(3000.*Math.random());
270                             count++;
271                         } while(time < 1500 && count < 5);
272                         if(count >= 4)
273                             time = 1500;
274                     }
275                     else
276                     {
277                         time = 6000;
278                         p.stopBattle();
279                     }
280                     grid.repaint(pi, pj);
281                 }
282                 Thread.sleep(time); // Wait rand time bt 1.5 and 3 sec exclusive
283             }
284             catch(Exception e) { }
285         }
286     }
287 }