-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathai.s
295 lines (278 loc) · 5.32 KB
/
ai.s
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
; simple mob AI procedure
.include "global.inc"
.export mob_ai
mob_index = a2
mob_dir = a3
.segment "CODE"
; update mob pos randomly, and attack player
; moves towards player if can see
; NOTE: mobs see further than player, so its a little challenging
; todo bug when moving out of mob range?
.proc mob_ai
ldy #mob_size
mob_ai_loop:
sty mob_index
jsr is_alive
beq do_ai
jmp continue_mob_ai
do_ai:
; first check if can see player
lda mobs + Mob::coords + Coord::xcoord
sta xpos
lda mobs + Mob::coords + Coord::ycoord
sta ypos
jsr line_of_sight
bne move_random
jmp move_towards_player
move_random:
; move mob random dir
jsr d4
sta mob_dir
jsr try_move_dir
beq do_move
jmp continue_mob_ai
do_move:
lda mob_dir
jsr move_dir
continue_mob_ai:
ldy mob_index
tya
clc
adc #mob_size
tay
cmp #mobs_size
beq done_ai_loop
jmp mob_ai_loop
done_ai_loop:
rts
move_towards_player:
ldy mob_index
try_x:
lda mobs + Mob::coords + Coord::xcoord
cmp mobs + Mob::coords + Coord::xcoord, y
bcc try_left
cont_try_x:
lda mobs + Mob::coords + Coord::xcoord
cmp mobs + Mob::coords + Coord::xcoord, y
beq try_y
bcs try_right
jmp try_y
try_left:
lda #Direction::left
sta mob_dir
jsr try_move_dir
beq finish_move
; check for player
lda mob_dir
jsr player_at_dir
beq attack_player
; nope, continue trying
ldy mob_index
jmp cont_try_x
try_right:
lda #Direction::right
sta mob_dir
jsr try_move_dir
beq finish_move
; check for player
lda mob_dir
jsr player_at_dir
beq attack_player
; nope, continue trying
ldy mob_index
try_y:
lda mobs + Mob::coords + Coord::ycoord
cmp mobs + Mob::coords + Coord::ycoord, y
bcc try_up
cont_try_y:
lda mobs + Mob::coords + Coord::ycoord
cmp mobs + Mob::coords + Coord::ycoord, y
beq continue_mob_ai
bcs try_down
jmp continue_mob_ai
try_up:
lda #Direction::up
sta mob_dir
jsr try_move_dir
beq finish_move
; check for player
lda mob_dir
jsr player_at_dir
beq attack_player
; nope, continue trying
ldy mob_index
jmp cont_try_y
try_down:
lda #Direction::down
sta mob_dir
jsr try_move_dir
beq finish_move
; check for player
lda mob_dir
jsr player_at_dir
beq attack_player
; nope, continue trying
ldy mob_index
jmp continue_mob_ai
finish_move:
jmp do_move
attack_player:
; update mob direction
ldy mob_index
lda mob_dir
sta mobs + Mob::direction, y
; remember y to stack
tya
pha
; use damage calc for mob
damage = a1
jsr mob_dmg
ldy #0 ; player index
sta damage
.ifndef WIZARD
jsr damage_mob
.endif
; push message
lda #Messages::hurt
ldx damage
jsr push_msg
; check if player dead
ldy #0
jsr is_alive
bne player_dead
; done
pla
sta mob_index
jmp continue_mob_ai
player_dead:
; dead
pla
rts
; try to move in direction
;
; in: direction
; clobbers: xpos, ypos, x, and y
.proc try_move_dir
lda mob_dir
cmp #Direction::left
beq try_left
cmp #Direction::right
beq try_right
cmp #Direction::down
beq try_down
; up
try_up:
jsr update_pos
dec ypos
jmp is_passable
try_down:
jsr update_pos
inc ypos
jmp is_passable
try_right:
jsr update_pos
inc xpos
jmp is_passable
try_left:
jsr update_pos
dec xpos
jmp is_passable
update_pos:
ldy mob_index
lda mobs + Mob::coords + Coord::xcoord, y
sta xpos
lda mobs + Mob::coords + Coord::ycoord, y
sta ypos
rts
.endproc
; is player at direction?
;
; in: direction
; clobbers: xpos, ypos, x, and y
.proc player_at_dir
cmp #Direction::left
beq try_left
cmp #Direction::right
beq try_right
cmp #Direction::down
beq try_down
; up
try_up:
jsr update_pos
dec ypos
jmp compare_player
try_down:
jsr update_pos
inc ypos
jmp compare_player
try_right:
jsr update_pos
inc xpos
jmp compare_player
try_left:
jsr update_pos
dec xpos
jmp compare_player
compare_player:
lda xpos
cmp mobs + Mob::coords + Coord::xcoord
bne fail
lda ypos
cmp mobs + Mob::coords + Coord::ycoord
rts
fail:
rts
update_pos:
ldy mob_index
lda mobs + Mob::coords + Coord::xcoord, y
sta xpos
lda mobs + Mob::coords + Coord::ycoord, y
sta ypos
rts
.endproc
; finish move in direction, xpos and ypos should be set from
; try_move_dir
;
; in: direction
.proc move_dir
ldy mob_index
sta mobs + Mob::direction, y
lda ypos
sta mobs + Mob::coords + Coord::ycoord, y
lda xpos
sta mobs + Mob::coords + Coord::xcoord, y
rts
.endproc
.endproc
; should be called each time turn in order to spawn mobs randomly
.proc mob_spawner
; try to spawn a mob every 8 turns
lda turn
lsr
bcs skip_spawn
lsr
bcs skip_spawn
lsr
bcs skip_spawn
jmp attempt_spawn
skip_spawn:
; don't spawn a mob this turn
rts
attempt_spawn:
; loop through mobs and try to find an empty spot
ldy #mob_size
loop:
lda mobs + Mob::hp, y
beq spawn
tya
clc
adc #mob_size
tay
cpy #mobs_size
bne loop
; no empty spot for mob found
rts
spawn:
jsr rand_mob
rts
.endproc