| Grid.java |
1 import java.util.*;
2 import java.awt.*;
3 import java.awt.event.*;
4 import java.applet.*;
5 import java.awt.geom.*;
6 import java.awt.image.*;
7
8 /**
9 * Class for displaying the map and handling the Player Movements. Fires Events for
10 * battles and redirects
11 *
12 * @see Player
13 * @see People
14 * @see MapObject
15 * @see Redirect
16 * @see RedirectEvent
17 * @see Game
18 * @see BattleEvent
19 */
20 public class Grid extends Panel
21 {
22 /**
23 * The default number of Rows/COlumns
24 */
25 public static final int DEFAULTNUM = 16;
26
27 /**
28 * Left direction
29 */
30 public static final int LEFT = 0;
31 /**
32 * Right direction
33 */
34 public static final int RIGHT = 1;
35 /**
36 * Up direction
37 */
38 public static final int UP = 2;
39 /**
40 * Down direction
41 */
42 public static final int DOWN = 3;
43
44 /**
45 * The number of rows
46 */
47 protected int numi; // Num Rows
48 /**
49 * The number of columns
50 */
51 protected int numj; // Num Columns
52
53 /**
54 * The position of the player, the row/i
55 */
56 protected int pi; // Player position i
57 /**
58 * The position of the player, the column/j
59 */
60 protected int pj; // Player position j
61
62 /**
63 * The BattleListeners
64 */
65 private Vector battleListeners;
66 /**
67 * The RedirectEventListeners
68 */
69 private Vector redirectListeners;
70
71 /**
72 * This
73 */
74 MapObject mp[][];
75 /**
76 * Default backdrop
77 */
78 MapObject def;
79 /**
80 * The Monsters allowed on this
81 */
82 Vector monAllow;
83 /**
84 * The Monster level for wild Monsters
85 */
86 int monsterLevel;
87 /**
88 * is there a battle
89 */
90 boolean battle;
91
92 /**
93 * Needed for calls to paintAll
94 */
95 Graphics g; // Needed for call to repaint
96
97 /**
98 * Construct a new Grid of size Grid.DEFAULTNUM
99 */
100 public Grid()
101 {
102 mp = new MapObject[DEFAULTNUM][DEFAULTNUM];
103 numi = DEFAULTNUM;
104 numj = DEFAULTNUM;
105 monAllow = new Vector();
106 monsterLevel = 10;
107 setLayout(new GridLayout(numi, numj, 0, 0));
108 battle = false;
109 enableEvents( AWTEvent.KEY_EVENT_MASK);
110 }
111
112 /**
113 * Gets the number of rows.
114 *
115 * @return the Number of rows
116 */
117 public int getNumRows() { return numi; }
118 /**
119 * Gets the number of columns
120 *
121 * @return the number of columns
122 */
123 public int getNumColumns() { return numj; }
124
125 /**
126 * Determines if the Location specified is a valid on this.
127 *
128 * @param i the row
129 * @param j the column
130 * @return true iff i & j are in this ie less than Grid.DEFAULTNUM, and greater than 0
131 */
132 public synchronized boolean isValidLocation(int i, int j)
133 {
134 if(i >= 0 && i < numi && j >= 0 && j < numj)
135 return true;
136 return false;
137 }
138
139 /**
140 * Determines if the Location specified can be moved into
141 *
142 * @param i the row
143 * @param j the column
144 * @return truee iff can be moved into, ie if isValidLocation, and canBeEntered
145 * @see MapObject
146 * @see Grass
147 * @see Floor
148 */
149 public synchronized boolean canMove(int i, int j)
150 {
151 if(!isValidLocation(i, j))
152 return false;
153 if(mp[i][j] == null)
154 return true;
155 return mp[i][j].canBeEntered();
156 }
157 /**
158 * Sets the default backdrop to display.
159 *
160 * @param m the MapObject to have as the backdrop
161 */
162 public synchronized void setDefault(MapObject m)
163 {
164 if(m == null)
165 return;
166 if(m.canBeEntered())
167 {
168 this.def = m;
169 }
170 }
171 /**
172 * Returns the preferred size of this.
173 * Needs be larger or equal to the size of the Applet
174 *
175 * @return the Dimension of this
176 * @see Game
177 */
178 public Dimension getPerferredSize()
179 {
180 return new Dimension(640, 480);
181 }
182 /**
183 * Sets the Player of this.
184 *
185 * @param p the new Player of this
186 */
187 public synchronized void setPlayer(Player p)
188 {
189 if(p != null)
190 {
191 try
192 {
193 removeObject(pi, pj);
194 setObjectAt(p, pi, pj);
195 }
196 catch(Exception e) { }
197 }
198 }
199 /**
200 * Sets the object at the Location specified
201 *
202 * @param mp the MapObject to set at i, j
203 * @param i the row
204 * @param j the column
205 * @exception InvalidLocationException iff !isValidException(i, j)
206 * @exception NonEmptyException iff !canMove(i, j)
207 */
208 public synchronized void setObjectAt(MapObject mp, int i, int j) throws InvalidLocationException, NonEmptyException
209 {
210 if(isValidLocation(i, j))
211 {
212 if(canMove(i, j))
213 {
214 try
215 {
216 remove(this.mp[i][j]);
217 }
218 catch(Exception e) { }
219 this.mp[i][j] = mp;
220 add(this.mp[i][j], numi*i+j);
221 if(mp.getType() == MapObject.PLAYER)
222 {
223 pi = i; pj = j;
224 }
225 }
226 else
227 throw new NonEmptyException("(" + i + "," + j + ") cannot be moved into");
228 }
229 else
230 throw new InvalidLocationException("Invalid Location (" + i + "," + j + ")");
231 }
232 /**
233 * Removes and returns the MapObject at the specified Location
234 *
235 * @param i the row
236 * @param j the column
237 * @exception InvalidLocationException iff !isValidException(i, j)
238 */
239 public synchronized MapObject removeObject(int i, int j) throws InvalidLocationException
240 {
241 if(isValidLocation(i, j))
242 {
243 remove(mp[i][j]);
244 MapObject mo = mp[i][j];
245 mp[i][j] = def.getClone();
246 add(mp[i][j], numi*i+j);
247 return mo;
248 }
249 else
250 throw new InvalidLocationException("Invalid Location (" + i + "," + j + ")");
251 }
252 /**
253 * Remove All Objects from the Grid.
254 */
255 public synchronized void removeAllObjects()
256 {
257 Player player = (Player)mp[pi][pj];
258 for(int i = 0; i < numi; i++)
259 {
260 for(int j = 0; j < numj; j++)
261 {
262 mp[i][j] = def.getClone();
263 }
264 }
265 mp[0][0] = player;
266 }
267
268 /**
269 * Gets the MapObject at i, j.
270 *
271 * @param i the row
272 * @param j the columne
273 * @exception InvalidLocationException iff !isValidException(i, j)
274 * @exception EmptyLocationException if the Location only contains the default MapObject
275 */
276 public synchronized MapObject mapObjectAt(int i, int j) throws EmptyLocationException, InvalidLocationException
277 {
278 if(battle)
279 return null;
280 if(isValidLocation(i, j))
281 {
282 if( !(mp[i][j].canBeEntered()) )
283 {
284 return mp[i][j];
285 }
286 else
287 {
288 throw new EmptyLocationException("("+ i + "," + j + " contains no usable Object");
289 }
290 }
291 else
292 throw new InvalidLocationException("("+ i + "," + j + " is not a valid location");
293 }
294
295 /**
296 * Gets the Location of the specified MapObject, uses equals(Object o).
297 * Has a O(n*n) run time.
298 *
299 * @param mp the MapObject to search for.
300 */
301 public Location locationOf(MapObject mp) throws InvalidLocationException
302 {
303 for(int i = 0; i < numi; i++)
304 {
305 for(int j = 0; j < numj; j++)
306 {
307 if(this.mp[i][j] == mp)
308 return new Location(i, j);
309 }
310 }
311 throw new InvalidLocationException("MapObject not found on Grid");
312 }
313 /**
314 * Returns the MapObject in the direction specified within the distance specified from the i, j specified.
315 *
316 * @param i the row
317 * @param j the column
318 * @param dir the direction as specified above
319 * @param distance the distance to look
320 * @exception InvalidLocationException iff !isValidException(i, j)
321 */
322 public synchronized MapObject isPeopleInDirection(int i, int j, int dir, int distance) throws InvalidLocationException
323 {
324 if(battle)
325 return null;
326 if(isValidLocation(i, j))
327 {
328 int d = 1;
329 if(dir == LEFT)
330 {
331 for(--j; j < numj && d <= distance && j >= 0; j--, d++)
332 {
333 if(mp[i][j].getType() == MapObject.PLAYER || mp[i][j].getType() == MapObject.PERSON)
334 {
335 return mp[i][j];
336 }
337 else if(!(mp[i][j].canBeEntered())) // can't see over rocks, etc
338 {
339 return null;
340 }
341 }
342 }
343 else if(dir == RIGHT)
344 {
345 for(++j; j < numj && d <= distance && j >=0; j++, d++)
346 {
347 if(mp[i][j].getType() == MapObject.PLAYER || mp[i][j].getType() == MapObject.PERSON)
348 {
349 return mp[i][j];
350 }
351 else if(!(mp[i][j].canBeEntered())) // can't see over rocks, etc
352 {
353 return null;
354 }
355 }
356 }
357 else if(dir == UP)
358 {
359 for(--i; i < numi && d <= distance && i >= 0; i--, d++)
360 {
361 if(mp[i][j].getType() == MapObject.PLAYER || mp[i][j].getType() == MapObject.PERSON)
362 {
363 return mp[i][j];
364 }
365 else if(!(mp[i][j].canBeEntered())) // can't see over rocks, etc
366 {
367 return null;
368 }
369 }
370 }
371 else if(dir == DOWN)
372 {
373 for(++i; i < numi && d <= distance && i >= 0; i++, d++)
374 {
375 if(mp[i][j].getType() == MapObject.PLAYER || mp[i][j].getType() == MapObject.PERSON)
376 {
377 return mp[i][j];
378 }
379 else if(!(mp[i][j].canBeEntered())) // can't see over rocks, etc
380 {
381 return null;
382 }
383 }
384 }
385 return null;
386 }
387 else
388 throw new InvalidLocationException("("+ i + "," + j + " is not a valid location");
389 }
390 /**
391 * Gets the Player of this.
392 *
393 * @return the Player of this
394 */
395 public synchronized Player getPlayer() { return (Player)mp[pi][pj]; }
396 /**
397 * Moves the Player in the direction specified
398 *
399 * @param direction the direction to move the player, as specified above
400 */
401 public synchronized void movePlayerTo(int direction) throws NonEmptyException, InvalidLocationException
402 {
403 battle = false;
404 switch(direction)
405 {
406 case LEFT:
407 {
408 if(pj-1 >= 0)
409 {
410 if(mp[pi][pj-1].getType() == MapObject.REDIRECT)
411 {
412 if(((Player)mp[pi][pj]).getBadgeCount() >= ((Redirect)mp[pi][pj-1]).getNumberBadgesRequired())
413 fireRedirectEvent((Redirect)mp[pi][pj-1]);
414 return;
415 }
416 else if(!canMove(pi, pj-1))
417 return;
418 Player player = (Player)removeObject(pi, pj);
419 pj--;
420 if(mp[pi][pj].getType() == MapObject.MONSTER)
421 {
422 Monster m = (Monster)removeObject(pi, pj);
423 setObjectAt(player, pi, pj);
424 beginBattleWithPlayer(m);
425 }
426 else
427 {
428 setObjectAt(player, pi, pj);
429 }
430 }
431 else
432 throw new NonEmptyException("(" + (pi-1) + "," + pj + ") is cannot be moved into");
433 break;
434 }
435 case RIGHT:
436 {
437 if(pj+1 < numj)
438 {
439 if(mp[pi][pj+1].getType() == MapObject.REDIRECT)
440 {
441 if(((Player)mp[pi][pj]).getBadgeCount() >= ((Redirect)mp[pi][pj+1]).getNumberBadgesRequired())
442 fireRedirectEvent((Redirect)mp[pi][pj+1]);
443 return;
444 }
445 else if(!canMove(pi, pj+1))
446 return;
447 Player player = (Player)removeObject(pi, pj);
448 pj++;
449 if(mp[pi][pj].getType() == MapObject.MONSTER)
450 {
451 Monster m = (Monster)removeObject(pi, pj);
452 setObjectAt(player, pi, pj);
453 beginBattleWithPlayer(m);
454 }
455 else
456 {
457 setObjectAt(player, pi, pj);
458 }
459 }
460 else
461 throw new NonEmptyException("(" + (pi+1) + "," + pj + ") is cannot be moved into");
462 break;
463 }
464 case UP:
465 {
466 if(pi-1 >= 0)
467 {
468 if(mp[pi-1][pj].getType() == MapObject.REDIRECT)
469 {
470 if(((Player)mp[pi][pj]).getBadgeCount() >= ((Redirect)mp[pi-1][pj]).getNumberBadgesRequired())
471 fireRedirectEvent((Redirect)mp[pi-1][pj]);
472 return;
473 }
474 else if(!canMove(pi-1, pj))
475 return;
476 Player player = (Player)removeObject(pi, pj);
477 pi--;
478 if(mp[pi][pj].getType() == MapObject.MONSTER)
479 {
480 Monster m = (Monster)removeObject(pi, pj);
481 setObjectAt(player, pi, pj);
482 beginBattleWithPlayer(m);
483 }
484 else
485 {
486 setObjectAt(player, pi, pj);
487 }
488 }
489 else
490 throw new NonEmptyException("(" + pi + "," + (pj-1) + ") is cannot be moved into");
491 break;
492 }
493 case DOWN:
494 {
495 if(pi+1 < numj)
496 {
497 if(mp[pi+1][pj].getType() == MapObject.REDIRECT)
498 {
499 if(((Player)mp[pi][pj]).getBadgeCount() >= ((Redirect)mp[pi+1][pj]).getNumberBadgesRequired())
500 fireRedirectEvent((Redirect)mp[pi+1][pj]);
501 return;
502 }
503 else if(!canMove(pi+1, pj))
504 return;
505 Player player = (Player)removeObject(pi, pj);
506 pi++;
507 if(mp[pi][pj].getType() == MapObject.MONSTER)
508 {
509 Monster m = (Monster)removeObject(pi, pj);
510 setObjectAt(player, pi, pj);
511 beginBattleWithPlayer(m);
512 }
513 else
514 {
515 setObjectAt(player, pi, pj);
516 }
517 }
518 else
519 throw new NonEmptyException("(" + pi + "," + (pj+1) + ") is cannot be moved into");
520 break;
521 }
522 }
523 }
524
525 /**
526 * Moves the MapObject at i, j to ni, nj.
527 *
528 * @param i the row originally at
529 * @param j the column origanally at
530 * @param ni the new row
531 * @param nj the new column
532 * @exception InvalidLocationException iff !isValidException(i, j)
533 * @exception NonEmptyException iff !canMove(i, j)
534 * @exception EmptyLocationException Will Not Be Thrown.
535 */
536 public synchronized void moveMapObjectTo(int i, int j, int ni, int nj) throws NonEmptyException, InvalidLocationException, EmptyLocationException
537 {
538 if(battle)
539 return;
540 if(isValidLocation(i, j))
541 {
542 if(isValidLocation(ni, nj))
543 {
544 if(canMove(ni, nj))
545 {
546 MapObject mp = removeObject(i, j);
547 if(mp.getType() == MapObject.PERSON)
548 setObjectAt(mp, ni, nj);
549 }
550 else
551 throw new NonEmptyException("(" + (i) + "," + j + ") is cannot be moved into");
552 }
553 }
554 else
555 throw new InvalidLocationException("(" + i + "," + j + ") is not a valid location");
556 }
557 /**
558 * Handle the Events. Overriden to handle the KeyEvents.
559 *
560 * @param e the AWTEvent to process
561 */
562 public synchronized void processEvent(AWTEvent e)
563 {
564 if(e.getID() == KeyEvent.KEY_PRESSED)
565 {
566 int ti = pi, tj = pj;
567 try
568 {
569 switch(((KeyEvent)e).getKeyCode())
570 {
571 case KeyEvent.VK_LEFT:
572 {
573 movePlayerTo(LEFT);
574 ((Player)mp[pi][pj]).setDirection(LEFT);
575 //((Player)mp[pi][pj]).stopBattle();
576 break;
577 }
578 case KeyEvent.VK_RIGHT:
579 {
580 movePlayerTo(RIGHT);
581 ((Player)mp[pi][pj]).setDirection(RIGHT);
582 //((Player)mp[pi][pj]).stopBattle();
583 break;
584 }
585 case KeyEvent.VK_UP:
586 {
587 movePlayerTo(UP);
588 ((Player)mp[pi][pj]).setDirection(UP);
589 //((Player)mp[pi][pj]).stopBattle();
590 break;
591 }
592 case KeyEvent.VK_DOWN:
593 {
594 movePlayerTo(DOWN);
595 ((Player)mp[pi][pj]).setDirection(DOWN);
596 //((Player)mp[pi][pj]).stopBattle();
597 break;
598 }
599 }
600 repaint(ti, tj);
601 repaint(pi, pj);
602 }
603 catch (Exception ile) { }
604 }
605 super.processEvent(e);
606 }
607 /**
608 * Allow wild Monsters of type m on this.
609 *
610 * @param m the Monster.<type> to allow
611 */
612 public void allowMonsterOnMap(int m)
613 {
614 if(m == Monster.ELECTRIC || m == Monster.EARTH || m == Monster.FIRE || m == Monster.WATER || m == Monster.GAS)
615 monAllow.add(new Integer(m));
616 }
617 /**
618 * Sets the wild Monsters level for this
619 *
620 * @param l the level of the wild Monsters
621 */
622 public void setMonsterLevel(int l)
623 {
624 if(l > 1 && l < Monster.MAXLEVEL)
625 monsterLevel = l;
626 }
627 /**
628 * Fills the Grid in a standard manner, useful for debugging.
629 */
630 public void fillGrid() // Temporary until MAP implemented
631 {
632 battle = false;
633 int wi, hi;
634 wi = getWidth()/numj;
635 hi = getHeight()/numi;
636 def = new Grass();
637
638 for(int i = 0; i < numi; i++)
639 {
640 for(int j = 0; j < numj; j++)
641 {
642 if(mp[i][j] == null)
643 {
644 if(i%5 == j%10)
645 mp[i][j] = new Rock();
646 else
647 mp[i][j] = def.getClone();
648 add(mp[i][j]);
649 }
650 }
651 }
652 try
653 {
654 removeObject(0, 0);
655 People pl = new Player();
656 setObjectAt(pl, 0, 0);
657 pi = 0; pj = 0;
658
659 removeObject(15, 15);
660 pl = new Person(DOWN);
661 setObjectAt(pl, 15, 15);
662 ((Person)pl).setGrid(this);
663
664 removeObject(numi/2,numj/2);
665 pl = new Person(LEFT);
666 setObjectAt(pl, numi/2, numj/2);
667 ((Person)pl).setGrid(this);
668
669 removeObject(numi/4,numj/4);
670 pl = new Person(LEFT);
671 setObjectAt(pl, numi/4, numj/4);
672 ((Person)pl).setGrid(this);
673
674 removeObject(numi/5,numj/5);
675 pl = new Person(LEFT);
676 setObjectAt(pl, numi/5, numj/5);
677 ((Person)pl).setGrid(this);
678
679 removeObject(numi/6,numj/6);
680 pl = new Person(LEFT);
681 setObjectAt(pl, numi/5, numj/5);
682 ((Person)pl).setGrid(this);
683 }
684 catch(Exception e) { }
685 }
686 /**
687 * Initialize the Grid, ie start the Peopl Moving, and fill this
688 * with wild Monsters
689 */
690 public void init()
691 {
692 battle = false;
693 try
694 {
695 Random r = new Random();
696 r.setSeed(System.currentTimeMillis());
697 for(int i = 0; i < DEFAULTNUM; i++)
698 {
699 for(int j = 0; j < DEFAULTNUM; j++)
700 {
701 if(mp[i][j].getType() == MapObject.PERSON)
702 {
703 ((Person)mp[i][j]).setGrid(this);
704 }
705 else if(mp[i][j].getType() == MapObject.TRAINER)
706 {
707 ((Trainer)mp[i][j]).setGrid(this);
708 }
709 else if(mp[i][j].getType() == MapObject.MONSTER)
710 {
711 removeObject(i, j);
712 }
713 }
714 }
715 if(monAllow.size() <= 0)
716 return;
717
718 // Adding 10 Monsters Randomly distrubuted
719 Monster m;
720 MapObject ma;
721 int lev10, lev7, lev6;
722 lev10 = monsterLevel*10;
723 lev7 = monsterLevel*7;
724 lev6 = monsterLevel*6;
725 for(int i = 0, j = 0, s, t, u; i < 10; i++, j=0)
726 {
727 do
728 {
729 j++;
730 s = r.nextInt(DEFAULTNUM);
731 t = r.nextInt(DEFAULTNUM);
732 } while( !(mp[s][t].canBeEntered()) && j < 5 );
733 removeObject(s, t);
734 ma = def.getClone();
735 u = r.nextInt(monAllow.size());
736 switch(((Integer)monAllow.get(u)).intValue())
737 {
738 case Monster.FIRE:
739 {
740 m = new FireMon((s%2 == 0 ? "MoPyro" : "Flamesaur"));
741 m.setBehind(ma);
742
743 m.setLevel(monsterLevel);
744 m.setMaxHP(lev10);
745 m.setHP(lev10);
746 m.setDefense(lev7);
747 m.setMaxDefense(lev7);
748 m.setAttack(lev6);
749 m.setMaxAttack(lev6);
750 m.setMaxExperience(lev10);
751 m.setExperience(Math.abs(lev10-20));
752
753 if(monsterLevel > 30)
754 m.addAttack(FireMon.A3);
755 if(monsterLevel >= 40)
756 m.addAttack(FireMon.A4);
757
758 setObjectAt(m,s, t);
759 break;
760 }
761 case Monster.WATER:
762 {
763 m = new WaterMon((s%2 == 0 ? "Alligatrix" : "Sharkasaur"));
764 m.setBehind(ma);
765
766 m.setLevel(monsterLevel);
767 m.setMaxHP(lev6);
768 m.setHP(lev6);
769 m.setDefense(lev10);
770 m.setMaxDefense(lev10);
771 m.setAttack(lev7);
772 m.setMaxAttack(lev7);
773 m.setMaxExperience(lev10);
774 m.setExperience(Math.abs(lev10-20));
775
776 if(monsterLevel > 30)
777 m.addAttack(WaterMon.A3);
778 if(monsterLevel >= 40)
779 m.addAttack(WaterMon.A4);
780
781 setObjectAt(m,s, t);
782 break;
783 }
784 case Monster.EARTH:
785 {
786 m = new EarthMon((s%2 == 0 ? "Rhono" : "Groundyx"));
787 m.setBehind(ma);
788
789 m.setLevel(monsterLevel);
790 m.setMaxHP(lev10);
791 m.setHP(lev10);
792 m.setDefense(lev6);
793 m.setMaxDefense(lev6);
794 m.setAttack(lev7);
795 m.setMaxAttack(lev7);
796 m.setMaxExperience(lev10);
797 m.setExperience(Math.abs(lev10-20));
798
799 if(monsterLevel > 30)
800 m.addAttack(EarthMon.A3);
801 if(monsterLevel >= 40)
802 m.addAttack(EarthMon.A4);
803
804 setObjectAt(m,s, t);
805 break;
806 }
807 case Monster.GAS:
808 {
809 m = new GasMon((s%2 == 0 ? "Smelltor" : "Eurekasaur"));
810 m.setBehind(ma);
811
812 m.setLevel(monsterLevel);
813 m.setMaxHP(lev7);
814 m.setHP(lev7);
815 m.setDefense(lev10);
816 m.setMaxDefense(lev10);
817 m.setAttack(lev6);
818 m.setMaxAttack(lev6);
819 m.setMaxExperience(lev10);
820 m.setExperience(Math.abs(lev10-20));
821
822 if(monsterLevel > 30)
823 m.addAttack(GasMon.A3);
824 if(monsterLevel >= 40)
825 m.addAttack(GasMon.A4);
826
827 setObjectAt(m,s, t);
828 break;
829 }
830 case Monster.ELECTRIC:
831 {
832 m = new ElectricMon((s%2 == 0 ? "Shockachu" : "Voltasaur"));
833 m.setBehind(ma);
834
835 m.setLevel(monsterLevel);
836 m.setMaxHP(lev6);
837 m.setHP(lev6);
838 m.setDefense(lev7);
839 m.setMaxDefense(lev7);
840 m.setAttack(lev10);
841 m.setMaxAttack(lev10);
842 m.setMaxExperience(lev10);
843 m.setExperience(Math.abs(lev10-20));
844
845 if(monsterLevel > 30)
846 m.addAttack(ElectricMon.A3);
847 if(monsterLevel >= 40)
848 m.addAttack(ElectricMon.A4);
849
850 setObjectAt(m,s, t);
851 break;
852 }
853 }
854 }
855 }
856 catch(Exception e) { }
857 }
858 /**
859 * Removes the older wild Monsters, and add new ones randomly
860 * from th selection allowed.
861 */
862 public void fillMonsters()
863 {
864 try
865 {
866 for(int i = 0; i < DEFAULTNUM; i++)
867 {
868 for(int j = 0; j < DEFAULTNUM; j++)
869 {
870 if(mp[i][j].getType() == MapObject.MONSTER)
871 {
872 removeObject(i, j);
873 }
874 }
875 }
876 Random r = new Random();
877 r.setSeed(System.currentTimeMillis());
878 battle = false;
879 if(monAllow.size() <= 0)
880 return;
881 // Adding 10 Monsters Randomly distrubuted
882 Monster m;
883 MapObject ma;
884 int lev10, lev7, lev6;
885 lev10 = monsterLevel*10;
886 lev7 = monsterLevel*7;
887 lev6 = monsterLevel*6;
888 for(int i = 0, s, t, u, j = 0; i < 10; i++, j = 0)
889 {
890 do
891 {
892 j++;
893 s = r.nextInt(DEFAULTNUM);
894 t = r.nextInt(DEFAULTNUM);
895 } while( !(mp[s][t].canBeEntered()) && j < 5);
896 removeObject(s, t);
897 ma = def.getClone();
898 u = r.nextInt(monAllow.size());
899 switch(((Integer)monAllow.get(u)).intValue())
900 {
901 case Monster.FIRE:
902 {
903 m = new FireMon((s%2 == 0 ? "MoPyro" : "Flamesaur"));
904 m.setBehind(ma);
905
906 m.setLevel(monsterLevel);
907 m.setMaxHP(lev10);
908 m.setHP(lev10);
909 m.setDefense(lev7);
910 m.setMaxDefense(lev7);
911 m.setAttack(lev6);
912 m.setMaxAttack(lev6);
913 m.setMaxExperience(lev10);
914 m.setExperience(Math.abs(lev10-20));
915
916 if(monsterLevel > 30)
917 m.addAttack(FireMon.A3);
918 if(monsterLevel >= 40)
919 m.addAttack(FireMon.A4);
920
921 setObjectAt(m,s, t);
922 break;
923 }
924 case Monster.WATER:
925 {
926 m = new WaterMon((s%2 == 0 ? "Alligatrix" : "Sharkasaur"));
927 m.setBehind(ma);
928
929 m.setLevel(monsterLevel);
930 m.setMaxHP(lev6);
931 m.setHP(lev6);
932 m.setDefense(lev10);
933 m.setMaxDefense(lev10);
934 m.setAttack(lev7);
935 m.setMaxAttack(lev7);
936 m.setMaxExperience(lev10);
937 m.setExperience(Math.abs(lev10-20));
938
939 if(monsterLevel > 30)
940 m.addAttack(WaterMon.A3);
941 if(monsterLevel >= 40)
942 m.addAttack(WaterMon.A4);
943
944 setObjectAt(m,s, t);
945 break;
946 }
947 case Monster.EARTH:
948 {
949 m = new EarthMon((s%2 == 0 ? "Rhono" : "Groundyx"));
950 m.setBehind(ma);
951
952 m.setLevel(monsterLevel);
953 m.setMaxHP(lev10);
954 m.setHP(lev10);
955 m.setDefense(lev6);
956 m.setMaxDefense(lev6);
957 m.setAttack(lev7);
958 m.setMaxAttack(lev7);
959 m.setMaxExperience(lev10);
960 m.setExperience(Math.abs(lev10-20));
961
962 if(monsterLevel > 30)
963 m.addAttack(EarthMon.A3);
964 if(monsterLevel >= 40)
965 m.addAttack(EarthMon.A4);
966
967 setObjectAt(m,s, t);
968 break;
969 }
970 case Monster.GAS:
971 {
972 m = new GasMon((s%2 == 0 ? "Smelltor" : "Eurekasaur"));
973 m.setBehind(ma);
974
975 m.setLevel(monsterLevel);
976 m.setMaxHP(lev7);
977 m.setHP(lev7);
978 m.setDefense(lev10);
979 m.setMaxDefense(lev10);
980 m.setAttack(lev6);
981 m.setMaxAttack(lev6);
982 m.setMaxExperience(lev10);
983 m.setExperience(Math.abs(lev10-20));
984
985 if(monsterLevel > 30)
986 m.addAttack(GasMon.A3);
987 if(monsterLevel >= 40)
988 m.addAttack(GasMon.A4);
989
990 setObjectAt(m,s, t);
991 break;
992 }
993 case Monster.ELECTRIC:
994 {
995 m = new ElectricMon((s%2 == 0 ? "Shockachu" : "Voltasaur"));
996 m.setBehind(ma);
997
998 m.setLevel(monsterLevel);
999 m.setMaxHP(lev6);
1000 m.setHP(lev6);
1001 m.setDefense(lev7);
1002 m.setMaxDefense(lev7);
1003 m.setAttack(lev10);
1004 m.setMaxAttack(lev10);
1005 m.setMaxExperience(lev10);
1006 m.setExperience(Math.abs(lev10-20));
1007
1008 if(monsterLevel > 30)
1009 m.addAttack(ElectricMon.A3);
1010 if(monsterLevel >= 40)
1011 m.addAttack(ElectricMon.A4);
1012
1013 setObjectAt(m,s, t);
1014 break;
1015 }
1016 }
1017 }
1018 }
1019 catch(Exception e) { }
1020 }
1021 /**
1022 * Destroy all threads tied to this by setting their
1023 * Grid Objects to null.
1024 *
1025 * @see PersonAI
1026 * @see Trainer
1027 */
1028 public void destroy()
1029 {
1030 for(int i = 0; i < DEFAULTNUM; i++)
1031 {
1032 for(int j = 0; j < DEFAULTNUM; j++)
1033 {
1034 if(mp[i][j].getType() == MapObject.PERSON)
1035 {
1036 ((Person)mp[i][j]).setGrid(null); // Kill AI
1037 }
1038 else if(mp[i][j].getType() == MapObject.TRAINER)
1039 {
1040 ((Trainer)mp[i][j]).setGrid(null); // Kill AI
1041 }
1042 mp[i][j] = null; // Kill ME
1043 }
1044 }
1045 }
1046 /**
1047 * Draws the components of this
1048 *
1049 * @param g the Graphics
1050 */
1051 public synchronized void paint(Graphics g)
1052 {
1053 this.g = g;
1054 super.paint(g);
1055 }
1056 /**
1057 * Overriden to rmove the flickering effect
1058 *
1059 * @param g the Graphics
1060 */
1061 public synchronized void update(Graphics g) // Remove Filcker Effect Limits to one the number of enterable MapObjects
1062 {
1063 paint(g);
1064 }
1065 /**
1066 * Repaint the Location specified.
1067 *
1068 * @param i the row
1069 * @param j the column
1070 */
1071 public synchronized void repaint(int i, int j)
1072 {
1073 if(isValidLocation(i, j))
1074 {
1075 int w = getSize().width/numj;
1076 int h = getSize().height/numi;
1077 int x = j*w/numj;
1078 int y = i*h/numi;
1079 g.setClip(x, y, w, h);
1080 paintAll(g);
1081 }
1082 }
1083
1084 /**
1085 * Add a class to be notified of Battles
1086 *
1087 * @param the class to notify
1088 */
1089 public void addBattleListener(BattleListener bl)
1090 {
1091 if ( battleListeners == null )
1092 battleListeners = new Vector();
1093 battleListeners.addElement( bl );
1094 }
1095 /**
1096 * Removes a class that was being notified.
1097 *
1098 * @param the class to stop notifying
1099 */
1100 public void removeBattleListener(BattleListener bl)
1101 {
1102 if ( battleListeners != null )
1103 battleListeners.removeElement( bl );
1104 }
1105 /**
1106 * Fire a BattleEvent, and inform all classes that are listening
1107 *
1108 * @param mp the MapObject of the Players Opponent
1109 */
1110 private synchronized void fireEvent(MapObject mp)
1111 {
1112 if ( battleListeners == null )
1113 return;
1114 BattleEvent event = new BattleEvent(this, BattleEvent.BATTLE_STARTED, this.mp[pi][pj], mp);
1115 for (Enumeration e = battleListeners.elements(); e.hasMoreElements(); )
1116 ((BattleListener)e.nextElement()).battleBegin( event );
1117 }
1118 /**
1119 * Add a class to be notified of Battles
1120 *
1121 * @param the class to notify
1122 */
1123 public void addRedirectListener(RedirectListener r)
1124 {
1125 if ( redirectListeners == null )
1126 redirectListeners = new Vector();
1127 redirectListeners.addElement( r );
1128 }
1129 /**
1130 * Removes a class that was being notified.
1131 *
1132 * @param the class to stop notifying
1133 */
1134 public void removeRedirectListener(RedirectListener r)
1135 {
1136 if ( redirectListeners != null )
1137 redirectListeners.removeElement( r );
1138 }
1139 /**
1140 * Fire a RedirectEvent, and inform all classes that are listening
1141 *
1142 * @param mp the Redirect
1143 * @see Redirect
1144 */
1145 private synchronized void fireRedirectEvent(Redirect mp)
1146 {
1147 synchronized(this.mp[pi][pj])
1148 {
1149 battle = true;
1150 if ( redirectListeners == null )
1151 return;
1152 RedirectEvent event = new RedirectEvent(this, RedirectEvent.REDIRECT_FIRED, mp.getMapTo(), (Player)this.mp[pi][pj]);
1153 for (Enumeration e = redirectListeners.elements(); e.hasMoreElements(); )
1154 ((RedirectListener)e.nextElement()).redirectFired( event );
1155 }
1156 }
1157 /**
1158 * Call to begin a battle with th Player, fires the events.
1159 *
1160 * @param opp the Opponent of the Player.
1161 */
1162 public synchronized void beginBattleWithPlayer(MapObject opp)
1163 {
1164 synchronized(mp[pi][pj]) // Don't let others look at me!
1165 { // They're all gonna laugh at me!!
1166 synchronized(opp)
1167 {
1168 if(((Player)mp[pi][pj]).isBattling())
1169 return;
1170 battle = true;
1171 ((Player)mp[pi][pj]).battle(); // I'll teach them a lesson!
1172 fireEvent(opp); // Let's fight, we'll see whose laughing!
1173 }
1174 }
1175 }
1176}