/* Mike Kemp
   Joe Lau
   Brendan Shaughnessy
   Jesse Eyerman
   Jon Havstad
*/


import java.util.*;


public class CharacterGroup extends Group {

    private boolean break_fail;     // If defending characters fail a break
                                    //   away check that round
    private boolean firefight;      // Firefight combat if true, hand to hand
                                    //   if false
    private boolean inactive_check; // Checks if inactive characters have
                                    //   broken off in this round's combat
    private boolean capture;        // Capture combat if true, kill if false
    private int att_strength;       // Attacking CharacterGroup's combat rating
    private int def_strength;       // Defending CharacterGroup's combat rating
    private int mon_strength;       // Monster's combat rating
    private int mon_endurance;      // Monster's endurance
    private int mon_duration;       // Duration of monster combat
    // private int mon_regen;       // Monster's regenitive ability
    private int mon_surprise;       // Column shift for Monster Surprise
    private int mon_breakoff;       // Modifier to breakoff rating caused
                                    //   by particular monsters

    // Group of inactive characters
    private Vector inactive;

    // Character Combat Results Table.
    // The first two integers correlate to the defender's die roll:
    //   the first is the number of wounds the attacker receives, and
    //   the second indicates a defending character has been captured (if
    //   capture is applicable).
    // The second two integers follow the same pattern but are referenced
    //   during the attackers die roll.
    private int[][][] charcomtable = 
    {{{4,0,0,0},{4,0,0,0},{3,0,0,0},{3,0,0,0},{2,0,0,0},{2,0,1,0}},
     {{3,0,0,0},{3,0,0,0},{3,1,0,0},{2,0,0,0},{2,0,0,0},{1,0,1,0}},
     {{3,0,0,0},{2,0,0,0},{2,0,0,0},{2,1,0,0},{1,0,1,0},{0,0,1,0}},
     {{2,0,0,0},{2,1,0,0},{2,0,0,0},{1,0,1,1},{1,0,1,0},{0,0,1,0}},
     {{2,0,0,0},{2,1,0,0},{1,0,0,1},{1,0,1,0},{0,0,1,0},{0,0,2,0}},
     {{2,1,0,0},{1,0,0,0},{1,0,1,0},{1,0,1,1},{0,0,1,0},{0,0,2,0}},
     {{2,0,0,0},{1,1,1,0},{1,0,1,0},{0,0,1,1},{0,0,2,1},{0,0,2,0}},
     {{1,0,1,0},{1,1,1,0},{1,0,1,1},{0,0,2,1},{0,1,2,0},{0,0,3,0}},
     {{1,0,1,1},{1,1,2,0},{0,0,2,1},{0,0,3,0},{0,0,3,1},{0,0,3,0}},
     {{1,0,2,0},{0,0,2,0},{0,0,3,0},{0,0,3,0},{0,0,4,0},{0,0,4,0}}};

    private int[][] breaktable = 
    {{4,6},{4,6},{3,5},{3,5},{3,4},{2,4},{2,4},{2,3},{2,3},{1,3}};
    

    protected Vector starships;
    
    public CharacterGroup(char s)
    {
	super();
	starships = new Vector();
	type = 'c';
	side = s;
    }

   /**
    * accessor methods
    */
   /**
    * MS team needs to know which spaceships are in a given environ
    * returns a vector of spacships
    */
    public Vector getStarships()
    {
	return starships;
    }
    
    /** Get strength of attacking CharacterGroup or Creature */
    public int getAttStrength()
    {
	return att_strength;
    }

    /** Get strength of defending CharacterGroup */
    public int getDefStrength()
    {
	return def_strength;
    }

    /** Get strength of attacking monster */
    public int getMonStrength()
    {
	return mon_strength;
    }
    
    /** Get endurance of attacking monster */
    public int getMonEndurance()
    {
	return mon_endurance;
    }

    /** Get Duration of a monster combat */
    public int getMonDur()
    {
	return mon_duration;
    }

    /** Returns a vector containing all active Characters */
    public Vector getActive(){

       	Vector activeIndex = new Vector(1,2);
	Charactr tmp;
	int i = 0;

	while(i < units.size()) {
		tmp = (Charactr)units.elementAt(i);

		if(tmp.getIsActive()) {
			activeIndex.add(tmp);
		}
		i++;
	}

	return activeIndex;

    }

    /** Check if a group of Characters have broken off (the group can
	be of any size smaller than the group there are breaking off of.
	This check modifies the inactive_check variable used to see
	if inactive Characters broke off during a specific combat
        round. */
    public boolean checkBreakOff()
    {
	// if the inactive group of characters has not been modified
	if (!(inactive_check))
	    return(false);
	else {
	    inactive_check = false;
	    return(true);
	}
    }

