Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Please write your code in MIPS assembly, thank you. Introduction to Computer Arc

ID: 3815567 • Letter: P

Question

Please write your code in MIPS assembly, thank you.

Introduction to Computer Architecture Multi-Dimensional Memory For this assignment, you will create a tic-tac-toe game by implementing the following functions: The initialize function should create a new empty game board and return a pointer to that data structure. play_X and play_0 place their respective symbols in the specified cell, then call the win function to determine if that move resulted in a win. Those functions return one of three values, representing a valid move, an invalid move, and a move resulting in a win. The win function uses the knowledge of the most recent move to only check for ways in which a win could have occurred this turn instead of having to test all possible solutions. It returns values representing either a win or no win. The draw_board function prints the current state of the game to the console. play_a_game uses the previous functions to allow two people to play tic-tac-toe.

Explanation / Answer

.text
.globl main

PRINTLINE:
la $t0, BORDER0   
move $t1, $a0

PRINTLINE_LOOP:
beqz $t1, PRINTLINE_BOTTOM
       move $a0, $t0
li $v0, 4
syscall

addi $t1, $t1, -1
j PRINTLINE_LOOP

PRINTLINE_BOTTOM:
la $a0, PLUS
li $v0, 4
syscall

jr $ra
PRINTBOARD:
  
addiu $sp, $sp, -4
sw $ra, 0($sp)

move $t0, $a0   
li $t1, 0   
li $t3, 0

li $t6, 0
add $t6, $t6, $t0   
add $t6, $t6, $t0   
addiu $t6, $t6, 1
PRINTBOARD_OUTERLOOP:
beq $t1, $t6, PRINTBOARD_BOTTOM
li $t2, 0       

li $t4, 2
div $t1, $t4
mfhi $t4
           li $t5, 1
beq $t4, $t5, PRINTBOARD_INNERLOOP_START
move $a0, $t0
       addi $sp, $sp, -8
sw $t0, 0($sp)
sw $t1, 4($sp)

jal PRINTLINE
   lw $t1, 4($sp)
lw $t0, 0($sp)
addiu $sp, $sp, 8

j PRINTBOARD_OUTERLOOP_BOTTOM

PRINTBOARD_INNERLOOP_START:
la $a0, PIPE
li $v0, 4
syscall
PRINTBOARD_INNERLOOP:
beq $t2, $t0, PRINTBOARD_OUTERLOOP_BOTTOM

la $a0, BOARD
add $a0, $a0, $t3      
lb $a0, 0($a0)
li $v0, 11
syscall

la $a0, PIPE   
li $v0, 4
   syscall

addiu $t3, $t3, 1   
addiu $t2, $t2, 1

j PRINTBOARD_INNERLOOP

PRINTBOARD_OUTERLOOP_BOTTOM:
addiu $t1, $t1, 1      

la $a0, NEWLINE
li $v0, 4
syscall

j PRINTBOARD_OUTERLOOP

# return;
PRINTBOARD_BOTTOM:
li $v0, 4
syscall

lw $ra, 0($sp)
addiu $sp, $sp, 4
jr $ra

AISTURN:

AISTURN_WINNINGMOVE_CHECKROWS:
li $t0, 0
li $t1, 0   

AISTURN_WINNINGMOVE_CHECKROWS_OUTERLOOP:
beq $t0, $s2, AISTURN_WINNINGMOVE_CHECKCOL
li $t1, 0   
li $t2, 0   
li $t3, 0
li $t4, -1

AISTURN_WINNINGMOVE_CHECKROWS_INNERLOOP:
beq $t1, $s2, AISTURN_WINNINGMOVE_CHECKROWS_OUTERLOOP_BOTTOM
mul $t5, $t0, $s2   
add $t5, $t5, $t1   
move $t8, $t5
la $t6, BOARD
addu $t6, $t6, $t5
lb $t5, 0($t6)   

li $t6, ' '
beq $t5, $t6, AISTURN_WINNINGMOVE_CHECKROWS_INNERLOOP_IF

j AISTURN_WINNINGMOVE_CHECKROWS_INNERLOOP_BOTTOM

