«Лучшая стратегия — та, которую враг не ожидал.»
Локальная LLM-управляемая ИИ для Supreme Commander: Forged Alliance через FAForever
Быстрый старт · Архитектура · Reflex Layer · LLM Pipeline · DLL Bridge
Трёхслойная ИИ-система, которая полностью работает на вашей машине — без облачных API, без интернета во время игры. Бот играет за UEF (союзник), принимая стратегические решения через комбинацию мгновенных рефлексов и LLM-рассуждений.
|
Три слоя принятия решений
|
Ключевые особенности
|
SupCom:FA (32-bit) Python Bridge Server
┌─────────────────────┐ ┌───────────────────────┐
│ Lua AI Brain │ Named │ State Processor │
│ ┌───────────────┐ │ Pipe │ ┌─────────────────┐ │
│ │ GameState │──┼───(IPC)──────>│ │ Prompt Builder │ │
│ │ Collector │ │ │ └────────┬────────┘ │
│ └───────────────┘ │ │ │ │
│ │ │ ┌────────▼────────┐ │
│ ┌───────────────┐ │ │ │ LLM Router │ │
│ │ Strategy <──┼──┼───(IPC)──────<│ │ 4B fast / 9B │──┼──> Ollama
│ │ Executor │ │ │ └────────┬────────┘ │ (local)
│ └───────────────┘ │ │ │ │
│ │ │ ┌────────▼────────┐ │
│ ┌───────────────┐ │ │ │ Command Builder │ │
│ │ Reflex Layer │ │ (no LLM) │ │ + Fallback │ │
│ │ < 1s response │ │ │ └─────────────────┘ │
│ └───────────────┘ │ │ │
└─────────────────────┘ └───────────────────────┘
IPC: Windows Named Pipe \\.\pipe\supcom_llm_bridge — 4-byte LE length-prefix + UTF-8 JSON.
Чистый Lua — мгновенная реакция без LLM:
| Условие | Действие | Кулдаун |
|---|---|---|
| Воздушная угроза базы > 15 | Поднять перехватчики | 20 тиков |
| Угроза базе > 30 | Отправить наземную поддержку | 20 тиков |
| Армия теряется быстро (< 60%) | Подкрепление | 20 тиков |
| Союзник столлит масс + свой > 300 | Поделиться массой | 20 тиков |
Кулдауны по сложности: easy=40, normal=20, hard=5 тиков.
GameStateCollector StateProcessor LLMRouter
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Resources │ │ Structured │ │ Trigger │
│ Units │──────────>│ Prompt + │──────>│ Severity │
│ Threats │ │ Game Context│ │ → 4B / 9B │
│ Map Control │ └──────────────┘ └──────┬───────┘
└──────────────┘ │
▼
StrategyExecutor CommandBuilder Ollama API
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Decision → │<──────────│ Validate │<──────│ think: false│
│ Game Cmds │ │ JSON schema │ │ Qwen3.5 │
└──────────────┘ └──────────────┘ └──────────────┘
Fallback: после 3 таймаутов 9B весь трафик автоматически маршрутизируется на 4B. При полной недоступности LLM — rule-based стратегия.
C++ DLL соединяет 32-bit Lua 5.0 VM движка SupCom и Python-сервер:
| Характеристика | Реализация |
|---|---|
| Зависимости | Только KERNEL32.dll + msvcrt.dll |
| Thread Safety | lua_sethook — хук срабатывает в потоке FA |
| IPC | InterlockedExchange-based lock-free очереди |
| Lua API | Direct function pointers к абсолютным адресам FA |
| Инъекция | CreateRemoteThread + LoadLibraryA через inject.exe |
// lua_api_direct.h — вызовы Lua C API через указатели на адреса FA
static inline void lua_pushstring(lua_State* L, const char* s) {
typedef void (*fn_t)(lua_State*, const char*);
((fn_t)0x90cdf0)(L, s); // FA address, no ASLR (2007 game)
}AI_For_Supreme_Com/
├── bridge/ # C++ DLL — game <-> Python
│ ├── src/
│ │ ├── pipe_client.cpp # Named Pipe (pure Win32 API)
│ │ ├── lua_bridge.cpp # LLMBridge.* регистрация
│ │ ├── lua_injector.cpp # Thread-safe lua_sethook
│ │ └── lua_api_direct.h # Direct fn-ptr к адресам FA
│ ├── inject.c # 32-bit DLL инжектор
│ └── CMakeLists.txt # MinGW GCC i686
│
├── server/ # Python asyncio bridge
│ ├── bridge_server.py # Entry point + process watcher
│ ├── llm_client.py # Ollama HTTP (think: false)
│ ├── llm_router.py # Роутинг 4B / 9B
│ ├── state_processor.py # Game state -> prompt
│ ├── command_builder.py # LLM response -> commands
│ └── fallback_strategy.py # Rule-based fallback
│
├── mod/ # FAF SIM мод
│ ├── lua/AI/
│ │ ├── LLMAIBrain.lua # Главный мозг + потоки
│ │ ├── LLMBridge.lua # DLL wrapper + offline mode
│ │ ├── GameStateCollector.lua # Сбор игрового состояния
│ │ ├── StrategyExecutor.lua # Решения -> команды
│ │ ├── ReflexLayer.lua # Мгновенные рефлексы
│ │ ├── EconomyManager.lua # Экономика / инженеры
│ │ └── JSON.lua # Lua 5.0 JSON codec
│ └── hook/lua/ # FAF hooks
│
├── mod-ui/ # FAF UI мод (lobby dropdown)
├── installer/ # Скрипты установки
├── tests/ # Unit + integration тесты
└── specs/ # Спецификации и контракты
| Компонент | Версия | Примечание |
|---|---|---|
| Python | 3.12+ | Bridge server |
| Ollama | latest | Локальный LLM inference |
| MSYS2 MinGW32 | GCC i686 | DLL компиляция (SupCom — 32-bit) |
| FAForever | latest | Игровой клиент |
| SupCom: FA | Steam | Базовая игра |
| VRAM | 6+ GB | Для Qwen3.5-9B (Q4_K_M) |
| Тег | Размер | VRAM | Назначение |
|---|---|---|---|
qwen3.5:9b |
Q4_K_M | ~5.5 GB | Глубокие стратегические решения |
qwen3.5:4b |
Q4_K_M | ~2.5 GB | Быстрые рутинные решения |
ollama pull qwen3.5:9b
ollama pull qwen3.5:4b# В MSYS2 MinGW32 shell:
cd bridge
cmake -B build_cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release
cmake --build build_cmake
# Output: bridge/build/supcom_llm_bridge.dll# Guided installer:
powershell -File installer/install.ps1
# Или вручную:
Copy-Item -Recurse mod/* "C:\FAFData\mods\supcom-llm-ai-bot\"
Copy-Item -Recurse mod-ui/* "C:\FAFData\mods\supcom-llm-ai-bot-ui\"
Copy-Item bridge\build\supcom_llm_bridge.dll "C:\ProgramData\FAForever\bin\llm_bridge.dll"
Copy-Item bridge\build\inject.exe "C:\ProgramData\FAForever\bin\inject.exe"# Terminal 1 — Ollama:
ollama serve
# Terminal 2 — Bridge server:
python server/bridge_server.py --config installer/config.json
# Terminal 3 — FAF: включить оба мода, добавить "LLM AI Bot (UEF)", играть!| Лог | Путь |
|---|---|
| Decision log | %ProgramData%\FAForever\logs\llm_ai_decisions.log |
| Injection log | %ProgramData%\FAForever\logs\llm_inject.log |
| Game log | %APPDATA%\Forged Alliance Forever\logs\game_*.log |
| In-game overlay | Ctrl+Shift+D (UI мод) |
| Ограничение | Решение |
|---|---|
Lua 5.0 — нет #, нет goto |
table.getn(), table.insert(), continue |
| 32-bit DLL — только MinGW i686 | CMakeLists + -m32 flags |
| ASCII paths — движок 2007 года | C:\FAFData вместо Документов |
| No ASLR — фиксированные адреса | Direct fn-ptr в lua_api_direct.h |
| Qwen3.5 thinking | "think": false в Ollama API |
# Тесты
uv run pytest -v
# Линтер
uv run ruff check .
uv run ruff format .MIT License — свободно используйте, форкайте, дорабатывайте.
Сухацкий Максим · МГТУ им. Н.Э. Баумана (Калужский филиал) · 2025–2026
🎮 «Лучшая стратегия — та, которую враг не ожидал.»