public void IsWalkableReturnsTrueForWalkableTiles()
        {
            File.WriteAllText("data/config.json", "{ 'PuzzlePushProbability': 0 }");
            new Config("data/config.json");

            var floor      = new CaveFloorMap(MapWidth, MapHeight);
            var foundFloor = false;
            var foundWall  = false;

            // There must be at least one walkable tile and one non-walkable tile, based on the current generation strategy
            for (var x = 0; x < MapWidth; x++)
            {
                for (var y = 0; y < MapHeight; y++)
                {
                    var walkable = floor.IsWalkable(x, y);
                    if (walkable)
                    {
                        foundFloor = true;
                    }
                    else
                    {
                        foundWall = true;
                    }
                }
            }

            Assert.That(foundFloor, Is.EqualTo(true));
            Assert.That(foundWall, Is.EqualTo(true));
        }
示例#2
0
        private void MoveTowardsGoal()
        {
            if (this.X == this.goal.X && this.Y == this.goal.Y)
            {
                this.goal    = map.FindEmptyPosition();
                this.goalMap = this.CreateGoalMap();
            }

            var path = goalMap.FindPath(this.X, this.Y);

            if (path != null)
            {
                var now      = path.Steps.First();
                var nextStep = path.Steps.Skip(1).FirstOrDefault();
                if (nextStep != null && map.IsWalkable(nextStep.X, nextStep.Y))
                {
                    this.Move(nextStep.X, nextStep.Y);
                }
                else
                {
                    // Pick a new goal next time
                    this.goal = new Point(this.X, this.Y);
                }
            }
            else
            {
                // No path to goal... Pick a new goal next time
                this.goal = new Point(this.X, this.Y);
            }
        }
