示例#1
0
        /// <summary>
        /// Repeatedly adds an increment to a given starting value as long as random
        /// numbers continue to be chosen from within a given range. Yields numbers
        /// whose probability gradually tapers off from the starting value.
        /// </summary>
        /// <param name="start">Starting value.</param>
        /// <param name="increment">Amount to modify starting value every successful
        /// iteration.</param>
        /// <param name="chance">The odds of an iteration being successful.</param>
        /// <param name="outOf">The range to choose from to see if the iteration
        /// is successful.</param>
        /// <returns>The resulting value.</returns>
        public static int Taper(int start, int increment, int chance, int outOf)
        {
            if (increment == 0)
            {
                throw new ArgumentOutOfRangeException("increment", "The increment cannot be zero.");
            }
            if (chance <= 0)
            {
                throw new ArgumentOutOfRangeException("chance", "The chance must be greater than zero.");
            }
            if (chance >= outOf)
            {
                throw new ArgumentOutOfRangeException("chance", "The chance must be less than the range.");
            }
            if (outOf <= 0)
            {
                throw new ArgumentOutOfRangeException("outOf", "The range must be positive.");
            }

            int value = start;

            while (Rng.Int(outOf) < chance)
            {
                value += increment;
            }

            return(value);
        }
示例#2
0
        private Rect CreateRoom(Connector connector)
        {
            int width  = Rng.Int(6, 13);
            int height = Rng.Int(6, 13);

            Rect bounds = CreateRectRoom(connector, width, height);

            // bail if we failed
            if (bounds == Rect.Empty)
            {
                return(bounds);
            }

            // place the room
            foreach (Vec pos in bounds)
            {
                mWriter.SetTile(pos, TileType.Floor);
            }

            TileType decoration = ChooseInnerWall();

            RoomDecoration.Decorate(bounds, new FeatureFactory.RoomDecorator(this,
                                                                             pos => mWriter.Populate(pos, 60, 200, mDepth + Rng.Int(mDepth / 10))));

            mWriter.LightRect(bounds, mDepth);

            // place the connectors
            AddRoomConnectors(connector, bounds);

            Populate(bounds, 20, 20, mDepth);

            return(bounds);
        }
示例#3
0
        private void AddRoomEdgeConnectors(Connector connector, Rect edge, Direction dir)
        {
            bool skip = Rng.OneIn(2);

            foreach (Vec pos in edge)
            {
                // don't place connectors close to the incoming connector
                if (connector != null)
                {
                    if (Vec.IsDistanceWithin(connector.Position, pos, 1))
                    {
                        continue;
                    }
                }

                if (!skip && (Rng.Int(100) < mWriter.Options.ChanceOfRoomConnector))
                {
                    mWriter.AddRoomConnector(pos, dir);
                    skip = true;
                }
                else
                {
                    skip = false;
                }
            }
        }
示例#4
0
        /// <summary>
        /// Creates an inner room with a single entrace inside the room.
        /// </summary>
        /// <example>
        /// ##########
        /// #        #
        /// # ****** #
        /// # *    * #
        /// # *    * #
        /// #      * #
        /// # *    * #
        /// # ****** #
        /// #        #
        /// ##########
        /// </example>
        public static void DecorateInnerRoom(Rect room, IRoomDecorator decorator)
        {
            if ((room.Width > 4) && (room.Height > 4))
            {
                foreach (Vec pos in room.Inflate(-1).Trace())
                {
                    decorator.AddDecoration(pos);
                }

                // populate the inside
                foreach (Vec pos in room.Inflate(-2))
                {
                    decorator.AddInsideRoom(pos);
                }

                // add an opening
                Vec opening = Vec.Zero;
                switch (Rng.Int(4))
                {
                case 0: opening = new Vec(Rng.Int(room.Left + 2, room.Right - 2), room.Y + 1); break;

                case 1: opening = new Vec(room.X + 1, Rng.Int(room.Top + 2, room.Bottom - 2)); break;

                case 2: opening = new Vec(Rng.Int(room.Left + 2, room.Right - 2), room.Bottom - 2); break;

                case 3: opening = new Vec(room.Right - 2, Rng.Int(room.Top + 2, room.Bottom - 2)); break;
                }
                decorator.AddDoor(opening);
            }
        }
