1 /* $Id$ */
2 /* File: wilderness.c */
3
4 /* Purpose: Wilderness generation */
5
6 /*
7 * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
8 *
9 * Copyright (c) 1999 Alex P. Dingle
10 *
11 * This software may be copied and distributed for educational, research, and
12 * not for profit purposes provided that this copyright and statement are
13 * included in all such copies.
14 */
15
16 /*
17 * Heavily modified and improved in 2001-2002 by Evileye
18 */
19
20 #define SERVER
21
22 #include "angband.h"
23
24
25 #ifdef WILDERNESS_NEW_FEATURES
26 /* Bleed with neighbours? (The main bleeding function).
27 WARNING: Toggling this feature can change house locations. */
28 #define BLEED_WITH_NEIGHBOURS
29 #else
30 /* Use a simple kind of bleeding just to indicate dangerous terrain ahead,
31 was just used ad interim. */
32 #define SIMPLE_BLEED
33 #endif
34
35 /* For BLEED_WITH_NEIGHBOURS:
36 Don't bleed involving/from towns because that can look a bit weird
37 sometimes, eg if Khazad-dum bleeds grassland into adjacent volcanos.
38 WARNING: Toggling this feature can change house locations.
39 ** Sort of deprecated - use BLEED_ENHANCED_TOWN below instead. - C. Blue */
40 //#define BLEED_AVOID_TOWN
41
42 /* For BLEED_WITH_NEIGHBOURS:
43 Bleed correct town terrain into town-adjacent sectors (hard-coded though).
44 WARNING: Toggling this feature can change house locations. */
45 #define BLEED_ENHANCED_TOWN
46
47 /* HACK: Disable new terrain types DESERT/WILD and other rng-affecting stuff? */
48 #ifndef WILDERNESS_NEW_FEATURES
49 #define __DISABLE_NEW
50 #endif
51
52 /* HACK: Disable house shortage counter measures? */
53 #ifndef WILDERNESS_NEW_FEATURES
54 #define __DISABLE_HOUSEBOOST
55 #endif
56
57
58 /* This function takes the players x,y level world coordinate and uses it to
59 calculate p_ptr->dun_depth. The levels are stored in a series of "rings"
60 radiating out from the town, as shown below. This storage mechanisim was
61 used because it does not place an initial restriction on the wilderness
62 dimensions.
63
64 In order to gracefully introduce the wilderness to the preexisting mangband
65 functions, the indexes are negative and apply to the same cave structure
66 that holds the dungeon levels.
67
68 Indexes (-) Ring # world_y
69
70 [05] [2] [ 2]
71 [12][01][06] [2][1][2] [ 1]
72 [11][04][To][02][07] [2][1][X][1][2] world_x [-2][-1][ 0][ 1][ 2]
73 [10][03][08] [2][1][2] [-1]
74 [09] [2] [-2]
75 -APD-
76
77 A special function is required to init the wild_info structures because I have not
78 been able to devise a simple algorithm to go from an index to an x,y coordinate.
79 I derived an equation that would calculate the ring from the index, but it involved
80 a square root.
81
82 */
83
world_index(int world_x,int world_y)84 int world_index(int world_x, int world_y)
85 {
86 int ring, base, offset, idx;
87
88 /* calculate which "ring" the level is in */
89 ring = abs(world_x) + abs(world_y);
90
91 /* hack -- the town is 0 */
92 if (!ring) {
93 return 0;
94 }
95
96 /* calculate the base offset of this ring */
97 base = 2*ring*(ring-1) + 1;
98
99 /* calculate the offset within this ring */
100 if (world_x >= 0) offset = ring - world_y;
101 else offset = (3 * ring) + world_y;
102
103 idx = -(base + offset);
104
105 return idx;
106 }
107
108 #ifdef SIMPLE_BLEED
bleed_warn_feat(int wild_type,cave_type * c_ptr)109 static void bleed_warn_feat(int wild_type, cave_type *c_ptr) {
110 switch (wild_type) {
111 case WILD_SWAMP: c_ptr->feat = FEAT_BUSH; break;
112 // case WILD_SHORE1: case WILD_SHORE2: case WILD_COAST:
113 case WILD_LAKE: case WILD_RIVER:
114 case WILD_OCEANBED1: case WILD_OCEANBED2:
115 case WILD_OCEAN: c_ptr->feat = FEAT_SHAL_WATER; break;
116 case WILD_MOUNTAIN: c_ptr->feat = FEAT_MOUNTAIN; break;
117 case WILD_VOLCANO: c_ptr->feat = FEAT_SHAL_LAVA; break;
118 }
119 }
120 #endif
121
122 /* Initialize the wild_info coordinates and radius. Uses a recursive fill algorithm.
123 This may seem a bit out of place, but I think it is too complex to go in init2.c.
124 Note that the flags for these structures are loaded from the server savefile.
125
126 Note that this has to be initially called with 0,0 to work properly.
127 */
128
towndist(int wx,int wy,s16b * townlev)129 static int towndist(int wx, int wy, s16b *townlev) {
130 int i;
131 int dist, mindist = 100;
132
133 *townlev = 0;
134 for (i = 0; i < numtowns; i++){
135 dist = abs(wx - town[i].x) + abs(wy - town[i].y);
136 if (dist < mindist) {
137 mindist = dist;
138 *townlev = town[i].baselevel;
139 }
140 }
141 return (mindist);
142 }
143
init_wild_info_aux(int x,int y)144 void init_wild_info_aux(int x, int y) {
145 s16b tlev;
146
147 wild_info[y][x].radius = towndist(x, y, &tlev);
148 wild_info[y][x].town_lev = tlev;
149 wild_info[y][x].town_idx = wild_gettown(x, y);
150
151 if (y + 1 < MAX_WILD_Y) {
152 if (!(wild_info[y + 1][x].radius))
153 init_wild_info_aux(x, y + 1);
154 }
155 if (x + 1 < MAX_WILD_X) {
156 if (!(wild_info[y][x + 1].radius))
157 init_wild_info_aux(x + 1, y);
158 }
159 if (y - 1 >= 0) {
160 if (!(wild_info[y - 1][x].radius))
161 init_wild_info_aux(x, y - 1);
162 }
163 if (x - 1 >= 0) {
164 if (!(wild_info[y][x - 1].radius))
165 init_wild_info_aux(x - 1, y);
166 }
167
168 }
169
initwild()170 void initwild() {
171 int i, j;
172
173 for (i = 0; i < MAX_WILD_X; i++)
174 for (j = 0; j < MAX_WILD_Y; j++)
175 wild_info[j][i].type = WILD_UNDEFINED;
176 }
177
178 /* Initialize the wild_info coordinates and radius. Uses a recursive fill algorithm.
179 This may seem a bit out of place, but I think it is too complex to go in init2.c.
180 Note that the flags for these structures are loaded from the server savefile.
181
182 Note that this has to be initially called with 0,0 to work properly.
183 */
184
addtown(int y,int x,int base,u16b flags,int type)185 void addtown(int y, int x, int base, u16b flags, int type) {
186 int n;
187
188 if (numtowns)
189 GROW(town, numtowns, numtowns+1, struct town_type);
190 else
191 MAKE(town, struct town_type);
192 town[numtowns].x = x;
193 town[numtowns].y = y;
194 town[numtowns].baselevel = base;
195 town[numtowns].flags = flags;
196 // town[numtowns].num_stores = MAX_BASE_STORES;
197 town[numtowns].num_stores = max_st_idx;
198 town[numtowns].type = type;
199 wild_info[y][x].type = WILD_TOWN;
200 wild_info[y][x].town_idx = numtowns;
201 wild_info[y][x].radius = base;
202 alloc_stores(numtowns);
203 /* Initialize the stores */
204 // for (n = 0; n < MAX_BASE_STORES; n++)
205 for (n = 0; n < max_st_idx; n++) {
206 /* make shop remember the town its in - C. Blue */
207 town[numtowns].townstore[n].town = numtowns;
208
209 //int i;
210 /* Initialize */
211 store_init(&town[numtowns].townstore[n]);
212
213 /* Ignore home and auction house */
214 // if ((n == MAX_BASE_STORES - 2) || (n == MAX_BASE_STORES - 1)) continue;
215
216 /* Maintain the shop */
217 store_maint(&town[numtowns].townstore[n]);
218 // for (i = 0; i < 10; i++) store_maint(&town[numtowns].townstore[n]);
219 }
220 numtowns++;
221 }
222
223 /* Erase a custom town again. Why wasn't this implemented already!? - C. Blue */
deltown(int Ind)224 void deltown(int Ind) {
225 int x, y, i;
226 s16b tlev;
227 struct worldpos *wpos = &Players[Ind]->wpos, tpos;
228
229 #if 1
230 for (x = wpos->wx - wild_info[wpos->wy][wpos->wx].radius;
231 x <= wpos->wx + wild_info[wpos->wy][wpos->wx].radius; x++)
232 for (y = wpos->wy - wild_info[wpos->wy][wpos->wx].radius;
233 y <= wpos->wy + wild_info[wpos->wy][wpos->wx].radius; y++)
234 if (in_bounds_wild(y, x) && (towndist(x, y, &tlev) <= abs(wpos->wx - x) + abs(wpos->wy - y))) {
235 tpos.wx = x; tpos.wy = y; tpos.wz = 0;
236 for (i = 0; i < num_houses; i++)
237 if (inarea(&tpos, &houses[i].wpos)) {
238 //#if 0
239 fill_house(&houses[i], FILL_MAKEHOUSE, NULL);
240 houses[i].flags |= HF_DELETED;
241 //#endif
242 }
243 wilderness_gen(&tpos);
244 }
245 #endif
246
247 if (numtowns <= 5) return;
248
249 // wild_info[wpos->wy][wpos->wx].type = WILD_GRASSLAND;
250 // wild_info[wpos->wy][wpos->wx].type = WILD_OCEAN;
251 wild_info[wpos->wy][wpos->wx].type = WILD_UNDEFINED; /* re-generate */
252 wild_info[wpos->wy][wpos->wx].radius = towndist(wpos->wy, wpos->wx, &tlev);
253 wild_info[wpos->wy][wpos->wx].town_lev = tlev;
254 wild_info[wpos->wy][wpos->wx].town_idx = wild_gettown(wpos->wx, wpos->wy);
255 wilderness_gen(wpos);
256
257 /* Shrink the town array */
258 SHRINK(town, numtowns, numtowns - 1, struct town_type);
259
260 numtowns--;
261 }
262
wild_bulldoze()263 void wild_bulldoze()
264 {
265 int x,y;
266
267 /* inefficient? thats an understatement */
268 for(y = 0; y < MAX_WILD_Y; y++){
269 for(x = 0; x < MAX_WILD_X; x++){
270 struct wilderness_type *w_ptr = &wild_info[y][x];
271 if (w_ptr->radius <= MAX_TOWNAREA &&
272 (w_ptr->type == WILD_WASTELAND ||
273 w_ptr->type == WILD_DESERT ||
274 w_ptr->type == WILD_ICE ||
275 w_ptr->type == WILD_DENSEFOREST ||
276 w_ptr->type == WILD_OCEAN ||
277 w_ptr->type == WILD_RIVER ||
278 w_ptr->type == WILD_VOLCANO ||
279 w_ptr->type == WILD_MOUNTAIN)) {
280 wild_info[y][x].type = WILD_GRASSLAND;
281 }
282 }
283 }
284 }
285
286 /*
287 * Makeshift towns/dungeons placer for v4
288 * This should be totally rewritten for v5! - Jir -
289 */
wild_spawn_towns()290 void wild_spawn_towns()
291 {
292 int x, y, i, j, k;
293 bool retry, skip;
294
295 int tries = 100;
296 worldpos wpos = {0, 0, 0};
297
298 /* Place towns */
299 for (i = 1 + 1; i < 6; i++) {
300 retry = FALSE;
301
302 /* avoid towns at the border of the world map (also: no housing space there!) */
303 y = 2 + rand_int(MAX_WILD_Y - 4);
304 x = 2 + rand_int(MAX_WILD_X - 4);
305
306 /* check wilderness type so that Bree is in forest and
307 * Minas Anor in mountain etc */
308 if (wild_info[y][x].type != town_profile[i].wild_req) {
309 i--;
310 continue;
311 }
312
313 /* Don't build them too near to each other */
314 for (j = 0; j < i - 1; j++) {
315 if (distance(y, x, town[j].y, town[j].x) < 8) {
316 retry = TRUE;
317 break;
318 }
319 }
320 if (retry) {
321 i--;
322 continue;
323 }
324 addtown(y, x, town_profile[i].dun_base, 0, i); /* base town */
325 }
326
327 /* Place dungeons */
328 for (i = 1; i < max_d_idx; i++) {
329 retry = FALSE;
330
331 /* Skip empty entry */
332 if (!d_info[i].name) continue;
333
334 /* Hack -- omit dungeons associated with towns */
335 if (tries == 100) {
336 skip = FALSE;
337
338 for (j = 1; j < 6; j++) {
339 for (k = 0; k < 2; k++) {
340 if (town_profile[j].dungeons[k] == i) skip = TRUE;
341 }
342 }
343
344 if (skip) continue;
345 }
346
347 y = rand_int(MAX_WILD_Y);
348 x = rand_int(MAX_WILD_X);
349
350 wpos.wy = y;
351 wpos.wx = x;
352
353 /* reserve sector 0,0 for special occasions, such as
354 Highlander Tournament dungeon and PvP Arena tower - C. Blue */
355 if (!y && !x) retry = TRUE; /* ((sector00separation)) */
356
357 /* Don't build them too near to towns
358 * (otherwise entrance can be within a house) */
359 for (j = 0; j < 5; j++) {
360 if (distance(y, x, town[j].y, town[j].x) <= MAX_TOWNAREA) {
361 retry = TRUE;
362 break;
363 }
364 }
365 if (!retry) {
366 if (wild_info[y][x].dungeon || wild_info[y][x].tower) retry = TRUE;
367
368 /* TODO: easy dungeons around Bree,
369 * hard dungeons around Lorien */
370 }
371 if (retry) {
372 if (tries-- > 0) i--;
373 continue;
374 }
375
376 add_dungeon(&wpos, 0, 0, 0, 0, 0, FALSE, i, 0, 0, 0);
377
378 /* 0 or MAX_{HGT,WID}-1 are bad places for stairs - mikaelh */
379 if (d_info[i].flags1 & DF1_TOWER) {
380 new_level_down_y(&wpos, 2 + rand_int(MAX_HGT - 4));
381 new_level_down_x(&wpos, 2 + rand_int(MAX_WID - 4));
382 } else {
383 new_level_up_y(&wpos, 2 + rand_int(MAX_HGT - 4));
384 new_level_up_x(&wpos, 2 + rand_int(MAX_WID - 4));
385 }
386 #if 0
387 if ((zcave = getcave(&p_ptr->wpos))) {
388 zcave[p_ptr->py][p_ptr->px].feat = FEAT_MORE;
389 }
390 #endif // 0
391
392 #if DEBUG_LEVEL > 0
393 s_printf("Dungeon %d is generated in %s.\n", i, wpos_format(0, &wpos));
394 #endif // 0
395
396 tries = 100;
397 }
398 }
399
init_wild_info()400 void init_wild_info() {
401 int x, y;
402
403 memset(&wild_info[0][0],0,sizeof(wilderness_type)*(MAX_WILD_Y*MAX_WILD_X));
404
405 /* evileye test new wilderness map */
406 initwild();
407
408 /* Jir tests new town allocator */
409 addtown(cfg.town_y, cfg.town_x, cfg.town_base, 0, 1); /* base town */
410 //if (new) wild_spawn_towns();
411
412 //init_wild_info_aux(0,0);
413
414 for (x = 0; x < MAX_WILD_X; x++) {
415 for (y = 0; y < MAX_WILD_Y; y++) {
416 wild_info[y][x].bled = WILD_GRASSLAND;
417 }
418 }
419 }
420
421
422
423 /* In the future, add all sorts of cool stuff could be added, such as clusters of
424 * buildings or abandoned towns. Also, maybe hack on additional wilderness
425 dungeons or "basements" of houses, which could be stored with indicies
426 > 128 and acceced by some sort of adressing array. Hmm, maybe make a
427 dungeon_type... of which the town's dungeon could be one. It would have
428 world_x, world_y, local_x, local_y, depth, type, etc.
429
430 The current wilderness generation is a quick hack generally, and it would be
431 cool if it was rewritten in the future with some sort of fractal system involving
432 seas, rivers, mountains, hills, mines, towns, roads, farms, etc.
433
434 HACK -- I added a WILD_CLONE type of terrain, which sets the terrain type to that
435 of a random neighbor, and if that neighbor is clone it goes rescursive until
436 it finds a non-clone piece of terrain. This will hopefully provide more
437 unified terrain. (i.e. big forests, big lakes, etc )
438 */
439
440
441 /*
442 * Helper function for wild_add_monster
443 *
444 * a hack not to have elven archers etc. on town.
445 */
wild_monst_aux_town(int r_idx)446 static bool wild_monst_aux_town(int r_idx)
447 {
448 monster_race *r_ptr = &r_info[r_idx];
449
450 if (r_ptr->flags8 & RF8_WILD_TOWN)
451 return TRUE;
452 else
453 return FALSE;
454 #if 0
455 /* Maggot is allowed :) */
456 if (!strcmp(&r_name[r_ptr->name],"Farmer Maggot")) return TRUE;
457
458 /* no special monsters allowed */
459 if (r_ptr->flags9 & RF9_SPECIAL_GENE) return FALSE;
460
461 /* non-town monsters are not allowed */
462 // if (r_ptr->level) return FALSE;
463
464 /* OK */
465 return TRUE;
466 #endif // 0
467 }
468
469
470 /*
471 * Helper function for wild_add_monster
472 */
wild_monst_aux_lake(int r_idx)473 static bool wild_monst_aux_lake(int r_idx)
474 {
475 monster_race *r_ptr = &r_info[r_idx];
476
477 /* no reproducing monsters allowed */
478 if (r_ptr->flags7 & RF7_MULTIPLY) return FALSE;
479
480 if (r_ptr->flags2 & RF2_AURA_FIRE)
481 return FALSE;
482
483 /* animals are OK */
484 if (r_ptr->flags3 & RF3_ANIMAL) return TRUE;
485 /* humanoids and other races are OK */
486 if (strchr("ph", r_ptr->d_char)) return TRUE;
487 /* always allow aquatics! */
488 if (r_ptr->flags7 & (RF7_AQUATIC | RF7_CAN_SWIM | RF7_CAN_FLY))
489 return TRUE;
490
491 /* No */
492 return FALSE;
493 }
494
495
496 /*
497 * Helper function for wild_add_monster
498 */
wild_monst_aux_grassland(int r_idx)499 static bool wild_monst_aux_grassland(int r_idx)
500 {
501 monster_race *r_ptr = &r_info[r_idx];
502
503 /* no reproducing monsters allowed */
504 if (r_ptr->flags7 & RF7_MULTIPLY) return FALSE;
505
506 if (r_ptr->flags8 & RF8_WILD_GRASS)
507 return TRUE;
508 else
509 return FALSE;
510
511 #if 0
512 /* no aquatic life here */
513 if (r_ptr->flags7 & RF7_AQUATIC) return FALSE;
514
515 /* no reproducing monsters allowed */
516 if (r_ptr->flags7 & RF7_MULTIPLY) return FALSE;
517
518 /* animals are OK */
519 if (r_ptr->flags3 & RF3_ANIMAL) return TRUE;
520
521 /* what exactly is a yeek? */
522 if (strchr("CEGOPTWYdhmpqvy", r_ptr->d_char)) return TRUE;
523
524 if (!strcmp(&r_name[r_ptr->name],"Hill orc")) return TRUE;
525 if (!strcmp(&r_name[r_ptr->name],"Uruk")) return TRUE;
526
527 /* town monsters are OK */
528 if (!r_ptr->level) return TRUE;
529
530 return FALSE;
531 #endif // 0
532 }
533
534 /*
535 * Helper function for wild_add_monster
536 */
wild_monst_aux_forest(int r_idx)537 static bool wild_monst_aux_forest(int r_idx)
538 {
539 monster_race *r_ptr = &r_info[r_idx];
540
541 if (r_ptr->flags8 & RF8_WILD_WOOD)
542 return TRUE;
543 else
544 return FALSE;
545 #if 0
546 /* snakes, wolves, beetles, and felines are OK */
547 if (strchr("JCKf", r_ptr->d_char)) return (TRUE);
548 if (!strcmp(&r_name[r_ptr->name],"Wood spider")) return TRUE;
549 if (!strcmp(&r_name[r_ptr->name],"Novice ranger")) return TRUE;
550 if (!strcmp(&r_name[r_ptr->name],"Novice archer")) return TRUE;
551 if (!strcmp(&r_name[r_ptr->name],"Druid")) return TRUE;
552 if (!strcmp(&r_name[r_ptr->name],"Forest wight")) return TRUE;
553 if (!strcmp(&r_name[r_ptr->name],"Forest troll")) return TRUE;
554 if (!strcmp(&r_name[r_ptr->name],"Dark elven druid")) return TRUE;
555 if (!strcmp(&r_name[r_ptr->name],"Mystic")) return TRUE;
556
557 return FALSE;
558 #endif // 0
559 }
560
561 /*
562 * Helper function for wild_add_monster
563 */
wild_monst_aux_swamp(int r_idx)564 static bool wild_monst_aux_swamp(int r_idx)
565 {
566 monster_race *r_ptr = &r_info[r_idx];
567
568 if (r_ptr->flags8 & RF8_WILD_SWAMP)
569 return TRUE;
570 else
571 return FALSE;
572 #if 0
573 /* swamps are full of annoying monsters */
574 if (strchr("Jwj,FGILMQRSVWceilmsz", r_ptr->d_char)) return TRUE;
575 if (!strcmp(&r_name[r_ptr->name],"Dark elven mage")) return TRUE;
576 if (!strcmp(&r_name[r_ptr->name],"Dark elven lord")) return TRUE;
577 if (!strcmp(&r_name[r_ptr->name],"Dark elven druid")) return TRUE;
578
579 return FALSE;
580 #endif // 0
581 }
582
583 /*
584 * Helper function for wild_add_monster
585 */
586 /* Hrm.. now it's exactly same with normal forest.. */
wild_monst_aux_denseforest(int r_idx)587 static bool wild_monst_aux_denseforest(int r_idx)
588 {
589 monster_race *r_ptr = &r_info[r_idx];
590
591 if (r_ptr->flags8 & RF8_WILD_WOOD)
592 return TRUE;
593 else
594 return FALSE;
595 #if 0
596 if (!strcmp(&r_name[r_ptr->name],"Forest Troll")) return TRUE;
597 if (!strcmp(&r_name[r_ptr->name],"Mirkwood spider")) return TRUE;
598 if (!strcmp(&r_name[r_ptr->name],"Forest wight")) return TRUE;
599 if (!strcmp(&r_name[r_ptr->name],"Dark elven druid")) return TRUE;
600
601 return FALSE;
602 #endif // 0
603 }
604
605 /*
606 * Helper function for wild_add_monster
607 */
wild_monst_aux_wasteland(int r_idx)608 static bool wild_monst_aux_wasteland(int r_idx)
609 {
610 monster_race *r_ptr = &r_info[r_idx];
611
612 if (r_ptr->flags8 & RF8_WILD_WASTE)
613 return TRUE;
614 else
615 return FALSE;
616 #if 0
617 /* no aquatic life here */
618 if (r_ptr->flags7 & RF7_AQUATIC) return FALSE;
619
620 /* wastelands are full of tough monsters */
621 if (strchr("ABCDEFHLMOPTUVWXYZdefghopqv", r_ptr->d_char)) return TRUE;
622
623 /* town monsters are OK ;-) */
624 if (!r_ptr->level) return TRUE;
625
626 return FALSE;
627 #endif // 0
628
629 }
630
631 /*
632 * Helper function for wild_add_monster
633 */
wild_monst_aux_desert(int r_idx)634 static bool wild_monst_aux_desert(int r_idx)
635 {
636 monster_race *r_ptr = &r_info[r_idx];
637
638 if (r_ptr->flags8 & RF8_WILD_DESERT) return TRUE;
639
640 /* borrow from wasteland monsters */
641 // if (r_ptr->flags8 & RF8_WILD_WASTE) return TRUE;
642
643 /* no aquatic life here */
644 if (r_ptr->flags7 & RF7_AQUATIC) return FALSE;
645
646 /* monsters that don't mind dry environment */
647 if (strchr("acsuwBCFIJKRS", r_ptr->d_char)) return TRUE;
648
649 return FALSE;
650 }
651
652 /*
653 * Helper function for wild_add_monster
654 */
wild_monst_aux_ice(int r_idx)655 static bool wild_monst_aux_ice(int r_idx)
656 {
657 monster_race *r_ptr = &r_info[r_idx];
658
659 if (r_ptr->flags8 & RF8_WILD_ICE) return TRUE;
660
661 /* no aquatic life here */
662 if (r_ptr->flags7 & RF7_AQUATIC) return FALSE;
663
664 /* no cold-susceptible monsters */
665 if (r_ptr->flags3 & RF3_SUSCEP_COLD) return FALSE;
666
667 /* monsters that don't mind cold environment */
668 if (r_ptr->flags3 & RF3_IM_COLD) return TRUE;
669 if (r_ptr->flags9 & RF9_RES_COLD) return TRUE;
670
671 /* borrow from wasteland monsters */
672 // if (r_ptr->flags8 & RF8_WILD_WASTE) return TRUE;
673
674 return FALSE;
675 }
676
677 #if 0 /* looks like these aren't used - mikaelh */
678 static bool wild_monst_aux_ocean(int r_idx)
679 {
680 monster_race *r_ptr = &r_info[r_idx];
681
682 if (r_ptr->flags8 & RF8_WILD_OCEAN)
683 return TRUE;
684 else
685 return FALSE;
686 }
687
688 static bool wild_monst_aux_shore(int r_idx)
689 {
690 monster_race *r_ptr = &r_info[r_idx];
691
692 if (r_ptr->flags8 & RF8_WILD_SHORE)
693 return TRUE;
694 else
695 return FALSE;
696 }
697
698 static bool wild_monst_aux_volcano(int r_idx)
699 {
700 monster_race *r_ptr = &r_info[r_idx];
701
702 if (r_ptr->flags8 & RF8_WILD_VOLCANO)
703 return TRUE;
704 else
705 return FALSE;
706 }
707 #endif // 0
708
set_mon_num_hook_wild(struct worldpos * wpos)709 void set_mon_num_hook_wild(struct worldpos *wpos)
710 {
711 switch(wild_info[wpos->wy][wpos->wx].type) {
712 case WILD_RIVER:
713 case WILD_OCEAN:
714 case WILD_LAKE: get_mon_num_hook = wild_monst_aux_lake; break;
715 case WILD_GRASSLAND: get_mon_num_hook = wild_monst_aux_grassland; break;
716 case WILD_FOREST: get_mon_num_hook = wild_monst_aux_forest; break;
717 case WILD_SWAMP: get_mon_num_hook = wild_monst_aux_swamp; break;
718 case WILD_DENSEFOREST: get_mon_num_hook = wild_monst_aux_denseforest; break;
719 case WILD_WASTELAND: get_mon_num_hook = wild_monst_aux_wasteland; break;
720 case WILD_DESERT: get_mon_num_hook = wild_monst_aux_desert; break;
721 case WILD_ICE: get_mon_num_hook = wild_monst_aux_ice; break;
722 case WILD_TOWN: get_mon_num_hook = wild_monst_aux_town; break;
723 default: get_mon_num_hook = dungeon_aux;
724 }
725 }
726
727
728 /* this may not be the most efficient way of doing things... */
wild_add_monster(struct worldpos * wpos)729 void wild_add_monster(struct worldpos *wpos)
730 {
731 int monst_x, monst_y, r_idx;
732 int tries = 0;
733 cave_type **zcave;
734 if (!(zcave = getcave(wpos))) return;
735
736 /* Don't spawn during highlander tournament or global events in general (ancient D vs lvl 10 is silyl) */
737 if (sector00separation && wpos->wx == WPOS_SECTOR00_X && wpos->wy == WPOS_SECTOR00_Y) return;
738
739 /* reset the monster sorting function */
740 set_mon_num_hook_wild(wpos);
741
742 /* find a legal, unoccupied space */
743 do {
744 monst_x = rand_int(MAX_WID);
745 monst_y = rand_int(MAX_HGT);
746
747 if (cave_naked_bold(zcave, monst_y, monst_x)) break;
748 tries++;
749 } while (tries < 50);
750
751 if (!cave_naked_bold(zcave, monst_y, monst_x)) {
752 /* Give up */
753 return;
754 }
755
756 /* Set the second hook according to the terrain type */
757 set_mon_num2_hook(zcave[monst_y][monst_x].feat);
758
759 get_mon_num_prep(0, NULL);
760
761 /* get the monster */
762 r_idx = get_mon_num(monster_level, monster_level);
763
764 /* place the monster */
765 place_monster_aux(wpos, monst_y, monst_x, r_idx, FALSE, TRUE, FALSE, 0);
766
767 /* hack -- restore the monster selection function */
768 get_mon_num_hook = dungeon_aux;
769 }
770
771
772
773
774 /* chooses a clear building location, possibly specified by xcen, ycen, and "reserves" it so
775 * nothing else can choose any of its squares for building again */
reserve_building_plot(struct worldpos * wpos,int * x1,int * y1,int * x2,int * y2,int xlen,int ylen,int xcen,int ycen)776 static void reserve_building_plot(struct worldpos *wpos, int *x1, int *y1, int *x2, int *y2, int xlen, int ylen, int xcen, int ycen)
777 {
778 int x,y, attempts = 0, plot_clear;
779 cave_type **zcave;
780 if (!(zcave = getcave(wpos))) return;
781
782 #ifdef DEVEL_TOWN_COMPATIBILITY
783 while (attempts < 200)
784 #else
785 while (attempts < 20)
786 #endif
787 {
788
789 /* if xcen, ycen have not been specified */
790 if (!in_bounds(ycen,xcen)) {
791 #ifdef DEVEL_TOWN_COMPATIBILITY
792 /* the upper left corner */
793 *x1 = rand_int(MAX_WID-xlen-3)+1;
794 *y1 = rand_int(MAX_HGT-ylen-3)+1;
795 #else
796 /* the upper left corner */
797 *x1 = rand_int(MAX_WID-xlen-4)+2;
798 *y1 = rand_int(MAX_HGT-ylen-4)+2;
799 #endif
800 /* the lower right corner */
801 *x2 = *x1 + xlen-1;
802 *y2 = *y1 + ylen-1;
803 } else {
804 *x1 = xcen - xlen/2;
805 *y1 = ycen - ylen/2;
806 *x2 = *x1 + xlen-1;
807 *y2 = *y1 + ylen-1;
808
809 if ( (!in_bounds(*y1, *x1)) ||
810 (!in_bounds(*y2, *x2)) ) {
811 *x1 = *y1 = *x2 = *y2 = -1;
812 return;
813 }
814 }
815
816 plot_clear = 1;
817
818 /* check if its clear */
819 for (y = *y1; y <= *y2; y++) {
820 for (x = *x1; x <= *x2; x++) {
821 switch (zcave[y][x].feat) {
822 /* Don't build on other buildings or farms */
823 case FEAT_LOOSE_DIRT:
824 case FEAT_CROP:
825 case FEAT_WALL_EXTRA:
826 case FEAT_PERM_EXTRA:
827 case FEAT_WALL_HOUSE:
828 case FEAT_LOGS:
829 plot_clear = 0;
830 break;
831 default: break;
832 }
833 #ifndef DEVEL_TOWN_COMPATIBILITY
834 /* any ickiness on the plot is NOT allowed */
835 if (zcave[y][x].info & CAVE_ICKY) plot_clear = 0;
836 /* spaces that have already been reserved are NOT allowed */
837 if (zcave[y][x].info & CAVE_XTRA) plot_clear = 0;
838 #endif
839 }
840 }
841
842 /* hack -- buildings and farms can partially, but not completly,
843 be built on water. */
844 if ( (zcave[*y1][*x1].feat == FEAT_DEEP_WATER) &&
845 (zcave[*y2][*x2].feat == FEAT_DEEP_WATER) ) plot_clear = 0;
846
847 /* if we have a clear plot, reserve it and return */
848 if (plot_clear) {
849 for (y = *y1; y <= *y2; y++) {
850 for (x = *x1; x <= *x2; x++) {
851 zcave[y][x].info |= CAVE_XTRA;
852 }
853 }
854 return;
855 }
856
857 attempts++;
858 }
859
860 /* plot allocation failed */
861 *x1 = *y1 = *x2 = *y2 = -1;
862 }
863
864 /* Adds a garden a reasonable distance from x,y.
865 Some crazy games are played with the RNG, so that whether we are dropping
866 food or not will not effect the final state it is in.
867 */
868
wild_add_garden(struct worldpos * wpos,int x,int y)869 static void wild_add_garden(struct worldpos *wpos, int x, int y)
870 {
871 int x1, y1, x2, y2, type, xlen, ylen;
872 #ifdef DEVEL_TOWN_COMPATIBILITY
873 int attempts = 0;
874 #endif
875 int i;
876 char orientation;
877 object_type food, *o_ptr;
878 int tmp_seed;
879 wilderness_type *w_ptr = &wild_info[wpos->wy][wpos->wx];
880 cave_type **zcave;
881 if (!(zcave = getcave(wpos))) return;
882
883 x1 = x2 = y1 = y2 = -1;
884
885 /* choose which type of garden it is */
886 type = rand_int(7);
887
888 /* choose a 'good' location for the garden */
889
890 xlen = rand_int(rand_int(60)) + 15;
891 ylen = rand_int(rand_int(20)) + 7;
892
893 #ifdef DEVEL_TOWN_COMPATIBILITY
894 /* hack -- maximum distance to house -- 30 */
895 while (attempts < 100) {
896 #endif
897
898 reserve_building_plot(wpos, &x1,&y1, &x2,&y2, xlen, ylen, -1, -1);
899 #ifdef DEVEL_TOWN_COMPATIBILITY
900 /* we have obtained a valid plot */
901 if (x1 > 0) {
902 /* maximum distance to field of 40 */
903 if ( ((x1-x)*(x1-x) + (y1-y)*(y1-y) <= 40*40) ||
904 ((x2-x)*(x2-x) + (y2-y)*(y2-y) <= 40*40) ) break;
905 }
906 attempts++;
907 }
908 #endif
909
910 /* if we failed to obtain a valid plot */
911 if (x1 < 0) return;
912
913 /* whether the crop rows are horizontal or vertical */
914 orientation = rand_int(2);
915
916 /* initially fill with a layer of dirt */
917 for (y = y1; y <= y2; y++) {
918 for (x = x1; x <= x2; x++) {
919 zcave[y][x].feat = FEAT_LOOSE_DIRT;
920 }
921 }
922
923 /* save the RNG */
924 tmp_seed = Rand_value;
925
926 /* randomize, so food doesn't grow at always same garden coordinates */
927 Rand_value = turn;
928
929 /* initially clear all previous items from it! */
930 if (!(w_ptr->flags & WILD_F_GARDENS))
931 for (i = 0; i < o_max; i++) {
932 o_ptr = &o_list[i];
933 /* Skip dead objects */
934 if (!o_ptr->k_idx) continue;
935 /* Skip objects not here */
936 if (!inarea(&o_ptr->wpos, wpos)) continue;
937 /* Skip carried objects */
938 if (o_ptr->held_m_idx) continue;
939 /* if it's on our field, erase it */
940 if (o_ptr->iy >= y1 && o_ptr->iy <= y2 &&
941 o_ptr->ix >= x1 && o_ptr->ix <= x2)
942 delete_object_idx(i, TRUE);
943 }
944
945 /* alternating rows of crops */
946 for (y = y1+1; y <= y2-1; y ++) {
947 for (x = x1+1; x <= x2-1; x++) {
948 /* different orientations */
949 if (((!orientation) && (y%2)) || ((orientation) && (x%2))) {
950 /* set to crop */
951 zcave[y][x].feat = FEAT_CROP;
952 /* random chance of food */
953 if (rand_int(100) < 40) {
954 switch (type) {
955 case WILD_CROP_POTATO:
956 invcopy(&food, lookup_kind(TV_FOOD, SV_FOOD_POTATO));
957 break;
958
959 case WILD_CROP_CABBAGE:
960 invcopy(&food, lookup_kind(TV_FOOD, SV_FOOD_HEAD_OF_CABBAGE));
961 break;
962
963 case WILD_CROP_CARROT:
964 invcopy(&food, lookup_kind(TV_FOOD, SV_FOOD_CARROT));
965 break;
966
967 case WILD_CROP_BEET:
968 invcopy(&food, lookup_kind(TV_FOOD, SV_FOOD_BEET));
969 break;
970
971 case WILD_CROP_SQUASH:
972 invcopy(&food, lookup_kind(TV_FOOD, SV_FOOD_SQUASH));
973 break;
974
975 case WILD_CROP_CORN:
976 invcopy(&food, lookup_kind(TV_FOOD, SV_FOOD_EAR_OF_CORN));
977 break;
978
979 /* hack -- useful mushrooms are rare */
980 case WILD_CROP_MUSHROOM:
981 invcopy(&food, lookup_kind(TV_FOOD, rand_int(rand_int(20))));
982 break;
983 default:
984 invcopy(&food, lookup_kind(TV_FOOD, SV_FOOD_SLIME_MOLD));
985 break;
986 }
987 /* Hack -- only drop food the first time */
988 food.marked2 = ITEM_REMOVAL_NEVER;
989 if (!(w_ptr->flags & WILD_F_GARDENS)) drop_near(&food, -1, wpos, y, x);
990 }
991 }
992 }
993 }
994 /* restore the RNG */
995 Rand_value = tmp_seed;
996 }
997
998
wild_monst_aux_invaders(int r_idx)999 static bool wild_monst_aux_invaders(int r_idx)
1000 {
1001 monster_race *r_ptr = &r_info[r_idx];
1002
1003 if(r_ptr->flags7 & RF7_AQUATIC) return FALSE;
1004
1005 /* invader species */
1006 if (strchr("oTpOKbrm", r_ptr->d_char)) return TRUE;
1007 if (!strcmp(&r_name[r_ptr->name],"Dark elven mage")) return TRUE;
1008 if (!strcmp(&r_name[r_ptr->name],"Dark elven priest")) return TRUE;
1009 if (!strcmp(&r_name[r_ptr->name],"Dark elven warrior")) return TRUE;
1010
1011 return FALSE;
1012 }
1013
wild_monst_aux_home_owner(int r_idx)1014 static bool wild_monst_aux_home_owner(int r_idx)
1015 {
1016 monster_race *r_ptr = &r_info[r_idx];
1017
1018 /* not aquatic */
1019 if (r_ptr->flags7 & RF7_AQUATIC) return FALSE;
1020
1021 /* home owner species */
1022 if (strchr("hpP", r_ptr->d_char)) return TRUE;
1023
1024 return FALSE;
1025 }
1026
wild_obj_aux_bones(int k_idx,u32b resf)1027 static int wild_obj_aux_bones(int k_idx, u32b resf)
1028 {
1029 object_kind *k_ptr = &k_info[k_idx];
1030
1031 /* paranoia */
1032 if (k_idx < 0) return 0;
1033
1034 if (k_ptr->tval == TV_SKELETON) return 100;
1035
1036 return 0;
1037 }
1038
1039 /* make a dwelling (building in the wilderness) 'interesting'.
1040 */
wild_furnish_dwelling(struct worldpos * wpos,int x1,int y1,int x2,int y2,int type)1041 static void wild_furnish_dwelling(struct worldpos *wpos, int x1, int y1, int x2, int y2, int type)
1042 {
1043 int x,y, cash, num_food, num_objects, num_bones, trys, r_idx, k_idx, food_sval;
1044 bool inhabited, at_home, taken_over;
1045 object_type forge;
1046 u32b old_seed = Rand_value;
1047 wilderness_type *w_ptr = &wild_info[wpos->wy][wpos->wx];
1048 cave_type **zcave;
1049 if (!(zcave = getcave(wpos))) return;
1050
1051 trys = cash = num_food = num_objects = num_bones = 0;
1052 inhabited = at_home = taken_over = FALSE;
1053
1054 /* hack -- 75% of buildings are inhabited */
1055 if (rand_int(100) < 75) inhabited = TRUE;
1056
1057 switch (type) {
1058 case WILD_LOG_CABIN:
1059 /* possibly add a farm */
1060 /* hack -- no farms near the town */
1061 if (w_ptr->radius > 1) {
1062 /* are we a farmer? */
1063 if (rand_int(100) < 50) wild_add_garden(wpos, (x1+x2)/2,(y1+y2)/2);
1064 }
1065 case WILD_ROCK_HOME:
1066 /* hack -- no farms near the town */
1067 if (w_ptr->radius > 1) {
1068 /* are we a farmer? */
1069 if (rand_int(100) < 40) wild_add_garden(wpos, (x1+x2)/2,(y1+y2)/2);
1070 }
1071
1072 case WILD_PERM_HOME:
1073 if (inhabited) {
1074 /* is someone to be found at this house */
1075 if (rand_int(100) < 80) at_home = TRUE;
1076
1077 /* is there any food inside */
1078 if (rand_int(100) < 80) num_food = rand_int(rand_int(20));
1079
1080 /* is there any cash inside */
1081 if (rand_int(100) < 40) cash = rand_int(10);
1082
1083 /* are there objects to be found */
1084 if (rand_int(100) < 50) num_objects = rand_int(rand_int(10));
1085 } else {
1086 if (rand_int(100) < 50) {
1087 /* taken over! */
1088 taken_over = TRUE;
1089 if (rand_int(100) < 40) cash = rand_int(20);
1090 if (rand_int(100) < 50) num_objects = rand_int(rand_int(10));
1091 if (rand_int(100) < 33) num_food = rand_int(3);
1092 num_bones = rand_int(20);
1093 }
1094 num_bones = rand_int(rand_int(1));
1095 }
1096 break;
1097 }
1098
1099
1100 /* add the cash */
1101 if (!(w_ptr->flags & WILD_F_CASH) && cash) {
1102 /* try to place the cash */
1103 while (trys < 50) {
1104 x = rand_range(x1,x2);
1105 y = rand_range(y1,y2);
1106
1107 if (cave_clean_bold(zcave,y,x)) {
1108 object_level = cash;
1109 place_gold(wpos,y,x, 0);
1110 break;
1111 }
1112 trys++;
1113 }
1114 }
1115
1116 /* add the objects */
1117 if (!(w_ptr->flags & WILD_F_OBJECTS)) {
1118 trys = 0;
1119 place_object_restrictor = RESF_NOHIDSM;
1120 while ((num_objects) && (trys < 300)) {
1121 x = rand_range(x1,x2);
1122 y = rand_range(y1,y2);
1123
1124 if (cave_clean_bold(zcave,y,x)) {
1125 object_level = w_ptr->radius/2 +1;
1126 place_object(wpos, y, x, FALSE, FALSE, FALSE, RESF_LOW, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
1127 num_objects--;
1128 }
1129 trys++;
1130 }
1131 place_object_restrictor = RESF_NONE;
1132 }
1133
1134 /* add the food */
1135 if (!(w_ptr->flags & WILD_F_FOOD)) {
1136 trys = 0;
1137 while ((num_food) && (trys < 100)) {
1138 x = rand_range(x1,x2);
1139 y = rand_range(y1,y2);
1140
1141 if (cave_clean_bold(zcave,y,x)) {
1142 food_sval = SV_FOOD_MIN_FOOD+rand_int(12);
1143 /* hack -- currently no food svals between 25 and 32 */
1144 if (food_sval > 25) food_sval += 6;
1145 /* hack -- currently no sval 34 */
1146 if (food_sval > 33) food_sval++;
1147
1148 k_idx = lookup_kind(TV_FOOD,food_sval);
1149 invcopy(&forge, k_idx);
1150 forge.marked2 = ITEM_REMOVAL_NEVER;
1151 drop_near(&forge, -1, wpos, y, x);
1152
1153 num_food--;
1154 }
1155 trys++;
1156 }
1157 }
1158
1159 /* add the bones */
1160 if (!(w_ptr->flags & WILD_F_BONES)) {
1161 trys = 0;
1162 get_obj_num_hook = wild_obj_aux_bones;
1163 get_obj_num_prep(RESF_WILD);
1164
1165 while ((num_bones) && (trys < 100)) {
1166 x = rand_range(x1,x2);
1167 y = rand_range(y1,y2);
1168
1169 if (cave_clean_bold(zcave,y,x)) {
1170 /* base of 500 feet for the bones */
1171 k_idx = get_obj_num(10, RESF_NONE);
1172 invcopy(&forge, k_idx);
1173 forge.marked2 = ITEM_REMOVAL_NEVER;
1174 drop_near(&forge, -1, wpos, y, x);
1175
1176 num_bones--;
1177 }
1178 trys++;
1179 }
1180 }
1181
1182
1183 /* hack -- restore the old object selection function */
1184 get_obj_num_hook = NULL;
1185 get_obj_num_prep(RESF_NONE);
1186
1187 /* add the inhabitants */
1188 if (!(w_ptr->flags & WILD_F_HOME_OWNERS)) {
1189 if (at_home) {
1190 /* determine the home owners species */
1191 get_mon_num_hook = wild_monst_aux_home_owner;
1192
1193 /* Set the second hook according to the floor type */
1194 set_mon_num2_hook(zcave[y1][x1].feat);
1195
1196 get_mon_num_prep(0, NULL);
1197
1198 /* homeowners can be tough */
1199 r_idx = get_mon_num(w_ptr->radius, w_ptr->radius);
1200
1201 /* get the owners location */
1202 #if 0 /* won't this cause monsters to be randomly spawned possibly _inside adjancent player houses_? o_O */
1203 x = rand_range(x1, x2) + rand_int(40) - 20;
1204 y = rand_range(y1, y2) + rand_int(16) - 8;
1205 #else
1206 x = rand_range(x1, x2);
1207 y = rand_range(y1, y2);
1208 #endif
1209
1210 /* place the owner */
1211 summon_override_checks = SO_HOUSE;
1212 place_monster_aux(wpos, y, x, r_idx, FALSE, FALSE, FALSE, 0);
1213 summon_override_checks = SO_NONE;
1214 }
1215 }
1216
1217 /* add the invaders */
1218 if (!(w_ptr->flags & WILD_F_INVADERS)) {
1219 if (taken_over) {
1220 /* determine the invaders species*/
1221 get_mon_num_hook = wild_monst_aux_invaders;
1222
1223 /* Set the second hook according to the floor type */
1224 set_mon_num2_hook(zcave[y1][x1].feat);
1225
1226 get_mon_num_prep(0, NULL);
1227 r_idx = get_mon_num((w_ptr->radius / 2) + 1, w_ptr->radius / 2);
1228
1229 /* add the monsters */
1230 summon_override_checks = SO_HOUSE;
1231 for (y = y1; y <= y2; y++) {
1232 for (x = x1; x <= x2; x++) {
1233 place_monster_aux(wpos, y,x, r_idx, FALSE, FALSE, FALSE, 0);
1234 }
1235 }
1236 summon_override_checks = SO_NONE;
1237 }
1238 }
1239
1240
1241 /* hack -- restore the RNG */
1242 Rand_value = old_seed;
1243 }
1244
1245 /* check if a location is suitable for placing a door - Jir - */
1246 /* TODO: check for houses built *after* door creation */
1247 #ifdef __DISABLE_HOUSEBOOST
dwelling_check_entrance(worldpos * wpos,int y,int x)1248 static bool dwelling_check_entrance(worldpos *wpos, int y, int x)
1249 {
1250 int i;
1251 cave_type *c_ptr;
1252 cave_type **zcave;
1253 if (!(zcave = getcave(wpos))) return(FALSE);
1254
1255 for (i = 1; i < tdi[1]; i++) {
1256 c_ptr = &zcave[y + tdy[i]][x + tdx[i]];
1257
1258 /* Inside a house */
1259 if (c_ptr->info & CAVE_ICKY) continue;
1260
1261 /* Wall blocking the door */
1262 if (f_info[c_ptr->feat].flags1 & FF1_WALL) continue;
1263
1264 /* Nasty terrain covering the door */
1265 if (c_ptr->feat == FEAT_DEEP_WATER || c_ptr->feat == FEAT_DEEP_LAVA)
1266 continue;
1267
1268 /* Found a neat entrance */
1269 return (TRUE);
1270 }
1271
1272 /* Assume failure */
1273 return (FALSE);
1274 }
1275 #else
dwelling_check_entrance(worldpos * wpos,int y,int x,int dir)1276 static bool dwelling_check_entrance(worldpos *wpos, int y, int x, int dir) {
1277 /*
1278 * HACK: There's a bug below where negative indices were accessed in ddx_cyc and ddy_cyc.
1279 * The result is undefined and depends on which compiler is used.
1280 * In order to preserve housing layout on the official server, we're going to emulate negative indices.
1281 * If we decide to do a worldmap reset, this hack can be removed.
1282 * - mikaelh
1283 */
1284 #define EMULATE_NEGATIVE_INDICES
1285 #ifdef EMULATE_NEGATIVE_INDICES
1286 static s16b ddx_cyc_emul[10] = { -1, 0, -1, 0, 1, 1, 1, 0, -1, -1 };
1287 static s16b ddy_cyc_emul[10] = { -1, -1, -1, -1, -1, 0, 1, 1, 1, 0 };
1288 static s16b *ddx_cyc = &ddx_cyc_emul[2];
1289 static s16b *ddy_cyc = &ddy_cyc_emul[2];
1290 #endif
1291 int i;
1292 cave_type *c_ptr;
1293 cave_type **zcave;
1294 if (!(zcave = getcave(wpos))) return FALSE;
1295
1296 switch (dir) {
1297 /* corners: 5 adjacent grids to check */
1298 case 0: case 2: case 4: case 6:
1299 for (i = -2; i <= 2; i++) {
1300 #ifdef EMULATE_NEGATIVE_INDICES
1301 c_ptr = &zcave[y + ddy_cyc[(dir + i) % 8]][x + ddx_cyc[(dir + i) % 8]];
1302 #else
1303 c_ptr = &zcave[y + ddy_cyc[(dir + i + 8) % 8]][x + ddx_cyc[(dir + i + 8) % 8]];
1304 #endif
1305
1306 /* Inside a house */
1307 if (c_ptr->info & CAVE_ICKY) continue;
1308
1309 /* Wall blocking the door */
1310 if (f_info[c_ptr->feat].flags1 & FF1_WALL) continue;
1311
1312 /* Nasty terrain covering the door */
1313 if (c_ptr->feat == FEAT_DEEP_WATER || c_ptr->feat == FEAT_DEEP_LAVA)
1314 continue;
1315
1316 /* Found a neat entrance */
1317 return TRUE;
1318 }
1319 break;
1320 /* sides: 3 adjacent grids to check */
1321 case 1: case 3: case 5: case 7:
1322 for (i = -1; i <= 1; i++) {
1323 c_ptr = &zcave[y + ddy_cyc[(dir + i) % 8]][x + ddx_cyc[(dir + i) % 8]];
1324
1325 /* Inside a house */
1326 if (c_ptr->info & CAVE_ICKY) continue;
1327
1328 /* Wall blocking the door */
1329 if (f_info[c_ptr->feat].flags1 & FF1_WALL) continue;
1330
1331 /* Nasty terrain covering the door */
1332 if (c_ptr->feat == FEAT_DEEP_WATER || c_ptr->feat == FEAT_DEEP_LAVA)
1333 continue;
1334
1335 /* Found a neat entrance */
1336 return TRUE;
1337 }
1338 break;
1339 }
1340
1341 /* Assume failure */
1342 return FALSE;
1343 }
1344 #endif
1345
1346 /* adds a building to the wilderness. if the coordinate is not given,
1347 find it randomly.
1348
1349 for now will make a simple box,
1350 but we could do really fun stuff with this later.
1351 */
wild_add_dwelling(struct worldpos * wpos,int x,int y)1352 static void wild_add_dwelling(struct worldpos *wpos, int x, int y)
1353 {
1354 int h_x1,h_y1,h_x2,h_y2, p_x1,p_y1,p_x2,p_y2,
1355 plot_xlen, plot_ylen, house_xlen, house_ylen,
1356 door_x, door_y, drawbridge_x[3], drawbridge_y[3],
1357 tmp, type, area, num_door_attempts;
1358 int size;
1359 #ifndef __DISABLE_HOUSEBOOST
1360 int xx, yy, door_dir = 0;
1361 bool hinders_door = FALSE;
1362 #endif
1363 char wall_feature = 0, door_feature = 0;
1364 char has_moat = 0;
1365 cave_type *c_ptr;
1366 bool rand_old = Rand_quick;
1367 bool trad = !magik(MANG_HOUSE_RATE);
1368 wilderness_type *w_ptr = &wild_info[wpos->wy][wpos->wx];
1369 cave_type **zcave;
1370 u32b floor_info;
1371
1372 if (!(zcave = getcave(wpos))) return;
1373
1374 /* Initialize drawbridge_x and drawbridge_y to make gcc happy */
1375 drawbridge_x[0] = drawbridge_x[1] = drawbridge_x[2] = 0;
1376 drawbridge_y[0] = drawbridge_y[1] = drawbridge_y[2] = 0;
1377
1378 /* Hack -- Use the "simple" RNG */
1379 Rand_quick = TRUE;
1380
1381 /* Hack -- Induce consistant wilderness */
1382 /* Rand_value = seed_town + (Depth * 600) + (w_ptr->dwellings * 200);*/
1383
1384
1385 /* find the dimensions of the house -
1386 depends on its placement within MAX_TOWNAREA */
1387
1388 #ifdef DEVEL_TOWN_COMPATIBILITY
1389 house_xlen = rand_int(10) + 3;
1390 house_ylen = rand_int(5) + 3;
1391 plot_xlen = house_xlen;
1392 plot_ylen = house_ylen;
1393 #else
1394 /* chance of being a "large" house */
1395 #ifdef __DISABLE_HOUSEBOOST
1396 if (!rand_int(2)) {
1397 #else
1398 /* more *huge* houses (villas) on the outskirts */
1399 if (w_ptr->radius == 3 && rand_int(3)) {
1400 house_xlen = rand_int(5) + rand_int(5) + 19;
1401 house_ylen = rand_int(3) + rand_int(3) + 10;
1402 }
1403 /* less "large" houses (to leave room for *huge* houses) in radius 3 */
1404 else if (!rand_int(w_ptr->radius == 3 ? 4 : 2)) {
1405 #endif
1406 house_xlen = rand_int(10) + rand_int(rand_int(10)) + 9;
1407 house_ylen = rand_int(5) + rand_int(rand_int(5)) + 6;
1408 }
1409 /* chance of being a "small" house */
1410 #ifdef __DISABLE_HOUSEBOOST
1411 else if (!rand_int(2)) {
1412 #else
1413 else if (!rand_int(w_ptr->radius == 1 ? 8 : 12)) {
1414 #endif
1415 house_xlen = rand_int(4) + 3;
1416 house_ylen = rand_int(2) + 3;
1417 }
1418 /* a "normal" house */
1419 else {
1420 #ifdef __DISABLE_HOUSEBOOST
1421 house_xlen = rand_int(10) + 3;
1422 house_ylen = rand_int(5) + 3;
1423 #else
1424 house_xlen = rand_int(7) + 6;
1425 house_ylen = rand_int(4) + 4;
1426 #endif
1427 }
1428 area = (house_xlen-2) * (house_ylen-2);
1429
1430 /* find the dimensions of the "lawn" the house is built on */
1431 #ifdef __DISABLE_HOUSEBOOST
1432 if (area < 30) {
1433 #else
1434 if (area < 45) {
1435 #endif
1436 plot_xlen = house_xlen;
1437 plot_ylen = house_ylen;
1438 #ifdef __DISABLE_HOUSEBOOST
1439 } else if (area < 60) {
1440 plot_xlen = house_xlen + (area/15)*2;
1441 plot_ylen = house_ylen + (area/25)*2;
1442 //plot_xlen = house_xlen + (area/10)*2;
1443 //plot_ylen = house_ylen + (area/16)*2;
1444 trad = FALSE;
1445 } else {
1446 plot_xlen = house_xlen + (area/8)*2;
1447 plot_ylen = house_ylen + (area/14)*2;
1448 trad = FALSE;
1449 }
1450 #else /* less lawn */
1451 } else if (area < 100) {
1452 plot_xlen = house_xlen + (area/20);
1453 plot_ylen = house_ylen + (area/30);
1454 trad = FALSE;
1455 } else {
1456 plot_xlen = house_xlen + (area/20) + 5;
1457 plot_ylen = house_ylen + (area/30) + 4;
1458 trad = FALSE;
1459 }
1460 #endif
1461
1462 /* Hack -- sometimes large buildings get moats */
1463 #ifdef __DISABLE_HOUSEBOOST
1464 if ((area >= 70) && (!rand_int(16))) has_moat = 1;
1465 if ((area >= 80) && (!rand_int(6))) has_moat = 1;
1466 if ((area >= 100) && (!rand_int(2))) has_moat = 1;
1467 if ((area >= 130) && (rand_int(4) < 3)) has_moat = 1;
1468 #else
1469 #if 0/* actually made moats less likely again due to new cfg.castles_per_player - this will also save building space */
1470 if (area >= 80 && !rand_int(9)) has_moat = 1;
1471 if (area >= 80 && !rand_int(6)) has_moat = 1;
1472 if (area >= 100 && !rand_int(2)) has_moat = 1;
1473 if (area >= 130 && rand_int(4) < 3) has_moat = 1;
1474 #else
1475 // if (area >= 100 && !rand_int(15)) has_moat = 1;
1476 // else if (area >= 140 && !rand_int(9)) has_moat = 1;
1477 // else if (area >= 180 && !rand_int(4)) has_moat = 1;
1478 // else if (area >= 200 && !rand_int(2)) has_moat = 1;
1479 if (area >= 220 && rand_int(3)) has_moat = 1;
1480 #endif
1481 #endif
1482 if (has_moat) plot_xlen += 8;
1483 if (has_moat) plot_ylen += 8;
1484 #endif
1485
1486 /* Determine the plot's boundaries */
1487 reserve_building_plot(wpos, &p_x1, &p_y1, &p_x2, &p_y2, plot_xlen, plot_ylen, x, y);
1488 /* Determine the building's boundaries */
1489 h_x1 = p_x1 + ((plot_xlen - house_xlen)/2); h_y1 = p_y1 + ((plot_ylen - house_ylen)/2);
1490 h_x2 = p_x2 - ((plot_xlen - house_xlen)/2); h_y2 = p_y2 - ((plot_ylen - house_ylen)/2);
1491
1492 /* return if we didn't get a plot */
1493 if (p_x1 < 0) return;
1494
1495 /* initialise x and y, which may not be specified at this point */
1496 x = (h_x1 + h_x2) / 2;
1497 y = (h_y1 + h_y2) / 2;
1498
1499 /* determine what kind of building it is */
1500 if (rand_int(100) < 60) type = WILD_LOG_CABIN;
1501 else if (rand_int(100) < 8) type = WILD_PERM_HOME;
1502 else type = WILD_ROCK_HOME;
1503
1504 /* hack -- add extra "for sale" homes near the town */
1505 if (w_ptr->radius == 1) {
1506 /* hack -- not many log cabins near town */
1507 if (type == WILD_LOG_CABIN) {
1508 #ifdef __DISABLE_HOUSEBOOST
1509 if (rand_int(100) < 80) type = WILD_ROCK_HOME;
1510 #else
1511 if (rand_int(100) < 90) type = WILD_ROCK_HOME;
1512 #endif
1513 }
1514 #ifdef DEVEL_TOWN_COMPATIBILITY
1515 if (rand_int(100) < 40) type = WILD_TOWN_HOME;
1516 #else
1517 #ifdef __DISABLE_HOUSEBOOST
1518 if (rand_int(100) < 90) type = WILD_TOWN_HOME;
1519 #else
1520 if (rand_int(100) < 95) type = WILD_TOWN_HOME;
1521 #endif
1522 #endif
1523 }
1524 if (w_ptr->radius == 2)
1525 #ifdef DEVEL_TOWN_COMPATIBILITY
1526 if (rand_int(100) < 10) type = WILD_TOWN_HOME;
1527 #else
1528 #ifdef __DISABLE_HOUSEBOOST
1529 if (rand_int(100) < 80) type = WILD_TOWN_HOME;
1530 #else
1531 if (rand_int(100) < 90) type = WILD_TOWN_HOME;
1532 #endif
1533 #endif
1534 #ifndef __DISABLE_HOUSEBOOST
1535 if ((w_ptr->radius == 3 && rand_int(100) < 80)
1536 || has_moat) /* no log cabins or rock homes with moats... */
1537 type = WILD_TOWN_HOME;
1538
1539 /* also, no giant log cabins or rock homes (near towns) */
1540 if (type == WILD_LOG_CABIN && area >= 50) type = WILD_ROCK_HOME;
1541 if (type == WILD_ROCK_HOME && area >= 80 && w_ptr->radius <= 3) type = WILD_TOWN_HOME;
1542 #endif
1543
1544 #ifndef __DISABLE_HOUSEBOOST
1545 /* Make sure our building isn't placed so that its walls block a
1546 house door of another house that has previously been generated.
1547 What could still happen is that a door is within a 'backalley'
1548 that isn't actually accessible without phasing. - C. Blue */
1549 /* Determine the building's boundaries */
1550 for (xx = h_x1; xx <= h_x2; xx++) {
1551 if (zcave[h_y1 - 1][xx].feat == FEAT_HOME ||
1552 zcave[h_y1 - 1][xx].feat == FEAT_DOOR_HEAD) {
1553 /* reduce house height accordingly */
1554 h_y1++;
1555 hinders_door = TRUE;
1556 break;
1557 }
1558 }
1559 for (xx = h_x1; xx <= h_x2; xx++) {
1560 if (zcave[h_y2 + 1][xx].feat == FEAT_HOME ||
1561 zcave[h_y2 + 1][xx].feat == FEAT_DOOR_HEAD) {
1562 /* reduce house height accordingly */
1563 h_y2--;
1564 hinders_door = TRUE;
1565 break;
1566 }
1567 }
1568 for (yy = h_y1; yy <= h_y2; yy++) {
1569 if (zcave[yy][h_x1 - 1].feat == FEAT_HOME ||
1570 zcave[yy][h_x1 - 1].feat == FEAT_DOOR_HEAD) {
1571 /* reduce house height accordingly */
1572 h_x1++;
1573 hinders_door = TRUE;
1574 break;
1575 }
1576 }
1577 for (yy = h_y1; yy <= h_y2; yy++) {
1578 if (zcave[yy][h_x2 + 1].feat == FEAT_HOME ||
1579 zcave[yy][h_x2 + 1].feat == FEAT_DOOR_HEAD) {
1580 /* reduce house height accordingly */
1581 h_x2--;
1582 hinders_door = TRUE;
1583 break;
1584 }
1585 }
1586
1587 /* Recalculate house parameters? */
1588 if (hinders_door) {
1589 /* has house become too small now (smaller than 3x3)? -> abort */
1590 if (h_x2 - h_x1 < 2 || h_y2 - h_y1 < 2) return;
1591
1592 area = (h_x2 - h_x1 - 1) * (h_y2 - h_y1 - 1);
1593
1594 x = (h_x1 + h_x2) / 2;
1595 y = (h_y1 + h_y2) / 2;
1596 }
1597 #endif
1598
1599 switch (type) {
1600 case WILD_LOG_CABIN:
1601 wall_feature = FEAT_LOGS;
1602
1603 /* doors are locked 1/3 of the time */
1604 if (rand_int(100) < 33) door_feature = FEAT_DOOR_HEAD + rand_int(7);
1605 else door_feature = FEAT_DOOR_HEAD;
1606
1607 break;
1608 case WILD_PERM_HOME:
1609 wall_feature = FEAT_PERM_EXTRA;
1610 // wall_feature = FEAT_WALL_HOUSE;
1611
1612 /* doors are locked 90% of the time */
1613 if (rand_int(100) < 90) door_feature = FEAT_DOOR_HEAD + rand_int(7);
1614 else door_feature = FEAT_DOOR_HEAD;
1615 break;
1616 case WILD_ROCK_HOME:
1617 wall_feature = FEAT_WALL_EXTRA;
1618
1619 /* doors are locked 60% of the time */
1620 if (rand_int(100) < 60) door_feature = FEAT_DOOR_HEAD + rand_int(7);
1621 else door_feature = FEAT_DOOR_HEAD;
1622 break;
1623 case WILD_TOWN_HOME:
1624 // wall_feature = FEAT_PERM_EXTRA;
1625 wall_feature = FEAT_WALL_HOUSE;
1626 door_feature = FEAT_HOME;
1627
1628 /* hack -- setup next possibile house addition */
1629 MAKE(houses[num_houses].dna, struct dna_type);
1630 houses[num_houses].x = h_x1;
1631 houses[num_houses].y = h_y1;
1632 houses[num_houses].flags = HF_RECT|HF_STOCK;
1633 if (trad) houses[num_houses].flags |= HF_TRAD;
1634 if (has_moat) houses[num_houses].flags |= HF_MOAT;
1635 houses[num_houses].coords.rect.width = h_x2-h_x1+1;
1636 houses[num_houses].coords.rect.height = h_y2-h_y1+1;
1637 wpcopy(&houses[num_houses].wpos, wpos);
1638 houses[num_houses].dna->price = initial_house_price(&houses[num_houses]);
1639 break;
1640 }
1641
1642
1643 /* select the door location... done here so we can
1644 try to prevent it form being put on water. */
1645
1646 /* hack -- avoid doors in water */
1647 /* avoid lava and wall too */
1648 num_door_attempts = 0;
1649 do {
1650 /* Pick a door direction (S,N,E,W) */
1651 tmp = rand_int(4);
1652
1653 /* Extract a "door location" */
1654 switch (tmp) {
1655 /* Bottom side */
1656 case DIR_SOUTH:
1657 door_y = h_y2;
1658 door_x = rand_range(h_x1, h_x2);
1659 if (has_moat) {
1660 drawbridge_y[0] = h_y2+1; drawbridge_y[1] = h_y2+2;
1661 drawbridge_y[2] = h_y2+3;
1662 drawbridge_x[0] = door_x; drawbridge_x[1] = door_x;
1663 drawbridge_x[2] = door_x;
1664 }
1665 #ifndef __DISABLE_HOUSEBOOST
1666 /* door directly on a corner? */
1667 if (door_x == h_x1) door_dir = 6;
1668 else if (door_x == h_x2) door_dir = 4;
1669 else door_dir = 5;
1670 #endif
1671 break;
1672 /* Top side */
1673 case DIR_NORTH:
1674 door_y = h_y1;
1675 door_x = rand_range(h_x1, h_x2);
1676 if (has_moat) {
1677 drawbridge_y[0] = h_y1-1; drawbridge_y[1] = h_y1-2;
1678 drawbridge_y[2] = h_y1-3;
1679 drawbridge_x[0] = door_x; drawbridge_x[1] = door_x;
1680 drawbridge_x[2] = door_x;
1681 }
1682 #ifndef __DISABLE_HOUSEBOOST
1683 /* door directly on a corner? */
1684 if (door_x == h_x1) door_dir = 0;
1685 else if (door_x == h_x2) door_dir = 2;
1686 else door_dir = 1;
1687 #endif
1688 break;
1689 /* Right side */
1690 case DIR_EAST:
1691 door_y = rand_range(h_y1, h_y2);
1692 door_x = h_x2;
1693 if (has_moat) {
1694 drawbridge_y[0] = door_y; drawbridge_y[1] = door_y;
1695 drawbridge_y[2] = door_y;
1696 drawbridge_x[0] = h_x2+1; drawbridge_x[1] = h_x2+2;
1697 drawbridge_x[2] = h_x2+3;
1698 }
1699 #ifndef __DISABLE_HOUSEBOOST
1700 /* door directly on a corner? */
1701 if (door_y == h_y1) door_dir = 2;
1702 else if (door_y == h_y2) door_dir = 4;
1703 else door_dir = 3;
1704 #endif
1705 break;
1706 /* Left side */
1707 default:
1708 door_y = rand_range(h_y1, h_y2);
1709 door_x = h_x1;
1710 if (has_moat) {
1711 drawbridge_y[0] = door_y; drawbridge_y[1] = door_y;
1712 drawbridge_y[2] = door_y;
1713 drawbridge_x[0] = h_x1-1; drawbridge_x[1] = h_x1-2;
1714 drawbridge_x[2] = h_x1-3;
1715 }
1716 #ifndef __DISABLE_HOUSEBOOST
1717 /* door directly on a corner? */
1718 if (door_y == h_y1) door_dir = 0;
1719 else if (door_y == h_y2) door_dir = 6;
1720 else door_dir = 7;
1721 #endif
1722 break;
1723 }
1724
1725 #ifdef __DISABLE_HOUSEBOOST
1726 num_door_attempts++;
1727 } while (dwelling_check_entrance(wpos, door_y, door_x) && num_door_attempts < 30);
1728 #else
1729 /* Break on success */
1730 if (dwelling_check_entrance(wpos, door_y, door_x, door_dir)) break;
1731
1732 num_door_attempts++;
1733 } while (num_door_attempts < 20);
1734 #endif
1735
1736 /* Build a rectangular building */
1737 for (y = h_y1; y <= h_y2; y++) {
1738 for (x = h_x1; x <= h_x2; x++) {
1739 /* Get the grid */
1740 c_ptr = &zcave[y][x];
1741
1742 /* Clear previous contents, add "basic" perma-wall */
1743 c_ptr->feat = wall_feature;
1744 }
1745 }
1746
1747
1748 /* set default floor info */
1749 floor_info = CAVE_ICKY;
1750
1751 /* does house already exist (created at server start)
1752 or has it just been created for the first time? */
1753 tmp = pick_house(wpos, door_y, door_x);
1754
1755 /* is it a 'suspended' guild hall? */
1756 if (tmp != -1
1757 && houses[tmp].dna->owner && houses[tmp].dna->owner_type == OT_GUILD
1758 && !guilds[houses[tmp].dna->owner].master)
1759 floor_info |= CAVE_GUILD_SUS;
1760
1761 /* TODO: use coloured roof, so that they look cute :) */
1762 #ifndef USE_MANG_HOUSE_ONLY
1763 if (type != WILD_TOWN_HOME || !trad)
1764 #endif // USE_MANG_HOUSE_ONLY
1765 /* make it hollow */
1766 for (y = h_y1 + 1; y < h_y2; y++) {
1767 for (x = h_x1 + 1; x < h_x2; x++) {
1768 /* Get the grid */
1769 c_ptr = &zcave[y][x];
1770
1771 /* Fill with floor */
1772 c_ptr->feat = FEAT_FLOOR;
1773
1774 /* Make it "icky" (and maybe more) */
1775 c_ptr->info |= floor_info;
1776 }
1777 }
1778
1779
1780 /* add the door */
1781 c_ptr = &zcave[door_y][door_x];
1782 c_ptr->feat = door_feature;
1783
1784 #ifdef HOUSE_PAINTING
1785 /* Add colour if house is painted */
1786 if (tmp != -1) {
1787 house_type *h_ptr = &houses[tmp];
1788 cave_type *hc_ptr;
1789 if (h_ptr->colour) {
1790 for (x = door_x - 1; x <= door_x + 1; x++)
1791 for (y = door_y - 1; y <= door_y + 1; y++) {
1792 if (!in_bounds(y, x)) continue;
1793 hc_ptr = &zcave[y][x];
1794 if (hc_ptr->feat == FEAT_WALL_HOUSE ||
1795 hc_ptr->feat == FEAT_HOME)
1796 hc_ptr->colour = h_ptr->colour;
1797 }
1798 }
1799 }
1800 #endif
1801
1802 /* Build the moat */
1803 if (has_moat) {
1804 /* North / South */
1805 for (x = h_x1-2; x <= h_x2+2; x++) {
1806 zcave[h_y1-2][x].feat = FEAT_DEEP_WATER; zcave[h_y1-2][x].info |= CAVE_ICKY;
1807 zcave[h_y1-3][x].feat = FEAT_DEEP_WATER; zcave[h_y1-3][x].info |= CAVE_ICKY;
1808 zcave[h_y2+2][x].feat = FEAT_DEEP_WATER; zcave[h_y2+2][x].info |= CAVE_ICKY;
1809 zcave[h_y2+3][x].feat = FEAT_DEEP_WATER; zcave[h_y2+3][x].info |= CAVE_ICKY;
1810 }
1811 /* East / West */
1812 for (y = h_y1-2; y <= h_y2+2; y++) {
1813 /* Get the grid */
1814 zcave[y][h_x1-2].feat = FEAT_DEEP_WATER; zcave[y][h_x1-2].info |= CAVE_ICKY;
1815 zcave[y][h_x1-3].feat = FEAT_DEEP_WATER; zcave[y][h_x1-3].info |= CAVE_ICKY;
1816 zcave[y][h_x2+2].feat = FEAT_DEEP_WATER; zcave[y][h_x2+2].info |= CAVE_ICKY;
1817 zcave[y][h_x2+3].feat = FEAT_DEEP_WATER; zcave[y][h_x2+3].info |= CAVE_ICKY;
1818 }
1819 zcave[drawbridge_y[0]][drawbridge_x[0]].feat = FEAT_DRAWBRIDGE;
1820 zcave[drawbridge_y[0]][drawbridge_x[0]].info |= CAVE_ICKY;
1821 zcave[drawbridge_y[1]][drawbridge_x[1]].feat = FEAT_DRAWBRIDGE;
1822 zcave[drawbridge_y[1]][drawbridge_x[1]].info |= CAVE_ICKY;
1823 zcave[drawbridge_y[2]][drawbridge_x[2]].feat = FEAT_DRAWBRIDGE;
1824 zcave[drawbridge_y[2]][drawbridge_x[2]].info |= CAVE_ICKY;
1825 }
1826
1827 /* Hack -- finish making a town house */
1828 if (type == WILD_TOWN_HOME) {
1829 struct c_special *cs_ptr;
1830 /* hack -- only add a house if it is not already in memory;
1831 Means: If it hasn't already been created on server startup. */
1832 if (tmp == -1) {
1833 cs_ptr = AddCS(c_ptr, CS_DNADOOR); /* XXX this can fail? */
1834 // cs_ptr->type = CS_DNADOOR;
1835 cs_ptr->sc.ptr = houses[num_houses].dna;
1836 houses[num_houses].dx = door_x;
1837 houses[num_houses].dy = door_y;
1838 houses[num_houses].dna->creator = 0L;
1839 houses[num_houses].dna->owner = 0L;
1840
1841 #ifndef USE_MANG_HOUSE_ONLY
1842 /* This can be changed later - house capacity doesn't need
1843 * to be bound to the house size any more.
1844 * TODO: add 'extension' command
1845 * TODO: implement 'bank'
1846 */
1847 /* XXX maybe new owner will be unhappy if area>STORE_INVEN_MAX;
1848 * this will be fixed when STORE_INVEN_MAX will be removed. - Jir
1849 */
1850 if (trad) {
1851 size = (area >= STORE_INVEN_MAX) ? STORE_INVEN_MAX : area;
1852 houses[num_houses].stock_size = size;
1853 houses[num_houses].stock_num = 0;
1854 /* TODO: pre-allocate some when launching the server */
1855 C_MAKE(houses[num_houses].stock, size, object_type);
1856 } else {
1857 houses[num_houses].stock_size = 0;
1858 houses[num_houses].stock_num = 0;
1859 }
1860 #endif // USE_MANG_HOUSE_ONLY
1861
1862 num_houses++;
1863 if((house_alloc-num_houses)<32){
1864 GROW(houses, house_alloc, house_alloc+512, house_type);
1865 house_alloc += 512;
1866 }
1867 } else {
1868 cs_ptr = AddCS(c_ptr, CS_DNADOOR);
1869 /* evileye temporary fix */
1870 #if 1
1871 houses[tmp].coords.rect.width = houses[num_houses].coords.rect.width;
1872 houses[tmp].coords.rect.height = houses[num_houses].coords.rect.height;
1873 #endif
1874 /* end evileye fix */
1875 /* malloc madness otherwise */
1876 KILL(houses[num_houses].dna, struct dna_type);
1877 // cs_ptr->type = CS_DNADOOR;
1878 cs_ptr->sc.ptr = houses[tmp].dna;
1879 }
1880 }
1881
1882 /* make the building interesting */
1883 wild_furnish_dwelling(wpos, h_x1+1,h_y1+1,h_x2-1,h_y2-1, type);
1884
1885 /* Hack -- use the "complex" RNG */
1886 Rand_quick = rand_old;
1887 }
1888
1889
1890
1891
1892 /* auxillary function to determine_wilderness_type, used for terminating
1893 infinite loops of clones pointing at eachother. see below. originially
1894 counted the length of the loop, but as virtually all loops turned out
1895 to be 2 in length, it was revised to find the total depth of the loop.
1896 */
1897
1898 static int wild_clone_closed_loop_total(struct worldpos *wpos)
1899 {
1900 int total_depth;
1901 struct worldpos start, curr, neigh; //, total;
1902 //wilderness_type *w_ptr = &wild_info[wpos->wy][wpos->wx];
1903 int iter = 0; /* hack ;( locks otherwise */
1904
1905 total_depth = 0;
1906
1907 /* save our initial position */
1908 wpcopy(&start,wpos);
1909 wpcopy(&curr,wpos); /* dont damage the one we were given */
1910
1911 /* until we arrive back at our initial position */
1912 do {
1913 /* seed the number generator */
1914 Rand_value = seed_town + (curr.wx+curr.wy*MAX_WILD_X) * 600;
1915 /* HACK -- the second rand after the seed is used for the beginning of the clone
1916 directions (see below function). This rand sets things up. */
1917 rand_int(100);
1918
1919 wpcopy(&neigh, &curr);
1920 do {
1921 switch (rand_int(4)) {
1922 case 0:
1923 neigh.wx++;
1924 break;
1925 case 1:
1926 neigh.wy++;
1927 break;
1928 case 2:
1929 neigh.wx--;
1930 break;
1931 case 3:
1932 neigh.wy--;
1933 }
1934 } while ((neigh.wx < 0 || neigh.wy < 0 || neigh.wx >= MAX_WILD_X || neigh.wy >= MAX_WILD_Y));
1935 /* move to this new location */
1936 wpcopy(&curr, &neigh);
1937
1938 /* increase our loop total depth */
1939 total_depth += (curr.wx + curr.wy * MAX_WILD_X);
1940 iter++;
1941 } while (!inarea(&curr, &start) && iter < 50);
1942 return total_depth;
1943 }
1944
1945
1946 /* figure out what kind of terrain a depth is
1947 * this function assumes that wild_info's world_x and world_y values
1948 * have been set. */
1949
1950 /* Hack -- Read this for an explenation of the wilderness generation.
1951 * Each square is seeded with a seed dependent on its depth, and this is
1952 * used to find its terrain type.
1953 * If it is of type 'clone', then a random direction is picked, and
1954 * it becomes the type of terrain that its neighbor is, using recursion
1955 * if neccecary. This was causing problems with closed loops of clones,
1956 * so I came up with a mega-hack solution :
1957 * if we notice we are in a closed loop, find the total depth of the loop
1958 * by adding all its components, and use this to seed the pseudorandom
1959 * number generator and set the loops terrain.
1960 *
1961 * Note that a lot of this craziness is performed to keep the wilderness'
1962 * terrain types independent of the order in which they are explored;
1963 * they are completly defiend by the pseudorandom seed seed_town.
1964 */
1965
1966 int determine_wilderness_type(struct worldpos *wpos)
1967 {
1968 int closed_loop = -0xFFF;
1969 wilderness_type *w_ptr = &wild_info[wpos->wy][wpos->wx];
1970 struct worldpos neighbor;
1971
1972 bool rand_old = Rand_quick;
1973 u32b old_seed = Rand_value;
1974
1975 /* Hack -- Use the "simple" RNG */
1976 Rand_quick = TRUE;
1977
1978 /* Hack -- Induce consistant wilderness */
1979 Rand_value = seed_town + (wpos->wx+wpos->wy*MAX_WILD_X) * 600;
1980
1981 /* check if the town */
1982 if (istown(wpos)) return WILD_TOWN;
1983
1984 /* check if already defined */
1985 if ((w_ptr->type != WILD_UNDEFINED) && (w_ptr->type != WILD_CLONE)) return w_ptr->type;
1986
1987 /* check for infinite loops */
1988 if (w_ptr->type == WILD_CLONE) {
1989 /* Mega-Hack -- we are in a closed loop of clones, find the length of the loop
1990 and use this to seed the pseudorandom number generator. */
1991 closed_loop = wild_clone_closed_loop_total(wpos);
1992 Rand_value = seed_town + closed_loop * 8973;
1993 }
1994
1995 /* randomly determine the level type */
1996 /* hack -- if already a clone at this point, we are in a closed loop. We
1997 terminate the loop by picking a nonclone terrain type. Yes, this prevents
1998 "large" features from forming, but the resulting terrain is still rather
1999 pleasing.
2000 */
2001 if ((rand_int(100) < 101) && (w_ptr->type != WILD_CLONE)) w_ptr->type = WILD_CLONE;
2002 else if (rand_int(100) < 1) w_ptr->type = WILD_ICE;
2003 else if (rand_int(100) < 1) w_ptr->type = WILD_DESERT;
2004 else if (rand_int(100) < 3) w_ptr->type = WILD_WASTELAND;
2005 else if (rand_int(100) < 5) w_ptr->type = WILD_DENSEFOREST;
2006 else if (rand_int(100) < 40) w_ptr->type = WILD_FOREST;
2007 else if (rand_int(100) < 10) w_ptr->type = WILD_SWAMP;
2008 else if (rand_int(100) < 15) w_ptr->type = WILD_LAKE;
2009 else w_ptr->type = WILD_GRASSLAND;
2010
2011
2012 #ifdef DEVEL_TOWN_COMPATIBILITY
2013 /* hack -- grassland is likely next to the town */
2014 if (closed_loop > -20)
2015 if (rand_int(100) < 60) w_ptr->type = WILD_GRASSLAND;
2016 #endif
2017
2018 /* if a "clone", copy the terrain type from a neighbor, and recurse if neccecary. */
2019 if (w_ptr->type == WILD_CLONE) {
2020 neighbor.wx = wpos->wx;
2021 neighbor.wy = wpos->wy;
2022 neighbor.wz = wpos->wz; /* just for inarea */
2023
2024 /* get a legal neighbor index */
2025 /* illegal locations -- the town and off the edge */
2026
2027 while ((istown(&neighbor) || (neighbor.wx < 0 || neighbor.wy < 0 || neighbor.wx >= MAX_WILD_X || neighbor.wy >= MAX_WILD_Y))) {
2028 switch (rand_int(4)) {
2029 case 0:
2030 neighbor.wx++;
2031 break;
2032 case 1:
2033 neighbor.wy++;
2034 break;
2035 case 2:
2036 neighbor.wx--;
2037 break;
2038 case 3:
2039 neighbor.wy--;
2040 }
2041 }
2042 w_ptr->type = determine_wilderness_type(&neighbor);
2043
2044 #ifndef DEVEL_TOWN_COMPATIBILITY
2045 if (w_ptr->radius <= 2)
2046 switch (w_ptr->type) {
2047 /* no wastelands next to town */
2048 case WILD_WASTELAND :
2049 w_ptr->type = WILD_GRASSLAND; break;
2050 /* no deserts next to town */
2051 case WILD_DESERT :
2052 w_ptr->type = WILD_GRASSLAND; break;
2053 /* no ice next to town */
2054 case WILD_ICE :
2055 w_ptr->type = WILD_GRASSLAND; break;
2056 /* dense forest is rarly next to town */
2057 case WILD_DENSEFOREST :
2058 if (rand_int(100) < 80) w_ptr->type = WILD_GRASSLAND; break;
2059 /* people usually don't build towns next to a swamp */
2060 case WILD_SWAMP :
2061 if (rand_int(100) < 50) w_ptr->type = WILD_GRASSLAND; break;
2062 /* forest is slightly less common near a town */
2063 case WILD_FOREST :
2064 if (rand_int(100) < 30) w_ptr->type = WILD_GRASSLAND; break;
2065 }
2066 #endif
2067 }
2068 /* Hack -- use the "complex" RNG */
2069 Rand_quick = rand_old;
2070 /* Hack -- don't touch number generation. */
2071 Rand_value = old_seed;
2072
2073 return w_ptr->type;
2074 }
2075
2076
2077 typedef struct terrain_type terrain_type;
2078
2079 struct terrain_type
2080 {
2081 int type;
2082
2083 int grass;
2084 int mud;
2085 int water;
2086 int tree;
2087
2088 int deadtree;
2089 int mountain;
2090 int lava;
2091 int sand;
2092
2093 int ice;
2094 int dwelling;
2095 int hotspot;
2096 int monst_lev;
2097 };
2098
2099
2100 /* determines terrain composition. seperated from gen_wilderness_aux for bleed functions.*/
2101 static void init_terrain(terrain_type *t_ptr, int radius)
2102 {
2103 /* init all at zero */
2104 *t_ptr = (terrain_type) {t_ptr->type, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
2105
2106 switch (t_ptr->type) {
2107 /* wasteland */
2108 case WILD_VOLCANO:
2109 {
2110 #ifndef __DISABLE_NEW
2111 t_ptr->grass = rand_int(10);
2112 t_ptr->deadtree = rand_int(4);
2113 t_ptr->mountain = rand_int(100)+650;
2114 t_ptr->lava = rand_int(150)+400;
2115 #else
2116 t_ptr->grass = rand_int(100);
2117 t_ptr->deadtree = rand_int(4);
2118 t_ptr->mountain = rand_int(100)+450;
2119 t_ptr->lava = rand_int(150)+800;
2120 #endif
2121 t_ptr->hotspot = rand_int(15) + 4;
2122 t_ptr->monst_lev = 20 + (radius / 2); break;
2123 break;
2124 }
2125 case WILD_MOUNTAIN:
2126 {
2127 t_ptr->grass = rand_int(100);
2128 t_ptr->tree = rand_int(5);
2129 t_ptr->deadtree = rand_int(4);
2130 #ifndef __DISABLE_NEW
2131 t_ptr->mountain = rand_int(100)+700;
2132 t_ptr->sand = rand_int(1);
2133 t_ptr->lava = rand_int(10);
2134 #else
2135 t_ptr->mountain = rand_int(100)+850;
2136 t_ptr->lava = rand_int(150)+200;
2137 #endif
2138 t_ptr->hotspot = rand_int(15) + 4;
2139 t_ptr->monst_lev = 20 + (radius / 2); break;
2140 break;
2141 }
2142 case WILD_WASTELAND:
2143 {
2144 t_ptr->grass = rand_int(100);
2145 #ifndef __DISABLE_NEW
2146 t_ptr->sand = rand_int(2);
2147 #endif
2148 t_ptr->deadtree = rand_int(4);
2149 t_ptr->hotspot = rand_int(15) + 4;
2150 t_ptr->monst_lev = 20 + (radius / 2); break;
2151 break;
2152 }
2153 case WILD_DESERT:
2154 {
2155 t_ptr->sand = rand_int(10) + 990;
2156 t_ptr->mountain = rand_int(1);
2157 t_ptr->hotspot = rand_int(2);
2158 t_ptr->monst_lev = 10 + (radius / 2); break;
2159 break;
2160 }
2161 case WILD_ICE:
2162 {
2163 t_ptr->ice = 1000;
2164 t_ptr->mountain = rand_int(5);
2165 t_ptr->hotspot = rand_int(4) + 2;
2166 t_ptr->monst_lev = 20 + (radius / 2); break;
2167 break;
2168 }
2169 /* dense forest */
2170 case WILD_DENSEFOREST:
2171 {
2172 t_ptr->grass = rand_int(100)+850;
2173 t_ptr->tree = rand_int(150)+600;
2174 t_ptr->deadtree = rand_int(10)+5;
2175 t_ptr->water = rand_int(15);
2176 t_ptr->dwelling = 8;
2177 t_ptr->hotspot = rand_int(15) +4;
2178 t_ptr->monst_lev = 15 + (radius / 2);
2179 /* you don't want to go into an evil forst at night */
2180 if (IS_NIGHT) t_ptr->monst_lev += 10;
2181 break;
2182 }
2183 /* normal forest */
2184 case WILD_FOREST:
2185 {
2186 t_ptr->grass = rand_int(400)+500;
2187 t_ptr->tree = rand_int(200)+100;
2188 t_ptr->water = rand_int(20);
2189 /*t_ptr->mud = rand_int(5);*/
2190 t_ptr->dwelling = 37;
2191 t_ptr->hotspot = rand_int(rand_int(10));
2192 t_ptr->monst_lev = 5 + (radius / 2);
2193 break;
2194 }
2195 /* swamp */
2196 case WILD_SWAMP:
2197 {
2198 t_ptr->grass = rand_int(900);
2199 t_ptr->tree = rand_int(500);
2200 t_ptr->water = rand_int(450) + 300;
2201 /*t_ptr->mud = rand_int(100);*/
2202 t_ptr->dwelling = 8;
2203 t_ptr->hotspot = rand_int(15) + 4;
2204 t_ptr->monst_lev = 12 + (radius / 2);
2205 /* you really don't want to go into swamps at night */
2206 if (IS_NIGHT) t_ptr->monst_lev *= 2;
2207 break;
2208 }
2209 /* lake */
2210 case WILD_RIVER:
2211 case WILD_OCEAN:
2212 case WILD_LAKE:
2213 {
2214 t_ptr->grass = rand_int(900);
2215 t_ptr->tree = rand_int(400);
2216 t_ptr->water = rand_int(4) + 996;
2217 t_ptr->dwelling = 25;
2218 t_ptr->hotspot = rand_int(15) + 4;
2219 t_ptr->monst_lev = 1 + (radius / 2);
2220 break;
2221 }
2222 /* grassland / paranoia */
2223 default:
2224 {
2225 /* paranoia */
2226 t_ptr->type = WILD_GRASSLAND;
2227
2228 t_ptr->grass = rand_int(200) + 850;
2229 t_ptr->tree = rand_int(15);
2230 t_ptr->water = rand_int(10);
2231 t_ptr->dwelling = 100;
2232 t_ptr->hotspot = rand_int(rand_int(6));
2233 t_ptr->monst_lev = 1 + (radius / 2);
2234 break;
2235 }
2236 }
2237 /* HACK -- monster levels are now negative, to support
2238 * "wilderness only" monsters
2239 * XXX disabling this, causing problems.
2240 */
2241 t_ptr->monst_lev *= 1;
2242 }
2243
2244 static unsigned char terrain_spot(terrain_type * terrain)
2245 {
2246 unsigned char feat = FEAT_DIRT;
2247 u32b tmp_seed;
2248
2249 if (rand_int(1000) < terrain->grass) feat = FEAT_GRASS;
2250 #ifndef __DISABLE_NEW
2251 if (rand_int(1000) < terrain->sand) feat = FEAT_SAND;
2252 if (rand_int(1000) < terrain->ice) feat = magik(90) ? FEAT_SNOW : (magik(75) ? FEAT_ICE : FEAT_ICE_WALL);
2253 #endif
2254 #if 1
2255 if (rand_int(1000) < terrain->tree) {
2256 /* actually it's cool that whether it's a grown tree or a small bush
2257 isn't determined by the consistent wilderness seed */
2258 tmp_seed = Rand_value; /* save RNG */
2259 Rand_value = seed_wild_extra;
2260 feat = get_seasonal_tree();
2261 seed_wild_extra = Rand_value; /* don't reset but remember */
2262 Rand_value = tmp_seed;
2263 }
2264 #else
2265 if (rand_int(1000) < terrain->tree) feat = FEAT_TREE;
2266 #endif
2267 #ifdef __DISABLE_NEW
2268 if (rand_int(1000) < terrain->deadtree) feat = FEAT_DEAD_TREE;
2269 #endif
2270 if (rand_int(1000) < terrain->water) feat = FEAT_DEEP_WATER;
2271 if (rand_int(1000) < terrain->mud) feat = FEAT_MUD;
2272 if (rand_int(1000) < terrain->mountain) feat = FEAT_MOUNTAIN;
2273 if (rand_int(1000) < terrain->lava) feat = magik(30) ? FEAT_DEEP_LAVA : FEAT_SHAL_LAVA;
2274 #ifndef __DISABLE_NEW
2275 if (rand_int(1000) < terrain->deadtree) feat = FEAT_DEAD_TREE;
2276 #endif
2277
2278 return(feat);
2279 }
2280
2281
2282 /* adds an island in a lake, or a clearing in a forest, or a glade in a plain.
2283 done to make the levels a bit more interesting.
2284
2285 chopiness defines the randomness of the circular shape.
2286
2287 */
2288 /* XXX -- I should make this use the new terrain structure, and terrain_spot. */
2289
2290 static void wild_add_hotspot(struct worldpos *wpos)
2291 {
2292 int x_cen,y_cen, max_mag, magnitude, magsqr, chopiness, x, y;
2293 terrain_type hot_terrain;
2294 bool add_dwelling = FALSE;
2295 wilderness_type *w_ptr = &wild_info[wpos->wy][wpos->wx];
2296 cave_type **zcave;
2297 if (!(zcave = getcave(wpos))) return;
2298
2299 magnitude = 0;
2300 /* set the terrain features to 0 by default */
2301 memset(&hot_terrain,0,sizeof(terrain_type));
2302
2303 /* hack -- minimum hotspot radius of 3 */
2304 while (magnitude < 3) {
2305 /* determine the rough "coordinates" of the feature */
2306 x_cen = rand_int(MAX_WID-11) + 5;
2307 y_cen = rand_int(MAX_HGT-11) + 5;
2308
2309 /* determine the maximum size of the feature, which is its distance to
2310 its closest edge.
2311 */
2312 max_mag = y_cen;
2313 if (x_cen < max_mag) max_mag = x_cen;
2314 if ((MAX_HGT - y_cen) < max_mag) max_mag = MAX_HGT - y_cen;
2315 if ((MAX_WID - x_cen) < max_mag) max_mag = MAX_WID - x_cen;
2316
2317 /* determine the magnitude of the feature. the triple rand is done to
2318 keep most features small, but have a rare large one. */
2319
2320 magnitude = rand_int(rand_int(rand_int(max_mag)));
2321 }
2322
2323 /* hack -- take the square to avoid square roots */
2324 magsqr = magnitude * magnitude;
2325
2326 /* the "roughness" of the hotspot */
2327 chopiness = 2 * magsqr / (rand_int(5) + 1);
2328
2329 /* for each point in the square enclosing the circle
2330 this algorithm could probably use some optimization
2331 */
2332 switch (w_ptr->type) {
2333 case WILD_GRASSLAND:
2334 /* sometimes a pond */
2335 if (rand_int(100) < 50) {
2336 hot_terrain.water = 1000;
2337 }
2338 /* otherwise a glade */
2339 else {
2340 hot_terrain.grass = rand_int(200) + 850;
2341 hot_terrain.tree = rand_int(600) + 300;
2342 }
2343 break;
2344 case WILD_FOREST:
2345 /* sometimes a pond */
2346 if (rand_int(100) < 60) {
2347 hot_terrain.water = 1000;
2348 }
2349 /* otherwise a clearing */
2350 else {
2351 hot_terrain.grass = rand_int(150)+900;
2352 hot_terrain.tree = rand_int(6)-3;
2353
2354 /* if a large clearing, maybe a house */
2355 if (magnitude > 8) {
2356 if (rand_int(100) < 25) add_dwelling = TRUE;
2357 }
2358 }
2359 break;
2360 case WILD_DENSEFOREST:
2361 /* 80% chance of being nothing */
2362 if (rand_int(100) < 80) {
2363 }
2364 /* otherwise 70% chance of being a pond */
2365 else if (rand_int(100) < 70) {
2366 hot_terrain.water = 1000;
2367 }
2368 /* otherwise a rare clearing */
2369 else {
2370 hot_terrain.tree = rand_int(30)+7;
2371
2372 /* sometimes a dwelling. wood-elves? */
2373 if (magnitude > 8) {
2374 if (rand_int(100) < 50) add_dwelling = TRUE;
2375 }
2376 }
2377 break;
2378 case WILD_SWAMP:
2379 /* sometimes a pond */
2380 if (rand_int(100) < 40) {
2381 hot_terrain.water = 1000;
2382 }
2383 /* otherwise a mud pit */
2384 else {
2385 hot_terrain.type = WILD_SWAMP;
2386 init_terrain(&hot_terrain, w_ptr->radius);
2387 hot_terrain.mud = rand_int(150) + 700;
2388 }
2389 break;
2390
2391 case WILD_DESERT:
2392 /* sometimes an oasis */
2393 if (rand_int(100) < 80) {
2394 hot_terrain.tree = 1000;
2395 hot_terrain.water = rand_int(100) + 900;
2396 }
2397 /* otherwise some dried out trees */
2398 else {
2399 #if 1 /* prevent FEAT_DIRT base? */
2400 hot_terrain.sand = 1000;
2401 #endif
2402 hot_terrain.deadtree = rand_int(200) + 200;
2403 }
2404 break;
2405
2406 case WILD_ICE:
2407 /* sometimes a pond */
2408 if (rand_int(100) < 30) {
2409 hot_terrain.water = 1000;
2410 }
2411 /* otherwise some dead trees and mountains */
2412 else {
2413 hot_terrain.deadtree = rand_int(100) + 150;
2414 hot_terrain.mountain = rand_int(300) + 250;
2415 hot_terrain.ice = 1000;
2416 }
2417 break;
2418
2419 case WILD_LAKE:
2420 /* island */
2421 hot_terrain.type = WILD_GRASSLAND;
2422 init_terrain(&hot_terrain, w_ptr->radius);
2423 break;
2424
2425 default: hot_terrain.deadtree = rand_int(800)+100;
2426 }
2427
2428 #if 0
2429 /* hack for ambient sound fx -- crickets at every little pond :-p */
2430 if (hot_terrain.water == 1000) {
2431 /* maybe add SFX_AMBIENT_LAKE, if not overriden by SFX_AMBIENT_SHORE */
2432 if (wild_info[wpos->wy][wpos->wx].bled != WILD_OCEAN)
2433 wild_info[wpos->wy][wpos->wx].bled = WILD_LAKE;
2434 }
2435 #endif
2436
2437 /* create the hotspot */
2438 for (y = y_cen - magnitude; y <= y_cen + magnitude; y++) {
2439 for (x = x_cen - magnitude; x <= x_cen + magnitude; x++) {
2440 /* a^2 + b^2 = c^2... the rand makes the edge less defined */
2441 /* HACK -- multiply the y's by 4 to "squash" the shape */
2442 if (((x - x_cen) * (x - x_cen)) + (((y - y_cen) * (y - y_cen))*4) < magsqr + rand_int(chopiness)) {
2443 zcave[y][x].feat = terrain_spot(&hot_terrain);
2444 }
2445 }
2446 }
2447
2448 /* add inhabitants */
2449 if (add_dwelling) wild_add_dwelling(wpos, x_cen, y_cen );
2450 }
2451
2452 #ifdef BLEED_WITH_NEIGHBOURS
2453 /* helper function to wild_gen_bleedmap */
2454 static void wild_gen_bleedmap_aux(int *bleedmap, int span, char dir)
2455 {
2456 int c = 0, above, below, noise_mag, rand_noise, bleedmag;
2457
2458 /* make a pass of the bleedmap */
2459 while (c < MAX_WID) {
2460 /* check that its clear */
2461 if (bleedmap[c] == 0xFFFF) {
2462 /* if these are aligned right, they shouldn't overflow */
2463 if (bleedmap[c - span] != 0xFFFF) above = bleedmap[c - span];
2464 else above = 0;
2465 if (bleedmap[c + span] != 0xFFFF) below = bleedmap[c + span];
2466 else below = 0;
2467
2468 noise_mag = (dir%2) ? 70 : 25;
2469 /* randomness proportional to span */
2470 rand_noise = ((rand_int(noise_mag*2) - noise_mag) * span)/64;
2471 bleedmag = ((above + below) / 2) + rand_noise;
2472
2473 /* bounds checking */
2474 if (bleedmag < 0) bleedmag = 0;
2475 if (bleedmag > (MAX_HGT-1)/2) bleedmag = (MAX_HGT-1)/2;
2476
2477 /* set the bleed magnitude */
2478 bleedmap[c] = bleedmag;
2479 }
2480
2481 c += span;
2482 }
2483
2484 span /= 2;
2485 /* do the next level of recursion */
2486 if (span) wild_gen_bleedmap_aux(bleedmap, span, dir);
2487
2488 }
2489
2490 /* using a simple fractal algorithm, generates the bleedmap used by the function below. */
2491 /* hack -- for this algorithm to work nicely, an initial span of a power of 2 is required. */
2492 static void wild_gen_bleedmap(int *bleedmap, char dir, int start, int end)
2493 {
2494 int c = 0, bound;
2495
2496 /* initialize the bleedmap */
2497 for (c = 0; c <= 256; c++) {
2498 bleedmap[c] = 0xFFFF;
2499 }
2500
2501 /* initialize the "top" and "bottom" */
2502 if (start < 0) bleedmap[0] = rand_int(((dir%2) ? 70 : 25));
2503 else bleedmap[0] = start;
2504 if (end < 0) bleedmap[256] = rand_int(((dir%2) ? 70 : 25));
2505 else {
2506 bound = (dir%2) ? MAX_HGT-3 : MAX_WID-3;
2507 for (c = bound; c <= 256; c++) bleedmap[c] = end;
2508 }
2509
2510 /* hack -- if the start and end are zeroed, add something in the middle
2511 to make exciting stuff happen. */
2512 if ((!start) && (!end)) {
2513 /* east or west */
2514 if (dir%2) bleedmap[32] = rand_int(40) + 15;
2515 /* north or south */
2516 else {
2517 bleedmap[64] = rand_int(20) + 8;
2518 bleedmap[128] = rand_int(20) + 8;
2519 }
2520 }
2521
2522 /* generate the bleedmap */
2523 wild_gen_bleedmap_aux(bleedmap, 256/2, dir);
2524
2525 /* hack -- no bleedmags less than 8 except near the edges */
2526 bound = (dir%2) ? MAX_HGT-1 : MAX_WID-1;
2527
2528 /* beginning to middle */
2529 for (c = 0; c < 8; c++) if (bleedmap[c] < c) bleedmap[c] = c;
2530 /* middle */
2531 for (c = 8; c < bound - 8; c++) {
2532 if (bleedmap[c] < 8) bleedmap[c] = rand_int(3) + 8;
2533 }
2534 /* middle to end */
2535 for (c = bound - 8; c < bound; c++) {
2536 if (bleedmap[c] < bound - c) bleedmap[c] = bound - c;
2537 }
2538
2539 }
2540
2541 /* this function "bleeds" the terrain type of bleed_from to the side of bleed_to
2542 specified by dir.
2543
2544 First, a bleedmap array is initialized using a simple fractal algorithm.
2545 This map specifies the magnitude of the bleed at each point along the edge.
2546 After this, the two structures bleed_begin and bleed_end are initialized.
2547
2548 After this structure is initialized, for each point along the bleed edge,
2549 up until the bleedmap[point] edge of the bleed, the terrain is set to
2550 that of bleed_from.
2551
2552 We should hack this to add interesting features near the bleed edge.
2553 Such as ponds near shoreline to make it more interesting and
2554 groves of trees near the edges of forest.
2555 */
2556
2557 static void wild_bleed_level(int bleed_to_x, int bleed_to_y, int bleed_from_x, int bleed_from_y, char dir, int start, int end)
2558 {
2559 int x, y;
2560 int bleedmap[256 + 1], bleed_begin[MAX_WID], bleed_end[MAX_WID];
2561 terrain_type terrain;
2562 cave_type *c_ptr, **zcave_bleed_to = getcave(&((struct worldpos) {bleed_to_x, bleed_to_y, 0}));
2563 #ifdef BLEED_ENHANCED_TOWN
2564 int type = -1, i;
2565 #endif
2566
2567 #ifdef BLEED_AVOID_TOWN
2568 // if (istownarea(&neighbor, 1)) return;
2569 if (istown(&((struct worldpos) {bleed_from_x, bleed_from_y, 0}))) return;
2570 #endif
2571 #ifdef BLEED_ENHANCED_TOWN
2572 if (istown(&((struct worldpos) {bleed_from_x, bleed_from_y, 0}))) {
2573 for (i = 0; i < numtowns; i++) {
2574 if (town[i].x == bleed_from_x && town[i].y == bleed_from_y) {
2575 type = town[i].type;
2576 break;
2577 }
2578 }
2579 switch (type) {
2580 case TOWN_BREE:
2581 wild_info[bleed_from_y][bleed_from_x].type = WILD_GRASSLAND;
2582 //if (wild_info[bleed_to_y][bleed_to_x].type != WILD_OCEAN) return;
2583 break;
2584 case TOWN_GONDOLIN:
2585 wild_info[bleed_from_y][bleed_from_x].type = WILD_GRASSLAND;
2586 //if (wild_info[bleed_to_y][bleed_to_x].type != WILD_OCEAN) return;
2587 break;
2588 case TOWN_MINAS_ANOR:
2589 wild_info[bleed_from_y][bleed_from_x].type = WILD_MOUNTAIN;
2590 //if (wild_info[bleed_to_y][bleed_to_x].type != WILD_OCEAN) return;
2591 break;
2592 case TOWN_LOTHLORIEN:
2593 wild_info[bleed_from_y][bleed_from_x].type = WILD_OCEAN;
2594 //if (wild_info[bleed_to_y][bleed_to_x].type != WILD_OCEAN) return;
2595 break;
2596 case TOWN_KHAZADDUM:
2597 wild_info[bleed_from_y][bleed_from_x].type = WILD_VOLCANO;
2598 //if (wild_info[bleed_to_y][bleed_to_x].type != WILD_OCEAN) return;
2599 break;
2600 }
2601 }
2602 #endif
2603
2604 /* paranoia */
2605 if (!zcave_bleed_to) {
2606 s_printf("getcave() failed in wild_bleed_level\n");
2607 #ifdef BLEED_ENHANCED_TOWN
2608 if (type != -1) wild_info[bleed_from_y][bleed_from_x].type = WILD_TOWN;
2609 #endif
2610 return;
2611 }
2612
2613 /* sanity check */
2614 if (wild_info[bleed_from_y][bleed_from_x].type == wild_info[bleed_to_y][bleed_to_x].type) {
2615 #ifdef BLEED_ENHANCED_TOWN
2616 if (type != -1) wild_info[bleed_from_y][bleed_from_x].type = WILD_TOWN;
2617 #endif
2618 return;
2619 }
2620
2621 /* initiliaze the terrain type */
2622 terrain.type = wild_info[bleed_from_y][bleed_from_x].type;
2623
2624 /* determine the terrain components */
2625 init_terrain(&terrain, -1);
2626
2627 /* generate the bleedmap */
2628 wild_gen_bleedmap(bleedmap, dir, start, end);
2629
2630 /* initialize the bleedruns */
2631 switch (dir) {
2632 case DIR_EAST:
2633 for (y = 1; y < MAX_HGT - 1; y++) {
2634 bleed_begin[y] = MAX_WID - bleedmap[y];
2635 bleed_end[y] = MAX_WID - 1;
2636 }
2637 break;
2638 case DIR_WEST:
2639 for (y = 1; y < MAX_HGT - 1; y++) {
2640 bleed_begin[y] = 1;
2641 bleed_end[y] = bleedmap[y];
2642 }
2643 break;
2644 case DIR_NORTH:
2645 for (x = 1; x < MAX_WID - 1; x++) {
2646 bleed_begin[x] = 1;
2647 bleed_end[x] = bleedmap[x];
2648 }
2649 break;
2650 case DIR_SOUTH:
2651 for (x = 1; x < MAX_WID - 1; x++) {
2652 bleed_begin[x] = MAX_HGT - bleedmap[x];
2653 bleed_end[x] = MAX_HGT - 1;
2654 }
2655 break;
2656 }
2657
2658 if ((dir == DIR_EAST) || (dir == DIR_WEST)) {
2659 for (y = 1; y < MAX_HGT - 1; y++) {
2660 for (x = bleed_begin[y]; x < bleed_end[y]; x++) {
2661 c_ptr = &zcave_bleed_to[y][x];
2662 c_ptr->feat = terrain_spot(&terrain);
2663 }
2664 }
2665 } else {
2666 for (x = 1; x < MAX_WID - 1; x++) {
2667 for (y = bleed_begin[x]; y < bleed_end[x]; y++) {
2668 c_ptr = &zcave_bleed_to[y][x];
2669 c_ptr->feat = terrain_spot(&terrain);
2670 }
2671 }
2672 }
2673
2674 #ifdef BLEED_ENHANCED_TOWN
2675 if (type != -1) wild_info[bleed_from_y][bleed_from_x].type = WILD_TOWN;
2676 #endif
2677
2678
2679 /* USE_SOUND_2010 - hack for ambient sound fx (sea waves): - C. Blue
2680 the 'to' wilderness sector gets a marker so that it will trigger the
2681 ambient sfx too, that the terrain type of the 'from' wilderness
2682 sector would trigger.
2683 idea: WILD_COAST should trigger the WILD_OCEAN ambient sfx, if there
2684 are actually some visible ocean feat grids bled onto it. */
2685
2686 /* need to use a priority list, if several different ambient-sfx-
2687 causing terrain types are bled into this sector: */
2688 switch (wild_info[bleed_from_y][bleed_from_x].type) {
2689 case WILD_OCEAN: //sea waves
2690 wild_info[bleed_to_y][bleed_to_x].bled = WILD_OCEAN;
2691 break;
2692 case WILD_RIVER: case WILD_LAKE: case WILD_SWAMP: //crickets^^
2693 if (wild_info[bleed_to_y][bleed_to_x].bled != WILD_OCEAN)
2694 wild_info[bleed_to_y][bleed_to_x].bled = WILD_LAKE;
2695 break;
2696 #if 0
2697 case WILD_VOLCANO: //dunno oO
2698 if (wild_info[bleed_to_y][bleed_to_x].bled != WILD_OCEAN &&
2699 wild_info[bleed_to_y][bleed_to_x].bled != WILD_LAKE)
2700 wild_info[bleed_to_y][bleed_to_x].bled = WILD_VOLCANO;
2701 break;
2702 #endif
2703 }
2704 }
2705
2706 /*
2707 * Old version of getlevel() from cave.c
2708 * Used for seeding the wilderness bleeding effects
2709 * Do not change this or house layout may change in some places
2710 */
2711 static int getlevel_wild_old(struct worldpos *wpos) {
2712 wilderness_type *w_ptr = &wild_info[wpos->wy][wpos->wx];
2713 return (w_ptr->radius);
2714 }
2715
2716 /* determines whether or not to bleed from a given depth in a given direction.
2717 useful for initial determination, as well as shared bleed points.
2718 */
2719 static bool should_we_bleed(struct worldpos *wpos, char dir)
2720 {
2721 int neigh_x = 0, neigh_y = 0, tmp;
2722 wilderness_type *w_ptr = &wild_info[wpos->wy][wpos->wx];
2723 struct worldpos neighbor;
2724
2725 /* get our neighbors index */
2726 switch (dir) {
2727 case DIR_NORTH:
2728 neigh_x = wpos->wx;
2729 neigh_y = wpos->wy + 1;
2730 break;
2731 case DIR_EAST:
2732 neigh_x = wpos->wx + 1;
2733 neigh_y = wpos->wy;
2734 break;
2735 case DIR_SOUTH:
2736 neigh_x = wpos->wx;
2737 neigh_y = wpos->wy - 1;
2738 break;
2739 case DIR_WEST:
2740 neigh_x = wpos->wx - 1;
2741 neigh_y = wpos->wy;
2742 break;
2743 }
2744
2745 /* determine whether to bleed or not */
2746 /* if a valid location */
2747 if (!in_bounds_wild(neigh_y, neigh_x)) return FALSE;
2748
2749 /* make sure the level type is defined */
2750 neighbor.wx = neigh_x;
2751 neighbor.wy = neigh_y;
2752 neighbor.wz = 0;
2753 wild_info[neigh_y][neigh_x].type = determine_wilderness_type(&neighbor);
2754
2755 /* check if our neighbor is of a different type */
2756 if (w_ptr->type != wild_info[neigh_y][neigh_x].type) {
2757 /* determine whether to bleed or not */
2758 Rand_value = seed_town + (getlevel_wild_old(wpos) + getlevel_wild_old(&neighbor)) * (93754);
2759 tmp = rand_int(2);
2760
2761 if (tmp && (getlevel(wpos) < getlevel(&neighbor))) return TRUE;
2762 else if (!tmp && (getlevel(wpos) > getlevel(&neighbor))) return TRUE;
2763 else return FALSE;
2764 }
2765
2766 return(FALSE);
2767 }
2768
2769 /* to determine whether we bleed into our neighbor or whether our neighbor
2770 bleeds into us, we seed the random number generator with our combined
2771 depth. If the resulting number is 0, we bleed into the greater (negative
2772 wise) level. Other wise we bleed into the lesser (negative wise) level.
2773
2774 I added in shared points.... turning this function into something extremly
2775 gross. This will be extremly anoying to get working. I wish I had a simpler
2776 way of doing this.
2777 */
2778 static void bleed_with_neighbors(struct worldpos *wpos)
2779 {
2780 int c, d, tmp, side[2], start, end, opposite;
2781 bool do_bleed[4], bleed_zero[4];
2782 int share_point[4][2];
2783 int old_seed = Rand_value;
2784 bool rand_old = Rand_quick;
2785 wilderness_type *w_ptr = &wild_info[wpos->wy][wpos->wx];
2786 struct worldpos neighbor, neighbor_tmp;
2787 neighbor.wz = neighbor_tmp.wz = 0;
2788
2789 /* Hack -- Use the "simple" RNG */
2790 Rand_quick = TRUE;
2791
2792 /* for each neighbor, determine whether to bleed or not */
2793 for (c = 0; c < 4; c++) do_bleed[c] = should_we_bleed(wpos ,c);
2794
2795 /* calculate the bleed_zero values */
2796 for (c = 0; c < 4; c++) {
2797 tmp = c - 1; if (tmp < 0) tmp = 3;
2798
2799 /* get our neighbors index */
2800 switch (c) {
2801 case DIR_NORTH:
2802 neighbor.wx = wpos->wx;
2803 neighbor.wy = wpos->wy + 1;
2804 neighbor_tmp.wx = wpos->wx - 1;
2805 neighbor_tmp.wy = wpos->wy;
2806 break;
2807 case DIR_EAST:
2808 neighbor.wx = wpos->wx + 1;
2809 neighbor.wy = wpos->wy;
2810 neighbor_tmp.wx = wpos->wx;
2811 neighbor_tmp.wy = wpos->wy + 1;
2812 break;
2813 case DIR_SOUTH:
2814 neighbor.wx = wpos->wx;
2815 neighbor.wy = wpos->wy - 1;
2816 neighbor_tmp.wx = wpos->wx + 1;
2817 neighbor_tmp.wy = wpos->wy;
2818 break;
2819 case DIR_WEST:
2820 neighbor.wx = wpos->wx - 1;
2821 neighbor.wy = wpos->wy;
2822 neighbor_tmp.wx = wpos->wx;
2823 neighbor_tmp.wy = wpos->wy - 1;
2824 break;
2825 }
2826
2827 if (in_bounds_wild(neighbor.wy, neighbor.wx) && in_bounds_wild(neighbor_tmp.wy, neighbor_tmp.wx)) {
2828 if (wild_info[neighbor_tmp.wy][neighbor_tmp.wx].type == wild_info[neighbor.wy][neighbor.wx].type) {
2829 /* calculate special case bleed zero values. */
2830
2831 if (do_bleed[c]) {
2832 /* if get the opposite direction from tmp */
2833 opposite = tmp - 2; if (opposite < 0) opposite += 4;
2834
2835 /* if the other one is bleeding towards us */
2836 if (should_we_bleed(&neighbor_tmp, opposite)) bleed_zero[c] = TRUE;
2837 else bleed_zero[c] = FALSE;
2838 } else if (do_bleed[tmp]) {
2839 /* get the opposite direction from c */
2840 opposite = c - 2; if (opposite < 0) opposite += 4;
2841
2842 /* if the other one is bleeding towards us */
2843 if (should_we_bleed(&neighbor, opposite)) bleed_zero[c] = TRUE;
2844 else bleed_zero[c] = FALSE;
2845 }
2846
2847 else bleed_zero[c] = FALSE;
2848 }
2849 else bleed_zero[c] = TRUE;
2850 }
2851 else bleed_zero[c] = FALSE;
2852 }
2853
2854
2855 /* calculate bleed shared points */
2856 for (c = 0; c < 4; c++) {
2857 side[0] = c - 1; if (side[0] < 0) side[0] = 3;
2858 side[1] = c + 1; if (side[1] > 3) side[1] = 0;
2859
2860 /* if this direction is bleeding */
2861 if (do_bleed[c]) {
2862 /* for the left and right sides */
2863 for (d = 0; d <= 1; d++) {
2864 /* get our neighbors index */
2865 switch (side[d]) {
2866 case DIR_NORTH:
2867 neighbor.wx = wpos->wx;
2868 neighbor.wy = wpos->wy + 1;
2869 break;
2870 case DIR_EAST:
2871 neighbor.wx = wpos->wx + 1;
2872 neighbor.wy = wpos->wy;
2873 break;
2874 case DIR_SOUTH:
2875 neighbor.wx = wpos->wx;
2876 neighbor.wy = wpos->wy - 1;
2877 break;
2878 case DIR_WEST:
2879 neighbor.wx = wpos->wx - 1;
2880 neighbor.wy = wpos->wy;
2881 break;
2882 }
2883
2884 /* if we have a valid neighbor */
2885 if (in_bounds_wild(neighbor.wy, neighbor.wx)) {
2886 /* if our neighbor is bleeding in a simmilar way */
2887 if (should_we_bleed(&neighbor, c)) {
2888 /* are we a simmilar type of terrain */
2889 if (wild_info[neighbor.wy][neighbor.wx].type == w_ptr->type) {
2890 /* share a point */
2891 /* seed the number generator */
2892 Rand_value = seed_town + (getlevel_wild_old(wpos) + getlevel_wild_old(&neighbor)) * (89791);
2893 share_point[c][d] = rand_int(((c%2) ? 70 : 25));
2894 }
2895 else share_point[c][d] = 0;
2896 }
2897 else share_point[c][d] = 0;
2898 }
2899 else share_point[c][d] = 0;
2900 }
2901 } else {
2902 share_point[c][0] = 0;
2903 share_point[c][1] = 0;
2904 }
2905 }
2906
2907 /* do the bleeds */
2908 for (c = 0; c < 4; c++) {
2909 tmp = c+1; if (tmp > 3) tmp = 0;
2910 if (do_bleed[c]) {
2911 if ((!share_point[c][0]) && (!bleed_zero[c])) start = -1;
2912 else if (share_point[c][0]) start = share_point[c][0];
2913 else start = 0;
2914
2915 if ((!share_point[c][1]) && (!bleed_zero[tmp])) end = -1;
2916 else if (share_point[c][1]) end = share_point[c][1];
2917 else end = 0;
2918
2919 /* get our neighbors index */
2920 switch (c) {
2921 case DIR_NORTH:
2922 neighbor.wx = wpos->wx;
2923 neighbor.wy = wpos->wy + 1;
2924 neighbor_tmp.wx = wpos->wx - 1;
2925 neighbor_tmp.wy = wpos->wy;
2926 break;
2927 case DIR_EAST:
2928 neighbor.wx = wpos->wx + 1;
2929 neighbor.wy = wpos->wy;
2930 neighbor_tmp.wx = wpos->wx;
2931 neighbor_tmp.wy = wpos->wy + 1;
2932 break;
2933 case DIR_SOUTH:
2934 neighbor.wx = wpos->wx;
2935 neighbor.wy = wpos->wy - 1;
2936 neighbor_tmp.wx = wpos->wx + 1;
2937 neighbor_tmp.wy = wpos->wy;
2938 break;
2939 case DIR_WEST:
2940 neighbor.wx = wpos->wx - 1;
2941 neighbor.wy = wpos->wy;
2942 neighbor_tmp.wx = wpos->wx;
2943 neighbor_tmp.wy = wpos->wy - 1;
2944 break;
2945 }
2946
2947 if (c < 2) {
2948 wild_bleed_level(wpos->wx, wpos->wy, neighbor.wx, neighbor.wy, c, start, end);
2949 } else {
2950 wild_bleed_level(wpos->wx, wpos->wy, neighbor.wx, neighbor.wy, c, end, start);
2951 }
2952 }
2953 }
2954
2955 /* hack -- restore the random number generator */
2956 Rand_value = old_seed;
2957 Rand_quick = rand_old;
2958 }
2959 #endif
2960
2961 static void flood(char *buf, int x, int y, int w, int h) {
2962 if (x >= 0 && x < w && y >= 0 && y < h && buf[x + y * w] == 0) {
2963 buf[x + y * w] = 6;
2964 flood(buf, x + 1, y, w, h);
2965 flood(buf, x - 1, y, w, h);
2966 flood(buf, x, y + 1, w, h);
2967 flood(buf, x, y - 1, w, h);
2968 }
2969 }
2970
2971 bool fill_house(house_type *h_ptr, int func, void *data) {
2972 /* polygonal house */
2973 /* draw all the outer walls cleanly */
2974 cptr coord = h_ptr->coords.poly;
2975 cptr ptr = coord;
2976 char *matrix;
2977 int sx = h_ptr->x;
2978 int sy = h_ptr->y;
2979 int dx, dy;
2980 int x, y;
2981 int minx, miny, maxx, maxy;
2982 int mw, mh;
2983 bool success = TRUE;
2984 struct worldpos *wpos = &h_ptr->wpos;
2985 cave_type *c_ptr;
2986 struct c_special *cs_ptr;
2987 cave_type **zcave;
2988 if (!(zcave = getcave(wpos))) return(FALSE);
2989
2990 if (func == FILL_PLAYER || func == FILL_OBJECT)
2991 success = FALSE;
2992
2993 if (h_ptr->flags & HF_RECT) {
2994 for (x = 0; x < h_ptr->coords.rect.width; x++) {
2995 for (y = 0; y < h_ptr->coords.rect.height; y++) {
2996 c_ptr = &zcave[h_ptr->y + y][h_ptr->x + x];
2997 if (func == FILL_GUILD) {
2998 return(FALSE); /* for now */
2999 if (((struct guildsave*)data)->mode) {
3000 fputc(c_ptr->feat, ((struct guildsave*)data)->fp);
3001 } else {
3002 c_ptr->feat = fgetc(((struct guildsave*)data)->fp);
3003 // if(c_ptr->feat>FEAT_INVIS)
3004 if(!cave_plain_floor_grid(c_ptr))
3005 c_ptr->info &= ~(CAVE_ROOM);
3006 }
3007 everyone_lite_spot(&h_ptr->wpos, h_ptr->y + y, h_ptr->x + x);
3008 }
3009 else if (func == FILL_OBJECT) { /* object in house? */
3010 object_type *o_ptr = (object_type*)data;
3011 if (o_ptr->ix == h_ptr->x + x && o_ptr->iy == h_ptr->y + y) {
3012 success = TRUE;
3013 break;
3014 }
3015 }
3016 else if (func == FILL_PLAYER) { /* player in house? */
3017 player_type *p_ptr = (player_type*)data;
3018 if (p_ptr->px == h_ptr->x + x && p_ptr->py == h_ptr->y + y) {
3019 success = TRUE;
3020 break;
3021 }
3022 }
3023 else if (func == FILL_MAKEHOUSE) {
3024 if (x && y && x < h_ptr->coords.rect.width - 1 && y < h_ptr->coords.rect.height - 1) {
3025 if((pick_house(wpos, h_ptr->y, h_ptr->x)) != -1)
3026 success = FALSE;
3027 c_ptr->info &= ~(CAVE_ICKY | CAVE_ROOM | CAVE_STCK | CAVE_JAIL);
3028 } else {
3029 /* fix: also erase cs-special, or server will panic on restart
3030 if someone kept this area static and has the former door grid
3031 in his los -> will try to call access_door_colour() on it,
3032 but the dna structure has already been nulled -> segfault. - C. Blue */
3033 if (c_ptr->feat == FEAT_HOME || c_ptr->feat == FEAT_HOME_OPEN) {
3034 cs_ptr = GetCS(c_ptr, CS_DNADOOR);
3035 if (cs_ptr) cs_erase(c_ptr, cs_ptr);
3036 }
3037 c_ptr->feat = FEAT_DIRT;
3038 c_ptr->info &= ~(CAVE_ICKY | CAVE_ROOM | CAVE_STCK | CAVE_JAIL);
3039 }
3040 everyone_lite_spot(&h_ptr->wpos, h_ptr->y + y, h_ptr->x + x);
3041 }
3042 else if (func == FILL_CLEAR) {
3043 delete_object(wpos, y, x, TRUE);
3044 everyone_lite_spot(&h_ptr->wpos, h_ptr->y + y, h_ptr->x + x);
3045 }
3046 else if (func == FILL_BUILD) {
3047 if (x && y && x < h_ptr->coords.rect.width - 1 && y < h_ptr->coords.rect.height - 1) {
3048 if (!(h_ptr->flags & HF_NOFLOOR))
3049 c_ptr->feat = FEAT_FLOOR;
3050 if (h_ptr->flags & HF_JAIL) {
3051 c_ptr->info |= (CAVE_STCK | CAVE_JAIL);
3052 }
3053 c_ptr->info |= (CAVE_ICKY | CAVE_ROOM);
3054
3055 #if 0 //moved to day->night change //note: below hack is overridden by night atm :/ todo:fix
3056 /* hack: lit owned houses for easier overview - only inside, not walls! */
3057 //done above already if (x > 0 && x < h_ptr->coords.rect.width - 1 && y > 0 && y < h_ptr->coords.rect.height)
3058 if (h_ptr->dna->owner) c_ptr->info |= CAVE_GLOW;
3059 #endif
3060
3061 /* 'suspended' guild houses ( = of leaderless guilds) */
3062 if ((h_ptr->flags & HF_GUILD_SUS)) c_ptr->info |= CAVE_GUILD_SUS;
3063
3064 everyone_lite_spot(&h_ptr->wpos, h_ptr->y + y, h_ptr->x + x);
3065 }
3066 }
3067 #ifdef HOUSE_PAINTING
3068 else if (func == FILL_UNPAINT) {
3069 c_ptr->colour = 0;
3070 /* refresh player's view on the freshly applied paint */
3071 everyone_lite_spot(&h_ptr->wpos, h_ptr->y + y, h_ptr->x + x);
3072 }
3073 #endif
3074 else if (func == FILL_GUILD_SUS) {
3075 if (x && y && x < h_ptr->coords.rect.width - 1 && y < h_ptr->coords.rect.height - 1) //obsolete check
3076 c_ptr->info |= CAVE_GUILD_SUS;
3077 }
3078 else if (func == FILL_GUILD_SUS_UNDO) {
3079 if (x && y && x < h_ptr->coords.rect.width - 1 && y < h_ptr->coords.rect.height - 1) //obsolete check
3080 c_ptr->info &= ~CAVE_GUILD_SUS;
3081 }
3082 else if (func == FILL_SFX_KNOCK) {
3083 if (c_ptr->m_idx < 0) {
3084 sound(-(c_ptr->m_idx), (h_ptr->flags & HF_MOAT) ? "knock_castle" : "knock", "block_shield_projectile", SFX_TYPE_COMMAND, FALSE);
3085 msg_print(-(c_ptr->m_idx), "\377sYou hear someone knocking on the house door.");
3086 }
3087 }
3088 else s_printf("rect fill house (func: %d\n", func);
3089 }
3090 }
3091 return(success);
3092 }
3093
3094 maxx = minx = h_ptr->x;
3095 maxy = miny = h_ptr->y;
3096 x = h_ptr->x;
3097 y = h_ptr->y;
3098
3099 while (ptr[0] || ptr[1]) {
3100 x += ptr[0];
3101 y += ptr[1];
3102 minx = MIN(x, minx);
3103 miny = MIN(y, miny);
3104 maxx = MAX(x, maxx);
3105 maxy = MAX(y, maxy);
3106 ptr += 2;
3107 }
3108 mw = maxx + 3 - minx;
3109 mh = maxy + 3 - miny;
3110 C_MAKE(matrix, mw * mh, char);
3111 ptr = coord;
3112
3113 while (ptr[0] || ptr[1]) {
3114 dx = ptr[0];
3115 dy = ptr[1];
3116 if (dx) { /* dx/dy mutually exclusive */
3117 if (dx < 0) {
3118 for (x = sx; x > (sx + dx); x--) {
3119 matrix[(x + 1 - minx) + (y + 1 - miny) * mw] = 1;
3120 }
3121 } else {
3122 for (x = sx; x < (sx + dx); x++) {
3123 matrix[(x + 1 - minx) + (y + 1 - miny) * mw] = 1;
3124 }
3125 }
3126 sx = x;
3127 } else {
3128 if (dy < 0) {
3129 for (y = sy; y > (sy + dy); y--) {
3130 matrix[(x + 1 - minx) + (y + 1 - miny) * mw] = 1;
3131 }
3132 } else {
3133 for (y = sy; y < (sy + dy); y++) {
3134 matrix[(x + 1 - minx) + (y + 1 - miny) * mw] = 1;
3135 }
3136 }
3137 sy = y;
3138 }
3139 ptr += 2;
3140 }
3141
3142 flood(matrix, 0, 0, mw, mh);
3143 for (y = 0; y < mh; y++) {
3144 for (x = 0; x < mw; x++) {
3145 switch (matrix[x + y * mw]) {
3146 case 2: /* do nothing */
3147 case 4:
3148 case 6: /* outside of walls */
3149 break;
3150 case 0: /* inside of walls */
3151 if (func == FILL_GUILD) {
3152 struct key_type *key;
3153 u16b id;
3154 FILE *gfp = ((struct guildsave*)data)->fp;
3155 c_ptr = &zcave[miny + (y - 1)][minx + (x - 1)];
3156 if (((struct guildsave*)data)->mode) {
3157 fputc(c_ptr->feat, gfp);
3158 if (c_ptr->feat == FEAT_HOME || c_ptr->feat == FEAT_HOME_OPEN) {
3159 id = 0;
3160 if ((cs_ptr = GetCS(c_ptr, CS_KEYDOOR)) && (key = cs_ptr->sc.ptr)) {
3161 fseek(gfp, -1, SEEK_CUR);
3162 fputc(FEAT_HOME_HEAD, gfp);
3163 id = key->id;
3164 fputc((id >> 8), gfp);
3165 fputc(id & 0xff, gfp);
3166 }
3167 }
3168 }
3169 else{
3170 c_ptr->feat = fgetc(((struct guildsave*)data)->fp);
3171 // if (c_ptr->feat > FEAT_INVIS)
3172 if (!cave_plain_floor_grid(c_ptr))
3173 c_ptr->info &= ~(CAVE_ROOM);
3174 if (c_ptr->feat == FEAT_HOME){
3175 id = (fgetc(gfp) << 8);
3176 id |= fgetc(gfp);
3177 /* XXX it's double check */
3178 if (!(cs_ptr = GetCS(c_ptr, CS_KEYDOOR))) { /* no, not really. - evileye */
3179 cs_ptr = AddCS(c_ptr, CS_KEYDOOR);
3180 MAKE(cs_ptr->sc.ptr, struct key_type);
3181 // cs_ptr->type = CS_KEYDOOR;
3182 }
3183 key = cs_ptr->sc.ptr; /* isn't it dangerous? -Jir */
3184 key->id = id;
3185 }
3186 }
3187 everyone_lite_spot(&h_ptr->wpos, miny + (y - 1), minx + (x - 1));
3188 break;
3189 }
3190 if (func == FILL_PLAYER) {
3191 player_type *p_ptr = (player_type*)data;
3192 if (p_ptr->px == minx + (x - 1) && p_ptr->py == miny + (y - 1)) {
3193 success = TRUE;
3194 }
3195 break;
3196 }
3197 if (func == FILL_MAKEHOUSE) {
3198 if ((pick_house(wpos,miny + (y - 1), minx + (x - 1)) != -1)) {
3199 success = FALSE;
3200 }
3201 zcave[miny + (y - 1)][minx + (x - 1)].info &= ~(CAVE_ICKY | CAVE_ROOM | CAVE_STCK | CAVE_JAIL);
3202 everyone_lite_spot(&h_ptr->wpos, miny + (y - 1), minx + (x - 1));
3203 break;
3204 }
3205 if (func == FILL_OBJECT) { /* object in house */
3206 object_type *o_ptr = (object_type*)data;
3207 if (o_ptr->ix == minx + (x - 1) && o_ptr->iy == miny + (y - 1)) {
3208 success = TRUE;
3209 }
3210 break;
3211 }
3212 if (func == FILL_CLEAR) {
3213 delete_object(wpos, miny + (y - 1), minx + (x - 1), TRUE);
3214 everyone_lite_spot(&h_ptr->wpos, miny + (y - 1), minx + (x - 1));
3215 break;
3216 }
3217 if (func == FILL_BUILD) {
3218 c_ptr = &zcave[miny + (y - 1)][minx + (x - 1)];
3219 if (!(h_ptr->flags & HF_NOFLOOR))
3220 c_ptr->feat = FEAT_FLOOR;
3221 c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
3222 if (h_ptr->flags & HF_JAIL) {
3223 c_ptr->info |= (CAVE_STCK | CAVE_JAIL);
3224 }
3225
3226 /* 'suspended' guild houses ( = of leaderless guilds) */
3227 if ((h_ptr->flags & HF_GUILD_SUS)) c_ptr->info |= CAVE_GUILD_SUS;
3228
3229 everyone_lite_spot(&h_ptr->wpos, miny + (y - 1), minx + (x - 1));
3230 break;
3231 }
3232 #ifdef HOUSE_PAINTING
3233 else if (func == FILL_UNPAINT) {
3234 zcave[miny + (y - 1)][minx + (x - 1)].colour = 0;
3235 /* refresh player's view on the freshly applied paint */
3236 everyone_lite_spot(&h_ptr->wpos, miny + (y - 1), minx + (x - 1));
3237 break;
3238 }
3239 #endif
3240 else if (func == FILL_GUILD_SUS) {
3241 zcave[miny + (y - 1)][minx + (x - 1)].info |= CAVE_GUILD_SUS;
3242 break;
3243 }
3244 else if (func == FILL_GUILD_SUS_UNDO) {
3245 zcave[miny + (y - 1)][minx + (x - 1)].info &= ~CAVE_GUILD_SUS;
3246 break;
3247 }
3248 else if (func == FILL_SFX_KNOCK) {
3249 c_ptr = &zcave[miny + (y - 1)][minx + (x - 1)];
3250 if (c_ptr->m_idx < 0) {
3251 sound(-(c_ptr->m_idx), (h_ptr->flags & HF_MOAT) ? "knock_castle" : "knock", "block_shield_projectile", SFX_TYPE_COMMAND, FALSE);
3252 msg_print(-(c_ptr->m_idx), "\377sYou hear someone knocking on the house door.");
3253 }
3254 }
3255 else s_printf("poly fill house (func: %d)\n", func);
3256 break;
3257 case 1: /* Actual walls */
3258 if (func == FILL_CLEAR) break;
3259 if (func == FILL_PLAYER) {
3260 player_type *p_ptr = (player_type*)data;
3261 if (p_ptr->px == minx + (x - 1) && p_ptr->py == miny + (y - 1))
3262 success = TRUE;
3263 break;
3264 }
3265 if (func == FILL_MAKEHOUSE) {
3266 c_ptr = &zcave[miny + (y - 1)][minx + (x - 1)];
3267 if (c_ptr->feat == FEAT_HOME || c_ptr->feat == FEAT_HOME_OPEN) {
3268 c_special *cs_ptr = GetCS(c_ptr, CS_DNADOOR);
3269 if (cs_ptr) cs_erase(c_ptr, cs_ptr);
3270 }
3271 c_ptr->feat = FEAT_DIRT;
3272 c_ptr->info &= ~(CAVE_ICKY | CAVE_ROOM | CAVE_STCK | CAVE_JAIL);
3273 everyone_lite_spot(&h_ptr->wpos, miny + (y - 1), minx + (x - 1));
3274 }
3275 else if (func == FILL_BUILD) {
3276 // zcave[miny + (y - 1)][minx + (x - 1)].feat = FEAT_PERM_EXTRA;
3277 zcave[miny + (y - 1)][minx + (x - 1)].feat = FEAT_WALL_HOUSE;
3278 if (h_ptr->flags & HF_JAIL) zcave[miny + (y - 1)][minx + (x - 1)].info |= CAVE_JAIL;
3279 everyone_lite_spot(&h_ptr->wpos, miny + (y - 1), minx + (x - 1));
3280 }
3281 #ifdef HOUSE_PAINTING
3282 else if (func == FILL_UNPAINT) {
3283 zcave[miny + (y - 1)][minx + (x - 1)].colour = 0;
3284 /* refresh player's view on the freshly applied paint */
3285 everyone_lite_spot(&h_ptr->wpos, miny + (y - 1), minx + (x - 1));
3286 break;
3287 }
3288 #endif
3289 else if (func == FILL_SFX_KNOCK) {
3290 c_ptr = &zcave[miny + (y - 1)][minx + (x - 1)];
3291 if (c_ptr->m_idx < 0) {
3292 sound(-(c_ptr->m_idx), (h_ptr->flags & HF_MOAT) ? "knock_castle" : "knock", "block_shield_projectile", SFX_TYPE_COMMAND, FALSE);
3293 msg_print(-(c_ptr->m_idx), "\377sYou hear someone knocking on the house door.");
3294 }
3295 }
3296 break;
3297 }
3298 }
3299 }
3300 C_KILL(matrix,mw*mh,char);
3301 return(success);
3302 }
3303
3304 void wild_add_uhouse(house_type *h_ptr) {
3305 int x,y;
3306 cave_type *c_ptr;
3307 struct worldpos *wpos = &h_ptr->wpos;
3308 cave_type **zcave;
3309 struct c_special *cs_ptr;
3310 if (!(zcave = getcave(wpos))) return;
3311
3312 if (h_ptr->flags & HF_DELETED) return; /* House destroyed. Ignore */
3313
3314 /* draw our user defined house */
3315 if (h_ptr->flags & HF_RECT) {
3316 for (x = 0; x < h_ptr->coords.rect.width; x++) {
3317 c_ptr = &zcave[h_ptr->y][h_ptr->x + x];
3318 c_ptr->feat = FEAT_WALL_HOUSE;
3319 if (h_ptr->flags & HF_JAIL) c_ptr->info |= CAVE_JAIL;
3320 }
3321 for (y = h_ptr->coords.rect.height - 1, x = 0; x < h_ptr->coords.rect.width; x++) {
3322 c_ptr = &zcave[h_ptr->y + y][h_ptr->x + x];
3323 c_ptr->feat = FEAT_WALL_HOUSE;
3324 if (h_ptr->flags & HF_JAIL) c_ptr->info |= CAVE_JAIL;
3325 }
3326 for (y = 1; y < h_ptr->coords.rect.height; y++) {
3327 c_ptr = &zcave[h_ptr->y + y][h_ptr->x];
3328 c_ptr->feat = FEAT_WALL_HOUSE;
3329 if (h_ptr->flags & HF_JAIL) c_ptr->info |= CAVE_JAIL;
3330 }
3331 for (x = h_ptr->coords.rect.width - 1, y = 1; y < h_ptr->coords.rect.height; y++) {
3332 c_ptr = &zcave[h_ptr->y + y][h_ptr->x + x];
3333 c_ptr->feat = FEAT_WALL_HOUSE;
3334 if (h_ptr->flags & HF_JAIL) c_ptr->info |= CAVE_JAIL;
3335 }
3336 }
3337 fill_house(h_ptr, FILL_BUILD, NULL);
3338 if (h_ptr->flags & HF_MOAT) {
3339 /* Draw a moat around our house */
3340 /* It is already valid at this point */
3341 if(h_ptr->flags & HF_RECT) {
3342 }
3343 }
3344
3345 /* get door */
3346 c_ptr = &zcave[h_ptr->dy][h_ptr->dx];
3347
3348 /*
3349 * usually, already done in poly_build..
3350 * right, Evileye? - Jir -
3351 */
3352 if (!(cs_ptr = AddCS(c_ptr, CS_DNADOOR))) {
3353 if (!(cs_ptr = GetCS(c_ptr, CS_DNADOOR))) {
3354 s_printf("House creation failed!! (wild_add_uhouse)\n");
3355 return;
3356 }
3357 }
3358 c_ptr->feat = FEAT_HOME;
3359
3360 cs_ptr->sc.ptr = h_ptr->dna;
3361 }
3362
3363 void wild_add_uhouses(struct worldpos *wpos) {
3364 int i;
3365 for(i = 0; i < num_houses; i++){
3366 if(inarea(&houses[i].wpos, wpos) && !(houses[i].flags & HF_STOCK)){
3367 wild_add_uhouse(&houses[i]);
3368 }
3369 }
3370 load_guildhalls(wpos);
3371 }
3372
3373 /* Called by wilderness_gen() - build a wilderness sector from memory */
3374 static void wilderness_gen_hack(struct worldpos *wpos)
3375 {
3376 int y, x, x1, x2, y1, y2;
3377 cave_type *c_ptr, *c2_ptr;
3378 int found_more_water;
3379 terrain_type terrain;
3380 bool rand_old = Rand_quick;
3381
3382 wilderness_type *w_ptr = &wild_info[wpos->wy][wpos->wx];
3383 cave_type **zcave;
3384 if(!(zcave = getcave(wpos))) return;
3385
3386 /* Hack -- Use the "simple" RNG */
3387 Rand_quick = TRUE;
3388
3389 /* Hack -- Induce consistant wilderness */
3390 seed_wild_extra = Rand_value; /* save for use in terrain_spot() */
3391 Rand_value = seed_town + (wpos->wx + wpos->wy * MAX_WILD_X) * 600;
3392
3393 /* if not already set, determine the type of terrain */
3394 if (w_ptr->type == WILD_UNDEFINED) w_ptr->type = determine_wilderness_type(wpos);
3395
3396 /* initialize the terrain */
3397 terrain.type = w_ptr->type;
3398 init_terrain(&terrain,w_ptr->radius);
3399
3400 /* hack -- set the monster level */
3401 monster_level = terrain.monst_lev;
3402
3403 /* Hack -- Start with basic floors */
3404 for (y = 1; y < MAX_HGT - 1; y++) {
3405 for (x = 1; x < MAX_WID - 1; x++) {
3406 c_ptr = &zcave[y][x];
3407 c_ptr->feat = terrain_spot(&terrain);
3408 }
3409 }
3410
3411 #ifdef BLEED_WITH_NEIGHBOURS
3412 /* to make the borders between wilderness levels more seamless, "bleed"
3413 the levels together */
3414 bleed_with_neighbors(wpos);
3415 #endif
3416
3417 /* hack -- reseed, just to make sure everything stays consistent. */
3418 Rand_value = seed_town + (wpos->wx + wpos->wy * MAX_WILD_X) * 287 + 490836;
3419
3420 /* to make the level more interesting, add some "hotspots" */
3421 if (w_ptr->type != WILD_OCEAN || istownarea(wpos, MAX_TOWNAREA))
3422 for (y = 0; y < terrain.hotspot; y++) wild_add_hotspot(wpos);
3423 /* oceans really have mostly water */
3424 else if (!rand_int(8)) //changing hotspot number in init_terrain() directly probably messes up world consistency?
3425 for (y = 0; y < terrain.hotspot / 3; y++) wild_add_hotspot(wpos); //..so just divide here, pfft
3426
3427 /* HACK -- if close to the town, make dwellings more likely */
3428 #ifdef DEVEL_TOWN_COMPATIBILITY
3429 if (w_ptr->radius == 1) terrain.dwelling *= 21;
3430 if (w_ptr->radius == 2) terrain.dwelling *= 9;
3431 if (w_ptr->radius == 3) terrain.dwelling *= 3;
3432 #else
3433 #ifdef __DISABLE_HOUSEBOOST
3434 if (w_ptr->radius == 1) terrain.dwelling *= 100;
3435 if (w_ptr->radius == 2) terrain.dwelling *= 20;
3436 if (w_ptr->radius == 3) terrain.dwelling *= 3;
3437 #else
3438 if (w_ptr->radius == 1) terrain.dwelling *= 160;
3439 if (w_ptr->radius == 2) terrain.dwelling *= 130;
3440 if (w_ptr->radius == 3) terrain.dwelling *= 40;
3441 #endif
3442 #endif
3443
3444 // wild_add_uhouses(wpos);
3445
3446
3447 #ifndef DEVEL_TOWN_COMPATIBILITY
3448 /* Hack -- 50% of the time on a radius 1 level there will be a "park" which will make
3449 * the rest of the level more densly packed together */
3450 if ((w_ptr->radius == 1) && !rand_int(2)) {
3451 reserve_building_plot(wpos, &x1, &y1, &x2, &y2, rand_int(30) + 15, rand_int(20) + 10, -1, -1);
3452 }
3453 #endif
3454
3455 /* add wilderness dwellings */
3456 /* hack -- the number of dwellings is proportional to their chance of existing */
3457 while (terrain.dwelling > 0) {
3458 if (rand_int(1000) < terrain.dwelling) wild_add_dwelling(wpos, -1, -1);
3459 terrain.dwelling -= 50;
3460 }
3461
3462 /* add user-built houses */
3463 wild_add_uhouses(wpos);
3464
3465 /* C. Blue - turn single deep water fields in wildernis to shallow (non-drownable) water:
3466 Also turn single non-deep water fields in oceans into deep water -_-. */
3467 for (y = 1; y < MAX_HGT - 1; y++)
3468 for (x = 1; x < MAX_WID - 1; x++) {
3469 c_ptr = &zcave[y][x];
3470 /* turn single deep water fields to shallow */
3471 if (c_ptr->feat == FEAT_DEEP_WATER) {
3472 found_more_water = 0;
3473 for (y2 = y-1; y2 <= y+1; y2++)
3474 for (x2 = x-1; x2 <= x+1; x2++) {
3475 c2_ptr = &zcave[y2][x2];
3476 if (y2 == y && x2 == x) continue;
3477 if (!in_bounds(y2, x2)) {
3478 found_more_water++; /* hack */
3479 continue;
3480 }
3481 if (c2_ptr->feat == FEAT_SHAL_WATER ||
3482 // c2_ptr->feat == FEAT_WATER ||
3483 c2_ptr->feat == FEAT_TAINTED_WATER ||
3484 c2_ptr->feat == FEAT_DEEP_WATER) {
3485 found_more_water++;
3486 }
3487 }
3488 // if (!found_more_water) c_ptr->feat = FEAT_SHAL_WATER;
3489 /* also important for SEASON_WINTER, to turn lake border into ice */
3490 if (found_more_water < 8) c_ptr->feat = FEAT_SHAL_WATER;
3491 }
3492 /* turn single non-<deep water> fields to deep water */
3493 else if (c_ptr->feat != FEAT_DEEP_WATER) {
3494 found_more_water = 0;
3495 for (y2 = y-1; y2 <= y+1; y2++)
3496 for (x2 = x-1; x2 <= x+1; x2++) {
3497 c2_ptr = &zcave[y2][x2];
3498 if (y2 == y && x2 == x) continue;
3499 if (!in_bounds(y2, x2)) {
3500 found_more_water++; /* hack */
3501 continue;
3502 }
3503 if (c2_ptr->feat == FEAT_SHAL_WATER ||
3504 // c2_ptr->feat == FEAT_WATER ||
3505 c2_ptr->feat == FEAT_TAINTED_WATER ||
3506 c2_ptr->feat == FEAT_DEEP_WATER) {
3507 found_more_water++;
3508 }
3509 }
3510 if (found_more_water >= 7) c_ptr->feat = FEAT_SHAL_WATER;
3511 }
3512 }
3513
3514 /* Hack -- use the "complex" RNG */
3515 Rand_quick = rand_old;
3516
3517 /* Hack -- reattach existing objects to the map */
3518 setup_objects();
3519 /* Hack -- reattach existing monsters to the map */
3520 setup_monsters();
3521 }
3522
3523
3524 /* Generates a wilderness level. */
3525 void wilderness_gen(struct worldpos *wpos)
3526 {
3527 int i, y, x;
3528 cave_type *c_ptr;
3529 wilderness_type *w_ptr = &wild_info[wpos->wy][wpos->wx];
3530 #ifdef SIMPLE_BLEED
3531 wilderness_type *w_ptr2;
3532 #endif
3533 cave_type **zcave;
3534 struct dungeon_type *d_ptr = NULL;
3535 if(!(zcave = getcave(wpos))) return;
3536
3537
3538 process_hooks(HOOK_WILD_GEN, "d", wpos);
3539
3540
3541 /* Perma-walls -- North/South*/
3542 for (x = 0; x < MAX_WID; x++) {
3543 /* North wall */
3544 c_ptr = &zcave[0][x];
3545
3546 /* Clear previous contents, add "clear" perma-wall */
3547 c_ptr->feat = FEAT_PERM_CLEAR;
3548
3549 /* South wall */
3550 c_ptr = &zcave[MAX_HGT-1][x];
3551
3552 /* Clear previous contents, add "clear" perma-wall */
3553 c_ptr->feat = FEAT_PERM_CLEAR;
3554
3555 /* Illuminate and memorize the walls
3556 c_ptr->info |= (CAVE_GLOW);*/
3557 }
3558
3559 /* Perma-walls -- West/East */
3560 for (y = 0; y < MAX_HGT; y++) {
3561 /* West wall */
3562 c_ptr = &zcave[y][0];
3563 /* Clear previous contents, add "clear" perma-wall */
3564 c_ptr->feat = FEAT_PERM_CLEAR;
3565
3566 /* Illuminate and memorize the walls
3567 c_ptr->info |= (CAVE_GLOW);*/
3568
3569 /* East wall */
3570 c_ptr = &zcave[y][MAX_WID-1];
3571
3572 /* Clear previous contents, add "clear" perma-wall */
3573 c_ptr->feat = FEAT_PERM_CLEAR;
3574
3575 /* Illuminate and memorize the walls
3576 c_ptr->info |= (CAVE_GLOW);*/
3577 }
3578
3579 /* Hack -- Build some wilderness (from memory) */
3580 wilderness_gen_hack(wpos);
3581 if((w_ptr->flags & WILD_F_UP) && can_go_up(wpos, 0x1)) {
3582 zcave[w_ptr->dn_y][w_ptr->dn_x].feat = FEAT_LESS;
3583 d_ptr = w_ptr->tower;
3584 y = w_ptr->dn_y; x = w_ptr->dn_x;
3585 #if 0
3586 /* Hack to fix custom (type 0) dungeons/towers that were corrupted by old
3587 /debug-dun (/update-dun) command. */
3588 if (x == 0) x = w_ptr->dn_x = y = w_ptr->dn_y = 3;
3589 #endif
3590 }
3591 if((w_ptr->flags & WILD_F_DOWN) && can_go_down(wpos, 0x1)) {
3592 zcave[w_ptr->up_y][w_ptr->up_x].feat = FEAT_MORE;
3593 d_ptr = w_ptr->dungeon;
3594 y = w_ptr->up_y; x = w_ptr->up_x;
3595 #if 0
3596 /* Hack to fix custom (type 0) dungeons/towers that were corrupted by old
3597 /debug-dun (/update-dun) command. */
3598 if (x == 0) x = w_ptr->up_x = y = w_ptr->up_y = 3;
3599 #endif
3600 }
3601 /* add ambient features to the entrance so it looks less bland ;) - C. Blue */
3602 if (!istown(wpos) && d_ptr
3603 /* don't overwrite house walls if house contains a staircase
3604 (also see second check for this, further below) */
3605 && !(zcave[y][x].info & (CAVE_ROOM | CAVE_ICKY))
3606 ) {
3607 int j, k, solidity = 4;
3608 dungeon_info_type *di_ptr = &d_info[d_ptr->type];
3609 int feat_ambient = di_ptr->fill_type[0];//->inner_wall;
3610 int feat_ambient2 = (feat_ambient == FEAT_TREE) ? FEAT_BUSH : feat_ambient;
3611 int feat_floor = FEAT_DIRT;
3612 bool rand_old = Rand_quick; /* save rng */
3613 u32b tmp_seed = Rand_value;
3614 Rand_value = seed_town + (wpos->wx + wpos->wy * MAX_WILD_X) * 600; /* seed rng */
3615 Rand_quick = TRUE;
3616 int zx, zy;
3617 bool rig_corners = FALSE; /* corners are always floor, to make ambient feats look more circular? */
3618
3619 /* hack for Cloud Planes */
3620 if (feat_ambient == FEAT_CLOUDYSKY) {
3621 feat_ambient = FEAT_HIGH_MOUNTAIN;
3622 feat_floor = FEAT_SNOW;
3623 solidity = 3;
3624 rig_corners = TRUE;
3625 } else
3626 /* grab usual floor tile */
3627 for (k = 0; k < 9; k++) {
3628 zx = x + ddx_ddd[k];
3629 zy = y + ddy_ddd[k];
3630
3631 if ((zcave[zy][zx].info & (CAVE_ROOM | CAVE_ICKY))) continue;
3632 if ((f_info[zcave[zy][zx].feat].flags1 & FF1_WALL)) continue;
3633 if ((f_info[zcave[zy][zx].feat].flags1 & FF1_PERMANENT)) continue; /* don't clone the stairs ;) */
3634
3635 feat_floor = zcave[zy][zx].feat;
3636 break;
3637 }
3638
3639 /* towers use granite walls that look a bit like a tower basement */
3640 if (d_ptr == w_ptr->tower) {
3641 int rigged_rng = 0;
3642 #if 1 /* clear inner ring? */
3643 for (k = 0; k < 9; k++) {
3644 zx = x + ddx_ddd[k];
3645 zy = y + ddy_ddd[k];
3646
3647 /* don't overwrite house walls if house contains a staircase
3648 (also see first check for this, further above) */
3649 if ((zcave[zy][zx].info & (CAVE_ROOM | CAVE_ICKY))) continue;
3650
3651 /* don't overwrite any perma walls (usually house walls) */
3652 if ((f_info[zcave[zy][zx].feat].flags1 & FF1_PERMANENT) &&
3653 /* exception for mountains though, since they're not house-related and can just be overwritten */
3654 zcave[zy][zx].feat != FEAT_MOUNTAIN)
3655 continue;
3656
3657 zcave[zy][zx].feat = feat_floor;
3658 }
3659 #endif
3660
3661 /* create 'disrupted' outer ring of 'tower walls' */
3662 for (k = 0; k < 16; k++) {
3663 zx = x + ddx_wide_cyc[k];
3664 zy = y + ddy_wide_cyc[k];
3665
3666 /* don't overwrite house walls if house contains a staircase
3667 (also see first check for this, further above) */
3668 if ((zcave[zy][zx].info & (CAVE_ROOM | CAVE_ICKY))) continue;
3669
3670 /* don't overwrite any perma walls (usually house walls) */
3671 if ((f_info[zcave[zy][zx].feat].flags1 & FF1_PERMANENT)) continue;
3672
3673 if (rig_corners && (k == 0 || k == 4 || k == 8 || k == 12)) continue;
3674
3675 /* random holes -- bug rig it to grant a hole at least every n spaces */
3676 if (!rand_int(solidity) || rigged_rng == 3) {
3677 rigged_rng = 0;
3678
3679 #if 1 /* convert grids where we don't set tower feats to actual floor? */
3680 /* don't overwrite house walls if house contains a staircase
3681 (also see first check for this, further above) */
3682 if ((zcave[zy][zx].info & (CAVE_ROOM | CAVE_ICKY))) continue;
3683
3684 /* don't overwrite any perma walls (usually house walls) */
3685 if ((f_info[zcave[zy][zx].feat].flags1 & FF1_PERMANENT) &&
3686 /* exception for mountains though, since they're not house-related and can just be overwritten */
3687 zcave[zy][zx].feat != FEAT_MOUNTAIN)
3688 continue;
3689
3690 zcave[zy][zx].feat = feat_floor;
3691 continue;
3692 #endif
3693 }
3694
3695 zcave[zy][zx].feat = feat_ambient;
3696 rigged_rng++;
3697 }
3698 }
3699
3700 /* dungeons use the inner_wall fill_type[0] somewhat scattered/clumped */
3701 if (d_ptr == w_ptr->dungeon) {
3702 int zx, zy, xoff, yoff;
3703
3704 /* pick amount of floor feats to set */
3705 j = rand_int(4) + 4;
3706 /* pick a random starting direction */
3707 i = randint(8);
3708 if (i == 5) i++; /* 5 isn't a legal direction */
3709 /* hack: avoid a bit silly-looking ones */
3710 if (j == 3 && (i % 2) == 1) i++;
3711 if (i == 10) i = 6; /* 10 isn't a legal direction */
3712
3713 /* old/basic: just create a partial ring of dungeon-specific wall feats */
3714 /* cycle forward 'j' more grids and set them accordingly */
3715 for (k = 0; k < j; k++) {
3716 xoff = ddx[cycle[chome[i] + k]];
3717 yoff = ddy[cycle[chome[i] + k]];
3718 zx = x + xoff;
3719 zy = y + yoff;
3720
3721 /* don't overwrite house walls if house contains a staircase
3722 (also see first check for this, further above) */
3723 if ((zcave[zy][zx].info & (CAVE_ROOM | CAVE_ICKY))) continue;
3724
3725 /* don't overwrite any perma walls (usually house walls) */
3726 if ((f_info[zcave[zy][zx].feat].flags1 & FF1_PERMANENT) &&
3727 /* exception for mountains though, since they're not house-related and can just be overwritten */
3728 zcave[zy][zx].feat != FEAT_MOUNTAIN)
3729 continue;
3730
3731 zcave[zy][zx].feat = feat_ambient;
3732
3733 #if 1 /* additionally extend the ambient feats slightly, into the 2nd ring, at random */
3734 #if 1
3735 if (xoff && yoff) continue; //extending onto 2nd ring diagonally looks bad
3736 if (!rand_int(3)) continue;
3737
3738 zx += xoff;
3739 zy += yoff;
3740 #else
3741 if (!rand_int(3)) continue;
3742
3743 switch (rand_int(3)) {
3744 case 0: zy += xoff; break;
3745 case 1: zy += yoff;
3746 case 2: zx += xoff;
3747 }
3748 #endif
3749
3750 /* don't overwrite house walls if house contains a staircase
3751 (also see first check for this, further above) */
3752 if ((zcave[zy][zx].info & (CAVE_ROOM | CAVE_ICKY))) continue;
3753
3754 /* don't overwrite any perma walls (usually house walls) */
3755 if ((f_info[zcave[zy][zx].feat].flags1 & FF1_PERMANENT) &&
3756 /* exception for mountains though, since they're not house-related and can just be overwritten */
3757 zcave[zy][zx].feat != FEAT_MOUNTAIN)
3758 continue;
3759
3760 zcave[zy][zx].feat = feat_ambient2;
3761 #endif
3762 }
3763
3764 #if 1
3765 /* new: also replace the rest with usual floor around here, for easier walking there */
3766 for (k = 0; k < 9; k++) {
3767 zx = x + ddx_ddd[k];
3768 zy = y + ddy_ddd[k];
3769
3770 /* don't overwrite house walls if house contains a staircase
3771 (also see first check for this, further above) */
3772 if ((zcave[zy][zx].info & (CAVE_ROOM | CAVE_ICKY))) continue;
3773
3774 /* don't overwrite any perma walls (usually house walls) */
3775 if ((f_info[zcave[zy][zx].feat].flags1 & FF1_PERMANENT) &&
3776 /* exception for mountains though, since they're not house-related and can just be overwritten */
3777 zcave[zy][zx].feat != FEAT_MOUNTAIN)
3778 continue;
3779
3780 /* and most importantly don't overwrite our dungeon-wall feats */
3781 if (zcave[zy][zx].feat == feat_ambient) continue;
3782
3783 zcave[zy][zx].feat = feat_floor;
3784 #endif
3785 }
3786 }
3787
3788 /* restore rng */
3789 Rand_quick = rand_old;
3790 Rand_value = tmp_seed;
3791 }
3792 /* TODO: add 'inscription' to the dungeon/tower entrances */
3793
3794
3795 /* Day Light */
3796 if (IS_DAY) {
3797 /* Make some day-time residents */
3798 if (!(w_ptr->flags & WILD_F_INHABITED)) {
3799 // for (i = 0; i < w_ptr->type; i++) wild_add_monster(wpos);
3800 for (i = 0; i < rand_int(8) + 3; i++) wild_add_monster(wpos);
3801 w_ptr->flags |= WILD_F_INHABITED;
3802 }
3803 }
3804 /* Night Time */
3805 else {
3806 /* Make some night-time residents */
3807 if (!(w_ptr->flags & WILD_F_INHABITED)) {
3808 // for (i = 0; i < w_ptr->type; i++) wild_add_monster(wpos);
3809 for (i = 0; i < rand_int(8) + 3; i++) wild_add_monster(wpos);
3810 w_ptr->flags |= WILD_F_INHABITED;
3811 }
3812 }
3813
3814 #ifdef SIMPLE_BLEED /* use the real bleed stuff again instead of bleed_warn_feat() silliness */
3815 /* Indicate certain adjacent wilderness terrain types, so players
3816 won't suddenly get stuck in lava or mountains - C. Blue */
3817 for (x = 1; x < MAX_WID - 1; x++) {
3818 if ((wpos->wy < MAX_HGT - 1) && magik(30) &&
3819 wild_info[wpos->wy + 1][wpos->wx].type != w_ptr->type) {
3820 w_ptr2 = &wild_info[wpos->wy + 1][wpos->wx];
3821 c_ptr = &zcave[1][x];
3822 /* Don't cover stairs - mikaelh */
3823 if (c_ptr->feat == FEAT_MORE || c_ptr->feat == FEAT_LESS) continue;
3824 bleed_warn_feat(w_ptr2->type, c_ptr);
3825 }
3826 if ((wpos->wy > 0) && magik(30) &&
3827 wild_info[wpos->wy - 1][wpos->wx].type != w_ptr->type) {
3828 w_ptr2 = &wild_info[wpos->wy - 1][wpos->wx];
3829 c_ptr = &zcave[MAX_HGT-2][x];
3830 /* Don't cover stairs - mikaelh */
3831 if (c_ptr->feat == FEAT_MORE || c_ptr->feat == FEAT_LESS) continue;
3832 bleed_warn_feat(w_ptr2->type, c_ptr);
3833 }
3834 }
3835 for (y = 1; y < MAX_HGT - 1; y++) {
3836 if ((wpos->wx < MAX_WID - 1) && magik(30) &&
3837 wild_info[wpos->wy][wpos->wx + 1].type != w_ptr->type) {
3838 w_ptr2 = &wild_info[wpos->wy][wpos->wx + 1];
3839 c_ptr = &zcave[y][MAX_WID-2];
3840 /* Don't cover stairs - mikaelh */
3841 if (c_ptr->feat == FEAT_MORE || c_ptr->feat == FEAT_LESS) continue;
3842 bleed_warn_feat(w_ptr2->type, c_ptr);
3843 }
3844 if ((wpos->wx > 0) && magik(30) &&
3845 wild_info[wpos->wy][wpos->wx - 1].type != w_ptr->type) {
3846 w_ptr2 = &wild_info[wpos->wy][wpos->wx - 1];
3847 c_ptr = &zcave[y][1];
3848 /* Don't cover stairs - mikaelh */
3849 if (c_ptr->feat == FEAT_MORE || c_ptr->feat == FEAT_LESS) continue;
3850 bleed_warn_feat(w_ptr2->type, c_ptr);
3851 }
3852 }
3853 #endif
3854
3855 /* Set if we have generated the level before (unused now though, that
3856 whether or not to respawn objects and monsters is decided by distinct
3857 flags of their own - C. Blue) */
3858 w_ptr->flags |= WILD_F_GENERATED;
3859
3860 /* set all those flags */
3861 w_ptr->flags |= WILD_F_INVADERS | WILD_F_HOME_OWNERS | WILD_F_BONES | WILD_F_FOOD | WILD_F_OBJECTS | WILD_F_CASH | WILD_F_GARDENS;
3862 }
3863
3864
3865 #define MAXISLAND 5 /* maximum 'generic' terrain type island size */
3866 #define SEADENSITY 96 /* land/sea ratio */
3867
3868 #define MAXMOUNT 4 /* maximum mountain range size */
3869 #define MAXWOOD 4 /* maximum forest size */
3870 #define MAXWASTE 4 /* maximum wasteland size */
3871 #define MAXLAKE 3 /* maximum lake size */
3872 #define MAXISLANDS 4 /* maximum water-related island size */
3873 #define MAXDESERT 6 /* maximum desert size (very rare, hence big) */
3874 #define MAXICE 6 /* maximum desert size (very rare, hence big) */
3875
3876 //proportional inverse = amount
3877 #define RIVERS 512 /* rivers (don't have a MAX size limiter) */
3878 #define ROCKY 512 /* mountains */
3879 #define WOODY 256 /* trees */
3880 #define WASTE 1024 /* wasteland */
3881 #define LAKES 512 /* lakes */
3882 #define ISLANDS 512 /* water-related islands */
3883 #define DESERT 1536 /* desert */
3884 #define ICE 2404 /* ice */
3885
3886 static bool island_aux(int y, int x, unsigned char type, unsigned char fill, int size, int size_org) {
3887 bool added_decently = TRUE;
3888 int ranval;
3889
3890 if (y < 0 || x < 0 || y >= MAX_WILD_Y || x >= MAX_WILD_Y) return (size_org - size >= 2);
3891 if (wild_info[y][x].type != fill) return (size_org - size >= 2);
3892 ranval = rand_int(15);
3893 if (size) {
3894 added_decently = FALSE;
3895 if (ranval&1) added_decently = island_aux(y, x - 1, type, fill, size - 1, size_org) || added_decently;
3896 if (ranval&2) added_decently = island_aux(y, x + 1, type, fill, size - 1, size_org) || added_decently;
3897 if (ranval&4) added_decently = island_aux(y - 1, x, type, fill, size - 1, size_org) || added_decently;
3898 if (ranval&8) added_decently = island_aux(y + 1, x, type, fill, size - 1, size_org) || added_decently;
3899 }
3900 if ((rand_int(7) == 0)) {
3901 switch(type){
3902 case WILD_MOUNTAIN:
3903 type = WILD_VOLCANO;
3904 break;
3905 case WILD_LAKE:
3906 type = WILD_SWAMP;
3907 break;
3908 }
3909 }
3910 wild_info[y][x].type = type;
3911 return added_decently;
3912 }
3913 static bool island(int y, int x, unsigned char type, unsigned char fill, int size) {
3914 int size_org = size;
3915 bool added_decently;
3916
3917 /* hack: smally planned islands are always decently done */
3918 if (size_org <= 4) size_org = 9999;
3919
3920 added_decently = island_aux(y, x, type, fill, size, size_org);
3921 return added_decently;
3922 }
3923
3924 static void makeland() {
3925 int p, i;
3926 int x, y;
3927 int density = MAXISLAND;
3928 p = (MAX_WILD_Y * MAX_WILD_X) / SEADENSITY;
3929 for(i = 0; i < p; i++){
3930 do{
3931 x = rand_int(MAX_WILD_X - 1);
3932 y = rand_int(MAX_WILD_Y - 1);
3933 }while(wild_info[y][x].type != WILD_UNDEFINED);
3934 island(y, x, WILD_GRASSLAND, WILD_UNDEFINED, rand_int(1<<density));
3935 }
3936 }
3937
3938 static unsigned short makecoast(unsigned char edge, unsigned char new, unsigned char type, unsigned char fill, int y, int x) {
3939 unsigned short r = 0;
3940 if(y < 0 || x < 0 || y >= MAX_WILD_Y || x >= MAX_WILD_X) return(0);
3941 if(wild_info[y][x].type != fill){
3942 return((wild_info[y][x].type == type));
3943 }
3944 wild_info[y][x].type = new;
3945 if(makecoast(edge, new, type, fill, y, x - 1)) r = 1;
3946 if(makecoast(edge, new, type, fill, y, x + 1)) r = 1;
3947 if(makecoast(edge, new, type, fill, y - 1, x)) r = 1;
3948 if(makecoast(edge, new, type, fill, y + 1, x)) r = 1;
3949 if(r)
3950 wild_info[y][x].type = edge;
3951 return(0);
3952 }
3953
3954 static bool addhills() {
3955 bool added = FALSE;
3956 int i, p;
3957 int x, y;
3958 p = (MAX_WILD_Y * MAX_WILD_X) / ROCKY;
3959 for(i = 0; i < p; i++){
3960 do{
3961 x = rand_int(MAX_WILD_X - 1);
3962 y = rand_int(MAX_WILD_Y - 1);
3963 }while(wild_info[y][x].type != WILD_GRASSLAND);
3964 if (island(y, x, WILD_MOUNTAIN, WILD_GRASSLAND, rand_int((1<<MAXMOUNT) - 1))) added = TRUE;
3965 }
3966 return added;
3967 }
3968
3969 static bool addlakes() {
3970 bool added = FALSE;
3971 int i, p;
3972 int x, y;
3973 p = (MAX_WILD_Y * MAX_WILD_X) / LAKES;
3974 for(i = 0; i < p; i++){
3975 do{
3976 x = rand_int(MAX_WILD_X - 1);
3977 y = rand_int(MAX_WILD_Y - 1);
3978 }while(wild_info[y][x].type != WILD_GRASSLAND);
3979 if (island(y, x, WILD_LAKE, WILD_GRASSLAND, rand_int((1<<MAXLAKE) - 1))) added = TRUE;
3980 }
3981 return added;
3982 }
3983
3984 static bool addwaste() {
3985 bool added = FALSE;
3986 int i, p;
3987 int x, y;
3988 p = (MAX_WILD_Y * MAX_WILD_X) / WASTE;
3989 for(i = 0; i < p; i++){
3990 do{
3991 x = rand_int(MAX_WILD_X - 1);
3992 y = rand_int(MAX_WILD_Y - 1);
3993 }while(wild_info[y][x].type != WILD_GRASSLAND);
3994 if (island(y, x, WILD_WASTELAND, WILD_GRASSLAND, rand_int((1<<MAXWASTE) - 1))) added = TRUE;
3995 }
3996 return added;
3997 }
3998
3999 static bool adddesert() {
4000 bool added = FALSE;
4001 int i, p;
4002 int x, y;
4003 p = (MAX_WILD_Y * MAX_WILD_X) / DESERT;
4004 for(i = 0; i < p; i++){
4005 do{
4006 x = rand_int(MAX_WILD_X - 1);
4007 y = rand_int(MAX_WILD_Y - 1);
4008 }while(wild_info[y][x].type != WILD_GRASSLAND);
4009 if (island(y, x, WILD_DESERT, WILD_GRASSLAND, (1<<(MAXDESERT-1)) + rand_int((1<<(MAXDESERT-1))) - 1)) added = TRUE;
4010 // if (island(y, x, WILD_DESERT, WILD_GRASSLAND, rand_int((1<<MAXDESERT) - 1))) added = TRUE;
4011 }
4012 return added;
4013 }
4014
4015 static bool addice() {
4016 bool added = FALSE;
4017 int i, p;
4018 int x, y;
4019 p = (MAX_WILD_Y * MAX_WILD_X) / ICE;
4020 for(i = 0; i < p; i++){
4021 do{
4022 x = rand_int(MAX_WILD_X - 1);
4023 y = rand_int(MAX_WILD_Y - 1);
4024 }while(wild_info[y][x].type != WILD_GRASSLAND);
4025 if (island(y, x, WILD_ICE, WILD_GRASSLAND, (1<<(MAXICE-1)) + rand_int((1<<(MAXICE-1))) - 1)) added = TRUE;
4026 // if (island(y, x, WILD_ICE, WILD_GRASSLAND, rand_int((1<<MAXICE) - 1))) added = TRUE;
4027 }
4028 return added;
4029 }
4030
4031 static bool addislands() {
4032 bool added = FALSE;
4033 int i, p;
4034 int x, y;
4035 p = (MAX_WILD_Y * MAX_WILD_X) / ISLANDS;
4036 for (i = 0; i < p; i++) {
4037 do {
4038 x = rand_int(MAX_WILD_X - 1);
4039 y = rand_int(MAX_WILD_Y - 1);
4040 } while (wild_info[y][x].type != WILD_OCEANBED1);
4041 if (island(y, x, WILD_GRASSLAND, WILD_OCEANBED1, rand_int((1 << MAXISLANDS) - 1))) added = TRUE;
4042 }
4043 return added;
4044 }
4045
4046 static bool addforest() {
4047 bool added = FALSE;
4048 int i, p;
4049 int x, y;
4050 int size;
4051 p = (MAX_WILD_Y * MAX_WILD_X) / WOODY;
4052 for (i = 0; i < p; i++) {
4053 do {
4054 x = rand_int(MAX_WILD_X - 1);
4055 y = rand_int(MAX_WILD_Y - 1);
4056 } while (wild_info[y][x].type != WILD_GRASSLAND);
4057 size = rand_int((1 << MAXWOOD) - 1);
4058 if (island(y, x, WILD_FOREST, WILD_GRASSLAND, size)) added = TRUE;
4059 if (size > 3)
4060 if (island(y, x, WILD_DENSEFOREST, WILD_FOREST, size - 3)) added = TRUE;
4061 }
4062 return added;
4063 }
4064
4065 static int mvx[] = {0, 1, 1, 1, 0, -1, -1, -1};
4066 static int mvy[] = {1, 1, 0, -1, -1, -1, 0, 1};
4067
4068 static void river(int y, int x) {
4069 int mx, my;
4070 int dir, cdir, t;
4071
4072 dir = rand_int(7);
4073 while (wild_info[y][x].type != WILD_OCEAN){
4074 cdir = dir;
4075 if (y < 0 || x < 0 || y >= MAX_WILD_Y || x >= MAX_WILD_X) break;
4076 wild_info[y][x].type = WILD_RIVER;
4077 t = rand_int(31);
4078 switch (t) {
4079 case 0: cdir += 4;
4080 break;
4081 case 1: cdir += 5;
4082 break;
4083 case 2: cdir += 3;
4084 break;
4085 case 3:
4086 case 4:
4087 cdir += 6;
4088 break;
4089 case 5:
4090 case 6: cdir += 2;
4091 break;
4092 case 7:
4093 case 8:
4094 case 9: cdir += 1;
4095 break;
4096 case 10:
4097 case 11:
4098 case 12: cdir += 7;
4099 break;
4100 }
4101 if (cdir > 7) cdir -= 8;
4102 mx = x + mvx[cdir];
4103 my = y + mvy[cdir];
4104 if (mx < 0 || my < 0 || mx >= MAX_WILD_X || my >= MAX_WILD_Y) continue;
4105 if (wild_info[my][mx].type == WILD_TOWN) continue;
4106 x = mx;
4107 y = my;
4108 }
4109 }
4110
4111 static bool addrivers() {
4112 bool added = FALSE;
4113 int i, p;
4114 int x, y;
4115 p = (MAX_WILD_Y * MAX_WILD_X) / RIVERS;
4116 for (i = 0; i < p; i++) {
4117 do {
4118 x = rand_int(MAX_WILD_X - 1);
4119 y = rand_int(MAX_WILD_Y - 1);
4120 } while (wild_info[y][x].type != WILD_MOUNTAIN);
4121 river(y, x);
4122 added = TRUE;
4123 }
4124 return added;
4125 }
4126
4127 /* remove coastlines that aren't adjacent to any sort of sea terrain - C. Blue */
4128 static void fix_coasts() {
4129 int x, y, d;
4130 bool sea;
4131
4132 for(x = 0; x < MAX_WILD_X; x++)
4133 for(y = 0; y < MAX_WILD_Y; y++) {
4134 if (wild_info[y][x].type != WILD_COAST) continue;
4135
4136 sea = FALSE;
4137 for (d = 0; d < 8; d++) {
4138 int x2 = x + ddx_cyc[d];
4139 int y2 = y + ddy_cyc[d];
4140 if (in_bounds_wild(y2, x2)) {
4141 switch (wild_info[y2][x2].type) {
4142 case WILD_OCEAN:
4143 case WILD_OCEANBED1: case WILD_OCEANBED2:
4144 case WILD_SHORE1: case WILD_SHORE2:
4145 sea = TRUE;
4146 break;
4147 }
4148 }
4149 }
4150 /* if this coast doesn't make sense, reset it to default fill type grassland */
4151 if (!sea) wild_info[y][x].type = WILD_GRASSLAND;
4152 }
4153 }
4154
4155 void genwild(bool all_terrains, bool dry_Bree) {
4156 int j,i;
4157 bool rand_old = Rand_quick;
4158 u32b old_seed = Rand_value;
4159 bool dry, got_everything;
4160
4161 Rand_quick = TRUE;
4162
4163 while (TRUE) {
4164 got_everything = TRUE;
4165
4166 Rand_value = seed_town;
4167
4168 island(cfg.town_y, cfg.town_x,WILD_GRASSLAND, WILD_UNDEFINED, 5);
4169 wild_info[cfg.town_y][cfg.town_x].type = WILD_TOWN;
4170 makeland();
4171 for (j = 0; j < MAX_WILD_Y; j++) {
4172 for (i = 0; i < MAX_WILD_X; i++) {
4173 if (wild_info[j][i].type == WILD_UNDEFINED) {
4174 makecoast(WILD_SHORE1, WILD_OCEANBED1, WILD_GRASSLAND, WILD_UNDEFINED, j, i);
4175 }
4176 }
4177 }
4178 for (j = 0 ; j < MAX_WILD_Y; j++) {
4179 for (i = 0 ;i < MAX_WILD_X; i++) {
4180 if (wild_info[j][i].type == WILD_OCEANBED1) {
4181 makecoast(WILD_SHORE2, WILD_OCEANBED2, WILD_SHORE1, WILD_OCEANBED1, j, i);
4182 }
4183 }
4184 }
4185 for (j = 0; j < MAX_WILD_Y; j++) {
4186 for (i = 0; i < MAX_WILD_X; i++) {
4187 if (wild_info[j][i].type == WILD_OCEANBED2) {
4188 makecoast(WILD_SHORE1, WILD_OCEANBED1, WILD_SHORE2, WILD_OCEANBED2, j, i);
4189 }
4190 }
4191 }
4192 addislands();
4193 for (j = 0; j <MAX_WILD_Y; j++) {
4194 for (i = 0; i < MAX_WILD_X; i++) {
4195 if (wild_info[j][i].type == WILD_SHORE1 || wild_info[j][i].type == WILD_SHORE2) {
4196 wild_info[j][i].type = WILD_OCEANBED1;
4197 }
4198 }
4199 }
4200 for (j = 0; j < MAX_WILD_Y;j++) {
4201 for (i = 0; i < MAX_WILD_X; i++) {
4202 if (wild_info[j][i].type == WILD_OCEANBED1) {
4203 makecoast(WILD_COAST, WILD_OCEAN, WILD_GRASSLAND, WILD_OCEANBED1, j, i);
4204 }
4205 }
4206 }
4207
4208 fix_coasts();
4209
4210 if (all_terrains) {
4211 got_everything = got_everything && addhills();
4212 got_everything = got_everything && addrivers();
4213 got_everything = got_everything && addforest();
4214 got_everything = got_everything && addlakes();
4215 got_everything = got_everything && addwaste();
4216 got_everything = got_everything && adddesert();
4217 got_everything = got_everything && addice();
4218 } else {
4219 addhills();
4220 addrivers();
4221 addforest();
4222 addlakes();
4223 addwaste();
4224 adddesert();
4225 addice();
4226 }
4227
4228 /* Check that Bree is surrounded by pretty dry terrain */
4229 if (dry_Bree) {
4230 int tol = 0, dist;
4231 dry = TRUE;
4232 for (i = cfg.town_x - MAX_TOWNAREA - tol; i <= cfg.town_x + MAX_TOWNAREA + tol; i++) {
4233 for (j = cfg.town_y - MAX_TOWNAREA - tol; j <= cfg.town_y + MAX_TOWNAREA + tol; j++) {
4234 /* use a radius, not a square */
4235 //if (distance(j, i, 32, 32) > MAX_TOWNAREA) continue;
4236 //if (wild_info[j][i].radius > MAX_TOWNAREA) continue;
4237 dist = abs(i - cfg.town_x) + abs(j - cfg.town_y);
4238 if (dist > MAX_TOWNAREA + tol) continue;
4239
4240 switch (wild_info[j][i].type) {
4241 #if 0
4242 case WILD_OCEANBED1: case WILD_OCEANBED2:
4243 case WILD_COAST:
4244 case WILD_SHORE1: case WILD_SHORE2:
4245 #endif
4246 /* hack: turn 'dry bree' rather into 'clean bree' */
4247 case WILD_FOREST:
4248 case WILD_DENSEFOREST:
4249 case WILD_SWAMP:
4250 case WILD_VOLCANO:
4251 case WILD_MOUNTAIN:
4252 if (dist <= 1) dry = FALSE;
4253 break;
4254
4255 case WILD_DESERT:
4256 case WILD_ICE:
4257 /* fall through */
4258
4259 /* the mainly annoying terrains: */
4260 case WILD_OCEAN:
4261 case WILD_RIVER:
4262 case WILD_LAKE:
4263 dry = FALSE;
4264 break;
4265 }
4266 }
4267 }
4268 got_everything = got_everything && dry;
4269 }
4270
4271 if (got_everything) break;
4272
4273 /* Change wilderness generation seed */
4274 seed_town = rand_int(0x10000000);
4275 /* Kill Bree */
4276 for (i = 0; i < numtowns; i++) dealloc_stores(i);
4277 C_KILL(town, numtowns, struct town_type);
4278 numtowns = 0;
4279 /* Re-init the wild_info array and try again */
4280 init_wild_info();
4281 }
4282
4283
4284 /* Restore random generator */
4285 Rand_quick = rand_old;
4286 Rand_value = old_seed;
4287 }
4288
4289
4290
4291
4292
4293 /* Show a small radius of wilderness around the player */
4294 bool reveal_wilderness_around_player(int Ind, int y, int x, int h, int w)
4295 {
4296 player_type *p_ptr = Players[Ind];
4297 int i, j;
4298 bool shown = FALSE;
4299
4300 /* Circle or square ? */
4301 if (h == 0) {
4302 for (i = x - w; i < x + w; i++) {
4303 for (j = y - w; j < y + w; j++) {
4304 /* Bound checking */
4305 if (!in_bounds_wild(j, i)) continue;
4306
4307 /* We want a radius, not a "squarus" :) */
4308 if (distance(y, x, j, i) >= w) continue;
4309
4310 /* New we know here */
4311 if (!(p_ptr->wild_map[(i + j * MAX_WILD_X) / 8] &
4312 (1 << ((i + j * MAX_WILD_X) % 8))))
4313 {
4314 p_ptr->wild_map[(i + j * MAX_WILD_X) / 8] |=
4315 (1 << ((i + j * MAX_WILD_X) % 8));
4316 shown = TRUE;
4317 }
4318
4319 #if 0
4320 wild_map[j][i].known = TRUE;
4321
4322 /* Only if we are in overview */
4323 if (p_ptr->wild_mode)
4324 {
4325 cave[j][i].info |= (CAVE_GLOW | CAVE_MARK);
4326
4327 /* Show it */
4328 lite_spot(j, i);
4329 }
4330 #endif // 0
4331 }
4332 }
4333 } else {
4334 for (i = x; i < x + w; i++) {
4335 for (j = y; j < y + h; j++) {
4336 /* Bound checking */
4337 if (!in_bounds_wild(j, i)) continue;
4338
4339 /* New we know here */
4340 if (!(p_ptr->wild_map[(i + j * MAX_WILD_X) / 8] &
4341 (1 << ((i + j * MAX_WILD_X) % 8))))
4342 {
4343 p_ptr->wild_map[(i + j * MAX_WILD_X) / 8] |=
4344 (1 << ((i + j * MAX_WILD_X) % 8));
4345 shown = TRUE;
4346 }
4347
4348 #if 0
4349 wild_map[j][i].known = TRUE;
4350
4351 /* Only if we are in overview */
4352 if (p_ptr->wild_mode) {
4353 cave[j][i].info |= (CAVE_GLOW | CAVE_MARK);
4354
4355 /* Show it */
4356 lite_spot(j, i);
4357 }
4358 #endif // 0
4359 }
4360 }
4361 }
4362
4363 return (shown);
4364 }
4365
4366 /* Add new dungeons/towers that were added to d_info.txt after the server was already initialized - C. Blue */
4367 void wild_add_new_dungeons(int Ind) {
4368 int i, j, k, x, y, tries, sx, sy;
4369 bool retry, skip, found;
4370 dungeon_type *d_ptr;
4371 worldpos wpos;
4372
4373 for (i = 1; i < max_d_idx; i++) {
4374 retry = FALSE;
4375
4376 /* Skip empty entry */
4377 if (!d_info[i].name) continue;
4378
4379 /* Hack -- omit dungeons associated with towns */
4380 skip = FALSE;
4381 for (j = 1; j < 6; j++) {
4382 for (k = 0; k < 2; k++)
4383 if (town_profile[j].dungeons[k] == i) skip = TRUE;
4384 }
4385 if (skip) continue;
4386
4387 /* Does this dungeon exist yet? */
4388 found = FALSE;
4389 for (y = 0; y < MAX_WILD_Y; y++)
4390 for (x = 0; x < MAX_WILD_X; x++) {
4391 if ((d_ptr = wild_info[y][x].tower)) {
4392 if (d_ptr->type == i) found = TRUE;
4393 }
4394 if ((d_ptr = wild_info[y][x].dungeon)) {
4395 if (d_ptr->type == i) found = TRUE;
4396 // if (!strcmp(d_ptr->name + d_name, d_info[i].name + d_name)) found = TRUE;
4397 // if (d_ptr->id == i) found = TRUE;
4398 }
4399 }
4400 if (found) continue;
4401
4402 /* Add it */
4403 tries = 100;
4404 while (tries) {
4405 if (!Ind) {
4406 y = rand_int(MAX_WILD_Y);
4407 x = rand_int(MAX_WILD_X);
4408 } else {
4409 y = Players[Ind]->wpos.wy;
4410 x = Players[Ind]->wpos.wx;
4411 tries = 1;
4412 }
4413 retry = FALSE;
4414
4415 wpos.wy = y;
4416 wpos.wx = x;
4417
4418 /* Don't build them too near to towns
4419 * (otherwise entrance can be within a house) */
4420 if (!Ind) for (j = 1; j < 6; j++) {
4421 if (distance(y, x, town[j].y, town[j].x) <= MAX_TOWNAREA) {
4422 retry = TRUE;
4423 break;
4424 }
4425 }
4426 if (!retry) {
4427 if (wild_info[y][x].dungeon || wild_info[y][x].tower) retry = TRUE;
4428
4429 /* TODO: easy dungeons around Bree,
4430 * hard dungeons around Lorien */
4431 }
4432 #if 0
4433 if (retry) {
4434 if (tries-- > 0) i--;
4435 continue;
4436 }
4437 #else
4438 tries--;
4439 if (!retry) break;
4440 #endif
4441 }
4442 if (!tries) s_printf("Dungeon %d couldn't get added.\n", i);
4443
4444 add_dungeon(&wpos, 0, 0, 0, 0, 0, FALSE, i, 0, 0, 0);
4445
4446 /* 0 or MAX_{HGT,WID}-1 are bad places for stairs - mikaelh */
4447 if (!Ind) {
4448 sx = 2 + rand_int(MAX_WID - 4);
4449 sy = 2 + rand_int(MAX_HGT - 4);
4450 } else {
4451 sx = Players[Ind]->px;
4452 sy = Players[Ind]->py;
4453 }
4454 if (d_info[i].flags1 & DF1_TOWER) {
4455 s_printf(" (nldy %d, nldx %d)\n", sy, sx);
4456 new_level_down_y(&wpos, sy);
4457 new_level_down_x(&wpos, sx);
4458 } else {
4459 s_printf(" (nluy %d, nlux %d)\n", sy, sx);
4460 new_level_up_y(&wpos, sy);
4461 new_level_up_x(&wpos, sx);
4462 }
4463 #if 0
4464 if ((zcave = getcave(&p_ptr->wpos))) {
4465 zcave[p_ptr->py][p_ptr->px].feat = FEAT_MORE;
4466 }
4467 #endif // 0
4468
4469 //#if DEBUG_LEVEL > 0
4470 s_printf("Dungeon %d is generated in %s.\n", i, wpos_format(0, &wpos));
4471 //#endif // 0
4472
4473 tries = 100;
4474 }
4475 }
4476
4477 /* manipulate flag of the player's wilderness level;
4478 accessible from lua */
4479 void wild_flags(int Ind, u32b flags) {
4480 /* -1 = just display flags */
4481 if (flags == -1) {
4482 msg_format(Ind, "Current flags: %d (0x%X).",
4483 wild_info[Players[Ind]->wpos.wy][Players[Ind]->wpos.wx].flags,
4484 wild_info[Players[Ind]->wpos.wy][Players[Ind]->wpos.wx].flags);
4485 return;
4486 }
4487
4488 msg_format(Ind, "Old flags: %d (0x%X). New flags: %d (0x%X).",
4489 wild_info[Players[Ind]->wpos.wy][Players[Ind]->wpos.wx].flags,
4490 wild_info[Players[Ind]->wpos.wy][Players[Ind]->wpos.wx].flags,
4491 flags, flags);
4492 wild_info[Players[Ind]->wpos.wy][Players[Ind]->wpos.wx].flags = flags;
4493 }
4494
4495 /* make wilderness more lively again, populating it in various ways - C. Blue
4496 flags values:
4497 0 -- season-dependant
4498 other than 0 -- clear flags in all wilderness (op: wildflags & ~flags)
4499 */
4500 void lively_wild(u32b flags) {
4501 int x, y;
4502 for (x = 0; x < MAX_WILD_X; x++)
4503 for (y = 0; y < MAX_WILD_Y; y++) {
4504 /* specific value? */
4505 if (flags) {
4506 wild_info[y][x].flags &= ~flags;
4507 continue;
4508 }
4509
4510 /* season-dependant? */
4511 /* except for winter, regrow gardens.
4512 Maybe not very realistic timing, but looks nice.. */
4513 if (season != SEASON_WINTER) wild_info[y][x].flags &= ~WILD_F_GARDENS;
4514 /* much to eat from harvesting */
4515 if (season == SEASON_AUTUMN) wild_info[y][x].flags &= ~WILD_F_FOOD;
4516 /* bones from last winter o_O - also new people arrive */
4517 if (season == SEASON_SPRING) wild_info[y][x].flags &= ~(WILD_F_BONES | WILD_F_HOME_OWNERS | WILD_F_OBJECTS | WILD_F_CASH);
4518 /* they return home and are stocking up for winter */
4519 if (season == SEASON_WINTER) wild_info[y][x].flags &= ~(WILD_F_HOME_OWNERS | WILD_F_OBJECTS | WILD_F_CASH);
4520 /* now they come ^^ */
4521 //if (season == SEASON_SUMMER) wild_info[y][x].flags |= WILD_F_INVADERS;
4522 wild_info[y][x].flags &= ~WILD_F_INVADERS; /* every time? */
4523 }
4524 }
4525
4526 #ifdef HOUSE_PAINTING
4527 /* Paints a house at the location with potion in slot 'k' - C. Blue */
4528 void paint_house(int Ind, int x, int y, int k) {
4529 player_type *p_ptr = Players[Ind];
4530 cave_type **zcave = getcave(&p_ptr->wpos), *hwc_ptr;
4531 struct c_special *cs_ptr;
4532 house_type *h_ptr = NULL;
4533 object_type *o_ptr;
4534 int h_idx, c;
4535 int hwx, hwy;
4536
4537 /* Sanity check */
4538 if (k < 0 || k >= INVEN_PACK) return;
4539
4540 /* see if we have a potion */
4541 o_ptr = &p_ptr->inventory[k];
4542 if (!o_ptr->k_idx) {
4543 msg_print(Ind, "\377oThat inventory slot is empty!");
4544 return;
4545 }
4546 if (o_ptr->tval != TV_POTION && o_ptr->tval != TV_POTION2) { /* please don't waste POTION2 for this oO */
4547 msg_print(Ind, "\377oThat inventory slot does not hold potions!");
4548 return;
4549 }
4550
4551 /* Check for a house door next to us */
4552 h_idx = pick_house(&p_ptr->wpos, y, x);
4553 if (h_idx == -1) {
4554 msg_print(Ind, "There is no house next to you.");
4555 return;
4556 }
4557 h_ptr = &houses[h_idx];
4558
4559 /* make sure we own the house */
4560 if (!(cs_ptr = GetCS(&zcave[y][x], CS_DNADOOR))) {
4561 msg_print(Ind, "You must have access to the house.");
4562 return;
4563 }
4564 if (!(access_door(Ind, cs_ptr->sc.ptr, FALSE) || is_admin(p_ptr))) {
4565 msg_print(Ind, "You must have access to the house.");
4566 return;
4567 }
4568 s_printf("HOUSE_PAINTING: %s used potion %d,%d.\n", p_ptr->name, o_ptr->tval, o_ptr->sval);
4569
4570 /* extract colour from the potion */
4571 /* acquire potion colour */
4572 c = potion_col[o_ptr->sval + (o_ptr->tval == TV_POTION2 ? 4 : 0)];
4573 /* translate flickering colours to static ones */
4574 switch (c) {
4575 case TERM_ACID: c = TERM_SLATE; break;
4576 case TERM_COLD: c = TERM_L_WHITE; break;
4577 case TERM_ELEC: c = TERM_BLUE; break;
4578 case TERM_FIRE: c = TERM_ORANGE; break;
4579 case TERM_POIS: c = TERM_GREEN; break;
4580 case TERM_LITE: c = TERM_ORANGE; break;
4581 case TERM_HALF: c = TERM_L_WHITE; break; /* they all mix ;-p */
4582 case TERM_MULTI: c = TERM_L_WHITE; break; /* ... */
4583 case TERM_DARKNESS: c = TERM_L_DARK; break;
4584 case TERM_SOUN: c = TERM_L_UMBER; break;
4585 case TERM_CONF: c = TERM_UMBER; break;
4586 case TERM_SHAR: c = TERM_UMBER; break;
4587 case TERM_SHIELDI: c = TERM_L_WHITE; break; /* mixage again.. */
4588 case TERM_SHIELDM: c = TERM_VIOLET; break; /* well, either that or red.. */
4589 }
4590 /* 0 means 'no colour' so we start at 1 for colour 0 */
4591 c++;
4592
4593 /* Hack: water removes paint :) */
4594 if (o_ptr->sval == SV_POTION_WATER) c = 0;
4595 /* Hack: add owner mode to colour */
4596 else if (h_ptr->dna->mode & MODE_EVERLASTING) c += 100;
4597
4598 /* potion used up */
4599 inven_item_increase(Ind, k, -1);
4600 inven_item_describe(Ind, k);
4601 inven_item_optimize(Ind, k);
4602
4603 /* paint house, colour adjacent walls accordingly */
4604 h_ptr->colour = c;
4605
4606 for (hwx = x - 1; hwx <= x + 1; hwx++)
4607 for (hwy = y - 1; hwy <= y + 1; hwy++) {
4608 if (!in_bounds(hwy, hwx)) continue;
4609
4610 hwc_ptr = &zcave[hwy][hwx];
4611 /* Only colour house wall grids */
4612 if (hwc_ptr->feat == FEAT_WALL_HOUSE ||
4613 hwc_ptr->feat == FEAT_HOME ||
4614 hwc_ptr->feat == FEAT_HOME_OPEN) {
4615 hwc_ptr->colour = c;
4616
4617 /* refresh player's view on the freshly applied paint */
4618 everyone_lite_spot(&p_ptr->wpos, hwy, hwx);
4619 }
4620 }
4621
4622 /* voila */
4623 if (c)
4624 msg_print(Ind, "With some effort, you paint your house door..");
4625 else
4626 msg_print(Ind, "With some effort, you remove the paint off your house door..");
4627 }
4628 #endif
4629
4630 void knock_house(int Ind, int x, int y) {
4631 player_type *p_ptr = Players[Ind];
4632 int h_idx;
4633
4634 /* Check for a house door next to us */
4635 h_idx = pick_house(&p_ptr->wpos, y, x);
4636 if (h_idx == -1) {
4637 msg_print(Ind, "There is no house next to you.");
4638 return;
4639 }
4640
4641 /* knock on the house door! */
4642 msg_format_near(Ind, "\377s%s knocks on the house door..", p_ptr->name);
4643 msg_print(Ind, "\377sYou knock on the house door..");
4644 #ifdef USE_SOUND_2010
4645 //item_magestaff, block_shield_projectile!, (tunnel_rubble)
4646 //sound_near_site(y, x, &p_ptr->wpos, 0, (houses[h_idx].flags & HF_MOAT) ? "knock_castle" : "knock", "block_shield_projectile", SFX_TYPE_COMMAND, FALSE);//don't require LOS
4647 sound_house_knock(h_idx, x, y);
4648 #endif
4649 }
4650
4651 /* Modify grids of an outdoor level:
4652 Change features depending on season,
4653 change lighting depending on daytime */
4654 void wpos_apply_season_daytime(worldpos *wpos, cave_type **zcave) {
4655 int x, y;
4656 cave_type *c_ptr;
4657
4658 /* hack - abuse for WILD_ICE */
4659 if (wild_info[wpos->wy][wpos->wx].type == WILD_ICE) {
4660 /* Turn all water into ice */
4661 if (!wpos->wz)
4662 for (y = 1; y < MAX_HGT - 1; y++)
4663 for (x = 1; x < MAX_WID - 1; x++) {
4664 c_ptr = &zcave[y][x];
4665 if (c_ptr->feat == FEAT_SHAL_WATER ||
4666 c_ptr->feat == FEAT_TAINTED_WATER ||
4667 c_ptr->feat == FEAT_DEEP_WATER) {
4668 c_ptr->feat = FEAT_ICE;
4669 }
4670 }
4671 }
4672 /* apply season-specific FEAT-manipulation */
4673 else if (season == SEASON_WINTER
4674 && wild_info[wpos->wy][wpos->wx].type != WILD_DESERT
4675 && wild_info[wpos->wy][wpos->wx].type != WILD_VOLCANO) {
4676 /* Turn some water into ice */
4677 if (!wpos->wz)
4678 for (y = 1; y < MAX_HGT - 1; y++)
4679 for (x = 1; x < MAX_WID - 1; x++) {
4680 c_ptr = &zcave[y][x];
4681 if (c_ptr->feat == FEAT_SHAL_WATER ||
4682 c_ptr->feat == FEAT_TAINTED_WATER) {
4683 c_ptr->feat = FEAT_ICE;
4684 }
4685 }
4686 }
4687
4688 /* apply nightly darkening or daylight */
4689 if (!wpos->wz) {
4690 if (IS_DAY) world_surface_day(wpos);
4691 else world_surface_night(wpos);
4692 }
4693 }
4694
4695 /* returns price for a house of a certain area */
4696 s32b house_price_area(int area, bool has_moat, bool random) {
4697 s32b price = 0;
4698
4699 // This is the dominant term for large houses
4700 if (area > 40) price = (area - 40) * (area - 40) * (area - 40) * 3;
4701 // This is the dominant term for medium houses
4702 price += area * area * 33;
4703 // This is the dominant term for small houses
4704 price += area * (950 + (random ? rand_int(100) : 100));
4705
4706 /* Castles cost more */
4707 if (has_moat) price = (price * 5) / 4;
4708
4709 return price;
4710 }
4711
4712 /* returns buying price of a house */
4713 s32b initial_house_price(house_type *h_ptr) {
4714 s32b price;
4715 int area = 0;
4716
4717 /* 'area' us used for both, HF_RECT and HF_NONE (poly) houses */
4718 if (h_ptr->flags & HF_RECT)
4719 area = (h_ptr->coords.rect.width - 2) * (h_ptr->coords.rect.height - 2);
4720 #if 0 /* TODO (only for house-creation-houses) */
4721 else {
4722 ..curr->cvert
4723 area =
4724 }
4725
4726 /* currently unused since this is only for house-creation houses,
4727 and those would require implementing non-HF_RECT area (see code above) first */
4728 if (h_ptr->flags & HF_SELFBUILT)
4729 return area * area * 400;
4730 #endif
4731
4732 #ifdef DEVEL_TOWN_COMPATIBILITY /* old */
4733 /* Setup some "house info" */
4734 price = (area * area);
4735 price *= 15;
4736 price *= 80 + randint(40);
4737 #else
4738 #ifdef __DISABLE_HOUSEBOOST
4739 // This is the dominant term for large houses
4740 if (area > 40) price = (area - 40) * (area - 40) * (area - 40) * 3;
4741 else price = 0;
4742 // This is the dominant term for medium houses
4743 price += area * area * 33;
4744 // This is the dominant term for small houses
4745 price += area * (900 + rand_int(200));
4746 #else
4747 price = house_price_area(area, (h_ptr->flags & HF_MOAT), TRUE);
4748 #endif
4749 #endif
4750
4751 return price;
4752 }
4753
4754 /* Returns town if we're within a town area of radius MAX_TOWNAREA (housing!).
4755 NOTE: This function assumes that towns have a minimum distance of 6,
4756 even diagonally! */
4757 int wild_gettown(int x, int y) {
4758 int i;
4759
4760 if (wild_info[y][x].type == WILD_TOWN) {
4761 for (i = 0; i < numtowns; i++)
4762 if (town[i].x == x && town[i].y == y) return i;
4763
4764 /* paranoia - shouldn't be possible */
4765 return -1;
4766 }
4767
4768 if (wild_info[y][x].radius > MAX_TOWNAREA) return -1;
4769
4770 for (i = 0; i < numtowns; i++) {
4771 if (town[i].x >= x - 3 &&
4772 town[i].x <= x + 3 &&
4773 town[i].y >= y - 3 &&
4774 town[i].y <= y + 3)
4775 return i;
4776 }
4777
4778 /* paranoia - shouldn't be possible */
4779 return -1;
4780 }
4781