Peg Solitaire (MIPS R2000 Assembly)

Spring 2011 | Project Length: 4 weeks (Elective coursework)

A Peg Solitaire game written from scratch in MIPS R2000 Assembly Language as a solo project. Done as a final project for my Computer Organization class. Validates user input, prints appropriate error messages, and detects when the game has ended.

The class itself was taken as a free elective. The full source code can be downloaded bottom of this page.

Example Session

   ************************
   **     Peg Puzzle     **
   ************************

    0  1  2  3  4  5  6
        +---------+
0       | X  X  X |
1 +-----+ X  X  X +-----+
2 | X  X  X  X  X  X  X |
3 | X  X  X     X  X  X |
4 | X  X  X  X  X  X  X |
5 +-----+ X  X  X +-----+
6       | X  X  X |
        +---------+

Enter the location of the peg to move (RC, -1 to quit): 00

Illegal location.

Enter the location of the peg to move (RC, -1 to quit): 33

Illegal move, no peg at source location.

Enter the location of the peg to move (RC, -1 to quit): 03
Enter the location where the peg is moving to (RC, -1 to quit): 23

Illegal move, destination location is occupied.

Enter the location where the peg is moving to (RC, -1 to quit): 33

Illegal move, can only jump over one peg, re-enter move.

Enter the location of the peg to move (RC, -1 to quit): 22
Enter the location where the peg is moving to (RC, -1 to quit): 33

Illegal move, can only jump over one peg, re-enter move.

Enter the location of the peg to move (RC, -1 to quit): 13
Enter the location where the peg is moving to (RC, -1 to quit): 33

    0  1  2  3  4  5  6
        +---------+
0       | X  X  X |
1 +-----+ X     X +-----+
2 | X  X  X     X  X  X |
3 | X  X  X  X  X  X  X |
4 | X  X  X  X  X  X  X |
5 +-----+ X  X  X +-----+
6       | X  X  X |
        +---------+

Enter the location of the peg to move (RC, -1 to quit): 33
Enter the location where the peg is moving to (RC, -1 to quit): 13

Illegal move, no peg being jumped over, re-enter move.

Enter the location of the peg to move (RC, -1 to quit): 43
Enter the location where the peg is moving to (RC, -1 to quit): 23

    0  1  2  3  4  5  6
        +---------+
0       | X  X  X |
1 +-----+ X     X +-----+
2 | X  X  X  X  X  X  X |
3 | X  X  X     X  X  X |
4 | X  X  X     X  X  X |
5 +-----+ X  X  X +-----+
6       | X  X  X |
        +---------+

Enter the location of the peg to move (RC, -1 to quit): 31
Enter the location where the peg is moving to (RC, -1 to quit): 33

    0  1  2  3  4  5  6
        +---------+
0       | X  X  X |
1 +-----+ X     X +-----+
2 | X  X  X  X  X  X  X |
3 | X        X  X  X  X |
4 | X  X  X     X  X  X |
5 +-----+ X  X  X +-----+
6       | X  X  X |
        +---------+

Enter the location of the peg to move (RC, -1 to quit): 34
Enter the location where the peg is moving to (RC, -1 to quit): 32

    0  1  2  3  4  5  6
        +---------+
0       | X  X  X |
1 +-----+ X     X +-----+
2 | X  X  X  X  X  X  X |
3 | X     X        X  X |
4 | X  X  X     X  X  X |
5 +-----+ X  X  X +-----+
6       | X  X  X |
        +---------+

Enter the location of the peg to move (RC, -1 to quit): 36
Enter the location where the peg is moving to (RC, -1 to quit): 34

    0  1  2  3  4  5  6
        +---------+
0       | X  X  X |
1 +-----+ X     X +-----+
2 | X  X  X  X  X  X  X |
3 | X     X     X       |
4 | X  X  X     X  X  X |
5 +-----+ X  X  X +-----+
6       | X  X  X |
        +---------+

Enter the location of the peg to move (RC, -1 to quit): 63
Enter the location where the peg is moving to (RC, -1 to quit): 43

    0  1  2  3  4  5  6
        +---------+
0       | X  X  X |
1 +-----+ X     X +-----+
2 | X  X  X  X  X  X  X |
3 | X     X     X       |
4 | X  X  X  X  X  X  X |
5 +-----+ X     X +-----+
6       | X     X |
        +---------+

There are no more legal moves.
You left 26 pegs on the board.

Code Snippet

Here’s the function that checks if a coordinate is a valid location on the board (i.e. not off the board, not in the dead-zones in the corners):

#
# Name:        is_valid_coordinate
#
# Description:    Helper method to check if a coord is a valid board location
#
# Arguments:    a0:    the coord to be checked
# Returns:    v0:    zero if coord invalid, otherwise non-zero
#
is_valid_coordinate:
        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)

    # extract row-col format into $s0,$s1 respectively
    addi    $t0, $zero, 10    # t0 = 10
    div    $a0, $t0    # lo = coord/10, hi(rem) = coord % 10
    mflo    $s0        # row: s0 := coord / 10
    mfhi    $s1        # col: s1 := coord % 10

    # assume false
    li    $v0, 0        # set default return to false

    # check for off-board
    slt    $t0, $s0, $zero                # if row < 0
    bne    $t0, $zero, is_valid_coordinate_done    #    return false

    slt    $t0, $s1, $zero                # if col < 0
    bne    $t0, $zero, is_valid_coordinate_done    #    return false

    li    $t1, 7 ### replace w/BOARD_WIDTH    # t1 = BOARD_WIDTH
    slt    $t0, $s0, $t1        # if row >= BOARD_WIDTH
    beq    $t0, $zero, is_valid_coordinate_done    # return false

    slt    $t0, $s1, $t1        # if col >= BOARD_WIDTH
    beq    $t0, $zero, is_valid_coordinate_done    # return false

is_valid_coordinate_checkRowSmall:
    # handle row < DEAD_ZONE_SIZE
    li    $t2, 2 ###    # t2 = DEAD_ZONE_SIZE
    sub    $t3, $t1, $t2        # t3 = BOARD_WIDTH - DEAD_ZONE_SIZE

    slt    $t0, $s0, $t2                # if !(row < DZS)
    beq    $t0, $zero, is_valid_coordinate_checkRowLarge    # skip

    # top-left corner
    # if row < DZS && col < DZS, return false
    slt    $t0, $s1, $t2                # if col < DZS
    bne    $t0, $zero, is_valid_coordinate_done    #    return false

    # top-right corner
    # if row < DZS && col >= BW - DZS, false
    slt    $t0, $s1, $t3                # if col >= BW - DZS
    beq    $t0, $zero, is_valid_coordinate_done    #     return false

is_valid_coordinate_checkRowLarge:
    # handle ROW >= BOARD_WIDTH - DEAD_ZONE_SIZE
    slt    $t0, $s0, $t3                # if !(row >= BW-DZS)
    bne    $t0, $zero, is_valid_coordinate_setTrue    #     skip

    # bottom-left corner
    # if row > BW-DZS && col < DZS, false
    slt    $t0, $s1, $t2                # if col < DZS
    bne    $t0, $zero, is_valid_coordinate_done    #    return false

    # bottom-right corner
    slt    $t0, $s1, $t3                # if col >= BW - DZS
    beq    $t0, $zero, is_valid_coordinate_done    #     return false

is_valid_coordinate_setTrue:
    # peg not in off-board location, must be on board
    li    $v0, 1        # set return to true (non-zero)

is_valid_coordinate_done:
        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

Downloads

peg_puzzle.asm (33.5 KB)