示例#5
0
        public static void DecorateVerticalWall(Rect room, IRoomDecorator decorator)
        {
            int x = Rng.Int(room.Left + 1, room.Right - 1);

            foreach (Vec pos in Rect.Column(x, room.Top + 1, room.Height - 2))
            {
                decorator.AddDecoration(pos);
            }
        }
示例#6
0
        public static void DecorateHorizontalWall(Rect room, IRoomDecorator decorator)
        {
            int y = Rng.Int(room.Top + 1, room.Bottom - 1);

            foreach (Vec pos in Rect.Row(room.Left + 1, y, room.Width - 2))
            {
                decorator.AddDecoration(pos);
            }
        }
示例#7
0
 void IFeatureWriter.LightRect(Rect bounds, int depth)
 {
     // light the room
     if ((depth <= Rng.Int(1, 80)))
     {
         foreach (Vec pos in bounds.Inflate(1))
         {
             mDungeon.SetTilePermanentLit(pos, true);
         }
     }
 }
示例#8
0
        protected override bool OnStandsFirm(Hit hit)
        {
            // can either dodge it or just tough it out
            int power = Stats.Strength + Stats.Agility;

            if (Rng.Int(Stat.BaseMax * 2) < power)
            {
                // resisted
                return(true);
            }

            return(false);
        }
示例#9
0
        /// <summary>
        /// Randomly chooses and applies a room decoration.
        /// </summary>
        /// <param name="room">Bounds of the room to decorate.</param>
        /// <param name="addDecoration">Callback to add a decoration at the given location.</param>
        public static void Decorate(Rect room, IRoomDecorator decorator)
        {
            // decorate it
            switch (Rng.Int(7))
            {
            case 0: DecorateVerticalWall(room, decorator); break;

            case 1: DecorateHorizontalWall(room, decorator); break;

            case 2: DecorateInnerPillars(room, decorator); break;

            case 3: DecorateOuterPillars(room, decorator); break;

            case 4: DecorateInnerRoom(room, decorator); break;
            }
        }
示例#10
0
        private bool MakeStair(Connector connector)
        {
            // check to see if we can place it
            Rect rect = new Rect(connector.Position.Offset(-1, -1), 3, 3);

            if (!mWriter.IsOpen(rect, connector.Position + connector.Direction.Rotate180))
            {
                return(false);
            }

            TileType type = (Rng.Int(10) < 6) ? TileType.StairsDown : TileType.StairsUp;

            mWriter.SetTile(connector.Position, type);

            return(true);
        }
示例#11
0
        private Rect CreateRectRoom(Connector connector, int width, int height)
        {
            int x = 0;
            int y = 0;

            // position the room
            if (connector == null)
            {
                // initial room, so start near center
                x = Rng.TriangleInt((mWriter.Bounds.Width - width) / 2, (mWriter.Bounds.Width - width) / 2 - 4);
                y = Rng.TriangleInt((mWriter.Bounds.Height - height) / 2, (mWriter.Bounds.Height - height) / 2 - 4);
            }
            else if (connector.Direction == Direction.N)
            {
                // above the connector
                x = Rng.Int(connector.Position.X - width + 1, connector.Position.X + 1);
                y = connector.Position.Y - height;
            }
            else if (connector.Direction == Direction.E)
            {
                // to the right of the connector
                x = connector.Position.X + 1;
                y = Rng.Int(connector.Position.Y - height + 1, connector.Position.Y + 1);
            }
            else if (connector.Direction == Direction.S)
            {
                // below the connector
                x = Rng.Int(connector.Position.X - width + 1, connector.Position.X + 1);
                y = connector.Position.Y + 1;
            }
            else if (connector.Direction == Direction.W)
            {
                // to the left of the connector
                x = connector.Position.X - width;
                y = Rng.Int(connector.Position.Y - height + 1, connector.Position.Y + 1);
            }

            Rect bounds = new Rect(x, y, width, height);

            // check to see if the room can be positioned
            if (!mWriter.IsOpen(bounds.Inflate(1), (connector != null) ? (Vec?)connector.Position : (Vec?)null))
            {
                return(Rect.Empty);
            }

            return(bounds);
        }