示例#3
0
        private void MovePlayerBy(Point amount, KeyboardInfo info = null)
        {
            var stopwatch = new System.Diagnostics.Stopwatch();

            stopwatch.Start();

            var currentFieldOfView = new RogueSharp.FieldOfView(this.currentMap.GetIMap());
            var playerView         = this.objects.Single(g => g.Name == "Player");

            var fovTiles = currentFieldOfView.ComputeFov(playerView.Position.X, playerView.Position.Y, Config.Instance.Get <int>("PlayerLightRadius"), true);

            this.MarkCurrentFovAsDiscovered(fovTiles);
            foreach (var obj in this.objects)
            {
                obj.IsVisible = false;
            }

            // Undo monster vision tile effect
            foreach (var monsterView in this.objects.Where(o => o.Data is Monster))
            {
                var data       = monsterView.Data as Monster;
                var monsterFov = currentFieldOfView.ComputeFov(data.X, data.Y, data.VisionSize, true);
                // If we can see them, they're discovered
                foreach (var cell in monsterFov)
                {
                    if (this.discoveredTiles.ContainsKey($"{cell.X}, {cell.Y}"))
                    {
                        this[cell.X, cell.Y].ApplyEffect(DiscoveredEffect);
                    }
                    else
                    {
                        this[cell.X, cell.Y].ApplyEffect(HiddenEffect);
                    }
                }
            }

            // Get the position the player will be at
            Point newPosition = playerView.Position + amount;

            // Is there a block there?
            if (currentMap.GetObjectsAt(newPosition.X, newPosition.Y).Any(e => e is Pushable))
            {
                // Is there an empty space behind it?
                var behindBlock = newPosition + amount;
                if (currentMap.IsWalkable(behindBlock.X, behindBlock.Y))
                {
                    // Push it (update data)
                    var obj = currentMap.GetObjectsAt(newPosition.X, newPosition.Y).Single(e => e is Pushable);
                    obj.Move(behindBlock.X, behindBlock.Y);
                    // Push it (move view object)
                    this.objects.Single(g => g.Data == obj).Move(behindBlock.X, behindBlock.Y);
                    this.CheckIfBlockPuzzleIsComplete();
                }
            }

            // Check to see if the position is within the map and walkable
            if (new Rectangle(0, 0, Width, Height).Contains(newPosition) && currentMap.IsWalkable(newPosition.X, newPosition.Y))
            {
                // Pull a block along if specified
                if (info.KeysDown.Contains(AsciiKey.Get(Keys.Space)))
                {
                    // Are you holding space? Did you move in a direction (eg. left) and there's a push block on the other side (eg. right)?
                    // If so, and if the target block position is walkable, pull it along. But this only works if you're pulling
                    // in the direction you're moving (eg. standing on top and pulling a block upward), NOT standing beside a block
                    // and pulling it upward or standing above a block and pulling to the left/right
                    var currentBlockPos = playerView.Position + new Point(amount.X * -1, amount.Y * -1);
                    if (currentMap.GetObjectsAt(currentBlockPos.X, currentBlockPos.Y).Any(e => e is Pullable))
                    {
                        // Given constraints above, target position is current player position
                        var obj = currentMap.GetObjectsAt(currentBlockPos.X, currentBlockPos.Y).Single(e => e is Pullable);
                        obj.Move(playerView.Position.X, playerView.Position.Y);
                        this.objects.Single(g => g.Data == obj).Move(playerView.Position.X, playerView.Position.Y);
                        this.CheckIfBlockPuzzleIsComplete();
                    }
                }

                // Move the player
                playerView.Position += amount;
                playerView.Data.Move(playerView.Position.X, playerView.Position.Y);
                CenterViewToPlayer();
            }

            var key = this.currentMap.GetObjectsAt(playerView.Position.X, playerView.Position.Y).Where(s => s is Key).SingleOrDefault();

            if (key != null)
            {
                // Not sure why two keys are spawned here
                var keys = this.objects.Where(s => s.Data == key).ToList();
                foreach (var k in keys)
                {
                    this.objects.Remove(k);
                    this.currentMap.Remove(key);
                }

                (this.objects.Single(o => o.Data is Player).Data as Player).Keys += 1;
                this.showMessageCallback("Got a key.");
            }

            // Door there, and we have a key? Unlock it!
            if ((playerView.Data as Player).Keys > 0 && this.currentMap.GetObjectsAt(newPosition.X, newPosition.Y).Any(o => o is LockedDoor))
            {
                var doorData = this.currentMap.GetObjectsAt(newPosition.X, newPosition.Y).Where(o => o is LockedDoor).ToList();
                var doors    = this.objects.Where(o => doorData.Contains(o.Data)).ToList();

                // Why, why WHY are there multiple copies?
                foreach (var door in doors)
                {
                    this.objects.Remove(door);
                    this.currentMap.Remove(door.Data);
                }
                showMessageCallback("You unlock the door.");
                (playerView.Data as Player).Keys -= 1;
            }

            fovTiles = currentFieldOfView.ComputeFov(playerView.Position.X, playerView.Position.Y, Config.Instance.Get <int>("PlayerLightRadius"), true);
            this.MarkCurrentFovAsVisible(fovTiles);

            // Monsters turn. Also, draw their field-of-view. Keep queuing turns until it's the player's turn again.
            var         monstersToMove = new List <IHasAgility>();
            IHasAgility next           = null;

            while (next != playerView.Data)
            {
                if (next != null)
                {
                    monstersToMove.Add(next);
                }
                next = turnCalculator.NextTurn();
            }

            while (monstersToMove.Any())
            {
                var m = monstersToMove[0];
                monstersToMove.RemoveAt(0);
                var monsterView = this.objects.Single(o => o.Data is Monster && o.Data == m);
                var data        = monsterView.Data as Monster;
                var hurtPlayer  = data.MoveWithAi(playerView.Data as Player);
                if (hurtPlayer)
                {
                    if ((playerView.Data as Player).IsDead)
                    {
                        showMessageCallback("The monster hits you! You die ...");
                        this.gameOver = true;
                    }
                    else
                    {
                        showMessageCallback("Monster hits you!");
                    }
                }
                else
                {
                    monsterView.Position = new Point(data.X, data.Y);
                    bool sawPlayer = false;

                    var monsterFov = currentFieldOfView.ComputeFov(data.X, data.Y, data.VisionSize, true);
                    foreach (var cell in monsterFov)
                    {
                        if (fovTiles.Any(f => f.X == data.X && f.Y == data.Y))
                        {
                            this[cell.X, cell.Y].ApplyEffect(MonsterVisionEffect);
                            if (playerView.Position.X == cell.X && playerView.Position.Y == cell.Y)
                            {
                                data.HuntPlayer();
                                monsterView.RenderCells.First().ActualForeground = new Color(255, 0, 0);
                                sawPlayer = true;
                            }
                        }
                        else
                        {
                            if (this.discoveredTiles.ContainsKey($"{data.X}, {data.Y}"))
                            {
                                this[cell.X, cell.Y].ApplyEffect(DiscoveredEffect);
                            }
                            else
                            {
                                this[cell.X, cell.Y].ApplyEffect(HiddenEffect);
                            }
                        }
                    }

                    if (!sawPlayer && monsterView.RenderCells.First().ActualForeground.R == 255)
                    {
                        monsterView.RenderCells.First().ActualForeground = new Color(data.Colour.R, data.Colour.G, data.Colour.B);
                    }
                }
            }

            stopwatch.Stop();
            var elapsed = stopwatch.Elapsed.TotalSeconds;

            Console.WriteLine($"Moving took {elapsed}s");
        }