Skip to content

Commit

Permalink
Create PlayersState
Browse files Browse the repository at this point in the history
  • Loading branch information
stephtelolahy committed Jun 28, 2024
1 parent 392d67d commit d12b43a
Show file tree
Hide file tree
Showing 13 changed files with 134 additions and 172 deletions.
108 changes: 108 additions & 0 deletions WildWestOnline/Core/Game/Sources/PlayersState/PlayersState.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
//
// PlayersState.swift
//
//
// Created by Hugues Stephano TELOLAHY on 24/06/2024.
//
// swiftlint:disable type_contents_order

import Foundation
import Redux

public struct PlayersState: Equatable, Codable {
public var players: [String: Player]

public struct Player: Equatable, Codable {
public let maxHealth: Int
public var health: Int
}
}

public extension PlayersState {
static let reducer: ThrowingReducer<Self> = { state, action in
switch action {
case let GameAction.heal(amount, id):
try state.heal(amount: amount, id: id)

case let GameAction.damage(amount, id):
state.damage(amount: amount, id: id)

default:
state
}
}
}

private extension PlayersState {
func heal(amount: Int, id: String) throws -> Self {
var playerObj = players.get(id)

guard playerObj.health < playerObj.maxHealth else {
throw GameError.playerAlreadyMaxHealth(id)
}

playerObj.health = min(playerObj.health + amount, playerObj.maxHealth)

var state = self
state.players[id] = playerObj
return state
}

func damage(amount: Int, id: String) -> Self {
var playerObj = players.get(id)
playerObj.health -= amount

var state = self
state.players[id] = playerObj
return state
}
}

public extension PlayersState {
class Builder {
private var players: [String: PlayersState.Player] = [:]

public func build() -> PlayersState {
.init(players: players)
}

public func withPlayer(_ id: String, builderFunc: (PlayersState.Player.Builder) -> PlayersState.Player.Builder = { $0 }) -> Self {
let builder = PlayersState.Player.makeBuilder()
let player = builderFunc(builder).build()
players[id] = player
return self
}
}

static func makeBuilder() -> Builder {
Builder()
}
}