AISTURN_WINNINGMOVE_CHECKROWS_INNERLOOP_IF:
addiu $t2, $t2, 1
move $t4, $t8   

AISTURN_WINNINGMOVE_CHECKROWS_INNERLOOP_BOTTOM:
li $t6, 'O'
seq $t6, $t5, $t6   
addu $t3, $t3, $t6   

addiu $t1, $t1, 1

j AISTURN_WINNINGMOVE_CHECKROWS_INNERLOOP

AISTURN_WINNINGMOVE_CHECKROWS_OUTERLOOP_BOTTOM:

li $t5, 1
seq $t6, $t2, $t5
move $t5, $s2
addiu $t5, $t5, -1
seq $t7, $t3, $t5   

and $t6, $t6, $t7

li $t5, 1
beq $t6, $t5, AISTURN_WINNINGMOVE_CHECKROWS_OUTERLOOP_EXIT

addiu $t0, $t0, 1 # ++i

j AISTURN_WINNINGMOVE_CHECKROWS_OUTERLOOP

AISTURN_WINNINGMOVE_CHECKROWS_OUTERLOOP_EXIT:
move $t0, $t4

la $t2, BOARD
add $t2, $t2, $t0
li $t3, 'O'
sb $t3, 0($t2)
addiu $s3, $s3, 1

la $a0, NEWLINE
li $v0, 4
syscall

j AI_WIN
  
AISTURN_WINNINGMOVE_CHECKCOL:
li $t0, 0
li $t1, 0 # j = 0

AISTURN_WINNINGMOVE_CHECKCOL_OUTERLOOP:
beq $t0, $s2, AISTURN_WINNINGMOVE_DIAGLEFT # No winning move found.
li $t1, 0 # j = 0
li $t2, 0 # numspaces = 0
li $t3, 0 # numos = 0
li $t4, -1

AISTURN_WINNINGMOVE_CHECKCOL_INNERLOOP:
beq $t1, $s2, AISTURN_WINNINGMOVE_CHECKCOL_OUTERLOOP_BOTTOM

mul $t5, $t1, $s2 # t5 = j * n
add $t5, $t5, $t0 # t5 = j * n + i
move $t8, $t5 # t8 = t5
la $t6, BOARD
addu $t6, $t6, $t5
lb $t5, 0($t6) # t5 = board[j * n + i]

li $t6, ' '
beq $t5, $t6, AISTURN_WINNINGMOVE_CHECKCOL_INNERLOOP_IF

j AISTURN_WINNINGMOVE_CHECKCOL_INNERLOOP_BOTTOM

AISTURN_WINNINGMOVE_CHECKCOL_INNERLOOP_IF:
addiu $t2, $t2, 1
move $t4, $t8 # index = i * n + j

AISTURN_WINNINGMOVE_CHECKCOL_INNERLOOP_BOTTOM:

li $t6, 'O'
seq $t6, $t5, $t6 # t6 = (board[i * n + j] == ' ')
addu $t3, $t3, $t6 # numos += t6

addiu $t1, $t1, 1 # ++j

j AISTURN_WINNINGMOVE_CHECKCOL_INNERLOOP

AISTURN_WINNINGMOVE_CHECKCOL_OUTERLOOP_BOTTOM:
# if (numspaces == 1 && numos == n - 1)
# board[index] = 'O'
li $t5, 1
seq $t6, $t2, $t5 # t6 = (numspaces == 1)
move $t5, $s2
addiu $t5, $t5, -1 # t5 = n - 1
seq $t7, $t3, $t5 # t7 = (numos == n - 1)

and $t6, $t6, $t7 # t6 = t6 && t7

li $t5, 1
beq $t6, $t5, AISTURN_WINNINGMOVE_CHECKCOL_OUTERLOOP_EXIT

addiu $t0, $t0, 1 # ++i

j AISTURN_WINNINGMOVE_CHECKCOL_OUTERLOOP

AISTURN_WINNINGMOVE_CHECKCOL_OUTERLOOP_EXIT:
move $t0, $t4

