/// <summary> /// Start a new autobattle round and returns round result to BattleEngine /// </summary> /// <returns></returns> public RoundEnum StartRoundAuto() { // Turn fight loop, go until monsters or characters are dead while (RoundResult.Equals(RoundEnum.NextTurn)) { // Fight still going // See whose turn it is CurrentPlayer = GetNextPlayerTurn(); // Select turn choice (move, attack, skill) var choice = TurnChoice(); // Do the turn with the current player TakeTurn(choice); // Check the round result RoundResult = GetRoundState(); } Referee.BattleScore.RoundCount++; if (Referee.BattleScore.RoundCount > 100) { return(RoundEnum.GameOver); } // Round is over, return result to BattleEngine return(RoundResult); }
/// <summary> /// Swap out the item if it is better /// /// Uses Value to determine /// </summary> /// <param name="fighter"></param> /// <param name="itemLocation"></param> public bool GetItemFromPoolIfBetter(DungeonFighterModel fighter, ItemLocationEnum itemLocation) { var items = Referee.ItemPool.Where(a => a.Location == itemLocation) .OrderByDescending(a => a.Value) .ToList(); // If no items in the list, return... if (!items.Any()) { return(false); } var currentItem = fighter.GetItemByLocation(itemLocation); if (currentItem == null) { SwapCharacterItem(fighter, itemLocation, items.FirstOrDefault()); return(true); } foreach (var droppedItem in items) { if (droppedItem.Value > currentItem.Value) { SwapCharacterItem(fighter, itemLocation, currentItem); return(true); } } return(true); }
/// <summary> /// Drop Items /// </summary> /// <param name="Target"></param> public int DropItems(DungeonFighterModel Target) { var DroppedMessage = "\nItems Dropped : \n"; // Drop Items to ItemModel Pool var myItemList = Target.DropAllItems(); // I feel generous, even when characters die, random drops happen :-) // If Random drops are enabled, then add some.... myItemList.AddRange(GetRandomMonsterItemDrops()); // Add to ScoreModel foreach (var ItemModel in myItemList) { Referee.BattleScore.ItemsDroppedList += ItemModel.FormatOutput() + "\n"; DroppedMessage += ItemModel.Name + "\n"; } Referee.ItemPool.AddRange(myItemList); if (myItemList.Count == 0) { DroppedMessage = " Nothing dropped. "; } Referee.BattleMessages.DroppedMessage = DroppedMessage; Referee.BattleScore.ItemModelDropList.AddRange(myItemList); return(myItemList.Count()); }
/// <summary> /// Return a stack layout for the Characters /// </summary> /// <param name="data"></param> /// <returns></returns> public StackLayout CreateCharacterDisplayBox(DungeonFighterModel data) { if (data == null) { data = new DungeonFighterModel(); } // Hookup the image var PlayerImage = new Image { Style = (Style)Application.Current.Resources["ImageBattleMediumStyle"], Source = data.ImageURI }; // Add the Level var PlayerLevelLabel_1 = new Label { Text = "Lv: " + data.Level, Style = (Style)Application.Current.Resources["ValueStyleSmall"], HorizontalOptions = LayoutOptions.Center, HorizontalTextAlignment = TextAlignment.Center, Padding = 0, LineBreakMode = LineBreakMode.TailTruncation, CharacterSpacing = 1, LineHeight = 1, MaxLines = 1, }; var PlayerLevelLabel_2 = new Label { Text = "HP: " + data.CurrentHealth + "/" + data.MaxHealth, Style = (Style)Application.Current.Resources["ValueStyleSmall"], HorizontalOptions = LayoutOptions.Center, HorizontalTextAlignment = TextAlignment.Center, Padding = 0, LineBreakMode = LineBreakMode.TailTruncation, CharacterSpacing = 1, LineHeight = 1, MaxLines = 1, }; // Put the Image Button and Text inside a layout var PlayerStack = new StackLayout { Style = (Style)Application.Current.Resources["ScoreCharacterInfoBox"], HorizontalOptions = LayoutOptions.Center, Padding = 0, Spacing = 0, Children = { PlayerImage, PlayerLevelLabel_1, PlayerLevelLabel_2 }, }; return(PlayerStack); }
/// <summary> /// Constructor taking a Referee, attacker, and the turn choice of the attacker /// </summary> /// <param name="referee"></param> /// <param name="attacker"></param> /// <param name="choice"></param> public TurnEngine(RefereeModel referee, DungeonFighterModel attacker, DungeonFighterModel target, TurnChoiceEnum choice) { rnd = new Random(); Referee = referee; Attacker = attacker; Target = target; ActionChoice = choice; }
/// <summary> /// Process attack from BattlePage /// </summary> public void AttackClicked() { // Auto select target Target = SelectMonsterToAttack(); // Do the turn TakeTurn(TurnChoiceEnum.Attack); // Update round state RoundResult = GetRoundState(); }
/// <summary> /// Attack as a Turn /// /// </summary> /// <param name="Attacker"></param> /// <returns></returns> public bool Attack(DungeonFighterModel Attacker) { if (Target == null) { return(false); } // Do Attack TurnAsAttack(Attacker, Target); return(true); }
/// <summary> /// If Dead process Targed Died /// </summary> /// <param name="Target"></param> public bool RemoveIfDead(DungeonFighterModel Target) { // Check for alive if (Target.CurrentHealth <= 0) { // check if miracle max is enabled if (Referee.ResurrectionsEnabled) { int resurrected; // works on characters only if (Referee.UsedResurrection.TryGetValue(Target, out resurrected)) { // If character has not resurrected before if (resurrected == 0) { // Set health back to max Target.CurrentHealth = Target.MaxHealth; // Toggle resurrection Referee.UsedResurrection[Target] = 1; return(false); } } } //check if monster can return to live if (zombieMonstersEnable && Target.PlayerType == CreatureEnum.Monster) { Random rnd = new Random(); int random = rnd.Next(0, 100 + 1); //if monster is return to live, change its name and health = 1/2 original health if (random <= returnToLiveAsZombie) { Target.CurrentHealth = Target.MaxHealth / 2; Target.Name = "Zombie " + Target.Name; return(false); } } Referee.BattleMessages.TurnMessageSpecial = Referee.BattleMessages.GetDeathMessage(); TargedDied(Target); return(true); } return(false); }
/// <summary> /// Decide whom to attack /// </summary> /// <param name="data"></param> /// <returns></returns> public DungeonFighterModel ChooseTarget(DungeonFighterModel data) { switch (data.PlayerType) { case CreatureEnum.Monster: return(SelectCharacterToAttack()); case CreatureEnum.Character: return(SelectMonsterToAttack()); default: return(null); } }
/// <summary> /// Perform the next turn using the specified choice /// </summary> public bool TakeTurn(TurnChoiceEnum choice) { // Select target automatically if monster is currently attacking or autobattle is enabled if (Referee.AutoBattleEnabled || CurrentPlayer.PlayerType.Equals(CreatureEnum.Monster)) { Target = ChooseTarget(CurrentPlayer); } // otherwise the target is being set externally through the Battle Page var turn = new TurnEngine(Referee, CurrentPlayer, Target, choice); turn.TakeTurn(); return(true); }
/// <summary> /// Pickup Items Dropped /// </summary> /// <param name="fighter"></param> public bool PickupItemsFromPool(DungeonFighterModel fighter) { // TODO: Teams, You need to implement your own Logic if not using auto apply // I use the same logic for Auto Battle as I do for Manual Battle // Have the character, walk the items in the pool, and decide if any are better than current one. // Use Mike's auto apply for now GetItemFromPoolIfBetter(fighter, ItemLocationEnum.Head); GetItemFromPoolIfBetter(fighter, ItemLocationEnum.Necklass); GetItemFromPoolIfBetter(fighter, ItemLocationEnum.PrimaryHand); GetItemFromPoolIfBetter(fighter, ItemLocationEnum.OffHand); GetItemFromPoolIfBetter(fighter, ItemLocationEnum.RightFinger); GetItemFromPoolIfBetter(fighter, ItemLocationEnum.LeftFinger); GetItemFromPoolIfBetter(fighter, ItemLocationEnum.Feet); return(true); }
public void RoundEngine_RemoveDeadPlayerFromList_Should_Remove_Dead_Players() { // Arrange DungeonFighterModel player1 = new DungeonFighterModel(); DungeonFighterModel player2 = new DungeonFighterModel(); player1.CurrentHealth = -1; Engine.FighterList.Add(player1); Engine.FighterList.Add(player2); // Act List <DungeonFighterModel> result = Engine.RemoveDeadPlayersFromList(); // Reset // Assert Assert.AreEqual(player2, Engine.FighterList.ElementAt(0)); }
public void RoundEngine_OrderFighters_Character_Must_Go_First() { // Arrange // Act var engine = Engine; DungeonFighterModel player1 = new DungeonFighterModel(); DungeonFighterModel player2 = new DungeonFighterModel(); engine.Referee.Characters.Add(player1); engine.MonsterList.Add(player2); engine.OrderFighters(); // Reset // Assert Assert.AreEqual(engine.FighterList[0], player1); Assert.AreEqual(engine.FighterList[1], player2); }
/// <summary> /// Calculate Experience /// Level up if needed /// </summary> /// <param name="Attacker"></param> /// <param name="Target"></param> public bool CalculateExperience(DungeonFighterModel Attacker, DungeonFighterModel Target) { if (Attacker.PlayerType == CreatureEnum.Character) { var experienceEarned = Target.CalculateExperienceEarned(Referee.BattleMessages.DamageAmount); Referee.BattleMessages.ExperienceEarned = " Earned " + experienceEarned + " points"; var LevelUp = Attacker.AddExperience(experienceEarned); if (LevelUp) { Referee.BattleMessages.LevelUpMessage = Attacker.Name + " is now Level " + Attacker.Level + " With Health Max of " + Attacker.GetMaxHealthTotal; Debug.WriteLine(Referee.BattleMessages.LevelUpMessage); } // Add Experinece to the Score Referee.BattleScore.ExperienceGainedTotal += experienceEarned; } return(true); }
/// <summary> /// Swap the Item the character has for one from the pool /// /// Drop the current item back into the Pool /// /// </summary> /// <param name="character"></param> /// <param name="setLocation"></param> /// <param name="newItem"></param> /// <returns></returns> private ItemModel SwapCharacterItem(DungeonFighterModel character, ItemLocationEnum setLocation, ItemModel newItem) { // Put on the new ItemModel, which drops the one back to the pool var droppedItem = character.AddItem(setLocation, newItem.Id); // Add the PoolItem to the list of selected items // ? //ItemModelSelectList.Add(newItem); // Remove the ItemModel just put on from the pool Referee.ItemPool.Remove(newItem); if (droppedItem != null) { // Add the dropped ItemModel to the pool Referee.ItemPool.Add(droppedItem); } return(droppedItem); }
/// <summary> /// Target Died /// /// Process for death... /// /// Returns the count of items dropped at death /// </summary> /// <param name="Target"></param> public bool TargedDied(DungeonFighterModel Target) { Referee.BattleMessages.TurnMessageSpecial = Referee.BattleMessages.GetDeathMessage(); // Remove target from list... // Using a switch so in the future additional PlayerTypes can be added (Boss...) switch (Target.PlayerType) { case CreatureEnum.Character: Target.Alive = false; Referee.Characters.Remove(Target); Referee.BattleScore.CharacterModelDeathList.Add(Target); // Add the CharacterModel to the killed list Referee.BattleScore.CharacterAtDeathList += Target.FormatOutput() + "\n"; DropItems(Target); break; default: Target.Alive = false; Referee.Monsters.Remove(Target); // Add one to the monsters killed count... Referee.BattleScore.MonsterSlainNumber++; // Add the MonsterModel to the killed list Referee.BattleScore.MonstersKilledList += Target.FormatOutput() + "\n"; DropItems(Target); break; } Debug.WriteLine(Referee.BattleMessages.TurnMessageSpecial); return(true); }
/// <summary> /// Set the target of the attack. Used in manual mode. /// </summary> /// <param name="target"></param> /// <returns></returns> public bool SetTarget(DungeonFighterModel target) { Target = target; return(true); }
public void HackathonScenario_Scenario_32_If_RoundCount_Is_Times_Of_5_Grandma_Goes_First_True() { /* * Scenario Number: * 32 * * Description: * Every 5th round, the sort order for turn order changes and list is sorted by Characters first, * then lowest health, then lowest speed * * Make 3 characters and 3 monsters, * CharacterA has 100 health and 2 speed but since it has lowest health in character so it goes first * CharacterB has 200 health and 1 speed same health with CharacterC but lower speed so it goes faster * CharacterC has 200 health and 3 speed but since it is character it should go third * Monster A has 100 health and 4 speed but since it has lowest health in monster so it goes fourth * Monster B has 200 health and 5 speed same health with CharacterC but lower speed so it goes fifth * MonsterC has 200 health and 6 speed but it has higher speed so it goes last * Normal: Monster C > Monster B > Monster A > Character C > Character A > Character B * Round in times of 5: Character A > Character B > Character C > Monster A > Monster B > Monster C * * Changes Required (Classes, Methods etc.) List Files, Methods, and Describe Changes: * Change to Round Engine * Changed OrderFight method * Check for First fighter's name * * Test Algrorithm: * Create three characters * Create three monster * Check for the orders. * * Test Conditions: * Test Fighters' name in order * * Validation: * Verify order of characters' name is Character A > Character B > Character C > Monster A > Monster B > Monster C * */ // Set Character Conditions var CharacterPlayerA = new CharacterModel { SpeedAttribute = 2, Level = 10, MaxHealth = 100, CurrentHealth = 100, ExperiencePoints = 100, Name = "CharacterA", }; var CharacterPlayerB = new CharacterModel { SpeedAttribute = 1, Level = 10, MaxHealth = 200, CurrentHealth = 100, ExperiencePoints = 100, Name = "CharacterB", }; var CharacterPlayerC = new CharacterModel { SpeedAttribute = 3, Level = 10, MaxHealth = 200, CurrentHealth = 100, ExperiencePoints = 100, Name = "CharacterC", }; // Make new player list var playerList = new List <CharacterModel>(); // Add Characters playerList.Add(CharacterPlayerA); playerList.Add(CharacterPlayerB); playerList.Add(CharacterPlayerC); // Give player list to BattleEngine BattleEngine.SetParty(playerList); // Set Monster Conditions // Add a monster to attack var MonsterPlayerA = new DungeonFighterModel( new MonsterModel { SpeedAttribute = 4, Level = 10, CurrentHealth = 100, ExperiencePoints = 1, Name = "MonsterA", }); var MonsterPlayerB = new DungeonFighterModel( new MonsterModel { SpeedAttribute = 5, Level = 10, CurrentHealth = 200, ExperiencePoints = 1, Name = "MonsterB", }); var MonsterPlayerC = new DungeonFighterModel( new MonsterModel { SpeedAttribute = 6, Level = 1, CurrentHealth = 200, ExperiencePoints = 1, Name = "MonsterC", }); //Set current round count = 5 BattleEngine.CurrentRound.RoundCount = 5; // Remove the automatically added monsters from the RoundEngine BattleEngine.CurrentRound.MonsterList.Clear(); BattleEngine.CurrentRound.FighterList.Clear(); // Add this monster instead BattleEngine.CurrentRound.MonsterList.Add(MonsterPlayerA); BattleEngine.CurrentRound.MonsterList.Add(MonsterPlayerB); BattleEngine.CurrentRound.MonsterList.Add(MonsterPlayerC); // Have dice roll 20 DiceHelper.EnableForcedRolls(); DiceHelper.SetForcedRollValue(20); BattleEngine.CurrentRound.OrderFighters(); // Choose only character in party BattleEngine.CurrentRound.CurrentPlayer = BattleEngine.CurrentRound.FighterList.FirstOrDefault(); //After sort the first player's name should be monster Assert.IsTrue(BattleEngine.CurrentRound.FighterList[0].Name.Equals("CharacterA")); Assert.IsTrue(BattleEngine.CurrentRound.FighterList[1].Name.Equals("CharacterB")); Assert.IsTrue(BattleEngine.CurrentRound.FighterList[2].Name.Equals("CharacterC")); Assert.IsTrue(BattleEngine.CurrentRound.FighterList[3].Name.Equals("MonsterA")); Assert.IsTrue(BattleEngine.CurrentRound.FighterList[4].Name.Equals("MonsterB")); Assert.IsTrue(BattleEngine.CurrentRound.FighterList[5].Name.Equals("MonsterC")); }
public void HackathonScenario_Scenario_16_Monster_Becomes_Zombie() { /* * Scenario Number: * 16 * * Description: * When a monster is killed, it returns from the dead and continue attacking as a zombie monster * * Changes Required (Classes, Methods etc.) List Files, Methods, and Describe Changes: * Added a switch to enable zombie mode to Turn Engine * Add default percentage for a monster to return to live as a zombie = 20% * Added check condition to RemoveIfDie in Turn Engine * When a monster is killed: * Roll a random number from 1 to 100, if number is < 20%, monster is back to life * Else, monster is dead * * Test Algrorithm: * Create an character * Create a monster * Set % of monster return to live = 100% * Let character attacks monster, and monster is killed after the attack * * Test Conditions: * With 100% chance to return to live, check if monster is still alive * after being killed * * Validation * Verify monster is alive (alive = true) * Verify a new HP = 1/2 original HP * Verify new name = Zombie Monster * */ //Arrange // Set Character Conditions var CharacterPlayerBigBoy = new CharacterModel { SpeedAttribute = 200, Level = 10, CurrentHealth = 100, ExperiencePoints = 100, Name = "BigBoy", }; //added character to character list var playerList = new List <CharacterModel>(); playerList.Add(CharacterPlayerBigBoy); BattleEngine.SetParty(playerList); // Set Monster Conditions with health = 1 var MonsterPlayer = new DungeonFighterModel( new MonsterModel { SpeedAttribute = 1, Level = 1, CurrentHealth = 1, ExperiencePoints = 1, Name = "Monster", MaxHealth = 100 }); // Remove auto added monsters BattleEngine.Referee.Monsters.Clear(); // Add this monster instead BattleEngine.Referee.Monsters.Add(MonsterPlayer); //do not enable autobattle BattleEngine.Referee.AutoBattleEnabled = false; // Have dice roll 20 DiceHelper.EnableForcedRolls(); DiceHelper.SetForcedRollValue(20); // Choose BigBoy BattleEngine.CurrentRound.CurrentPlayer = BattleEngine.Referee.Characters.FirstOrDefault(); // Choose Monster BattleEngine.CurrentRound.Target = BattleEngine.Referee.Monsters.FirstOrDefault(); //set monster health = 1 so it will die after next attack MonsterPlayer.CurrentHealth = 1; //enable feature that monster can return to live as zombies TurnEngine.zombieMonstersEnable = true; //set % of return to live of target of this round = 100% TurnEngine.returnToLiveAsZombie = 100; //Act var result = BattleEngine.CurrentRound.TakeTurn(Game.Models.Enum.TurnChoiceEnum.Attack); //Reset TurnEngine.zombieMonstersEnable = false; TurnEngine.returnToLiveAsZombie = 20; DiceHelper.DisableForcedRolls(); BattleEngine.NewRound(); //Assert Assert.AreEqual("Zombie Monster", MonsterPlayer.Name); Assert.AreEqual(50, MonsterPlayer.CurrentHealth); Assert.AreEqual(true, MonsterPlayer.Alive); }
public void HackathonScenario_Scenario_5_Critical_Hit_Not_Enable_Roll_20_Always_Hit_() { /* * Scenario Number: * 5 * * Description: * The attacker will automatically hit and cause double damage * if the tohit roll is a natural 20 * * Changes Required (Classes, Methods etc.) List Files, Methods, and Describe Changes: * TurnEngine: * Create bool to enable critical hit * TurnAsAttack method: added critical hit case where target takes double damage amount * HitStatusEnum: added status for critical hit * * Test Algrorithm: * Create an character BigBoy * Create a monster * Disable Critical Hit * Let the character BigBoy rolls 20 and attack monster * * Test Conditions: * Check if monster get hit, but not double damage from character * * Validation * Verify monster gets hit with the right damage amount * */ //Arrange // Set Character Conditions var CharacterPlayerBigBoy = new CharacterModel { SpeedAttribute = 200, Level = 10, CurrentHealth = 100, ExperiencePoints = 100, Name = "BigBoy", }; var playerList = new List <CharacterModel>(); playerList.Add(CharacterPlayerBigBoy); BattleEngine.SetParty(playerList); // Set Monster Conditions var MonsterPlayer = new DungeonFighterModel( new MonsterModel { SpeedAttribute = 1, Level = 1, CurrentHealth = 100, ExperiencePoints = 1, Name = "Monster", }); //enable critical hit TurnEngine.criticalHitEnable = false; //do not enable autobattle BattleEngine.Referee.AutoBattleEnabled = false; // Remove auto added monsters BattleEngine.Referee.Monsters.Clear(); // Add this monster instead BattleEngine.Referee.Monsters.Add(MonsterPlayer); // Have dice roll 20 DiceHelper.EnableForcedRolls(); DiceHelper.SetForcedRollValue(20); // Choose BigBoy BattleEngine.CurrentRound.CurrentPlayer = BattleEngine.Referee.Characters.FirstOrDefault(); // Choose Monster BattleEngine.CurrentRound.Target = BattleEngine.Referee.Monsters.FirstOrDefault(); MonsterPlayer.CurrentHealth = 100; //Act var result = BattleEngine.CurrentRound.TakeTurn(Game.Models.Enum.TurnChoiceEnum.Attack); //Reset TurnEngine.criticalHitEnable = false; DiceHelper.DisableForcedRolls(); BattleEngine.NewRound(); //Assert Assert.AreEqual(result, true); Assert.AreEqual(BattleEngine.Referee.BattleMessages.DamageAmount, (100 - MonsterPlayer.CurrentHealth)); }
public void HackathonScenario_Scenario_15_If_TimeWarp_False_Faster_Character_Moves_First() { /* * Scenario Number: * 15 * * Description: * Make a character and a monster, Character has higher speed than monster * Time warp boolean * If true character acts first, if false monster moves first * * Changes Required (Classes, Methods etc.) List Files, Methods, and Describe Changes: * Change to Round Engine * Changed OrderFight method * Check for First fighter's name * * Test Algrorithm: * Create Character with higher speed attribute (200) * Create Monster with lower speed attribute (1) * Order FighterList and see who moves first * * Test Conditions: * Test Current Figher's name * * Validation: * Verify Mike has taken first move * */ // Set Character Conditions var CharacterPlayerMike = new CharacterModel { SpeedAttribute = 200, Level = 10, MaxHealth = 100, CurrentHealth = 100, ExperiencePoints = 100, Name = "Mike", }; // Make new player list var playerList = new List <CharacterModel>(); // Add Mike playerList.Add(CharacterPlayerMike); // Give player list to BattleEngine BattleEngine.SetParty(playerList); // Set Monster Conditions // Add a monster to attack var MonsterPlayer = new DungeonFighterModel( new MonsterModel { SpeedAttribute = 1, Level = 1, CurrentHealth = 5, ExperiencePoints = 1, Name = "ABC", }); // Remove the automatically added monsters from the RoundEngine BattleEngine.CurrentRound.MonsterList.Clear(); // Add this monster instead BattleEngine.CurrentRound.MonsterList.Add(MonsterPlayer); // Have dice roll 20 DiceHelper.EnableForcedRolls(); DiceHelper.SetForcedRollValue(20); //set timewarp true BattleEngine.CurrentRound.TimeWarp = false; BattleEngine.CurrentRound.OrderFighters(); // Choose only character in party BattleEngine.CurrentRound.CurrentPlayer = BattleEngine.CurrentRound.FighterList.FirstOrDefault(); //After sort the first player's name should be monster Assert.IsTrue(BattleEngine.CurrentRound.CurrentPlayer.Name.Equals("Mike")); }
public void HackathonScenario_Scenario_9_Character_Revives_After_Death() { /* * Scenario Number: * 9 * * Description: * * Miracle Max steps in and helps characters who are Mostly Dead avoid Total Death. * If the damaged received would make the currentHealth points Zero or below, then * Miracle Max steps in and helps out. One time per battle, a character may be revived * by magic to their maxhealth. This happens instead of death. Because this is allowed * only one time per battle per character, they can have more fun storming the castle. * * Miracle Max loves it when you advertise his business in the output window * * * Changes Required (Classes, Methods etc.) List Files, Methods, and Describe Changes: * * TurnEngine: Add logic for dealing with resurrections * Referee: Add dictionary that keeps track of resurrections * * * Test Algrorithm: * Create Character with 1 health and -1 speed * Create Monster with level 20 and 10 speed * Call Turn, check if character is alive * Call Turn again, check if character is dead * * Test Conditions: * Test with Character health at 1 * * Validation: * Verify character does not die when health <= 0 * Verify character dies after one resurrection * */ var CharacterPlayerMike = new CharacterModel { SpeedAttribute = -1, Level = 1, MaxHealth = 1, CurrentHealth = 1, ExperiencePoints = 1, Name = "Mike", }; // Make list of players var playerList = new List <CharacterModel>(); // Add Mike to player list playerList.Add(CharacterPlayerMike); // Give player list to BattleEngine BattleEngine.SetParty(playerList); // Create strong monster var MonsterPlayer = new DungeonFighterModel( new MonsterModel { SpeedAttribute = 10, Level = 20, MaxHealth = 100, CurrentHealth = 100, ExperiencePoints = 100, Name = "Monster", }); // Remove auto added monsters BattleEngine.CurrentRound.MonsterList.Clear(); // Add this monster instead BattleEngine.CurrentRound.MonsterList.Add(MonsterPlayer); BattleEngine.Referee.SetResurrection(true); // Have dice roll 20 DiceHelper.EnableForcedRolls(); DiceHelper.SetForcedRollValue(20); // Choose Monster as current BattleEngine.CurrentRound.CurrentPlayer = BattleEngine.CurrentRound.MonsterList.FirstOrDefault(); // Choose Mike as target BattleEngine.CurrentRound.Target = BattleEngine.Referee.Characters.Find(character => character.Name.Equals("Mike")); //Act var result = BattleEngine.CurrentRound.TakeTurn(Game.Models.Enum.TurnChoiceEnum.Attack); // Assert Mike not dead Assert.AreEqual(true, result); Assert.IsTrue(CharacterPlayerMike.Alive); // Act again var nextResult = BattleEngine.CurrentRound.TakeTurn(Game.Models.Enum.TurnChoiceEnum.Attack); //Reset DiceHelper.DisableForcedRolls(); BattleEngine.NewRound(); BattleEngine.Referee.SetResurrection(false); // Assert Mike dead this time var deadMike = BattleEngine.Referee.BattleScore.CharacterModelDeathList.Find(character => character.Name.Equals("Mike")); Assert.AreEqual(true, nextResult); Assert.IsFalse(deadMike.Alive); }
public void HackathonScenario_Scenario_2_Character_Not_Bob_Should_Hit() { /* * Scenario Number: * 2 * * Description: * See Default Test * * Changes Required (Classes, Methods etc.) List Files, Methods, and Describe Changes: * See Defualt Test * * Test Algrorithm: * Create Character named Mike * Create Monster * Call TurnAsAttack so Mike can attack Monster * * Test Conditions: * Control Dice roll so natural hit * Test with Character of not named Bob * * Validation * Verify Enum is Hit * */ //Arrange // Set Character Conditions var CharacterPlayerMike = new CharacterModel { SpeedAttribute = 200, Level = 10, CurrentHealth = 100, ExperiencePoints = 100, Name = "Mike", }; // Make new player list var playerList = new List <CharacterModel>(); // Add Mike playerList.Add(CharacterPlayerMike); // Give player list to BattleEngine BattleEngine.SetParty(playerList); // Set Monster Conditions // Add a monster to attack var MonsterPlayer = new DungeonFighterModel( new MonsterModel { SpeedAttribute = 1, Level = 1, CurrentHealth = 1, ExperiencePoints = 1, Name = "Monster", }); // Remove auto added monsters BattleEngine.CurrentRound.MonsterList.Clear(); // Add this monster instead BattleEngine.CurrentRound.MonsterList.Add(MonsterPlayer); // Have dice roll 20 DiceHelper.EnableForcedRolls(); DiceHelper.SetForcedRollValue(20); // Choose Not Bob BattleEngine.CurrentRound.CurrentPlayer = BattleEngine.Referee.Characters.FirstOrDefault(); // Choose Monster BattleEngine.CurrentRound.Target = BattleEngine.Referee.Monsters.FirstOrDefault(); //Act var result = BattleEngine.CurrentRound.TakeTurn(Game.Models.Enum.TurnChoiceEnum.Attack); //Reset DiceHelper.DisableForcedRolls(); BattleEngine.NewRound(); //Assert Assert.AreEqual(true, result); Assert.AreEqual(HitStatusEnum.Hit, BattleEngine.Referee.BattleMessages.HitStatus); }
public void HackathonScenario_Scenario_2_Character_Bob_Should_Miss() { /* * Scenario Number: * 2 * * Description: * Make a Character called Bob * Bob Always Misses * Other Characters Always Hit * * Changes Required (Classes, Methods etc.) List Files, Methods, and Describe Changes: * Change to Turn Engine * Changed TurnAsAttack method * Check for Name of Bob and return miss * * Test Algrorithm: * Create Character named Bob * Create Monster * Call TurnAsAttack * * Test Conditions: * Test with Character of Named Bob * Test with Character of any other name * * Validation: * Verify Enum is Miss * */ //Arrange // Set Character Conditions // Create Bob var CharacterPlayerBob = new CharacterModel { SpeedAttribute = 200, Level = 10, CurrentHealth = 100, ExperiencePoints = 100, Name = "Bob", }; // Create new player list var playerList = new List <CharacterModel>(); // Add Bob to the list of players playerList.Add(CharacterPlayerBob); // Give list to BattleEngine BattleEngine.SetParty(playerList); // Set Monster Conditions // Add a monster to attack var MonsterPlayer = new DungeonFighterModel( new MonsterModel { SpeedAttribute = 1, Level = 1, CurrentHealth = 1, ExperiencePoints = 1, Name = "Monster", }); // Remove the automatically added monsters from the RoundEngine BattleEngine.CurrentRound.MonsterList.Clear(); // Add this monster instead BattleEngine.CurrentRound.MonsterList.Add(MonsterPlayer); // Have dice rull 19 DiceHelper.EnableForcedRolls(); DiceHelper.SetForcedRollValue(19); // Set up turn // Choose Bob BattleEngine.CurrentRound.CurrentPlayer = BattleEngine.Referee.Characters.FirstOrDefault(); // Choose Monster BattleEngine.CurrentRound.Target = BattleEngine.Referee.Monsters.FirstOrDefault(); //Act var result = BattleEngine.CurrentRound.TakeTurn(Game.Models.Enum.TurnChoiceEnum.Attack); //Reset DiceHelper.DisableForcedRolls(); BattleEngine.NewRound(); //Assert Assert.AreEqual(true, result); Assert.AreEqual(HitStatusEnum.Miss, BattleEngine.Referee.BattleMessages.HitStatus); }
public void HackathonScenario_Scenario_23_Enraged_Makes_Extra_Damage() { /* * Scenario Number: * 23 * * Description: * When a monster recieve damage, the monster is anraged * and does d20 extra damage on its next attack * * Changes Required (Classes, Methods etc.) List Files, Methods, and Describe Changes: * CreatureModel: added boolean isEnraged to monsterModel. set default = false * TurnEngine: * TurnAsAttack method: * when a monster is a target of an attack, generate a random number from 1 - 100 * if number < 20 (20%): enable monster enraged mode * when a monster is an attacker * check if monster is enraged: double the damage, then disable enrage mode of that monster * added a switch to enable enraged mode * added an integer to contain % of chance that a monster will get enraged * * Test Algrorithm: * Create an character * Create a monster * Let character attacks monster, make sure monster is still alive * Force monster to be enraged * Next turn, monster is enraged and makes an attack. * * Test Conditions: * With enraged mode on, monster will have double attack * * Validation * Verify if monster makes double damage attack on its turn * */ //Arrange // Set Character Conditions var CharacterPlayerBigBoy = new CharacterModel { SpeedAttribute = 200, Level = 10, CurrentHealth = 100, ExperiencePoints = 100, Name = "Character", MaxHealth = 100 }; //added character to character list var playerList = new List <CharacterModel>(); playerList.Add(CharacterPlayerBigBoy); BattleEngine.SetParty(playerList); // Set Monster Conditions var MonsterPlayer = new DungeonFighterModel( new MonsterModel { SpeedAttribute = 1, Level = 1, CurrentHealth = 100, ExperiencePoints = 1, Name = "Monster", }); // Remove auto added monsters BattleEngine.Referee.Monsters.Clear(); // Add this monster instead BattleEngine.Referee.Monsters.Add(MonsterPlayer); //do not enable autobattle BattleEngine.Referee.AutoBattleEnabled = false; //enable monster enraged mode TurnEngine.monsterEnragedModeEnable = true; //set chance for monster to be enraged = 100% TurnEngine.enragedChance = 100; // Have dice roll 20 DiceHelper.EnableForcedRolls(); DiceHelper.SetForcedRollValue(20); // Choose Character BattleEngine.CurrentRound.CurrentPlayer = BattleEngine.Referee.Characters.FirstOrDefault(); // Choose Monster BattleEngine.CurrentRound.Target = BattleEngine.Referee.Monsters.FirstOrDefault(); //Act //character is attacker BattleEngine.CurrentRound.TakeTurn(Game.Models.Enum.TurnChoiceEnum.Attack); // Have dice roll 20 DiceHelper.EnableForcedRolls(); DiceHelper.SetForcedRollValue(20); // Choose monster BattleEngine.CurrentRound.CurrentPlayer = MonsterPlayer; // Choose target BattleEngine.CurrentRound.Target = BattleEngine.Referee.Characters.FirstOrDefault(); //Act //monster is now an anraged attacker - make double damage BattleEngine.CurrentRound.TakeTurn(Game.Models.Enum.TurnChoiceEnum.Attack); //Reset TurnEngine.monsterEnragedModeEnable = false; TurnEngine.enragedChance = 20; DiceHelper.DisableForcedRolls(); BattleEngine.NewRound(); //Assert Assert.AreEqual(BattleEngine.Referee.BattleMessages.DamageAmount * 2, (100 - BattleEngine.Referee.Characters.FirstOrDefault().CurrentHealth)); }
// Battle section /// <summary> /// Run through a turn. /// If it's a monster, the monster will do a turn. /// Characters will be prompted for the next action. /// </summary> async void DoNextTurn() { // Check for all characters dead if (BattleEngine.Engine.CurrentRound.RoundResult.Equals(RoundEnum.GameOver)) { //Debug.WriteLine("GAME OVER"); //Debug.WriteLine("Total turns taken: " + BattleEngine.Engine.Referee.BattleScore.TurnCount); //Debug.WriteLine("Monsters killed: " + BattleEngine.Engine.Referee.BattleScore.MonsterSlainNumber); //Debug.WriteLine("Highest round: " + BattleEngine.Engine.RoundCount); //await Navigation.PushAsync(new ScorePage()); BattleEngine.Engine.CurrentRound.RoundResult = RoundEnum.GameOver; // Wrap up BattleEngine.Engine.EndBattle(); // Pause Task.Delay(WaitTime); Debug.WriteLine("Game Over"); ShowScore(); return; } // Check for all monsters dead if (BattleEngine.Engine.CurrentRound.RoundResult.Equals(RoundEnum.NewRound)) { // show some sort of "new round" graphic Debug.WriteLine("New Round"); // Tell Battle Engine to create new Round object, also update CurrentRound SetupRound(); ShowScore(); } // Remember player count var currentPlayerCount = BattleEngine.Engine.CurrentRound.FighterList.Count; // See whos turn it is CurrentlySelectedPlayer = CurrentRound.GetNextPlayerTurn(); // If it's a monster, let them do their attack if (CurrentlySelectedPlayer.PlayerType.Equals(CreatureEnum.Monster)) { // Find the monster in the battle grid // Make their image jiggle or something to show an attack animation // update round state BattleEngine.Engine.CurrentRound.CurrentPlayer = CurrentlySelectedPlayer; // redraw board if anyone died if (BattleEngine.Engine.CurrentRound.FighterList.Count < currentPlayerCount) { AddBattlefieldGridCharacter(); } // display hit information GameMessage(); } else // otherwise, update battlepage state to show actions { BattleEngine.Engine.CurrentRound.CurrentPlayer = CurrentlySelectedPlayer; AttackerImage.Source = CurrentlySelectedPlayer.ImageURI; // wait for attack/move/skill... } }
/// <summary> /// /// Determine Attack Score /// Determine DefenseScore /// /// Do the Attack /// </summary> /// <param name="Attacker"></param> /// <param name="AttackScore"></param> /// <param name="Target"></param> /// <param name="DefenseScore"></param> /// <returns></returns> public bool TurnAsAttack(DungeonFighterModel Attacker, DungeonFighterModel Target) { if (Attacker == null) { return(false); } if (Target == null) { return(false); } // Set Messages to empty Referee.BattleMessages.ClearMessages(); // Load current player info to battle messages Referee.BattleMessages.AttackerName = Attacker.Name; Referee.BattleMessages.PlayerType = Attacker.PlayerType; Referee.BattleMessages.AttackerHealth = Attacker.CurrentHealth; // Load target info to battle messages Referee.BattleMessages.TargetName = Target.Name; Referee.BattleMessages.TargetHealth = Target.CurrentHealth; // Attacker prepares to attack message Debug.WriteLine(Referee.BattleMessages.GetPreamble()); // Set Attack and Defense var AttackScore = Attacker.Level + Attacker.GetAttack(); var DefenseScore = Target.GetDefense() + Target.Level; // Poor Bob always misses if (Attacker.Name.Equals("Bob")) { Referee.BattleMessages.HitStatus = HitStatusEnum.Miss; } else { Referee.BattleMessages.HitStatus = RollToHitTarget(AttackScore, DefenseScore); } switch (Referee.BattleMessages.HitStatus) { case HitStatusEnum.Miss: // It's a Miss Debug.WriteLine("It's a miss!"); break; case HitStatusEnum.Hit: // It's a Hit //Calculate Damage Debug.WriteLine("It's a hit!"); Referee.BattleMessages.DamageAmount = Attacker.GetDamageRollValue(); //if the enrage mode is on if (monsterEnragedModeEnable) { //if attacker is monster and enraged if (Attacker.PlayerType == CreatureEnum.Monster && Attacker.isEnraged) { Target.TakeDamage(Referee.BattleMessages.DamageAmount * 2); Attacker.isEnraged = false; } //if target is monster if (Target.PlayerType == CreatureEnum.Monster) { //random a number Random rnd = new Random(); int random = rnd.Next(1, 101); //if random number is <= 20 (20%) //monster is enraged if (random <= enragedChance) { Target.isEnraged = true; } } } else { Target.TakeDamage(Referee.BattleMessages.DamageAmount); // If it is a character apply the experience earned CalculateExperience(Attacker, Target); } // Update target's health for game display Referee.BattleMessages.TargetHealth = Target.CurrentHealth; // Set Referee.BattleMessages.TurnMessage = Referee.BattleMessages.GetTurnMessage(); //Referee.BattleMessages.TurnMessage = Referee.BattleMessages.GetHTMLFormattedTurnMessage(); break; case HitStatusEnum.CriticalHit: // It's a Hit //Calculate Damage Debug.WriteLine(Referee.BattleMessages.GetCriticalHitMessage()); Referee.BattleMessages.DamageAmount = Attacker.GetDamageRollValue(); Target.TakeDamage(Referee.BattleMessages.DamageAmount * 2); Referee.BattleMessages.TargetHealth = Target.CurrentHealth; Debug.WriteLine(Referee.BattleMessages.GetHitMessage()); Debug.WriteLine(Referee.BattleMessages.GetCurrentHealthMessage()); break; } RemoveIfDead(Target); return(true); }