Пост про пятый и шестой дни остановился 16 октября в 17:53: на карте исследования 29 строк, 28 из них после ревью, а запуск по бою, первый запуск симуляции, ещё впереди. Этот пост — об остатке того вечера и о пяти днях после него, до 21 октября, 12:11. Теперь на карте 36 строк и 35 после ревью. Единственная, которая ещё нет, снова самая новая: строка chain, добавленная 20-го, для спецификаций ядра, прогнанных одной цепочкой от сида игры до дропа на полу, без единого значения, взятого из игры по дороге.

Главное отличие от прошлых постов: я не играл. В шестой день семь сессий были моими; за эти пять дней — ни одной. Список того, что делал я, короткий: вечером 16-го я одобрил шесть планов, чтобы они шли без присмотра, 20-го — ещё пять и порядок того, что осталось, 17-го выполнил одну команду от root, чтобы показать, что файрвол и так закрывает порт игры снаружи, а без этого двух клиентов в одну игру не пускали, утвердил семь ADR, которые мне принесли, дважды ставил лейны на паузу, а 20-го попросил убрать закрытое из бэклога в архив, потому что он разросся. Всё остальное ниже сделали лейны, каждый — агент со своей копией репозитория, на харнессе, то есть на игре под отладчиком с подключённым логгером, и сделали за ночи, в которые машину выключали, она спала девять часов, потом семь, а один раз осталась без памяти.

Карта работы

Карта исследования к каждой отсечке

  • не начато
  • в плане
  • находки
  • черновик спецификации
  • спецификация после ревью

3 спецификация после ревью 1 находки 1 в плане 23 не начато из 28

Ядро

  • rng спецификация после ревью
  • items/tc находки
  • items/quality не начато
  • items/affixes не начато
  • items/uniques-sets не начато
  • items/properties не начато
  • monsters/pool не начато
  • monsters/spawn не начато
  • monsters/special не начато
  • drlg/overview в плане
  • drlg/preset не начато
  • drlg/maze не начато
  • drlg/outdoor не начато
  • drlg/warps не начато
  • objects не начато

Опоры

  • data/excel спецификация после ревью
  • data/calc не начато
  • data/strings не начато
  • rng/seeds спецификация после ревью
  • drlg/collision не начато
  • save/d2s не начато

Пути создания

  • items/vendors не начато
  • items/cube не начато
  • items/sockets-runewords не начато
  • items/quest-drops не начато
  • monsters/stats не начато
  • hirelings не начато
  • player/creation не начато

28 спецификация после ревью 1 в плане из 29

Ядро

  • rng спецификация после ревью
  • items/tc спецификация после ревью ↑
  • items/quality спецификация после ревью ↑
  • items/affixes спецификация после ревью ↑
  • items/uniques-sets спецификация после ревью ↑
  • items/properties спецификация после ревью ↑
  • monsters/pool спецификация после ревью ↑
  • monsters/spawn спецификация после ревью ↑
  • monsters/special спецификация после ревью ↑
  • drlg/overview спецификация после ревью ↑
  • drlg/preset спецификация после ревью ↑
  • drlg/maze спецификация после ревью ↑
  • drlg/outdoor спецификация после ревью ↑
  • drlg/warps спецификация после ревью ↑
  • objects спецификация после ревью ↑

Опоры

  • data/excel спецификация после ревью
  • data/calc спецификация после ревью ↑
  • data/strings спецификация после ревью ↑
  • rng/seeds спецификация после ревью
  • drlg/collision спецификация после ревью ↑
  • save/d2s спецификация после ревью ↑

Пути создания

  • items/vendors спецификация после ревью ↑
  • items/cube спецификация после ревью ↑
  • items/sockets-runewords спецификация после ревью ↑
  • items/quest-drops спецификация после ревью ↑
  • monsters/stats спецификация после ревью ↑
  • hirelings спецификация после ревью ↑
  • player/creation спецификация после ревью ↑

Симуляция

  • combat/formulas в плане

32 спецификация после ревью 3 находки из 35

Ядро

  • rng спецификация после ревью
  • items/tc спецификация после ревью
  • items/quality спецификация после ревью
  • items/affixes спецификация после ревью
  • items/uniques-sets спецификация после ревью
  • items/properties спецификация после ревью
  • monsters/pool спецификация после ревью
  • monsters/spawn спецификация после ревью
  • monsters/special спецификация после ревью
  • drlg/overview спецификация после ревью
  • drlg/preset спецификация после ревью
  • drlg/maze спецификация после ревью
  • drlg/outdoor спецификация после ревью
  • drlg/warps спецификация после ревью
  • objects спецификация после ревью

Опоры

  • data/excel спецификация после ревью
  • data/calc спецификация после ревью
  • data/strings спецификация после ревью
  • rng/seeds спецификация после ревью
  • drlg/collision спецификация после ревью
  • save/d2s спецификация после ревью
  • drlg/lifecycle спецификация после ревью

Пути создания

  • items/vendors спецификация после ревью
  • items/cube спецификация после ревью
  • items/sockets-runewords спецификация после ревью
  • items/quest-drops спецификация после ревью
  • monsters/stats спецификация после ревью
  • hirelings спецификация после ревью
  • player/creation спецификация после ревью

Симуляция

  • combat/formulas спецификация после ревью ↑
  • stats/aggregate спецификация после ревью
  • stats/states спецификация после ревью

Правила игры

  • quests/progression находки
  • quests/travel находки
  • items/economy находки

35 спецификация после ревью 1 находки из 36

Ядро

  • rng спецификация после ревью
  • items/tc спецификация после ревью
  • items/quality спецификация после ревью
  • items/affixes спецификация после ревью
  • items/uniques-sets спецификация после ревью
  • items/properties спецификация после ревью
  • monsters/pool спецификация после ревью
  • monsters/spawn спецификация после ревью
  • monsters/special спецификация после ревью
  • drlg/overview спецификация после ревью
  • drlg/preset спецификация после ревью
  • drlg/maze спецификация после ревью
  • drlg/outdoor спецификация после ревью
  • drlg/warps спецификация после ревью
  • objects спецификация после ревью
  • chain находки

Опоры

  • data/excel спецификация после ревью
  • data/calc спецификация после ревью
  • data/strings спецификация после ревью
  • rng/seeds спецификация после ревью
  • drlg/collision спецификация после ревью
  • save/d2s спецификация после ревью
  • drlg/lifecycle спецификация после ревью

Пути создания

  • items/vendors спецификация после ревью
  • items/cube спецификация после ревью
  • items/sockets-runewords спецификация после ревью
  • items/quest-drops спецификация после ревью
  • monsters/stats спецификация после ревью
  • hirelings спецификация после ревью
  • player/creation спецификация после ревью

Симуляция

  • combat/formulas спецификация после ревью
  • stats/aggregate спецификация после ревью
  • stats/states спецификация после ревью

Правила игры

  • quests/progression спецификация после ревью ↑
  • quests/travel спецификация после ревью ↑
  • items/economy спецификация после ревью ↑

Стрелка отмечает строку, которая сдвинулась с прошлого снимка. Источник: docs/specs/README.md на коммитах 8faba4f2, 33dc648, 02d790d и 483728e. Полоса «Правила игры» добавлена вечером 16 октября решением ADR-0017; строка chain — планом 0048 20-го.

