tic-tac-toe dne
This commit is contained in:
@@ -5,4 +5,6 @@ Making a game for linux terminal using pure asm
|
|||||||
|
|
||||||
[Linux syscalls reference table](https://syscalls.mebeim.net/?table=x86/64/x64/v6.12)
|
[Linux syscalls reference table](https://syscalls.mebeim.net/?table=x86/64/x64/v6.12)
|
||||||
|
|
||||||
[synthwave radio 🌌 beats to chill/game to](https://www.youtube.com/watch?v=4xDzrJKXOOY)
|
[synthwave radio 🌌 beats to chill/game to](https://www.youtube.com/watch?v=4xDzrJKXOOY)
|
||||||
|
|
||||||
|
[nasm instructions manual](http://home.myfairpoint.net/fbkotler/nasmdocc.html#section-A.4.184)
|
||||||
307
game.s
307
game.s
@@ -1,18 +1,315 @@
|
|||||||
|
; TODO out of moves check
|
||||||
|
|
||||||
global _start
|
global _start
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
|
|
||||||
_start:
|
checkVictory:
|
||||||
|
mov rax, 0
|
||||||
|
|
||||||
|
mov cl, [fieldBuffer + 12]
|
||||||
|
and cl, [fieldBuffer + 14]
|
||||||
|
and cl, [fieldBuffer + 16]
|
||||||
|
cmp cl, dil
|
||||||
|
je .returnTrue
|
||||||
|
|
||||||
|
mov cl, [fieldBuffer + 22]
|
||||||
|
and cl, [fieldBuffer + 24]
|
||||||
|
and cl, [fieldBuffer + 26]
|
||||||
|
cmp cl, dil
|
||||||
|
je .returnTrue
|
||||||
|
|
||||||
|
mov cl, [fieldBuffer + 32]
|
||||||
|
and cl, [fieldBuffer + 34]
|
||||||
|
and cl, [fieldBuffer + 36]
|
||||||
|
cmp cl, dil
|
||||||
|
je .returnTrue
|
||||||
|
|
||||||
|
mov cl, [fieldBuffer + 12]
|
||||||
|
and cl, [fieldBuffer + 22]
|
||||||
|
and cl, [fieldBuffer + 32]
|
||||||
|
cmp cl, dil
|
||||||
|
je .returnTrue
|
||||||
|
|
||||||
|
mov cl, [fieldBuffer + 14]
|
||||||
|
and cl, [fieldBuffer + 24]
|
||||||
|
and cl, [fieldBuffer + 34]
|
||||||
|
cmp cl, dil
|
||||||
|
je .returnTrue
|
||||||
|
|
||||||
|
mov cl, [fieldBuffer + 16]
|
||||||
|
and cl, [fieldBuffer + 26]
|
||||||
|
and cl, [fieldBuffer + 36]
|
||||||
|
cmp cl, dil
|
||||||
|
je .returnTrue
|
||||||
|
|
||||||
|
mov cl, [fieldBuffer + 12]
|
||||||
|
and cl, [fieldBuffer + 24]
|
||||||
|
and cl, [fieldBuffer + 36]
|
||||||
|
cmp cl, dil
|
||||||
|
je .returnTrue
|
||||||
|
|
||||||
|
mov cl, [fieldBuffer + 16]
|
||||||
|
and cl, [fieldBuffer + 24]
|
||||||
|
and cl, [fieldBuffer + 32]
|
||||||
|
cmp cl, dil
|
||||||
|
je .returnTrue
|
||||||
|
|
||||||
|
mov rax, 0
|
||||||
|
ret
|
||||||
|
.returnTrue:
|
||||||
|
mov rax, 1
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
makeAIMove:
|
||||||
|
rdtsc
|
||||||
|
mov rbx, rax
|
||||||
|
.loop:
|
||||||
|
; RAND from wiki https://en.wikipedia.org/wiki/Linear_congruential_generator. Numerical Recipes ranqd1, Chapter 7.1, §An Even Quicker Generator, Eq. 7.1.6 parameters from Knuth and H. W. Lewis
|
||||||
|
mov rdx, 1664525
|
||||||
|
mul rdx
|
||||||
|
add rax, 1013904223
|
||||||
|
mov rbx, rax
|
||||||
|
|
||||||
|
; clamping to 1-3 range and moving to rdi
|
||||||
|
mov rsi, 3
|
||||||
|
mov rax, 0
|
||||||
|
mov ah, bh
|
||||||
|
mov dx, 0
|
||||||
|
div si ;TODO for some reason div sil causes division by zero
|
||||||
|
inc dx
|
||||||
|
mov di, dx
|
||||||
|
shl di, 8
|
||||||
|
mov rax, 0
|
||||||
|
mov ah, bl
|
||||||
|
mov dx, 0
|
||||||
|
div si
|
||||||
|
inc dx
|
||||||
|
mov dil, dl
|
||||||
|
mov rsi, 'o'
|
||||||
|
call placeChar
|
||||||
|
cmp rax, 0
|
||||||
|
je .return
|
||||||
|
mov rax, rbx
|
||||||
|
jmp .loop
|
||||||
|
|
||||||
|
.return:
|
||||||
|
ret
|
||||||
|
|
||||||
|
drawField:
|
||||||
mov rax, 1 ; sys_write
|
mov rax, 1 ; sys_write
|
||||||
mov rdi, 1 ; out
|
mov rdi, 1 ; out
|
||||||
mov rsi, helloThere ; str
|
mov rsi, fieldBuffer ; str
|
||||||
mov rdx, helloThereLen ; size
|
mov rdx, fieldBufferLen ; size
|
||||||
|
syscall ;
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
placeChar:
|
||||||
|
;computing pos in string
|
||||||
|
mov dx, di
|
||||||
|
|
||||||
|
mov rcx, 0
|
||||||
|
; cl = dh * 10
|
||||||
|
mov cl, dh
|
||||||
|
shl cl, 3
|
||||||
|
add cl, dh
|
||||||
|
add cl, dh
|
||||||
|
|
||||||
|
; cl += dl * 2
|
||||||
|
shl dl, 1
|
||||||
|
add cl, dl
|
||||||
|
|
||||||
|
;checking if it was occupied char to the string
|
||||||
|
mov rax, 0
|
||||||
|
mov byte al, [fieldBuffer + rcx]
|
||||||
|
sub al, ' '
|
||||||
|
jne .return
|
||||||
|
;placing char to the string
|
||||||
|
mov byte [fieldBuffer + rcx], sil
|
||||||
|
.return:
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
readXY:
|
||||||
|
; clearing input buffer
|
||||||
|
mov dword [userInputBuffer], 0
|
||||||
|
|
||||||
|
mov rax, 0 ; sys_read
|
||||||
|
mov rdi, 0 ; in
|
||||||
|
mov rsi, userInputBuffer ; str
|
||||||
|
mov rdx, 256 ; size
|
||||||
|
syscall ;
|
||||||
|
|
||||||
|
; only accept strings with length of 4 (reading more to skip some invalid inputs)
|
||||||
|
cmp rax, 4
|
||||||
|
jne .return
|
||||||
|
|
||||||
|
mov ax, 0
|
||||||
|
cmp byte [userInputBuffer+1], ' ' ; second should be whitespace
|
||||||
|
jne .return
|
||||||
|
cmp byte [userInputBuffer+3], 0xA ; fourth should be \n
|
||||||
|
jne .return
|
||||||
|
|
||||||
|
mov al, [userInputBuffer] ; x
|
||||||
|
sub al, '0'
|
||||||
|
mov ah, [userInputBuffer + 2] ; y
|
||||||
|
sub ah, '0'
|
||||||
|
.return:
|
||||||
|
ret
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; call drawField
|
||||||
|
|
||||||
|
mov rax, 1 ; sys_write
|
||||||
|
mov rdi, 1 ; out
|
||||||
|
mov rsi, greetingsMessage ; str
|
||||||
|
mov rdx, greetingsMessageLen ; size
|
||||||
|
syscall ;
|
||||||
|
|
||||||
|
call drawField
|
||||||
|
mov rax, 1 ; sys_write
|
||||||
|
mov rdi, 1 ; out
|
||||||
|
mov rsi, readInputsMessage ; str
|
||||||
|
mov rdx, readInputsMessageLen ; size
|
||||||
syscall ;
|
syscall ;
|
||||||
|
|
||||||
|
.loop:
|
||||||
|
;reading input
|
||||||
|
call readXY
|
||||||
|
|
||||||
|
;reading check x,y range
|
||||||
|
cmp al, 1
|
||||||
|
jl .printInputError
|
||||||
|
cmp al, 3
|
||||||
|
jg .printInputError
|
||||||
|
cmp ah, 1
|
||||||
|
jl .printInputError
|
||||||
|
cmp ah, 3
|
||||||
|
jg .printInputError
|
||||||
|
|
||||||
|
mov rdi, rax ; passing xy to placeChar function
|
||||||
|
mov sil, 'x' ; passing char to placeChar function
|
||||||
|
call placeChar
|
||||||
|
|
||||||
|
; failed to place a char
|
||||||
|
jne .printOccupiedError
|
||||||
|
|
||||||
|
;check win condition
|
||||||
|
mov rdi, 'x'
|
||||||
|
call checkVictory
|
||||||
|
cmp rax, 0
|
||||||
|
jne .printYouWon
|
||||||
|
|
||||||
|
;drawing field again
|
||||||
|
call drawField
|
||||||
|
|
||||||
|
;ai thinking...
|
||||||
|
mov rax, 1 ; sys_write
|
||||||
|
mov rdi, 1 ; out
|
||||||
|
mov rsi, aiThinkingMessage ; str
|
||||||
|
mov rdx, aiThinkingMessageLen ; size
|
||||||
|
syscall ;
|
||||||
|
|
||||||
|
mov rbx, 10
|
||||||
|
.thinkingReallyHardLoop:
|
||||||
|
mov rax, 1000000000
|
||||||
|
.thinkingReallyHardInnerLoop:
|
||||||
|
dec rax
|
||||||
|
jne .thinkingReallyHardInnerLoop
|
||||||
|
|
||||||
|
mov rax, 1 ; sys_write
|
||||||
|
mov rdi, 1 ; out
|
||||||
|
mov rsi, aiThinkingDotMessage ; str
|
||||||
|
mov rdx, aiThinkingDotMessageLen ; size
|
||||||
|
syscall ;
|
||||||
|
dec rbx
|
||||||
|
jne .thinkingReallyHardLoop
|
||||||
|
|
||||||
|
mov rax, 1 ; sys_write
|
||||||
|
mov rdi, 1 ; out
|
||||||
|
mov rsi, endlnMessage ; str
|
||||||
|
mov rdx, endlnMessageLen ; size
|
||||||
|
syscall ;
|
||||||
|
|
||||||
|
call makeAIMove
|
||||||
|
call drawField
|
||||||
|
mov rdi, 'o'
|
||||||
|
call checkVictory
|
||||||
|
cmp rax, 0
|
||||||
|
jne .printYouLost
|
||||||
|
|
||||||
|
;printing input message again
|
||||||
|
mov rax, 1 ; sys_write
|
||||||
|
mov rdi, 1 ; out
|
||||||
|
mov rsi, readInputsMessage ; str
|
||||||
|
mov rdx, readInputsMessageLen ; size
|
||||||
|
syscall ;
|
||||||
|
|
||||||
|
jmp .loop
|
||||||
|
|
||||||
|
.printInputError:
|
||||||
|
mov rax, 1 ; sys_write
|
||||||
|
mov rdi, 1 ; out
|
||||||
|
mov rsi, wrongValuesMessage ; str
|
||||||
|
mov rdx, wrongValuesMessageLen ; size
|
||||||
|
syscall ;
|
||||||
|
jmp .loop
|
||||||
|
.printOccupiedError:
|
||||||
|
mov rax, 1 ; sys_write
|
||||||
|
mov rdi, 1 ; out
|
||||||
|
mov rsi, occupiedMessage ; str
|
||||||
|
mov rdx, occupiedMessageLen ; size
|
||||||
|
syscall ;
|
||||||
|
jmp .loop
|
||||||
|
|
||||||
|
|
||||||
|
.printYouWon:
|
||||||
|
call drawField
|
||||||
|
mov rax, 1 ; sys_write
|
||||||
|
mov rdi, 1 ; out
|
||||||
|
mov rsi, youWonMessage ; str
|
||||||
|
mov rdx, youWonMessageLen ; size
|
||||||
|
syscall ;
|
||||||
|
jmp .exit
|
||||||
|
|
||||||
|
.printYouLost:
|
||||||
|
call drawField
|
||||||
|
mov rax, 1 ; sys_write
|
||||||
|
mov rdi, 1 ; out
|
||||||
|
mov rsi, youLostMessage ; str
|
||||||
|
mov rdx, youLostMessageLen ; size
|
||||||
|
syscall ;
|
||||||
|
|
||||||
|
.exit:
|
||||||
|
; exiting program
|
||||||
mov rax, 60 ; sys_exit
|
mov rax, 60 ; sys_exit
|
||||||
mov rdi, 0 ; code
|
mov rdi, 0 ; code
|
||||||
syscall ;
|
syscall ;
|
||||||
|
|
||||||
section .rodata
|
section .rodata
|
||||||
helloThere: db "Hello there ;)", 0xA, "General Kenobi!!!", 0xA
|
greetingsMessage: db "Welcome to tic-tac-toe!", 0xA
|
||||||
helloThereLen: equ $ - helloThere
|
greetingsMessageLen: equ $ - greetingsMessage
|
||||||
|
readInputsMessage: db "Type [x y] to place a cross:", 0xA
|
||||||
|
readInputsMessageLen: equ $ - readInputsMessage
|
||||||
|
wrongValuesMessage: db "Unexpected x or y value. Could be 1,2 or 3 in [x y] format. Try again:", 0xA
|
||||||
|
wrongValuesMessageLen: equ $ - wrongValuesMessage
|
||||||
|
occupiedMessage: db "Cell is already occupied. Try again:", 0xA
|
||||||
|
occupiedMessageLen: equ $ - occupiedMessage
|
||||||
|
youWonMessage: db "YOU WON!!!", 0xA
|
||||||
|
youWonMessageLen: equ $ - youWonMessage
|
||||||
|
youLostMessage: db "you lost T_T", 0xA
|
||||||
|
youLostMessageLen: equ $ - youLostMessage
|
||||||
|
aiThinkingMessage: db "AI thinking"
|
||||||
|
aiThinkingMessageLen: equ $ - aiThinkingMessage
|
||||||
|
aiThinkingDotMessage: db "."
|
||||||
|
aiThinkingDotMessageLen: equ $ - aiThinkingDotMessage
|
||||||
|
endlnMessage: db 0xA
|
||||||
|
endlnMessageLen: equ $ - endlnMessage
|
||||||
|
|
||||||
|
section .bss
|
||||||
|
userInputBuffer resb 256
|
||||||
|
section .data
|
||||||
|
fieldBuffer: db "#########", 0xA, "# #", 0xA, "# #", 0xA, "# #", 0xA, "#########", 0xA
|
||||||
|
fieldBufferLen: equ $ - fieldBuffer
|
||||||
Reference in New Issue
Block a user