Kodeco Forums

GameplayKit Tutorial: Artificial Intelligence

In this tutorial, you'll learn how to implement artificial intelligence (AI) in a SpriteKit game using GameplayKit and Swift.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/834-gameplaykit-tutorial-artificial-intelligence

Thanks for the interesting tutorial. I am surprised though that AI doesn’t obvious moves. Is there a way to see its decision making process?

I’m glad you liked it! The best move is selected by the strategist using the following code from the tutorial:

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

This is a very basic implementation for the AI. As it calculates all possible moves looking for the winning scenario it uses this score method to determine if that single move is optimal.

To further this logic you can determine if the move blocked the opponent from winning, if the move is in the center of the board, or other strategies found on the wikipedia page: Tic-tac-toe - Wikipedia.

So essentially the more complex you make the score(for player: GKGameModelPlayer) method the smarter the AI will be!

Thanks for this tutorial! Any chance of a couple of more hints :slight_smile:

Thanks for the tutorial! Trying to wrap my head around the AI logic. If I wanted to add logic to block the opponent for winning would I just create a new “if” statement that tracks all possible winning combos and plays on one if the opponent already has two played?

The Strategist is not ranking every move

It looks like the strategist is not ranking every possible move. I downloaded the final project, changed the lookahead to 2, and added log statements. I thought the score function would be called 72 times (9 options for player 1 * 8 for player 2) but it was only called 44 times. Can @naturaln0va or anyone else explain what is going on?

I am using OS version 10.12.4 and Xcode 8.3.2

Strategist.swift
Modifications:

  1. change maxLookAheadDepth from 5 to 2 to reduce the number of output messages

  2. change randomSource to nil so the strategist behaves the same each time

    // 1
    private let strategist: GKMinmaxStrategist = {
    let strategist = GKMinmaxStrategist()

     strategist.maxLookAheadDepth = 2    //5
     strategist.randomSource = nil       //GKARC4RandomSource()
     
     return strategist
    

    }()

