1 /**
2  * @file lighting.cpp
3  *
4  * Implementation of light and vision.
5  */
6 #include "all.h"
7 
8 DEVILUTION_BEGIN_NAMESPACE
9 
10 LightListStruct VisionList[MAXVISION];
11 BYTE lightactive[MAXLIGHTS];
12 LightListStruct LightList[MAXLIGHTS];
13 int numlights;
14 BYTE lightradius[16][128];
15 BOOL dovision;
16 int numvision;
17 char lightmax;
18 BOOL dolighting;
19 BYTE lightblock[64][16][16];
20 int visionid;
21 BYTE *pLightTbl;
22 BOOL lightflag;
23 
24 /**
25  * CrawlTable specifies X- and Y-coordinate deltas from a missile target coordinate.
26  *
27  * n=4
28  *
29  *    y
30  *    ^
31  *    |  1
32  *    | 3#4
33  *    |  2
34  *    +-----> x
35  *
36  * n=16
37  *
38  *    y
39  *    ^
40  *    |  314
41  *    | B7 8C
42  *    | F # G
43  *    | D9 AE
44  *    |  526
45  *    +-------> x
46  */
47 const char CrawlTable[2749] = {
48 	// clang-format off
49 	1, // Table 0, offset 0
50 	  0,   0,
51 	4, // Table 1, offset 3
52 	 0,    1,    0,  -1,   -1,  0,    1,  0,
53 	16, // Table 2, offset 12
54 	  0,   2,    0,  -2,   -1,  2,    1,  2,
55 	 -1,  -2,    1,  -2,   -1,  1,    1,  1,
56 	 -1,  -1,    1,  -1,   -2,  1,    2,  1,
57 	 -2,  -1,    2,  -1,   -2,  0,    2,  0,
58 	24, // Table 3, offset 45
59 	  0,   3,    0,  -3,   -1,  3,    1,  3,
60 	 -1,  -3,    1,  -3,   -2,  3,    2,  3,
61 	 -2,  -3,    2,  -3,   -2,  2,    2,  2,
62 	 -2,  -2,    2,  -2,   -3,  2,    3,  2,
63 	 -3,  -2,    3,  -2,   -3,  1,    3,  1,
64 	 -3,  -1,    3,  -1,   -3,  0,    3,  0,
65 	32, // Table 4, offset 94
66 	  0,   4,    0,  -4,   -1,  4,    1,  4,
67 	 -1,  -4,    1,  -4,   -2,  4,    2,  4,
68 	 -2,  -4,    2,  -4,   -3,  4,    3,  4,
69 	 -3,  -4,    3,  -4,   -3,  3,    3,  3,
70 	 -3,  -3,    3,  -3,   -4,  3,    4,  3,
71 	 -4,  -3,    4,  -3,   -4,  2,    4,  2,
72 	 -4,  -2,    4,  -2,   -4,  1,    4,  1,
73 	 -4,  -1,    4,  -1,   -4,  0,    4,  0,
74 	40, // Table 5, offset 159
75 	  0,   5,    0,  -5,   -1,  5,    1,  5,
76 	 -1,  -5,    1,  -5,   -2,  5,    2,  5,
77 	 -2,  -5,    2,  -5,   -3,  5,    3,  5,
78 	 -3,  -5,    3,  -5,   -4,  5,    4,  5,
79 	 -4,  -5,    4,  -5,   -4,  4,    4,  4,
80 	 -4,  -4,    4,  -4,   -5,  4,    5,  4,
81 	 -5,  -4,    5,  -4,   -5,  3,    5,  3,
82 	 -5,  -3,    5,  -3,   -5,  2,    5,  2,
83 	 -5,  -2,    5,  -2,   -5,  1,    5,  1,
84 	 -5,  -1,    5,  -1,   -5,  0,    5,  0,
85 	48, // Table 6, offset 240
86 	  0,   6,    0,  -6,   -1,  6,    1,  6,
87 	 -1,  -6,    1,  -6,   -2,  6,    2,  6,
88 	 -2,  -6,    2,  -6,   -3,  6,    3,  6,
89 	 -3,  -6,    3,  -6,   -4,  6,    4,  6,
90 	 -4,  -6,    4,  -6,   -5,  6,    5,  6,
91 	 -5,  -6,    5,  -6,   -5,  5,    5,  5,
92 	 -5,  -5,    5,  -5,   -6,  5,    6,  5,
93 	 -6,  -5,    6,  -5,   -6,  4,    6,  4,
94 	 -6,  -4,    6,  -4,   -6,  3,    6,  3,
95 	 -6,  -3,    6,  -3,   -6,  2,    6,  2,
96 	 -6,  -2,    6,  -2,   -6,  1,    6,  1,
97 	 -6,  -1,    6,  -1,   -6,  0,    6,  0,
98 	56, // Table 7, offset 337
99 	  0,   7,    0,  -7,   -1,  7,    1,  7,
100 	 -1,  -7,    1,  -7,   -2,  7,    2,  7,
101 	 -2,  -7,    2,  -7,   -3,  7,    3,  7,
102 	 -3,  -7,    3,  -7,   -4,  7,    4,  7,
103 	 -4,  -7,    4,  -7,   -5,  7,    5,  7,
104 	 -5,  -7,    5,  -7,   -6,  7,    6,  7,
105 	 -6,  -7,    6,  -7,   -6,  6,    6,  6,
106 	 -6,  -6,    6,  -6,   -7,  6,    7,  6,
107 	 -7,  -6,    7,  -6,   -7,  5,    7,  5,
108 	 -7,  -5,    7,  -5,   -7,  4,    7,  4,
109 	 -7,  -4,    7,  -4,   -7,  3,    7,  3,
110 	 -7,  -3,    7,  -3,   -7,  2,    7,  2,
111 	 -7,  -2,    7,  -2,   -7,  1,    7,  1,
112 	 -7,  -1,    7,  -1,   -7,  0,    7,  0,
113 	64, // Table 8, offset 450
114 	  0,   8,    0,  -8,   -1,  8,    1,  8,
115 	 -1,  -8,    1,  -8,   -2,  8,    2,  8,
116 	 -2,  -8,    2,  -8,   -3,  8,    3,  8,
117 	 -3,  -8,    3,  -8,   -4,  8,    4,  8,
118 	 -4,  -8,    4,  -8,   -5,  8,    5,  8,
119 	 -5,  -8,    5,  -8,   -6,  8,    6,  8,
120 	 -6,  -8,    6,  -8,   -7,  8,    7,  8,
121 	 -7,  -8,    7,  -8,   -7,  7,    7,  7,
122 	 -7,  -7,    7,  -7,   -8,  7,    8,  7,
123 	 -8,  -7,    8,  -7,   -8,  6,    8,  6,
124 	 -8,  -6,    8,  -6,   -8,  5,    8,  5,
125 	 -8,  -5,    8,  -5,   -8,  4,    8,  4,
126 	 -8,  -4,    8,  -4,   -8,  3,    8,  3,
127 	 -8,  -3,    8,  -3,   -8,  2,    8,  2,
128 	 -8,  -2,    8,  -2,   -8,  1,    8,  1,
129 	 -8,  -1,    8,  -1,   -8,  0,    8,  0,
130 	72, // Table 9, offset 579
131 	  0,   9,    0,  -9,   -1,  9,    1,  9,
132 	 -1,  -9,    1,  -9,   -2,  9,    2,  9,
133 	 -2,  -9,    2,  -9,   -3,  9,    3,  9,
134 	 -3,  -9,    3,  -9,   -4,  9,    4,  9,
135 	 -4,  -9,    4,  -9,   -5,  9,    5,  9,
136 	 -5,  -9,    5,  -9,   -6,  9,    6,  9,
137 	 -6,  -9,    6,  -9,   -7,  9,    7,  9,
138 	 -7,  -9,    7,  -9,   -8,  9,    8,  9,
139 	 -8,  -9,    8,  -9,   -8,  8,    8,  8,
140 	 -8,  -8,    8,  -8,   -9,  8,    9,  8,
141 	 -9,  -8,    9,  -8,   -9,  7,    9,  7,
142 	 -9,  -7,    9,  -7,   -9,  6,    9,  6,
143 	 -9,  -6,    9,  -6,   -9,  5,    9,  5,
144 	 -9,  -5,    9,  -5,   -9,  4,    9,  4,
145 	 -9,  -4,    9,  -4,   -9,  3,    9,  3,
146 	 -9,  -3,    9,  -3,   -9,  2,    9,  2,
147 	 -9,  -2,    9,  -2,   -9,  1,    9,  1,
148 	 -9,  -1,    9,  -1,   -9,  0,    9,  0,
149 	80, // Table 10, offset 724
150 	  0,  10,    0, -10,   -1, 10,    1, 10,
151 	 -1, -10,    1, -10,   -2, 10,    2, 10,
152 	 -2, -10,    2, -10,   -3, 10,    3, 10,
153 	 -3, -10,    3, -10,   -4, 10,    4, 10,
154 	 -4, -10,    4, -10,   -5, 10,    5, 10,
155 	 -5, -10,    5, -10,   -6, 10,    6, 10,
156 	 -6, -10,    6, -10,   -7, 10,    7, 10,
157 	 -7, -10,    7, -10,   -8, 10,    8, 10,
158 	 -8, -10,    8, -10,   -9, 10,    9, 10,
159 	 -9, -10,    9, -10,   -9,  9,    9,  9,
160 	 -9,  -9,    9,  -9,  -10,  9,   10,  9,
161 	-10,  -9,   10,  -9,  -10,  8,   10,  8,
162 	-10,  -8,   10,  -8,  -10,  7,   10,  7,
163 	-10,  -7,   10,  -7,  -10,  6,   10,  6,
164 	-10,  -6,   10,  -6,  -10,  5,   10,  5,
165 	-10,  -5,   10,  -5,  -10,  4,   10,  4,
166 	-10,  -4,   10,  -4,  -10,  3,   10,  3,
167 	-10,  -3,   10,  -3,  -10,  2,   10,  2,
168 	-10,  -2,   10,  -2,  -10,  1,   10,  1,
169 	-10,  -1,   10,  -1,  -10,  0,   10,  0,
170 	88, // Table 11, offset 885
171 	  0,  11,    0, -11,   -1, 11,    1, 11,
172 	 -1, -11,    1, -11,   -2, 11,    2, 11,
173 	 -2, -11,    2, -11,   -3, 11,    3, 11,
174 	 -3, -11,    3, -11,   -4, 11,    4, 11,
175 	 -4, -11,    4, -11,   -5, 11,    5, 11,
176 	 -5, -11,    5, -11,   -6, 11,    6, 11,
177 	 -6, -11,    6, -11,   -7, 11,    7, 11,
178 	 -7, -11,    7, -11,   -8, 11,    8, 11,
179 	 -8, -11,    8, -11,   -9, 11,    9, 11,
180 	 -9, -11,    9, -11,  -10, 11,   10, 11,
181 	-10, -11,   10, -11,  -10, 10,   10, 10,
182 	-10, -10,   10, -10,  -11, 10,   11, 10,
183 	-11, -10,   11, -10,  -11,  9,   11,  9,
184 	-11,  -9,   11,  -9,  -11,  8,   11,  8,
185 	-11,  -8,   11,  -8,  -11,  7,   11,  7,
186 	-11,  -7,   11,  -7,  -11,  6,   11,  6,
187 	-11,  -6,   11,  -6,  -11,  5,   11,  5,
188 	-11,  -5,   11,  -5,  -11,  4,   11,  4,
189 	-11,  -4,   11,  -4,  -11,  3,   11,  3,
190 	-11,  -3,   11,  -3,  -11,  2,   11,  2,
191 	-11,  -2,   11,  -2,  -11,  1,   11,  1,
192 	-11,  -1,   11,  -1,  -11,  0,   11,  0,
193 	96, // Table 12, offset 1062
194 	  0,  12,    0, -12,   -1, 12,    1, 12,
195 	 -1, -12,    1, -12,   -2, 12,    2, 12,
196 	 -2, -12,    2, -12,   -3, 12,    3, 12,
197 	 -3, -12,    3, -12,   -4, 12,    4, 12,
198 	 -4, -12,    4, -12,   -5, 12,    5, 12,
199 	 -5, -12,    5, -12,   -6, 12,    6, 12,
200 	 -6, -12,    6, -12,   -7, 12,    7, 12,
201 	 -7, -12,    7, -12,   -8, 12,    8, 12,
202 	 -8, -12,    8, -12,   -9, 12,    9, 12,
203 	 -9, -12,    9, -12,  -10, 12,   10, 12,
204 	-10, -12,   10, -12,  -11, 12,   11, 12,
205 	-11, -12,   11, -12,  -11, 11,   11, 11,
206 	-11, -11,   11, -11,  -12, 11,   12, 11,
207 	-12, -11,   12, -11,  -12, 10,   12, 10,
208 	-12, -10,   12, -10,  -12,  9,   12,  9,
209 	-12,  -9,   12,  -9,  -12,  8,   12,  8,
210 	-12,  -8,   12,  -8,  -12,  7,   12,  7,
211 	-12,  -7,   12,  -7,  -12,  6,   12,  6,
212 	-12,  -6,   12,  -6,  -12,  5,   12,  5,
213 	-12,  -5,   12,  -5,  -12,  4,   12,  4,
214 	-12,  -4,   12,  -4,  -12,  3,   12,  3,
215 	-12,  -3,   12,  -3,  -12,  2,   12,  2,
216 	-12,  -2,   12,  -2,  -12,  1,   12,  1,
217 	-12,  -1,   12,  -1,  -12,  0,   12,  0,
218 	104, // Table 13, offset 1255
219 	  0,  13,    0, -13,   -1, 13,    1, 13,
220 	 -1, -13,    1, -13,   -2, 13,    2, 13,
221 	 -2, -13,    2, -13,   -3, 13,    3, 13,
222 	 -3, -13,    3, -13,   -4, 13,    4, 13,
223 	 -4, -13,    4, -13,   -5, 13,    5, 13,
224 	 -5, -13,    5, -13,   -6, 13,    6, 13,
225 	 -6, -13,    6, -13,   -7, 13,    7, 13,
226 	 -7, -13,    7, -13,   -8, 13,    8, 13,
227 	 -8, -13,    8, -13,   -9, 13,    9, 13,
228 	 -9, -13,    9, -13,  -10, 13,   10, 13,
229 	-10, -13,   10, -13,  -11, 13,   11, 13,
230 	-11, -13,   11, -13,  -12, 13,   12, 13,
231 	-12, -13,   12, -13,  -12, 12,   12, 12,
232 	-12, -12,   12, -12,  -13, 12,   13, 12,
233 	-13, -12,   13, -12,  -13, 11,   13, 11,
234 	-13, -11,   13, -11,  -13, 10,   13, 10,
235 	-13, -10,   13, -10,  -13,  9,   13,  9,
236 	-13,  -9,   13,  -9,  -13,  8,   13,  8,
237 	-13,  -8,   13,  -8,  -13,  7,   13,  7,
238 	-13,  -7,   13,  -7,  -13,  6,   13,  6,
239 	-13,  -6,   13,  -6,  -13,  5,   13,  5,
240 	-13,  -5,   13,  -5,  -13,  4,   13,  4,
241 	-13,  -4,   13,  -4,  -13,  3,   13,  3,
242 	-13,  -3,   13,  -3,  -13,  2,   13,  2,
243 	-13,  -2,   13,  -2,  -13,  1,   13,  1,
244 	-13,  -1,   13,  -1,  -13,  0,   13,  0,
245 	112, // Table 14, offset 1464
246 	  0,  14,    0, -14,   -1, 14,    1, 14,
247 	 -1, -14,    1, -14,   -2, 14,    2, 14,
248 	 -2, -14,    2, -14,   -3, 14,    3, 14,
249 	 -3, -14,    3, -14,   -4, 14,    4, 14,
250 	 -4, -14,    4, -14,   -5, 14,    5, 14,
251 	 -5, -14,    5, -14,   -6, 14,    6, 14,
252 	 -6, -14,    6, -14,   -7, 14,    7, 14,
253 	 -7, -14,    7, -14,   -8, 14,    8, 14,
254 	 -8, -14,    8, -14,   -9, 14,    9, 14,
255 	 -9, -14,    9, -14,  -10, 14,   10, 14,
256 	-10, -14,   10, -14,  -11, 14,   11, 14,
257 	-11, -14,   11, -14,  -12, 14,   12, 14,
258 	-12, -14,   12, -14,  -13, 14,   13, 14,
259 	-13, -14,   13, -14,  -13, 13,   13, 13,
260 	-13, -13,   13, -13,  -14, 13,   14, 13,
261 	-14, -13,   14, -13,  -14, 12,   14, 12,
262 	-14, -12,   14, -12,  -14, 11,   14, 11,
263 	-14, -11,   14, -11,  -14, 10,   14, 10,
264 	-14, -10,   14, -10,  -14,  9,   14,  9,
265 	-14,  -9,   14,  -9,  -14,  8,   14,  8,
266 	-14,  -8,   14,  -8,  -14,  7,   14,  7,
267 	-14,  -7,   14,  -7,  -14,  6,   14,  6,
268 	-14,  -6,   14,  -6,  -14,  5,   14,  5,
269 	-14,  -5,   14,  -5,  -14,  4,   14,  4,
270 	-14,  -4,   14,  -4,  -14,  3,   14,  3,
271 	-14,  -3,   14,  -3,  -14,  2,   14,  2,
272 	-14,  -2,   14,  -2,  -14,  1,   14,  1,
273 	-14,  -1,   14,  -1,  -14,  0,   14,  0,
274 	120, // Table 15, offset 1689
275 	  0,  15,    0, -15,   -1, 15,    1, 15,
276 	 -1, -15,    1, -15,   -2, 15,    2, 15,
277 	 -2, -15,    2, -15,   -3, 15,    3, 15,
278 	 -3, -15,    3, -15,   -4, 15,    4, 15,
279 	 -4, -15,    4, -15,   -5, 15,    5, 15,
280 	 -5, -15,    5, -15,   -6, 15,    6, 15,
281 	 -6, -15,    6, -15,   -7, 15,    7, 15,
282 	 -7, -15,    7, -15,   -8, 15,    8, 15,
283 	 -8, -15,    8, -15,   -9, 15,    9, 15,
284 	 -9, -15,    9, -15,  -10, 15,   10, 15,
285 	-10, -15,   10, -15,  -11, 15,   11, 15,
286 	-11, -15,   11, -15,  -12, 15,   12, 15,
287 	-12, -15,   12, -15,  -13, 15,   13, 15,
288 	-13, -15,   13, -15,  -14, 15,   14, 15,
289 	-14, -15,   14, -15,  -14, 14,   14, 14,
290 	-14, -14,   14, -14,  -15, 14,   15, 14,
291 	-15, -14,   15, -14,  -15, 13,   15, 13,
292 	-15, -13,   15, -13,  -15, 12,   15, 12,
293 	-15, -12,   15, -12,  -15, 11,   15, 11,
294 	-15, -11,   15, -11,  -15, 10,   15, 10,
295 	-15, -10,   15, -10,  -15,  9,   15,  9,
296 	-15,  -9,   15,  -9,  -15,  8,   15,  8,
297 	-15,  -8,   15,  -8,  -15,  7,   15,  7,
298 	-15,  -7,   15,  -7,  -15,  6,   15,  6,
299 	-15,  -6,   15,  -6,  -15,  5,   15,  5,
300 	-15,  -5,   15,  -5,  -15,  4,   15,  4,
301 	-15,  -4,   15,  -4,  -15,  3,   15,  3,
302 	-15,  -3,   15,  -3,  -15,  2,   15,  2,
303 	-15,  -2,   15,  -2,  -15,  1,   15,  1,
304 	-15,  -1,   15,  -1,  -15,  0,   15,  0,
305 	(char)128, // Table 16, offset 1930
306 	  0,  16,    0, -16,   -1, 16,    1, 16,
307 	 -1, -16,    1, -16,   -2, 16,    2, 16,
308 	 -2, -16,    2, -16,   -3, 16,    3, 16,
309 	 -3, -16,    3, -16,   -4, 16,    4, 16,
310 	 -4, -16,    4, -16,   -5, 16,    5, 16,
311 	 -5, -16,    5, -16,   -6, 16,    6, 16,
312 	 -6, -16,    6, -16,   -7, 16,    7, 16,
313 	 -7, -16,    7, -16,   -8, 16,    8, 16,
314 	 -8, -16,    8, -16,   -9, 16,    9, 16,
315 	 -9, -16,    9, -16,  -10, 16,   10, 16,
316 	-10, -16,   10, -16,  -11, 16,   11, 16,
317 	-11, -16,   11, -16,  -12, 16,   12, 16,
318 	-12, -16,   12, -16,  -13, 16,   13, 16,
319 	-13, -16,   13, -16,  -14, 16,   14, 16,
320 	-14, -16,   14, -16,  -15, 16,   15, 16,
321 	-15, -16,   15, -16,  -15, 15,   15, 15,
322 	-15, -15,   15, -15,  -16, 15,   16, 15,
323 	-16, -15,   16, -15,  -16, 14,   16, 14,
324 	-16, -14,   16, -14,  -16, 13,   16, 13,
325 	-16, -13,   16, -13,  -16, 12,   16, 12,
326 	-16, -12,   16, -12,  -16, 11,   16, 11,
327 	-16, -11,   16, -11,  -16, 10,   16, 10,
328 	-16, -10,   16, -10,  -16,  9,   16,  9,
329 	-16,  -9,   16,  -9,  -16,  8,   16,  8,
330 	-16,  -8,   16,  -8,  -16,  7,   16,  7,
331 	-16,  -7,   16,  -7,  -16,  6,   16,  6,
332 	-16,  -6,   16,  -6,  -16,  5,   16,  5,
333 	-16,  -5,   16,  -5,  -16,  4,   16,  4,
334 	-16,  -4,   16,  -4,  -16,  3,   16,  3,
335 	-16,  -3,   16,  -3,  -16,  2,   16,  2,
336 	-16,  -2,   16,  -2,  -16,  1,   16,  1,
337 	-16,  -1,   16,  -1,  -16,  0,   16,  0,
338 	(char)136, // Table 16, offset 2187
339 	  0,  17,    0, -17,   -1, 17,    1, 17,
340 	 -1, -17,    1, -17,   -2, 17,    2, 17,
341 	 -2, -17,    2, -17,   -3, 17,    3, 17,
342 	 -3, -17,    3, -17,   -4, 17,    4, 17,
343 	 -4, -17,    4, -17,   -5, 17,    5, 17,
344 	 -5, -17,    5, -17,   -6, 17,    6, 17,
345 	 -6, -17,    6, -17,   -7, 17,    7, 17,
346 	 -7, -17,    7, -17,   -8, 17,    8, 17,
347 	 -8, -17,    8, -17,   -9, 17,    9, 17,
348 	 -9, -17,    9, -17,  -10, 17,   10, 17,
349 	-10, -17,   10, -17,  -11, 17,   11, 17,
350 	-11, -17,   11, -17,  -12, 17,   12, 17,
351 	-12, -17,   12, -17,  -13, 17,   13, 17,
352 	-13, -17,   13, -17,  -14, 17,   14, 17,
353 	-14, -17,   14, -17,  -15, 17,   15, 17,
354 	-15, -17,   15, -17,  -16, 17,   16, 17,
355 	-16, -17,   16, -17,  -16, 16,   16, 16,
356 	-16, -16,   16, -16,  -17, 16,   17, 16,
357 	-17, -16,   17, -16,  -17, 15,   17, 15,
358 	-17, -15,   17, -15,  -17, 14,   17, 14,
359 	-17, -14,   17, -14,  -17, 13,   17, 13,
360 	-17, -13,   17, -13,  -17, 12,   17, 12,
361 	-17, -12,   17, -12,  -17, 11,   17, 11,
362 	-17, -11,   17, -11,  -17, 10,   17, 10,
363 	-17, -10,   17, -10,  -17,  9,   17,  9,
364 	-17,  -9,   17,  -9,  -17,  8,   17,  8,
365 	-17,  -8,   17,  -8,  -17,  7,   17,  7,
366 	-17,  -7,   17,  -7,  -17,  6,   17,  6,
367 	-17,  -6,   17,  -6,  -17,  5,   17,  5,
368 	-17,  -5,   17,  -5,  -17,  4,   17,  4,
369 	-17,  -4,   17,  -4,  -17,  3,   17,  3,
370 	-17,  -3,   17,  -3,  -17,  2,   17,  2,
371 	-17,  -2,   17,  -2,  -17,  1,   17,  1,
372 	-17,  -1,   17,  -1,  -17,  0,   17,  0,
373 	(char)144, // Table 16, offset 2460
374 	  0,  18,    0, -18,   -1, 18,    1, 18,
375 	 -1, -18,    1, -18,   -2, 18,    2, 18,
376 	 -2, -18,    2, -18,   -3, 18,    3, 18,
377 	 -3, -18,    3, -18,   -4, 18,    4, 18,
378 	 -4, -18,    4, -18,   -5, 18,    5, 18,
379 	 -5, -18,    5, -18,   -6, 18,    6, 18,
380 	 -6, -18,    6, -18,   -7, 18,    7, 18,
381 	 -7, -18,    7, -18,   -8, 18,    8, 18,
382 	 -8, -18,    8, -18,   -9, 18,    9, 18,
383 	 -9, -18,    9, -18,  -10, 18,   10, 18,
384 	-10, -18,   10, -18,  -11, 18,   11, 18,
385 	-11, -18,   11, -18,  -12, 18,   12, 18,
386 	-12, -18,   12, -18,  -13, 18,   13, 18,
387 	-13, -18,   13, -18,  -14, 18,   14, 18,
388 	-14, -18,   14, -18,  -15, 18,   15, 18,
389 	-15, -18,   15, -18,  -16, 18,   16, 18,
390 	-16, -18,   16, -18,  -17, 18,   17, 18,
391 	-17, -18,   17, -18,  -17, 17,   17, 17,
392 	-17, -17,   17, -17,  -18, 17,   18, 17,
393 	-18, -17,   18, -17,  -18, 16,   18, 16,
394 	-18, -16,   18, -16,  -18, 15,   18, 15,
395 	-18, -15,   18, -15,  -18, 14,   18, 14,
396 	-18, -14,   18, -14,  -18, 13,   18, 13,
397 	-18, -13,   18, -13,  -18, 12,   18, 12,
398 	-18, -12,   18, -12,  -18, 11,   18, 11,
399 	-18, -11,   18, -11,  -18, 10,   18, 10,
400 	-18, -10,   18, -10,  -18,  9,   18,  9,
401 	-18,  -9,   18,  -9,  -18,  8,   18,  8,
402 	-18,  -8,   18,  -8,  -18,  7,   18,  7,
403 	-18,  -7,   18,  -7,  -18,  6,   18,  6,
404 	-18,  -6,   18,  -6,  -18,  5,   18,  5,
405 	-18,  -5,   18,  -5,  -18,  4,   18,  4,
406 	-18,  -4,   18,  -4,  -18,  3,   18,  3,
407 	-18,  -3,   18,  -3,  -18,  2,   18,  2,
408 	-18,  -2,   18,  -2,  -18,  1,   18,  1,
409 	-18,  -1,   18,  -1,  -18,  0,   18,  0,
410 	// clang-format on
411 };
412 
413 /*
414  * vCrawlTable specifies the X- Y-coordinate offsets of lighting visions.
415  *  The last entry-pair is only for alignment.
416  */
417 const BYTE vCrawlTable[23][30] = {
418 	// clang-format off
419 	{ 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10,  0, 11,  0, 12,  0, 13,  0, 14,  0, 15,  0 },
420 	{ 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 1, 9, 1, 10,  1, 11,  1, 12,  1, 13,  1, 14,  1, 15,  1 },
421 	{ 1, 0, 2, 0, 3, 0, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9, 1, 10,  1, 11,  1, 12,  2, 13,  2, 14,  2, 15,  2 },
422 	{ 1, 0, 2, 0, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 2, 9, 2, 10,  2, 11,  2, 12,  2, 13,  3, 14,  3, 15,  3 },
423 	{ 1, 0, 2, 1, 3, 1, 4, 1, 5, 1, 6, 2, 7, 2, 8, 2, 9, 3, 10,  3, 11,  3, 12,  3, 13,  4, 14,  4,  0,  0 },
424 	{ 1, 0, 2, 1, 3, 1, 4, 1, 5, 2, 6, 2, 7, 3, 8, 3, 9, 3, 10,  4, 11,  4, 12,  4, 13,  5, 14,  5,  0,  0 },
425 	{ 1, 0, 2, 1, 3, 1, 4, 2, 5, 2, 6, 3, 7, 3, 8, 3, 9, 4, 10,  4, 11,  5, 12,  5, 13,  6, 14,  6,  0,  0 },
426 	{ 1, 1, 2, 1, 3, 2, 4, 2, 5, 3, 6, 3, 7, 4, 8, 4, 9, 5, 10,  5, 11,  6, 12,  6, 13,  7,  0,  0,  0,  0 },
427 	{ 1, 1, 2, 1, 3, 2, 4, 2, 5, 3, 6, 4, 7, 4, 8, 5, 9, 6, 10,  6, 11,  7, 12,  7, 12,  8, 13,  8,  0,  0 },
428 	{ 1, 1, 2, 2, 3, 2, 4, 3, 5, 4, 6, 5, 7, 5, 8, 6, 9, 7, 10,  7, 10,  8, 11,  8, 12,  9,  0,  0,  0,  0 },
429 	{ 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 5, 7, 6, 8, 7, 9, 8, 10,  9, 11,  9, 11, 10,  0,  0,  0,  0,  0,  0 },
430 	{ 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,  0,  0,  0,  0,  0,  0,  0,  0 },
431 	{ 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9,  9, 10,  9, 11, 10, 11,  0,  0,  0,  0,  0,  0 },
432 	{ 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 5, 7, 6, 8, 7, 9,  7, 10,  8, 10,  8, 11,  9, 12,  0,  0,  0,  0 },
433 	{ 1, 1, 1, 2, 2, 3, 2, 4, 3, 5, 4, 6, 4, 7, 5, 8, 6, 9,  6, 10,  7, 11,  7, 12,  8, 12,  8, 13,  0,  0 },
434 	{ 1, 1, 1, 2, 2, 3, 2, 4, 3, 5, 3, 6, 4, 7, 4, 8, 5, 9,  5, 10,  6, 11,  6, 12,  7, 13,  0,  0,  0,  0 },
435 	{ 0, 1, 1, 2, 1, 3, 2, 4, 2, 5, 3, 6, 3, 7, 3, 8, 4, 9,  4, 10,  5, 11,  5, 12,  6, 13,  6, 14,  0,  0 },
436 	{ 0, 1, 1, 2, 1, 3, 1, 4, 2, 5, 2, 6, 3, 7, 3, 8, 3, 9,  4, 10,  4, 11,  4, 12,  5, 13,  5, 14,  0,  0 },
437 	{ 0, 1, 1, 2, 1, 3, 1, 4, 1, 5, 2, 6, 2, 7, 2, 8, 3, 9,  3, 10,  3, 11,  3, 12,  4, 13,  4, 14,  0,  0 },
438 	{ 0, 1, 0, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 2, 8, 2, 9,  2, 10,  2, 11,  2, 12,  3, 13,  3, 14,  3, 15 },
439 	{ 0, 1, 0, 2, 0, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9,  1, 10,  1, 11,  2, 12,  2, 13,  2, 14,  2, 15 },
440 	{ 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 1, 8, 1, 9,  1, 10,  1, 11,  1, 12,  1, 13,  1, 14,  1, 15 },
441 	{ 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9,  0, 10,  0, 11,  0, 12,  0, 13,  0, 14,  0, 15 },
442 	// clang-format on
443 };
444 
445 /** RadiusAdj maps from vCrawlTable index to lighting vision radius adjustment. */
446 const BYTE RadiusAdj[23] = { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 4, 3, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0 };
447 
RotateRadius(int * x,int * y,int * dx,int * dy,int * lx,int * ly,int * bx,int * by)448 void RotateRadius(int *x, int *y, int *dx, int *dy, int *lx, int *ly, int *bx, int *by)
449 {
450 	int swap;
451 
452 	*bx = 0;
453 	*by = 0;
454 
455 	swap = *dx;
456 	*dx = 7 - *dy;
457 	*dy = swap;
458 	swap = *lx;
459 	*lx = 7 - *ly;
460 	*ly = swap;
461 
462 	*x = *dx - *lx;
463 	*y = *dy - *ly;
464 
465 	if (*x < 0) {
466 		*x += 8;
467 		*bx = 1;
468 	}
469 	if (*y < 0) {
470 		*y += 8;
471 		*by = 1;
472 	}
473 }
474 
SetLight(int x,int y,char v)475 void SetLight(int x, int y, char v)
476 {
477 	if (LoadMapObjsFlag)
478 		dPreLight[x][y] = v;
479 	else
480 		dLight[x][y] = v;
481 }
482 
GetLight(int x,int y)483 char GetLight(int x, int y)
484 {
485 	if (LoadMapObjsFlag)
486 		return dPreLight[x][y];
487 	else
488 		return dLight[x][y];
489 }
490 
DoLighting(int nXPos,int nYPos,int nRadius,int Lnum)491 void DoLighting(int nXPos, int nYPos, int nRadius, int Lnum)
492 {
493 	int x, y, v, xoff, yoff, mult, radius_block;
494 	int min_x, max_x, min_y, max_y;
495 	int dist_x, dist_y, light_x, light_y, block_x, block_y, temp_x, temp_y;
496 
497 	xoff = 0;
498 	yoff = 0;
499 	light_x = 0;
500 	light_y = 0;
501 	block_x = 0;
502 	block_y = 0;
503 
504 	if (Lnum >= 0) {
505 		xoff = LightList[Lnum]._xoff;
506 		yoff = LightList[Lnum]._yoff;
507 		if (xoff < 0) {
508 			xoff += 8;
509 			nXPos--;
510 		}
511 		if (yoff < 0) {
512 			yoff += 8;
513 			nYPos--;
514 		}
515 	}
516 
517 	dist_x = xoff;
518 	dist_y = yoff;
519 
520 	if (nXPos - 15 < 0) {
521 		min_x = nXPos + 1;
522 	} else {
523 		min_x = 15;
524 	}
525 	if (nXPos + 15 > MAXDUNX) {
526 		max_x = MAXDUNX - nXPos;
527 	} else {
528 		max_x = 15;
529 	}
530 	if (nYPos - 15 < 0) {
531 		min_y = nYPos + 1;
532 	} else {
533 		min_y = 15;
534 	}
535 	if (nYPos + 15 > MAXDUNY) {
536 		max_y = MAXDUNY - nYPos;
537 	} else {
538 		max_y = 15;
539 	}
540 
541 	if (nXPos >= 0 && nXPos < MAXDUNX && nYPos >= 0 && nYPos < MAXDUNY) {
542 		if (currlevel < 17) {
543 			SetLight(nXPos, nYPos, 0);
544 		} else if (GetLight(nXPos, nYPos) > lightradius[nRadius][0]) {
545 			SetLight(nXPos, nYPos, lightradius[nRadius][0]);
546 		}
547 	}
548 
549 	mult = xoff + 8 * yoff;
550 	for (y = 0; y < min_y; y++) {
551 		for (x = 1; x < max_x; x++) {
552 			radius_block = lightblock[mult][y][x];
553 			if (radius_block < 128) {
554 				temp_x = nXPos + x;
555 				temp_y = nYPos + y;
556 				v = lightradius[nRadius][radius_block];
557 				if (temp_x >= 0 && temp_x < MAXDUNX && temp_y >= 0 && temp_y < MAXDUNY)
558 					if (v < GetLight(temp_x, temp_y))
559 						SetLight(temp_x, temp_y, v);
560 			}
561 		}
562 	}
563 	RotateRadius(&xoff, &yoff, &dist_x, &dist_y, &light_x, &light_y, &block_x, &block_y);
564 	mult = xoff + 8 * yoff;
565 	for (y = 0; y < max_y; y++) {
566 		for (x = 1; x < max_x; x++) {
567 			radius_block = lightblock[mult][y + block_y][x + block_x];
568 			if (radius_block < 128) {
569 				temp_x = nXPos + y;
570 				temp_y = nYPos - x;
571 				v = lightradius[nRadius][radius_block];
572 				if (temp_x >= 0 && temp_x < MAXDUNX && temp_y >= 0 && temp_y < MAXDUNY)
573 					if (v < GetLight(temp_x, temp_y))
574 						SetLight(temp_x, temp_y, v);
575 			}
576 		}
577 	}
578 	RotateRadius(&xoff, &yoff, &dist_x, &dist_y, &light_x, &light_y, &block_x, &block_y);
579 	mult = xoff + 8 * yoff;
580 	for (y = 0; y < max_y; y++) {
581 		for (x = 1; x < min_x; x++) {
582 			radius_block = lightblock[mult][y + block_y][x + block_x];
583 			if (radius_block < 128) {
584 				temp_x = nXPos - x;
585 				temp_y = nYPos - y;
586 				v = lightradius[nRadius][radius_block];
587 				if (temp_x >= 0 && temp_x < MAXDUNX && temp_y >= 0 && temp_y < MAXDUNY)
588 					if (v < GetLight(temp_x, temp_y))
589 						SetLight(temp_x, temp_y, v);
590 			}
591 		}
592 	}
593 	RotateRadius(&xoff, &yoff, &dist_x, &dist_y, &light_x, &light_y, &block_x, &block_y);
594 	mult = xoff + 8 * yoff;
595 	for (y = 0; y < min_y; y++) {
596 		for (x = 1; x < min_x; x++) {
597 			radius_block = lightblock[mult][y + block_y][x + block_x];
598 			if (radius_block < 128) {
599 				temp_x = nXPos - y;
600 				temp_y = nYPos + x;
601 				v = lightradius[nRadius][radius_block];
602 				if (temp_x >= 0 && temp_x < MAXDUNX && temp_y >= 0 && temp_y < MAXDUNY)
603 					if (v < GetLight(temp_x, temp_y))
604 						SetLight(temp_x, temp_y, v);
605 			}
606 		}
607 	}
608 }
609 
DoUnLight(int nXPos,int nYPos,int nRadius)610 void DoUnLight(int nXPos, int nYPos, int nRadius)
611 {
612 	int x, y, min_x, min_y, max_x, max_y;
613 
614 	nRadius++;
615 	min_y = nYPos - nRadius;
616 	max_y = nYPos + nRadius;
617 	min_x = nXPos - nRadius;
618 	max_x = nXPos + nRadius;
619 
620 	if (min_y < 0) {
621 		min_y = 0;
622 	}
623 	if (max_y > MAXDUNY) {
624 		max_y = MAXDUNY;
625 	}
626 	if (min_x < 0) {
627 		min_x = 0;
628 	}
629 	if (max_x > MAXDUNX) {
630 		max_x = MAXDUNX;
631 	}
632 
633 	for (y = min_y; y < max_y; y++) {
634 		for (x = min_x; x < max_x; x++) {
635 			if (x >= 0 && x < MAXDUNX && y >= 0 && y < MAXDUNY)
636 				dLight[x][y] = dPreLight[x][y];
637 		}
638 	}
639 }
640 
DoUnVision(int nXPos,int nYPos,int nRadius)641 void DoUnVision(int nXPos, int nYPos, int nRadius)
642 {
643 	int i, j, x1, y1, x2, y2;
644 
645 	nRadius++;
646 	nRadius++; // increasing the radius even further here prevents leaving stray vision tiles behind and doesn't seem to affect monster AI - applying new vision happens in the same tick
647 	y1 = nYPos - nRadius;
648 	y2 = nYPos + nRadius;
649 	x1 = nXPos - nRadius;
650 	x2 = nXPos + nRadius;
651 
652 	if (y1 < 0) {
653 		y1 = 0;
654 	}
655 	if (y2 > MAXDUNY) {
656 		y2 = MAXDUNY;
657 	}
658 	if (x1 < 0) {
659 		x1 = 0;
660 	}
661 	if (x2 > MAXDUNX) {
662 		x2 = MAXDUNX;
663 	}
664 
665 	for (i = x1; i < x2; i++) {
666 		for (j = y1; j < y2; j++) {
667 			dFlags[i][j] &= ~(BFLAG_VISIBLE | BFLAG_LIT);
668 		}
669 	}
670 }
671 
DoVision(int nXPos,int nYPos,int nRadius,BOOL doautomap,BOOL visible)672 void DoVision(int nXPos, int nYPos, int nRadius, BOOL doautomap, BOOL visible)
673 {
674 	BOOL nBlockerFlag;
675 	int nCrawlX, nCrawlY, nLineLen, nTrans;
676 	int j, k, v, x1adj, x2adj, y1adj, y2adj;
677 
678 	if (nXPos >= 0 && nXPos <= MAXDUNX && nYPos >= 0 && nYPos <= MAXDUNY) {
679 		if (doautomap) {
680 			if (dFlags[nXPos][nYPos] >= 0) {
681 				SetAutomapView(nXPos, nXPos);
682 			}
683 			dFlags[nXPos][nYPos] |= BFLAG_EXPLORED;
684 		}
685 		if (visible) {
686 			dFlags[nXPos][nYPos] |= BFLAG_LIT;
687 		}
688 		dFlags[nXPos][nYPos] |= BFLAG_VISIBLE;
689 	}
690 
691 	for (v = 0; v < 4; v++) {
692 		for (j = 0; j < 23; j++) {
693 			nBlockerFlag = FALSE;
694 			nLineLen = 2 * (nRadius - RadiusAdj[j]);
695 			for (k = 0; k < nLineLen && !nBlockerFlag; k += 2) {
696 				x1adj = 0;
697 				x2adj = 0;
698 				y1adj = 0;
699 				y2adj = 0;
700 				switch (v) {
701 				case 0:
702 					nCrawlX = nXPos + vCrawlTable[j][k];
703 					nCrawlY = nYPos + vCrawlTable[j][k + 1];
704 					if (vCrawlTable[j][k] > 0 && vCrawlTable[j][k + 1] > 0) {
705 						x1adj = -1;
706 						y2adj = -1;
707 					}
708 					break;
709 				case 1:
710 					nCrawlX = nXPos - vCrawlTable[j][k];
711 					nCrawlY = nYPos - vCrawlTable[j][k + 1];
712 					if (vCrawlTable[j][k] > 0 && vCrawlTable[j][k + 1] > 0) {
713 						y1adj = 1;
714 						x2adj = 1;
715 					}
716 					break;
717 				case 2:
718 					nCrawlX = nXPos + vCrawlTable[j][k];
719 					nCrawlY = nYPos - vCrawlTable[j][k + 1];
720 					if (vCrawlTable[j][k] > 0 && vCrawlTable[j][k + 1] > 0) {
721 						x1adj = -1;
722 						y2adj = 1;
723 					}
724 					break;
725 				case 3:
726 					nCrawlX = nXPos - vCrawlTable[j][k];
727 					nCrawlY = nYPos + vCrawlTable[j][k + 1];
728 					if (vCrawlTable[j][k] > 0 && vCrawlTable[j][k + 1] > 0) {
729 						y1adj = -1;
730 						x2adj = 1;
731 					}
732 					break;
733 				}
734 				if (nCrawlX >= 0 && nCrawlX < MAXDUNX && nCrawlY >= 0 && nCrawlY < MAXDUNY) {
735 					nBlockerFlag = nBlockTable[dPiece[nCrawlX][nCrawlY]];
736 					if ((x1adj + nCrawlX >= 0 && x1adj + nCrawlX < MAXDUNX && y1adj + nCrawlY >= 0 && y1adj + nCrawlY < MAXDUNY
737 					        && !nBlockTable[dPiece[x1adj + nCrawlX][y1adj + nCrawlY]])
738 					    || (x2adj + nCrawlX >= 0 && x2adj + nCrawlX < MAXDUNX && y2adj + nCrawlY >= 0 && y2adj + nCrawlY < MAXDUNY
739 					        && !nBlockTable[dPiece[x2adj + nCrawlX][y2adj + nCrawlY]])) {
740 						if (doautomap) {
741 							if (dFlags[nCrawlX][nCrawlY] >= 0) {
742 								SetAutomapView(nCrawlX, nCrawlY);
743 							}
744 							dFlags[nCrawlX][nCrawlY] |= BFLAG_EXPLORED;
745 						}
746 						if (visible) {
747 							dFlags[nCrawlX][nCrawlY] |= BFLAG_LIT;
748 						}
749 						dFlags[nCrawlX][nCrawlY] |= BFLAG_VISIBLE;
750 						if (!nBlockerFlag) {
751 							nTrans = dTransVal[nCrawlX][nCrawlY];
752 							if (nTrans != 0) {
753 								TransList[nTrans] = TRUE;
754 							}
755 						}
756 					}
757 				}
758 			}
759 		}
760 	}
761 }
762 
FreeLightTable()763 void FreeLightTable()
764 {
765 	MemFreeDbg(pLightTbl);
766 }
767 
InitLightTable()768 void InitLightTable()
769 {
770 	assert(!pLightTbl);
771 	pLightTbl = DiabloAllocPtr(LIGHTSIZE);
772 }
773 
MakeLightTable()774 void MakeLightTable()
775 {
776 	int i, j, k, l, lights, shade, l1, l2, cnt, rem, div;
777 	double fs, fa;
778 	BYTE col, max;
779 	BYTE *tbl, *trn;
780 	BYTE blood[16];
781 
782 	tbl = pLightTbl;
783 	shade = 0;
784 
785 	if (light4flag) {
786 		lights = 3;
787 	} else {
788 		lights = 15;
789 	}
790 
791 	for (i = 0; i < lights; i++) {
792 		*tbl++ = 0;
793 		for (j = 0; j < 8; j++) {
794 			col = 16 * j + shade;
795 			max = 16 * j + 15;
796 			for (k = 0; k < 16; k++) {
797 				if (k != 0 || j != 0) {
798 					*tbl++ = col;
799 				}
800 				if (col < max) {
801 					col++;
802 				} else {
803 					max = 0;
804 					col = 0;
805 				}
806 			}
807 		}
808 		for (j = 16; j < 20; j++) {
809 			col = 8 * j + (shade >> 1);
810 			max = 8 * j + 7;
811 			for (k = 0; k < 8; k++) {
812 				*tbl++ = col;
813 				if (col < max) {
814 					col++;
815 				} else {
816 					max = 0;
817 					col = 0;
818 				}
819 			}
820 		}
821 		for (j = 10; j < 16; j++) {
822 			col = 16 * j + shade;
823 			max = 16 * j + 15;
824 			for (k = 0; k < 16; k++) {
825 				*tbl++ = col;
826 				if (col < max) {
827 					col++;
828 				} else {
829 					max = 0;
830 					col = 0;
831 				}
832 				if (col == 255) {
833 					max = 0;
834 					col = 0;
835 				}
836 			}
837 		}
838 		if (light4flag) {
839 			shade += 5;
840 		} else {
841 			shade++;
842 		}
843 	}
844 
845 	for (i = 0; i < 256; i++) {
846 		*tbl++ = 0;
847 	}
848 
849 	if (leveltype == DTYPE_HELL) {
850 		tbl = pLightTbl;
851 		for (i = 0; i < lights; i++) {
852 			l1 = lights - i;
853 			l2 = l1;
854 			div = lights / l1;
855 			rem = lights % l1;
856 			cnt = 0;
857 			blood[0] = 0;
858 			col = 1;
859 			for (j = 1; j < 16; j++) {
860 				blood[j] = col;
861 				l2 += rem;
862 				if (l2 > l1 && j < 15) {
863 					j++;
864 					blood[j] = col;
865 					l2 -= l1;
866 				}
867 				cnt++;
868 				if (cnt == div) {
869 					col++;
870 					cnt = 0;
871 				}
872 			}
873 			*tbl++ = 0;
874 			for (j = 1; j <= 15; j++) {
875 				*tbl++ = blood[j];
876 			}
877 			for (j = 15; j > 0; j--) {
878 				*tbl++ = blood[j];
879 			}
880 			*tbl++ = 1;
881 			tbl += 224;
882 		}
883 		*tbl++ = 0;
884 		for (j = 0; j < 31; j++) {
885 			*tbl++ = 1;
886 		}
887 		tbl += 224;
888 	}
889 	if (currlevel >= 17) {
890 		tbl = pLightTbl;
891 		for (i = 0; i < lights; i++) {
892 			*tbl++ = 0;
893 			for (j = 1; j < 16; j++)
894 				*tbl++ = j;
895 			tbl += 240;
896 		}
897 		*tbl++ = 0;
898 		for (j = 1; j < 16; j++)
899 			*tbl++ = 1;
900 		tbl += 240;
901 	}
902 
903 	trn = LoadFileInMem("PlrGFX\\Infra.TRN", NULL);
904 	for (i = 0; i < 256; i++) {
905 		*tbl++ = trn[i];
906 	}
907 	mem_free_dbg(trn);
908 
909 	trn = LoadFileInMem("PlrGFX\\Stone.TRN", NULL);
910 	for (i = 0; i < 256; i++) {
911 		*tbl++ = trn[i];
912 	}
913 	mem_free_dbg(trn);
914 
915 	for (i = 0; i < 8; i++) {
916 		for (col = 226; col < 239; col++) {
917 			if (i != 0 || col != 226) {
918 				*tbl++ = col;
919 			} else {
920 				*tbl++ = 0;
921 			}
922 		}
923 		*tbl++ = 0;
924 		*tbl++ = 0;
925 		*tbl++ = 0;
926 	}
927 	for (i = 0; i < 4; i++) {
928 		col = 224;
929 		for (j = 224; j < 239; j += 2) {
930 			*tbl++ = col;
931 			col += 2;
932 		}
933 	}
934 	for (i = 0; i < 6; i++) {
935 		for (col = 224; col < 239; col++) {
936 			*tbl++ = col;
937 		}
938 		*tbl++ = 0;
939 	}
940 
941 	for (j = 0; j < 16; j++) {
942 		for (i = 0; i < 128; i++) {
943 			if (i > (j + 1) * 8) {
944 				lightradius[j][i] = 15;
945 			} else {
946 				fs = (double)15 * i / ((double)8 * (j + 1));
947 				lightradius[j][i] = (BYTE)(fs + 0.5);
948 			}
949 		}
950 	}
951 
952 	if (currlevel >= 17) {
953 		for (j = 0; j < 16; j++) {
954 			fa = (sqrt((double)(16 - j))) / 128;
955 			fa *= fa;
956 			for (i = 0; i < 128; i++) {
957 				lightradius[15 - j][i] = 15 - (BYTE)(fa * (double)((128 - i) * (128 - i)));
958 				if (lightradius[15 - j][i] > 15)
959 					lightradius[15 - j][i] = 0;
960 				lightradius[15 - j][i] = lightradius[15 - j][i] - (BYTE)((15 - j) / 2);
961 				if (lightradius[15 - j][i] > 15)
962 					lightradius[15 - j][i] = 0;
963 			}
964 		}
965 	}
966 	for (j = 0; j < 8; j++) {
967 		for (i = 0; i < 8; i++) {
968 			for (k = 0; k < 16; k++) {
969 				for (l = 0; l < 16; l++) {
970 					fs = (BYTE)sqrt((double)(8 * l - j) * (8 * l - j) + (8 * k - i) * (8 * k - i));
971 					fs += fs < 0 ? -0.5 : 0.5;
972 
973 					lightblock[j * 8 + i][k][l] = fs;
974 				}
975 			}
976 		}
977 	}
978 }
979 
980 #ifdef _DEBUG
ToggleLighting()981 void ToggleLighting()
982 {
983 	int i;
984 
985 	lightflag ^= TRUE;
986 
987 	if (lightflag) {
988 		memset(dLight, 0, sizeof(dLight));
989 	} else {
990 		memcpy(dLight, dPreLight, sizeof(dLight));
991 		for (i = 0; i < MAX_PLRS; i++) {
992 			if (plr[i].plractive && plr[i].plrlevel == currlevel) {
993 				DoLighting(plr[i]._px, plr[i]._py, plr[i]._pLightRad, -1);
994 			}
995 		}
996 	}
997 }
998 #endif
999 
InitLightMax()1000 void InitLightMax()
1001 {
1002 	if (light4flag) {
1003 		lightmax = 3;
1004 	} else {
1005 		lightmax = 15;
1006 	}
1007 }
1008 
InitLighting()1009 void InitLighting()
1010 {
1011 	int i;
1012 
1013 	numlights = 0;
1014 	dolighting = FALSE;
1015 	lightflag = FALSE;
1016 
1017 	for (i = 0; i < MAXLIGHTS; i++) {
1018 		lightactive[i] = i;
1019 	}
1020 }
1021 
AddLight(int x,int y,int r)1022 int AddLight(int x, int y, int r)
1023 {
1024 	int lid;
1025 
1026 	if (lightflag) {
1027 		return NO_LIGHT;
1028 	}
1029 
1030 	lid = NO_LIGHT;
1031 
1032 	if (numlights < MAXLIGHTS) {
1033 		lid = lightactive[numlights++];
1034 		LightList[lid]._lx = x;
1035 		LightList[lid]._ly = y;
1036 		LightList[lid]._lradius = r;
1037 		LightList[lid]._xoff = 0;
1038 		LightList[lid]._yoff = 0;
1039 		LightList[lid]._ldel = FALSE;
1040 		LightList[lid]._lunflag = FALSE;
1041 		dolighting = TRUE;
1042 	}
1043 
1044 	return lid;
1045 }
1046 
AddUnLight(int i)1047 void AddUnLight(int i)
1048 {
1049 	if (lightflag || i == NO_LIGHT) {
1050 		return;
1051 	}
1052 
1053 	LightList[i]._ldel = TRUE;
1054 	dolighting = TRUE;
1055 }
1056 
ChangeLightRadius(int i,int r)1057 void ChangeLightRadius(int i, int r)
1058 {
1059 	if (lightflag || i == NO_LIGHT) {
1060 		return;
1061 	}
1062 
1063 	LightList[i]._lunflag = TRUE;
1064 	LightList[i]._lunx = LightList[i]._lx;
1065 	LightList[i]._luny = LightList[i]._ly;
1066 	LightList[i]._lunr = LightList[i]._lradius;
1067 	LightList[i]._lradius = r;
1068 	dolighting = TRUE;
1069 }
1070 
ChangeLightXY(int i,int x,int y)1071 void ChangeLightXY(int i, int x, int y)
1072 {
1073 	if (lightflag || i == NO_LIGHT) {
1074 		return;
1075 	}
1076 
1077 	LightList[i]._lunflag = TRUE;
1078 	LightList[i]._lunx = LightList[i]._lx;
1079 	LightList[i]._luny = LightList[i]._ly;
1080 	LightList[i]._lunr = LightList[i]._lradius;
1081 	LightList[i]._lx = x;
1082 	LightList[i]._ly = y;
1083 	dolighting = TRUE;
1084 }
1085 
ChangeLightOff(int i,int x,int y)1086 void ChangeLightOff(int i, int x, int y)
1087 {
1088 	if (lightflag || i == NO_LIGHT) {
1089 		return;
1090 	}
1091 
1092 	LightList[i]._lunflag = TRUE;
1093 	LightList[i]._lunx = LightList[i]._lx;
1094 	LightList[i]._luny = LightList[i]._ly;
1095 	LightList[i]._lunr = LightList[i]._lradius;
1096 	LightList[i]._xoff = x;
1097 	LightList[i]._yoff = y;
1098 	dolighting = TRUE;
1099 }
1100 
ChangeLight(int i,int x,int y,int r)1101 void ChangeLight(int i, int x, int y, int r)
1102 {
1103 	if (lightflag || i == NO_LIGHT) {
1104 		return;
1105 	}
1106 
1107 	LightList[i]._lunflag = TRUE;
1108 	LightList[i]._lunx = LightList[i]._lx;
1109 	LightList[i]._luny = LightList[i]._ly;
1110 	LightList[i]._lunr = LightList[i]._lradius;
1111 	LightList[i]._lx = x;
1112 	LightList[i]._ly = y;
1113 	LightList[i]._lradius = r;
1114 	dolighting = TRUE;
1115 }
1116 
ProcessLightList()1117 void ProcessLightList()
1118 {
1119 	int i, j;
1120 	BYTE temp;
1121 
1122 	if (lightflag) {
1123 		return;
1124 	}
1125 
1126 	if (dolighting) {
1127 		for (i = 0; i < numlights; i++) {
1128 			j = lightactive[i];
1129 			if (LightList[j]._ldel) {
1130 				DoUnLight(LightList[j]._lx, LightList[j]._ly, LightList[j]._lradius);
1131 			}
1132 			if (LightList[j]._lunflag) {
1133 				DoUnLight(LightList[j]._lunx, LightList[j]._luny, LightList[j]._lunr);
1134 				LightList[j]._lunflag = FALSE;
1135 			}
1136 		}
1137 		for (i = 0; i < numlights; i++) {
1138 			j = lightactive[i];
1139 			if (!LightList[j]._ldel) {
1140 				DoLighting(LightList[j]._lx, LightList[j]._ly, LightList[j]._lradius, j);
1141 			}
1142 		}
1143 		i = 0;
1144 		while (i < numlights) {
1145 			if (LightList[lightactive[i]]._ldel) {
1146 				numlights--;
1147 				temp = lightactive[numlights];
1148 				lightactive[numlights] = lightactive[i];
1149 				lightactive[i] = temp;
1150 			} else {
1151 				i++;
1152 			}
1153 		}
1154 	}
1155 
1156 	dolighting = FALSE;
1157 }
1158 
SavePreLighting()1159 void SavePreLighting()
1160 {
1161 	memcpy(dPreLight, dLight, sizeof(dPreLight));
1162 }
1163 
InitVision()1164 void InitVision()
1165 {
1166 	int i;
1167 
1168 	numvision = 0;
1169 	dovision = FALSE;
1170 	visionid = 1;
1171 
1172 	for (i = 0; i < TransVal; i++) {
1173 		TransList[i] = FALSE;
1174 	}
1175 }
1176 
AddVision(int x,int y,int r,BOOL mine)1177 int AddVision(int x, int y, int r, BOOL mine)
1178 {
1179 	int vid = -1; // BUGFIX: if numvision >= MAXVISION behavior is undefined (fixed)
1180 
1181 	if (numvision < MAXVISION) {
1182 		VisionList[numvision]._lx = x;
1183 		VisionList[numvision]._ly = y;
1184 		VisionList[numvision]._lradius = r;
1185 		vid = visionid++;
1186 		VisionList[numvision]._lid = vid;
1187 		VisionList[numvision]._ldel = FALSE;
1188 		VisionList[numvision]._lunflag = FALSE;
1189 		VisionList[numvision]._lflags = mine != 0;
1190 		numvision++;
1191 		dovision = TRUE;
1192 	}
1193 
1194 	return vid;
1195 }
1196 
ChangeVisionRadius(int id,int r)1197 void ChangeVisionRadius(int id, int r)
1198 {
1199 	int i;
1200 
1201 	for (i = 0; i < numvision; i++) {
1202 		if (VisionList[i]._lid == id) {
1203 			VisionList[i]._lunflag = TRUE;
1204 			VisionList[i]._lunx = VisionList[i]._lx;
1205 			VisionList[i]._luny = VisionList[i]._ly;
1206 			VisionList[i]._lunr = VisionList[i]._lradius;
1207 			VisionList[i]._lradius = r;
1208 			dovision = TRUE;
1209 		}
1210 	}
1211 }
1212 
ChangeVisionXY(int id,int x,int y)1213 void ChangeVisionXY(int id, int x, int y)
1214 {
1215 	int i;
1216 
1217 	for (i = 0; i < numvision; i++) {
1218 		if (VisionList[i]._lid == id) {
1219 			VisionList[i]._lunflag = TRUE;
1220 			VisionList[i]._lunx = VisionList[i]._lx;
1221 			VisionList[i]._luny = VisionList[i]._ly;
1222 			VisionList[i]._lunr = VisionList[i]._lradius;
1223 			VisionList[i]._lx = x;
1224 			VisionList[i]._ly = y;
1225 			dovision = TRUE;
1226 		}
1227 	}
1228 }
1229 
ProcessVisionList()1230 void ProcessVisionList()
1231 {
1232 	int i;
1233 	BOOL delflag;
1234 
1235 	if (dovision) {
1236 		for (i = 0; i < numvision; i++) {
1237 			if (VisionList[i]._ldel) {
1238 				DoUnVision(VisionList[i]._lx, VisionList[i]._ly, VisionList[i]._lradius);
1239 			}
1240 			if (VisionList[i]._lunflag) {
1241 				DoUnVision(VisionList[i]._lunx, VisionList[i]._luny, VisionList[i]._lunr);
1242 				VisionList[i]._lunflag = FALSE;
1243 			}
1244 		}
1245 		for (i = 0; i < TransVal; i++) {
1246 			TransList[i] = FALSE;
1247 		}
1248 		for (i = 0; i < numvision; i++) {
1249 			if (!VisionList[i]._ldel) {
1250 				DoVision(
1251 				    VisionList[i]._lx,
1252 				    VisionList[i]._ly,
1253 				    VisionList[i]._lradius,
1254 				    VisionList[i]._lflags,
1255 				    VisionList[i]._lflags);
1256 			}
1257 		}
1258 		do {
1259 			delflag = FALSE;
1260 			for (i = 0; i < numvision; i++) {
1261 				if (VisionList[i]._ldel) {
1262 					numvision--;
1263 					if (numvision > 0 && i != numvision) {
1264 						VisionList[i] = VisionList[numvision];
1265 					}
1266 					delflag = TRUE;
1267 				}
1268 			}
1269 		} while (delflag);
1270 	}
1271 
1272 	dovision = FALSE;
1273 }
1274 
lighting_color_cycling()1275 void lighting_color_cycling()
1276 {
1277 	int i, j, l;
1278 	BYTE col;
1279 	BYTE *tbl;
1280 
1281 	l = light4flag ? 4 : 16;
1282 
1283 	if (leveltype != DTYPE_HELL) {
1284 		return;
1285 	}
1286 
1287 	tbl = pLightTbl;
1288 
1289 	for (j = 0; j < l; j++) {
1290 		tbl++;
1291 		col = *tbl;
1292 		for (i = 0; i < 30; i++) {
1293 			tbl[0] = tbl[1];
1294 			tbl++;
1295 		}
1296 		*tbl = col;
1297 		tbl += 225;
1298 	}
1299 }
1300 
1301 DEVILUTION_END_NAMESPACE
1302