Creating Positions and Jumps in a Checkers Game
.data
askrow: .asciiz "Row: "
askcol: .asciiz "Column: "
askval: .asciiz "Value: "
askr1: .asciiz "R1: "
askc1: .asciiz "C1: "
askr2: .asciiz "R2: "
askc2: .asciiz "C2: "
res1: .asciiz "isValidMove(): "
res2: .asciiz "isValidJump(): "
invalidPos: .asciiz "Invalid position. Please try again.\n"
board: .word 0 #pointer to allocated board space
.text
.globl main
# ---------------------------------------------------------------
# main function
# C prototype:
# main()
# ---------------------------------------------------------------
main:
li $a0,400 # allocate space for 10x10 values of 4 bytes
syscall $malloc
la $t0,board
sw $v0,($t0) # save pointer to allocated space in the board variable
# initialize board to zeros
la $t0,board # load board pointer
lw $t0,($t0)
li $t1,100 # counter for 400 elements
1:
sw $0,($t0) # save 0 in the board
addi $t0,$t0,4 # go to next board position
addi $t1,$t1,-1 # decrement number of remaining elements
bnez $t1,1b
la $t0,board
lw $s0,($t0) # load board pointer in s0
loop:
move $a0,$s0 # move board pointer to a0
jal displayBoard
la $a0,askrow # ask for a row
syscall $print_string
syscall $read_int # read row from user
move $t1,$v0 # save row in t1
beq $t1,-1,loop2
la $a0,askcol # ask for a column
syscall $print_string
syscall $read_int # read column from user
move $t2,$v0 # save column in t2
move $a0,$t1
move $a1,$t2
jal isLegalPosition # verify that the position is legal
bnez $v0,2f # if legal, skip to 2
la $a0,invalidPos # print error message
syscall $print_string
b loop # start over
2:
la $a0,askval # ask for a value
syscall $print_string
syscall $read_int # read value from user
# save value in board
li $t3,10
mul $t4,$t3,$t1 # row*10
add $t4,$t4,$t2 # row*10+col
sll $t4,$t4,2 # multiply by 4 to get offset in bytes
add $t4,$t4,$s0 # add offset to board address
sw $v0,($t4) # save value at selected position in board
b loop
loop2:
move $a0,$s0 # move board pointer to a0
jal displayBoard
la $a0,askr1 # ask for r1
syscall $print_string
syscall $read_int # read r1 from user
move $s1,$v0 # save r1 in s1
la $a0,askc1 # ask for c1
syscall $print_string
syscall $read_int # read c1 from user
move $s2,$v0 # save c1 in s2
la $a0,askr2 # ask for r2
syscall $print_string
syscall $read_int # read r2 from user
move $s3,$v0 # save r2 in s3
la $a0,askc2 # ask for c2
syscall $print_string
syscall $read_int # read c2 from user
move $s4,$v0 # save c2 in s4
move $a0,$s0
move $a1,$s1
move $a2,$s2
move $a3,$s3
addi $sp,$sp,-4 # allocate space in stack
sw $s4,0($sp) # save c2 in the stack
jal isValidMove # call isValidMove
add $sp,$sp,4 # restore stack pointer
la $a0,res1 # print isValidMove
syscall $print_string
move $a0,$v0
syscall $print_int # print the return value
li $a0,'\n
syscall $print_char # print a new line
move $a0,$s0
move $a1,$s1
move $a2,$s2
move $a3,$s3
addi $sp,$sp,-4 # allocate space in stack
sw $s4,0($sp) # save c2 in the stack
jal isValidJump # call isValidJump
add $sp,$sp,4 # restore stack pointer
la $a0,res2 # print isValidJump
syscall $print_string
move $a0,$v0
syscall $print_int # print the return value
li $a0,'\n
syscall $print_char # print a new line
b loop2
syscall $exit # exit from the program
# ---------------------------------------------------------------
# function to determine is a move is legal,
# C prototype:
# int isLegalPosition(int row, int column)
# Arguments:
# $a0=row
# $a1=column
# Return value:
# $v0
# ---------------------------------------------------------------
isLegalPosition:
li $v0,0 # set return value as illegal by default
bltz $a0,1f # row<0 is illegal
bgt $a0,9,1f # row>9 is illegal
bltz $a1,1f # col<0 is illegal
bgt $a1,9,1f # col>9 is illegal
add $t0,$a0,$a1 # add col and row
andi $t0,$t0,1 # see if it's an odd number
bnez $t0,1f # if it's odd it's illegal because the position is black
li $v0,1 # if we get here, set return value to 1, legal position
1:
jr $ra
# ---------------------------------------------------------------
# function to determine if a move is valid, C prototype:
# C prototype:
# int isValidMove(int *board, int r1, int c1, int r2, int c2)
# Arguments:
# $a0 = *board
# $a1 = r1
# $a2 = c1
# $a3 = r2
# ($sp) = c2
# Return value:
# $v0
# ---------------------------------------------------------------
isValidMove:
addi $sp,$sp,-4 # allocate space in stack
sw $ra,0($sp) # save return address in the stack
move $t1,$a1 # t1=r1
move $t2,$a2 # t2=c1
move $t3,$a3 # t3=r2
lw $t4,4($sp) # t4 = c2 (from stack)
move $t5,$a0 # load board pointer in t5
move $a0,$t1
move $a1,$t2
jal isLegalPosition # see if r1,c1 is a valid position
beqz $v0,rfail # illegal position returns 0
move $a0,$t3
move $a1,$t4
jal isLegalPosition # see if r2,c2 is a valid position
beqz $v0,rfail # illegal position returns 0
li $v0,0 # set $v0 to 0 to return 0 by default
li $t0,10
mul $t6,$t3,$t0 # r2*10
add $t6,$t6,$t4 # r2*10+c2
sll $t6,$t6,2 # multiply by 4 to get offset in bytes
add $t6,$t6,$t5 # address of board[r2*10+c2]
lw $t6,($t6) # load board(r2,c2)
bnez $t6,rfail # if it's not empty, return 0
mul $t7,$t1,$t0 # r1*10
add $t7,$t7,$t2 # r1*10+c2
sll $t7,$t7,2 # multiply by 4 to get offset in bytes
add $t7,$t7,$t5 # address of board[r1*10+c1]
lw $t7,($t7) # load board(r1,c1)
beqz $t7,rfail # if the piece to move is empty return 0
andi $t0,$t7,4 # see if the piece was a king
bnez $t0,kpiece # if it's king, skip
andi $t0,$t7,2 # see if the piece was a white
beqz $t0,rpiece # if it's red go to red piece
wpiece:
#white piece
sub $t0,$t1,$t3 # r1-r2
beq $t0,1,tstcol # if r1-r2==1, test columns
b rfail # else fail
rpiece:
# red piece
sub $t0,$t3,$t1 # r2-r1
beq $t0,1,tstcol # if r2-r1==1, test columns
b rfail # else fail
kpiece:
# king piece
sub $t0,$t3,$t1 # r2-r1
beq $t0,1,tstcol # if r2-r1==1, go to test columns
beq $t0,-1,tstcol # if r2-r1==-1, go to test columns
b rfail
tstcol:
sub $t0,$t4,$t2 # c2-c1
beq $t0,1,rok # if c2-c1==1, pass ok
bne $t0,-1,rfail # if c2-c1!=-1, fail
rok:
li $v0,1
rfail:
lw $ra,0($sp) # load return address from the stack
addi $sp,$sp,4 # restore stack pointer
jr $ra
# ---------------------------------------------------------------
# function to determine if a jump is valid
# C prototype:
# int isValidJump(int *board, int r1, int c1, int r2, int c2)
# Arguments:
# $a0 = *board
# $a1 = r1
# $a2 = c1
# $a3 = r2
# ($sp) = c2
# Return value:
# $v0
# ---------------------------------------------------------------
isValidJump:
addi $sp,$sp,-4 # allocate space in stack
sw $ra,0($sp) # save return address in the stack
move $t1,$a1 # t1=r1
move $t2,$a2 # t2=c1
move $t3,$a3 # t3=r2
lw $t4,4($sp) # t4 = c2 (from stack)
move $t5,$a0 # load board pointer in t5
move $a0,$t1
move $a1,$t2
jal isLegalPosition # see if r1,c1 is a valid position
beqz $v0,rfail2 # illegal position returns 0
move $a0,$t3
move $a1,$t4
jal isLegalPosition # see if r2,c2 is a valid position
beqz $v0,rfail2 # illegal position returns 0
li $v0,0 # set $v0 to 0 to return 0 by default
li $t0,10
mul $t6,$t3,$t0 # r2*10
add $t6,$t6,$t4 # r2*10+c2
sll $t6,$t6,2 # multiply by 4 to get offset in bytes
add $t6,$t6,$t5 # address of board[r2*10+c2]
lw $t6,($t6) # load board(r2,c2)
bnez $t6,rfail2 # if it's not empty, return 0
li $t0,10
add $t8,$t1,$t3 # add r1+r2
srl $t8,$t8,1 # position of middle piece r=(r1+r2)/2
mul $t6,$t8,$t0 # r*10
add $t8,$t2,$t4 # add c1+c2
srl $t8,$t8,1 # position of middle piece c=(c1+c2)/2
add $t6,$t6,$t8 # r*10+c
sll $t6,$t6,2 # multiply by 4 to get offset in bytes
add $t6,$t6,$t5 # address of board[r*10+c]
lw $t6,($t6) # load board(r,c)
beqz $t6,rfail2 # if it's empty, return 0
mul $t7,$t1,$t0 # r1*10
add $t7,$t7,$t2 # r1*10+c2
sll $t7,$t7,2 # multiply by 4 to get offset in bytes
add $t7,$t7,$t5 # address of board[r1*10+c1]
lw $t7,($t7) # load board(r1,c1)
xor $t8,$t6,$t7 # compare the middle piece and the jumping piece
andi $t8,$t8,2 # see if the pieces were different color
beqz $t8,rfail2 # if they were equal color, fail, can't jump over it
andi $t0,$t7,4 # see if the piece was a king
bnez $t0,kpiece2 # if it's king, skip
andi $t0,$t7,2 # see if the piece was a white
beqz $t0,rpiece2 # if it's red go to red piece
wpiece2:
#white piece
sub $t0,$t1,$t3 # r1-r2
beq $t0,2,tstcol2 # if r1-r2==2, test columns
b rfail2 # else fail
rpiece2:
# red piece
sub $t0,$t3,$t1 # r2-r1
beq $t0,2,tstcol2 # if r2-r1==2, test columns
b rfail2 # else fail
kpiece2:
# king piece
sub $t0,$t3,$t1 # r2-r1
beq $t0,2,tstcol2 # if r2-r1==2, go to test columns
beq $t0,-2,tstcol2 # if r2-r1==-2, go to test columns
b rfail2
tstcol2:
sub $t0,$t4,$t2 # c2-c1
beq $t0,2,rok2 # if c2-c1==2, pass ok
bne $t0,-2,rfail2 # if c2-c1!=-2, fail
rok2:
li $v0,1
rfail2:
lw $ra,0($sp) # load return address from the stack
addi $sp,$sp,4 # restore stack pointer
jr $ra
# ---------------------------------------------------------------
# function to print the board
# C prototype:
# void displayBoard(int* board)
# $a0 = *board
# ---------------------------------------------------------------
displayBoard:
move $t0,$a0 # save board address in t0
li $t1,9 # counter for rows
1:
li $t2,0 # counter for columns
2:
add $t3,$t1,$t2 # add row+column
andi $t3,$t3,1 # see if the sum is odd
beqz $t3,3f # if is even, skip
li $a0,219 # black square
b print # print it
3:
li $t3,10
mul $t4,$t3,$t1 # row*10
add $t4,$t4,$t2 # row*10+col
sll $t4,$t4,2 # multiply by 4 to get offset in bytes
add $t4,$t4,$t0 # add offset to board address
lw $a0,($t4) # load value at current position in board
bne $a0,3,4f # if board[row,col]!=3
li $a0,'w
b print
4:
bne $a0,1,5f # if board[row,col]!=1
li $a0,'r
b print
5:
bne $a0,5,6f # if board[row,col]!=5
li $a0,'R
b print
6:
bne $a0,7,7f # if board[row,col]!=7
li $a0,'W
b print
7:
li $a0,32 # white square (space)
print:
syscall $print_char # print the char
addi $t2,$t2,1 # increment column
blt $t2,10,2b # repeat while the column < 10
li $a0,'\n
syscall $print_char # print a new line
addi $t1,$t1,-1 # decrement row number
bgez $t1,1b # repeat while the row >=0
jr $ra