public Action ChooseAction(Character actor, Party friendlyParty, Party hostileParty) { this.Actor = actor; this.FriendlyParty = friendlyParty; this.HostileParty = hostileParty; Trait groupHealingTrait = GetGroupHealingTrait(); int totalGroupHealth = friendlyParty.CharacterList.Sum(x => x.Hitpoints); int totalGroupMaxHealth = friendlyParty.CharacterList.Sum(x => x.MaxHitpoints); if (groupHealingTrait != null && Actor.Mana >= groupHealingTrait.Mana && totalGroupMaxHealth - totalGroupHealth > 100) { return(new Action(Actor, friendlyParty, groupHealingTrait)); } Trait directHealingTrait = GetDirectHealingTrait(); Character injuredAlly = FindLowestHPInjuredAlly(); if (directHealingTrait != null && Actor.Mana >= directHealingTrait.Mana && injuredAlly != null) { return(new Action(Actor, injuredAlly, directHealingTrait)); } List <Trait> groupBuffTraits = GetGroupBuffTraits(); foreach (Trait groupBuffTrait in groupBuffTraits) { if (Actor.Mana >= groupBuffTrait.Mana) { foreach (Buff buff in groupBuffTrait.Buffs) { if (friendlyParty.CharacterList.FindAll(x => x.Buffs.Contains(buff)).Count < friendlyParty.CharacterList.Count) { return(new Action(Actor, friendlyParty, groupBuffTrait)); } } } } Trait groupDamageTrait = GetGroupDamageTrait(); int aliveEnemiesCount = hostileParty.CharacterList.FindAll(x => x.Alive).Count; if (groupDamageTrait != null && Actor.Mana >= groupDamageTrait.Mana && aliveEnemiesCount > 1) { return(new Action(Actor, hostileParty, groupDamageTrait)); } Trait directDamageTrait = GetDirectDamageTrait(); if (directDamageTrait != null && Actor.Mana >= directDamageTrait.Mana) { return(new Action(Actor, FindLowestHPTarget(), directDamageTrait)); } Trait meleeTrait = GetMeleeTrait(); Character meleeTarget = FindLowestHPMeleeTarget(); if (meleeTrait != null && meleeTarget != null) { return(new Action(Actor, meleeTarget, meleeTrait)); } return(null); }
public Party Duel(List <Party> parties) { // Initialize Combatants string output = ""; int longestString = 0; for (var i = 0; i < parties.Count; i++) { foreach (var character in parties[i].CharacterList) { character.PartyId = i; this.combatants.Add(character); } string currentString = String.Format("{0}: total point cost is {1}\n", parties[i].Name, parties[i].PointCost()); if (currentString.Length > longestString) { longestString = currentString.Length; } output += currentString; } Console.WriteLine(new String('=', longestString)); Console.Write(output); Console.WriteLine(new String('=', longestString)); // Round Party winner = null; int roundCount = 1; while (winner == null) { Random rand = new Random(); Console.WriteLine("*** ROUND " + roundCount.ToString() + " ***"); // Roll Initiative foreach (var combatant in combatants) { int maxInitiative = combatant.Stats[Stat.Dexterity] * 5; combatant.Initiative = rand.Next(maxInitiative); } // Sort Combatants by Initiative combatants.Sort(); // Loop through combatants foreach (var combatant in combatants) { if (!combatant.Alive) { continue; } if (combatant.Effects.Contains(Effect.Poison)) { Trait poisonDamage = Trait.GetTrait("poison_damage"); Action poisonAction = new Action(combatant, combatant, poisonDamage); int minDamage = 1; int maxDamage = poisonAction.Trait.Power; DoSingleDamage(poisonAction, minDamage, maxDamage, rand); } if (!combatant.Alive) { continue; } if (combatant.Mana < combatant.MaxMana) { combatant.Mana += combatant.ManaRegen; } Party friendlyParty = null; Party hostileParty = null; for (var i = 0; i < parties.Count; i++) { if (i == combatant.PartyId) { friendlyParty = parties[i]; } else { hostileParty = parties[i]; } } // Do an action Action action = combatant.AI.ChooseAction(combatant, friendlyParty, hostileParty); if (action == null) { continue; } if (action.Trait.Mana > 0) { action.Actor.Mana -= action.Trait.Mana; } switch (action.Trait.Type) { case TraitType.Melee: int minDamage = combatant.Stats[Stat.Strength]; int maxDamage = combatant.Stats[Stat.Strength] + action.Trait.Power; DoSingleDamage(action, minDamage, maxDamage, rand); break; case TraitType.DirectDamage: minDamage = action.Trait.Power; maxDamage = combatant.Stats[Stat.Intelligence] + action.Trait.Power; DoSingleDamage(action, minDamage, maxDamage, rand); break; case TraitType.DirectHealing: int minHeal = action.Trait.Power; int maxHeal = combatant.Stats[Stat.Wisdom] + action.Trait.Power; DoSingleHealing(action, minHeal, maxHeal, rand); break; case TraitType.GroupDamage: foreach (Character target in hostileParty.CharacterList) { Action targetedAction = new Action(action.Actor, target, action.Trait); minDamage = (combatant.Stats [Stat.Intelligence] / 4); maxDamage = combatant.Stats [Stat.Intelligence] + action.Trait.Power; DoSingleDamage(targetedAction, minDamage, maxDamage, rand); } break; case TraitType.GroupHealing: foreach (Character target in friendlyParty.CharacterList) { if (!target.Alive) { continue; } Action targetedAction = new Action(action.Actor, target, action.Trait); minHeal = action.Trait.Power; maxHeal = combatant.Stats[Stat.Wisdom] + action.Trait.Power; DoSingleHealing(targetedAction, minHeal, maxHeal, rand); } break; case TraitType.GroupBuff: foreach (Character target in friendlyParty.CharacterList) { Action targetedAction = new Action(action.Actor, target, action.Trait); DoSingleBuff(targetedAction); } break; } // Check for victory List <Party> deadPartyList = new List <Party> (); foreach (var party in parties) { if (party.CharacterList.Find(x => x.Hitpoints > 0) == null) { deadPartyList.Add(party); } } if (deadPartyList.Count == parties.Count - 1) { foreach (var party in parties) { if (deadPartyList.Contains(party)) { continue; } Console.ForegroundColor = ConsoleColor.Green; Console.BackgroundColor = ConsoleColor.White; Console.Write("The winner is " + party.Name); Console.ResetColor(); Console.Write("\n"); winner = party; DisplayMatchup(parties); return(winner); } } else if (deadPartyList.Count == parties.Count) { Console.WriteLine("The match is a draw"); DisplayMatchup(parties); winner = new Party(); return(winner); } } DisplayMatchup(parties); roundCount++; // TODO: make Round Limit configurable if (roundCount == 500) { Console.WriteLine("Round limit hit"); return(new Party()); } } return(winner); }
public Character(string name, string raceName, Row row, List <String> traits) { var racePath = "data/races/"; this.Name = name; raceName = raceName.ToLower(); var yaml = File.ReadAllText(racePath + raceName + ".yaml"); var deserializer = new DeserializerBuilder() .WithNamingConvention(new CamelCaseNamingConvention()) .Build(); var race = deserializer.Deserialize <Race>(yaml); this.Race = race.Name; this.Size = race.Size; this.BaseStats = race.Stats; this.BaseResists = race.Resists; this.PointCost += race.Points; this.Traits = new List <Trait>(); this.Effects = new List <Effect>(); this.Buffs = new List <Buff>(); this.Alive = true; this.Row = row; this.ManaRegen = 0; //TODO: load AI choice this.AI = new GeneralAI(); foreach (var t in race.Traits) { Trait trait = LoadTrait(t); this.Traits.Add(trait); } foreach (var t in traits) { Trait trait = LoadTrait(t); this.Traits.Add(trait); this.PointCost += trait.PointCost; } this.Resists = this.BaseResists; this.Stats = this.BaseStats; foreach (var t in this.Traits) { if (t.Type != TraitType.StatChange) { continue; } if (t.Stat == Stat.AC) { this.AC += t.Power; } if (this.Stats.ContainsKey(t.Stat)) { this.Stats[t.Stat] += t.Power; } } this.MaxHitpoints = (this.Stats[Stat.Constitution] * 4) + 50; this.Hitpoints = this.MaxHitpoints; this.MaxMana = (this.Stats[Stat.Intelligence] * 2) + (this.Stats[Stat.Wisdom] * 2) + 25; this.Mana = MaxMana; this.ManaRegen += (int)Math.Round((double)(this.Stats[Stat.Wisdom] / 10)); this.AC += this.Stats[Stat.Dexterity] / 4; }