Игра = данные. Движок (engine/) умеет бегать, прыгать, сталкиваться с тайлами и исполнять кубики — переиспользуемые игровые примитивы, не знающие о теме. Игра (games/<id>/index.js) описывает понятия и уровни: ASCII-карту, легенду и список объектов.
{
id: 'tokenizer', title: 'Лес слов', concept: 'token',
intro: 'Модель не видит слов…', task: 'Разбей три слова и собери 8 токенов',
map: [
'..............................',
'..P...........................',
'######....####################',
],
legend: { 'k': { type: 'pickup', label: 'кот', tag: 'token', count: 'tokens' } },
objects: [
{ type: 'splitter', at: [8, 1], word: 'переподготовка', cuts: [4, 12], ids: [2041, 17733, 285] },
{ type: 'gate', at: [20, 0], h: 3, requires: { counter: ['tokens', 8] }, label: 'токены' },
{ type: 'sign', at: [3, 1], text: 'LLM видит не слова, а токены' },
],
hud: [{ counter: 'tokens', label: 'Токены', of: 8 }],
goal: { counter: ['tokens', 8] },
outro: 'Ты порезал слова так же, как это делает BPE-токенизатор.',
}
Символы карты по умолчанию: # земля, = платформа (односторонняя), ^ шипы, ~ лава, < > конвейеры, B кирпич, G стекло, H труба, P игрок, E выход, C чекпоинт. Любой другой символ описывается в legend.
Условия (requires, goal): {flag:'x'}, {counter:['tokens', 8]}, {var:['volts','>=',60]}, {all:[…]}, {any:[…]}, {not:…}. Эффекты (onComplete, onAccept…): {flag}, {counter:[k, +n]}, {var:[k,'+',n]}, {list:[k, item]}.
| type | Название | Что делает | Поля |
|---|
games/<id>/index.js с export default { id, title, theme, concepts, levels }.games/index.js.engine/themes.js.engine/mechanics/ с create(spec, world) и doc, строка в engine/mechanics/index.js. Логику стоит покрыть тестом в tests/ (бот проходит мини-уровень).