GKMinmaxStrategist — не работает для начального хода (Swift 4)

#swift #gameplay-kit #gkminmaxstrategist

#swift #игровой набор #gkminmaxstrategist

Вопрос:

Я работаю над настольной стратегической игрой для двух игроков с возможностью играть против процессора, и я использую GKMinmaxStrategist, чтобы дать немного мозгов игроку с процессором.Просто для справки, в игре есть две «фракции» (Король, Враг), и всегда начинается та, которая играет в Короля.

Теперь мне удалось внедрить стратегию, и она работает, если я играю королем против процессора и делаю первый ход. Однако, когда я играю за врага, а процессор должен сделать первый ход (играя за короля), это, как ни странно, не работает. Похоже, что после вызова метода bestMove стратега он не вызывает ни один из базовых методов моделирования, таких как isWin, apply, score и т. Д.

Я пытался изменить правила так, чтобы противник всегда начинал, но опять же это не сработало, в то время как он выдавал ходы за противника, когда я играл королем и делал первый ход (как упоминалось выше).

Кроме того, вместо использования стратега я просто выбирал ходы случайным образом (из всех возможных ходов), просто чтобы посмотреть, работает ли пошаговая логика, и это сработало. Для обеих фракций это происходит тогда, когда и как я бы этого ожидал.

Итак, этот первый шаг, независимо от того, для какой фракции он кажется проблемой, и я не могу понять, почему это так. Кто-нибудь сталкивался с подобной проблемой или у кого-нибудь есть какие-нибудь яркие идеи относительно того, почему это может быть так?

Любая помощь будет высоко оценена.

Это расширение игровой модели, включающее стратега, а также GameVC, который управляет игровым процессом.

 extension Board: GKGameModel {
    var activePlayer: GKGameModelPlayer? {
        return currentPlayer
    }

    var players: [GKGameModelPlayer]? {
        return Player.allPlayers
    }

    func copy(with zone: NSZone? = nil) -> Any {
        let copy = Board()
        copy.setGameModel(self)
        return copy
    }

    func setGameModel(_ gameModel: GKGameModel) {
        if let board = gameModel as? Board {
            tokens = board.tokens
        }
    }

    func isWin(for player: GKGameModelPlayer) -> Bool {
        guard let player = player as? Player else {
            return false
        }
        if let winner = isWinner() {
            return player.player == winner
        } else {
            return false
        }
    }

    func gameModelUpdates(for player: GKGameModelPlayer) -> [GKGameModelUpdate]? {
        guard let player = player as? Player else {
            return nil
        }
        if isWin(for: player) {
            return nil
        }
        return allPossibleMoves(faction: player.player)
    }

    func apply(_ gameModelUpdate: GKGameModelUpdate) {
        guard  let move = gameModelUpdate as? Move else {
            return
        }
        performMove(move: move)
        currentPlayer = currentPlayer.opponent
    }

    func score(for player: GKGameModelPlayer) -> Int {
        guard let player = player as? Player else {
            return Score.none.rawValue
        }
        if isWin(for: player) {
            return Score.win.rawValue
        } else {
            return Score.none.rawValue
        }
    }
}```

```class GameViewController: UIViewController, BoardDelegate {

    var scene: GameScene!
    var board: Board!
    var strategist: GKMinmaxStrategist!

    override func loadView() {
        self.view = SKView(frame: UIScreen.main.bounds)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        let skView = view as! SKView
        skView.isMultipleTouchEnabled = false
        skView.isUserInteractionEnabled = false
        scene = GameScene(size: skView.bounds.size)
        scene.scaleMode = .aspectFill
        board = Board()
        board.delegate = self
        scene.board = board
        scene.handleUserMove = handleUserMove
        scene.fillBoardWithSprites()
        strategist = GKMinmaxStrategist()
        strategist.maxLookAheadDepth = 1
        strategist.randomSource = GKARC4RandomSource()
        strategist.gameModel = board
        skView.presentScene(scene)
        initiateMove()
    }

    //Check if user`s turn
    func checkUserTurn() -> Bool {
        return board.userPlayer.player == board.currentPlayer.player
    }

    //Change turn of players between user and CPU
    func changeTurn() {
        board.currentPlayer = board.currentPlayer.opponent
    }

    //Find best move for CPU using GKMinmaxStrategist
    func chooseCpuMove() -> Move? {
        if let move = strategist.bestMove(for: board.currentPlayer) as? Move {
            print("found move")
            return move
        }
        return nil
    }

    //Perform CPU move
    func handleCpuMove(move: Move) {
        scene.animateMove(move: move) {}
        board.performMove(move: move)
        board.moved()
    }

    //Check whose turn it is and either turn on user interaction or start CPU move
    func initiateMove() {
        print("initiating")
        self.view.isUserInteractionEnabled = checkUserTurn()
        if checkUserTurn() {
            //Wait for user to move
        } else {
            print("checking cpuMove")
            if let cpuMove = chooseCpuMove() {
                handleCpuMove(move: cpuMove)
            }
        }
    }

    func handleUserMove(move: Move, bool: Bool) {
        if board.isMoveAllowed(move: move) {
            scene.animateMove(move: move) {}
            board.performMove(move: move)
            board.moved()
        }
    }

    func currentPlayerDidMove(board: Board) {
        changeTurn()
        if board.isWinner() != nil {
            board.endGame()
        } else {
            DispatchQueue.main.asyncAfter(deadline: .now()   2.0) {
                self.initiateMove()
            }
        }
    }

    func gameDidEnd(board: Board) {
        self.view.isUserInteractionEnabled = false
        UserDefaults.standard.set(board.currentPlayer.player.name, forKey: "winner")
        AppDelegate.shared.rootViewController.gameOverScreen()
    }
}```