# li $v0, 4
# la $a0, AIWINNER
# syscall
la $t2, BOARD
add $t2, $t2, $t0
li $t3, 'O'
sb $t3, 0($t2)
addiu $s3, $s3, 1

la $a0, NEWLINE
li $v0, 4
syscall
j AI_WIN
# j AISTURN_MAKE_MOVE

AISTURN_WINNINGMOVE_DIAGLEFT:
li $t0, 0 # i = 0
li $t1, 0 # numspaces = 0
li $t2, 0 # numos = 0
li $t3, 0 # index = 0

AISTURN_WINNINGMOVE_DIAGLEFT_LOOP:
beq $t0, $s2, AISTURN_WINNINGMOVE_DIAGLEFT_CHECK

la $t4, BOARD # load address of board
mul $t5, $t0, $s2
add $t5, $t5, $t0
add $t8, $t5, $t4
lb $t4, 0($t8)

# Count an O if it is seen.
li $t6, 'O'
seq $t7, $t4, $t6
addu $t2, $t2, $t7

li $t6, ' '
beq $t4, $t6, AISTURN_WINNINGMOVE_DIAGLEFT_LOOP_IF

AISTURN_WINNINGMOVE_DIAGLEFT_LOOP_BOTTOM:
addiu $t0, $t0, 1    # ++i
j AISTURN_WINNINGMOVE_DIAGLEFT_LOOP

AISTURN_WINNINGMOVE_DIAGLEFT_CHECK:
addi $t6, $s2, -1

seq $t7, $t2, $t6 # t7 = (numos == n - 1)

li $t6, 1
seq $t8, $t1, $t6 # t8 = (numspaces == 1)

and $t7, $t7, $t8 # t7 = ((numos == n - 1) && (numspaces == 1))

li $t6, 1
beq $t7, $t6, AISTURN_WINNINGMOVE_DIAGLEFT_LOOP_EXIT

j AISTURN_WINNINGMOVE_DIAGRIGHT

AISTURN_WINNINGMOVE_DIAGLEFT_LOOP_IF:
addiu $t1, $t1, 1 # inc numspaces
move $t3, $t5 # index = i * n + i

j    AISTURN_WINNINGMOVE_DIAGLEFT_LOOP_BOTTOM

AISTURN_WINNINGMOVE_DIAGLEFT_LOOP_EXIT:
move $t0, $t3
# j AISTURN_MAKE_MOVE

la $t2, BOARD
add $t2, $t2, $t0
li $t3, 'O'
sb $t3, 0($t2)
addiu $s3, $s3, 1

la $a0, NEWLINE
li $v0, 4
syscall

j AI_WIN

AISTURN_WINNINGMOVE_DIAGRIGHT:
li $t0, 0 # i = 0
li $t1, 0 # numspaces = 0
li $t2, 0 # numos = 0
li $t3, 0 # index = 0
addi $t9, $s2, -1 # j = n - 1

AISTURN_WINNINGMOVE_DIAGRIGHT_LOOP:
beq $t0, $s2, AISTURN_WINNINGMOVE_DIAGRIGHT_CHECK

la $t4, BOARD # load address of board
add $t5, $t9, $t4
lb $t4, 0($t5)

# Count an O if it is seen.
li $t6, 'O'
seq $t7, $t4, $t6
addu $t2, $t2, $t7

li $t6, ' '
beq $t4, $t6, AISTURN_WINNINGMOVE_DIAGRIGHT_LOOP_IF

AISTURN_WINNINGMOVE_DIAGRIGHT_LOOP_BOTTOM:
addiu $t0, $t0, 1    # ++i
add $t9, $t9, $s2 # j += n - 1
addi $t9, $t9, -1
j AISTURN_WINNINGMOVE_DIAGRIGHT_LOOP

AISTURN_WINNINGMOVE_DIAGRIGHT_CHECK:
move $t6, $s2
addi $t6, $t6, -1

seq $t7, $t2, $t6 # t7 = (numos == n - 1)

li $t6, 1
seq $t8, $t1, $t6 # t8 = (numspaces == 1)

