/// <summary>
        /// Default constructor
        /// </summary>
        public Game()
        {
            // Construct dungeons
            // Not doing this tidily and programmicably - 'cause it is going to change and we don't
            // want 10 identically boring levels
            DungeonStore["D01"] = DungeonGenerators.RoomsGenerator.Generate(40, 20, new List <Passage>()
            {
                new Passage(Passage.PassageTypeEnum.OneWay, "START"),
                new Passage(Passage.PassageTypeEnum.StairsDown, "D02")
            });

            DungeonStore["D02"] = DungeonGenerators.RoomsGenerator.Generate(40, 20, new List <Passage>()
            {
                new Passage(Passage.PassageTypeEnum.StairsUp, "D01"),
                new Passage(Passage.PassageTypeEnum.StairsDown, "D03")
            });

            DungeonStore["D03"] = DungeonGenerators.RoomsGenerator.Generate(40, 20, new List <Passage>()
            {
                new Passage(Passage.PassageTypeEnum.StairsUp, "D02"),
                new Passage(Passage.PassageTypeEnum.StairsDown, "D04")
            });

            DungeonStore["D04"] = DungeonGenerators.RoomsGenerator.Generate(40, 20, new List <Passage>()
            {
                new Passage(Passage.PassageTypeEnum.StairsUp, "D03"),
                new Passage(Passage.PassageTypeEnum.StairsDown, "D05")
            });

            DungeonStore["D05"] = DungeonGenerators.RoomsGenerator.Generate(40, 20, new List <Passage>()
            {
                new Passage(Passage.PassageTypeEnum.StairsUp, "D05")
            });

            // Set the Dungeon for each passage
            foreach (var dungeon in DungeonStore)
            {
                foreach (var passage in dungeon.Value.Passages)
                {
                    DungeonStore.TryGetValue(passage.DestinationID, out passage.Destination);
                }
            }

            Player = new Player(DungeonStore["D01"]);

            // Create empty messages list - prevent crash on first turn
            MessagesData.Add(new List <Message.Message>());
        }
        /// <summary>
        /// Do a turn in the game
        /// </summary>
        public void DoTurn()
        {
            var turnMessages = CurrentDungeon.DoTurn();

            MessagesData.Add(turnMessages);

            if (Player.Dead)
            {
                GameOver    = true;
                EndGameText = new List <string>()
                {
                    "Would you like your corpse identified?",
                    "Congratulations!",
                    "Your journey end here. In many pieces",
                    "Rest in many pieces",
                    "Death was too good for you!",
                    "Y. A. S. D",
                    "How sad. I'm sorry. I really am. <beat> I'm not."
                }.RandomItem();
                EndGameTitle = "You have died";
            }
        }
        /// <summary>
        /// Do a turn in the game
        /// </summary>
        public void DoTurn()
        {
            var turnMessages = CurrentDungeon.DoTurn();

            MessagesData.Add(turnMessages);
        }
        /// <summary>
        /// Default constructor
        /// </summary>
        /// <param name="getAssetStream">Asset stream getter - if not default (filesystem)</param>
        public Game(TGetAssetStream getAssetStream = null)
        {
            // Set GetAssetStream if changed from default
            GetAssetStream = getAssetStream ?? GetAssetStream;

            // Load the data from Monsters.Json into the Monster Factory
            using (var monsterFileReader = new StreamReader(GetAssetStream("monsters.json")))
            {
                var monsterFileText = monsterFileReader.ReadToEnd();
                var deserializedMonsterPrototypes =
                    JsonConvert.DeserializeObject <Dictionary <String, JObject> >(monsterFileText);
                foreach (var prototype in deserializedMonsterPrototypes)
                {
                    MonsterFactory.AddPrototype(prototype.Key, prototype.Value);
                }
            }

            // Construct dungeons
            // We get the parameters for building them, then we build them
            Dictionary <string, DungeonPrototype> dungeonsToDig;

            using (var dungeonsFileReader = new StreamReader(GetAssetStream("dungeons.json")))
            {
                var dungeonsFileText = dungeonsFileReader.ReadToEnd();
                dungeonsToDig = JsonConvert.DeserializeObject <Dictionary <string, DungeonPrototype> >
                                    (dungeonsFileText);
            }
            foreach (var dungeonToDig in dungeonsToDig)
            {
                var dungeon = dungeonToDig.Value.Generator.Generate(
                    width: dungeonToDig.Value.Width,
                    height: dungeonToDig.Value.Height,
                    passages: dungeonToDig.Value.Passages);
                DungeonStore.Add(dungeonToDig.Key, dungeon);

                // Place enemies per the dungeon to dig
                for (int i = 0; i < 20; ++i)
                {
                    var monster   = dungeonToDig.Value.MonstersToBuild.RandomItem();
                    var spawnArea = dungeon.SpawnAreas.RandomItem();
                    if (spawnArea.Area.Count > 0)
                    {
                        var spawnLocation = spawnArea.Area.RandomItem();
                        spawnArea.Area.Remove(spawnLocation);
                        MonsterFactory.CreateMonster(this, dungeon, monster, spawnLocation);
                    }
                }
            }

            // Set the Dungeon for each passage
            foreach (var dungeon in DungeonStore)
            {
                foreach (var passage in dungeon.Value.Passages)
                {
                    DungeonStore.TryGetValue(passage.DestinationID, out passage.Destination);
                }
            }

            // Find the start passage - and what dungeon it's in
            var start = DungeonStore.SelectMany(i => i.Value.Passages)
                        .First(i => i.DestinationID == "START");
            var startDungeon = DungeonStore.First(i => i.Value.Passages.Contains(start)).Value;

            Player = new Player(startDungeon);

            // Create empty messages list - prevent crash on first turn
            MessagesData.Add(new List <Message.Message>());
        }