GKMinmaxStrategist - не работает для начала движения (Swift 4) - PullRequest
0 голосов
/ 15 апреля 2019

Я работаю над стратегической настольной игрой для двух игроков с возможностью играть против процессора, и я использую 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()
    }
}```
...