~ubuntu-branches/ubuntu/utopic/meritous/utopic

« back to all changes in this revision

Viewing changes to src/mapgen.c

  • Committer: Bazaar Package Importer
  • Author(s): Dylan R. E. Moonfire
  • Date: 2008-02-11 13:45:02 UTC
  • Revision ID: james.westby@ubuntu.com-20080211134502-8o235kfyej0lrag8
Tags: upstream-1.2+dfsg
ImportĀ upstreamĀ versionĀ 1.2+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
//   mapgen.c
 
3
//
 
4
//   Copyright 2007, 2008 Lancer-X/ASCEAI
 
5
//
 
6
//   This file is part of Meritous.
 
7
//
 
8
//   Meritous is free software: you can redistribute it and/or modify
 
9
//   it under the terms of the GNU General Public License as published by
 
10
//   the Free Software Foundation, either version 3 of the License, or
 
11
//   (at your option) any later version.
 
12
//
 
13
//   Meritous is distributed in the hope that it will be useful,
 
14
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
//   GNU General Public License for more details.
 
17
//
 
18
//   You should have received a copy of the GNU General Public License
 
19
//   along with Meritous.  If not, see <http://www.gnu.org/licenses/>.
 
20
//
 
21
 
 
22
#include <stdio.h>
 
23
#include <stdlib.h>
 
24
#include <string.h>
 
25
#include <math.h>
 
26
#include <time.h>
 
27
#include <assert.h>
 
28
 
 
29
#include <SDL.h>
 
30
#include "save.h"
 
31
#include "levelblit.h"
 
32
 
 
33
void NewLevel();
 
34
        
 
35
void SaveLevel();
 
36
 
 
37
int Generate();
 
38
 
 
39
int DoRepeat = 0;
 
40
 
 
41
int place_of_power = 0;
 
42
 
 
43
struct RoomConnection {
 
44
        int x, y;
 
45
        int x2, y2;
 
46
        int c;
 
47
        struct RoomConnection *n;
 
48
};
 
49
 
 
50
typedef struct {
 
51
        int x, y;
 
52
        int w, h;
 
53
        int creator;
 
54
        int visited;
 
55
        int checkpoint;
 
56
        int s_dist;
 
57
        int connections;
 
58
        int room_type;
 
59
        int room_param;
 
60
        int enemies;
 
61
        struct RoomConnection *con;
 
62
} Room;
 
63
 
 
64
typedef struct {
 
65
        int w, h;
 
66
        unsigned char *m;
 
67
        int *r;
 
68
        int totalRooms;
 
69
        //Room *rooms;
 
70
} GameLevel;
 
71
 
 
72
GameLevel map;
 
73
Room rooms[3000];
 
74
int total_rooms = 0;
 
75
 
 
76
int rdir = 0;
 
77
 
 
78
int next_check = 30;
 
79
 
 
80
int GetRoom(int x, int y);
 
81
 
 
82
int rndnum(int max)
 
83
{
 
84
        return rand() % (max+1);
 
85
}
 
86
 
 
87
int r_fails[4] = {0};
 
88
int r_successes[4] = {0};
 
89
 
 
90
unsigned char floortiles[4] = {12, 18, 19, 20};
 
91
 
 
92
void WriteRoomData(Room *rm)
 
93
{
 
94
        struct RoomConnection *rt;
 
95
        FWInt(rm->x);
 
96
        FWInt(rm->y);
 
97
        FWInt(rm->w);
 
98
        FWInt(rm->h);
 
99
        FWInt(rm->creator);
 
100
        FWInt(rm->visited);
 
101
        FWInt(rm->checkpoint);
 
102
        FWInt(rm->s_dist);
 
103
        FWInt(rm->connections);
 
104
        FWInt(rm->room_type);
 
105
        FWInt(rm->room_param);
 
106
        rt = rm->con;
 
107
        while (rt != NULL) {
 
108
                FWInt(rt->x);
 
109
                FWInt(rt->y);
 
110
                FWInt(rt->x2);
 
111
                FWInt(rt->y2);
 
112
                FWInt(rt->c);
 
113
                rt = rt->n;
 
114
        }
 
115
}
 
116
 
 
117
void ReadRoomData(Room *rm)
 