Показать таблицей
Подсистема День 1День 6День 8День 11
rng спецификация после ревьюспецификация после ревьюспецификация после ревьюспецификация после ревью
items/tc находкиспецификация после ревьюспецификация после ревьюспецификация после ревью
items/quality не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
items/affixes не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
items/uniques-sets не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
items/properties не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
monsters/pool не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
monsters/spawn не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
monsters/special не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
drlg/overview в планеспецификация после ревьюспецификация после ревьюспецификация после ревью
drlg/preset не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
drlg/maze не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
drlg/outdoor не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
drlg/warps не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
objects не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
chain ———находки
data/excel спецификация после ревьюспецификация после ревьюспецификация после ревьюспецификация после ревью
data/calc не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
data/strings не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
rng/seeds спецификация после ревьюспецификация после ревьюспецификация после ревьюспецификация после ревью
drlg/collision не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
save/d2s не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
drlg/lifecycle ——спецификация после ревьюспецификация после ревью
items/vendors не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
items/cube не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
items/sockets-runewords не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
items/quest-drops не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
monsters/stats не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
hirelings не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
player/creation не начатоспецификация после ревьюспецификация после ревьюспецификация после ревью
combat/formulas —в планеспецификация после ревьюспецификация после ревью
stats/aggregate ——спецификация после ревьюспецификация после ревью
stats/states ——спецификация после ревьюспецификация после ревью
quests/progression ——находкиспецификация после ревью
quests/travel ——находкиспецификация после ревью
items/economy ——находкиспецификация после ревью

Семь строк новые. Две — вторая фаза симуляции, характеристики и состояния. Одна — жизненный цикл комнат, опора, о которой никто не вспоминал, пока запуск по циклу не показал, что усыплённая и разбуженная комната создаёт предметы заново. Три — новая полоса, правила игры: продвижение по квестам, перемещения и экономика предметов, две области, которые второе решение проекта в первый же день оставило за рамками. И одна — цепочка.

Каждая строка прошла те же стадии, что и раньше: статическое чтение кода с пометкой [I], запуск на харнессе под отладчиком, который поднимает воспроизведённое до [C], спецификация, ревью агентом, который её не писал. Запуски за это время:

ЗапускЧто воспроизвела модельРасхождений
Бой40 логов, 40 655 событий атак и эффектов при попадании, сцепленных по сидам0
Характеристики и состояния18 сессий; 891 844 чтения характеристик, 3 643 наложения состояний, 54 719 тиков регенерации0
Жизненный цикл комнат13 сессий, 2 215 807 проверок; 2 440 усыплений комнат и 1 362 пробуждения0
Цикл комнат, монстр идёт за игроком3 сессии на Hell, 675 849 проверок4, объяснены
Квесты и перемещения, три запуска45 сессий, 45 714 проверок0
Экономика, два запуска33 901 вызов расчёта цены, 1 061 бросок прочности, 1 412 событий износа, 14 воскрешений0
Два клиента19 сессий с двумя настоящими клиентами игры; 417 убийств в группе, 385 делений опыта, 230 атак игрока на игрока0
Недоборы симуляции31 лог боя, 18 737 событий; 10 логов характеристик; 1 лог перемещений0
Объекты, ревизия22 сессии, 234 315 проверок0 у модели
Предметы, три пакета ревизии35 сессий; 873 вызова treasure class, 1 043 создания, 1 078 выборов метательного оружия0
Навыки, одиннадцать пакетов в эмуляторе99 450 случаев функций навыков и снарядов, прогнанных в дизассемблере без игры0
От сида к миру, запуск 128 логов, 156 уровней, 9 057 объектов, 1 286 предметов из одного сида игры2, открыты

Проверка здесь — одно значение, которое модель предсказала, а игра записала в лог. Treasure class, который в таблице встречается дважды, — это строка таблицы дропа, по которой бросает монстр или сундук. Сессии вели агенты по скриншотам, пилотом из четвёртого дня, кроме одиннадцати пакетов по навыкам: те шли в эмуляторе, о котором писал пост про шестой день, по правилу, которое 20-го расширили, об этом ниже.

Запуск по бою

Шестой день закончился тем, что формулы боя были прочитаны в коде, а запуск на харнессе ещё ждал. Его приняли 16-го в 19:26, через полтора часа после отсечки того поста: 19 сессий, 15 358 событий, ноль расхождений. В плане стояло 2 000 атак игрока, вышло 2 030; 1 000 атак монстров, вышло 4 533, потому что монстры много промахиваются: 697 попаданий против 3 836 промахов, из них 2 243 заблокированы. Каждый вид событий нужно было сцепить: сид на входе второго события предсказывается по выходу первого, не меньше двадцати пар на вид, и «каждый вид проходит порог в 20 с обоих концов».

События первой партии запуска по бою, 19 сессий

Событие — один вызов именованной точки входа: одна атака по одной цели, досчитанная до результата, один эффект при попадании.

Атаки монстров по игроку 4 533
Атаки игрока по монстрам 2 030
Броски защиты от снарядов 1 957
Атаки наёмника 1 259
Попадания Nova 519
Crushing blow 316
Deadly strike 250
Open wounds 246

docs/findings/combat/experiments.md, run:2026-10-16-combat. К следующему утру лейн-продолжение довёл запуск до 40 логов и 40 655 событий.

Показать числа
событий
Атаки монстров по игроку 4 533
Атаки игрока по монстрам 2 030
Броски защиты от снарядов 1 957
Атаки наёмника 1 259
Попадания Nova 519
Crushing blow 316
Deadly strike 250
Open wounds 246

До чего первая партия не дотянулась — до Andariel на Hell: лейну не хватило времени, две попытки, и так и записано. Недоборы взял лейн-продолжение, и в тот же вечер он остановился на «сроке владельца для машины». Он закончил к 07:56 следующего утра: 40 логов, 40 655 событий, по-прежнему ноль расхождений, и три вещи, для которых нужен был босс. Crushing blow по боссу акта, 34 события на Andariel, — одна восьмая, как и прочитано; по суперуникальным, 55 событий, тоже одна восьмая; а процент урона наёмника по ней — 50 на Normal, 35 на Nightmare и 25 на Hell, одно значение из таблицы, по номеру сложности, и именно 25 на Hell отличает этот столбец от соседнего, где стоит 20.

Запуск поймал чтение на ошибке. В чтении было сказано, что open wounds по боссу акта кровоточит в полную силу, и в спецификации тоже. А чекер был написан по проверке из кода, которая делит кровотечение пополам для любого монстра с флагами типа 0x0C, и у Andariel стоит 0x08, флаг уникального. Все 63 её open wounds были поделены пополам. Словами ревью: «„нет /2 для босса“ в находке и „боссы акта получают полную величину“ в спецификации были ошибкой, а чекер всё это время моделировал правильно». Спецификация закрылась 17-го в 08:16: 190 подтверждённых утверждений против 139 выведенных, и четыре утверждения сообщества, которые в шестой день были опровергнуты чтением, бонус класса к уровню, лечение от поглощения, crushing blow по уникальным и его зависимость от числа игроков, теперь опровергнуты запуском. Запуск по недоборам через три дня добавил чемпионов: «52 crushing blow по чемпионам сняли 1/4». Не одну восьмую.