示例#12
0
        private void PlaceDoor(Vec pos)
        {
            int choice = Rng.Int(100);

            if (choice < mWriter.Options.ChanceOfOpenDoor)
            {
                mWriter.SetTile(pos, TileType.DoorOpen);
            }
            else if (choice - mWriter.Options.ChanceOfOpenDoor < mWriter.Options.ChanceOfClosedDoor)
            {
                mWriter.SetTile(pos, TileType.DoorClosed);
            }
            else
            {
                mWriter.SetTile(pos, TileType.Floor);
            }
            //### bob: add locked and secret doors
        }
示例#13
0
        /// <summary>
        /// Randomly walks the given level using a... unique distribution. The
        /// goal is to return a value that approximates a bell curve centered
        /// on the start level whose wideness increases as the level increases.
        /// Thus, starting at a low start level will only walk a short distance,
        /// while starting at a higher level can wander a lot farther.
        /// </summary>
        /// <returns></returns>
        public static int WalkLevel(int level)
        {
            int result = level;

            // stack a few triangles to approximate a bell
            for (int i = 0; i < Math.Min(5, level); i++)
            {
                // the width of the triangle is based on the level
                result += Rng.TriangleInt(0, 1 + (level / 20));
            }

            // also have an exponentially descreasing change of going out of depth
            while (Rng.OneIn(10))
            {
                result += 1 + Rng.Int(2 + (level / 5));
            }

            return(result);
        }
示例#14
0
        /// <summary>
        /// Gets whether or not the Entity resists an attempt to physically move it against its will.
        /// </summary>
        /// <param name="damage">The hit that's moving the Entity.</param>
        /// <returns><c>true</c> if the Entity resists and should not be moved.</returns>
        public bool StandsFirm(Hit hit)
        {
            // if the element of the attack is resisted, always stand firm
            if (OnGetResistance(hit.Attack.Element) < 1.0f)
            {
                return(true);
            }

            // give the derived one a chance to resist too
            if (OnStandsFirm(hit))
            {
                return(true);
            }

            // by default, the odds of resisting are half the fraction of the max health that
            // the damage is doing. so, if the damage is taking half the entity's health,
            // the odds of resisting are 1 in 4.
            return(Rng.Int(Health.Max) < (hit.Damage / 2));
        }
示例#15
0
        void IFeatureWriter.Populate(Vec pos, int monsterDensity, int itemDensity, int depth)
        {
            // test every open tile
            if (mDungeon.Tiles[pos].IsPassable)
            {
                // place a monster
                if ((mDungeon.Entities.GetAt(pos) == null) && (Rng.Int(1000) < monsterDensity + (depth / 4)))
                {
                    Monster.AddRandom(mDungeon, depth, pos);
                }

                // place an item
                if (Rng.Int(1000) < itemDensity + (depth / 4))
                {
                    Race race = Race.Random(mDungeon, depth, false);
                    race.PlaceDrop(mDungeon, pos);
                }
            }
        }
示例#16
0
        public static Item Random(Vec pos, ItemType type, int level)
        {
            Item item = new Item(pos, type);

            // let the level wander
            level = Rng.WalkLevel(level);

            // randomly give it a power
            if (Rng.Int(150) <= level)
            {
                PowerType powerType = type.Content.Powers.Random(level, item.Type.Supercategory, item.Type.Subcategory);

                if (powerType != null)
                {
                    item.mPower = new Power(powerType);
                }
            }

            return(item);
        }
示例#17
0
        /// <summary>
        /// Churns the store's inventory a bit. Should be called more frequently the longer it's been
        /// since the Hero last visited.
        /// </summary>
        public void UpdateInventory()
        {
            for (int i = 0; i < Rng.Int(10); i++)
            {
                // drop some new items
                foreach (Item item in mType.Value.Drop.Create(mType.Value.Depth))
                {
                    // as the store gets more full, remove items
                    if (mInventory.Count > Rng.Int(mInventory.Max))
                    {
                        mInventory.RemoveAt(Rng.Int(mInventory.Count));
                    }

                    mInventory.Stack(item);

                    if (item.Quantity > 0)
                    {
                        mInventory.Add(item);
                    }
                }
            }
        }
