-
Notifications
You must be signed in to change notification settings - Fork 0
/
Map.cs
407 lines (367 loc) · 14.7 KB
/
Map.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Binding_of_Isaac_console
{
class Map
{
public List<Room> Rooms { get; private set; }
public int YMax { get; private set; }
public int XMax { get; private set; }
public Map() { }
public Map(List<Room> rooms)
{
Rooms = rooms;
}
/// <summary>
/// Returns a randomized new map with numRooms amount of rooms
/// (numRooms must be greater than or equal to 15)
/// </summary>
/// <param name="numRooms"></param>
/// <returns></returns>
public static Map GenerateNewMap(int numRooms)
{
if (numRooms < 10)
{
throw new Exception("Please generate a map with at least 10 rooms.");
}
else if (numRooms > 50)
{
throw new Exception("Please generate a map with no more than 50 rooms.");
}
else
{
List<Room> rooms;
Map newMap;
int[] tempLocation = new int[2];
do
{
rooms = new List<Room>();
rooms.Add(new BossRoom(NewLocation(rooms)));
for (int i = 0; i < numRooms - 4; i++)
{
do
{
tempLocation = NewLocation(rooms);
} while (MakesABox(rooms, tempLocation));
rooms.Add(new NormRoom(NewLocation(rooms)));
}
rooms.Add(new ItemRoom(NewLocation(rooms)));
rooms.Add(new SuperSecretRoom(NewLocation(rooms)));
rooms.Add(new SecretRoom(NewLocation(rooms)));
int minY = GetMinY(rooms), minX = GetMinX(rooms);
foreach (Room r in rooms)
{
r.Coordinates[0] -= minY;
r.Coordinates[1] -= minX;
}
newMap = new Map(rooms);
} while (!IsGoodMap(newMap));
newMap.YMax = GetMaxY(rooms);
newMap.XMax = GetMaxX(rooms);
return newMap;
}
}
/// <summary>
/// Prints an ASCII representation of map to console (N = normal room, I = item room,
/// B = boss room, S = secret room, U = super secret room)
/// </summary>
/// <param name="map"></param>
public static void ShowMap(Map map)
{
for (int i = 0; i <= map.YMax; i++)
{
for (int j = 0; j <= map.XMax; j++)
{
if (!map.Rooms.Exists(e => e.Coordinates[0] == i && e.Coordinates[1] == j))
{
Console.Write(" ");
}
else if (map.Rooms.Exists(e => e.Coordinates[0] == i && e.Coordinates[1] == j && e.HasBoss))
{
Console.Write("B");
}
else if (map.Rooms.Exists(e => e.Coordinates[0] == i && e.Coordinates[1] == j && e.IsItemRoom))
{
Console.Write("I");
}
else if (map.Rooms.Exists(e => e.Coordinates[0] == i && e.Coordinates[1] == j && e.IsSecret))
{
Console.Write("S");
}
else if (map.Rooms.Exists(e => e.Coordinates[0] == i && e.Coordinates[1] == j && e.IsSuperSecret))
{
Console.Write("U");
}
else
{
Console.Write("N");
}
}
Console.WriteLine();
}
}
/// <summary>
/// Returns a valid set of coordinates adjacent to a random existing room
/// (returns coordinates { 0, 0 } when there are no existing rooms)
/// </summary>
/// <param name="existingRooms"></param>
/// <returns></returns>
private static int[] NewLocation(List<Room> existingRooms)
{
Random rng = new Random();
int directionalRng, roomRng;
int[] newCoord = new int[2] { 0, 0 };
if (existingRooms.Count > 0)
{
do
{
directionalRng = rng.Next(4);
roomRng = rng.Next(existingRooms.Count);
newCoord[0] = existingRooms[roomRng].Coordinates[0];
newCoord[1] = existingRooms[roomRng].Coordinates[1];
if (directionalRng == 0)
{
newCoord[0] += 1;
}
else if (directionalRng == 1)
{
newCoord[0] -= 1;
}
else if (directionalRng == 2)
{
newCoord[1] += 1;
}
else
{
newCoord[1] -= 1;
}
} while (!IsValid(existingRooms, newCoord));
}
return newCoord;
}
/// <summary>
/// Returns a boolean indicating whether testCoord is a
/// valid location for a new room to be spawned
/// </summary>
/// <param name="rooms"></param>
/// <param name="testCoord"></param>
/// <returns></returns>
private static bool IsValid(List<Room> rooms, int[] testCoord)
{
foreach (Room r in rooms)
{
//Tests to make sure testCoord doesn't have the same coordinates as an existing room
if (testCoord[0] == r.Coordinates[0] && testCoord[1] == r.Coordinates[1])
{
return false;
}
//Tests to make sure testCoord isn't adjacent to a boss room that
//already has at least one other room adjacent to it
else if (IsAdjacentTo(r.Coordinates, testCoord) && r.HasBoss
&& AdjacentTo(rooms, r.Coordinates).Count >= 1)
{
return false;
}
//Tests to make sure testCoord isn't adjacent to a super secret room that
//already has at least one other room adjacent to it
else if (IsAdjacentTo(r.Coordinates, testCoord) && r.IsSuperSecret
&& AdjacentTo(rooms, r.Coordinates).Count >= 1)
{
return false;
}
//Tests to make sure testCoord isn't adjacent to an item room when
//the item room already has at least two rooms, including a secret room,
//adjacent to it.
else if (IsAdjacentTo(r.Coordinates, testCoord) && r.IsItemRoom
&& AdjacentTo(rooms, r.Coordinates).Exists(e => e.IsSecret == true)
&& AdjacentTo(rooms, r.Coordinates).Count >= 2)
{
return false;
}
//Tests to make sure there are no 2x2 orientations of normal rooms
/*else if (MakesABox(rooms, testCoord))
{
return false;
}*/
}
return true;
}
private static bool IsGoodMap(Map map)
{
//Tests to make sure the super secret room only spawns adjacent to at most one room
if (map.Rooms.Exists(e => e.IsSuperSecret &&
AdjacentTo(map.Rooms, e.Coordinates).Count > 1))
{
return false;
}
//Tests to make sure the super secret room cannot be adjacent to the
//item room or the regular secret room
else if (map.Rooms.Exists(e => e.IsSuperSecret &&
AdjacentTo(map.Rooms, e.Coordinates).Exists(f => f.IsItemRoom || f.IsSecret)))
{
return false;
}
//Tests to make sure the item room cannot spawn adjacent to more than one normal room
else if (map.Rooms.Exists(e => e.IsItemRoom &&
AdjacentTo(map.Rooms, e.Coordinates).Where(f => f.IsNormRoom).Count() > 1))
{
return false;
}
//Tests to make sure the secret room must spawn adjacent to at least two rooms
else if (map.Rooms.Exists(e => e.IsSecret && AdjacentTo(map.Rooms, e.Coordinates).Count() <= 1))
{
return false;
}
return true;
}
/// <summary>
/// Returns a boolean indicating whether coord1 is adjacent to coord2
/// </summary>
/// <param name="coord1"></param>
/// <param name="coord2"></param>
/// <returns></returns>
private static bool IsAdjacentTo(int[] coord1, int[] coord2)
{
if (coord1[0] == coord2[0] && coord1[1] == coord2[1] + 1)
{
return true;
}
else if (coord1[0] == coord2[0] && coord1[1] == coord2[1] - 1)
{
return true;
}
else if (coord1[0] == coord2[0] + 1 && coord1[1] == coord2[1])
{
return true;
}
else if (coord1[0] == coord2[0] - 1 && coord1[1] == coord2[1])
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// Returns a list of all rooms adjacent to coord
/// </summary>
/// <param name="rooms"></param>
/// <param name="coord"></param>
/// <returns></returns>
private static List<Room> AdjacentTo(List<Room> rooms, int[] coord)
{
List<Room> adjRooms = new List<Room>();
foreach (Room r in rooms)
{
if (IsAdjacentTo(r.Coordinates, coord))
{
adjRooms.Add(r);
}
}
return adjRooms;
}
/// <summary>
/// Returns the minimum y-value of all coordinate pairs in rooms
/// </summary>
/// <param name="rooms"></param>
/// <returns></returns>
private static int GetMinY(List<Room> rooms)
{
List<int> yValues = new List<int>();
foreach (Room r in rooms)
{
yValues.Add(r.Coordinates[0]);
}
return yValues.Min();
}
/// <summary>
/// Returns the minimum x-value of all coordinate pairs in rooms
/// </summary>
/// <param name="rooms"></param>
/// <returns></returns>
private static int GetMinX(List<Room> rooms)
{
List<int> xValues = new List<int>();
foreach (Room r in rooms)
{
xValues.Add(r.Coordinates[1]);
}
return xValues.Min();
}
/// <summary>
/// Returns the maximum y-value of all coordinate pairs in rooms
/// </summary>
/// <param name="rooms"></param>
/// <returns></returns>
private static int GetMaxY(List<Room> rooms)
{
List<int> yValues = new List<int>();
foreach (Room r in rooms)
{
yValues.Add(r.Coordinates[0]);
}
return yValues.Max();
}
/// <summary>
/// Returns the maximum x-value of all coordinate pairs in rooms
/// </summary>
/// <param name="rooms"></param>
/// <returns></returns>
private static int GetMaxX(List<Room> rooms)
{
List<int> xValues = new List<int>();
foreach (Room r in rooms)
{
xValues.Add(r.Coordinates[1]);
}
return xValues.Max();
}
/// <summary>
/// Returns a boolean indicating whether a room placed at coords will
/// form a 2x2 box with other normal rooms
/// </summary>
/// <param name="allRooms"></param>
/// <param name="coords"></param>
/// <returns></returns>
private static bool MakesABox(List<Room> allRooms, int[] coords)
{
int[] roomS = new int[2] { coords[0] + 1, coords[1] };
int[] roomE = new int[2] { coords[0], coords[1] + 1};
int[] roomSE = new int[2] { coords[0] + 1, coords[1] + 1 };
int[] roomN = new int[2] { coords[0] - 1, coords[1] };
int[] roomW = new int[2] { coords[0], coords[1] - 1 };
int[] roomNW = new int[2] { coords[0] - 1, coords[1] - 1 };
int[] roomNE = new int[2] { coords[0] - 1, coords[1] + 1 };
int[] roomSW = new int[2] { coords[0] + 1, coords[1] - 1 };
if (allRooms.Exists(e => e.Coordinates[0] == roomS[0] && e.Coordinates[1] == roomS[1] && e.IsNormRoom)
&& allRooms.Exists(e => e.Coordinates[0] == roomE[0] && e.Coordinates[1] == roomE[1] && e.IsNormRoom)
&& allRooms.Exists(e => e.Coordinates[0] == roomSE[0] && e.Coordinates[1] == roomSE[1] && e.IsNormRoom))
{
return true;
}
else if (allRooms.Exists(e => e.Coordinates[0] == roomS[0] && e.Coordinates[1] == roomS[1] && e.IsNormRoom)
&& allRooms.Exists(e => e.Coordinates[0] == roomW[0] && e.Coordinates[1] == roomW[1] && e.IsNormRoom)
&& allRooms.Exists(e => e.Coordinates[0] == roomSW[0] && e.Coordinates[1] == roomSW[1] && e.IsNormRoom))
{
return true;
}
else if (allRooms.Exists(e => e.Coordinates[0] == roomN[0] && e.Coordinates[1] == roomN[1] && e.IsNormRoom)
&& allRooms.Exists(e => e.Coordinates[0] == roomW[0] && e.Coordinates[1] == roomW[1] && e.IsNormRoom)
&& allRooms.Exists(e => e.Coordinates[0] == roomNW[0] && e.Coordinates[1] == roomNW[1] && e.IsNormRoom))
{
return true;
}
else if (allRooms.Exists(e => e.Coordinates[0] == roomN[0] && e.Coordinates[1] == roomN[1] && e.IsNormRoom)
&& allRooms.Exists(e => e.Coordinates[0] == roomE[0] && e.Coordinates[1] == roomE[1] && e.IsNormRoom)
&& allRooms.Exists(e => e.Coordinates[0] == roomNE[0] && e.Coordinates[1] == roomNE[1] && e.IsNormRoom))
{
return true;
}
return false;
}
}
}