# Sashite.Pin
[](https://hex.pm/packages/sashite_pin)
[](https://hexdocs.pm/sashite_pin)
[](https://github.com/sashite/pin.ex/blob/main/LICENSE.md)
> **PIN** (Piece Identifier Notation) implementation for Elixir.
## What is PIN?
PIN (Piece Identifier Notation) provides an ASCII-based format for representing pieces in abstract strategy board games. PIN translates piece attributes from the [Game Protocol](https://sashite.dev/game-protocol/) into a compact, portable notation system.
This library implements the [PIN Specification v1.0.0](https://sashite.dev/specs/pin/1.0.0/).
## Installation
Add `sashite_pin` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:sashite_pin, "~> 1.0"}
]
end
```
## Usage
```elixir
# Parse PIN strings
{:ok, pin} = Sashite.Pin.parse("K")
pin.type # => :K
pin.side # => :first
pin.state # => :normal
pin.terminal # => false
Sashite.Pin.to_string(pin) # => "K"
# Parse with pattern matching
{:ok, king} = Sashite.Pin.parse("K^") # Terminal king
{:ok, rook} = Sashite.Pin.parse("+R") # Enhanced rook
{:ok, pawn} = Sashite.Pin.parse("-p") # Diminished second player pawn
# Bang version for direct access
pin = Sashite.Pin.parse!("K")
# Create identifiers directly
pin = Sashite.Pin.new(:K, :first)
pin = Sashite.Pin.new(:K, :first, :enhanced)
pin = Sashite.Pin.new(:K, :first, :normal, terminal: true)
# Validation
Sashite.Pin.valid?("K") # => true
Sashite.Pin.valid?("+R") # => true
Sashite.Pin.valid?("K^") # => true
Sashite.Pin.valid?("invalid") # => false
# State transformations (return new structs)
enhanced = Sashite.Pin.enhance(pin)
Sashite.Pin.to_string(enhanced) # => "+K"
diminished = Sashite.Pin.diminish(pin)
Sashite.Pin.to_string(diminished) # => "-K"
normalized = Sashite.Pin.normalize(enhanced)
Sashite.Pin.to_string(normalized) # => "K"
# Side transformation
flipped = Sashite.Pin.flip(pin)
Sashite.Pin.to_string(flipped) # => "k"
# Terminal transformations
terminal = Sashite.Pin.mark_terminal(pin)
Sashite.Pin.to_string(terminal) # => "K^"
non_terminal = Sashite.Pin.unmark_terminal(terminal)
Sashite.Pin.to_string(non_terminal) # => "K"
# Type transformation
queen = Sashite.Pin.with_type(pin, :Q)
Sashite.Pin.to_string(queen) # => "Q"
# State queries
Sashite.Pin.normal?(pin) # => true
Sashite.Pin.enhanced?(enhanced) # => true
Sashite.Pin.diminished?(diminished) # => true
# Side queries
Sashite.Pin.first_player?(pin) # => true
Sashite.Pin.second_player?(flipped) # => true
# Terminal queries
Sashite.Pin.terminal?(terminal) # => true
# Comparison
king1 = Sashite.Pin.parse!("K")
king2 = Sashite.Pin.parse!("k")
Sashite.Pin.same_type?(king1, king2) # => true
Sashite.Pin.same_side?(king1, king2) # => false
```
## Format Specification
### Structure
```
[<state-modifier>]<letter>[<terminal-marker>]
```
### Components
| Component | Values | Description |
|-----------|--------|-------------|
| Letter | `A-Z`, `a-z` | Piece type and side |
| State Modifier | `+`, `-`, (none) | Enhanced, diminished, or normal |
| Terminal Marker | `^`, (none) | Terminal piece or not |
### Side Convention
- **Uppercase** (`A-Z`): First player
- **Lowercase** (`a-z`): Second player
### Examples
| PIN | Side | State | Terminal | Description |
|-----|------|-------|----------|-------------|
| `K` | First | Normal | No | Standard king |
| `K^` | First | Normal | Yes | Terminal king |
| `+R` | First | Enhanced | No | Promoted rook |
| `-p` | Second | Diminished | No | Weakened pawn |
| `+K^` | First | Enhanced | Yes | Enhanced terminal king |
## API Reference
### Parsing
```elixir
Sashite.Pin.parse(pin_string) # => {:ok, %Sashite.Pin{}} | {:error, reason}
Sashite.Pin.parse!(pin_string) # => %Sashite.Pin{} | raises ArgumentError
Sashite.Pin.valid?(pin_string) # => boolean
```
### Creation
```elixir
Sashite.Pin.new(type, side)
Sashite.Pin.new(type, side, state)
Sashite.Pin.new(type, side, state, terminal: boolean)
```
### Conversion
```elixir
Sashite.Pin.to_string(pin) # => String.t()
```
### Transformations
All transformations return new `%Sashite.Pin{}` structs:
```elixir
# State
Sashite.Pin.enhance(pin)
Sashite.Pin.diminish(pin)
Sashite.Pin.normalize(pin)
# Side
Sashite.Pin.flip(pin)
# Terminal
Sashite.Pin.mark_terminal(pin)
Sashite.Pin.unmark_terminal(pin)
# Attribute changes
Sashite.Pin.with_type(pin, new_type)
Sashite.Pin.with_side(pin, new_side)
Sashite.Pin.with_state(pin, new_state)
Sashite.Pin.with_terminal(pin, boolean)
```
### Queries
```elixir
# State
Sashite.Pin.normal?(pin)
Sashite.Pin.enhanced?(pin)
Sashite.Pin.diminished?(pin)
# Side
Sashite.Pin.first_player?(pin)
Sashite.Pin.second_player?(pin)
# Terminal
Sashite.Pin.terminal?(pin)
# Comparison
Sashite.Pin.same_type?(pin1, pin2)
Sashite.Pin.same_side?(pin1, pin2)
Sashite.Pin.same_state?(pin1, pin2)
Sashite.Pin.same_terminal?(pin1, pin2)
```
## Data Structure
```elixir
%Sashite.Pin{
type: :A..:Z, # Piece type (always uppercase atom)
side: :first | :second, # Player side
state: :normal | :enhanced | :diminished,
terminal: boolean()
}
```
## Protocol Mapping
Following the [Game Protocol](https://sashite.dev/game-protocol/):
| Protocol Attribute | PIN Encoding |
|-------------------|--------------|
| Piece Name | ASCII letter choice |
| Piece Side | Letter case |
| Piece State | Optional prefix (`+`/`-`) |
| Terminal Status | Optional suffix (`^`) |
## Related Specifications
- [Game Protocol](https://sashite.dev/game-protocol/) — Conceptual foundation
- [PNN](https://sashite.dev/specs/pnn/) — Piece Name Notation
- [PIN Specification](https://sashite.dev/specs/pin/1.0.0/) — Official specification
## License
Available as open source under the [MIT License](https://opensource.org/licenses/MIT).
## About
Maintained by [Sashité](https://sashite.com/) — promoting chess variants and sharing the beauty of board game cultures.