示例#18
0
        private void InitBuildings(Content content, List <Rect> maxSizes)
        {
            if (maxSizes.Count != 6)
            {
                throw new ArgumentException("Should have the max sizes for 6 buildings.");
            }

            List <TileType> buildings = new List <TileType>()
            {
                TileType.DoorStore1, TileType.DoorStore2, TileType.DoorStore3,
                TileType.DoorStore4, TileType.DoorStore5, TileType.DoorStore6
            };

            // make each building
            foreach (Rect maxSize in maxSizes)
            {
                // pick an actual rect within it
                Vec size = new Vec(Rng.Int(6, maxSize.Width), Rng.Int(4, maxSize.Height));
                Vec pos  = maxSize.Position + Rng.Vec(maxSize.Size - size);

                Rect bounds = new Rect(pos, size);

                // pick the type
                int index = Rng.Int(buildings.Count);
                while (buildings[index] == TileType.Floor)
                {
                    index = (index + 1) % 6;
                }

                TileType type = buildings[index];
                // don't use this store again
                buildings[index] = TileType.Floor;

                Store store = new Store(content.Stores[index]);

                Vec doorPos = new Vec(Rng.IntInclusive(bounds.Left + 1, bounds.Right - 1), bounds.Bottom - 1);
                mBuildings.Add(new Building(store, type, bounds, doorPos));
            }
        }
示例#19
0
        private bool MakePit(Connector connector)
        {
            // pits use room size right now
            int  width  = Rng.Int(mWriter.Options.RoomSizeMin, mWriter.Options.RoomSizeMax);
            int  height = Rng.Int(mWriter.Options.RoomSizeMin, mWriter.Options.RoomSizeMax);
            Rect bounds = CreateRectRoom(connector, width, height);

            // bail if we failed
            if (bounds == Rect.Empty)
            {
                return(false);
            }

            // light it
            mWriter.LightRect(bounds, mDepth);

            // choose a group
            IList <Race> races = mWriter.Content.Races.AllInGroup(Rng.Item(mWriter.Content.Races.Groups));

            // make sure we've got some races that aren't too out of depth
            races = new List <Race>(races.Where(race => race.Depth <= mDepth + 10));
            if (races.Count == 0)
            {
                return(false);
            }

            // place the room
            foreach (Vec pos in bounds)
            {
                mWriter.SetTile(pos, TileType.Floor);
            }

            RoomDecoration.DecorateInnerRoom(bounds, new RoomDecorator(this,
                                                                       pos => mWriter.AddEntity(new Monster(pos, Rng.Item(races)))));

            return(true);
        }
示例#20
0
 public bool ResistDrain()
 {
     //### bob enemy will should affect
     return(Rng.Int(100) < Current);
 }
示例#21
0
        private bool MakeJunction(Connector connector)
        {
            // create a random junction
            Vec center = connector.Position + connector.Direction;

            bool left     = false;
            bool right    = false;
            bool straight = false;

            int choice = Rng.Int(100);

            if (choice < mWriter.Options.ChanceOfTurn)
            {
                if (Rng.OneIn(2))
                {
                    left = true;
                }
                else
                {
                    right = true;
                }
            }
            else if (choice - mWriter.Options.ChanceOfTurn < mWriter.Options.ChanceOfFork)
            {
                if (Rng.OneIn(2))
                {
                    left = true;
                }
                else
                {
                    right = true;
                }
                straight = true;
            }
            else if (choice - mWriter.Options.ChanceOfTurn
                     - mWriter.Options.ChanceOfFork < mWriter.Options.ChanceOfTee)
            {
                left  = true;
                right = true;
            }
            else if (choice - mWriter.Options.ChanceOfTurn
                     - mWriter.Options.ChanceOfFork
                     - mWriter.Options.ChanceOfTee < mWriter.Options.ChanceOfFourWay)
            {
                left     = true;
                right    = true;
                straight = true;
            }
            else
            {
                straight = true;
            }

            // check to see if we can place it
            Rect rect = new Rect(center.Offset(-1, -1), 3, 3);

            if (!mWriter.IsOpen(rect, center + connector.Direction.Rotate180))
            {
                return(false);
            }

            // place the junction
            mWriter.SetTile(center, TileType.Floor);

            // add the connectors
            if (left)
            {
                mWriter.AddRoomConnector(center + connector.Direction.RotateLeft90, connector.Direction.RotateLeft90);
            }
            if (right)
            {
                mWriter.AddRoomConnector(center + connector.Direction.RotateRight90, connector.Direction.RotateRight90);
            }
            if (straight)
            {
                mWriter.AddRoomConnector(center + connector.Direction, connector.Direction);
            }

            return(true);
        }
