예제 #1
0
        protected internal override void OnZap(int cell)
        {
            var localLevel = Level;

            var n = localLevel + 2;

            if (Actor.FindChar(cell) != null && Ballistica.Distance > 2)
            {
                cell = Ballistica.Trace[Ballistica.Distance - 2];
            }

            var passable = BArray.or(levels.Level.passable, levels.Level.avoid, null);

            foreach (var actor in Actor.All.OfType <Character>())
            {
                passable[(actor).pos] = false;
            }

            PathFinder.BuildDistanceMap(cell, passable, n);
            var dist = 0;

            if (Actor.FindChar(cell) != null)
            {
                PathFinder.Distance[cell] = int.MaxValue;
                dist = 1;
            }

            float lifespan = localLevel + 3;

sheepLabel:
            for (var i = 0; i < n; i++)
            {
                do
                {
                    for (var j = 0; j < levels.Level.Length; j++)
                    {
                        if (PathFinder.Distance[j] != dist)
                        {
                            continue;
                        }

                        var sheep = new Sheep();
                        sheep.Lifespan = lifespan;
                        sheep.pos      = j;
                        GameScene.Add(sheep);
                        Dungeon.Level.MobPress(sheep);

                        CellEmitter.Get(j).Burst(Speck.Factory(Speck.WOOL), 4);

                        PathFinder.Distance[j] = int.MaxValue;

                        goto sheepLabel;
                    }
                    dist++;
                } while (dist < n);
            }
        }
예제 #2
0
파일: Blob.cs 프로젝트: zvinch/SharpDungeon
        protected internal virtual void Evolve()
        {
            var notBlocking = BArray.not(levels.Level.solid, null);

            for (var i = 1; i < Height - 1; i++)
            {
                var from = i * Width + 1;
                var to   = from + Width - 2;

                for (var pos = from; pos < to; pos++)
                {
                    if (notBlocking[pos])
                    {
                        var count = 1;
                        var sum   = Cur[pos];

                        if (notBlocking[pos - 1])
                        {
                            sum += Cur[pos - 1];
                            count++;
                        }

                        if (notBlocking[pos + 1])
                        {
                            sum += Cur[pos + 1];
                            count++;
                        }

                        if (notBlocking[pos - Width])
                        {
                            sum += Cur[pos - Width];
                            count++;
                        }

                        if (notBlocking[pos + Width])
                        {
                            sum += Cur[pos + Width];
                            count++;
                        }

                        var value = sum >= count ? (sum / count) - 1 : 0;
                        Off[pos] = value;

                        Volume += value;
                    }
                    else
                    {
                        Off[pos] = 0;
                    }
                }
            }
        }
예제 #3
0
        public static void Observe()
        {
            if (Level == null)
            {
                return;
            }

            Level.UpdateFieldOfView(Hero);
            Array.Copy(Level.fieldOfView, 0, Visible, 0, Visible.Length);

            BArray.or(Level.visited, Visible, Level.visited);

            GameScene.AfterObserve();
        }
예제 #4
0
        public override void Activate(Character ch)
        {
            base.Activate(ch);

            PathFinder.BuildDistanceMap(Pos, BArray.not(Level.losBlocking, null), 1);

            var fire = (Fire)Dungeon.Level.Blobs[typeof(Fire)];

            for (var i = 0; i < Level.Length; i++)
            {
                if (PathFinder.Distance[i] < int.MaxValue)
                {
                    Freezing.Affect(i, fire);
                }
            }
        }
