1; (define (troll-display . args)
2;   (display (kern-get-ticks))
3;   (display ":")
4;   (apply display args))
5; (define (troll-newline) (newline))
6
7(define (troll-display . args) )
8(define (troll-newline) )
9(define troll-melee-weapon t_horns)
10
11;;----------------------------------------------------------------------------
12;; Troll AI
13;;----------------------------------------------------------------------------
14(define (troll-is-critical? ktroll)
15  (< (kern-char-get-hp ktroll) 5))
16
17(define (troll-wander ktroll)
18  (troll-display "troll-wander")(troll-newline)
19  (wander ktroll))
20
21(define (troll-flee ktroll)
22  (troll-display "troll-flee")(troll-newline)
23  (flee ktroll))
24
25(define (troll-foes-in-weapon-range ktroll karms kfoes)
26  (troll-display "troll-foes-in-weapon-range")(troll-newline)
27  (all-in-range (kern-obj-get-location ktroll)
28                (kern-arms-type-get-range karms)
29                 kfoes))
30
31(define (weaker? a b)
32  (< (kern-char-get-hp a) (kern-char-get-hp b)))
33
34(define (troll-pick-target ktroll foes)
35  (troll-display "troll-pick-target")(troll-newline)
36  (foldr (lambda (a b) (if (weaker? a b) a b))
37         (car foes)
38         (cdr foes)))
39
40(define (troll-pathfind-foe ktroll foes)
41  (troll-display "troll-pathfind-foe")(troll-newline)
42  (let ((ktarg (troll-pick-target ktroll foes)))
43    (if (notnull? ktarg)
44        (pathfind ktroll (kern-obj-get-location ktarg)))))
45
46(define (troll-attack ktroll karms foes)
47  (troll-display "troll-attack")(troll-newline)
48  (kern-char-attack ktroll
49                    karms
50                    (troll-pick-target ktroll
51                                       foes)))
52
53;; Given an "origin" location and a list of locations, find the location in the
54;; list closest to the coordinates.
55(define (loc-closest origin lst)
56  (if (null? lst) nil
57      (foldr (lambda (a b) (if (loc-closer? a b origin) a b))
58             (car lst)
59             (cdr lst))))
60
61(define (troll-stronger? ktroll foes)
62  (> (kern-char-get-strength ktroll)
63     (foldr (lambda (a b) (+ a (kern-char-get-strength b)))
64            0
65            foes)))
66
67(define (troll-has-ranged-weapon? ktroll)
68  (in-inventory? ktroll troll-ranged-weapon))
69
70;; troll-get-ammo -- give troll a boulder and convert terrain to grass
71(define (troll-get-terrain-ammo ktroll coords)
72  (troll-display "troll-get-terrain-ammo")(troll-newline)
73  (kern-obj-add-to-inventory ktroll troll-ranged-weapon 1)
74  (kern-place-set-terrain coords t_grass)
75  (kern-map-repaint)
76  (kern-obj-dec-ap ktroll troll-ripup-boulder-ap)
77  )
78
79;; ----------------------------------------------------------------------------
80;; troll-get-loose-ammo -- search the objects at the location for ammo and give
81;; it to the th character
82;; ----------------------------------------------------------------------------
83(define (troll-get-loose-ammo ktroll loc)
84  (troll-display "troll-get-loose-ammo")(troll-newline)
85  (kobj-get-at ktroll loc troll-ranged-weapon))
86
87;; ----------------------------------------------------------------------------
88;; troll-terrain-is-ammo -- true iff the given location's terrain can be
89;; converted by a troll into ammo
90;; ----------------------------------------------------------------------------
91(define (troll-terrain-is-ammo? coords)
92  (eqv? t_boulder (kern-place-get-terrain coords)))
93
94;; ----------------------------------------------------------------------------
95;; troll-find-nearest-ammo -- return the closest location with ammo objects or
96;; with terrain that can be converted to ammo objects.
97;; ----------------------------------------------------------------------------
98(define (troll-find-nearest-ammo ktroll)
99  (troll-display "troll-find-nearest-ammo")(troll-newline)
100  (define (scanobjlst lst)
101    (foldr (lambda (a b)
102             (or a (eqv? (kern-obj-get-type b) troll-ranged-weapon)))
103           #f
104           lst))
105  (define (check lst loc)
106    (if (troll-terrain-is-ammo? loc)
107        (cons loc lst)
108        (if (scanobjlst (kern-get-objects-at loc))
109            (cons loc lst)
110            lst)))
111  (let* ((loc (kern-obj-get-location ktroll))
112         (rad (kern-obj-get-vision-radius ktroll))
113         (coords (profile foldr-rect (loc-place loc)
114                              (- (loc-x loc) (/ rad 2))
115                              (- (loc-y loc) (/ rad 2))
116                              (* 1 rad)
117                              (* 1 rad)
118                              check
119                              nil)))
120    (troll-display coords)(troll-newline)
121    (profile loc-closest loc coords)))
122
123(define (troll-find-nearest-ammo2 ktroll)
124  (troll-display "troll-find-nearest-ammo2")(troll-newline)
125  (let* ((loc (kern-obj-get-location ktroll))
126         (rad (kern-obj-get-vision-radius ktroll))
127         (coords (profile kern-search-rect (loc-place loc)
128                                   (- (loc-x loc) (/ rad 2))
129                                   (- (loc-y loc) (/ rad 2))
130                                   (* 1 rad)
131                                   (* 1 rad)
132                                   t_boulder
133                                   troll-ranged-weapon)))
134    (profile loc-closest loc coords)))
135
136(define (troll-find-nearest-ammo3 ktroll)
137  (troll-display "troll-find-nearest-ammo3")(troll-newline)
138  (define (scanobjlst lst)
139    (foldr (lambda (a b)
140             (or a (eqv? (kern-obj-get-type b) troll-ranged-weapon)))
141           #f
142           lst))
143  (define (check lst loc)
144    (if (troll-terrain-is-ammo? loc)
145        (cons loc lst)
146        (if (scanobjlst (kern-get-objects-at loc))
147            (cons loc lst)
148            lst)))
149  (let* ((loc (kern-obj-get-location ktroll))
150         (rad (kern-obj-get-vision-radius ktroll))
151         (coords (profile kern-fold-rect (loc-place loc)
152                          (- (loc-x loc) (/ rad 2))
153                          (- (loc-y loc) (/ rad 2))
154                          (* 1 rad)
155                          (* 1 rad)
156                          check
157                          nil)))
158    (troll-display coords)(troll-newline)
159    (profile loc-closest loc coords)))
160
161(define (troll-find-nearest-ammo4 ktroll)
162  (troll-display "troll-find-nearest-ammo4")(troll-newline)
163  (let* ((loc (kern-obj-get-location ktroll))
164         (rad (kern-obj-get-vision-radius ktroll))
165         (terrain-coords (profile kern-search-rect-for-terrain (loc-place loc)
166                                  (- (loc-x loc) (/ rad 2))
167                                  (- (loc-y loc) (/ rad 2))
168                                  (* 1 rad)
169                                  (* 1 rad)
170                                  t_boulder))
171         (closest-terrain (profile loc-closest loc terrain-coords))
172         (obj-coords (profile kern-search-rect-for-obj-type (loc-place loc)
173                              (- (loc-x loc) (/ rad 2))
174                              (- (loc-y loc) (/ rad 2))
175                              (* 1 rad)
176                              (* 1 rad)
177                              troll-ranged-weapon))
178         (closest-obj (profile loc-closest loc obj-coords)))
179    (cond ((null? closest-obj) closest-terrain)
180          ((null? closest-terrain) closest-obj)
181          (else
182           (if (loc-closer? closest-obj closest-terrain loc)
183               closest-obj
184               closest-terrain)))))
185
186;; ----------------------------------------------------------------------------
187;; troll-get-ammo -- given the location of an ammo object or terrain that can
188;; be converted to ammo, have the troll get the ammo
189;; ----------------------------------------------------------------------------
190(define (troll-get-ammo ktroll loc)
191  (troll-display "troll-get-ammo")(troll-newline)
192  (if (troll-terrain-is-ammo? loc)
193      (troll-get-terrain-ammo ktroll loc)
194      (troll-get-loose-ammo ktroll loc)))
195
196;; ----------------------------------------------------------------------------
197;; troll-hunt-for-ammo2 -- find the nearest available ammo and pathfind to it
198;; or pick it up. Returns false iff none available.
199;; ----------------------------------------------------------------------------
200(define (troll-hunt-for-ammo ktroll)
201  (troll-display "troll-hunt-for-ammo")(troll-newline)
202  (let ((nearest (profile troll-find-nearest-ammo2 ktroll))
203        (kloc (kern-obj-get-location ktroll)))
204    (troll-display "nearest=")(troll-display nearest)(troll-newline)
205    (if (null? nearest)
206        #f
207        (begin
208          (do-or-goto ktroll nearest troll-get-ammo)
209          #t))))
210
211(define (troll-display-objs lst)
212  (if (null? lst)
213      (troll-newline)
214      (begin
215        (troll-display (kern-obj-get-name (car lst)))
216        (troll-display " ")
217        (troll-display-objs (cdr lst)))))
218
219(define (troll-no-hostiles ktroll)
220  (troll-display "troll-no-hostiles")(troll-newline)
221  (troll-wander ktroll))
222
223(define troll-taunts
224  (list
225   "[primal howl]"
226   "[hateful roar]"
227   "[raging bellow]"
228   ))
229
230(define (troll-taunt ktroll ktarg)
231  (taunt ktroll ktarg troll-taunts)
232  (npcg-set-taunted! (gob ktroll) #t))
233
234(define (troll-hostiles ktroll foes)
235  (troll-display "troll-hostiles")(troll-newline)
236  (if (troll-is-critical? ktroll)
237      (troll-flee ktroll)
238      (let ((melee-targs (troll-foes-in-weapon-range ktroll
239                                                     troll-melee-weapon
240                                                     foes)))
241        (troll-display "troll-ai:melee-targs=")
242        (troll-display melee-targs)
243        (troll-newline)
244        (or (npcg-taunted? (gob ktroll))
245            (troll-taunt ktroll (car foes)))
246        (if (null? melee-targs)
247            (if (troll-has-ranged-weapon? ktroll)
248                (let
249                    ((ranged-foes
250                      (troll-foes-in-weapon-range ktroll
251                                                  troll-ranged-weapon
252                                                  foes)))
253                  (troll-display "troll-ai:ranged-foes=")
254                  (troll-display ranged-foes)
255                  (troll-newline)
256                  (if (null? ranged-foes)
257                      (troll-pathfind-foe ktroll foes)
258                      (troll-attack ktroll troll-ranged-weapon
259                                    ranged-foes)))
260                (or (troll-hunt-for-ammo ktroll)
261                    (troll-pathfind-foe ktroll foes)))
262            (if (troll-stronger? ktroll melee-targs)
263                (troll-attack ktroll troll-melee-weapon melee-targs)
264                (evade ktroll melee-targs))))))
265
266;; ----------------------------------------------------------------------------
267;; troll-ai -- combat ai for a troll npc. Called repeatedly by the kernel on
268;; the troll's turn until the troll is out of ap.
269;; ----------------------------------------------------------------------------
270(define (troll-ai ktroll)
271  (troll-display "troll-ai")(troll-newline)
272  (let ((foes (all-visible-hostiles ktroll)))
273    (if (null? foes)
274        (troll-wander ktroll)
275        (troll-hostiles ktroll foes))
276    #t))
277