   /**
    * modifier methods
    */
   /**
    * adds a Spaceship to the vector
    */
    public void addSpaceship(Spaceship s)
    {
	starships.add(s);
    }
   /**
    * removes a Spaceship from the vector
    */
    public void removeSpaceship(Spaceship s)
    {
	starships.remove(s);
    }

    /** Called to set firefight to true or false */
    public void setfirefight(boolean value)
    {
	firefight = value;
    }

    /** Called to set capture to true or false */
    public void setcapture(boolean value)
    {
	capture = value;
    }

    /** General Character vs. Character Combat
	att: attacker, def: defender
	returns 0 if no Group is eliminated,
	        1 if attacking Group is eliminated,
	        2 if defending Group is eliminated  */
    public boolean CharCombat(CharacterGroup att)
    {
	// if defender is rebel
	if (side == 'r') {
	    firefight = AI.CheckRange();     // AI chooses HtH or firefight
	    capture = AI.CheckLethal();      // AI chooses capture or kill
	    // PossessionGUI();              // Player chooses what possessions
                                             //   to use (if any)
	}
	else
	new charMethodGUI(this).show();      // Player chooses HtH or firfight
                                             //   and capture or kill

	firefight = true;
	capture = false;

	def_strength = CharGroupStrength();
	att_strength = att.CharGroupStrength();
	
	new charGUI(this, att).show();       // Initiate main combat GUI
	// charFightTest(att);

	if (CheckEmpty())                    // all defenders dead or captured
	    return(true);              

	return(false);                       // neither side eliminated
    }
    
    /** Military vs. Character Combat
	att: attacker (Military)
	returns false if neither Group is eliminated,
	        true if defending Group is eliminated  */
    public boolean SquadCombat(MilitaryGroup att)
    {
 	if (side == 'r') {                // if rebel characters defending
	    capture = AI.CheckLethal();   // AI chooses capture or kill
	// PossessionGUI();               // Player chooses which possessions
                                          //   to use (if any)
	}
//	else
	// CombatMethodGUI(this);         // Player chooses capture or kill

 	firefight = true;                 // squad combat is always firefight

	// CharCombatGUI(this, att);      // Initiate main combat GUI
	squadFightTest(att);

 	if (CheckEmpty())                 // all defenders dead or captured
	    return(true);              
	
	return(false);                    // neither side eliminated
    }
    
    /** Monster Attack
	returns false if characters survive,
	        true if characters die  */
    public boolean MonsterCombat()
    {
	Environ env;
	String monster;

	System.out.println("\nStarting Monster Combat\n");

	env = getEnviron();

	firefight = false;
	capture = false;

	monster = env.getCreature();

	MonsterStats(monster);

	new monGUI(this, monster).show();
	// monsterTest(monster);


	if (CheckEmpty())
	    return(true);

	return(false);
    }

