예제 #1
0
        public static CardInstance FindIdenticalCardInSource(IList <CardInstance> source, CardInstance card, IList <CardInstance> exclusions = null, bool failureOkay = false)
        {
            if (exclusions == null)
            {
                exclusions = new List <CardInstance>();
            }
            CardInstance res = null;
            var          cs  = card.ToString();

            foreach (var c in source)
            {
                if (!exclusions.Contains(c) && c.ToString() == cs)
                {
                    return(c);
                }
            }
            if (res == null)
            {
                if (failureOkay)
                {
                    return(null);
                }
                throw new Exception("No card.");
            }
            return(res);
        }
예제 #2
0
        public void Exhaust(CardInstance ci, EffectSet ef)
        {
            ci.OtherAction(Action.Exhaust, ef);

            //this has to somehow hook into relics that care about exhaust, and also player / monster statuses which care too.
            ExhaustCard?.Invoke(ef);
            ExhaustPile.Add(ci);
        }
예제 #3
0
        /// <summary>
        /// after block is accounted.
        /// bool represents if they are still alive.
        /// For use by essence of steel status too.
        /// </summary>
        public bool ApplyDamage(int amount, EffectSet ef, CardInstance ci, List <string> history)
        {
            HP -= amount;
            //this is for any damage type.
            TakeDamage?.Invoke(ef, amount, ci);
            history.Add($"{Name} took {amount} dmg");

            return(true);
        }
예제 #4
0
 internal void BeforePlayingCard(CardInstance ci)
 {
     ///Todo this will be a problem with playing cards that have just been created.
     if (!Hand.Contains(ci))
     {
         throw new Exception("playing card you don't have");
     }
     Hand.Remove(ci);
 }
예제 #5
0
        internal CardInstance Copy()
        {
            var ci = new CardInstance(Card, UpgradeCount);

            ci.PerTurnOverrideEnergyCost  = PerTurnOverrideEnergyCost;
            ci.PerFightOverrideEnergyCost = PerFightOverrideEnergyCost;
            ci.OverrideExhaust            = OverrideExhaust;
            return(ci);
        }
예제 #6
0
 public void ExhaustFromHand(CardInstance ci, EffectSet ef, List <string> h)
 {
     if (ci == null)
     {
         return;
     }
     Hand.Remove(ci);
     Exhaust(ci, ef);
     h.Add($"Exhausted {ci}");
 }
예제 #7
0
        public override List <int> GetKeys(Deck d, CardInstance ci)
        {
            var res = new List <int>();

            for (var ii = 0; ii < d.GetDrawPile.Count + 1; ii++)
            {
                res.Add(ii);
            }
            return(res);
        }
예제 #8
0
        internal override void Play(EffectSet ef, Player player, IEnemy enemy, int upgradeCount, IList <CardInstance> targets = null, Deck deck = null, long?key = null)
        {
            var dmg = upgradeCount == 0 ? 21 : 28;

            ef.EnemyEffect.SetInitialDamage(dmg);
            ef.DeckEffect.Add((Deck d, List <string> h) =>
            {
                var burn = new CardInstance(new Burn(), 0);
                d.AddToDiscardPile(burn);
                h.Add("Added burn to discard pile");
            });
        }
예제 #9
0
        internal override void Play(EffectSet ef, Player player, IEnemy enemy, int upgradeCount, IList <CardInstance> targets = null, Deck deck = null, long?key = null)
        {
            var dmg = upgradeCount == 0 ? 7 : 10;

            ef.DeckEffect.Add((Deck d, List <string> h) =>
            {
                var dazed    = new CardInstance(new Dazed(), 0);
                var position = d.AddToRandomSpotInDrawPile(dazed, key);
                h.Add($"Reckless charge added dazed to draw position {position}");
            });
            ef.EnemyEffect.SetInitialDamage(dmg);
        }
예제 #10
0
        internal override void Play(EffectSet ef, Player player, IEnemy enemy, int upgradeCount, IList <CardInstance> targets = null, Deck deck = null, long?key = null)
        {
            var dmg = upgradeCount == 0 ? 6 : 8;

            ef.EnemyEffect.SetInitialDamage(dmg);
            ef.DeckEffect.Add((Deck d, List <string> h) =>
            {
                var copy = new CardInstance(this, upgradeCount);
                d.AddToDiscardPile(copy);
                h.Add("Duplicated Anger into discard pile");
            });
        }
예제 #11
0
 /// <summary>
 /// add to hand if hand isn't too bigyet.
 /// </summary>
 private void TryAddToHand(CardInstance ci, EffectSet ef)
 {
     if (Hand.Count < 10)
     {
         Hand.Add(ci);
         DrawCard?.Invoke(ci, ef);
     }
     else
     {
         DiscardPile.Add(ci);
     }
 }
