В прошлых статьях про инженерную архитектуру ГИГАХРУЩА мы разбирали, как в одном браузерном файле на чистом TypeScript держится тороидальный клеточный мир 1024x1024, кастомный WebGL-рэйкастер, симуляция A-Life и объемный генератор MESH PASS.
Сегодня мы расскажем историю создания речевого ядра проекта — историю о том, как попытка уйти от хардкода привела нас к теории категорий, дистрибутивной семантике и ошеломляющим открытиям: оказывается, если взглянуть на художественные тексты через чистую линейную алгебру, математика сама начинает «понимать» смысл слов и строить сюжетные конструкции.
В этой статье мы покажем, как с помощью векторного анализа корпусов, классов эквивалентности и PCA-осей нам удалось заставить Марковское ядро генерировать живую, контекстную речь для тысяч НПС — без сторонних фреймворков ("dependencies": {}), с задержкой 0 миллисекунд и 100% детерминизмом по SeedRng.

1. Откровение дистрибутивной алгебры: Как математика видит слова в тексте
Когда мы только подступили к задаче озвучки НПС (диалоги, баблы над головами, лог речи, посты в локальную соцсеть «Инфосеть Демос»), перед нами встала дилемма.
Жесткий хардкод (
If-Else/ шаблоны): Написать 5000 заготовок"{npc} пришел в {place}". Скучно, видно швы, игроку надоедает через полчаса.Наивный Марков по сырому тексту: Выдает колоссальное разнообразие, но страдает «синтаксической шизофренией» — НПС придумывает ложные факты, путает термины и уходит в бессвязный бред.
LLM в облаке: Недопустимо. Контракт ГИГАХРУЩА — автономный браузерный билд, который должен работать 60 FPS даже на кассовом терминале без доступа к сети.
Мы задались вопросом: можно ли обойтись без захардкоженных словарей и регексов, заставив математику саму извлечь структуру человеческого языка из литературы?
Мы взяли 11 обучающих корпусов (16,900+ предложений из «Пикника на обочине», «Самосбор-тредов», «Метро 2033», «S.T.A.L.K.E.R.», «Града обреченного», «Соляриса», советских инструкций Гражданской Обороны и ГОСТов) и написали офлайн-исследователь scripts/discover_categories.ts.
Факторизация словаря ()
Мы не кормили алгоритму готовые словари. Вместо этого алгоритм скользил окном контекста по тысячам страниц и строил вектор окружения для каждого слова .
Затем мы ввели на словаре отношение эквивалентности :
И произошло то, что поразило нас самих: математика без знания русского языка сама сгруппировала слова в идеальные смысловые кластеры (фактор-множество )!
Вот реальный фрагмент вывода нашего скрипта scripts/discover_categories.ts:
[Категория #20] (Векторный узел: ОБОРУДОВАНИЕ / ПАТРОНЫ) патронов/патроны (+0.43), оборудования/оборудование (-0.20), огонь (-0.11), заблокировать (-0.21), сальников (-0.25) [Категория #28] (Векторный узел: ГЕРМЕТИЗАЦИЯ / ПРОХОД) герметизация/герметизации (+1.00), кабели/кабелей (+0.57), проход/прохода (+0.50), автомат (+0.10), расход (-0.22) [Категория #29] (Векторный узел: ЖИЛОЙ БЛОК) жилом/жилой (+0.54), свой (+0.56), жертв/жертву (+0.66), ванны/ванной (-0.33)
Алгоритм сам понял, что [чай, кофе, тушенка, концентрат] выполняют одинаковую ролевую функцию в предложении, а [гермозатвор, шлюз, вентиляция, трансформатор] являются объектами пространства!
Живой пример: От Сидоровича и Артема к Ольге Дмитриевне и Майору Громову
Давайте наглядно разберем, как чужие литературные персонажи превращаются в канонических жителей ГИГАХРУЩА.
Представьте исходную строку из обучающего корпуса S.T.A.L.K.E.R. или «Метро 2033»:
«Сидорович сидит за гермодверью бункера и просит Меченого принести редкий артефакт из вентиляционной шахты.»
Алгоритм не хардкодит имена. При факторизации текста по предложение превращается в абстрактную матричную цепочку:
Формируется чистый грамматический скелет:
Когда движок ГИГАХРУЩА выполняет Категориальный Изоморфизм в рантайме, он подставляет персонажей и предметы нашей мегаструктуры:
Ольга Дмитриевна (врач санпропускника) или Сержант Баринов (начальник оружейки)
проходчик Яков или ликвидатор
дозиметр ДП-5В,чистый фильтр АФУ-300,малахитовый артефактзащитный шлюз,приёмный покой
И на выходе речевой роутер выдает аутентичную речь ГИГАХРУЩА:
“Ольга Дмитриевна сидит у защитного шлюза санпропускника и просит ликвидатора принести чистый фильтр АФУ-300 из вентиляционной шахты.”
Никакого regex-хардкода: мы взяли живую драму и синтаксис человеческой литературы, но в слоты встали персонажи нашей игры — Ольга Дмитриевна, Сержант Баринов, Яков и Майор Громов!

2. Извлечение синтаксических скелетов (Patterns Discovery)
Чтобы Марковская цепь движка не перескакивала хаотично с существительного на глагол, второй скрипт (scripts/discover_patterns.ts) повторно прошел по корпусам и извлек устойчивые синтаксические скелеты предложений:
Вот реальный вывод из discover_patterns.ts:
Freq: 33 | Pattern: <МЕСТО> -> <ЦЕННЫЙ_ПРЕДМЕТ> Freq: 29 | Pattern: <СУБЪЕКТ> -> <УГРОЗА> Freq: 22 | Pattern: <МЕСТО> -> <УГРОЗА> Freq: 18 | Pattern: <УГРОЗА> -> <МЕСТО>
Марковское ядро больше не блуждает «вслепую». Очерченный скелет указывает графу точный порядок категорий: например, сначала озвучиваем МЕСТО, затем ЦЕННЫЙ_ПРЕДМЕТ, а затем реакцию СУБЪЕКТА.

3. Векторизация и PCA-оси: Дорого vs Дешево, Опасно vs Безопасно
Но как НПС понимает, какой именно предмет или угрозу подставить в слот? Ведь и «гаусс-пушка», и «грязный бинт» принадлежат одной категории , но применить их в одинаковых ситуациях нельзя!
Здесь вступает в силу Метод Главных Компонент (PCA). Внутри каждого класса эквивалентности математика вычисляет оси дисперсии от -1.0 до +1.0:
Категория: <ЦЕННЫЙ_ПРЕДМЕТ> -1.0 (Дешевый мусор) <------------------------------------> +1.0 (Редчайший артефакт) [грязный бинт: -0.9, талон на воду: -0.7] ... [дозиметр: +0.4, гаусс-пушка: +1.0] Категория: <УГРОЗА> -1.0 (Бытовой риск) <-------------------------------------> +1.0 (Смертельная катастрофа) [истощение: +0.2, черная слизь: +0.75] ... [бетонник: +0.85, Самосбор: +1.0]
В момент генерации движок собирает текущий игровой контекст НПС MarkovTextContext:
И скатывает марковский выбор по косинусному сходству векторов:
Если НПС нашел предмет стоимостью 5000 кредитов (), вероятностная матрица моментально гасит вес
грязного бинта и выводит на вершину гаусс-пушку!

4. Разбор 10 Примеров Сгенерированной Речи НПС в ГИГАХРУЩЕ
Ниже приведены реальные результаты прогона нашего прототипа scripts/markov_core_prototype.ts.

Пример 1: Бытовой диалог обывателя у гермодвери
Игровой контекст
:
floorZ: 12,roomType: жилая_ячейка,occupation: обыватель,dangerLevel: 5,foundItemValue: 15(талон на воду).Вектор контекста:
.
Синтаксический скелет:
-
Результат генерации:
“Если паразитический мицелий вырвется из талон на воду, бункер Гражданской Обороны придется опечатать на месяц.”
Разбор ядра: Мирный бытовой контекст направил Марковский граф по слотам инструкции ГО, вставив в слот предмета бытовой артефакт
талон на воду, а в слот места —бункер Гражданской Обороны.
Пример 2: Тревога ликвидатора у вентиляционной шахты
Игровой контекст
:
floorZ: -4,roomType: вентиляционная_шахта,occupation: ликвидатор,dangerLevel: 85,roomMemory: ['черная_слизь'].Вектор контекста:
.
Синтаксический скелет:
-
Результат генерации:
“Там только что бетонник уже близко, надо уходить за трансформаторную ячейку. Во время тревоги тоннели могут перестраиваться, говорил старый ликвидатор.”
Разбор ядра: Высокий
поднял веса категории
. Движок выбрал бетоноеда и задействовал рефлекс ухода за укрытие.
Пример 3: Сирена САМОСБОРА (Паника и задраивание шлюзов)
Игровой контекст
:
floorZ: 42,roomType: коридор_сектора,occupation: дежурный_по_герме,dangerLevel: 100,isSamosborActive: true.Вектор контекста:
.
Синтаксический скелет:
-
Результат генерации:
“Появилась точная цель, но не сам Самосбор, а его обитатели. Мы ковыряемся в кровавом тупике жизнеобеспечения, выносите мясника из центра!”
Разбор ядра: При активной фазе Самосбора
граф скатился в корпус канонических Самосбор-тредов, активировав атмосферу паники и зачистки тупиков.
Пример 4: Находка ценного хабара (Гаусс-пушка)
Игровой контекст
:
floorZ: -12,roomType: кровавый_тупик,occupation: проходчик,dangerLevel: 60,foundItemValue: 5000.Вектор контекста:
.
Синтаксический скелет:
-
Результат генерации:
“Проходчик долго осматривал гаусс-пушку. За такой хабар бригадир смены выставит три нормы пайкового концентрата у шлюза.”
Разбор ядра: Выходной параметр ценности предметов
foundItemValue: 5000дал зашкаливающий вектор по оси, моментально выбравший топовое вооружение из слота ценностей.
Пример 5: Слесарь-параноик у мокрого шва гермодвери
Игровой контекст
:
floorZ: 88,roomType: трансформаторная,powerStatus: 'off',occupation: слесарь-параноик,dangerLevel: 40.Вектор контекста:
.
Синтаксический скелет:
-
Результат генерации:
“Слесарь-параноик не верил тишине: у гермы шов мокрый. Сначала уплотнитель, потом разговор.”
Разбор ядра: Профессиональные теги гильдии слесарей
repairвытащили из корпуса специфические бытовые действия ремонта и проверки герметичности.
Пример 6: Лаборант НИИ в продувочной прачечной
Игровой контекст
:
floorZ: 104,roomType: продувочная_прачечная,occupation: лаборант НИИ,dangerLevel: 15.Вектор контекста:
.
Синтаксический скелет:
-
Результат генерации:
“Лаборант НИИ установил дозиметр ДП-5В у продувочной прачечной. Реагенты в норме, инспекционный шлюз чист.”
Разбор ядра: Категория
scienceподтянула строго научные приборы (дозиметр ДП-5В) и канцелярит НИИ “Щит”.
Пример 7: Раненый домком просит помощи (Критический голод и ранение)
Игровой контекст
:
floorZ: 3,roomType: жилая_ячейка,hp: 15,thirst: 95,recentTrauma: true,occupation: домком.Вектор контекста:
.
Синтаксический скелет:
-
Результат генерации:
“Домком едва дышал на полу: грязный бинт и талон на воду решают быстрее любого разговора.”
Разбор ядра: Критический уровень потребностей
сфокусировал ядро на предметах первой помощи (
грязный бинт,талон на воду), проигнорировав оружие и хабар.
Пример 8: Мясник у Кровавого Алтаря (Пси-излучение)
Игровой контекст
:
floorZ: -69,roomType: алтарь_чернобожия,karma: -100,occupation: мясник,dangerLevel: 95.Вектор контекста:
.
Синтаксический скелет:
-
Результат генерации:
“Пси-излучение заполнило кровавый тупик. Мясник шептал слова бетона, пока процедурная аномалия не закрыла шлюз.”
Разбор ядра: Отрицательная карма (
karma: -100) и специфическая глубинная комната запустили цепочку атомов с тегамиmysticиblood.
Пример 9: Инструктаж бригадира смены у бункера ГО
Игровой контекст
:
floorZ: 0,roomType: бункер_ГО,karma: 80,occupation: бригадир смены,dangerLevel: 10.Вектор контекста:
.
Синтаксический скелет:
-
Результат генерации:
“Бригадир смены проверил защитный шлюз: сначала снимите фильтр АФУ-300, затем доложите дежурному по блоку.”
Разбор ядра: Административный статус НПС и высокий показатель кармы задали уставной порядок команд Гражданской Обороны.
Пример 10: Дежурный электрик в сборочном цеху
Контекст мира
:
floorZ: 16,roomType: сборочный_цех,occupation: дежурный электрик,dangerLevel: 25.Вектор контекста:
.
Синтаксический скелет:
-
Результат генерации:
“Дежурный электрик зашел в сборочный цех и достал герметизирующую мастику. Если щиток гудит — не трогай тумблер.”
Разбор ядра: Производственная зона направила граф по техническому словарю ремонта и работы со станками.

5. Ограничения и главное откровение
Для нас эта работа стала доказательством того, что математическая элегантность дистрибутивной алгебры избавляет инди-разработчика от написания тысяч строк хардкода.
Конечно, у этого подхода есть свои границы. Если вы ищете в процедурных репликах глубокого философского романа, длинных многоходовых логических цепочек или тонких детективных расследований — вы их там не найдёте. В своей основе это всё те же вероятностные Марковские цепи.
Но в мире с сотнями тысяч процедурных НПС этот метод, как никакой иной, создаёт осязаемый, живой, независимый от игрока, а главное — контекстно осмысленный слой текстов. Теперь у жителей мегаструктуры есть рот, и они наконец могут кричать то, как из их собственной точки отсчёта выглядит бесконечный ГИГАХРУЩ.

Полезные ссылки проекта:
Telegram-паблик разработчиков (обновления и девлоги): https://t.me/gigah_rush
Онлайн-версия игры (прямо в браузере): https://gigahrush.github.io/
Русская версия на Пикабу Игры: https://games.pikabu.ru/game/gigakhrushch
Комментарии (9)

cyberxx
23.07.2026 01:43Вместо этого алгоритм скользил окном контекста по тысячам страниц и строил вектор окружения для каждого слова
Это что-то типа Word2vec?

martyncev
23.07.2026 01:43Прочитал, ничего не понял, кроме того, что это шедеврально) This is magic!))

VladimirFarshatov
23.07.2026 01:43Корпус обучения бы побольше, конечно же. Круто, тоже всегда считал что марковские цепи в логике ИИ нужны как воздух. Спс.

francyfox
23.07.2026 01:43честно говоря напомнило игру из передачи игр на вынос туннельные крысы. Темно как у не*ра в *опе. Непонятно куда идти. Понять где дверь можно только по миникарте (что еще в старых играх бесило). Пространства слишком большие и пустые, больше похоже на школу или офис со странной планировкой, чем на хрущ. Тараканов нельзя лопать
Void-Cowboy
таки живы!
вы кстати не думали опубликоваться в телеге как web-app? по идее ваш формат как раз идеально войдет
TENEVIK Автор
Блин, а ведь это гениальная идея! Почему то даже не думали в эту сторону!
Спасибо за наводку, займёмся прям на этих выходных)
Void-Cowboy
могу еще странных идей подкинуть - например что бы сервер был доступен и из-под сети yggdrasil что бы всякие блокировки и тд не мешали наслаждаться гигахрущем)