118
{
 
119
        int i;
 
120
        struct RoomConnection *rt;
 
121
        
 
122
        rm->x = FRInt();
 
123
        rm->y = FRInt();
 
124
        rm->w = FRInt();
 
125
        rm->h = FRInt();
 
126
        rm->creator = FRInt();
 
127
        rm->visited = FRInt();
 
128
        rm->checkpoint = FRInt();
 
129
        rm->s_dist = FRInt();
 
130
        rm->connections = FRInt();
 
131
        rm->room_type = FRInt();
 
132
        rm->room_param = FRInt();
 
133
        
 
134
        rm->con = NULL;
 
135
        
 
136
        rm->enemies = 0;
 
137
        
 
138
        for (i = 0; i < rm->connections; i++) {
 
139
                rt = rm->con;
 
140
                rm->con = malloc(sizeof(struct RoomConnection));
 
141
                rm->con->x = FRInt();
 
142
                rm->con->y = FRInt();
 
143
                rm->con->x2 = FRInt();
 
144
                rm->con->y2 = FRInt();
 
145
                rm->con->c = FRInt();
 
146
                rm->con->n = rt;
 
147
        }
 
148
}
 
149
 
 
150
void WriteMapData()
 
151
{
 
152
        int i;
 
153
 
 
154
        FWInt(map.w);
 
155
        FWInt(map.h);
 
156
        FWInt(map.totalRooms);
 
157
        FWInt(place_of_power);
 
158
        for (i = 0; i < map.w*map.h; i++) {
 
159
                FWChar(map.m[i]);
 
160
                FWInt(map.r[i]);
 
161
                if ((i % 7447) == 7446) {
 
162
                        SavingScreen(0, (float)i / (float)(map.w*map.h));
 
163
                }
 
164
        }
 
165
        for (i = 0; i < map.totalRooms; i++) {
 
166
                WriteRoomData(&rooms[i]);
 
167
                if ((i % 85)==84) {
 
168
                        SavingScreen(1, (float)i / (float)map.totalRooms);
 
169
                }
 
170
        }
 
171
}
 
172
 
 
173
void ReadMapData()
 
174
{
 
175
        int i;
 
176
 
 
177
        map.w = FRInt();
 
178
        map.h = FRInt();
 
179
        map.totalRooms = total_rooms = FRInt();
 
180
        place_of_power = FRInt();
 
181
        for (i = 0; i < map.w*map.h; i++) {
 
182
                if ((i % 7447) == 7446) {
 
183
                        LoadingScreen(0, (float)i / (float)(map.w*map.h));
 
184
                }
 
185
                map.m[i] = FRChar();
 
186
                map.r[i] = FRInt();
 
187
        }
 
188
        LoadingScreen(0, 1);
 
189
        for (i = 0; i < map.totalRooms; i++) {
 
190
                ReadRoomData(&rooms[i]);
 
191
                if ((i % 85)==84) {
 
192
                        LoadingScreen(1, (float)i / (float)map.totalRooms);
 
193
                }
 
194
        }
 
195
        LoadingScreen(1, 1);
 
196
}
 
197
 
 
198
int rndval(int a, int b)
 
199
{
 
200
        int temp;
 
201
        
 
202
        if (a == b) {
 
203
                return a;
 
204
        }
 
205
        
 
206
        if (b < a) {
 
207
                temp = a;
 
208
                a = b;
 
209
                b = temp;
 
210
        }
 
211
        
 
212
        temp = rndnum(b - a);
 
213
        
 
214
        return temp + a;
 
215
}
 
216
 
 
217
void RandomGenerateMap()
 
218
{
 
219
        int trying = 1;
 
220
        if (game_load) {
 
221
                NewLevel();
 
222
                ReadMapData();
 
223
        } else {
 
224
                NewLevel();
 
225
                while (trying) {
 
226
                
 
227
                        trying = !Generate();
 
228
                }
 
229
        }
 
230
        //SaveLevel();
 
231
}
 
232
 
 
233
void NewLevel()
 
234
{
 
235
        int x, y;
 
236
        unsigned char *map_p;
 
237
        
 
238
        map.w = 512;
 
239
        map.h = 512;
 
240
        
 
241
        map.m = malloc(map.w * map.h * sizeof(unsigned char));
 
242
        map.r = malloc(map.w * map.h * sizeof(int));
 
243
        map_p = map.m;
 
244
        
 
245
        for (y = 0; y < map.h; y++) {
 
246
                for (x = 0; x < map.w; x++) {
 
247
                        *(map_p++) = 17;
 
248
                        map.r[y*map.w+x] = -1;
 
249
                }
 
250
        }
 
251
}
 
252
 
 
253
void DestroyDungeon()
 
254
{
 
255
        int i;
 
256
        struct RoomConnection *c, *d;
 
257
        
 
258
        // Destroy map
 
259
        free(map.m);
 
260
        free(map.r);
 
261
        
 
262
        // Destroy rooms
 
263
        for (i = 0; i < total_rooms; i++) {
 
264
                c = rooms[i].con;
 
265
                while (c != NULL) {
 
266
                        d = c;
 
267
                        c = c->n;
 
268
                        free(d);
 
269
                }
 
270
        }
 
271
        total_rooms = 0;
 
272
}
 
