public static void AnimateStorm(pos origin,int radius,int num_frames,int num_per_frame,colorchar ch){
			for(int i=0;i<num_frames;++i){
				List<pos> cells = new List<pos>();
				List<pos> nearby = origin.PositionsWithinDistance(radius);
				for(int j=0;j<num_per_frame;++j){
					cells.Add(nearby.RemoveRandom());
				}
				Screen.AnimateMapCells(cells,ch);
			}
		}
 public bool AddRockFormations(int percent_chance_per_room,int minimum_distance_from_wall)
 {
     return ForEachRoom(list => {
         if(PercentChance(percent_chance_per_room)){
             int start_r = list.WhereLeast(x=>x.row)[0].row;
             int end_r = list.WhereGreatest(x=>x.row)[0].row;
             int start_c = list.WhereLeast(x=>x.col)[0].col;
             int end_c = list.WhereGreatest(x=>x.col)[0].col;
             Dungeon room = new Dungeon((end_r - start_r) + 3,(end_c - start_c) + 3); //includes borders
             while(true){
                 room.FillWithRandomWalls(25);
                 room.ApplyCellularAutomataXYRule(3);
                 for(int i=start_r;i<=end_r;++i){
                     for(int j=start_c;j<=end_c;++j){
                         pos p = new pos(i,j);
                         if(!p.PositionsWithinDistance(minimum_distance_from_wall-1,room.map).All(x=>list.Contains(x))){ //todo: I probably broke this.
                             room[i-start_r+1,j-start_c+1] = CellType.RoomInterior;
                         }
                     }
                 }
                 room.ConnectDiagonals();
                 room.RemoveDeadEndCorridors();
                 room.RemoveUnconnectedAreas();
                 for(int i=start_r;i<=end_r;++i){
                     for(int j=start_c;j<=end_c;++j){
                         if(list.Contains(new pos(i,j))){
                             map[i,j] = room[(i-start_r)+1,(j-start_c)+1];
                         }
                     }
                 }
                 break;
             }
         }
         return true;
     });
 }
 public bool ForEachRoom(RoomDelegate action)
 {
     List<pos> completed = new List<pos>();
     for(int i=1;i<H-1;++i){
         for(int j=1;j<W-1;++j){
             pos p = new pos(i,j);
             bool good = true;
             foreach(pos neighbor in p.PositionsWithinDistance(1,map)){ //assumes at least 3x3 rooms. this might need to change in the future.
                 if(!map[neighbor].IsRoomType()){
                     good = false;
                     break;
                 }
             }
             if(good && !completed.Contains(p)){
                 List<pos> room = map.GetFloodFillPositions(p,false,x=>map[x].IsRoomType());
                 if(!action(room)){
                     //return false;
                 }
                 foreach(pos p2 in room){
                     completed.Add(p2);
                 }
             }
         }
     }
     return true;
 }
 public static void AnimateStorm(pos origin,int radius,int num_frames,int num_per_frame,colorchar ch)
 {
     for(int i=0;i<num_frames;++i){
         List<pos> cells = new List<pos>();
         List<pos> nearby = origin.PositionsWithinDistance(radius);
         for(int j=0;j<num_per_frame;++j){
             pos p = nearby.RemoveRandom();
             if(BoundsCheck(p.row,p.col)){ //the ones that are out of bounds still count toward the total, so they don't become more dense as you get near edges.
                 cells.Add(p);
             }
         }
         Screen.AnimateMapCells(cells,ch);
     }
 }
Beispiel #5
0
 private void UpdateDensity(pos position)
 {
     foreach(pos p in position.PositionsWithinDistance(8,monster_density)){
         int dist = p.DistanceFrom(position);
         if(dist <= 1){
             monster_density[p] += 3;
         }
         else{
             if(dist <= 4){
                 monster_density[p] += 2;
             }
             else{
                 monster_density[p]++;
             }
         }
     }
 }
