# Description: A game to play a very simplified version of "Battleship"
.data
row_prompt:
.asciiz "row ? "
column_prompt:
.asciiz "column ? "
already_guessed:
.asciiz "You already guessed that, try again\n"
you_missed:
.asciiz "You missed\n"
you_lose:
.asciiz "Out of guesses -- too bad, you lose!\n"
you_win:
.asciiz "You sank my fleet - you win!\n"
ducky_hit:
.asciiz "You hit my rubber ducky!\n"
pirate_hit:
.asciiz "You hit my pirate ship!\n"
ducky_sank:
.asciiz "You sank my rubber ducky!\n"
pirate_sank:
.asciiz "You sank my pirate ship!\n"
next_game:
.asciiz "Ready for another game? (y or n)\n"
# game specific data structures
# use to keep track of whether this location has been guess already
guessed:
.space MAX_SIZE
# these are the data structures that will be passed to play_game
game1:
.word ships1
.word ships1 # need to add PIRATE_SIZE to this at run time
.word guessed
game2:
.word ships2
.word ships2 # need to add DUCKY_SIZE to this at run time
.word guessed
# your code should never access these directly - you'll find them
# via the game structure
ships1:
.byte PIRATE, 3 # type of ship, length of ship
.byte 0,0 # for alignment
.word 1,1,FALSE # row, column, hit=FALSE
.word 1,2,FALSE # row, column, hit=FALSE
.word 1,3,FALSE # row, column, hit=FALSE
.byte DUCKY, 2 # type of ship, length of ship
.byte 0,0 # for alignment
.word 3,0,FALSE # row, column, hit=FALSE
.word 4,0,FALSE # row, column, hit=FALSE
ships2:
.byte DUCKY,2
.byte 0,0 # for alignment
.word 0,2,FALSE
.word 0,3,FALSE
.byte PIRATE, 3
.byte 0,0 # for alignment
.word 4,4,FALSE
.word 3,4,FALSE
.word 2,4,FALSE
buffer: .space 10
.text
play_game:
addi $sp,$sp,-40 # allocate stack frame (on doubleword boundary)
sw $ra, 32($sp) # store the ra & s reg's on the stack
sw $s7, 28($sp)
sw $s6, 24($sp)
sw $s5, 20($sp)
sw $s4, 16($sp)
sw $s3, 12($sp)
sw $s2, 8($sp)
sw $s1, 4($sp)
sw $s0, 0($sp)
move $s0, $a0 # save the game address
li $t7, MAX_SHIPS # number of ships not sank
##
# initialize the game matrix
##
lw $t0, GUESSES($a0) # load the guess grid address
add $t1, $t0, MAX_SIZE # load the last address
li $t2, FALSE # set the values to FALSE
init_loop:
beq $t0, $t1, done_init
sb $t2, 0($t0) # store FALSE in the grid spot
addi $t0, $t0, 1 # increment the grid spot
j init_loop
done_init:
move $s1, $zero # zero out guesses taken
check_num_guesses:
li $t0, MAX_GUESSES
beq $s1, $t0, out_of_guesses
prompt:
##
# Get row and col data
##
la $a0, row_prompt
li $v0, PRINT_STRING
syscall
li $v0, READ_INT
syscall
move $s2, $v0
la $a0, column_prompt
li $v0, PRINT_STRING
syscall
li $v0, READ_INT
syscall
move $s3, $v0
##
# Check state of guess grid
##
li $t0, 5 # load 5 into t0
mult $s2, $t0 # multiply row by 5
mflo $t0 # get answer into t0
add $t0, $t0, $s3 # add col to get index
lw $t1, GUESSES($s0) # create pointer to start of grid
add $t1, $t1, $t0 # move the pointer
lb $t0, 0($t1) # load state into t0
move $s4, $t1 # save the address of the cur guess
bnez $t0, dupe_guess # if the number was already guessed
lw $s5, SHIP1($s0) # give it the first ship
move $s7, $zero # zero out ships counter
jal check_hit
addi $s1, $s1, 1 # increment shots taken
j check_num_guesses
check_hit:
li $t0, MAX_SHIPS
beq $s7, $t0, not_hit # done if its the max
move $a0, $s5 # save the addr of boat
move $s6, $zero # create a counter of holes
checking_loop:
lb $t1, LENGTH($s5) # get length of structure
beq $t1, $s6, done_checking_loop
addi $s6, $s6, 1 # increment counter
##
# Check row
##
lw $t1, ROW($a0) # load row offset from spot
bne $s2, $t1, miss
##
# Check col
##
lw $t1, COLUMN($a0) # load col offset from spot
bne $s3, $t1, miss
##
# At this point it is a hit
##
li $t1, TRUE # load the TRUE flag into t1
sw $t1, HIT($a0) # store it in the hit word of ship
lb $t1, TYPE($s5) # load type into t1
sb $t1, 0($s4) # store the ship type in the matrix
# print which ship is hit
li $t2, DUCKY
beq $t2, $t1, hit_ducky
li $t2, PIRATE
beq $t2, $t1, hit_pirate
hit_ducky:
la $a0, ducky_hit
j print_hit
hit_pirate:
la $a0, pirate_hit
print_hit:
li $v0, PRINT_STRING
syscall
j is_sunk
jr $ra
miss:
addi $a0, $a0, HOLE_SIZE # move to the next hole
j checking_loop
done_checking_loop:
move $t3, $s0
addi $t3, $t3, 4 # move to the next ship
lw $s5, 0($t3) # load the addr of next ship
addi $s7, $s7, 1 # increment ships counter
j check_hit
not_hit:
# update grid with NOT_HIT then print and j $ra
li $t1, GOT_HIT
sb $t1, 0($s4)
la $a0, you_missed
li $v0, PRINT_STRING
syscall
jr $ra
is_sunk:
lb $t1, LENGTH($s5) # length of current ship
move $t2, $s5 # make a temp copy of the address
sunk_loop:
beq $t1, $zero, sunk # if number of holes left to check is 0
addi $t1, $t1, -1 # decrement
li $t3, HOLE_SIZE
add $t2, $t2, $t3
lw $t5, 0($t2) # load the value of the HIT
li $t4, TRUE # load TRUE
beq $t4, $t5, sunk_loop
jr $ra
sunk:
lb $t3, TYPE($s5) # get the type of the ship
li $t2, DUCKY
beq $t2, $t3, sunk_ducky # if the ducky was sank
li $t2, PIRATE
beq $t2, $t3, sunk_pirate # if the pirate was sank
sunk_ducky:
la $a0, ducky_sank
j print_sunk
sunk_pirate:
la $a0, pirate_sank
print_sunk:
li $v0, PRINT_STRING
syscall
addi $t7, $t7, -1 # decrement number of ships
beq $t7, $zero, done_game_win
jr $ra
dupe_guess:
la $a0, already_guessed
li $v0, PRINT_STRING
syscall
j prompt
done_game_win:
la $a0, you_win
li $v0, PRINT_STRING
syscall
j done_play_game
out_of_guesses:
la $a0, you_lose
li $v0, PRINT_STRING
syscall
done_play_game:
lw $ra, 32($sp) # restore the ra & s reg's from the stack
lw $s7, 28($sp)
lw $s6, 24($sp)
lw $s5, 20($sp)
lw $s4, 16($sp)
lw $s3, 12($sp)
lw $s2, 8($sp)
lw $s1, 4($sp)
lw $s0, 0($sp)
addi $sp,$sp,40 # clean up stack
jr $ra
FS_M = 8
main:
sub $sp, $sp, FS_M
sw $ra, -4+FS_M($sp)
# fiddle with addresses in structure because the stupid assembler
# can't handle arithmetic with .word
li $t0, PIRATE_SIZE
la $t1, game1
lw $t2, 4($t1)
add $t2, $t2, $t0
sw $t2, 4($t1)
li $t0, DUCKY_SIZE
la $t1, game2
lw $t2, 4($t1)
add $t2, $t2, $t0
sw $t2, 4($t1)
# now let's get rolling and play the game!
# pass address of first game structure in a0
la $a0, game1
jal play_game
# ask if they want to play again
la $a0, next_game
li $v0, PRINT_STRING
syscall
# read the answer
li $v0, READ_STRING
la $a0, buffer
li $a1, 3
syscall
# see if it is yes
li $t0, 'y'
lb $t1, buffer
bne $t0, $t1, done_main
# they want to play again, so load up new game into a0
la $a0, game2
jal play_game
done_main:
# all done!
lw $ra, -4+FS_M($sp)
add $sp, $sp, FS_M
jr $ra