    /** Irate Locals Combat.
	returns false if characters survive,
	        true if characters all perish */
    public boolean IrateLocals()
    {
	String race, star_race;
	char env_type;
	Environ env;
	// HashTable locals = new HashTable();
	
	System.out.println("\nStarting Irate Locals Combat\n");
	
	mon_duration = -1;
	// mon_regen = 0;
	mon_surprise = 0;
	mon_breakoff = 0;

	env = getEnviron();
	race = env.getRace(0);

	capture = false;

	

	if (race.equals("Anons")) {
	    mon_strength = 4;
	    mon_endurance = 2;
	    firefight = false;
	}
	else if (race.equals("Ardorats")) {
	    mon_strength = 4;
	    mon_endurance = 4;
	    firefight = true;
	}
	else if (race.equals("Borks")) {
	    mon_strength = 8;
	    mon_endurance = 2;
	    firefight = true;
	}
	else if (race.equals("Calmas")) {
	    mon_strength = 5;
	    mon_endurance = 4;
	    firefight = true;
	}
	else if (race.equals("Charkhans")) {
	    mon_strength = 5;
	    mon_endurance = 4;
	    firefight = true;
	}
	else if (race.equals("Cavalcus")) {
	    mon_strength = 4;
	    mon_endurance = 3;
	    firefight = false;
	}
	else if (race.equals("Deaxins")) {
	    mon_strength = 5;
	    mon_endurance = 5;
	    firefight = false;
	}
	else if (race.equals("Illias")) {
	    mon_strength = 4;
	    mon_endurance = 4;
	    firefight = true;
	}
	else if (race.equals("Henones")) {
	    mon_strength = 6;
	    mon_endurance = 6;
	    firefight = true;
	}
	else if (race.equals("Kirts")) {
	    mon_strength = 5;
	    mon_endurance = 4;
	    firefight = true;
	}
	else if (race.equals("Jopers")) {
	    mon_strength = 6;
	    mon_endurance = 2;
	    firefight = true;
	}
	else if (race.equals("Leonids")) {
	    mon_strength = 6;
	    mon_endurance = 4;
	    firefight = true;
	}
	else if (race.equals("Moghas")) {
	    mon_strength = 7;
	    mon_endurance = 3;
	    firefight = false;
	}
	else if (race.equals("Mowevs")) {
	    mon_strength = 4;
	    mon_endurance = 4;
	    firefight = false;
	}
	else if (race.equals("Ornotins")) {
	    mon_strength = 6;
	    mon_endurance = 4;
	    firefight = true;
	}
	else if (race.equals("Phans")) {
	    mon_strength = 4;
	    mon_endurance = 4;
	    firefight = true;
	}
	else if (race.equals("Rylians")) {
	    mon_strength = 8;
	    mon_endurance = 2;
	    firefight = false;
	}
	else if (race.equals("Susperans")) {
	    mon_strength = 4;
	    mon_endurance = 4;
	    firefight = true;
	}
	else if (race.equals("Theshians")) {
	    mon_strength = 4;
	    mon_endurance = 2;
	    firefight = true;
	}
	else if (race.equals("Thoks")) {
	    mon_strength = 6;
	    mon_endurance = 5;
	    firefight = false;
	}
	else if (race.equals("Ultraks")) {
	    mon_strength = 4;
	    mon_endurance = 4;
	    firefight = true;
	}
	else if (race.equals("Urgaks")) {
	    mon_strength = 6;
	    mon_endurance = 4;
	    firefight = true;
	}
	else if (race.equals("Ursi")) {
	    mon_strength = 7;
	    mon_endurance = 6;
	    firefight = false;
	}
	// Race is starfaring.  Starfaring Races have additional characters
	//   in their strings related to the environ they inhabit.  Therefore,
	//   this section compares the first three letters of the string to
	//   the first three characters of each starfaring races name.
	//   Afterward, the final character is looked at to find the specific
	//   environ that race is inhabiting currently.
	else {
	    star_race = race.substring(0,3);
	    firefight = false;                  // no firefights at this point

	    if (star_race.equals("Rho")) {
		env_type = race.charAt(8);
		switch (env_type) {
		case 'U':
		    mon_strength = 5;
		    mon_endurance = 4;
		    break;
		case 'W':
		    mon_strength = 4;
		    mon_endurance = 4;
		    break;
		case 'S':
		    mon_strength = 4;
		    mon_endurance = 4;
		    break;
		default:
		    mon_strength = 0;
		    mon_endurance = 1;
		    race = "Not found";
		    break;
		}
	    }

	    else if (star_race.equals("Sau")) {
		env_type = race.charAt(9);
		switch (env_type) {
		case 'U':
		    mon_strength = 5;
		    mon_endurance = 6;
		    break;
		case 'W':
		    mon_strength = 5;
		    mon_endurance = 4;
		    break;
		case 'S':
		    mon_strength = 5;
		    mon_endurance = 2;
		    break;
		case 'L':
		    mon_strength = 5;
		    mon_endurance = 2;
		    break;
		default:
		    mon_strength = 0;
		    mon_endurance = 1;
		    race = "Not found";
		    break;
		}
	    }

	    else if (star_race.equals("Seg")) {
		env_type = race.charAt(11);
		switch (env_type) {
		case 'U':
		    mon_strength = 6;
		    mon_endurance = 4;
		    break;
		case 'L':
		    mon_strength = 5;
		    mon_endurance = 2;
		    break;
		default:
		    mon_strength = 0;
		    mon_endurance = 1;
		    race = "Not found";
		    break;
		}
	    }

	    else if (star_race.equals("Suv")) {
		env_type = race.charAt(8);
		switch (env_type) {
		case 'U':
		    mon_strength = 6;
		    mon_endurance = 2;
		    break;
		case 'L':
		    mon_strength = 7;
		    mon_endurance = 4;
		    break;
		default:
		    mon_strength = 0;
		    mon_endurance = 1;
		    race = "Not found";
		    break;
		}
	    }

	    else if (star_race.equals("Pio")) {
		env_type = race.charAt(9);
		switch (env_type) {
		case 'U':
		    mon_strength = 4;
		    mon_endurance = 4;
		    break;
		case 'S':
		    mon_strength = 6;
		    mon_endurance = 6;
		    break;
		default:
		    mon_strength = 0;
		    mon_endurance = 1;
		    race = "Not found";
		    break;
		}
	    }

	    else if (star_race.equals("Xan")) {
		env_type = race.charAt(10);
		switch (env_type) {
		case 'F':
		    mon_strength = 8;
		    mon_endurance = 6;
		    break;
		default:
		    mon_strength = 0;
		    mon_endurance = 1;
		    race = "Not found";
		    break;
		}
	    }

	    else if (star_race.equals("Yes")) {
		env_type = race.charAt(8);
		switch (env_type) {
		case 'U':
		    mon_strength = 6;
		    mon_endurance = 2;
		    break;
		case 'A':
		    mon_strength = 6;
		    mon_endurance = 4;
		    break;
		default:
		    mon_strength = 0;
		    mon_endurance = 1;
		    race = "Yesters' Environ Not found";
		    break;
		}
	    }

	    else if (star_race.equals("Kay")) {
		env_type = race.charAt(8);
		switch (env_type) {
		case 'W':
		    mon_strength = 7;
		    mon_endurance = 6;
		    break;
		case 'S':
		    mon_strength = 6;
		    mon_endurance = 4;
		    break;
		default:
		    mon_strength = 0;
		    mon_endurance = 1;
		    race = "Not found";
		    break;
		}
	    }

	    else {
		mon_strength = 0;
		mon_endurance = 1;
		race = "Race Not Found";
	    }
	}

	new monGUI(this, race).show();
	// monsterTest(race);

	if (CheckEmpty())
	    return(true);	

	return false;
    }