Один монстр в модель не вписался: сессия с Fleshripper, уникальным ножом, который не даёт монстрам лечиться, оставила 101 расхождение, все в обработчике убийства, который работает в той же функции, что наносит урон, и который никто не читал. Сессию отложили, а обработчик ушёл в план по навыкам, и 20-го чтение нашло, где накладывается состояние ножа: в ветке, где бросок на попадание удался, между попаданием и блоком.

Кинжал, который сломал модель

  • Fleshripper, уникальный клыкастый нож: картинка из инвентаря, кадры его падения и персонаж с ним в руках Fleshripper: его состояние «не лечиться» накладывается между попаданием и блоком

Лист предмета из инструмента проекта tools/item_art.py: картинка из инвентаря и кадры падения предмета на землю. Графика Diablo II © Blizzard Entertainment.

Характеристики и состояния

Вторую фазу симуляции одобрили вечером 16-го, а закрылась она 17-го в 20:06. Это та часть игры, которая всё суммирует: как бонус предмета доходит до силы того, кто его носит, и как состояние с таймером, благословение святилища, аура, проклятие, накладывается, обновляется и истекает. Восемнадцать сессий с шестью персонажами, собранными инструментами, ноль расхождений, и числа такие, какие даёт прогон дерева: 891 844 чтения характеристик в залогированных окнах, 232 042 записи в кеш, 17 634 проверки требований, 3 643 наложения состояний, из них 2 608 — обновление уже наложенного, и 6 207 длительностей аур, каждая равна задержке ауры плюс один.

Статическое чтение утверждало, что ни одна функция этой фазы не берёт случайного числа, и план превратил это в проверку: сид пишется в лог на входе и на выходе каждого вида событий. Один вид число взял. Аура с уроном, Sanctuary, берёт «одно RNG_RangeB на попадание», так что её проверили сцеплением, 746 пар. 21-го каталог уточнил: одно число на один прогон ауры, сколько бы юнитов она ни задела; пока только [I].

Три вещи из спецификации, которых игрок не угадал бы. Бонус предмета «за уровень», тот, что растёт с уровнем персонажа, «не обновляется, когда носитель получает уровень», 94 записи, подтверждено; он пересчитывается, когда предмет переложили. От эфирной скидки к требованиям, десять единиц, в запуске зависели 30 проверок: персонаж с силой от 115 до 124 против War Boots, которым нужно 125. А пересчёт всего дерева запускается каждые 136 кадров без всякого действия игрока; что его ставит в очередь, не прочитано. Справочник сообщества пишет, что операция 6 над характеристиками «не работает», а операция 7 обновляется только на клиенте; сервер считает обе, просто ни один стандартный предмет до них не доходит, потому что два аффикса, которые ими пользуются, не могут появиться. Ревью ещё вычеркнуло из чтения число «96 с при 25 кадрах в секунду» для святилища: правило проекта с шестого дня — время только в кадрах и ни в чём другом.

Комнаты, которые спят

В посте про шестой день жизненного цикла комнат нет, потому что о нём никто не вспоминал. Игра усыпляет комнату, когда рядом нет игрока, и будит, когда он возвращается, а пробуждение восстанавливает юниты: заново создаёт монстров, объекты и предметы по записям, которые она сохранила. Любая реализация обязана делать это так же, иначе игрок, который отошёл и вернулся, найдёт другую комнату. План одобрили 16-го в 21:15, и его запуск 17-го стал самым большим за эти дни: 13 сессий, 2 215 807 проверок, 2 440 комнат усыплены и 1 362 разбужены, 2 035 монстров возвращены, у каждого ровно та жизнь, которую предсказала модель.

Чтение кода ошиблось в четырёх местах, вот три из них. Восстановление предмета берёт два числа с сида игры, а простой предмет возвращается с нулевым начальным сидом. Визит игрока между двумя проходами усыпления не сбрасывает счётчик простоя. А главный сюрприз чтения, мёртвый чемпион, сохранённый и возвращённый живым, оказался невозможен: «Маска 0x18 в проверке сохранения — это „особый или миньон“. У каждого залогированного чемпиона стоит 0x08, так что мёртвый чемпион не сохраняется никогда».

С сообществом спецификация цикла комнат расходится как раз в том, что игроки повторяют часто. Про уровень без флага SaveMonsters говорят, что он оставляет монстров «ранеными»; в 1.14d «любой другой живой монстр усыплённой комнаты освобождается без записи, а комната заново не заселяется, так что он исчезает, а не ранен». Про Blood Raven говорят, что через двадцать минут она снова с полным здоровьем; правило такое: восстановленный монстр сохраняет записанную жизнь, если между сохранением и восстановлением прошло меньше 7 500 кадров, иначе получает максимум. А Prevent Monster Heal якобы сбрасывается, если отойти слишком далеко: по расстоянию не сбрасывается ничего, «усыплённый и разбуженный монстр — это новый юнит».

Монстр, о котором ходит правило двадцати минут

  • Blood Raven: порченая Rogue-лучница с луком, стоит на месте Blood Raven, как игра рисует её класс

Собрано из слоёв спрайтов самой игры инструментом tools/cof.py: первый кадр спокойной позы с луком, без смены цвета, которую суперуникальный получает в игре. Графика Diablo II © Blizzard Entertainment.

Один случай запуск не достал: монстр, который идёт за игроком в город. Пакет-продолжение попробовал три сессии на Hell 17-го и закончил 18-го: 675 849 проверок и единственное ненулевое число расхождений у законченного запуска за эти дни, четыре. Все четыре объяснены одинаково: бит флага, который восстановление не копирует обратно, четыре записи из 1 689. Преследователь ни разу не прошёл через город, и прогон по 106 раскладкам городов без игры показал, почему это невозможно: из 93 944 пар клеток ни один маршрут через город не короче, потому что «внутренность каждого города встречается с соседним уровнем в одних воротах». Пакет заодно вычитал, что уборка истёкших предметов идёт каждые 1 500 кадров, а не каждые 20, как было в чтении; 20 — это таймер квестов рядом. Это остаётся выведенным: запуск исключает 20, не подтверждая 1 500.

У запуска был сбой, и сбой стал правилом. Один запуск игры наложился на идущую сессию разработки на том же слоте харнесса, убили обоих, а частичный лог наложившегося запуска удалили. Теперь в руководстве по игре на харнессе написано: «Частичные логи сохраняются. Прерванная сессия или сессия, которая наложилась на другую на том же слоте, оставляет частичный лог: хранить его… и никогда не удалять». А третью сессию на Hell убили 17-го в 21:38, когда машина выключилась посреди её второго захода, ухода из комнаты и возвращения; её частичный лог вошёл в запись, а черновик лейна, лежавший во временной папке, пропал, и его переписали по якорям.

Ревизия

В шестой день появился план 0038: ревизия 1 526 выведенных утверждений, которые ещё оставались в спецификациях после ревью, разложенных по пакетам: статическим, где доказательство уже лежит в сохранённом логе или во втором источнике, и пакетам на харнессе, которым нужны новые сессии. К отсечке того поста прошли два пакета. За эти дни прошли ещё восемнадцать.