예제 #5
0
        protected internal override void OnZap(int cell)
        {
            Sample.Instance.Play(Assets.SND_ROCKS);

            var localLevel = Level;

            Ballistica.Distance = Math.Min(Ballistica.Distance, 8 + localLevel);

            var size = 1 + localLevel / 3;

            PathFinder.BuildDistanceMap(cell, BArray.not(levels.Level.solid, null), size);

            for (var i = 0; i < levels.Level.Length; i++)
            {
                int d = PathFinder.Distance[i];

                if (d >= int.MaxValue)
                {
                    continue;
                }

                var ch = Actor.FindChar(i);
                if (ch != null)
                {
                    ch.Sprite.Flash();

                    ch.Damage(pdsharp.utils.Random.Int(2, 6 + (size - d) * 2), this);

                    if (ch.IsAlive && pdsharp.utils.Random.Int(2 + d) == 0)
                    {
                        Buff.Prolong <Paralysis>(ch, pdsharp.utils.Random.IntRange(2, 6));
                    }
                }

                CellEmitter.Get(i).Start(Speck.Factory(Speck.ROCK), 0.07f, 3 + (size - d));
                Camera.Main.Shake(3, 0.07f * (3 + (size - d)));
            }

            if (CurUser.IsAlive)
            {
                return;
            }

            Dungeon.Fail(Utils.Format(ResultDescriptions.WAND, name, Dungeon.Depth));
            GLog.Negative("You killed yourself with your own Wand of Avalanche...");
        }
예제 #6
0
        protected internal override void Shatter(int cell)
        {
            PathFinder.BuildDistanceMap(cell, BArray.not(Level.losBlocking, null), Distance);

            var fire = (Fire)Dungeon.Level.Blobs[typeof(Fire)];

            for (var i = 0; i < Level.Length; i++)
            {
                if (PathFinder.Distance[i] < int.MaxValue)
                {
                    Freezing.Affect(i, fire);
                }
            }

            splash(cell);
            Sample.Instance.Play(Assets.SND_SHATTER);

            SetKnown();
        }
예제 #7
0
        public static int Flee(Character ch, int cur, int from, bool[] pass, bool[] visible)
        {
            if (ch.Flying)
            {
                BArray.or(pass, Level.avoid, Passable);
            }
            else
            {
                Array.Copy(pass, 0, Passable, 0, Level.Length);
            }

            foreach (var pos in Actor.All.OfType <Character>().Select(c => c.pos).Where(pos => visible[pos]))
            {
                Passable[pos] = false;
            }

            Passable[cur] = true;

            return(PathFinder.GetStepBack(cur, from, Passable));
        }
예제 #8
0
        public static int FindPath(Character ch, int from, int to, bool[] pass, bool[] visible)
        {
            if (Level.Adjacent(from, to))
            {
                return(Actor.FindChar(to) == null && (pass[to] || Level.avoid[to]) ? to : -1);
            }

            if (ch.Flying || ch.Buff <Amok>() != null)
            {
                BArray.or(pass, Level.avoid, Passable);
            }
            else
            {
                Array.Copy(pass, 0, Passable, 0, Level.Length);
            }

            foreach (int pos in Actor.All.OfType <Character>().Select(actor => (actor).pos).Where(pos => visible[pos]))
            {
                Passable[pos] = false;
            }

            return(PathFinder.GetStep(from, to, Passable));
        }
예제 #9
0
        /// <summary>
        /// Helper method to get a random element in a BSON array.
        /// </summary>
        public BValue ArrayElement(BArray props, int?min = null, int?max = null)
        {
            var r = Number(min: min ?? 0, max: max - 1 ?? props.Count - 1);

            return(props[r]);
        }
예제 #10
0
        protected internal override void Shatter(int cell)
        {
            PathFinder.BuildDistanceMap(cell, BArray.not(Level.losBlocking, null), DISTANCE);

            var procd = false;

            Blob[] blobs = { Dungeon.Level.Blobs[typeof(ToxicGas)], Dungeon.Level.Blobs[typeof(ParalyticGas)] };

            foreach (var blob in blobs)
            {
                if (blob == null)
                {
                    continue;
                }

                for (var i = 0; i < Level.Length; i++)
                {
                    if (PathFinder.Distance[i] >= int.MaxValue)
                    {
                        continue;
                    }

                    var value = blob.Cur[i];
                    if (value <= 0)
                    {
                        continue;
                    }

                    blob.Cur[i]  = 0;
                    blob.Volume -= value;
                    procd        = true;

                    CellEmitter.Get(i).Burst(Speck.Factory(Speck.DISCOVER), 1);
                }
            }

            var heroAffected = PathFinder.Distance[Dungeon.Hero.pos] < int.MaxValue;

            if (procd)
            {
                splash(cell);
                Sample.Instance.Play(Assets.SND_SHATTER);

                SetKnown();

                if (heroAffected)
                {
                    GLog.Positive(TXT_FRESHNESS);
                }
            }
            else
            {
                base.Shatter(cell);

                if (!heroAffected)
                {
                    return;
                }

                GLog.Information(TXT_FRESHNESS);
                SetKnown();
            }
        }
