示例#1
0
        public void TestWinningCondition()
        {
            // 1x1 map
            int           w            = 1;
            int           h            = 1;
            IMapGenerator mapGenerator = MapGeneratorFactory.CreateOpenMapGenerator();
            Map           map          = mapGenerator.GenerateMap(w, h, IMapGeneratorConstants.NO_SEED);

            // place player
            AbstractPlayer player = AIPlayerFactory.CreateEmptyAIPlayer("Test empty AI", map.Grid[0, 0]);

            // create game instance
            Game game = new Game()
            {
                GameMap = map
            };

            game.AddAIPlayer(player);

            // perform one game loop step
            game.GameLoopStep();

            // check winner
            Assert.IsTrue(game.IsWinner, "No winner after game loop step!");
            Assert.IsNotNull(game.Winner, "Winner is null!");
        }
        /// <summary>
        /// Generates new game with given parameters. If aiCount+1 (1 for human player) is greater than width*heght, exception is thrown.
        /// </summary>
        /// <param name="width">Width of the map.</param>
        /// <param name="height">Height of the map.</param>
        /// <param name="mapSeed">Map seed.</param>
        /// <param name="aiCount">Number of AIs (simple AI is used).</param>
        /// <param name="monsterDensity">Density of monsters 0..1</param>
        /// <param name="itemDensity">Density of items 0..1</param>
        /// <param name="humanPlayerName">Name of the human player.</param>
        /// <returns>Generated game instance.</returns>
        public static Game GenerateGame(int width, int height, int mapSeed, int aiCount, double monsterDensity, double itemDensity, string humanPlayerName)
        {
            // check
            if (aiCount + 1 > width * height)
            {
                throw new Exception($"Počet protihráčů {aiCount} je na plochu {width}x{height} moc velký!");
            }

            Map.Map gameMap = MapGeneratorFactory.CreateSimpleMapGenerator().GenerateMap(width, height, mapSeed);
            Game    game    = new Game()
            {
                GameMap = gameMap
            };
            Random r = new Random();


            // sets of occupied position for creatures and items, '{x}:{y}'
            HashSet <String> creatureOccupiedPositions = new HashSet <string>();
            HashSet <string> itemsOccupiedPositions    = new HashSet <string>();

            // place human player
            int            x      = r.Next(width);
            int            y      = r.Next(height);
            AbstractPlayer player = new HumanPlayer(humanPlayerName, gameMap.Grid[x, y]);

            game.AddHumanPlayer(player);
            creatureOccupiedPositions.Add($"{x}:{y}");

            // place AI players
            int pCount = 1;

            AddObjectsToGame(width, height, aiCount, 20, (ox, oy) =>
            {
                if (!creatureOccupiedPositions.Contains($"{ox}:{oy}"))
                {
                    game.AddAIPlayer(AIPlayerFactory.CreateSimpleAIPLayer($"Simple AI Player {pCount}", gameMap.Grid[ox, oy]));
                    creatureOccupiedPositions.Add(($"{ox}:{oy}"));
                    pCount++;
                    return(true);
                }
                else
                {
                    return(false);
                }
            });

            // monster count from density:
            // density is expected to be in range 0..1 and will be mapped to the count of remaining free map blocks
            // this number is then lowered to 2/3 and this result is used as a base
            // then monsterCount = base + random.next(base/3)
            double monsterCountBase = 2 * (monsterDensity * (width * height - aiCount)) / 3;
            int    monsterCount     = (int)(monsterCountBase + r.NextDouble() * (monsterCountBase / 3));

            // place monsters
            AddObjectsToGame(width, height, monsterCount, 20, (ox, oy) =>
            {
                if (!creatureOccupiedPositions.Contains($"{ox}:{oy}"))
                {
                    game.AddMonster(MonsterFactory.CreateRandomMonster(gameMap.Grid[ox, oy]));
                    creatureOccupiedPositions.Add(($"{ox}:{oy}"));
                    return(true);
                }
                else
                {
                    return(false);
                }
            });


            // item count is calculated the same way as monster count is
            double itemCountBase = 2 * (itemDensity * (width * height - aiCount)) / 3;
            int    itemCount     = (int)(itemCountBase + r.NextDouble() * (itemCountBase / 3));

            // place items
            AddObjectsToGame(width, height, itemCount, 20, (ox, oy) =>
            {
                if (!itemsOccupiedPositions.Contains($"{ox}:{oy}"))
                {
                    game.AddItem(ItemFactory.CreateRandomItem(gameMap.Grid[ox, oy]));
                    itemsOccupiedPositions.Add(($"{ox}:{oy}"));
                    return(true);
                }
                else
                {
                    return(false);
                }
            });

            return(game);
        }
        /// <summary>
        /// Places SelectedToolboxItem to the map. If no item is selected, nothing happnes.
        ///
        /// If the map block is occupied, coordinates are out of range, map is null or item type is unknown, exception is raised.
        ///
        /// </summary>
        /// <param name="mapX">X coordinate of map block to place this item.</param>
        /// <param name="mapY">Y coordinate of map block to place this item.</param>
        public void PlaceSelectedToolboxItem(int mapX, int mapY)
        {
            EditorToolboxItem item = SelectedToolboxItem;

            // no item selected => do nothing
            if (item == null)
            {
                return;
            }

            if (GameMap == null)
            {
                throw new Exception("Není herní mapa!");
            }
            else if (mapX < 0 || mapX >= GameMap.Width || mapY < 0 || mapY >= GameMap.Height)
            {
                throw new Exception($"[{mapX},{mapY}] není v rozsahu mapy!");
            }
            else if ((item.ItemType == EditorToolboxItemType.AI_PLAYER || item.ItemType == EditorToolboxItemType.MONSTER) && GameMap.Grid[mapX, mapY].Occupied)
            {
                throw new Exception($"Na pozici [{mapX},{mapY}] už je umístěn hráč, nebo monstrum!");
            }
            else if ((item.ItemType == EditorToolboxItemType.ITEM || item.ItemType == EditorToolboxItemType.ARMOR || item.ItemType == EditorToolboxItemType.WEAPON) && GameMap.Grid[mapX, mapY].Item != null)
            {
                throw new Exception($"Na pozici [{mapX},{mapY}] už je umístěn předmět!");
            }

            int uid = -1;

            switch (item.ItemType)
            {
            case EditorToolboxItemType.HUMAN_PLAYER:
                if (HumanPlayerPlaced)
                {
                    throw new Exception("Na hrací plochu lze umístit pouze jednoho lidského hráče!");
                }
                GameMap.Grid[mapX, mapY].Creature = new HumanPlayer("Human player", GameMap.Grid[mapX, mapY]);
                uid = GameMap.Grid[mapX, mapY].Creature.UniqueId;
                HumanPlayerPlaced = true;
                break;

            case EditorToolboxItemType.AI_PLAYER:
                GameMap.Grid[mapX, mapY].Creature = AIPlayerFactory.CreateSimpleAIPLayer("Simple AI Player", GameMap.Grid[mapX, mapY]);
                uid = GameMap.Grid[mapX, mapY].Creature.UniqueId;
                break;

            case EditorToolboxItemType.MONSTER:
                GameMap.Grid[mapX, mapY].Creature = MonsterFactory.CreateRandomMonster(GameMap.Grid[mapX, mapY]);
                uid = GameMap.Grid[mapX, mapY].Creature.UniqueId;
                break;

            case EditorToolboxItemType.ITEM:
                GameMap.Grid[mapX, mapY].Item = ItemFactory.CreateBasicItem(GameMap.Grid[mapX, mapY]);
                uid = GameMap.Grid[mapX, mapY].Item.UniqueId;
                break;

            case EditorToolboxItemType.ARMOR:
                GameMap.Grid[mapX, mapY].Item = ItemFactory.CreateLeatherArmor(GameMap.Grid[mapX, mapY]);
                uid = GameMap.Grid[mapX, mapY].Item.UniqueId;
                break;

            case EditorToolboxItemType.WEAPON:
                GameMap.Grid[mapX, mapY].Item = ItemFactory.CreateAxe(GameMap.Grid[mapX, mapY]);
                uid = GameMap.Grid[mapX, mapY].Item.UniqueId;
                break;

            default:
                throw new Exception($"Neznámý typ umisťovaného předmětu: {item.ItemType}!");
            }
            EditorToolboxItem placedItem = item.Clone();

            placedItem.UID = uid;
            PlacedItems.Add(placedItem);

            OnPropertyChanged("PlacedItems");
        }