예제 #12
0
        public static List <CardInstance> GetRandomCards(int ccount)
        {
            var ac    = AllCards.Cards.Keys.ToList();
            var cards = new List <CardInstance>();

            for (var ii = 0; ii < ccount; ii++)
            {
                var card = AllCards.Cards[ac[Rnd.Next(ac.Count)]];
                var ci   = new CardInstance(card, Rnd.Next(2) == 1 ? 1 : 0);
                cards.Add(ci);
            }
            return(cards);
        }
예제 #13
0
        public static CardInstance GetCi(string name)
        {
            var x    = SplitCardName(name);
            var card = AllCards.Cards[x.Item1];

            if (card == null)
            {
                throw new Exception("Missing card.");
            }

            var ci = new CardInstance(card, x.Item2);

            return(ci);
        }
예제 #14
0
        /// <summary>
        /// Returns position key.
        /// </summary>
        internal long AddToRandomSpotInDrawPile(CardInstance ci, long?key = null)
        {
            long position;

            if (key == null)
            {
                position = Rnd.Next(DrawPile.Count + 1);
            }
            else
            {
                position = key.Value;
            }
            DrawPile.Insert((int)position, ci);
            return(position);
        }
예제 #15
0
        /// <summary>
        /// Todo: Why do I manually use the components of the monster move ef rather than just using
        /// applyEffectSet?
        /// </summary>
        /// <param name="cardInstance"></param>
        /// <param name="history"></param>
        public void _Attack(CardInstance cardInstance, List <string> history)
        {
            var enemy  = _Enemies[0];
            var player = _Player;
            var ef     = new EffectSet();

            cardInstance.Play(ef, _Player, _Enemies[0]);
            _Player.NotifyAttacked(ef);

            foreach (var si in enemy.StatusInstances)
            {
                var statusIsTargeted = false;
                si.Apply(cardInstance.Card, ef.EnemyEffect, ef.PlayerEffect, statusIsTargeted, false);
            }
            foreach (var si in player.StatusInstances)
            {
                var statusIsTargeted = true;
                si.Apply(cardInstance.Card, ef.EnemyEffect, ef.PlayerEffect, statusIsTargeted, false);
            }

            //this won't be right for Torii for example.
            foreach (var relic in _Player.Relics)
            {
                relic.CardPlayed(cardInstance.Card, ef, player: _Player, enemy: _Enemies[0]);
            }

            GainBlock(_Player, ef.PlayerEffect, history);
            GainBlock(_Enemies[0], ef.EnemyEffect, history);
            ReceiveDamage(_Enemies[0], ef.EnemyEffect, ef, history, cardInstance);
            ReceiveDamage(_Player, ef.PlayerEffect, ef, history, cardInstance);

            ApplyStatus(_Player, ef.PlayerEffect.Status, history);
            ApplyStatus(_Enemies[0], ef.EnemyEffect.Status, history);

            //enemy dying of  flame barrier status while killing the player, still results in a loss for the player.
            if (_Player.HP <= 0)
            {
                history.Add("Player Died from enemy attack");
                Died(_Player, history);
                return;
            }
            if (_Enemies[0].HP <= 0)
            {
                history.Add("Enemy Died on his turn");
                Died(_Enemies[0], history);
            }
        }
예제 #16
0
        internal override void Play(EffectSet ef, Player player, IEnemy enemy, int upgradeCount, IList <CardInstance> targets = null, Deck deck = null, long?key = null)
        {
            //I need some way to:
            // * make sure the childnode from playing this ends up in the random list (not choices)
            // * distinguish between those random entries.
            ef.DeckEffect.Add((Deck d, List <string> h) =>
            {
                var newCi    = new CardInstance(new Wound(), 0);
                var position = d.AddToRandomSpotInDrawPile(newCi, key);
                h.Add($"Wound added to draw pile position:{position}");
            });
            var dmg = upgradeCount == 0 ? 12 : 17;

            ef.EnemyEffect.SetInitialDamage(dmg);
            ef.HadRandomness = true;
            ef.Key           = key ?? 0;
        }
예제 #17
0
        public static IList <CardInstance> GetCis(params string[] names)
        {
            var cis = new List <CardInstance>();

            foreach (var name in names)
            {
                var x    = SplitCardName(name);
                var card = AllCards.Cards[x.Item1];
                if (card == null)
                {
                    throw new Exception("Missing card.");
                }

                var ci = new CardInstance(card, x.Item2);
                cis.Add(ci);
            }
            return(cis);
        }
