code: def getTransitionProbabilities(state, action):
      
      #assert isValid(state)
      assert 0 <= action < ACTIONS
      if not isLegal(state, action):
          # If the action is illegal, then transition back to the same state but
          # incur a high negative reward
          s1 = [convertTupleToIndex(state)]
          return(s1, [1], -10)
      # Update the state with the action
      state = list(state)
      state[action] = PLAYER
      if isWon(state, PLAYER):
          # If the player's action is a winning move then transition to the
          # winning state and receive a reward of 1.
          s1 = [convertTupleToIndex(state)]
          return(s1, [1], 1)
      elif isDraw(state):
          s1 = [convertTupleToIndex(state)]
          return(s1, [1], 0)
      # Now we search through the opponents moves, and calculate transition
      # probabilities based on maximising the opponents chance of winning..
      s1 = []
      p = []
      legal_a = getLegalActions(state)
      for a in legal_a:
          state[a] = OPPONENT
          # If the opponent is going to win, we assume that the winning move will
          # be chosen:
          if isWon(state, OPPONENT):
              s1 = [convertTupleToIndex(state)]
              return(s1, [1], -1)
          elif isDraw(state):
              s1 = [convertTupleToIndex(state)]
              return(s1, [1], 0)
          # Otherwise we assume the opponent will select a move with uniform
          # probability across potential moves:
          s1.append(convertTupleToIndex(state))
          p.append(1.0 / len(legal_a))
          state[a] = 0
      # During non-terminal play states the reward is 0.
      return(s1, p, 0)
docs: Parameters
      ----------
      state : tuple
          The state
      action : int
          The action
      
      Returns
      -------
      s1, p, r : tuple of two lists and an int
          s1 are the next states, p are the probabilities, and r is the reward