Первая часть рассказа и вторая часть рассказа.
Ночные сидения дают себя знать, и до компьютера я доползаю только к 11:00. Первым делом читаю логи за вчера (еще одна ошибка - за прогрессом товарищей надо следить раз в час) и оцениваю обстановку. Похоже, что jyp вчера завалился спать в 22:30(!), что-то сделав с BLNCE, но не достигнув особых успехов. Lemmih закончил свой 2d-компилятор к 16:00, но остаток дня ушел у него на то, чтобы выловить баги в коде рейтрейсера на этом дивном языке. К ночи баги были выловлены, но оказалось, что за рейтрейсер нам дали не 1200+, на которую мы рассчитывали, а всего 800. Vincenz взялся соптимизировать получившийся результат (фактически, ужать кучу ASCII art-like картинок так, чтобы они занимали меньшую площадь). Lemmih, как и ожидалось, переключился на BLNCE, пробуя "взять" его переборными алгоритмами.
К моему удивлению, утром на канале тишина - похоже, что не один я "сгорел" вчера ночью. К 12:00 в все сползаются в онлайне - даже vincenz, который ушел спать около шести-семи утра, впрочем достигнув своей цели - за оптимизированные решения CIRCS нам дали 1300+!. Мы поднимаемся на седьмое место (не знаю, с какого).
Совещания, как такогово, не происходит. Кто чем занимается - не очень понятно. Я понимаю, что все равно ничем, кроме adventure заняться не смогу, т.к. меня на нем "заклинило". У остальных либо такая же ситуация, либо они спят на ходу. Судя по "darcs changes", jyp продолжает работать над BLNCE, а потом выжимает еще сколько-то очков из CIRCS. Lemmih и vincenz, похоже, спят (на ходу?) после совместной борьбы с CIRCS в течении этой ночи.
Я (наконец-то!) решаю прочитать все доступные в игре источники информации, и обнаруживаю все провтыки, о которых я писал в прошлом посте. И то, что полезные предметы можно собрать, не выходя за пределы комнаты, в которой они лежат, и то, что дальше надо каким-то образом попасть в музей истории науки и техники (а как? с карты нету никаких выходов?), и то, что герой игры - робот, и uploader и downloader нужны для того, чтобы этот робот мог до чего-то там такого добраться.
Я делюсь своим открытиями с женой (очень полезно иметь возможность постоянно с кем-то обсуждать свои идеи, причем не по irc - жалко, что я пользовался этой возможность меньше, чем было нужно). Она говорит, что раз пошла такая пьянка и полезные предметы собираются в рамках одной комнаты, то "вторую карту" можно просто пройти "вручную".
Вот тут бы мне послушать женщину ... и сделать так, как она советует :) Но нет - я допускаю очередную ошибку. Я думаю, что музей науки и техники - это все-таки будут вариации на тему "ходим по карте, собираем предметы", и автоматический solver все-таки пригодится. Я сажусь бороться с прологом, жена пробует свою рекомендацию на практике.
Благодаря вновь приобретенной информации и изменениям в структурах данных, которые я внес этой ночью, работа движется споро. Первым делом я "учу" свой решатель избавляться от максимума ненужного барахла, и в результате мой робот ЖЖОТ! :) Первые действий пятьдесят-сто уходять у него на то, чтобы методично объехать все комнаты и сжечь в них все ненужное барахло :) Через некоторое время я добавляю в код еще пару вариантов поведения, и неожидано добиваюсь существенного прорыва. - из 10 необходимых запчастей для download-ера и uploader-а мое решение автоматически собирает 7.
Я уже в предвкушении того, что сейчас нам обломится жирный бонус (пока что в adventure набирается где-то баллов 150, а максимум - 810). Жена показывает, как собрать вручную три недостающие детали, и вот он долгожданный момент: недостающие запчасти (всего 20 баллов каждая, ну да ладно) втыкаются в downloader и uploader.
5 очков! 5 ОЧКОВ! И это все, что дают за uploader и downloader. "Кот в панике"(с)история про дурдом.
Хуже того - на карте не открываются новые двери или проходы, не появляются новые предметы. Не происходит вообще ничего.
WTF?!
Вспомнив о том, что собраный на первой карте keypad надо было применить, я делаю "use downloader".
На экран выезжает несколько страниц кода(?), и "ключ" на +20 очков. Я копирую код в файл, читаю его, медленно офигеваю, засовываю его в darcs и поднимаю панику на irc. Вот выдержки из кода:
(* * gc.rml - robot mind source for garbage collector (model 3) * * Maps robot consciousness into world engine (i.e. implements lower brain * functions). Carries out motor functions by appropriate calls to system * libraries and routes feedback back to robot perceptual system. * * Updated to match Municipal Censory Engine interface v2 in March 192000. *) [...] fun hide_item (item : item) : datum = (* XXX a big hack -- let's hope we are never audited! *) case room_from_name (TRASH) of NoRoom { } => return failed_command ("incinerate", describe_item (item), "internal error (report for maintenance!)") | SomeRoom { trash } => [ do move_item_to_room (item, trash). return success_command ("incinerate", describe_item (item)) ]. [...] (* Main handler: all robots must define a function "process" of type command -> datum The resulting data will be sent downstream to the Censory Engine and finally to the robot perception systems. In addition to the resulting perceptions, non-passive robots may also affect the world using the library calls above. This function will be called at each time step where the robot consciousness has issued a valid command. *) fun process (c : command) : datum = case c of Go { d } => [ let r1 = here (). case neighbor (r1, d) of NoRoom { } => [ let s = direction_tostring (d). return failed_command ("go", Atom { s }, "there is no way " ^ s ^ " from here") ] | SomeRoom { r2 } => [ do move_self_to_room (r2). return success_command ("go", describe_room (r2)) ] ] [...]
Я нахожу в коде место, в котором делается проверка на то, что в inventory нельзя засунуть больше 6-и предметов, меняю 6 на 666, и делаю в игре "use uploader". Мне отвечают "enter the mind source code, terminated by EOM"! Я делаю paste моего варианта, вбиваю руками EOM и мне говорят - "code is verified and valid, mind updated". Проверка показывает, что теперь действительно можно брать больше шести предметов!
Тут моя челюсть отваливается еще раз - я пишу программу на диалекте ML, которая исполняется в виртуальной среде игры adventure, которая исполняется в виртуальной среде UMIX, которая исполняется в виртуальной среде написаной нами UM!
В irc бодрствует один vincenz, который быстро въезжает, что к чему, и мы с ним наперегонки пользуемся возможностью "hack the system" :) Робот получает возможность: брать неограниченное кол-во предметов, класть их на пол, "воскрешать из пепла" раннее сожженные предметы (который, как видна из приведеного выше куска кода, просто перекладываются в некую специальную "мусорную" комнату), телепортироваться в любое место карты (если знать его название).
После чего мы телепортируемся в музей истории науки и техники, благо имя соотвествующего location-а четко прописано в записке, лежащей на второй карте.
Чуствуешь себя обманутым с особым цинизмом. За это мега-достижение, которым я уже почти приготовился гордится, нам дают ... очередные 5 очков!
До конца контеста остается около 1.5 часов.
Ладно, война - фигня, прорвемся. В музее науки и техники обнаруживается аж три комнаты. Одна - пустая, одна - чертежом, одна - с 52-я предметами, при ближайшем рассмотрении составляющими полную колоду карт.
Облом, чертеж нельзя прочитать - [__REDACTED__]. Пресловутый Censory Engine в действии. Ну, мы ж уже модные хакеры - сейчас мы его description засунем ему в, допустим, поле condition, и будет у нас не "blueprint, in pristine condition", а "blueprint,
А фигушки - куда description не суй, все равно получается [__REDACTED__]. Перечитваем все записки. Получается, что описание "запрещенных" предметов "вырезается цензурой" именно в момент вывода на экран, а внутри "мозга" со значением description вполне можно работать. Одна беда - Censory Engine "отслеживает" все значения, вычисленные из описаний "запрешенных" предметов. И попытка вывести результаты таких вычислений все равно превращается в [__REDACTED__] (т.е. в этом ML-интерпретаторе реализовано что-то типа perl-овского taint).
Пол-часа возни в попытках как-то вывести description подтверждают, что информация не врет - как ни крути, а получается только [__REDACTED__].
На этой печальной ноте и наступает окончание ICFPC-2006.
Как показало общение в IRC сразу после окончания contest-а, народ пользовался подсказкой о том, что "Censory Engine blocks your perception, not your actions", и преващал описания запрещенных предметов в серии определенных манипуляций с inventory, которые можно было наблюдать и на основании этих наблюдений char-by-char декодировать описание. Не знаю, был ли это правильный или самый простой способ, но именно так народ шел к максимуму - к 810-и очкам. Как я понял, после музея науки и техники есть как минимум еще одна карта, и вот она-то - на тему "ходим и собираем предметы"...
Печальные итоги подведем
Прошло трое суток.
Мы набрали 3595 очков.
Мы заняли, скорее всего, место ниже десятого, но выше двадцатого.
Это лучше, чем все мои предыдущие ICFCP-шные результаты.
Я получил в 10 раз больше фана, чем на всех предыдущих ICFPC, вместе взятых.
Я доволен своей командой (ну, возможно - за исключением jyp-а).
Lessons learned с прошлого ICFPC, которые "сыграли":
* "Готовить команду сильно загодя" - мы готовили, и это себя оправдало.
* "Вовремя спать и есть, невзирая ни на что" - так и было, вплоть до последних суток. Надо было держаться до конца :)
Lessons learned, которые "не сыграли":
* "Tests are your salvation" - мы подготовили две test harness, для QuickCheck-style тестов, и для HUnit. Ни та, ни другая - не пригодились, т.к. результаты работы кода можно было тут же проверять верификаторами, живущими в UM. Впрочем, это просто невезение, и в следующий раз я обязательно буду готовиться к написанию богатого на тесты кода.
Новые lessons learned:
* Рядом обязательно должен быть кто-то, с кем можно (постоянно и на родном языке) обсуждать то, что ты делаешь. От собеседника требуется минимальное понимание того, что такое програмирование, и любовь к решению головоломок. Глубокий background в IT - только приветствутеся. Еще раз привет любимой жене :)
* На подобные беседы надо тратить минимум час в сутки. Лучше - на прогулке по свежему воздуху. Лучше - два раза в день, утром и вечером. Три - вообще хорошо. Если бы я половину того времени, что я провел in the zone, борясь с собственным кодом, потратил на обсуждения и размышления - результат был бы совсем другой. Особенно хорошо это понимаешь, когда после окончания контеста начинаешь обсуждать (в расслабленом режиме) задачи и провтыки, и за пол-часа придумываешь сразу несколько ярких идей ... но поезд уже ушел :(
* Планирование регулярных status report-ов от всех членов команды и неукоснительное соблюдение графика - is a must. Будет это раз в час или раз в день - не важно, главное - чтобы оно было, все понимали нужность мероприятия и добровольно в нем участвовали.
* Всегда, постоянно, надо давать feedback товарищам по команде. Застрял? Скажи. Нет идей? Скажи. Движешься вперед? Скажи. Сам найди 30 секунд и скажи, а не жди, пока тебя начнут дергать.
* Если застрял - надо все-таки делать над собой усилие (насилие?) и бросать нафиг задачу (переключаться), даже если в нее уже вложено сутки времени. Передай ее другому, обстоятельно расскажи о своем прогрессе и препятствиях - глядишь, в процессе рассказа сам поймешь, в чем причина и где решение :)
* Любой самый маленький успех должен немедленно быть закреплен commit-ом.
Возможно, выводы кому-то покажутся очевидными, но именно очевидные веши имеют свойство быть забытыми в самую первую очередь :)
Резюме
В следующем году - не ниже третьего места :)
UPD:
На наш код можно посмотреть так:
darcs get --partial http://adept.linux.kiev.ua/repos/icfpc2006
Кто хочет насладиться полной историей изменений - уберите ключик "partial"
← Ctrl ← Alt
Ctrl → Alt →
← Ctrl ← Alt
Ctrl → Alt →