273
 
 
274
void ResetLevel()
 
275
{
 
276
        int x, y;
 
277
        unsigned char *map_p;
 
278
        
 
279
        map.w = 512;
 
280
        map.h = 512;
 
281
        map_p = map.m;
 
282
        
 
283
        total_rooms = 0;
 
284
 
 
285
        rdir = 0;
 
286
 
 
287
        next_check = 30;
 
288
        
 
289
        for (y = 0; y < map.h; y++) {
 
290
                for (x = 0; x < map.w; x++) {
 
291
                        *(map_p++) = 17;
 
292
                        map.r[y*map.w+x] = -1;
 
293
                }
 
294
        }
 
295
}
 
296
 
 
297
void SaveLevel()
 
298
{
 
299
        int x, y, i;
 
300
        SDL_Surface *map_surf;
 
301
        char cs[2] = ".";
 
302
        char rnum[5] = "0000";
 
303
        unsigned char ch;
 
304
        unsigned char *map_p;
 
305
        SDL_Color cpalette[4];
 
306
        Uint8 cl;
 
307
        
 
308
        map_surf = SDL_CreateRGBSurface(0, 4096, 4096, 8, 0, 0, 0, 0);
 
309
        
 
310
        map_p = map.m;
 
311
        
 
312
        cpalette[0].r = cpalette[0].g = cpalette[0].b = 0;
 
313
        cpalette[1].r = cpalette[1].g = cpalette[1].b = 255;
 
314
        cpalette[2].r = 255; cpalette[2].g = 0; cpalette[2].b = 255;
 
315
        cpalette[3].r = 0; cpalette[3].g = 255; cpalette[3].b = 128;
 
316
        
 
317
        SDL_SetPalette(map_surf, SDL_LOGPAL | SDL_PHYSPAL, cpalette, 0, 4);
 
318
        
 
319
        for (y = 0; y < map.h; y++) {
 
320
                for (x = 0; x < map.w; x++) {
 
321
                        ch = *(map_p++);
 
322
                        
 
323
                        if (IsSolid(ch))
 
324
                                *cs = 4;
 
325
                        else
 
326
                                *cs = 5;
 
327
                                
 
328
                        if (ch == 17)
 
329
                                *cs = 0;
 
330
                                
 
331
                        cl = 1;
 
332
                        if (rooms[GetRoom(x, y)].room_type == 2) cl = 2;
 
333
                        if (rooms[GetRoom(x, y)].room_type == 3) cl = 3;
 
334
                        
 
335
                        draw_text_ex(x*8, y*8, cs, cl, map_surf);
 
336
                }
 
337
        }
 
338
        for (i = 0; i < 3000; i++) {
 
339
                sprintf(rnum, "%d", i);
 
340
                draw_text_ex(rooms[i].x * 8, rooms[i].y * 8, rnum, 0, map_surf);
 
341
        }
 
342
        
 
343
        SDL_SaveBMP(map_surf, "map.bmp");
 
344
}
 
345
 
 
346
void CreateRoomDimensions(int *w, int *h)
 
347
{
 
348
        *w = rndval(5, 12);
 
349
        *h = rndval(5, 12);
 
350
        
 
351
        if (*w == 12) {
 
352
                *w = rndval(12, 15);
 
353
        }
 
354
        if (*h == 12) {
 
355
                *h = rndval(12, 15);
 
356
        }
 
357
}
 
358
 
 
359
void Put(int x, int y, unsigned char tile, int room)
 
360
{
 
361
        map.m[map.w*y+x] = tile;
 
362
        map.r[map.w*y+x] = room;
 
363
}
 
364
 
 
365
unsigned char Get(int x, int y)
 
366
{
 
367
        if (x < 0) return 17;
 
368
        if (y < 0) return 17;
 
369
        if (x >= map.w) return 17;
 
370
        if (y >= map.h) return 17;
 
371
        
 
372
        return map.m[map.w*y+x];
 
373
}
 
374
 
 
375
int GetRoom(int x, int y)
 
376
{
 
377
        if (x < 0) return -1;
 
378
        if (y < 0) return -1;
 
379
        if (x >= map.w) return -1;
 
380
        if (y >= map.h) return -1;
 
381
        
 
382
        return map.r[map.w*y+x];
 
383
}
 
384
 
 
385
int GetVisited(int x, int y)
 
386
{
 
387
        if (x < 0) return 0;
 
388
        if (y < 0) return 0;
 
389
        if (x >= map.w) return 0;
 
390
        if (y >= map.h) return 0;
 
391
        
 
392
        return rooms[GetRoom(x, y)].visited;
 
393
}
 
394
 
 
395
void Paint(int xp, int yp, int w, int h, char *fname)
 