Beispiel #6
0
 public void GenerateLevel()
 {
     if(current_level < 20){
         ++current_level;
     }
     InitializeNewLevel();
     PosArray<CellType> map = GenerateMap(level_types[current_level-1]);
     List<pos> interesting_tiles = new List<pos>();
     for(int i=0;i<ROWS;++i){
         for(int j=0;j<COLS;++j){
             if(map[i,j] == CellType.InterestingLocation){
                 interesting_tiles.Add(new pos(i,j));
             }
         }
     }
     int attempts = 0;
     List<CellType> shrines = null;
     if(current_level % 2 == 1){
         shrines = new List<CellType>{CellType.SpecialFeature1,CellType.SpecialFeature2,CellType.SpecialFeature3,CellType.SpecialFeature4,CellType.SpecialFeature5};
         shrines.Randomize(); // after this initialization step, shrines are only removed from the front of the list, to enable prediction of pairs.
         nextLevelShrines = new List<CellType>();
         int n = R.Between(0,5);
         for(int i=0;i<n;++i){
             nextLevelShrines.Add(shrines.RemoveLast());
         }
     }
     else{
         shrines = nextLevelShrines;
         nextLevelShrines = null;
     }
     while(shrines.Count > 0){
         attempts = 0;
         for(bool done=false;!done;++attempts){
             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;
             }
             pos temp = new pos(rr,rc);
             if(shrines.Count > 1){
                 if(map[rr,rc].IsFloor()){
                     if(attempts > 1000){
                         bool good = true;
                         foreach(pos p in temp.PositionsWithinDistance(4,map)){
                             CellType ch = map[p];
                             if(ch.Is(CellType.SpecialFeature1,CellType.SpecialFeature2,CellType.SpecialFeature3,CellType.SpecialFeature4,CellType.SpecialFeature5)){
                                 good = false;
                             }
                         }
                         if(good){
                             List<pos> dist2 = new List<pos>();
                             foreach(pos p2 in temp.PositionsAtDistance(2,map)){
                                 if(map[p2].IsFloor()){
                                     dist2.Add(p2);
                                 }
                             }
                             if(dist2.Count > 0){
                                 map[rr,rc] = shrines.RemoveFirst();
                                 pos p2 = dist2.Random();
                                 map[p2.row,p2.col] = shrines.RemoveFirst();
                                 done = true;
                                 break;
                             }
                         }
                         else{
                             interesting_tiles.Remove(temp);
                         }
                     }
                     bool floors = true;
                     foreach(pos p in temp.PositionsAtDistance(1,map)){
                         if(!map[p.row,p.col].IsFloor()){
                             floors = false;
                         }
                     }
                     foreach(pos p in temp.PositionsWithinDistance(3,map)){
                         CellType ch = map[p];
                         if(ch.Is(CellType.SpecialFeature1,CellType.SpecialFeature2,CellType.SpecialFeature3,CellType.SpecialFeature4,CellType.SpecialFeature5)){
                             floors = false;
                         }
                     }
                     if(floors){
                         if(R.CoinFlip()){
                             map[rr-1,rc] = shrines.RemoveFirst();
                             map[rr+1,rc] = shrines.RemoveFirst();
                         }
                         else{
                             map[rr,rc-1] = shrines.RemoveFirst();
                             map[rr,rc+1] = shrines.RemoveFirst();
                         }
                         CellType center = CellType.Wall;
                         while(center == CellType.Wall){
                             switch(R.Roll(5)){
                             case 1:
                                 if(level_types[current_level-1] != LevelType.Hive && level_types[current_level-1] != LevelType.Garden){
                                     center = CellType.Pillar;
                                 }
                                 break;
                             case 2:
                                 center = CellType.Statue;
                                 break;
                             case 3:
                                 if(level_types[current_level-1] != LevelType.Garden){
                                     center = CellType.FirePit;
                                 }
                                 break;
                             case 4:
                                 center = CellType.ShallowWater;
                                 break;
                             case 5:
                                 if(level_types[current_level-1] != LevelType.Hive){
                                     center = CellType.Torch;
                                 }
                                 break;
                             }
                         }
                         map[rr,rc] = center;
                         interesting_tiles.Remove(temp);
                         done = true;
                         break;
                     }
                 }
             }
             else{
                 if(map[rr,rc].IsFloor()){
                     bool good = true;
                     foreach(pos p in temp.PositionsWithinDistance(2,map)){
                         CellType ch = map[p];
                         if(ch.Is(CellType.SpecialFeature1,CellType.SpecialFeature2,CellType.SpecialFeature3,CellType.SpecialFeature4,CellType.SpecialFeature5)){
                             good = false;
                         }
                     }
                     if(good){
                         if(attempts > 1000){
                             map[rr,rc] = shrines.RemoveFirst();
                             interesting_tiles.Remove(temp);
                             done = true;
                             break;
                         }
                         else{
                             bool floors = true;
                             foreach(pos p in temp.PositionsAtDistance(1,map)){
                                 if(!map[p.row,p.col].IsFloor()){
                                     floors = false;
                                 }
                             }
                             if(floors){
                                 map[rr,rc] = shrines.RemoveFirst();
                                 interesting_tiles.Remove(temp);
                                 done = true;
                                 break;
                             }
                         }
                     }
                 }
                 if(map[rr,rc].IsWall()){
                     if(!map[rr+1,rc].IsFloor() && !map[rr-1,rc].IsFloor() && !map[rr,rc-1].IsFloor() && !map[rr,rc+1].IsFloor()){
                         continue; //no floors? retry.
                     }
                     bool no_good = false;
                     foreach(pos p in temp.PositionsWithinDistance(2,map)){
                         CellType ch = map[p];
                         if(ch.Is(CellType.SpecialFeature1,CellType.SpecialFeature2,CellType.SpecialFeature3,CellType.SpecialFeature4,CellType.SpecialFeature5)){
                             no_good = true;
                         }
                     }
                     if(no_good){
                         continue;
                     }
                     int walls = 0;
                     foreach(pos p in temp.PositionsAtDistance(1,map)){
                         if(map[p].IsWall()){
                             ++walls;
                         }
                     }
                     if(walls >= 5){
                         int successive_walls = 0;
                         CellType[] rotated = new CellType[8];
                         for(int i=0;i<8;++i){
                             pos temp2;
                             temp2 = temp.PosInDir(8.RotateDir(true,i));
                             rotated[i] = map[temp2.row,temp2.col];
                         }
                         for(int i=0;i<15;++i){
                             if(rotated[i%8].IsWall()){
                                 ++successive_walls;
                             }
                             else{
                                 successive_walls = 0;
                             }
                             if(successive_walls == 5){
                                 done = true;
                                 map[rr,rc] = shrines.RemoveFirst();
                                 interesting_tiles.Remove(temp);
                                 break;
                             }
                         }
                     }
                 }
             }
         }
     }
     int num_chests = R.Between(0,1);
     if(level_types[current_level-1] == LevelType.Crypt){
         num_chests -= map.PositionsWhere(x=>map[x] == CellType.Chest).Count;
     }
     for(int i=0;i<num_chests;++i){
         int tries = 0;
         for(bool done=false;!done;++tries){
             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[rr,rc] = CellType.RoomInterior;
             }
             if(map[rr,rc].IsFloor()){
                 bool floors = true;
                 pos temp = new pos(rr,rc);
                 foreach(pos p in temp.PositionsAtDistance(1,map)){
                     if(!map[p.row,p.col].IsFloor()){
                         floors = false;
                     }
                 }
                 if(floors || tries > 1000){ //after 1000 tries, place it anywhere
                     map[rr,rc] = CellType.Chest;
                     done = true;
                 }
             }
         }
     }
     attempts = 0;
     for(bool done=false;!done;++attempts){
         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;
             pos temp = new pos(rr,rc);
             foreach(pos p in temp.PositionsAtDistance(1,map)){
                 if(!map[p.row,p.col].IsFloor()){
                     floors = false;
                 }
             }
             if(floors || attempts > 1000){
                 map[rr,rc] = CellType.Stairs;
                 done = true;
             }
         }
     }
     if(level_types[current_level-1] != LevelType.Garden){
         GenerateFloorTypes(map);
         GenerateFeatures(map,interesting_tiles);
     }
     int num_traps = R.Roll(2,3);
     for(int i=0;i<num_traps;++i){
         int tries = 0;
         for(bool done=false;!done && tries < 100;++tries){
             int rr = R.Roll(ROWS-2);
             int rc = R.Roll(COLS-2);
             if(map[rr,rc].IsFloor() && map[rr,rc] != CellType.ShallowWater){
                 map[rr,rc] = CellType.Trap;
                 done = true;
             }
         }
     }
     List<Tile> hidden = new List<Tile>();
     Event grave_dirt_event = null;
     Event poppy_event = null;
     Tile stairs = null;
     for(int i=0;i<ROWS;++i){
         for(int j=0;j<COLS;++j){
             //Screen.WriteMapChar(i,j,map[i,j]);
             switch(map[i,j]){
             case CellType.Wall:
             case CellType.Pillar:
                 Tile.Create(TileType.WALL,i,j);
                 break;
             case CellType.Door:
                 if(R.OneIn(120)){
                     if(R.CoinFlip()){
                         Tile.Create(TileType.STONE_SLAB,i,j);
                         Q.Add(new Event(tile[i,j],new List<Tile>{tile[i,j]},100,EventType.STONE_SLAB));
                     }
                     else{
                         Tile.Create(TileType.HIDDEN_DOOR,i,j);
                         hidden.Add(tile[i,j]);
                     }
                 }
                 else{
                     Tile.Create(TileType.DOOR_C,i,j);
                 }
                 break;
             case CellType.Stairs:
                 if(current_level < 20){
                     Tile.Create(TileType.STAIRS,i,j);
                     stairs = tile[i,j];
                 }
                 else{
                     if(current_level == 20){
                         Tile.Create(TileType.STAIRS,i,j);
                         tile[i,j].color = Color.Red;
                         tile[i,j].SetName("scorched stairway");
                         stairs = tile[i,j];
                     }
                     else{
                         Tile.Create(TileType.FLOOR,i,j);
                     }
                 }
                 break;
             case CellType.Statue:
                 Tile.Create(TileType.STATUE,i,j);
                 break;
             case CellType.Rubble:
                 Tile.Create(TileType.RUBBLE,i,j);
                 break;
             case CellType.FirePit:
                 Tile.Create(TileType.FIREPIT,i,j);
                 break;
             case CellType.Pool:
                 Tile.Create(TileType.POOL_OF_RESTORATION,i,j);
                 break;
             case CellType.BlastFungus:
                 Tile.Create(TileType.BLAST_FUNGUS,i,j);
                 break;
             case CellType.CrackedWall:
                 Tile.Create(TileType.CRACKED_WALL,i,j);
                 break;
             case CellType.Chest:
                 Tile.Create(TileType.CHEST,i,j);
                 break;
             case CellType.Trap:
             {
                 TileType type = Tile.RandomTrap();
                 Tile.Create(type,i,j);
                 if(tile[i,j].IsTrap()){
                     tile[i,j].name = "floor";
                     tile[i,j].the_name = "the floor";
                     tile[i,j].a_name = "a floor";
                     tile[i,j].symbol = '.';
                     tile[i,j].color = Color.White;
                     hidden.Add(tile[i,j]);
                 }
                 break;
             }
             case CellType.Geyser:
                 Tile.Create(TileType.FIRE_GEYSER,i,j);
                 int frequency = R.Roll(31) + 8; //9-39
                 int variance = R.Roll(10) - 1; //0-9
                 int variance_amount = (frequency * variance) / 10;
                 int number_of_values = variance_amount*2 + 1;
                 int minimum_value = frequency - variance_amount;
                 if(minimum_value < 5){
                     int diff = 5 - minimum_value;
                     number_of_values -= diff;
                     minimum_value = 5;
                 }
                 int delay = ((minimum_value - 1) + R.Roll(number_of_values)) * 100;
                 Q.Add(new Event(tile[i,j],delay + 200,EventType.FIRE_GEYSER,(frequency*10)+variance)); //notice the hacky way the value is stored
                 Q.Add(new Event(tile[i,j],delay,EventType.FIRE_GEYSER_ERUPTION,2));
                 break;
             case CellType.FogVent:
                 Tile.Create(TileType.FOG_VENT,i,j);
                 Q.Add(new Event(tile[i,j],100,EventType.FOG_VENT));
                 break;
             case CellType.PoisonVent:
                 Tile.Create(TileType.POISON_GAS_VENT,i,j);
                 Q.Add(new Event(tile[i,j],100,EventType.POISON_GAS_VENT));
                 break;
             case CellType.Tombstone:
             {
                 Tile t = Tile.Create(TileType.TOMBSTONE,i,j);
                 if(R.OneIn(8)){
                     Q.Add(new Event(null,new List<Tile>{t},100,EventType.TOMBSTONE_GHOST));
                 }
                 break;
             }
             case CellType.HiddenDoor:
                 Tile.Create(TileType.HIDDEN_DOOR,i,j);
                 hidden.Add(tile[i,j]);
                 break;
             case CellType.SpecialFeature1:
                 Tile.Create(TileType.COMBAT_SHRINE,i,j);
                 break;
             case CellType.SpecialFeature2:
                 Tile.Create(TileType.DEFENSE_SHRINE,i,j);
                 break;
             case CellType.SpecialFeature3:
                 Tile.Create(TileType.MAGIC_SHRINE,i,j);
                 break;
             case CellType.SpecialFeature4:
                 Tile.Create(TileType.SPIRIT_SHRINE,i,j);
                 break;
             case CellType.SpecialFeature5:
                 Tile.Create(TileType.STEALTH_SHRINE,i,j);
                 break;
             case CellType.DeepWater:
             case CellType.ShallowWater:
                 Tile.Create(TileType.WATER,i,j);
                 break;
             case CellType.Barrel:
                 Tile.Create(TileType.BARREL,i,j);
                 break;
             case CellType.Brush:
                 Tile.Create(TileType.BRUSH,i,j);
                 break;
             case CellType.GlowingFungus:
                 Tile.Create(TileType.GLOWING_FUNGUS,i,j);
                 break;
             case CellType.GraveDirt:
                 Tile.Create(TileType.GRAVE_DIRT,i,j);
                 if(grave_dirt_event == null){
                     grave_dirt_event = new Event(new List<Tile>{tile[i,j]},100,EventType.GRAVE_DIRT);
                     Q.Add(grave_dirt_event);
                 }
                 else{
                     grave_dirt_event.area.Add(tile[i,j]);
                 }
                 break;
             case CellType.Gravel:
                 Tile.Create(TileType.GRAVEL,i,j);
                 break;
             case CellType.Ice:
                 Tile.Create(TileType.ICE,i,j);
                 break;
             case CellType.Oil:
                 Tile.Create(TileType.FLOOR,i,j);
                 tile[i,j].AddFeature(FeatureType.OIL);
                 break;
             case CellType.PoisonBulb:
                 Tile.Create(TileType.POISON_BULB,i,j);
                 break;
             case CellType.Poppies:
                 Tile.Create(TileType.POPPY_FIELD,i,j);
                 if(poppy_event == null){
                     poppy_event = new Event(new List<Tile>{tile[i,j]},100,EventType.POPPIES);
                     Q.Add(poppy_event);
                 }
                 else{
                     poppy_event.area.Add(tile[i,j]);
                 }
                 break;
             case CellType.Slime:
                 Tile.Create(TileType.FLOOR,i,j);
                 tile[i,j].AddFeature(FeatureType.SLIME);
                 break;
             case CellType.Torch:
                 Tile.Create(TileType.STANDING_TORCH,i,j);
                 break;
             case CellType.Vine:
                 Tile.Create(TileType.VINE,i,j);
                 break;
             case CellType.Webs:
                 Tile.Create(TileType.FLOOR,i,j);
                 tile[i,j].AddFeature(FeatureType.WEB);
                 break;
             default:
                 Tile.Create(TileType.FLOOR,i,j);
                 break;
             }
             //alltiles.Add(tile[i,j]);
             tile[i,j].solid_rock = true;
         }
     }
     //Input.ReadKey();
     player.ResetForNewLevel();
     foreach(Tile t in AllTiles()){
         if(t.light_radius > 0){
             t.UpdateRadius(0,t.light_radius);
         }
     }
     int num_items = R.Between(0,2);
     for(int i=num_items;i>0;--i){
         SpawnItem();
     }
     bool poltergeist_spawned = false; //i'm not sure this is the right call, but for now
     bool mimic_spawned = false; // i'm limiting these guys, to avoid "empty" levels
     bool marble_horror_spawned = false;
     int num_monsters = R.Roll(2,2) + 4;
     if(num_monsters == 6){
         num_monsters += R.Roll(3); //this works out to 7/12 seven, 4/12 eight, and 1/12 nine.
     }
     for(int i=num_monsters;i>0;--i){
         ActorType type = MobType();
         if(type == ActorType.POLTERGEIST){
             if(!poltergeist_spawned){
                 SpawnMob(type);
                 poltergeist_spawned = true;
             }
             else{
                 ++i; //try again..
             }
         }
         else{
             if(type == ActorType.MIMIC){
                 if(!mimic_spawned){
                     SpawnMob(type);
                     mimic_spawned = true;
                 }
                 else{
                     ++i;
                 }
             }
             else{
                 if(type == ActorType.MARBLE_HORROR){
                     Tile statue = AllTiles().Where(t=>t.type == TileType.STATUE).RandomOrDefault();
                     if(!marble_horror_spawned && statue != null){
                         SpawnMob(type);
                         marble_horror_spawned = true;
                     }
                     else{
                         ++i;
                     }
                 }
                 else{
                     if(type == ActorType.ENTRANCER){
                         if(i >= 2){ //need 2 slots here
                             Actor entrancer = SpawnMob(type);
                             entrancer.attrs[AttrType.WANDERING]++;
                             List<Tile> tiles = new List<Tile>();
                             int dist = 1;
                             while(tiles.Count == 0 && dist < 100){
                                 foreach(Tile t in entrancer.TilesAtDistance(dist)){
                                     if(t.passable && !t.IsTrap() && t.actor() == null){
                                         tiles.Add(t);
                                     }
                                 }
                                 ++dist;
                             }
                             if(tiles.Count > 0){
                                 ActorType thralltype = ActorType.SPECIAL;
                                 bool done = false;
                                 while(!done){
                                     thralltype = MobType();
                                     switch(thralltype){ //not on the list: group/stealth/ranged/rare/immobile/hazardous monsters, plus carrion crawler, mechanical knight, mud elemental, and luminous avenger
                                     case ActorType.ROBED_ZEALOT:
                                     case ActorType.WILD_BOAR:
                                     case ActorType.TROLL:
                                     case ActorType.DERANGED_ASCETIC:
                                     case ActorType.ALASI_BATTLEMAGE:
                                     case ActorType.ALASI_SOLDIER:
                                     case ActorType.SKITTERMOSS:
                                     case ActorType.STONE_GOLEM:
                                     case ActorType.OGRE_BARBARIAN:
                                     case ActorType.SNEAK_THIEF:
                                     case ActorType.CRUSADING_KNIGHT:
                                     case ActorType.CORROSIVE_OOZE:
                                     case ActorType.ALASI_SENTINEL:
                                     case ActorType.CYCLOPEAN_TITAN:
                                         done = true;
                                         break;
                                     }
                                 }
                                 Tile t = tiles.Random();
                                 Actor thrall = Actor.Create(thralltype,t.row,t.col,TiebreakerAssignment.InsertAfterCurrent);
                                 if(entrancer.group == null){
                                     entrancer.group = new List<Actor>{entrancer};
                                 }
                                 entrancer.group.Add(thrall);
                                 thrall.group = entrancer.group;
                                 --i;
                             }
                         }
                         else{
                             ++i;
                         }
                     }
                     else{
                         Actor a = SpawnMob(type);
                         if(type == ActorType.WARG){
                             if(a.group != null){
                                 foreach(Actor a2 in a.group){
                                     a2.attrs[AttrType.WANDERING]++;
                                 }
                             }
                         }
                         else{
                             if(a.AlwaysWanders() || (R.PercentChance(40) && a.CanWanderAtLevelGen())){
                                 a.attrs[AttrType.WANDERING]++;
                             }
                         }
                     }
                 }
             }
         }
     }
     for(int i=(current_level-3)/4;i>0;--i){ //yes, this is all copied and pasted for a one-line change. i'll try to fix it later.
         if(R.CoinFlip()){ //generate some shallow monsters
             ActorType type = ShallowMobType();
             if(type == ActorType.POLTERGEIST){
                 if(!poltergeist_spawned){
                     SpawnMob(type);
                     poltergeist_spawned = true;
                 }
                 else{
                     ++i; //try again..
                 }
             }
             else{
                 if(type == ActorType.MIMIC){
                     if(!mimic_spawned){
                         SpawnMob(type);
                         mimic_spawned = true;
                     }
                     else{
                         ++i;
                     }
                 }
                 else{
                     if(type == ActorType.MARBLE_HORROR){
                         Tile statue = AllTiles().Where(t=>t.type == TileType.STATUE).RandomOrDefault();
                         if(!marble_horror_spawned && statue != null){
                             SpawnMob(type);
                             marble_horror_spawned = true;
                         }
                         else{
                             ++i;
                         }
                     }
                     else{
                         if(type == ActorType.ENTRANCER){
                             if(i >= 2){ //need 2 slots here
                                 Actor entrancer = SpawnMob(type);
                                 entrancer.attrs[AttrType.WANDERING]++;
                                 List<Tile> tiles = new List<Tile>();
                                 int dist = 1;
                                 while(tiles.Count == 0 && dist < 100){
                                     foreach(Tile t in entrancer.TilesAtDistance(dist)){
                                         if(t.passable && !t.IsTrap() && t.actor() == null){
                                             tiles.Add(t);
                                         }
                                     }
                                     ++dist;
                                 }
                                 if(tiles.Count > 0){
                                     ActorType thralltype = ActorType.SPECIAL;
                                     bool done = false;
                                     while(!done){
                                         thralltype = MobType();
                                         switch(thralltype){
                                         case ActorType.ROBED_ZEALOT:
                                         case ActorType.DERANGED_ASCETIC:
                                         case ActorType.BERSERKER:
                                         case ActorType.TROLL:
                                         case ActorType.CRUSADING_KNIGHT:
                                         case ActorType.SKITTERMOSS:
                                         case ActorType.OGRE_BARBARIAN:
                                         case ActorType.SNEAK_THIEF:
                                         case ActorType.STONE_GOLEM:
                                         case ActorType.LUMINOUS_AVENGER:
                                         case ActorType.WILD_BOAR:
                                         case ActorType.ALASI_SOLDIER:
                                         case ActorType.CORROSIVE_OOZE:
                                         case ActorType.ALASI_SENTINEL:
                                             done = true;
                                             break;
                                         }
                                     }
                                     Tile t = tiles.Random();
                                     Actor thrall = Actor.Create(thralltype,t.row,t.col,TiebreakerAssignment.InsertAfterCurrent);
                                     if(entrancer.group == null){
                                         entrancer.group = new List<Actor>{entrancer};
                                     }
                                     entrancer.group.Add(thrall);
                                     thrall.group = entrancer.group;
                                     --i;
                                 }
                             }
                             else{
                                 ++i;
                             }
                         }
                         else{
                             Actor a = SpawnMob(type);
                             if(type == ActorType.WARG){
                                 if(a.group != null){
                                     foreach(Actor a2 in a.group){
                                         a2.attrs[AttrType.WANDERING]++;
                                     }
                                 }
                             }
                             else{
                                 if(a.AlwaysWanders() || (R.PercentChance(40) && a.CanWanderAtLevelGen())){
                                     a.attrs[AttrType.WANDERING]++;
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
     int minimum_distance_from_stairs = 0;
     PosArray<int> distance_from_stairs = null;
     if(stairs != null){
         distance_from_stairs = tile.GetDijkstraMap(new List<pos>{stairs.p},x=>tile[x].BlocksConnectivityOfMap());
         minimum_distance_from_stairs = distance_from_stairs[distance_from_stairs.PositionsWhere(x=>distance_from_stairs[x].IsValidDijkstraValue()).WhereGreatest(x=>distance_from_stairs[x]).Random()] / 2;
     }
     bool[,] good_location = new bool[ROWS,COLS];
     for(int i=0;i<ROWS;++i){
         for(int j=0;j<COLS;++j){
             if(tile[i,j].Is(TileType.FLOOR) && !tile[i,j].Is(FeatureType.WEB) && (stairs == null || distance_from_stairs[i,j] >= minimum_distance_from_stairs)){
                 good_location[i,j] = true;
             }
             else{
                 good_location[i,j] = false;
             }
         }
     }
     foreach(Actor a in AllActors()){
         if(a != player){
             good_location[a.row,a.col] = false;
             for(int i=0;i<ROWS;++i){
                 for(int j=0;j<COLS;++j){
                     if(good_location[i,j] && a.HasLOS(i,j)){
                         good_location[i,j] = false;
                     }
                 }
             }
         }
     }
     bool at_least_one_good = false;
     for(int i=0;i<ROWS && !at_least_one_good;++i){
         for(int j=0;j<COLS && !at_least_one_good;++j){
             if(good_location[i,j]){
                 at_least_one_good = true;
             }
         }
     }
     if(!at_least_one_good){
         foreach(Actor a in AllActors()){
             if(a != player){
                 good_location[a.row,a.col] = false;
                 for(int i=0;i<ROWS;++i){
                     for(int j=0;j<COLS;++j){
                         if(good_location[i,j] && a.CanSee(i,j)){ //checking CanSee this time
                             good_location[i,j] = false;
                         }
                     }
                 }
             }
         }
     }
     List<Tile> goodtiles = new List<Tile>();
     for(int i=0;i<ROWS;++i){
         for(int j=0;j<COLS;++j){
             if(good_location[i,j]){
                 goodtiles.Add(tile[i,j]);
             }
         }
     }
     if(goodtiles.Count > 0){
         Tile t = goodtiles.Random();
         int light = player.light_radius;
         int burning = player.attrs[AttrType.BURNING];
         int shining = player.attrs[AttrType.SHINING];
         player.light_radius = 0;
         player.attrs[AttrType.BURNING] = 0;
         player.attrs[AttrType.SHINING] = 0;
         player.Move(t.row,t.col);
         player.light_radius = light;
         player.attrs[AttrType.BURNING] = burning;
         player.attrs[AttrType.SHINING] = shining;
         player.UpdateRadius(0,player.LightRadius());
     }
     else{
         for(bool done=false;!done;){
             int rr = R.Roll(ROWS-2);
             int rc = R.Roll(COLS-2);
             bool good = true;
             foreach(Tile t in tile[rr,rc].TilesWithinDistance(1)){
                 if(t.IsTrap()){
                     good = false;
                 }
             }
             if(good && tile[rr,rc].passable && actor[rr,rc] == null){
                 int light = player.light_radius;
                 int burning = player.attrs[AttrType.BURNING];
                 int shining = player.attrs[AttrType.SHINING];
                 player.light_radius = 0;
                 player.attrs[AttrType.BURNING] = 0;
                 player.attrs[AttrType.SHINING] = 0;
                 player.Move(rr,rc);
                 player.light_radius = light;
                 player.attrs[AttrType.BURNING] = burning;
                 player.attrs[AttrType.SHINING] = shining;
                 player.UpdateRadius(0,player.LightRadius());
                 done = true;
             }
         }
     }
     actor[player.row,player.col] = player; //this line fixes a bug that occurs when the player ends up in the same position on a new level
     Screen.screen_center_col = player.col;
     if(R.CoinFlip()){ //todo: copied and pasted below
         bool done = false;
         for(int tries=0;!done && tries<500;++tries){
             int rr = R.Roll(ROWS-4) + 1;
             int rc = R.Roll(COLS-4) + 1;
             bool good = true;
             foreach(Tile t in tile[rr,rc].TilesWithinDistance(2)){
                 if(t.type != TileType.WALL){
                     good = false;
                     break;
                 }
             }
             if(good){
                 List<int> dirs = new List<int>();
                 bool long_corridor = false;
                 int connections = 0;
                 for(int i=2;i<=8;i+=2){
                     Tile t = tile[rr,rc].TileInDirection(i).TileInDirection(i);
                     bool good_dir = true;
                     int distance = -1;
                     while(good_dir && t != null && t.type == TileType.WALL){
                         if(t.TileInDirection(i.RotateDir(false,2)).type != TileType.WALL){
                             good_dir = false;
                         }
                         if(t.TileInDirection(i.RotateDir(true,2)).type != TileType.WALL){
                             good_dir = false;
                         }
                         t = t.TileInDirection(i);
                         if(t != null && t.type == TileType.STATUE){
                             good_dir = false;
                         }
                         ++distance;
                     }
                     if(good_dir && t != null){
                         dirs.Add(i);
                         ++connections;
                         if(distance >= 4){
                             long_corridor = true;
                         }
                     }
                 }
                 if(dirs.Count > 0){
                     List<TileType> all_possible_traps = new List<TileType>{TileType.GRENADE_TRAP,TileType.POISON_GAS_TRAP,TileType.PHANTOM_TRAP,TileType.FIRE_TRAP,TileType.SHOCK_TRAP,TileType.SCALDING_OIL_TRAP,TileType.FLING_TRAP,TileType.STONE_RAIN_TRAP};
                     List<TileType> possible_traps = new List<TileType>();
                     //int trap_roll = R.Roll(7);
                     int num_types = R.Between(2,3);
                     /*if(trap_roll == 1){
                         num_types = 1;
                     }
                     else{
                         if(trap_roll <= 4){
                             num_types = 2;
                         }
                         else{
                             num_types = 3;
                         }
                     }*/
                     for(int i=0;i<num_types;++i){
                         TileType tt = all_possible_traps.Random();
                         if(possible_traps.Contains(tt)){
                             --i;
                         }
                         else{
                             possible_traps.Add(tt);
                         }
                     }
                     bool stone_slabs = false; //(instead of hidden doors)
                     if(R.OneIn(4)){
                         stone_slabs = true;
                     }
                     foreach(int i in dirs){
                         Tile t = tile[rr,rc].TileInDirection(i);
                         int distance = -2; //distance of the corridor between traps and secret door
                         while(t.type == TileType.WALL){
                             ++distance;
                             t = t.TileInDirection(i);
                         }
                         if(long_corridor && distance < 4){
                             continue;
                         }
                         t = tile[rr,rc].TileInDirection(i);
                         while(t.type == TileType.WALL){
                             if(distance >= 4){
                                 TileType tt = TileType.FLOOR;
                                 if(R.Roll(3) >= 2){
                                     tt = possible_traps.Random();
                                     hidden.Add(t);
                                 }
                                 t.TransformTo(tt);
                                 t.name = "floor";
                                 t.the_name = "the floor";
                                 t.a_name = "a floor";
                                 t.symbol = '.';
                                 t.color = Color.White;
                                 if(t.DistanceFrom(tile[rr,rc]) < distance+2){
                                     Tile neighbor = t.TileInDirection(i.RotateDir(false,2));
                                     if(neighbor.TileInDirection(i.RotateDir(false,1)).type == TileType.WALL
                                        && neighbor.TileInDirection(i.RotateDir(false,2)).type == TileType.WALL
                                        && neighbor.TileInDirection(i.RotateDir(false,3)).type == TileType.WALL){
                                         tt = TileType.FLOOR;
                                         if(R.Roll(3) >= 2){
                                             tt = possible_traps.Random();
                                         }
                                         neighbor.TransformTo(tt);
                                         if(possible_traps.Contains(tt)){
                                             neighbor.name = "floor";
                                             neighbor.the_name = "the floor";
                                             neighbor.a_name = "a floor";
                                             neighbor.symbol = '.';
                                             neighbor.color = Color.White;
                                             hidden.Add(neighbor);
                                         }
                                     }
                                     neighbor = t.TileInDirection(i.RotateDir(true,2));
                                     if(neighbor.TileInDirection(i.RotateDir(true,1)).type == TileType.WALL
                                        && neighbor.TileInDirection(i.RotateDir(true,2)).type == TileType.WALL
                                        && neighbor.TileInDirection(i.RotateDir(true,3)).type == TileType.WALL){
                                         tt = TileType.FLOOR;
                                         if(R.Roll(3) >= 2){
                                             tt = possible_traps.Random();
                                         }
                                         neighbor.TransformTo(tt);
                                         if(possible_traps.Contains(tt)){
                                             neighbor.name = "floor";
                                             neighbor.the_name = "the floor";
                                             neighbor.a_name = "a floor";
                                             neighbor.symbol = '.';
                                             neighbor.color = Color.White;
                                             hidden.Add(neighbor);
                                         }
                                     }
                                 }
                             }
                             else{
                                 TileType tt = TileType.FLOOR;
                                 if(R.CoinFlip()){
                                     tt = Tile.RandomTrap();
                                     hidden.Add(t);
                                 }
                                 t.TransformTo(tt);
                                 if(tt != TileType.FLOOR){
                                     t.name = "floor";
                                     t.the_name = "the floor";
                                     t.a_name = "a floor";
                                     t.symbol = '.';
                                     t.color = Color.White;
                                 }
                             }
                             t = t.TileInDirection(i);
                         }
                         t = t.TileInDirection(i.RotateDir(true,4));
                         if(stone_slabs){
                             t.TransformTo(TileType.STONE_SLAB);
                             Q.Add(new Event(t,new List<Tile>{t.TileInDirection(i.RotateDir(true,4))},100,EventType.STONE_SLAB));
                         }
                         else{
                             t.TransformTo(TileType.HIDDEN_DOOR);
                             hidden.AddUnique(t);
                         }
                         t = t.TileInDirection(i.RotateDir(true,4));
                         if(R.CoinFlip()){
                             if(t.IsTrap()){
                                 t.type = TileType.ALARM_TRAP;
                             }
                             else{
                                 t.TransformTo(TileType.ALARM_TRAP);
                                 t.name = "floor";
                                 t.the_name = "the floor";
                                 t.a_name = "a floor";
                                 t.symbol = '.';
                                 t.color = Color.White;
                                 hidden.AddUnique(t);
                             }
                         }
                     }
                     if(long_corridor && connections == 1){
                         foreach(Tile t in tile[rr,rc].TilesWithinDistance(1)){
                             t.TransformTo(possible_traps.Random());
                             t.name = "floor";
                             t.the_name = "the floor";
                             t.a_name = "a floor";
                             t.symbol = '.';
                             t.color = Color.White;
                             hidden.Add(t);
                         }
                         tile[rr,rc].TileInDirection(dirs[0].RotateDir(true,4)).TransformTo(TileType.CHEST);
                         tile[rr,rc].TileInDirection(dirs[0].RotateDir(true,4)).color = Color.Yellow;
                     }
                     else{
                         foreach(Tile t in tile[rr,rc].TilesAtDistance(1)){
                             t.TransformTo(Tile.RandomTrap());
                             t.name = "floor";
                             t.the_name = "the floor";
                             t.a_name = "a floor";
                             t.symbol = '.';
                             t.color = Color.White;
                             hidden.Add(t);
                         }
                         tile[rr,rc].TransformTo(TileType.CHEST);
                         tile[rr,rc].color = Color.Yellow;
                     }
                     done = true;
                 }
             }
         }
     }
     /*if(R.CoinFlip()){
         bool done = false;
         for(int tries=0;!done && tries<500;++tries){
             int rr = R.Roll(ROWS-4) + 1;
             int rc = R.Roll(COLS-4) + 1;
             bool good = true;
             foreach(Tile t in tile[rr,rc].TilesWithinDistance(2)){
                 if(t.type != TileType.WALL){
                     good = false;
                     break;
                 }
             }
             if(good){
                 List<int> dirs = new List<int>();
                 bool long_corridor = false;
                 int connections = 0;
                 for(int i=2;i<=8;i+=2){
                     Tile t = tile[rr,rc].TileInDirection(i).TileInDirection(i);
                     bool good_dir = true;
                     int distance = -1;
                     while(good_dir && t != null && t.type == TileType.WALL){
                         if(t.TileInDirection(i.RotateDir(false,2)).type != TileType.WALL){
                             good_dir = false;
                         }
                         if(t.TileInDirection(i.RotateDir(true,2)).type != TileType.WALL){
                             good_dir = false;
                         }
                         t = t.TileInDirection(i);
                         if(t != null && t.type == TileType.STATUE){
                             good_dir = false;
                         }
                         ++distance;
                     }
                     if(good_dir && t != null){
                         dirs.Add(i);
                         ++connections;
                         if(distance >= 4){
                             long_corridor = true;
                         }
                     }
                 }
                 if(dirs.Count > 0){
                     List<TileType> possible_traps = new List<TileType>();
                     int trap_roll = R.Roll(7);
                     if(trap_roll == 1 || trap_roll == 4 || trap_roll == 5 || trap_roll == 7){
                         possible_traps.Add(TileType.GRENADE_TRAP);
                     }
                     if(trap_roll == 2 || trap_roll == 4 || trap_roll == 6 || trap_roll == 7){
                         possible_traps.Add(TileType.POISON_GAS_TRAP);
                     }
                     if(trap_roll == 3 || trap_roll == 5 || trap_roll == 6 || trap_roll == 7){
                         possible_traps.Add(TileType.PHANTOM_TRAP);
                     }
                     bool stone_slabs = false; //(instead of hidden doors)
                     if(R.OneIn(4)){
                         stone_slabs = true;
                     }
                     foreach(int i in dirs){
                         Tile t = tile[rr,rc].TileInDirection(i);
                         int distance = -2; //distance of the corridor between traps and secret door
                         while(t.type == TileType.WALL){
                             ++distance;
                             t = t.TileInDirection(i);
                         }
                         if(long_corridor && distance < 4){
                             continue;
                         }
                         t = tile[rr,rc].TileInDirection(i);
                         while(t.type == TileType.WALL){
                             if(distance >= 4){
                                 TileType tt = TileType.FLOOR;
                                 if(R.Roll(3) >= 2){
                                     tt = possible_traps.Random();
                                     hidden.Add(t);
                                 }
                                 t.TransformTo(tt);
                                 t.name = "floor";
                                 t.the_name = "the floor";
                                 t.a_name = "a floor";
                                 t.symbol = '.';
                                 t.color = Color.White;
                                 if(t.DistanceFrom(tile[rr,rc]) < distance+2){
                                     Tile neighbor = t.TileInDirection(i.RotateDir(false,2));
                                     if(neighbor.TileInDirection(i.RotateDir(false,1)).type == TileType.WALL
                                        && neighbor.TileInDirection(i.RotateDir(false,2)).type == TileType.WALL
                                        && neighbor.TileInDirection(i.RotateDir(false,3)).type == TileType.WALL){
                                         tt = TileType.FLOOR;
                                         if(R.Roll(3) >= 2){
                                             tt = possible_traps.Random();
                                         }
                                         neighbor.TransformTo(tt);
                                         if(possible_traps.Contains(tt)){
                                             neighbor.name = "floor";
                                             neighbor.the_name = "the floor";
                                             neighbor.a_name = "a floor";
                                             neighbor.symbol = '.';
                                             neighbor.color = Color.White;
                                             hidden.Add(neighbor);
                                         }
                                     }
                                     neighbor = t.TileInDirection(i.RotateDir(true,2));
                                     if(neighbor.TileInDirection(i.RotateDir(true,1)).type == TileType.WALL
                                        && neighbor.TileInDirection(i.RotateDir(true,2)).type == TileType.WALL
                                        && neighbor.TileInDirection(i.RotateDir(true,3)).type == TileType.WALL){
                                         tt = TileType.FLOOR;
                                         if(R.Roll(3) >= 2){
                                             tt = possible_traps.Random();
                                         }
                                         neighbor.TransformTo(tt);
                                         if(possible_traps.Contains(tt)){
                                             neighbor.name = "floor";
                                             neighbor.the_name = "the floor";
                                             neighbor.a_name = "a floor";
                                             neighbor.symbol = '.';
                                             neighbor.color = Color.White;
                                             hidden.Add(neighbor);
                                         }
                                     }
                                 }
                             }
                             else{
                                 TileType tt = TileType.FLOOR;
                                 if(R.CoinFlip()){
                                     tt = Tile.RandomTrap();
                                     hidden.Add(t);
                                 }
                                 t.TransformTo(tt);
                                 if(tt != TileType.FLOOR){
                                     t.name = "floor";
                                     t.the_name = "the floor";
                                     t.a_name = "a floor";
                                     t.symbol = '.';
                                     t.color = Color.White;
                                 }
                             }
                             t = t.TileInDirection(i);
                         }
                         t = t.TileInDirection(i.RotateDir(true,4));
                         if(stone_slabs){
                             t.TransformTo(TileType.STONE_SLAB);
                             Q.Add(new Event(t,new List<Tile>{t.TileInDirection(i.RotateDir(true,4))},100,EventType.STONE_SLAB));
                         }
                         else{
                             t.TransformTo(TileType.HIDDEN_DOOR);
                             hidden.AddUnique(t);
                         }
                         t = t.TileInDirection(i.RotateDir(true,4));
                         if(R.CoinFlip()){
                             if(t.IsTrap()){
                                 t.type = TileType.ALARM_TRAP;
                             }
                             else{
                                 t.TransformTo(TileType.ALARM_TRAP);
                                 t.name = "floor";
                                 t.the_name = "the floor";
                                 t.a_name = "a floor";
                                 t.symbol = '.';
                                 t.color = Color.White;
                                 hidden.AddUnique(t);
                             }
                         }
                     }
                     if(long_corridor && connections == 1){
                         foreach(Tile t in tile[rr,rc].TilesWithinDistance(1)){
                             t.TransformTo(possible_traps.Random());
                             t.name = "floor";
                             t.the_name = "the floor";
                             t.a_name = "a floor";
                             t.symbol = '.';
                             t.color = Color.White;
                             hidden.Add(t);
                         }
                         tile[rr,rc].TileInDirection(dirs[0].RotateDir(true,4)).TransformTo(TileType.CHEST);
                         tile[rr,rc].TileInDirection(dirs[0].RotateDir(true,4)).color = Color.Yellow;
                     }
                     else{
                         foreach(Tile t in tile[rr,rc].TilesAtDistance(1)){
                             t.TransformTo(Tile.RandomTrap());
                             t.name = "floor";
                             t.the_name = "the floor";
                             t.a_name = "a floor";
                             t.symbol = '.';
                             t.color = Color.White;
                             hidden.Add(t);
                         }
                         tile[rr,rc].TransformTo(TileType.CHEST);
                         tile[rr,rc].color = Color.Yellow;
                     }
                     done = true;
                 }
             }
         }
     }*/
     foreach(Tile t in AllTiles()){
         if(t.type != TileType.WALL){
             foreach(Tile neighbor in t.TilesAtDistance(1)){
                 neighbor.solid_rock = false;
             }
         }
         if(t.type == TileType.GLOWING_FUNGUS){
             foreach(Tile neighbor in t.TilesAtDistance(1)){
                 if(neighbor.type == TileType.WALL){
                     neighbor.color = Color.RandomGlowingFungus;
                 }
             }
         }
     }
     if(level_types[current_level-1] == LevelType.Hive){
         var dijkstra = tile.GetDijkstraMap(x=>tile[x].type != TileType.WALL,x=>false);
         for(int i=0;i<ROWS;++i){
             for(int j=0;j<COLS;++j){
                 if((dijkstra[i,j] == 1 && !R.OneIn(20)) || (dijkstra[i,j] == 2 && R.CoinFlip())){
                     if(i == 0 || j == 0 || i == ROWS-1 || j == COLS-1){
                         tile[i,j].color = Color.DarkYellow;
                         tile[i,j].SetName("waxy wall"); //borders become waxy but don't burn
                     }
                     else{
                         tile[i,j].Toggle(null,TileType.WAX_WALL);
                     }
                 }
             }
         }
     }
     if(level_types[current_level-1] == LevelType.Fortress){
         foreach(pos p in tile.PositionsWhere(x=>tile[x].Is(TileType.WALL,TileType.HIDDEN_DOOR))){
             tile[p].color = Color.TerrainDarkGray;
         }
     }
     string desc = GetDungeonDescription();
     for(int i=0;i<ROWS;++i){
         for(int j=0;j<COLS;++j){ //todo fix this!
             if(!tile.BoundsCheck(i,j,false)) continue;
             pos p = new pos(i,j);
             if(SchismExtensionMethods.Extensions.ConsecutiveAdjacent(p,x=>!tile[x].BlocksConnectivityOfMap()) >= 3){ //todo, fix check!
                 dungeon_description[i,j] = desc;
             }
             else{
                 dungeon_description[i,j] = "You pass through a hallway of hewn stone."; //todo, fix message!
             }
         }
     }
     if(poppy_event != null){
         CalculatePoppyDistanceMap();
     }
     if(hidden.Count > 0){
         Event e = new Event(hidden,100,EventType.CHECK_FOR_HIDDEN);
         e.tiebreaker = 0;
         Q.Add(e);
     }
     {
         Event e = new Event(10000,EventType.RELATIVELY_SAFE);
         e.tiebreaker = 0;
         Q.Add(e);
     }
     {
         Event e = new Event(R.Between(400,450)*100,EventType.SPAWN_WANDERING_MONSTER);
         e.tiebreaker = 0;
         Q.Add(e);
     }
     if(current_level == 1){
         B.Add("In the mountain pass where travelers vanish, a stone staircase leads downward... Welcome, " + Actor.player_name + "! ");
     }
     else{
         B.Add(LevelMessage());
     }
 }