Что поднял каждый пакет ревизии

Утверждение поднято, когда доказательство пакета покрывает его целиком; частично — когда часть его случаев; недобор — утверждение, до которого пакет собирался дойти и не дошёл.

  • поднято
  • поднято частично
  • недобор
S1e, эмуляция: формулы, таблицы, строки, ГСЧ, сохранения 74
S2c, статический: предметы 75
S1b, статический: данные, ГСЧ 75
S1a, статический: файл сохранения 54
H4b, харнесс: монстры 45
S2b, статический: аффиксы, свойства, уникальные 49
H5c, харнесс: уровни и переходы 40
S3a, статический: монстры, наёмники, игрок 39
S4b, статический: уровни и объекты 39
H5e, харнесс: лабиринты 22
H5a, харнесс: связи уровней 16
S1f, эмуляция, второй пакет 15
H2b, харнесс: цепочка предметов 20
H2a, харнесс: treasure class 17
S3b, статический: монстры, наёмники, игрок 15
H5b, харнесс: объекты 28
H6d, харнесс: квестовые дропы 16
H2c, подменённые таблицы: метательное оружие 7

docs/plans/0038-inferred-claims-sweep.md, итоговая строка ревью каждого пакета. У H5b посчитаны строки описи, у остальных — утверждения.

Показать числа
поднятоподнято частичнонедобор всего
S1e, эмуляция: формулы, таблицы, строки, ГСЧ, сохранения 6914 74
S2c, статический: предметы 48270 75
S1b, статический: данные, ГСЧ 47280 75
S1a, статический: файл сохранения 39150 54
H4b, харнесс: монстры 3591 45
S2b, статический: аффиксы, свойства, уникальные 30181 49
H5c, харнесс: уровни и переходы 23611 40
S3a, статический: монстры, наёмники, игрок 20190 39
S4b, статический: уровни и объекты 19137 39
H5e, харнесс: лабиринты 1822 22
H5a, харнесс: связи уровней 1600 16
S1f, эмуляция, второй пакет 1500 15
H2b, харнесс: цепочка предметов 1451 20
H2a, харнесс: treasure class 1250 17
S3b, статический: монстры, наёмники, игрок 1140 15
H5b, харнесс: объекты 10117 28
H6d, харнесс: квестовые дропы 592 16
H2c, подменённые таблицы: метательное оружие 421 7

Два пакета шли не в игре, а в эмуляторе, способом, который ADR-0015 разрешил в шестой день: одна функция бинарника за раз, в эмуляторе процессора из Ghidra, на входах, которые выбрал пакет, с трассировкой каждого чтения памяти. Первый прогнал 28 643 случая по десяти семействам функций, и каждый сошёлся бит в бит, а отрицательный контроль упал, как и должен. Второй добавил 18 800 случаев и директиву guard: случай, у которого счётчик команд доходит до фатального пути, останавливается, а не блуждает дальше. Он же нашёл предел самого эмулятора: по его модели команд деление наименьшего 32-битного целого на минус единицу возвращает ноль там, где настоящий процессор уходит в исключение. «Это не меняет ни одного решения, так что владельцу ничего не выносим».

Два утверждения вернулись опровергнутыми. В спецификации сидов было сказано, что сид от 2³¹ и выше задаётся в командной строке своим отрицательным десятичным значением. Запуск показал, что парсер копирует текст ключа только до следующего дефиса, так что -seed -1 приходит пустым, читается как ноль, и игра берёт часы; значение от 2³¹ и выше обрезается до максимума. Из командной строки воспроизводимы сиды от 1 до 0x7FFFFFFF. А в спецификации Куба было написано, что поиск места для коровьего портала берёт число; не берёт, число берёт объект портала, 171, 173 и 171 шаг в трёх открытиях. Пакет по treasure class нашёл именно такое завышение, ради которого ревизия и нужна: ограничитель в броске качества, про который в заметке к шагу стояло «ни разу не сработал в запусках», срабатывает в 667 бросках пакета и в 138 меняет результат. Заметка была верна для двух запусков по качеству, на которых её написали неделей раньше.

Когда пакеты спецификации легли, её перетегируют и пересчитывают шапку:

Подтверждённые утверждения в перетегированных спецификациях до и после ревизии

  • до
  • после
items/tc 49 119
items/affixes 112 152
items/properties 130 152
drlg/preset 98 134
data/calc 77 129
drlg/maze 105 122
drlg/room-tiles 89 120
drlg/warps 91 104
drlg/outdoor 170 180
rng/seeds 62 76
drlg/README 60 75
rng/README 22 28

Числа из шапок спецификаций, которые записывает каждый раунд перетегирования в docs/plans/0038-inferred-claims-sweep.md. Выведенных становится меньше примерно на столько же, на сколько больше подтверждённых: у items/tc их стало 60 вместо 81.

Показать числа
допосле
items/tc 49119
items/affixes 112152
items/properties 130152
drlg/preset 98134
data/calc 77129
drlg/maze 105122
drlg/room-tiles 89120
drlg/warps 91104
drlg/outdoor 170180
rng/seeds 6276
drlg/README 6075
rng/README 2228

Опись на отсечке: 567 утверждений в статических пакетах, 526 в пакетах на харнессе, 414 заблокированы и 17 подняты самой описью. Из заблокированных у 288 до доказательства не добраться, 73 нужна подменённая таблица, 28 нужна симуляция, 7 нужны два игрока в одной игре и 10 нужна моя игра. В шестой день впереди был двадцать один пакет на харнессе; осталось двенадцать, в порядке, который я задал 20-го: сначала ядро и опоры.

Правила игры

Второе решение проекта в первый день очертило рамки вокруг создания: предметы, монстры, уровни. Шестой день добавил симуляцию. Вечером 16-го третье решение, ADR-0017, добавило то, что в ADR названо правилами игры, две области и три строки на карте, вне порядка фаз симуляции: продвижение по квестам с перемещениями и экономика предметов. Довод: «Реализация, в которой есть каждый путь создания, но нет продвижения по квестам, вейпоинтов и цен, — это не игра, в которую можно играть, и именно на эти дыры тот, кто переписывает игру, натыкается в первую очередь после генератора мира». Правило о доказательствах зависит от формы утверждения. Функция, которая считается один раз, цена, стоимость починки, количество золота, воспроизводится так же, как путь создания; изменение по событию, бит квеста после убийства, очко прочности после удара, воспроизводится по событиям по правилу симуляции. И ADR называет цену: «Квесты зашиты в код. Таблицы квестов нет; 1.14d встраивает колбэки каждого квеста прямо в код».

Квесты и перемещения

Три запуска, 17-го, 18-го и 19-го: 11, 21 и 13 сессий, 45 714 проверок, ноль расхождений. В статическом чтении квестов 596 символов, а спецификация, которая из него вышла, самая «выведенная» на карте, 322 выведенных против 117 подтверждённых, потому что колбэки каждого квеста — это код, и очень многих колбэков ни одна сессия не коснулась.

