public DungeonArrayFloor(GeneratorOptions options, RDungeonChamberReq req) { Rooms = new DungeonArrayRoom[4, 4]; //array of all rooms VHalls = new DungeonArrayHall[4, 3]; //vertical halls HHalls = new DungeonArrayHall[3, 4]; //horizontal halls Start = new DungeonPoint(-1, -1); //marks spawn point End = new DungeonPoint(-1, -1); //marks stairs Chamber = new DungeonPoint(-1, -1); //marks chamber int i, j, a = -1, b; //counter variables MapArray = new int[50, 50]; // stores map grid int x, y; // used for navigating map array bool isDone; // bool used for various purposes // Part of Options class now //int trapFreq = 66; // adjust to number between 0 and 100 to see changes //int trapMin = 5; // adjust to number between 0 and 255 to see changes //int trapMax = 30; // adjust to number between 0 and 255 to see changes //initialize map array to empty for (y = 0; y < 50; y++) { for (x = 0; x < 50; x++) { MapArray[x, y] = UBLOCK; } } //initialize all rooms+halls to closed by default for (x = 0; x <= Rooms.GetUpperBound(0); x++) { for (y = 0; y <= Rooms.GetUpperBound(1); y++) { Rooms[x, y] = new DungeonArrayRoom(); } } for (x = 0; x <= VHalls.GetUpperBound(0); x++) { for (y = 0; y <= VHalls.GetUpperBound(1); y++) { VHalls[x, y] = new DungeonArrayHall(); } } for (x = 0; x <= HHalls.GetUpperBound(0); x++) { for (y = 0; y <= HHalls.GetUpperBound(1); y++) { HHalls[x, y] = new DungeonArrayHall(); } } // path generation algorithm Start = new DungeonPoint(random.Next(0, Rooms.GetUpperBound(0) + 1), random.Next(0, Rooms.GetUpperBound(1) + 1)); // randomly determine start room DungeonPoint wanderer = Start; //start = random.Next(0, 16); // randomly determine start room //x = start; i = 0; j = random.Next(0, 6) + 5; // magic numbers, determine what the dungeon looks like (in general, paths) b = -1; // direction of movement do { if (random.Next(0, (2 + i)) == 0) {//will end the current path and start a new one from the start if (random.Next(0, 2) == 0) {//determine if the room should be open or a hall Rooms[wanderer.X, wanderer.Y].Opened = OPEN; } else { Rooms[wanderer.X, wanderer.Y].Opened = HALL; } i++; wanderer = Start; b = -1; } else { bool working = true; do { DungeonPoint sample = wanderer; y = random.Next(0, 4); if (y != b) {//makes sure there is no backtracking switch (y) { case 0: sample.Y--; b = 1; break; case 1: sample.Y++; b = 0; break; case 2: sample.X--; b = 3; break; case 3: sample.X++; b = 2; break; } if (sample.X >= 0 && sample.X <= Rooms.GetUpperBound(0) && sample.Y >= 0 && sample.Y <= Rooms.GetUpperBound(1)) {// a is the room to be checked after making a move between rooms openHallBetween(wanderer, sample); wanderer = sample; working = false; } } else { b = -1; } } while (working); if (random.Next(0, 2) == 0) {//determine if the room should be open or a hall Rooms[wanderer.X, wanderer.Y].Opened = OPEN; } else { Rooms[wanderer.X, wanderer.Y].Opened = HALL; } } } while (i < j); Rooms[Start.X, Start.Y].Opened = OPEN; //Determine key rooms if (req == null || req.End != Enums.Acceptance.Always) { isDone = false; do { //determine ending room randomly x = random.Next(0, Rooms.GetUpperBound(0) + 1); y = random.Next(0, Rooms.GetUpperBound(1) + 1); if (Rooms[x, y].Opened == OPEN) { End = new DungeonPoint(x, y); //Console.WriteLine(x); isDone = true; } } while (!isDone); } Start = new DungeonPoint(-1, -1); if (req == null || req.Start != Enums.Acceptance.Always) { isDone = false; do { //determine starting room randomly x = random.Next(0, Rooms.GetUpperBound(0) + 1); y = random.Next(0, Rooms.GetUpperBound(1) + 1); if (Rooms[x, y].Opened == OPEN) { Start = new DungeonPoint(x, y); //Console.WriteLine(x); isDone = true; } } while (!isDone); } if (req != null) { isDone = false; for (int n = 0; n < 100; n++) { //determine chamber room randomly x = random.Next(0, Rooms.GetUpperBound(0) + 1); y = random.Next(0, Rooms.GetUpperBound(1) + 1); bool approved = true; //if the chamber cannot be on a start, and it picked the start if (req.Start == Enums.Acceptance.Never && Start.X == x && Start.Y == y) { approved = false; } //if the chamber cannot be on an end, and it picked the end if (req.End == Enums.Acceptance.Never && End.X == x && End.Y == y) { approved = false; } //if the chamber demands a certain setup, and it doesn't meet the setup if (req.TopAcceptance == Enums.Acceptance.Always) { if (y == 0 || !VHalls[x, y - 1].Open) approved = false; } else if (req.TopAcceptance == Enums.Acceptance.Never) { if (y > 0 && VHalls[x, y - 1].Open) approved = false; } if (req.BottomAcceptance == Enums.Acceptance.Always) { if (y == Rooms.GetUpperBound(1) || !VHalls[x, y].Open) approved = false; } else if (req.BottomAcceptance == Enums.Acceptance.Never) { if (y < Rooms.GetUpperBound(1) && VHalls[x, y].Open) approved = false; } if (req.LeftAcceptance == Enums.Acceptance.Always) { if (x == 0 || !HHalls[x - 1, y].Open) approved = false; } else if (req.LeftAcceptance == Enums.Acceptance.Never) { if (x > 0 && HHalls[x - 1, y].Open) approved = false; } if (req.RightAcceptance == Enums.Acceptance.Always) { if (x == Rooms.GetUpperBound(0) || !HHalls[x, y].Open) approved = false; } else if (req.RightAcceptance == Enums.Acceptance.Never) { if (x < Rooms.GetUpperBound(0) && HHalls[x, y].Open) approved = false; } if (Rooms[x, y].Opened == OPEN && approved) { //set chamber to the point Chamber = new DungeonPoint(x, y); //if start or end is on this point, set to this location if (End.X == -1 && End.Y == -1) { End = new DungeonPoint(x, y); } if (Start.X == -1 && Start.Y == -1) { Start = new DungeonPoint(x, y); } //Console.WriteLine(x); isDone = true; break; } } if (!isDone) { //chamber could not be placed; reroll start and end if they were set to -1 assuming that chamber was going to take care of it if (End.X == -1 && End.Y == -1) { isDone = false; do { //determine ending room randomly x = random.Next(0, Rooms.GetUpperBound(0) + 1); y = random.Next(0, Rooms.GetUpperBound(1) + 1); if (Rooms[x, y].Opened == OPEN) { End = new DungeonPoint(x, y); //Console.WriteLine(x); isDone = true; } } while (!isDone); } if (Start.X == -1 && Start.Y == -1) { isDone = false; do { //determine starting room randomly x = random.Next(0, Rooms.GetUpperBound(0) + 1); y = random.Next(0, Rooms.GetUpperBound(1) + 1); if (Rooms[x, y].Opened == OPEN) { Start = new DungeonPoint(x, y); //Console.WriteLine(x); isDone = true; } } while (!isDone); } } } // begin part 2, creating ASCII map //create rooms //Console.WriteLine("ROOMS:"); //Console.WriteLine(Chamber.X + "," + Chamber.Y); for (i = 0; i <= Rooms.GetUpperBound(0); i++) { for (j = 0; j <= Rooms.GetUpperBound(1); j++) { if (Rooms[i, j].Opened != CLOSED && (Chamber.X != i || Chamber.Y != j)) { createRoom(i, j, options, req); } } } //Console.WriteLine(Chamber.X + "," + Chamber.Y); //create chamber if (Chamber.X > -1 && Chamber.Y > -1) { createChamber(options, req); } //Console.WriteLine("DRAW:"); for (i = 0; i <= Rooms.GetUpperBound(0); i++) { for (j = 0; j <= Rooms.GetUpperBound(1); j++) { if (Rooms[i, j].Opened != CLOSED) { drawRoom(i, j); } } } for (i = 0; i <= Rooms.GetUpperBound(0); i++) { for (j = 0; j <= Rooms.GetUpperBound(1); j++) { if (Rooms[i, j].Opened != CLOSED) { padSingleRoom(i, j); } } } //Console.WriteLine("HALLS:"); for (i = 0; i <= VHalls.GetUpperBound(0); i++) { for (j = 0; j <= VHalls.GetUpperBound(1); j++) { if (VHalls[i, j].Open) { createVHall(i, j, options, req); } } } for (i = 0; i <= HHalls.GetUpperBound(0); i++) { for (j = 0; j <= HHalls.GetUpperBound(1); j++) { if (HHalls[i, j].Open) { createHHall(i, j, options, req); } } } for (i = 0; i <= VHalls.GetUpperBound(0); i++) { for (j = 0; j <= VHalls.GetUpperBound(1); j++) { if (VHalls[i, j].Open) { DrawHalls(VHalls[i, j]); } } } for (i = 0; i <= HHalls.GetUpperBound(0); i++) { for (j = 0; j <= HHalls.GetUpperBound(1); j++) { if (HHalls[i, j].Open) { DrawHalls(HHalls[i, j]); } } } // create halls //for (i = 0; i < 12; i++) { // if (VHalls[i] == OPEN) { // createVHall(i, options); // } // if (HHalls[i] == OPEN) { // createHHall(i, options); // } //} //Console.WriteLine("SE:"); if (Start.X != Chamber.X || Start.Y != Chamber.Y) { addSEpos(Start, START, req); } if (End.X != Chamber.X || End.Y != Chamber.Y) { addSEpos(End, END, req); } //Console.WriteLine("WATER:"); //add water DrawWater(options); DrawCraters(options); //Console.WriteLine("TRAPS:"); // add traps int finalTraps = random.Next(options.TrapMin, options.TrapMax + 1); if (finalTraps > 0) { for (i = 0; i < finalTraps; i++) { // add traps for (j = 0; j < 200; j++) { a = random.Next(0, Rooms.GetUpperBound(0) + 1); b = random.Next(0, Rooms.GetUpperBound(1) + 1); x = random.Next(Rooms[a, b].StartX, Rooms[a, b].EndX + 1); y = random.Next(Rooms[a, b].StartY, Rooms[a, b].EndY + 1); if (Rooms[a, b].Opened == OPEN && MapArray[x, y] == GROUND) { MapArray[x, y] = TRAPTILE; break; } } } } //if (options.TrapFrequency > 0 && options.TrapMax > 0) { // for (i = options.TrapMin; i < options.TrapMax; i++) { // if (random.Next(0, 100) + 1 >= options.TrapFrequency) { // then generate a trap // a = random.Next(0, 16); // convertRoomToXY(a, ref x, ref y); // x = x + 1 + (random.Next(0, 6)); // y = y + 1 + (random.Next(0, 5)); // if (mapArray[y, x] == '.') { // mapArray[y, x] = 'Q'; // } // } // } //} //Console.WriteLine("ITEMS:"); // generate items (up to 16) ~moved to its own method //for (i = 0; i < 16; i++) { //bool success = false; // for (int k = 0; k < 200; k++) { // do until you succeed // a = random.Next(0, 16); //convertRoomToXY(a, ref x, ref y); // x = random.Next(room[a,1], room[a,3]+1); // y = random.Next(room[a,2], room[a,4]+1); // if (mapArray[y, x] == '.' /* mapArray[y, x] != 'S' && mapArray[y, x] != 'E' && // mapArray[y, x] != ' '*/) { // mapArray[y, x] = (char)(96 + i); //ascii for lowercase letters // break; // } // } //} //return MapArray; }
void openHallBetween(DungeonPoint room1, DungeonPoint room2) { if (room1.X == room2.X) { int d = room2.Y - room1.Y; if (d == 1) { VHalls[room1.X, room1.Y].Open = true; } else if (d == -1) { VHalls[room2.X, room2.Y].Open = true; } } else if (room1.Y == room2.Y) { int d = room2.X - room1.X; if (d == 1) { HHalls[room1.X, room1.Y].Open = true; } else if (d == -1) { HHalls[room2.X, room2.Y].Open = true; } } //if (room2 < room1) { // int temp = room1; // room1 = room2; // room2 = temp; //} //if (room2 - room1 == 1) { //horizontal // x = room2 / 4; // hhall[room1 - x] = OPEN; //} else { //vertical // vhall[room1] = OPEN; //} }
void createChamber(GeneratorOptions options, RDungeonChamberReq req) { int x = 0, y = 0, u = 0, v = 0, w, l; // variables used for position convertRoomToXY(Chamber.X, Chamber.Y, ref x, ref y); int roomX = Chamber.X; int roomY = Chamber.Y; bool eclipse = true; int iterations = 100; if (req.MinX == req.MaxX && req.MinY == req.MaxY) { iterations = 1; } for (int k = 0; k < iterations && eclipse == true; k++) { //Determine room length/width //chamber cannot be a hall w = random.Next(req.MinX, req.MaxX + 1) - 1; l = random.Next(req.MinY, req.MaxY + 1) - 1; if (w < 1) w = 1; if (l < 1) l = 1; if (w > 47) w = 47; if (l > 47) l = 47; //move X and Y to a random starting point that still would include the original x/y; exceptional case for l/w under or equal to 6 if (w <= 6) { x -= (random.Next(0, (13 - w)) + w - 7); } else { x -= random.Next(0, w + 1); } if (l <= 6) { y -= (random.Next(0, (13 - l)) + l - 7); } else { y -= random.Next(0, l + 1); } if (x < 1) x = 1; if ((x + w) > 48) x = (48 - w); if (y < 1) y = 1; if ((y + l) > 48) y = (48 - l); // once we have our room coords, render it on the map u = x + w; v = y + l; eclipse = false; if (req.Start == Enums.Acceptance.Never || req.End == Enums.Acceptance.Never) {//if we're dealing with a chamber with no tolerance to entrances/exits for (int i = 0; i <= Rooms.GetUpperBound(0); i++) { for (int j = 0; j <= Rooms.GetUpperBound(1); j++) { if (Chamber.X != i || Chamber.Y != j) {//if the room not is this room if (doesBigRoomEclipseSmallRoom(x, y, u, v, Rooms[i, j].StartX, Rooms[i, j].StartY, Rooms[i, j].EndX, Rooms[i, j].EndY)) { if (req.Start == Enums.Acceptance.Never && Start.X == i && Start.Y == j) { eclipse = true; } if (req.End == Enums.Acceptance.Never && End.X == i && End.Y == j) { eclipse = true; } } } } } } } if (eclipse) { //the chamber has eclipsed a start/end room; it can't stay Chamber = new DungeonPoint(-1, -1); //reroll everything w = random.Next(options.RoomWidthMin, options.RoomWidthMax + 1) - 1; l = random.Next(options.RoomLengthMin, options.RoomLengthMax + 1) - 1; if (w < 1) w = 1; if (l < 1) l = 1; if (w > 47) w = 47; if (l > 47) l = 47; //move X and Y to a random starting point that still would include the original x/y; exceptional case for l/w under or equal to 6 if (w <= 6) { x -= (random.Next(0, (13 - w)) + w - 7); } else { x -= random.Next(0, w + 1); } if (l <= 6) { y -= (random.Next(0, (13 - l)) + l - 7); } else { y -= random.Next(0, l + 1); } if (x < 1) x = 1; if ((x + w) > 48) x = (48 - w); if (y < 1) y = 1; if ((y + l) > 48) y = (48 - l); // once we have our room coords, render it on the map u = x + w; v = y + l; } for (int i = 0; i <= Rooms.GetUpperBound(0); i++) { for (int j = 0; j <= Rooms.GetUpperBound(1); j++) { if ((roomX == i && roomY == j) ||//if the room is this room doesBigRoomEclipseSmallRoom(x, y, u, v, Rooms[i, j].StartX, Rooms[i, j].StartY, Rooms[i, j].EndX, Rooms[i, j].EndY)) { Rooms[i, j].StartX = x; Rooms[i, j].StartY = y; Rooms[i, j].EndX = u; Rooms[i, j].EndY = v; } } } // done }
void DrawHall(DungeonPoint point1, DungeonPoint point2, ref bool addedEntrance) { if (point1.X == point2.X) { if (point2.Y > point1.Y) { for (int i = point1.Y; i <= point2.Y; i++) { DrawHallTile(point1.X, i, ref addedEntrance); } } else if (point2.Y < point1.Y) { for (int i = point1.Y; i >= point2.Y; i--) { DrawHallTile(point1.X, i, ref addedEntrance); } } } else if (point1.Y == point2.Y) { if (point2.X > point1.X) { for (int i = point1.X; i <= point2.X; i++) { DrawHallTile(i, point1.Y, ref addedEntrance); } } else if (point2.X < point1.X) { for (int i = point1.X; i >= point2.X; i--) { DrawHallTile(i, point1.Y, ref addedEntrance); } } } }
void addSEpos(DungeonPoint point, int type, RDungeonChamberReq req) { //Console.WriteLine("SE Added: " + type); int x = 0, y = 0, u = 0, v = 0; int c; if (type == START) c = STARTTILE; else c = ENDTILE; //convertRoomToXY(roomNum, ref x, ref y); x = Rooms[point.X, point.Y].StartX; y = Rooms[point.X, point.Y].StartY; u = Rooms[point.X, point.Y].EndX; v = Rooms[point.X, point.Y].EndY; //Console.WriteLine(roomNum + " " + type); //bool done = false; int randx = 0, randy = 0; for (int i = 0; i < 200; i++) { bool approved = true; randx = random.Next(x, u + 1); randy = random.Next(y, v + 1); //Console.WriteLine(x + "," + y + "," + u + "," + v); if (MapArray[randx, randy] != GROUND) { approved = false; } if (Chamber.X > -1 && Chamber.Y > -1) { if (randx >= Rooms[Chamber.X, Chamber.Y].StartX && randx <= Rooms[Chamber.X, Chamber.Y].EndX && randy >= Rooms[Chamber.X, Chamber.Y].StartY && randy <= Rooms[Chamber.X, Chamber.Y].EndY) { //if the start or end was picked to be inside a chamber if (type == START) { if (req.Start == Enums.Acceptance.Never) { approved = false; } else { //the chamber is okay with having a START inside it Start = new DungeonPoint(Chamber.X, Chamber.Y); return; } } else { if (req.End == Enums.Acceptance.Never) { approved = false; } else { //the chamber is okay with having a End inside it End = new DungeonPoint(Chamber.X, Chamber.Y); return; } } } } if (approved) { MapArray[randx, randy] = c; return; } } while (true) {//backup plan in case rooms are so small that all there's left is halls and doors bool approved = true; randx = random.Next(x, u + 1); randy = random.Next(y, v + 1); //Console.WriteLine(x + "," + y + "," + u + "," + v); if (MapArray[randx, randy] != HALLTILE && MapArray[randx, randy] != DOORTILE && MapArray[randx, randy] != GROUND) { approved = false; } if (Chamber.X > -1 && Chamber.Y > -1) { if (randx >= Rooms[Chamber.X, Chamber.Y].StartX && randx <= Rooms[Chamber.X, Chamber.Y].EndX && randy >= Rooms[Chamber.X, Chamber.Y].StartY && randy <= Rooms[Chamber.X, Chamber.Y].EndY) { //if the start or end was picked to be inside a chamber if (type == START) { if (req.Start == Enums.Acceptance.Never) { approved = false; } else { //the chamber is okay with having a START inside it Start = new DungeonPoint(Chamber.X, Chamber.Y); return; } } else { if (req.End == Enums.Acceptance.Never) { approved = false; } else { //the chamber is okay with having a End inside it End = new DungeonPoint(Chamber.X, Chamber.Y); return; } } } } if (approved) { MapArray[randx, randy] = c; return; } } }