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/pythonimport cursesimport letters # Letter scores and distributionsimport libsquares # Locations of bonus squaresimport randomimport refrom optparse import OptionParser# Command-line optionsparser = 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 dictionaryif options.dict == sowpods:   dictionary = open('sowpods.txt', 'r') # SOWPODS dictionary - Internationalelse:   dictionary = open('TWL06.txt', 'r')     #TWL dictionary - American# --------------------------------------------# Defines a player classclass Player:    def __init__(player, name):        player.name = name        player.score = 0        player.rack = []        player.index = -1# Defines a class for a square on the boardclass 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 boardclass 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 scoredef 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
Is this code too messy to send to an employer as a code sample?
python;interview questions
I have little experience with python, so I can't offer critique on the finer points of your code, just the big picture. That said, several things stick out to me. First, you have some large chunks which are duplicated two, three, or even four times (see lines 198-215). Scour through the code and extract these into their own functions. Second, several of your functions are massively too long: findAndScore(161 lines), playTiles(97 lines), oneTurn(228 lines). findAndScore, once you get rid of the previously mentioned duplication, could easily be broken into two functions: the finding and the scoring. oneTurn is too long simply because it contains all of the input handling. The section within the block starting at line 435 absolutely should be its own function, if not more since it clocks in at 144 lines.Finally, and this is more observation than critique, your classes do nothing but operate as organized data structures. This isn't necessarily a wrong approach, but it would look good if you were to refactor your code to be a bit more object oriented, especially since this is intended as a code sample.