示例#22
0
        private bool MakeMaze(Connector connector)
        {
            // in maze units (i.e. thin walls), not tiles
            int width  = Rng.Int(mWriter.Options.MazeSizeMin, mWriter.Options.MazeSizeMax);
            int height = Rng.Int(mWriter.Options.MazeSizeMin, mWriter.Options.MazeSizeMax);

            int  tileWidth  = width * 2 + 3;
            int  tileHeight = height * 2 + 3;
            Rect bounds     = CreateRectRoom(connector, tileWidth, tileHeight);

            // bail if we failed
            if (bounds == Rect.Empty)
            {
                return(false);
            }

            // the hallway around the maze
            foreach (Vec pos in bounds.Trace())
            {
                mWriter.SetTile(pos, TileType.Floor);
            }

            // sometimes make the walls low
            if (Rng.OneIn(2))
            {
                foreach (Vec pos in bounds.Inflate(-1))
                {
                    mWriter.SetTile(pos, TileType.LowWall);
                }
            }

            // add an opening in one corner
            Vec doorway;

            switch (Rng.Int(8))
            {
            case 0: doorway = bounds.TopLeft.Offset(2, 1); break;

            case 1: doorway = bounds.TopLeft.Offset(1, 2); break;

            case 2: doorway = bounds.TopRight.Offset(-3, 1); break;

            case 3: doorway = bounds.TopRight.Offset(-2, 2); break;

            case 4: doorway = bounds.BottomRight.Offset(-3, -2); break;

            case 5: doorway = bounds.BottomRight.Offset(-2, -3); break;

            case 6: doorway = bounds.BottomLeft.Offset(2, -2); break;

            case 7: doorway = bounds.BottomLeft.Offset(1, -3); break;

            default: throw new Exception();
            }
            PlaceDoor(doorway);

            // carve the maze
            Maze maze = new Maze(width, height);

            maze.GrowTree();

            Vec offset = bounds.Position.Offset(1, 1);

            maze.Draw(pos => mWriter.SetTile(pos + offset, TileType.Floor));

            mWriter.LightRect(bounds, mDepth);

            // populate it
            int boostedDepth = mDepth + Rng.Int(mDepth / 5) + 2;

            Populate(bounds.Inflate(-2), 200, 300, boostedDepth);

            // place the connectors
            AddRoomConnectors(connector, bounds);

            return(true);
        }
示例#23
0
 public void Randomize()
 {
     mEnergy = Rng.Int(ActionCost);
 }
