Program.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. namespace D21._1
  6. {
  7. public class Program
  8. {
  9. public enum EnumDifficulty
  10. {
  11. Normal = 0,
  12. Hard = 1
  13. }
  14. public static EnumDifficulty Difficulty { get; set; }
  15. static bool Attack(MonsterBoss boss, SpellSequence spellBook)
  16. {
  17. var heroe = new Heroe();
  18. boss.Heal();
  19. var activeEffects = new Queue<(Spell, int)>();
  20. var spellSequence = spellBook;
  21. while (heroe.HitPoints > 0 && boss.HitPoints > 0 && spellSequence != null)
  22. {
  23. HeroeTakesTurn(boss, heroe, activeEffects, spellSequence);
  24. if (heroe.Mana <= 0 || heroe.HitPoints <= 0 || boss.HitPoints <= 0)
  25. break;
  26. BossTakesTurn(boss, heroe, activeEffects);
  27. spellSequence = spellSequence?.NextEntry;
  28. }
  29. return boss.HitPoints <= 0 && heroe.HitPoints > 0;
  30. }
  31. private static void BossTakesTurn(MonsterBoss boss, Heroe heroe, Queue<(Spell, int)> activeEffects)
  32. {
  33. ResolveActiveEffects(boss, heroe, activeEffects);
  34. if (boss.HitPoints <= 0) return;
  35. var batk = Math.Max(boss.Damage - heroe.Armor, 1);
  36. heroe.HitPoints -= batk;
  37. }
  38. public static void HeroeTakesTurn(MonsterBoss boss, Heroe heroe, Queue<(Spell, int)> activeEffects, SpellSequence spellSequence)
  39. {
  40. heroe.HitPoints -= (int) Difficulty;
  41. if (heroe.HitPoints <= 0) return;
  42. ResolveActiveEffects(boss, heroe, activeEffects);
  43. if (boss.HitPoints <= 0) return;
  44. var spell = spellSequence?.Spell;
  45. heroe.Mana -= spell?.Cost ?? 0;
  46. spell?.ActiveEffect(heroe, boss);
  47. if (spell?.EffectDuration.HasValue ?? false)
  48. activeEffects.Enqueue((spell, spell.EffectDuration.Value));
  49. }
  50. private static void ResolveActiveEffects(MonsterBoss boss, Heroe heroe, Queue<(Spell, int)> activeEffects)
  51. {
  52. int active = activeEffects.Count;
  53. while (active-- > 0)
  54. {
  55. (Spell s, int duration) = activeEffects.Dequeue();
  56. s.ApplyEffect(heroe, boss);
  57. if (--duration != 0) activeEffects.Enqueue((s, duration));
  58. else s.WornOutEffect(heroe, boss);
  59. }
  60. }
  61. public static void TrySpellSequence(List<Spell> spellBook, MonsterBoss boss, ref int best, int cost = 0, HashSet<SpellSequence> triedSpellSequence = null, SpellSequence spellSequence = null, int depth = 0)
  62. {
  63. if (depth > 9) return;
  64. if (triedSpellSequence == null) triedSpellSequence = new HashSet<SpellSequence>();
  65. if (triedSpellSequence.Contains(spellSequence) == false)
  66. {
  67. if (Attack(boss, spellSequence) && cost < best) best = cost;
  68. triedSpellSequence.Add(spellSequence);
  69. }
  70. foreach (Spell spell in spellBook)
  71. {
  72. var firstOccurence = spellSequence?.Position(spell) ?? -1;
  73. if (spellSequence != null && spell.EffectDuration > 0
  74. && firstOccurence != -1 && firstOccurence < (spell.EffectDuration - 1) / 2)
  75. continue;
  76. var newSpellSequence = new SpellSequence() { Spell = spell, NextEntry = spellSequence };
  77. TrySpellSequence(spellBook, boss, ref best, cost + spell.Cost, triedSpellSequence, newSpellSequence, depth + 1);
  78. }
  79. }
  80. static void Main(string[] args)
  81. {
  82. if (args.Length < 1) throw new ArgumentException();
  83. if (File.Exists(args[0]) == false) throw new FileNotFoundException();
  84. var spellBook = BuildSpellBook();
  85. MonsterBoss boss = ParseFile(args);
  86. int best = int.MaxValue;
  87. TrySpellSequence(spellBook, boss, ref best);
  88. Console.WriteLine($"Best spell sequence costs {best} MP");
  89. }
  90. public static MonsterBoss ParseFile(string[] args)
  91. {
  92. int hp = 0, atk = 0;
  93. using (var file = File.OpenText(args[0]))
  94. {
  95. hp = int.Parse(file.ReadLine().Split(": ")[1]);
  96. atk = int.Parse(file.ReadLine().Split(": ")[1]);
  97. }
  98. return new MonsterBoss(hp)
  99. {
  100. Damage = atk
  101. };
  102. }
  103. public static List<Spell> BuildSpellBook() => new List<Spell>
  104. {
  105. new MagicMissile(),
  106. new Drain(),
  107. new Shield(),
  108. new Poison(),
  109. new Recharge()
  110. };
  111. }
  112. }