예제 #18
0
        internal void EvolveCardDrawnEvent(CardInstance ci, EffectSet ef)
        {
            var si = Entity.StatusInstances.SingleOrDefault(el => el.Status.StatusType == StatusType.EvolveStatus);

            if (si == null)
            {
                return;
            }
            if (ci.Card.CardType == CardType.Curse || ci.Card.CardType == CardType.Status)
            {
                var newEf = new EffectSet();
                newEf.DeckEffect.Add((Deck d, List <string> h) =>
                {
                    var drawn = d.DrawToHand(null, si.Intensity, true, null, newEf, h);
                    h.Add($"{ci} Caused card draw: {string.Join(',', drawn)}");
                });
                ef.AddNextEf(newEf);
            }
        }
예제 #19
0
 internal void AfterPlayingCard(CardInstance ci, EffectSet ef, List <string> history)
 {
     if (ci.Card.CardType == CardType.Power)
     {
         //card just disappears.
     }
     else
     {
         ci.LeavingHand(ef);
         if (ci.Exhausts())
         {
             Exhaust(ci, ef);
             history.Add($"Exhausted {ci}");
         }
         else
         {
             PutIntoDiscardAfterApplyingEffectSet = ci;
         }
     }
 }
예제 #20
0
        /// <summary>
        /// When we generate an action, we check to see if it's already a duplicate (in randoms or choices).  This is how we compare them.
        /// </summary>
        public bool IsEqual(FightAction other)
        {
            if (FightActionType != other.FightActionType)
            {
                return(false);
            }
            if (CardInstance?.ToString() != other.CardInstance?.ToString())
            {
                return(false);
            }
            if (Potion?.Name != other.Potion?.Name)
            {
                return(false);
            }
            if (Target?.Name != other.Target?.Name)
            {
                return(false);
            }
            if (CardTargets != null && other.CardTargets == null)
            {
                return(false);
            }
            if (CardTargets == null && other.CardTargets != null)
            {
                return(false);
            }
            if (!Helpers.CompareHands(CardTargets, other.CardTargets, out var msg2))
            {
                return(false);
            }
            //if (Key != other.Key) return false;
            //we do not compare key here because this is at the "choice" stage.
            if (Random != other.Random)
            {
                return(false);
            }

            return(true);
        }
예제 #21
0
 public virtual List <int> GetKeys(Deck d, CardInstance ci)
 {
     throw new System.Exception("Can't call this upon non-random marked card.");
 }
예제 #22
0
 internal void MoveFromDiscardToDraw(CardInstance headbuttTarget)
 {
     DiscardPile.Remove(headbuttTarget);
     DrawPile.Add(headbuttTarget);
 }
예제 #23
0
 internal void AddToDiscardPile(CardInstance newCi)
 {
     //assuming we want to interleave it.
     DiscardPile.Add(newCi);
 }
예제 #24
0
        /// <summary>
        /// an action in a fight is one of:
        /// * player play card
        /// * player drink pot
        /// * player end turn
        ///
        /// * enemy play card (enemyAttack)
        /// * enemy buff (or do nothing)
        /// * enemy playerStatusATtack
        /// </summary>
        public FightAction(FightActionEnum fightActionType, CardInstance card = null, IList <CardInstance> cardTargets = null, Potion potion = null,
                           IEntity target = null, List <string> history = null, long?key = null, List <long> keys = null, bool hadRandomEffects = false, bool playable = true)
        {
            CardTargets     = cardTargets;
            FightActionType = fightActionType;
            Potion          = potion?.Copy();
            CardInstance    = card?.Copy();
            Target          = target;
            History         = history;
            Keys            = keys;
            Key             = key;
            Random          = hadRandomEffects;

            // For console view, whether it can actually be chosen/played.
            Playable = playable;
            switch (fightActionType)
            {
            case FightActionEnum.Potion:
                if (hadRandomEffects != potion.Random)
                {
                    throw new Exception("Enemy moves always random.");
                }
                break;

            case FightActionEnum.PlayCard:
                if (hadRandomEffects && !card.Card.RandomEffects)
                {
                    throw new Exception("Unexpected");
                }
                //had => rE but RE !=> had since not every randomizable effect card will actually have an effect every time.
                break;

            case FightActionEnum.EndTurn:
            case FightActionEnum.StartTurnEffect:
            case FightActionEnum.EndTurnEffect:
            case FightActionEnum.EndTurnDeckEffect:
            case FightActionEnum.EndTurnOtherEffect:
            case FightActionEnum.StartFightEffect:
            case FightActionEnum.EndFightEffect:
            case FightActionEnum.EnemyDied:
            case FightActionEnum.EndEnemyTurn:

            case FightActionEnum.WonFight:
            case FightActionEnum.LostFight:
            case FightActionEnum.TooLong:
            case FightActionEnum.NotInitialized:
            case FightActionEnum.StartTurn:
                if (hadRandomEffects)
                {
                    throw new Exception($"{fightActionType} is not random since deck was already shuffled.");
                }
                break;

            case FightActionEnum.StartFight:
                if (!hadRandomEffects)
                {
                    throw new Exception($"StartFight should be random.");
                }
                break;

            case FightActionEnum.EnemyMove:
                if (!hadRandomEffects)
                {
                    throw new Exception("Enemy moves always random.");
                }
                //I need a key to disambiguate the same actions.
                //i.e. if a monster has two choices that would be key 0 and key 1.
                //harder is to find a way to handle draws. ideally it'd be hand.GetHash()
                break;
            }

            Validate();
        }
