-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsnake.asm
More file actions
2025 lines (1646 loc) · 29.8 KB
/
Copy pathsnake.asm
File metadata and controls
2025 lines (1646 loc) · 29.8 KB
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
model tiny
handler_key_direction macro direct, oposit
call get_snake_dir
cmp al, oposit
jz @@end
mov al, direct
mov [changed_direction], al
@@end:
endm
.code
org 100h
locals @@
_start:
call parse_args
call save_state
call set_params
call main
call load_prev_state
call end_prog
save_state proc
push ax
push di
push es
mov di, 0040h
mov es, di
mov di, 0062h
mov ah, byte ptr es:[di]
mov byte ptr [cur_page], ah
mov di, 0049h
mov ah, byte ptr es:[di]
mov byte ptr [cur_mode], ah
pop es
pop di
pop ax
ret
save_state endp
set_params proc
push ax
push bx
push cx
push di
push es
mov ah, 00h
mov al, work_mode
int 10h
mov ah, 05h
mov al, work_page
int 10h
pop es
pop di
pop cx
pop bx
pop ax
ret
set_params endp
main proc
push ax
call add_int_handlers
call init_game
@@game_loop:
call check_end_rule
cmp al, 0
jg @@end_loop
call handle_all_keys
mov al, [handle_tick]
cmp al, 0
jnz @@tick
hlt
jmp @@game_loop
@@tick:
call update_game_on_tick
cmp al, byte ptr[skip_update]
jl @@game_loop
xor al, al
mov [handle_tick], al
mov al, [on_pause]
cmp al, 1
jz @@after_update
call update_snake
@@after_update:
call draw_window
jmp @@game_loop
@@end_loop:
cmp al, state_hard_leave
jz @@end
;показ результатов
@@loop:
call handle_all_keys
mov al, [current_game_state]
cmp al, state_hard_leave
jnz @@loop
@@end:
call revert_int_handlers
pop ax
ret
main endp
load_prev_state proc
push ax
push bx
mov ah, 00h
mov al, [cur_mode]
int 10h
mov ah, 05h
mov al, [cur_page]
int 10h
pop bx
pop ax
ret
load_prev_state endp
end_prog proc
mov ax, 4c00h
int 21h
end_prog endp
;====================END_MAIN_CODE==========================
;=====================MAIN_LOGIC============================
init_game proc
push ax
push cx
push dx
push si
call srandsystime
mov dx, 0101h
call add_coordinate_to_buffer
mov dx, 0202h
call add_coordinate_to_buffer
mov dx, 0303h
call add_coordinate_to_buffer
mov ax, 0
call remove_coordinate_from_buffer
mov ax, 1
call remove_coordinate_from_buffer
mov ax, 0
call remove_coordinate_from_buffer
mov al, start_skip_upd
mov [skip_update], al
mov dx, 0000h
mov cx, game_field_height
mov al, cdWallVoltage
@@voltage:
call set_field_cell
inc dh
loop @@voltage ;стена с напряжением
xor dx, dx
inc dl
mov cx, game_field_width
sub cx, 2
mov al, cdWallTeleport
@@teleport1:
call set_field_cell
inc dl
loop @@teleport1 ;верхняя стена телепорта
mov dh, game_field_height
dec dh
mov dl, 1
mov cx, game_field_width
sub cx, 2
mov al, cdWallTeleport
@@teleport2:
call set_field_cell
inc dl
loop @@teleport2 ;нижняя стена телепорта
mov dl, game_field_width
dec dl
xor dh, dh
mov cx, game_field_height
mov al, cdWallRubber
@@rubber:
call set_field_cell
inc dh
loop @@rubber ;стена с отскоком
mov dx, 0101h
mov al, 1
call add_snake_head
call add_snake_seg
mov al, 2
call set_head_dir
call add_snake_seg
call add_snake_seg
call move_snake ;начальное положение змейки
xor al, al
call set_snake_on_field
call get_snake_dir
mov [changed_direction], al
xor ch, ch
mov cl, [started_add_seg]
mov al, cdAddSeg
call spawn_ardtefacts
mov cl, [started_damage]
mov al, cdDamage
call spawn_ardtefacts
mov cl, [started_dead]
mov al, cdDead
call spawn_ardtefacts ;начальный спавн артефактов
call draw_game_field
pop si
pop dx
pop cx
pop ax
ret
init_game endp
spawn_ardtefacts proc ;al - код артефакта, cx - количество артефактов
push cx
cmp cx, 0
jz @@end
@@loop:
call set_random_game_sell
loop @@loop
@@end:
pop cx
ret
spawn_ardtefacts endp
check_end_rule proc ;al - текущее состояние игры
push bx
mov al, [current_game_state]
cmp al, state_continue
jg @@end
mov bl, [current_len_snake]
cmp bl, 0
jnz @@next
mov al, state_lose
jmp @@end
@@next:
cmp bl, max_len_snake
jnz @@end
mov al, state_win
@@end:
pop bx
ret
check_end_rule endp
update_game_on_tick proc
push ax
xor al, al
mov [is_updated_on_cur_tick], al
pop ax
ret
update_game_on_tick endp
convert_to_field proc ;dl,dh - позиция на поле; ВЫХОД: di - указатель на эл. на поле
push ax
push dx
mov di, offset game_field
xor ax, ax
mov al, dh
mov dh, game_field_width
mul dh
add di, ax
xor dh, dh
add di, dx
pop dx
pop ax
ret
convert_to_field endp
get_field_cell proc ;dl,dh - позиция на поле; ВЫХОД: al - элемент поля
push di
call convert_to_field
mov al, [di]
pop di
ret
get_field_cell endp
set_field_cell proc ;dl,dh - позиция на поле, al - элемент поля
push di
call convert_to_field
mov [di], al
pop di
ret
set_field_cell endp
game_field_width equ 32
game_field_height equ 25
game_field db game_field_width * game_field_height dup(0)
;====================END_MAIN_LOGIC=========================
;==================RANDOM_FIELD_CELL========================
set_random_game_sell proc ;al - код добавляемого объекта
push ax
push bx
push dx
mov bl, al
mov al, [is_updated_on_cur_tick]
cmp al, 1
jz @@next
call fill_buffer_with_empty_cells
@@next:
mov ax, [len_game_sells]
cmp ax, 0
jz @@end
call randint
call get_coordinate_from_buffer
call remove_coordinate_from_buffer
mov al, bl
call set_field_cell
@@end:
pop dx
pop bx
pop ax
ret
set_random_game_sell endp
fill_buffer_with_empty_cells proc
push ax
push dx
call clear_sells_buffer
xor dx, dx
@@loop:
call get_field_cell
cmp al, cdEmpty
jnz @@continue
call add_coordinate_to_buffer
@@continue:
inc dl
cmp dl, game_field_width
jnz @@loop
xor dl, dl
inc dh
cmp dh, game_field_height
jnz @@loop
mov al, 1
mov [is_updated_on_cur_tick], al
pop dx
pop ax
ret
fill_buffer_with_empty_cells endp
add_coordinate_to_buffer proc ;dl,dh - координаты клетки
push ax
push si
mov ax, [len_game_sells]
call get_pointer_on_cell
mov [si], dl
mov [si + 1], dh
inc [len_game_sells]
pop si
pop ax
ret
add_coordinate_to_buffer endp
remove_coordinate_from_buffer proc ;ax - номер в массиве
push ax
push si
call get_pointer_on_cell
xor al, al
mov [si], al
mov [si + 1], al
add si, size_struct_sell
@@loop:
mov al, [si]
mov ah, [si + 1]
cmp al, 0
jnz @@next
cmp ah, 0
jnz @@next
jmp @@end
@@next:
mov [si - 2], al
mov [si - 1], ah
xor al, al
mov [si], al
mov [si + 1], al
add si, size_struct_sell
jmp @@loop
@@end:
dec [len_game_sells]
pop si
pop ax
ret
remove_coordinate_from_buffer endp
clear_sells_buffer proc
push ax
xor ax, ax
mov [len_game_sells], ax
pop ax
ret
clear_sells_buffer endp
get_coordinate_from_buffer proc ;ax - номер в массиве; ВЫХОД: dl,dh - координаты
push si
call get_pointer_on_cell
mov dl, [si]
mov dh, [si + 1]
pop si
ret
get_coordinate_from_buffer endp
get_pointer_on_cell proc ;ax - номер в массиве; ВЫХОД: si - указатель на координаты
push ax
shl ax, 1
mov si, offset sells_buffer
add si, ax
pop ax
ret
get_pointer_on_cell endp
size_struct_sell equ 2
is_updated_on_cur_tick db 0
len_game_sells dw 0
sells_buffer db size_struct_sell * game_field_width * game_field_height dup(0)
empty_sells db 0, 0
;================END_RANDOM_FIELD_CELL======================
;========================SNAKE==============================
update_snake proc
push ax
mov al, [changed_direction]
call set_head_dir
call move_snake_with_handle
pop ax
ret
update_snake endp
move_snake_with_handle proc
push ax
push bx
push dx
call get_cell_front_head
call get_field_cell
call get_handler_for_entity
xor al, al
cmp dx, 0
jz @@next
call dx
@@next:
mov ah, 1
call set_snake_on_field
cmp al, 1
jz @@next1
call move_snake
@@next1:
xor ah, ah
call set_snake_on_field
pop dx
pop bx
pop ax
ret
move_snake_with_handle endp
move_snake proc
push ax
push cx
push dx
push si
mov ah, [current_len_snake]
cmp ah, 0
jz @@end
dec ah
mov al, ah
call get_pointer_on_seg
@@loop:
cmp si, offset snake_array
jz @@move_head
mov dl, [si - 3]
mov dh, [si - 2]
mov al, [si - 1]
mov [si], dl
mov [si + 1], dh
mov [si + 2], al
sub si, size_snake_elem
jmp @@loop
@@move_head:
mov dl, [si]
mov dh, [si + 1]
mov al, [si + 2]
call offset_coordinate
mov [si], dl
mov [si + 1], dh
mov [si + 2], al
@@end:
pop si
pop dx
pop cx
pop ax
ret
move_snake endp
add_snake_seg proc
push ax
push dx
push si
mov ah, [current_len_snake]
dec ah
mov al, ah
call get_pointer_on_seg
mov dl, [si]
mov dh, [si + 1]
mov al, [si + 2]
call move_snake
add si, size_snake_elem
mov [si], dl
mov [si + 1], dh
mov [si + 2], al
inc [current_len_snake]
pop si
pop dx
pop ax
ret
add_snake_seg endp
add_snake_head proc ;dl,dh - координаты головы, al - направление движения
push di
mov di, offset snake_array
mov [di], dl
mov [di + 1], dh
mov [di + 2], al
inc [current_len_snake]
pop di
ret
add_snake_head endp
remove_last_seg proc
push ax
push si
mov al, [current_len_snake]
cmp al, 0
jz @@end
call get_pointer_on_last_seg
xor al, al
mov [si], al
mov [si + 1], al
mov [si + 2], al
dec [current_len_snake]
@@end:
pop si
pop ax
ret
remove_last_seg endp
remove_from_seg proc ;cl - с какого сегмента удалять элементы
push cx
mov ch, [current_len_snake]
cmp cl, ch
jz @@end
inc cl
@@loop:
mov ch, [current_len_snake]
cmp cl, ch
jz @@end
call remove_last_seg
jmp @@loop
@@end:
pop cx
ret
remove_from_seg endp
set_head_dir proc ;al - направление движения
push ax
push di
mov ah, [current_len_snake]
cmp ah, 0
jz @@end
mov di, offset snake_array
mov [di + 2], al
@@end:
pop di
pop ax
ret
set_head_dir endp
set_head_coordinate proc ;dl,dh - новые координаты
push di
mov di, offset snake_array
mov [di], dl
mov [di + 1], dh
pop di
ret
set_head_coordinate endp
get_cell_front_head proc ;ВЫХОД: dl,dh - координаты клетки, куда смотрит змейка
push ax
push si
mov si, offset snake_array
mov dl, [si]
mov dh, [si + 1]
mov al, [si + 2]
call offset_coordinate
pop si
pop ax
ret
get_cell_front_head endp
get_pointer_on_seg proc ;al - номер сегмента; ВЫХОД: si - указатель на сегмент
push ax
push bx
mov si, offset snake_array
xor ah, ah
mov bl, size_snake_elem
mul bl
add si, ax
pop bx
pop ax
ret
get_pointer_on_seg endp
get_pointer_on_last_seg proc ;ВЫХОД: si - указатель на последний сегмент
push ax
mov al, [current_len_snake]
cmp al, 0
jz @@next
dec al
@@next:
call get_pointer_on_seg
pop ax
ret
get_pointer_on_last_seg endp
set_snake_on_field proc ;ah (0 - рисовать змейку, 1 - затереть змейку)
push ax
push cx
push dx
push si
mov al, [current_len_snake]
cmp al, 0
jz @@end
call get_pointer_on_last_seg
cmp ah, 0
jz @@draw
mov al, cdEmpty
jmp @@after_draw
@@draw:
mov al, cdSnakeBody
@@after_draw:
xor ch, ch
mov cl, [current_len_snake]
@@loop:
mov dl, [si]
mov dh, [si + 1]
cmp ah, 1
jz @@next
cmp si, offset snake_array
jnz @@next
mov al, cdSnakeHead
@@next:
call set_field_cell
sub si, size_snake_elem
loop @@loop
@@end:
pop si
pop dx
pop cx
pop ax
ret
set_snake_on_field endp
get_snake_dir proc ;al - направление движения змейки
push si
mov si, offset snake_array
mov al, [si + 2]
pop si
ret
get_snake_dir endp
get_num_snake_seg_by_coord proc ;dl,dh - координаты сегмента; ВЫХОД: cl - номер сегмента, ch - не сохраняется
push bx
push dx
push si
mov si, offset snake_array
xor cx, cx
mov ch, [current_len_snake]
@@loop:
cmp cl, ch
jz @@end
mov bl, [si]
mov bh, [si + 1]
cmp bl, dl
jnz @@next
cmp bh, dh
jnz @@next
jmp @@end
@@next:
add si, size_snake_elem
inc cl
jmp @@loop
@@end:
pop si
pop dx
pop bx
ret
get_num_snake_seg_by_coord endp
max_len_snake equ 30
size_snake_elem equ 3
changed_direction db 0
current_len_snake db 0
snake_array db max_len_snake * size_snake_elem dup(0)
;[0,1,x | 1,1,y | 2,1,dirrection]
;======================END_SNAKE============================
;====================GAME_ENTITIES==========================
get_handler_for_entity proc ;al - код сущности; ВЫХОД: bx - обработчик графики, dx - обработчик пересечения
push si
mov si, offset entTable
@@loop:
mov bx, [si]
cmp bx, 0FFFFh
jz @@set_handlers
cmp bl, al
jz @@set_handlers
add si, 6
jmp @@loop
@@set_handlers:
mov bx, [si + 2]
mov dx, [si + 4]
pop si
ret
get_handler_for_entity endp
cdEmpty equ 0
cdWallVoltage equ 1
cdWallRubber equ 2
cdWallTeleport equ 3
cdSnakeBody equ 4
cdSnakeHead equ 5
cdAddSeg equ 6
cdDamage equ 7
cdDead equ 8
entTable dw cdEmpty, offset draw_empty, 0
dw cdWallVoltage, offset draw_wall_voltage, offset inter_wall_voltage
dw cdWallRubber, offset draw_wall_rubber, offset inter_wall_rubber
dw cdWallTeleport, offset draw_wall_teleport, offset inter_wall_teleport
dw cdSnakeBody, offset draw_snake_body, offset inter_snake_body
dw cdSnakeHead, offset draw_snake_head, 0
dw cdAddSeg, offset draw_add_seg, offset inter_add_seg
dw cdDead, offset draw_dead, offset inter_wall_voltage
dw cdDamage, offset draw_damage, offset inter_damage
dw 0FFFFh, 0, 0
;==================END_GAME_ENTITIES========================
;====================DRAW_HANDLERS==========================
draw_empty proc
push ax
push bx
push cx
push di
push es
mov cx, 4
@@loop:
xor ax, ax
xor bx, bx
call draw_two_line
loop @@loop
pop es
pop di
pop cx
pop bx
pop ax
ret
draw_empty endp
draw_default proc ;es:di - указатель на позицию;
push ax
push cx
push di
push es
mov cx, 4
@@loop:
mov ax, 0AAAAh
mov bx, 05555h
call draw_two_line
loop @@loop
pop es
pop di
pop cx
pop ax
ret
draw_default endp
draw_wall_voltage proc
push ax
push bx
push cx
mov ax, 7777h
mov bx, ax
mov cx, 2
@@loop1:
call draw_two_line
loop @@loop1
mov ax, 0DDDDh
mov bx, ax
mov cx, 2
@@loop2:
call draw_two_line
loop @@loop2
pop cx
pop bx
pop ax
ret
draw_wall_voltage endp
draw_wall_rubber proc
push ax
push bx
push cx
mov ax, 0AAAAh
mov bx, ax
mov cx, 4
@@loop:
call draw_two_line
loop @@loop
pop cx
pop bx
pop ax
ret
draw_wall_rubber endp
draw_wall_teleport proc
push ax
push bx
push cx
mov ax, 0CCCCh
mov bx, ax
mov cx, 4
@@loop:
call draw_two_line
loop @@loop
pop cx
pop bx
pop ax
ret
draw_wall_teleport endp
draw_snake_body proc
push ax
push bx
push cx
mov ax, 0A00Ah
mov bx, 0A82Ah
call draw_two_line
mov cx, 2
mov ax, 0AAAAh
mov bx, 0AAAAh
@@loop:
call draw_two_line
loop @@loop
mov ax, 0A82Ah
mov bx, 0A00Ah
call draw_two_line
pop cx
pop bx
pop ax