396
{
 
397
        FILE *fp;
 
398
        int x, y;
 
399
        fp = fopen(fname, "rb");
 
400
        
 
401
        for (y = 0; y < h; y++) {
 
402
                for (x = 0; x < w; x++) {
 
403
                        Put(x+xp, y+yp, fgetc(fp), GetRoom(x+xp, y+yp));
 
404
                }
 
405
        }
 
406
        fclose(fp);
 
407
}
 
408
 
 
409
void DrawRoom(int place_x, int place_y, int room_w, int room_h, int room_id)
 
410
{
 
411
        int x, y, i;
 
412
        int f_type;
 
413
        
 
414
        f_type = rand()%4;
 
415
        // Corners
 
416
        Put(place_x, place_y, 11, room_id);
 
417
        Put(place_x + room_w - 1, place_y, 10, room_id);
 
418
        Put(place_x, place_y + room_h - 1, 9, room_id);
 
419
        Put(place_x + room_w - 1, place_y + room_h - 1, 8, room_id);
 
420
        
 
421
        // Walls
 
422
        
 
423
        for (i = 0; i < room_w - 2; i++) {
 
424
                Put(place_x + 1 + i, place_y + room_h - 1, 4, room_id);
 
425
                if (rand() % 16 == 0) Put(place_x + 1 + i, place_y + room_h - 1, 45 + (rand()%2)*4, room_id);
 
426
                Put(place_x + 1 + i, place_y, 5, room_id);
 
427
                if (rand() % 16 == 0) Put(place_x + 1 + i, place_y, 46 + (rand()%2)*4, room_id);
 
428
        }
 
429
        for (i = 0; i < room_h - 2; i++) {
 
430
                Put(place_x + room_w - 1, place_y + 1 + i, 6, room_id);
 
431
                if (rand() % 16 == 0) Put(place_x + room_w - 1, place_y + 1 + i, 47 + (rand()%2)*4, room_id);
 
432
                Put(place_x, place_y + 1 + i, 7, room_id);
 
433
                if (rand() % 16 == 0) Put(place_x, place_y + 1 + i, 48 + (rand()%2)*4, room_id);
 
434
        }
 
435
        
 
436
        // Floor
 
437
        
 
438
        for (y = 0; y < room_h - 2; y++) {
 
439
                for (x = 0; x < room_w - 2; x++) {
 
440
                        Put(place_x + 1 + x, place_y + 1 + y, floortiles[f_type], room_id);
 
441
                }
 
442
        }
 
443
 
 
444
        // Magic Tiles
 
445
 
 
446
        if ((room_id % 30) == 29) {
 
447
                if (Get(place_x + 1 + rand()%(room_w-2), place_y + 1 + rand()%(room_h-2)) == floortiles[f_type]) {
 
448
                        Put(place_x + 1 + rand()%(room_w-2), place_y + 1 + rand()%(room_h-2), 28+rand()%3, room_id);
 
449
                }
 
450
        }
 
451
 
 
452
        // Save tiles
 
453
        
 
454
        if ((room_id % 25) == 20) {
 
455
                x = place_x + 1 + rand()%(room_w-2);
 
456
                y = place_y + 1 + rand()%(room_h-2);
 
457
                if (Get(x, y) == floortiles[f_type]) {
 
458
                        Put(x, y, 31, room_id);
 
459
                }
 
460
        }
 
461
 
 
462
        // Summon tiles
 
463
        if ((room_id % 75) == 48) {
 
464
                x = place_x + 1 + rand()%(room_w-2);
 
465
                y = place_y + 1 + rand()%(room_h-2);
 
466
                if (Get(x, y) == floortiles[f_type]) {
 
467
                        Put(x, y, 32, room_id);
 
468
                }
 
469
        }
 
470
        
 
471
        // Compass tile
 
472
        
 
473
        if ((room_id % 20) == 19) {
 
474
                x = place_x + 1 + rand()%(room_w-2);
 
475
                y = place_y + 1 + rand()%(room_h-2);
 
476
                if (Get(x, y) == floortiles[f_type]) {
 
477
                        Put(x, y, 53, room_id);
 
478
                }
 
479
        }
 
480
        
 
481
        // First room
 
482
        if (room_id == 0) {
 
483
                Paint(place_x+1, place_y+1, room_w-2, room_h-2, "dat/d/centre.loc");
 
484
        }
 
485
        // Power object rooms
 
486
        if ((room_id % 1000) == 499) {
 
487
                Paint(place_x+1, place_y+1, room_w-2, room_h-2, "dat/d/weapon.loc");
 
488
        }
 
489
        // Boss rooms
 
490
        if ((room_id % 1000) == 999) {
 
491
                Paint(place_x+1, place_y+1, room_w-2, room_h-2, "dat/d/bossroom.loc");
 
492
        }
 
493
}
 
