-
Notifications
You must be signed in to change notification settings - Fork 1
/
logic.asm
323 lines (275 loc) · 5.57 KB
/
logic.asm
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
.model small
.386
include DOSSnake\const.inc
.data
random_seed dw 0
.code
;===========================
; Checks if some key pressed
;
; Output: ah - keycode
;===========================
GetchAsync proc near
mov ah, INT16_KEY_STATUS
int KEYBOARD_SERVICE
jz exit_getch ; No key pressed
mov ah, INT16_READ_CHAR
int KEYBOARD_SERVICE
exit_getch:
ret
GetchAsync endp
;================================
; Handles all movements
;
; Input: esi - snake head adress
; edx - Settings adress
; ah - pressed char
;================================
HandleMovements proc near
cmp ah, 4Bh
je turn_left
cmp ah, 4Dh
je turn_right
cmp ah, 48h
je turn_up
cmp ah, 50h
je turn_down
jmp move
turn_left:
cmp [edx].snake_direction, 1 ; If going right
je move
mov [edx].snake_direction, 0
jmp move
turn_right:
cmp [edx].snake_direction, 0 ; If going left
je move
mov [edx].snake_direction, 1
jmp move
turn_up:
cmp [edx].snake_direction, 3 ; If going down
je move
mov [edx].snake_direction, 2
jmp move
turn_down:
cmp [edx].snake_direction, 2 ; If going up
je move
mov [edx].snake_direction, 3
move:
cmp [edx].snake_direction, -1
je exit_handle_mov
call ShiftSnakeCells
inc word ptr [ebx]
cmp [edx].snake_direction, 0
je @move_left
cmp [edx].snake_direction, 1
je @move_right
cmp [edx].snake_direction, 2
je @move_up
jg @move_down
@move_left:
sub [esi].pos_x, VELOCITY_X
jmp exit_handle_mov
@move_right:
add [esi].pos_x, VELOCITY_X
jmp exit_handle_mov
@move_up:
sub [esi].pos_y, VELOCITY_Y
jmp exit_handle_mov
@move_down:
add [esi].pos_y, VELOCITY_Y
exit_handle_mov:
ret
HandleMovements endp
;==========================================
; Checks if head of a snake collided
; with a wall, apple or snake body
;
; Input: esi - adress of snake head
; edi - apple adress
; ebx - snake tail
; edx - Settings instance
;==========================================
CheckCollisions proc near
push edx
cmp [esi].pos_x, 0
jl collided_wall
cmp [esi].pos_x, SCREEN_WIDTH - CELL_SIZE
jg collided_wall
cmp [esi].pos_y, 0
jl collided_wall
cmp [esi].pos_y, SCREEN_HEIGHT - CELL_SIZE
jg collided_wall
mov ax, [esi].pos_x
sub ax, [edi].pos_x
cwd ;
xor ax, dx ; abs(ax)
sub ax, dx ;
cmp ax, CELL_SIZE
jge check_body_collision
mov ax, [esi].pos_y
sub ax, [edi].pos_y
cwd ;
xor ax, dx ; abs(ax)
sub ax, dx ;
cmp ax, CELL_SIZE - 1
jl collided_food
jmp check_body_collision
check_body_collision:
push edi
mov edi, esi
call CheckSnakeCollision
cmp ax, 1
je collided_itself
pop edi
jmp exit_check_collision
collided_itself:
pop edi
collided_wall:
pop edx
mov [edx].game_ended, 1
push edx
jmp exit_check_collision
collided_food:
pop edx
inc [edx].score
push edx
inc word ptr [ebx]
call GenerateApple
jmp exit_check_collision
exit_check_collision:
pop edx
ret
CheckCollisions endp
;==========================================
; Resets all game data
;
; Input: esi - adress of snake head
; edi - apple adress
; ebx - snake tail
; edx - Settings instance
;==========================================
ResetAllData proc near
; Settings
mov [edx].score, 0
mov [edx].game_ended, 0
mov [edx].snake_direction, -1
; Apple
mov [edi].pos_x, 10
mov [edi].pos_y, 10
;Snake tail
mov [ebx], 2
snake_clear_loop:
cmp [esi].pos_x, 0
je exit_reset
mov [esi].pos_x, 0
mov [esi].pos_y, 0
add esi, (type Cell)
jmp snake_clear_loop
exit_reset:
ret
ResetAllData endp
InitializeRandom proc near
mov Ah, 00h ; Interrupt to get system timer
int 1Ah
mov [random_seed], dx
ret
InitializeRandom endp
;=======================================================
; Private procedures
;=======================================================
;==========================================
; Checks if snake body collides with a cell
;
; Input: esi - snake head adress
; edi - cell adress to check collider
; ebx - snake tail adress
; Output: ax - 1 if collides, otherwise 0
;=========================================
CheckSnakeCollision proc near
push esi
push edx
mov cx, [ebx]
check_loop:
add esi, (type Cell)
dec cx
cmp cx, 0
jz not_collided
mov ax, [esi].pos_x
sub ax, [edi].pos_x
cwd ;
xor ax, dx ; abs(ax)
sub ax, dx ;
cmp ax, CELL_SIZE
jge check_loop
mov ax, [esi].pos_y
sub ax, [edi].pos_y
cwd ;
xor ax, dx ; abs(ax)
sub ax, dx ;
cmp ax, CELL_SIZE - 1
jl collided
jg check_loop
collided:
mov ax, 1
jmp exit_check_snake_collision
not_collided:
xor ax, ax
exit_check_snake_collision:
pop edx
pop esi
ret
CheckSnakeCollision endp
Randomize proc near
push cx
mov ax, 25173
mul word ptr [random_seed]
add ax, 13849
mov [random_seed], ax
pop cx
xor dx, dx
div cx
ret
Randomize endp
GenerateApple proc near
push ax
push bx
push edx
randomize_loop:
mov cx, SCREEN_WIDTH - CELL_SIZE
call Randomize
mov bx, dx
mov cx, SCREEN_HEIGHT - CELL_SIZE
call Randomize
mov [edi].pos_x, bx
mov [edi].pos_y, dx
call CheckSnakeCollision
cmp ax, 1
je randomize_loop
pop edx
pop bx
pop ax
ret
GenerateApple endp
ShiftSnakeCells proc near
push eax
push edi
mov edi, esi
xor eax, eax
mov ax, [ebx]
imul ax, (type Cell)
add edi, eax
shift_loop:
mov ax, [edi-(type Cell)].pos_x
mov [edi].pos_x, ax
mov ax, [edi-(type Cell)].pos_y
mov [edi].pos_y, ax
sub edi, (type Cell)
cmp edi, esi
jg shift_loop
dec word ptr [ebx] ; Removing tail
pop edi
pop eax
ret
ShiftSnakeCells endp
public GetchAsync, HandleMovements, CheckCollisions, InitializeRandom, ResetAllData
end