title: Error in unbeatable tic tac toe game
body: <p>I'm trying to follow a book I purchased Python Programming for the absolute beginner 3rd edition. Chapter 6 Challenge 4, asks to make the game tic-tac-toe unbeatable. By amending the computer_move() function. I've amended it to make the game unbeatable (when the human player takes the opposite corners in the first two moves was the hole in the strategy). But I've now broken the part where the computer goes first. And I have no idea why.</p>
  
  <p>I get the error
  <code>TypeError: list indices must be integers, not NoneType</code></p>
  
  <pre><code># Tic-Tac-Toe
  # Plays the game of tic-tac-toe against a human opponent
  
  # global constants
  X = "X"
  O = "O"
  EMPTY = " "
  TIE = "TIE"
  NUM_SQUARES = 9
  
  
  def display_instruct():
      """Display game instructions."""  
      print(
      """
      Welcome to the greatest intellectual challenge of all time: Tic-Tac-Toe.  
      This will be a showdown between your human brain and my silicon processor.  
  
      You will make your move known by entering a number, 0 - 8.  The number 
      will correspond to the board position as illustrated:
  
                      0 | 1 | 2
                      ---------
                      3 | 4 | 5
                      ---------
                      6 | 7 | 8
  
      Prepare yourself, human.  The ultimate battle is about to begin. \n
      """
      )
  
  def ask_yes_no(question):
      """Ask a yes or no question."""
      response = None
      while response not in ("y", "n"):
          response = input(question).lower()
      return response
  
  def ask_number(question, low, high):
      """Ask for a number within a range."""
      response = None
      while response not in range(low, high):
          response = int(input(question))
      return response
  
  def pieces():
      """Determine if player or computer goes first."""
      go_first = ask_yes_no("Do you require the first move? (y/n): ")
      if go_first == "y":
          print("\nThen take the first move.  You will need it.")
          human = X
          computer = O
      else:
          print("\nYour bravery will be your undoing... I will go first.")
          computer = X
          human = O
      return computer, human
  
  def new_board():
      """Create new game board."""
      board = []
      for square in range(NUM_SQUARES):
          board.append(EMPTY)
      return board
  
  def display_board(board):
      """Display game board on screen."""
      print("\n\t", board[0], "|", board[1], "|", board[2])
      print("\t", "---------")
      print("\t", board[3], "|", board[4], "|", board[5])
      print("\t", "---------")
      print("\t", board[6], "|", board[7], "|", board[8], "\n")
  
  def legal_moves(board):
      """Create list of legal moves."""
      moves = []
      for square in range(NUM_SQUARES):
          if board[square] == EMPTY:
              moves.append(square)
      return moves
  
  def winner(board):
      """Determine the game winner."""
      WAYS_TO_WIN = ((0, 1, 2),
                     (3, 4, 5),
                     (6, 7, 8),
                     (0, 3, 6),
                     (1, 4, 7),
                     (2, 5, 8),
                     (0, 4, 8),
                     (2, 4, 6))
  
      for row in WAYS_TO_WIN:
          if board[row[0]] == board[row[1]] == board[row[2]] != EMPTY:
              winner = board[row[0]]
              return winner
  
      if EMPTY not in board:
          return TIE
  
      return None
  
  def human_move(board, human):
      """Get human move."""  
      legal = legal_moves(board)
      move = None
      while move not in legal:
          move = ask_number("Where will you move? (0 - 8):", 0, NUM_SQUARES)
          if move not in legal:
              print("\nThat square is already occupied, foolish human.  Choose    another.\n")
      print("Fine...")
      return move
  
  def computer_move(board, computer, human):
      """Make computer move."""
      # make a copy to work with since function will be changing list
      board = board[:]
      # the best positions to have, in order
      BEST_MOVES = (4, 0, 2, 6, 8, 1, 3, 5, 7)
      #INCLUDED FOR CHALLENGE 4 CHAPTER 6 TO MAKE THE GAME UNBEATABLE
      SMART_HUMAN = ((2, 0), (6, 8))
      print("I shall take square number", end=" ")
  
      # if computer can win, take that move
      for move in legal_moves(board):
          board[move] = computer
          if winner(board) == computer:
              print(move)
              return move
          # done checking this move, undo it
          board[move] = EMPTY
  
      # if human can win, block that move
      for move in legal_moves(board):
          board[move] = human
          if winner(board) == human:
              print(move)
              return move
          # done checkin this move, undo it
          board[move] = EMPTY
  
      # since no one can win on next move, pick best open square
      for move in BEST_MOVES:
          if move in legal_moves(board):
              print(move)
              return move
      #EXTENDED FOR CHALLENGE 4 CHAPTER 6 TO MAKE THE GAME UNBEATABLE
          elif move not in legal_moves(board):
              for position in SMART_HUMAN:
                  for move in position:
                      board[move] = computer
                      if move in legal_moves(board):
                          print (move)
                          return move
  
  
  
  def next_turn(turn):
      """Switch turns."""
      if turn == X:
          return O
      else:
          return X
  
  
  def congrat_winner(the_winner, computer, human):
      """Congratulate the winner."""
      if the_winner != TIE:
          print(the_winner, "won!\n")
      else:
          print("It's a tie!\n")
  
      if the_winner == computer:
          print("As I predicted, human, I am triumphant once more.  \n" \
                "Proof that computers are superior to humans in all regards.")
  
      elif the_winner == human:
          print("No, no!  It cannot be!  Somehow you tricked me, human. \n" \
                "But never again!  I, the computer, so swear it!")
  
      elif the_winner == TIE:
          print("You were most lucky, human, and somehow managed to tie me.  \n" \
                "Celebrate today... for this is the best you will ever achieve.")
  
  def main():
      display_instruct()
      computer, human = pieces()
      turn = X
      board = new_board()
      display_board(board)
  
      while not winner(board):
          if turn == human:
              move = human_move(board, human)
              board[move] = human
          else:
              move = computer_move(board, computer, human)
              board[move] = computer
          display_board(board)
          turn = next_turn(turn)
  
      the_winner = winner(board)
      congrat_winner(the_winner, computer, human)
  
  # start the program
  main()
  input("\n\nPress the enter key to quit.")
  </code></pre>
  
  <p>I'm not too sure where it is producing NoneType from, I've been working on it for quite a few days now, and I can't see the error. It's producing the error in the main function, but I haven't amended there and I wasn't supposed to.</p>
  
  <p>I felt like I was really out of my depth with this, I think it's because I used tuples for the <code>SMART_HUMAN</code> I changed amending it to lists, but I get a similar error.</p>
  
  <p>Any help would be really appreciated!</p>
  
  <hr>
  
  <p>Edit: The full error I get is:</p>
  
  <pre><code>I shall take square number Traceback (most recent call last):
  File "\chapter_6_challenge_4_computer_move_amended.py", line 217, in &lt;module&gt;
  main()
  File "\chapter_6_challenge_4_computer_move_amended.py", line 208, in main
  board[move] = computer
  TypeError: list indices must be integers, not NoneType
  </code></pre>