    /** Sets the strength and endurance of a particular Monster */
    private void MonsterStats(String monster)
    {
	mon_duration = -1;
	// mon_regen = 0;
	mon_surprise = 0;
	mon_breakoff = 0;

	if (monster.equals("Alweg")) {
	    mon_strength = 8;
	    mon_endurance = 1;
	    mon_duration = 1;
	}
	else if (monster.equals("Arags")) {
	    mon_strength = 4;
	    mon_endurance = 3;
	}
	else if (monster.equals("Batranoban")) {
	    mon_strength = 4;
	    mon_endurance = 3;
	    mon_surprise = 1;
	}
	else if (monster.equals("Chantenes")) {
	    mon_strength = 5;
	    mon_endurance = 5;
	    // mon_regen = 1;
	}
	else if (monster.equals("Chardireeds")) {
	    mon_strength = 4;
	    mon_endurance = 4;
	    mon_surprise = 1;
	}
	else if (monster.equals("Chlorofix")) {
	    mon_strength = 0;
	    mon_endurance = 1;
	    // mon_delay = 1;
	}
	else if (monster.equals("Crunge")) {
	    mon_strength = 2;
	    mon_endurance = 1;
	}
	else if (monster.equals("Derigion")) {
	    mon_strength = 4;
	    mon_endurance = 6;
	}
	else if (monster.equals("Dindin")) {
	    mon_strength = 7;
	    mon_endurance = 5;
	    mon_breakoff = 1;
	}
	else if (monster.equals("Drusers")) {
	    mon_strength = 5;
	    mon_endurance = 5;
	}
	else if (monster.equals("Drants")) {
	    mon_strength = 6;
	    mon_endurance = 1;
	    mon_duration = 1;
	}
	else if (monster.equals("Elilad")) {
	    mon_strength = 2;
	    mon_endurance = 31;
	}
	else if (monster.equals("Fog")) {
	    mon_strength = 0;
	    mon_endurance = 5;
	}
	else if (monster.equals("Frost mist")) {
	    mon_strength = 5;
	    mon_endurance = 5;
	}
	else if (monster.equals("Gach")) {
	    mon_strength = 7;
	    mon_endurance = 6;
	    // mon_regen = -1;
	}
	else if (monster.equals("Gadhars")) {
	    mon_strength = 5;
	    mon_endurance = 4;
	    // mon_regen = .5;
	}
	else if (monster.equals("Gamels")) {
	    mon_strength = 3;
	    mon_endurance = 2;
	}
	else if (monster.equals("Gilekite")) {
	    mon_strength = 3;
	    mon_endurance = 3;
	    mon_surprise = 2;
	}
	else if (monster.equals("Glane")) {
	    mon_strength = 6;
	    mon_endurance = 6;
	    firefight = true;
	}
	else if (monster.equals("Gragg")) {
	    mon_strength = 3;
	    mon_endurance = 2;
	    mon_surprise = 1;
	}
	else if (monster.equals("Gyrogos")) {
	    mon_strength = 6;
	    mon_endurance = 31;
	    mon_breakoff = -1;
	}
	else if (monster.equals("Hysnatons")) {
	    mon_strength = 5;
	    mon_endurance = 4;
	}
	else if (monster.equals("Kinsog")) {
	    mon_strength = 3;
	    mon_endurance = 2;
	    mon_surprise = 2;
	}
	else if (monster.equals("Laboroid")) {
	    mon_strength = 3;
	    mon_endurance = 3;
	    mon_surprise = 2;
	}
	else if (monster.equals("Lomrels")) {
	    mon_strength = 5;
	    mon_endurance = 3;
	}
	else if (monster.equals("Leonus")) {
	    mon_strength = 5;
	    mon_endurance = 4;
	    mon_surprise = 1;
	}
	else if (monster.equals("Magron")) {
	    mon_strength = 1;
	    mon_endurance = 5;
	}
	else if (monster.equals("Mish")) {
	    mon_strength = 6;
	    mon_endurance = 3;
	}
	else if (monster.equals("Morna")) {
	    mon_strength = 6;
	    mon_endurance = 4;
	}
	else if (monster.equals("Muggers")) {
	    mon_strength = 5;
	    mon_endurance = 4;
	    mon_duration = 3;
	}
	else if (monster.equals("Namdasn")) {
	    mon_strength = 4;
	    mon_endurance = 4;
	    mon_surprise = 2;
	}
	else if (monster.equals("Onflam")) {
	    mon_strength = 6;
	    mon_endurance = 2;
	    mon_breakoff = 1;
	}
	else if (monster.equals("Propang")) {
	    mon_strength = 5;
	    mon_endurance = 3;
	    mon_breakoff = 1;
	}
	else if (monster.equals("Prox")) {
	    mon_strength = 6;
	    mon_endurance = 4;
	    mon_breakoff = -1;
	}
	else if (monster.equals("Queemer")) {
	    mon_strength = 3;
	    mon_endurance = 5;
	}
	else if (monster.equals("Rotron")) {
	    mon_strength = 3;
	    mon_endurance = 3;
	}
	else if (monster.equals("Sandiabs")) {
	    mon_strength = 0;
	    mon_endurance = 3;
	}
	else if (monster.equals("Skekers")) {
	    mon_strength = 6;
	    mon_endurance = 2;
	}
	else if (monster.equals("Snorkas")) {
	    mon_strength = 8;
	    mon_endurance = 1;
	    mon_duration = 1;
	}
	else if (monster.equals("Snow Giants")) {
	    mon_strength = 6;
	    mon_endurance = 4;
	}
	else if (monster.equals("Spithid")) {
	    mon_strength = 6;
	    mon_endurance = 1;
	}
	else if (monster.equals("Stromuse")) {
	    mon_strength = 2;
	    mon_endurance = 2;
	    mon_surprise = 3;
	}
	else if (monster.equals("Synestins")) {
	    mon_strength = 3;
	    mon_endurance = 3;
	}
	else if (monster.equals("Telebots")) {
	    mon_strength = 3;
	    mon_endurance = 3;
	}
	else if (monster.equals("Thinagig")) {
	    mon_strength = 8;
	    mon_endurance = 8;
	    mon_breakoff = -2;
	}
	else if (monster.equals("Thunk")) {
	    mon_strength = 5;
	    mon_endurance = 4;
	}
	else if (monster.equals("Valaterix")) {
	    mon_strength = 0;
	    mon_endurance = 3;
	}
	else if (monster.equals("Verfusier")) {
	    mon_strength = 4;
	    mon_endurance = 3;
	}
	else if (monster.equals("Virus")) {
	    mon_strength = 10;
	    mon_endurance = 31;
	}
	else if (monster.equals("Vorozion")) {
	    mon_strength = 6;
	    mon_endurance = 3;
	    mon_duration = 3;
	}
	else if (monster.equals("Vrialta")) {
	    mon_strength = 10;
	    mon_endurance = 10;
	    firefight = true;
	}
	else if (monster.equals("Wyths")) {
	    mon_strength = 9;
	    mon_endurance = 4;
	}
	else if (monster.equals("Ym-Barror")) {
	    mon_strength = 4;
	    mon_endurance = 4;
	}
	else if (monster.equals("Zernipak")) {
	    mon_strength = 5;
	    mon_endurance = 4;
	}
	else if (monster.equals("Zop")) {
	    mon_strength = 0;
	    mon_endurance = 1;
	}
	else {
	    monster = "Not Found";
	    mon_strength = 0;
	    mon_endurance = 2;
	    mon_duration = 1;
	}
    }
    