and $t7, $t7, $t8 # t7 = ((numos == n - 1) && (numspaces == 1))

li $t6, 1
beq $t7, $t6, AISTURN_WINNINGMOVE_DIAGRIGHT_LOOP_EXIT

j AI_BLOCK_MOVE

AISTURN_WINNINGMOVE_DIAGRIGHT_LOOP_IF:
addiu $t1, $t1, 1 # inc numspaces
move $t3, $t9 # index = j

j    AISTURN_WINNINGMOVE_DIAGRIGHT_LOOP_BOTTOM

AISTURN_WINNINGMOVE_DIAGRIGHT_LOOP_EXIT:
move $t0, $t3
# j AISTURN_MAKE_MOVE
la $t2, BOARD
add $t2, $t2, $t0
li $t3, 'O'
sb $t3, 0($t2)
addiu $s3, $s3, 1

la $a0, NEWLINE
li $v0, 4
syscall

j AI_WIN


AI_BLOCK_MOVE:

AISTURN_BLOCK_CHECKROWS:
li $t0, 0 # i = 0
li $t1, 0 # j = 0

AISTURN_BLOCK_CHECKROWS_OUTERLOOP:
beq $t0, $s2, AISTURN_BLOCK_CHECKCOL # No winning move found.
li $t1, 0 # j = 0
li $t2, 0 # numspaces = 0
li $t3, 0 # numos = 0
li $t4, -1

AISTURN_BLOCK_CHECKROWS_INNERLOOP:
beq $t1, $s2, AISTURN_BLOCK_CHECKROWS_OUTERLOOP_BOTTOM

mul $t5, $t0, $s2 # t5 = i * n
add $t5, $t5, $t1 # t5 = i * n + j
move $t8, $t5 # t8 = t5
la $t6, BOARD
addu $t6, $t6, $t5
lb $t5, 0($t6) # t5 = board[i * n + j]

li $t6, ' '
beq $t5, $t6, AISTURN_BLOCK_CHECKROWS_INNERLOOP_IF

j AISTURN_BLOCK_CHECKROWS_INNERLOOP_BOTTOM

AISTURN_BLOCK_CHECKROWS_INNERLOOP_IF:
addiu $t2, $t2, 1 # ++numspaces
move $t4, $t8 # index = i * n + j

AISTURN_BLOCK_CHECKROWS_INNERLOOP_BOTTOM:
# if (board[i * n + j] == 'O')
# ++numspaces;
li $t6, 'X' #$$$$$$$$$$
seq $t6, $t5, $t6 # t6 = (board[i * n + j] == ' ')
addu $t3, $t3, $t6 # numos += t6

addiu $t1, $t1, 1 # ++j

j AISTURN_BLOCK_CHECKROWS_INNERLOOP

AISTURN_BLOCK_CHECKROWS_OUTERLOOP_BOTTOM:
# if (numspaces == 1 && numos == n - 1)
# board[index] = 'O'
li $t5, 1
seq $t6, $t2, $t5 # t6 = (numspaces == 1)
move $t5, $s2
addiu $t5, $t5, -1 # t5 = n - 1
seq $t7, $t3, $t5 # t7 = (numos == n - 1)

and $t6, $t6, $t7 # t6 = t6 && t7

li $t5, 1
beq $t6, $t5, AISTURN_BLOCK_CHECKROWS_OUTERLOOP_EXIT

addiu $t0, $t0, 1 # ++i

j AISTURN_BLOCK_CHECKROWS_OUTERLOOP

AISTURN_BLOCK_CHECKROWS_OUTERLOOP_EXIT:
move $t0, $t4

# li $v0, 4
# la $a0, AIWINNER
# syscall

j AISTURN_MAKE_MOVE


AISTURN_BLOCK_CHECKCOL:
li $t0, 0 # i = 0
li $t1, 0 # j = 0

AISTURN_BLOCK_CHECKCOL_OUTERLOOP:
beq $t0, $s2, AISTURN_BLOCK_DIAGLEFT # No winning move found.
li $t1, 0 # j = 0
li $t2, 0 # numspaces = 0
li $t3, 0 # numos = 0
li $t4, -1

