sashite-cgsn 0.2.0 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4ad5676b320060471229ab9926bce89a0c9435a327404f8a8d1bed076f502566
4
- data.tar.gz: 99266756eb144bd3910035559859102d442a1dff5e6e7b3ae06cdbade39a4b82
3
+ metadata.gz: beabf96294851634c57936be72455275fa16edcff57486184e4d3ae8ac014bc5
4
+ data.tar.gz: e034d7544b1d632a10b6eb4f3c57b24b40665e714b9d757e7e9e8dc390b76f33
5
5
  SHA512:
6
- metadata.gz: 075a7253c398c3bebf01b9ec5e19d6ed4ac1445fb35f2b6451583b176841fb7d0645f95302afdaf73cfb0b6af964814442dc272810ded910e6d69fab062cb379
7
- data.tar.gz: 57aade4830f9ed6f9ad57294881b1e0659296d18f1da8a9e21434164186701b359848909b3c02747841f436d0d4a9328f85cabac7ccf44d5ec4d19cf450e78b2
6
+ metadata.gz: 64656fe401a7c64a3759da560398e3729cad44161562aa67bf35380a9fc1eb848565e4b76e346b5ed580626fc50348a1a04de28271218b3c9cd51ecfd5ced261
7
+ data.tar.gz: ef4d40a1e9066fa77b9bdafa91885ef21ffd7b675d5f236a5ef1bd4df16eef326ff83b1079684e1b668f5386480317e8844fce6daebe52125609f092e58a9445
data/README.md CHANGED
@@ -1,22 +1,27 @@
1
- # Cgsn.rb
1
+ # Sashite::Cgsn
2
2
 
