sashite-cell 1.0.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 +7 -0
- data/LICENSE.md +22 -0
- data/README.md +351 -0
- data/lib/sashite/cell/location/hand_char.rb +16 -0
- data/lib/sashite/cell/location.rb +136 -0
- data/lib/sashite/cell.rb +61 -0
- data/lib/sashite-cell.rb +15 -0
- metadata +54 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1071f1a4bf4e1d9f6893185fe61fc25a361ca97ba8e9d74e3e72f2fba1300362
|
4
|
+
data.tar.gz: 2b723da1c614caed08b87bbb8eb382d484a5cc0e915ab6ed7c87949196322ded
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 86c6f48a5c77440ddfe886b6c7da0e8871149af862164b7fc060dd07002afa18e69bffc0f897f1de392ecbf7bcc2507786903b326513b6241251f3be20638c81
|
7
|
+
data.tar.gz: 37dd7540c541a6aaee7d8a29ff8e6eb03119dabdc6c0c0f21cd63fdcb8ed59ff2d80d74b479a9b9a8e6cbb84cb8dbd981ed2492cd48c2c07e3fe383a917a5a8f
|
data/LICENSE.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2025 Sashite
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,351 @@
|
|
1
|
+
# Cell.rb
|
2
|
+
|
3
|
+
[](https://github.com/sashite/cell.rb/tags)
|
4
|
+
[](https://rubydoc.info/github/sashite/cell.rb/main)
|
5
|
+

|
6
|
+
[](https://github.com/sashite/cell.rb/raw/main/LICENSE.md)
|
7
|
+
|
8
|
+
> **CELL** (Coordinate Expression Location Label) support for the Ruby language.
|
9
|
+
|
10
|
+
## What is CELL?
|
11
|
+
|
12
|
+
CELL (Coordinate Expression Location Label) defines a consistent and rule-agnostic format for representing locations in abstract strategy board games. CELL provides a standardized way to identify positions on game boards and pieces held in hand/reserve, establishing a common foundation for location reference across the Sashité notation ecosystem.
|
13
|
+
|
14
|
+
This gem implements the [CELL Specification v1.0.0](https://sashite.dev/documents/cell/1.0.0/), providing a Ruby interface for working with game locations through a clean and simple API that serves as a foundational building block for other Sashité specifications.
|
15
|
+
|
16
|
+
## Installation
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
# In your Gemfile
|
20
|
+
gem "sashite-cell"
|
21
|
+
```
|
22
|
+
|
23
|
+
Or install manually:
|
24
|
+
|
25
|
+
```sh
|
26
|
+
gem install sashite-cell
|
27
|
+
```
|
28
|
+
|
29
|
+
## CELL Format
|
30
|
+
|
31
|
+
A CELL location is represented by a single string following one of two patterns:
|
32
|
+
|
33
|
+
### Board Coordinates
|
34
|
+
|
35
|
+
Any non-empty string containing only alphanumeric characters (`a-z`, `A-Z`, `0-9`):
|
36
|
+
|
37
|
+
```
|
38
|
+
e4 # Chess notation
|
39
|
+
5c # Shōgi notation
|
40
|
+
A3a # 3D coordinate
|
41
|
+
center # Custom coordinate
|
42
|
+
```
|
43
|
+
|
44
|
+
### Hand/Reserve Location
|
45
|
+
|
46
|
+
The reserved character `*` represents pieces held off-board:
|
47
|
+
```
|
48
|
+
* # Hand/reserve location
|
49
|
+
```
|
50
|
+
|
51
|
+
## Basic Usage
|
52
|
+
|
53
|
+
### Creating Location Objects
|
54
|
+
|
55
|
+
The primary interface is the `Sashite::Cell::Location` class, which represents a game location in CELL format:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
require "sashite/cell"
|
59
|
+
|
60
|
+
# Parse CELL strings into location objects
|
61
|
+
board_pos = Sashite::Cell::Location.parse("e4")
|
62
|
+
# => #<Sashite::Cell::Location:0x... @coordinate="e4">
|
63
|
+
|
64
|
+
hand_pos = Sashite::Cell::Location.parse("*")
|
65
|
+
# => #<Sashite::Cell::Location:0x... @coordinate="*">
|
66
|
+
|
67
|
+
# Create directly with constructor
|
68
|
+
location = Sashite::Cell::Location.new("e4")
|
69
|
+
hand = Sashite::Cell::Location.new("*")
|
70
|
+
|
71
|
+
# Convenience method
|
72
|
+
location = Sashite::Cell.location("e4")
|
73
|
+
```
|
74
|
+
|
75
|
+
### Converting to CELL String
|
76
|
+
|
77
|
+
Convert a location object back to its CELL string representation:
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
location = Sashite::Cell::Location.parse("e4")
|
81
|
+
location.to_s
|
82
|
+
# => "e4"
|
83
|
+
|
84
|
+
hand = Sashite::Cell::Location.parse("*")
|
85
|
+
hand.to_s
|
86
|
+
# => "*"
|
87
|
+
```
|
88
|
+
|
89
|
+
### Checking Location Types
|
90
|
+
|
91
|
+
Distinguish between board coordinates and hand/reserve locations:
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
board_loc = Sashite::Cell::Location.parse("e4")
|
95
|
+
hand_loc = Sashite::Cell::Location.parse("*")
|
96
|
+
|
97
|
+
board_loc.board? # => true
|
98
|
+
board_loc.hand? # => false
|
99
|
+
|
100
|
+
hand_loc.board? # => false
|
101
|
+
hand_loc.hand? # => true
|
102
|
+
```
|
103
|
+
|
104
|
+
## Game-Specific Examples
|
105
|
+
|
106
|
+
### Chess
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
# Standard chess coordinates
|
110
|
+
locations = %w[a1 e4 h8].map { |coord| Sashite::Cell::Location.parse(coord) }
|
111
|
+
|
112
|
+
# Check if valid chess square
|
113
|
+
def valid_chess_square?(location)
|
114
|
+
return false unless location.board?
|
115
|
+
|
116
|
+
coord = location.to_s
|
117
|
+
coord.length == 2 &&
|
118
|
+
coord[0].between?("a", "h") &&
|
119
|
+
coord[1].between?("1", "8")
|
120
|
+
end
|
121
|
+
|
122
|
+
valid_chess_square?(Sashite::Cell::Location.parse("e4")) # => true
|
123
|
+
valid_chess_square?(Sashite::Cell::Location.parse("z9")) # => false
|
124
|
+
```
|
125
|
+
|
126
|
+
### Shōgi
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
# Shōgi board coordinates and hand
|
130
|
+
board_positions = %w[9a 5e 1i].map { |coord| Sashite::Cell::Location.parse(coord) }
|
131
|
+
hand_position = Sashite::Cell::Location.parse("*")
|
132
|
+
|
133
|
+
# Group by location type
|
134
|
+
positions = board_positions + [hand_position]
|
135
|
+
grouped = positions.group_by(&:hand?)
|
136
|
+
# => {false => [board positions], true => [hand position]}
|
137
|
+
```
|
138
|
+
|
139
|
+
### Go
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
# Go coordinates (traditional notation)
|
143
|
+
go_positions = %w[A1 T19 K10].map { |coord| Sashite::Cell::Location.parse(coord) }
|
144
|
+
|
145
|
+
# Custom validation for Go board
|
146
|
+
def valid_go_position?(location, board_size = 19)
|
147
|
+
return false unless location.board?
|
148
|
+
|
149
|
+
coord = location.to_s
|
150
|
+
return false unless [2, 3].include?(coord.length)
|
151
|
+
|
152
|
+
letter = coord[0]
|
153
|
+
number = coord[1..].to_i
|
154
|
+
|
155
|
+
letter.between?("A", ("A".ord + board_size - 1).chr) &&
|
156
|
+
number.between?(1, board_size)
|
157
|
+
end
|
158
|
+
```
|
159
|
+
|
160
|
+
### Custom Coordinate Systems
|
161
|
+
|
162
|
+
```ruby
|
163
|
+
# 3D chess coordinates
|
164
|
+
location_3d = Sashite::Cell::Location.parse("A3a")
|
165
|
+
|
166
|
+
# Named locations
|
167
|
+
center = Sashite::Cell::Location.parse("center")
|
168
|
+
corner = Sashite::Cell::Location.parse("NE")
|
169
|
+
|
170
|
+
# Hexagonal coordinates
|
171
|
+
hex_coord = Sashite::Cell::Location.parse("Q3R7")
|
172
|
+
```
|
173
|
+
|
174
|
+
## Advanced Usage
|
175
|
+
|
176
|
+
### Working with Collections
|
177
|
+
|
178
|
+
```ruby
|
179
|
+
# Mix of board and hand locations
|
180
|
+
locations = [
|
181
|
+
Sashite::Cell::Location.parse("e4"),
|
182
|
+
Sashite::Cell::Location.parse("d5"),
|
183
|
+
Sashite::Cell::Location.parse("*"),
|
184
|
+
Sashite::Cell::Location.parse("a1")
|
185
|
+
]
|
186
|
+
|
187
|
+
# Separate board from hand locations
|
188
|
+
board_locations = locations.select(&:board?)
|
189
|
+
hand_locations = locations.select(&:hand?)
|
190
|
+
|
191
|
+
# Convert collection to strings
|
192
|
+
coordinates = locations.map(&:to_s)
|
193
|
+
# => ["e4", "d5", "*", "a1"]
|
194
|
+
```
|
195
|
+
|
196
|
+
### Game State Representation
|
197
|
+
|
198
|
+
```ruby
|
199
|
+
# Represent piece positions
|
200
|
+
piece_locations = {
|
201
|
+
"white_king" => Sashite::Cell::Location.parse("e1"),
|
202
|
+
"black_king" => Sashite::Cell::Location.parse("e8"),
|
203
|
+
"white_rook" => Sashite::Cell::Location.parse("a1"),
|
204
|
+
"captured_pieces" => Sashite::Cell::Location.parse("*")
|
205
|
+
}
|
206
|
+
|
207
|
+
# Find pieces on specific ranks/files
|
208
|
+
def pieces_on_file(locations, file)
|
209
|
+
locations.select do |piece, location|
|
210
|
+
location.board? && location.to_s.start_with?(file)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
e_file_pieces = pieces_on_file(piece_locations, "e")
|
215
|
+
```
|
216
|
+
|
217
|
+
### Validation and Error Handling
|
218
|
+
|
219
|
+
```ruby
|
220
|
+
# Check validity before parsing
|
221
|
+
Sashite::Cell.valid?("e4") # => true
|
222
|
+
Sashite::Cell.valid?("*") # => true
|
223
|
+
Sashite::Cell.valid?("") # => false
|
224
|
+
Sashite::Cell.valid?("e-4") # => false
|
225
|
+
Sashite::Cell.valid?("@") # => false
|
226
|
+
|
227
|
+
# Safe parsing
|
228
|
+
def safe_parse(coord_string)
|
229
|
+
return nil unless Sashite::Cell.valid?(coord_string)
|
230
|
+
|
231
|
+
Sashite::Cell::Location.parse(coord_string)
|
232
|
+
rescue ArgumentError
|
233
|
+
nil
|
234
|
+
end
|
235
|
+
|
236
|
+
# Invalid coordinates raise ArgumentError
|
237
|
+
begin
|
238
|
+
Sashite::Cell::Location.parse("")
|
239
|
+
rescue ArgumentError => e
|
240
|
+
puts "Invalid coordinate: #{e.message}"
|
241
|
+
end
|
242
|
+
```
|
243
|
+
|
244
|
+
### Integration with Other Notations
|
245
|
+
|
246
|
+
```ruby
|
247
|
+
# CELL serves as foundation for move notation
|
248
|
+
class SimpleMove
|
249
|
+
def initialize(from, to)
|
250
|
+
@from = Sashite::Cell::Location.parse(from)
|
251
|
+
@to = Sashite::Cell::Location.parse(to)
|
252
|
+
end
|
253
|
+
|
254
|
+
def from_board?
|
255
|
+
@from.board?
|
256
|
+
end
|
257
|
+
|
258
|
+
def to_board?
|
259
|
+
@to.board?
|
260
|
+
end
|
261
|
+
|
262
|
+
def drop_move?
|
263
|
+
@from.hand? && @to.board?
|
264
|
+
end
|
265
|
+
|
266
|
+
def capture_move?
|
267
|
+
@from.board? && @to.board?
|
268
|
+
end
|
269
|
+
|
270
|
+
def to_s
|
271
|
+
"#{@from}→#{@to}"
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
# Usage
|
276
|
+
move = SimpleMove.new("e4", "e5") # Normal move
|
277
|
+
drop = SimpleMove.new("*", "e4") # Drop from hand
|
278
|
+
```
|
279
|
+
|
280
|
+
## API Reference
|
281
|
+
|
282
|
+
### Module Methods
|
283
|
+
|
284
|
+
- `Sashite::Cell.valid?(cell_string)` - Check if a string is valid CELL notation
|
285
|
+
- `Sashite::Cell.location(coordinate)` - Convenience method to create locations
|
286
|
+
|
287
|
+
### Sashite::Cell::Location Class Methods
|
288
|
+
|
289
|
+
- `Sashite::Cell::Location.parse(cell_string)` - Parse a CELL string into a location object
|
290
|
+
- `Sashite::Cell::Location.new(coordinate)` - Create a new location instance
|
291
|
+
|
292
|
+
### Instance Methods
|
293
|
+
|
294
|
+
#### Type Checking
|
295
|
+
- `#board?` - Check if location represents a board coordinate
|
296
|
+
- `#hand?` - Check if location represents hand/reserve
|
297
|
+
|
298
|
+
#### Conversion
|
299
|
+
- `#to_s` - Convert to CELL string representation
|
300
|
+
- `#inspect` - Detailed string representation for debugging
|
301
|
+
|
302
|
+
#### Comparison
|
303
|
+
- `#==` - Compare locations for equality
|
304
|
+
- `#eql?` - Strict equality comparison
|
305
|
+
- `#hash` - Hash value for use in collections
|
306
|
+
|
307
|
+
## Properties of CELL
|
308
|
+
|
309
|
+
* **Rule-agnostic**: CELL does not encode game states, movement rules, or game-specific conditions
|
310
|
+
* **Universal location identification**: Supports both board positions and hand/reserve areas
|
311
|
+
* **Canonical representation**: Equivalent locations yield identical strings
|
312
|
+
* **Arbitrary coordinate systems**: Flexible format supports any alphanumeric coordinate system
|
313
|
+
* **Foundational specification**: Serves as building block for other Sashité notations
|
314
|
+
|
315
|
+
## Constraints
|
316
|
+
|
317
|
+
* Board coordinates must contain only alphanumeric characters (`a-z`, `A-Z`, `0-9`)
|
318
|
+
* Board coordinates must be non-empty strings
|
319
|
+
* Hand/reserve locations must be exactly the character `*`
|
320
|
+
* No other characters or formats are permitted
|
321
|
+
|
322
|
+
## Use Cases
|
323
|
+
|
324
|
+
CELL is particularly useful in the following scenarios:
|
325
|
+
|
326
|
+
1. **Move notation systems**: As coordinate foundation for MIN, PMN, and GGN specifications
|
327
|
+
2. **Game engine development**: When implementing position tracking across different board layouts
|
328
|
+
3. **Board representation**: When storing piece positions in databases or memory structures
|
329
|
+
4. **Cross-game compatibility**: When building systems that work with multiple game types
|
330
|
+
5. **Position analysis**: When comparing locations across different coordinate systems
|
331
|
+
6. **User interface development**: When translating between display coordinates and logical positions
|
332
|
+
|
333
|
+
## Dependencies
|
334
|
+
|
335
|
+
This gem has no external dependencies beyond Ruby standard library.
|
336
|
+
|
337
|
+
## Specification
|
338
|
+
|
339
|
+
- [CELL Specification](https://sashite.dev/documents/cell/1.0.0/)
|
340
|
+
|
341
|
+
## Documentation
|
342
|
+
|
343
|
+
- [CELL Documentation](https://rubydoc.info/github/sashite/cell.rb/main)
|
344
|
+
|
345
|
+
## License
|
346
|
+
|
347
|
+
The [gem](https://rubygems.org/gems/sashite-cell) is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
348
|
+
|
349
|
+
## About Sashité
|
350
|
+
|
351
|
+
This project is maintained by [Sashité](https://sashite.com/) — promoting chess variants and sharing the beauty of Chinese, Japanese, and Western chess cultures.
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sashite
|
4
|
+
module Cell
|
5
|
+
class Location
|
6
|
+
# Character representing hand/reserve location in CELL notation
|
7
|
+
#
|
8
|
+
# This character is used to identify pieces held off-board in a player's
|
9
|
+
# hand or reserve, as opposed to pieces positioned on the game board.
|
10
|
+
#
|
11
|
+
# @return [String] the hand/reserve character
|
12
|
+
# @see https://sashite.dev/documents/cell/1.0.0/ CELL Specification v1.0.0
|
13
|
+
HAND_CHAR = "*"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "location/hand_char"
|
4
|
+
|
5
|
+
module Sashite
|
6
|
+
module Cell
|
7
|
+
# Represents a game location in CELL format
|
8
|
+
#
|
9
|
+
# A Location object encapsulates either a board coordinate (alphanumeric string)
|
10
|
+
# or a hand/reserve location (the "*" character). This class provides methods
|
11
|
+
# to distinguish between location types and convert to string representation.
|
12
|
+
#
|
13
|
+
# @see https://sashite.dev/documents/cell/1.0.0/ CELL Specification v1.0.0
|
14
|
+
class Location
|
15
|
+
# The coordinate string for this location
|
16
|
+
# @return [String] the coordinate in CELL format
|
17
|
+
attr_reader :coordinate
|
18
|
+
|
19
|
+
# Create a new Location object
|
20
|
+
#
|
21
|
+
# @param coordinate [String] the coordinate string in CELL format
|
22
|
+
# @raise [ArgumentError] if the coordinate is not valid CELL notation
|
23
|
+
#
|
24
|
+
# @example Create board locations
|
25
|
+
# Location.new("e4") # Chess square
|
26
|
+
# Location.new("5c") # Shōgi square
|
27
|
+
# Location.new("A3a") # 3D coordinate
|
28
|
+
# Location.new("center") # Custom coordinate
|
29
|
+
#
|
30
|
+
# @example Create hand/reserve location
|
31
|
+
# Location.new("*") # Hand/reserve
|
32
|
+
def initialize(coordinate)
|
33
|
+
raise ::ArgumentError, "Invalid CELL coordinate: #{coordinate.inspect}" unless Sashite::Cell.valid?(coordinate)
|
34
|
+
|
35
|
+
@coordinate = coordinate.freeze
|
36
|
+
|
37
|
+
freeze
|
38
|
+
end
|
39
|
+
|
40
|
+
# Parse a CELL string into a Location object
|
41
|
+
#
|
42
|
+
# @param cell_string [String] the CELL string to parse
|
43
|
+
# @return [Location] a new Location object
|
44
|
+
# @raise [ArgumentError] if the string is not valid CELL notation
|
45
|
+
#
|
46
|
+
# @example
|
47
|
+
# location = Location.parse("e4")
|
48
|
+
# hand = Location.parse("*")
|
49
|
+
def self.parse(cell_string)
|
50
|
+
new(cell_string)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Check if this location represents a board coordinate
|
54
|
+
#
|
55
|
+
# @return [Boolean] true if this is a board coordinate, false if hand/reserve
|
56
|
+
#
|
57
|
+
# @example
|
58
|
+
# Location.new("e4").board? # => true
|
59
|
+
# Location.new("*").board? # => false
|
60
|
+
def board?
|
61
|
+
@coordinate != HAND_CHAR
|
62
|
+
end
|
63
|
+
|
64
|
+
# Check if this location represents a hand/reserve location
|
65
|
+
#
|
66
|
+
# @return [Boolean] true if this is hand/reserve, false if board coordinate
|
67
|
+
#
|
68
|
+
# @example
|
69
|
+
# Location.new("e4").hand? # => false
|
70
|
+
# Location.new("*").hand? # => true
|
71
|
+
def hand?
|
72
|
+
@coordinate == HAND_CHAR
|
73
|
+
end
|
74
|
+
|
75
|
+
# Convert to CELL string representation
|
76
|
+
#
|
77
|
+
# @return [String] the coordinate in CELL format
|
78
|
+
#
|
79
|
+
# @example
|
80
|
+
# Location.new("e4").to_s # => "e4"
|
81
|
+
# Location.new("*").to_s # => "*"
|
82
|
+
def to_s
|
83
|
+
@coordinate
|
84
|
+
end
|
85
|
+
|
86
|
+
# Detailed string representation for debugging
|
87
|
+
#
|
88
|
+
# @return [String] detailed representation showing class and coordinate
|
89
|
+
#
|
90
|
+
# @example
|
91
|
+
# Location.new("e4").inspect
|
92
|
+
# # => "#<Sashite::Cell::Location:0x... @coordinate=\"e4\">"
|
93
|
+
def inspect
|
94
|
+
"#<#{self.class}:0x#{object_id.to_s(16)} @coordinate=#{@coordinate.inspect}>"
|
95
|
+
end
|
96
|
+
|
97
|
+
# Compare locations for equality
|
98
|
+
#
|
99
|
+
# Two locations are equal if they have the same coordinate string.
|
100
|
+
#
|
101
|
+
# @param other [Object] the object to compare with
|
102
|
+
# @return [Boolean] true if locations are equal
|
103
|
+
#
|
104
|
+
# @example
|
105
|
+
# loc1 = Location.new("e4")
|
106
|
+
# loc2 = Location.new("e4")
|
107
|
+
# loc1 == loc2 # => true
|
108
|
+
def ==(other)
|
109
|
+
other.is_a?(Location) && @coordinate == other.coordinate
|
110
|
+
end
|
111
|
+
|
112
|
+
# Strict equality comparison
|
113
|
+
#
|
114
|
+
# @param other [Object] the object to compare with
|
115
|
+
# @return [Boolean] true if objects are equal
|
116
|
+
def eql?(other)
|
117
|
+
self == other
|
118
|
+
end
|
119
|
+
|
120
|
+
# Hash value for use in collections
|
121
|
+
#
|
122
|
+
# Ensures that equal locations have the same hash value.
|
123
|
+
#
|
124
|
+
# @return [Integer] hash value based on coordinate
|
125
|
+
#
|
126
|
+
# @example
|
127
|
+
# locations = Set.new
|
128
|
+
# locations << Location.new("e4")
|
129
|
+
# locations << Location.new("e4") # Won't be added (same hash)
|
130
|
+
# locations.size # => 1
|
131
|
+
def hash
|
132
|
+
[self.class, @coordinate].hash
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
data/lib/sashite/cell.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "cell/location"
|
4
|
+
|
5
|
+
# Sashité module providing implementations of various game notation specifications
|
6
|
+
#
|
7
|
+
# @see https://sashite.com/ Sashité
|
8
|
+
module Sashite
|
9
|
+
# CELL (Coordinate Expression Location Label) implementation
|
10
|
+
#
|
11
|
+
# CELL defines a consistent and rule-agnostic format for representing locations
|
12
|
+
# in abstract strategy board games. CELL provides a standardized way to identify
|
13
|
+
# positions on game boards and pieces held in hand/reserve.
|
14
|
+
#
|
15
|
+
# @see https://sashite.dev/documents/cell/1.0.0/ CELL Specification v1.0.0
|
16
|
+
module Cell
|
17
|
+
# Regular expression for validating CELL notation
|
18
|
+
#
|
19
|
+
# Matches either:
|
20
|
+
# - Hand/reserve location: exactly "*"
|
21
|
+
# - Board coordinate: one or more alphanumeric characters [a-zA-Z0-9]
|
22
|
+
#
|
23
|
+
# @return [Regexp] the validation pattern
|
24
|
+
CELL_PATTERN = /\A(#{::Regexp.escape(Location::HAND_CHAR)}|[a-zA-Z0-9]+)\z/
|
25
|
+
|
26
|
+
# Check if a string is valid CELL notation
|
27
|
+
#
|
28
|
+
# @param cell_string [String] the string to validate
|
29
|
+
# @return [Boolean] true if valid CELL notation, false otherwise
|
30
|
+
#
|
31
|
+
# @example Valid CELL strings
|
32
|
+
# Sashite::Cell.valid?("e4") # => true
|
33
|
+
# Sashite::Cell.valid?("*") # => true
|
34
|
+
# Sashite::Cell.valid?("A3a") # => true
|
35
|
+
# Sashite::Cell.valid?("center") # => true
|
36
|
+
#
|
37
|
+
# @example Invalid CELL strings
|
38
|
+
# Sashite::Cell.valid?("") # => false
|
39
|
+
# Sashite::Cell.valid?("e-4") # => false
|
40
|
+
# Sashite::Cell.valid?("@") # => false
|
41
|
+
# Sashite::Cell.valid?("e4!") # => false
|
42
|
+
def self.valid?(cell_string)
|
43
|
+
return false unless cell_string.is_a?(::String)
|
44
|
+
|
45
|
+
CELL_PATTERN.match?(cell_string)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Convenience method to create a Location object
|
49
|
+
#
|
50
|
+
# @param coordinate [String] the coordinate string in CELL format
|
51
|
+
# @return [Location] a new Location object
|
52
|
+
# @raise [ArgumentError] if the coordinate is invalid
|
53
|
+
#
|
54
|
+
# @example
|
55
|
+
# location = Sashite::Cell.location("e4")
|
56
|
+
# hand = Sashite::Cell.location("*")
|
57
|
+
def self.location(coordinate)
|
58
|
+
Location.new(coordinate)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/sashite-cell.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Sashité namespace for board game notation libraries
|
4
|
+
module Sashite
|
5
|
+
# Coordinate Expression Location Label (CELL) implementation for Ruby
|
6
|
+
#
|
7
|
+
# CELL defines a consistent and rule-agnostic format for representing locations
|
8
|
+
# in abstract strategy board games. CELL provides a standardized way to identify
|
9
|
+
# positions on game boards and pieces held in hand/reserve, establishing a
|
10
|
+
# common foundation for location reference across the Sashité notation ecosystem.
|
11
|
+
#
|
12
|
+
# @see https://sashite.dev/documents/cell/1.0.0/ CELL Specification v1.0.0
|
13
|
+
end
|
14
|
+
|
15
|
+
require_relative "sashite/cell"
|
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sashite-cell
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Cyril Kato
|
8
|
+
bindir: bin
|
9
|
+
cert_chain: []
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
|
+
dependencies: []
|
12
|
+
description: CELL defines a consistent and rule-agnostic format for representing locations
|
13
|
+
in abstract strategy board games. This gem provides a Ruby interface for working
|
14
|
+
with game locations, serving as a foundational building block for the Sashité notation
|
15
|
+
ecosystem.
|
16
|
+
email: contact@cyril.email
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- LICENSE.md
|
22
|
+
- README.md
|
23
|
+
- lib/sashite-cell.rb
|
24
|
+
- lib/sashite/cell.rb
|
25
|
+
- lib/sashite/cell/location.rb
|
26
|
+
- lib/sashite/cell/location/hand_char.rb
|
27
|
+
homepage: https://github.com/sashite/cell.rb
|
28
|
+
licenses:
|
29
|
+
- MIT
|
30
|
+
metadata:
|
31
|
+
bug_tracker_uri: https://github.com/sashite/cell.rb/issues
|
32
|
+
documentation_uri: https://rubydoc.info/github/sashite/cell.rb/main
|
33
|
+
homepage_uri: https://github.com/sashite/cell.rb
|
34
|
+
source_code_uri: https://github.com/sashite/cell.rb
|
35
|
+
specification_uri: https://sashite.dev/documents/cell/1.0.0/
|
36
|
+
rubygems_mfa_required: 'true'
|
37
|
+
rdoc_options: []
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 3.2.0
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
requirements: []
|
51
|
+
rubygems_version: 3.6.7
|
52
|
+
specification_version: 4
|
53
|
+
summary: CELL (Coordinate Expression Location Label) implementation for Ruby
|
54
|
+
test_files: []
|