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 +4 -4
- data/README.md +67 -114
- data/lib/sashite/cgsn.rb +129 -99
- metadata +4 -5
- data/lib/sashite/cgsn/status.rb +0 -85
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: beabf96294851634c57936be72455275fa16edcff57486184e4d3ae8ac014bc5
|
|
4
|
+
data.tar.gz: e034d7544b1d632a10b6eb4f3c57b24b40665e714b9d757e7e9e8dc390b76f33
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 64656fe401a7c64a3759da560398e3729cad44161562aa67bf35380a9fc1eb848565e4b76e346b5ed580626fc50348a1a04de28271218b3c9cd51ecfd5ced261
|
|
7
|
+
data.tar.gz: ef4d40a1e9066fa77b9bdafa91885ef21ffd7b675d5f236a5ef1bd4df16eef326ff83b1079684e1b668f5386480317e8844fce6daebe52125609f092e58a9445
|
data/README.md
CHANGED
|
@@ -1,22 +1,27 @@
|
|
|
1
|
-
# Cgsn
|
|
1
|
+
# Sashite::Cgsn
|
|
2
2
|
|
|
3
3
|
[](https://github.com/sashite/cgsn.rb/tags)
|
|
4
4
|
[](https://rubydoc.info/github/sashite/cgsn.rb/main)
|
|
5
5
|

|
|
6
6
|
[](https://github.com/sashite/cgsn.rb/raw/main/LICENSE.md)
|
|
7
7
|
|
|
8
|
-
> **CGSN** (Chess Game Status Notation) implementation for
|
|
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)
|
|
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
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
36
|
+
CGSN status values are **lowercase string identifiers** (e.g. `checkmate`, `repetition`).
|
|
45
37
|
|
|
46
|
-
|
|
47
|
-
* `Sashite::Cgsn.parse(value)` - Parse status value (module convenience method)
|
|
38
|
+
CGSN v1.0.0 standard statuses are:
|
|
48
39
|
|
|
49
|
-
|
|
40
|
+
### Terminal Piece statuses (position-inferable)
|
|
50
41
|
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
54
|
+
### Position statuses (position-inferable)
|
|
62
55
|
|
|
63
|
-
|
|
56
|
+
These describe global properties of the Position (not tied to a single piece).
|
|
64
57
|
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
|
|
65
|
+
### External event statuses (explicit-only)
|
|
69
66
|
|
|
70
|
-
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
#
|
|
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
|
-
#
|
|
112
|
-
Sashite::Cgsn.inferable?("
|
|
113
|
-
Sashite::Cgsn.
|
|
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
|
-
|
|
123
|
-
|
|
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
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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
|
-
|
|
101
|
+
Sashite::Cgsn.inferable_statuses
|
|
102
|
+
# => ["check", "stale", "checkmate", "stalemate", "nomove", "bareking", "mareking", "insufficient"]
|
|
143
103
|
|
|
144
|
-
|
|
145
|
-
#
|
|
146
|
-
|
|
147
|
-
cd cgsn.rb
|
|
104
|
+
Sashite::Cgsn.explicit_only_statuses
|
|
105
|
+
# => ["resignation", "illegalmove", "timelimit", "movelimit", "repetition", "agreement"]
|
|
106
|
+
```
|
|
148
107
|
|
|
149
|
-
|
|
150
|
-
bundle install
|
|
108
|
+
## Rule-agnostic design
|
|
151
109
|
|
|
152
|
-
|
|
153
|
-
ruby test.rb
|
|
110
|
+
CGSN records **observable conditions** without defining outcomes.
|
|
154
111
|
|
|
155
|
-
|
|
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
|
-
##
|
|
114
|
+
## Related specifications
|
|
160
115
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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)
|
|
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
|
-
#
|
|
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
|
-
#
|
|
12
|
-
#
|
|
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
|
-
#
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
44
|
+
check
|
|
45
|
+
stale
|
|
34
46
|
checkmate
|
|
35
47
|
stalemate
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
48
|
+
nomove
|
|
49
|
+
bareking
|
|
50
|
+
mareking
|
|
39
51
|
insufficient
|
|
40
52
|
].freeze
|
|
41
53
|
|
|
42
|
-
#
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
62
|
+
illegalmove
|
|
63
|
+
timelimit
|
|
64
|
+
movelimit
|
|
48
65
|
repetition
|
|
49
66
|
agreement
|
|
50
67
|
].freeze
|
|
51
68
|
|
|
52
|
-
#
|
|
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
|
-
# @
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
#
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
#
|
|
81
|
+
# Returns all CGSN v1.0.0 status identifiers.
|
|
72
82
|
#
|
|
73
|
-
#
|
|
74
|
-
#
|
|
75
|
-
# @
|
|
83
|
+
# The returned array has a stable order.
|
|
84
|
+
#
|
|
85
|
+
# @return [Array<String>] all status identifiers
|
|
76
86
|
#
|
|
77
87
|
# @example
|
|
78
|
-
# Sashite::Cgsn.
|
|
79
|
-
#
|
|
80
|
-
#
|
|
81
|
-
def self.
|
|
82
|
-
|
|
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
|
-
#
|
|
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
|
-
# @
|
|
88
|
-
# @return [Boolean] true if the status is inferable
|
|
100
|
+
# @return [Array<String>] inferable status identifiers
|
|
89
101
|
#
|
|
90
102
|
# @example
|
|
91
|
-
# Sashite::Cgsn.
|
|
92
|
-
#
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
#
|
|
109
|
+
# Returns all explicit-only CGSN v1.0.0 status identifiers.
|
|
102
110
|
#
|
|
103
|
-
#
|
|
104
|
-
#
|
|
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.
|
|
108
|
-
#
|
|
109
|
-
|
|
110
|
-
|
|
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
|
-
#
|
|
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
|
-
# @
|
|
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.
|
|
123
|
-
#
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
#
|
|
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
|
-
# @
|
|
149
|
+
# @note Returns false for non-String inputs and unknown identifiers.
|
|
131
150
|
#
|
|
132
151
|
# @example
|
|
133
|
-
# Sashite::Cgsn.
|
|
134
|
-
#
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
#
|
|
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
|
-
# @
|
|
167
|
+
# @note Returns false for non-String inputs and unknown identifiers.
|
|
142
168
|
#
|
|
143
169
|
# @example
|
|
144
|
-
# Sashite::Cgsn.
|
|
145
|
-
# # =>
|
|
146
|
-
|
|
147
|
-
|
|
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.
|
|
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,
|
|
17
|
-
|
|
18
|
-
constraints (
|
|
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
|
data/lib/sashite/cgsn/status.rb
DELETED
|
@@ -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
|