    /** Sentry Combat is a special instance of monster combat where no
	monsters were in the environ.  Other than initialization, it is
	identical to mmonster combat.  
	num represents the number of sentry droids appearing.
	0 is returned if 1 or more characters survive.
	1 is returned if no characters survive.   */
    public boolean SentryCombat(int num) 
    {
	System.out.println("\nStarting Sentry Combat\n");

	mon_duration = 0;
	mon_surprise = 0;
	mon_breakoff = 0;
	
	if (num == 1) {
	    mon_strength = 4;
	    mon_endurance = 2;
	}
	else {
	    mon_strength = 7;
	    mon_endurance = 4;
	}
	
	new monGUI(this, "Sentry Robots").show(); 
	// monsterTest("Sentry Robots");
	
	if (CheckEmpty())
	    return(true);
	
	return(false);	
    }	 

    /** Returns the Charactr at the given index in a CharacterGroup */
    public Charactr getChar(int index) {
	Charactr c = (Charactr)(units.elementAt(index));
	return(c);
    }

    /** Returns a vector of Possessions owned in a CharacterGroup */
    public Vector PossessionList() {
	int i, j, k= 0;                    // iteration counters
	Vector pos = new Vector();         // character possession list
	Vector list = new Vector();        // group possession list
	Charactr c;                        // character holder
	
	if (side == 'i')
	    return(null);

	// for every character in group
	for (i = units.size() - 1; i >= 0; i--) {
	    c = (Charactr)(units.elementAt(i));      // c holds character at
                                                     //    index i
	    pos = c.getPossessions();                // pos is possesion list
	    
	    if (pos != null)                         // skip if no possessions
		for (j = pos.size() - 1; j >= 0; j--) {
		    list.add(k, pos.elementAt(j));   // concatenate vectors
		    k++;
		}
	}
	
	return(list);                      // return group possession list
    }

