Skip to content

Commit

Permalink
Add validation options (#1)
Browse files Browse the repository at this point in the history
This option set will be used to further control the validation settings,
with convenience measures for the base game and What the Taiji?!.
  • Loading branch information
alicerunsonfedora committed Jan 12, 2025
1 parent d798525 commit 2de8034
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 13 deletions.
5 changes: 3 additions & 2 deletions Sources/PuzzleKit/Taiji/PKTaijiPuzzle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ public struct PKTaijiPuzzle: Equatable, Sendable {
public extension PKTaijiPuzzle {
/// Validates the current puzzle, checking for any unsatisfied constraints.
/// - Returns: The result from validation.
func validate() -> PKTaijiPuzzleValidator.ValidationResult {
PKTaijiPuzzleValidator(puzzle: self).validate()
func validate(options: PKTaijiPuzzleValidator.Options = []) -> PKTaijiPuzzleValidator.ValidationResult {
let validator = PKTaijiPuzzleValidator(puzzle: self, options: options)
return validator.validate()
}
}

Expand Down
31 changes: 30 additions & 1 deletion Sources/PuzzleKit/Taiji/PKTaijiPuzzleValidator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,22 @@ public enum PKTaijiPuzzleValidatorError: Sendable, Equatable, Error {
public class PKTaijiPuzzleValidator {
/// A type representing the validation result.
public typealias ValidationResult = Result<Void, PKTaijiPuzzleValidatorError>

/// A structure representing the options the validator can accept.
public struct Options: OptionSet, Sendable {
/// The raw value representing the options available.
public var rawValue: Int

/// Ignore color mechanics when validating.
public static let ignoresColor = Options(rawValue: 1 << 0)

/// Allow color mechanics to match against any type of symbol when necessary.
public static let colorsMatchAnySymbols = Options(rawValue: 1 << 1)

public init(rawValue: Int) {
self.rawValue = rawValue
}
}

struct SymbolLUT {
var diamonds = [PKGridCoordinate]()
Expand All @@ -28,15 +44,17 @@ public class PKTaijiPuzzleValidator {
var flowers = [PKGridCoordinate]()
}

var options: Options
var puzzle: PKTaijiPuzzle
var symbolLUT = SymbolLUT()
var regionMap = [PKGridCoordinate: Int]()
var regions = [Int: PKGridRegion]()

var totalRegions: Int { return regions.count }

public init(puzzle: PKTaijiPuzzle) {
public init(puzzle: PKTaijiPuzzle, options: Options = []) {
self.puzzle = puzzle
self.options = options

var currentRegion = 1
self.regionMap = [PKGridCoordinate: Int]()
Expand Down Expand Up @@ -226,3 +244,14 @@ public class PKTaijiPuzzleValidator {
return foundMatch
}
}

public extension PKTaijiPuzzleValidator.Options {
/// The typical validator rules associated with the base game.
static let baseGame: Self = [.colorsMatchAnySymbols]

/// The typical validator rules associated with the "What the Taiji?!" spinoff.
///
/// Due to technical limitations with the Playdate, this validator style ignores some aspects of typical Taiji
/// puzzles, such as the lack of color.
static let whatTheTaiji: Self = [.ignoresColor]
}
21 changes: 11 additions & 10 deletions Tests/PuzzleKitTests/Taiji/PKTaijiPuzzleValidator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ struct PKTaijiPuzzleValidatorTests {
}
}

@Test("Diamond constraints")
func validationDiamondConstraints() async throws {
@Test("Diamond constraints (WTT)")
func validationDiamondConstraintsWTT() async throws {
let okDiamonds = try PKTaijiPuzzle(decoding: "3:Sw20Sw2Sw20Sw22Sw0Sw0")
#expect(throws: Never.self) {
try okDiamonds.validate().get()
try okDiamonds.validate(options: .whatTheTaiji).get()
}

let notOkDiamonds = try PKTaijiPuzzle(decoding: "3:Sw+BSw2Sw+BSw22Sw0Sw0")
Expand All @@ -62,11 +62,11 @@ struct PKTaijiPuzzleValidatorTests {
}
}

@Test("Dots constraints")
func validationDotConstraints() async throws {
@Test("Dots constraints (WTT)")
func validationDotConstraintsWTT() async throws {
let okDots = try PKTaijiPuzzle(decoding: "3:Dw20222Jw420Dw4")
#expect(throws: Never.self) {
try okDots.validate().get()
try okDots.validate(options: .whatTheTaiji).get()
}

let notOkDots = try PKTaijiPuzzle(decoding: "3:Dw20222Jw4+BDw4")
Expand All @@ -75,11 +75,11 @@ struct PKTaijiPuzzleValidatorTests {
}
}

@Test("Slashdash constraints")
func validationSlashdashConstraints() async throws {
@Test("Slashdash constraints (WTT)")
func validationSlashdashConstraintsWTT() async throws {
let okSlashdash = try PKTaijiPuzzle(decoding: "6:644+B26Tw640Uw22644+B2")
#expect(throws: Never.self) {
try okSlashdash.validate().get()
try okSlashdash.validate(options: .whatTheTaiji).get()
}

let notOkSlashdash = try PKTaijiPuzzle(decoding: "4:02+CUw2Uw440Uw0Tw6+C60")
Expand All @@ -104,6 +104,7 @@ struct PKTaijiPuzzleValidatorTests {
return tile
}()

#expect(PKTaijiPuzzleValidator.slashdashRotates(lhs: lhs, rhs: rhs, lhsOrigin: lhsOrigin, rhsOrigin: rhsOrigin))
#expect(
PKTaijiPuzzleValidator.slashdashRotates(lhs: lhs, rhs: rhs, lhsOrigin: lhsOrigin, rhsOrigin: rhsOrigin))
}
}

0 comments on commit 2de8034

Please sign in to comment.