Что решили запуски. Портал в город берёт три числа, а не пять, как было в чтении: «Оба конца выходят из SUnitCreate уже в своём режиме… так что числа не берёт ни создание, ни следующий за ним SetMode». Дверь на Arreat Summit читает один байт, личный бит квеста 35 «выполнено в этой игре», и не пустила обоих персонажей, собранных для проверки: одного с пустым словом квеста, другого со всеми выполненными квестами. Обработчик квеста 11 пишет бит в слово квеста 12, пока квест 11 выключен, 44 записи. Камни Тристрама нужно трогать в определённом порядке, и порядок — это число с сида квестов, взятое один раз за игру при первом использовании расшифрованного свитка. Перемещение Tyrael в Harrogath — не строка в его меню: в стандартном меню строки перемещения нет, а перемещает объект портала рядом с ним. А задержка после объявления враждебности, которую сообщество называет десятью секундами на выход из города: «подтвердилось для вейпоинтов (10 000 мс), опровергнуто для порталов: ворота портала ждут 5 000 мс».

Две вещи о методе. Ревью третьего запуска понизило строки меню, подтверждённые по скриншоту: «Скриншота для [C] недостаточно». А ночь с 18-го на 19-е стала первой из плохих ночей этих дней: машина ушла в сон примерно на девять часов, игра закрылась, а драйвер продолжал кликать в окно, которого больше не было, пока главная сессия не убила его в 07:23. Теперь у каждой сессии есть сторожевой таймер.

В первом запуске до Hell не дошла ни одна сессия: «скриптовый проход к городскому вейпоинту не удался в пяти запусках на Hell». В третьем дошли две. Ни один вейпоинт не был активирован из спящего состояния, потому что каждый вейпоинт, который встретили сессии, уже был активен. А шаги с боссами в квестах, убийства, которые переключают биты квеста, отмечены как кандидаты на мою игру с пометкой «По-прежнему необязательно». Я их не сыграл.

Экономика

Покупка, продажа, gamble, починка, наём и воскрешение наёмника, золото на полу и золото, потерянное при смерти, и износ предметов в бою. Запуск начался 17-го, переходил из лейна в лейн и закрылся 19-го: 26 525 вызовов расчёта цены по 3 762 различным входам, 138 сумм «починить всё», 22 найма, 14 воскрешений, из них в 4 отказано, 20 потерь при смерти, 1 061 бросок прочности и 1 412 событий износа, ноль расхождений. Второй запуск в тот же день добавил 7 376 вызовов расчёта цены для случаев, которые первый пропустил: крафтовые предметы, починка на Hell, gamble на 3-м уровне.

Спецификация экономики сверила с кодом 22 утверждения сообщества:

Двадцать два утверждения сообщества о ценах и износе против кода

  • подтвердилось
  • подтвердилось с уточнением
  • опровергнуто
  • не покрыто
items/economy 22

docs/specs/items/economy.md, § Leads. Пять из шести опровергнутых воспроизведены и запуском; шестое, про Books, на стандартных данных даёт то же самое.

Показать числа
подтвердилосьподтвердилось с уточнениемопровергнутоне покрыто всего
items/economy 10561 22

Опровергнутые:

  • Эфирный предмет продаётся на 25 процентов дешевле. Он продаётся за четверть: цена продажи сдвигается вправо на два бита. Классовый предмет делится на четыре ещё раз.
  • Эфирное метательное оружие всегда стоит одну монету. Стопка эфирных дротиков ушла за 1 040 у каждого из пятнадцати торговцев.
  • Множитель цены у аффикса считается в долях от 1 024 при покупке и от 4 096 при продаже. Все три значения делятся на 1 024.
  • Столбец gamble cost — это цена gamble. Он читается только для колец, амулетов и предметов версии 0; любая другая цена gamble вычисляется.
  • Броня изнашивается по весам слотов 2, 3, 2, 1, 1, 1 для головы, тела, щита, пояса, ног и рук. В таблице в бинарнике семь слотов с весами 3, 5, 4, 4, 2, 2, 2, и 964 из 964 выборов износа в запуске назвали слот, чей предмет потом и изнашивался.

Что подтвердилось точно: 4 процента на износ оружия и 10 на износ брони за удар, потеря при смерти в min(L, 20) процентов с сохранением 500 золотых за уровень в одиночной игре, цена воскрешения L² / 2 × 15 с потолком в 50 000. И «„Sell mult“ — это цена покупки». Есть функция, которая берёт деньги за лечение, и её никто не вызывает: 1.14d лечит бесплатно. В одном чтение кода ошиблось, и первая же проверка это поймала на четырёх провалившихся воскрешениях: отказанное воскрешение ничего не берёт и никого не воскрешает, чего в находке не было. И деталь клиента, которую запуск заметил по дороге: он спрашивает «Repair… Gold: cost — Yes / No», даже когда заплатить нечем.

Золото, которое пересчитал запуск по экономике

  • Wirt's Leg, деревянная нога вместо дубины: картинка из инвентаря, кадры её падения и персонаж с ней в руках Wirt's Leg: под ней запуск насчитал 18 кучек золота и воспроизвёл каждую

Из tools/item_art.py. Второй запуск по экономике проверил золото, которое падает с тела Wirt: число кучек и уровень предмета у каждой. Графика Diablo II © Blizzard Entertainment.

Два игрока в одной игре

ADR-0008, харнесс на два клиента, висел в статусе «предложен» со второго дня, а принят был 16-го, с одним условием: прежде чем какая-либо сессия создаст игру, лейн убеждается, что порт 4000, порт игры, недоступен снаружи машины, и записывает, как проверял. Это и была моя единственная команда от root за эти дни, 17-го. Запись цитирует вывод ufw status verbose построчно, «Default: deny (incoming)», единственные разрешённые порты, и заканчивает: «Ни одно правило не называет 4000, ни один диапазон его не содержит, и у каждого правила указан порт. Значит, TCP 4000 отбрасывается на каждом интерфейсе, кроме loopback… Условие ADR-0008 выполнено». В запросе лейна было сказано: «Больше ничего не просим: ни зонда снаружи, ни второй машины».

Сам запуск был 20-го: 19 сессий с двумя настоящими клиентами на двух слотах харнесса, причём второго игрока вели по логу первого, потому что у второго нет отладчика; 417 убийств в группе с дропом, 46 событий ассортимента торговца при двух игроках, 385 делений опыта, 12 записей квестовых битов при обоих игроках в игре, 230 атак одного игрока на другого, у каждого чекера ноль расхождений. Четыре раза чекер пришлось менять, и каждый раз ревью постановило: «ошибался чекер, а не игра»; в одном был зашит один игрок. Что нашли два клиента, чего один не мог: доля опыта в группе считается 80-битным произведением доли и уровня с плавающей точкой, без округления до 32 бит, и 98 входов разводят эти два варианта; стандартный клиент не даёт объявить враждебность вне города; у мёртвого игрока свой режим, 17.

Ревью нашло и то, что скрипт, проверявший файрвол перед каждой сессией с открытием игры, всегда завершался с нулём, так что проверка, в которую он был встроен, не остановила бы ни одной сессии. Теперь он падает при любой ошибке, а по правилу его нельзя вызывать без || exit 1. Перетегирование подняло 28 утверждений по одиннадцати спецификациям, случаев с двумя игроками, которые ревизия держала заблокированными, стало 7 вместо 14, и план закрылся 20-го в 15:23. Четыре случая, где два игрока нужны у босса, оставлены мне, «Ничего не блокируют».

