File: physical.h

package info (click to toggle)
xevil 2.02r2-8
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 7,980 kB
  • ctags: 8,004
  • sloc: cpp: 47,789; makefile: 224; csh: 4
file content (3439 lines) | stat: -rw-r--r-- 96,191 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
/* 
 * XEvil(TM) Copyright (C) 1994,2000 Steve Hardt and Michael Judge
 * http://www.xevil.com
 * satan@xevil.com
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program, the file "gpl.txt"; if not, write to the Free
 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA, or visit http://www.gnu.org.
 */

// "physical.h"  
// Interior nodes of the physical object tree.  These classes
// are never instantiated.


#ifndef PHYSICAL_H
#define PHYSICAL_H

#if X11
	#ifndef NO_PRAGMAS
	#pragma interface
	#endif
#endif

// Include Files
#include "utils.h"
#include "coord.h"
#include "xdata.h"
#include "area.h"
#include "world.h"
#include "id.h"
#include "intel.h"
#include "locator.h"
#include "streams.h"


// Defines
#define PH_WEAPONS_MAX 10
#define PH_ITEMS_MAX 20
//#define PH_AMMO_UNLIMITED  in coord.h
#define PH_GRAVITY 2
#define PH_PUSH_OFF 3
// PH_AUTO_GEN means generate pixmap bits from another direction 
// via Transfrom2D.
// Assuming that no pixmap bits are 0xffffffff.
// Safe on Windows because resource symbols are a max of 65K.
#define PH_AUTO_GEN ((CMN_BITS_ID)-1)

// Default time to be invisible for cloaks, or for invisible client object
// if no new updates come in.
#define PH_INVISIBLE_TIME 1500  // One minute.



////////////////////////////////////////////////////////////////////////////
//----------------------- MACROS FOR STREAM IO ---------------------------//

// Add a ';' after this.
#define DECLARE_INTERNAL_NODE_IO(CLASSNAME) \
  CLASSNAME(InStreamP,const CLASSNAME ## Context &, \
            CLASSNAME ## Xdata &, \
            WorldP, \
            LocatorP); \
  virtual void update_from_stream(InStreamP in); \
  void _update_from_stream(InStreamP); \
  virtual int get_write_length(); \
  virtual void write(OutStreamP)

