bastien.monsarrat 6 years ago
parent
commit
f1915228ab
7 changed files with 239 additions and 0 deletions
  1. 6 0
      Adv2015.sln
  2. 9 0
      D21.1/D21.csproj
  3. 52 0
      D21.1/Inventory.cs
  4. 30 0
      D21.1/Player.cs
  5. 131 0
      D21.1/Program.cs
  6. 8 0
      D21.1/Properties/launchSettings.json
  7. 3 0
      D21.1/input.txt

+ 6 - 0
Adv2015.sln

@@ -77,6 +77,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "D20.1", "D20.1\D20.1.csproj
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "D20.2", "D20.2\D20.2.csproj", "{2303B37A-6752-415A-824C-BCF146EB613D}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "D21", "D21.1\D21.csproj", "{CEA47E9A-0933-4F73-BE0F-F069A9AE6784}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -231,6 +233,10 @@ Global
 		{2303B37A-6752-415A-824C-BCF146EB613D}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{2303B37A-6752-415A-824C-BCF146EB613D}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{2303B37A-6752-415A-824C-BCF146EB613D}.Release|Any CPU.Build.0 = Release|Any CPU
+		{CEA47E9A-0933-4F73-BE0F-F069A9AE6784}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CEA47E9A-0933-4F73-BE0F-F069A9AE6784}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CEA47E9A-0933-4F73-BE0F-F069A9AE6784}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CEA47E9A-0933-4F73-BE0F-F069A9AE6784}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 9 - 0
D21.1/D21.csproj

@@ -0,0 +1,9 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>netcoreapp2.1</TargetFramework>
+    <RootNamespace>D21._1</RootNamespace>
+  </PropertyGroup>
+
+</Project>

+ 52 - 0
D21.1/Inventory.cs

@@ -0,0 +1,52 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace D21._1
+{
+    public class Inventory : IEnumerable<Item>
+    {
+        public Item Item;
+        public Inventory NextEntry;
+
+        public int Count<T>() where T : Item => (NextEntry?.Count<T>() ?? 0) + (Item is T ? 1 : 0);
+        public override int GetHashCode() => HashCode.Combine(Item, NextEntry);
+        public bool Contains(Item i)
+        {
+            var cur = this;
+            while (cur != null)
+            {
+                if (i.Equals(cur.Item)) return true;
+                cur = cur.NextEntry;
+            }
+            return false;
+        }
+
+        public IEnumerator<Item> GetEnumerator()
+        {
+            var cur = this;
+            while (cur != null)
+            {
+                yield return cur.Item;
+                cur = cur.NextEntry;
+            }
+        }
+
+        IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
+    }
+
+    public abstract class Item
+    {
+        public string Name { get; set; }
+        public int Damage { get; set; }
+        public int Armor { get; set; }
+
+        public override bool Equals(object obj) => obj is Item item && Name.Equals(item.Name, StringComparison.OrdinalIgnoreCase);
+
+        public override int GetHashCode() => HashCode.Combine(Name);
+    }
+
+    public class Weapon : Item { }
+    public class Armor : Item { }
+    public class Ring : Item { }
+}

+ 30 - 0
D21.1/Player.cs

@@ -0,0 +1,30 @@
+namespace D21._1
+{
+    public abstract class Player
+    {
+        protected int OrigHitPoints { get; set; }
+        public int HitPoints { get; set; }
+        public int Damage { get; set; }
+        public int Armor { get; set; }
+
+        public void Heal() => HitPoints = OrigHitPoints;
+    }
+
+    public class Heroe : Player
+    {
+        public Heroe()
+        {
+            HitPoints = 100;
+            OrigHitPoints = 100;
+        }
+    }
+
+    public class MonsterBoss : Player
+    {
+        public MonsterBoss(int hp)
+        {
+            HitPoints = hp;
+            OrigHitPoints = hp;
+        }
+    }
+}

+ 131 - 0
D21.1/Program.cs