Навыки, в двух планах

Третья фаза симуляции — навыки и снаряды, и она больше двух первых вместе: 357 навыков, 64 различные стартовые функции и 138 функций действия на сервере, 684 строки снарядов со своими функциями движения, попадания и урона. ADR-0020, принятый 20-го, делит её надвое: «Если читать ADR-0014 буквально, он держал бы ИИ монстров (фазу 4), пока у каждой из этих функций не появится спецификация после ревью». План 0045 — машинерия, диспетчеризация, сетевые пакеты, снаряды и обработчики событий, и его спецификация считается спецификацией фазы; план 0046 — каталог каждой нумерованной функции, и он идёт рядом с четвёртой фазой, не блокируя её. В тот же день я поменял местами фазы четыре и пять: анимация и тайминг кадров раньше ИИ монстров, «потому что таймингу навыков и боя сначала нужны счётчики кадров».

Статическая фаза машинерии закрылась 20-го. Прогрессивное добивание число с сида не берёт, а подглядывает: сид сохраняется и восстанавливается. Из 61 утверждения сообщества о навыках и снарядах 27 подтвердились, 25 подтвердились с уточнением, 5 опровергнуты и 4 не покрыты, всё по чтению кода и с пометкой «выведено», с оговоркой в находке: расхождение с источником сообщества «может быть изменением из Resurrected». Опровергнутая пятёрка, теперь каждое — случай для фазы на харнессе: уровень поднятого скелета — не уровень заклинателя, а min(max(L × 3/4 + уровень навыка, 1), L); скорость снаряда — (VelLev × lvl) / 8 + Vel, сдвинутое влево на восемь, а не Vel плюс VelLev за уровень; Accel прибавляется на каждом пятом шаге пути, а не каждый кадр; у LevRange нет минус единицы; а снаряд, который промахнулся с пробиванием, освобождается на этом юните, а не летит дальше.

Каталог — это 310 записей, и идёт он в эмуляторе, потому что функцию, создающую снаряд, нельзя тысячу раз прогнать в игре с выбранными входами, а в эмуляторе можно. Пятнадцать пакетов; к отсечке приняты одиннадцать, 230 записей из 310, 99 450 случаев, ноль расхождений. Первую сессию пакета по амазонке убил менеджер памяти до проверки; сохранённый прогон — второй.

После первого пакета понадобился ADR. Большинство функций каталога кончаются вызовом, входы которого нельзя объявить: выделение юнита, планировщик пути, спавн монстра, и лейн останавливал свои случаи на этом вызове и заявлял только то, что происходило до вызова. Ревью решило, что это «не отвечает ADR-0015 (1) и (3) в том виде, как они написаны», оставило утверждения пакета на «выведено» и написало для меня ADR-0021: случай может заканчиваться на наблюдаемой границе, входе в названную вызываемую функцию, где эмулятор останавливается перед первой командой и записывает регистры, стек и память, а на то, что после вызова, утверждение не распространяется: «ничего после вызова». Отвергнутый вариант: прочитать старое правило так, будто оно это уже разрешает, «расширять правило о доказательствах толкованием — дело ADR, а не ревью». Я принял его 20-го в 14:56, и утверждения пакета перешли в подтверждённые без повторного прогона.

Что эмулятор нашёл такого, чего чтение не видело: функция действия у Fend, Zeal и Fury «возвращает 0 на каждом пути»; две стартовые функции передают ноль как attack rating в проверку попадания в ближнем бою, так что бонус Power Strike к попаданию до неё не доходит; бросок стихийного урона у одной функции делается один раз за прогон, а не на каждый юнит, тогда как в спецификации характеристик стояло «на попадание»; попадание Blade Fury создаёт снаряд класса 0, а это стрела; снаряды-кольца никогда не проверяют счётчик шагов, так что счётчик ноль не заканчивается никогда. И одно для паладинов: функция, которую Raise Skeleton и Revive выполняют раньше всего остального, «бьёт заклинателя-игрока класса 3 на maxhp / 8», а класс 3 в порядке классов — паладин; выведено: ни один случай не прогнал это с паладином.

От сида к миру

Каждую спецификацию ядра проверяли с оракулами на границах: там, где значение порождает другая спецификация, его брали из игры, а не предсказывали. Запуск по treasure class читал сид монстра из лога; запуск по дропу читал сид предмета. Так и задумано, ADR-0004, и это оставило вопрос, которого планы никогда не задавали: стыкуются ли спецификации друг с другом? План 0048 его задаёт. Его фаза 0 пересчитала оракулы по спецификациям ядра, 31, и десять из них решила убрать. Фаза 1 убрала восемь: модификаторы посохов, сид юнита после создания, монстров окна пресетов, одну функцию объектов, юниты одного пути расстановки, сид другой комнаты как состояние цепочки, сиды золотых предметов, дроп объекта. Два не получилось: один читается и по-прежнему логируется, один назван и не смоделирован. Инструмент, который гонит цепочку, называется tools/chain.py.

Планка фазы 2 — первое место, где проект требует всё сразу: «2 000 заселений комнат от сида игры до конца (без оракула сида в окне); 300 созданий объектов; 100 особых монстров…; 500 дропов, предсказанных от залогированного сида умирающего юнита через treasure class, качество, аффиксы, уникальность или сет и броски свойств без оракула сборщика». Запуск 1 начался 20-го и шёл всю ночь. Одну сессию оборвало в 20:12, когда менеджер памяти убил агента лейна вместе с драйвером, а игра шла дальше без пилота, пока её не остановил таймер. Другая пережила семичасовой сон машины и прошла проверку без расхождений. Итог: 28 логов, 26 проходят, 156 уровней каждого типа генератора в каждом акте и на каждой сложности, 9 057 объектов, 44 группы чемпионов и 110 уникальных со 147 бросками модификаторов, 849 дропов с монстров с 951 предметом, 2 514 вызовов treasure class и 1 286 созданий предметов, ни одного провала. В двух логах по одному расхождению в модели объектов, и собственное объяснение лейна было ошибочным; по чтению ревью, оба кандидата — монстры, созданные заново после того, как их комнату усыпили и разбудили, «у пересозданных нет строки CM и нет смоделированной отметки». До планки не хватило: 1 222 заселения из 2 000, это ещё около шестнадцати сессий. Запуск 2 сейчас на слоте 1. Строку chain добавили в полосу ядра на ревью фазы 0, поэтому на карте одна строка без ревью.

Первый сквозной запуск против своей планки

Что фаза 2 просила от одного сида игры и что дали 26 проходящих логов запуска 1.

  • просили
  • получили
Заселения комнат без оракула сида 2 000 1 222
Дропы с монстров, предсказанные до предмета 500 849
Создания объектов 300 9 057
Группы чемпионов и уникальных 100 154

docs/plans/0048-seed-to-world.md, условие готовности фазы 2 и исправленные на ревью числа. Не хватило только заселений; запуск 2 ради них.

