10 char terrain_blocked
[256] = {0,0,0,0,0,5,5,1,5,5,
11 1,5,5,1,5,5,1,5,5,5,
12 5,5,5,5,5,5,5,5,5,5,
13 5,5,5,5,5,5,0,0,0,0,
14 0,0,0,0,0,0,0,0,0,0,
16 3,3,3,3,3,3,3,3,3,3,
17 3,3,3,0,3,0,0,0,0,0,
18 0,3,0,0,3,2,2,4,2,0,
19 0,0,4,0,0,0,3,4,0,0,
20 0,5,5,0,0,4,0,0,0,0,
22 5,5,1,5,5,5,5,0,4,0,
23 5,4,5,5,5,5,4,5,5,1,
24 5,5,5,5,0,4,0,5,5,5,
25 5,4,5,5,1,5,5,5,5,0,
26 4,0,5,5,5,5,5,4,4,4,
28 0,0,2,0,4,4,4,4,4,4,
29 4,4,4,4,5,4,4,4,0,0,
30 0,0,0,0,4,4,4,4,4,4,
31 4,4,4,4,0,4,0,2,4,4,
32 4,0,4,0,4,0,0,0,4,4,
34 0,0,4,4,4,4,4,4,4,0,
35 0,4,0,4,4,0,4,2,2,2,
36 2,2,2,2,2,2,2,2,5,5,
37 2,2,0,0,0,0,0,2,2,2,
38 2,2,2,2,2,0,0,0,0,0,
43 short short_can_see();
44 Boolean
combat_pt_in_light();
45 extern short town_size
[3];
47 location which_party_sec
;
49 extern party_record_type far party
;
50 extern piles_of_stuff_dumping_type
*data_store
;
51 extern piles_of_stuff_dumping_type2
*data_store2
;
52 extern talking_record_type far talking
;
53 extern scenario_data_type far scenario
;
55 extern current_town_type far c_town
;
56 extern short overall_mode
,which_combat_type
,current_pc
,town_type
;
57 extern big_tr_type far t_d
;
58 extern outdoor_record_type far outdoors
[2][2];
59 extern unsigned char far out
[96][96];
60 extern unsigned char far out_e
[96][96];
61 extern unsigned char far combat_terrain
[64][64];
62 extern location pc_pos
[6],center
;
63 extern pc_record_type far adven
[6];
64 extern Boolean belt_present
,web
,crate
,barrel
,fire_barrier
,force_barrier
,quickfire
,force_wall
,fire_wall
,antimagic
,scloud
,ice_wall
,blade_wall
;
65 extern unsigned char far map_graphic_placed
[8][64]; // keeps track of what's been filled on map
67 location light_locs
[40];
72 void set_terrain_blocked()
76 for (i
= 0; i
< 256; i
++)
77 terrain_blocked
[i
] = scenario
.ter_types
[i
].blockage
;
80 short dist(location p1
,location p2
)
82 return (short) sqrt((double)((p1
.x
- p2
.x
) * (p1
.x
- p2
.x
) +
83 (p1
.y
- p2
.y
) * (p1
.y
- p2
.y
)));
86 short ex_sqrt(short val
)
88 return (short) sqrt((double)(val
));
90 short vdist(location p1
,location p2
) {
92 i
= a_v((short) (p1
.x
- p2
.x
)); j
= a_v((short) (p1
.y
- p2
.y
));
96 Boolean
adjacent(location p1
,location p2
)
98 if ((a_v((short) (p1
.x
- p2
.x
)) <= 1) && (a_v((short) (p1
.y
- p2
.y
)) <= 1))
103 Boolean
point_onscreen(location center
,location check
)
105 if ((a_v((short) (center
.x
- check
.x
)) <=4) && (a_v((short) (center
.y
- check
.y
)) <= 4))
111 short set_direction (location old_pt
, location new_pt
)
113 if (old_pt
.x
== new_pt
.x
)
114 if (old_pt
.y
> new_pt
.y
)
117 if (old_pt
.x
> new_pt
.x
) {
118 if (old_pt
.y
> new_pt
.y
)
120 if (old_pt
.y
< new_pt
.y
)
124 if (old_pt
.y
> new_pt
.y
)
126 if (old_pt
.y
< new_pt
.y
)
131 location
global_to_local(location global
)
136 if (party
.i_w_c
.x
== 1)
137 local
.x
= local
.x
- 48;
138 if (party
.i_w_c
.y
== 1)
139 local
.y
= local
.y
- 48;
142 location
local_to_global(location local
)
147 if (party
.i_w_c
.x
== 1)
148 global
.x
= global
.x
+ 48;
149 if (party
.i_w_c
.y
== 1)
150 global
.y
= global
.y
+ 48;
153 Boolean
loc_off_world(location p1
)
155 if ((p1
.x
< 0) || (p1
.x
> town_size
[town_type
]) || (p1
.y
< 0) || (p1
.y
> town_size
[town_type
]))
160 Boolean
loc_off_act_area(location p1
)
162 if ((p1
.x
> c_town
.town
.in_town_rect
.left
) && (p1
.x
< c_town
.town
.in_town_rect
.right
) &&
163 (p1
.y
> c_town
.town
.in_town_rect
.top
) && (p1
.y
< c_town
.town
.in_town_rect
.bottom
))
168 location
get_cur_loc()
170 switch (overall_mode
) {
175 case 1: case 2: case 3: case 4: case 36:
180 return pc_pos
[current_pc
];
185 short short_can_see(shortloc p1
,shortloc p2
)
193 return (can_see(s1
,s2
,0));
196 Boolean
is_lava(short x
,short y
)////
200 ter
= coord_to_ter(x
,y
);
201 if (scenario
.ter_types
[ter
].picture
== 404)
207 short can_see(location p1
,location p2
,short mode
)
208 //short mode; // 0 - normal 1 - counts 1 for blocked spaces or lava (used for party placement in
210 // 2 - no light check
212 short dx
,dy
,count
,storage
= 0;
214 if (is_combat()) { // Light check
215 if ((mode
!= 2) && (combat_pt_in_light(p2
) == FALSE
)) {
220 if ((mode
!= 2) && (pt_in_light(p1
,p2
) == FALSE
)) {
227 for (count
= p2
.x
+ 1; count
< p1
.x
; count
++) {
228 storage
= storage
+ get_obscurity(count
, p1
.y
);
229 if (((terrain_blocked
[coord_to_ter(count
,p1
.y
)] > 2) || (is_lava(count
,p1
.y
) == TRUE
)) && (mode
== 1))
234 for (count
= p1
.x
+ 1; count
< p2
.x
; count
++) {
236 storage
= storage
+ get_obscurity(count
, p1
.y
);
237 if (((terrain_blocked
[coord_to_ter(count
,p1
.y
)] > 2) || (is_lava(count
,p1
.y
) == TRUE
)) && (mode
== 1))
245 for (count
= p1
.y
- 1; count
> p2
.y
; count
--) {
246 storage
= storage
+ get_obscurity(p1
.x
, count
);
247 if (((terrain_blocked
[coord_to_ter(p1
.x
,count
)] > 2) || (is_lava(p1
.x
,count
) == TRUE
)) && (mode
== 1))
252 for (count
= p1
.y
+ 1; count
< p2
.y
; count
++) {
253 storage
= storage
+ get_obscurity(p1
.x
, count
);
254 if (((terrain_blocked
[coord_to_ter(p1
.x
,count
)] > 2) || (is_lava(p1
.x
,count
) == TRUE
)) && (mode
== 1))
263 if (ex_abs(dy
) > ex_abs(dx
)) {
265 for (count
= 1; count
< dy
; count
++) {
266 storage
= storage
+ get_obscurity(p1
.x
+ (count
* dx
) / dy
, p1
.y
+ count
);
267 if ( ((terrain_blocked
[coord_to_ter(p1
.x
+ (count
* dx
) / dy
,p1
.y
+ count
)] > 2) ||
268 (is_lava(p1
.x
+ (count
* dx
) / dy
,p1
.y
+ count
) == TRUE
))
274 for (count
= -1; count
> dy
; count
--) {
275 storage
= storage
+ get_obscurity(p1
.x
+ (count
* dx
) / dy
, p1
.y
+ count
);
276 if ( ((terrain_blocked
[coord_to_ter(p1
.x
+ (count
* dx
) / dy
, p1
.y
+ count
)] > 2) ||
277 (is_lava(p1
.x
+ (count
* dx
) / dy
, p1
.y
+ count
) == TRUE
))
284 if (ex_abs(dy
) <= ex_abs(dx
)) {
286 for (count
= 1; count
< dx
; count
++) {
287 storage
= storage
+ get_obscurity(p1
.x
+ count
, p1
.y
+ (count
* dy
) / dx
);
288 if (((terrain_blocked
[coord_to_ter(p1
.x
+ count
,p1
.y
+ (count
* dy
) / dx
)] > 2) ||
289 (is_lava(p1
.x
+ count
,p1
.y
+ (count
* dy
) / dx
) == TRUE
))
295 for (count
= -1; count
> dx
; count
--) {
296 storage
= storage
+ get_obscurity(p1
.x
+ count
, p1
.y
+ (count
* dy
) / dx
);
297 if ( ((terrain_blocked
[coord_to_ter(p1
.x
+ count
,p1
.y
+ (count
* dy
) / dx
)] > 2) ||
298 (is_lava(p1
.x
+ count
,p1
.y
+ (count
* dy
) / dx
) == TRUE
))
310 short get_obscurity(short x
,short y
)
312 unsigned char what_terrain
;
315 what_terrain
= coord_to_ter(x
,y
);
317 if ((what_terrain
>= 237) && (what_terrain
<= 242))
320 store
= get_blockage(what_terrain
);
327 if ((is_town()) || (is_combat())) {
330 if ((is_fire_barrier(x
,y
)) || (is_force_barrier(x
,y
)))
332 if ((is_crate(x
,y
)) || (is_barrel(x
,y
)))
339 unsigned char coord_to_ter(short x
,short y
)
343 if ((overall_mode
== 0) || (overall_mode
== 35))
344 what_terrain
= out
[x
][y
];
345 else if (((overall_mode
> 0) && (overall_mode
< 10))|| (overall_mode
== 36))
346 what_terrain
= t_d
.terrain
[x
][y
];
348 what_terrain
= combat_terrain
[x
][y
];
354 Boolean
is_container(location loc
)
359 if ((is_barrel(loc
.x
,loc
.y
)) || (is_crate(loc
.x
,loc
.y
)))
361 ter
= coord_to_ter(loc
.x
,loc
.y
);
362 if (scenario
.ter_types
[ter
].special
== 14)
367 void update_explored(location dest
)
369 shortloc shortdest
,look
;
375 shortdest
.x
= (short) dest
.x
;
376 shortdest
.y
= (short) dest
.y
;
378 which_party_sec
.x
= party
.outdoor_corner
.x
+ party
.i_w_c
.x
;
379 which_party_sec
.y
= party
.outdoor_corner
.y
+ party
.i_w_c
.y
;
381 if (overall_mode
== 0) {
382 out_e
[dest
.x
][dest
.y
] = 2;
383 for (look
.x
= shortdest
.x
- 4; look
.x
< shortdest
.x
+ 5; look
.x
++)
384 for (look
.y
= shortdest
.y
- 4; look
.y
< shortdest
.y
+ 5; look
.y
++) {
385 if ((look
.x
== minmax(0,95,look
.x
)) && (look
.y
== minmax(0,95,look
.y
))) {
386 if (out_e
[look
.x
][look
.y
] == 0)
387 if (short_can_see(shortdest
, look
) < 5)
388 out_e
[look
.x
][look
.y
] = 1;
395 if (overall_mode
> 0) {
396 make_explored(dest
.x
,dest
.y
);
397 for (look2
.x
= max(0,dest
.x
- 4); look2
.x
< min(town_size
[town_type
],dest
.x
+ 5); look2
.x
++)
398 for (look2
.y
= max(0,dest
.y
- 4); look2
.y
< min(town_size
[town_type
],dest
.y
+ 5); look2
.y
++)
399 if (is_explored(look2
.x
,look2
.y
) == FALSE
)
400 if ((can_see(dest
, look2
,0) < 5) && (pt_in_light(dest
,look2
) == TRUE
))
401 make_explored(look2
.x
,look2
.y
);
406 // All purpose function to check is spot is free for travel into.
407 Boolean
is_blocked(location to_check
)
414 if (impassable(out
[to_check
.x
][to_check
.y
]) == TRUE
) {
417 if (same_point (to_check
,party
.p_loc
) == TRUE
)
419 for (i
= 0; i
< 20; i
++)
420 if ((party
.out_c
[i
].exists
) == TRUE
)
421 if (same_point(party
.out_c
[i
].m_loc
, to_check
) == TRUE
)
426 if ((is_town()) || (is_combat())) {
427 ter
= (is_town()) ? t_d
.terrain
[to_check
.x
][to_check
.y
] : combat_terrain
[to_check
.x
][to_check
.y
];
428 gr
= scenario
.ter_types
[ter
].picture
;
431 if (impassable(ter
) == TRUE
) {
435 // Keep away from marked specials during combat
436 if ((is_combat()) && (gr
<= 212) && (gr
>= 207))
438 if ((is_combat()) && (gr
== 406))
443 if (same_point (to_check
,c_town
.p_loc
) == TRUE
)
446 for (i
= 0; i
< 6; i
++)
447 if ((adven
[i
].main_status
== 1) && (same_point (to_check
,pc_pos
[i
]) == TRUE
))
451 if (monst_there(to_check
) < 90)
455 if (is_force_barrier(to_check
.x
,to_check
.y
))
463 Boolean
monst_on_space(location loc
,short m_num
)
467 if (c_town
.monst
.dudes
[m_num
].active
== 0)
469 if ((loc
.x
- c_town
.monst
.dudes
[m_num
].m_loc
.x
>= 0) &&
470 (loc
.x
- c_town
.monst
.dudes
[m_num
].m_loc
.x
<= c_town
.monst
.dudes
[m_num
].m_d
.x_width
- 1) &&
471 (loc
.y
- c_town
.monst
.dudes
[m_num
].m_loc
.y
>= 0) &&
472 (loc
.y
- c_town
.monst
.dudes
[m_num
].m_loc
.y
<= c_town
.monst
.dudes
[m_num
].m_d
.y_width
- 1))
477 short monst_there(location where
) // returns 90 if no
481 for (i
= 0; i
< T_M
; i
++)
482 if ((c_town
.monst
.dudes
[i
].active
!= 0) && (monst_on_space(where
,i
) == TRUE
))
486 Boolean
monst_can_be_there(location loc
,short m_num
)
489 location destination
;
491 // First clear monst away so it doesn't block itself
492 c_town
.monst
.dudes
[m_num
].m_loc
.x
+= 100;
494 for (i
= 0; i
< c_town
.monst
.dudes
[m_num
].m_d
.x_width
; i
++)
495 for (j
= 0; j
< c_town
.monst
.dudes
[m_num
].m_d
.y_width
; j
++) {
496 destination
.x
= loc
.x
+ i
; destination
.y
= loc
.y
+ j
;
497 if ((is_blocked(destination
) == TRUE
)
498 || (loc_off_act_area(destination
) == TRUE
)) {
499 c_town
.monst
.dudes
[m_num
].m_loc
.x
-= 100;
503 c_town
.monst
.dudes
[m_num
].m_loc
.x
-= 100;
507 Boolean
monst_adjacent(location loc
,short m_num
)
510 location destination
;
512 for (i
= 0; i
< c_town
.monst
.dudes
[m_num
].m_d
.x_width
; i
++)
513 for (j
= 0; j
< c_town
.monst
.dudes
[m_num
].m_d
.y_width
; j
++) {
514 destination
.x
= c_town
.monst
.dudes
[m_num
].m_loc
.x
+ i
;
515 destination
.y
= c_town
.monst
.dudes
[m_num
].m_loc
.y
+ j
;
516 if (adjacent(destination
,loc
) == TRUE
)
522 Boolean
monst_can_see(short m_num
,location l
)
525 location destination
;
527 for (i
= 0; i
< c_town
.monst
.dudes
[m_num
].m_d
.x_width
; i
++)
528 for (j
= 0; j
< c_town
.monst
.dudes
[m_num
].m_d
.y_width
; j
++) {
529 destination
.x
= c_town
.monst
.dudes
[m_num
].m_loc
.x
+ i
;
530 destination
.y
= c_town
.monst
.dudes
[m_num
].m_loc
.y
+ j
;
531 if (can_see(destination
,l
,0) < 5)
537 Boolean
party_can_see_monst(short m_num
)
540 location destination
;
542 for (i
= 0; i
< c_town
.monst
.dudes
[m_num
].m_d
.x_width
; i
++)
543 for (j
= 0; j
< c_town
.monst
.dudes
[m_num
].m_d
.y_width
; j
++) {
544 destination
.x
= c_town
.monst
.dudes
[m_num
].m_loc
.x
+ i
;
545 destination
.y
= c_town
.monst
.dudes
[m_num
].m_loc
.y
+ j
;
546 if (party_can_see(destination
) < 6)
552 Boolean
can_see_monst(location l
,short m_num
)
555 location destination
;
557 for (i
= 0; i
< c_town
.monst
.dudes
[m_num
].m_d
.x_width
; i
++)
558 for (j
= 0; j
< c_town
.monst
.dudes
[m_num
].m_d
.y_width
; j
++) {
559 destination
.x
= c_town
.monst
.dudes
[m_num
].m_loc
.x
+ i
;
560 destination
.y
= c_town
.monst
.dudes
[m_num
].m_loc
.y
+ j
;
561 if (can_see(l
,destination
,0) < 5)
567 Boolean
outd_is_blocked(location to_check
)
571 if (overall_mode
== 0) {
572 if (impassable(out
[to_check
.x
][to_check
.y
]) == TRUE
) {
575 for (i
= 0; i
< 10; i
++)
576 if ((party
.out_c
[i
].exists
) == TRUE
)
577 if (same_point(party
.out_c
[i
].m_loc
, to_check
) == TRUE
)
584 Boolean
special_which_blocks_monst(location to_check
)
586 if (terrain_blocked
[coord_to_ter(to_check
.x
,to_check
.y
)] == 2)
591 // Checks if space is a special that prevents movement into or placement of a PC on
592 Boolean
is_special(location to_check
)
594 unsigned char which_ter
;
596 if (special_which_blocks_monst(to_check
) == FALSE
)
598 which_ter
= coord_to_ter(to_check
.x
,to_check
.y
);
599 if (terrain_blocked
[which_ter
] == 2)
604 Boolean
outd_is_special(location to_check
)
606 if (overall_mode
== 0) {
607 if (terrain_blocked
[out
[to_check
.x
][to_check
.y
]] == 2) {
615 Boolean
impassable(unsigned char terrain_to_check
)
617 if (terrain_blocked
[terrain_to_check
] > 2)
622 short get_blockage(unsigned char terrain_type
)
624 // little kludgy in here for pits
625 if ((terrain_type
== 90) && (is_combat()) && (which_combat_type
== 0))
627 if ((terrain_blocked
[terrain_type
] == 5) || (terrain_blocked
[terrain_type
] == 1))
629 else if (terrain_blocked
[terrain_type
] > 3)
641 short extra_levels
[6] = {10,20,50,75,110,140};
643 if (((which_combat_type
== 0) && (is_combat()))
644 || (is_out()) || (c_town
.town
.lighting
== 0))
646 for (i
= 0; i
< 6; i
++)
647 if (party
.light_level
> extra_levels
[i
])
652 Boolean
pt_in_light(location from_where
,location to_where
) // Assumes, of course, in town or combat
656 if (c_town
.town
.lighting
== 0)
658 if ((to_where
.x
< 0) || (to_where
.x
>= town_size
[town_type
])
659 || (to_where
.y
< 0) || (to_where
.y
>= town_size
[town_type
]))
661 if (t_d
.lighting
[to_where
.x
/ 8][to_where
.y
] & (char) (s_pow(2,to_where
.x
% 8)))
664 if (dist(from_where
,to_where
) <= light_radius())
670 Boolean
combat_pt_in_light(location to_where
)
674 if ((c_town
.town
.lighting
== 0) || (which_combat_type
== 0))
676 if ((to_where
.x
< 0) || (to_where
.x
>= town_size
[town_type
])
677 || (to_where
.y
< 0) || (to_where
.y
>= town_size
[town_type
]))
679 if (t_d
.lighting
[to_where
.x
/ 8][to_where
.y
] & (char) (s_pow(2,to_where
.x
% 8)))
682 rad
= light_radius();
683 for (i
= 0; i
< 6; i
++)
684 if (adven
[i
].main_status
== 1) {
685 if (dist(pc_pos
[i
],to_where
) <= rad
)
692 Boolean
party_sees_a_monst() // Returns true is a hostile monster is in sight.
696 for (i
= 0; i
< T_M
; i
++) {
697 if (c_town
.monst
.dudes
[i
].active
> 0)
698 if ((c_town
.monst
.dudes
[i
].attitude
== 1) &&
699 (party_can_see_monst(i
) == TRUE
))
707 // Returns 6 if can't see, O.W. returns the # of a PC that can see
708 short party_can_see(location where
)
711 Boolean in_light
= FALSE
;
714 if ((point_onscreen(party
.p_loc
,where
) == TRUE
) && (can_see(party
.p_loc
,where
,0) < 5))
719 if ( ((point_onscreen(c_town
.p_loc
,where
) == TRUE
) || (overall_mode
== 36)) && (pt_in_light(c_town
.p_loc
,where
) == TRUE
)
720 && (can_see(c_town
.p_loc
,where
,0) < 5))
725 // Now for combat checks. Doing separately for efficiency. Check first for light. If
727 if ((which_combat_type
!= 0) && (combat_pt_in_light(where
) == FALSE
))
730 for (i
= 0; i
< 6; i
++)
731 if (adven
[i
].main_status
== 1) {
732 if (can_see(pc_pos
[i
],where
,0) < 5)
738 location
push_loc(location from_where
,location to_where
)
742 loc_to_try
= to_where
;
743 loc_to_try
.x
= loc_to_try
.x
+ (to_where
.x
- from_where
.x
);
744 loc_to_try
.y
= loc_to_try
.y
+ (to_where
.y
- from_where
.y
);
745 if ((t_d
.terrain
[loc_to_try
.x
][loc_to_try
.y
] == 90) ||
746 ((t_d
.terrain
[loc_to_try
.x
][loc_to_try
.y
] >= 50)&& (t_d
.terrain
[loc_to_try
.x
][loc_to_try
.y
] <= 64))
747 || (t_d
.terrain
[loc_to_try
.x
][loc_to_try
.y
] == 71)
748 || ((t_d
.terrain
[loc_to_try
.x
][loc_to_try
.y
] >= 74)&& (t_d
.terrain
[loc_to_try
.x
][loc_to_try
.y
] <= 78))
754 if ((get_obscurity((short) loc_to_try
.x
,(short) loc_to_try
.y
) > 0) ||
755 (terrain_blocked
[t_d
.terrain
[loc_to_try
.x
][loc_to_try
.y
]] > 0) ||
756 (loc_off_act_area(loc_to_try
) == TRUE
) ||
757 (monst_there(loc_to_try
) < 90) ||
758 (pc_there(loc_to_try
) < 6))
760 else return loc_to_try
;
765 Boolean
spot_impassable(short i
,short j
)
769 ter
= coord_to_ter(i
,j
);
770 if (terrain_blocked
[ter
] == 5)
775 void swap_ter(short i
,short j
,unsigned char ter1
,unsigned char ter2
)
777 if (coord_to_ter(i
,j
) == ter1
)
778 alter_space(i
,j
,ter2
);
779 else if (coord_to_ter(i
,j
) == ter2
)
780 alter_space(i
,j
,ter1
);
783 void alter_space(short i
,short j
,unsigned char ter
)
789 map_graphic_placed
[i
/ 8][j
] =
790 map_graphic_placed
[i
/ 8][j
] & ~((unsigned char)(s_pow(2,i
% 8)));
793 l
= local_to_global(l
);
795 outdoors
[party
.i_w_c
.x
][party
.i_w_c
.y
].terrain
[i
][j
] = ter
;
798 t_d
.terrain
[i
][j
] = ter
;
799 combat_terrain
[i
][j
] = ter
;
800 if ((scenario
.ter_types
[t_d
.terrain
[i
][j
]].special
>= 16) &&
801 (scenario
.ter_types
[t_d
.terrain
[i
][j
]].special
<= 19))