    /** Returns the total combat rating of all active Charactrs in a
	CharacterGroup */
    private int CharGroupStrength() {
	int i, total = 0;
	Charactr c;

	for (i = 0; i < units.size(); i++) {
	    c = (Charactr)(units.elementAt(i));
	    // if (c.getIsActive() == true)
		// if (c.getIsPrisoner() == false)
		total += c.getCombat();
	}

	return(total);
    }

    /** Calculate wounds to assign and call AssignWounds to handle
	modification of the Characters
	returns 2 if defending CharacterGroup is eliminated,
	        1 if attacking CharacterGroup is eliminated,
	        0 if neither is eliminated */
    public int CombatResults(Group att) 
    {
	int indexx, indexy, damage;
	Random die = new Random();

	indexx = xIndex();           // finds x index for combat results table
	indexy = die.nextInt(6);     // generates a random number (0 - 5) for
	                             //  attacker's attack :P
	
	damage = charcomtable[indexx][indexy][2];
	if (firefight)
	    damage = damage * 2;

	// Assigns appropriate damage to the defender
	assignWounds(damage);

	System.out.println("Defenders took " + damage + "wounds.\n");

	if (capture)                                  // if capture combat is
	    if (charcomtable[indexx][indexy][3] == 1) //   taking place, check
		CreatePrisoner(att);                  //   for unit capture

	// if there are still defenders
	if (!CheckEmpty()) {
	    indexx = xIndex();       // redetermines x index in case characters
	                             //   have died
	    indexy = die.nextInt(6); // rolls die for defender's attack
	    
	    damage = charcomtable[indexx][indexy][0];
	    if (firefight)
		damage = damage * 2;
	    
	    // Assigns appropriate damage to the attacker
	    if (att.getType() == 'c') {
		att.assignWounds(damage);
	    }
	    else if (att.getType() == 'm')
		att_strength -= (damage);
	    else {
		System.out.println("\n**Group Type not assigned.");
		System.out.println("**Exiting combat.\n\n");
		return(1);
	    }

	    System.out.println("Attackers took " + damage + "wounds.\n");

	    if (capture)                                  // check for captures
		if (charcomtable[indexx][indexy][1] == 1) //   if applicable
		    CreatePrisoner(att);
	}
	// there are no defenders left
	else
	    return(2);
	
	// there are no attackers left
	if (att_strength <= 0)
	    return(1);

	// both Groups are still alive
	return(0);
    }