494
 
 
495
int NoRoomCollision(int place_x, int place_y, int room_w, int room_h)
 
496
{
 
497
        int x, y;
 
498
        
 
499
        if (place_x < 0) return 0;
 
500
        if (place_y < 0) return 0;
 
501
        if ((place_x+room_w) > map.w) return 0;
 
502
        if ((place_y+room_h) > map.h) return 0;
 
503
 
 
504
        for (y = 0; y < room_h; y++) {
 
505
                for (x = 0; x < room_w; x++) {
 
506
                        if (Get(place_x + x, place_y + y) != 17) return 0;
 
507
                }
 
508
        }
 
509
        
 
510
        return 1;
 
511
}
 
512
 
 
513
void MakeConnect(int x, int y, int type)
 
514
{
 
515
        int nx, ny;
 
516
        int d1, d2;
 
517
        int room_1, room_2;
 
518
        struct RoomConnection *rconnect;
 
519
        
 
520
        switch (type) {
 
521
                case 0:
 
522
                        nx = x;
 
523
                        ny = y - 1;
 
524
                        d1 = 14;
 
525
                        d2 = 13;
 
526
                        break;
 
527
                case 1:
 
528
                        nx = x;
 
529
                        ny = y + 1;
 
530
                        d1 = 13;
 
531
                        d2 = 14;
 
532
                        break;
 
533
                case 2:
 
534
                        nx = x - 1;
 
535
                        ny = y;
 
536
                        d1 = 16;
 
537
                        d2 = 15;
 
538
                        break;
 
539
                case 3:
 
540
                        nx = x + 1;
 
541
                        ny = y;
 
542
                        d1 = 15;
 
543
                        d2 = 16;
 
544
                        break;
 
545
                default:
 
546
                        nx = 0;
 
547
                        ny = 0;
 
548
                        d1 = 0;
 
549
                        d2 = 0;
 
550
                        break;
 
551
        }
 
552
        
 
553
        room_1 = GetRoom(x, y);
 
554
        room_2 = GetRoom(nx, ny);
 
555
        if ((room_1 % 1000) == 999) {
 
556
                d1 = d1 - 13 + 21;
 
557
                d2 = d2 - 13 + 38;
 
558
        } else {
 
559
                if ((room_2 % 1000) == 999) {
 
560
                        d1 = d1 - 13 + 38;
 
561
                        d2 = d2 - 13 + 21;
 
562
                }
 
563
        }
 
564
        Put(x, y, d1, GetRoom(x, y));
 
565
        Put(nx, ny, d2, GetRoom(nx, ny));
 
566
 
 
567
        rooms[room_1].connections++;
 
568
        rconnect = rooms[room_1].con;
 
569
        rooms[room_1].con = malloc(sizeof(struct RoomConnection));
 
570
        rooms[room_1].con->n = rconnect;
 
571
        rooms[room_1].con->x = x;
 
572
        rooms[room_1].con->y = y;
 
573
        rooms[room_1].con->x2 = nx;
 
574
        rooms[room_1].con->y2 = ny;
 
575
        rooms[room_1].con->c = room_2;
 
576
        
 
577
        rooms[room_2].connections++;
 
578
        rconnect = rooms[room_2].con;
 
579
        rooms[room_2].con = malloc(sizeof(struct RoomConnection));
 
580
        rooms[room_2].con->n = rconnect;
 
581
        rooms[room_2].con->x = nx;
 
582
        rooms[room_2].con->y = ny;
 
583
        rooms[room_2].con->x2 = x;
 
584
        rooms[room_2].con->y2 = y;
 
585
        rooms[room_2].con->c = room_1;
 
586
 
 
587
}
 
588
 
 
589
int SuitableConnection(int t)
 
590
{
 
591
        switch (t) {
 
592
                case 4:
 
593
                case 5:
 
594
                case 6:
 
595
                case 7:
 
596
                
 
597
                case 45:
 
598
                case 46:
 
599
                case 47:
 
600
                case 48:
 
601
                
 
602
                case 49:
 
603
                case 50:
 
604
                case 51:
 
605
                case 52:
 
606
                        return 1;
 
607
                        break;
 
608
                        
 
609
                default:
 
610
                        break;
 
611
        }
 
612
        return 0;
 
613
}
 
614
 
 
615
void NewRoom(int place_x, int place_y, int room_w, int room_h, int creator)
 
