sashite-ggn 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,97 +1,64 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative File.join("..", "move_validator")
4
- require_relative File.join("source", "destination")
3
+ require_relative "source/destination"
5
4
 
6
5
  module Sashite
7
6
  module Ggn
8
7
  class Ruleset
9
- # Represents the possible source positions for a specific piece type.
8
+ # Represents movement possibilities for a piece type
10
9
  #
11
- # A Source instance contains all the starting positions from which
12
- # a piece can move on the board. Since GGN focuses exclusively on
13
- # board-to-board transformations, all source positions are regular
14
- # board squares.
15
- #
16
- # @example Basic usage with chess king
17
- # piece_data = Sashite::Ggn.load_file('chess.json')
18
- # source = piece_data.select('CHESS:K')
19
- # destinations = source.from('e1')
20
- #
21
- # @example Complete move evaluation workflow
22
- # piece_data = Sashite::Ggn.load_file('chess.json')
23
- # king_source = piece_data.select('CHESS:K')
24
- # destinations = king_source.from('e1')
25
- # engine = destinations.to('e2')
26
- #
27
- # board_state = { 'e1' => 'CHESS:K', 'e2' => nil }
28
- # transitions = engine.where(board_state, 'CHESS')
29
- #
30
- # if transitions.any?
31
- # puts "King can move from e1 to e2"
32
- # end
10
+ # @see https://sashite.dev/specs/ggn/1.0.0/
33
11
  class Source
34
- include MoveValidator
12
+ # @return [String] The QPI piece identifier
13
+ attr_reader :piece
35
14
 
36
- # Creates a new Source instance from movement data.
37
- #
38
- # @param data [Hash] The movement data where keys are source positions
39
- # (square labels) and values contain destination data.
40
- # @param actor [String] The GAN identifier for this piece type
41
- #
42
- # @raise [ArgumentError] If data is not a Hash
43
- #
44
- # @example Creating a Source instance
45
- # source_data = {
46
- # "e1" => { "e2" => [...], "f1" => [...] },
47
- # "d4" => { "d5" => [...], "e5" => [...] }
48
- # }
49
- # source = Source.new(source_data, actor: "CHESS:K")
50
- def initialize(data, actor:)
51
- raise ::ArgumentError, "Expected Hash, got #{data.class}" unless data.is_a?(::Hash)
15
+ # @return [Hash] The sources data
16
+ attr_reader :data
52
17
 
18
+ # Create a new Source
19
+ #
20
+ # @param piece [String] QPI piece identifier
21
+ # @param data [Hash] Sources data structure
22
+ def initialize(piece, data)
23
+ @piece = piece
53
24
  @data = data
54
- @actor = actor
55
25
 
56
26
  freeze
57
27
  end
58
28
 
59
- # Retrieves possible destinations from a specific source position.
29
+ # Specify the source location for the piece
60
30
  #
61
- # @param origin [String] The source position label. Must be a regular
62
- # square label (e.g., 'e1', '5i', 'a1').
31
+ # @param source [String] Source location (CELL coordinate or HAND "*")
32
+ # @return [Destination] Destination selector object
33
+ # @raise [KeyError] If source not found for this piece
63
34
  #
64
- # @return [Destination] A Destination instance containing all possible
65
- # target squares and their movement conditions from this origin.
35
+ # @example
36
+ # destination = source.from("e1")
37
+ def from(source)
38
+ raise ::KeyError, "Source not found: #{source}" unless source?(source)
39
+
40
+ Destination.new(piece, source, data.fetch(source))
41
+ end
42
+
43
+ # Return all valid source locations for this piece
66
44
  #
67
- # @raise [KeyError] If the origin position is not found in the data
45
+ # @return [Array<String>] Source locations
68
46
  #
69
- # @example Getting moves from a specific square
70
- # destinations = source.from('e1')
71
- # engine = destinations.to('e2')
47
+ # @example
48
+ # source.sources # => ["e1", "d1", "*"]
49
+ def sources
50
+ data.keys
51
+ end
52
+
53
+ # Check if location is a valid source for this piece
72
54
  #
73
- # @example Handling missing origins
74
- # begin
75
- # destinations = source.from('invalid_square')
76
- # rescue KeyError => e
77
- # puts "No moves from this position: #{e.message}"
78
- # end
55
+ # @param location [String] Source location
56
+ # @return [Boolean]
79
57
  #
80
- # @example Iterating through all possible origins
81
- # # Assuming you have access to the source data keys
82
- # available_origins = ['e1', 'd1', 'f1'] # example origins
83
- # available_origins.each do |pos|
84
- # begin
85
- # destinations = source.from(pos)
86
- # puts "Piece can move from #{pos}"
87
- # # Process destinations...
88
- # rescue KeyError
89
- # puts "No moves available from #{pos}"
90
- # end
91
- # end
92
- def from(origin)
93
- data = @data.fetch(origin)
94
- Destination.new(data, actor: @actor, origin: origin)
58
+ # @example
59
+ # source.source?("e1") # => true
60
+ def source?(location)
61
+ data.key?(location)
95
62
  end
96
63
  end
97
64
  end