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

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)
}
}
}