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    * Defines the battling arena.  Displays the Player and opponents health,
10   * Handles the use of Items, Switches the Active Monster, and if opponent is
11   * a Trainer gives the Player his Badge if Player wins.  The Player recieves
12   * half of the money carried by the opponent and recieves experience propertional
13   * to the level of the opponent's Monster(s).  Displays the dialogue associated with the 
14   * opponent after the conclusion of the battle if Player wins, else Fires a GameOverEvent.
15   * 
16   * @see Monster
17   * @see MapObject
18   * @see People
19   * @see Person
20   * @see Player
21   * @see BattleEndEvent
22   * @see BattleEndListener
23   * @see GameOverEvent
24   * @see GameOverListener
25   * @see ImageMap
26   * @see Item
27   * @author Matt, Sam
28   * @version 5.4.99.123.456
29   */
30  public class Battle extends Component 
31  {
32      /**
33       * The Color used for the Player's Health bar
34       */
35      private static final Color playerHealth = new Color(82, 184, 249);
36      /**
37       * The Color used for the opponents Health bar
38       */
39      private static final Color opponentHealth = new Color(82, 249, 208);
40  
41      /** 
42       * The Player
43       */
44      Player p;
45      /**
46       * The opponent
47       */
48      MapObject opp;
49  
50      /**
51       * The ImageMap of the Monsters of the Game
52       */
53      ImageMap[] pl; // Add Monster Images
54      /**
55       * Location im pl of Player/opponent Active Monster
56       */
57      int actp, actop; // Location in arr of Player/Opponent monster
58  
59      /**
60       * The BattleEndListeners
61       */
62      Vector battleEndListeners;
63      /**
64       * The GameOverListeners
65       */
66      Vector gameOverListeners;
67  
68      /**
69       * If AttackFullException is thrown need
70       * to have the Attack thrown to be abl to add it
71       * if the Player chooses to remove another Attack
72       */
73      Attack a;
74  
75      /**
76       * Default screen, show options
77       */
78      private static final int DEF = 0;
79      /**
80       * Player Attack was selected
81       */
82      private static final int ATTACKS = 1;
83      /**
84       * Player Item was selected
85       */
86      private static final int ITEMS = 2;
87      /**
88       * Change was selected
89       */
90      private static final int CHANGE = 3;
91      /**
92       * Dialogue/Information is being shown
93       */
94      private static final int DIAG = 4;
95      /**
96       * A New Attack is ready to add, but the Monster has too many Attacks
97       */
98      private static final int NEWATT = 5;
99  
100     private static final String[] def = {"Attacks", "Items", "Change", "Run"};
101     /**
102      * Items of the Player
103      */
104     private String[] items;
105     /**
106      * Monsters of the Player
107      */
108     private String[] monsters;
109     /**
110      * Attacks of the Active Monster
111      */
112     private String[] attacks;
113     /**
114      * What is shown now.
115      */
116     private String[] shown;
117 
118     /** 
119      * Width, Height
120      */
121     int w, h;
122     /**
123      * Selected, start-offset, displayed
124      */
125     int sel, start, disp;
126     /**
127      * Player turn over, end the battle, new Attack ready to add
128      */
129     boolean pturn, end, natt;
130 
131     /**
132      * Construct a Battle between Player and the MapObject.
133      * 
134      * @param p the Player to battle with
135      * @param opp the opponent of the Player
136      * @see Player
137      * @see MapObject
138      * @see Trainer
139      * @see People
140      * @see Person
141      */
142     public Battle(Player p, MapObject opp)
143     {
144         this.p = p;
145         this.opp = opp;
146         sel = 0;
147         start = 0;
148         disp = 0;
149         shown = new String[def.length];
150         for(int i = 0; i < def.length; i++)
151             shown[i] = def[i];
152 
153         items = p.getItems();
154         monsters = p.getMonsters();
155         attacks = p.getMonsterAttacks(p.getActiveMonster());
156 
157         pturn = false;
158         end = false;
159 
160         enableEvents( AWTEvent.KEY_EVENT_MASK);
161     }
162     /**
163      * Construct a Battle between Player and the MapObject using images in the ImageMap.
164      * 
165      * @param p the Player to battle with
166      * @param opp the opponent of the Player
167      * @param monsterImageMap the Images (Front and Back) of all the Monsters used
168      * @see Player
169      * @see MapObject
170      * @see Trainer
171      * @see People
172      * @see Person
173      * @see ImageMap
174      */
175     public Battle(Player p, MapObject opp, ImageMap[] monsterImageMap)
176     {
177         this.p = p;
178         this.opp = opp;
179         sel = 0;
180         start = 0;
181         disp = 0;
182         shown = new String[def.length];
183         for(int i = 0; i < def.length; i++)
184             shown[i] = def[i];
185 
186         items = p.getItems();
187         monsters = p.getMonsters();
188         attacks = p.getMonsterAttacks(p.getActiveMonster());
189 
190         pl = monsterImageMap;
191 
192         actp = find(pl, p.getMonster(p.getActiveMonster()).getName(), true);
193         if(opp.getType() == MapObject.PERSON || opp.getType() == MapObject.TRAINER)
194             actop = find(pl, ((People)opp).getMonster(((People)opp).getActiveMonster()).getName(), false);
195         else if(opp.getType() == MapObject.MONSTER)
196             actop = find(pl, ((Monster)opp).getName(), false);
197         if(actp == -1) actp = 0;
198         if(actop == -1) actop = 0;
199 
200         pturn = false;
201         end = false;
202 
203         enableEvents( AWTEvent.KEY_EVENT_MASK);
204     }
205 
206     /**
207      * Process the events passed to this.  Overrides the implementation 
208      * of KeyEvent.KEY_PRESSED, and allows super to handle the rest.
209      * 
210      * @param e the AWTEvent to handle
211      */
212     public void processEvent(AWTEvent e) 
213     {
214         int wi = (int)(w*.4)+2;
215         int hi = (int)(h*.8);
216         int bw = w - wi - 5;
217         int bh = (int)(.7*h - 10);
218 
219         if(e.getID() == KeyEvent.KEY_PRESSED)
220         {
221             switch(((KeyEvent)e).getKeyCode())
222             {
223                 case KeyEvent.VK_UP:
224                 {
225                     if(disp != ITEMS)
226                     {
227                         if(sel > 0)
228                         {
229                             if(shown[sel-1] != null)
230                                 sel--;
231                         }
232                         else
233                         {
234                             if(shown[3] != null)
235                                 sel = 3;
236                         }
237                     }
238                     else
239                     {
240                         if(sel == 0)
241                         {
242                             if(start == 0)
243                             {
244                                 if(shown.length - 4 >= 0)
245                                     start = shown.length-4;
246                                 else
247                                     start = 0;
248                                 sel = shown.length-1-start;
249                             }
250                             else if( (start - 5) >= 0)
251                             {
252                                 start -= 5;
253                                 sel = 0;
254                             }
255                             else
256                             {
257                                 start = 0;
258                                 sel = 0;
259                             }
260                         }
261                         else
262                         {
263                             if(shown[sel-1] != null)
264                                 sel--;
265                         }
266                     }
267                     break;
268                 }
269                 case KeyEvent.VK_DOWN:
270                     {
271                     if(disp != ITEMS)
272                     {
273                         if(sel < 3)
274                         {
275                             if(shown[sel+1] != null)
276                                 sel++;
277                         }
278                         else
279                         {
280                             if(shown[0] != null)
281                                 sel = 0;
282                         }
283                     }
284                     else
285                     {
286                         if((sel+start) == shown.length-1)
287                         {
288                             start = 0;
289                             sel = 0;
290                         }
291                         else if(sel == 3)
292                         {
293                             if((start+4) < shown.length)
294                             {
295                                 start += 4;
296                                 sel = 0;
297                             }
298                             else
299                             {
300                                 start = shown.length-5;
301                                 sel = 0;
302                             }
303                         }
304                         else
305                         {
306                             if(shown[sel+1] != null)
307                                 sel++;
308                         }
309                     }
310                     break;
311                 }
312                 case KeyEvent.VK_ENTER:
313                 case KeyEvent.VK_SPACE:
314                     {
315                     start = 0;
316                     if(disp == DEF)
317                     {
318                         switch(sel)
319                         {
320                             case 0:
321                                 {
322                                 sel = 0;
323                                 for(int i = 0; i < attacks.length; i++)
324                                 {
325                                     shown[i] = attacks[i];
326                                 }
327                                 disp = ATTACKS;
328                                 break;
329                             }
330                             case 1:
331                                 {
332                                 shown = new String[items.length];
333                                 sel = 0;
334                                 for(int i = start; i < items.length; i++)
335                                 {
336                                     if(items[i] != null)
337                                         shown[i] = items[i] + " x " + p.getItemCount(items[i]);
338                                     else
339                                         shown[i] = null;
340                                 }
341                                 disp = ITEMS;
342                                 break;
343                             }
344                             case 2:
345                                 {
346                                 sel = 0;
347                                 for(int i = 0; i < monsters.length; i++)
348                                 {
349                                     shown[i] = monsters[i];
350                                 }
351                                 disp = CHANGE;
352                                 break;
353                             }
354                             case 3:
355                                 {
356                                 if(opp == null)
357                                     fireEvent(p);
358                                 else if(opp.getType() != MapObject.TRAINER)
359                                     fireEvent(p); // End Battle
360                                 else
361                                 {
362                                     shown[0] = "Cannot run away from";
363                                     shown[1] = " a trainer battle";
364                                     shown[2] = null;
365                                     shown[3] = null;
366                                     disp = DIAG;
367                                     pturn = false;
368                                 }
369                                 break;
370                             }
371                         }
372                     }
373                     else if(disp == ATTACKS)
374                     {
375                         handleAttack(p, opp, p.getMonster(p.getActiveMonster()).getAttack(sel));
376                         sel = 0;
377                         if(!natt)
378                             disp = DIAG;
379                         pturn = true;
380                     }
381                     else if(disp == CHANGE)
382                     {
383                         if(p.getMonster(p.getActiveMonster()).equals(p.getMonster(sel)))
384                         {
385                             shown[0] = "Cannot change to th monster ";
386                             shown[1] = "that is already active";
387                             shown[2] = null;
388                             shown[3] = null;
389                             disp = DIAG;
390                             pturn = false;
391                         }
392                         else
393                         {
394                             p.setActiveMonster(sel);
395                             attacks = p.getMonsterAttacks(p.getActiveMonster());
396 
397                             Monster m = p.getMonster(p.getActiveMonster());
398 
399                             sel = 0;
400                             shown[0] = p.getName() + " changed active monster to:";
401                             shown[1] = m.getName();
402                             shown[2] = null;
403                             disp = DIAG;
404                             pturn = true;
405                             actp = find(pl, p.getMonster(p.getActiveMonster()).getName(), true);
406                             repaint();
407                         }
408                     }
409                     else if(disp == ITEMS)
410                     {
411                         if(shown[sel+start] == null)
412                             return;
413                         if(handleItem(p.getItem(shown[sel+start].substring(0, shown[sel+start].indexOf(" x")))))
414                         {
415                             pturn = true;
416                         }
417                         else
418                         {
419                             pturn = false;
420                             // Redo turn
421                         }
422                         sel = 0;
423                         start = 0;
424                         disp = DIAG;
425                     }
426                     else if(disp == DIAG)
427                     {
428                         if(!pturn)
429                         {
430                             sel = 0;
431                             for(int i = 0; i < def.length; i++)
432                             {
433                                 shown[i] = def[i];
434                             }
435                             disp = DEF;
436                             pturn = false;
437                         }
438                         else if(end)
439                         {
440                             disp = DEF;
441                             pturn = false;
442                             repaint();
443                             fireEvent(p);
444                         }
445                         else
446                         {
447                             if(opp.getType() == MapObject.MONSTER)
448                             {
449                                 Attack a = BattleAI.recommendMonsterAttack((Monster)opp, p.getMonster(p.getActiveMonster()));
450                                 handleAttack(opp, p, a);
451                             }
452                             else
453                             {
454                                 try
455                                 {
456                                     Attack a = BattleAI.recommendPlayerAttack((People)opp, p);
457                                     handleAttack(opp, p, a);
458                                 }
459                                 catch(ItemChangeException ie)
460                                 {
461                                     Item it = ie.getItem();
462                                     Monster mon = ((People)opp).getMonster(((People)opp).getActiveMonster());
463                                     ((People)opp).useItem(it, mon);
464 
465                                     shown[0] = ((People)opp).getName() + " used " + it.getName() + " on ";
466                                     shown[1] = mon.getName();
467                                     shown[2] = null;
468                                     shown[3] = null;
469                                 }
470                                 catch(MonsterChangeException me)
471                                 {
472 
473                                     ((People)opp).setActiveMonster(me.getNewMonster());
474 
475                                     Monster m = ((People)opp).getMonster(((People)opp).getActiveMonster());
476 
477                                     shown[0] = ((People)opp).getName() + " changed active monster to:";
478                                     shown[1] = m.getName();
479                                     shown[2] = null;
480                                     disp = DIAG;
481                                     pturn = true;
482                                     actop = find(pl, ((People)opp).getMonster(((People)opp).getActiveMonster()).getName(), false);
483                                     repaint();
484                                 }
485                             }
486                             disp = DIAG;
487                             pturn = false;
488                         }
489                     }
490                     else if(disp == NEWATT)
491                     {
492                         if(natt)
493                         {
494                             sel = 0;
495                             for(int i = 0; i < attacks.length; i++)
496                             {
497                                 shown[i] = attacks[i];
498                             }
499                             disp = NEWATT;
500                             natt = false;
501                         }
502                         else
503                         {
504                             Monster m = p.getMonster(p.getActiveMonster());
505                             Attack ab = m.getAttack(sel);
506                             m.substituteAttack(ab, a);
507                             shown[0] = m.getName() + " Learned Attack:";
508                             shown[1] = a.getName() + "!";
509                             shown[2] = null;
510                             shown[3] = null;
511                             attacks = p.getMonsterAttacks(p.getActiveMonster());
512                             disp = DIAG;
513                             pturn = true;
514                             sel = 0;
515                         }
516                     }
517                     break;
518                 }
519                 case KeyEvent.VK_ESCAPE:
520                 {
521                     start = 0;
522                     if(disp != DIAG)
523                     {
524                         sel = 0;
525                         for(int i = 0; i < def.length; i++)
526                         {
527                             shown[i] = def[i];
528                         }
529                         disp = DEF;
530                         pturn = false;
531                     }
532                     break;
533                 }
534             }
535             repaint(bw, bh, wi, hi);
536         }
537         else if(((KeyEvent)e).getID() == KeyEvent.KEY_RELEASED) { }
538         super.processEvent(e);
539     }
540 
541     /**
542      * Draws the Battle screen system with Monsters, Health bars, and Menus
543      * 
544      * @param g the Graphics
545      */
546     public synchronized void paint(Graphics g)
547     {
548         w = getWidth();
549         h = getHeight();
550 
551         g.setColor(Color.white);
552         g.fillRect(0, 0, w, h);
553 
554         if(pl != null)
555             g.drawImage(pl[actp].getImage(), 5, h - pl[actp].getImage().getHeight(this) + 5, this);
556         if(pl[actop] != null)
557             g.drawImage(pl[actop].getImage(), w - pl[actop].getImage().getWidth(this) - 5, 5, this);
558         drawMenu(g);
559         if(opp != null && p != null && g != null)
560             drawHealth(p, opp, g);
561     }
562     /**
563      * Draws the Menu of options or the dialogue.
564      * 
565      * @param g the Graphics
566      */
567     private synchronized void drawMenu(Graphics g)
568     {
569         int wi = (int)(w*.4);
570         int hi = (int)(h*.2);
571         int bw = w - wi - 5;
572         int bh = h - hi - 5;
573 
574         g.setColor(Color.white);
575         g.fillRect(bw, bh, wi, hi);
576 
577         g.setColor(Color.black);
578         g.drawRect(bw, bh, wi, hi);
579 
580         if(shown == null)
581             return;
582 
583         int posh = 0;
584         int he = hi/4;
585         for(int i = start, j = 0; i < shown.length && shown[i] != null && j < 4; i++, j++)
586         {
587             if(j == sel && disp != DIAG && !natt)
588             {
589                 g.setColor(Color.red);
590             }
591             else g.setColor(Color.black);
592             g.drawString(shown[i], bw+7, bh+posh+15);
593             posh += hi/4;
594         }
595 
596         if(disp != DIAG && !natt)
597         {
598             g.setColor(Color.red);
599             g.drawLine(bw+7, bh + sel*he+15+3, bw+wi-7, bh + sel*he+15+3);
600         }
601     }
602     /**
603      * Draws the Health bars of the Player and opponent.
604      * 
605      * @param pl the Player
606      * @param op the opponent
607      * @param g the Graphics
608      */
609     private synchronized void drawHealth(Player pl, MapObject op, Graphics g)
610     {
611         int wi = (int)(w*.4);
612         int hi = (int)(h*.05);
613         int bw = w - wi - 5;
614         int bh = h - (int)(h*.2) - hi - 10;
615         int eh = h - (int)(h*.2) - hi*2 - 10;
616 
617         Monster m = pl.getMonster(pl.getActiveMonster()); // Player
618         if(m != null)
619         {
620             int hp = m.getHP();
621             int mhp = m.getMaxHP();
622             double hpend = (double)wi*(double)hp/(double)mhp;
623 
624             g.setColor(playerHealth);
625             g.fillRect(bw, bh, (int)hpend, hi);
626             g.setColor(Color.black);
627             g.drawRect(bw, bh, wi, hi);
628             g.drawString(pl.getName() + ": " + m.getName() + ", L: " + m.getLevel(), bw + 5, bh + (int)(hi/2));
629         }
630 
631         String output = "";
632         if(op.getType() == MapObject.PERSON || op.getType() == MapObject.TRAINER)
633         {
634             m = ((People)op).getMonster(((People)op).getActiveMonster()); // Opponent
635             if(m != null)
636                 output = opp.getName() + ": " + m.getName() + ", L: " + m.getLevel();
637         }
638         else if(op.getType() == MapObject.MONSTER)
639         {
640             m = (Monster)op;
641             output = m.getName() + ", L: " + m.getLevel();
642         }
643         if(m != null)
644         {
645             int hp = m.getHP();
646             int mhp = m.getMaxHP();
647             double hpend = (double)wi*(double)hp/(double)mhp;
648 
649             g.setColor(opponentHealth);
650             g.fillRect(bw, eh, (int)hpend, hi);
651             g.setColor(Color.black);
652             g.drawRect(bw, eh, wi, hi);
653             g.drawString(output, bw + 5, eh + (int)(hi/2));
654         }
655     }
656     /**
657      * Adds a BattleEndListener to be informed.
658      * 
659      * @param bl the Class to be informed of BattleEndEvents.
660      * @see BattleEndEvent
661      * @see BattleEndListener
662      */
663     public void addBattleEndListener(BattleEndListener bl)
664     {
665         if ( battleEndListeners == null )
666             battleEndListeners = new Vector();
667         battleEndListeners.addElement( bl );
668     }
669     /**
670      * Removes a BattleEndListener to not be informed anymore.
671      * 
672      * @param bl the Class to stop being informed of BattleEndEvents.
673      * @see BattleEndEvent
674      * @see BattleEndListener
675      */
676     public void removeBattleListener(BattleEndListener bl)
677     {
678         if ( battleEndListeners != null )
679             battleEndListeners.removeElement( bl );
680     }
681     /**
682      * Fires the BattleEndEvent to all listeners
683      * 
684      * @param mp the MapObject to pass along.
685      * @see BattleEndEvent
686      * @see BattleEndListener
687      */
688     private void fireEvent(MapObject mp) 
689     {
690         if ( battleEndListeners == null )
691             return;
692         BattleEndEvent event = new BattleEndEvent(this, BattleEndEvent.BATTLE_ENDED, p);
693         for (Enumeration e = battleEndListeners.elements(); e.hasMoreElements(); )
694             ((BattleEndListener)e.nextElement()).battleEnd( event );
695     }
696     /**
697      * Adds a GameOverListener to be informed.
698      * 
699      * @param bl the Class to be informed of GameOverEvents.
700      * @see GameOverEvent
701      * @see GameOverListener
702      */
703     public void addGameOverListener(GameOverListener bl)
704     {
705         if ( gameOverListeners == null )
706             gameOverListeners = new Vector();
707         gameOverListeners.addElement( bl );
708     }
709     /**
710      * Removes a GameOverListener to stop being informed.
711      * 
712      * @param bl the Class to stop being informed of GameOverEvents.
713      * @see GameOverEvent
714      * @see GameOverListener
715      */
716     public void removeGameOverListener(GameOverListener bl)
717     {
718         if ( gameOverListeners != null )
719             gameOverListeners.removeElement( bl );
720     }
721     /**
722      * Fires a GameOverEvent to all Listeners
723      * 
724      * @see GameOverEvent
725      * @see GameOverListener
726      */
727     private void fireGameOverEvent() 
728     {
729         if ( gameOverListeners == null )
730             return;
731         GameOverEvent event = new GameOverEvent(this, GameOverEvent.GAME_OVER);
732         for (Enumeration e = gameOverListeners.elements(); e.hasMoreElements(); )
733             ((GameOverListener)e.nextElement()).gameOver( event );
734     }
735     /**
736      * Handle the attack choice between the attacker, reciever using Attack pla.
737      * 
738      * @param attacker the MapObject attacking
739      * @param reciever the MapObject being attacked
740      * @param pla the Attack being used
741      * @see MapObject
742      * @see Attack
743      * @see Trainer
744      * @see Player
745      * @see Person
746      * @see People
747      * @see Monster
748      */
749     private void handleAttack(MapObject attacker, MapObject reciever, Attack pla)
750     {
751         Player p = null;
752         People op = null;
753         Monster pm = null, om = null;
754         String attName = null;
755         if(attacker.getType() == MapObject.PLAYER)
756         {
757             p = (Player)attacker;
758             pm = p.getMonster(p.getActiveMonster());
759             attName = p.getName();
760         }
761         else if(attacker.getType() == MapObject.PERSON || attacker.getType() == MapObject.TRAINER)
762         {
763             op = (People)attacker;
764             pm = op.getMonster(op.getActiveMonster());
765             attName = op.getName();
766         }
767         else if(attacker.getType() == MapObject.MONSTER)
768         {
769             pm = (Monster)attacker;
770             attName = pm.getName();
771         }
772         if(reciever.getType() == MapObject.PERSON || reciever.getType() == MapObject.TRAINER)
773         {
774             op = (People)reciever;
775             om = op.getMonster(op.getActiveMonster());
776         }
777         else if(reciever.getType() == MapObject.PLAYER)
778         {
779             p = (Player)reciever;
780             om = p.getMonster(p.getActiveMonster());
781         }
782         else if(reciever.getType() == MapObject.MONSTER)
783         {
784             om = (Monster)reciever;
785         }
786 
787         if(pm != null && om != null)
788         {
789             double pa = pla.getPower();
790             int damage;
791             int rhp = om.getHP();
792             int min = Math.abs((pm.getLevel() - om.getLevel()) * (pm.getLevel() / 25) / 3);
793             min = (min == 0 ? 2 : min);
794             if(isWeakAgainst(pm.getKind(), om.getKind()))
795             {
796                 damage = (int)( (2*pm.getAttack()*Attack.DAMAGEMULT - .5*om.getDefense())*pa *(pm.getLevel()/om.getLevel()));
797                 if(damage > min)
798                 {
799                     om.setHP(rhp - damage);
800                 }
801                 else
802                 {
803                     damage = (int)(rhp/64);
804                     om.setHP(rhp - (damage > min ? damage : min));
805                 }
806             }
807             else
808             {
809                 damage = (int)( (2*pm.getAttack() - .5*om.getDefense())*pa *(pm.getLevel()/om.getLevel()));
810                 if(damage > min)
811                 {
812                     om.setHP(rhp - damage);
813                 }
814                 else
815                 {
816                     damage = (int)(rhp/64);
817                     damage = (damage > 0 ? damage : 2);
818                     om.setHP(rhp - damage);
819                 }
820             }
821 
822             if(attacker.getType() == MapObject.MONSTER)
823                 shown[0] = pm.getName() + " did:";
824             else
825                 shown[0] = attName + "'s " + pm.getName() + " did:";
826             shown[1] = damage + " damage to " + om.getName() + (om.getHP() == 0 ? " killing him." : "" );
827             shown[2] = null;
828             shown[3] = null;
829             if(pa == pla.DAMAGE1)
830             {
831                 om.setDefense(om.getDefense()-5);
832                 shown[2] = "and lowered " + om.getName() + " Defense by 5";
833             }
834             else if(pa == pla.DAMAGE3)
835             {
836                 om.setAttack(om.getAttack() -8);
837                 shown[2] = "and lowered " + om.getName() + " Attack by 8";
838             }
839             else if(pa == pla.DAMAGE4)
840             {
841                 om.setDefense(om.getDefense()-5);
842                 om.setAttack(om.getAttack() -8);
843                 pm.setHP(pm.getHP() - (int)(pm.getHP()*.01));
844                 shown[2] = "and lowered " + om.getName() + " Defense by 5, Attack by 8";
845                 shown[3] = "and lowered " + pm.getName() + " to: " + pm.getHP();
846             }
847             else if(pa == pla.DAMAGE5)
848             {
849                 om.setDefense(om.getDefense()-8);
850                 om.setAttack(om.getAttack() -9);
851                 pm.setHP(pm.getHP() - (int)(pm.getHP()*.05));
852                 shown[2] = "and lowered " + om.getName() + " Defense by 8, Attack by 9";
853                 shown[3] = "and lowered " + pm.getName() + " to: " + pm.getHP();
854             }
855 
856             if(om.getHP() == 0)
857             {
858                 if(reciever.getType() == MapObject.PERSON || reciever.getType() == MapObject.TRAINER)
859                 {
860                     if(op.getNumberOfMonsters() == 0)
861                     {
862                         p.stopBattle();
863                         givePlayerExperience(pm, om);
864                         finishFight(om);
865                         if(!natt)
866                         {
867                             shown[0] = ((People)reciever).getDialogue(); // Add real Dialogue
868                             shown[1] = "You defeated my monsters,";
869                             shown[2] = "I will have my revenge!!";;
870                             shown[3] = null;
871                         }
872                         end = true;
873                     }
874                     else
875                     {
876                         givePlayerExperience(pm, om);
877                         op.setActiveMonster(0);
878                         actop = find(pl, ((People)opp).getMonster(((People)opp).getActiveMonster()).getName(), false);
879                         repaint();
880                         // Force Opp change
881                     }
882                 }
883                 else if(reciever.getType() == MapObject.MONSTER)
884                 {
885                     p.stopBattle();
886                     givePlayerExperience(pm, om);
887                     finishFight(om);
888                     if(!natt)
889                     {
890                         shown[0] = "Arrgh!"; // Add real Dialogue
891                         shown[1] = reciever.getName();
892                         shown[2] = null;
893                         shown[3] = null;
894                     }
895                     end = true;
896                 }
897                 else
898                 {
899                     if(p.getNumberOfMonsters() == 0)
900                     {
901                         fireGameOverEvent();
902                     }
903                     else
904                     {
905                         p.setActiveMonster(0);
906 
907                         monsters = p.getMonsters();
908                         attacks = p.getMonsterAttacks(0);
909                         actp = find(pl, p.getMonster(p.getActiveMonster()).getName(), true);
910                         repaint();
911                     }
912                 }
913             }
914         }
915     }
916     /**
917      * If the Player's active Monster won give him the experience propertional to the difference between
918      * his level and the opponent's Monster level.
919      * 
920      * @param pm the Players Monster
921      * @param om the opponents Monster
922      * @see Monster
923      */
924     private void givePlayerExperience(Monster pm, Monster om)
925     {
926         try
927         {
928             if(pm.finishFight(om))
929             {
930                 attacks = p.getMonsterAttacks(p.getActiveMonster());
931                 shown[0] = pm.getName() + " leveled up to level" + pm.getLevel();
932                 shown[1] = "Now has attacks:" ;
933                 shown[2] = "";
934                 shown[3] = "";
935                 for(int i = 0; i < 2 && attacks[i] != null; i++)
936                 {
937                     shown[2] += attacks[i] + " , ";
938                 }
939                 for(int i = 2; i < attacks.length && attacks[i] != null; i++)
940                 {
941                     shown[3] += attacks[i] + " , ";
942                 }
943             }
944             pturn = true;
945         }
946         catch(AttacksFullException e)
947         {
948             a = e.getAttack();
949             natt = true;
950             disp = NEWATT;
951             shown[0] = pm.getName() + " is trying to learn ";
952             shown[1] = a.getName() + " Press enter or space to";
953             shown[2] = "select an attack to forget,";
954             shown[3] = "or press escape to keep attacks known";
955         }
956     }
957     /**
958      * Do the cleanup to finish a fight.
959      * 
960      * @paramom th opponents Monster
961      */
962     private void finishFight(Monster om)
963     {
964         if(opp.getType() == MapObject.PERSON || opp.getType() == MapObject.TRAINER)
965         {
966             People op = (People)opp;
967             if(op.getType() == MapObject.TRAINER)
968             {
969                 String b = ((Trainer)op).getBadge();
970                 p.addBadge(b);
971                 ((Trainer)op).setBadge("");
972                 shown[3] = "You earned Badge: " + b;
973             }
974             int mon = ((int)(op.getMoney())/2);
975             p.setMoney(p.getMoney() + mon);
976             op.setMoney(op.getMoney() - mon);
977             op.beat();
978         }
979     }
980     /**
981      * Determines if a Monster is weak against the other.
982      * 
983      * @param plt the Monster to check against
984      * @param opt the Monster to check
985      * @see Attack
986      * @see Monster
987      */
988     private boolean isWeakAgainst(int plt, int opt) // If opt < plt
989     {
990         switch(plt)
991         {
992             case Monster.GAS:
993             {
994                 if(opt == Monster.ELECTRIC || opt == Monster.EARTH)
995                     return true;
996                 return false;
997             }
998             case Monster.FIRE:
999             {
1000                if(opt == Monster.GAS || opt == Monster.ELECTRIC)
1001                    return true;
1002                return false;
1003            }
1004            case Monster.WATER:
1005            {
1006                if(opt == Monster.GAS || opt == Monster.FIRE)
1007                    return true;
1008                return false;
1009            }
1010            case Monster.EARTH:
1011            {
1012                if(opt == Monster.WATER || opt == Monster.FIRE)
1013                    return true;
1014                return false;
1015            }
1016            case Monster.ELECTRIC:
1017            {
1018                if(opt == Monster.EARTH || opt == Monster.WATER)
1019                    return true;
1020                return false;
1021            }
1022        }
1023        return false;
1024    }
1025    /**
1026     * Use the Item that was selected, if possible.  For example
1027     * MonsterBalls cannot be used on already captured Monsters.
1028     * 
1029     * @param it the Item to use
1030     * @see Item
1031     * @see Monster
1032     */
1033    private boolean handleItem(Item it)
1034    {
1035        if(it == null)
1036            return false;
1037        shown = new String[4];
1038        if(it.getBrand() == Item.MONSTERBALL)
1039        {
1040            if(opp.getType() == MapObject.PERSON || opp.getType() == MapObject.TRAINER)
1041            {
1042                shown[0] = "Cannot use Monster Balls on monsters";
1043                shown[1] = "have been captured by people";
1044                shown[2] = null;
1045                shown[3] = null;
1046                return false;
1047            }
1048            else
1049            {
1050                Monster mon = (Monster)opp;
1051                if(it.useItem(mon))
1052                {
1053                    if(p.addMonster(mon))
1054                    {
1055                        shown[0] = mon.getName() + " was captured and added to";
1056                        shown[1] = p.getName() + "'s hand using the";
1057                        shown[2] = it.getName();
1058                        shown[3] = null;
1059                    }
1060                    else
1061                    {
1062                        shown[0] = mon.getName() + " was captured and added to";
1063                        shown[1] = p.getName() + "'s home collection using the";
1064                        shown[2] = it.getName();
1065                        shown[3] = null;
1066                    }
1067                    opp = null;
1068                    end = true;
1069                }
1070                else
1071                {
1072                    shown[0] = mon.getName() + " evaded capture narrowly avoiding";
1073                    shown[1] = "the " + it.getName();
1074                    shown[2] = null;
1075                    shown[3] = null;
1076                }
1077            }
1078        }
1079        else if(it.getBrand() == Item.POTION)
1080        {
1081            Monster mon = p.getMonster(p.getActiveMonster());
1082            p.useItem(it, mon);
1083            items = p.getItems();
1084            shown[0] = p.getName() + " used " + it.getName() + " on ";
1085            shown[1] = mon.getName();
1086            shown[2] = null;
1087            shown[3] = null;
1088        }
1089        return true;
1090    }
1091    /**
1092     * Find the index in the ImageMap array that the MapObject's
1093     * Image is at.
1094     * 
1095     * @param im th ImageMap  array
1096     * @param n the Name of the Monster
1097     * @param player true iff Player false otherwise
1098     */
1099    private int find(ImageMap[] im, String n, boolean player)
1100    {
1101        for(int i = 0; i < im.length; i++)
1102        {
1103            if(im[i].equals(n, player))
1104                return i;
1105        }
1106        System.out.println("|" + n + "|");
1107        return -1;
1108    }
1109}