#define DECLARE_ROOT_NODE_IO(CLASSNAME) \
  CLASSNAME(InStreamP,const CLASSNAME ## Context &,WorldP,LocatorP); \
  virtual void update_from_stream(InStreamP); \
  virtual int get_write_length(); \
  virtual void write(OutStreamP)

#define DECLARE_NULL_INTERNAL_NODE_IO(CLASSNAME) \
  CLASSNAME(InStreamP,const CLASSNAME ## Context &, \
            CLASSNAME ## Xdata &, \
            WorldP,LocatorP)

// Appropriate Context will be named "cx" and Xdata named "x_data".
#define CONSTRUCTOR_INTERNAL_NODE_IO(CLASSNAME,PARENT,parent) \
   CLASSNAME::CLASSNAME(InStreamP in,const CLASSNAME ## Context &cx, \
                         CLASSNAME ## Xdata &x_data, \
                         WorldP w,LocatorP l) \
   : PARENT(in,cx. parent ## Context,x_data,w,l) 

// Used by internal nodes and leaves.
#define DEFINE_UPDATE_FROM_STREAM(CLASSNAME,PARENT) \
  void CLASSNAME::update_from_stream(InStreamP in) { \
    PARENT::update_from_stream(in); \
    _update_from_stream(in); \
  }

#define DECLARE_ABILITY_IO(CLASSNAME) \
  CLASSNAME(InStreamP,CreatureP,const CLASSNAME ## Context &,CLASSNAME ## Xdata &); \
  void update_from_stream(InStreamP in); \
  int get_write_length(); \
  void write(OutStreamP); \
  static AbilityP create_from_stream(InStreamP,CreatureP)  

#define DECLARE_NULL_ABILITY_IO(CLASSNAME) \
  CLASSNAME(InStreamP,CreatureP,const CLASSNAME ## Context &,CLASSNAME ## Xdata &); \
  static AbilityP create_from_stream(InStreamP,CreatureP)


#if 0
// Hack to shut the fucking compiler up about unused variables.
#define ABILITY_IO_HACK \
  void *dummy; \
  dummy = (void *)in; \
  dummy = (void *)&cx; \
  dummy = (void *)&x_data;

// Define several functions.
#define DEFINE_NULL_PRE_LEAF_IO(CLASSNAME) \
  void CLASSNAME::update_from_stream(InStreamP) { \
  } \
  int CLASSNAME::get_write_length() { \
    return 0; \
  } \
  void CLASSNAME::write(OutStreamP) { \
  }
#endif

#define DECLARE_NULL_LEAF_IO(CLASSNAME) \
  CLASSNAME(InStreamP,WorldP,LocatorP); \
  static PhysicalP create_from_stream(InStreamP,WorldP,LocatorP)

#define DECLARE_LEAF_IO(CLASSNAME) \
  CLASSNAME(InStreamP,WorldP,LocatorP); \
  virtual void update_from_stream(InStreamP); \
  void _update_from_stream(InStreamP); \
  virtual int get_write_length(); \
  virtual void write(OutStreamP); \
  static PhysicalP create_from_stream(InStreamP,WorldP,LocatorP)

// Assumes the appropriate context is named "context".
#define CONSTRUCTOR_LEAF_IO(CLASSNAME,PARENT) \
  CLASSNAME::CLASSNAME(InStreamP in,WorldP w,LocatorP l) \
  : PARENT(in,context,xdata,w,l)

#define DEFINE_CREATE_FROM_STREAM(CLASSNAME) \
  PhysicalP CLASSNAME::create_from_stream(InStreamP in, \
                                          WorldP w,LocatorP l) { \
    PhysicalP p = new CLASSNAME(in,w,l); \
    if (p->creation_ok() && in->alive()) { \
      return p; \
    } \
    else { \
      delete p; \
      return NULL; \
    } \
  } 

// Note that defaultContext and defaultXdata are static to CLASSNAME.
#define DEFINE_CREATE_ABILITY_FROM_STREAM(CLASSNAME) \
AbilityP CLASSNAME::create_from_stream(InStreamP in,CreatureP creat) { \
  AbilityP ret = new CLASSNAME(in,creat,defaultContext,defaultXdata); \
  assert(ret); \
  return ret; \
}

#if 0
#define DECLARE_CREATURE_IO(CLASSNAME) \
  CLASSNAME(InStreamP,WorldP,LocatorP); \
  virtual void update_from_stream(InStreamP); \
  virtual int get_write_length(); \
  virtual void write(OutStreamP); \
  static PhysicalP create_from_stream(InStreamP,WorldP,LocatorP)
#endif

#define DECLARE_NULL_CREATURE_IO(CLASSNAME) \
  CLASSNAME(InStreamP, WorldP,LocatorP); \
  static PhysicalP create_from_stream(InStreamP,WorldP,LocatorP)


//--------------------------- END IO MACROS ------------------------------//
////////////////////////////////////////////////////////////////////////////



enum PHsig {PH_NO_SIG, PH_NOT_SET, PH_ID_CHANGED};



class Protection;
typedef Protection *ProtectionP;
class Modifier;
typedef Modifier *ModifierP;
class Ability;
typedef Ability *AbilityP;
class Holder;
typedef Holder *HolderP;
class Locomotion;
typedef Locomotion *LocomotionP;
class Composite;
typedef Composite *CompositeP;



////////// Physical
/* Physical is the parent class of all physical objects. */

/* PhysicalContext plays a double role.  Like all the other "contexts", 
   MovingContext, CreatureContext, etc., it is a place to specify paramaters
   for a specific class.  E.g. if you look at the PhysicalContext in 
   ninja.bitmaps you will see where the mass, max health, etc, for a Ninja is
   specified.
   
   But, it also plays a role for the Object Locator.  All classes of Physical
   objects (not just the objects, but the classes) are registered with
   Locator::register_context().  So, the Locator has a list of all the classes
   in the game.  For example, if the Locator wanted to create one of each type
   of object, it could just go through the list of registed classes and 
   call the PhysicalContext->create() method on each.
   Only PhysicalContext is used for this extra functionality.  MovingContext,
   ShotContext, etc, only play the first role.
   */
struct PhysicalContext {
  Health health;
  Mass mass;
  ClassId classId;
  const char *className;


  /* Global fields for the Game as a whole. */

  // Can a Transmogifier turn something into this class of object.
  Boolean transmogifyTarget;
  // Can objects of this class use doppelgangers.  E.g. we don't want 
  // FireDemons to start duplicating themselves.  This is independent of 
  // whether this class is derived from class User.  
  Boolean doppelUser;
  // Can a Human player start out as an object of this class.
  Boolean potentialHuman;
  // Can an Enemy(Machine) player start out as an object of this class.
  Boolean potentialEnemy;
#if 0  // This needs to be added for Game::intel_options_for()
  // Only meaningful if potentialEnemy is True.
  // If an enemy is created of this class, will it receive a psychotic Intel.
  Boolean enemyIsPsychotic;
#endif
  // This gives the likelihood that an enemy will
  // be created of this class.  For reference Ninja is 3.  E.g. if 
  // enemyWeight is 1, then there will be one third as many of these objects
  // as there are Ninjas.
  // NOTE: This may be used even if potentialEnemy is False.  A Scenario may
  // specifically request a set of potential enemies, e.g. Seals.
  int enemyWeight;
  // Is this a weapon or item that can magically fall out of the sky.
  // Only one of potentialWeapon, potentialOtherItem should be True.
  Boolean potentialWeapon;
  Boolean potentialOtherItem;
  // If the Physical is a potential item or weapon, this gives a measure of
  // how many of the object will be created.  You can think of this as the 
  // "percent" of the World that is covered by the item/weapon.
  float objectWorldPercent;
  // If the Physical is a potential item or weapon, this gives the maximum
  // number of times the object will appear that level.  
  // 0 means infinity, i.e. no limit.
  int levelMaxTimes;
  // The maximum size of the Physical corresponding to this context.
  Size sizeMax;
  // A pointer to a function that creates an instance of the Physical 
  // corresponding to this context.
  PhysicalP (*create)(void *arg,WorldP w,LocatorP l,const Pos &pos);
  // Flags that determine what statistics will be printed out when XEvil is
  // exited.  You probably only want to set one of these, if any.
  // E.g. For Shot, we are interested in the number that were 
  // created (fired), so statsCreations would be True.  E.g. For MedKit, 
  // we care more about how many were used than how many were created, so we
  // set statsUses.  For Ninja, the most interesting thing is how many of 
  // got killed (and average lifespan), so we set statsDeath.  E.g. for Rock
  // we don't set any of them, (who cares about a rock).
  Boolean statsCreations;
  Boolean statsUses;
  Boolean statsDeaths;
  // Return the stats for the class.  This will be NULL if the class does not
  // have stats.  I.e. a NULL function, NOT a function that returns NULL.
  // This is non-NULL iff any of the stats{Creations,Uses,Deaths} flags
  // are set.
  // 
  // I could probably have put the actual Stats here instead of
  // every class having to have its own stats.  But, I really wanted to keep
  // all the "Contexts" constant, and Stats obviously have to change during
  // game play.
  Stats &(*get_stats)(void *arg);  // Not const anymore.
  // Argument passed to create() and get_stats().  NULL except for templates.
  void *arg;
  // A very poorly named function.  Multi-purpose graphics function for this 
  // class.  See Moving::init_x().
  void (*init_x)(Xvars &xvars,IXCommand command,void* arg);
  // Read in a new Physical from an InStream.  Return NULL if failure.
  PhysicalP (*create_from_stream)(InStreamP,WorldP,LocatorP);
  // If non-null, will return whether the given class derives from 
  // Item or Weapon.  Will also return a bitmap icon suitable for a 
  // status window (WIN32 only for now).
  // If null, the class is guaranteed not to be an Item or Weapon.
  void (*get_item_info)(Boolean &isItem,Boolean &isWeapon,CMN_BITS_ID &iconId);
  
//******* This needs to be added in, see Locator::draw_ticks()  ********/
  // Should always draw the tick marks on the edge of the screen for this 
  // Physical, e.g. Flag, Xit
//  Boolean alwaysDrawTicks;
};


class Physical {
public:
  Physical(const PhysicalContext &,WorldP,LocatorP);
  /* EFFECTS: Create a new, mapped physical with no Id with undefined area. */

  Physical();
  /* NOTE: Should never be called. */

  Boolean creation_ok() {return creationOk;}
  /* EFFECTS: Create physical by reading in from stream.  Use 
     Physical::creation_ok() to see if it was successfully read in. */

  DECLARE_ROOT_NODE_IO(Physical);
  void _update_from_stream(InStreamP,Boolean alreadyExists);
  /* NOTE: alreadyExists is used for checking consistency when
     updating an existing object from a stream. */
  
  virtual ~Physical();

  virtual const Area &get_area() = 0;

  virtual const Area &get_area_next() = 0;
  /* NOTE: Should only be used by the Locator. */

  Health get_health() {return health;}

  Health get_health_next() {return healthNext;}
  /* NOTE: Should only be used by the Locator to prepare for death.
     Somewhat of a hack. */

  virtual Health get_health_max();
  /* NOTE: Overridden in Creature. */

  Mass get_mass() {return mass;}
  virtual Vel get_vel();
  virtual Dir get_dir();

  ClassId get_class_id() {return pc->classId;}
  const char *get_class_name() {return pc->className;}

  virtual int get_drawing_level();

  const PhysicalContext *get_context() {return pc;}

  Boolean delete_me() {return deleteMe;}

  Boolean alive() {assert (health >= 0 || dieCalled); return health >= 0;}
  /* NOTE: Is publicly known that (health >= 0) <=> alive.  So this function is
   just for convenience. */

  Boolean die_called() 
//  {assert (healthNext < 0 || !dieCalled);  return dieCalled;}
    {return dieCalled;}
  /* EFFECTS: Returns whether die() has been called or not.  Not clocked. */

  /* Should only be used for abstract classes.  Actual classes can be tested
     for with get_class_id(). */
  virtual Boolean is_moving();
  virtual Boolean is_shot();
  virtual Boolean is_item(); 
  virtual Boolean is_shield();
  virtual Boolean is_bomb();
  virtual Boolean is_weapon();
  virtual Boolean is_cutter();
  virtual Boolean is_gun();
  virtual Boolean is_creature(); 
  virtual Boolean is_auto_use();
  virtual Boolean is_drugs();
  virtual Boolean is_liftable();


  virtual AbilityP get_ability(AbilityId);
  virtual HolderP get_holder();
  virtual LocomotionP get_locomotion();
  virtual CompositeP get_composite();
  /* NOTE: These are really only meaningful for Creature.  Provided here
     for convenience. */

  Boolean get_mapped() {return mapped;}

  virtual Boolean collidable();
  /* NOTE: This value never changes for an object. */

  const Acc *get_unit_accs() {return unitAccs;}
  const Vel *get_unit_vels() {return unitVels;}

  Id get_id() {return id;}

  PHsig get_id(Id &id);
  /* MODIFIES: id */
  /* EFFECTS: Set id to be the Id and return PH_NO_SIG if set.  Otherwise, 
     return PH_NOT_SET. */

  Id get_dont_collide() {return dontCollide;}
  /* EFFECTS: If there is another object that *this is not allowed to collide
     with, return it.  Otherwise return NULL; */

  CompositeId get_dont_collide_composite() {return dontCollideComposite;}
  /* NOTE: Return COMPOSITE_ID_NONE if the flag isn't set. */

  IntelP get_intel() {return intel;}
  /* NOTE: Can be NULL. */

  Boolean get_flash() {return !flashTimer.ready();}

  Boolean get_quiet_death() {return quietDeath;}

  virtual void get_followers(PtrList &list);
  /* EFFECTS: Fill list with all the follower objects of the Creature, e.g.
     Chainsaws, Shields.  list will be a list of PhysicalP. */
  /* NOTE: All mapped and unmapped followers. */
  /* NOTE: Call up the tree. */
  /* WARNING: Careful not to cache the results, as it is a list of PhysicalP,
     not of Id. */
  /* NOTE: Maybe we should be using PtrList::add_unique() instead of add() to
     fill the list. */

  virtual void follow(const Area &followeeArea,Dir followeeDir,
                      Boolean currentAndNext);
  /* EFFECTS: Follow the followee.  If currentAndNext is True, set current
   and next state, e.g. after reading from a stream.  If False, only set
   next state, e.g. normal clock(). */
  /* NOTE: Sure would be nice to have delegation to a IFollowable 
     interface. */

  NetDataP get_net_data();
  /* EFFECTS: Get the chuck of data specific to network play.  Not a copy,
   do not free results. */

  void set_command(ITcommand c) {command = c;}
  /* EFFECTS: Sets the command to be c, overrides any previous command 
     setting. */
  /* NOTE: command is not clocked. */

  virtual Boolean command_repeatable(ITcommand c);
  /* EFFECTS: Given the current state of the Physical, should c be allowed 
     to be sent repeatedly through set_command().  Or must there be a delay
     after the invocation of set_command(c).  Decide whether we can do key 
     repeat or not. */

  void set_id(const Id &id);
  /* REQUIRES: Id not already set. */
  /* EFFECTS: Set the Id to be id. */

  void set_dont_collide(const Id &other) {dontCollide = other;}
  /* EFFECTS: *this will not be allowed to collide with other.  Any previous 
     value will be overridden.  Pass in an invalid Id to disable dontCollide. */
  
  void set_dont_collide_composite(CompositeId compId) {dontCollideComposite = compId;}
  /* EFFECTS: Similar to set_dont_collide(), but for all members of a composite object. */

  virtual void set_intel(IntelP i);
  /* REQUIRES: Object has been added to locator (has valid id.) */
  /* NOTE: Can be NULL. */
  /* NOTE: Is virtual so Creature can inform Abilities of change. */

  void set_health_next(Health h) {assert(alive()); healthNext = h;}

  virtual void heal();
  /* EFFECTS: Called by MedKit. */
  /* NOTE: Calls up the tree. */
  
  virtual void set_mapped_next(Boolean val);
  /* NOTE: Should be ok to set the value to the previous value. */
  /* NOTE: idempotent */
  /* Calls up the tree. */

  void set_delete_me() {deleteMe = True;}
  /* NOTE: Should only be called by self and Locator. */

  void flash();
  /* EFFECTS: Object will be drawn for FLASH_TIME turns. */

  void set_no_death_delete() {noDeathDelete = True;}

  virtual Boolean corporeal_attack(PhysicalP killer,int damage); 
  /* NOTE: negative damage can be passed in, this "superficial damage" will
     not hurt the object, just causes indications of getting hit.  E.g. 
     bleed even though not really hurt. */
  virtual void heat_attack(PhysicalP,int heat,Boolean secondary = False);
  /* NOTE: Sometimes call up the tree. */
  /* NOTE: killer is the one responsible for causing the damage.  Can be 
     NULL.  Adds kills to the killer. */
  /* NOTE: Only the last call before the update cycle takes effect. */

  virtual Boolean swap_protect();
  virtual Boolean frog_protect();
  /* EFFECTS: Returns whether the Physical is protected from a swap or frog
     attack.  May have side effects, so call only once per attack. */
  /* NOTE: Using a Transmogifier is considered a swap attack. */
  
  virtual void avoid(PhysicalP);
  virtual void collide(PhysicalP);
  /* EFFECTS: Collision procedures.  avoid is called on the lighter of the two
     objects.  collide is called on both objects. */
  /* NOTE: Not always called up the tree. */

  void intelligence() {if (intel) intel->clock(this);}

  void kill_self() {healthNext = -1;}
  /* NOTE: Called in act/collision_checks phase.  Do not call this in the 
     die phase. (or update phase?) */

  virtual void set_quiet_death();
  /* EFFECTS: When this dies, do not do any funny things like leaving corpses
     or exploding or any other type of physical evidence. */
  /* WARNING: When a User dies, it drops all weapons and items even if 
     set_quiet_death() has been called.  This is somewhat of a hack. */
  /* NOTE: Calls up the tree. */

  void virtual act();
  /* EFFECTS: Action phase.  All next variables must be set here.  Commands 
     are interpreted here.*/

  void virtual update(); 
  /* EFFECTS: Set current variables to be the next ones.  No interactions 
     between physical objects. */

  void virtual draw(CMN_DRAWABLE buffer,Xvars &xvars,int dpyNum,
		    const Area &area) = 0;
  /* REQUIRES: buffer is at least as big as area. */
  /* EFFECTS: Draw the physical object in buffer.  buffer represents area. */
  /* NOTE: Does not check for overlap */
  /* NOTE: X variables initialized in draw.  Thus, if draw is never called for
     a base class, the X variables never need to be initialized. */

  void virtual die();
  /* EFFECTS:  If the *this dies a natural death (I.e. health < 0), then this
     function is called.  Not called if *this is 
     destroyed for any other reason.  E.g. end of game.  The default is to 
     kill the intel and set_delete_me. */
  /* NOTE: Called only in the die phase. */
  /* NOTE: Calls up the tree. */
  /* NOTE: Guaranteed to be called only once. */

  virtual void dr_clock();
  /* EFFECTS: Perform one step of dead reckoning on the client.
     This will only be called on turns where update_from_stream() isn't 
     called. Simulates calls to act() and update(). */
  /* NOTE: calls up the tree. */

  virtual ClassId get_weapon_string(const char *&str);
  /* EFFECTS: str is set to point to a static string containing the string
     for ClassId. */
  /* NOTE: BuiltIn returns something for get_weapon_string(), but NULL
     for get_weapon_current. */

  virtual void drop_all();
  /* NOTE: Not in Holder since, e.g. Frog::drop_all must be able to call drop_all
     on the unmapped object. */

  void hack_update_area_next() {update_area_next(True);}
  /* NOTE: Game::off_clock_kill() wants area to match areaNext when
     killing objects. */


#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
  WorldP get_world() {return world;}

  Boolean alive_next() {return healthNext >= 0;}

  virtual Dir get_dir_next();

  LocatorP get_locator() {return locator;}

  virtual ITcommand get_command();
  /* EFFECTS: Gets the command. */
  /* NOTE: command is not clocked. */

  Boolean get_mapped_next() {return mappedNext;}

  void set_mass_next(Mass mss) {massNext = mss;}

  void creation_failed() {creationOk = False;}
  /* EFFECTS: Used by children to mark that the creation of the Physical
     from a stream failed. */

  virtual void update_area_next(Boolean currentAndNext);
  /* EFFECTS: Called to adjust for any change in the size and position of 
     the Physical.  Used in two ways.  
     (1) During the act() phase it is called 
     with False anytime something effects the next values affecting area, 
     may be called before or after this->act().  
     (2) Outside of the clock, e.g. when reading from a stream, it is 
     called with True.  Right now this only happens when one object calls
     follow() on another. */
  

private:
  void _update_area_next(Boolean currentAndNext);
  /* EFFECTS: Handle making object follow(). */

  void init_static();

  static Boolean staticValid;
  static Acc unitAccs[CO_DIR_MAX]; 
  static Vel unitVels[CO_DIR_MAX]; 
  Id id;
  WorldP world;
  LocatorP locator;
  ITcommand command;
  const PhysicalContext *pc; 
  Health health, healthNext;
  Mass mass, massNext;
  Id dontCollide;
  CompositeId dontCollideComposite;
  IntelP intel;
  Boolean deleteMe;
  Boolean mapped,mappedNext;
  Boolean noDeathDelete; // Should set_delete_me be called at death.
  Boolean dieCalled;
  int heat, heatNext;
  Boolean previousHeatWasSecondary;
  Timer flashTimer;
  Boolean quietDeath;
  NetDataP netData; // Only allocated when needed.
  Boolean creationOk;
};
// PhysicalP defined in locator.h



////////// Protection
// Parent: Physical
// Created by a Shield.  Protects a Moving against various types of attacks.
// Not a subclass of Moving because we don't want to worry about hitting 
// walls.
struct ProtectionContext {
  CMN_COLOR colorName;
  PhysicalContext physicalContext;
};


class Protection : public Physical {
public:
  Protection(const ProtectionContext &,ProtectionXdata &,
	     WorldP,LocatorP,const Area &);

  DECLARE_INTERNAL_NODE_IO(Protection);

  virtual Boolean collidable();
  virtual const Area &get_area();
  virtual const Area &get_area_next();

  virtual void follow(const Area &followeeArea,Dir followeeDir,
                      Boolean currentAndNext);
  ///////// Following comments only apply if currentAndNext is False.
  /* NOTE: Can be called multiple times in one turn. */
  /* EFFECTS: Called in act() phase by the Moving being protected. 
   aNext is the next Area of the Moving.  Can be called before or after
   this->act(). */

  virtual Boolean corporeal_protect(int damage) = 0;
  virtual Boolean heat_protect(int heat,Boolean secondary) = 0;
  /* EFFECTS: The Moving has received an attack.  Return wheter the Protection
     will protect against the attack. */

  virtual void draw(CMN_DRAWABLE,Xvars &,int,const Area &);

  virtual void act();
  virtual void update();

  virtual void dr_clock();


#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
  virtual void update_area_next(Boolean currentAndNext);

  static void init_x(Xvars &,IXCommand command,void* arg,const ProtectionContext &,ProtectionXdata &);


private:
  void _act();

  enum {DELTA_MIN = -2,DELTA_MAX = 5};  // DELTA_MIN <= delta < DELTA_MAX


  const ProtectionContext *prc;
  ProtectionXdata *pXdata;
  int delta;  // When drawn, how far the Protection sticks out.
  Area areaBaseNext;
  Area area,areaNext;
};
// ProtectionP defined above.



////////// Moving
// Parent: Physical
// Has all 19 directions.  Multiple pixmaps.  Can change size and position. 
// Top speed is VEL_MAX.

/* Only sizes[CO_air] and offsets[CO_air] are required to be set.  
   Gives initial size and offset. */
struct MovingContext {
  CMN_COLOR foreColorName;
  Boolean foreWhiteDefault;
  CMN_COLOR backColorName;
  Boolean backWhiteDefault;
  int animMax[CO_DIR_MAX];
  Size sizes[CO_DIR_MAX]; // in world coords
  Size depreciated_offsets[CO_DIR_MAX];  
  CMN_BITS_ID pixmapBits[CO_DIR_MAX][PH_ANIM_MAX];
  CMN_BITS_ID maskBits[CO_DIR_MAX][PH_ANIM_MAX];
  PhysicalContext physicalContext;
  // The bitmaps are already in high resolution, don't stretch them.
  // Only used on Win32.
  Boolean hiRes;
  // Used to override behavior for generating offsets.
  // If NULL, use Moving::offset_generator.
  Touching (*offsetGenerator)(Dir); 
  // Used to override behavior for auto-generating bitmaps.
  // Specifies which bitmaps are transformations of other
  // bitmaps.
  TransformMap* transformOverride;
  // The bitmaps are specified as color XPM (X Pixmap).
  // Only used on X11.
  Boolean useXPM;
  // Can this object ever be invisible.  Right now, this only applies
  // to Creatures that use a Cloak.  Masks be generated iff this flag 
  // is True.
  Boolean invisibility;
};



class Moving: public Physical {
public:
  Moving(const MovingContext &m_c,MovingXdata &x_data,
	       WorldP world,LocatorP l,const Pos &rawPos,
	       Dir dirInitial = CO_air);

  Moving();
  /* NOTE: Should never be called. */

  DECLARE_INTERNAL_NODE_IO(Moving);
 
  void patch_size_and_size_next();
  /* EFFECTS: Deal with the problem that client and server may have different 
     ideas about the size of a Moving object. */

  virtual Boolean is_moving();

  virtual const Area &get_area();

  virtual const Area &get_area_next();
  /* NOTE: Should only be used by the Locator or in a protected context. */

  Boolean is_invisible() {return !invisible.ready();}
  /* NOTE: Invisible as long as the invisibility timer is running. */

  virtual Boolean ignore_walls();
  /* NOTE: Override this to make something able to "walk through walls." */

  virtual Vel get_vel();
  const Pos &get_raw_pos() {return rawPos;}
  virtual Dir get_dir();

  virtual Id get_protection();

  virtual void get_followers(PtrList &list);

  Boolean supports_invisibility() {return mc->invisibility;}
  /* EFFECTS: Can this object be made invisible. */

  virtual void follow(const Area &followeeArea,Dir followeeDir,
                      Boolean currentAndNext);
  
  void set_vel_next(const Vel &vel) {velNext = vel;}
  void set_vel_next(int zero) {assert (zero == 0); velNext.set_zero();}
  /* EFFECTS: Sets the next velocity for the object to be vel.  Can be called
     multiple times before update, only the last call is used. */

  void set_middle_next(const Pos &pos);
  /* EFFECTS: Sets the middle to pos according to the current (not next) values
     of dir, and area (for size). */
  /* NOTE: May be called before or after act phase. */

  void relocate(const Pos &p);
  /* EFFECTS: Moves the raw position of the Moving to p. Can and must be 
     called outside of Locator::clock. */
  /* REQUIRES: Must be relocated to an open area of the World. */
  /* NOTE: Sets current and next values. */

  virtual void set_mapped_next(Boolean val);

  void set_extra_vel_next(const Vel &vel) 
  {extraVelNext = vel; extraVelNextSet = True;}
  void set_extra_vel_next(int zero) 
  {assert (zero == 0); velNext.set_zero(); extraVelNextSet = True;}

  virtual void set_protection(const Id &);

  void set_invisible_next(int turns);
  /* EFFECTS: For turns >= 0, sets object to be invisible for at least 
     the given number of turns.  For turns == -1, turns off invisibility
     next turn. */
  /* REQUIRES: supports_invisibility() is True. */

  void set_attack_hook(void (*hook)(PhysicalP)) {attackHook = hook;}
  /* NOTE: Overrides previous value if any. */

  void attack_hook() {if (attackHook) attackHook(this);}
  /* EFFECTS: Should be called whenever *this attacks anything. */

  virtual Boolean corporeal_attack(PhysicalP killer,int damage); 
  /* EFFECTS: Return False if attack was blocked. */

  virtual void heat_attack(PhysicalP,int heat,Boolean secondary = False);

  virtual int new_anim_num(int animPrev,int animMax);
  /* EFFECTS: Override to determine behavior of animation.  Returns
    new animNum given the old value and the maximum animNum for that
    direction. */

  virtual void act();
  virtual void update();
  virtual void draw(CMN_DRAWABLE,Xvars &,int,const Area &);
  virtual void avoid(PhysicalP);
  virtual void collide(PhysicalP);
  virtual void die();
  virtual void dr_clock();

  const MovingContext *get_moving_context() {return mc;}
  /* NOTE: Now public so we can tell when we can turn something into a Sticky. 
     Perhaps we should just export the list of animMax. */

  static Touching offset_generator(Dir dir);
  /* EFFECTS: The default offset_generator.  Map a direction to the
     "wall" it touches. */


#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
  Boolean hit_wall() {return hitWall;}
  Boolean hit_wall_next() {return hitWallNext;}

  virtual Dir get_dir_next();

  Vel get_vel_next() {return velNext;}

  virtual int get_anim_time();
  /* EFFECTS: Override this to make objects animate faster or slower.
     Returns the number of turns per frame.  Default is MOVING_ANIM_TIME. */

  Size *get_offsets();
  /* EFFECTS: Return array of size CO_DIR_MAX with all the offsets for
     this Moving. */
  /* DEFAULT: Compute generic offsets from Coord::generate_offsets(). */

  virtual Boolean draw_outline(ColorNum &colorNum);
  /* MODIFIES: colorNum */
  /* EFFETS: Override this to control drawing the four dots in the 
     corners around the object.  colorNum should be set if True is returned. */

  virtual Boolean generate_masks();
  /* EFFECTS: On Windows decide whether to auto-generate masks for 
     this object. */
  /* DEFAULT: False */

  void set_vel(const Vel &v) {vel = v;}
  void set_vel(int zero) {assert (zero == 0); vel.set_zero();}

  void set_dir(const Dir &d) {dir = d;}
  /* NOTE: Only used by Lance for initialization. */

  void set_dir_next(const Dir &d) {dirNext = d;}

  void _set_middle_next(const Pos &pos);
  /* NOTE: Nothing special about this, just like set_dir_next() or 
     set_raw_pos_next() in that it just sets the next variables, does not
     call update_area_next. */

  void set_mover_vel(const Size &v) {moverVel = v;}
  /* EFFECTS: Called in act phase before Moving::act(), only lasts for that
      turn.  Used by Creature::act() to follow a Mover. */

  void set_raw_pos_next(const Pos &rpos)
    {rawPosNext = rpos; rawPosChanged = True;}

  void update_area_next(Boolean currentAndNext);
  /* EFFECTS: Compute areaNext and hitWallNext.  May modify rawPosNext or 
     dirNext. */
  /* NOTE: May be called more than once per turn. */

  virtual void get_pixmap_mask(Xvars &xvars,int dpyNum,
                               CMN_IMAGEDATA &imageData,
                               Dir dir,int animNum);
  /* MODIFIES: imageData */
  /* NOTE: Only used so that children of Moving can affect Moving's actions. 
     imageData is basically a pixmap and a mask. */
  
  virtual void get_size_offset_next(Size &size,Size &offset,Dir dirNext);
  /* MODIFIES: size, offset */
  /* NOTE: Only used so that children of Moving can affect Moving's actions. */

  void set_size_offset_current_and_next(const Size &size,const Size &offset);
  /* EFFECTS: Sets immediate and next values of size and offset. */
  /* NOTE: Kind of a hack.  Only needs to be called if a child uses 
	 get_size_offset_next() and does something different on the initial state. 
     Only called in child constructor. */

  static void init_x(Xvars &,IXCommand command,void* arg,const MovingContext &,MovingXdata &);
  /* EFFECTS: Initialize all graphics for the concrete class that derives from 
     Moving.  E.g. Ninja::init_x() will call Moving::init_x() to initialize all the
     graphics in the Moving part of the Ninja.   On windows, this is a two-phase
     process.  First init_x() is called with command==IX_ADD.  This just adds the 
     requests for surfaces to the SurfaceManager.  Later, it is called with 
     command=IX_INIT which actually loads the bitmaps into the surfaces.  On UNIX, 
     there is only one phase and command is always IX_INIT. */
  /* NOTE: Now called up the tree. */
  /* NOTE: This method is now poorly names as we are overloading its use.  There is
     now also an IX_LIST command on Windows.  We should really call this gfx_function, 
     or something to indicate that this is a multi-purpose graphics-related function 
     for the class.  Have to go through all the .bitmaps files to fix the naming. */
  /* NOTE: See the platform-specific definition of IXCommand to see all the 
     commands. */


private:
  void _act();
  void _update();
  /* NOTE: Used by act(), update() and by dr_clock(). 
     No special semantics like act(), or update(), or update_area_next().
     Consider _act() to be any other method that sets the next dirs, like
     set_dir_next(). */

  void _update_area_next(Boolean currentAndNext);

  Boolean context_valid();
  /* EFFECTS: Returns True if this->cx is valid, False otherwise. */

  float compute_collision(Mass m1,float v1,Mass m2,float v2);

  static void check_generate_offsets(const MovingContext &,MovingXdata *);
  /* EFFECTS: Make sure offsets have been generated for the MovingContext. */
  /* NOTE: Hack here, using movingXdata to store non-graphics-related info. */

  static void* compute_key(Dir dir,int animNum,Boolean isMask,
                           const MovingContext *,MovingXdata *);
  /* EFFECTS: Compute hash key for storing a bitmap in the SurfaceManager.  Only 
     used on Windows. */

  static void check_auto_generated(const MovingContext&);
  /* EFFECTS: Check that sizes and animMax match up for auto-generated
     bitmaps. */


  MovingXdata *movingXdata;
  int movingAnimNum;
  Timer animTimer;
  const MovingContext *mc;
  Pos rawPos,rawPosNext; Boolean rawPosChanged;
  Area area,areaNext;   
  Dir dir,dirNext;
  Vel vel,velNext; 
  Boolean extraVelNextSet;
  Vel extraVel,extraVelNext; // Follows clock in non-standard way.
  Size moverVel; // Only exists in act() phase.
  Boolean hitWall,hitWallNext;
  Id protection;
  Timer invisible;  // Invisible if the timer is running, i.e. !ready().
  // Number of turns to be invisible, -1 means turn off invisibilty.
  int invisibleNext;  
  void (*attackHook)(PhysicalP);
};
typedef Moving *MovingP;



////////// Shot
// Parent: Moving

struct ShotContext {
  int damage; 
  Speed speed;
  SoundName soundId;
  Boolean repeatingSound;
  MovingContext movingContext;
};


typedef MovingXdata ShotXdata ;


class Shot: public Moving {
public:
  Shot(const ShotContext &,ShotXdata &,WorldP,LocatorP,
       const Pos &,const Id &shooter,
       Dir shotDir,Dir movingDir = CO_air);
  /* NOTE: compId may be COMPOSITE_ID_NONE */  

  DECLARE_NULL_INTERNAL_NODE_IO(Shot);

  const Id &get_shooter() {return shooter;}

  virtual Boolean is_shot();

  virtual void avoid(PhysicalP other);
  virtual void collide(PhysicalP other);

  virtual void act();

  virtual void update();


#ifndef PROTECTED_IS_PUBLIC
 protected:
#endif
  int get_damage() {return context->damage;}


private:
  Boolean firstTurn;
  Id shooter;
  const ShotContext *context;
};



////////// Droplet
// Parent: Moving
// Moving with gravity.  Sticks to walls.

struct DropletContext {
  int dissolveTime;
  MovingContext movingContext;
};

typedef MovingXdata DropletXdata;

enum DropletType { DROPLET_NONE, DROPLET_BLOOD, DROPLET_GREEN_BLOOD, DROPLET_OIL,
                   DROPLET_SPARK = DROPLET_NONE}; // sparks disabled

class Droplet: public Moving {
public:
  Droplet(const DropletContext &,DropletXdata &,
	  WorldP world,LocatorP l,const Pos &rawPos,
	  const Vel &vel,Dir dir = CO_air);
  /* NOTE: If dir is not CO_air, then it specifies the direction of the
     Droplet in the air.  Else, the direction will be the appropriate 
     "pure" directions while in the air. */

  DECLARE_NULL_INTERNAL_NODE_IO(Droplet);

  virtual Boolean collidable();

  virtual void act();

  static Size get_size_max(DropletType);
  static PhysicalP create_and_add_if(DropletType,WorldP,LocatorP,const Pos &,const Vel &);
  /* EFFECTS: Just call appropriate function on child class. */


#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
  static int get_available_entry(LocatorP l);
  /* EFFECTS: Return index for set_entry() or -1 if none 
    available. */

  static void set_entry(int index,const Id &);
  /* EFFECTS: All children of Droplet should call set_entry() on
    creation. */


private: 
  const DropletContext *context;
  Timer timer;
  Boolean inAir;

  // If True, the dir never changes for the droplet, it is 
  // specified in the constructor.
  Boolean staticDir; 

  // Max number of droplets of all type in the game.
  enum {DROPLET_MAX=45};
  static Id dropletList[DROPLET_MAX];
  static int dropletMax;
};



////////// Falling
// Parent: Moving
// Moving with gravity.  Falls until it is blocked by the world.  

struct FallingContext {
  MovingContext movingContext;
};


typedef MovingXdata FallingXdata;


class Falling: public Moving {
public:
  Falling(const FallingContext &h_c,FallingXdata &x_data,
	  WorldP world,LocatorP l,const Pos &rawPos,
	  Dir dirInitial = CO_air);
  
  DECLARE_NULL_INTERNAL_NODE_IO(Falling);

  virtual void act();


#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
  virtual Boolean gravity_on();
  /* EFFECTS: Called during act() to see if gravity affects
     the Falling. */
  /* DEFAULT: True */
};



////////// Touchable
// Parent: Falling
// Remembers if it has ever been touched by a Human controlled Physical.

struct TouchableContext {
  FallingContext fallingContext;
};


typedef FallingXdata TouchableXdata;


class Touchable: public Falling {
 public:
  Touchable(const TouchableContext &,TouchableXdata &x_data,
	    WorldP,LocatorP,const Pos &);

  DECLARE_NULL_INTERNAL_NODE_IO(Touchable);

  virtual int get_drawing_level();
  /* EFFECTS:  Touchable is drawn behind everything else. */
  
  Boolean wasTouched() {return touched;}
  /* EFFECTS:  Has a Physical with Human intelligence touched the Xit. */
  
  virtual Boolean collidable();
  virtual void act();


private:
  Boolean touched;
  const TouchableContext *context;
};
typedef Touchable *TouchableP;



//////////// Heavy
// Parent: Falling
// Does damage to things it lands on.

struct HeavyContext {
  int damage;
  FallingContext fallingContext;
};


typedef FallingXdata HeavyXdata;


class Heavy: public Falling {
 public:
  Heavy(const HeavyContext &h_c,
	HeavyXdata &x_data,
	WorldP world,
	LocatorP l,
	const Pos &rawPos);
  
  DECLARE_NULL_INTERNAL_NODE_IO(Heavy);

  virtual void collide(PhysicalP);
  /* EFFECTS: Crush things it falls on. */
  

#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
  void set_pusher(const Id &id) {pusher = id;}
  /* EFFECTS: Used by Liftable to give the Lifter credit for kills. */


 private:
  Id pusher; // Who last touched the heavy.
  const HeavyContext *context;
};



//////////// Liftable
// Parent: Heavy
// Can be carried by a Lifter

struct LiftableContext {
  HeavyContext heavyContext;
};

typedef HeavyXdata LiftableXdata;

class Liftable: public Heavy {
 public:
  Liftable(const LiftableContext &h_c,
           LiftableXdata &x_data,
           WorldP world,
           LocatorP l,
           const Pos &rawPos);
  
  DECLARE_NULL_INTERNAL_NODE_IO(Liftable);

  virtual Boolean is_liftable();

  virtual int get_drawing_level();

  Boolean being_lifted();
  /* EFFECTS: Return if something is already lifting this Liftable. */

  virtual void update();
  
  virtual void collide(PhysicalP);
  /* NOTE: Don't hurt anything if being lifted. */
  
  void lift(PhysicalP lifter);
  /* EFFECTS: A lifter has started lifting the Liftable. */

  void release(PhysicalP lifter);
  /* EFFECTS: A lifter has dropped/thrown the Liftable. */
    

private:
  Id lifter;  // valid iff being lifted or excludedTime.
  Timer excludedTimer;
  Boolean excludedTime; // Was just dropped, don't pick up again.
};
typedef Liftable *LiftableP;

  

//////////// Item
// Parent: Falling
// 
struct ItemContext {
  Boolean persists; 
  // Provides ranking for weapons/items when switching.  
  // No two weapons should have the same coolness and no two items
  // should have the same coolness.  
  // Negative coolness means that the item should never be automatically 
  // selected.
  int coolness; 
	SoundName useSound;
  FallingContext fallingContext;
};


typedef FallingXdata ItemXdata;


class Item: public Falling {
public:
  Item(const ItemContext &c_x,
       ItemXdata &x_data,
       WorldP w,
       LocatorP l,
       const Pos &pos,Dir dirInitial = CO_air);
  
  DECLARE_INTERNAL_NODE_IO(Item);

  Boolean is_item() {return True;}

  Boolean is_held() {return held;}
  
  Boolean can_take(PhysicalP taker);
  /* EFFECTS: Returns whether the object can be picked up by taker. */

  virtual int get_drawing_level();

  Id get_holder_id();
  /* EFFECTS: Returns the holder Id if held or an invalid Id if not held.  */

	virtual int get_coolness();
	/* NOTE: Coolness may change for an item. */

  void set_quiet_death();

  Boolean persists() {return context->persists;}

  virtual void taken(PhysicalP);
  /* EFFECTS:  The object has been taken by another Physical. */
  /* NOTE: Changes immediate externally visible state.  Should only be called
     in the collision phase. */

  void dropped(PhysicalP);
  /* EFFECTS:  The object has been dropped by another Physical. */
  /* NOTE: Called by another object in the act phase. */
  /* NOTE: Called in either the act or update phase. */
  /* NOTE: Calls up the tree. */

  virtual void use(PhysicalP);
  /* EFFECTS: p uses *this. */
  /* NOTES: Called by another object in act phase.  Can also be called in
     collide phase. (see AutoUse::collide)  Calls up the tree. */

  virtual void act();
  
  virtual void die();
  
  
#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
  virtual Boolean gravity_on();
  /* NOTE: Don't want to be affected by gravity while held. */

  void set_cant_take() {cantTake = True;}
  
  
private:
  enum MESSAGE {NONE,USED,DESTROYED};

  Boolean held;
  Id holderId; // Valid iff held.
  Boolean dieMessage;

  //  Timer canTake;
  // While excludedTimer is not ready(), excluded cannot take this.
  Id excluded;
  Timer excludedTimer;
  
  Boolean cantTake;
  const ItemContext *context;
};
typedef Item *ItemP;



//////////// AutoUse
// Parent: Item
// Automatically gets used when it collides with a non-user creature.
// WARNING: All children of this class must be able to be used by a non-user.

struct AutoUseContext {
  Boolean humansOnly; // Only automatically used by humans.
  ItemContext itemContext;
};


typedef ItemXdata AutoUseXdata;


class AutoUse : public Item {
public:
  AutoUse(const AutoUseContext &c_x,
	  AutoUseXdata &x_data,
	  WorldP w,
	  LocatorP l,
	  const Pos &pos);

  DECLARE_NULL_INTERNAL_NODE_IO(AutoUse);

  virtual Boolean is_auto_use();
  
  virtual void collide(PhysicalP);


private:
  const AutoUseContext *context;
};



//////////// Drugs
// Parent: AutoUse
struct DrugsContext {
  int odChance;  // zero means no chance of OD
  AutoUseContext autoUseContext;
};

typedef AutoUseXdata DrugsXdata;

class Drugs : public AutoUse {
public:
  Drugs(const DrugsContext &c_x,DrugsXdata &x_data,WorldP w,LocatorP l,const Pos &pos);

  DECLARE_NULL_INTERNAL_NODE_IO(Drugs);

  virtual Boolean is_drugs();

  virtual void taken(PhysicalP);

  virtual void use(PhysicalP);


#ifndef PROTECTED_IS_PUBLIC
  protected:
#endif
  virtual ModifierP create_modifier() = 0;
  /* EFFECTS: Override to give drug of your choice. */

  const DrugsContext *context;
};



//////////// Shield
// Parent: AutoUse
struct ShieldContext {
  AutoUseContext autoUseContext;
};


typedef AutoUseXdata ShieldXdata;


class Shield: public AutoUse {
public:
  Shield(const ShieldContext &,ShieldXdata &,
	 WorldP w,LocatorP l,const Pos &pos);

  DECLARE_NULL_INTERNAL_NODE_IO(Shield);

  virtual Boolean is_shield();
  
  virtual void use(PhysicalP);

  
#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
  virtual ProtectionP create_protection(const Area&) = 0;
  /* EFFECTS: Create the type of Protection specific to this type of Shield. */
};



//////////// Animated
// Parent: Item
//
struct AnimatedContext {
  ItemContext itemContext;
};

typedef ItemXdata AnimatedXdata;

class Animated: public Item {
public:
  Animated(const AnimatedContext &,AnimatedXdata &,
	   WorldP,LocatorP,const Pos &,Frame frameInitial = CO_R);
  /* NOTE: CO_R should really be FRAME_BASE, lame compilers. */

  DECLARE_NULL_INTERNAL_NODE_IO(Animated);


#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
  void set_frame(Frame fr) {set_dir(fr + FRAME_BASE);}
  void set_frame_next(Frame fr) {set_dir_next(fr + FRAME_BASE);}
  Frame get_frame() {return get_dir() - FRAME_BASE;}


private:
  enum {FRAME_BASE = CO_R};
};



//////////// Weapon
// Parent: Item
// 
struct WeaponContext {
  // Defaultable has been superceeded by using negative values for
  // ItemContext::coolness.
  SoundName soundid;
  ItemContext itemContext;
};


typedef ItemXdata WeaponXdata;


class Weapon;
typedef Weapon *WeaponP;


class Weapon: public Item {
public:
  Weapon(const WeaponContext &c_x,
	 WeaponXdata &x_data,
	 WorldP w,
	 LocatorP l,
	 const Pos &pos,Dir dirInitial = CO_air);
  
  DECLARE_NULL_INTERNAL_NODE_IO(Weapon);

  Boolean is_weapon() {return True;}

  virtual Boolean ready() = 0;
  /* EFFECTS: Can the weapon be fired now. */
  /* NOTE: Sometimes calls up the tree.*/

  //  Boolean defaultable() {return wc->defaultable;}
  /* EFFECTS: Is this a type of weapon that can safely be set automatically as
     the current weapon.  E.g. You do not want to set a soul-swapper as the 
     current weapon unless the user explicitly says so. */

  virtual int get_ammo() = 0;
  virtual int get_ammo_max() = 0;
  /* NOTE: Can return PH_AMMO_UNLIMITED. */

  virtual Boolean useful_no_ammo();
  /* EFFECTS: Is this weapon useful even if it is out of ammo.  (Otherwise User 
    will kill it when it runs out.) */
  /* DEFAULT: False */

  virtual Boolean fire_repeatedly();
  /* EFFECTS: Should this weapon be fired repeatedly if the user holds down the 
     fire key. */
  /* DEFAULT: True */

  virtual void fire(const Id &id,ITcommand command);
  /* REQUIRES: command is a weapon command. */
  /* EFFECTS: Fire the weapon according to the specified command.  id is the
     physical firing the weapon.  */

  virtual void use(PhysicalP);
  /* NOTE: Does nothing. Doesn't even call Item::use(). */

  virtual void enter_scope_next(PhysicalP user);
  virtual void leave_scope_next(PhysicalP user);
  /* NOTE: Called during act(collide) or update phase. Should be just 
     act(). */
  /* NOTE: Calls up the tree. */
  /* NOTE: ok to call multiple times in same turn, but must enter/leave scope
     in proper order. */

  virtual void take_ammo_from(WeaponP other);
  /* EFFECTS: Take as much ammo as possible from the other weapon. */


#ifndef PROTECTED_IS_PUBLIC
 protected:
#endif
  Boolean entered_scope() {return enteredScope;}

  virtual void set_ammo(int) = 0;

  virtual Dir compute_weapon_dir(ITcommand c);
  /* EFFECTS:  Returns the direction the weapon should be fired, 
     {CO_R ... CO_UP_R}, or CO_air. */


private:
  const WeaponContext *wc;
  Boolean enteredScope; // not clocked
};
// typedef Weapon *WeaponP; Defined above.



//////////// Cutter
// Parent: Weapon
// NOTE: Uses CO_center for cutter directly in front of user.
struct CutterContext {
  int damage;  // per turn
  Size offsets[CO_DIR_MAX];  // From User's middle to Cutter's middle.

  SoundName cuttingsound;
  WeaponContext weaponContext;
};

typedef WeaponXdata CutterXdata;

class Cutter: public Weapon {
public:
  Cutter(const CutterContext &c_x,CutterXdata &x_data,
	 WorldP w,LocatorP l,const Pos &pos);
  
  DECLARE_INTERNAL_NODE_IO(Cutter);

  virtual Boolean is_cutter();

  virtual Boolean ready();

  virtual int get_ammo();
  virtual int get_ammo_max();

  virtual Boolean ignore_walls();
  /* NOTE: We don't want cutters that are held to get bounced through walls. */

  virtual void set_ammo(int);

  virtual void follow(const Area &,Dir,Boolean);

  virtual void enter_scope_next(PhysicalP);
  virtual void leave_scope_next(PhysicalP);

  virtual void collide(PhysicalP);

  virtual void update();

  virtual void take_ammo_from(WeaponP);
  /* EFFECTS: "Heal" up the chainsaw as if chainsaws had been switched. */

  
private:
  enum {UNHELD_DIR = CO_R};
  
  Dir dir_4_from_user_dir(Dir);

  Boolean inScope,inScopeNext;
  Id killerId;  // Valid iff inScope.
  const CutterContext *context;
};



//////////// Gun
// Parent: Weapon
// Shoots shells.  Has timer between allowed shots.
struct GunContext {
  int shotTime;
  int ammoInitial;
  int ammoMax;  
  WeaponContext weaponContext;
};
typedef WeaponXdata GunXdata;


class Gun: public Weapon {
public:
  Gun(const GunContext &,GunXdata &,WorldP,LocatorP,const Pos &);

  DECLARE_INTERNAL_NODE_IO(Gun);

  virtual Boolean is_gun();
  virtual Boolean ready();
  int get_ammo();
  int get_ammo_max();

  virtual void update();


#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
  void set_ammo(int);
  void set_shot_timer() {timer.set();}

  virtual Size get_shot_size(Dir);

  virtual void fire(const Id &id,ITcommand command);
  void _fire(const Id &id,Dir dir,Boolean setTimer = True,
	     Boolean costsAmmo = True);
  /* NOTE: Only the first of these two functions should be overridden. */
  /* EFFECTS: Gun is fired by the shooter id with ITcommand command or in Dir
     dir.  setTimer says whether or not to force a delay between shots. 
     costsAmmo says whether a unit of ammo is subtracted for the shot.*/
  
  virtual PhysicalP create_shot(PhysicalP shooter,WorldP world,
				LocatorP locator,const Pos &pos,Dir dir);
  /* EFFECTS: Create the object to be fired out of the gun.  E.g. shell, 
     swap_shell. shooter is the object firing the gun. */
  /* DEFAULT: Create a Shell. */


private:
  Timer timer;
  int ammo;
  const GunContext *gc;
};



//////////// SingleGun
// Parent: Gun
struct SingleGunContext {
  GunContext gunContext;
};
typedef GunXdata SingleGunXdata;


class SingleGun: public Gun {
public:
  SingleGun(const SingleGunContext &,SingleGunXdata &,
	    WorldP,LocatorP,const Pos &);

  DECLARE_NULL_INTERNAL_NODE_IO(SingleGun);

  virtual Boolean ready();
  

private:
  virtual void fire(const Id &id,ITcommand command);
  
  Id shotId;
};



//////////// Whistle
// Parent: Weapon
struct WhistleContext {
  int coolnessNoAmmo;
  int ammo;  // Must be <= Whistle::PET_MAX. 
  // Chance that the alternate pet will be created, 0 if no alternate
  // pet is ever created.
  int alternateChance; 
  WeaponContext weaponContext;
};

typedef WeaponXdata WhistleXdata;

class Whistle: public Weapon {
public:    
  Whistle(const WhistleContext &,WhistleXdata &,WorldP w,LocatorP l,const Pos &pos);

  DECLARE_INTERNAL_NODE_IO(Whistle);
  
  virtual Boolean ready();
  
  virtual int get_ammo();
  virtual int get_ammo_max();
  /* NOTE: Can return PH_AMMO_UNLIMITED. */
  
  virtual int get_coolness();
  
  virtual Boolean useful_no_ammo();
  
  virtual Boolean fire_repeatedly();

  virtual void fire(const Id &id,ITcommand command);
  /* REQUIRES: command is a weapon command. */
  /* EFFECTS: Fire the weapon according to the specified command.  id is the
     physical firing the weapon.  */
  
  virtual void act();
  

#ifndef PROTECTED_IS_PUBLIC
protected: 
#endif
  virtual void set_ammo(int);
  
  virtual PetP create_pet(IntelP master,Boolean alternatePet,int n) = 0;
  /* EFFECTS: Create the object that the Whistle controls. 
     Whistles may have the ability to create an alternate pet than the
     ususal one.  alternatePet will be True in this case. 
     0 < n < number of pets created this turn, in case the Whistle wants to 
     do something different for different pets.
     Create and register Intel and Physical.  Return intel. */
  

private:
  enum {PET_MAX = 10};    
  
  IntelId pets[PET_MAX];  // Must all be class Pet.
  int petNum;
  int ammo;
  const WhistleContext *context;
};



////////// Creature
// Parent: Moving
// Moving with stances.  Can be affected by gravity.  Has list of Capabilites.
struct CreatureContext {
  Speed crawlSpeed;
  Speed centerSpeed; 
  Speed airSpeed;
  Speed climbSpeed;
  Speed jump;
  Speed acceleration;
  Health corpseHealth; // A positive number.

  Boolean biological;
  DropletType dropletType;

  SoundName deadSoundId;
  MovingContext movingContext;
};

typedef MovingXdata CreatureXdata;  

// By itself, Modifier is a dummy.
typedef int Attribute;

class Modifier {
public:
enum {
  ACCELERATION,AIR_SPEED,CENTER_SPEED,CLIMB_SPEED,CRAWL_SPEED,JUMP, // creatureContext
  DAMAGE, // fighter, prickly
  HIGH, // A Boolean, tells whether Creature is high or not.
  HEALTH_MAX, // Changes maximum health (not current health)
  CORPOREAL_ATTACK,HEAT_ATTACK, // Full protection from an attack.
  ATTRIB_NONE
};


/////// Operations acting on this specific Modifier.
  Modifier(int timed = 0,Boolean head = False);
  /* EFFECTS: If head is True, this is the start of a new list of modifiers.
      else, this is a modifier to insert into a list. */

  virtual ~Modifier();
  /* EFFECTS: Delete self and any modifiers following in the chain.
     If you want to just delete a single modifier, make sure to remove
     it from its list first. */

  void clear();
  /* EFFECTS: Make this an empty list.  I.e. only the head. */
  /* REQUIRES: This is the head. */

  virtual ModifierId get_modifier_id();

//  virtual int apply(Attribute attr,int startVal);
  /* EFFECTS: Apply this Modifier to the attribute. */

  virtual void combine(Modifier *other);
  /* EFFECTS: Combine other modifier into this one. */  
  /* NOTE: Call up the tree. */

  void remove();
  /* EFFECTS: Remove self from list. */


/////// List operations, where "this" is the head of the list.
//  void prepend(Modifier *);
  /* EFFECTS: Add to front of list. */

  void append_unique(Modifier *);
  /* EFFECTS: Add to end of list if none with same ModifierId, else use 
      combine() to merge them. */

//  void remove(Modifier *);


/////// List operations on the remainder of list.
  virtual int apply(Attribute attr,int startVal);
  /* EFFECTS: Apply all Modifiers in list starting with this. */

  virtual void clock(PhysicalP p);
  /* EFFECTS: Clock all modifiers in list. */


#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
  virtual void preDie(PhysicalP p);
  /* EFFECTS: Called just before modifier kills itself. */


  Modifier *next;
  Modifier *prev;
  Boolean timed;
  Timer timer;
  

private:
  Boolean isHead; // Is this the dummy Modifer at the head of the list.
};



// doubles an attribute, then triples, then quadruples as you
// combine() more of them.
class Doubler: public Modifier {
public:
  Doubler(int timed = 0);

  void combine(ModifierP);


#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
  // Children can change these values.
  float multiplier;
  float increment;
};



class Creature: public Moving {
// All template classes must be able to access protected methods of creature.
friend class BSticky;
friend class BPrickly;

public:
  Creature(const CreatureContext &m_c,
	         CreatureXdata &x_data,
           PtrList *abilities,
	         WorldP world,LocatorP l,const Pos &rawPos);
  /* NOTE: Creature owns the memory pointed to by abilities, and will 
    delete it when finished. */

  Creature();
  /* NOTE: Should never be called. */

  // Can't use DECLARE_INTERNAL_NODE_IO() because of the PtrList argument.
  Creature(InStreamP,const CreatureContext &,
           CreatureXdata &,
           WorldP,LocatorP);
  virtual void update_from_stream(InStreamP in);
  void _update_from_stream(InStreamP);
  virtual int get_write_length();
  virtual void write(OutStreamP);
 
  virtual ~Creature();

  virtual Boolean is_creature();

  Stance get_stance() {return stance;}

  Boolean can_climb() {return canClimb;}

  virtual ITcommand get_command();
  /* NOTE: Will return ITnone if the Creature is stunned. */

  const Hanging &get_hanging() {return hanging;}
  /* EFFECTS: Get the corner that the object is hanging off of, or CO_AIR if
     not hanging off a corner. */

  const Touching &get_touching_area() {return touching;}
  /* EFFECTS: The object's actual touching.  I.e. according to its area. */

  Grav get_grav() {return grav;}

  Boolean get_alien_immune() {return !alienImmune.ready();}
  /* EFFECTS: Is Creature immune to Alien and Hugger attacks. */

  ModifierP get_modifiers() {return modifiers;}
  /* EFFECTS: Returns the modifier list for this Creature.  Not a copy. 
     Will never return NULL. */

  virtual void get_followers(PtrList &list);
  /* NOTE: Just for the abilities. */

  Boolean stunned() {return !stunTimer.ready();}

  Boolean biological() {return cc->biological;}
  /* EFFECTS: Is the Creature a biological organism.  E.g. as opposed to a 
     machine. */

  Boolean on_door();
  /* NOTE: Convenience function to say whether *this is on top of a door. */

  Boolean get_want_climb() {return wantClimb;}
  void set_want_climb(Boolean val) {wantClimb = val;}
  /* NOTE: Actually, ALL climbing should be in Creature. */

  virtual Boolean command_repeatable(ITcommand c);
  /* EFFECTS: Don't repeat going through doors, or getting up from a crouch. */

  Boolean standing_squarely();
  /* EFFECTS: Standing squarely on solid ground, not hanging over the edge. */

  virtual ClassId get_weapon_string(const char *&str);

  virtual int get_drawing_level();
  /* NOTE: Just for the abilities. */

  virtual int get_anim_time();
  /* NOTE: Just for the abilities. */

  virtual void follow(const Area &followeeArea,Dir followeeDir,
                      Boolean currentAndNext);
  /* NOTE: Delegate to abilities. */
  
  virtual Boolean swap_protect();
  /* NOTE: Just for the abilities. */

  virtual Boolean frog_protect();
  /* NOTE: Just for the abilities. */

  void stun_next(int time);
  /* EFFECTS: Stun the creature for time turns. */

  virtual void set_intel(IntelP i);
  /* NOTE: Just for informing the abilities. */

  void set_alien_immune(int immTime) {alienImmune.set(immTime);}
  /* EFFECTS: Will be immune to alien and hugger attacks for immTime turns. */
  /* NOTE: Immediate. */

  virtual void set_quiet_death();
  /* NOTE: Calling set_quiet_death on a corpse destroys it. */

  virtual void heal();
  /* NOTE: Just for informing the abilities. */

  virtual void set_mapped_next(Boolean val);
  /* NOTE: Just for informing the abilities. */

  virtual void drop_all();
  /* NOTE: Just for informing the abilities. */

  virtual Boolean corporeal_attack(PhysicalP,int damage); 
  virtual void heat_attack(PhysicalP,int heat,Boolean secondary); 

  virtual void act();
  virtual void update();
  virtual void die();

  virtual void dr_clock();
  /* NOTE: Just to deal with weirdness with Composite objects. */

  virtual void collide(PhysicalP);

  virtual AbilityP get_ability(AbilityId);
  /* EFFECTS: Return the ability if the Creature has it, else return 
     NULL. */

  virtual HolderP get_holder();
  /* EFFECTS: Return the Holder ability, if the Creature has it, 
     else NULL. */  

  virtual LocomotionP get_locomotion();

  virtual CompositeP get_composite();

  void add_ability(AbilityP);
  /* REQUIRES: The creature does not already have the ability. */
  /* EFFECTS: Add a new abilitity to the Creature. */
  /* NOTE: Creature now owns the memory for the ability. */

  void remove_ability(AbilityId abilityId);
  /* REQUIRES: The creature has the ability in question. */
  /* EFFECTS: Remove ability from the Creature.  Calls the die() method on the
     ability. */

  static const Stats &get_stats() {return stats;}

  static TransformMap uprightTransformOverride;
  /* EFFECTS: A convenience object.  Not actually used by Creature, but useful
     for auto-generating pixmaps for creatures that walk upright when they
     are on the walls or ceiling, e.g. Walker with the Sticky ability.  The
     default in Transform2D is to generate bitmaps for wall and ceiling that
     are rotations of the crawling bitmaps (CO_dn_*).  This lets you generate 
     bitmaps for wall and ceiling that are rotations of the upright walking 
     bitmaps (CO_center_*). */


// Now they must be public so that the children of Ability can 
// access them.  It is not enough to make Ability a friend class.
#if 0
#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
#endif
  enum {DEAD_DIR = CO_R};

  virtual Boolean generate_masks();
  /* EFFECTS: On Windows decide whether to auto-generate masks for 
     this object. */

  Stance get_stance_next() {return stanceNext;}

  virtual Health get_health_max();


  Speed get_acceleration(); 
  Speed get_jump(); 
  // Only used for an assert in Fighter::Fighter
  Touching (*get_offset_generator())(Dir)
  {return cc->movingContext.offsetGenerator;}
  TransformMap* get_transform_override()
  {return cc->movingContext.transformOverride;}
  /* NOTE: These methods replace get_creature_context().  Add more if necessary. */


  Touching get_touching_stance();
  /* EFFECTS: The object's touching according to its stance. */

  time_t get_birth_time() {return birthTime;}

  virtual void get_pixmap_mask(Xvars &,int dpyNum,CMN_IMAGEDATA &imageData,
                               Dir dir,int animNum);
  /* NOTE: Calls through all abilities.  Calls up the tree. */
  /* MODIFIES: pixmap, mask */

  void _get_pixmap_mask(Xvars &,int dpyNum,CMN_IMAGEDATA &imageData,
                        Dir dir,int animNum);
  /* EFFECTS: Creature-specific functionality of get_pixmap_mask(), does not call 
     abilities.  Does call up the tree. */
  /* NOTE: Abilities can use this to implement Ability::get_pixmap_mask(). */

  void _heat_attack(PhysicalP killer,int heat,Boolean secondary);
  /* EFFECTS: Creature-specific functionality of get_pixmap_mask(), does not 
     call abilities.  Called after applying modifiers. Does call up the 
     tree. */
  /* NOTE: Abilities can use this to implement Ability::heat_attack(). */
  
  virtual void get_size_offset_next(Size &size,Size &offset,Dir dirNext);
  /* MODIFIES: size, offset */

  void _get_size_offset_next(Size &size,Size &offset,Dir dirNext);
  /* MODIFIES: size, offset */
  /* EFFECTS: Creature-specific functionality of get_size_offset_next(), does 
     not call abilities.  Does call up the tree. */
  /* NOTE: Abilities can use this to implement Ability::get_size_offset_next(). */

  Boolean stunned_next() {return stunNext ? True : False;}

  int compute_droplets_num(int damage);
  /* EFFECTS: Number of droplets (of blood) to produce when hit with the
     given amount of damage. */

  void set_stance(const Stance &st) {stance = st;}

  void set_stance_next(const Stance &stance);
  /* EFFECTS: Sets the next stanceection for the object to be stance.  Can be
     called multiple times before update, only the last call is used. */

  void set_grav_next(const Grav &g)
    {gravNext = g;}
  /* EFFECTS: Sets the pull of gravity for the next turn to be grav. */

  void center_wsquare_x_next(const Loc &loc);
  /* REQUIRES: loc overlaps with the area, stanceNext set to CO_climb */
  /* EFFECTS: Tries to center the x position object on the wsquare at loc.  
     (May be bumped a bit if a wall prevents exact centering.) */

  void corner(const Hanging &hanging);
  /* REQUIRES: stanceNext is set to correspond to h.corner. */
  /* EFFECTS: Tries to move the object around the corner it is hanging off of.
     Note that hanging.corner is the initial corner, not the desired final 
     one. */

  int apply_modifiers(Attribute attr,int initial,int maximum = -1);
  /* EFFECTS: Apply Intel and Creature modifiers to attr, starting with
    initial.  Clamp to maximum if supplied. */

  // Must make these public for Ability to get to them.
  LocatorP get_locator() {return Moving::get_locator();}  
  Boolean get_mapped_next() {return Moving::get_mapped_next();}
  Boolean alive_next() {return Moving::alive_next();}
  virtual Dir get_dir_next();
  void set_raw_pos_next(const Pos &rpos) {Moving::set_raw_pos_next(rpos);}
  WorldP get_world() {return Moving::get_world();}
  void _set_middle_next(const Pos &pos) {Moving::_set_middle_next(pos);}
  virtual void update_area_next(Boolean currentAndNext);


private:
  
  virtual Boolean stick_touching(Touching touching);
  /* EFFECTS: Should the Creature stick to walls in the specified direction. */

  static Dir compute_dir(const Stance &stance,const Vel &vel);
  /* USES: nothing */
  /* EFFECTS: Return the dir corresponding to stance and vel. */

  Boolean context_valid();

  void initialize_abilities(PtrList *caps);

  void check_abilities();

  ABBitField compute_abilities_bit_field();


  Touching touching;
  MoverId touchingMoverId;
  Hanging hanging;
  Boolean canClimb;
  Stance stance,stanceNext; 
  Grav grav,gravNext; 
  const CreatureContext *cc;
  Timer corpseTimer;
  Boolean wantClimb;  // actually, ALL climbing should be in Creature.
  //  Id killerId;   Now in Intel.
  time_t birthTime;
  static Stats stats;

  // If non-zero, indicates how many turns Creature should be stunned for.
  int stunNext; 
  Timer stunTimer;
  Timer alienImmune;

  ModifierP modifiers;

  // Could make this a PtrList to save space at the cost of lookup time.
  AbilityP abilities[AB_MAX];

// Don't cache, so we don't have to worry about maintaining the cache.
//  HolderP holder;
//  LocomotionP locomotion;
};
typedef Creature *CreatureP;


typedef AbilityP (*AbilityCreateFunctionType)(InStreamP,CreatureP);

class Ability {
public:
  Ability();

  virtual ~Ability();

  Ability(InStreamP,CreatureP);
  /* EFFECTS: Stream ctor. */

  virtual void initialize(CreatureP);
  /* EFFECTS: Called immediately after Creature has finished constructing itself.
     Pass in the Creature. */
  /* NOTE: This is not used for the stream constructor. */

  virtual void update_from_stream(InStreamP in);
  /* DEFAULT: do nothing */

  virtual int get_write_length();
  /* DEFAULT: return 0 */

  virtual void write(OutStreamP);
  /* DEFAULT: do nothing */


  virtual AbilityId get_ability_id() = 0;

  virtual Boolean is_holder();
  /* DEFAULT: False */

  virtual Boolean is_locomotion();
  /* DEFAULT: False */
  
  virtual Boolean is_composite();
  /* DEFAULT: False */

  virtual Boolean get_pixmap_mask(Xvars &,int dpyNum,CMN_IMAGEDATA &,Dir,int);
  virtual Boolean get_size_offset_next(Size &size,Size &offset,Dir dirNext);
  /* DEFAULT: return False */

  virtual ClassId get_weapon_string(const char *&str);
  /* MODIFIES: str */
  /* DEFAULT: return A_None */
  /* NOTE: Must only modify str if something other than A_None is 
     returned. */

  virtual void drop_all();
  /* DEFAULT: do nothing */  

  virtual void get_followers(PtrList &list);
  /* DEFAULT: do nothing */

  virtual Boolean follow(const Area &followeeArea,Dir followeeDir,
                         Boolean currentAndNext);
  /* DEFAULT: return False */

  virtual Boolean command_repeatable(ITcommand);
  /* DEFAULT: True. */

  virtual int get_drawing_level();
  /* EFFECTS: Return the drawing level if the Ability wants to override the
     Creature's behavior, else return -1. */
  /* DEFAULT: return -1 */

  virtual int get_anim_time();
  /* EFFECTS: Return the anim time if the Ability wants to override the
     Creature's behavior, else return -1. */
  /* DEFAULT: return -1 */

  virtual Boolean heat_attack(PhysicalP killer,int heat,Boolean secondary);
  /* DEFAULT: return False */

  virtual Boolean swap_protect();
  /* DEFAULT: return False */

  virtual Boolean frog_protect();
  /* DEFAULT: return False */
  
  virtual void set_intel(IntelP i);
  /* DEFAULT: do nothing. */

  virtual void heal();
  /* DEFAULT: do nothing */

  virtual void set_mapped_next(Boolean val);
  /* DEFAULT: do nothing */

  virtual void act();
  /* DEFAULT: do nothing */

  virtual void update();
  /* DEFAULT: do nothing */

  virtual void die();
  /* NOTE: Also called when the ability is removed from a Creature. */  
  /* DEFAULT: do nothing */

  virtual Boolean collide(PhysicalP other);
  /* DEFAULT: return False */

  virtual Boolean stick_touching(Touching touching);
  /* EFFECTS: Does this Ability explicitly give the ability to stick when 
     touching in the specified direction.  False means no extra ability is 
     granted. */     
  /* DEFAULT: return False */

  static void register_abilities();
  /* EFFECTS: Must be called before any abilities have been read from stream. */

  static AbilityP create_from_stream(InStreamP in,AbilityId aId,CreatureP);
  /* EFFECTS: Create and initialize() an ability of type aId from the stream.  
     The ability will be used for the given Creature. */


#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
  CreatureP cre; // short for easy use.

  // Static list of all create_from_stream() functions.
  static AbilityCreateFunctionType create_function[AB_MAX];
};



///////// Locomotion
// Gives the ability to move in some fashion.
class Locomotion: public Ability {
public:
  Locomotion();
  Locomotion(InStreamP,CreatureP);

  virtual Boolean is_locomotion();
};



///////// Grounded
// Sticks to the ground only.  Affected by gravity.  Can't climb or jump. 
struct GroundedContext {
  int dummy;
}; 


struct GroundedXdata {};


class Grounded: public Locomotion {
 public:
  Grounded(const GroundedContext &,GroundedXdata &);

  DECLARE_NULL_ABILITY_IO(Grounded);
  
  virtual AbilityId get_ability_id();

  virtual void act();

  static GroundedContext defaultContext;
  static GroundedXdata defaultXdata;
};



//////// Suicide
// Kills self if the command IT_ITEM_USE is seen.
struct SuicideContext {
  int dummy;
};


struct SuicideXdata {};


class Suicide: public Ability {
 public:
  Suicide(const SuicideContext &,SuicideXdata &);

  DECLARE_NULL_ABILITY_IO(Suicide);

  virtual AbilityId get_ability_id();
  
  virtual void act();

  static SuicideContext defaultContext;
  static SuicideXdata defaultXdata;
};



////////// Hopping
// Parent: Creature
// 
struct HoppingContext {
  int dummy;
}; 


struct HoppingXdata {};


class Hopping: public Locomotion {
 public:
  Hopping(const HoppingContext &,HoppingXdata &);

  DECLARE_NULL_ABILITY_IO(Hopping);
  
  virtual AbilityId get_ability_id();

  virtual void act();

  static HoppingContext defaultContext;
  static HoppingXdata defaultXdata;
};



///////// Holder
// Can hold weapons and/or items.
class Holder: public Ability {
public:
  Holder();
  Holder(InStreamP,CreatureP);

  virtual Boolean is_holder();

  virtual int get_weapons_num() = 0;
  virtual int get_items_num() = 0;
  /* NOTE: Returned value is not valid after current turn. */
  
  virtual PhysicalP get_weapon(int) = 0;
  virtual PhysicalP get_item(int) = 0;
  virtual PhysicalP get_weapon_current() = 0;
  virtual PhysicalP get_item_current() = 0;
  /* NOTE: Can return NULL. */
  /* IMPLEMENTATION: get_item_current() should try to return non-NULL if 
     get_items_num() is > 0.  Unlike weapons, there should always be an
     item ready if possible.  We don't quite live up to this right now, as
     User and Carrier count the items in act() when they should do it in
     update() to see if any items have been killed that turn. */

  virtual int get_item_count() = 0;
  /* EFFECTS: If get_item() is non-NULL, return the number of that item
     the Physical is carrying.  Elese return 0. */

  // already has get_weapon_string.

  Boolean ok_to_hold(PhysicalP other);
  /* EFFECTS: Checks a) cre is alive
                     b) other is an Item and can_take()
                     c) no conflicts with other Abilities (important).
   */
  /* NOTE: Now is public, so OnFire knows not to burn stuff. */
};



////////// User
// Holds and uses items and weapons.  The items and weapons are made to follow
// the User. 
struct UserContext {
  Boolean usesWeapons;
  Boolean usesItems;
};  


struct UserXdata {};


class User: public Holder {
public:
  User(const UserContext &,UserXdata &);

  DECLARE_ABILITY_IO(User);

  virtual AbilityId get_ability_id();

  virtual int get_weapons_num();
  virtual int get_items_num(); 
  /* NOTE: Returned value is not valid after current turn. */
  
  virtual PhysicalP get_weapon(int);
  virtual PhysicalP get_item(int); 
  virtual PhysicalP get_weapon_current();
  virtual PhysicalP get_item_current();
  /* NOTE: Can return NULL. */

  virtual int get_item_count();

  virtual ClassId get_weapon_string(const char *&str);
  /* EFFECTS: str is set to point to a static string containing the string
     for ClassId. */

  virtual void get_followers(PtrList &list);

  virtual Boolean command_repeatable(ITcommand c);

  virtual void set_mapped_next(Boolean val);
  /* EFFECTS: Bring current weapon in/out of scope and then change mapped. */

  virtual void drop_all();

  virtual void act();

  virtual void update();

  virtual Boolean collide(PhysicalP);

  virtual void die();

  static UserContext defaultContext;
  static UserXdata defaultXdata;


private:
  Boolean has_weapon(Weapon **weapon,ClassId classId);
  /* MODIFIES: weapon */
  /* EFFECTS: Like has_weapon(ClassId) except will return the 
     weapon in weapon if not NULL. */

  int coolest_weapon();
  /* EFFECTS: Return index of weapon with highest coolness or weaponsNum if 
     builtIn weapon is coolest.  Only consider weapons with nonNegative 
     coolness. */

  int coolest_item();
  /* EFFECTS: Return index of coolest item or itemsNum. */

  int next_coolest_weapon();
  /* EFFECTS: Return the coolest weapon (or builtIn weapon) that is less cool
     than the current weapon. Can be non-negative coolness.  If none found, 
     return coolest_weapon(). */

  int next_coolest_item();
  /* EFFECTS: Return coolest item less cool than current item.  Cycle around
     to coolest_item() if none found. */

  //  int defaultable_weapon();
  /* REQUIRES: weaponsNum and weapons are properly updated. */
  /* EFFECTS: Returns the index of a wepon in weapons that is defaultable or
     weaponsNum if there is none. */

  void weapon_use(ITcommand command);
  void weapon_change();
  void weapon_drop();
  void item_use();
  void item_change();
  void item_drop();
  /* NOTE: Called in User::_act(). */

  int item_class_count(ClassId);
  /* EFFECTS: Returns the number of items held of the given class. */

  Id weapons[PH_WEAPONS_MAX];
  int weaponsNum;
  // weaponCurrent == weaponsNum if using builtIn weapon or no weapon.
  int weaponCurrent; 
  // If weaponCycleTimer is not ready(), cycle to next weapon on IT_WEAPON_CHANGE.
  // If ready(), start again from coolest_weapon().
  Timer weaponCycleTimer;
  //  Memory of previous weapon dir is now in ui.

  Id items[PH_ITEMS_MAX];
  int itemsNum;
  // itemCurrent == itemsNum if no selected item.
  int itemCurrent; 
  // Like weaponCycleTimer.
  Timer itemCycleTimer;
  // How many of the current item the User has.
  int itemCount,itemCountNext;
  
  const UserContext *context;
};
typedef User *UserP;



////////// Carrier
// Holds one item or weapon.  The items and weapons are made to follow
// the Carrier.  Can use items, but not weapons. 
struct CarrierContext {
    int dummy; 
};


struct CarrierXdata {};


class Carrier: public Holder {
public:
  Carrier(const CarrierContext &,CarrierXdata &);

  DECLARE_NULL_ABILITY_IO(Carrier);
  
  virtual AbilityId get_ability_id();

  virtual int get_weapons_num();
  virtual int get_items_num(); 
  /* NOTE: Returned value is not valid after current turn. */
  
  virtual PhysicalP get_weapon(int);
  virtual PhysicalP get_weapon_current(); 
  virtual PhysicalP get_item(int); 
  virtual PhysicalP get_item_current();
  /* NOTE: Can return NULL. */

  virtual int get_item_count();

  virtual void get_followers(PtrList &list);
  
  virtual void drop_all();

  virtual void act();

  virtual Boolean collide(PhysicalP);

  virtual void die();

  static CarrierContext defaultContext;
  static CarrierXdata defaultXdata;


private:
  Boolean hasItem;
  Id item;
};
typedef Carrier *CarrierP;



////////// Fighter
// Can attack in different directions.
struct FighterContext {
  CMN_COLOR foreground;  // default = black
  CMN_COLOR background;  // default = white
  int slide;
  int jumpHorizontal;
  int jumpVertical;
  int damageStuck;
  int damageFree;

  Size hotSpots[CO_DIR_MAX];  // Must add in offset to use.
  SoundName attackSound;
};


// Bitmaps stored in FighterXdata have all moved to MovingXdata.
struct FighterXdata {};


class Fighter: public Ability {
public:
  Fighter(const FighterContext &f_c,FighterXdata &x_data);
  /* NOTE: This is currently the only Ability that uses its xdata.  Also, 
     the only one
     that needs the correct context if we are a Client. */

  DECLARE_ABILITY_IO(Fighter);

  virtual void initialize(CreatureP);

  virtual AbilityId get_ability_id();

  virtual Boolean get_pixmap_mask(Xvars &,int dpyNum,CMN_IMAGEDATA &imageData,
                               Dir dir,int animNum);
  
  virtual Boolean get_size_offset_next(Size &size,Size &offset,Dir dirNext);

  virtual ClassId get_weapon_string(const char *&str);

  virtual void act();

  virtual void update();

  virtual Boolean collide(PhysicalP);

  static Touching offset_generator(Dir);
  /* EFFECTS: Used to modify the way Moving generates offsets.  It takes
     into account the mapping of dir to attackDir, i.e. holding the attacking
     pixmaps in unused slots in MovingContext. */
  /* NOTE: All classes that have the fighter ability must have 
     Fighter::offset_generator as the value of MovingContext::offsetGenerator.
     This will cause problems if we want to be able to dynamically add
     or remove the Fighter Ability to/from a creature.  Fix it when it
     comes up. */

  static TransformMap transformOverride;
  /* EFFECTS: Similar to offset_generator in that it overrides behavior in 
     Moving to deal with the mapping of dir to attackDir.  In this case it is 
     needed to provide info about which bitmaps are transformations of other 
     bitmaps. */
  static TransformMap uprightTransformOverride;


private:
  static Attack dir_to_attack(Dir dir);

  static Dir dir_to_attack_dir(Dir dir);
  /* REQUIRES: dir has a corresponding attack dir */
  /* EFFECTS: Returns the dir used to store the attacking pixmaps given
     the non-attacking dir. */

  static Boolean is_attack_dir(Dir dir);

  static Dir attack_dir_to_dir(Dir dir);
  /* REQUIRES: dir is an attack dir */
  /* EFFECTS: Inverse of dir_to_attack_dir. */

  void attack_stuck(Dir dir,Stance stance);
  void attack_free_horizontal(Dir dir);
  /* NOTE: Does not zero vertical velocity. */

  void attack_free_vertical(Dir dir);
  /* NOTE: Vertical velocity only. */

  static const FighterContext *lookup_context(ClassId);
  /* NOTE: Fighter has its own functional registry of all Fighters in the 
     system. Not very extendable right now.  Would have to be redone for 
     templates. */
  static FighterXdata defaultXdata;

  const FighterContext *fc;
  Attack attack, attackNext;
  Timer stuckTimer;
};



////////// Walking
// Sticks to the ground only.  Affected by gravity.
struct WalkingContext {
  int dummy;
}; 


struct WalkingXdata {};


class Walking: public Locomotion {
public:
  Walking(const WalkingContext &,WalkingXdata &);

  DECLARE_NULL_ABILITY_IO(Walking);
  
  virtual AbilityId get_ability_id();

  virtual void act();

  static WalkingContext defaultContext;
  static WalkingXdata defaultXdata;


private:
  Pos rawPosPrev;
  Vel velPrev;
};



////////// Sticky
// Sticks to and walks on flat surfaces in four directions.  Affected by 
// gravity.
struct StickyContext {
  Speed wallCrawlSpeed;
};  


struct StickyXdata {};


class Sticky: public Locomotion {
public:
  Sticky(const StickyContext &,StickyXdata &);

  DECLARE_NULL_ABILITY_IO(Sticky);
  
  virtual void initialize(CreatureP);

  virtual AbilityId get_ability_id();

  virtual Boolean stick_touching(Touching touching);

  virtual void act();

  Speed get_wall_crawl_speed() {return context->wallCrawlSpeed;}
  /* EFFECTS: Returns the maximum speed for crawling on walls and 
     ceiling. */  

  static Boolean has_required_frames(const MovingContext *);
  /* EFFECTS: Does a Creature with the given MovingContext have all the 
     animation frames needed for the Sticky Ability. */
  
  static StickyContext defaultContext;
  static StickyXdata defaultXdata;
  /* NOTE: Just dummies to create object from a stream. */


#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
  Boolean want_corner(const Corner &corner);
  /* EFFECTS: Returns True if the object should go around the given corner,
     False otherwise.  corner is the initial, not final corner.*/

  Stance cornered_stance(const Hanging &h);
  /* EFFECTS: Returns the stance to take in order to go around the corner
     of h. */

  void set_want_corner(const Corner &c1) 
    {wantCorner1 = c1; wantCorner2 = CO_air;}
  void set_want_corner(const Corner &c1,const Corner &c2) 
    {wantCorner1 = c1; wantCorner2 = c2;}
  /* EFFECTS: Tell the object that it should go around a corner if possible.
     The given values are in effect until changed. */
  /* NOTE: set_want_corner(CO_air) should be used to disable cornering. */


private:
  ///// DISABLED
  void set_dont_attach(Boolean val) {dontAttach = val;}
  Boolean get_dont_attach() {return False; /* dontAttach; */}
  /* NOTE: We may want to make these virtual or methods of Creature
     later on. */
  
  Corner wantCorner1,wantCorner2;
  Boolean dontAttach;

  const StickyContext *context;
};



////////// Flying
// Floats around.  Can walk on the ground.
struct FlyingContext 
{
  int gravTime;
};  

struct FlyingXdata {};

class Flying: public Locomotion {
public:
  Flying(const FlyingContext &,FlyingXdata &);
  
  DECLARE_NULL_ABILITY_IO(Flying);
  
  virtual AbilityId get_ability_id();

  virtual void act();

  static FlyingContext defaultContext;
  static FlyingXdata defaultXdata;


private:
  Timer gravTimer;
  const FlyingContext *context;
};



////////// BuiltIn
// Has a directional built in weapon.
// NOTE: BuiltIn depends on existence of Holder, in act() and 
// get_weapon_string().
struct BuiltInContext {
  int shotTime;
  ClassId weaponClassId;
  const char *weaponStr;
  int coolness; // of the builtIn weapon.
  SoundName attackSound;

  Size (*get_shot_size)(Dir);
  PhysicalP (*create_shot)(WorldP,LocatorP,const Pos &,const Id &shooter,Dir);
  Dir (*compute_weapon_dir)(ITcommand); // may be NULL.
};  


struct BuiltInXdata {};


class BuiltIn: public Ability {
public:
  BuiltIn(const BuiltInContext &,BuiltInXdata &);
  /* NOTE: Must pass in static functions for get_shot_size, create_shot, and
     compute_weapon_dir.  compute_weapon_dir may be NULL, BuiltIn will use the
     default. */
  
  DECLARE_NULL_ABILITY_IO(BuiltIn);
  
  virtual AbilityId get_ability_id();

  virtual ClassId get_weapon_string(const char *&str);
  /* EFFECTS: str is set to point to a static string containing the string
     for ClassId. */

  virtual void act();

  int get_weapon_coolness() {return context->coolness;}
  /* EFFECTS: Return the coolness of the built-in weapon. */

  Boolean ready();
  /* EFFECTS: Is the BuiltIn ready to fire. */
  /* NOTE: This is not overriding any parent's ready() method anymore. */

  static BuiltInContext defaultContext;
  static BuiltInXdata defaultXdata;



private:
#if 0
  virtual Dir compute_weapon_dir(ITcommand);
  /* EFFECTS:  Returns the direction the weapon should be fired, 
     {CO_R ... CO_UP_R}, or CO_air. */

  virtual Size get_shot_size(Dir) = 0;

  virtual PhysicalP create_shot(const Pos &,Dir) = 0;
#endif

  Timer shotTimer;
  const BuiltInContext *context;
};
typedef BuiltIn *BuiltInP;



////////// Hugger
// Hugs onto any creature it collides with (except A_Alien and A_Hugger)
// and stuns them, then turns them into an Alien.
struct HuggerContext {
  // Which intel, the hugger's or the huggee's intel is implanted in the new
  // Alien.
  Boolean useHuggeeIntel; 
};  


struct HuggerXdata {};


class Hugger: public Ability {
public:
  Hugger(const HuggerContext &,HuggerXdata &);

  DECLARE_NULL_ABILITY_IO(Hugger);
  
  virtual AbilityId get_ability_id();

  virtual int get_drawing_level();

  virtual void act();

  virtual Boolean collide(PhysicalP other);

  static HuggerContext defaultContext;
  static HuggerXdata defaultXdata;


private:
  Id huggeeId;
  const HuggerContext *context;
};



///////// Prickly
// Hurts anything it touches.
struct PricklyContext {
  int damage;
};


struct PricklyXdata {};


class Prickly: public Ability {
public:
  Prickly(const PricklyContext &,PricklyXdata &);
	
  DECLARE_NULL_ABILITY_IO(Prickly);
  
  virtual AbilityId get_ability_id();

  virtual ClassId get_weapon_string(const char *&str);

  virtual Boolean collide(PhysicalP);

  static PricklyContext defaultContext;
  static PricklyXdata defaultXdata;
  

private:
  const PricklyContext *context;
};



///////// Healing
// Heals up to twice its minimum ever damage.
struct HealingContext
{
	float multiplier;
	int unit;
	int time;
};

// Not used now.
struct HealingXdata {};

class Healing: public Ability {
public:
  Healing(const HealingContext &,HealingXdata &);
  // Ignores the HealingXdata parameter.  Important for AltarOfSin.

  DECLARE_NULL_ABILITY_IO(Healing);

  virtual void initialize(CreatureP);
  
  virtual AbilityId get_ability_id();
  
  virtual void heal();
  
  virtual void act();

  static HealingContext defaultContext;
  static HealingXdata defaultXdata;


private:
	Timer healTimer;
	Health healthMin;
	const HealingContext *context;
};



///////// Lifter
// Can lift Liftables if there is no current weapon.
struct LifterContext {
  int throwSpeed;  // 0 means the Lifter can't throw
};


struct LifterXdata {};


class LifterSpeedModifier : public Modifier {
public:
  LifterSpeedModifier();

  virtual ModifierId get_modifier_id();
  
  virtual int apply(Attribute attr,int startVal);

   void set_lifting(Boolean val) {lifting = val;}
  /* NOTE: Lifter sets data on LifterSpeedModifier instead of vice-versa
     because we can't easily cast a Physical to a Lifter.  C++ virtual 
     base class bullshit. */
  /* NOTE about NOTE: We could fix this now with our Ability architecture. */


private:
  Boolean lifting;
};


class Lifter: public Ability {
public:
  Lifter(const LifterContext &,LifterXdata &);

  DECLARE_NULL_ABILITY_IO(Lifter);

  virtual void initialize(CreatureP);
  
  virtual AbilityId get_ability_id();

  virtual ClassId get_weapon_string(const char *&str);

  virtual void act();
  /* NOTE: Make Liftable follow Lifter. */

  virtual Boolean collide(PhysicalP);

  Boolean is_lifting();

  static LifterContext defaultContext;
  static LifterXdata defaultXdata;


private:
  void drop_liftable(PhysicalP liftable);

  void throw_liftable(PhysicalP liftable,Dir);

  Id liftable; // lifting something iff this is valid.
  ModifierP speedModifier; // cleaned up by Creature.
  const LifterContext *context;
};
typedef Lifter *LifterP;



///////// Morphed
// Some other object was morphed into this one.  Will revert back to the
// original one after some time.
struct MorphedContext
{
  int revertTime;
};

struct MorphedXdata {};

class Morphed: public Ability {
public:
  Morphed(const MorphedContext &,MorphedXdata &,PhysicalP);

  DECLARE_NULL_ABILITY_IO(Morphed);
  
  virtual AbilityId get_ability_id();

  virtual void get_followers(PtrList &list);
  
  virtual void drop_all();

  virtual void act();

  virtual void die();

  static MorphedContext defaultContext;
  static MorphedXdata defaultXdata;


private:
  Boolean unmappedSet;
  Id unmapped;
  Timer timer; // Only meaningful if unmappedSet.
};



///////// AnimTime
// Something with other than MOVING_ANIM_TIME
struct AnimTimeContext {
  int animTime;
}; 

struct AnimTimeXdata {};

class AnimTime: public Ability {
public:
  AnimTime(const AnimTimeContext &,AnimTimeXdata &);

  DECLARE_NULL_ABILITY_IO(AnimTime);
  
  virtual void initialize(CreatureP);
  
  virtual AbilityId get_ability_id();

  virtual int get_anim_time();

  static const AnimTimeContext *lookup_context(ClassId);
  static AnimTimeXdata defaultXdata;


private:
  const AnimTimeContext *context;    
};



///////// OnFire
// Constantly spouting flames, resistant to heat attacks, burns those that
// touch it.
struct OnFireContext {
  int fires;  // How many Fire objects are created per turn.
  int heat;
  Boolean deadBurns; // Does a dead object burn.
}; 

struct OnFireXdata {};

class OnFire: public Ability{
public:
  OnFire(const OnFireContext &,OnFireXdata &);

  DECLARE_NULL_ABILITY_IO(OnFire);
  
  virtual AbilityId get_ability_id();

  virtual Boolean heat_attack(PhysicalP,int heat,Boolean secondary);

  virtual void act();

  virtual Boolean collide(PhysicalP other);

  static OnFireContext defaultContext;
  static OnFireXdata defaultXdata;


private:
  const OnFireContext *context;
};



///////// SwapProtect
// Has limited protection from swap attacks.  Unlimited protection from Frog attacks.
//
struct SwapProtectContext {
  int swapResistance;
}; 

struct SwapProtectXdata {};

class SwapProtect: public Ability {
public:
  SwapProtect(const SwapProtectContext &,SwapProtectXdata &);

  DECLARE_NULL_ABILITY_IO(SwapProtect);
  
  virtual AbilityId get_ability_id();

  virtual Boolean swap_protect();

  virtual Boolean frog_protect();

  static SwapProtectContext defaultContext;
  static SwapProtectXdata defaultXdata;


private:
  int swapResistance;
};



///////// Composite
// A set of creatures that act like a single creature.
//
class Composite: public Ability {
public:
  Composite();
  Composite(InStreamP,CreatureP);

  Boolean is_composite();

  virtual Boolean is_leader() = 0;
  /* EFFECTS: Is this object the leader of the rest of the objects. */

  CompositeId get_composite_id() {return compositeId;}

  void set_composite_id(CompositeId cId) {compositeId = cId;}

  virtual PhysicalP get_draw_before_me();
  /* DEFAULT: return NULL */
  /* EFFECTS: Override this to control the drawing order of the Composite
     object. Return an object that must be drawn before this one. */

  static void reset_id_generator() {idGenerator = 0;}

#if 0
  static CompositeId extract_composite_id(PhyscialP p);
  /* EFFECTS: Helper function to get the compositeId from a physical, or return
     COMPOSITE_ID_NONE, if p is not a Composite object. */
#endif


#ifndef PROTECTED_IS_PUBLIC
protected:
#endif 
  static CompositeId generate_id() {return idGenerator++;}
  /* EFFECTS: Create a unique CompositeId for a new composite object. */


private: 
  CompositeId compositeId;
  static CompositeId idGenerator;
};



///////// Segmented
// One segment of a segmented composite creature.  Acts like the head if
// it is the first in the chain.
//
// Use it by fully creating each Creature segment, then link them together.
//
struct SegmentedContext {
  int followDistance;
}; 

struct SegmentedXdata {};

class Segmented: public Composite {
public:
  Segmented(const SegmentedContext &,SegmentedXdata &);

  DECLARE_ABILITY_IO(Segmented);
  /* EFFECTS: Write out prev and next, so can draw properly. */  

  virtual AbilityId get_ability_id();

  virtual void get_followers(PtrList &list);

  virtual Boolean follow(const Area &followeeArea,Dir followeeDir,
                         Boolean currentAndNext);

  virtual Boolean get_pixmap_mask(Xvars &,int dpyNum,CMN_IMAGEDATA &imageData,
                                  Dir dir,int animNum);
  /* EFFECTS: Used to decide whether to draw the head or not. */

  virtual void set_intel(IntelP i);
  /* NOTE: All the intel's in the chain must be consistent. */

  virtual void act();

  virtual void update();

  virtual Boolean is_leader();

  virtual PhysicalP get_draw_before_me();

  Id get_prev() {return prev;}
  Id get_next() {return next;}
  /* EFFECTS: Search through chain of segments. */

  static void create_and_add_composite(PtrList &ret,
    WorldP,LocatorP,int segmentsNum,const Pos &,
    PhysicalP (*create)(void *arg,WorldP w,LocatorP l,const Pos &pos),
    void *arg);
  /* MODIFIES: ret */
  /* REQUIRES: create() creates something that has the Segmented ability. */
  /* EFFECTS: Create a Composite object as a chain of Segments.
     Add all segments to the locator. Fill ret with all the Physicals of 
     the chain,
     with the head in element 0. */
  /* NOTE: Must return all segments in ret, since we can't traverse the 
     segments via their Id's 
     until after the first Locator::clock(). */

  static SegmentedContext defaultContext;
  static SegmentedXdata defaultXdata;


private:
  // Where to store the bitmaps in MovingContext.
  enum {
    LEADER_DIR = CO_DN_R_R,
    LEADER_ANIM_TIME = 4,
  };
  
  void insert_before(CreatureP c);
  /* REQUIRES: c must have the Segmented Ability. */
  /* EFFECTS: Insert this object in the chain before c. */

  Boolean compatible_prev(PhysicalP);
  Boolean compatible_next(PhysicalP);
  /* EFFECTS: Is the object a compatible member of this composite object. */

  void assume_leadership();
  /* EFFECTS: Called when a non-leader becomes a leader. Not called in
     the constructor for a leader. */

  void map_dir_anim_num(Dir& mappedDir,int& mappedAnimNum,Dir dir,int animNum);
  /* MODIFIES: mappedDir, mappedAnimNum */
  /* EFFECTS: Get the direction and animNum to use to actually display
     the head, body, or dead pixmap. */


  // These should be separated into current and next variables.
  Boolean isLeader;
  Id prev;
  Id next;
  Timer leaderAnimTimer;
  int leaderAnimNum; // Chosen randomly.  Animation frame to use if leader.
  const SegmentedContext* context;
  // Use this followDistance, not the one in context.  So, that reading 
  // from stream works properly.
  int followDistance;
};
typedef Segmented* SegmentedP;



///////// Sensitive
// Sensitive to certain types of attacks, e.g. Yeti takes extra damage from
// heat attacks.  Not an ability you really want to have.  
struct SensitiveContext {
  int corporealMultiplier; // 0 means no change
  int heatMultiplier;  // 0 means no change
}; 

struct SensitiveXdata {};

class Sensitive: public Ability {
public:
  Sensitive(const SensitiveContext&,SensitiveXdata&);

  DECLARE_NULL_ABILITY_IO(Sensitive);
  /* EFFECTS: Write out prev and next, so can draw properly. */  

  virtual AbilityId get_ability_id();

//  virtual Boolean corporeal_attack(PhysicalP killer,int damage); 
// Implement it when we need it.

  virtual Boolean heat_attack(PhysicalP killer,int heat,Boolean secondary);

  static SensitiveContext defaultContext;
  static SensitiveXdata defaultXdata;


private:
  const SensitiveContext* context;  
};
typedef Sensitive* SensitiveP;
#endif