AISTURN_BLOCK_CHECKCOL_INNERLOOP:
beq $t1, $s2, AISTURN_BLOCK_CHECKCOL_OUTERLOOP_BOTTOM

mul $t5, $t1, $s2 # t5 = j * n
add $t5, $t5, $t0 # t5 = j * n + i
move $t8, $t5 # t8 = t5
la $t6, BOARD
addu $t6, $t6, $t5
lb $t5, 0($t6) # t5 = board[j * n + i]

li $t6, ' '
beq $t5, $t6, AISTURN_BLOCK_CHECKCOL_INNERLOOP_IF

j AISTURN_BLOCK_CHECKCOL_INNERLOOP_BOTTOM

AISTURN_BLOCK_CHECKCOL_INNERLOOP_IF:
addiu $t2, $t2, 1 # ++numspaces
move $t4, $t8 # index = i * n + j

AISTURN_BLOCK_CHECKCOL_INNERLOOP_BOTTOM:
# if (board[i * n + j] == 'O')
# ++numspaces;
li $t6, 'X'#$$$$$$$$$$$$$
seq $t6, $t5, $t6 # t6 = (board[i * n + j] == ' ')
addu $t3, $t3, $t6 # numos += t6

addiu $t1, $t1, 1 # ++j

j AISTURN_BLOCK_CHECKCOL_INNERLOOP

AISTURN_BLOCK_CHECKCOL_OUTERLOOP_BOTTOM:
# if (numspaces == 1 && numos == n - 1)
# board[index] = 'O'
li $t5, 1
seq $t6, $t2, $t5 # t6 = (numspaces == 1)
move $t5, $s2
addiu $t5, $t5, -1 # t5 = n - 1
seq $t7, $t3, $t5 # t7 = (numos == n - 1)

and $t6, $t6, $t7 # t6 = t6 && t7

li $t5, 1
beq $t6, $t5, AISTURN_BLOCK_CHECKCOL_OUTERLOOP_EXIT

addiu $t0, $t0, 1 # ++i

j AISTURN_BLOCK_CHECKCOL_OUTERLOOP

AISTURN_BLOCK_CHECKCOL_OUTERLOOP_EXIT:
move $t0, $t4

j AISTURN_MAKE_MOVE

AISTURN_BLOCK_DIAGLEFT:
li $t0, 0 # i = 0
li $t1, 0 # numspaces = 0
li $t2, 0 # numos = 0
li $t3, 0 # index = 0

AISTURN_BLOCK_DIAGLEFT_LOOP:
beq $t0, $s2, AISTURN_BLOCK_DIAGLEFT_CHECK

la $t4, BOARD # load address of board
mul $t5, $t0, $s2
add $t5, $t5, $t0
add $t8, $t5, $t4
lb $t4, 0($t8)

li $t6, 'X'
seq $t7, $t4, $t6
addu $t2, $t2, $t7

li $t6, ' '
beq $t4, $t6, AISTURN_BLOCK_DIAGLEFT_LOOP_IF

AISTURN_BLOCK_DIAGLEFT_LOOP_BOTTOM:
addiu $t0, $t0, 1    # ++i
j AISTURN_BLOCK_DIAGLEFT_LOOP

AISTURN_BLOCK_DIAGLEFT_CHECK:
addi $t6, $s2, -1

seq $t7, $t2, $t6 # t7 = (numos == n - 1)

li $t6, 1
seq $t8, $t1, $t6 # t8 = (numspaces == 1)

and $t7, $t7, $t8 # t7 = ((numos == n - 1) && (numspaces == 1))

li $t6, 1
beq $t7, $t6, AISTURN_BLOCK_DIAGLEFT_LOOP_EXIT

j AISTURN_BLOCK_DIAGRIGHT

AISTURN_BLOCK_DIAGLEFT_LOOP_IF:
addiu $t1, $t1, 1 # inc numspaces
move $t3, $t5 # index = i * n + i

