/// <summary>
    /// Gets a list with the monsters available on the AIs field sorted into
    /// strongest to weakest.
    /// </summary>
    /// <returns>The strongest to weakest monsters.</returns>
    /// <param name="ml">Monsterzone list to sort</param>
    protected List <DuelMonsterZoneScript> GetStrongestToWeakestMonsters(
        DuelMonsterZoneScript[] ml)
    {
        bool flag = true;

        for (int o = 1; (o < ml.Length) && flag; o++)           //Do an outer loop
        //around the array
        {
            flag = false;
            for (int i = 0; i < ml.Length - 1; i++)
            {
                //Foreach of the numbers next to the outer loop point
                if (((Monster)ml [i + 1].ZoneCard).Attack >
                    ((Monster)ml [i].ZoneCard).Attack)                       //Compare the attacks
                //Swap the monsters in the array
                {
                    DuelMonsterZoneScript temp = ml [i];
                    ml [i]     = ml [i + 1];
                    ml [i + 1] = temp;
                    flag       = true;
                }
            }
        }
        return(ml.ToList());         //Return the array back as list
    }
 /// <summary>
 /// Button to cancel the attack and close the overlay. Will also reset any
 /// variables that have been effected during the attack process
 /// </summary>
 public void btn_CloseOverlay()
 {
     attackingMonster.hasAttacked = false;         //Fixed a bug here!
     attackingMonster             = null;
     defendingMonster             = null;
     gameObject.SetActive(false);
 }
    /// <summary>
    /// Coroutine to conduct the animation and logic for a direct attack battle
    /// between the attacking monster and the defending monsters life points
    /// </summary>
    /// <returns>void</returns>
    /// <param name="attackingMonster">Attacking monster.</param>
    /// <param name="againstPlayer">If set to <c>true</c> against player.</param>
    public IEnumerator IMakeAttack(DuelMonsterZoneScript attackingMonster,
                                   bool againstPlayer)
    {
        yield return(new WaitForSeconds(1.0f));

        //This is when a direct attack has been made
        int attackersScore = ((Monster)attackingMonster.ZoneCard).Attack;
        int defendersScore = 0;
        int damage         = defendersScore - attackersScore;

        ui_attackersPicture.sprite = ((Monster)attackingMonster.ZoneCard).Image;
        ui_defendersPicture.sprite = null;
        ui_defendersPicture.color  = Color.black;
        ui_attackersDamage.text    = "";
        ui_defendersDamage.text    = damage.ToString();

        ui_attackingOverlay.SetActive(true);

        glob_audiomanager.SendMessage("PlayDuelDirectHit");
        yield return(new WaitForSeconds(2.1f));

        ui_attackingOverlay.SetActive(false);

        if (againstPlayer)
        {
            //This means the AI is attacking the player
            player_liveLifePoints -= attackersScore;
        }
        else
        {
            //The player is attacking the AI directly
            duel_ai.ai_liveLifePoints -= attackersScore;
        }
    }
    /// <summary>
    /// Coroutine to begin a battle between an attacking monster and a direct
    /// attack against the opponent
    /// </summary>
    /// <returns>void</returns>
    /// <param name="attackingMonster">Attacking monster.</param>
    /// <param name="againstPlayer">If set to <c>true</c> against player.</param>
    public IEnumerator IPlayerBattle(DuelMonsterZoneScript attackingMonster,
                                     bool againstPlayer)
    {
        yield return(StartCoroutine(IMakeAttack(attackingMonster, false)));

        yield return(new WaitForSeconds(1.0f));

        yield return(StartCoroutine(IReduceLifePoints()));
    }
 /// <summary>
 /// Logic for the AI setting a monster
 /// </summary>
 /// <returns>void</returns>
 /// <param name="emptyZone">Empty monster zone to set the card too</param>
 /// <param name="cardToSet">Card to set</param>
 protected IEnumerator ISetMonster(DuelMonsterZoneScript emptyZone,
                                   Monster cardToSet)
 {
     Debug.Log("AI: Setting " + cardToSet.Name);
     duel_controller.ShowMessageFromAI(ai_details.ai_image,
                                       ai_details.speech_SetCard); //Display message
     emptyZone.PlaceCardOnZone(cardToSet, true);
     ai_hand.Remove(cardToSet);                                    //Remove card from the AI's hand
     yield return(new WaitForSeconds(1.3f));
 }
 /// <summary>
 /// Logic for the AI to summon a monster
 /// </summary>
 /// <returns>void</returns>
 /// <param name="emptyZone">Empty monster zone to summon the card too</param>
 /// <param name="cardToSummon">Card to summon to the empty zone</param>
 protected IEnumerator ISummonMonster(DuelMonsterZoneScript emptyZone,
                                      Monster cardToSummon)
 {
     Debug.Log("AI: Summoning " + cardToSummon.Name);
     //Show summoning message
     duel_controller.ShowMessageFromAI(ai_details.ai_image,
                                       ai_details.speech_SummonCard + cardToSummon.Name);
     //Start the summoning sequence and animation in the DuelMonsterZoneScript
     emptyZone.PlaceCardOnZone(cardToSummon, false);
     //Since the card has been played onto the field, we can
     //now remove it from the AIs hand
     ai_hand.Remove(cardToSummon);
     yield return(new WaitForSeconds(1.3f));
 }
 /// <summary>
 /// Called when the user presses one of the UI buttons over the AI monster
 /// zone. Gets the defending monsters details depending on which button it
 /// was that was pressed.
 /// </summary>
 /// <param name="positionOnField">Position of targeted monster</param>
 public void btn_Selected(int positionOnField)
 {
     //Get the defending monster details
     defendingMonster =
         duelControllerScript.ui_ai_monsterZones [positionOnField];
     //Start the battle sequence/animation
     duelControllerScript.StartCoroutine(
         duelControllerScript.IPlayerBattle(
             attackingMonster,
             defendingMonster, false));
     //Close down this overlay
     attackingMonster = null;
     defendingMonster = null;
     gameObject.SetActive(false);
 }
    /// <summary>
    /// Logic for making a direct attack
    /// </summary>
    /// <returns>void</returns>
    /// <param name="cardToAttack">Card zone attacking with</param>
    protected IEnumerator IDirectAttack(DuelMonsterZoneScript cardToAttack)
    {
        duel_controller.ShowMessageFromAI(ai_details.ai_image,
                                          ai_details.speech_DirectAttack + cardToAttack.ZoneCard.Name);
        //Output message
        yield return(new WaitForSeconds(1.3f));

        yield return(StartCoroutine(duel_controller.
                                    IMakeAttack(cardToAttack, true))); //Start the animation/sequence

        yield return(new WaitForSeconds(0.7f));

        //Reduce the life points of either the Player or AI depending on who
        //took what damage
        yield return(StartCoroutine(duel_controller.IReduceLifePoints()));
    }
    /// <summary>
    /// Method for getting the first avaialble Monster Zone of the players
    /// field
    /// </summary>
    /// <returns>The empty monster zone script</returns>
    private DuelMonsterZoneScript getEmptyMonsterZone()
    {
        DuelMonsterZoneScript returnScript = null;

        if (!isMonsterZonesFull())            //No point continuing if the zones are full
        {
            foreach (DuelMonsterZoneScript zone in
                     duelController.ui_playerMonsterZones)
            {
                if (zone.ZoneCard == null)
                {
                    returnScript = zone;
                    break;
                }
            }
        }
        return(returnScript);
    }
    /// <summary>
    /// Logic for the AI attackin a monster with one of its own
    /// </summary>
    /// <returns>void</returns>
    /// <param name="attackingMonster">Attacking monster.</param>
    /// <param name="defendingMonster">Defending monster.</param>
    protected IEnumerator IMakeAttack(DuelMonsterZoneScript attackingMonster,
                                      DuelMonsterZoneScript defendingMonster)
    {
        duel_controller.ShowMessageFromAI(ai_details.ai_image,
                                          ai_details.speech_NormalAttack + attackingMonster.ZoneCard.Name);
        //Output message and wait
        yield return(new WaitForSeconds(1.3f));

        yield return(StartCoroutine(duel_controller.
                                    IMakeAttack(attackingMonster, defendingMonster, true))); //Start

        //the attacking sequence/animation
        yield return(new WaitForSeconds(0.7f));         //Wait

        //Reduce the Life Points of either the Player or AI depending on who
        //took the damage
        yield return(StartCoroutine(duel_controller.IReduceLifePoints()));
    }
    /// <summary>
    /// Gets the first empty monster zone on the AI's side of the field
    /// </summary>
    /// <returns>The first empty monster zone.</returns>
    protected DuelMonsterZoneScript GetFirstEmptyMonsterZone()
    {
        DuelMonsterZoneScript returnScript = null; //The returned zone

        if (!isMonsterZonesFull())                 //If the monster zones are all full
        //then no point in even going into the loop
        {
            foreach (DuelMonsterZoneScript zone in ai_monsterzones)
            {
                if (zone.ZoneCard == null)                   //Check if the zonecard is null
                //If it is null then it means a monster doesn't occupy
                //that space and we can return it
                {
                    returnScript = zone;
                    break;
                }
            }
        }
        return(returnScript);
    }
    /// <summary>
    /// Gets the strongest monster on player field.
    /// </summary>
    /// <returns>The strongest monster on player field.</returns>
    public DuelMonsterZoneScript GetStrongestMonsterOnPlayerField()
    {
        DuelMonsterZoneScript returnCard = null;
        int flaggedStrongest             = 0;

        foreach (DuelMonsterZoneScript mon in ui_playerMonsterZones)
        {
            //foreach monster card in the monster card zone
            if (mon.ZoneCard != null)               //If it's not empty
            {
                DuelMonsterZoneScript temp = mon;
                //Compare the monsters attack with the previously found attack
                if (((Monster)mon.ZoneCard).Attack > flaggedStrongest)
                {
                    //Assign it
                    flaggedStrongest = ((Monster)mon.ZoneCard).Attack;
                    returnCard       = temp;
                }
            }
        }
        return(returnCard);        //Return
    }
 /// <summary>
 /// Command executed when the UI button in the Monster position selection
 /// menu is pressed. Depending if facedown is selected or not will
 /// depend on how the game places the card onto the screen/field
 /// </summary>
 /// <param name="facedown">If set to <c>true</c> facedown.</param>
 public void btn_PlaceMonsterCard(bool facedown)
 {
     glob_audiomanager.SendMessage("PlayClickB");
     if (temp != null && temp is Monster)           //Only do this if it is a monster!
     {
         Monster monster          = (Monster)temp;
         DuelMonsterZoneScript dz = getEmptyMonsterZone();              //Get empty zone
         //to assign this card to
         if (dz != null)
         {
             Debug.Log("DuelCardScannerScript: Player summoning " +
                       monster.Name);
             //Play the animation/sequence for displaying the card
             dz.PlaceCardOnZone(monster, facedown);
             CloseSafely();
         }
         else
         {
             Debug.Log("DuelCardScannerScript: Monster Zones full");
             //Display error message
         }
     }
 }
    /// <summary>
    /// Coroutine to conduct the animation and logic for a battle involving
    /// an attacking monster and the defending monster.
    /// </summary>
    /// <returns>void</returns>
    /// <param name="attackingMonster">Attacking monster.</param>
    /// <param name="defendingMonster">Defending monster.</param>
    /// <param name="againstPlayer">If set to <c>true</c> against player.</param>
    public IEnumerator IMakeAttack(DuelMonsterZoneScript attackingMonster,
                                   DuelMonsterZoneScript defendingMonster, bool againstPlayer)
    {
        yield return(new WaitForSeconds(1.0f));

        int attackersScore = ((Monster)attackingMonster.ZoneCard).Attack;
        int defendersScore = 0;

        //Decided whether we are using the defenders Defence or Attack score
        if (defendingMonster.isDefenceMode)
        {
            //Use defence mode score
            defendersScore = ((Monster)defendingMonster.ZoneCard).Defence;
        }
        else
        {
            //Use attack mode score
            defendersScore = ((Monster)defendingMonster.ZoneCard).Attack;
        }
        //Workout the damage
        int damage = defendersScore - attackersScore;
        int lifePointsToReduceBy = 0;

        //Assign monster images
        ui_attackersPicture.sprite = ((Monster)attackingMonster.ZoneCard).Image;
        ui_defendersPicture.color  = Color.white;        //Reset incase a direct
        //attack as happened as the black with hide the picutre we set
        ui_defendersPicture.sprite = ((Monster)defendingMonster.ZoneCard).Image;
        //Check what damage is done to what card
        if (damage <= 0)
        {
            ui_attackersDamage.text = "";
            ui_defendersDamage.text = damage.ToString();
        }
        else
        {
            ui_attackersDamage.text = (-damage).ToString();
            ui_defendersDamage.text = "";
        }
        //Display the Attackers overlay
        ui_attackingOverlay.SetActive(true);
        glob_audiomanager.SendMessage("PlayDuelDirectHit");
        yield return(new WaitForSeconds(2.1f));

        ui_attackingOverlay.SetActive(false);
        //Work out, which monster(s) gets destroyed and the life points to
        //reduce
        if (damage < 0)
        {
            //Defending monster is destroyed
            if (!defendingMonster.isDefenceMode)
            {
                lifePointsToReduceBy = -damage;
            }
            yield return(StartCoroutine(
                             defendingMonster.IDestroyCard(againstPlayer)));
        }
        else if (damage == 0 && !defendingMonster.isDefenceMode)
        {
            //When the battle is a tie and the monster is in defence, then
            //no monsters are destroyed, otherwise...
            yield return(StartCoroutine(
                             defendingMonster.IDestroyCard(againstPlayer)));

            yield return(StartCoroutine(
                             attackingMonster.IDestroyCard(!againstPlayer)));
            //Damage would be 0 because Attack was equal
            //Therefore we do not touch the lifepoints to reduce variable
        }
        else
        {
            //The attacking monster is weaker than the opponents defending,
            //so destroy the attacking monster
            yield return(StartCoroutine(
                             attackingMonster.IDestroyCard(againstPlayer)));

            lifePointsToReduceBy = damage;
            //Reverse the damage because the attacker is taking the damage
            againstPlayer = !againstPlayer;
        }
        //Do damage to the appropriate player
        if (againstPlayer)
        {
            player_liveLifePoints -= lifePointsToReduceBy;
        }
        else
        {
            duel_ai.ai_liveLifePoints -= lifePointsToReduceBy;
        }
        canPlayerAttack       = checkCanPlayerAttack();
        canPlayerDirectAttack = checkCanPlayerDirectAttack();
        yield return(new WaitForSeconds(0.5f));
    }
 /// <summary>
 /// Called when the Player selects a monster on his/her side of the field
 /// and selects the attack option. Brings up this overlay
 /// </summary>
 /// <param name="aMonster">Selected monster</param>
 public void StartTargetSelection(DuelMonsterZoneScript aMonster)
 {
     attackingMonster = aMonster;         //Assign it to the attacking monster pos
 }
 /// <summary>
 /// Shows the card options overlay when a monster zone has been selected
 /// </summary>
 /// <param name="selectedCard">Selected card.</param>
 public void ShowCardOptionsOverlay(DuelMonsterZoneScript selectedCard)
 {
     selectedZone = selectedCard;         //Assign the selected card to the var
     //so when one of the button functions is called it knows which card
     //to check/use
 }
    /// <summary>
    /// Executes all the logic done in the Main Phase 1 of the AIs turn
    /// Typically this is all logic to do with summoning a monster
    /// </summary>
    /// <returns>void</returns>
    protected IEnumerator MainPhase1()
    {
        //Use this space for activiating Spell/Trap cards and Summoning monsters
        Debug.Log("AI: Entering Main Phase 1");
        duel_controller.ChangeTurnPhase(DuelSceneScript.TurnPhase.MAINPHASE1);
        //Setup variables used in checking
        DuelMonsterZoneScript emptyZone;
        Monster strongestInHand;
        Monster aStrongestField;
        Monster pStrongestField;
        Monster aDefenseInHand;

        //Monster aDefenseOnField;
        if (canSummon && !isMonsterZonesFull())
        {
            Debug.Log("AI: Can summon a monster");
            //Then we can summon a monster
            emptyZone = GetFirstEmptyMonsterZone();
            if (duel_controller.turnCounter <= 1)               //If AI is playing first turn,
            //Then let us pick the strongest monster and place it in attack
            {
                Monster monster = GetHighestAttackMonsterInHand();
                if (monster != null && emptyZone != null)
                {
                    yield return(StartCoroutine(
                                     ISummonMonster(emptyZone, monster)));
                }
            }
            else               //Otherwise lets check the Player field and make a decision
            {
                strongestInHand = GetHighestAttackMonsterInHand();
                aStrongestField = GetHighestAttackMonsterOnField();

                DuelMonsterZoneScript tempFind =
                    duel_controller.GetStrongestMonsterOnPlayerField();
                pStrongestField = (tempFind != null) ?
                                  (Monster)tempFind.ZoneCard : null;
                //
                if (pStrongestField == null)
                {
                    //The players field is empty! We can summon our strongest
                    //monster and go for a direct attack!
                    if (strongestInHand != null && emptyZone != null)
                    {
                        //We have space on our field and got a monster from
                        //our hand. We can now summon it!
                        yield return(StartCoroutine(
                                         ISummonMonster(emptyZone, strongestInHand)));
                    }
                }
                else                   //The player has a monster on the field
                {
                    if (strongestInHand != null && aStrongestField != null)
                    {
                        //The AIs hand is not empty and the AI's field is not
                        //empty
                        if (strongestInHand.Attack >= pStrongestField.Attack ||
                            aStrongestField.Attack >= pStrongestField.Attack)
                        {
                            yield return(StartCoroutine(
                                             ISummonMonster(emptyZone, strongestInHand)));
                        }
                        else
                        {
                            goDefensive = true;
                        }
                    }
                    else if (strongestInHand != null)
                    {
                        //The AIs hand is not empty but the field may be empty
                        if (strongestInHand.Attack >= pStrongestField.Attack)
                        {
                            yield return(StartCoroutine(
                                             ISummonMonster(emptyZone, strongestInHand)));
                        }
                        else
                        {
                            goDefensive = true;
                        }
                    }
                    else if (aStrongestField != null)
                    {
                        //The AI's field is not empty but the hand might be
                        if (aStrongestField.Attack >= pStrongestField.Attack)
                        {
                            if (aStrongestField.Attack == pStrongestField.Attack &&
                                ai_monsterzones.Count > 1)
                            {
                                //When the AI has a monster of equal attack
                                //which is can 'throw away' in a monster for
                                //monster battle but still have monsters to
                                //defend or attack with
                                if (strongestInHand != null)
                                {
                                    yield return(StartCoroutine(
                                                     ISummonMonster(emptyZone,
                                                                    strongestInHand)));
                                }
                            }
                        }
                        else
                        {
                            //The AI has nothing strong enough, go defensive
                            goDefensive = true;
                        }
                    }
                }
            }
        }
        else
        {
            //AI cannot summon or monster zones are full
            Debug.Log("AI: Cannot summon a monster");
            //Check field to see if the AI needs to go defensive as we cannot
            //summon this turn
            aStrongestField = GetHighestAttackMonsterOnField();
            pStrongestField =
                (Monster)duel_controller.
                GetStrongestMonsterOnPlayerField().ZoneCard;

            if (pStrongestField != null)
            {
                if (aStrongestField != null)
                {
                    if (aStrongestField.Attack < pStrongestField.Attack)
                    {
                        goDefensive = true;
                    }
                }
                else
                {
                    goDefensive = true;
                }
            }
        }

        if (goDefensive && canSummon && !isMonsterZonesFull())
        {
            //Check if we can place a Facedown defense position mosnter
            //instead
            Debug.Log("AI: going defensive");
            emptyZone      = GetFirstEmptyMonsterZone();
            aDefenseInHand = GetHighestDefenceMonsterInHand();
            if (aDefenseInHand != null && emptyZone != null)
            {
                yield return(StartCoroutine(ISetMonster(emptyZone,
                                                        aDefenseInHand)));
            }
        }
    }
    /// <summary>
    /// Executes all logic for the AIs Battle Phase. Normally has to do with
    /// selecting which monster battles or if the AI can directly attack the
    /// player
    /// </summary>
    /// <returns>void</returns>
    protected IEnumerator BattlePhase()
    {
        //You cannot conduct a Battle Phase on your first turn, therefore
        Debug.Log("AI: Entering Battle Phase");
        duel_controller.ChangeTurnPhase(DuelSceneScript.TurnPhase.BATTLEPHASE);
        //Get a list of monsters that are able to attack first!
        //First check if the opponents field is empty
        List <DuelMonsterZoneScript> ml = GetMonstersAvailableToAttack();

        //If the list is empty, then no point in doing any more check!
        if (ml != null && ml.Count > 0)
        {
            //Avaialble for a direct attack?
            if (canDirectAttack())
            {
                Debug.Log("AI: Is able to make a direct attack");
                foreach (DuelMonsterZoneScript monster in ml)
                {
                    yield return(StartCoroutine(IDirectAttack(monster)));
                }
            }
            else
            {
                //Player has some monsters on the field
                //Scan field and pair AI monsters to attack/stats of Players
                Debug.Log("AI: Cannot make a direct attack");
                if (!goDefensive)
                {
                    ml = GetStrongestToWeakestMonsters(ml.ToArray());

                    for (int i = 0; i < ml.Count; i++)
                    {
                        if (canDirectAttack())
                        {
                            //Direct attack
                            yield return(StartCoroutine(
                                             IDirectAttack(ml[i])));
                        }
                        else
                        {
                            //Get the strongest monster on the field, or next
                            //strongest monster as the AI counts downwards
                            //from it's strongest monster
                            DuelMonsterZoneScript pMonster = duel_controller.
                                                             GetStrongestMonsterOnPlayerField();
                            //Compare and attack
                            //Check first if the defending monster is in defence
                            //mode or attack mode
                            if (pMonster != null)
                            {
                                if (pMonster.isDefenceMode)
                                {
                                    //Monster is in defence
                                    if (((Monster)ml [i].ZoneCard).Attack >
                                        ((Monster)pMonster.ZoneCard).Defence)
                                    {
                                        //Attack the defensive monster!
                                        yield return(StartCoroutine(
                                                         IMakeAttack(ml [i], pMonster)));
                                    }
                                }
                                else
                                {
                                    if (((Monster)ml [i].ZoneCard).Attack >=
                                        ((Monster)pMonster.ZoneCard).Attack)
                                    {
                                        //Attack the attacking monster,
                                        //this AI is going all out!
                                        yield return(StartCoroutine(
                                                         IMakeAttack(ml [i], pMonster)));
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    Debug.Log("AI: Going defensive so not conducting battle");
                }
            }
        }
        else
        {
            Debug.Log("AI: No monsters available to attack");
        }
    }