// Package encoding defines the compact byte conventions shared by the board, rack,
// move output and (for letters) the dictionary graph.
//
// One uniform "symbol byte" is used everywhere:
//
//	bits 0..5  the alphabet letter index plus one (1..63); 0 means "empty / no tile"
//	bit 6      reserved (unused)
//	bit 7      Blank — the tile is a blank standing for that letter; it scores 0
//
// The +1 offset lets 0 mean an empty board square. The same byte represents a board
// cell, a placed tile and a rack tile; the graph stores raw letter indexes (without the
// +1).
package encoding

const (
	// Blank flags a tile as a blank standing for its letter; a blank scores 0.
	Blank byte = 0x80

	// Empty is the value of an unoccupied board square.
	Empty byte = 0x00

	letterBits byte = 0x3f // low 6 bits: letter index + 1
)

// Cell builds the byte for a tile of the given alphabet letter index. When blank is
// true the tile is marked as a blank (it scores 0).
func Cell(letter byte, blank bool) byte {
	c := (letter + 1) & letterBits
	if blank {
		c |= Blank
	}
	return c
}

// IsEmpty reports whether a board cell is unoccupied.
func IsEmpty(cell byte) bool { return cell&letterBits == 0 }

// Letter returns the alphabet letter index of a non-empty cell or tile byte. The
// result is meaningless for an empty cell.
func Letter(cell byte) byte { return (cell & letterBits) - 1 }

// IsBlank reports whether a cell or tile byte is a blank (scores 0).
func IsBlank(cell byte) bool { return cell&Blank != 0 }
