0

I'm working on a local game which relies on turn order.

Rules;

  • There are a number of phases in the game (ie: Buy, Sell)
  • During each phase, a player takes a single turn
  • Each phase is not considered complete until every player (in turn order) has completed their turn.

I'm not sure how to manage this data. There are a number of things to track.

  1. The phase we are in
  2. The current player on turn
  3. When all players have completed their turns
  4. When the end of the turn order has been reached so we can move to next phase.
  5. Resetting all turn completions when all phases are complete

I'm thinking that a subscription model is the best approach to this, but I'm not used to such a pattern.

Currently I'm using a similar system to a to-do where the phase itself can be marked complete or incomplete.

This is the way I'm currently handling turn orders and phases in Swift playground.

// Turn order management

class TurnOrderManager: NSObject
{
    static var instance = TurnOrderManager()

    var turnOrder: [Player] = [Player]()
    private var turnOrderIndex = 0

    var current: Player {
        return turnOrder[turnOrderIndex]
    }

    func next() {
        if (self.turnOrderIndex < (self.turnOrder.count-1)) {
            turnOrderIndex += 1
        }
        else {
            print("Reached end of line")
        }
    }
}

class Player: NSObject {
    var name: String = ""

    override var description: String {
        return self.name
    }

    init(name: String) {
        super.init()
        self.name = name
    }
}

let p1:Player = Player.init(name: "Bob")
let p2:Player = Player.init(name: "Alex")

TurnOrderManager.instance.turnOrder = [p1,p2]
print (TurnOrderManager.instance.current)

TurnOrderManager.instance.next()
print (TurnOrderManager.instance.current)

TurnOrderManager.instance.next()
print (TurnOrderManager.instance.current)

// ---------------------------------

// Phase management
enum PhaseType: Int {
    case buying = 1
    case selling
}

struct Phase {
    var id: PhaseType
    var title: String
    var completed: Bool = false {
        didSet {
            // Notify subscribers of completion
            guard completed else { return }
            handlers.forEach { $0(self) }
        }
    }

    var description:String {
        return "Phase: \(self.title), completed: \(completed)"
    }

    // Task queue
    var handlers = [(Phase) -> Void]()

    init(id: PhaseType, title: String, initialSubscription: @escaping (Phase) -> Void =
        {_ in})
    {
        self.id = id
        self.title = title
        subscribe(completion: initialSubscription)
    }

    mutating func subscribe(completion: @escaping (Phase) -> Void) {
        handlers.append(completion)
    }
}

class MyParentController {

    lazy var phase1: Phase = {
        return Phase(id: .buying, title: "Phase #1") {
            print("Do something with phase: \($0.title)")
        }
    }()

}

let controller = MyParentController()

controller.phase1.completed = true

Question:

I'm wanting to notify:

  • Turn is complete
  • All turns are complete (so that it can move to next phase)

How do I make my TurnOrderManager alert the PhaseManager that the current turn is complete.

How do I make my PhaseManager know that when all turns are complete to move to the next phase.

I apologize for the verboseness of my query.

Many thanks

zardon
  • 1,601
  • 4
  • 23
  • 46

1 Answers1

1

You're going to want to define a delegate relationship PhaseManager and your TurnOrderManager.

Here is the Apple docs on protocols.

Here is a great article on delegation.

First you'll need to define a protocol. Something like this:

protocol TurnManagerDelegate {
   func complete(turn: objectType)
   func allTurnsComplete()
}

Next you'll have to conform your PhaseManager to the protocol:

class PhaseManager: TurnManagerDelegate {
   ...

   func complete(turn: objectType) {
      // implement 
   }

   func allTurnsComplete() {
      // implement 
   }
   ...
}

Last you'll have to add a property on your TurnOrderManager with the delegate:

class TurnOrderManager {
...
   var delegate: TurnManagerDelegate
...
}

and call the functions whenever needed in your TurnOrderManager:

...
delegate?.allTurnsComplete() //example
...

You'll also have to set your PhaseManager as the delegate before your TurnOrderManager would try to call any of the delegate methods.

Donovan King
  • 855
  • 1
  • 6
  • 18
  • This makes more sense. I appreciate your help. I was thinking I could use a subscription model; but I don't really understand how it works in real terms -- but the delegate / protocol method seems to make sense to me so I will certainly try it out in a new playground file and start from scratch – zardon May 08 '17 at 20:21
  • No problem! NSNotifications (subscription model) really should only be used when you need to communicate to a lot of objects or you need to sign up for system notifications (such as keyboard notifications) – Donovan King May 08 '17 at 22:20