hexchess 2.0.0

A Rust / TypeScript library for Gliński's hexagonal chess, and the brain of hexchess.club
Documentation
# [`@bedard/hexchess`]https://github.com/scottbedard/hexchess

[![Build](https://github.com/scottbedard/hexchess/actions/workflows/build.yml/badge.svg)](https://github.com/scottbedard/hexchess/actions/workflows/build.yml)
[![Coverage](https://codecov.io/gh/scottbedard/hexchess/graph/badge.svg?token=uHmFqhQDps)](https://codecov.io/gh/scottbedard/hexchess)
[![Crates.io](https://img.shields.io/crates/v/hexchess?logo=rust&logoColor=%23f74c00&label=cargo)](https://crates.io/crates/hexchess)
[![NPM](https://img.shields.io/npm/v/%40bedard%2Fhexchess?logo=javascript&logoColor=%23f7df1e)](https://www.npmjs.com/package/@bedard/hexchess)
[![Bundlephobia](https://img.shields.io/bundlephobia/minzip/%40bedard%2Fhexchess?label=size)](https://bundlephobia.com/package/@bedard/hexchess)
[![License](https://img.shields.io/badge/license-MIT-blue)](https://github.com/scottbedard/hexchess/blob/main/LICENSE)

A Rust / TypeScript library for [Gliński's hexagonal chess](https://en.wikipedia.org/wiki/Hexagonal_chess#Gli%C5%84ski's_hexagonal_chess), and the brain of [hexchess.club](https://hexchess.club).

<p align="center">
  <a href="https://hexchess.club">
    <img src="assets/hexchess.svg" width="500" />
  </a>
</p>

## Installation

Install this package via NPM.

> Depending on your bundler and target, you may need plugins for [Web Assembly]https://developer.mozilla.org/en-US/docs/WebAssembly and [top-level await]https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await#top_level_await to utilize WASM bindings.

```
npm install @bedard/hexchess

pnpm install @bedard/hexchess

yarn add @bedard/hexchess
```

This JaveScript portions of this library may also be accessed using a CDN.

```html
<script src="https://unpkg.com/@bedard/hexchess"></script>
```

[View source &rarr;](https://unpkg.com/@bedard/hexchess)

## Basic usage

The `Hexchess` class is a deserialized version of [Forsyth–Edwards Notation](https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation). It contains the board state, current turn, en passant, and move numbers. Since castling is not a part of hexagonal chess, that section is omitted. The board data is stored as an array of `Piece | null`, sorted in FEN-order.

To create a game at the starting position, use `Hexchess.init`.

```ts
import { Hexchess } from '@bedard/hexchess'

const hexchess = Hexchess.init()
```

`Hexchess` instances have the following shape. The `board` represents an array of position values, sorted in FEN-order.

```ts
{
  board: [
    'b',  'q',  'b',  'k',  'n',  null, 'b',  null, 'n',  'r',
    null, null, null, null, null, 'r',  'p',  'p',  'p',  'p',
    'p',  'p',  'p',  'p',  'p',  null, null, null, null, null,
    null, null, null, null, null, null, null, null, null, null,
    null, 'P',  null, null, null, null, null, null, null, null,
    null, 'P',  null, 'P',  null, null, null, null, null, null,
    null, 'P',  null, 'B',  null, 'P',  null, null, null, null,
    null, 'P',  null, null, 'B',  null, null, 'P',  null, null,
    null, 'P',  'R',  'N',  'Q',  'B',  'K',  'N',  'R',  'P',
    null
  ],
  turn: 'w',
  ep: null,
  halfmove: 0,
  fullmove: 1
}
```

The following methods are available for interacting with the game. A pair of constants named `initialPosition` and `positions` are available as well.

#### `apply`

Apply a whitespace separated sequence of moves.

```ts
const hexchess = Hexchess.init()

hexchess.apply('g4g5 e7e6 f5f6 e6f6')

hexchess.toString() // 'b/qbk/n1b1n/r5r/ppp1ppppp/5p5/6P4/4P6/3P1B1P3/2P2B2P2/1PRNQBKNRP1 w - 0 3'
```

#### `applyMove`

Apply a single move from `string` or `San`.

```ts
const hexchess = Hexchess.init()

hexchess.applyMove(San.parse('g4g6'))

hexchess.toString() // 'b/qbk/n1b1n/r5r/ppppppppp/11/5PP4/4P6/3P1B1P3/2P2B2P2/1PRNQBKNRP1 b - 0 1'
```

#### `applyMoveUnsafe`

Apply a single move from `string` or `San`, regardless of turn or legality.

```ts
const hexchess = Hexchess.init()

hexchess.applyMoveUnsafe('b1b6')

hexchess.toString() // 'b/qbk/n1b1n/r5r/ppppppppp/1P9/5P5/4P1P4/3P1B1P3/2P2B2P2/2RNQBKNRP1 b - 0 1'
```

#### `clone`

Deeply clone a `Hexchess` instance.

```ts
const hexchess = Hexchess.init()

const clone = hexchess.clone()

hexchess === clone // false
```

#### `currentMoves`

Get all current legal moves.

```ts
const hexchess = new Hexchess('1/3/5/7/9/11/5P5/11/11/11/11 w - 0 1')

const moves = hexchess.currentMoves()

moves.map(String) // ['f5f6, 'f5f7', ...]
```

#### `findKing`

Find FEN index for king belonging to `Color`.

```ts
const hexchess = Hexchess.init()

hexchess.findKing('b') // 3
hexchess.findKing('w') // 86
```

#### `get`

Get board value from position name.

```ts
const hexchess = Hexchess.init()

hexchess.get('e1') // 'Q'
```

#### `getColor`

Get all board indices occupied by `Color` pieces.

```ts
const hexchess = Hexchess.init()

hexchess.getColor('b') // [0,  1,  2,  ...]
```

#### `isCheck`

Test if the board is in check.

```ts
const hexchess = Hexchess.init()

isCheck(hexckess) // false
```

#### `isCheckmate`

Test if the game is in checkmate.

```ts
const hexchess = Hexchess.init()

isCheckmate(hexckess) // false
```

#### `isStalemate`

Test if the game is in stalemate.

```ts
const hexchess = Hexchess.init()

isStalemate(hexckess) // false
```

#### `movesFrom`

Get all legal moves from a position.

```ts
const hexchess = Hexchess.init()

const moves = hexchess.movesFrom('f6')

moves.map(String) // ['f6f7']
```

#### `movesFromUnsafe`

Get all moves from a position, including ones that result in self-check.

```ts
const hexchess = Hexchess.parse('1/3/5/7/4r4/5K5/11/11/11/11/11 w - 0 1')

const moves = hexchess.movesUnsafe()

moves.map(String) // ['f6f7', 'f6g7' ...]
```

#### `toString`

Serialize a `Hexchess` instance to string.

```ts
const hexchess = Hexchess.init()

hexchess.toString() // 'b/qbk/n1b1n/r5r/ppppppppp/11/5P5/4P1P4/3P1B1P3/2P2B2P2/1PRNQBKNRP1 w - 0 1'
```

## Wasm Bindings

The Rust crate for this library is exposed via WebAssembly. All APIs are the same as above, but with a functional syntax that accepts a `HexchessStruct`, and returns a new `HexchessStruct`.

```ts
import {
  apply,
  initHexchess,
  stringifyHexchess,
} from '@bedard/hexchess/wasm' // <- note the import path

const hexchess = apply(initHexchess(), 'g4g6 f7g6 f5f7 g6f6')

stringifyHexchess(hexchess) // 'b/qbk/n1b1n/r5r/pppp1pppp/5p5/11/4P6/3P1B1P3/2P2B2P2/1PRNQBKNRP1 w - 0 3'
```

A [native web target](https://rustwasm.github.io/docs/wasm-pack/commands/build.html#target) is also available at `@bedard/hexchess/wasm/web`.

Below are the available bindings,

- `apply`
- `applyMove`
- `applyMoveUnsafe`
- `createHexchess`
- `currentMoves`
- `findKing`
- `get`
- `initHexchess`
- `isCheck`
- `isCheckmate`
- `isStalemate`
- `movesFrom`
- `movesFromUnsafe`
- `parseHexchess`
- `parseSan`
- `stringifyHexchess`
- `stringifySan`

## License

[MIT](https://github.com/scottbedard/hexchess/blob/main/LICENSE)

Copyright (c) 2024-present, Scott Bedard