1 /* File: wild3.c */
2
3 /* Purpose: Wilderness drawing */
4
5 /*
6 * Copyright (c) 1989, 2003 James E. Wilson, Robert A. Koeneke,
7 * Robert Ruehlmann, Steven Fuerst
8 *
9 * This software may be copied and distributed for educational, research, and
10 * not for profit purposes provided that this copyright and statement are
11 * included in all such copies.
12 */
13 #include "angband.h"
14
15 #include "wild.h"
16
17 /*
18 * Helper functions that can be called recursively. (Need function prototypes.)
19 * See make_wild_03() for an instance of this.
20 * This ability will also be used by other routines in the future.
21 */
22 static void gen_block_helper(blk_ptr block_ptr, byte *data, int gen_type,
23 bool road);
24 static void blend_helper(cave_type *c_ptr, byte *data, int g_type);
25
26
27
28 /*
29 * Generate the selected place
30 */
place_gen(place_type * pl_ptr)31 static void place_gen(place_type *pl_ptr)
32 {
33 switch (pl_ptr->type)
34 {
35 case TOWN_OLD:
36 {
37 van_town_gen(pl_ptr);
38 break;
39 }
40 case TOWN_FRACT:
41 {
42 draw_city(pl_ptr);
43 break;
44 }
45 case TOWN_QUEST:
46 {
47 draw_quest(pl_ptr);
48 break;
49 }
50 case TOWN_DUNGEON:
51 {
52 draw_dungeon(pl_ptr);
53 break;
54 }
55 default:
56 {
57 quit("Unknown town/quest type in wilderness");
58 }
59 }
60
61 /* Hack - set global region back to wilderness value */
62 set_region(0);
63 }
64
65
66 /*
67 * Overlay the town block
68 * If the town is not built correctly, build it
69 */
overlay_place(int x,int y,u16b w_place,blk_ptr block_ptr)70 static void overlay_place(int x, int y, u16b w_place, blk_ptr block_ptr)
71 {
72 int i, j, x1, y1, x2, y2;
73
74 int fld_idx, type;
75
76 wild_done_type *w_ptr = &wild[y][x].done;
77
78 /* Generation level for monsters and objects */
79 int level = w_ptr->mon_gen;
80
81 cave_type *c_ptr;
82 place_type *pl_ptr = &place[w_place];
83
84 /* Check that place region exists */
85 if (!pl_ptr->region)
86 {
87 /* Create the place */
88 place_gen(pl_ptr);
89 }
90
91 /* Paranoia */
92 if (!pl_ptr->region) quit("Could not get a region for the town/quest");
93
94 /* Find block to copy */
95 x1 = (x - place[w_place].x) * WILD_BLOCK_SIZE;
96 y1 = (y - place[w_place].y) * WILD_BLOCK_SIZE;
97
98 /* copy 16x16 block from the region */
99 for (j = 0; j < WILD_BLOCK_SIZE; j++)
100 {
101 for (i = 0; i < WILD_BLOCK_SIZE; i++)
102 {
103 /* Get pointer to overlay info */
104 c_ptr = access_region(x1 + i, y1 + j, pl_ptr->region);
105
106 /* Only copy terrain if there is something there. */
107 if (c_ptr->feat != FEAT_NONE)
108 {
109 /* Copy the terrain */
110 block_ptr[j][i].feat = c_ptr->feat;
111 }
112 /* Get destination */
113 x2 = x * WILD_BLOCK_SIZE + i;
114 y2 = y * WILD_BLOCK_SIZE + j;
115
116
117 /*
118 * Instantiate field
119 *
120 * Note that most types of field are not in this list.
121 *
122 * Doors, buildings, traps, quests etc.
123 * are all that are in this list.
124 */
125 fld_idx = c_ptr->fld_idx;
126
127 if (fld_idx)
128 {
129 type = t_info[c_ptr->fld_idx].type;
130 }
131 else
132 {
133 type = FTYPE_NOTHING;
134 }
135
136 switch (type)
137 {
138 case FTYPE_NOTHING:
139 {
140 /* Nothing */
141 break;
142 }
143
144 case FTYPE_TRAP:
145 {
146 /* Trap */
147
148 /* Activate the trap */
149 if (place_field(x2, y2, c_ptr->fld_idx))
150 {
151 field_type *f_ptr = &fld_list[block_ptr[j][i].fld_idx];
152
153 /* Initialise it */
154 (void)field_script_single(f_ptr, FIELD_ACT_INIT, "");
155 }
156
157 break;
158 }
159
160 case FTYPE_DOOR:
161 {
162 /* Door */
163 int data = 9;
164
165 /* Add a door field */
166 if (place_field(x2, y2, c_ptr->fld_idx))
167 {
168 field_type *f_ptr = &fld_list[block_ptr[j][i].fld_idx];
169
170 /* Add "power" of lock / jam to the field */
171 (void)field_script_single(f_ptr, FIELD_ACT_INIT,
172 "i:", LUA_VAR_NAMED(data, "power"));
173 }
174
175 break;
176 }
177
178 case FTYPE_BUILD:
179 {
180 /* Stores + buildings */
181 (void)place_field(x2, y2, c_ptr->fld_idx);
182
183 break;
184 }
185 }
186
187 /*
188 * Instantiate object
189 */
190 place_specific_object(x2, y2, level, c_ptr->o_idx);
191
192 /*
193 * Instantiate monster
194 */
195 if (c_ptr->m_idx)
196 {
197 place_monster_one(x2, y2, c_ptr->m_idx, FALSE, FALSE, FALSE);
198 }
199 }
200 }
201 }
202
203
204
205 /* Clear the temporary block */
clear_temp_block(void)206 void clear_temp_block(void)
207 {
208 int i, j;
209
210 /* Clear the section */
211 for (i = 0; i <= WILD_BLOCK_SIZE; i++)
212 {
213 for (j = 0; j <= WILD_BLOCK_SIZE; j++)
214 {
215 /* MAX_SHORT is a flag for "not done yet" */
216 temp_block[j][i] = MAX_SHORT;
217 }
218 }
219 }
220
221
222 /* Set the corners of the temporary block to val */
set_temp_corner_val(u16b val)223 void set_temp_corner_val(u16b val)
224 {
225 temp_block[0][0] = val;
226 temp_block[0][WILD_BLOCK_SIZE] = val;
227 temp_block[WILD_BLOCK_SIZE][0] = val;
228 temp_block[WILD_BLOCK_SIZE][WILD_BLOCK_SIZE] = val;
229 }
230
231
232 /* Set the middle of the temporary block to val */
set_temp_mid(u16b val)233 void set_temp_mid(u16b val)
234 {
235 temp_block[WILD_BLOCK_SIZE / 2][WILD_BLOCK_SIZE / 2] = val;
236 }
237
238
239 /*
240 * Initialise the temporary block based on the value of a wilderness
241 * 'info' flag for gradient information.
242 *
243 * This is used for rivers, beaches, lakes etc.
244 */
wild_info_bounds(int x,int y,byte info)245 static bool wild_info_bounds(int x, int y, byte info)
246 {
247 int i, x1, y1;
248 bool grad1[10], grad2[10], any;
249
250 /* No flags set yet */
251 any = FALSE;
252
253 /* If center is set, then whole square is "on" */
254 if (wild[y][x].done.info & info)
255 {
256 /* Set all flags */
257 grad1[5] = TRUE;
258
259 /* A flag is set */
260 any = TRUE;
261 }
262 else
263 {
264 /* Check each adjacent square to see if flag is set */
265 for (i = 1; i < 10; i++)
266 {
267 /* Get direction */
268 x1 = x + ddx[i];
269 y1 = y + ddy[i];
270
271 grad1[i] = FALSE;
272
273 /* Check bounds */
274 if ((x1 >= 0) && (x1 < max_wild) && (y1 >= 0) && (y1 < max_wild))
275 {
276 /* Check flag status */
277 if (wild[y1][x1].done.info & info)
278 {
279 /* Flag is set */
280 grad1[i] = TRUE;
281 any = TRUE;
282 }
283 }
284 }
285 }
286
287 /* Exit if there are no set flags */
288 if (any == FALSE) return (FALSE);
289
290 /* Clear temporary block */
291 clear_temp_block();
292
293 /* Set grad2[] depending on values of grad1[] */
294
295 /* If center is set - all are set */
296 if (grad1[5])
297 {
298 for (i = 1; i < 10; i++)
299 {
300 grad2[i] = TRUE;
301 }
302 }
303 else
304 {
305 /* Clear grad2[] */
306 for (i = 1; i < 10; i++)
307 {
308 grad2[i] = FALSE;
309 }
310
311 /* Copy orthogonal flags */
312 for (i = 1; i < 5; i++)
313 {
314 grad2[i * 2] = grad1[i * 2];
315 }
316
317 /* Set diagonally adjacent flags depending on values of orthogonal flags. */
318
319 /* Upper left */
320 if (grad1[4] || grad1[8])
321 {
322 grad2[7] = TRUE;
323 }
324
325 /* Upper right */
326 if (grad1[8] || grad1[6])
327 {
328 grad2[9] = TRUE;
329 }
330
331 /* Lower right */
332 if (grad1[6] || grad1[2])
333 {
334 grad2[3] = TRUE;
335 }
336
337 /* Lower left */
338 if (grad1[2] || grad1[4])
339 {
340 grad2[1] = TRUE;
341 }
342 }
343
344 /* If a flag is set - make that side maximum */
345 for (i = 1; i < 10; i++)
346 {
347 /* Hack - get only orthogonal directions */
348 x1 = (1 + ddx[i]) * WILD_BLOCK_SIZE / 2;
349 y1 = (1 + ddy[i]) * WILD_BLOCK_SIZE / 2;
350
351 if (grad2[i])
352 {
353 temp_block[y1][x1] = WILD_BLOCK_SIZE * 256;
354 }
355 else
356 {
357 temp_block[y1][x1] = WILD_BLOCK_SIZE * 64;
358 }
359 }
360
361 /* There are flags set */
362 return (TRUE);
363 }
364
365
366 /*
367 * Explanation of the plasma fractal algorithm:
368 *
369 * A grid of points is created with the properties of a 'height-map'
370 * This is done by making the corners of the grid have a random value.
371 * The grid is then subdivided into one with twice the resolution.
372 * The new points midway between two 'known' points can be calculated
373 * by taking the average value of the 'known' ones and randomly adding
374 * or subtracting an amount proportional to the distance between those
375 * points. The final 'middle' points of the grid are then calculated
376 * by averaging all four of the originally 'known' corner points. An
377 * random amount is added or subtracted from this to get a value of the
378 * height at that point. The scaling factor here is adjusted to the
379 * slightly larger distance diagonally as compared to orthogonally.
380 *
381 * This is then repeated recursively to fill an entire 'height-map'
382 * A rectangular map is done the same way, except there are different
383 * scaling factors along the x and y directions.
384 *
385 */
frac_block(void)386 void frac_block(void)
387 {
388 u16b lstep, hstep, i, j, size;
389
390 /*
391 * Size is one bigger than normal blocks for speed
392 * of algorithm with 2^n + 1
393 */
394 size = WILD_BLOCK_SIZE;
395
396 /* Initialize the step sizes */
397 lstep = hstep = size;
398
399 /*
400 * Fill in the square with fractal height data -
401 * like the 'plasma fractal' in fractint.
402 */
403 while (hstep > 1)
404 {
405 /* Halve the step sizes */
406 lstep = hstep;
407 hstep /= 2;
408
409 /* middle top to bottom. */
410 for (i = hstep; i <= size - hstep; i += lstep)
411 {
412 for (j = 0; j <= size; j += lstep)
413 {
414 /* only write to points that are "blank" */
415 if (temp_block[j][i] == MAX_SHORT)
416 {
417 /* Average of left and right points +random bit */
418 temp_block[j][i] = (((temp_block[j][i - hstep] +
419 temp_block[j][i + hstep]) +
420 (randint1(lstep * 256) -
421 (hstep * 256))) / 2);
422 }
423 }
424 }
425
426 /* middle left to right. */
427 for (j = hstep; j <= size - hstep; j += lstep)
428 {
429 for (i = 0; i <= size; i += lstep)
430 {
431 /* only write to points that are "blank" */
432 if (temp_block[j][i] == MAX_SHORT)
433 {
434 /* Average of up and down points +random bit */
435 temp_block[j][i] = (((temp_block[j - hstep][i] +
436 temp_block[j + hstep][i]) +
437 (randint1(lstep * 256) -
438 (hstep * 256))) / 2);
439 }
440 }
441 }
442
443 /* center. */
444 for (i = hstep; i <= size - hstep; i += lstep)
445 {
446 for (j = hstep; j <= size - hstep; j += lstep)
447 {
448 /* only write to points that are "blank" */
449 if (temp_block[j][i] == MAX_SHORT)
450 {
451 /*
452 * Average over all four corners + scale by 181 to
453 * reduce the effect of the square grid on the
454 * shape of the fractal
455 */
456 temp_block[j][i] = ((temp_block[j - hstep][i - hstep] +
457 temp_block[j + hstep][i - hstep] +
458 temp_block[j - hstep][i + hstep] +
459 temp_block[j + hstep][i +
460 hstep]) / 4) +
461 (((randint1(lstep * 256) - (hstep * 256)) * 181) / 256);
462 }
463 }
464 }
465 }
466 }
467
468
469 /*
470 * This function smoothly interpolates between
471 * the points on the grid. (As opposed to frac_block()
472 * which adds random offsets to make a rough
473 * pattern.
474 */
smooth_block(void)475 static void smooth_block(void)
476 {
477 u16b lstep, hstep, i, j, size;
478
479 /*
480 * Size is one bigger than normal blocks for speed
481 * of algorithm with 2^n + 1
482 */
483 size = WILD_BLOCK_SIZE;
484
485 /* Initialize the step sizes */
486 lstep = hstep = size;
487
488 while (hstep > 1)
489 {
490 /* Halve the step sizes */
491 lstep = hstep;
492 hstep /= 2;
493
494 /* middle top to bottom. */
495 for (i = hstep; i <= size - hstep; i += lstep)
496 {
497 for (j = 0; j <= size; j += lstep)
498 {
499 /* only write to points that are "blank" */
500 if (temp_block[j][i] == MAX_SHORT)
501 {
502 /* Average of left and right points */
503 temp_block[j][i] = ((temp_block[j][i - hstep] +
504 temp_block[j][i + hstep]) / 2);
505 }
506 }
507 }
508
509
510 /* middle left to right. */
511 for (j = hstep; j <= size - hstep; j += lstep)
512 {
513 for (i = 0; i <= size; i += lstep)
514 {
515 /* only write to points that are "blank" */
516 if (temp_block[j][i] == MAX_SHORT)
517 {
518 /* Average of up and down points */
519 temp_block[j][i] = ((temp_block[j - hstep][i] +
520 temp_block[j + hstep][i]) / 2);
521 }
522 }
523 }
524
525 /* center. */
526 for (i = hstep; i <= size - hstep; i += lstep)
527 {
528 for (j = hstep; j <= size - hstep; j += lstep)
529 {
530 /* only write to points that are "blank" */
531 if (temp_block[j][i] == MAX_SHORT)
532 {
533 /* Average of corner points */
534 temp_block[j][i] = ((temp_block[j - hstep][i - hstep] +
535 temp_block[j + hstep][i - hstep] +
536 temp_block[j - hstep][i + hstep] +
537 temp_block[j + hstep][i + hstep]) / 4);
538 }
539 }
540 }
541 }
542 }
543
544
545 /*
546 * This function picks a terrain feature from a list of four
547 * based on a "probability factor". The further 'prob' is
548 * from 'prob1' etc. the less likely that feature is.
549 * This weights the distribution.
550 *
551 * As a special case, feature 0 is defined to be "nonexistant"
552 * so that choices can be made with less than 4 features.
553 */
pick_feat(byte feat1,byte feat2,byte feat3,byte feat4,byte prob1,byte prob2,byte prob3,byte prob4,byte prob)554 static byte pick_feat(byte feat1, byte feat2, byte feat3, byte feat4,
555 byte prob1, byte prob2, byte prob3, byte prob4, byte prob)
556 {
557 /* Chance factors */
558 u32b c1, c2, c3, c4, choice;
559
560 /* Zero the chance factors */
561 c1 = c2 = c3 = c4 = 0;
562
563
564 /* Calculate chance factors if feature != 0 */
565 if (feat1)
566 {
567 if (prob1 == prob)
568 {
569 c1 = 0x1000000;
570 }
571 else
572 {
573 c1 = 0x1000000 / ABS((long)prob1 - prob);
574 }
575 }
576 if (feat2)
577 {
578 if (prob2 == prob)
579 {
580 c2 = 0x1000000;
581 }
582 else
583 {
584 c2 = 0x1000000 / ABS((long)prob2 - prob);
585 }
586 }
587 if (feat3)
588 {
589 if (prob3 == prob)
590 {
591 c3 = 0x1000000;
592 }
593 else
594 {
595 c3 = 0x1000000 / ABS((long)prob3 - prob);
596 }
597 }
598
599 if (feat4)
600 {
601 if (prob4 == prob)
602 {
603 c4 = 0x1000000;
604 }
605 else
606 {
607 c4 = 0x1000000 / ABS((long)prob4 - prob);
608 }
609 }
610
611 /* get choice */
612 choice = Rand_div(c1 + c2 + c3 + c4);
613
614 /* Return terrain feature based on weighted chance */
615 if (choice < c1) return (feat1);
616
617 choice -= c1;
618 if (choice < c2) return (feat2);
619
620 choice -= c2;
621 if (choice < c3) return (feat3);
622
623 return (feat4);
624 }
625
626
627 /*
628 * This function creates the sea based on the number in sea_type.
629 * The higher the number - the greater the chance of deeper water.
630 *
631 * Note WILD_SEA and above generation types are reserved for use
632 * with this function.
633 */
make_wild_sea(blk_ptr block_ptr,byte sea_type)634 static void make_wild_sea(blk_ptr block_ptr, byte sea_type)
635 {
636 int i, j;
637
638 for (j = 0; j < WILD_BLOCK_SIZE; j++)
639 {
640 for (i = 0; i < WILD_BLOCK_SIZE; i++)
641 {
642 block_ptr[j][i].feat = pick_feat(FEAT_SHAL_WATER, FEAT_DEEP_WATER,
643 FEAT_OCEAN_WATER, FEAT_NONE, 0, 10,
644 20, 40, sea_type);
645 block_ptr[j][i].info = 0;
646 }
647 }
648 }
649
650
651 /*
652 * Build a road or a track at this location
653 *
654 * This function counts the number of other road / tracks
655 * adjacent to this square, and uses that information to
656 * build a plasma fractal. The fractal then is used to
657 * make a road.
658 */
make_wild_road(blk_ptr block_ptr,int x,int y)659 static void make_wild_road(blk_ptr block_ptr, int x, int y)
660 {
661 int i, j, x1, y1;
662 u16b grad1[10], grad2[10], any;
663
664 cave_type *c_ptr;
665
666 bool bridge = FALSE, need_bridge = FALSE;
667
668
669 /* Only draw if road is on the square */
670 if (!(wild[y][x].done.info & (WILD_INFO_TRACK | WILD_INFO_ROAD)))
671 {
672 /* No flags set yet */
673 any = FALSE;
674
675 /* Only do the sides */
676 for (i = 2; i < 10; i += 2)
677 {
678 /* Get direction */
679 x1 = x + ddx[i];
680 y1 = y + ddy[i];
681
682 grad1[i] = 0;
683
684 /* Check bounds */
685 if ((x1 >= 0) && (x1 < max_wild) && (y1 >= 0) && (y1 < max_wild))
686 {
687 /* Check flag status */
688 if (wild[y1][x1].done.info & WILD_INFO_TRACK)
689 {
690 /* Flag is set */
691 grad1[i] = TRACK_LEVEL;
692 any = TRUE;
693 }
694
695 if (wild[y1][x1].done.info & WILD_INFO_ROAD)
696 {
697 /* Flag is set */
698 grad1[i] = ROAD_LEVEL;
699 any = TRUE;
700
701 /* Bridges are narrow */
702 if (wild[y1][x1].done.info & WILD_INFO_WATER)
703 {
704 grad1[i] = TRACK_LEVEL;
705 }
706 }
707 }
708 }
709
710 /* No nearby roads */
711 if (!any) return;
712
713 /* Convert from grad1 to grad2 */
714 for (i = 1; i < 10; i++)
715 {
716 grad2[i] = GROUND_LEVEL;
717 }
718
719 /* Upper left */
720 if (grad1[4] && grad1[8])
721 {
722 grad2[7] = MAX(grad1[4], grad1[8]);
723
724 any = FALSE;
725 }
726
727 /* Upper right */
728 if (grad1[8] && grad1[6])
729 {
730 grad2[9] = MAX(grad1[8], grad1[6]);
731
732 any = FALSE;
733 }
734
735 /* Lower right */
736 if (grad1[6] && grad1[2])
737 {
738 grad2[3] = MAX(grad1[6], grad1[2]);
739
740 any = FALSE;
741 }
742
743 /* Lower left */
744 if (grad1[2] && grad1[4])
745 {
746 grad2[1] = MAX(grad1[2], grad1[4]);
747
748 any = FALSE;
749 }
750
751 /* Hack - only if there really is a road */
752 if (any) return;
753 }
754 else
755 {
756 /* Do everything */
757
758 /* Check each adjacent square to see if is road or track */
759 for (i = 1; i < 10; i++)
760 {
761 /* Get direction */
762 x1 = x + ddx[i];
763 y1 = y + ddy[i];
764
765 grad2[i] = GROUND_LEVEL;
766
767 /* Check bounds */
768 if ((x1 >= 0) && (x1 < max_wild) && (y1 >= 0) && (y1 < max_wild))
769 {
770 /* Check flag status */
771 if (wild[y1][x1].done.info & WILD_INFO_TRACK)
772 {
773 /* Flag is set */
774 grad2[i] = TRACK_LEVEL;
775 }
776
777 if (wild[y1][x1].done.info & WILD_INFO_ROAD)
778 {
779 /* Flag is set */
780 grad2[i] = ROAD_LEVEL;
781
782 /* Bridges are narrow */
783 if (wild[y1][x1].done.info & WILD_INFO_WATER)
784 {
785 grad2[i] = TRACK_LEVEL;
786 }
787 }
788 }
789 }
790 }
791
792 /* Scan sides for ground */
793 for (i = 1; i < 10; i++)
794 {
795 /* Get direction */
796 x1 = x + ddx[i];
797 y1 = y + ddy[i];
798
799 if (wild[y1][x1].done.info & WILD_INFO_WATER)
800 {
801 /* We are over water - so we need a bridge */
802 need_bridge = TRUE;
803 }
804 else
805 {
806 /* We are adjacent to solid ground */
807 bridge = TRUE;
808 }
809 }
810
811 /* Only use wood terrain if we need a bridge */
812 if (!need_bridge) bridge = FALSE;
813
814 /* Clear temporary block */
815 clear_temp_block();
816
817 /* Set sides of block */
818 for (i = 1; i < 10; i++)
819 {
820 x1 = (1 + ddx[i]) * WILD_BLOCK_SIZE / 2;
821 y1 = (1 + ddy[i]) * WILD_BLOCK_SIZE / 2;
822
823 temp_block[y1][x1] = grad2[i];
824 }
825
826 /* Build the road "density map" */
827 smooth_block();
828
829 /* Copy the result over the block */
830 for (i = 0; i < WILD_BLOCK_SIZE; i++)
831 {
832 for (j = 0; j < WILD_BLOCK_SIZE; j++)
833 {
834 /* Is it a road square? */
835 if (temp_block[j][i] >= ROAD_BORDER)
836 {
837 /* Point to square */
838 c_ptr = &block_ptr[j][i];
839
840 /* Bad liquid terrain? */
841 if ((c_ptr->feat == FEAT_SHAL_LAVA) ||
842 (c_ptr->feat == FEAT_DEEP_LAVA) ||
843 (c_ptr->feat == FEAT_SHAL_ACID) ||
844 (c_ptr->feat == FEAT_DEEP_ACID))
845 {
846 c_ptr->feat = FEAT_PEBBLES;
847 }
848 else if (bridge)
849 {
850 c_ptr->feat = FEAT_FLOOR_WOOD;
851 }
852
853 else if ((c_ptr->feat == FEAT_SHAL_WATER) ||
854 (c_ptr->feat == FEAT_DEEP_WATER))
855 {
856 c_ptr->feat = FEAT_PEBBLES;
857 }
858 else if (c_ptr->feat == FEAT_OCEAN_WATER)
859 {
860 c_ptr->feat = FEAT_SHAL_WATER;
861 }
862 else
863 {
864 if (one_in_(3))
865 {
866 c_ptr->feat = FEAT_PEBBLES;
867 }
868 else
869 {
870 c_ptr->feat = FEAT_DIRT;
871 }
872 }
873 }
874 }
875 }
876 }
877
878 /*
879 * Using gradient information given in temp_block,
880 * overlay on top of wilderness block.
881 *
882 * This is used to make rivers, beaches etc.
883 */
wild_add_gradient(blk_ptr block_ptr,byte feat1,byte feat2)884 static void wild_add_gradient(blk_ptr block_ptr, byte feat1, byte feat2)
885 {
886 int i, j;
887
888 for (j = 0; j < WILD_BLOCK_SIZE; j++)
889 {
890 for (i = 0; i < WILD_BLOCK_SIZE; i++)
891 {
892 if (temp_block[j][i] >= WILD_BLOCK_SIZE * 213)
893 {
894 /* 25% of the time use the other tile : it looks better this way */
895 if (one_in_(4))
896 {
897 block_ptr[j][i].feat = feat1;
898 }
899 else
900 {
901 block_ptr[j][i].feat = feat2;
902 }
903 }
904 else if (temp_block[j][i] >= WILD_BLOCK_SIZE * 128)
905 {
906 /* 25% of the time use the other tile : it looks better this way */
907 if (one_in_(4))
908 {
909 block_ptr[j][i].feat = feat2;
910 }
911 else
912 {
913 block_ptr[j][i].feat = feat1;
914 }
915 }
916 }
917 }
918 }
919
920
921
922 /*
923 * Make wilderness generation type 1
924 *
925 * Make a plasma fractal. Convert the heightmap to terrain
926 * via the pick_feat function.
927 * This routine uses all data fields.
928 * Odd fields in the data[] array are the terrain features.
929 * The even fields are the region of the hieght-map where
930 * those features are most common.
931 */
make_wild_01(blk_ptr block_ptr,byte * data,bool road)932 static void make_wild_01(blk_ptr block_ptr, byte *data, bool road)
933 {
934 int i, j;
935 byte new_feat, element;
936
937 /* Ignore road for now */
938 (void)road;
939
940 /* Initialise temporary block */
941 clear_temp_block();
942 set_temp_corner_val(WILD_BLOCK_SIZE * 128);
943 set_temp_mid(WILD_BLOCK_SIZE * 128);
944
945 /* Generate plasma factal */
946 frac_block();
947
948 /* Make terrain block based on height map */
949 for (j = 0; j < WILD_BLOCK_SIZE; j++)
950 {
951 for (i = 0; i < WILD_BLOCK_SIZE; i++)
952 {
953 /* Get value */
954 element = temp_block[j][i] / WILD_BLOCK_SIZE;
955
956 /* Work out terrain feature to use */
957 new_feat = pick_feat(data[0], data[2], data[4], data[6],
958 data[1], data[3], data[5], data[7], element);
959
960 block_ptr[j][i].feat = new_feat;
961 block_ptr[j][i].info = 0;
962 }
963 }
964 }
965
966
967 /*
968 * Make wilderness generation type 2
969 *
970 * Make a uniform field from the feature in data[0]
971 * Next, add the lower probability features in data[2], [4] etc.
972 * using the probabilities in data[1], [3] etc.
973 * Use feat = 0 to mark the end of the list of features.
974 *
975 * This uses a different probability function than type 1.
976 * (It is cumulative.)
977 *
978 * This is good for making "flat density" regions like grasslands etc.
979 */
make_wild_02(blk_ptr block_ptr,byte * data,bool road)980 static void make_wild_02(blk_ptr block_ptr, byte *data, bool road)
981 {
982 int i, j, k;
983 byte new_feat, feat, chance;
984
985 /* Ignore road for now */
986 (void)road;
987
988 for (i = 0; i < WILD_BLOCK_SIZE; i++)
989 {
990 for (j = 0; j < WILD_BLOCK_SIZE; j++)
991 {
992 /* Init. counter */
993 k = 0;
994
995 /* Hack - if first feature is zero - use grass */
996 feat = FEAT_GRASS;
997
998 while (1)
999 {
1000 /* Get feature */
1001 new_feat = data[k * 2];
1002
1003 /* End of list? */
1004 if (new_feat == 0) break;
1005
1006 /* Use new feature */
1007 feat = new_feat;
1008
1009 /* Done counting? */
1010 if (k == 3) break;
1011
1012 chance = data[k * 2 + 1];
1013
1014 /* Exit if chance is zero */
1015 if (!chance) break;
1016
1017 /* Stop if chance fails */
1018 if (randint0(chance + 1)) break;
1019
1020 /* Increment counter + loop */
1021 k++;
1022 }
1023
1024 /* Store feature in block */
1025 block_ptr[j][i].feat = feat;
1026 }
1027 }
1028 }
1029
1030
1031 /*
1032 * This function makes a wilderness type specifed by data[0].
1033 * It then overlays a "circle" of other terrain on top.
1034 * data[1], [2] and [3] specify these.
1035 * Note - this function is a major hack. It uses the _number_
1036 * of another wilderness type - which in turn has its own data[]
1037 * and generation type.
1038 * It is possible to use recursion to make some interesting effects.
1039 * These include: Tiny lakes of water, lava, acid. Craters. Rock pillars.
1040 * Bogs. Clumps of trees. etc.
1041 */
make_wild_03(blk_ptr block_ptr,byte * data,bool road)1042 static void make_wild_03(blk_ptr block_ptr, byte *data, bool road)
1043 {
1044 int i, j, element;
1045
1046 /* Call the other routine to make the "base" terrain. */
1047 gen_block_helper(block_ptr, wild_gen_data[data[0]].data,
1048 wild_gen_data[data[0]].gen_routine, road);
1049
1050 /* Initialise temporary block */
1051 clear_temp_block();
1052
1053 /* Large in center - small on sides */
1054 set_temp_corner_val(WILD_BLOCK_SIZE * 64);
1055 set_temp_mid(WILD_BLOCK_SIZE * 256);
1056
1057 /* Generate plasma factal */
1058 frac_block();
1059
1060 /* Overlay the "circle" of terrain */
1061 for (i = 0; i < WILD_BLOCK_SIZE; i++)
1062 {
1063 for (j = 0; j < WILD_BLOCK_SIZE; j++)
1064 {
1065 element = temp_block[j][i];
1066
1067 /* Outside circle? */
1068 if (element < WILD_BLOCK_SIZE * 128) continue;
1069
1070 if ((element < WILD_BLOCK_SIZE * 171) && one_in_(2))
1071 {
1072 /* Outermost terrain */
1073 block_ptr[j][i].feat = data[1];
1074 continue;
1075 }
1076
1077 if ((element < WILD_BLOCK_SIZE * 213) && one_in_(2))
1078 {
1079 /* Middle terrain */
1080 block_ptr[j][i].feat = data[2];
1081 continue;
1082 }
1083
1084 /* Inner terrain */
1085 block_ptr[j][i].feat = data[3];
1086 }
1087 }
1088 }
1089
1090
1091 /*
1092 * Draw a pleasant field (farm)
1093 */
make_wild_04(blk_ptr block_ptr,byte * data,bool road)1094 static void make_wild_04(blk_ptr block_ptr, byte *data, bool road)
1095 {
1096 int x, y, x1, y1, x2, y2, i, j;
1097 int type;
1098
1099 cave_type *c_ptr;
1100
1101 /* Hack - ignore parameter */
1102 (void)data;
1103
1104 /* Hack - generate and throw away a few random numbers */
1105 randint0(100);
1106 randint0(100);
1107 randint0(100);
1108
1109 /* Get location of building */
1110 x = rand_range(4, 11);
1111 y = rand_range(3, 12);
1112
1113 /* Get size of building */
1114 x1 = x - randint1(3);
1115 x2 = x + randint1(3);
1116 y1 = y - randint1(2);
1117 y2 = y + randint1(2);
1118
1119 /* Get type of ground */
1120 switch (randint0(8))
1121 {
1122 case 0:
1123 case 1:
1124 case 2:
1125 {
1126 /* Grass */
1127 type = 1;
1128 break;
1129 }
1130 case 3:
1131 #if 0
1132 {
1133 /* Use "underlying" type */
1134 gen_block_helper(block_ptr, wild_gen_data[data[0]].data,
1135 wild_gen_data[data[0]].gen_routine, road);
1136 return;
1137 }
1138 #endif
1139 case 4:
1140 {
1141 /* Alternating grass & dirt */
1142 type = 3;
1143 break;
1144 }
1145 case 5:
1146 {
1147 /* Dirt */
1148 type = 2;
1149 break;
1150 }
1151 case 6:
1152 {
1153 /* Dirt with building */
1154 type = 4;
1155 break;
1156 }
1157 default:
1158 {
1159 /* Grass with building */
1160 type = 5;
1161 break;
1162 }
1163 }
1164
1165 /*
1166 * If there is a road or river going through here we should
1167 * use types 1 or 2 because we don't want roads running through
1168 * buildings and other weirdness.
1169 */
1170 if (road && (type > 2)) type = rand_range(1, 2);
1171
1172 for (i = 0; i < WILD_BLOCK_SIZE; i++)
1173 {
1174 for (j = 0; j < WILD_BLOCK_SIZE; j++)
1175 {
1176 /* Get location */
1177 c_ptr = &block_ptr[j][i];
1178
1179 /* Place ground */
1180 if (type == 1 || (type == 3 && j % 2 == 0) || type == 5)
1181 {
1182 c_ptr->feat = FEAT_GRASS;
1183 }
1184 else
1185 {
1186 c_ptr->feat = FEAT_DIRT;
1187 }
1188
1189 if ((i >= x1) && (i <= x2) && (j >= y1) && (j <= y2) && (type >= 4))
1190 {
1191 /* Build an invulnerable rectangular building */
1192 c_ptr->feat = FEAT_PERM_EXTRA;
1193 }
1194 else if ((i >= x1 - 1) && (i <= x2 + 1) &&
1195 (j >= y1 - 1) && (j <= y2 + 1) && (type >= 4))
1196 {
1197 c_ptr->feat = FEAT_DIRT;
1198 }
1199 }
1200 }
1201 }
1202
1203
1204
1205 /*
1206 * This function blends adjacent sea blocks
1207 * (by picking the feat type to use)
1208 */
blend_sea(cave_type * c_ptr,byte sea_type)1209 static void blend_sea(cave_type *c_ptr, byte sea_type)
1210 {
1211 c_ptr->feat = pick_feat(FEAT_SHAL_WATER, FEAT_DEEP_WATER,
1212 FEAT_OCEAN_WATER, FEAT_NONE, 0, 10, 20, 40,
1213 sea_type);
1214 }
1215
1216
1217 /*
1218 * The function that picks a "blending feature" for wild. gen. type 1
1219 */
blend_wild_01(cave_type * c_ptr,byte * data)1220 static void blend_wild_01(cave_type *c_ptr, byte *data)
1221 {
1222 /* Store an "average" terrain feature */
1223 c_ptr->feat = pick_feat(data[0], data[2], data[4], data[6],
1224 data[1], data[3], data[5], data[7], 128);
1225 }
1226
1227
1228 /*
1229 * The function that picks a "blending feature" for wild. gen. type 2
1230 */
blend_wild_02(cave_type * c_ptr,byte * data)1231 static void blend_wild_02(cave_type *c_ptr, byte *data)
1232 {
1233 /* Store the most likely terrain feature */
1234 c_ptr->feat = data[0];
1235 }
1236
1237
blend_helper(cave_type * c_ptr,byte * data,int g_type)1238 static void blend_helper(cave_type *c_ptr, byte *data, int g_type)
1239 {
1240 /* Based on type - choose wilderness block generation function */
1241 switch (g_type)
1242 {
1243 case 1:
1244 {
1245 /* Fractal plasma with weighted terrain probabilites */
1246 blend_wild_01(c_ptr, data);
1247 break;
1248 }
1249 case 2:
1250 {
1251 /* Simple weighted probabilities on flat distribution */
1252 blend_wild_02(c_ptr, data);
1253 break;
1254 }
1255 case 3:
1256 {
1257 /* Use the other terrain's blend function */
1258 blend_helper(c_ptr, wild_gen_data[data[0]].data,
1259 wild_gen_data[data[0]].gen_routine);
1260 /* break; Restore this when we do something for case 4 */
1261 }
1262 case 4:
1263 {
1264 /* Don't do anything */
1265 break;
1266 }
1267 default:
1268 {
1269 msgf("Illegal wilderness type %d ", g_type);
1270 }
1271 }
1272 }
1273
1274
1275 /*
1276 * Blend a block based on the adjacent blocks
1277 * This makes the wilderness look much better.
1278 */
blend_block(int x,int y,blk_ptr block_ptr,u16b type)1279 static void blend_block(int x, int y, blk_ptr block_ptr, u16b type)
1280 {
1281 int i, j, dx, dy;
1282
1283 u16b w_type;
1284
1285 /* Get current location */
1286 w_type = wild[y][x].done.wild;
1287
1288 /* Farms do not blend */
1289 if (wild_gen_data[w_type].gen_routine == 4) return;
1290
1291 /* Blend based on height map */
1292 for (j = 0; j < WILD_BLOCK_SIZE; j++)
1293 {
1294 for (i = 0; i < WILD_BLOCK_SIZE; i++)
1295 {
1296 /* Chance to blend is 1 in 2 */
1297 if (quick_rand()) continue;
1298
1299 /* Work out adjacent block */
1300 if (i < WILD_BLOCK_SIZE / 4)
1301 {
1302 dx = -1;
1303 }
1304 else if (i > (WILD_BLOCK_SIZE * 3) / 4)
1305 {
1306 dx = +1;
1307 }
1308 else
1309 {
1310 dx = 0;
1311 }
1312
1313 if (j < WILD_BLOCK_SIZE / 4)
1314 {
1315 dy = -1;
1316 }
1317 else if (j > (WILD_BLOCK_SIZE * 3) / 4)
1318 {
1319 dy = +1;
1320 }
1321 else
1322 {
1323 dy = 0;
1324 }
1325
1326 /* Check to see if adjacent square is not in bounds */
1327 if (((y + dy) < 0) || ((y + dy) >= max_wild) ||
1328 ((x + dx) < 0) || ((x + dx) >= max_wild)) continue;
1329
1330 /* Don't blend with yourself */
1331 if ((dx == 0) && (dy == 0)) continue;
1332
1333 w_type = wild[y + dy][x + dx].done.wild;
1334
1335 /* If adjacent type is the same as this one - don't blend */
1336 if (w_type == type) continue;
1337
1338 /* The sea doesn't blend. (Use rivers) */
1339 if (w_type >= WILD_SEA)
1340 {
1341 if (type >= WILD_SEA)
1342 {
1343 blend_sea(&block_ptr[j][i], (byte)(w_type - WILD_SEA));
1344 }
1345 else
1346 {
1347 /* Do not try to blend sea with land */
1348 /* We need to fix the blocky look of oceans though */
1349 continue;
1350 }
1351 }
1352
1353 /* Blend with generation type specified by gen_routine */
1354 blend_helper(&block_ptr[j][i], wild_gen_data[w_type].data,
1355 wild_gen_data[w_type].gen_routine);
1356 }
1357 }
1358 }
1359
1360
1361 /*
1362 * Make the specified terrain type at a wilderness block
1363 */
gen_block_helper(blk_ptr block_ptr,byte * data,int gen_type,bool road)1364 static void gen_block_helper(blk_ptr block_ptr, byte *data, int gen_type,
1365 bool road)
1366 {
1367 /* Based on type - choose wilderness block generation function */
1368 switch (gen_type)
1369 {
1370 case 1:
1371 {
1372 /* Fractal plasma with weighted terrain probabilites */
1373 make_wild_01(block_ptr, data, road);
1374 break;
1375 }
1376 case 2:
1377 {
1378 /* Uniform field + rare "out-crops" */
1379 make_wild_02(block_ptr, data, road);
1380 break;
1381 }
1382 case 3:
1383 {
1384 /* Use another type + overlay a "circle" of terrain. */
1385 make_wild_03(block_ptr, data, road);
1386 break;
1387 }
1388 case 4:
1389 {
1390 /* Draw a farm. */
1391 make_wild_04(block_ptr, data, road);
1392 break;
1393 }
1394 default:
1395 {
1396 quit("Illegal wilderness block type.");
1397 }
1398 }
1399 }
1400
1401
1402 /*
1403 * Fill the block with perm. walls. This is only used by the vanilla town option.
1404 */
fill_perm_wall(blk_ptr block_ptr)1405 static void fill_perm_wall(blk_ptr block_ptr)
1406 {
1407 int i, j;
1408
1409 /* Overlay the block with permament walls */
1410 for (i = 0; i < WILD_BLOCK_SIZE; i++)
1411 {
1412 for (j = 0; j < WILD_BLOCK_SIZE; j++)
1413 {
1414 block_ptr[j][i].feat = FEAT_PERM_OUTER;
1415 }
1416 }
1417 }
1418
1419
1420 /* Add monsters to the wilderness block */
add_monsters_block(int x,int y)1421 static void add_monsters_block(int x, int y)
1422 {
1423 int i, j, xx, yy;
1424 long prob;
1425
1426 /* Day time */
1427 if ((turn % (10L * TOWN_DAWN)) < ((10L * TOWN_DAWN) / 2))
1428 {
1429 /* Monsters are rarer in the day */
1430 prob = 32786;
1431 }
1432 else
1433 {
1434 /* Monsters are more common at night */
1435 prob = 20000;
1436 }
1437
1438 /*
1439 * Probability of a monster being on a certain sqaure.
1440 * Perhaps this should include the effects of stealth.
1441 */
1442 prob /= (wild[y][x].done.mon_prob + 1);
1443
1444 xx = x * WILD_BLOCK_SIZE;
1445 yy = y * WILD_BLOCK_SIZE;
1446
1447 for (i = 0; i < WILD_BLOCK_SIZE; i++)
1448 {
1449 for (j = 0; j < WILD_BLOCK_SIZE; j++)
1450 {
1451 /* See if monster should go on square */
1452 if (!randint0(prob))
1453 {
1454 if (one_in_(2))
1455 {
1456 /* Monsters are awake */
1457 (void)place_monster(xx + i, yy + j, FALSE, TRUE, 0);
1458 }
1459 else
1460 {
1461 /* Monsters are asleep */
1462 (void)place_monster(xx + i, yy + j, TRUE, TRUE, 0);
1463 }
1464 }
1465 }
1466 }
1467 }
1468
light_dark_square(int x,int y,bool daytime)1469 void light_dark_square(int x, int y, bool daytime)
1470 {
1471 cave_type *c_ptr = area(x, y);
1472 pcave_type *pc_ptr = parea(x, y);
1473
1474 if (daytime)
1475 {
1476 /* Assume lit */
1477 c_ptr->info |= (CAVE_GLOW);
1478
1479 /* Memorize lit grids */
1480 remember_grid(c_ptr, pc_ptr);
1481
1482 /* If is daytime - have seen this square */
1483 wild[y / 16][x / 16].done.info |= WILD_INFO_SEEN;
1484 }
1485 else
1486 {
1487 /* Darken "boring" features */
1488 if (!(((c_ptr->feat >= FEAT_OPEN) &&
1489 (c_ptr->feat <= FEAT_MORE)) ||
1490 ((c_ptr->feat >= FEAT_CLOSED) &&
1491 (c_ptr->feat <= FEAT_PERM_SOLID))))
1492 {
1493 /* Hack - Forget the grid */
1494 c_ptr->info &= ~(CAVE_GLOW);
1495 forget_grid(pc_ptr);
1496 }
1497 else
1498 {
1499 /* Assume lit */
1500 c_ptr->info |= (CAVE_GLOW);
1501
1502 /* Memorize lit grids */
1503 remember_grid(c_ptr, pc_ptr);
1504 }
1505 }
1506
1507 /* Hack -- Light spot */
1508 lite_spot(x, y);
1509 }
1510
1511
1512 /* Lighten / Darken new block depending on Day/ Night */
light_dark_block(int x,int y)1513 static void light_dark_block(int x, int y)
1514 {
1515 int i, j;
1516
1517 bool daytime;
1518
1519 /* Day time */
1520 if ((turn % (10L * TOWN_DAWN)) < ((10L * TOWN_DAWN) / 2))
1521 daytime = TRUE;
1522 else
1523 daytime = FALSE;
1524
1525 /* If is daytime - have seen this square */
1526 if (daytime) wild[y][x].done.info |= WILD_INFO_SEEN;
1527
1528 /* Light up or darken the area */
1529 for (j = 0; j < WILD_BLOCK_SIZE; j++)
1530 {
1531 for (i = 0; i < WILD_BLOCK_SIZE; i++)
1532 {
1533 light_dark_square(x * WILD_BLOCK_SIZE + i, y * WILD_BLOCK_SIZE + j,
1534 daytime);
1535 }
1536 }
1537 }
1538
1539
1540 /*
1541 * Make a new block based on the terrain type
1542 */
gen_block(int x,int y)1543 static void gen_block(int x, int y)
1544 {
1545 u16b w_place, w_type;
1546 blk_ptr block_ptr = wild_grid[y][x];
1547 bool road = FALSE;
1548
1549 /* Hack -- Use the "simple" RNG */
1550 Rand_quick = TRUE;
1551
1552 /* Hack -- Induce consistant wilderness blocks */
1553 Rand_value = wild_seed + x + y * max_wild;
1554
1555 /* Generate a terrain block */
1556
1557 /* Get wilderness type */
1558 w_type = wild[y][x].done.wild;
1559
1560 /* Is there a road here? */
1561 if (wild[y][x].done.info & (WILD_INFO_TRACK | WILD_INFO_ROAD))
1562 {
1563 road = TRUE;
1564 }
1565
1566 /* Create sea terrains if type >= WILD_SEA */
1567 if (w_type >= WILD_SEA)
1568 {
1569 make_wild_sea(block_ptr, (byte)(w_type - WILD_SEA));
1570 }
1571
1572 /* Hack -Check for the vanilla town wall option. */
1573 else if (w_type == 0)
1574 {
1575 /* Fill the block with permanent walls */
1576 fill_perm_wall(block_ptr);
1577 }
1578 else
1579 {
1580 /* Make terrain based on wilderness generation type */
1581 gen_block_helper(block_ptr, wild_gen_data[w_type].data,
1582 wild_gen_data[w_type].gen_routine, road);
1583
1584 /* Blend with adjacent terrains */
1585 blend_block(x, y, block_ptr, w_type);
1586
1587 /* Add water boundary effects. (Rivers / Ocean) */
1588 if (wild_info_bounds(x, y, WILD_INFO_WATER))
1589 {
1590 /* Hack, above function sets bounds */
1591
1592 /* Generate plasma factal */
1593 frac_block();
1594
1595 /* Overlay water */
1596 wild_add_gradient(block_ptr, FEAT_SHAL_WATER, FEAT_DEEP_WATER);
1597 }
1598
1599 /* Add lava boundary effects. */
1600 else if (wild_info_bounds(x, y, WILD_INFO_LAVA))
1601 {
1602 /* Hack, above function sets bounds */
1603
1604 /* Generate plasma factal */
1605 frac_block();
1606
1607 /* Overlay lava */
1608 wild_add_gradient(block_ptr, FEAT_SHAL_LAVA, FEAT_DEEP_LAVA);
1609 }
1610
1611 /* Add acid boundary effects. */
1612 else if (wild_info_bounds(x, y, WILD_INFO_ACID))
1613 {
1614 /* Hack, above function sets bounds */
1615
1616 /* Generate plasma factal */
1617 frac_block();
1618
1619 /* Overlay acid */
1620 wild_add_gradient(block_ptr, FEAT_SHAL_ACID, FEAT_DEEP_ACID);
1621 }
1622
1623 /* Add roads */
1624 make_wild_road(block_ptr, x, y);
1625 }
1626
1627 /* Hack -- Use the "complex" RNG */
1628 Rand_quick = FALSE;
1629
1630 /* Overlay place */
1631 w_place = wild[y][x].done.place;
1632
1633 /* Is there a place? */
1634 if (w_place)
1635 {
1636 /* overlay place on wilderness */
1637 overlay_place(x, y, w_place, block_ptr);
1638
1639 /* Paranoia */
1640 if (!place[w_place].region) quit("Unallocated place region");
1641 }
1642
1643 /* Day / Night - lighten or darken the new block */
1644 light_dark_block(x, y);
1645
1646 /* Add monsters */
1647 add_monsters_block(x, y);
1648 }
1649
1650
1651 /*
1652 * Erase the player grid information in a block
1653 */
erase_grids(pblk_ptr block_ptr)1654 static void erase_grids(pblk_ptr block_ptr)
1655 {
1656 int i, j;
1657
1658 for (i = 0; i < WILD_BLOCK_SIZE; i++)
1659 {
1660 for (j = 0; j < WILD_BLOCK_SIZE; j++)
1661 {
1662 /* No memorised feature */
1663 block_ptr[i][j].feat = FEAT_NONE;
1664
1665 /* All flags off */
1666 block_ptr[i][j].player = 0x00;
1667 }
1668 }
1669 }
1670
1671
1672 /*
1673 * The following four functions shift the visible
1674 * section of the wilderness by 16 units. This is
1675 * done by scrolling the grid of pointers.
1676 */
shift_down(void)1677 static void shift_down(void)
1678 {
1679 u16b i, j;
1680 pblk_ptr block_ptr;
1681
1682 for (i = 0; i < WILD_VIEW; i++)
1683 {
1684 /* The block on the edge */
1685 block_ptr = p_ptr->pwild[0][i];
1686
1687 /* Delete the block */
1688 erase_grids(block_ptr);
1689
1690 /* Scroll pointers */
1691 for (j = 1; j < WILD_VIEW; j++)
1692 {
1693 p_ptr->pwild[j - 1][i] = p_ptr->pwild[j][i];
1694 }
1695
1696 /* Connect new grid to wilderness */
1697 p_ptr->pwild[WILD_VIEW - 1][i] = block_ptr;
1698 }
1699 }
1700
1701
shift_up(void)1702 static void shift_up(void)
1703 {
1704 u16b i, j;
1705 pblk_ptr block_ptr;
1706
1707 for (i = 0; i < WILD_VIEW; i++)
1708 {
1709 /* The block on the edge */
1710 block_ptr = p_ptr->pwild[WILD_VIEW - 1][i];
1711
1712 /* Delete the block */
1713 erase_grids(block_ptr);
1714
1715 /* Scroll pointers */
1716 for (j = WILD_VIEW - 1; j > 0; j--)
1717 {
1718 p_ptr->pwild[j][i] = p_ptr->pwild[j - 1][i];
1719 }
1720
1721 /* Connect new grid to wilderness */
1722 p_ptr->pwild[0][i] = block_ptr;
1723 }
1724 }
1725
1726
shift_right(void)1727 static void shift_right(void)
1728 {
1729 u16b i, j;
1730 pblk_ptr block_ptr;
1731
1732 for (j = 0; j < WILD_VIEW; j++)
1733 {
1734 /* The block on the edge */
1735 block_ptr = p_ptr->pwild[j][0];
1736
1737 /* Delete the block */
1738 erase_grids(block_ptr);
1739
1740 /* Scroll pointers */
1741 for (i = 1; i < WILD_VIEW; i++)
1742 {
1743 p_ptr->pwild[j][i - 1] = p_ptr->pwild[j][i];
1744 }
1745
1746 /* Connect new grid to wilderness */
1747 p_ptr->pwild[j][WILD_VIEW - 1] = block_ptr;
1748 }
1749 }
1750
1751
shift_left(void)1752 static void shift_left(void)
1753 {
1754 u16b i, j;
1755 pblk_ptr block_ptr;
1756
1757 for (j = 0; j < WILD_VIEW; j++)
1758 {
1759 /* The block on the edge */
1760 block_ptr = p_ptr->pwild[j][WILD_VIEW - 1];
1761
1762 /* Delete the block */
1763 erase_grids(block_ptr);
1764
1765 /* Scroll pointers */
1766 for (i = WILD_VIEW - 1; i > 0; i--)
1767 {
1768 p_ptr->pwild[j][i] = p_ptr->pwild[j][i - 1];
1769 }
1770
1771 /* Connect new grid to wilderness */
1772 p_ptr->pwild[j][0] = block_ptr;
1773 }
1774 }
1775
1776
1777 /* Delete a wilderness block */
del_block(int x,int y)1778 static void del_block(int x, int y)
1779 {
1780 blk_ptr block_ptr;
1781 int xx, yy;
1782 int m_idx;
1783
1784 wild_type *w_ptr = &wild[y][x];
1785 place_type *pl_ptr = &place[w_ptr->done.place];
1786
1787 if (!wild_refcount[y][x]) quit("Dead wilderness cache!");
1788
1789 /* Decrement refcount */
1790 wild_refcount[y][x]--;
1791
1792 /* Don't do anything if someone else is here */
1793 if (wild_refcount[y][x]) return;
1794
1795 /* Is there a place? */
1796 if (w_ptr->done.place)
1797 {
1798 /* Decrease refcount region */
1799 pl_ptr->region = unref_region(pl_ptr->region);
1800 }
1801
1802 /* Time to delete it - get block pointer */
1803 block_ptr = wild_grid[y][x];
1804
1805 for (xx = 0; xx < WILD_BLOCK_SIZE; xx++)
1806 {
1807 for (yy = 0; yy < WILD_BLOCK_SIZE; yy++)
1808 {
1809 /* Clear old terrain data */
1810 block_ptr[yy][xx].info = 0;
1811 block_ptr[yy][xx].feat = 0;
1812
1813 /* Delete monster on the square */
1814 m_idx = block_ptr[yy][xx].m_idx;
1815
1816 /* Only delete if one exists */
1817 if (m_idx)
1818 {
1819 delete_monster_idx(m_idx);
1820 block_ptr[yy][xx].m_idx = 0;
1821 }
1822
1823 /* Delete objects on the square */
1824 delete_object_list(&block_ptr[yy][xx].o_idx);
1825
1826 /* Delete fields on the square */
1827 delete_field_location(&block_ptr[yy][xx]);
1828 }
1829 }
1830
1831 /* Clear old reference */
1832 wild_grid[y][x] = NULL;
1833
1834 /* Attach to head of the list */
1835 wild_cache[--wc_cnt] = block_ptr;
1836 }
1837
1838 /*
1839 * Allocate a new block
1840 */
allocate_block(int x,int y)1841 static void allocate_block(int x, int y)
1842 {
1843 byte place_num = wild[y][x].done.place;
1844
1845 /* Increment refcount */
1846 wild_refcount[y][x]++;
1847
1848 /* Need to make the block if it doesn't exist */
1849 if (!wild_grid[y][x])
1850 {
1851 /* Paranoia */
1852 if (wc_cnt >= WILD_CACHE) quit("Out of wilderness cache");
1853
1854 /* Get new block */
1855 wild_grid[y][x] = wild_cache[wc_cnt++];
1856
1857
1858 /* Are we in the process of loading the game? */
1859 if (character_loaded)
1860 {
1861 /* Generate the block */
1862 gen_block(x, y);
1863
1864 if (place_num)
1865 {
1866 /* Increase refcount for region */
1867 incref_region(place[place_num].region);
1868 }
1869 }
1870
1871 /* We need to make sure the refcounted regions work */
1872 else if (place_num)
1873 {
1874 place_type *pl_ptr = &place[place_num];
1875
1876 /* Do we need to make the map? */
1877 if (!pl_ptr->region)
1878 {
1879 /* Create the place */
1880 place_gen(pl_ptr);
1881 }
1882
1883 /* Increase refcount for region */
1884 incref_region(pl_ptr->region);
1885 }
1886 }
1887 }
1888
1889
shift_in_bounds(int * x,int * y)1890 void shift_in_bounds(int *x, int *y)
1891 {
1892 /* Vanilla town is special */
1893 if (vanilla_town)
1894 {
1895 *x = 0;
1896 *y = 0;
1897 return;
1898 }
1899
1900 /* Recenter map */
1901 *x -= WILD_VIEW / 2;
1902 *y -= WILD_VIEW / 2;
1903
1904 /* Move if out of bounds */
1905 if (*x < 0) *x = 0;
1906 if (*y < 0) *y = 0;
1907
1908 /* Hack XXX This isn't set when we are called during loading */
1909 if (max_wild)
1910 {
1911 if (*x + WILD_VIEW >= max_wild) *x = max_wild - WILD_VIEW - 1;
1912 if (*y + WILD_VIEW >= max_wild) *y = max_wild - WILD_VIEW - 1;
1913 }
1914 }
1915
1916
1917 /*
1918 * Centre grid of wilderness blocks around player.
1919 * This must be called after the player moves in the wilderness.
1920 * If the player is just walking around, all that needs to be done is
1921 * to scroll the grid of pointers - not recalculate them all.
1922 * However, when the player teleports, all have to ba allocated.
1923 */
move_wild(void)1924 void move_wild(void)
1925 {
1926 int x, y;
1927 int ox = p_ptr->old_wild_x, oy = p_ptr->old_wild_y;
1928 int i, j;
1929
1930 quest_type *q_ptr;
1931 place_type *pl_ptr;
1932 wild_done_type *w_ptr;
1933
1934 /* Get upper left hand block in grid. */
1935
1936 /* Divide by WILD_BLOCK_SIZE to get block from (x,y) coord */
1937 x = ((u16b)p_ptr->wilderness_x / WILD_BLOCK_SIZE);
1938 y = ((u16b)p_ptr->wilderness_y / WILD_BLOCK_SIZE);
1939
1940 w_ptr = &wild[y][x].done;
1941
1942 /* The player sees the wilderness block he is on. */
1943 w_ptr->info |= WILD_INFO_SEEN;
1944
1945 /* Hack - set place */
1946 p_ptr->place_num = w_ptr->place;
1947
1948 /* Move boundary */
1949 shift_in_bounds(&x, &y);
1950
1951 /* If we haven't moved block - exit */
1952 if ((ox == x) && (oy == y)) return;
1953
1954 /* We have moved, notice the new town/dungeon */
1955 activate_quests(0);
1956
1957 pl_ptr = &place[p_ptr->place_num];
1958
1959 /* Check for wilderness quests */
1960 if (pl_ptr->quest_num)
1961 {
1962 q_ptr = &quest[pl_ptr->quest_num];
1963
1964 /* Some quests are completed by walking on them */
1965 if (q_ptr->x_type == QX_WILD_ENTER)
1966 {
1967 /* Done? */
1968 trigger_quest_complete(QX_WILD_ENTER, (vptr)q_ptr);
1969 }
1970 }
1971
1972 /* Shift the player information */
1973 while (ox < x)
1974 {
1975 ox++;
1976 shift_right();
1977 }
1978
1979 while (ox > x)
1980 {
1981 ox--;
1982 shift_left();
1983 }
1984
1985 while (oy < y)
1986 {
1987 oy++;
1988 shift_down();
1989 }
1990
1991 while (oy > y)
1992 {
1993 oy--;
1994 shift_up();
1995 }
1996
1997 /* Reset bounds */
1998 p_ptr->min_wid = x * WILD_BLOCK_SIZE;
1999 p_ptr->min_hgt = y * WILD_BLOCK_SIZE;
2000 p_ptr->max_wid = p_ptr->min_wid + WILD_VIEW * WILD_BLOCK_SIZE;
2001 p_ptr->max_hgt = p_ptr->min_hgt + WILD_VIEW * WILD_BLOCK_SIZE;
2002
2003 /* Allocate new blocks */
2004 for (i = 0; i < WILD_VIEW; i++)
2005 {
2006 for (j = 0; j < WILD_VIEW; j++)
2007 {
2008 allocate_block(x + i, y + j);
2009 }
2010 }
2011
2012 /* Deallocate old blocks */
2013 for (i = 0; i < WILD_VIEW; i++)
2014 {
2015 for (j = 0; j < WILD_VIEW; j++)
2016 {
2017 del_block(p_ptr->old_wild_x + i, p_ptr->old_wild_y + j);
2018 }
2019 }
2020
2021 /* Redraw depth */
2022 p_ptr->redraw |= (PR_DEPTH);
2023
2024 /* Save the new location */
2025 p_ptr->old_wild_x = x;
2026 p_ptr->old_wild_y = y;
2027 }
2028
2029
2030 /*
2031 * Access the cave region data.
2032 */
access_cave(int x,int y)2033 static cave_type *access_cave(int x, int y)
2034 {
2035 return (cave_p(x, y));
2036 }
2037
2038
2039 /*
2040 * Access player information in dungeon
2041 */
access_pcave(int x,int y)2042 static pcave_type *access_pcave(int x, int y)
2043 {
2044 return (&p_ptr->pcave[y][x]);
2045 }
2046
2047 /*
2048 * Access wilderness
2049 */
access_wild(int x,int y)2050 static cave_type *access_wild(int x, int y)
2051 {
2052 /*
2053 * Divide by 16 to get block.
2054 * Logical AND with 15 to get location within block.
2055 */
2056 return (&wild_grid[y / WILD_BLOCK_SIZE][x / WILD_BLOCK_SIZE]
2057 [y & 15][x & 15]);
2058 }
2059
2060 /*
2061 * Access player information in wilderness
2062 */
access_pwild(int x,int y)2063 static pcave_type *access_pwild(int x, int y)
2064 {
2065 /*
2066 * Divide by 16 to get block.
2067 * Logical AND with 15 to get location within block.
2068 */
2069 return (&p_ptr->pwild[(y - p_ptr->min_hgt) / WILD_BLOCK_SIZE]
2070 [(x - p_ptr->min_wid) / WILD_BLOCK_SIZE][y & 15][x & 15]);
2071 }
2072
2073
2074 /*
2075 * Bounds checking
2076 *
2077 * Hack - in_bounds() and in_bounds2() are the same
2078 * in the wilderness.
2079 */
in_bounds_wild(int x,int y)2080 static bool in_bounds_wild(int x, int y)
2081 {
2082 /* Make sure we are inside the wilderness */
2083 if ((y < 0) || (x < 0) ||
2084 (y >= max_wild * WILD_BLOCK_SIZE) || (x >= max_wild * WILD_BLOCK_SIZE))
2085 {
2086 return (FALSE);
2087 }
2088
2089 /* Return TRUE if block is in use */
2090 return (wild_refcount[y / WILD_BLOCK_SIZE][x / WILD_BLOCK_SIZE] != 0);
2091 }
2092
in_bounds_cave(int x,int y)2093 static bool in_bounds_cave(int x, int y)
2094 {
2095 return ((y > p_ptr->min_hgt) && (x > p_ptr->min_wid)
2096 && (y < p_ptr->max_hgt - 1) && (x < p_ptr->max_wid - 1));
2097 }
2098
in_bounds2_cave(int x,int y)2099 static bool in_bounds2_cave(int x, int y)
2100 {
2101 return ((y >= p_ptr->min_hgt) && (x >= p_ptr->min_wid)
2102 && (y < p_ptr->max_hgt) && (x < p_ptr->max_wid));
2103 }
2104
2105 /*
2106 * In bounds for the player information?
2107 */
in_bounds_wild_player(int x,int y)2108 static bool in_bounds_wild_player(int x, int y)
2109 {
2110 /* Use the same player bounds information as in_bounds_cave() */
2111 return ((y >= p_ptr->min_hgt) && (x >= p_ptr->min_wid)
2112 && (y < p_ptr->max_hgt) && (x < p_ptr->max_wid));
2113 }
2114
2115
2116 /* Allocate all grids around player */
init_wild_cache(void)2117 static void init_wild_cache(void)
2118 {
2119 int x = p_ptr->old_wild_x, y = p_ptr->old_wild_y;
2120 int i, j;
2121
2122 pblk_ptr block_ptr;
2123
2124 /* Allocate blocks around player */
2125 for (i = 0; i < WILD_VIEW; i++)
2126 {
2127 for (j = 0; j < WILD_VIEW; j++)
2128 {
2129 /* Hack - erase the player knowledge */
2130 block_ptr = p_ptr->pwild[j][i];
2131 erase_grids(block_ptr);
2132
2133 allocate_block(x + i, y + j);
2134 }
2135 }
2136 }
2137
2138 /* Deallocate all grids around player */
del_wild_cache(void)2139 static void del_wild_cache(void)
2140 {
2141 int x = p_ptr->old_wild_x, y = p_ptr->old_wild_y;
2142 int i, j;
2143
2144 if (!wc_cnt) quit("Deleting empty wilderness cache!");
2145
2146 /* The player no longer is in the wilderness */
2147 character_dungeon = FALSE;
2148
2149 /* Deallocate blocks around player */
2150 for (i = 0; i < WILD_VIEW; i++)
2151 {
2152 for (j = 0; j < WILD_VIEW; j++)
2153 {
2154 del_block(x + i, y + j);
2155 }
2156 }
2157 }
2158
2159
2160 /*
2161 * Fix problems due to dungeons not starting at level 1.
2162 *
2163 * direction is -1 for going down, and +1 for up.
2164 */
move_dun_level(int direction)2165 void move_dun_level(int direction)
2166 {
2167 place_type *pl_ptr = &place[p_ptr->place_num];
2168 dun_type *d_ptr = pl_ptr->dungeon;
2169
2170 /* Change depth */
2171 p_ptr->depth += direction;
2172
2173 /* Leaving */
2174 p_ptr->state.leaving = TRUE;
2175
2176 /* Out of bounds? */
2177 if (p_ptr->depth < d_ptr->min_level)
2178 {
2179 /* We have just decended - and have to decend more? */
2180 if (direction == 1)
2181 {
2182 p_ptr->depth = d_ptr->min_level;
2183 }
2184 else
2185 {
2186 /* Go to surface. */
2187 p_ptr->depth = 0;
2188 }
2189 }
2190
2191 /* Make sure the deepest level is set correctly */
2192 d_ptr->recall_depth = MAX(d_ptr->recall_depth, p_ptr->depth);
2193 }
2194
2195
2196 /*
2197 * This function _must_ be called whenever the dungeon level changes.
2198 * It makes sure the bounds and access functions point to the correct
2199 * functions. If this is not done - bad things happen.
2200 */
2201
change_level(int level)2202 void change_level(int level)
2203 {
2204 place_type *pl_ptr = &place[p_ptr->place_num];
2205
2206 bool switched = FALSE;
2207
2208 /* Hack - reset trap detection flag */
2209 p_ptr->state.detected = FALSE;
2210
2211 /* Clear the monster lights */
2212 clear_mon_lite();
2213
2214 /* Toggle list of active quests */
2215 activate_quests(level);
2216
2217 if (level == 0)
2218 {
2219 if (pl_ptr->dungeon && pl_ptr->dungeon->region)
2220 {
2221 /* Delete dungeon */
2222 pl_ptr->dungeon->region = unref_region(pl_ptr->dungeon->region);
2223 }
2224
2225 /* In the wilderness */
2226 p_ptr->px = (s16b)p_ptr->wilderness_x;
2227 p_ptr->py = (s16b)p_ptr->wilderness_y;
2228
2229 /* Notice player location */
2230 Term_move_player();
2231
2232 /* Used to be in the dungeon? */
2233 if (area_aux != access_wild) switched = TRUE;
2234
2235 /* Access the wilderness */
2236 area_aux = access_wild;
2237 parea_aux = access_pwild;
2238
2239 /* Bounds checking rountine */
2240 in_bounds = in_bounds_wild;
2241 in_bounds2 = in_bounds_wild;
2242 in_boundsp = in_bounds_wild_player;
2243
2244 /* Initialise the boundary */
2245 p_ptr->min_wid = p_ptr->old_wild_x * WILD_BLOCK_SIZE;
2246 p_ptr->min_hgt = p_ptr->old_wild_y * WILD_BLOCK_SIZE;
2247 p_ptr->max_wid = p_ptr->min_wid + WILD_VIEW * WILD_BLOCK_SIZE;
2248 p_ptr->max_hgt = p_ptr->min_hgt + WILD_VIEW * WILD_BLOCK_SIZE;
2249
2250 /* Update panels (later) */
2251 p_ptr->update |= (PU_MAP);
2252
2253 /*
2254 * Restore the outside town if it exists
2255 * This is mainly done to reinit the fields
2256 */
2257 if (switched)
2258 {
2259 /* Create wilderness */
2260 init_wild_cache();
2261 }
2262 }
2263 else
2264 {
2265 /* In the dungeon */
2266 if (pl_ptr->dungeon && pl_ptr->dungeon->region)
2267 {
2268 /* Delete old dungeon */
2269 pl_ptr->dungeon->region = unref_region(pl_ptr->dungeon->region);
2270
2271 /* New dungeon is created in generate.c */
2272 }
2273
2274 /* Used to be in the wilderness? */
2275 if (area_aux == access_wild)
2276 {
2277 /* Hack XXX XXX Delete the wilderness cache */
2278 del_wild_cache();
2279 }
2280
2281 /*
2282 * Default bounds - allocated in generate.c
2283 *
2284 * Should these be set here at all???
2285 */
2286 p_ptr->min_hgt = 0;
2287 p_ptr->max_hgt = MAX_HGT;
2288 p_ptr->min_wid = 0;
2289 p_ptr->max_wid = MAX_WID;
2290
2291 /* Access the cave */
2292 area_aux = access_cave;
2293 parea_aux = access_pcave;
2294
2295 /* Bounds checking */
2296 in_bounds = in_bounds_cave;
2297 in_bounds2 = in_bounds2_cave;
2298 in_boundsp = in_bounds2_cave;
2299 }
2300
2301 /* Tell the rest of the world that the map is no longer valid */
2302 Term_erase_map();
2303 }
2304
2305
2306 /*
2307 * Get the base level for objects and monsters
2308 * around the player.
2309 */
base_level(void)2310 int base_level(void)
2311 {
2312 wild_done_type *w_ptr;
2313
2314 /* Are we in the dungeon? */
2315 if (p_ptr->depth) return (p_ptr->depth);
2316
2317 /* Point to wilderness block info */
2318 w_ptr = &wild[p_ptr->py / 16][p_ptr->px / 16].done;
2319
2320 /* The level of the wilderness */
2321 return(w_ptr->mon_gen);
2322 }
2323
2324
2325 /*
2326 * What is the current dungeon?
2327 */
dungeon(void)2328 dun_type *dungeon(void)
2329 {
2330 place_type *pl_ptr = &place[p_ptr->place_num];
2331
2332 /* Return the dungeon */
2333 return (pl_ptr->dungeon);
2334 }
2335
2336
2337 /*
2338 * Delete all active things
2339 */
wipe_all_list(void)2340 void wipe_all_list(void)
2341 {
2342 int i;
2343
2344 /* Hack - cull the players inventory */
2345 if (p_ptr->inventory) delete_object_list(&p_ptr->inventory);
2346
2347 /* Clear the store cache */
2348 for (i = 0; i < store_cache_num; i++)
2349 {
2350 if (store_cache[i]->stock)
2351 {
2352 delete_object_list(&store_cache[i]->stock);
2353 }
2354 }
2355 store_cache_num = 0;
2356
2357 if (p_ptr->depth)
2358 {
2359 /* In the dungeon */
2360 wipe_rg_list();
2361
2362 /* No more dungeon */
2363 cur_region = 0;
2364 }
2365 else
2366 {
2367 /* In the wilderness - delete cache if it exists */
2368 if (wc_cnt) del_wild_cache();
2369 }
2370
2371 /* reset function pointers */
2372 area_aux = NULL;
2373 parea_aux = NULL;
2374
2375 in_bounds = NULL;
2376 in_bounds2 = NULL;
2377 in_boundsp = NULL;
2378 }
2379
2380 /*
2381 * Get the maximum dungeon level ever reached.
2382 */
max_dun_level_reached(void)2383 int max_dun_level_reached(void)
2384 {
2385 int i, max = 0;
2386
2387 place_type *pl_ptr;
2388 dun_type *d_ptr;
2389
2390 /* Scan all places */
2391 for (i = 0; i < place_count; i++)
2392 {
2393 pl_ptr = &place[i];
2394
2395 if (pl_ptr->dungeon)
2396 {
2397 d_ptr = pl_ptr->dungeon;
2398
2399 /* Best depth? */
2400 if (d_ptr->recall_depth > max)
2401 {
2402 max = d_ptr->recall_depth;
2403 }
2404 }
2405 }
2406
2407 /* Done */
2408 return (max);
2409 }
2410