Показать числа
просилиполучили
Заселения комнат без оракула сида 2 0001 222
Дропы с монстров, предсказанные до предмета 500849
Создания объектов 3009 057
Группы чемпионов и уникальных 100154
flowchart TB
gs["сид игры"] --> lv["сиды и раскладки уровней: drlg/overview, preset, maze, outdoor, warps"]
lv --> ob["объекты, сундуки и святилища: objects"]
lv --> pop["заселение комнат: monsters/pool, spawn, special, stats"]
pop --> kill["монстр умирает: его залогированный сид"]
kill --> tc["treasure class и NoDrop: items/tc"]
tc --> q["качество: items/quality"]
q --> af["аффиксы, уникальные и сеты, свойства"]
af --> floor["предмет на полу со своими характеристиками"]

Как это было организовано

Лейны шли как в шестой день: не больше двух лейнов на харнессе, на слотах 1 и 2, слот 0 мой, не больше двух статических лейнов с Ghidra, у каждого лейна своя копия репозитория, ревью архитектором в порядке поступления, и правило с 20-го: фазу, чьё предусловие ещё не легло, пропускают, а не ждут. Что изменилось — ревью теперь считают. 17-го появился журнал: по строке на лейн и по строке на ревью от проверяющего агента, которого проект называет архитектором: токены, вызовы инструментов, минуты, вердикт и правки по категориям. За эти дни в нём 121 строка лейнов и 107 ревью. Два вердикта — «принято» без оговорок, шесть лейнов влиты без ревью: пять учётных и один по моей просьбе, ни одного «отклонено», остальные 113 — «принято с правками», всего 514 правок.

Что правили ревью с 16 по 21 октября

Каждая правка посчитана один раз, в первой подходящей категории, в том порядке, в каком их перечисляет журнал.

Завышение: тег или формулировка сильнее доказательства 142
Пропуск 112
Неверное чтение: утверждение, которому противоречат код или данные 80
Устаревшая ссылка 45
Другое 43
Ошибка в счёте: число не пересчитано 40
Неверный якорь 21
Занижение 16
Инструмент не сохранён 10
Конфликт символов 3
Склейка учёта 2

docs/plans/metrics.md. Предупреждение самого файла: «Число правок — это классификация ревьюера, а не мера качества лейна: ревью, которое читает больше, находит больше».

Показать числа
правок
Завышение: тег или формулировка сильнее доказательства 142
Пропуск 112
Неверное чтение: утверждение, которому противоречат код или данные 80
Устаревшая ссылка 45
Другое 43
Ошибка в счёте: число не пересчитано 40
Неверный якорь 21
Занижение 16
Инструмент не сохранён 10
Конфликт символов 3
Склейка учёта 2

У журнала есть назначение помимо счёта: каждые несколько ревью проверяющий читает его последние строки и превращает любую правку, встреченную дважды, в правило в собственном списке того лейна, а правило, которое не повторилось за тридцать ревью, убирает. Списки теперь есть, по одному на каждый навык лейна, и у каждого правила написано, на каком лейне его увидели. Из списка реверсера: «Новое чтение кода — это [I]. Для [C] нужен названный второй источник». «Пересчитывать каждое число по бинарнику сохранённой командой, никогда по памяти и никогда по частичному просмотру». «„Никогда“, „только“, „нет X“: говорить, что именно разделяет запуск. Если один случай несёт оба чтения (у Andariel и флаг 0x08, и boss), эта половина остаётся на [I]». А из списка самого архитектора, который он называет своими слепыми пятнами: «Утверждение, решённое на ревью, получает ту же проверку, что и у лейна». «Оценки в плане помечать как оценки».

Бэклог дважды менял форму. 17-го это был один файл в 730 строк и 519 записей, 464 из них вычеркнуты, за два дня в него добавили около 170 записей и «почти каждое вливание лейна конфликтовало в этом файле». ADR-0018 сделал по файлу на запись, без общего оглавления в репозитории, «потому что общее оглавление вернёт ту же горячую точку». Через три дня в папке лежали 55 открытых и 80 закрытых записей, я сказал, что она разрослась, и ADR-0019 перенёс закрытые в архив. На отсечке: 43 открытых, 186 в архиве.

И ночи. 17-го: выключение около 21:38, которое убило сессию на Hell посреди захода. С 18-го на 19-е: девятичасовой сон. 19-го, в воскресенье: к десяти утра три лейна «остановились на лимите использования владельца», то есть на лимите моей подписки, и после этого не легло ничего. 20-го: сбой отладчика под Wine посреди пакета, гонка потоков в gdb 18.1; в 20:12 менеджер памяти убил всех агентов разом, без заметки для продолжения; а с 23:17 до 06:20 машина снова спала, так что журнал записывает 428 из 624 минут одного лейна как сон. Ни одно утверждение от этого не потерялось.

Числа

Где проект сейчас, в сравнении с первым и шестым днём

Спецификации после ревью (28 строк до дня 4, 29 в день 6, 35 в день 8, 36 в день 11)

3 день 1
28 день 6
32 день 8
35 день 11

[C] подтверждённые утверждения в находках

48 день 1
1 150 день 6
1 773 день 8
2 540 день 11

[I] выведенные утверждения в находках

175 день 1
1 189 день 6
1 896 день 8
2 667 день 11

Именованные адреса в Game.exe

278 день 1
1 814 день 6
2 772 день 8
3 373 день 11

Инструменты на Python

26 день 1
91 день 6
144 день 8
170 день 11

Закрытые планы

5 день 1
36 день 6
39 день 8
44 день 11

У каждого показателя своя шкала. Источники: карта исследования, docs/findings, re/symbols.csv, tools/ и docs/plans/done на каждой отсечке.

Подтверждённые и выведенные утверждения в находках

[C] — прочитано в коде и подтверждено чем-то независимым, обычно запуском. [I] — только прочитано в коде. Ночи вырезаны.

  • [C] подтверждено
  • [I] выведено
0 200 400 600 800 1000 1200 1400 1600 1800 2000 2200 2400 2600 2800 11 окт. 12 окт. 13 окт. 14 окт. 15 окт. 16 окт. 17 окт. 18 окт. 19 окт. 20 окт. 21 окт. [C] 2540 [I] 2667

Пустые 18-е и 19-е — сон машины и лимит. 20-го обе линии растут вместе, потому что каждое новое чтение ложится как [I], а его запуск поднимает только часть.