616
{
 
617
        int connect_points = 0;
 
618
        int cplist_x[100], cplist_y[100], cplist_r[100], cplist_t[100];
 
619
        
 
620
        int sr_cps = 0;
 
621
        int sr_cp[100];
 
622
        
 
623
        int sr_nps = 0;
 
624
        int sr_np[100];
 
625
        
 
626
        int i;
 
627
        
 
628
        // Draw this room
 
629
        rooms[total_rooms].checkpoint = 0;
 
630
        DrawRoom(place_x, place_y, room_w, room_h, total_rooms);
 
631
        
 
632
        rooms[total_rooms].x = place_x;
 
633
        rooms[total_rooms].y = place_y;
 
634
        
 
635
        rooms[total_rooms].w = room_w;
 
636
        rooms[total_rooms].h = room_h;
 
637
        
 
638
        rooms[total_rooms].room_type = 0;
 
639
        rooms[total_rooms].room_param = 0;
 
640
        
 
641
        rooms[total_rooms].creator = creator;
 
642
        
 
643
        rooms[total_rooms].connections = 0;
 
644
        rooms[total_rooms].con = NULL;
 
645
        rooms[total_rooms].enemies = 0;
 
646
        
 
647
        rooms[total_rooms].visited = 0;
 
648
 
 
649
        rooms[total_rooms].s_dist = -1;
 
650
        
 
651
        if (total_rooms == 0) {
 
652
                rooms[total_rooms].checkpoint = 1;
 
653
        }
 
654
        
 
655
        
 
656
        
 
657
        total_rooms++;
 
658
 
 
659
        if (creator == -1) return;
 
660
        
 
661
        // Find connection points
 
662
        
 
663
        for (i = 0; i < room_w - 2; i++) {
 
664
                if (SuitableConnection(Get(place_x + 1 + i, place_y - 1))) {
 
665
                        cplist_x[connect_points] = place_x + 1 + i;
 
666
                        cplist_y[connect_points] = place_y;
 
667
                        cplist_r[connect_points] = GetRoom(place_x + 1 + i, place_y - 1);
 
668
                        cplist_t[connect_points] = 0;
 
669
                        connect_points++;
 
670
                }
 
671
                
 
672
                if (SuitableConnection(Get(place_x + 1 + i, place_y + room_h))) {
 
673
                        cplist_x[connect_points] = place_x + 1 + i;
 
674
                        cplist_y[connect_points] = place_y + room_h - 1;
 
675
                        cplist_r[connect_points] = GetRoom(place_x + 1 + i, place_y + room_h);
 
676
                        cplist_t[connect_points] = 1;
 
677
                        connect_points++;
 
678
                }
 
679
        }
 
680
        for (i = 0; i < room_h - 2; i++) {
 
681
                if (SuitableConnection(Get(place_x - 1, place_y + 1 + i))) {
 
682
                        cplist_x[connect_points] = place_x;
 
683
                        cplist_y[connect_points] = place_y + 1 + i;
 
684
                        cplist_r[connect_points] = GetRoom(place_x - 1, place_y + 1 + i);
 
685
                        cplist_t[connect_points] = 2;
 
686
                        connect_points++;
 
687
                }
 
688
                
 
689
                if (SuitableConnection(Get(place_x + room_w, place_y + 1 + i))) {
 
690
                        cplist_x[connect_points] = place_x + room_w - 1;
 
691
                        cplist_y[connect_points] = place_y + 1 + i;
 
692
                        cplist_r[connect_points] = GetRoom(place_x + room_w, place_y + 1 + i);
 
693
                        cplist_t[connect_points] = 3;
 
694
                        connect_points++;
 
695
                }
 
696
        }
 
697
        
 
698
        for (i = 0; i < connect_points; i++) {
 
699
                if (cplist_r[i] == creator) {
 
700
                        sr_cp[sr_cps++] = i;
 
701
                } else {
 
702
                        sr_np[sr_nps++] = i;
 
703
                }
 
704
        }
 
705
        
 
706
        //printf("cps: %d      room: %d\n", sr_cps, total_rooms);
 
707
 
 
708
        assert(sr_cps > 0);
 
709
        
 
710
        i = rndval(0, sr_cps-1);
 
711
        MakeConnect(cplist_x[sr_cp[i]], cplist_y[sr_cp[i]], cplist_t[sr_cp[i]]);
 
712
        
 
713
        // one other connection (if we can)
 
714
        if (sr_nps > 0) {
 
715
                i = rndval(0, sr_nps-1);
 
716
                MakeConnect(cplist_x[sr_np[i]], cplist_y[sr_np[i]], cplist_t[sr_np[i]]);
 
717
        }
 
718
 
 
719
}
 
720
 
 
721
int AddChild(int room_id)
 