@@ -0,0 +1,131 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace D21._1
+{
+    class Program
+    {
+        static bool Attack(MonsterBoss boss, Inventory inventory)
+        {
+            var heroe = new Heroe();
+            foreach (var item in inventory)
+            {
+                heroe.Armor += item.Armor;
+                heroe.Damage += item.Damage;
+            }
+
+            boss.Heal();
+
+            while (heroe.HitPoints > 0 && boss.HitPoints > 0)
+            {
+                var hatk = Math.Max(heroe.Damage - boss.Armor, 1);
+                boss.HitPoints -= hatk;
+
+                if (boss.HitPoints <= 0) break;
+
+                var batk = Math.Max(boss.Damage - heroe.Armor, 1);
+                heroe.HitPoints -= batk;
+            }
+
+            return heroe.HitPoints > 0;
+        }
+
+        static void TryOutfits(Dictionary<Item, int> armory, MonsterBoss boss, ref int best, ref int worst, int cost = 0, HashSet<Inventory> triedInventories = null, Inventory heroeInventory = null)
+        {
+            var wCount = heroeInventory?.Count<Weapon>() ?? 0;
+            var aCount = heroeInventory?.Count<Armor>() ?? 0;
+            var rCount = heroeInventory?.Count<Ring>() ?? 0;
+
+            if (triedInventories == null) triedInventories = new HashSet<Inventory>();
+            if (wCount == 1 && aCount == 1 && rCount == 2)
+            {
+                if (cost > best && cost < worst) return;
+                if (triedInventories.Contains(heroeInventory) == false)
+                {
+                    if (Attack(boss, heroeInventory)) { if (cost < best) best = cost; }
+                    else { if (cost > worst) worst = cost; }
+
+                    triedInventories.Add(heroeInventory);
+                }
+
+                return;
+            }
+
+            foreach ((Item item, int price) in armory)
+            {
+                if (heroeInventory?.Contains(item) ?? false) continue;
+                if (item is Weapon && wCount == 1) continue;
+                if (item is Armor && aCount == 1) continue;
+                if (item is Ring && rCount == 2) continue;
+
+                var newInventory = new Inventory() { Item = item, NextEntry = heroeInventory };
+                TryOutfits(armory, boss, ref best, ref worst, cost + price, triedInventories, newInventory);
+            }
+        }
+
+        static void Main(string[] args)
+        {
+            if (args.Length < 1) throw new ArgumentException();
+            if (File.Exists(args[0]) == false) throw new FileNotFoundException();
+
+            var armory = BuildArmory();
+
+            MonsterBoss boss = ParseFile(args);
+
+            int best = int.MaxValue, worst = 0;
+            TryOutfits(armory, boss, ref best, ref worst);
+
+            Console.WriteLine($"Best outfit is worth {best} gp");
+            Console.WriteLine($"Worst outfit is worth {worst} gp");
+        }
+
+        private static MonsterBoss ParseFile(string[] args)
+        {
+            int hp = 0, atk = 0, ac = 0;
+            using (var file = File.OpenText(args[0]))
+            {
+                hp = int.Parse(file.ReadLine().Split(": ")[1]);
+                atk = int.Parse(file.ReadLine().Split(": ")[1]);
+                ac = int.Parse(file.ReadLine().Split(": ")[1]);
+            }
+
+
+            var boss = new MonsterBoss(hp)
+            {
+                Damage = atk,
+                Armor = ac
+            };
+            return boss;
+        }
+
+        private static Dictionary<Item, int> BuildArmory()
+        {
+            return new Dictionary<Item, int>
+            {
+                { new Weapon() { Name = "Dagger", Damage = 4 }, 8 },
+                { new Weapon() { Name = "Shortsword", Damage = 5 }, 10 },
+                { new Weapon() { Name = "Warhammer", Damage = 6 }, 25 },
+                { new Weapon() { Name = "Longsword", Damage = 7 }, 40 },
+                { new Weapon() { Name = "Greataxe", Damage = 8 }, 74 },
+
+                { new Armor() { Name = "None" }, 0 },
+                { new Armor() { Name = "Leather", Armor = 1 }, 13 },
+                { new Armor() { Name = "Chainmail", Armor = 2 }, 31 },
+                { new Armor() { Name = "Splintmail", Armor = 3 }, 53 },
+                { new Armor() { Name = "Bandedmail", Armor = 4 }, 75 },
+                { new Armor() { Name = "Platemail", Armor = 5 }, 102 },
+
+                { new Ring() { Name = "Left Hand" }, 0 },
+                { new Ring() { Name = "Right Hand" }, 0 },
+                { new Ring() { Name = "Damage +1", Damage = 1 }, 25 },
+                { new Ring() { Name = "Damage +2", Damage = 2 }, 50 },
+                { new Ring() { Name = "Damage +3", Damage = 3 }, 100 },
+                { new Ring() { Name = "Defense +1", Armor = 1 }, 20 },
+                { new Ring() { Name = "Defense +2", Armor = 2 }, 40 },
+                { new Ring() { Name = "Defense +3", Armor = 3 }, 80 },
+            };
+        }
+    }
+}

+ 8 - 0
D21.1/Properties/launchSettings.json

@@ -0,0 +1,8 @@
+{
+  "profiles": {
+    "D21.1": {
+      "commandName": "Project",
+      "commandLineArgs": "\"..\\..\\..\\..\\D21.1\\input.txt\""
+    }
+  }
+}

+ 3 - 0
D21.1/input.txt

@@ -0,0 +1,3 @@
+Hit Points: 109
+Damage: 8
+Armor: 2