A prospective employer asked me for a code sample, but unfortunately this is the best project I've done, most of my other programs were very short (~100 lines). Should I send this in/try to refactor it? Or would it be best to send a shorter sample, or quickly write a new project?

```
#!/usr/bin/python

import curses
import letters # Letter scores and distributions
import libsquares # Locations of bonus squares
import random
import re
from optparse import OptionParser

# Command-line options
parser = OptionParser()
parser.add_option("-c", "--challenge", action="store_true", dest="challenge",
                  default=False, help="Enable challenges (disabled by default)")
parser.add_option("-d", "--dictionary", dest="dict", default="twl",
                  help="Choose dictionary (pick \"twl\" or \"sowpods\")")
(options, args) = parser.parse_args()

# Choose your dictionary
if options.dict == "sowpods":
   dictionary = open('sowpods.txt', 'r') # SOWPODS dictionary - International
else:
   dictionary = open('TWL06.txt', 'r')     #TWL dictionary - American

# --------------------------------------------
# Defines a "player" class
class Player:
    def __init__(player, name):
        player.name = name
        player.score = 0
        player.rack = []
        player.index = -1

# Defines a class for a square on the board
class Square:
    def __init__(square, x, y, multiplier):
        square.x = x
        square.y = y
        # Note that the multiplier gets set to 1 when a tile is placed
        # on the board
        square.multiplier = multiplier
        square.letter = ""
        square.age = -1

# Defines a class for a tile that hasn't yet been placed on the board
class Tile:
    def __init__(tile, x, y, letter):
        tile.x = x
        tile.y = y
        tile.letter = letter

# Defines a class for a turn.  A turn object gives you the player, the
# tiles used, the squares used on the board, the score of the move,
# and its validity.
class Turn:
    def __init__(turn, player, lettersUsed, squaresUsed, addedScore, validity):
        turn.player = player # The object "player."
        turn.lettersUsed = lettersUsed
        turn.squaresUsed = squaresUsed
        turn.addedScore = addedScore
        # Validity of a turn can be 0, 1, or 2.  0 means invalid.  1
        # means valid.  2 means if you challenge it, you won't lose
        # your turn, but the word won't be taken off the table either.
        turn.validity = validity

# -------------------------------------------
# Redraws the rack, which should happen every time a letter is placed.
def redrawRack(rack, stdscr):
    for i in range(7):
        stdscr.delch(19, 15 + i)
    for i in range(len(rack)):
        stdscr.addch(19, 15 + i, rack[i])

# Visually shuffle the rack.
def shuffleRack(rack, stdscr):
    random.shuffle(rack)
    redrawRack(rack, stdscr)

# Display score
def displayScore(players, numPlayers, stdscr):
    for i in range(70):
        stdscr.delch(2, 18)
    for i in range(numPlayers):
        stdscr.addstr(2, 18 + 9*i, str(players[i].score))

# Returns "1" if all words are proper Scrabble words, returns 0 if
# they are not.
def verifyWords(words):
    # First, prune word list so that no word appears more than once.
    # This is so the "index" function works correctly.
    prunedList = []
    for word in words:
        if word in prunedList: pass
        else: prunedList.append(word)

    # Each number in the list "check" is 0 or 1, and if it's 0, the
    # corresponding word is invalid, and if it's 1, the corresponding
    # word is valid.  Each word starts "invalid" and becomes valid
    # once it is found in the dictionary.
    check = [0] * len(prunedList)

    dictionary.seek(0) # Go to beginning of file

    for line in dictionary:
        for word in prunedList:
            expression = "^" + word + "\n" + "$"
            object = re.compile(expression)
            if object.match(line) != None:
                check[prunedList.index(word)] = 1

    if check == [1] * len(prunedList): return 1
    else: return 0

# Given a tile and the direction of a word that it's a part of, find
# the coordinates of the first letter of the word.  Also, the last
# letter of the word.  Note that seek only finds coordinates in one
# direction.
def seek(x0, y0, direction, squares):
    if direction == "horiz":
        xLeft = x0
        xRight = x0
        while xLeft > 0 and squares[(xLeft-1, y0)].letter != "":
            xLeft = xLeft - 1
        while xRight < 14 and squares[(xRight+1, y0)].letter != "":
            xRight = xRight + 1
        return (xLeft, xRight)

    elif direction == "vert":
        yUp = y0
        yDown = y0
        while yDown < 14 and squares[(x0, yDown+1)].letter != "":
            yDown = yDown + 1
        while yUp > 0 and squares[(x0, yUp-1)].letter != "":
            yUp = yUp - 1
        return (yUp, yDown)

    else: raise NameError('Unspecified direction')

# Given a board configuration, return the score.  The board
# configuration specifies the age of every tile, and it returns the
# score associated with all tiles of age 0.  (age 0 means it was
# placed on the square on that particular turn).  Also it finds all
# words generated by a bunch of new tiles.
def findAndScore(squares):
    score = 0
    wordList = []

    # First find which tiles are new
    newTiles = []
    for tuple in squares.keys():
        if squares[tuple].age == 0:
            newTiles.append(squares[tuple])

    # Since squares must form a word, we can take two squares and see
    # which coordinate they differ by, and that will give us the
    # direction of the word.  We can count the parallel word, and then
    # count all the perpendicular words.  If there is one square, the
    # direction can be horizontal.

    if len(newTiles) == 1:
        # Check to see what direction it's in, that is, where the old
        # tiles are.  We want to find the start and end of a proposed
        # word both horizontally and vertically, and if the start
        # equals the end, it's not a word.
        horizRange = seek(newTiles[0].x, newTiles[0].y, "horiz", squares)
        vertRange = seek(newTiles[0].x, newTiles[0].y, "vert", squares)
        if horizRange[0] != horizRange[1]:
            direction = "horiz"
        elif vertRange[0] != vertRange[1]:
            direction = "vert"
        else: return 3
    elif len(newTiles) > 1:
        if newTiles[0].x - newTiles[1].x == 0:
            direction = "vert"
        elif newTiles[0].y - newTiles[1].y == 0:
            direction = "horiz"
        else:
            raise NameError('Two squares do not form a line')
    else:
        raise NameError('len(newTiles) < 1')

    # Now we count the parallel word (we can only count this once, we
    # can't count it once for each letter, which is why we have to
    # count it separately).  Make sure to check that tiles form one
    # continuous word.

    # To find the start and end of the word, we use seek:

    wordRange = seek(newTiles[0].x, newTiles[0].y, direction, squares)
    word = ""
    wordScore = 0
    if direction == "horiz":
        # Check that tiles form one continuous word
        for tile in newTiles:
            if tile.x in range(wordRange[0], wordRange[1]+1): pass
            else: return 3
        y = newTiles[0].y

        wordBonus = 1 # Multiply by this at the end - DW, TW
        for x in range(wordRange[0], wordRange[1] + 1):
            # Find the word
            word = word + squares[(x, y)].letter
            # Score the word - count letters first, then once the word
            # is formed, multiply the DW and TW scores in.

            letterBonus = 1 # Accounts for DL, TL bonuses
            letterValue = letters.score[squares[(x, y)].letter]
            if squares[(x, y)].age == 0:
                bonus = squares[(x, y)].multiplier
                if bonus == "DW": wordBonus = 2*wordBonus
                elif bonus == "TW": wordBonus = 3*wordBonus
                elif bonus == "DL": letterBonus = 2*letterBonus
                elif bonus == "TL": letterBonus = 3*letterBonus
                else: pass
            wordScore = wordScore + letterValue*letterBonus
        wordScore = wordScore*wordBonus

    elif direction == "vert":
        # Check that tiles form one continuous word
        for tile in newTiles:
            if tile.y in range(wordRange[0], wordRange[1]+1): pass
            else: return 3
        x = newTiles[0].x

        wordBonus = 1 # Multiply by this at the end - DW, TW
        for y in range(wordRange[0], wordRange[1] + 1):
            # Find the word
            word = word + squares[(x, y)].letter
            # Score the word

            letterBonus = 1
            letterValue = letters.score[squares[(x, y)].letter]
            if squares[(x, y)].age == 0:
                bonus = squares[(x, y)].multiplier
                if bonus == "DW": wordBonus = 2*wordBonus
                elif bonus == "TW": wordBonus = 3*wordBonus
                elif bonus == "DL": letterBonus = 2*letterBonus
                elif bonus == "TL": letterBonus = 3*letterBonus
                else: pass
            wordScore = wordScore + letterValue*letterBonus
        wordScore = wordScore*wordBonus
    else: raise NameError('Wrong direction')
    wordList.append(word) # Add parallel word to list of words
    score = score + wordScore

    # Now count perpendicular words in the exact same way!
    for tile in newTiles:
        word = ""
        wordScore = 0
        if direction == "horiz":
            wordRange = seek(tile.x, tile.y, "vert", squares)
            x = tile.x

            wordBonus = 1
            for y in range(wordRange[0], wordRange[1] + 1):
                # Find the word
                word = word + squares[(x, y)].letter
                # Score the word

                letterBonus = 1
                letterValue = letters.score[squares[(x, y)].letter]
                if squares[(x, y)].age == 0:
                    bonus = squares[(x, y)].multiplier
                    if bonus == "DW": wordBonus = 2*wordBonus
                    elif bonus == "TW": wordBonus = 3*wordBonus
                    elif bonus == "DL": letterBonus = 2*letterBonus
                    elif bonus == "TL": letterBonus = 3*letterBonus
                    else: pass
                wordScore = wordScore + letterValue*letterBonus
            wordScore = wordScore*wordBonus

        elif direction == "vert":
            wordRange = seek(tile.x, tile.y, "horiz", squares)
            y = tile.y

            wordBonus = 1
            for x in range(wordRange[0], wordRange[1] + 1):
                # Find the word
                word = word + squares[(x, y)].letter
                # Score the word

                letterBonus = 1
                letterValue = letters.score[squares[(x, y)].letter]
                if squares[(x, y)].age == 0:
                    bonus = squares[(x, y)].multiplier
                    if bonus == "DW": wordBonus = 2*wordBonus
                    elif bonus == "TW": wordBonus = 3*wordBonus
                    elif bonus == "DL": letterBonus = 2*letterBonus
                    elif bonus == "TL": letterBonus = 3*letterBonus
                    else: pass
                wordScore = wordScore + letterValue*letterBonus
            wordScore = wordScore*wordBonus

        else: raise NameError('Wrong direction')
        if wordRange[0] != wordRange[1]:
            wordList.append(word) # Add perpendicular word to word list
            score = score + wordScore

    # Bingos
    if len(newTiles) == 7:
        score = score + 50

    # Now we have counted all the tiles and found all the words!
    return [wordList, score]

# Removes a turn.
def removeTurn(turn, players, numPlayers, squares, stdscr):
    # Reset score
    turn.player.score = turn.player.score - turn.addedScore
    displayScore(players, numPlayers, stdscr)
    # Reset squares
    for square in turn.squaresUsed:
        square.letter = ""
        if (square.x, square.y) in libsquares.bonuses.keys():
            color = libsquares.colors[square.multiplier]
            stdscr.addch(square.y, square.x, " ", curses.color_pair(color))
        else: stdscr.addch(square.y, square.x, ".", curses.color_pair(1))
    # Reset racks
    for letter in turn.lettersUsed:
        turn.player.rack.append(letter)
    redrawRack(turn.player.rack, stdscr)
    # Subtract from age of tiles
    for tuple in squares.keys():
        if squares[tuple].age > -1:
            squares[tuple].age = squares[tuple].age - 1

# Play the tiles.  Tiles are written as a tile object.
def playTiles(player, tiles, players, numPlayers, squares, stdscr):
    lettersUsed = []
    squaresUsed = []
    # See which letters and squares are being used
    for tile in tiles:
        lettersUsed.append(tile.letter)
        squaresUsed.append(squares[(tile.x, tile.y)])

    # Check that at least one letter has been used
    if len(tiles) < 1: return 3
    # Check that letters are not on top of other letters
    for tile in tiles:
        if squares[(tile.x, tile.y)].letter != "":
            return 3
    # Check that tiles are in a line
    if len(tiles) == 1: direction = "horiz"
    else:
        # If x coordinates are the same
        if tiles[0].x - tiles[1].x == 0:
            direction = "vert"
        # If y coordinates are the same
        elif tiles[0].y - tiles[1].y == 0:
            direction = "horiz"
        else:
            return 3
    if direction == "horiz":
        # Make sure y coordinates are the same
        for tile in tiles:
            if tile.y != tiles[0].y:
                return 3
    elif direction == "vert":
        # Make sure x coordinates are the same
        for tile in tiles:
            if tile.x != tiles[0].x:
                return 3
    else: raise NameError('Wrong direction')

    # Check that tiles form one connected word (done in
    # "findAndScore")

    # Check to see if it's the first move.
    firstMove = 1
    for tuple in squares.keys():
        if squares[tuple].age > -1: firstMove = 0

    # Check that tiles link to at least one old tile, unless it's the
    # first move.
    link = 0
    for tile in tiles:
        if tile.y + 1 <= 14:
            if squares[(tile.x, tile.y+1)].age > -1: link = 1
        if tile.y - 1 >= 0:
            if squares[(tile.x, tile.y-1)].age > -1: link = 1
        if tile.x + 1 <= 14:
            if squares[(tile.x+1, tile.y)].age > -1: link = 1
        if tile.x - 1 >= 0:
            if squares[(tile.x-1, tile.y)].age > -1: link = 1
    if link == 0 and firstMove == 0: return 3

    # If it's the first move, check to see that the tiles go through
    # the center.
    if firstMove == 1:
        goThroughCenter = 0
        for tile in tiles:
            if tile.x == 7 and tile.y == 7: goThroughCenter = 1
        if goThroughCenter == 0: return 3  # Comment to debug

    # Play word (age 0) and age other tiles
    for tuple in squares.keys():
        if squares[tuple].age > -1:
            squares[tuple].age = squares[tuple].age + 1
    for tile in tiles:
        squares[(tile.x, tile.y)].letter = tile.letter
        squares[(tile.x, tile.y)].age = 0

    # Score word
    wordsAndScore = findAndScore(squares)
    wordList = wordsAndScore[0]
    addedScore = wordsAndScore[1]

    player.score = player.score + addedScore

    # Display score
    displayScore(players, numPlayers, stdscr)

    # Create a turn object and check validity
    if verifyWords(wordList) == 1: validity = 1
    elif verifyWords(wordList) == 0: validity = 0
    else: raise NameError('verifyWords returns neither 1 nor 0')
    newturn = Turn(player, lettersUsed, squaresUsed, addedScore, validity)

    # Remove turn if word verification is on and the word is wrong
    if validity == 0 and options.challenge == False:
        removeTurn(newturn, players, numPlayers, squares, stdscr)
        return 4
    else:
        return newturn

# A player takes a turn.  Return a turn object and the "turnCounter"
# (something indicating who is going next).
def oneTurn(previousTurn, player, squares, stdscr, bag, players, numPlayers):
    # Announce whose turn it is
    stdscr.addnstr(17, 3, player.name + "'s turn", 70)

    # Give player a rack
    while len(player.rack) < 7 and len(bag) > 0:
        tile = random.choice(bag)
        player.rack.append(tile)
        bag.remove(tile)

    tiles = [] # Tiles the player will place on the board this turn

    # Display rack
    redrawRack(player.rack, stdscr)

    # Graphics stuff
    while 1:
        c = stdscr.getch()
        coords = stdscr.getyx()
        x = coords[1]; y = coords[0]

        # Arrow keys move the cursor (or hjkl)
        if c == curses.KEY_LEFT or c == 104:
            if x == 0: pass
            else: stdscr.move(y, x-1)
        elif c == curses.KEY_RIGHT or c == 108:
            if x == 79: pass
            else: stdscr.move(y, x+1)
        elif c == curses.KEY_UP or c == 107:
            if y == 0: pass
            else: stdscr.move(y-1, x)
        elif c == curses.KEY_DOWN or c == 106:
            if y == 23: pass
            else: stdscr.move(y+1, x)
        # yubn moves diagonally (nethack-style)
        elif c == 121:
            if x == 0 or y == 0: pass
            else: stdscr.move(y-1, x-1)
        elif c == 117:
            if x == 79 or y == 0: pass
            else: stdscr.move(y-1, x+1)
        elif c == 98:
            if x == 0 or y == 23: pass
            else: stdscr.move(y+1, x-1)
        elif c == 110:
            if x == 79 or y == 23: pass
            else: stdscr.move(y+1, x+1)

        elif c == 8 or c == 127: # Backspace - remove tile from board
            # Ensure that cursor is over a tile, and if so, find the
            # tile
            ourTile = 0
            for tile in tiles:
                if tile.x == x and tile.y == y: ourTile = tile

            if ourTile != 0:
                # Repaint square on board
                if (x, y) in libsquares.bonuses.keys():
                    color = libsquares.colors[squares[(x, y)].multiplier]
                    stdscr.addch(y, x, " ", curses.color_pair(color))
                else: stdscr.addch(y, x, ".", curses.color_pair(1))
                # Remove tile from tile list
                tiles.remove(ourTile)
                # Add tile to rack
                player.rack.append(ourTile.letter)
                redrawRack(player.rack, stdscr)
                stdscr.move(y, x)

        elif c == 32 or c == 115: # Space or "s" - shuffle tiles
            shuffleRack(player.rack, stdscr)
            stdscr.move(y, x)
        # Once a player presses Enter, that's like inputting a command.
        # Deal with commands accordingly.
        elif c == 10: # New line - submit data
            # Submit word
            if x < 15 and y < 15:
                a = playTiles(player, tiles, players, numPlayers, squares, stdscr)
                if a == 3: # User has made an error
                    turnObject = previousTurn
                    turnCounter = player
                    # Remove stuff from the board
                    for tile in tiles:
                        if (tile.x, tile.y) in libsquares.bonuses.keys():
                            color = libsquares.colors[squares[(tile.x, tile.y)].multiplier]
                            stdscr.addch(tile.y, tile.x, " ", \
                            curses.color_pair(color))
                        else: stdscr.addch(tile.y, tile.x, ".", \
                        curses.color_pair(1))
                        player.rack.append(tile.letter)
                    tiles = []
                    redrawRack(player.rack, stdscr)
                elif a == 4: # User has made an invalid word (we need
                # a separate case because if this has happened the rack
                # has already been removed)
                    turnObject = previousTurn
                    turnCounter = player
                    tiles = []
                else:
                    turnObject = a
                    if player.index < numPlayers - 1:
                        turnCounter = players[player.index + 1]
                    elif player.index == numPlayers - 1:
                        turnCounter = players[0]
                    else:
                        raise NameError('Unknown player index')
                break

            elif y == 21: # On the shuffle/recall/pass line
                # Shuffle rack
                if x >= 2 and x <= 8:
                    shuffleRack(player.rack, stdscr)
                    stdscr.move(21, 2)
                # Recall tiles
                elif x >= 11 and x <= 16:
                    for tile in tiles:
                        if (tile.x, tile.y) in libsquares.bonuses.keys():
                            color = libsquares.colors[squares[(tile.x, \
                            tile.y)].multiplier]
                            stdscr.addch(tile.y, tile.x, " ", \
                            curses.color_pair(color))
                        else: stdscr.addch(tile.y, tile.x, ".", \
                        curses.color_pair(1))
                        player.rack.append(tile.letter)
                    tiles = []
                    redrawRack(player.rack, stdscr)
                    stdscr.move(21, 11)
                # Exchange tiles
                elif x >= 19 and x <= 31:
                    if len(bag) >= 7:
                        # Skip your turn
                        if player.index == numPlayers - 1:
                            turnCounter = players[0]
                        else: turnCounter = players[player.index + 1]
                        turnObject = Turn(player, [], [], 0, 2)
                        stdscr.addstr(21, 34, "Exchange tiles:")
                        stdscr.addstr(22, 34, "(press Enter when done or Esc to cancel)")
                        exchange = []
                        while 1:
                            c = stdscr.getch()
                            if c == 10: # New line - submit exchanged tiles
                                # Now add tiles from the bag
                                while len(player.rack) < 7:
                                    tile = random.choice(bag)
                                    player.rack.append(tile)
                                    bag.remove(tile)
                                for tile in exchange:
                                    bag.append(tile)
                                # Now erase the exchange messages from
                                # the screen
                                for i in range(45):
                                    stdscr.addch(21, 34 + i, " ")
                                    stdscr.addch(22, 34 + i, " ")
                                break

                            elif c == 8 or c == 127: # Backspace - delete a tile
                                if len(exchange) > 0:
                                    stdscr.delch(21, 50 + len(exchange) - 1)
                                    tile = exchange.pop()
                                    player.rack.append(tile)
                            elif c == 27: # Esc (Escape) - don't exchange
                                turnCounter = player
                                turnObject = previousTurn
                                for tile in exchange:
                                    player.rack.append(tile)
                                exchange = []
                                for i in range(45):
                                    stdscr.addch(21, 34 + i, " ")
                                    stdscr.addch(22, 34 + i, " ")
                                break
                            else:
                                if player.rack.count(chr(c)) > 0:
                                    stdscr.addch(21, 50 + len(exchange), chr(c))
                                    exchange.append(chr(c))
                                    player.rack.remove(chr(c))
                            redrawRack(player.rack, stdscr)
                        break
                    else:
                        stdscr.addstr(21, 34, "Less than 7 tiles left in bag")
                    stdscr.move(21, 19)

            # Undo the last turn (so that it is once again the
            # previous player's turn)
            elif y == 5 and x >= 20 and x <= 23:
                removeTurn(previousTurn, players, numPlayers, squares, stdscr)
                turnCounter = previousTurn.player
                turnObject = Turn(previousTurn.player, [], [], 0, 2)
                stdscr.move(5, 20)
                break

            # Challenge the last turn
            elif y == 7 and x >= 20 and x <= 28:
                if previousTurn.validity == 0:
                # Player uses his turn to invalidate the other's move,
                # then takes another turn
                    removeTurn(previousTurn, players, numPlayers, squares, stdscr)
                    turnCounter = player
                    turnObject = Turn(player, [], [], 0, 2)
                elif previousTurn.validity == 1:
                    # Player doesn't get a turn if the challenged word
                    # is valid
                    if player.index == numPlayers - 1:
                        turnCounter = players[0]
                    else: turnCounter = players[player.index + 1]
                    turnObject = Turn(player, [], [], 0, 2)
                elif previousTurn.validity == 2:
                # Then just go on as usual, nobody loses his turn.
                    turnCounter = player
                    turnObject = Turn(player, [], [], 0, 2)
                else: raise NameError('Validity not 0, 1, or 2')
                stdscr.move(7, 20)
                break

            # Quit the game
            elif y == 9 and x >= 20 and x <= 23:
                turnObject = previousTurn
                turnCounter = 0
                stdscr.move(9, 20)
                break
        elif c == 113 and (x >= 15 or y >= 15): # the letter "q"
            turnObject = previousTurn
            turnCounter = 0
            stdscr.move(9, 20)
            break

        else: # If on the board, assume he is adding tiles
            if x < 15 and y < 15:
                # Make sure tile is in rack and you are adding to a
                # blank space

```