722
{
 
723
        Room r = rooms[room_id];
 
724
        int place_x = r.x;
 
725
        int place_y = r.y;
 
726
        int room_w = r.w;
 
727
        int room_h = r.h;
 
728
        int new_w, new_h, new_x, new_y;
 
729
        int room_pos;
 
730
        
 
731
        int trying;
 
732
        int attempts;
 
733
        
 
734
 
 
735
        
 
736
        trying = 1;
 
737
        attempts = 0;
 
738
        while (trying) {
 
739
                attempts++;
 
740
                
 
741
                if (( (total_rooms+1) % 500)==0) {
 
742
                        new_w = 20;
 
743
                        new_h = 15;
 
744
                } else {
 
745
                        CreateRoomDimensions(&new_w, &new_h);
 
746
                }
 
747
                
 
748
                room_pos = (rdir++)%4;
 
749
                
 
750
                if (room_pos < 2) {
 
751
                        // vertical placement
 
752
                        new_x = rndval(place_x - (new_w - 3), place_x + (room_w - 3));
 
753
                        if (room_pos == 0) {
 
754
                                new_y = place_y - new_h;
 
755
                        } else {
 
756
                                new_y = place_y + room_h;
 
757
                        }
 
758
                } else {
 
759
                        // horiz placement
 
760
                        new_y = rndval(place_y - (new_h - 3), place_y + (room_h - 3));
 
761
                        if (room_pos == 2) {
 
762
                                new_x = place_x - new_w;
 
763
                        } else {
 
764
                                new_x = place_x + room_w;
 
765
                        }
 
766
                }
 
767
                
 
768
                if (NoRoomCollision(new_x, new_y, new_w, new_h)) {
 
769
                        //printf("SUCCESS\n");
 
770
                        r_successes[room_pos]++;
 
771
                        NewRoom(new_x, new_y, new_w, new_h, room_id);
 
772
                        return 1;
 
773
                } else {
 
774
                        //printf("FAIL %d\n", attempts);
 
775
                        r_fails[room_pos]++;
 
776
                        if (attempts > 20) return 0;
 
777
                }
 
778
        }
 
779
        return 0;
 
780
}
 
781
 
 
782
void RecurseSetDist()
 
783
{
 
784
        struct RoomConnection *rc;
 
785
        int queue[10000];
 
786
        int q_top = 1;
 
787
        int q_bot = 0;
 
788
        int rooms_left = 3000;
 
789
        int c_room;
 
790
        queue[0] = 0;
 
791
        
 
792
        if (rooms_left % 100 == 0) {
 
793
                LoadingScreen(1, 1.0 - ((float)rooms_left / 3000.0));
 
794
        }
 
795
        
 
796
        rooms[0].s_dist = 0;
 
797
        
 
798
        while ((rooms_left > 0)) {      
 
799
                c_room = queue[q_bot];
 
800
                q_bot++;
 
801
                rooms_left--;
 
802
                
 
803
                rc = rooms[c_room].con;
 
804
                
 
805
                while (rc != NULL) {
 
806
                        //assert(qp < 3000);
 
807
                        if (rooms[rc->c].s_dist == -1) {
 
808
                                queue[q_top] = rc->c;
 
809
                                q_top++;
 
810
                                rooms[rc->c].s_dist = rooms[c_room].s_dist+1;
 
811
                        }
 
812
                        rc = rc->n;
 
813
                }
 
814
        }
 
815
}
 
816
 
 
817
int RoomSize(int c_room)
 
818
{
 
819
        return sqrt(rooms[c_room].w*rooms[c_room].w + rooms[c_room].h*rooms[c_room].h);
 
820
}
 
821
 
 
822
void MakeSpecialRooms()
 