3
3
  [![Version](https://img.shields.io/github/v/tag/sashite/cgsn.rb?label=Version&logo=github)](https://github.com/sashite/cgsn.rb/tags)
4
4
  [![Yard documentation](https://img.shields.io/badge/Yard-documentation-blue.svg?logo=github)](https://rubydoc.info/github/sashite/cgsn.rb/main)
5
5
  ![Ruby](https://github.com/sashite/cgsn.rb/actions/workflows/main.yml/badge.svg?branch=main)
6
6
  [![License](https://img.shields.io/github/license/sashite/cgsn.rb?label=License&logo=github)](https://github.com/sashite/cgsn.rb/raw/main/LICENSE.md)
7
7
 
8
- > **CGSN** (Chess Game Status Notation) implementation for the Ruby language.
8
+ > **CGSN** (Chess Game Status Notation) reference implementation for Ruby.
9
9
 
10
10
  ## What is CGSN?
11
11
 
12
- CGSN (Chess Game Status Notation) provides a **rule-agnostic** taxonomy of observable game status values for abstract strategy board games. CGSN defines standardized identifiers for terminal conditions, player actions, and game progression states that can be recorded independently of competitive interpretation.
12
+ CGSN (Chess Game Status Notation) defines a **finite, standardized list** of **rule-agnostic** status identifiers describing **observable aspects of a game state** for two-player, turn-based abstract strategy board games.
13
13
 
14
- This gem implements the [CGSN Specification v1.0.0](https://sashite.dev/specs/cgsn/1.0.0/), providing a minimal Ruby interface for status validation and categorization with immutable status objects.
14
+ CGSN focuses on *what can be observed or verified*, not on *how a status impacts the result* (win/loss/draw), which remains Rule System– or competition-defined.
15
+
16
+ This library implements the **CGSN Specification v1.0.0**:
17
+ - https://sashite.dev/specs/cgsn/1.0.0/
18
+ - Examples: https://sashite.dev/specs/cgsn/1.0.0/examples/
15
19
 
16
20
  ## Installation
17
21
 
22
+ Add to your Gemfile:
23
+
18
24
  ```ruby
19
- # In your Gemfile
20
25
  gem "sashite-cgsn"
21
26
  ```
22
27
 
@@ -26,145 +31,93 @@ Or install manually:
26
31
  gem install sashite-cgsn
27
32
  ```
28
33
 
29
- ## Format
30
-
31
- CGSN status values are lowercase strings using underscore separators:
32
-
33
- ```ruby
34
- "checkmate"
35
- "bare_king"
36
- "time_limit"
37
- "in_progress"
38
- ```
39
-
40
- ## API Reference
41
-
42
- ### Status Class
34
+ ## Status identifiers
43
35
 
44
- #### Creation and Parsing
36
+ CGSN status values are **lowercase string identifiers** (e.g. `checkmate`, `repetition`).
45
37
 
46
- * `Sashite::Cgsn::Status.new(value)` - Create status instance from string
47
- * `Sashite::Cgsn.parse(value)` - Parse status value (module convenience method)
38
+ CGSN v1.0.0 standard statuses are:
48
39
 
49
- #### Instance Methods
40
+ ### Terminal Piece statuses (position-inferable)
50
41
 
51
- * `#inferable?` - Check if status can be inferred from position analysis
52
- * `#explicit_only?` - Check if status requires explicit declaration
53
- * `#to_s` - Convert to string representation
54
- * `#==(other)` - Equality comparison
55
- * `#hash` - Hash value for use in collections
42
+ These describe the condition of a **specific Terminal Piece** of the active player's side relative to opponent capture threats.
43
+ They are **position-inferable** given the current Position + Rule System.
56
44
 
57
- ### Module Methods
45
+ | Status | Description |
46
+ | ----------- | ------------------------------------------------------------------------------------------------------------------- |
47
+ | `check` | A specific Terminal Piece of the active player's side can be captured by an opponent's Pseudo-Legal Move |
48
+ | `stale` | A specific Terminal Piece of the active player's side cannot be captured by any opponent's Pseudo-Legal Move |
49
+ | `checkmate` | That same Terminal Piece is in `check`, and every Pseudo-Legal Move by the active player still leaves it in `check` |
50
+ | `stalemate` | That same Terminal Piece is `stale`, but every Pseudo-Legal Move by the active player would put it in `check` |
58
51
 
59
- #### Validation
52
+ > Note: In CGSN's model, `check`/`stale` are evaluated **per Terminal Piece** (some games may have multiple Terminal Pieces per side).
60
53
 
61
- * `Sashite::Cgsn.valid?(status)` - Check if string is a valid CGSN status value
54
+ ### Position statuses (position-inferable)
62
55
 
63
- #### Categorization
56
+ These describe global properties of the Position (not tied to a single piece).
64
57
 
65
- * `Sashite::Cgsn.inferable?(status)` - Check if status can be inferred from position analysis
66
- * `Sashite::Cgsn.explicit_only?(status)` - Check if status requires explicit declaration
58
+ | Status | Description |
59
+ | -------------- | ----------------------------------------------------------------------------------------------------------------------- |
60
+ | `nomove` | No Pseudo-Legal Moves exist for the active player |
61
+ | `bareking` | At least one side has **exactly one piece on the Board**, and that piece is a Terminal Piece (Hands are not considered) |
62
+ | `mareking` | At least one side has **no Terminal Pieces on the Board** |
63
+ | `insufficient` | Under the Rule System's insufficiency rules, neither side can force a decisive outcome with the available material |
67
64
 
68
- #### Status Lists
65
+ ### External event statuses (explicit-only)
69
66
 
70
- * `Sashite::Cgsn.statuses` - Array of all defined CGSN status values
71
- * `Sashite::Cgsn.inferable_statuses` - Array of position-derivable statuses
72
- * `Sashite::Cgsn.explicit_only_statuses` - Array of statuses requiring explicit recording
67
+ These cannot be derived from Position + Rule System alone. They require extra context (history, clocks, declarations, etc.) and must be explicitly recorded by the surrounding notation when they occur.
73
68
 
74
- ### Constants
75
-
76
- * `Sashite::Cgsn::STATUSES` - Frozen array of all defined status values
77
- * `Sashite::Cgsn::INFERABLE_STATUSES` - Frozen array of inferable status values
78
- * `Sashite::Cgsn::EXPLICIT_ONLY_STATUSES` - Frozen array of explicit-only status values
69
+ | Status | Description |
70
+ | ------------- | ------------------------------------------------------------------------------------------- |
71
+ | `resignation` | A player explicitly resigned |
72
+ | `illegalmove` | A played move is recognized as not being a Legal Move under the Game Protocol + Rule System |
73
+ | `timelimit` | A player exceeded the time control limit |
74
+ | `movelimit` | The match reached a move-count limit defined by rules or competition regulations |
75
+ | `repetition` | A position repeated according to the Rule System's repetition policy |
76
+ | `agreement` | Both players mutually agreed to end the match |
79
77
 
80
78
  ## Usage
81
79
 
82
- ### Object-Oriented Approach
83
-
84
80
  ```ruby
85
81
  require "sashite/cgsn"
86
82
 
87
- # Parse status into object
88
- status = Sashite::Cgsn.parse("checkmate")
89
- status.inferable? # => true
90
- status.explicit_only? # => false
91
- status.to_s # => "checkmate"
92
-
93
- # Create from string
94
- status = Sashite::Cgsn::Status.new("resignation")
95
- status.inferable? # => false
96
- status.explicit_only? # => true
97
-
98
- # Immutable objects
99
- status.frozen? # => true
100
- ```
101
-
102
- ### Functional Approach
103
-
104
- ```ruby
105
- require "sashite/cgsn"
106
-
107
- # Validate status strings
83
+ # Validation (CGSN v1.0.0 standard vocabulary)
108
84
  Sashite::Cgsn.valid?("checkmate") # => true
85
+ Sashite::Cgsn.valid?("resignation") # => true
109
86
  Sashite::Cgsn.valid?("invalid") # => false
87
+ Sashite::Cgsn.valid?("") # => false
110
88
 
111
- # Check inference capability
112
- Sashite::Cgsn.inferable?("stalemate") # => true
113
- Sashite::Cgsn.explicit_only?("time_limit") # => true
114
-
115
- # Get all statuses
116
- Sashite::Cgsn.statuses
117
- # => ["in_progress", "checkmate", "stalemate", ...]
118
- ```
119
-
120
- ## Properties
89
+ # Classification
90
+ Sashite::Cgsn.inferable?("checkmate") # => true
91
+ Sashite::Cgsn.inferable?("repetition") # => false
121
92
 
122
- * **Rule-agnostic**: Independent of specific game mechanics or outcome interpretation
123
- * **Observable-focused**: Records verifiable facts without competitive judgment
124
- * **Inference-aware**: Distinguishes position-derivable from explicit-only statuses
125
- * **String-based**: Simple string representation for broad compatibility
126
- * **Functional**: Pure functions with no side effects
127
- * **Immutable**: All status instances and data structures are frozen
128
- * **Object-oriented**: Status objects with query methods
93
+ Sashite::Cgsn.explicit_only?("repetition") # => true
94
+ Sashite::Cgsn.explicit_only?("stalemate") # => false
129
95
 
130
- ## Related Specifications
131
-
132
- - [CGSN](https://sashite.dev/specs/cgsn/) - Chess Game Status Notation (this specification)
133
- - [PCN](https://sashite.dev/specs/pcn/) - Portable Chess Notation (uses CGSN for status field)
134
- - [Game Protocol](https://sashite.dev/protocol/) - Conceptual foundation for abstract strategy games
135
-
136
- ## Documentation
137
-
138
- - [Official CGSN Specification v1.0.0](https://sashite.dev/specs/cgsn/1.0.0/)
139
- - [CGSN Examples](https://sashite.dev/specs/cgsn/1.0.0/examples/)
140
- - [API Documentation](https://rubydoc.info/github/sashite/cgsn.rb/main)
96
+ # Lists
97
+ Sashite::Cgsn.statuses
98
+ # => ["check", "stale", "checkmate", "stalemate", "nomove", "bareking", "mareking", "insufficient",
99
+ # "resignation", "illegalmove", "timelimit", "movelimit", "repetition", "agreement"]
141
100
 
142
- ## Development
101
+ Sashite::Cgsn.inferable_statuses
102
+ # => ["check", "stale", "checkmate", "stalemate", "nomove", "bareking", "mareking", "insufficient"]
143
103
 
144
- ```sh
145
- # Clone the repository
146
- git clone https://github.com/sashite/cgsn.rb.git
147
- cd cgsn.rb
104
+ Sashite::Cgsn.explicit_only_statuses
105
+ # => ["resignation", "illegalmove", "timelimit", "movelimit", "repetition", "agreement"]
106
+ ```
148
107
 
149
- # Install dependencies
150
- bundle install
108
+ ## Rule-agnostic design
151
109
 
152
- # Run tests
153
- ruby test.rb
110
+ CGSN records **observable conditions** without defining outcomes.
154
111
 
155
- # Generate documentation
156
- yard doc
157
- ```
112
+ Example: `stalemate` is commonly a draw in Western chess, but other Rule Systems may treat it differently. CGSN only records the underlying condition.
158
113
 
159
- ## Contributing
114
+ ## Related specifications
160
115
 
161
- 1. Fork the repository
162
- 2. Create a feature branch (`git checkout -b feature/new-feature`)
163
- 3. Add tests for your changes
164
- 4. Ensure all tests pass (`ruby test.rb`)
165
- 5. Commit your changes (`git commit -am 'Add new feature'`)
166
- 6. Push to the branch (`git push origin feature/new-feature`)
167
- 7. Create a Pull Request
116
+ * CGSN Specification — [https://sashite.dev/specs/cgsn/1.0.0/](https://sashite.dev/specs/cgsn/1.0.0/)
117
+ * CGSN Examples [https://sashite.dev/specs/cgsn/1.0.0/examples/](https://sashite.dev/specs/cgsn/1.0.0/examples/)
118
+ * Sashité Game Protocol [https://sashite.dev/game-protocol/](https://sashite.dev/game-protocol/)
119
+ * Sashité Glossary [https://sashite.dev/glossary/](https://sashite.dev/glossary/)
120
+ * PCN [https://sashite.dev/specs/pcn/](https://sashite.dev/specs/pcn/)
168
121
 
169
122
  ## License
170
123
 
data/lib/sashite/cgsn.rb CHANGED
@@ -1,150 +1,180 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "cgsn/status"
4
-
5
3
  module Sashite
6
- # CGSN (Chess Game Status Notation) implementation for Ruby
4
+ # CGSN (Chess Game Status Notation) vocabulary for Ruby.
5
+ #
6
+ # This module exposes the CGSN v1.0.0 standard status identifiers (as strings)
7
+ # and helpers to validate / classify them.
8
+ #
9
+ # CGSN statuses are categorized as either:
10
+ #
11
+ # - *position-inferable*: can be determined from Position + Rule System,
12
+ # - *explicit-only*: require extra context (history, clocks, declarations, etc.).
13
+ #
14
+ # This implementation is intentionally *rule-agnostic* and *does not compute*
15
+ # game statuses. It only provides a stable vocabulary and membership checks.
16
+ #
17
+ # Specification:
18
+ # https://sashite.dev/specs/cgsn/1.0.0/
19
+ #
20
+ # @note Some statuses (e.g. +check+, +stalemate+) are defined *per Terminal Piece* in the spec.
21
+ # Associating such a status with a specific piece belongs to the surrounding protocol / notation.
7
22
  #
8
- # Provides functionality for working with rule-agnostic game status values
9
- # for abstract strategy board games.
23
+ # @note While the spec allows extensions, this module validates only the *standard v1.0.0 vocabulary*.
10
24
  #
11
- # This implementation is strictly compliant with CGSN Specification v1.0.0
12
- # @see https://sashite.dev/specs/cgsn/1.0.0/ CGSN Specification v1.0.0
25
+ # @example Validation
26
+ # Sashite::Cgsn.valid?("checkmate") # => true
27
+ # Sashite::Cgsn.valid?("invalid") # => false
28
+ #
29
+ # @example Classification
30
+ # Sashite::Cgsn.inferable?("checkmate") # => true
31
+ # Sashite::Cgsn.explicit_only?("resignation") # => true
32
+ #
33
+ # @see https://sashite.dev/specs/cgsn/1.0.0/ CGSN Specification
34
+ # @see https://sashite.dev/game-protocol/ Game Protocol
35
+ # @see https://sashite.dev/glossary/ Glossary
13
36
  module Cgsn
14
- # Complete list of all defined CGSN status values
15
- STATUSES = %w[
16
- in_progress
17
- checkmate
18
- stalemate
19
- staleturn
20
- bare_king
21
- mare_king
22
- insufficient
23
- resignation
24
- illegal_move
25
- time_limit
26
- move_limit
27
- repetition
28
- agreement
29
- ].freeze
30
-
31
- # Statuses that can be inferred from position analysis
37
+ # Position-inferable status identifiers.
38
+ #
39
+ # "Position-inferable" means: given the current Position and the Rule System,
40
+ # the status can be determined without external context (history, clocks, declarations, etc.).
41
+ #
42
+ # @return [Array<String>] frozen array of inferable status identifiers
32
43
  INFERABLE_STATUSES = %w[
33
- in_progress
44
+ check
45
+ stale
34
46
  checkmate
35
47
  stalemate
36
- staleturn
37
- bare_king
38
- mare_king
48
+ nomove
49
+ bareking
50
+ mareking
39
51
  insufficient
40
52
  ].freeze
41
53
 
42
- # Statuses that require explicit declaration
54
+ # Explicit-only status identifiers.
55
+ #
56
+ # "Explicit-only" means: the status cannot be derived from Position + Rule System alone
57
+ # because it requires external context (history, clocks, declarations, etc.).
58
+ #
59
+ # @return [Array<String>] frozen array of explicit-only status identifiers
43
60
  EXPLICIT_ONLY_STATUSES = %w[
44
61
  resignation
45
- illegal_move
46
- time_limit
47
- move_limit
62
+ illegalmove
63
+ timelimit
64
+ movelimit
48
65
  repetition
49
66
  agreement
50
67
  ].freeze
51
68
 
52
- # Check if a string is a valid CGSN status value
53
- #
54
- # @param value [String] the status to validate
55
- # @return [Boolean] true if the status is valid
69
+ # All CGSN v1.0.0 status identifiers.
56
70
  #
57
- # @example
58
- # Sashite::Cgsn.valid?("checkmate") # => true
59
- # Sashite::Cgsn.valid?("staleturn") # => true
60
- # Sashite::Cgsn.valid?("time_limit") # => true
61
- # Sashite::Cgsn.valid?("invalid") # => false
62
- # Sashite::Cgsn.valid?("Checkmate") # => false
63
- # Sashite::Cgsn.valid?(:checkmate) # => true (converts to "checkmate")
64
- def self.valid?(value)
65
- status_string = String(value)
66
- STATUSES.include?(status_string)
67
- rescue ::TypeError
68
- false
69
- end
71
+ # @return [Array<String>] frozen array of all status identifiers
72
+ STATUSES = (INFERABLE_STATUSES + EXPLICIT_ONLY_STATUSES).freeze
73
+
74
+ # Fast membership lookup sets (private implementation detail).
75
+ INFERABLE_SET = INFERABLE_STATUSES.to_set.freeze
76
+ EXPLICIT_ONLY_SET = EXPLICIT_ONLY_STATUSES.to_set.freeze
77
+ STATUS_SET = STATUSES.to_set.freeze
78
+
79
+ private_constant :INFERABLE_SET, :EXPLICIT_ONLY_SET, :STATUS_SET
70
80
 
71
- # Parse a status value into a Status object
81
+ # Returns all CGSN v1.0.0 status identifiers.
72
82
  #
73
- # @param value [String] the status value to parse
74
- # @return [Status] new status instance
75
- # @raise [ArgumentError] if the status value is invalid
83
+ # The returned array has a stable order.
84
+ #
85
+ # @return [Array<String>] all status identifiers
76
86
  #
77
87
  # @example
78
- # Sashite::Cgsn.parse("checkmate") # => #<Cgsn::Status value="checkmate">
79
- # Sashite::Cgsn.parse("staleturn") # => #<Cgsn::Status value="staleturn">
80
- # Sashite::Cgsn.parse("resignation") # => #<Cgsn::Status value="resignation">
81
- def self.parse(value)
82
- Status.new(value)
88
+ # Sashite::Cgsn.statuses
89
+ # # => ["check", "stale", "checkmate", "stalemate", "nomove", "bareking", "mareking", "insufficient",
90
+ # # "resignation", "illegalmove", "timelimit", "movelimit", "repetition", "agreement"]
91
+ def self.statuses
92
+ STATUSES
83
93
  end
84
94
 
85
- # Check if a status can be inferred from position analysis
95
+ # Returns all position-inferable CGSN v1.0.0 status identifiers.
96
+ #
97
+ # "Position-inferable" means: given the current Position and the Rule System,
98
+ # the status can be determined without external context (history, clocks, declarations, etc.).
86
99
  #
87
- # @param status [String, Status] the status to check
88
- # @return [Boolean] true if the status is inferable
100
+ # @return [Array<String>] inferable status identifiers
89
101
  #
90
102
  # @example
91
- # Sashite::Cgsn.inferable?("checkmate") # => true
92
- # Sashite::Cgsn.inferable?("staleturn") # => true
93
- # Sashite::Cgsn.inferable?("resignation") # => false
94
- def self.inferable?(status)
95
- status_string = String(status)
96
- INFERABLE_STATUSES.include?(status_string)
97
- rescue ::TypeError
98
- false
103
+ # Sashite::Cgsn.inferable_statuses
104
+ # # => ["check", "stale", "checkmate", "stalemate", "nomove", "bareking", "mareking", "insufficient"]
105
+ def self.inferable_statuses
106
+ INFERABLE_STATUSES
99
107
  end
100
108
 
101
- # Check if a status requires explicit declaration
109
+ # Returns all explicit-only CGSN v1.0.0 status identifiers.
102
110
  #
103
- # @param status [String, Status] the status to check
104
- # @return [Boolean] true if the status is explicit-only
111
+ # "Explicit-only" means: the status cannot be derived from Position + Rule System alone
112
+ # because it requires external context (history, clocks, declarations, etc.).
113
+ #
114
+ # @return [Array<String>] explicit-only status identifiers
105
115
  #
106
116
  # @example
107
- # Sashite::Cgsn.explicit_only?("resignation") # => true
108
- # Sashite::Cgsn.explicit_only?("checkmate") # => false
109
- # Sashite::Cgsn.explicit_only?("staleturn") # => false
110
- def self.explicit_only?(status)
111
- status_string = String(status)
112
- EXPLICIT_ONLY_STATUSES.include?(status_string)
113
- rescue ::TypeError
114
- false
117
+ # Sashite::Cgsn.explicit_only_statuses
118
+ # # => ["resignation", "illegalmove", "timelimit", "movelimit", "repetition", "agreement"]
119
+ def self.explicit_only_statuses
120
+ EXPLICIT_ONLY_STATUSES
115
121
  end
116
122
 
117
- # Get the list of all defined CGSN status values
123
+ # Checks whether the given value is a standard CGSN v1.0.0 status identifier.
124
+ #
125
+ # This method is intentionally strict: it validates membership in the official
126
+ # CGSN v1.0.0 vocabulary. It does *not* validate or accept non-standard extensions.
118
127
  #
119
- # @return [Array<String>] array of all status values
128
+ # @param status [Object] the value to check
129
+ # @return [Boolean] true if the value is a valid CGSN status identifier
120
130
  #
121
131
  # @example
122
- # Sashite::Cgsn.statuses
123
- # # => ["in_progress", "checkmate", "stalemate", "staleturn", ...]
124
- def self.statuses
125
- STATUSES.dup
132
+ # Sashite::Cgsn.valid?("checkmate") # => true
133
+ # Sashite::Cgsn.valid?("resignation") # => true
134
+ # Sashite::Cgsn.valid?("invalid") # => false
135
+ # Sashite::Cgsn.valid?("") # => false
136
+ # Sashite::Cgsn.valid?(nil) # => false
137
+ # Sashite::Cgsn.valid?(123) # => false
138
+ def self.valid?(status)
139
+ return false unless status.is_a?(::String)
140
+
141
+ STATUS_SET.include?(status)
126
142
  end
127
143
 
128
- # Get the list of inferable status values
144
+ # Checks whether the given status is position-inferable in CGSN v1.0.0.
145
+ #
146
+ # @param status [Object] the value to check
147
+ # @return [Boolean] true if the status is position-inferable, false otherwise
129
148
  #
130
- # @return [Array<String>] array of inferable status values
149
+ # @note Returns false for non-String inputs and unknown identifiers.
131
150
  #
132
151
  # @example
133
- # Sashite::Cgsn.inferable_statuses
134
- # # => ["in_progress", "checkmate", "stalemate", "staleturn", ...]
135
- def self.inferable_statuses
136
- INFERABLE_STATUSES.dup
152
+ # Sashite::Cgsn.inferable?("checkmate") # => true
153
+ # Sashite::Cgsn.inferable?("stalemate") # => true
154
+ # Sashite::Cgsn.inferable?("repetition") # => false
155
+ # Sashite::Cgsn.inferable?("invalid") # => false
156
+ def self.inferable?(status)
157
+ return false unless status.is_a?(::String)
158
+
159
+ INFERABLE_SET.include?(status)
137
160
  end
138
161
 
139
- # Get the list of explicit-only status values
162
+ # Checks whether the given status is explicit-only in CGSN v1.0.0.
163
+ #
164
+ # @param status [Object] the value to check
165
+ # @return [Boolean] true if the status is explicit-only, false otherwise
140
166
  #
141
- # @return [Array<String>] array of explicit-only status values
167
+ # @note Returns false for non-String inputs and unknown identifiers.
142
168
  #
143
169
  # @example
144
- # Sashite::Cgsn.explicit_only_statuses
145
- # # => ["resignation", "illegal_move", "time_limit", ...]
146
- def self.explicit_only_statuses
147
- EXPLICIT_ONLY_STATUSES.dup
170
+ # Sashite::Cgsn.explicit_only?("resignation") # => true
171
+ # Sashite::Cgsn.explicit_only?("timelimit") # => true
172
+ # Sashite::Cgsn.explicit_only?("checkmate") # => false
173
+ # Sashite::Cgsn.explicit_only?("invalid") # => false
174
+ def self.explicit_only?(status)
175
+ return false unless status.is_a?(::String)
176
+
177
+ EXPLICIT_ONLY_SET.include?(status)
148
178
  end
149
179
  end
150
180
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sashite-cgsn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyril Kato
@@ -13,9 +13,9 @@ description: |
13
13
  CGSN (Chess Game Status Notation) provides a rule-agnostic taxonomy of observable game status
14
14
  values for abstract strategy board games. This gem implements the CGSN Specification v1.0.0 with
15
15
  a minimal Ruby interface featuring immutable status objects and functional programming principles.
16
- CGSN defines standardized identifiers for terminal conditions (checkmate, stalemate, bare_king,
17
- mare_king, insufficient), player actions (resignation, agreement, illegal_move), and temporal
18
- constraints (time_limit, move_limit, repetition), enabling precise and portable status identification
16
+ CGSN defines standardized identifiers for terminal conditions (checkmate, stalemate, bareking,
17
+ mareking, insufficient), player actions (resignation, agreement, illegalmove), and temporal
18
+ constraints (timelimit, movelimit, repetition), enabling precise and portable status identification
19
19
  across multiple games and variants. Perfect for game engines, notation systems, and hybrid gaming
20
20
  platforms requiring consistent, rule-agnostic game state representation.
21
21
  email: contact@cyril.email
@@ -27,7 +27,6 @@ files:
27
27
  - README.md
28
28
  - lib/sashite-cgsn.rb
29
29
  - lib/sashite/cgsn.rb
30
- - lib/sashite/cgsn/status.rb
31
30
  homepage: https://github.com/sashite/cgsn.rb
32
31
  licenses:
33
32
  - MIT
@@ -1,85 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sashite
4
- module Cgsn
5
- # Represents a status value in CGSN (Chess Game Status Notation) format.
6
- #
7
- # A status consists of a lowercase string with optional underscore separators.
8
- # Each status represents an observable game state that can be recorded
9
- # independently of competitive interpretation.
10
- #
11
- # All instances are immutable.
12
- class Status
13
- # Error message for invalid status values
14
- ERROR_INVALID_STATUS = "Invalid CGSN status: %s"
15
-
16
- # Create a new status instance
17
- #
18
- # @param value [String] status value
19
- # @raise [ArgumentError] if the value is invalid
20
- #
21
- # @example
22
- # Status.new("checkmate") # => #<Cgsn::Status value="checkmate">
23
- # Status.new("resignation") # => #<Cgsn::Status value="resignation">
24
- def initialize(value)
25
- @value = String(value)
26
-
27
- raise ::ArgumentError, format(ERROR_INVALID_STATUS, @value) unless Cgsn::STATUSES.include?(@value)
28
-
29
- freeze
30
- end
31
-
32
- # Check if the status can be inferred from position analysis
33
- #
34
- # @return [Boolean] true if inferable
35
- #
36
- # @example
37
- # Status.new("checkmate").inferable? # => true
38
- # Status.new("resignation").inferable? # => false
39
- def inferable?
40
- Cgsn::INFERABLE_STATUSES.include?(@value)
41
- end
42
-
43
- # Check if the status requires explicit declaration
44
- #
45
- # @return [Boolean] true if explicit-only
46
- #
47
- # @example
48
- # Status.new("resignation").explicit_only? # => true
49
- # Status.new("checkmate").explicit_only? # => false
50
- def explicit_only?
51
- Cgsn::EXPLICIT_ONLY_STATUSES.include?(@value)
52
- end
53
-
54
- # Convert the status to its string representation
55
- #
56
- # @return [String] status value
57
- #
58
- # @example
59
- # Status.new("checkmate").to_s # => "checkmate"
60
- def to_s
61
- @value
62
- end
63
-
64
- # Custom equality comparison
65
- #
66
- # @param other [Object] object to compare with
67
- # @return [Boolean] true if statuses are equal
68
- def ==(other)
69
- return false unless other.is_a?(self.class)
70
-
71
- to_s == other.to_s
72
- end
73
-
74
- # Alias for == to ensure Set functionality works correctly
75
- alias eql? ==
76
-
77
- # Custom hash implementation for use in collections
78
- #
79
- # @return [Integer] hash value
80
- def hash
81
- [self.class, @value].hash
82
- end
83
- end
84
- end
85
- end