j    AISTURN_BLOCK_DIAGLEFT_LOOP_BOTTOM

AISTURN_BLOCK_DIAGLEFT_LOOP_EXIT:
move $t0, $t3
j AISTURN_MAKE_MOVE

AISTURN_BLOCK_DIAGRIGHT:
li $t0, 0 # i = 0
li $t1, 0 # numspaces = 0
li $t2, 0 # numos = 0
li $t3, 0 # index = 0
addi $t9, $s2, -1 # j = n - 1

AISTURN_BLOCK_DIAGRIGHT_LOOP:
beq $t0, $s2, AISTURN_BLOCK_DIAGRIGHT_CHECK

la $t4, BOARD # load address of board
add $t5, $t9, $t4
lb $t4, 0($t5)

# Count an X if it is seen.
li $t6, 'X'
seq $t7, $t4, $t6
addu $t2, $t2, $t7

li $t6, ' '
beq $t4, $t6, AISTURN_BLOCK_DIAGRIGHT_LOOP_IF

AISTURN_BLOCK_DIAGRIGHT_LOOP_BOTTOM:
addiu $t0, $t0, 1    # ++i
add $t9, $t9, $s2 # j += n - 1
addi $t9, $t9, -1
j AISTURN_BLOCK_DIAGRIGHT_LOOP

AISTURN_BLOCK_DIAGRIGHT_CHECK:
move $t6, $s2
addi $t6, $t6, -1

seq $t7, $t2, $t6 # t7 = (numos == n - 1)

li $t6, 1
seq $t8, $t1, $t6 # t8 = (numspaces == 1)

and $t7, $t7, $t8 # t7 = ((numos == n - 1) && (numspaces == 1))

li $t6, 1
beq $t7, $t6, AISTURN_BLOCK_DIAGRIGHT_LOOP_EXIT

j AISTURN_PICKFIRST

AISTURN_BLOCK_DIAGRIGHT_LOOP_IF:
addiu $t1, $t1, 1 # inc numspaces
move $t3, $t9 # index = j

j    AISTURN_BLOCK_DIAGRIGHT_LOOP_BOTTOM

AISTURN_BLOCK_DIAGRIGHT_LOOP_EXIT:
move $t0, $t3
j AISTURN_MAKE_MOVE


AISTURN_PICKFIRST:
li $t0, 0 # i = 0
mul $t1, $s2, $s2 # t1 = n * n

AISTURN_PICKFIRST_LOOP:
la $t2, BOARD
add $t2, $t2, $t0
lb $t2, 0($t2)
li $t3, ' '
beq $t2, $t3, AISTURN_MAKE_MOVE

addiu $t0, $t0, 1    # ++i
j AISTURN_PICKFIRST_LOOP


AISTURN_MAKE_MOVE:
la $t2, BOARD
add $t2, $t2, $t0
li $t3, 'O'
sb $t3, 0($t2)
addiu $s3, $s3, 1

la $a0, NEWLINE
li $v0, 4
syscall

j GAMELOOP_BOTTOM
main:
   li $s3, 1

   li $v0, 4
   la $a0, GREETING
   syscall

   li $v0, 4
   la $a0, ENTERn
   syscall

# get n from the user
li $v0, 5
syscall
move $s2, $v0
la $t0, BOARD
li $t1, 0
mul $t2, $s2, $s2


INITBOARD:
beq $t1, $t2 INITBOARD_END


li $t3, ' '


add $t4, $t0, $t1

  
sb $t3, 0($t4)

addiu $t1, $t1, 1 # ++i
j INITBOARD


INITBOARD_END:
add $t4, $t0, $t1 # get board[n]
li $t3, 0
sb $t3, 0($t4) # board[n] = ' '

li $v0, 4
la $a0, FIRST
syscall

addi $t0, $s2, -1
li    $t1, 2
div $t0, $t1
mflo $t0

addi $t2, $s2, -1
div $t2, $t1
mflo $t2

mul $t0, $t0, $s2
add $t0, $t0, $t2
la    $t1, BOARD
add $t0, $t0, $t1

