You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
3.8 KiB
130 lines
3.8 KiB
import Foundation
|
|
import Connect4Core
|
|
import Connect4Players
|
|
import Connect4Rules
|
|
import Connect4Persistance
|
|
|
|
class IngameVM: ObservableObject {
|
|
let gameName: String
|
|
|
|
let game: Game
|
|
|
|
// @Published
|
|
var rulesName: String { game.rules.name }
|
|
|
|
var columns: Int { game.rules.nbColumns }
|
|
/// alias for columns
|
|
var width: Int { self.columns }
|
|
var rows: Int { game.rules.nbRows }
|
|
/// alias for rows
|
|
var height: Int { self.rows }
|
|
|
|
var player1: PlayerVM
|
|
var player2: PlayerVM
|
|
|
|
@Published
|
|
var currentPlayer: Owner = .noOne
|
|
|
|
@Published
|
|
var currentBoard: Board
|
|
|
|
@Published
|
|
var paused: Bool = false {
|
|
didSet {
|
|
Task.detached(priority: .userInitiated) {
|
|
if (self.paused) {
|
|
// TODO
|
|
} else {
|
|
// TODO
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private var running: Bool = false
|
|
|
|
init?(settings: NewGameVM, player1: PlayerSettingsVM, player2: PlayerSettingsVM) {
|
|
let fmt = DateFormatter()
|
|
fmt.locale = Locale(identifier: "EN") // No "root" locale?
|
|
self.gameName = fmt.string(from: Date.now)
|
|
|
|
let rulesInit: (Int, Int, Int) -> (any Rules)? = switch (settings.rulesType) {
|
|
case .Classic: Connect4Rules.init
|
|
case .TicTacToe: TicTacToeRules.init
|
|
case .PopOut: PopOutRules.init
|
|
}
|
|
guard let rules = rulesInit(
|
|
Int(settings.height),
|
|
Int(settings.width),
|
|
Int(settings.alignedTokens)
|
|
) else { return nil }
|
|
|
|
guard let player1 = Self.playerOf(settings: player1, id: .player1) else { return nil }
|
|
guard let player2 = Self.playerOf(settings: player2, id: .player2) else { return nil }
|
|
|
|
self.game = try! Game(withRules: rules, andPlayer1: player1, andPlayer2: player2)
|
|
|
|
self.player1 = PlayerVM(inner: player1)
|
|
self.player2 = PlayerVM(inner: player2)
|
|
|
|
self.currentBoard = self.game.board
|
|
|
|
game.addGameOverListener { board, result, player in
|
|
print("game over")
|
|
DispatchQueue.main.async {
|
|
self.currentPlayer = .noOne
|
|
}
|
|
// TODO
|
|
}
|
|
game.addGameChangedListener { game, result in
|
|
print("game changed")
|
|
// TODO
|
|
}
|
|
game.addGameStartedListener { board in
|
|
print("game started")
|
|
// TODO
|
|
}
|
|
game.addBoardChangedListener { board, lastCell in
|
|
DispatchQueue.main.async {
|
|
self.currentBoard = board
|
|
}
|
|
}
|
|
game.addPlayerNotifiedListener { board, player in
|
|
DispatchQueue.main.async {
|
|
self.currentPlayer = player.id
|
|
}
|
|
}
|
|
}
|
|
|
|
public func start() {
|
|
if running { return }
|
|
running = true
|
|
Task.detached(priority: .userInitiated) {
|
|
try await self.game.start()
|
|
}
|
|
}
|
|
|
|
public func pieceDropped(at: (row: Int, column: Int)) {
|
|
Task.detached(priority: .userInitiated) {
|
|
try await self.game.onPlayed(move: Move(
|
|
of: self.currentPlayer,
|
|
toRow: at.row,
|
|
toColumn: at.column
|
|
))
|
|
}
|
|
}
|
|
|
|
private static func playerOf(settings: PlayerSettingsVM, id: Owner) -> Player? {
|
|
return switch (settings.type) {
|
|
case .Human:
|
|
HumanPlayer(withName: settings.name, andId: id)
|
|
case .AIRandom:
|
|
RandomPlayer(withName: settings.name, andId: id)
|
|
case .AIFinnishHim:
|
|
FinnishHimPlayer(withName: settings.name, andId: id)
|
|
case .AISimpleNegaMax:
|
|
SimpleNegaMaxPlayer(withName: settings.name, andId: id)
|
|
}
|
|
}
|
|
}
|