Показать числа
Время[C][I]
11 окт. 10:31 0 0
11 окт. 13:35 7 15
11 окт. 15:05 21 58
11 окт. 16:00 28 59
11 окт. 16:25 42 62
11 окт. 17:57 45 104
11 окт. 19:06 48 148
11 окт. 20:11 48 175
11 окт. 22:12 57 176
11 окт. 22:23 57 176
12 окт. 08:04 80 173
12 окт. 08:41 103 183
12 окт. 09:02 104 184
12 окт. 09:31 108 217
12 окт. 09:58 109 228
12 окт. 10:16 117 278
12 окт. 10:42 135 295
12 окт. 11:51 139 295
12 окт. 12:21 159 291
12 окт. 13:41 161 292
12 окт. 14:10 168 295
12 окт. 15:19 168 320
12 окт. 15:46 184 354
12 окт. 15:58 184 354
13 окт. 08:05 196 348
13 окт. 08:26 204 374
13 окт. 08:33 205 422
13 окт. 10:11 206 448
13 окт. 13:43 223 449
13 окт. 15:59 225 452
13 окт. 18:56 229 453
13 окт. 19:21 236 452
13 окт. 19:28 240 455
13 окт. 21:15 279 429
13 окт. 22:02 279 442
14 окт. 08:11 279 442
14 окт. 08:49 282 443
14 окт. 09:21 282 493
14 окт. 09:36 282 495
14 окт. 09:49 290 536
14 окт. 10:00 291 537
14 окт. 10:09 293 586
14 окт. 10:20 293 587
14 окт. 11:05 332 567
14 окт. 13:10 356 562
14 окт. 17:35 376 560
14 окт. 19:22 376 611
14 окт. 19:56 395 651
14 окт. 20:36 402 691
14 окт. 20:50 446 721
14 окт. 20:59 451 757
14 окт. 21:16 461 796
14 окт. 22:37 506 772
14 окт. 22:50 545 743
15 окт. 02:10 574 733
15 окт. 02:44 587 732
15 окт. 02:54 612 737
15 окт. 03:05 619 727
15 окт. 03:29 629 739
15 окт. 03:57 671 738
15 окт. 04:14 711 716
15 окт. 07:39 718 733
15 окт. 08:47 729 737
15 окт. 08:48 737 779
15 окт. 08:54 746 782
15 окт. 09:05 771 791
15 окт. 09:17 773 848
15 окт. 19:08 774 890
15 окт. 19:10 786 941
15 окт. 19:13 797 940
15 окт. 19:25 801 982
15 окт. 19:33 829 1015
15 окт. 19:38 829 1057
15 окт. 19:48 841 1064
15 окт. 19:56 845 1066
15 окт. 20:13 845 1072
15 окт. 20:24 848 1095
15 окт. 23:42 875 1092
15 окт. 23:54 886 1095
16 окт. 00:15 886 1094
16 окт. 00:21 889 1096
16 окт. 01:43 905 1093
16 окт. 02:23 918 1098
16 окт. 02:28 923 1103
16 окт. 03:49 956 1090
16 окт. 06:40 987 1065
16 окт. 14:29 1003 1072
16 окт. 15:31 1023 1075
16 окт. 16:08 1023 1152
16 окт. 17:21 1080 1181
16 окт. 17:36 1140 1189
16 окт. 17:53 1150 1189
16 окт. 18:24 1174 1194
16 окт. 18:34 1228 1208
16 окт. 18:35 1267 1217
16 окт. 19:26 1281 1238
16 окт. 19:29 1321 1250
16 окт. 20:49 1391 1257
16 окт. 21:01 1412 1263
16 окт. 21:29 1486 1263
16 окт. 22:07 1505 1269
16 окт. 22:19 1515 1306
16 окт. 22:26 1566 1314
16 окт. 22:41 1577 1319
17 окт. 07:51 1577 1367
17 окт. 07:56 1585 1375
17 окт. 08:02 1597 1380
17 окт. 08:35 1612 1432
17 окт. 08:47 1650 1434
17 окт. 09:04 1647 1430
17 окт. 09:09 1647 1512
17 окт. 09:45 1657 1536
17 окт. 09:55 1669 1539
17 окт. 10:44 1670 1729
17 окт. 10:50 1670 1796
17 окт. 10:58 1670 1808
17 окт. 11:07 1681 1816
17 окт. 11:15 1683 1826
17 окт. 16:44 1707 1827
17 окт. 17:18 1707 1838
17 окт. 17:33 1707 1839
17 окт. 18:26 1708 1849
17 окт. 19:16 1746 1858
17 окт. 19:27 1747 1870
17 окт. 20:06 1747 1871
17 окт. 20:56 1770 1884
18 окт. 20:09 1773 1896
19 окт. 08:00 1788 1907
19 окт. 08:10 1804 1923
19 окт. 08:44 1805 1924
19 окт. 09:26 1814 1929
20 окт. 08:30 1849 1953
20 окт. 09:11 1849 1955
20 окт. 09:54 1853 2032
20 окт. 10:17 1856 2059
20 окт. 10:29 1914 2070
20 окт. 10:51 1917 2110
20 окт. 10:58 1947 2125
20 окт. 11:19 1973 2133
20 окт. 11:51 1973 2188
20 окт. 12:29 1973 2189
20 окт. 13:11 2022 2217
20 окт. 13:20 2036 2266
20 окт. 14:53 2037 2268
20 окт. 14:53 2076 2308
20 окт. 14:56 2099 2293
20 окт. 14:57 2108 2300
20 окт. 15:43 2110 2302
20 окт. 15:47 2154 2360
20 окт. 18:55 2178 2374
20 окт. 18:55 2230 2414
20 окт. 19:19 2230 2416
20 окт. 19:54 2272 2450
20 окт. 21:31 2312 2484
20 окт. 22:21 2347 2508
20 окт. 23:11 2381 2538
21 окт. 07:17 2420 2570
21 окт. 07:37 2431 2581
21 окт. 07:46 2445 2586
21 окт. 08:21 2479 2619
21 окт. 11:24 2489 2628
21 окт. 11:53 2539 2667
21 окт. 11:57 2540 2667

В шестой день в находках было 1 150 подтверждённых утверждений против 1 189 выведенных. Теперь 2 540 против 2 667, и доля та же, 49 процентов, потому что каждое чтение новой области приходит выведенным, а запуск подтверждает часть. Спецификации, которые и есть результат, прошли от 2 546 подтверждённых и 1 539 выведенных к 3 791 и 2 322. Именованных адресов в Game.exe стало 3 373 вместо 1 814, инструментов 170 вместо 91, рецептов сохранений 233 вместо 112, закрытых планов 44 вместо 36. Вики, про которую в шестой день я написал, что она хорошая и её нужно дорабатывать, получила страницы про бой, характеристики и состояния, квесты и экономику.

Что открыто

  • Запуск по навыкам. Фаза плана 0045 на харнессе ждёт оба слота: пять опровергнутых утверждений о снарядах, Blaze, навык, который ни один запуск не применял, и обработчик того Fleshripper. Три строки навыков появятся на карте, когда она начнётся.
  • Последние четыре пакета каталога: предметы с Unsummon, потом ещё три.
  • От сида к миру, запуск 2: отметки пересозданных монстров в логе и в модели, перепроверить два расхождения, около шестнадцати сессий.
  • Оставшиеся пакеты ревизии, двенадцать, и 414 заблокированных утверждений, десяти из которых нужен я.
  • Фазы четыре и пять, анимация и тайминг кадров, потом ИИ монстров: плана пока нет; решение о конвейере фаз позволяет плану четвёртой фазы пойти следом за запуском по навыкам.
  • То, что сыграть могу только я, всё помечено как необязательное: кузница, Andariel и Ancients со вторым игроком, шаги с боссами в квестах, пара сессий с Diablo из пакета по квестовым дропам и сессия у Hellforge на Hell ради одного свойства treasure class, где пилот «погиб на 19-м переходе в River of Flame».

Воксельный движок прожил свои пять дней в другом репозитории и прошёл от версии 0.3 до 0.24.