Example #1
0
 public void GenerateFeatures(PosArray<CellType> map,List<pos> interesting_tiles)
 {
     List<DungeonFeature> features = new List<DungeonFeature>();
     foreach(DungeonFeature df in Enum.GetValues(typeof(DungeonFeature))){
         features.Add(df);
     }
     int[] rarity = null;
     switch(level_types[current_level-1]){
     case LevelType.Standard:
         rarity = new int[]{30,40,15,30,
             25,6,8,15,15,3,3,4,4,4};
         break;
     case LevelType.Cave:
         rarity = new int[]{30,15,10,15,
             15,100,8,10,30,5,25,6,3,4};
         break;
     case LevelType.Mine:
         rarity = new int[]{30,20,5,16,
             18,6,7,15,10,3,5,30,1,1};
         break;
     case LevelType.Hive:
         rarity = new int[]{30,15,100,50,
             50,100,4,10,10,100,100,15,25,0};
         break;
     case LevelType.Fortress:
         rarity = new int[]{30,100,100,100,
             100,1,8,25,8,6,1,100,20,15};
         break;
     case LevelType.Garden:
         rarity = new int[]{20,50,50,0,
             20,30,20,20,20,20,5,5,8,15};
         break;
     case LevelType.Crypt:
         rarity = new int[]{30,50,50,25,
             25,30,8,10,15,20,30,5,8,8};
         break;
     case LevelType.Slime: //todo
     default:
         rarity = new int[]{30,20,15,12,
             10,4,8,10,7,3,3,3,4,10};
         break;
     }
     /*int[] rarity = new int[]{30,20,15,12,
             10,4,8,10,7,3,3,3,4};
     int[] frequency = new int[]{1,1,2,2,3,3,3,
         4,4,4,4,2,2,5,5,5,6,5,5,8};*/
     int[] removal_chance = new int[]{95,20,10,60,
         30,25,70,50,60,35,12,10,10,20};
     /*List<DungeonFeature> feature_pool = new List<DungeonFeature>();
     for(int i=0;i<20;++i){
         for(int j=frequency[i];j>0;--j){
             feature_pool.Add(features[i]);
         }
     }*/
     List<DungeonFeature> feature_pool = new List<DungeonFeature>();
     while(feature_pool.Count < 3){
         feature_pool.Clear();
         for(int i=0;i<14;++i){
             if(rarity[i] > 0 && R.OneIn(rarity[i])){
                 feature_pool.Add(features[i]);
             }
         }
     }
     List<DungeonFeature> selected_features = new List<DungeonFeature>();
     for(int i=0;i<5 && feature_pool.Count > 0;++i){
         selected_features.Add(feature_pool.RemoveRandom());
     }
     List<DungeonFeature> result = new List<DungeonFeature>();
     for(int count=5;count>0 && selected_features.Count > 0;--count){
         DungeonFeature df = selected_features.Random();
         if(R.PercentChance(removal_chance[(int)df])){
             selected_features.Remove(df);
         }
         result.Add(df);
     }
     List<pos> thin_walls = null;
     if(result.Contains(DungeonFeature.CRACKED_WALL)){
         thin_walls = map.AllPositions().Where(x=>map[x].IsWall() && x.HasOppositePairWhere(true,y=>y.BoundsCheck(tile) && map[y].IsFloor()));
     }
     while(result.Count > 0){
         DungeonFeature df = result.RemoveRandom();
         switch(df){
         case DungeonFeature.POOL_OF_RESTORATION:
         case DungeonFeature.FIRE_PIT:
         {
             for(int i=0;i<50;++i){
                 int rr = R.Roll(ROWS-4)+1;
                 int rc = R.Roll(COLS-4)+1;
                 if(interesting_tiles.Count > 0){
                     pos p = interesting_tiles.RemoveRandom();
                     rr = p.row;
                     rc = p.col;
                     map[p] = CellType.RoomInterior;
                 }
                 if(map[rr,rc].IsFloor()){
                     bool floors = true;
                     foreach(pos p in new pos(rr,rc).PositionsAtDistance(1,map)){
                         if(!map[p].IsFloor()){
                             floors = false;
                             break;
                         }
                     }
                     if(floors){
                         if(df == DungeonFeature.POOL_OF_RESTORATION){
                             map[rr,rc] = CellType.Pool;
                         }
                         if(df == DungeonFeature.FIRE_PIT){
                             map[rr,rc] = CellType.FirePit;
                         }
                         break;
                     }
                 }
             }
             break;
         }
         case DungeonFeature.BARREL:
         case DungeonFeature.TORCH:
             for(int i=0;i<50;++i){
                 int rr = R.Roll(ROWS-2);
                 int rc = R.Roll(COLS-2);
                 if(map[rr,rc].IsRoomType() && map[rr,rc].IsFloor()){
                     if(df == DungeonFeature.BARREL){
                         map[rr,rc] = CellType.Barrel;
                     }
                     if(df == DungeonFeature.TORCH){
                         map[rr,rc] = CellType.Torch;
                     }
                     break;
                 }
             }
             break;
         case DungeonFeature.WEBS:
         case DungeonFeature.RUBBLE:
         {
             for(int i=0;i<50;++i){
                 int rr = R.Roll(ROWS-2);
                 int rc = R.Roll(COLS-2);
                 if(map[rr,rc].IsRoomType()){
                     CellType cell = CellType.Webs;
                     int max_radius = 2;
                     switch(df){
                     case DungeonFeature.WEBS:
                         cell = CellType.Webs;
                         max_radius = 3;
                         break;
                     case DungeonFeature.RUBBLE:
                         cell = CellType.Rubble;
                         max_radius = 2;
                         break;
                     }
                     map[rr,rc] = cell;
                     for(int j=1;j<=max_radius;++j){
                         List<pos> added = new List<pos>();
                         foreach(pos p in new pos(rr,rc).PositionsWithinDistance(j,map)){
                             if(map[p] == cell){
                                 foreach(pos neighbor in p.CardinalAdjacentPositions()){
                                     if(map[neighbor].IsFloor() && R.CoinFlip()){
                                         added.AddUnique(neighbor);
                                     }
                                 }
                             }
                         }
                         foreach(pos p in added){
                             /*if(df == DungeonFeature.RUBBLE){
                                 foreach(pos neighbor in p.CardinalAdjacentPositions()){
                                     if(!added.Contains(neighbor) && map[neighbor].IsFloor() && R.OneIn(3)){
                                         map[neighbor] = CellType.Gravel;
                                     }
                                 }
                             }*/
                             map[p] = cell;
                         }
                     }
                     break;
                 }
             }
             break;
         }
         case DungeonFeature.SLIME:
         case DungeonFeature.OIL:
         {
             for(int i=0;i<50;++i){
                 int rr = R.Roll(ROWS-2);
                 int rc = R.Roll(COLS-2);
                 if(map[rr,rc].IsFloor()){
                     CellType cell = CellType.Wall;
                     int max_radius = 2;
                     switch(df){
                     case DungeonFeature.SLIME:
                         cell = CellType.Slime;
                         max_radius = 3;
                         break;
                     case DungeonFeature.OIL:
                         cell = CellType.Oil;
                         max_radius = 3;
                         break;
                     }
                     map[rr,rc] = cell;
                     for(int j=1;j<=max_radius;++j){
                         List<pos> added = new List<pos>();
                         foreach(pos p in new pos(rr,rc).PositionsWithinDistance(j,map)){
                             if(map[p] == cell){
                                 foreach(pos neighbor in p.CardinalAdjacentPositions()){
                                     if(map[neighbor].IsFloor() && R.CoinFlip()){
                                         added.AddUnique(neighbor);
                                     }
                                 }
                             }
                         }
                         foreach(pos p in added){
                             map[p] = cell;
                         }
                     }
                     break;
                 }
             }
             break;
         }
         case DungeonFeature.FIRE_GEYSER:
         {
             for(int i=0;i<50;++i){
                 int rr = R.Roll(ROWS-4)+1;
                 int rc = R.Roll(COLS-4)+1;
                 if(map[rr,rc].IsFloor()){
                     bool floors = true;
                     foreach(pos p in new pos(rr,rc).PositionsAtDistance(1,map)){
                         if(!map[p].IsFloor()){
                             floors = false;
                             break;
                         }
                     }
                     if(floors){
                         map[rr,rc] = CellType.Geyser;
                         break;
                     }
                 }
             }
             break;
         }
         case DungeonFeature.VINES:
         {
             for(int i=0;i<500;++i){
                 int rr = R.Roll(ROWS-2);
                 int rc = R.Roll(COLS-2);
                 pos p = new pos(rr,rc);
                 if(map[p].IsRoomType() && p.HasAdjacentWhere(x=>map.BoundsCheck(x) && map[x].IsWall())){
                     PosArray<bool> vine = map.GetFloodFillArray(p,false,x=>map[x].IsRoomType() && x.HasAdjacentWhere(y=>map.BoundsCheck(y) && map[y].IsWall()) && !R.OneIn(3)); //changed from one in 6 so vines won't fill caves so often
                     rr = R.Roll(ROWS-2);
                     rc = R.Roll(COLS-2);
                     pos p2 = new pos(rr,rc);
                     PosArray<bool> new_vine = new PosArray<bool>(ROWS,COLS);
                     int max = Math.Max(ROWS,COLS);
                     for(int dist=0;dist<max;++dist){
                         bool found = false;
                         foreach(pos possible_vine in p2.PositionsAtDistance(dist)){
                             if(possible_vine.BoundsCheck(new_vine,false)){
                                 found = true;
                                 if(vine[possible_vine] && possible_vine.PositionsAtDistance(1,new_vine).Where(x=>new_vine[x] || map[x] == CellType.Vine).Count < 3){
                                     new_vine[possible_vine] = true;
                                 }
                             }
                         }
                         if(!found){
                             break;
                         }
                     }
                     List<pos> added = new List<pos>();
                     for(int s=1;s<ROWS-1;++s){
                         for(int t=1;t<COLS-1;++t){
                             if(new_vine[s,t]){
                                 pos neighbor = new pos(s,t);
                                 foreach(int dir in U.FourDirections){
                                     if(R.OneIn(6) && map[neighbor.PosInDir(dir)].IsFloor()){
                                         added.AddUnique(neighbor.PosInDir(dir));
                                     }
                                 }
                             }
                         }
                     }
                     foreach(pos neighbor in added){
                         new_vine[neighbor] = true;
                     }
                     for(int s=1;s<ROWS-1;++s){
                         for(int t=1;t<COLS-1;++t){
                             if(new_vine[s,t]){
                                 if(R.OneIn(35)){
                                     map[s,t] = CellType.PoisonBulb;
                                 }
                                 else{
                                     map[s,t] = CellType.Vine;
                                 }
                             }
                         }
                     }
                     break;
                 }
             }
             break;
         }
         case DungeonFeature.BLAST_FUNGUS:
         case DungeonFeature.FOG_VENT:
         case DungeonFeature.POISON_VENT:
             for(int i=0;i<50;++i){
                 int rr = R.Roll(ROWS-2);
                 int rc = R.Roll(COLS-2);
                 if(map[rr,rc].IsFloor()){
                     if(df == DungeonFeature.BLAST_FUNGUS){
                         map[rr,rc] = CellType.BlastFungus;
                     }
                     if(df == DungeonFeature.FOG_VENT){
                         map[rr,rc] = CellType.FogVent;
                     }
                     if(df == DungeonFeature.POISON_VENT){
                         map[rr,rc] = CellType.PoisonVent;
                     }
                     break;
                 }
             }
             break;
         case DungeonFeature.CRACKED_WALL:
             for(int i=R.Between(2,4);i>0;--i){
                 if(thin_walls.Count > 0){
                     map[thin_walls.RemoveRandom()] = CellType.CrackedWall;
                 }
             }
             break;
         }
     }
 }