%include "rw32-2018.inc" ;------------------------------------------------------------------------------; ; POUZITE KONSTANTY ; ;------------------------------------------------------------------------------; ; bits/locale.h %define LC_ALL 6 ; curses.h %define CURSES_ERR -1 %define CURSES_OK 0 ; curses.h %define KEY_ESC 0x001B %define KEY_ENTER 0x000A %define KEY_BKSP 0x007F %define KEY_UP 0x0103 %define KEY_DOWN 0x0102 %define KEY_LEFT 0x0104 %define KEY_RIGHT 0x0105 %define KEY_INS 0x014B %define KEY_DEL 0x014A %define KEY_HOME 0x0106 %define KEY_END 0x0168 %define KEY_PGUP 0x0153 %define KEY_PGDOWN 0x0152 %define KEY_RESIZE 0x019A ;------------------------------------------------------------------------------; ; INTERNI REPREZENTACE HRISTE ; ;------------------------------------------------------------------------------; section .data ; ASnek Playground ; definuje prekazky, obsah je pred vykreslenim prekodovan dle kodove tabulky playground db "2000000000000000000000000000000000000000000000000000000000000003" db "1 1" db "1 1" db "1 86666666666 66666666669 1" db "1 7 7 1" db "1 7 7 1" db "1 1" db "1 1" db "1 1" db "1 1" db "1 1" db "1 1" db "1 1" db "1 7 7 1" db "1 7 7 1" db "1 :6666666666 6666666666; 1" db "1 1" db "1 1" _mark db "4000000000000000000000000000000000000000000000000000000000000005" WIDTH equ $ - _mark HEIGHT equ ($ - playground) / WIDTH SIZE equ $ - playground ; overeni velikosti hriste %if WIDTH * HEIGHT != SIZE %error Malformed Playground %endif %if WIDTH > 255 || HEIGHT > 255 %error Playground is too big %endif %if WIDTH < 16 || HEIGHT < 3 %error Playground is too small %endif ;------------------------------------------------------------------------------; ; FUNKCE K IMPLEMENTACI ; ;------------------------------------------------------------------------------; section .text CMAIN: mov ebp, esp; for correct debugging ; inicializace curses call InitGame ; vykresleni hriste call DrawPlayground ; inicializace a vykresleni hada call InitSnek ; bx -- pozice hlavy ; spocteni prazdnych poli do edi call CountEmptyPlaces ; edi -- pocet prazdnych poli ; generovani prvniho jidla call PutFood ; inicializace skore mov esi, 0 ; esi -- skore call UpdateScore ; vykresleni vychoziho stavu call refresh ; sekunda na pripravu push dword 1000 call napms add esp, 4 ; registre ukladajici dalsi stav hry mov cx, KEY_RIGHT ; cx -- smer pohybu, pocatocni stav ;--------------------------------------------------------------------------; ; Ukol 4: Doplnte obsah herni smycky ; ; Ridte se pseudokodem v PDF dokumentu k cviceni ; ;--------------------------------------------------------------------------; .game_loop: .game_over: ; nevalidni umisteni hlavy, pro ilustraci call PlaceHead ; vypis konce hry push game_over_str push dword (WIDTH - game_over_len) / 2 push dword HEIGHT / 2 call mvaddstr add esp, 12 ; prekresleni okna call refresh ; kratke cekani pred ukoncenim push dword 3000 call napms add esp,4 ; uklizeni curses call endwin ; navratova hodnota a navrat z main xor eax, eax ret ;------------------------------------------------------------------------------; ; Ukol 1: Doplnte funkci pro ziskani vstupu ; ; Ridte se pseudokodem v PDF dokumentu k cviceni ; ;------------------------------------------------------------------------------; GetInput: ret ;------------------------------------------------------------------------------; ; Ukol 2: Doplnte funkci pro aktualizaci pozice hlavy hada ; ; Ridte se pseudokodem v PDF dokumentu k cviceni ; ;------------------------------------------------------------------------------; UpdateHeadPosition: ret ;------------------------------------------------------------------------------; ; Ukol 3: Doplnte funkci pro ziskani ziskani znaku z interni reprezentace ; ; Ridte se pseudokodem v PDF dokumentu k cviceni ; ;------------------------------------------------------------------------------; GetTile: ret ; ; ;-- OBSAH NIZE PROSIM NEUPRAVUJTE (JESTLI NEVITE CO DELATE) -------------------; ; ; ;------------------------------------------------------------------------------; ; DEKLARACE EXTERNE VOLANYCH FUNKCI ; ;------------------------------------------------------------------------------; extern setlocale extern initscr extern resizeterm extern cbreak extern noecho extern keypad extern curs_set extern addstr extern mvaddstr extern endwin extern getch extern nodelay extern refresh extern napms extern rand extern srand extern time extern mvprintw ;------------------------------------------------------------------------------; ; OSTATNI DATA ; ;------------------------------------------------------------------------------; section .data ; znaky hada a potravy ; interni reprezentace snek_body_int equ '<' snek_food_int equ '=' ; vykreslovana reprezentace snek_head_str db "✕",0 snek_body_str db "◼",0 snek_food_str db "◇",0 ; kodova tabulka pro hriste space db " ",0 hl db "─",0 vl db "│",0 tlc db "┌",0 trc db "┐",0 blc db "└",0 brc db "┘",0 hlb db "━",0 vlb db "┃",0 tlcb db "┏",0 trcb db "┓",0 blcb db "┗",0 brcb db "┛",0 pg_ct_min equ '0' pg_ct_max equ ';' align 4,db 0 ; prekladova lookup tabulka pg_ct dd hl,vl,tlc,trc,blc,brc,hlb,vlb,tlcb,trcb,blcb,brcb ; dalsi pomocne promenne tk_wnd dd 0 ; WINDOW* locale_str db "en_US.UTF-8",0 ; locale score_fmt db " Score: %5u ",0 ; formatovaci retezec pro skore game_over_str db "G A M E O V E R",0 ; retezec pro konec hry game_over_len equ $ - game_over_str - 1 ; indexy do snek_indices align 4,db 0 snek_prev dw 0 snek_head dw 0 snek_tail dw 0 section .bss ; seznam pozic na kterych je had snek_indices resw SIZE ;------------------------------------------------------------------------------; ; DALSI INTERNI FUNKCE ; ;------------------------------------------------------------------------------; section .text InitGame: ; nastaveni locale na UTF-8 variantu push locale_str push dword LC_ALL call setlocale add esp, 8 ; inicializace curses call initscr mov [tk_wnd], eax ; keypad rezim push dword 1 push eax call keypad add esp, 4 ; neblokujici vstup push dword [tk_wnd] call nodelay add esp, 8 ; neviditelny kurzor push dword 0 call curs_set add esp, 4 ; velikost terminalu push dword WIDTH push dword HEIGHT call resizeterm add esp, 8 ; nebuffrovany vstup call cbreak ; vypnuti vypisovani prectenych symbolu call noecho ; seedovani pseudonahodneho generatoru push dword 0 call time push eax call srand add esp, 8 ; navrat ret DrawPlayground: ; zaloha esi push esi ; iterace pres interni reprezentaci transformace na terminal mov esi, playground .loop: ; nacteni znaku z interni reprezentace movzx eax, byte [esi] ; overeni zda je znak prekladan (z rozsahu ) cmp eax, pg_ct_min jb .default cmp eax, pg_ct_max ja .default ; preklad znaku dle tabulky pg_ct sub eax, pg_ct_min push dword [pg_ct + eax*4] jmp .print .default: ; vypis mezery v pripade, ze znak neni v tabulce push space .print: call addstr add esp,4 ; inkrementace ukazatele a test na konec inc esi cmp esi, playground + SIZE jne .loop ; obnova esi pop esi ; navrat ret InitSnek: ; do stredu hriste umistime hada mov bx, ((WIDTH / 2 - 2) << 8) + HEIGHT / 2 .loop: inc bh call PlaceHead cmp bx, ((WIDTH / 2) << 8) + HEIGHT / 2 jne .loop ; navrat ret CountEmptyPlaces: ; zaloha registru push eax push esi ; cyklus pres hriste mov esi, playground xor edi, edi .loop: mov al, [esi] cmp al, ' ' jne .occupied ; podminena inkrementace edi inc edi .occupied: ; posun ukazatele a test na konec hriste inc esi cmp esi, playground + SIZE jne .loop ; obnova registru pop esi pop eax ; navrat ret PutFood: ; test na nula prazdnich mist test edi, edi jnz .not_zero ret .not_zero: ; zaloha registru push ecx push edx push esi ; ziskani nahodneho cisla v rozsahu <0, edi) xor edx, edx cmp edi, 1 je .not_random call rand xor edx, edx div edi .not_random: ; nalezeni ciloveho mista pro jidlo mov esi, playground .loop: mov al, [esi] cmp al, ' ' jne .occupied test edx, edx jz .end dec edx .occupied: ; posun ukazatele do hriste inc esi jmp .loop .end: ; zapis do interni reprezentace mov byte [esi], snek_food_int ; vypis na terminal -- ziskani souradnic sub esi, playground mov ax, si mov cl, WIDTH div cl ; al = radek, ah = sloupec movzx edx, ah movzx eax, al ; vypis na terminal -- volani funkce push snek_food_str push edx push eax call mvaddstr add esp, 12 ; dekrementace poctu prazdnych poli dec edi ; obnova registru pop esi pop edx pop ecx ; navrat ret UpdateScore: ; zaloha registru push eax push ecx push edx ; vypis skore push esi push score_fmt push dword 5 push dword 0 call mvprintw add esp, 16 ; obnova registru pop edx pop ecx pop eax ; navrat ret GetChar: ; cdecl kompatibilni wrapper -- zaloha registru push edx push ecx call getch pop ecx pop edx ret PlaceHead: ; zaloha registru push eax push ecx push edx ; overeni existence predchozi hlavy movzx ecx, word [snek_prev] cmp cx, [snek_head] je .first_head ; nahrazeni predchozi hlavy mov cx, [snek_indices + ecx*2] push snek_body_str movzx edx, ch movzx eax, cl push edx push eax call mvaddstr add esp, 12 .first_head: ; aktualizace snek_indices movzx ecx, word [snek_head] mov [snek_indices + ecx*2], bx ; pridani nove hlavy na terminal movzx edx, bh movzx eax, bl push snek_head_str push edx push eax call mvaddstr add esp, 12 ; pridani nove hlavy do interni reprezentace movzx edx, bh movzx eax, bl mov cl, WIDTH mul cl add eax, edx mov byte [playground + eax], snek_body_int ; aktualizace indexu prev_head mov ax, [snek_head] mov [snek_prev], ax ; posun indexu snek_head xor dx, dx inc ax mov cx, SIZE div cx mov [snek_head], dx ; obnova registru pop edx pop ecx pop eax ret RemoveTail: ; zaloha registru push eax push ecx push edx ; ziskani aktualni pozice ocasu movzx ecx, word [snek_tail] movzx eax, byte [snek_indices + ecx*2] ; radek movzx edx, byte [snek_indices + ecx*2 + 1] ; sloupec ; odstraneni ocasu z terminalu -- zaloha registru push eax push edx ; odstraneni ocasu z terminalu -- volani funkce push dword space push edx push eax call mvaddstr add esp, 12 ; odstraneni ocasu z terminalu -- obnova registru pop edx pop eax ; odstraneni ocasu z interni reprezentace mov cl, WIDTH mul cl add eax, edx mov byte [playground + eax], ' ' ; posun indexu snek_tail xor dx, dx mov ax, [snek_tail] inc ax mov cx, SIZE div cx mov [snek_tail], dx ; obnova registru pop edx pop ecx pop eax ; navrat ret DrawAndSleep: ; zaloha registru push ecx push edx ; prekresleni terminalu call refresh ; sleep na 150 milisekund push dword 150 call napms add esp, 4 ; obnova registru pop edx pop ecx ; navrat ret