private void MaybeSet(ref Tile[,] map, int x, int y, string tileName) { if (map[x, y].Definition.Wall && !map[x, y].Definition.CanBurn) { map[x, y].Index = TileDefinition.Find(tileName).Index; } }
public void Clear(int biomeID) { this.Entities.Clear(); this.GetToken("biome").Value = biomeID; this.GetToken("music").Text = BiomeData.Biomes[biomeID].Music; var ground = TileDefinition.Find(BiomeData.Biomes[biomeID].GroundTile, true); for (int row = 0; row < Height; row++) { for (int col = 0; col < Width; col++) { var def = ground; if (Random.Flip() && def.Variants.Tokens.Count > 0) { var chance = Random.NextDouble(); var variants = def.Variants.Tokens.Where(v => v.Value < chance).ToArray(); if (variants.Length > 0) { def = TileDefinition.Find(variants.PickOne().Name); } } SetTile(row, col, def); } } }
public void UpdateMapSolidity() { if (ParentBoard == null) { return; } ParentBoard.Tilemap[XPosition, YPosition].Definition = TileDefinition.Find(closed ? "doorwayClosed" : "doorwayOpened"); }
public static BiomeData FromToken(Token t, int realmNum) { var n = new BiomeData(); n.Realm = (Realms)realmNum; n.Name = t.Text; var cvars = t.GetToken("rect").Text.Split(' ').Select(i => int.Parse(i)).ToArray(); n.Rect = new System.Drawing.Rectangle(cvars[0], cvars[1], cvars[2] - cvars[0], cvars[3] - cvars[1]); n.GroundTile = (int)t.GetToken("ground").Value; if (n.GroundTile == 0) { n.GroundTile = TileDefinition.Find(t.GetToken("ground").Text, true).Index; } var encounters = t.GetToken("encounters"); if (encounters == null) { n.Encounters = new string[0]; } else { n.MaxEncounters = 10; if (encounters.Value > 0) { n.MaxEncounters = (int)encounters.Value; } n.Encounters = encounters.Tokens.Select(x => x.Name).ToArray(); } var cultures = t.GetToken("cultures"); if (cultures == null) { n.Cultures = new[] { "human" } } ; else { n.Cultures = cultures.Tokens.Select(x => x.Name).Where(e => Culture.Cultures.ContainsKey(e)).ToArray(); } if (t.HasToken("music")) { n.Music = t.GetToken("music").Text; } return(n); }
/// <summary> /// Replaces one tile with another across the board. /// </summary> /// <param name="replaceThis">A <see cref="Noxico.TileDefinition"/>, tile name as a string, or tile number, or a Lua callback function.</param> /// <param name="withThis">A <see cref="Noxico.TileDefinition"/>, tile name as a string, or tile number, or a Lua callback function.</param> /// <remarks>The callback functions takes the tile number and TileDefinition at the current coordinates in the line and the coordinates. One must return a boolean, the other a TileDef, string, or int.</remarks> public void Replace(object replaceThis, object withThis) { if (replaceThis is TileDefinition) { replaceThis = ((TileDefinition)replaceThis).Index; } else if (replaceThis is string) { replaceThis = TileDefinition.Find((string)replaceThis).Index; } if (withThis is TileDefinition) { withThis = ((TileDefinition)withThis).Index; } else if (withThis is string) { withThis = TileDefinition.Find((string)withThis).Index; } for (var y = 0; y < Width; y++) { for (var x = 0; x < Height; x++) { if (replaceThis is int) { if (Tilemap[y, x].Index != (int)replaceThis) { continue; } } else if (replaceThis is Func <object, object, object, object, Neo.IronLua.LuaResult> ) { var callback = (Func <object, object, object, object, Neo.IronLua.LuaResult>)replaceThis; var tileHere = Tilemap[y, x]; if (!(bool)callback(tileHere.Index, tileHere.Definition, x, y)[0]) { continue; } } var w = withThis; if (w is Func <object, object, object, object, Neo.IronLua.LuaResult> ) { var callback = (Func <object, object, object, object, Neo.IronLua.LuaResult>)withThis; var tileHere = Tilemap[y, x]; w = callback(tileHere.Index, tileHere.Definition, x, y)[0]; } SetTile(x, y, (int)w); } } }
public override void ToTilemap(ref Tile[,] map) { //TODO: make these biome-dependent (use this.biome) //var stoneFloor = Color.FromArgb(65, 66, 87); //var wallStart = Color.FromArgb(119, 120, 141); //var wallEnd = Color.FromArgb(144, 144, 158); //var floorCrud = " \x146".ToCharArray(); var tiles = new[] { "stoneFloor", "stoneWall" }; for (var row = 0; row < Board.Height; row++) { for (var col = 0; col < Board.Width; col++) { map[col, row].Index = TileDefinition.Find(tiles[this.map[col, row]]).Index; } } #region Fade out the walls var dijkstra = new int[Board.Width, Board.Height]; for (var col = 0; col < Board.Width; col++) { for (var row = 0; row < Board.Height; row++) { if (!map[col, row].SolidToWalker) { continue; } dijkstra[col, row] = 9000; } } Dijkstra.JustDoIt(ref dijkstra, Board.Height, Board.Width); for (var row = 0; row < Board.Height; row++) { for (var col = 0; col < Board.Width; col++) { //if (map[col, row].Fluid != Fluids.Dry) // continue; //if (map[col, row].Definition.Wall && !map[col, row].Definition.CanBurn) { //if (dijkstra[col, row] > 1) map[col, row].InherentLight = dijkstra[col, row]; } } } #endregion }
public virtual void Draw() { var localX = this.XPosition - NoxicoGame.CameraX; var localY = this.YPosition - NoxicoGame.CameraY; if (localX >= Program.Cols || localY >= Program.Rows || localX < 0 || localY < 0) { return; } var b = ((MainForm)NoxicoGame.HostForm).IsMultiColor ? TileDefinition.Find(this.ParentBoard.Tilemap[this.XPosition, this.YPosition].Index, true).Background : this.BackgroundColor; if (ParentBoard.IsLit(this.YPosition, this.XPosition)) { NoxicoGame.HostForm.SetCell(localY, localX, this.Glyph, this.ForegroundColor, b); } //else // NoxicoGame.HostForm.SetCell(localY, localX, this.Glyph, this.ForegroundColor.Night(), b.Night()); }
public void ClearToWorld(WorldMapGenerator generator) { if (!this.HasToken("coordinate")) { return; } var coord = this.Coordinate; var x = coord.X; var y = coord.Y; var biomeID = generator.RoughBiomeMap[y, x]; if (biomeID == -1) { return; } this.Entities.Clear(); this.Width = WorldMapGenerator.TileWidth; this.Height = WorldMapGenerator.TileHeight; this.Tilemap = new Tile[this.Width, this.Height]; this.Lightmap = new bool[this.Width, this.Height]; for (int row = 0; row < Height; row++) { for (int col = 0; col < Width; col++) { this.Tilemap[col, row] = new Tile(); } } this.GetToken("biome").Value = biomeID; var worldMapX = x * Width; var worldMapY = y * Height; for (int row = 0; row < Height; row++) { for (int col = 0; col < Width; col++) { var b = generator.DetailedMap[worldMapY + row, worldMapX + col]; var h = generator.WaterMap[worldMapY + row, worldMapX + col]; this.Tilemap[col, row].Index = TileDefinition.Find(BiomeData.Biomes[b].GroundTile).Index; this.Tilemap[col, row].Fluid = h == 1 ? BiomeData.WaterTypes[(int)Realm] : Fluids.Dry; } } }
/// <summary> /// Draws a line from one point to another. /// </summary> /// <param name="x1">The starting row.</param> /// <param name="y1">The starting column.</param> /// <param name="x2">The ending row.</param> /// <param name="y2">The ending column.</param> /// <param name="brush">A <see cref="Noxico.TileDefinition"/>, tile name as a string, or tile number, or a Lua callback function.</param> /// <remarks>The callback function takes the tile number and TileDefinition at the current coordinates in the line and the coordinates, and must return a TileDef, string, or int.</remarks> public void Line(int x1, int y1, int x2, int y2, object brush) { if (brush is TileDefinition) { brush = ((TileDefinition)brush).Index; } else if (brush is string) { brush = TileDefinition.Find((string)brush).Index; } if (brush is int) { foreach (var point in Toolkit.Line(x1, y1, x2, y2)) { SetTile(point.X, point.Y, (int)brush); } } else if (brush is Func <object, object, object, object, Neo.IronLua.LuaResult> ) { var callback = (Func <object, object, object, object, Neo.IronLua.LuaResult>)brush; foreach (var point in Toolkit.Line(x1, y1, x2, y2)) { var tileHere = Tilemap[point.Y, point.Y]; brush = callback(tileHere.Index, tileHere.Definition, point.X, point.Y)[0]; if (brush is TileDefinition) { brush = ((TileDefinition)brush).Index; } else if (brush is string) { brush = TileDefinition.Find((string)brush).Index; } SetTile(point.X, point.Y, (int)brush); } } }
public override void ToTilemap(ref Tile[,] map) { //TODO: make these biome-dependent (use this.biome) //Base fill var baseFill = TileDefinition.Find("stoneWall").Index; for (var row = 0; row < Board.Height; row++) { for (var col = 0; col < Board.Width; col++) { map[col, row].Index = baseFill; } } //TODO: add clutter. /* My idea: have a list of points. For each room, randomly scatter a few points around, and make sure there's a few around the edges. * When carving corridors, remove any points in your way. Then, when done with corridors, add the actual clutter and special tiles. */ foreach (var room in rooms) { var bounds = room.Bounds; var tileType = "woodFloor"; if (room.Material == RoomMaterials.Stone) { tileType = "stoneFloor"; } for (var row = bounds.Top; row <= bounds.Bottom; row++) { for (var col = bounds.Left; col <= bounds.Right; col++) { map[col, row].Index = TileDefinition.Find(tileType).Index; } } } foreach (var room in rooms) { if (room.Material == RoomMaterials.Stone) { continue; } var bounds = room.Bounds; var inflated = new SysRectangle(bounds.Left - 1, bounds.Top - 1, bounds.Width + 2, bounds.Height + 2); for (var row = inflated.Top; row <= inflated.Bottom; row++) { MaybeSet(ref map, inflated.Left, row, "innerWoodWall"); MaybeSet(ref map, inflated.Right, row, "innerWoodWall"); } for (var col = inflated.Left; col <= inflated.Right; col++) { MaybeSet(ref map, col, inflated.Top, "innerWoodWall"); MaybeSet(ref map, col, inflated.Bottom, "innerWoodWall"); } } foreach (var corridor in corridors) { var bounds = corridor.Bounds; var inRoom = false; Tile there = null; foreach (var point in Toolkit.Line(bounds.Left, bounds.Top, bounds.Right, bounds.Bottom, true)) { var here = map[point.X, point.Y]; if (there != null && there.Definition.Wall && there.Definition.CanBurn && here.Definition.Wall && !here.Definition.CanBurn) { there.Index = TileDefinition.Find("woodFloor").Index; inRoom = false; } if (here.Definition.Wall) { if (!here.Definition.CanBurn) { map[point.X, point.Y].Index = TileDefinition.Find("stoneFloor").Index; inRoom = false; } else if (!inRoom) { map[point.X, point.Y].Index = TileDefinition.Find("woodFloor").Index; inRoom = true; } } there = here; } } Board.ResolveVariableWalls(); #region Fade out the walls var dijkstra = new int[Board.Width, Board.Height]; for (var col = 0; col < Board.Width; col++) { for (var row = 0; row < Board.Height; row++) { if (!map[col, row].SolidToWalker) { continue; } dijkstra[col, row] = 9000; } } Dijkstra.JustDoIt(ref dijkstra, Board.Height, Board.Width); for (var row = 0; row < Board.Height; row++) { for (var col = 0; col < Board.Width; col++) { //if (map[col, row].Fluid != Fluids.Dry) // continue; if (map[col, row].Definition.Wall && !map[col, row].Definition.CanBurn) { //if (dijkstra[col, row] > 1) map[col, row].InherentLight = dijkstra[col, row]; } } } #endregion }
public virtual void ToTilemap(ref Tile[,] map) { var woodFloor = Color.FromArgb(86, 63, 44); var caveFloor = Color.FromArgb(65, 66, 87); var wall = Color.FromArgb(20, 15, 12); var water = BiomeData.Biomes[BiomeData.ByName(biome.Realm == Realms.Nox ? "Water" : "KoolAid")]; allowCaveFloor = false; Clutter.ParentBoardHack = Board; var doorCount = 0; var safeZones = new List <Rectangle>(); for (var row = 0; row < plotRows; row++) { for (var col = 0; col < plotCols; col++) { if (plots[col, row].BaseID == null) { //Can clutter this up! if (includeClutter && Random.Flip()) { Board.AddClutter(col * plotWidth, row * plotHeight, (col * plotWidth) + plotWidth, (row * plotHeight) + plotHeight + row); } else { safeZones.Add(new Rectangle() { Left = col * plotWidth, Top = row * plotHeight, Right = (col * plotWidth) + plotWidth, Bottom = (row * plotHeight) + plotHeight + row }); } continue; } if (plots[col, row].BaseID == "<spillover>") { continue; } var building = plots[col, row]; var template = building.Template; var sX = (col * plotWidth) + building.XShift; var sY = (row * plotHeight) + building.YShift; for (var y = 0; y < template.Height; y++) { for (var x = 0; x < template.Width; x++) { var tc = template.MapScans[y][x]; var def = string.Empty; var fluid = Fluids.Dry; var addDoor = true; if (tc == '/') { addDoor = false; tc = '\\'; } switch (tc) { case '\'': continue; case ',': def = "pathWay"; // FIXME: kind of ugly but does the job break; case '.': def = "woodFloor"; break; case '+': //Exit -- can't be seen, coaxes walls into shape. def = "doorwayClosed"; if (addDoor) { doorCount++; var door = new Door() { XPosition = sX + x, YPosition = sY + y, ForegroundColor = woodFloor, BackgroundColor = woodFloor.Darken(), ID = building.BaseID + "_Door" + doorCount, ParentBoard = Board, Closed = true, Glyph = '+' }; Board.Entities.Add(door); } break; case '=': def = "outerWoodWall"; break; case '-': def = "innerWoodWall"; break; case '#': def = allowCaveFloor ? "stoneFloor" : "woodFloor"; break; default: if (template.Markings.ContainsKey(tc)) { #region Custom markings var m = template.Markings[tc]; if (m.Text == "block") { throw new Exception("Got a BLOCK-type marking in a building template."); } if (m.Text != "tile" && m.Text != "floor" && m.Text != "water") { //Keep a floor here. The entity fills in the blank. def = "woodFloor"; var tileDef = TileDefinition.Find(def, false); map[sX + x, sY + y].Index = tileDef.Index; //var owner = m.Owner == 0 ? null : building.Inhabitants[m.Owner - 1]; var owner = (Character)null; if (m.HasToken("owner")) { owner = building.Inhabitants[(int)m.GetToken("owner").Value - 1]; } if (m.Text == "bed") { var newBed = new Clutter() { XPosition = sX + x, YPosition = sY + y, Name = "Bed", ID = "Bed_" + (owner == null ? Board.Entities.Count.ToString() : owner.Name.ToID()), Description = owner == null?i18n.GetString("freebed") : i18n.Format("someonesbed", owner.Name.ToString(true)), ParentBoard = Board, }; Clutter.ResetToKnown(newBed); Board.Entities.Add(newBed); } if (m.Text == "container") { //var type = c == '\x14B' ? "cabinet" : c == '\x14A' ? "chest" : "container"; var type = "chest"; if (m.HasToken("wardrobe")) { type = "wardrobe"; } var contents = DungeonGenerator.GetRandomLoot("container", type, new Dictionary <string, string>() { { "gender", owner.PreferredGender.ToString().ToLowerInvariant() }, { "biome", BiomeData.Biomes[DungeonGenerator.DungeonGeneratorBiome].Name.ToLowerInvariant() }, }); if (owner != null) { foreach (var content in contents) { content.AddToken("owner", 0, owner.ID); } } var newContainer = new Container(type, contents) //owner == null ? type.Titlecase() : owner.Name.ToString(true) + "'s " + type, contents) { XPosition = sX + x, YPosition = sY + y, ID = "Container_" + type + "_" + (owner == null ? Board.Entities.Count.ToString() : owner.Name.ToID()), ParentBoard = Board, }; Clutter.ResetToKnown(newContainer); Board.Entities.Add(newContainer); } else if (m.Text == "clutter") { if (m.HasToken("id")) { var newClutter = new Clutter() { XPosition = sX + x, YPosition = sY + y, ParentBoard = Board, ID = m.GetToken("id").Text, Name = string.Empty, }; Clutter.ResetToKnown(newClutter); Board.Entities.Add(newClutter); } else { var newClutter = new Clutter() { Glyph = (char)m.GetToken("char").Value, //m.Params.Last()[0], XPosition = sX + x, YPosition = sY + y, ForegroundColor = Color.Black, BackgroundColor = tileDef.Background, ParentBoard = Board, Name = m.GetToken("name").Text, //Name, Description = m.HasToken("description") ? m.GetToken("description").Text : string.Empty, Blocking = m.HasToken("blocking"), }; Board.Entities.Add(newClutter); } } } else if (m.Text == "water") { fluid = Fluids.Water; } else { def = TileDefinition.Find((int)m.GetToken("index").Value).Name; } #endregion } break; } map[sX + x, sY + y].Index = TileDefinition.Find(def).Index; map[sX + x, sY + y].Fluid = fluid; } } for (var i = 0; i < building.Inhabitants.Count; i++) { var inhabitant = building.Inhabitants[i]; //Find each inhabitant's bed so we can give them a starting place. //Alternatively, place them anywhere there's a ' ' within their sector. var bc = new BoardChar(inhabitant); //var bedID = building.BaseID + "_Bed_" + inhabitant.Name.FirstName; //var bed = Board.Entities.OfType<Clutter>().FirstOrDefault(b => b.ID == bedID); //if (bed != null) //{ // bc.XPosition = bed.XPosition; // bc.YPosition = bed.YPosition; //} //else { //var okay = false; var x = 0; var y = 0; var lives = 100; while (lives > 0) { lives--; x = (col * plotWidth) + Random.Next(plotWidth); y = (row * plotHeight) + Random.Next(plotHeight); if (!map[x, y].Definition.Wall && (!template.AllowOutside && map[x, y].Definition.Ceiling) && Board.Entities.FirstOrDefault(e => e.XPosition == x && e.YPosition == y) == null) { break; } } bc.XPosition = x; bc.YPosition = y; } bc.Character.AddToken("sectorlock"); bc.ParentBoard = Board; bc.AdjustView(); bc.Sector = string.Format("s{0}x{1}", row, col); Board.Entities.Add(bc); } } } Board.ResolveVariableWalls(); if (safeZones.Count > 0 && includeWater) { Board.AddWater(safeZones); } }
public static bool ResetToKnown(Entity thing) { if (!(thing is Clutter) && !(thing is Container)) { throw new InvalidCastException("ResetToKnown only takes Clutter and Container objects."); } var name = string.Empty; if (thing is Clutter) { name = ((Clutter)thing).Name; } else if (thing is Container) { name = ((Container)thing).Name; } if (clutterDB == null) { clutterDB = Mix.GetTokenTree("clutter.tml", true); } var knownThing = clutterDB.FirstOrDefault(kc => thing.Glyph == kc.GetToken("char").Value || (!name.IsBlank() && name.Equals(kc.Text, StringComparison.InvariantCultureIgnoreCase)) || thing.ID.StartsWith(kc.Text, StringComparison.InvariantCultureIgnoreCase)); if (knownThing != null) { thing.Glyph = (int)knownThing.GetToken("char").Value; if (knownThing.HasToken("color")) { thing.ForegroundColor = Color.FromName(knownThing.GetToken("color").Text); thing.BackgroundColor = thing.ForegroundColor.Darken(); //TileDefinition.Find(parentBoardHack.Tilemap[e.XPosition, e.YPosition].Index).Background; } if (knownThing.HasToken("background")) { if (knownThing.GetToken("background").Text == "inherit") { thing.BackgroundColor = TileDefinition.Find((thing.ParentBoard ?? ParentBoardHack).Tilemap[thing.XPosition, thing.YPosition].Index).Background; } else { thing.BackgroundColor = Color.FromName(knownThing.GetToken("background").Text); } } if (thing is Clutter) { ((Clutter)thing).CanBurn = knownThing.HasToken("canburn"); } //else if (thing is Container) ((Container)thing).CanBurn = knownClutter.HasToken("canburn"); thing.Blocking = knownThing.HasToken("blocking"); if (knownThing.HasToken("description")) { if (thing is Clutter) { ((Clutter)thing).Description = knownThing.GetToken("description").Text; ((Clutter)thing).descriptionFromDB = true; } else if (thing is Container && !((Container)thing).Token.HasToken("description")) { ((Container)thing).Token.AddToken("description", knownThing.GetToken("description").Text); } } if (knownThing.HasToken("name")) { if (thing is Clutter) { ((Clutter)thing).Name = knownThing.GetToken("name").Text; } if (thing is Container) { ((Container)thing).Name = knownThing.GetToken("name").Text; } } if (knownThing.HasToken("role") && thing is Clutter) { ((Clutter)thing).DBRole = knownThing.GetToken("role").Text; } return(true); } return(false); }
public void MergeBitmap(string fileName, string tiledefs) { var bitmap = Mix.GetBitmap(fileName); var tileset = new Token(); tileset.AddSet(Mix.GetTokenTree(tiledefs, true)); var width = Width; var height = Height; if (width > bitmap.Width) { width = bitmap.Width; } if (height > bitmap.Height) { height = bitmap.Height; } for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { var color = bitmap.GetPixel(x, y); if (color.Name == "ff000000" || color.A == 0) { continue; } var key = color.Name.Substring(2).ToUpperInvariant(); if (!tileset.HasToken(key)) { continue; } var tile = tileset.GetToken(key); //Keep the original tile, but drain it. if (tile.Text == "drain") { this.Tilemap[x, y].Fluid = Fluids.Dry; continue; } this.Tilemap[x, y].Index = TileDefinition.Find(tile.Text).Index; if (tile.Text.StartsWith("doorway")) { var door = new Door() { XPosition = x, YPosition = y, ForegroundColor = this.Tilemap[x, y].Definition.Background, BackgroundColor = this.Tilemap[x, y].Definition.Background.Darken(), ID = "mergeBitmap_Door" + x + "_" + y, ParentBoard = this, Closed = tile.Text.EndsWith("Closed"), Glyph = '+' }; this.Entities.Add(door); } if (tile.HasToken("clutter")) { var nc = new Clutter() { XPosition = x, YPosition = y, ParentBoard = this }; this.Entities.Add(nc); var properties = tile.GetToken("clutter"); foreach (var property in properties.Tokens) { switch (property.Name) { case "id": nc.ID = property.Text; break; case "name": nc.Name = property.Text; break; case "desc": nc.Description = property.Text; break; case "glyph": nc.Glyph = (int)property.Value; break; case "fg": if (property.Text.StartsWith('#')) { nc.ForegroundColor = Color.FromCSS(property.Text); } else { nc.ForegroundColor = Color.FromName(property.Text); } break; case "bg": if (property.Text.StartsWith('#')) { nc.BackgroundColor = Color.FromCSS(property.Text); } else { nc.BackgroundColor = Color.FromName(property.Text); } break; case "block": nc.Blocking = true; break; case "burns": nc.CanBurn = true; break; } } } if (tile.HasToken("unique")) { var unique = tile.GetToken("unique"); var newChar = new BoardChar(Character.GetUnique(unique.Text)) { XPosition = x, YPosition = y, ParentBoard = this }; this.Entities.Add(newChar); newChar.AssignScripts(unique.Text); newChar.ReassignScripts(); } if (!tile.HasToken("fluid")) { this.Tilemap[x, y].Fluid = Fluids.Dry; } else { this.Tilemap[x, y].Fluid = (Fluids)Enum.Parse(typeof(Fluids), tile.GetToken("fluid").Text, true); } } } this.ResolveVariableWalls(); }
/// <summary> /// Replaces every tile found in a floodfill with another. /// </summary> /// <param name="startX">The starting row.</param> /// <param name="startY">The starting column.</param> /// <param name="replaceThis">Null/nil, a <see cref="Noxico.TileDefinition"/>, tile name as a string, or tile number, or a Lua callback function.</param> /// <param name="withThis">A <see cref="Noxico.TileDefinition"/>, tile name as a string, or tile number, or a Lua callback function.</param> /// <param name="allowDiagonals">If true, flood in eight directions, passing through more gaps.</param> /// <remarks>The callback functions takes the tile number and TileDefinition at the current coordinates in the line and the coordinates. One must return a boolean, the other a TileDef, string, or int. If a null/nil is given, the tile number at the starting coordinates is used.</remarks> public void Floodfill(int startX, int startY, object replaceThis, object withThis, bool allowDiagonals) { if (replaceThis is TileDefinition) { replaceThis = ((TileDefinition)replaceThis).Index; } else if (replaceThis is string) { replaceThis = TileDefinition.Find((string)replaceThis).Index; } if (withThis is TileDefinition) { withThis = ((TileDefinition)withThis).Index; } else if (withThis is string) { withThis = TileDefinition.Find((string)withThis).Index; } if (replaceThis == null) { replaceThis = Tilemap[startY, startX].Index; } var stack = new Stack <Point>(); stack.Push(new Point(startX, startY)); while (stack.Count > 0) { var point = stack.Pop(); var x = point.X; var y = point.Y; if (x < 0 || y < 0 || x >= Height || y >= Width) { continue; } if (replaceThis is int) { if (Tilemap[y, x].Index != (int)replaceThis) { continue; } } else if (replaceThis is Func <object, object, object, object, Neo.IronLua.LuaResult> ) { var callback = (Func <object, object, object, object, Neo.IronLua.LuaResult>)replaceThis; var tileHere = Tilemap[y, x]; if (!(bool)callback(tileHere.Index, tileHere.Definition, x, y)[0]) { continue; } } { var w = withThis; if (w is Func <object, object, object, object, Neo.IronLua.LuaResult> ) { var callback = (Func <object, object, object, object, Neo.IronLua.LuaResult>)withThis; var tileHere = Tilemap[y, x]; w = callback(tileHere.Index, tileHere.Definition, x, y)[0]; } SetTile(x, y, (int)w); stack.Push(new Point(x - 1, y)); stack.Push(new Point(x + 1, y)); stack.Push(new Point(x, y - 1)); stack.Push(new Point(x, y + 1)); if (allowDiagonals) { stack.Push(new Point(x - 1, y - 1)); stack.Push(new Point(x - 1, y + 1)); stack.Push(new Point(x + 1, y - 1)); stack.Push(new Point(x + 1, y + 1)); } } } }