823
{
 
824
        int i, j;
 
825
        int c_tier;
 
826
        int c_room;
 
827
        int biggest_room_sz = 0;
 
828
        int biggest_room_n = -1;
 
829
        int rtyp[8] = {0};
 
830
        int ctyp;
 
831
        int x, y;
 
832
        
 
833
        // Special rooms are:
 
834
        // - Boss rooms @ 500, 1000, 1500, 2000, 2500, 3000
 
835
        // - Artifact rooms (biggest non-boss room of a given tier)
 
836
        //              Tiers: 5-9  10-14  15-19  20-24  25-29  30-34  35-39  40-44
 
837
        
 
838
        // boss rooms
 
839
        for (i = 0; i < 3; i++) {
 
840
                c_room = i*1000+999;
 
841
                rooms[c_room].room_type = 2;
 
842
                rooms[c_room].room_param = i;
 
843
        }
 
844
        // power object rooms
 
845
        for (i = 0; i < 3; i++) {
 
846
                c_room = i*1000+499;
 
847
                rooms[c_room].room_type = 5;
 
848
                rooms[c_room].room_param = i;
 
849
        }
 
850
        
 
851
        // artifact rooms
 
852
        for (c_tier = 0; c_tier < 8; c_tier++) {
 
853
                biggest_room_sz = 0;
 
854
                for (c_room = 0; c_room < 3000; c_room++) {
 
855
                        if (rooms[c_room].room_type == 0) {
 
856
                                if (rooms[c_room].s_dist >= (c_tier*5+5)) {
 
857
                                        if (rooms[c_room].s_dist <= (c_tier*5+9)) {
 
858
                                                if (RoomSize(c_room) > biggest_room_sz) {
 
859
                                                        biggest_room_sz = RoomSize(c_room);
 
860
                                                        biggest_room_n = c_room;
 
861
                                                }
 
862
                                        }
 
863
                                }
 
864
                        }
 
865
                }
 
866
                rooms[biggest_room_n].room_type = 3;
 
867
                
 
868
                // pick a #
 
869
                for (;;) {
 
870
                        ctyp = rand()%8;
 
871
                        if (rtyp[ctyp] == 0) {
 
872
                                rtyp[ctyp] = 1;
 
873
                                break;
 
874
                        }
 
875
                }
 
876
                
 
877
                rooms[biggest_room_n].room_param = ctyp;
 
878
                
 
879
                //printf("Artifact room for tier %d is room %d (size %d), with artifact %d\n", c_tier, biggest_room_n, biggest_room_sz, ctyp);
 
880
        }
 
881
        
 
882
        // place of power
 
883
        // The room with the highest s_dist that is not of any other type
 
884
        
 
885
        for (i = 0; i < 3000; i++) {
 
886
                if (rooms[i].s_dist > rooms[place_of_power].s_dist) {
 
887
                        if (rooms[i].room_type == 0) {
 
888
                                place_of_power = i;
 
889
                        }
 
890
                }
 
891
        }
 
892
 
 
893
        rooms[place_of_power].room_type = 6;
 
894
        
 
895
        // Now place some checkpoints in the remaining rooms
 
896
        // Normally, we would have a checkpoint for every 30
 
897
        // rooms, BUT since we aren't using that method any
 
898
        // more, we will simply use an equivalent--namely, to
 
899
        // divide the map into an 8x8 grid and place one
 
900
        // checkpoint per square
 
901
 
 
902
        for (y = 0; y < 8; y++) {
 
903
                for (x = 0; x < 8; x++) {
 
904
                        j = -1;
 
905
                        for (i = 0; i < 20; i++) {
 
906
                                j = GetRoom(rand() % 64 + x * 64, rand() % 64 + y * 64);
 
907
                
 
908
                if (j >= 0) {
 
909
                    if (rooms[j].room_type == 0) {
 
910
                        Put(rooms[j].x + rooms[j].w / 2, rooms[j].y + rooms[j].h / 2, 25, j);
 
911
                        rooms[j].checkpoint = 1;
 
912
                        break;
 
913
                    }
 
914
                }
 
915
                        }
 
916
                }
 
917
        }
 
918
        
 
919
        next_check--;
 
920
}
 
921
 
 
922
int Generate()
 
923
{
 
924
        int attempts = 0;
 
925
        int i;
 
926
        int correct_dist = 0;
 
927
        int maxdist = 0;
 
928
        rdir = rand()%4;
 
929
        NewRoom(map.w / 2 - 20 / 2, map.h / 2 - 15 / 2, 20, 15, -1);
 
930
        
 
931
        for (attempts = 0; attempts < 100000; attempts++) {
 
932
        assert(map.w == 512);
 
933
                AddChild(rndval(rndval(0, total_rooms-1), total_rooms-1));
 
934
                if (total_rooms % 100 == 99) {
 
935
                        LoadingScreen(0, (float)total_rooms / 3000.0);
 
936
                }
 
937
                if (total_rooms == 3000) break;
 
938
        }
 
939
        
 
940
        if ((total_rooms < 3000)||(DoRepeat == 1)) {
 
941
                DoRepeat = 0;
 
942
                ResetLevel();
 
943
                return 0;
 
944
        }
 
945
        
 
946
        RecurseSetDist();
 
947
        
 
948
        for (i = 0; i < 3000; i++) {
 
949
                if (rooms[i].s_dist > maxdist) {
 
950
                        maxdist = rooms[i].s_dist;
 
951
                }
 
952
                
 
953
                if (rooms[i].s_dist >= 50) {
 
954
                        correct_dist = 1;
 
955
                }
 
956
        }
 
957
        
 
958
        if (correct_dist == 0) {
 
959
                //printf("Dist fail (only %d)\n", maxdist);
 
960
                DoRepeat = 0;
 
961
                ResetLevel();
 
962
                return 0;
 
963
        }
 
964
        
 
965
        //printf("Rooms: %d\n", total_rooms);
 
966
        
 
967
        MakeSpecialRooms();
 
968
        
 
969
        map.totalRooms = total_rooms;
 
970
        return 1;
 
971
}
 
972