
"""PuzzleModel  models the slide puzzle"""

PUZZLE_SIZE = 4 

# the puzzle, where 0 marks the empty space/cell:
puzzle = [ [15, 14, 13, 12],
           [11, 10,  9,  8],
           [ 7,  6,  5,  4],
           [ 3,  2,  1,  0] ]

# it is convenient to remember which cell is empty:
empty_space = (3, 3)


def printPuzzle() :
    """printPuzzle prints a copy of the puzzle as trace info"""
    for row in puzzle :
        print row


def moveAt(i, j) :
    """moveAt attempts to move the piece at row i, column j.

       returns True, if the piece is moved; returns False, otherwise
    """
    global empty_space
    outcome = False
    # are coordinates valid ?
    if 0 <= i and i < PUZZLE_SIZE and 0 <= j and j < PUZZLE_SIZE :
        # check if the piece is adjacent to the empty space: 
	if (empty_space == (i-1, j))    \
	   or (empty_space == (i+1, j)) \
	   or (empty_space == (i, j-1)) \
	   or (empty_space == (i, j+1)) :
	    # if True, it's ok to move  num  into the empty space:
            puzzle[empty_space[0]][empty_space[1]] = puzzle[i][j]
	    # remember that the former cell holding  num  is now empty:
	    puzzle[i][j] = 0
	    empty_space = (i, j)
            outcome = True
    return outcome


def movePiece(num) :
    """movePiece attempts to move the piece numbered by num, an int

       returns: True, if the piece is found and moved; returns False, else
       NOTE: this function is not used in the solution to Assignment 7.
    """
    # search the puzzle for the piece numbered  num:
    global puzzle
    global empty_space
    piece = ()  # will remember the cell coordinates where  num  rests
    for i in range(PUZZLE_SIZE):
        for j in range(PUZZLE_SIZE) :
	    if num == puzzle[i][j] :
	        piece = (i, j)  # we found  num  at cell i,j
	        break
    # did we find the piece ?
    if piece == () :
        return False
    else :  # we did find it, so let's try to move it:
        return moveAt(piece[0], piece[1])


def getValueAt(row, col) :
    """getValue returns the number of the piece at  row  and col(umn)"""
    if row >= 0 and row < PUZZLE_SIZE and col >= 0 and col < PUZZLE_SIZE :
        return puzzle[row][col]
    else :
        return -1


