Это классический вопрос компромисса (trade-off) между оптимизацией машинной памяти и удобством использования (Developer Experience / Analytics). Ты мыслишь абсолютно как разработчик шахматных движков, потому что именно там применяются битовые маски и числа!

Давай разберем каждый тип данных по отдельности, плюсы и минусы обоих подходов.

1. active_color: Символ (‘w’/‘b’) vs Логическое значение (Boolean)

Если использовать Boolean (например, is_white = true):

  • Плюсы: Самый строгий тип данных. Невозможно записать опечатку вроде 'x'.
  • Минусы: В базах данных (особенно PostgreSQL) Boolean всё равно занимает 1 байт физической памяти (из-за выравнивания страниц). Экономии места нет. Кроме того, при чтении или отладке сырых данных в SQL-консоли нужно постоянно держать в голове: true — это белые или черные?
  • Вывод: Символ CHAR(1) с ограничением (CHECK active_color IN ('w', 'b')) занимает тот же 1 байт, но при этом данные самодокументируемые. Мы сразу видим ‘w’ и понимаем, чей ход.

2. castling: Строка (‘KQkq’) vs Число (Битовая маска)

У нас 4 возможных права рокировки (Белый Король, Белая Королева, Черный Король, Черная Королева). Если использовать Число (битовую маску от 0 до 15): Например, 1-й бит — K, 2-й — Q, 3-й — k, 4-й — q. Число 15 в бинарном виде 1111 означает KQkq. Число 5 (0101) означает Kk.

  • Плюсы: Идеально для работы шахматного движка. Очень быстро считать в процессоре через побитовые операции (AND, OR).
  • Минусы: Если аналитику (или тебе через пару лет) захочется найти партии, где белые могли сделать длинную рокировку, ему придется писать SQL-запрос с побитовыми операторами: SELECT * FROM positions WHERE (castling_mask & 2) > 0. Это сложно читать, сложно дебажить и легко ошибиться.
  • Вывод: В базе данных мы чаще выбираем строку. VARCHAR(4) занимает всего около 5 байт. Запрос WHERE castling LIKE '%Q%' гораздо понятнее для человека.

3. en_passant: Строка (‘a3c3e3’) vs Битовая маска (Bitboard)

Это самый интересный случай, потому что в Dice Chess у нас бывает множественный en_passant. В классических шахматах поле одно, и его можно было бы сохранить как число от 0 до 63 (индекс клетки). В Dice Chess так не получится.

Если использовать Число (64-битный Bitboard): Мы можем использовать 64-битное число (BIGINT), где каждый бит соответствует клетке на доске. Если 3-й бит включен, значит бить можно на c3.

  • Плюсы: С точки зрения базы данных, хранить 64-битное число — это 8 байт памяти.
  • Минусы: Строка a3c3e3 тоже занимает всего 7 байт (плюс небольшой оверхед Postgres на VARCHAR)! То есть выигрыш в памяти практически нулевой. А вот сложность SQL-запросов взлетает до небес. Как найти позиции, где можно побить пешку на линии ‘e’? С битбордом это сложная математика. Со строкой: WHERE en_passant LIKE '%e%'.

Общий вывод по Trade-off

В разработке есть правило: Движок должен быть оптимизирован для машины, а База данных — для человека (аналитика).

  • В движке Scala (где каждая микросекунда на счету) мы обязаны использовать числа, битовые маски и Long для досок (Bitboards). И ты это уже делаешь!
  • В базе данных PostgreSQL (где узкое место — это время аналитика на написание SQL-запросов) мы предпочитаем читаемые строки. Экономия 3-4 байт на строке не стоит того, чтобы превращать работу с базой данных в расшифровку числовых ребусов.

Так что выбранные строковые типы — это осознанный компромисс в пользу скорости написания аналитических запросов и читаемости данных при ничтожных (в рамках современных серверов) потерях дискового пространства.