Skip to content

Commit

Permalink
Elaborate restriction settings for writing direction
Browse files Browse the repository at this point in the history
* update proto schema
* provide setting for first and following turns
* different setting values
* instead of a move counter, append the moves to an array and determine the last move's direction from this
  • Loading branch information
tamaracha committed Feb 21, 2019
1 parent 36b0371 commit 2a41c47
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 24 deletions.
44 changes: 31 additions & 13 deletions Sources/Games/Begriffix.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@ import Utility
public struct Begriffix: DyadicGame, Trackable {
public typealias Word = [Unicode.Scalar]
public typealias Board = BegriffixBoard
public typealias MinWordLength = (restricted: Int, liberal: Int)
public typealias MinWordLength = (first: Int, other: Int)
/// Modes of restriction for the writing direction
public enum DirectionRestrictionMode {
/// Starter is unrestricted, opponent must write orthogonally to starter
case variable
/// Starter must write horizontally, opponent must write vertically
case fixed
}
public typealias DirectionRestrictions = (first: DirectionRestrictionMode?, other: DirectionRestrictionMode?)
public typealias Players = DyadicPlayers<Begriffix>
public typealias Status = GameStatus<Begriffix>
public typealias Notify = ((_ status: Status) -> Void)?
Expand All @@ -27,14 +35,14 @@ public struct Begriffix: DyadicGame, Trackable {
}
}
public static let name = "Begriffix"
/// How many times the starter and opponent have provided a move
public private(set) var moveCount: Int = 0
/// The already inserted moves
public private(set) var moves: [Move] = []
public var turn: Int {
return moveCount/2
return moves.count / 2
}
/// The current player position
public var player: Players.Position {
return moveCount % 2 == 0 ? .starter : .opponent
return moves.count % 2 == 0 ? .starter : .opponent
}
/// The players coordinator
public var players: Players
Expand All @@ -44,21 +52,21 @@ public struct Begriffix: DyadicGame, Trackable {
public let vocabulary: Radix?
/// The minimum word lengths for the two game phases
public let minWordLength: MinWordLength
/// Indicates if opponent must write orthogonally to starter in the first turn
public let firstOrthogonal: Bool
/// The restrictions of writing direction in and after the first turn
public let directionRestrictions: DirectionRestrictions
public var notify: Notify
/// Initialize a new begriffix game
public init(
board: Board,
players: Players,
minWordLength: MinWordLength = (restricted: 5, liberal: 4),
firstOrthogonal: Bool = true,
minWordLength: MinWordLength = (first: 5, other: 4),
directionRestrictions: DirectionRestrictions = (first: .variable, other: nil),
vocabulary: Radix? = nil
) {
self.board = board
self.players = players
self.minWordLength = minWordLength
self.firstOrthogonal = firstOrthogonal
self.directionRestrictions = directionRestrictions
self.vocabulary = vocabulary
}
/// Play the game and pass notifications if a notify callback is set
Expand All @@ -76,12 +84,22 @@ public struct Begriffix: DyadicGame, Trackable {
/// Apply a move to the game
public mutating func insert(_ move: Move) throws {
try board.insert(move.word, at: move.place)
moveCount += 1
moves.append(move)
}
/// The direction which can currently be used to write, nil if not restricted
public var dir: Direction? {
guard let mode = turn == 0 ? directionRestrictions.first : directionRestrictions.other else {return nil}
switch mode {
case .fixed:
return self.player == .starter ? .horizontal : .vertical
case .variable:
return self.player == .opponent ? moves.last?.place.direction.orthogonal : nil
}
}
/// Find every place where words with allowed direction and length could be written
public func find() -> FlattenCollection<[[Place]]> {
let min = turn == 0 ? minWordLength.restricted : minWordLength.liberal
if moveCount == 1, firstOrthogonal, let dir = board.findBalance() {
let min = turn == 0 ? minWordLength.first : minWordLength.other
if let dir = self.dir {
return (min...board.sideLength)
.concurrentMap {self.board.find(direction: dir, count: $0)}
.joined()
Expand Down
29 changes: 20 additions & 9 deletions Sources/HangmanCLI/Simulation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,24 +57,35 @@ extension SGSimulation.Info {
}
}

extension Begriffix.DirectionRestrictionMode {
init?(condition: SGSimulation.Condition.DirectionRestrictions.Mode) {
switch condition {
case .none: return nil
case .fixed: self = .fixed
case .starter: self = .variable
default: return nil
}
}
}

extension Begriffix {
init?(condition: SGSimulation.Condition) {
guard let starter = try? Player(config: condition.starter) else {return nil}
let opponent = (try? Player(config: condition.opponent)) ?? starter
let vocabulary = try? condition.vocabulary.load()
guard let board = BegriffixBoard(condition: condition) else {return nil}
let players = DyadicPlayers<Begriffix>(starter: starter.move, opponent: opponent.move)
guard condition.hasWordMinLength else {
self.init(board: board, players: players, firstOrthogonal: condition.firstOrthogonal, vocabulary: vocabulary)
return
}
let minWordLength = (
restricted: Int(condition.wordMinLength.restricted),
liberal: Int(condition.wordMinLength.liberal)
)
let minWordLength = condition.hasWordMinLength ?
(first: Int(condition.wordMinLength.first), other: Int(condition.wordMinLength.other)) : (first: 5, other: 4)
let directionRestrictions = condition.hasDirectionRestrictions ?
(
first: Begriffix.DirectionRestrictionMode(condition: condition.directionRestrictions.first),
other: Begriffix.DirectionRestrictionMode(condition: condition.directionRestrictions.other)
) :
(first: .variable, other: nil)
self.init(
board: board, players: players,
minWordLength: minWordLength, firstOrthogonal: condition.firstOrthogonal, vocabulary: vocabulary
minWordLength: minWordLength, directionRestrictions: directionRestrictions, vocabulary: vocabulary
)
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/HangmanCLI/play.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ let playCommand = Command(
private func move(_ game: Begriffix) -> Begriffix.Move? {
let start: Point = ask("Which position do you want to start writing from?")
let direction: Direction
if game.moveCount == 1, let dir = game.board.findBalance() {
if let dir = game.dir {
print("Direction is \(dir), because we are in turn 1 and you are opponent")
direction = dir
} else {
Expand Down
2 changes: 1 addition & 1 deletion Sources/HangmanCLI/proto
Submodule proto updated 1 files
+21 −6 SimulationSchema.proto
1 change: 1 addition & 0 deletions Tests/GamesTests/GameTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class BegriffixTests: XCTestCase {
XCTAssertEqual(move.hits?.count, 40)
try! game.insert(move)
guard let move2 = game.players.opponent(game) else {return}
XCTAssertEqual(game.moves.count, 1)
XCTAssertEqual(move2.hits?.count, 20)
XCTAssertNotEqual(move.place.direction, move2.place.direction)
try! game.insert(move2)
Expand Down

0 comments on commit 2a41c47

Please # to comment.