li $t2, 'O'
sb $t2, 0($t0)

GAMELOOP:
move $a0, $s2 # hello
jal PRINTBOARD

li $t0, 2
div $s3, $t0
mfhi $t0
beqz $t0, AISTURN

li $v0, 4
la $a0, INPUTROW
syscall

li $v0, 5 # get row selection from user
syscall
move $s0, $v0

li $v0, 4
la $a0, INPUTCOLUMN
syscall

li $v0, 5 # get column selection from user
syscall
move $s1, $v0

# if (row < 0 || row >= n) goto INVALID_MOVE
VALIDATE_ROW:
bltz $s0, INVALID_MOVE
move $t0, $s2
bge $s0, $t0, INVALID_MOVE

# if (col < 0 || col >= n) goto INVALID_MOVE
VALIDATE_COL:
bltz $s1, INVALID_MOVE
move $t0, $s2
bge $s1, $t0, INVALID_MOVE

VALIDATE_ROWCOL:

mul $t0, $s0, $s2
add $t0, $t0, $s1

la $t1, BOARD # t1 = board[0]
addu $t1, $t1, $t0 # t1 = board[0] + i
lb $t1, 0($t1) # t1 = *(board[0] + i)
li $t2, ' '
bne $t1, $t2, INVALID_MOVE
j VALID_MOVE

INVALID_MOVE:
li $v0, 4
la $a0, INVALIDMOVESTR
syscall
j GAMELOOP_BOTTOM

VALID_MOVE:
mul $t0, $s0, $s2
add $t0, $t0, $s1
la $t1, BOARD
add $t1, $t1, $t0
li $t2, 'X'
sb $t2, 0($t1)

addiu $s3, $s3, 1 # turncount++
GAMELOOP_BOTTOM:

CHICKEN_DINNER:

CHICKEN_DINNER_CHECKROWS:
li $t0, 0 # i = 0
li $t1, 0 # j = 0

CHICKEN_DINNER_CHECKROWS_OUTERLOOP:
beq $t0, $s2, CHICKEN_DINNER_CHECKCOL # No winning move found.
li $t1, 0 # j = 0
li $t2, 0 # numspaces = 0
li $t3, 0 # numos = 0
li $t4, -1

CHICKEN_DINNER_CHECKROWS_INNERLOOP:
beq $t1, $s2, CHICKEN_DINNER_CHECKROWS_OUTERLOOP_BOTTOM

# if (board[i * n + j] == ' ')
# ++numspaces;
mul $t5, $t0, $s2 # t5 = i * n
add $t5, $t5, $t1 # t5 = i * n + j
move $t8, $t5 # t8 = t5
la $t6, BOARD
addu $t6, $t6, $t5
lb $t5, 0($t6) # t5 = board[i * n + j]

li $t6, ' '
beq $t5, $t6, CHICKEN_DINNER_CHECKROWS_INNERLOOP_IF

j CHICKEN_DINNER_CHECKROWS_INNERLOOP_BOTTOM

CHICKEN_DINNER_CHECKROWS_INNERLOOP_IF:
addiu $t2, $t2, 1 # ++numspaces
move $t4, $t8 # index = i * n + j

CHICKEN_DINNER_CHECKROWS_INNERLOOP_BOTTOM:
# if (board[i * n + j] == 'O')
# ++numspaces;
li $t6, 'X' #$$$$$$$$$$
seq $t6, $t5, $t6 # t6 = (board[i * n + j] == ' ')
addu $t3, $t3, $t6 # numos += t6

addiu $t1, $t1, 1 # ++j

j CHICKEN_DINNER_CHECKROWS_INNERLOOP

CHICKEN_DINNER_CHECKROWS_OUTERLOOP_BOTTOM:
# if (numspaces == 0 && numos == n)
# board[index] = 'O'
li $t5, 0
seq $t6, $t2, $t5 # t6 = (numspaces == 1)
move $t5, $s2
seq $t7, $t3, $t5 # t7 = (numos == n - 1)

and $t6, $t6, $t7 # t6 = t6 && t7

