tic-tac-toe dne

This commit is contained in:
2025-02-05 22:28:50 +00:00
parent 9842267f8c
commit bff239624c
2 changed files with 305 additions and 6 deletions

View File

@@ -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
View File

@@ -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