예제 #11
0
        public override void Paint(Level level)
        {
            var w = GetWidth();
            var h = GetHeight();

            var old = Painter.Clip;

            Painter.Clip = null;
            Painter.Fill(level, this, Wall);
            Painter.Clip = old;

            Painter.FillEllipse(level, this, 3, Tile.FloorA);
            Painter.FillEllipse(level, this, (int)(Math.Min(w, h) / 2f - 2), Tile.FloorD);

            var r = GetCenterRect();

            PaintTunnel(level, Tile.FloorA, r, true);
            PaintTunnel(level, Tile.FloorD, r);

            Pass((x, y) => {
                var t = level.Get(x, y);

                if (t != Tile.FloorD || Rnd.Chance(30))
                {
                    if (t == Tile.WallA && Rnd.Chance(10))
                    {
                        Painter.Set(level, x, y, Tile.FloorA);
                    }

                    return;
                }

                var sz = Rnd.Int(2, 4);

                for (var xx = -sz; xx <= sz; xx++)
                {
                    for (var yy = -sz; yy <= sz; yy++)
                    {
                        if (level.Get(x + xx, y + yy) != Tile.FloorD)
                        {
                            Painter.Set(level, x + xx, y + yy, Rnd.Chance(30) ? Tile.WallA : Tile.FloorA);
                        }
                    }
                }
            });

            var array    = new byte[w, h];
            var oldArray = new byte[w, h];

            Pass((x, y) => {
                var t = level.Get(x, y);

                if (t == Tile.FloorA && Rnd.Float() > 0.55f - (float)(Math.Cos(x / 16f) * 0.02f + Math.Cos(y / 16f) * 0.1f))
                {
                    t = Tile.WallA;
                    Painter.Set(level, x, y, t);
                }

                var v = t == Tile.FloorA ? 0 : 1;

                if (t == Tile.FloorD)
                {
                    v = 2;
                }

                array[x - Left, y - Top]    = (byte)v;
                oldArray[x - Left, y - Top] = (byte)v;
            });

            for (var i = 0; i < 5; i++)
            {
                for (var x = 0; x < w; x++)
                {
                    for (var y = 0; y < h; y++)
                    {
                        var c = oldArray[x, y];
                        var n = 0;

                        foreach (var d in MathUtils.AllDirections)
                        {
                            var xx = x + (int)d.X;
                            var yy = y + (int)d.Y;

                            if (xx < 0 || xx >= w || yy < 0 || yy >= h)
                            {
                                n++;
                                continue;
                            }

                            if (oldArray[xx, yy] == 1)
                            {
                                n++;
                            }
                        }

                        if (c != 2)
                        {
                            if (n < DeathCondition)
                            {
                                c = 0;
                            }
                            else if (n > BirthCondition)
                            {
                                c = 1;
                            }
                        }

                        array[x, y] = c;
                    }
                }

                for (var x = 0; x < w; x++)
                {
                    for (var y = 0; y < h; y++)
                    {
                        oldArray[x, y] = array[x, y];
                    }
                }
            }

            Action <int, int> fill = null;
            var queue = new Queue <Dot>();
            var m     = 0;

            fill = (x, y) => {
                if (x < 0 || y < 0 || x >= w || y >= h)
                {
                    return;
                }

                var v = array[x, y];

                if (v == 1 || v == 3)
                {
                    return;
                }

                m++;
                array[x, y] = 3;

                queue.Enqueue(new Dot(x - 1, y));
                queue.Enqueue(new Dot(x + 1, y));
                queue.Enqueue(new Dot(x, y - 1));
                queue.Enqueue(new Dot(x, y + 1));
            };

            var painted = false;

            foreach (var dr in Connected.Values)
            {
                var st = new Dot(dr.X, dr.Y);

                if (dr.X == Left)
                {
                    st = new Dot(dr.X + 1, dr.Y);
                }
                else if (dr.X == Right)
                {
                    st = new Dot(dr.X - 1, dr.Y);
                }
                else if (dr.Y == Top)
                {
                    st = new Dot(dr.X, dr.Y + 1);
                }
                else if (dr.Y == Bottom)
                {
                    st = new Dot(dr.X, dr.Y - 1);
                }

                fill(st.X - Left, st.Y - Top);

                if (queue.Count != 0)
                {
                    painted = true;
                    break;
                }
            }

            if (!painted)
            {
                Log.Error("Did not spot a spot in the jungle room!");
                Paint(level);
                return;
            }

            while (queue.Count > 0)
            {
                var d = queue.Dequeue();
                fill(d.X, d.Y);
            }

            var start = 0;

            var ww = GetWidth();
            var hh = GetHeight();

            Func <int, int, int> toIndex = (x, y) => (x - Left) + (y - Top) * ww;

            foreach (var d in Connected.Values)
            {
                if (d.X == Left)
                {
                    start = toIndex(d.X + 1, d.Y);
                }
                else if (d.X == Right)
                {
                    start = toIndex(d.X - 1, d.Y);
                }
                else if (d.Y == Top)
                {
                    start = toIndex(d.X, d.Y + 1);
                }
                else if (d.Y == Bottom)
                {
                    start = toIndex(d.X, d.Y - 1);
                }
            }

            Pass((x, y) => {
                if (x > Left && x < Right && y > Top && y < Bottom)
                {
                    Painter.Set(level, x, y, array[x - Left, y - Top] == 3 ? Floor : Wall);
                }
            });

            var patch = new bool[ww * hh];

            for (var y = 0; y < hh; y++)
            {
                for (var x = 0; x < ww; x++)
                {
                    patch[y * ww + x] = !level.Get(Left + x, Top + y).IsPassable();
                }
            }

            PathFinder.SetMapSize(ww, hh);
            PathFinder.BuildDistanceMap(start, BArray.Not(patch, null));
            var valid = true;

            for (var i = 0; i < patch.Length; i++)
            {
                if (!patch[i] && PathFinder.Distance[i] == Int32.MaxValue)
                {
                    valid = false;
                    break;
                }
            }

            // level.Set(Left + start % ww, Top + start / ww, Tile.Cobweb);
            PathFinder.SetMapSize(level.Width, level.Height);

            if (!valid)
            {
                Log.Error("Failed to build path");
                Paint(level);
                return;
            }

            patch = Patch.GenerateWithNoise(w, h, Rnd.Float(10000), 0.25f, 0.1f);

            if (Floor2 != Floor)
            {
                Pass((x, y) => {
                    if (level.Get(x, y) == Floor && patch[(x - Left) + (y - Top) * w])
                    {
                        Painter.Set(level, x, y, Floor2);
                    }
                });
            }
        }
