public bool CellIsPassable(Point p) // will get optional flags param if needed //check everything that could block a cell, which currently is probably just the tile type { TileType type = Tiles[p]; return(TileDefinition.IsPassable(type)); }
///<summary>Returns true if cell is lit from any direction.</summary> public bool IsLit(Point cell) { if (MagicalLightState == MagicalLightState.MagicalLight) { return(true); } else if (MagicalLightState == MagicalLightState.MagicalDarkness) { return(false); } else { if (TileDefinition.IsOpaque(Map.Tiles[cell])) { foreach (Point neighbor in cell.EnumeratePointsAtChebyshevDistance(1, false, false)) { if (!neighbor.ExistsBetweenMapEdges()) { continue; } if (cellBrightness[neighbor] > 0 && !TileDefinition.IsOpaque(Map.Tiles[neighbor])) { return(true); } } return(false); } else { return(cellBrightness[cell] > 0); } } }
public bool CellIsOpaque(Point p) { TileType type = Tiles[p]; if (TileDefinition.IsOpaque(type)) { return(true); } if (Features[p].IsOpaque()) { return(true); } return(false); }
private void UpdateBrightnessWithinRadius(Point sourceCell, int radius, int increment) { for (int i = sourceCell.Y - radius; i <= sourceCell.Y + radius; ++i) { for (int j = sourceCell.X - radius; j <= sourceCell.X + radius; ++j) { Point p = new Point(j, i); if (!p.ExistsBetweenMapEdges()) { continue; } if (!TileDefinition.IsOpaque(Map.Tiles[p]) && sourceCell.CheckReciprocalBresenhamLineOfSight(p, Map.Tiles)) { cellBrightness[p] += increment; } } } }
///<summary>Returns true if cell is lit AND (for opaque cells) if the observer is on the right side to see the light.</summary> public bool CellAppearsLitToObserver(Point cell, Point observer) { if (MagicalLightState == MagicalLightState.MagicalLight) { return(true); } else if (!IsLit(cell)) { return(false); // If it isn't lit at all, stop here. } else { if (TileDefinition.IsOpaque(Map.Tiles[cell])) { // Light for opaque cells must be done carefully so light sources aren't visible through walls. // If the observer has LOS to any adjacent lit nonopaque cell, that observer knows this wall is lit. for (int i = 0; i < 8; ++i) { Dir8 dir = EightDirections.Eight[i]; Point neighbor = cell.PointInDir(dir); if (!neighbor.ExistsBetweenMapEdges()) { continue; } if (cellBrightness[neighbor] == 0) { continue; } if (observer.CheckReciprocalBresenhamLineOfSight(neighbor, Map.Tiles)) { return(true); } } return(false); } else { return(true); // Cell is lit and not opaque, so it appears lit from anywhere. } } }
public static bool HasLOS(this Point source, Point destination, PointArray <TileType> map) //todo, move this, to use NeverInLOS from DungeonMap { if (TileDefinition.IsOpaque(map[destination])) { Point[] neighbors = GetNeighborsBetween(destination, source); for (int i = 0; i < neighbors.Length; ++i) { if (TileDefinition.IsOpaque(map[neighbors[i]])) { continue; } if (CheckReciprocalBresenhamLineOfSight(source, neighbors[i], map)) { return(true); } } return(false); } else { return(CheckReciprocalBresenhamLineOfSight(source, destination, map)); } }
public static bool CheckReciprocalBresenhamLineOfSight(this Point source, Point destination, PointArray <TileType> map) //todo, what to do with map? { int x1 = source.X; int y1 = source.Y; int x2 = destination.X; int y2 = destination.Y; int dx = Math.Abs(x2 - x1); int dy = Math.Abs(y2 - y1); int incrementX = x1 == x2? 0 : x1 < x2? 1 : -1; int incrementY = y1 == y2? 0 : y1 < y2? 1 : -1; if (dx <= 1 && dy <= 1) { return(true); // Automatically pass the check for anything in the same or adjacent cells. } // Next, handle simple cases that don't need Bresenham at all. These cases correspond to straight lines in the 8 directions: if (dx == 0 || dy == 0 || (y1 + x1 == y2 + x2) || (y1 - x1 == y2 - x2)) // (if slope is undefined, 0, -1, or 1) { do { x1 += incrementX; // Increment first, so that the opacity of 'source' is ignored. y1 += incrementY; if (TileDefinition.IsOpaque(map[x1, y1])) { return(false); } } while(x1 != x2 || y1 != y2); return(true); } // If it wasn't a simple case, move on to reciprocal Bresenham: bool xMajor = (dx > dy); int er = 0; // error accumulator bool blockedA = false; // These 2 are used to track whether each of the 2 possible paths per line is blocked or not. bool blockedB = false; // (The result is equivalent to calculating 2 regular Bresenham lines, source->dest and dest->source.) if (xMajor) { do { x1 += incrementX; er += dy; if (er << 1 > dx) { y1 += incrementY; er -= dx; } if (TileDefinition.IsOpaque(map[x1, y1])) { if (blockedB || er << 1 != dx) { return(false); } blockedA = true; } if (er << 1 == dx) // This is the part that makes this reciprocal, by checking both options while crossing a corner. { y1 += incrementY; // Increment Y, then check the new position: if (TileDefinition.IsOpaque(map[x1, y1])) { if (blockedA || er << 1 != dx) { return(false); } blockedB = true; } er -= dx; } } while(x1 != x2); } else // Y-major { do { y1 += incrementY; er += dx; if (er << 1 > dy) { x1 += incrementX; er -= dy; } if (TileDefinition.IsOpaque(map[x1, y1])) { if (blockedB || er << 1 != dy) { return(false); } blockedA = true; } if (er << 1 == dy) { x1 += incrementX; if (TileDefinition.IsOpaque(map[x1, y1])) { if (blockedA || er << 1 != dy) { return(false); } blockedB = true; } er -= dy; } } while(y1 != y2); } return(true); }
public void GenerateMap() { CurrentLevelType = MapRNG.OneIn(4) ? DungeonLevelType.Cramped : DungeonLevelType.Sparse; int wallRarity = CurrentLevelType == DungeonLevelType.Cramped ? 6 : 20; int waterRarity = CurrentLevelType == DungeonLevelType.Cramped ? 50 : 8; string[][] tempMaps = new string[][] { new string[] { "------------------------------------------------------------------", "-------------------------------------------------#----------------", "-######.###############--------------------------#----------------", "------------------------------------#####--------#----------------", "#######.####################-----####---#################---------", "--------------------------------------#----------#----------------", "-######-#############-#-------###############----#----------------", "----------------------#-------#------------------#----------------", "-#-##################-#-------#-###########------#----------------", "---------#------#-----###-----#-----------#------#----------------", "-###-#####-####-#######-------###########-#------#----------------", "##########-###-----#--###-----#---------#-#------#----------------", "-------------------#--#-------#-#######-#-#------#----------------", "---#######----BBBB------------#-#>------#-#------#----------------", "#-----####-BBBBBBBBBBBBBBBBB--#-#########-#------#----------------", "####--####-BBBBBBBBBBB--------#-----------#------#----------------", "#-----####--BBBBBBBBB--#########################################--", "#-##--####--BBB----BBBB#------------------------------------------", "#--###-########-##-BBBB#------------------------------------------", "##-###-##-#------#B-BBB#------------------------------------------", "#>-#--###-#------#BBBB-#------------------------------------------", "###################-----------------------------------------------" }, new string[] { "##################################################################", "##########-############---###-###########-#------#-------------w5#", "##############-ww5ww--#####5###---------#-#------#----------->-w5#", "#-----#---------www---#---www-#-#######-#-#------####-############", "#--####-######--------#-------#-#-------#-#------#,M,,,,,,M,,,M,,#", "#######-######----------------###########-#------#,,,,M,M,,,M,,,M#", "#---------------------#---------#----------------#,,M,,,,,,,,,M,,#", "#---##########---##############-#######----------#M,,,,M,,M,M,,,M#", "#---######---#---#-----########-##,,,M############,,,M,,,,,,,,,,,#", "#w-----###---#---#-----#------#--,,M,,,---#--#----,M,,,,,M,,,,M,,#", "#5w-##-###########-----#------####,,,,###-####-###,,,,M,,,,,M,,,M#", "######-##-#------#-----#---------#,M,M#---,,,,--##M,M,,,M,,,,,M,,#", "######-################----------######------www##,,,,M,,,M,M,,,M#", "#----#--#---------------------------###------w5w##M,M,,,M,,,,,,,,#", "#######.####################-----####-######-www#########,,M,,M,,#", "#-----#-#---------#####---------------#----#----##------#M,,,,,,M#", "#######-###########---######################----##------#,,,M,M,,#", "#5------------------#-#-------#------------#----##------##########", "##-##################-#-#-----#-##################---------------#", "#-----####----------#---#---,,#-----------#------#---------------#", "#-----#####------#--##5##--,,,#----------------------------------#", "##################################################################" }, new string[] { "##################################################################", "##############---####-#--#####,,#-##########--#####-#-I###i#######", "#--------,,###--------#---------#--C--##------##------IIiiiiiWWW##", "#----#####---##---------------#-----------##---#-#-----IIiiiiWW--#", "#---##---#,-----------#---------#-------###----#---##--IIiiiii---#", "#--####-####---------###------###-----#####----#-#######Iiiii----#", "#---##---###---------####-------###---------####---##--IIiiiii--##", "#--###########---##############-#######---###----#----IIiiiiiiI###", "##-#######III#ii-###---###--###-##----#######--###################", "##------##IIIIiiiiW#####--------#--------------#--#-------------##", "##--##-#####IIIiiiiiWW##------####----###w####w###################", "##---------##IIIiiiWW##---------#----wwWWWWiWWwWi##------------###", "##--------###IIIIiiiWW#---------#----wwWiiiiiiWWiw-----####------#", "#----#--#--######Iiiiii-------------###Wiii-iiiii#--------###--#>#", "#-#####################--########----#iIII---III#########--#,,-,,#", "#iii###----------######--#------#---##III-C----III#---##---#######", "#iiiii####------##-##---##--,,###---------------I##--##---------##", "###ii#####------#-------#---,,##-----------------#---##-----#---##", "#iiiii####------#####---#---,,##---####---#-----##---#----###----#", "#ii##i####----------#---#---,,###--#--#####-----##---###---------#", "#iii#######------#--#####--,,,#-####------##--###------###-----###", "##################################################################" }, new string[] { "------------------------------------------------------------------", "-####---##-----------------#BBBBB-------###------#----------------", "-####--.###############----#-BBBBBBBB------------#----------------", "#--------------------------#--BBBBBB#####--------#----------------", "#-###--.####################-BBBB####---#################---------", "--------#-------------#----BBBBBB#----#-----######----------------", "-###--#-#----########-#--BBB--###############--mm#################", "---#--#-#----#BBBBB---#---BBB-#------#-------mmmm-----------------", "#--####-#-####BBBB----#-------#-#----#--#-##--mmm#------mmmmmmm--#", "#########-####----------------###########-##-mmmm#-----mmmmm->---#", "#---------5#-#--------mmmmmmmm--#-----#-------mmm#------mmmmm----#", "#---##########---mmmmmmmmmmmmm#-#######-----mmmm-#---------------#", "----#-----#-----mmmmmmmmmmmmm---#########-#-mmmm------------------", "---#####-------mmmmmmmmmmmmmm-#-#------##-#--mm--################-", "#-----######-mmmmmmmmmmmmmmm--#-#########-#--mm--#----------------", "####--####-#-mmmmmmmmmmm------#-----------#------#----------------", "#-----####-#--mmmmmmmmm#-#######################################--", "#-##--####-#--mmmmmmmmm#-B----#-----------------------------------", "#--###-###########mmmmm#---B--#-----------------------------------", "##-###-##-#------#######-----5#-----------------------------------", "#--#--###-#------#-----#--BB--#-----------------------------------", "###################-----------------------------------------------" } }; string[] map = tempMaps[GameUniverse.CurrentDepth - 1]; for (int x = 0; x < Width; ++x) { for (int y = 0; y < Height; ++y) { if (x == 0 || y == 0 || x == Width - 1 || y == Height - 1) { Tiles[x, y] = TileType.Wall; } else if (map[y][x] == 'W') { Tiles[x, y] = TileType.DeepWater; } else if (map[y][x] == 'w') { Tiles[x, y] = TileType.Floor; Features.Add(x, y, FeatureType.Water); } else if (map[y][x] == 'I') { Tiles[x, y] = TileType.ThickIce; } else if (map[y][x] == 'i') { Tiles[x, y] = TileType.DeepWater; Features.Add(x, y, FeatureType.Ice); } else if (map[y][x] == '5') { Tiles[x, y] = TileType.Statue; } else if (map[y][x] == 'M') { Tiles[x, y] = TileType.GiantMushroom; } else if (map[y][x] == ',') { Tiles[x, y] = TileType.GlowingFungus; } else if (map[y][x] == 'C') { Tiles[x, y] = TileType.LightCrystal; } else if (map[y][x] == '>') { Tiles[x, y] = TileType.Staircase; } else if (map[y][x] == 'B') { Tiles[x, y] = TileType.Brush; } else if (map[y][x] == 'm') { Tiles[x, y] = TileType.DeepMud; } else if (map[y][x] == '#') { Tiles[x, y] = TileType.Wall; } else { Tiles[x, y] = TileType.Floor; } /*else if(x < 7 && y < 7){ * Tiles[x,y] = TileType.Floor; * Features.Add(x, y, FeatureType.Water); * } * else if(x < 33 && x > 25 && y < 7){ * Tiles[x,y] = TileType.ThickIce; * } * else if(x < 7 && y > 17){ * Tiles[x,y] = TileType.DeepWater; * } * else { * Tiles[x,y] = TileType.DeepWater; * Features.Add(x, y, FeatureType.Ice); * }/* * /*else if(MapRNG.OneIn(wallRarity)) * Tiles[x,y] = TileType.Wall; * else if(MapRNG.OneIn(waterRarity)) * Tiles[x,y] = TileType.DeepWater; * else * Tiles[x,y] = TileType.Floor;*/ } } /*for(int x=Width/3;x<Width;++x) { * Tiles[x, Height/2] = TileType.Wall; * }*/ //Tiles[Width / 3, Height / 3] = TileType.Staircase; //Light.AddLightSource(new Point(Width / 3, Height / 3), 2);//todo remove for (int x = 1; x < Width - 1; ++x) { for (int y = 1; y < Height - 1; ++y) { Point p = new Point(x, y); int? rad = TileDefinition.LightRadius(TileTypeAt(p)); if (rad != null) { Light.AddLightSource(p, rad.Value); } //Light.AddLightSource(new Point(x, y), 2);//todo remove } } int numEnemies = MapRNG.GetNext(9); for (int i = 0; i < numEnemies; ++i) { Creature c = new Creature(GameUniverse) { OriginalType = CreatureType.Goblin }; Creatures.Add(c, new Point(MapRNG.GetNext(Width - 2) + 1, MapRNG.GetNext(Height - 2) + 1)); Initiative initiative = Q.CreateInitiative(RelativeInitiativeOrder.Last); Q.Schedule(new AiTurnEvent(c), GameUniverse.TicksPerTurn * 10, initiative); } /* for shrine placement: * int count = 50; * for(int i=0;i<NUM_LEVELS;++i){ * int depthChance = (NUM_LEVELS - i); * int countOnThisLevel = 0; * for(int j=0;j<count;++j){ * if(OneIn(depthChance)) countOnThisLevel++; * } * Console.WriteLine("Depth " + (i+1).ToString().PadLeft(2) + " has " + countOnThisLevel.ToString()); * count -= countOnThisLevel; * } */ }