示例#24
0
        public bool MakeHall(Connector connector)
        {
            // create a random hall
            int length = Rng.Int(mWriter.Options.HallLengthMin, mWriter.Options.HallLengthMax);

            // check to see if we can place it
            Rect bounds = Rect.Empty;

            if (connector.Direction == Direction.N)
            {
                bounds = new Rect(connector.Position.X - 1, connector.Position.Y - length, 3, length + 1);
            }
            if (connector.Direction == Direction.S)
            {
                bounds = new Rect(connector.Position.X - 1, connector.Position.Y, 3, length + 1);
            }
            if (connector.Direction == Direction.E)
            {
                bounds = new Rect(connector.Position.X, connector.Position.Y - 1, length + 1, 3);
            }
            if (connector.Direction == Direction.W)
            {
                bounds = new Rect(connector.Position.X - length, connector.Position.Y - 1, length + 1, 3);
            }

            if (!mWriter.IsOpen(bounds, null))
            {
                return(false);
            }

            // make sure the end corners aren't open unless the position in front of the end is too
            // prevents cases like:
            Vec pos = connector.Position + (connector.Direction.Offset * (length + 1));

            if (!mWriter.Bounds.Contains(pos))
            {
                return(false);
            }
            if (!mWriter.Bounds.Contains(pos + connector.Direction.RotateLeft90))
            {
                return(false);
            }
            if (!mWriter.Bounds.Contains(pos + connector.Direction.RotateRight90))
            {
                return(false);
            }
            // ####..
            // ####..
            // ....## <- new hall ends at corner of room
            // ######
            if ((mWriter.GetTile(pos + connector.Direction.RotateLeft90) != TileType.Wall) &&
                (mWriter.GetTile(pos) == TileType.Wall))
            {
                return(false);
            }

            if ((mWriter.GetTile(pos + connector.Direction.RotateRight90) != TileType.Wall) &&
                (mWriter.GetTile(pos) == TileType.Wall))
            {
                return(false);
            }

            // place the hall
            pos = connector.Position;
            for (int i = 0; i <= length; i++)
            {
                mWriter.SetTile(pos, TileType.Floor);

                pos += connector.Direction;
            }

            PlaceDoor(connector.Position);
            PlaceDoor(connector.Position + (connector.Direction.Offset * length));

            // add the connectors
            mWriter.AddHallConnector(connector.Position + (connector.Direction.Offset * length),
                                     connector.Direction);

            Populate(bounds, 10, 10, mDepth);

            return(true);
        }
示例#25
0
        protected override ActionResult OnProcess()
        {
            Hero hero = (Hero)Entity;

            // restore to max
            mStat.Restore();

            if (mStat.Base < Stat.BaseMax)
            {
                // pick a stat to drain
                int i = Rng.Int(hero.Stats.Count - 1);
                if (hero.Stats[i] == mStat)
                {
                    // picked the stat being raised, so skip it
                    i++;
                }

                // drain one
                hero.Stats[i].Base--;

                // to raise another
                mStat.Base++;

                if (mStat == hero.Stats.Strength)
                {
                    Log(LogType.PermanentGood, "{subject} feel[s] filled with brute strength!");
                }
                else if (mStat == hero.Stats.Agility)
                {
                    Log(LogType.PermanentGood, "{subject} feel[s] thin and nimble!");
                }
                else if (mStat == hero.Stats.Stamina)
                {
                    Log(LogType.PermanentGood, "{subject} feel[s] solid as a rock!");
                }
                else if (mStat == hero.Stats.Will)
                {
                    Log(LogType.PermanentGood, "{subject} feel[s] filled with blind courage!");
                }
                else if (mStat == hero.Stats.Intellect)
                {
                    Log(LogType.PermanentGood, "{subject} feel[s] clever!");
                }
                else if (mStat == hero.Stats.Charisma)
                {
                    Log(LogType.PermanentGood, "{subject} feel[s] pretty!");
                }
                else
                {
                    throw new Exception("Unknown stat \"" + mStat.Name + "\".");
                }
            }
            else
            {
                if (mStat == hero.Stats.Strength)
                {
                    Log(LogType.DidNotWork, "{subject} do[es]n't feel any stronger.");
                }
                else if (mStat == hero.Stats.Agility)
                {
                    Log(LogType.DidNotWork, "{subject} do[es]n't feel any more graceful.");
                }
                else if (mStat == hero.Stats.Stamina)
                {
                    Log(LogType.DidNotWork, "{subject} do[es]n't feel any tougher.");
                }
                else if (mStat == hero.Stats.Will)
                {
                    Log(LogType.DidNotWork, "{subject} do[es]n't feel any more courageous.");
                }
                else if (mStat == hero.Stats.Intellect)
                {
                    Log(LogType.DidNotWork, "{subject} do[es]n't feel any smarter.");
                }
                else if (mStat == hero.Stats.Charisma)
                {
                    Log(LogType.DidNotWork, "{subject} do[es]n't feel any prettier.");
                }
                else
                {
                    throw new Exception("Unknown stat \"" + mStat.Name + "\".");
                }
            }

            return(ActionResult.Done);
        }