    /** Monster Combat main phase.
        Returns true if all Characters or monster dies,
        returns false otherwise */
    public boolean MonsterCombatResults()
    {
	int indexx, indexy;
	int damage;
	
	Random die = new Random();

	att_strength = mon_strength;
	def_strength = CharGroupStrength();
	
	indexx = xIndex();
	indexy = die.nextInt(6);
	
	damage = charcomtable[indexx][indexy][2];

	if (firefight)
	    damage = damage * 2;

	System.out.println("*** Your characters took " +
			   damage + " wounds\n");

	// Assigns appropriate damage to the defender
	assignWounds(damage);
	
	if (!CheckEmpty()) {
	    indexx = xIndex();
	    indexy = die.nextInt(6);
	    
	    damage = charcomtable[indexx][indexy][0];

	    if (firefight)
		damage = damage * 2;

	    System.out.println("*** You dealt " +
			       damage +
			       " wounds to the monster.\n");
	    
	    mon_endurance -= damage;
	}
	else
	    return(true);
	
	if (mon_endurance <= 0)
	    return(true);
	
	return(false);
    }

    /** Checks to see if a break away attempt passed or failed */
    public boolean BreakAway(CharacterGroup att)
    {
	int indexx, randomroll, i;
	Charactr c;

	Random die = new Random();
	att_strength = att.CharGroupStrength();

	indexx = xIndex();

	randomroll = die.nextInt(6);

	if (randomroll <= breaktable[indexx][0])
	    return(true);

	else if (randomroll <= breaktable[indexx][1]) {
	    for (i = 0; i < units.size(); i++) {
		c = (Charactr)(units.elementAt(i));
		if (!c.getIsActive()) {
		    inactive.add(c);
		    units.remove(c);
		}
	    }
	    inactive_check = true;
	}

	else
	    break_fail = true;
	
	return(false);
	
    }

    /** Checks to see if a break away attempt passed for monster combat */
    public boolean BreakAway()
    {
	int indexx, randomroll, i;
	Charactr c;

	Random die = new Random();
	att_strength = mon_strength;

	indexx = xIndex();

	indexx += mon_breakoff;

	randomroll = die.nextInt(6);

	if (randomroll <= breaktable[indexx][0])
	    return(true);

	else if (randomroll <= breaktable[indexx][1])
	    for (i = 0; i < units.size(); i++) {
		c = (Charactr)(units.elementAt(i));
		if (!c.getIsActive()) {
		    inactive.add(c);
		    units.remove(c);
		}
	    }

	else
	    break_fail = true;
	
	return(false);
	
    }

    /** Returns the first index in Character Combat Results Table 3d
	array (Referred to sometimes as the x index of the array). */
    private int xIndex()
    {
	int combat_diff, indexx;

	def_strength = CharGroupStrength();        // defender's strength
	
	combat_diff = att_strength - def_strength; // difference between
	                                           //   strengths
	
	// This set of if/else statements determines the x index to access
	//   on the character combat result table
	if (combat_diff < -6)
	    indexx = 0;
	else if (combat_diff < -3)
	    indexx = 1;
	else if (combat_diff < -1)
	    indexx = 2;
	else if (combat_diff < 0)
	    indexx = 3;
	else if (combat_diff < 1)
	    indexx = 4;
	else if (combat_diff < 2)
	    indexx = 5;
	else if (combat_diff < 4)
	    indexx = 6;
	else if (combat_diff < 7)
	    indexx = 7;
	else if (combat_diff < 11)
	    indexx = 8;
	else
	    indexx = 9;
	
	// Capture combat shifts table two points in defender's favor
	if (capture == true)
	    indexx -= 2;
	
	// If the defender's tried to break off this round, there is a
	//   shift of one point in the attacker's favor.
	if (break_fail == true) {
	    indexx  += 1;
	    break_fail = false;
	}
	
	// Monster's may surprise characters and gain an advantage on the
        //   results table
	if (mon_surprise > 0) {
	    indexx += mon_surprise;
	    mon_surprise = 0;
	}  
	
	return(indexx);
    }

    /** Creates prisoners and adds them to the attacking Group */
    private void CreatePrisoner(Group att) 
    {
	int randint;
	Random rand = new Random();
	Charactr c;

	randint = rand.nextInt(units.size()); // randomly choose defender
	c = (Charactr)(getChar(randint));     // cast c as defender
	c.setIsPrisoner(true);                // assign c as a prisoner
	att.add(c);                           // add c to attacker group
	remove(c);                            // remove prisoner from defense
    }
    
