1   import java.util.Random;
2   /**
3    * Simple AI to determine the best course of attack/Item use/Monster switch
4    * based on the two battling Monsters.
5    * 
6    * @see Monster
7    * @see Battle
8    * @author Samuel Baumgardner
9    */
10  public class BattleAI
11  {
12      /**
13       * Recommends the best Attack corresponding for the Monster
14       * 
15       * @param attacker the Monster attacking
16       * @param opponent the Monster defending
17       * @return the recommended Attack
18       */
19      public static Attack recommendMonsterAttack(Monster attacker, Monster opponent)
20      {
21          //requires: attacker and opponent be non-null and initialized
22          //that myMonster's attacks are sorted from lowest to highest
23          //effects: returns the best attack for attacker.
24  
25          Monster myMonster = attacker;
26          Monster mangyBastard = opponent;
27  
28          //Strategy one: If my opponent is weak against me then sock it to him.
29          if(isWeakAgainst(myMonster.getType(),mangyBastard.getType()))
30              return myMonster.getAttack(myMonster.getAttacks().length-1);
31  
32          //Strategy two: If I am weaker than my opponent tip toe thru the house and try not to disturb.
33          if(isWeakAgainst(mangyBastard.getType(),myMonster.getType()))
34              return myMonster.getAttack(0);
35  
36          //Strategy three: return a reasonable attack
37          //if the random number is greater than the current level then choose the highest
38          //attack possible
39          //if the random number is less than the current level then choose a random attack that is weaker than the highest
40          //attack possible
41  
42  
43          int attack;
44          Random random = new Random();
45          random.setSeed(System.currentTimeMillis());
46          attack = random.nextInt(myMonster.getMaxLevel());
47          if(attack <= (myMonster.getLevel()-1))
48              return myMonster.getAttack(myMonster.getNumberOfAttacks()-1);
49          attack = random.nextInt(myMonster.getNumberOfAttacks()-1);
50          return myMonster.getAttack(attack);
51      }
52  
53      /**
54       * Determines if the itemType is available, ie is in the People's
55       * Item collection.
56       * 
57       * @param itemType the brand of the Item to search for
58       * @param itemSubType the subBrand of the Item to search for
59       * @param items the String array of items the People is carrying
60       * @param itemContainer the People to search in.
61       * @return the Item if it is owned, else null.
62       * @see Item
63       * @see People
64       */
65      private static Item itemLookUp(int itemType, int itemSubType, String[] items, People itemContainer)
66      {
67          for(int i = 0;i < items.length;i++)
68          {
69              if(items[i] != null)
70              {
71                  Item item = itemContainer.getItem(items[i]);
72                  if(item.getBrand() == itemType)
73                  {
74                      if(item.getSubBrand() == itemSubType)
75                          return item;
76                  }
77              }
78          }
79          return null;
80      }
81      /**
82       * Recommends the best Attack corresponding for the People against the Player
83       * 
84       * @param attacker the People attacking
85       * @param opponent the Player defending
86       * @return the recommended Attack
87       * @exception ItemChangeException if the best course of action is to use an Item
88       * @exception MonsterChangeException if the best course of action is to switch Monsters
89       * @see Monster
90       * @see People
91       * @see Player
92       * @see Item
93       */
94      public static Attack recommendPlayerAttack(People attacker, Player opponent) throws ItemChangeException, MonsterChangeException
95      {
96          Monster opp = opponent.getMonster(opponent.getActiveMonster());
97          Monster att = attacker.getMonster(attacker.getActiveMonster());
98  
99  
100         //Strategy 1: If health points are low < 20% use max potion to increase health
101         //Strategy 2: If defense is low < 20% use potion to increase defense
102         //Strategy 3: If attack is low < 20% use potion to increase attack
103 
104             String[] items = attacker.getItems();
105 
106             PotionItem potion = null;
107 
108             if((100 * (att.getDefense()/att.getMaxDefense())) < 20)
109             {
110                 potion = (PotionItem)itemLookUp(Item.POTION, PotionItem.DEFUP, attacker.getItems(), attacker);
111                 if(potion != null)
112                     throw new ItemChangeException(potion);
113             }
114             
115             if((100 * (att.getAttack()/att.getMaxAttack())) < 20)
116             {
117                 potion = (PotionItem)itemLookUp(Item.POTION, PotionItem.ATTUP, attacker.getItems(), attacker);
118                 if(potion != null)
119                     throw new ItemChangeException(potion);
120             }
121 
122             if((100 * (att.getHP()/att.getMaxHP())) < 20)
123             {
124                 potion = (PotionItem)itemLookUp(Item.POTION, PotionItem.HPUPFULL, attacker.getItems(), attacker);
125                 if(potion != null)
126                     throw new ItemChangeException(potion);
127 
128                 potion = (PotionItem)itemLookUp(Item.POTION, PotionItem.HPUPHALF, attacker.getItems(), attacker);
129                 if(potion != null)
130                     throw new ItemChangeException(potion);
131 
132                 potion = (PotionItem)itemLookUp(Item.POTION, PotionItem.HPUPTHIRD, attacker.getItems(), attacker);
133                 if(potion != null)
134                     throw new ItemChangeException(potion);
135             }
136 
137         if( isWeakAgainst(opp.getKind(), att.getKind()) )
138         {
139             for(int i = 0; i < attacker.getNumberOfMonsters(); i++)
140             {
141                 if( !isWeakAgainst(opp.getKind(), attacker.getMonster(i).getKind()) )
142                     throw new MonsterChangeException(attacker.getActiveMonster(), i);
143             }
144         }
145         return recommendMonsterAttack(att, opp);
146     }
147 
148     /**
149      * Determine if a Monster type is weak against another.
150      * 
151      * @param plt the one to determine based on, ie the attacker
152      * @param opt the one to determine against, ie the defender
153      * @return true if opt is weak against plt, false othrwise.
154      */
155     private static boolean isWeakAgainst(int plt, int opt) // If opt < plt
156     {
157         switch(plt)
158         {
159             case Monster.GAS:
160             {
161                 if(opt == Monster.ELECTRIC || opt == Monster.EARTH)
162                     return true;
163                 return false;
164             }
165             case Monster.FIRE:
166             {
167                 if(opt == Monster.GAS || opt == Monster.ELECTRIC)
168                     return true;
169                 return false;
170             }
171             case Monster.WATER:
172             {
173                 if(opt == Monster.GAS || opt == Monster.FIRE)
174                     return true;
175                 return false;
176             }
177             case Monster.EARTH:
178             {
179                 if(opt == Monster.WATER || opt == Monster.FIRE)
180                     return true;
181                 return false;
182             }
183             case Monster.ELECTRIC:
184             {
185                 if(opt == Monster.EARTH || opt == Monster.WATER)
186                     return true;
187                 return false;
188             }
189         }
190         return false;
191     }
192 
193 }