예제 #12
0
        protected void Setup(Level level, RoomDef room, float fill, int clustering, bool ensurePath)
        {
            Run.Level = level;
            var w = room.GetWidth() - 2;
            var h = room.GetHeight() - 2;

            if (ensurePath)
            {
                PathFinder.SetMapSize(w, h);

                var valid   = false;
                var attempt = 0;

                do
                {
                    Patch = BurningKnight.level.Patch.Generate(w, h, fill, clustering);
                    var start = 0;

                    foreach (var d in room.Connected.Values)
                    {
                        if (d.X == room.Left)
                        {
                            start = ToIndex(room, d.X + 1, d.Y);

                            Patch[ToIndex(room, d.X + 1, d.Y)] = false;
                            Patch[ToIndex(room, d.X + 2, d.Y)] = false;
                        }
                        else if (d.X == room.Right)
                        {
                            start = ToIndex(room, d.X - 1, d.Y);

                            Patch[ToIndex(room, d.X - 1, d.Y)] = false;
                            Patch[ToIndex(room, d.X - 2, d.Y)] = false;
                        }
                        else if (d.Y == room.Top)
                        {
                            start = ToIndex(room, d.X, d.Y + 1);

                            Patch[ToIndex(room, d.X, d.Y + 1)] = false;
                            Patch[ToIndex(room, d.X, d.Y + 2)] = false;
                        }
                        else if (d.Y == room.Bottom)
                        {
                            start = ToIndex(room, d.X, d.Y - 1);

                            Patch[ToIndex(room, d.X, d.Y - 1)] = false;
                            Patch[ToIndex(room, d.X, d.Y - 2)] = false;
                        }
                    }

                    PathFinder.BuildDistanceMap(start, BArray.Not(Patch, null));
                    valid = true;

                    for (var i = 0; i < Patch.Length; i++)
                    {
                        if (!Patch[i] && PathFinder.Distance[i] == Int32.MaxValue)
                        {
                            valid = false;
                            break;
                        }
                    }

                    if (!valid && fill > 0.1f)
                    {
                        fill -= 0.01f;
                    }
                } while (attempt++ < 1000 && !valid);

                if (!valid)
                {
                    Log.Error("Failed to generate patch");

                    for (var i = 0; i < Patch.Length; i++)
                    {
                        Patch[i] = false;
                    }
                }

                PathFinder.SetMapSize(level.Width, level.Height);
            }
            else
            {
                Patch = BurningKnight.level.Patch.Generate(w, h, fill, clustering);
            }
        }