li $t5, 1
beq $t6, $t5, CHICKEN_DINNER_CHECKROWS_OUTERLOOP_EXIT

addiu $t0, $t0, 1 # ++i

j CHICKEN_DINNER_CHECKROWS_OUTERLOOP

CHICKEN_DINNER_CHECKROWS_OUTERLOOP_EXIT:
j CHICKEN_DINNER_PRINT_WINNER

CHICKEN_DINNER_CHECKCOL:
li $t0, 0 # i = 0
li $t1, 0 # j = 0

CHICKEN_DINNER_CHECKCOL_OUTERLOOP:
beq $t0, $s2, CHICKEN_DINNER_DIAGLEFT # No winning move found.
li $t1, 0 # j = 0
li $t2, 0 # numspaces = 0
li $t3, 0 # numos = 0
li $t4, -1

CHICKEN_DINNER_CHECKCOL_INNERLOOP:
beq $t1, $s2, CHICKEN_DINNER_CHECKCOL_OUTERLOOP_BOTTOM

# if (board[i * n + j] == ' ')
# ++numspaces;
mul $t5, $t1, $s2 # t5 = j * n
add $t5, $t5, $t0 # t5 = j * n + i
move $t8, $t5 # t8 = t5
la $t6, BOARD
addu $t6, $t6, $t5
lb $t5, 0($t6) # t5 = board[j * n + i]

li $t6, ' '
beq $t5, $t6, CHICKEN_DINNER_CHECKCOL_INNERLOOP_IF

j CHICKEN_DINNER_CHECKCOL_INNERLOOP_BOTTOM

CHICKEN_DINNER_CHECKCOL_INNERLOOP_IF:
addiu $t2, $t2, 1 # ++numspaces
move $t4, $t8 # index = i * n + j

CHICKEN_DINNER_CHECKCOL_INNERLOOP_BOTTOM:
# if (board[i * n + j] == 'O')
# ++numspaces;
li $t6, 'X'#$$$$$$$$$$$$$
seq $t6, $t5, $t6 # t6 = (board[i * n + j] == ' ')
addu $t3, $t3, $t6 # numos += t6

addiu $t1, $t1, 1 # ++j

j CHICKEN_DINNER_CHECKCOL_INNERLOOP

CHICKEN_DINNER_CHECKCOL_OUTERLOOP_BOTTOM:
# if (numspaces == 0 && numos == n)
# board[index] = 'O'
li $t5, 0
seq $t6, $t2, $t5 # t6 = (numspaces == 1)
move $t5, $s2
seq $t7, $t3, $t5 # t7 = (numos == n - 1)

and $t6, $t6, $t7 # t6 = t6 && t7

li $t5, 1
beq $t6, $t5, CHICKEN_DINNER_CHECKCOL_OUTERLOOP_EXIT

addiu $t0, $t0, 1 # ++i

j CHICKEN_DINNER_CHECKCOL_OUTERLOOP

CHICKEN_DINNER_CHECKCOL_OUTERLOOP_EXIT:
j CHICKEN_DINNER_PRINT_WINNER

CHICKEN_DINNER_DIAGLEFT:
li $t0, 0 # i = 0
li $t1, 0 # numspaces = 0
li $t2, 0 # numos = 0
li $t3, 0 # index = 0

CHICKEN_DINNER_DIAGLEFT_LOOP:
beq $t0, $s2, CHICKEN_DINNER_DIAGLEFT_CHECK

la $t4, BOARD # load address of board
mul $t5, $t0, $s2
add $t5, $t5, $t0
add $t8, $t5, $t4
lb $t4, 0($t8)

# Count an X if it is seen.
li $t6, 'X'
seq $t7, $t4, $t6
addu $t2, $t2, $t7

li $t6, ' '
beq $t4, $t6, CHICKEN_DINNER_DIAGLEFT_LOOP_IF

CHICKEN_DINNER_DIAGLEFT_LOOP_BOTTOM:
addiu $t0, $t0, 1    # ++i
j CHICKEN_DINNER_DIAGLEFT_LOOP