예제 #25
0
        public static CardInstance Copy(CardInstance ci)
        {
            var newCi = new CardInstance(ci.Card, ci.UpgradeCount);

            return(newCi);
        }
예제 #26
0
 internal bool DiscardPileContains(CardInstance headbuttTarget)
 {
     return(DiscardPile.Contains(headbuttTarget));
 }
예제 #27
0
        public void PlayCard(CardInstance ci, List <CardInstance> cardTargets = null, bool forceExhaust = false, bool newCard = false, IList <CardInstance> source = null)
        {
            var action = new FightAction(FightActionEnum.PlayCard, card: ci, cardTargets: cardTargets, hadRandomEffects: ci.Card.RandomEffects);

            PlayCard(action, forceExhaust: forceExhaust, newCard: newCard, source: source);
        }
예제 #28
0
        private void ApplyEffectSet(EffectSet ef, Player player, IEnemy enemy, List <string> history, Potion potion = null, CardInstance ci = null, bool subEffectSet = false)
        {
            //TODO not clear if this order is the most sensible really or not.
            //complex effects like afterImage + playing defend with neg dex.

            //What happens if a deckeffect has further effects like exhausting a card, and the player has a status that triggers on this?

            //TODO this is complicated.  Evolve actually adds new deckeffects in the deckeffect evaluation.
            foreach (var f in ef.DeckEffect)
            {
                f.Invoke(_Deck, history);
            }

            GainBlock(player, ef.PlayerEffect, history);
            ReceiveDamage(enemy, ef.EnemyEffect, ef, history, ci);

            GainBlock(enemy, ef.EnemyEffect, history);
            ReceiveDamage(player, ef.PlayerEffect, ef, history, ci);
            ApplyStatus(player, ef.PlayerEffect.Status, history);
            ApplyStatus(enemy, ef.EnemyEffect.Status, history);

            if (ef.PlayerEnergy != 0)
            {
                _Player.Energy += ef.PlayerEnergy;
                history.Add($"Gained ${ef.PlayerEnergy} to {_Player.Energy}");
            }


            ef.FightEffect.ForEach(fe => fe.Action.Invoke(this, _Deck, history));

            foreach (var en in _Enemies)
            {
                if (!en.Dead)
                {
                    if (en.HP <= 0)
                    {
                        history.Add($"{en.Name} Died at {en.HP} HP");
                        Died(en, history);
                    }
                }
            }
            if (_Player.HP <= 0)
            {
                if (!_Player.Dead)
                {
                    history.Add("Player Died");
                    Died(_Player, history);
                }
            }

            if (!subEffectSet)
            {
                while (ef.NextEffectSet.Count > 0)
                {
                    var next = ef.NextEffectSet.First();
                    ef.NextEffectSet.RemoveAt(0);
                    ApplyEffectSet(next, player, enemy, history, potion, ci);
                }
            }
        }
예제 #29
0
        private void ReceiveDamage(IEntity entity, IndividualEffect ie, EffectSet ef, List <string> history, CardInstance ci)
        {
            if (ie.GetInitialDamage() == null && ie.DamageAdjustments?.Count > 0)
            {
                throw new Exception("should not happen");
                //Vuln will only add a progression if initialdamage != null
            }

            //We don't actually want to
            if (ie.GetInitialDamage() != null)
            {
                var val = ie.GetInitialDamage().Select(el => (double)el);

                foreach (var prog in ie.DamageAdjustments.OrderBy(el => el.Order))
                {
                    val = prog.Fun(val.ToList());
                }

                var usingVal = val.Select(el => (int)Math.Floor(el));
                history.Add($"{entity.Name} got attacked for {string.Join(',', usingVal)}");
                foreach (var el in usingVal)
                {
                    var elCopy = el;
                    if (elCopy > 0)
                    {
                        //handle block here.
                        if (entity.Block > 0)
                        {
                            if (elCopy > entity.Block)
                            {
                                elCopy = elCopy - entity.Block;
                                history.Add($"{entity.Name} blocked {entity.Block}");
                                entity.Block = 0;
                            }
                            else
                            {
                                entity.Block -= el;
                                history.Add($"{entity.Name} blocked {el}");
                                elCopy = 0;
                            }
                        }
                        if (elCopy > 0)
                        {
                            entity.ApplyDamage(elCopy, ef, ci, history);
                        }
                    }
                }
                //history.Add($"{entity.Details()}");
            }
        }