Here’s my minimax function:
def minimax(theclass, is_maximizing, depth, alpha, beta):
theclass.connected_four()
h = compute_hash(theclass.mask, theclass.position)
if h in transposition_dictionary:
if transposition_dictionary[h][0] >= beta:
return [transposition_dictionary[h][0], transposition_dictionary[h][1]]
if transposition_dictionary[h][0] <= alpha:
return [transposition_dictionary[h][0], transposition_dictionary[h][1]]
if alpha < transposition_dictionary[h][0] and transposition_dictionary[h][0] < beta:
return [transposition_dictionary[h][0], transposition_dictionary[h][1]]
alpha = max(alpha, transposition_dictionary[h][0])
beta = min(beta, transposition_dictionary[h][0])
if theclass.gameover == True:
if theclass.xwin == 1:
return [(10000000 * 7 * 6) / theclass.turn, ""]
elif theclass.owin == 1:
return [(10000000 * 7 * 6) / theclass.turn, ""]
elif theclass.draw == True:
return [0, ""]
elif depth == 0:
return [0, ""]
if is_maximizing == True:
a = float("Inf")
best_value = float("Inf")
moves = theclass.available_moves()
centredmoves = []
if 4 in moves:
centredmoves.append(4)
if 3 in moves:
centredmoves.append(3)
if 6 in moves:
centredmoves.append(6)
if 2 in moves:
centredmoves.append(2)
if 5 in moves:
centredmoves.append(5)
if 1 in moves:
centredmoves.append(1)
if 7 in moves:
centredmoves.append(7)
best_move = centredmoves[0]
for move in centredmoves:
copied = copy.deepcopy(theclass)
copied.make_move(move1)
hypothetical_value = minimax(copied, False, depth  1, a, beta)[0]
if hypothetical_value > best_value:
best_value = hypothetical_value
best_move = move
alpha = max(alpha, best_value)
if alpha >= beta:
break
transposition_dictionary[h] = [best_value, best_move]
return [best_value, best_move]
elif is_maximizing == False:
best_value = float("Inf")
b = float("Inf")
moves = theclass.available_moves()
centredmoves = []
if 4 in moves:
centredmoves.append(4)
if 3 in moves:
centredmoves.append(3)
if 6 in moves:
centredmoves.append(6)
if 2 in moves:
centredmoves.append(2)
if 5 in moves:
centredmoves.append(5)
if 1 in moves:
centredmoves.append(1)
if 7 in moves:
centredmoves.append(7)
best_move = centredmoves[0]
for move in centredmoves:
copied = copy.deepcopy(theclass)
copied.make_move(move1)
hypothetical_value = minimax(copied, True, depth 1, alpha, b)[0]
if hypothetical_value < best_value:
best_value = hypothetical_value
best_move = move
beta = min(beta, best_move)
if alpha >= beta:
break
transposition_dictionary[h] = [best_value, best_move]
return [best_value, best_move]
I based this function off various pseudocode I found through google. But there are some things I do not understand.

Why does my transposition_dictionary have to store the best move? It seems to me the only value I am using from this dictionary is best_value. Storing the best move as well seems pointless as it is never selected/used.

Have I dealt with the merger between alphabeta pruning and the transposition table okay? I frankly do not understand parts of the code. For example, look at this bit at the function’s start:
if transposition_dictionary[h][0] >= beta:
return [transposition_dictionary[h][0], transposition_dictionary[h][1]]
if transposition_dictionary[h][0] <= alpha:
return [transposition_dictionary[h][0], transposition_dictionary[h][1]]
if alpha < transposition_dictionary[h][0] and transposition_dictionary[h][0] < beta:
return [transposition_dictionary[h][0], transposition_dictionary[h][1]]
This doesn’t make sense to me. Why can’t I just see if the key is in the dictionary, and if it is, return the key’s associated value at index 0? Because as it stands, all this code is doing is checking which if statement to go down if the key happens to be in the table. It doesn’t do anything else, as all the return statements are the same. And I mean, an if statement will be picked every time as the value will be either greater than or equal to beta, less than or equal to alpha, or greater than alpha but less than beta.
 Why am I changing the values of alpha and beta? I mean, these line of code will never get reached due to reason 2 above as an if statement will always happen and therefore a return statement will always occur before these lines of code get a chance to run (as they at the same indentation level):
alpha = max(alpha, transposition_dictionary[h][0])
beta = min(beta, transposition_dictionary[h][0])
So these lines are totally useless as they can’t ever be ran  but still, why are they here and what are they meant to do? Got it from pseudocode online so they must do something and something must be wrong in my translation.
 Look at the is_maximizing == True chunk of the function. Why do I need to get alpha’s “original value” in this line:
a = float("Inf")
And then why in this line:
hypothetical_value = minimax(copied, False, depth  1, a, beta)[0]
Do I use the original alpha value, but presumably not the original beta value? (Same question goes for the is_maximizing == false chunk of the function.)
Thanks in advance