| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- namespace D21._1
- {
- public class Program
- {
- public enum EnumDifficulty
- {
- Normal = 0,
- Hard = 1
- }
- public static EnumDifficulty Difficulty { get; set; }
- static bool Attack(MonsterBoss boss, SpellSequence spellBook)
- {
- var heroe = new Heroe();
- boss.Heal();
- var activeEffects = new Queue<(Spell, int)>();
- var spellSequence = spellBook;
- while (heroe.HitPoints > 0 && boss.HitPoints > 0 && spellSequence != null)
- {
- HeroeTakesTurn(boss, heroe, activeEffects, spellSequence);
- if (heroe.Mana <= 0 || heroe.HitPoints <= 0 || boss.HitPoints <= 0)
- break;
- BossTakesTurn(boss, heroe, activeEffects);
- spellSequence = spellSequence?.NextEntry;
- }
- return boss.HitPoints <= 0 && heroe.HitPoints > 0;
- }
- private static void BossTakesTurn(MonsterBoss boss, Heroe heroe, Queue<(Spell, int)> activeEffects)
- {
- ResolveActiveEffects(boss, heroe, activeEffects);
- if (boss.HitPoints <= 0) return;
- var batk = Math.Max(boss.Damage - heroe.Armor, 1);
- heroe.HitPoints -= batk;
- }
- public static void HeroeTakesTurn(MonsterBoss boss, Heroe heroe, Queue<(Spell, int)> activeEffects, SpellSequence spellSequence)
- {
- heroe.HitPoints -= (int) Difficulty;
- if (heroe.HitPoints <= 0) return;
- ResolveActiveEffects(boss, heroe, activeEffects);
- if (boss.HitPoints <= 0) return;
- var spell = spellSequence?.Spell;
- heroe.Mana -= spell?.Cost ?? 0;
- spell?.ActiveEffect(heroe, boss);
- if (spell?.EffectDuration.HasValue ?? false)
- activeEffects.Enqueue((spell, spell.EffectDuration.Value));
- }
- private static void ResolveActiveEffects(MonsterBoss boss, Heroe heroe, Queue<(Spell, int)> activeEffects)
- {
- int active = activeEffects.Count;
- while (active-- > 0)
- {
- (Spell s, int duration) = activeEffects.Dequeue();
- s.ApplyEffect(heroe, boss);
- if (--duration != 0) activeEffects.Enqueue((s, duration));
- else s.WornOutEffect(heroe, boss);
- }
- }
- 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)
- {
- if (depth > 9) return;
- if (triedSpellSequence == null) triedSpellSequence = new HashSet<SpellSequence>();
- if (triedSpellSequence.Contains(spellSequence) == false)
- {
- if (Attack(boss, spellSequence) && cost < best) best = cost;
- triedSpellSequence.Add(spellSequence);
- }
- foreach (Spell spell in spellBook)
- {
- var firstOccurence = spellSequence?.Position(spell) ?? -1;
- if (spellSequence != null && spell.EffectDuration > 0
- && firstOccurence != -1 && firstOccurence < (spell.EffectDuration - 1) / 2)
- continue;
- var newSpellSequence = new SpellSequence() { Spell = spell, NextEntry = spellSequence };
- TrySpellSequence(spellBook, boss, ref best, cost + spell.Cost, triedSpellSequence, newSpellSequence, depth + 1);
- }
- }
- static void Main(string[] args)
- {
- if (args.Length < 1) throw new ArgumentException();
- if (File.Exists(args[0]) == false) throw new FileNotFoundException();
- var spellBook = BuildSpellBook();
- MonsterBoss boss = ParseFile(args);
- int best = int.MaxValue;
- TrySpellSequence(spellBook, boss, ref best);
- Console.WriteLine($"Best spell sequence costs {best} MP");
- }
- public static MonsterBoss ParseFile(string[] args)
- {
- int hp = 0, atk = 0;
- using (var file = File.OpenText(args[0]))
- {
- hp = int.Parse(file.ReadLine().Split(": ")[1]);
- atk = int.Parse(file.ReadLine().Split(": ")[1]);
- }
- return new MonsterBoss(hp)
- {
- Damage = atk
- };
- }
- public static List<Spell> BuildSpellBook() => new List<Spell>
- {
- new MagicMissile(),
- new Drain(),
- new Shield(),
- new Poison(),
- new Recharge()
- };
- }
- }
|