예제 #13
0
        public override void Paint(Level level, RoomDef room, Rect inside)
        {
            var fill = 0.25f + (room.GetWidth() * room.GetHeight()) / 1024f;
            var s    = Rnd.Chance();

            bool[] oldPatch = null;

            if (s)
            {
                Setup(level, room, fill, 4, true);
                CleanDiagonalEdges(room);
                PaintPatch(level, room, Tiles.RandomSolid());
                oldPatch = ArrayUtils.Clone(Patch);
            }

            SimplePaint(level, room);

            if (s)
            {
                PathFinder.SetMapSize(room.GetWidth() - 2, room.GetHeight() - 2);
                var start = 0;

                foreach (var d in room.Connected.Values)
                {
                    if (d.X == room.Left)
                    {
                        start = ToIndex(room, d.X + 1, d.Y);
                    }
                    else if (d.X == room.Right)
                    {
                        start = ToIndex(room, d.X - 1, d.Y);
                    }
                    else if (d.Y == room.Top)
                    {
                        start = ToIndex(room, d.X, d.Y + 1);
                    }
                    else if (d.Y == room.Bottom)
                    {
                        start = ToIndex(room, d.X, d.Y - 1);
                    }
                }

                for (var i = 0; i < Patch.Length; i++)
                {
                    if (oldPatch[i])
                    {
                        Patch[i] = true;
                    }
                }

                PathFinder.BuildDistanceMap(start, BArray.Not(Patch, null));
                var valid = true;

                for (var i = 0; i < Patch.Length; i++)
                {
                    if (!Patch[i] && PathFinder.Distance[i] == Int32.MaxValue)
                    {
                        valid = false;
                        break;
                    }
                }

                PathFinder.SetMapSize(level.Width, level.Height);

                if (!valid)
                {
                    Painter.Fill(level, room, 1, Tiles.RandomFloor());
                    SimplePaint(level, room);
                }
            }
        }