kolibrios/programs/games/snake/trunk/level.asm
Ivan Baravy 72eb0b5fb7 snake: version 0.7
git-svn-id: svn://kolibrios.org@1677 a494cfbc-eb01-0410-851d-a64ba20cac60
2010-10-24 19:11:32 +00:00

847 lines
21 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;===Level_mode================================================================================================================
Level_begin:
call Load_level
call Get_eat
mcall 66,1,1 ; set scan codes mode for keyboard
Level_body:
;;===Level_body========================================================================================================
call Hide_cursor
mcall 26, 9
mov [time_before_waiting], eax
mov eax, [time_wait_limit]
mov [time_to_wait], eax
.redraw:
call Set_geometry
mcall 12,1
mcall 0, , ,[window_style], ,window_title
call Draw_decorations
call Draw_stones
call Draw_snake
call Draw_eat
call Draw_level_strings
mcall 12,2
.still:
mcall 26, 9
push eax
sub eax, [time_before_waiting]
pop [time_before_waiting]
cmp [time_to_wait], eax
jg @f
cmp [action], 0
jne Game_step
@@:
sub [time_to_wait], eax
mcall 23, [time_to_wait] ;
test al, al
jnz @f
cmp [action], 0
jne Game_step
mcall 26, 9
mov [time_before_waiting], eax
mov eax, [time_wait_limit]
mov [time_to_wait], eax
jmp .still
@@:
.message: ; ok, what an event?
dec al ; has the window been moved or resized?
jz .redraw ;
dec al ; was a key pressed?
jz .key ;
dec al ; was a button pressed?
jz .button ;
.button: ; ¯à®æ¥¤ãà  ®¡à ¡®ª¨ ª­®¯®ª ¢ ¯à®£à ¬¬¥
mcall 17 ; äã­ªæ¨ï 17: ¯®«ãç¨âì ­®¬¥à ­ ¦ â®© ª­®¯ª¨
shr eax, 8 ; ᤢ¨£ ¥¬ ॣ¨áâà eax ­  8 ¡¨â ¢¯à ¢®, çâ®¡ë ¯®«ãç¨âì ­®¬¥à ­ ¦ â®© ª­®¯ª¨
cmp eax, 1
je Save_do_smth_else_and_exit
jmp .still
.key:
mcall 2 ; get keycode
;pushf
;pusha
;movzx eax, ah
;dph eax
;newline
;popa
;popf
cmp ah, 0x01 ; Escape
je First_menu
cmp ah, 0x39 ; Space
je Pause_mode
cmp ah, 0x4B ; Left
je .key.left
cmp ah, [shortcut_move_left] ; Left
je .key.left
cmp ah, 0x50 ; Down
je .key.down
cmp ah, [shortcut_move_down] ; Down
je .key.down
cmp ah, 0x48 ; Up
je .key.up
cmp ah, [shortcut_move_up] ; Up
je .key.up
cmp ah, 0x4D ; Right
je .key.right
cmp ah, [shortcut_move_right] ; Right
je .key.right
cmp ah, 0x4B+0x80 ; Left released
je .key.released.left
mov al, [shortcut_move_left]
add al, 0x80
cmp ah, al ; Left released
je .key.released.left
cmp ah, 0x50+0x80 ; Down released
je .key.released.down
mov al, [shortcut_move_down]
add al, 0x80
cmp ah, al ; Down released
je .key.released.down
cmp ah, 0x48+0x80 ; Up released
je .key.released.up
mov al, [shortcut_move_up]
add al, 0x80
cmp ah, al ; Up released
je .key.released.up
cmp ah, 0x4D+0x80 ; Right released
je .key.released.right
mov al, [shortcut_move_right]
add al, 0x80
cmp ah, al ; Right released
je .key.released.right
cmp ah, [shortcut_reverse]
jne @f
call Reverse_snake
jmp .still
@@:
cmp ah, [shortcut_increase]
jne @f
call Increase_geometry
jmp .redraw
@@:
cmp ah, [shortcut_decrease]
jne @f
call Decrease_geometry
jmp .redraw
@@:
jmp .still ; jump to wait for another event
.key.left:
bts [action], 0
jc @f
mov [time_to_wait], 0
@@:
cmp [smart_reverse], 1
jne @f
cmp [snake_direction], RIGHT
je .still
@@:
mov [snake_direction_next], LEFT
bts [acceleration_mask], LEFT
jc Game_step
jmp .still
.key.down:
bts [action], 0
jc @f
mov [time_to_wait], 0
@@:
cmp [smart_reverse], 1
jne @f
cmp [snake_direction], UP
je .still
@@:
mov [snake_direction_next], DOWN
bts [acceleration_mask], DOWN
jc Game_step
jmp .still
.key.up:
bts [action], 0
jc @f
mov [time_to_wait], 0
@@:
cmp [smart_reverse], 1
jne @f
cmp [snake_direction], DOWN
je .still
@@:
mov [snake_direction_next], UP
bts [acceleration_mask], UP
jc Game_step
jmp .still
.key.right:
bts [action], 0
jc @f
mov [time_to_wait], 0
@@:
cmp [smart_reverse], 1
jne @f
cmp [snake_direction], LEFT
je .still
@@:
mov [snake_direction_next], RIGHT
bts [acceleration_mask], RIGHT
jc Game_step
jmp .still
.key.released.left:
btr [acceleration_mask], LEFT
jmp .still
.key.released.down:
btr [acceleration_mask], DOWN
jmp .still
.key.released.up:
btr [acceleration_mask], UP
jmp .still
.key.released.right:
btr [acceleration_mask], RIGHT
jmp .still
Game_step:
cmp [snake_direction], LEFT ; are we moving to left?
jz .left
cmp [snake_direction], DOWN ; ... down?
jz .down
cmp [snake_direction], UP ; ... up?
jz .up
jmp .right ; then right
.left:
cmp [snake_direction_next], RIGHT ; next step is to right?
jz .with_reverse
jmp .without_reverse
.down:
cmp [snake_direction_next], UP ; next step is to up?
jz .with_reverse
jmp .without_reverse
.up:
cmp [snake_direction_next], DOWN ; next step is to bottom?
jz .with_reverse
jmp .without_reverse
.right:
cmp [snake_direction_next], LEFT ; next step is to left?
jz .with_reverse
jmp .without_reverse
.with_reverse:
call Set_reverse_direction
call Reverse
.without_reverse:
mov edx, snake_dots-2
add edx, [snake_length_x2]
cmp [snake_direction_next], LEFT
je .to_left
cmp [snake_direction_next], DOWN
je .to_down
cmp [snake_direction_next], UP
je .to_up
cmp [snake_direction_next], RIGHT
je .to_right
.to_left:
mov [snake_direction], LEFT
mov ax, [edx]
dec al
cmp al, -1
jne @f
mov al, GRID_WIDTH
dec al
@@:
jmp Snake_move
.to_down:
mov [snake_direction], DOWN
mov ax, [edx]
inc ah
cmp ah, GRID_HEIGHT
jne @f
mov ah, 0
@@:
jmp Snake_move
.to_up:
mov [snake_direction], UP
mov ax, [edx]
dec ah
cmp ah, -1
jne @f
mov ah, GRID_HEIGHT
dec ah
@@:
jmp Snake_move
.to_right:
mov [snake_direction], RIGHT
mov ax, [edx]
inc al
cmp al, GRID_WIDTH
jne @f
mov al, 0
@@:
jmp Snake_move
;;---Level_body--------------------------------------------------------------------------------------------------------
;;---Level_mode----------------------------------------------------------------------------------------------------------------
;;===Some_functions============================================================================================================
Draw_snake:
;;===Draw_snake========================================================================================================
call Draw_head_prehead
mov edx, [snake_color]
mov esi, snake_dots-6
add esi, [snake_length_x2]
@@:
mov bx, [esi]
sub esi, 2
call Draw_square
cmp esi, snake_dots-2
jne @b
ret
;;---Draw_snake--------------------------------------------------------------------------------------------------------
Draw_head_prehead:
;;===Draw_head_prehead=================================================================================================
mov edx, [snake_head_color]
mov esi, snake_dots-2
add esi, [snake_length_x2]
mov bx, [esi]
call Draw_square
sub esi, 2
mov bx, [esi]
mov edx, [snake_color]
call Draw_square
call Draw_lives_in_head
ret
;;---Draw_head_prehead-------------------------------------------------------------------------------------------------
Draw_level_strings:
;;===Draw_level_strings================================================================================================
mov ebx, [window_width]
shr ebx, 1
sub ebx, string_pause_space.size*3+6
shl ebx, 16
add ebx, [top_strings]
mcall 4, ,[navigation_strings_color],string_pause_space ; Draw 'PAUSE - SPACE' string
; call Draw_menu_esc
call Draw_score_string
call Draw_score_number ; Draw score (number)
call Draw_champion_string
call Draw_champion_name
call Draw_hiscore_string
call Draw_hiscore_number
cmp [play_mode], LEVELS_MODE
jne @f
mov ebx, [window_width]
shr ebx, 3
sub ebx, 5
shl ebx, 16
add ebx, [bottom_bottom_strings]
mcall 4, ,[level_string_color],string_level
mov edx, [window_width]
shr edx, 3
sub edx, 5+1
add edx, string_level.size*6
shl edx, 16
add edx, [bottom_bottom_strings]
mcall 47,0x00020000,[cur_level_number], ,[level_number_color],[background_color]
@@:
ret
;;---Draw_level_strings------------------------------------------------------------------------------------------------
Reverse:
;;===Reverse===========================================================================================================
mov ecx, [snake_length_x2]
shr ecx, 2
mov esi, snake_dots
mov edi, snake_dots-2
add edi, [snake_length_x2]
@@:
mov ax, [edi]
xchg ax, [esi]
mov [edi], ax
add esi, 2
sub edi, 2
dec cx
jnz @b
ret
;;---Reverse-----------------------------------------------------------------------------------------------------------
Draw_eat:
;;===Draw_eat==========================================================================================================
mov bx, word[eat]
mov edx, [eat_color]
call Draw_square
ret
;;---Draw_eat----------------------------------------------------------------------------------------------------------
Get_eat:
;;===Get_eat===========================================================================================================
;; in :
;;
;; out :
;; ax = coord's of the eat square (al=x, ah=y)
;;
mcall 26,9
; xor eax, esp
shl eax, 1
xor edx, edx
div word[number_of_free_dots]
mov ebx, field_map
.loop:
cmp byte[ebx], 0
jne @f
test dx, dx
jz .place_found
dec dx
@@:
inc ebx
jmp .loop
.place_found:
sub ebx, field_map
mov eax, ebx
mov bl, GRID_WIDTH
div bl
xchg al, ah
mov word[eat], ax
ret
;;---Get_eat-----------------------------------------------------------------------------------------------------------
Sdvig:
;;===Sdvig=============================================================================================================
mov esi, snake_dots+2
mov edi, snake_dots
mov ecx, [snake_length_x2]
shr ecx, 1
cld
rep movsw
ret
;;---Sdvig-------------------------------------------------------------------------------------------------------------
Set_reverse_direction:
;;===Set_reverse_direction==================================================================================================
mov eax, snake_dots
mov ebx, snake_dots+2
mov cl, [eax] ; The last dot x_coord
mov ch, [ebx] ; The pre_last dot x_coord
cmp cl, ch
je .X_ravny
cmp cl, 0
jne .skip2
mov dl, GRID_WIDTH
dec dl
cmp ch, dl
jne .Normal_y_ravny
mov [snake_direction_next], RIGHT
ret
.skip2:
mov dl, GRID_WIDTH
dec dl
cmp cl, dl
jne .Normal_y_ravny
cmp ch, 0
jne .Normal_y_ravny
mov [snake_direction_next], LEFT
ret
.Normal_y_ravny:
cmp cl, ch
jg .Napravlenie_to_right
mov [snake_direction_next], LEFT
ret
.Napravlenie_to_right:
mov [snake_direction_next], RIGHT
ret
.X_ravny:
inc eax
inc ebx
mov cl, [eax]
mov ch, [ebx]
cmp cl, 0
jne .skip3
mov dl, GRID_HEIGHT
dec dl
cmp ch, dl
jne .Normal_x_ravny
mov [snake_direction_next], DOWN
ret
.skip3:
mov dl, GRID_HEIGHT
dec dl
cmp ch, dl
jne .Normal_x_ravny
cmp ch, 0
jne .Normal_x_ravny
mov [snake_direction_next], UP
ret
.Normal_x_ravny:
cmp cl, ch ; !!!
jg .Napravlenie_to_down ; 0 1 2 ...
mov [snake_direction_next], UP ; 1
ret ; 2
; .
.Napravlenie_to_down: ; .
mov [snake_direction_next], DOWN ; .
ret
;;---Set_reverse_direction--------------------------------------------------------------------------------------------------
Snake_move:
;;===Snake_move=============================================================================================================
;; in :
;; ax = coord's of new head
;; edx = snake_dots+[snake_length_x2]-2 (snake head)
;;
add edx, 2
mov [edx], ax
cmp ax, word[eat]
jne .eat_and_new_head_are_different
add [snake_length_x2], 2
add [score], SCORE_EAT
dec [number_of_free_dots]
cmp [number_of_free_dots], 0
je Game_over
mov ax, word[eat]
mov cl, 1
call Draw_on_map
call Draw_head_prehead
cmp [play_mode], CLASSIC_MODE
jne .is_not_classic_mode
dec byte[speed_up_counter]
jns @f
mov al, byte[speed_up_counter+1]
mov byte[speed_up_counter], al
cmp [time_wait_limit], 4
jl @f
dec [time_wait_limit]
@@:
.is_not_classic_mode:
cmp [play_mode], LEVELS_MODE
jne .is_not_levels_mode
cmp [snake_length_x2], (EAT_TO_END_LEVEL+3)*2
je .skip
.is_not_levels_mode:
call Get_eat
call Draw_eat
.skip:
jmp Keys_done
.eat_and_new_head_are_different:
push ax
mov ax, word[snake_dots]
mov cl, 0
call Draw_on_map
pop ax
call Get_from_map
test bl, bl
jnz Game_over
mov cl, 1
call Draw_on_map
mov bx, word[snake_dots]
mov edx, [background_color]
call Draw_square
call Sdvig
call Draw_head_prehead
Keys_done:
cmp [score], 0
je @f
dec [score]
call Draw_score_number
@@:
cmp [play_mode], LEVELS_MODE
jne @f
cmp [snake_length_x2], (EAT_TO_END_LEVEL+3)*2
je Do_smth_between_levels
@@:
mcall 26, 9
mov [time_before_waiting], eax
mov eax, [time_wait_limit]
mov [time_to_wait], eax
jmp Level_body.still
;;---Snake_move------------------------------------------------------------------------------------------------------------
Do_smth_between_levels:
;;===Do_smth_between_levels================================================================================================
inc [cur_level_number]
cmp [cur_level_number], LAST_LEVEL_NUMBER+1
jne @f
mov [cur_level_number], LEVELS_MODE_FIRST_LEVEL
@@:
call Draw_splash
@@:
mcall 2
cmp eax, 1
jne @b
jmp Level_begin
;;---Do_smth_between_levels------------------------------------------------------------------------------------------------
Draw_splash:
;;===Draw_splash===========================================================================================================
mov al, 0
mov cl, GRID_WIDTH-1
mov edx, [splash_background_color]
.draw:
mov bh, GRID_HEIGHT-1
mov bl, al
@@:
call Draw_square
sub bh, 2
cmp bh, 0
jg @b
inc al
mov bh, GRID_HEIGHT-2
mov bl, cl
@@:
call Draw_square
sub bh, 2
cmp bh, 0
jnl @b
dec cl
cmp cl, 0
jl .picture
push eax ebx
mcall 5,PAUSE_WHILE_DRAWING_SPLASH
mcall 2
cmp ah, 0x39 ; Space
jne @f
pop ebx eax
jmp .quit
@@:
cmp ah, 0x1C ; Enter
jne @f
pop ebx eax
jmp .quit
@@:
pop ebx eax
jmp .draw
.picture:
mov ax, 2*0x100+24
mov cx, 1*0x100+5
mov edx, [splash_level_string_color]
mov esi, picture_level
call Draw_picture
mov eax, [cur_level_number]
mov dl, 10
div dl
push ax
mov esi, digits_font
@@:
test al, al
jz @f
add esi, 5
dec al
jmp @b
@@:
mov ax, 9*0x100+4
mov cx, 8*0x100+5
mov edx, [splash_level_number_color]
call Draw_picture
pop ax
mov esi, digits_font
@@:
test ah, ah
jz @f
add esi, 5
dec ah
jmp @b
@@:
mov ax, 15*0x100+4
mov cx, 8*0x100+5
mov edx, [splash_level_number_color]
call Draw_picture
mcall 26,9
mov [time_before_waiting], eax
mov [time_to_wait], PAUSE_BETWEEN_LEVELS
@@:
mcall 23,[time_to_wait]
mcall 2
cmp ah, 0x39 ; Space
je .quit
cmp ah, 0x1C ; Enter
je .quit
mcall 26,9
push eax
sub eax, [time_before_waiting]
pop [time_before_waiting]
sub [time_to_wait], eax
jns @b
.quit:
ret
;;---Draw_splash-----------------------------------------------------------------------------------------------------------
Draw_lives_in_head:
;;===Draw_lives_in_head====================================================================================================
cmp [play_mode], LEVELS_MODE
jne .quit
test [show_lives_style], 2
jz .quit
mov eax, snake_dots-2
add eax, [snake_length_x2]
mov ax, word[eax]
mov bl, ah
mul byte[g_s]
mov edx, [gbxm1]
add dx, ax
shl edx, 16
mov al, bl
mul byte[g_s]
mov dx, word[gbym1]
add dx, ax
mov eax, [g_s]
shl eax, 16
add eax, [g_s]
and eax, 0xfffefffe
shr eax, 1
add edx, eax
sub edx, 0x00020003
mcall 47,0x80010001,lives,,[lives_in_head_number_color]
.quit:
ret
;;---Draw_lives_in_head----------------------------------------------------------------------------------------------------
;;---Some_functions------------------------------------------------------------------------------------------------------------