Board.swift
Modifications:

  1. Add scoreCounter variable to classBoard to count the number of times the score function is called

  2. Add NSLog statements to gameModelUpdates showing the set of moves

  3. Increment scoreCounter every time score is called

  4. Add NSLog statements to score showing the board being scored

    class Board: NSObject {

    var scoreCounter = 0;
    (snip)

    func gameModelUpdates(for player: GKGameModelPlayer) → [GKGameModelUpdate]? {
    // 1
    guard let player = player as? Player else {
    return nil
    }

     NSLog ("gameModelUpdates")
     if isWin(for: player) {
       return nil
     }
     
     var moves = [Move]()
     
     // 2
     for x in 0..<values.count {
       for y in 0..<values[x].count {
         let position = CGPoint(x: x, y: y)
         if canMove(at: position) {
           moves.append(Move(position))
           NSLog ("    Move x= \(x), y=\(y)")
         }
       }
     }
     
     return moves
    

    }

(snip)

  func score(for player: GKGameModelPlayer) -> Int {
    scoreCounter += 1
    guard let player = player as? Player else {
      return Move.Score.none.rawValue
    }
    
    NSLog ("score")
    NSLog ("    scoreCounter = \(scoreCounter)")
    NSLog ("    \(values[0][0]) \(values[0][1]) \(values[0][2]) ")
    NSLog ("    \(values[1][0]) \(values[1][1]) \(values[1][2]) ")
    NSLog ("    \(values[2][0]) \(values[2][1]) \(values[2][2]) ")
    if isWin(for: player) {
      return Move.Score.win.rawValue
    } else {
      return Move.Score.none.rawValue
    }
  }

Log File
In the log file, I thought the score function would be called 72 times (9 options for player 1 * 8 for player 2) but it was only called 44 times.

I noticed that the board is not being updated correctly. The piece name toggles between brain and zombie between score calls but I believe that is not causing the missing calls to the score function.

2017-04-26 08:19:53.249 TicTacToe[1383:92470] gameModelUpdates
2017-04-26 08:19:53.251 TicTacToe[1383:92470]     Move x= 0, y=0
2017-04-26 08:19:53.253 TicTacToe[1383:92470]     Move x= 0, y=1
2017-04-26 08:19:53.254 TicTacToe[1383:92470]     Move x= 0, y=2
2017-04-26 08:19:53.254 TicTacToe[1383:92470]     Move x= 1, y=0
2017-04-26 08:19:53.254 TicTacToe[1383:92470]     Move x= 1, y=1
2017-04-26 08:19:53.254 TicTacToe[1383:92470]     Move x= 1, y=2
2017-04-26 08:19:53.255 TicTacToe[1383:92470]     Move x= 2, y=0
2017-04-26 08:19:53.255 TicTacToe[1383:92470]     Move x= 2, y=1
2017-04-26 08:19:53.256 TicTacToe[1383:92470]     Move x= 2, y=2
2017-04-26 08:19:53.257 TicTacToe[1383:92470] gameModelUpdates
2017-04-26 08:19:53.259 TicTacToe[1383:92470]     Move x= 0, y=1
2017-04-26 08:19:53.259 TicTacToe[1383:92470]     Move x= 0, y=2
2017-04-26 08:19:53.259 TicTacToe[1383:92470]     Move x= 1, y=0
2017-04-26 08:19:53.260 TicTacToe[1383:92470]     Move x= 1, y=1
2017-04-26 08:19:53.261 TicTacToe[1383:92470]     Move x= 1, y=2
2017-04-26 08:19:53.261 TicTacToe[1383:92470]     Move x= 2, y=0
2017-04-26 08:19:53.261 TicTacToe[1383:92470]     Move x= 2, y=1
2017-04-26 08:19:53.261 TicTacToe[1383:92470]     Move x= 2, y=2
2017-04-26 08:19:53.262 TicTacToe[1383:92470] score
2017-04-26 08:19:53.262 TicTacToe[1383:92470]     scoreCounter = 1
2017-04-26 08:19:53.339 TicTacToe[1383:92470]     brain empty empty 
2017-04-26 08:19:53.339 TicTacToe[1383:92470]     zombie empty empty 
2017-04-26 08:19:53.339 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.340 TicTacToe[1383:92470] score
2017-04-26 08:19:53.340 TicTacToe[1383:92470]     scoreCounter = 2
2017-04-26 08:19:53.340 TicTacToe[1383:92470]     brain empty empty 
2017-04-26 08:19:53.340 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.341 TicTacToe[1383:92470]     brain empty empty 
2017-04-26 08:19:53.341 TicTacToe[1383:92470] score
2017-04-26 08:19:53.341 TicTacToe[1383:92470]     scoreCounter = 3
2017-04-26 08:19:53.341 TicTacToe[1383:92470]     brain zombie empty 
2017-04-26 08:19:53.342 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.342 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.342 TicTacToe[1383:92470] score
2017-04-26 08:19:53.343 TicTacToe[1383:92470]     scoreCounter = 4
2017-04-26 08:19:53.343 TicTacToe[1383:92470]     brain empty empty 
2017-04-26 08:19:53.343 TicTacToe[1383:92470]     empty brain empty 
2017-04-26 08:19:53.343 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.344 TicTacToe[1383:92470] score
2017-04-26 08:19:53.344 TicTacToe[1383:92470]     scoreCounter = 5
2017-04-26 08:19:53.344 TicTacToe[1383:92470]     brain empty empty 
2017-04-26 08:19:53.344 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.345 TicTacToe[1383:92470]     empty zombie empty 
2017-04-26 08:19:53.345 TicTacToe[1383:92470] score
2017-04-26 08:19:53.345 TicTacToe[1383:92470]     scoreCounter = 6
2017-04-26 08:19:53.346 TicTacToe[1383:92470]     brain empty brain 
2017-04-26 08:19:53.346 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.346 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.346 TicTacToe[1383:92470] score
2017-04-26 08:19:53.347 TicTacToe[1383:92470]     scoreCounter = 7
2017-04-26 08:19:53.347 TicTacToe[1383:92470]     brain empty empty 
2017-04-26 08:19:53.347 TicTacToe[1383:92470]     empty empty zombie 
2017-04-26 08:19:53.347 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.348 TicTacToe[1383:92470] score
2017-04-26 08:19:53.348 TicTacToe[1383:92470]     scoreCounter = 8
2017-04-26 08:19:53.348 TicTacToe[1383:92470]     brain empty empty 
2017-04-26 08:19:53.348 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.349 TicTacToe[1383:92470]     empty empty brain 
2017-04-26 08:19:53.349 TicTacToe[1383:92470] gameModelUpdates
2017-04-26 08:19:53.349 TicTacToe[1383:92470]     Move x= 0, y=0
2017-04-26 08:19:53.350 TicTacToe[1383:92470]     Move x= 0, y=2
2017-04-26 08:19:53.350 TicTacToe[1383:92470]     Move x= 1, y=0
2017-04-26 08:19:53.350 TicTacToe[1383:92470]     Move x= 1, y=1
2017-04-26 08:19:53.350 TicTacToe[1383:92470]     Move x= 1, y=2
2017-04-26 08:19:53.350 TicTacToe[1383:92470]     Move x= 2, y=0
2017-04-26 08:19:53.350 TicTacToe[1383:92470]     Move x= 2, y=1
2017-04-26 08:19:53.351 TicTacToe[1383:92470]     Move x= 2, y=2
2017-04-26 08:19:53.351 TicTacToe[1383:92470] score
2017-04-26 08:19:53.351 TicTacToe[1383:92470]     scoreCounter = 9
2017-04-26 08:19:53.351 TicTacToe[1383:92470]     zombie empty empty 
2017-04-26 08:19:53.352 TicTacToe[1383:92470]     zombie empty empty 
2017-04-26 08:19:53.352 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.352 TicTacToe[1383:92470] score
2017-04-26 08:19:53.352 TicTacToe[1383:92470]     scoreCounter = 10
2017-04-26 08:19:53.352 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.353 TicTacToe[1383:92470]     zombie empty empty 
2017-04-26 08:19:53.353 TicTacToe[1383:92470]     brain empty empty 
2017-04-26 08:19:53.384 TicTacToe[1383:92470] score
2017-04-26 08:19:53.385 TicTacToe[1383:92470]     scoreCounter = 11
2017-04-26 08:19:53.385 TicTacToe[1383:92470]     empty zombie empty 
2017-04-26 08:19:53.385 TicTacToe[1383:92470]     zombie empty empty 
2017-04-26 08:19:53.386 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.386 TicTacToe[1383:92470] score
2017-04-26 08:19:53.386 TicTacToe[1383:92470]     scoreCounter = 12
2017-04-26 08:19:53.387 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.387 TicTacToe[1383:92470]     zombie brain empty 
2017-04-26 08:19:53.387 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.388 TicTacToe[1383:92470] score
2017-04-26 08:19:53.388 TicTacToe[1383:92470]     scoreCounter = 13
2017-04-26 08:19:53.388 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.388 TicTacToe[1383:92470]     zombie empty empty 
2017-04-26 08:19:53.389 TicTacToe[1383:92470]     empty zombie empty 
2017-04-26 08:19:53.389 TicTacToe[1383:92470] score
2017-04-26 08:19:53.390 TicTacToe[1383:92470]     scoreCounter = 14
2017-04-26 08:19:53.390 TicTacToe[1383:92470]     empty empty brain 
2017-04-26 08:19:53.390 TicTacToe[1383:92470]     zombie empty empty 
2017-04-26 08:19:53.391 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.392 TicTacToe[1383:92470] score
2017-04-26 08:19:53.392 TicTacToe[1383:92470]     scoreCounter = 15
2017-04-26 08:19:53.393 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.393 TicTacToe[1383:92470]     zombie empty zombie 
2017-04-26 08:19:53.394 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.394 TicTacToe[1383:92470] score
2017-04-26 08:19:53.394 TicTacToe[1383:92470]     scoreCounter = 16
2017-04-26 08:19:53.395 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.395 TicTacToe[1383:92470]     zombie empty empty 
2017-04-26 08:19:53.395 TicTacToe[1383:92470]     empty empty brain 
2017-04-26 08:19:53.396 TicTacToe[1383:92470] gameModelUpdates
2017-04-26 08:19:53.396 TicTacToe[1383:92470]     Move x= 0, y=0
2017-04-26 08:19:53.396 TicTacToe[1383:92470]     Move x= 0, y=1
2017-04-26 08:19:53.397 TicTacToe[1383:92470]     Move x= 1, y=0
2017-04-26 08:19:53.397 TicTacToe[1383:92470]     Move x= 1, y=1
2017-04-26 08:19:53.398 TicTacToe[1383:92470]     Move x= 1, y=2
2017-04-26 08:19:53.398 TicTacToe[1383:92470]     Move x= 2, y=0
2017-04-26 08:19:53.398 TicTacToe[1383:92470]     Move x= 2, y=1
2017-04-26 08:19:53.399 TicTacToe[1383:92470]     Move x= 2, y=2
2017-04-26 08:19:53.399 TicTacToe[1383:92470] score
2017-04-26 08:19:53.399 TicTacToe[1383:92470]     scoreCounter = 17
2017-04-26 08:19:53.400 TicTacToe[1383:92470]     zombie empty empty 
2017-04-26 08:19:53.400 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.400 TicTacToe[1383:92470]     brain empty empty 
2017-04-26 08:19:53.401 TicTacToe[1383:92470] gameModelUpdates
2017-04-26 08:19:53.401 TicTacToe[1383:92470]     Move x= 0, y=0
2017-04-26 08:19:53.401 TicTacToe[1383:92470]     Move x= 0, y=1
2017-04-26 08:19:53.402 TicTacToe[1383:92470]     Move x= 0, y=2
2017-04-26 08:19:53.402 TicTacToe[1383:92470]     Move x= 1, y=1
2017-04-26 08:19:53.402 TicTacToe[1383:92470]     Move x= 1, y=2
2017-04-26 08:19:53.403 TicTacToe[1383:92470]     Move x= 2, y=0
2017-04-26 08:19:53.403 TicTacToe[1383:92470]     Move x= 2, y=1
2017-04-26 08:19:53.403 TicTacToe[1383:92470]     Move x= 2, y=2
2017-04-26 08:19:53.404 TicTacToe[1383:92470] score
2017-04-26 08:19:53.404 TicTacToe[1383:92470]     scoreCounter = 18
2017-04-26 08:19:53.404 TicTacToe[1383:92470]     brain zombie empty 
2017-04-26 08:19:53.404 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.405 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.405 TicTacToe[1383:92470] score
2017-04-26 08:19:53.405 TicTacToe[1383:92470]     scoreCounter = 19
2017-04-26 08:19:53.406 TicTacToe[1383:92470]     empty zombie empty 
2017-04-26 08:19:53.406 TicTacToe[1383:92470]     zombie empty empty 
2017-04-26 08:19:53.406 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.407 TicTacToe[1383:92470] score
2017-04-26 08:19:53.407 TicTacToe[1383:92470]     scoreCounter = 20
2017-04-26 08:19:53.407 TicTacToe[1383:92470]     empty zombie empty 
2017-04-26 08:19:53.408 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.408 TicTacToe[1383:92470]     brain empty empty 
2017-04-26 08:19:53.408 TicTacToe[1383:92470] score
2017-04-26 08:19:53.409 TicTacToe[1383:92470]     scoreCounter = 21
2017-04-26 08:19:53.409 TicTacToe[1383:92470]     empty zombie empty 
2017-04-26 08:19:53.409 TicTacToe[1383:92470]     empty zombie empty 
2017-04-26 08:19:53.410 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.410 TicTacToe[1383:92470] score
2017-04-26 08:19:53.410 TicTacToe[1383:92470]     scoreCounter = 22
2017-04-26 08:19:53.411 TicTacToe[1383:92470]     empty zombie empty 
2017-04-26 08:19:53.411 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.411 TicTacToe[1383:92470]     empty brain empty 
2017-04-26 08:19:53.412 TicTacToe[1383:92470] score
2017-04-26 08:19:53.412 TicTacToe[1383:92470]     scoreCounter = 23
2017-04-26 08:19:53.412 TicTacToe[1383:92470]     empty zombie zombie 
2017-04-26 08:19:53.413 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.413 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.413 TicTacToe[1383:92470] score
2017-04-26 08:19:53.414 TicTacToe[1383:92470]     scoreCounter = 24
2017-04-26 08:19:53.414 TicTacToe[1383:92470]     empty zombie empty 
2017-04-26 08:19:53.414 TicTacToe[1383:92470]     empty empty brain 
2017-04-26 08:19:53.415 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.415 TicTacToe[1383:92470] score
2017-04-26 08:19:53.415 TicTacToe[1383:92470]     scoreCounter = 25
2017-04-26 08:19:53.416 TicTacToe[1383:92470]     empty zombie empty 
2017-04-26 08:19:53.416 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.416 TicTacToe[1383:92470]     empty empty zombie 
2017-04-26 08:19:53.417 TicTacToe[1383:92470] gameModelUpdates
2017-04-26 08:19:53.417 TicTacToe[1383:92470]     Move x= 0, y=0
2017-04-26 08:19:53.419 TicTacToe[1383:92470]     Move x= 0, y=1
2017-04-26 08:19:53.420 TicTacToe[1383:92470]     Move x= 0, y=2
2017-04-26 08:19:53.420 TicTacToe[1383:92470]     Move x= 1, y=0
2017-04-26 08:19:53.421 TicTacToe[1383:92470]     Move x= 1, y=2
2017-04-26 08:19:53.421 TicTacToe[1383:92470]     Move x= 2, y=0
2017-04-26 08:19:53.421 TicTacToe[1383:92470]     Move x= 2, y=1
2017-04-26 08:19:53.421 TicTacToe[1383:92470]     Move x= 2, y=2
2017-04-26 08:19:53.422 TicTacToe[1383:92470] score
2017-04-26 08:19:53.422 TicTacToe[1383:92470]     scoreCounter = 26
2017-04-26 08:19:53.423 TicTacToe[1383:92470]     brain empty empty 
2017-04-26 08:19:53.423 TicTacToe[1383:92470]     empty brain empty 
2017-04-26 08:19:53.424 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.424 TicTacToe[1383:92470] gameModelUpdates
2017-04-26 08:19:53.425 TicTacToe[1383:92470]     Move x= 0, y=0
2017-04-26 08:19:53.425 TicTacToe[1383:92470]     Move x= 0, y=1
2017-04-26 08:19:53.426 TicTacToe[1383:92470]     Move x= 0, y=2
2017-04-26 08:19:53.426 TicTacToe[1383:92470]     Move x= 1, y=0
2017-04-26 08:19:53.426 TicTacToe[1383:92470]     Move x= 1, y=1
2017-04-26 08:19:53.427 TicTacToe[1383:92470]     Move x= 2, y=0
2017-04-26 08:19:53.427 TicTacToe[1383:92470]     Move x= 2, y=1
2017-04-26 08:19:53.428 TicTacToe[1383:92470]     Move x= 2, y=2
2017-04-26 08:19:53.428 TicTacToe[1383:92470] score
2017-04-26 08:19:53.428 TicTacToe[1383:92470]     scoreCounter = 27
2017-04-26 08:19:53.429 TicTacToe[1383:92470]     zombie empty empty 
2017-04-26 08:19:53.429 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.429 TicTacToe[1383:92470]     empty zombie empty 
2017-04-26 08:19:53.430 TicTacToe[1383:92470] score
2017-04-26 08:19:53.430 TicTacToe[1383:92470]     scoreCounter = 28
2017-04-26 08:19:53.430 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.431 TicTacToe[1383:92470]     brain empty empty 
2017-04-26 08:19:53.431 TicTacToe[1383:92470]     empty zombie empty 
2017-04-26 08:19:53.431 TicTacToe[1383:92470] score
2017-04-26 08:19:53.432 TicTacToe[1383:92470]     scoreCounter = 29
2017-04-26 08:19:53.432 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.432 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.433 TicTacToe[1383:92470]     zombie zombie empty 
2017-04-26 08:19:53.433 TicTacToe[1383:92470] score
2017-04-26 08:19:53.433 TicTacToe[1383:92470]     scoreCounter = 30
2017-04-26 08:19:53.434 TicTacToe[1383:92470]     empty brain empty 
2017-04-26 08:19:53.434 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.434 TicTacToe[1383:92470]     empty zombie empty 
2017-04-26 08:19:53.435 TicTacToe[1383:92470] score
2017-04-26 08:19:53.435 TicTacToe[1383:92470]     scoreCounter = 31
2017-04-26 08:19:53.435 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.436 TicTacToe[1383:92470]     empty zombie empty 
2017-04-26 08:19:53.436 TicTacToe[1383:92470]     empty zombie empty 
2017-04-26 08:19:53.436 TicTacToe[1383:92470] score
2017-04-26 08:19:53.436 TicTacToe[1383:92470]     scoreCounter = 32
2017-04-26 08:19:53.437 TicTacToe[1383:92470]     empty empty brain 
2017-04-26 08:19:53.437 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.437 TicTacToe[1383:92470]     empty zombie empty 
2017-04-26 08:19:53.437 TicTacToe[1383:92470] score
2017-04-26 08:19:53.437 TicTacToe[1383:92470]     scoreCounter = 33
2017-04-26 08:19:53.438 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.438 TicTacToe[1383:92470]     empty empty zombie 
2017-04-26 08:19:53.438 TicTacToe[1383:92470]     empty zombie empty 
2017-04-26 08:19:53.439 TicTacToe[1383:92470] score
2017-04-26 08:19:53.439 TicTacToe[1383:92470]     scoreCounter = 34
2017-04-26 08:19:53.439 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.439 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.439 TicTacToe[1383:92470]     empty zombie brain 
2017-04-26 08:19:53.440 TicTacToe[1383:92470] gameModelUpdates
2017-04-26 08:19:53.440 TicTacToe[1383:92470]     Move x= 0, y=0
2017-04-26 08:19:53.440 TicTacToe[1383:92470]     Move x= 0, y=1
2017-04-26 08:19:53.440 TicTacToe[1383:92470]     Move x= 0, y=2
2017-04-26 08:19:53.440 TicTacToe[1383:92470]     Move x= 1, y=0
2017-04-26 08:19:53.441 TicTacToe[1383:92470]     Move x= 1, y=1
2017-04-26 08:19:53.441 TicTacToe[1383:92470]     Move x= 1, y=2
2017-04-26 08:19:53.441 TicTacToe[1383:92470]     Move x= 2, y=1
2017-04-26 08:19:53.441 TicTacToe[1383:92470]     Move x= 2, y=2
2017-04-26 08:19:53.441 TicTacToe[1383:92470] score
2017-04-26 08:19:53.442 TicTacToe[1383:92470]     scoreCounter = 35
2017-04-26 08:19:53.442 TicTacToe[1383:92470]     zombie empty brain 
2017-04-26 08:19:53.442 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.442 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.443 TicTacToe[1383:92470] gameModelUpdates
2017-04-26 08:19:53.443 TicTacToe[1383:92470]     Move x= 0, y=0
2017-04-26 08:19:53.443 TicTacToe[1383:92470]     Move x= 0, y=1
2017-04-26 08:19:53.443 TicTacToe[1383:92470]     Move x= 0, y=2
2017-04-26 08:19:53.443 TicTacToe[1383:92470]     Move x= 1, y=0
2017-04-26 08:19:53.444 TicTacToe[1383:92470]     Move x= 1, y=1
2017-04-26 08:19:53.444 TicTacToe[1383:92470]     Move x= 1, y=2
2017-04-26 08:19:53.444 TicTacToe[1383:92470]     Move x= 2, y=0
2017-04-26 08:19:53.444 TicTacToe[1383:92470]     Move x= 2, y=2
2017-04-26 08:19:53.444 TicTacToe[1383:92470] score
2017-04-26 08:19:53.445 TicTacToe[1383:92470]     scoreCounter = 36
2017-04-26 08:19:53.445 TicTacToe[1383:92470]     brain empty empty 
2017-04-26 08:19:53.445 TicTacToe[1383:92470]     empty empty zombie 
2017-04-26 08:19:53.445 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.445 TicTacToe[1383:92470] score
2017-04-26 08:19:53.446 TicTacToe[1383:92470]     scoreCounter = 37
2017-04-26 08:19:53.446 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.446 TicTacToe[1383:92470]     zombie empty zombie 
2017-04-26 08:19:53.446 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.447 TicTacToe[1383:92470] score
2017-04-26 08:19:53.447 TicTacToe[1383:92470]     scoreCounter = 38
2017-04-26 08:19:53.447 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.447 TicTacToe[1383:92470]     empty empty zombie 
2017-04-26 08:19:53.448 TicTacToe[1383:92470]     brain empty empty 
2017-04-26 08:19:53.448 TicTacToe[1383:92470] score
2017-04-26 08:19:53.448 TicTacToe[1383:92470]     scoreCounter = 39
2017-04-26 08:19:53.448 TicTacToe[1383:92470]     empty zombie empty 
2017-04-26 08:19:53.448 TicTacToe[1383:92470]     empty empty zombie 
2017-04-26 08:19:53.449 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.449 TicTacToe[1383:92470] score
2017-04-26 08:19:53.449 TicTacToe[1383:92470]     scoreCounter = 40
2017-04-26 08:19:53.449 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.450 TicTacToe[1383:92470]     empty brain zombie 
2017-04-26 08:19:53.450 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.450 TicTacToe[1383:92470] score
2017-04-26 08:19:53.450 TicTacToe[1383:92470]     scoreCounter = 41
2017-04-26 08:19:53.451 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.451 TicTacToe[1383:92470]     empty empty zombie 
2017-04-26 08:19:53.451 TicTacToe[1383:92470]     empty zombie empty 
2017-04-26 08:19:53.451 TicTacToe[1383:92470] score
2017-04-26 08:19:53.451 TicTacToe[1383:92470]     scoreCounter = 42
2017-04-26 08:19:53.452 TicTacToe[1383:92470]     empty empty brain 
2017-04-26 08:19:53.452 TicTacToe[1383:92470]     empty empty zombie 
2017-04-26 08:19:53.452 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.452 TicTacToe[1383:92470] score
2017-04-26 08:19:53.453 TicTacToe[1383:92470]     scoreCounter = 43
2017-04-26 08:19:53.453 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.453 TicTacToe[1383:92470]     empty empty zombie 
2017-04-26 08:19:53.453 TicTacToe[1383:92470]     empty empty zombie 
2017-04-26 08:19:53.453 TicTacToe[1383:92470] gameModelUpdates
2017-04-26 08:19:53.454 TicTacToe[1383:92470]     Move x= 0, y=0
2017-04-26 08:19:53.454 TicTacToe[1383:92470]     Move x= 0, y=1
2017-04-26 08:19:53.454 TicTacToe[1383:92470]     Move x= 0, y=2
2017-04-26 08:19:53.454 TicTacToe[1383:92470]     Move x= 1, y=0
2017-04-26 08:19:53.454 TicTacToe[1383:92470]     Move x= 1, y=1
2017-04-26 08:19:53.455 TicTacToe[1383:92470]     Move x= 1, y=2
2017-04-26 08:19:53.455 TicTacToe[1383:92470]     Move x= 2, y=0
2017-04-26 08:19:53.455 TicTacToe[1383:92470]     Move x= 2, y=1
2017-04-26 08:19:53.455 TicTacToe[1383:92470] score
2017-04-26 08:19:53.456 TicTacToe[1383:92470]     scoreCounter = 44
2017-04-26 08:19:53.456 TicTacToe[1383:92470]     brain empty empty 
2017-04-26 08:19:53.456 TicTacToe[1383:92470]     empty empty empty 
2017-04-26 08:19:53.457 TicTacToe[1383:92470]     empty empty brain

This was a very basic implementation of the min max strategist. This resulted in the AI not being as intelligent as it could be. Check out this repo for an example of a more intelligent tic-toe model. GameplayKitSandbox/Board.swift at master · tnantoka/GameplayKitSandbox · GitHub. There are also some other GameplayKit related material in this repo that is interesting if you want more.

I thought that if the function gameModelUpdates returned 8 moves appended together that then the function score would be called 8 times, once for each move. My log file shows that sometimes the code works that way, for example scoreCounter 1-8, 9-16 but sometimes it doesn’t, for example scoreCounter 17, 26, 35, 44. Can you explain what is going on?

I’ll check out the other example you mentioned but I’m still very interested in your opinion on the behavior I’m observing in this tutorial…

@naturaln0va I downloaded the GitHub example you reference, hardcoded maxLookaheadDepth to 2, and added log statements. It behaves similarly to your tutorial.

If you modify your tutorial to have a maxLookaheadDepth of 2, are you able to duplicate the behavior I am seeing? Is there some kind of branch elimination occurring? Am I misunderstanding something?

@andy_de_jong Hi, I have same confusion here, the strategist didn’t try every move, and is always making silly decisions, did you found out why ? May I have a discussion with you? my email is wangruihit@gmail.com, thank you.

I found the reason, the strategist combines alpha-beta pruning algorithm to eliminate some branches for better performance, so it will not try every move.

This tutorial is more than six months old so questions are no longer supported at the moment for it. We will update it as soon as possible. Thank you! :]