public extension PlayersState.Player {
class Builder {
private var maxHealth: Int = 0
private var health: Int = 0

public func build() -> PlayersState.Player {
.init(
maxHealth: maxHealth,
health: health
)
}

public func withHealth(_ value: Int) -> Self {
health = value
return self
}

public func withMaxHealth(_ value: Int) -> Self {
maxHealth = value
return self
}
}

static func makeBuilder() -> Builder {
Builder()
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ protocol GameActionReducer {

extension GameAction {
func reduce(state: GameState) throws -> GameState {
try reducer().reduce(state: state)
var newState = try reducer().reduce(state: state)
newState.playersState = try PlayersState.reducer(state.playersState, self)
return newState
}
}

Expand All @@ -28,11 +30,11 @@ private extension GameAction {
case let .handicap(card, target, player):
ActionHandicap(player: player, card: card, target: target)

case let .heal(amount, player):
ActionHeal(player: player, amount: amount)
case .heal:
ActionIdentity()

case let .damage(amount, player):
ActionDamage(player: player, amount: amount)
case .damage:
ActionIdentity()

case let .discardHand(card, player),
let .discardPlayed(card, player):
Expand Down Expand Up @@ -112,3 +114,9 @@ private extension GameAction {
}
}
}

private struct ActionIdentity: GameActionReducer {
func reduce(state: GameState) throws -> GameState {
state
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,6 @@
//

extension Player {
var isDamaged: Bool {
health < maxHealth
}

var handLimitAtEndOfTurn: Int {
attributes[.handLimit] ?? health
}

mutating func gainHealth(_ value: Int) throws {
guard health < maxHealth else {
throw GameError.playerAlreadyMaxHealth(id)
}

let newHealth = min(health + value, maxHealth)
health = newHealth
}

mutating func looseHealth(_ value: Int) {
health -= value
}

mutating func setValue(_ value: Int?, forAttribute key: String) {
attributes[key] = value
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

public extension GameState {
class Builder {
private var playersStateBuilder: PlayersState.Builder = .init()
private var players: [String: Player] = [:]
private var playOrder: [String] = []
private var turn: String?
Expand All @@ -25,6 +26,7 @@ public extension GameState {

public func build() -> GameState {
.init(
playersState: playersStateBuilder.build(),
players: players,
playOrder: playOrder,
startOrder: playOrder,
Expand All @@ -44,6 +46,11 @@ public extension GameState {
)
}

public func withPlayersState(_ builderFunc: (PlayersState.Builder) -> PlayersState.Builder) -> Self {
_ = builderFunc(playersStateBuilder)
return self
}

public func withTurn(_ value: String) -> Self {
turn = value
return self
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ public extension Player {
private var figure: String = ""
private var abilities: Set<String> = []
private var attributes: [String: Int] = [:]
private var health: Int = 0
private var hand: [String] = []
private var inPlay: [String] = []

Expand All @@ -23,7 +22,6 @@ public extension Player {
figure: figure,
abilities: abilities,
attributes: attributes,
health: health,
hand: hand,
inPlay: inPlay
)
Expand All @@ -39,11 +37,6 @@ public extension Player {
return self
}

public func withHealth(_ value: Int) -> Self {
health = value
return self
}

public func withAttributes(_ value: [String: Int]) -> Self {
attributes = value
return self
Expand Down
3 changes: 3 additions & 0 deletions WildWestOnline/Core/Game/Sources/State/GameState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import Foundation
/// Game is turn based, cards have actions, cards have properties and cards have rules
/// These state objects are passed around everywhere and maintained on both client and server seamlessly
public struct GameState: Codable, Equatable {
/// Players
public var playersState: PlayersState

/// All players
public var players: [String: Player]

Expand Down
3 changes: 0 additions & 3 deletions WildWestOnline/Core/Game/Sources/State/Player.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ public struct Player: Codable, Equatable {
/// Current attributes
public var attributes: [String: Int]

/// Life points
public var health: Int

/// Hand cards
public var hand: [String]

Expand Down
58 changes: 0 additions & 58 deletions WildWestOnline/Core/Game/Tests/DSL/GameTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -164,62 +164,4 @@ final class GameTests: XCTestCase {
XCTAssertEqual(state.player("p2").hand, ["c21", "c22"])
XCTAssertEqual(state.player("p2").inPlay, ["c23", "c24"])
}

func test_game_shouldBeSerializable() throws {
// Given
let JSON = """
{
"winner": "p1",
"players": {
"p1": {
"id": "p1",
"figure": "p1",
"health": 3,
"abilities": [],
"attributes": {},
"hand": [],
"inPlay": []
}
},
"attributes": {},
"abilities": [],
"playOrder": [
"p1"
],
"startOrder": [
"p1"
],
"turn": "p1",
"deck": [
"c1"
],
"discard": [
"c2"
],
"arena": [],
"sequence": [],
"events": [],
"playedThisTurn": {},
"chooseOne": {},
"active": {},
"playMode": {},
"cards": {},
"waitDelayMilliseconds": 100
}
"""
let jsonData = try XCTUnwrap(JSON.data(using: .utf8))

// When
let sut = try JSONDecoder().decode(GameState.self, from: jsonData)

// Then
XCTAssertEqual(sut.winner, "p1")
XCTAssertNotNil(sut.players["p1"])
XCTAssertEqual(sut.playOrder, ["p1"])
XCTAssertEqual(sut.turn, "p1")
XCTAssertEqual(sut.deck, ["c1"])
XCTAssertEqual(sut.discard, ["c2"])
XCTAssertEqual(sut.arena, [])
XCTAssertEqual(sut.waitDelayMilliseconds, 100)
}
}
Loading

0 comments on commit d12b43a

Please sign in to comment.