    /** Textual Test Function for Monster Combat */
    private void monsterTest(String enemy)
    {
	int i, j;
	Charactr c;
	boolean combat = false;

	while (!combat) {
	    for (i = 0; i < units.size(); i++) {
		c = (Charactr)(units.elementAt(i));
		if (!c.getIsPrisoner()) {
		    System.out.println(c.getCharName() + 
				   ":  Combat - " + c.getCombat() +
				       "   Endurance - " + c.getEndurance() +
				       "   Wounds - " 
				       + (c.getEndurance() - c.getLife()) +
				       "\n");
		}
	    }

	    def_strength = CharGroupStrength();

	    System.out.println("Character Group Strength - " + def_strength);
	
	    System.out.println("\nVersus\n");
	    
	    System.out.println(enemy + ":  Combat - " + mon_strength +
			       "   Endurance - " + mon_endurance + "\n");
	    
	    combat = MonsterCombatResults();

	}

	    if (mon_endurance <= 0)
		System.out.println("Monster killed!\n");
	    else
		System.out.println("All Characters defeated!\n");
    }

    /** Textual Test Function for Character vs. Character Combat */
    private void charFightTest(CharacterGroup att)
    {
	int i, j, combat = 0;
	Charactr c;
	boolean breakoff = false;

	def_strength = CharGroupStrength();
	att_strength = att.CharGroupStrength();

	while (combat == 0 && breakoff == false) {
	    for (i = 0; i < units.size(); i++) {
		c = (Charactr)(units.elementAt(i));
		if (!c.getIsPrisoner()) {
		    System.out.println(c.getCharName() + 
				   ":  Combat - " + c.getCombat() +
				       "   Endurance - " + c.getEndurance() +
				       "   Wounds - " 
				       + (c.getEndurance() - c.getLife()) +
				       "\n");
		}
	    }
	    System.out.println("Defending Group Strength - " + def_strength);
	
	    System.out.println("\nVersus\n");
	    
	    for (i = 0; i < att.units.size(); i++) {
		c = (Charactr)(att.units.elementAt(i));
		if (!c.getIsPrisoner()) {
		    System.out.println(c.getCharName() + 
				       ":  Combat - " + c.getCombat() +
				       "   Endurance - " + c.getEndurance() +
				       "   Wounds - " 
				       + (c.getEndurance() - c.getLife()) +
				       "\n");
		}
	    }
	    System.out.println("Attacking Group Strength - " + att_strength);

	    // System.out.println("Defender: (F)ight or (B)reak?");
	    // break_fail = false;

	    //	    if (input == 'B')
	    //		breakoff = BreakAway();

	    //	    if (!breakoff)
		combat = CombatResults(att);
	    
	}
	
	if (combat == 1)
	    System.out.println("Enemy defeated!\n");
	else if (combat == 2)
	    System.out.println("You have been defeated!\n");

	//	else
	//	    System.out.println("Successful Break.");
	
	//	if (!inactive.isEmpty())
	//	    for (i = inactive.size() - 1; i >= 0; i--) {
	//		c = (Charactr)(units.elementAt(i));
	//		add(c);
	//		inactive.remove(c);
	//	    }
    }

    /** Text test function for Military vs. Character Combat */
    private void squadFightTest(MilitaryGroup att)
    {
	
	int i, j, combat = 0, milstr, milend;
	Charactr c;
	boolean breakoff = false;
	Unit u;
	CharacterGroup chars = new CharacterGroup(att.side);

	def_strength = CharGroupStrength();
	milstr = att.TotalCombatStrength();
	att_strength = (int)(milstr / 2);

	while (combat == 0 && breakoff == false) {
	    for (i = 0; i < units.size(); i++) {
		c = (Charactr)(units.elementAt(i));
		if (!c.getIsPrisoner()) {
		    System.out.println(c.getCharName() + 
				   ":  Combat - " + c.getCombat() +
				       "   Endurance - " + c.getEndurance() +
				       "   Wounds - " 
				       + (c.getEndurance() - c.getLife()) +
				       "\n");
		}
	    }
	    System.out.println("Defending Group Strength - " + def_strength);
	
	    System.out.println("\n**Versus**\n");

	    System.out.println("Military squads: Strength - " + att_strength +
			       "    Endurance - " + att_strength + "\n");
	   
	    // System.out.println("Defender: (F)ight or (B)reak?");
	    // break_fail = false;

	    //	    if (input == 'B')
	    //		breakoff = BreakAway();

	    //	    if (!breakoff)
		combat = CombatResults(att);
	    
	}
	
	if (combat == 1)
	    System.out.println("Enemy defeated!\n");
	else if (combat == 2)
	    System.out.println("You have been defeated!\n");

	//	else
	//	    System.out.println("Successful Break.");
	
	//	if (!inactive.isEmpty())
	//	    for (i = inactive.size() - 1; i >= 0; i--) {
	//		c = (Charactr)(units.elementAt(i));
	//		add(c);
	//		inactive.remove(c);
	//	    }
	
    }
}
