In the method pseudocode for player_can_always_force_win, the player has full control over which piece will appear next (i.e. the pseudocode in its current form should be called player_can_possibly_win). I think it should read:
BOOLEAN player_can_always_force_win(well w) {
for each piece p {
BOOLEAN player_will_win = FALSE
for each landing state of piece p in well w {
well w2 = result
if(
that_makes_a_line(w2)
or player_can_always_force_win(w2)
) {
player_will_win = TRUE
}
}
if (!player_will_win) {
// If the AI selects this piece, the AI wins
return FALSE
}
}
// There is no piece the AI can select that will cause the player to lose
return TRUE
}
who_wins(well W) {
for each piece P {
for each landing state of piece P in well W {
well W2 = result
if(that_makes_a_line(W2)) {
next piece
}
if(who_wins(W2) == PLAYERWINS) {
next piece
}
}
// AI wins every landing state
return AIWINS
}
// Player wins every piece
return PLAYERWINS
}
print who_wins(empty_well)