-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtictactoe.asm
More file actions
305 lines (229 loc) · 6.27 KB
/
Copy pathtictactoe.asm
File metadata and controls
305 lines (229 loc) · 6.27 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
%include "functions.asm"
SECTION .data
filename db "field.txt", 0h
welcome_msg db "WELCOME TO TICTACTOE", 0ah, 0h
wrong_input db "INPUT IS INCORRECT, TRY AGAIN: ", 0h
impossible_move db "THIS MOVE IS IMPOSSIBLE, TRY AGAIN: ", 0h
X_turn db "PLAYER X, CHOOSE A POSITION: ", 0h
O_turn db "PLAYER O, CHOOSE A POSITION: ", 0h
draw db "GAME ENDS IN A DRAW!", 0h
X_won db "PLAYER X WON!", 0h
O_won db "PLAYER O WON!", 0h
field_offsets db 2, 6, 10, 26, 30, 34, 50, 54, 58
SECTION .bss
field resb 255 ; holds the playfield with the made choices
turns resb 9 ; 2D mapped into 1D array of the made turns: 1 for X, -1 for O
count resb 1 ; counts turns made
player_input resb 255 ; large buffer in the case the user is stupid
index resb 1 ; the index chosen by the user
offset resb 1 ; the offset of the character that has to be placed in the field
char resb 1 ; will be 'X' or 'O'
id resb 1 ; will be 1 or -1
SECTION .text
global _start
_start:
mov eax, welcome_msg
call sprint
call _readField
call _printField
_setUpX:
mov byte [char], 'X'
mov byte [id], 1
mov eax, X_turn
call sprint
jmp _turn
_setUpO:
mov byte [char], 'O'
mov byte [id], -1
mov eax, O_turn
call sprint
jmp _turn
_turn:
call _takeInput
call _checkInput
call _parseInput
call _verifyTurn
call _updateTurnsArray
call _placeChar
inc byte [count]
call _printField
_referee:
; after 5 turns we begin checking if someone has won
cmp byte [count], 5
jge .checkWinner
.continueGame:
; when reaching 9 turns the game ends in a draw
cmp byte [count], 9
je _endGameInDraw
; checking the parity of count to know who is next
test byte [count], 1
jnz _setUpO
jz _setUpX
.checkWinner:
call _horizontalCheck
call _verticalCheck
call _diagonalCheck
jmp .continueGame
; --------------------- ------------ ---------------------
; --------------------- needed funcs ---------------------
; --------------------- ------------ ---------------------
;------------------------------------------
; Reads the field from field.txt and saves it
_readField:
; opening the file -> file operand will end up in eax
mov eax, 5
mov ebx, filename
mov ecx, 0
int 80h
; reading the file
mov ebx, eax ; first move the file operand from eax to ebx
mov eax, 3
mov ecx, field
mov edx, 255
int 80h
ret
;------------------------------------------
; Reads 255 bytes from STDIN
_takeInput:
mov eax, 3
mov ebx, 1
mov ecx, player_input
mov edx, 255
int 80h
ret
;------------------------------------------
; Checks if the input of the user is valid
_checkInput:
xor edx, edx
mov dl, byte [player_input]
cmp dl, '1'
jl .wrong
cmp dl, '9'
jg .wrong
jmp .finished
.wrong:
mov eax, wrong_input
call sprint
jmp _turn
.finished:
ret
;------------------------------------------
; Parsing the input to the integer, continues using what checkInput put in dl
_parseInput:
mov [index], dl
sub byte [index], 49
ret
;------------------------------------------
; Verifies if the turn is not made on top of another turn
_verifyTurn:
xor eax, eax
mov al, [index]
cmp byte [turns+eax], 0
jne .wrong
jmp .finished
.wrong:
mov eax, impossible_move
call sprint
jmp _turn
.finished:
ret
;------------------------------------------
; Will put the correct ID in the array
_updateTurnsArray:
xor eax, eax
xor ebx, ebx
mov al, [index]
mov bl, [id]
mov [turns+eax], bl
ret
;------------------------------------------
; Places the character into the field
_placeChar:
xor eax, eax
xor ebx, ebx
mov al, [index]
mov bl, byte [field_offsets+eax]
mov cl, byte [char]
mov [field+ebx], cl
ret
;------------------------------------------
; Loops through eacht horizontal row and checks the made moves
_horizontalCheck:
xor ebx, ebx
xor ecx, ecx
.loop:
xor eax, eax
inc ecx
add al, byte [turns+ebx]
inc ebx
add al, byte [turns+ebx]
inc ebx
add al, byte [turns+ebx]
inc ebx
cmp al, 3
je _winnerIsX
cmp al, -3
je _winnerIsO
cmp ecx, 9
jl .loop
ret
;------------------------------------------
; Same as above but then vertical
_verticalCheck:
xor ebx, ebx
xor ecx, ecx
.loop:
xor eax, eax
inc ecx
add al, byte [turns+ebx]
add bl, 3
add al, byte [turns+ebx]
add bl, 3
add al, byte [turns+ebx]
sub bl, 5
cmp al, 3
je _winnerIsX
cmp al, -3
je _winnerIsO
cmp ecx, 9
jl .loop
ret
;------------------------------------------
; Checks the diagonals in a hardcoded way because a loop for it is weird
_diagonalCheck:
xor eax, eax
add al, byte[turns]
add al, byte[turns+4]
add al, byte[turns+8]
cmp al, 3
je _winnerIsX
cmp al, -3
je _winnerIsO
xor eax, eax
add al, byte[turns+2]
add al, byte[turns+4]
add al, byte[turns+6]
cmp al, 3
je _winnerIsX
cmp al, -3
je _winnerIsO
ret
;------------------------------------------
; Do these need a description??
_printField:
mov eax, field
call sprint
ret
_winnerIsX:
mov eax, X_won
jmp _endGameWithWinner
_winnerIsO:
mov eax, O_won
jmp _endGameWithWinner
_endGameInDraw:
mov eax, draw
call sprintLF
call quit
_endGameWithWinner:
call sprintLF
call quit