示例#26
0
 public bool ShouldAttempt()
 {
     return(Rng.Int(Info.Range) < Info.Chance);
 }
        public Direction GetDirection(Monster monster, Entity target)
        {
            Vec relative = target.Position - monster.Position;

            // walk towards player
            Direction direction = Direction.Towards(relative);

            // move erratically
            switch (mPursue)
            {
            case Pursue.Closely:
                // do nothing
                break;

            case Pursue.SlightlyErratically:
                while (Rng.OneIn(3))
                {
                    if (Rng.OneIn(2))
                    {
                        direction = direction.Next;
                    }
                    else
                    {
                        direction = direction.Previous;
                    }
                }
                break;

            case Pursue.Erratically:
                while (Rng.OneIn(2))
                {
                    if (Rng.OneIn(2))
                    {
                        direction = direction.Next;
                    }
                    else
                    {
                        direction = direction.Previous;
                    }
                }
                break;

            case Pursue.VeryErratically:
                int turns = Rng.Int(3);
                for (int i = 0; i < turns; i++)
                {
                    if (Rng.OneIn(2))
                    {
                        direction = direction.Next;
                    }
                    else
                    {
                        direction = direction.Previous;
                    }
                }
                break;
            }

            // don't walk through walls
            if (!monster.CanMove(direction) || monster.IsOccupiedByOtherMonster(direction.Offset, target))
            {
                // try to go around obstacle
                Direction firstTry  = direction.Previous;
                Direction secondTry = direction.Next;

                // don't always try the same order
                if (Rng.OneIn(2))
                {
                    Obj.Swap(ref firstTry, ref secondTry);
                }

                if (monster.CanMove(firstTry) && !monster.IsOccupiedByOtherMonster(firstTry.Offset, target))
                {
                    direction = firstTry;
                }
                else if (monster.CanMove(secondTry) && !monster.IsOccupiedByOtherMonster(secondTry.Offset, target))
                {
                    direction = secondTry;
                }
                else
                {
                    // give up
                    direction = Direction.None;
                }
            }

            return(direction);
        }
示例#28
0
        public IEnumerable <T> Create(int level)
        {
            // find the drops before and after the level
            int before = -1;
            int after  = -1;

            for (int i = 0; i < Choices.Count; i++)
            {
                if (Choices[i].Odds <= level)
                {
                    before = i;
                }
                else if (Choices[i].Odds >= level)
                {
                    after = i;
                    break;
                }
            }

            if (before == -1)
            {
                before = after;
            }
            if (after == -1)
            {
                after = before;
            }

            // choose between the two drops, weighted by the level's distance to each one
            int index = before;

            if (before != after)
            {
                if (Rng.IntInclusive((int)Choices[before].Odds, (int)Choices[after].Odds) <= level)
                {
                    index = after;
                }
                else
                {
                    index = before;
                }
            }

            const int ChanceOfDecrement = 40; // out of 100
            const int ChanceOfIncrement = 10;

            // randomly walk through the drops
            if (Rng.Int(100) < ChanceOfDecrement)
            {
                // walk down
                while (index > 0)
                {
                    index--;

                    if (Rng.Int(100) >= ChanceOfDecrement)
                    {
                        break;
                    }
                }
            }
            else if (Rng.Int(100) < ChanceOfIncrement)
            {
                // walk up
                while (index < Choices.Count - 1)
                {
                    index++;

                    if (Rng.Int(100) >= ChanceOfIncrement)
                    {
                        break;
                    }
                }
            }

            // drop it
            foreach (var item in Choices[index].Drop.Create(level))
            {
                yield return(item);
            }
        }
示例#29
0
 void IFeatureWriter.AddHallConnector(Vec pos, Direction dir)
 {
     mUnusedConnectors.Insert(Rng.Int(mUnusedConnectors.Count), new Connector(ConnectFrom.Hall, dir, pos));
 }