protected internal virtual void PaintGrass() { var grass = Grass(); if (feeling == Feeling.GRASS) { foreach (var room in Rooms.Where(room => room.type != RoomType.NULL && room.type != RoomType.PASSAGE && room.type != RoomType.TUNNEL)) { grass[(room.Left + 1) + (room.Top + 1) * Width] = true; grass[(room.Right - 1) + (room.Top + 1) * Width] = true; grass[(room.Left + 1) + (room.Bottom - 1) * Width] = true; grass[(room.Right - 1) + (room.Bottom - 1) * Width] = true; } } for (var i = Width + 1; i < Length - Width - 1; i++) { if (map[i] != Terrain.EMPTY || !grass[i]) { continue; } var count = 1 + NEIGHBOURS8.Count(n => grass[i + n]); map[i] = (Random.Float() < count / 12f) ? Terrain.HIGH_GRASS : Terrain.GRASS; } }
public virtual void Move(int step) { if (Buff <Vertigo>() != null) { var candidates = new List <int>(); foreach (var dir in Level.NEIGHBOURS8) { var p = pos + dir; if ((Level.passable[p] || Level.avoid[p]) && FindChar(p) == null) { candidates.Add(p); } } step = Random.Element(candidates.ToArray()); } if (Dungeon.Level.map[pos] == Terrain.OPEN_DOOR) { Door.Leave(pos); } pos = step; if (Flying && Dungeon.Level.map[pos] == Terrain.DOOR) { Door.Enter(pos); } if (this != Dungeon.Hero) { Sprite.Visible = Dungeon.Visible[pos]; } }
public override int DefenseProc(Character enemy, int damage) { var thorns = Buff <RingOfThorns.Thorns>(); if (thorns != null) { var dmg = Random.IntRange(0, damage); if (dmg > 0) { enemy.Damage(dmg, thorns); } } var armor = Buff <Earthroot.Armor>(); if (armor != null) { damage = armor.Absorb(damage); } if (Belongings.Armor != null) { damage = Belongings.Armor.Proc(enemy, this, damage); } return(damage); }
public static bool Hit(Character attacker, Character defender, bool magic) { float acuRoll = Random.Float(attacker.AttackSkill(defender)); float defRoll = Random.Float(defender.DefenseSkill(attacker)); return((magic ? acuRoll * 2 : acuRoll) >= defRoll); }
private void PlaceDoors(Room r) { foreach (var n in r.Connected.Keys.ToList()) { var door = r.Connected[n]; if (door != null) { continue; } var i = r.Intersect(n); if (i.Width() == 0) { door = new Room.Door(i.Left, Random.Int(i.Top + 1, i.Bottom)); } else { door = new Room.Door(Random.Int(i.Left + 1, i.Right), i.Top); } if (r.Connected.ContainsKey(n)) { r.Connected[n] = door; } else { r.Connected.Add(n, door); } n.Connected[r] = door; } }
private static void PaintBurned(Level level, Room room) { for (var i = room.Top + 1; i < room.Bottom; i++) { for (var j = room.Left + 1; j < room.Right; j++) { var t = Terrain.EMBERS; switch (Random.Int(5)) { case 0: t = Terrain.EMPTY; break; case 1: t = Terrain.FIRE_TRAP; break; case 2: t = Terrain.SECRET_FIRE_TRAP; break; case 3: t = Terrain.INACTIVE_TRAP; break; } level.map[i * Level.Width + j] = t; } } }
protected internal virtual void PaintDoors(Room r) { foreach (var n in r.Connected.Keys) { if (JoinRooms(r, n)) { continue; } var d = r.Connected[n]; var door = d.X + d.Y * Width; switch (d.Type) { case levels.Room.Door.DoorType.EMPTY: map[door] = Terrain.EMPTY; break; case levels.Room.Door.DoorType.TUNNEL: map[door] = TunnelTile(); break; case levels.Room.Door.DoorType.REGULAR: if (Dungeon.Depth <= 1) { map[door] = Terrain.DOOR; } else { var localSecret = (Dungeon.Depth < 6 ? Random.Int(12 - Dungeon.Depth) : Random.Int(6)) == 0; map[door] = localSecret ? Terrain.SECRET_DOOR : Terrain.DOOR; if (localSecret) { SecretDoors++; } } break; case levels.Room.Door.DoorType.UNLOCKED: map[door] = Terrain.DOOR; break; case levels.Room.Door.DoorType.HIDDEN: map[door] = Terrain.SECRET_DOOR; break; case levels.Room.Door.DoorType.BARRICADE: map[door] = Random.Int(3) == 0 ? Terrain.BOOKSHELF : Terrain.BARRICADE; break; case levels.Room.Door.DoorType.LOCKED: map[door] = Terrain.LOCKED_DOOR; break; } } }
protected internal override void CreateItems() { #if DEBUG return; #endif var nItems = 3; while (Random.Float() < 0.3f) { nItems++; } for (var i = 0; i < nItems; i++) { Heap.Type type; switch (Random.Int(20)) { case 0: type = Heap.Type.Skeleton; break; case 1: case 2: case 3: case 4: type = Heap.Type.Chest; break; default: type = Heap.Type.Heap; break; } Drop(Generator.Random(), RandomDropCell()).HeapType = type; } foreach (var itemToSpawn in itemsToSpawn) { var cell = RandomDropCell(); if (itemToSpawn is ScrollOfUpgrade) { while (map[cell] == Terrain.FIRE_TRAP || map[cell] == Terrain.SECRET_FIRE_TRAP) { cell = RandomDropCell(); } } Drop(itemToSpawn, cell).HeapType = Heap.Type.Heap; } var item = Bones.Get(); if (item != null) { Drop(item, RandomDropCell()).HeapType = Heap.Type.Skeleton; } }
protected internal virtual Room RandomRoom(RoomType type, int tries) { for (var i = 0; i < tries; i++) { var room = Random.Element(Rooms); if (room.type == type) { return(room); } } return(null); }
protected internal virtual void PlaceTraps() { var numberOfTraps = NumberOfTraps(); var trapChances = TrapChances(); for (var i = 0; i < numberOfTraps; i++) { var trapPos = Random.Int(Length); if (map[trapPos] != Terrain.EMPTY) { continue; } switch (Random.Chances(trapChances)) { case 0: map[trapPos] = Terrain.SECRET_TOXIC_TRAP; break; case 1: map[trapPos] = Terrain.SECRET_FIRE_TRAP; break; case 2: map[trapPos] = Terrain.SECRET_PARALYTIC_TRAP; break; case 3: map[trapPos] = Terrain.SECRET_POISON_TRAP; break; case 4: map[trapPos] = Terrain.SECRET_ALARM_TRAP; break; case 5: map[trapPos] = Terrain.SECRET_LIGHTNING_TRAP; break; case 6: map[trapPos] = Terrain.SECRET_GRIPPING_TRAP; break; case 7: map[trapPos] = Terrain.SECRET_SUMMONING_TRAP; break; } } }
private static bool Chance(int[] quota, int number) { for (var i = 0; i < quota.Length; i += 2) { var qDepth = quota[i]; if (Depth > qDepth) { continue; } var qNumber = quota[i + 1]; return(Random.Float() < (float)(qNumber - number) / (qDepth - Depth + 1)); } return(false); }
public override int DamageRoll() { var wep = RangedWeapon ?? Belongings.Weapon; int dmg; if (wep != null) { dmg = wep.DamageRoll(this); } else { dmg = STR > 10 ? Random.IntRange(1, STR - 9) : 1; } return(Buff <Fury>() != null ? (int)(dmg * 1.5f) : dmg); }
public override int RandomDestination() { while (true) { var room = Random.Element(Rooms); if (room == null) { continue; } var cell = room.Random(); if (passable[cell]) { return(cell); } } }
public virtual void Damage(int dmg, object src) { if (HP <= 0) { return; } buffs.Buff.Detach <Frost>(this); var srcClass = src.GetType(); if (Immunities().Contains(srcClass)) { dmg = 0; } else if (Resistances().Contains(srcClass)) { dmg = Random.IntRange(0, dmg); } if (Buff <Paralysis>() != null) { if (Random.Int(dmg) >= Random.Int(HP)) { buffs.Buff.Detach <Paralysis>(this); if (Dungeon.Visible[pos]) { GLog.Information(TxtOutOfParalysis, Name); } } } HP -= dmg; if (dmg > 0 || src is Character) { Sprite.ShowStatus(HP > HT / 2 ? CharSprite.Warning : CharSprite.Negative, dmg.ToString()); } if (HP <= 0) { Die(src); } }
private static void PaintFissure(Level level, Room room) { Fill(level, room.Left + 1, room.Top + 1, room.Width() - 1, room.Height() - 1, Terrain.EMPTY); for (var i = room.Top + 2; i < room.Bottom - 1; i++) { for (var j = room.Left + 2; j < room.Right - 1; j++) { var v = Math.Min(i - room.Top, room.Bottom - i); var h = Math.Min(j - room.Left, room.Right - j); if (Math.Min(v, h) > 2 || Random.Int(2) == 0) { Set(level, j, i, Terrain.CHASM); } } } }
private static void PaintGraveyard(Level level, Room room) { Fill(level, room.Left + 1, room.Top + 1, room.Width() - 1, room.Height() - 1, Terrain.GRASS); var w = room.Width() - 1; var h = room.Height() - 1; var nGraves = Math.Max(w, h) / 2; var index = Random.Int(nGraves); var shift = Random.Int(2); for (var i = 0; i < nGraves; i++) { var pos = w > h ? room.Left + 1 + shift + i * 2 + (room.Top + 2 + Random.Int(h - 2)) * Level.Width : (room.Left + 2 + Random.Int(w - 2)) + (room.Top + 1 + shift + i * 2) * Level.Width; level.Drop(i == index ? Generator.Random() : new Gold(), pos).HeapType = Heap.Type.Tomb; } }
public static void Init() { #if !Console Challenges = PixelDungeon.Challenges(); #endif Actor.Clear(); PathFinder.SetMapSize(Level.Width, Level.Height); Scroll.InitLabels(); Potion.InitColors(); Wand.InitWoods(); Ring.InitGems(); Statistics.Reset(); Journal.Reset(); Depth = 0; Gold = 0; PotionOfStrength = 0; ScrollsOfUpgrade = 0; ArcaneStyli = 0; DewVial = true; Transmutation = Random.IntRange(6, 14); Chapters = new HashSet <int?>(); Ghost.Quest.reset(); Wandmaker.Quest.Reset(); Blacksmith.Quest.Reset(); Imp.Quest.Reset(); Room.ShuffleTypes(); Hero = new Hero(); Hero.Live(); Badge.Reset(); StartScene.curClass.InitHero(Hero); }
public override void Move(int step) { base.Move(step); if (Flying) { return; } if (Level.water[pos]) { Sample.Instance.Play(Assets.SND_WATER, 1, 1, Random.Float(0.8f, 1.25f)); } else { Sample.Instance.Play(Assets.SND_STEP); } Dungeon.Level.Press(pos, this); }
protected internal virtual void Split(Rect rect) { var w = rect.Width(); var h = rect.Height(); if (w > MaxRoomSize && h < MinRoomSize) { var vw = Random.Int(rect.Left + 3, rect.Right - 3); Split(new Rect(rect.Left, rect.Top, vw, rect.Bottom)); Split(new Rect(vw, rect.Top, rect.Right, rect.Bottom)); } else if (h > MaxRoomSize && w < MinRoomSize) { var vh = Random.Int(rect.Top + 3, rect.Bottom - 3); Split(new Rect(rect.Left, rect.Top, rect.Right, vh)); Split(new Rect(rect.Left, vh, rect.Right, rect.Bottom)); } else if ((new System.Random(1).NextDouble() <= (MinRoomSize * MinRoomSize / rect.Square()) && w <= MaxRoomSize && h <= MaxRoomSize) || w < MinRoomSize || h < MinRoomSize) { Rooms.Add((Room) new Room().Set(rect)); } else { if (Random.Float() < (float)(w - 2) / (w + h - 4)) { var vw = Random.Int(rect.Left + 3, rect.Right - 3); Split(new Rect(rect.Left, rect.Top, vw, rect.Bottom)); Split(new Rect(vw, rect.Top, rect.Right, rect.Bottom)); } else { var vh = Random.Int(rect.Top + 3, rect.Bottom - 3); Split(new Rect(rect.Left, rect.Top, rect.Right, vh)); Split(new Rect(rect.Left, vh, rect.Right, rect.Bottom)); } } }
protected internal virtual void Paint() { foreach (var r in Rooms) { if (r.type != RoomType.NULL) { PlaceDoors(r); r.Paint(this, r); } else { if (feeling == Feeling.CHASM && Random.Int(2) == 0) { Painter.Fill(this, r, Terrain.WALL); } } } foreach (var r in Rooms) { PaintDoors(r); } }
public override void Update() { base.Update(); if (Target != null) { FocusOn(Target); } if ((_shakeTime -= Game.Elapsed) > 0) { var damping = _shakeTime / _shakeDuration; ShakeX = Random.Float(-_shakeMagX, +_shakeMagX) * damping; ShakeY = Random.Float(-_shakeMagY, +_shakeMagY) * damping; } else { ShakeX = 0; ShakeY = 0; } UpdateMatrix(); }
public virtual void Wither() { Dungeon.Level.Uproot(Pos); Sprite.Kill(); if (Dungeon.Visible[Pos]) { CellEmitter.Get(Pos).Burst(LeafParticle.Factory, 6); } if (Dungeon.Hero.subClass != HeroSubClass.WARDEN) { return; } if (Random.Int(5) == 0) { Dungeon.Level.Drop(Generator.Random(Generator.Category.SEED), Pos).Sprite.Drop(); } if (Random.Int(5) == 0) { Dungeon.Level.Drop(new Dewdrop(), Pos).Sprite.Drop(); } }
public virtual bool Search(bool intentional) { var smthFound = false; var positive = 0; var negative = 0; foreach (var bonus in Buffs <RingOfDetection.Detection>().Select(buff => buff.Level)) { if (bonus > positive) { positive = bonus; } else if (bonus < 0) { negative += bonus; } } var distance = 1 + positive + negative; var level = intentional ? (2 * Awareness - Awareness * Awareness) : Awareness; if (distance <= 0) { level /= 2 - distance; distance = 1; } var cx = pos % Level.Width; var cy = pos / Level.Width; var ax = cx - distance; if (ax < 0) { ax = 0; } var bx = cx + distance; if (bx >= Level.Width) { bx = Level.Width - 1; } var ay = cy - distance; if (ay < 0) { ay = 0; } var by = cy + distance; if (by >= Level.Height) { by = Level.Height - 1; } for (var y = ay; y <= by; y++) { for (int x = ax, p = ax + y * Level.Width; x <= bx; x++, p++) { if (!Dungeon.Visible[p]) { continue; } if (intentional) { Sprite.Parent.AddToBack(new CheckedCell(p)); } if (!Level.secret[p] || (!intentional && !(Random.Float() < level))) { continue; } var oldValue = Dungeon.Level.map[p]; GameScene.DiscoverTile(p, oldValue); Level.Set(p, Terrain.discover(oldValue)); GameScene.UpdateMap(p); ScrollOfMagicMapping.Discover(p); smthFound = true; } } if (intentional) { Sprite.ShowStatus(CharSprite.Default, TxtSearch); Sprite.DoOperate(pos); if (smthFound) { SpendAndNext(Random.Float() < level ? TimeToSearch : TimeToSearch * 2); } else { SpendAndNext(TimeToSearch); } } if (!smthFound) { return(false); } GLog.Warning(TxtNoticedSmth); Sample.Instance.Play(Assets.SND_SECRET); Interrupt(); return(true); }
private static void PaintBridge(Level level, Room room) { Fill(level, room.Left + 1, room.Top + 1, room.Width() - 1, room.Height() - 1, !Dungeon.BossLevel() && !Dungeon.BossLevel(Dungeon.Depth + 1) && Random.Int(3) == 0 ? Terrain.CHASM : Terrain.WATER); Point door1 = null; Point door2 = null; foreach (var p in room.Connected.Values) { if (door1 == null) { door1 = p; } else { door2 = p; } } if ((door1.X == room.Left && door2.X == room.Right) || (door1.X == room.Right && door2.X == room.Left)) { var s = room.Width() / 2; DrawInside(level, room, door1, s, Terrain.EMPTY_SP); DrawInside(level, room, door2, s, Terrain.EMPTY_SP); Fill(level, room.Center().X, Math.Min(door1.Y, door2.Y), 1, Math.Abs(door1.Y - door2.Y) + 1, Terrain.EMPTY_SP); } else if ((door1.Y == room.Top && door2.Y == room.Bottom) || (door1.Y == room.Bottom && door2.Y == room.Top)) { int s = room.Height() / 2; DrawInside(level, room, door1, s, Terrain.EMPTY_SP); DrawInside(level, room, door2, s, Terrain.EMPTY_SP); Fill(level, Math.Min(door1.X, door2.X), room.Center().Y, Math.Abs(door1.X - door2.X) + 1, 1, Terrain.EMPTY_SP); } else if (door1.X == door2.X) { Fill(level, door1.X == room.Left ? room.Left + 1 : room.Right - 1, Math.Min(door1.Y, door2.Y), 1, Math.Abs(door1.Y - door2.Y) + 1, Terrain.EMPTY_SP); } else if (door1.Y == door2.Y) { Fill(level, Math.Min(door1.X, door2.X), door1.Y == room.Top ? room.Top + 1 : room.Bottom - 1, Math.Abs(door1.X - door2.X) + 1, 1, Terrain.EMPTY_SP); } else if (door1.Y == room.Top || door1.Y == room.Bottom) { DrawInside(level, room, door1, Math.Abs(door1.Y - door2.Y), Terrain.EMPTY_SP); DrawInside(level, room, door2, Math.Abs(door1.X - door2.X), Terrain.EMPTY_SP); } else if (door1.X == room.Left || door1.X == room.Right) { DrawInside(level, room, door1, Math.Abs(door1.X - door2.X), Terrain.EMPTY_SP); DrawInside(level, room, door2, Math.Abs(door1.Y - door2.Y), Terrain.EMPTY_SP); } }
public static bool AsNeeded() { return(Random.Int(12 * (1 + ArcaneStyli)) < Depth); }
protected internal virtual int NumberOfTraps() { return(Dungeon.Depth <= 1 ? 0 : Random.Int(1, Rooms.Count + Dungeon.Depth)); }
public virtual bool Attack(Character enemy) { var visibleFight = Dungeon.Visible[pos] || Dungeon.Visible[enemy.pos]; if (Hit(this, enemy, false)) { if (visibleFight) { GLog.Information(TxtHit, Name, enemy.Name); } // FIXME var dr = this is Hero && ((Hero)this).RangedWeapon != null && ((Hero)this).subClass == HeroSubClass.SNIPER ? 0 : Random.IntRange(0, enemy.Dr()); var dmg = DamageRoll(); var effectiveDamage = Math.Max(dmg - dr, 0); effectiveDamage = AttackProc(enemy, effectiveDamage); effectiveDamage = enemy.DefenseProc(this, effectiveDamage); enemy.Damage(effectiveDamage, this); if (visibleFight) { Sample.Instance.Play(Assets.SND_HIT, 1, 1, Random.Float(0.8f, 1.25f)); } if (enemy == Dungeon.Hero) { Dungeon.Hero.Interrupt(); } enemy.Sprite.BloodBurstA(Sprite.Center(), effectiveDamage); enemy.Sprite.Flash(); if (!enemy.IsAlive && visibleFight) { if (enemy == Dungeon.Hero) { if (Dungeon.Hero.KillerGlyph != null) { Dungeon.Fail(Utils.Format(ResultDescriptions.GLYPH, Dungeon.Hero.KillerGlyph.Name(), Dungeon.Depth)); GLog.Negative(TxtKill, Dungeon.Hero.KillerGlyph.Name()); } else { if (Bestiary.IsUnique(this)) { Dungeon.Fail(Utils.Format(ResultDescriptions.BOSS, Name, Dungeon.Depth)); } else { Dungeon.Fail(Utils.Format(ResultDescriptions.MOB, Utils.Indefinite(Name), Dungeon.Depth)); } GLog.Negative(TxtKill, Name); } } else { GLog.Information(TxtDefeat, Name, enemy.Name); } } return(true); } if (!visibleFight) { return(false); } var defense = enemy.DefenseVerb(); enemy.Sprite.ShowStatus(CharSprite.Neutral, defense); if (this == Dungeon.Hero) { GLog.Information(TxtYouMissed, enemy.Name, defense); } else { GLog.Information(TxtSmbMissed, enemy.Name, defense, Name); } Sample.Instance.Play(Assets.SND_MISS); return(false); }
public override int NMobs() { return(2 + Dungeon.Depth % 5 + Random.Int(3)); }
public override void Paint(Level level, Room room) { Fill(level, room, Terrain.WALL); foreach (var door in room.Connected.Values) { door.Set(Room.Door.DoorType.REGULAR); } if (!Dungeon.BossLevel() && Random.Int(5) == 0) { switch (Random.Int(6)) { case 0: if (level.feeling != Level.Feeling.GRASS) { if (Math.Min(room.Width(), room.Height()) >= 4 && Math.Max(room.Width(), room.Height()) >= 6) { PaintGraveyard(level, room); return; } } break; case 1: if (Dungeon.Depth > 1) { PaintBurned(level, room); return; } break; case 2: if (Math.Max(room.Width(), room.Height()) >= 4) { PaintStriped(level, room); return; } break; case 3: if (room.Width() >= 6 && room.Height() >= 6) { PaintStudy(level, room); return; } break; case 4: if (level.feeling != Level.Feeling.WATER) { if (room.Connected.Count == 2 && room.Width() >= 4 && room.Height() >= 4) { PaintBridge(level, room); return; } } break; case 5: if (!Dungeon.BossLevel() && !Dungeon.BossLevel(Dungeon.Depth + 1) && Math.Min(room.Width(), room.Height()) >= 5) { PaintFissure(level, room); return; } break; } } Fill(level, room, 1, Terrain.EMPTY); }
protected override bool Build() { if (!InitRooms()) { return(false); } int distance; var retry = 0; var minDistance = (int)Math.Sqrt(Rooms.Count); do { do { RoomEntrance = Random.Element(Rooms); }while (RoomEntrance.Width() < 4 || RoomEntrance.Height() < 4); do { RoomExit = Random.Element(Rooms); }while (RoomExit == RoomEntrance || RoomExit.Width() < 4 || RoomExit.Height() < 4); Graph.BuildDistanceMap(Rooms, RoomExit); distance = RoomEntrance.Distance(); if (retry++ > 10) { return(false); } }while (distance < minDistance); RoomEntrance.type = RoomType.ENTRANCE; RoomExit.type = RoomType.EXIT; var connected = new List <Room>(); connected.Add(RoomEntrance); Graph.BuildDistanceMap(Rooms, RoomExit); var path = Graph.BuildPath(Rooms, RoomEntrance, RoomExit); var room = RoomEntrance; foreach (var next in path) { room.Connect(next); room = next; connected.Add(room); } Graph.SetPrice(path, RoomEntrance.distance); Graph.BuildDistanceMap(Rooms, RoomExit); path = Graph.BuildPath(Rooms, RoomEntrance, RoomExit); room = RoomEntrance; foreach (var next in path) { room.Connect(next); room = next; connected.Add(room); } var nConnected = (int)(Rooms.Count * Random.Float(0.5f, 0.7f)); while (connected.Count < nConnected) { var cr = Random.Element(connected); var or = Random.Element(cr.Neigbours); if (connected.Contains(or)) { continue; } cr.Connect(or); connected.Add(or); } if (Dungeon.ShopOnLevel()) { var shop = RoomEntrance.Connected.Keys.FirstOrDefault(r => r.Connected.Count == 1 && r.Width() >= 5 && r.Height() >= 5); if (shop == null) { return(false); } shop.type = RoomType.SHOP; } Specials = new List <RoomType>(levels.Room.SPECIALS); if (Dungeon.BossLevel(Dungeon.Depth + 1)) { Specials.Remove(RoomType.WEAK_FLOOR); } AssignRoomType(); Paint(); PaintWater(); PaintGrass(); PlaceTraps(); return(true); }