I have the following code in my main.swift
:
let strategist = GKMinmaxStrategist()
strategist.gameModel = position
strategist.maxLookAheadDepth = 1
strategist.randomSource = nil
let move = strategist.bestMoveForActivePlayer()
...where position
is an instance of my GKGameModel
subclass Position
. After this code is run, move
is nil
. bestMoveForPlayer(position.activePlayer!)
also results in nil
(but position.activePlayer!
results in a Player
object).
However,
let moves = position.gameModelUpdatesForPlayer(position.activePlayer!)!
results in a non-empty array of possible moves. From Apple's documentation (about bestMoveForPlayer(_:)
):
Returns nil if the player is invalid, the player is not a part of the game model, or the player has no valid moves available.
As far as I know, none of this is the case, but the function still returns nil
. What could be going on here?
If it can be of any help, here's my implementation of the GKGameModel
protocol:
var players: [GKGameModelPlayer]? = [Player.whitePlayer, Player.blackPlayer]
var activePlayer: GKGameModelPlayer? {
return playerToMove
}
func setGameModel(gameModel: GKGameModel) {
let position = gameModel as! Position
pieces = position.pieces
ply = position.ply
reloadLegalMoves()
}
func gameModelUpdatesForPlayer(thePlayer: GKGameModelPlayer) -> [GKGameModelUpdate]? {
let player = thePlayer as! Player
let moves = legalMoves(ofPlayer: player)
return moves.count > 0 ? moves : nil
}
func applyGameModelUpdate(gameModelUpdate: GKGameModelUpdate) {
let move = gameModelUpdate as! Move
playMove(move)
}
func unapplyGameModelUpdate(gameModelUpdate: GKGameModelUpdate) {
let move = gameModelUpdate as! Move
undoMove(move)
}
func scoreForPlayer(thePlayer: GKGameModelPlayer) -> Int {
let player = thePlayer as! Player
var score = 0
for (_, piece) in pieces {
score += piece.player == player ? 1 : -1
}
return score
}
func isLossForPlayer(thePlayer: GKGameModelPlayer) -> Bool {
let player = thePlayer as! Player
return legalMoves(ofPlayer: player).count == 0
}
func isWinForPlayer(thePlayer: GKGameModelPlayer) -> Bool {
let player = thePlayer as! Player
return isLossForPlayer(player.opponent)
}
func copyWithZone(zone: NSZone) -> AnyObject {
let copy = Position(withPieces: pieces.map({ $0.1 }), playerToMove: playerToMove)
copy.setGameModel(self)
return copy
}
If there's any other code I should show, let me know.
isWin
method. If your this method return true for your player, the game is over and there is no best move. My implementation was related toisLoss
like "return !isLoss". Now I got it, that it is wrong. I advice anybody who have such issue check isWin. – Gershwin