ICFPC 2019

В этот понедельник закончился трехдневный марафон под названием ICFPC. Это такое соревнование, где команды программистов со всего мира пытаются на время как можно лучше решить некую задачу. В этот раз – обход лабиринтов с разным доп. инвентарем. Условия можно прочитать здесь. Это как бы отчет, но на самом деле памятка самому себе на случай, если буду играть еще через год.

Мне очень понравилось. То есть я конечно устал как собака, но есть что-то приятное в том что этот опыт а) имеет конечную продолжительность, а не тянется годами, как основная работа. И б) можно полностью отдаться задаче, не думая о том зачем это все и что ты делаешь со своей жизнью. Такой вот повод упоенно фигачить на полной скорости какое-то время, чтобы ветер свистел в ушах. Ну и просто весело.

Очень любопытно посмотреть, чего ты стоишь. В голове-то ты мог много себе про себя нафантазировать, а тут вот объективная реальность, ладдер, и ты либо можешь компьютер заставить делать что ты хочешь, либо не можешь. Никаких «если бы», никаких «возможно, наверное, мне кажется». Мы довольно посредственно выступили (на момент закрытия 29 место из 142 участвовавших, в лучший свой момент были на пятом).

Исторический скриншот. Дальше мы сильно сдали
Исторический скриншот. Дальше мы сильно сдали

Участвовали втроем, я в первый раз. Как я понял, средний размер команды ~5 человек, не редкость и восемь встретить. Втроем у нас довольно хорошо делились области ответственности, было бы больше появился бы организационный оверхед (как мне кажется). Восемь человек я бы вообще офигел менеджить и вообще ничего бы не написал, наверное. С другой стороны, больше рук – можно попробовать больше подходов. Можно вложиться в инфрастуктуру. Наверное.

Задача достаточно нетривиальная, чтобы решить ее до конца было в принципе невозможно. Но и не супер-сложная, чтобы как-то ее решить можно было бы даже иногда и руками (ну, самые простые примеры). Как правило это значит перебор вариантов в каком-то NP-полном поле, соревнование эвристик.

Собери бонусы, закрась лабиринт
Собери бонусы, закрась лабиринт

Clojure, несмотря на все плюсы языка высокого уровня и быстрого iteration time, по ощущениям подошла довольно плохо. Потому что все упирается в перформанс. Можно сколько угодно рассуждать про «глобальные оптимизации против локальных», ненавидеть байтоебство, мыслить как стратег с высоты птичьего полета и гордиться тем, что не знаешь, как устроен компьютер, но это все и в императивных языках можно делать. Они же не отнимают способности мыслить и планировать. Да, механика записи мысли чуть более многословна, ну зато оно того стоит. Плюс за три дня вы разницы может и не заметите даже. А вот по перформансу заметите, еще как. Как ни крути, а команда, которая обсчитает за условное время X в два раза больше вариантов, чем ее конкурент, будет в топе выше. КАК НИ КРУТИ. Больше здесь строго лучше. Либо больше итераций, больше вариантов попробовать, либо решения будут более глубокими, а значит и очков принесут больше.

ICFPC это как раз такой случай, когда лучше чуть больше устать но получить программу которая будет нагружать процессор по делу, а не только мусор за юзером подбирать. К тому же, как ни странно, старые императивные языки может и не очень легко позволяют до энтерпрайзных масштабов раздувать программы, но что-что а бегать по массивам и мутировать структуры они похлеще функциональных могут. Ирония – соревнование приурочено к конференции по функциональному программированию, а побеждают в нем все стабильнее C++ и императивщина.

Выглядит красиво, жаль вся эта мощь обслуживает всякое говно вроде lazy sequences, primitive boxing, high-order functions вместо того, чтобы решать задачу
Выглядит красиво, жаль вся эта мощь обслуживает всякое говно вроде lazy sequences, primitive boxing, high-order functions вместо того, чтобы решать задачу

Сейчас я думаю, что даже если бы мы выбрали просто Java с unboxed примитивами и примитивными массивами, было бы качественно лучше. C++/OCaml/Rust может быть дали бы еще 1,5-2 раза прирост, но это уже не изменило бы ситуацию качественно. Но может и нет, цифры так, с потолка.

Про типизацию – да, было определенное количество багов, связанных с опечатками и лукапами не в тех структурах. Конечно типы бы от этого спасли. Но был и интересный момент, когда под конец соревнования понадобилось кардинально поменять интерфейс решателя задач, и вот тут отсутствие типов позволило мне зарефакторить решатель, оставив генератор (вторую большую часть программы) на старых структурах. В статически типизированном языке мне пришлось бы рефакторить всю программу целиком, что съело бы ценное время. Конечно, это просто забавный аргумент, курьез, я его привожу тут только потому, что все остальные традиционные скучные примеры традиционно указывают в обратную сторону.

Да, я думаю именно в этой ситуации—сверхинтенсивной коллаборации над одним маленьким сверхчасто редактируемым куском кода—типы бы больше помогли, чем мешали — их нужно немного, по сути это структуры даже просто, которые спасли бы от глупых опечаток. В более спокойной обстановке, без цейтнота, оба примера, и опечатки, и рефакторинг, не имели бы такого веса, когда есть и тесты, и время сделать все нормально.

Кстати, многие ошибки, которые все-таки у нас были, были связаны с подстановкой переменной того же типа, где никакая система типов бы никого не спасла. Ну оно и не удивительно, когда у тебя большая часть программы, процентов 90, гоняет инты направо и налево. Это же алгоритмы.

не с этого хакатона, но смысл такой же
не с этого хакатона, но смысл такой же

Очень важно оказалось докапываться до причин каждой странности. Удивительно, на самом деле, насколько программа может как-то работать и выдавать решения, имея локальные проблемы и ошибки в каких-то местах. Почти как нечто живое, выживающее. Пару багов мы поймали просто глазами, когда увидели, что бот иногда на пару ходов ведет себя странно, хотя и решает в итоге все задачи.

лабиринты, генерируемые нашим алгоритмом, имели хорошо узнаваемый вид
лабиринты, генерируемые нашим алгоритмом, имели хорошо узнаваемый вид

Очень важна базовая гигиена. Ну там код неиспользуемый удалять, переменные нормально называть, на функции разбивать нормально где нужно, не писать по два-три раза почти одно и то же, если уже написано. Казалось бы, тоже — хакатон, вы через три дня все это выкините, так ли это важно? Вот оказалось что да. Потому что там где в обычном проекте косяки может через полгода-год всплывут, здесь если ты что-то поленился, коллега уже через полчаса об это споткнется. Причем споткнется обязательно, потому что кода мало и все используют всё постоянно. Так что лучше пять минут потерять, но поправить самому, пока контекст у тебя в голове, чем заставить коллег тебя материть и тебя же дергать. Чисто по времени выгоднее. Несмотря на.

Пилу нужно точить. Как бы ни казалось, что три дня уж без удобств можно прожить, удобства все-таки решают. Мы очень страдали от отсутствия визуализатора. Организаторы предлагали готовый, но в браузере (на ScalaJS кстати), и это не оч удобно было (для каждого запуска нужно было накликать мышкой и выбрать два раза через диалог выбора файла два файла).

Визуализатор организаторов
Визуализатор организаторов
ух как же меня бесило выбирать эти файлы каждый раз!
ух как же меня бесило выбирать эти файлы каждый раз!

Самое большое, чего там не хватало — пошагового реплея, перемотки назад и вперед, ну и доп информацию тоже иногда хочется какую-то вывести. Как разбился лабиринт, что думает бот, такое. Я написал в какой-то момент простой визуализатор через println и clear screen, он даже мультики показывал типа, но хотелось бы чего-то более удобного и универсального.

То же самое касается проверок на ошибки, на тупизну, на то что задача в принципе дорешивается. Причем желательно чтобы это был код независимый от основной codebase — какое-то довольно продолжительное время мы отправляли задачи и не знали, что часть из них тупо не принималась организаторами, хотя мы думали, что все решили. Тесты, конечно, писать некогда. Но вот ассерты, ассерты помогают. Иногда как раз такие странные косяки ловить, когда вроде и все еще работает, но какое-то ожидание нарушено, и значит где-то что-то пошло не так, как ты думал.

Приходить надо было подготовленным. У ребят, например, из контура, была инфраструктура заготовлена: сервера, гоняющие задачи, сбор ответов, дашборд, сравнение. Мы этого, конечно, не знали, у нас в лучшем случае запустил программу на ноуте — в терминал вывалился результат. Пик инфраструктуры.

Очень пожалел, что не сделали систему сбора и записи всех прогонов, чтобы из всего массива запусков периодически выбирался бы лучший вариант. Ведь если на какой-то специфичной версии алгоритма какая-то специфичная карта особенно удачно решилась, нет причин не отправлять это решение, даже если алгоритм потом менялся десять раз. Ну и сравнивать эффективность решений наглядно было бы полезно (мы потом похожую штуку сделали, но решения надо было вручную в репозиторий коммитить, такое себе).

Вторая безусловно полезная штука, которой нам не хватало — центр координации, который бы следил, какие задачи где считаются, и раздавал работу. Так можно было бы и решать быстрее (запустил на всех ноутах, и задачи считаются разные, не пересекаются), и гипотез разных потестировать, и на дашборд красиво вывести. Ведь известно заранее, что будет N задач, у каждой есть вход и выход, инфраструктура под это довольно универсальная получается.

Как правильно распределять силы я пока не понял. Я выложился по максимуму в первый день (до 6 утра, на следующий встал в 11) чтобы как можно больше впихнуть в Lightning Round (первые 24 часа). В результате весь второй день был как в тумане и работалось как на автопилоте. В третий зашли нормально, я переписал алгоритм даже, но тоже было очень тяжело. Возможно, здоровый сон каждый день (ну ок, кроме последнего) суммарно дал бы больше эффективности за три дня, чем такое.

Перерыв на обед
Перерыв на обед

В целом мне кажется, мы выступили неплохо для первого раза, но в целом неудовлетворительно. По ощущением наших сил едва хватило, чтобы выкатить самый простой жадный алгоритм с самым простым lookahead и мы даже не преступили к стадии, когда тестировали бы разные гипотезы и прочие умные идеи бы пробовали. То есть просто боролись со сложностью задачи.

С высоты

Про Clojure и что я все сильнее про него ощущаю.

В каком-то смысле это продолжение моих размышлений, куда податься после Software Disenchantment, когда я понял, что надо что-то менять, но не понял, на что именно.

Да, Clojure это прекрасный, замечательный высокоуровневый/прикладной язык, лучший на свете. Прикладной в том смысле, что на нем хорошо писать программы, решающие конечную задачу – обслуживать, например, бизнес. Ну да, таких задач большинство. И ценности у них как раз вполне конкретные. Ясность коммуникации. Изоляция-локализация частей. Предсказуемость, надежность.

Во всем этом Clojure не просто блистает, она открывает следующий уровень. Иммутабельность снижает ошибки, функции хорошо композируются, мапы удобнее классов, и т.п. Да, Clojure позволяет двигаться безумно быстро. Скажем, загрузить файл, распарсить его, разложить аккуратно по нужным структуркам – это делается буквально за несколько строк. На таких скоростях не до абстракций — загрузчик, класс, конструктор, интерфейсы, методы... все это тупо не нужно, когда ты в одном инлайн выражении, даже имен никаких промежуточных не вводя, не то что классов, можешь столько работы проделать, сколько в Джаве обычно на целый maven-пакет размазывают.

Прикладные задачи нужно писать на настолько высокоуровневом языке, насколько позволяют требования по производительности. Ну вы все видели бум электрон-приложений. Если пишешь что-то типа сайта с тремя калеками-посетителями в день, или там мобильное приложение для листания фоточек, где все привыкли к latency и самое сложное что тебе предстоит это ну максимум побороть лайаут чтобы кнопки не распидарасило, то писать как-то по-другому, по-старому, было бы глупо. И это правильно, при прочих равных, писать надо на том, на чем писать приятно. А писать на Кложе приятно очень.

Но мир интереснее и разнообразнее, а писать такое все могут. Непонятно, как там выделяться, делать что-то значимое. Лучшее, что ты можешь на такой работе – взять что дают, максимально ясно все описать и максимально аккуратно все организовать. Такие себе цели. В смысле, достойные, но не так уж и сложно, каждый второй так может.

Хочется что-то более фундаментальное, что-то, чем будут пользоваться другие программисты, что-то, что хоть немного изменит ландшафт. Элементы инфраструктуры, базовые алгоритмы, структуры данных. Основы. И вот тут уже выбирать не приходится. Они должны быть настолько быстрыми, насколько это возможно. Оправданий делать наоборот быть не может. Никто не пойдет писать базу данных на JavaScript, потому что ей потом никто не будет пользоваться, с такой-то скоростью. Ну примерно как автомобили – если ты потребитель и купил машину, можешь ездить на ней как и когда хочешь, она может годами у тебя стоять без дела, можешь пользоваться ей неправильно, заправлять не тот бензин, всем пофиг. Но если ты делаешь эту машину, то будь добр выложись по полной – каждый узел, каждая деталь должны быть сделаны на пределах текущих возможностей и по качеству, и по производительности.

Никого не волнует, насколько инженеру хотелось бы и было бы удобнее печатать, скажет, фару на тридэ принтере из резины. Важен только результат. Большинство программистов вокруг нас пишут на прикладных языках высокого уровня – они просто ездят на машинах, они потребители. Но для того, чтобы они могли это делать, сами машины должны быть сделаны максимально хорошо.

И вот меня тянет как будто все больше в эту область. Инструментов, основ каких-то, значит. А трагедия в том, что моя любимая Clojure ну никак для этого не подходит, как бы мне этого ни хотелось. Чем дальше, тем больше понимаешь, что эта чудесная простота дается не бесплатно. Просто задачи были такие, что небесплатность была незаметна. Приглядишься бывает, с одной стороны hot loop из семи залуп, а с другой внутри вдруг вылазят какие-то промежуточные сиквенсы, какой-то там pointer chasing, primitive unboxing, вспыхивают на доли секунды замыкания просто чтобы что-то найти в трехэлементном массиве с помощью функции второго порядка, для того чтобы вернуть 2д точку выделяется на всякий случай целый Персистентный Вектор, для того что бы обновить пять полей в структуре у тебя создастся и тут же выбросится четыре промежуточных версии этой самой структуры, а вместо того чтобы посчитать что-то в цикле создастся целая ленивая последовательность, которая, фиг бы с ней, посчитается позже, просто сколько же оверхеда уйдет на то, что по сути могло быть простой итерацией с одной short переменной и оперировать вообще по константной памяти, еще и последовательно уложенной.

Вот кусок, написанный на идиоматичной Clojure:

(concat
 (mapv
    (fn [y] [from-x y])
    (range from-y (quot to-y 2)))
  (mapv
    (fn [y] [to-x y])
    (range (quot to-y 2) to-y)))

Тут тебе все: и ленивость (concat), и ФВП (mapv), и лямбды с замыканиями, и бесконечные ленивые последовательности (range). Вопросов нет, это действительно нормальные, часто используемые Clojure примитивы. Я даже не могу этот код назвать не-идиоматичным. Но. Просто представьте, сколько механизмов там крутится под капотом, чтобы вся эта красивая запись отработала. А ведь все что там по сути происходит это один очень простой цикл:

Point[] res = new Point[to_y - from_y];
for (int y = from_y; y < to_y; ++y)
  res[y - from_y] = Point(y < to-y / 2 ? from_x : to_x, y); 

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

Когда мы говорим о разнице между условными C++/OCaml/Rust, Java и скажем Clojure (особенно средне-идеоматичной Clojure, с коллекциями там всякими), то эта разница может быть 1 к 2-3 к 100 например очень легко. Я помню, когда решал Project Euler и учил Clojure и OCaml, то Кложе-решения мне приходилось ждать какое-то ненулевое время (ну там задачи не шибко сложные, но все же). А OCaml успевал перекомпилять (!) программу, запустить, все обсчитать и выдать ответ за время, пока Java-машина с Clojure только стартовали.

Да, язык формирует образ мысли. Так или иначе, когда язык уже выбран, поиск решения – это вертеть в уме разные варианты имеющихся в нем кубиков, комбинировать, собирать решение из того, что язык предлагает. Можно мыслить на языке. Писать идиоматичный код. Но неплохо бы еще мыслить «на языке компьютера», т.е. представлять себе цену всех этих удобств. Выбирать неуклюжий reduce комбинации из ФВП и трединга. Вынести в record то, что лежало в мапе. Сделать loop, наконец. Иногда цикл это всего лишь цикл. И никак по-другому ты его не запишешь. И это нормально. Компьютер скажет спасибо.

Но это полдела. Если уж быть до конца честным, Clojure для perf-critical подходит из рук вон плохо. Даже Java подходит с очень большой натяжкой. То есть ее конечно можно разогнать, но зачем? Зачем героически бороться, чтобы в конечном итоге все равно, пусть немножко, но проиграть, потерять что-то? В итоге все упирается в то, что лучшее что я могу сейчас делать – учить Rust. А дальше-то что? Что на нем писать-то? Непонятно опять. Проблема.

Справа налево

Не хочу специально набрасывать, но вот вчера попалось на глаза и я прям прослезился.

Смотрю, что если в столбце справа путь «abc+что-то», то все нормально. Как только что-то пропадает, «abc+» превращается в «+abc». При том что в DOM мы отдаем совершенно точно «abc+». Одним текстовым блоком. Никаких там вам флексов, это уж точно. Как так? Что-то с глазами? Как такое вообще возможно? Кто вообще посмел раздербанить мою строку, да еще по каким-то дебильным правилам, и если подобное возможно, на какие гарантии в принципе можно рассчитывать? Начитавшись Лю Цысиня, я решил, что инопланетяне нарочно играются с моим мозгом с целью свести меня с ума.

В итоге расследование привело меня типовое решение со StackOverflow. Оказывается (!) веб-разработчикам в целом как-то лень бывает городить лишний вложенный div, и они придумали: а чего бы не заабюзить свойство direction для арабских языков? Только писать в него все равно латиницей. Гениально!

Ну да, текст начинает как бы выравниваться по правому краю. Есть правда нюансы. Цифры, разделенные пробелами, переворачиваются. Знаки препинания переезжают налево. Диапазоны показываются задом наперед, от большего к меньшему.

Проблема? Проблема. Блин че делать? Читаем: you need to wrap the contained elements in another element with direction: ltr rule to reverse the effect. Классическое «придумал себе проблему и героически ее решил». Ооок.

Да, это самый популярный ответ на то, как обрезать текст слева. Да, авторы с удовольствием принимают такой ответ.

Ну и веб он весь такой. Сделают что-то задом наперед, заабюзят супер-редкую фичу из даже не смежной области, как-то где-то в каких-то тепличных условиях один раз заработало и так и оставили, а на картину в целом смотреть не интересно. Может, даже на конференции про это расскажут. Не, а что, смекалочка же.

Инстаграм. Истории

На тридцать пятом году жизни я понял наконец зачем и почему сторис в инстаграме. Мне они казались жутко неудобными по всем фронтам — листать фиг пойми как, приблизить нельзя, рассмотреть/прочитать ничего не успеваешь — следующая включается. В итоге сидишь как дурак, держишь пальцем в полупролистнутом состоянии, и на оставшейся половинке экрана пытаешься разглядеть, че там вообще сфотано.

Для меня была самоочевидной идея, что потреблением контента надо управлять. Чем больше управления и оно точнее, тем лучше. Поэтому, например, я так не люблю всякие анимации на сайтах. Они стараются сделать мне красиво, но мешаются, когда мне нужно самому что-то найти. Превращают интерактивный медиум в пассивный. Сторис в этом смысле собрали в себя все плохое. Как с таким плохим дизайном можно так долго жить, думал я?

Оказалось, неверными были мои ожидания, а не дизайн инстаграмма. Надо положить телефон, включить первую сторис и начинать есть. И все. Они идеально работают именно без рук. Телевизор такой.

А если пользоваться неправильно, будет сильно неудобно. Больно даже.

Клавиатуры и дизайн

Сразу предупреждаю: это будет странный, открытый пост без вывода и готового решения, а пишу я его только для того, чтобы как-то сдвинуть собственные размышления с мертвой точки.

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

Так вот, об изъянах. Давайте их быстренько перечислим, чтобы вы могли ход рассуждений проследить. Пост как бы не о них, но они важная часть нарратива, кроме того, это самая практичная и интересная его часть, я полагаю.

Первое: смещенные ряды.

Вон артемий лебедев сначала две собственных клавиатуры сдизайнил, а спустя аж тринадцать (!) лет внезапно открыл целую формулу, на сколько долей у клавиатур кнопки смещены. Как будто это основополагающий принцип какой, смещение это. Нет, обычный исторический курьез, деталь, которая давным давно ни для чего не нужна, но по привычке осталась. Типа аппендецита.

Так вот, ряды смещены, потому что в печатных машинках  из-под каждой кнопки вверх шел здоровый металлический рычаг. Крепился он под центр кнопки, соответственно, физически одну кнопку ровно под другой разместить было нельзя. Вот и придумали сдвигать ряды. Тоже, кстати, красивое решение.

Четыря ряда — смещение на четверть. Вот и вся формула, блядь, как сказал бы Артемий.

Разумеется, в компьютерных клавиатурах никаких штырей никуда не идет, так что кнопки можно разместить как угодно, хоть на шарике.

Поэтому встает вопрос: а есть ли какое-то эргономическое преимущество у смещенного расположения? Оказывается нет, оно вредит даже. Пальцы вместо того чтобы предсказуемо ходить вверх-вниз по колонкам должны двигаться по странной траектории и находить кнопки в странных местах. Клавиатуры, лишенные этого недостатка, называются ортолинейными (ortholinear).

Вторая беда — угол расположения кнопок. К сожалению, руки у человека растут не из живота, как хотелось бы производителям клавиатур:

А из плеч. Поэтому для работы на традиционной клавиатуре их приходится неестественно изгибать:

У всех, кто так работает, в старости руки превращаются вот в это:

Если рассудок и жизнь дороги вам, не гуглите “Ulnar Deviation”
Если рассудок и жизнь дороги вам, не гуглите “Ulnar Deviation”

Так что вы там это, любители ноутбуков, поосторожнее. Идите там на улице погуляйте лучше, нечего на своем компуктере сидеть. В бадминтон поиграйте, не знаю.

Решается проблема довольно просто: делаем клавиатуру изогнутой. Вуаля:

И ваши руки теперь ну хотя бы не изгибаются в противоестественных местах.

Но тут кродеться проблема №3: люди-то оказывается разные. Я как человек ростом значительно выше среднего, остро это ощущаю, например. А у других людей вообще разная там ширина плеч, длина рук, глубина стола (глубина стола у меня как у человека довольно-таки средняя, надо признаться). Короче, угол входа рук в клавиатуру у всех разный. Поэтому если этот угол захардкодить, то он может просто не подойти. Как всегда случается, у некоторых производителей уже все формы отлиты, картинки на сайт поставлены, а человек такой взял и вырос больше, чем расчитывали! Проблема.

Что делать? Ну а что делать? Надо вынести угол в конфиг, конечно. Такие клавиатуры есть, называется эта фича «split», выглядит так примерно:

Меняй угол как хочешь, хоть параллельно на ширину плеч ставь. Ну и понятно что ничего лучше для роскошного проветривания подмышек прямо во время кодинга еще не приудмали.

Следующая проблема это цифровой блок. Короче, основное эргономическое наблюдение насчет работы с устройствами ввода такое: чем меньше надо двигать рукой, тем быстее и эффективнее ощущается работа (да и связкам полезнее, ну вроде — я ж не врач). Почему некоторые программисты яро не любят мышь? Да потому что за ней тянуться надо. А это далеко. Особенно если через цифровой блок.

Я вообще-то готов объявить цифровой блок в принципе бесполезным. Выкидываешь его и всем легчает. Мышь рядом, все счастливы.

И поверьте, в мелких движениях кистью даже лишних два сантиметра это разница между жизнью и смертью.

Ну а если цифровой блок прям нужен-нужен, ну поставьте вы его налево, где он и присутствовать будет, и мешать не станет. Microsoft, кстати, это осознала и сделала блок в Sculpt автономным. Клади куда хочешь (хотеть надо слева, а не там куда обычно — просто уточняю):

Правда в следующих ревизиях они его прибили гвоздями обратно. Наверное, люди слишком мало им пользовались, и кто-то решил что раз не хотят заставим. Но это шаг назад конечно.

Продолжая тему коротких пальчиков, которые не хотят далеко ходить. На клавиатуре есть так называемый home row — это дефолтное положение, где предполагается что будут лежать ваши пальцы, прежде чем что-то начать печатать, «стартовая» позиция. 

Ну как стартовая — она же и конечная, и промежуточная, как зона комфорта короче — выбежал, сделал че-то и скорей-скорей вернулся. Под эту позицию на кнопках F и J даже делают пупырышки, чтобы ты %username% мог с закрытыми глазами среди ночи найти этот самый home row. Скандалы интриги расследования. Не рассказывайте артемию.

Одна беда — home row в середине, а кнопки управления курсором далеко. А у программиста какое любимое занятие? Правильно, курсор туда-сюда гонять. Тут тоже решение довольно простое — управление курсором надо вынести на home row, с модификатором, тогда пальцы никуда далеко таскать не нужно будет. И вот тогда заживем! (п-с-с! Как это сделать написано тут).

Ну а раз курсор мы перенесли, можно еще место справа освободить, и мышь станет еще ближе, а клавиатура еще компактнее. Это все называется 60%. Типа, всего 60% клавиш от full-size клавиатуры, а так же удобно и ничем не уступает.

В жизни:

Можно пойти еще дальше и сказать, что пальцы штука короткая и двигаются они комфортно в лучшем случае на расстояние одной соседней кнопки от home row, дальше уже связки растягиваются, а там и сколиоз, и артрит, и геморрой с могилой. И если избавиться от четвертого и пятого рядок кнопок (цифры и F-кнопки), станет еще удобнее.

Так мы придем к идее 40% клавиатуры: у тебя есть несколько модификаторов, которые полностью меняют назначение кнопок. Таким образом какая-нибудь буква G это не только G, но и цифра 5, и процент, и какая-нибудь там открывающая скобка, в зависимости от нажатого сейчас модификатора. Пальцы далеко от home row не уходят, всё рядом, сплошные профиты.

Сколько модификаторов нужно? Вообще хватает двух, как ни странно. Вроде кажется, как же так, кнопок же дофига, не влезет же ничего! Но если раскидать, оказывается, что влезает очень даже комфортно. Да там еще и место свободное остается! (40% * 3 = 120% для математиков в треде)

Следующая все еще весьма разумная идея (да они все так или иначе разумные) это что большой палец у нас мышца здоровая, а нагружать его мы при печати особо не нагружаем.

Кстати, лирическое отступление. Никогда не задумывались, почему пробел делают таким длинным? Вроде бы символ как символ, печатается не чаще других букв, а некоторых может и пореже. Если знаете почему — расскажите.

Так вот, большой палец недонагружен. Он мог бы нажимать пять-шесть разных клавиш, а сейчас у него в лучшем случае пробел (причем дублируется на оба пальца, опять же — зачем?) и command. А чего на клавиатуре всегда не хватает, так это модификаторов. Точнее так — не хватает модификаторов, да и обычных кнопок тоже, которые было бы удобно нажимать. Мы уже выяснили, что все что вокруг home row на одну кнопку нажимать более-менее удобно.

А вот тянуться за всякими табами, энтерами, контролами и эскейпами очень не удобно. Да и мизинец существо довольно нежное, по-хорошему его бы разгрузить. Так что если есть возможность перенести часть неудобных кнопок туда, где они будут удобнее и комфортнее нажиматься, надо это обязательно делать!

Так мы приходим к раскладке называемой kinesis advantage, ну или ergodox: нагрузить большие пальцы по самое нехочу.

Есть, в принципе, и другие с похожими принципами. Просто на этом этапе мы так далеко ушли в область маргинального, что нельзя больше говорить о «трендах», «стандартах», «проверенных временем, устоявшихся решениях». Скорее разговор идет на уровне конкретных умельцев и их светлых идей.

Я пропустил про смещенные по вертикали ряды еще — ну тут довольно просто, пальцы у нас разной длины, и кнопки это учитывают.

Заметьте еще, что пришли мы к этому дизайну очень логичным путем, «благими намерениями». Мы фиксили то что сломано, новых проблем не добавляли, все изменения так или иначе были к лучшему.

Такие клавиатуры действительно лучше традиционных — ими действительно удобнее пользоваться. Иначе бы мы — клавиатурные энтузиасты, нерды, — этим бы не занимались. Даже на собственном опыте, вот моя клавиатура еще не до конца по фичам «дожата», не все улучшения включает в себя. Но даже на ней эффект заметен — посадка лучше, печатать приятнее и быстрее. Называется Let’s split, а точнее ее модификация Levinson.

— Но это же ужасно! Кто будет этим пользоваться? Как на этом печатать вообще?

Согласен, выглядит непривычно. Но давайте представим, что мы не решаем задачу «как изменить status quo» в текущем доминировании традиционных клавиатур. Вместо этого мы хотим предложить новый дизайн, который исправит все проблемы, до которых мы смогли дотянуться. И этот новый дизайн например настолько всех поразит своей логичностью и преимуществами, что люди, которые только знакомятся с компьютерами и им все равно нужно научиться печатать на чем-то в первый раз, эти люди будут сразу учиться на нашей клавиатуре.

Это мысленный эксперимент. Да, да, я знаю, такого никогда не случится. Но тем не менее. Представьте, короче что барьера на переобучение нет. Просто объективно — могла бы де-факто клавиатура быть такой, если бы ее сразу такой придумали? Было бы лучше?

И вот почему я спрашиваю. Ага, наконец-то переходим к выводам, которые, как я и обещал, разочаруют. Я проделал весь этот путь. Я глубоко согласен с каждым шагом, и по отдельности, и вместе. У меня нет порога на переобучение — я уже переобучился. На меня не действует сила привычки или давление мейнстрима — я глубоко презираю все мейнстримное и люблю выделять себя из толпы, демонстрируя свободу мышления. Я люблю интересные решения и out-of-the-box thinking, в конце концов.

Но что-то не клеится. Ну да, не клеится. Есть что-то еще. Недавно Рахим рассказал мне, что он тоже купил Microsoft Sculpt и пользуется теперь эргономичной клавиатурой. Но когда я был у него в гостях, оказалось что Sculpt отодвинут в сторону, а на столе лежит обычная Apple Wireless Keyboard. Не знаю, говорит, пробую разное, но все равно возвращаюсь к эпплу. Почему?

В принципе, я и сам долго облизывался на Ergodox EZ. Она как бы логически лучше, правильнее моей let’s split. Но потом думаешь, что как-то too much. Может ли вещь быть ну слишком уж эргономичной? Чересчур? Вот посмотрите на эти ножки:

−20 к сексуальности
−20 к сексуальности

Да, с их помощью ты еще более правильно расположишь кисти рук. Но как-то наоборот, отбивает немножко желаение, а не прибавляет, да? Типа как два свитера надеть — логически вроде теплее, но на люди почему-то выйти неудобно.

Или вот недавно мне показали Jian. Это вот такой красавец:

Логично? Да! Прекрасный проект. По многим параметрам, опять же, он лучше моего текущего положения. Раскладка умнее, кнопки правильнее и в правильных местах. Однако впечатление — на меня — производит что у человека с такой клавиатурой нет друзей. Слишком много ума, слишком мало чего-то еще. Чего?

Я сам не знаю :) Я же предупреждал, что пост разочарует.

Самое близкое, что может сойти за выводы, звучит наверное так. Получается что ты можешь быть дофига умным и прийти и порешать существующие проблемы. Это в общем-то не то чтобы просто, но допустим я до какой-то степени научился это делать.

Но оказывается этого мало! Мало решить максимальное количество проблем максимально логичным способом. Есть еще один этап — перерешать те же проблемы так, чтобы на результат было приятно смотреть. Нет, я не знаю что значит «приятно». Does it bring joy?

Конкретно с клавиатурами, может быть, чтобы эта самая «умность» не слишком фонила, не оттягивала на себя внимание, не перебивала собой настоящие утилитарные качества. Чтобы, в конце концов, вещь излучала простоту, а не сложность. Чтобы голова расслаблялась при ее виде, а не активизировала все мыслительные резервы.

И вот это уже сложно.

Что случилось с GUI-фреймворками?

Это третий пост в моем квесте по поиску GUI-фреймворка для десктопных приложений. Первый, второй.

Давайте немного сориентирую, что я ищу. Для многих «GUI-фреймворк» почти равно библиотека виджетов, чем больше тем лучше. Чтобы GUI собрать из кубиков лего минимальными силами. Меня это не очень возбуждает, потому что универсальных виджетов мало, а что-то более интересное надо делать под себя все равно. Поэтому для фреймворка важнее «уметь доделать свое», чем «побольше готового».

Также популярно мнение что GUI-фреймворк это look and feel, платформенно-зависимый или же просто не вырвиглазный. Типа это сложная часть, повторить лук платформы. Мне тоже пофиг. Дело в том, что сейчас самое идеальное время для GUI-фреймворка: все наигрались в игру «сделай look and feel как настоящий» и привыкли к веб-приложениям, где вообще каждый первый сайт разный. Плюс в моду вошел flat и минимализм, то есть виджеты рисовать дешево и просто, как никогда. А платформенный look and feel это иллюзия, все равно в каждом реальном приложении миллион случаев, которые не укладываются в стандартные checkbox/input/dropdown. И чем больше приложение, тем больше надо тюнить и дорисовывать самому. UI это не лего, его надо дизайнить и рисовать как целое, тогда будет гармонично.

Таким образом, от GUI фреймворка мне бы хотелось иметь базовые сложные вещи покрытыми (платформенно-зависимая обработка ввода, скроллинг, быстрый рендеринг, вывод шрифтов, dpi handling), какие-то базовые графические примитивы (прямоугольник там, линия, градиент, тенюшечки, svg) и возможность залезть под капот и все застайлить и запрогать как хочется.

Я НЕ ищу сокращения затрат на дизайнера за счет использования готовых компонент/дефолтного look and feel. Меня интересует возможность потратить много и долго, но сделать самому и хорошо, чем кое-как и из готового. Pixel-перфект и именно так, как мне нужно, а не так, как автор фреймворка сделал и сейчас уже хрен отковыряешь. Качественное вылизанное end-user приложение, а не дешево выглядящий массово производимый enterprise.

UPD: Ну и не надо учить меня программировать. Наверное навязывать там свой MVC или VDOM или что сейчас модное и свежее сильно не стоит. А то мода меняется, а фреймворк должен выжить.

То есть нужны идеально композируемые низкоуровневые примитивы без look and feel.

Чтобы не повторять ошибок истории, надо их знать. Я не знаю. Поэтому мне нужна ваша помощь: расскажите, что да как, коротко, доходчиво, грубо. Вопросы конечно кажутся философскими, но нужны именно конкретные инсайты. Ответ «WPF гААААвно» не нужен, он не конкретный и непонятно, в чем конкретно затык, а вот «в WPF нельзя было делать мультидокументные приложения, поэтому он сошел на нет» (например) очень хороший ответ.

Вопросы примерно такие:

— Почему у Java не получилось AWT?

— Зачем понадобился Swing? Что принципиально изменилось по сравнению с AWT? Я так понимаю AWT пилился на C++, а Swing на Java? И стало лень писать по версии под платформу?

— Почему Swing плохо работает? Это косяк реализации или какая-то принципиальная проблема? И в чем именно заключается это «плохо работает»? Тормозит? Разъезжается? Что?

— Что за история с JavaFX, зачем он был нужен, зачем начинать опять новый фреймворк, какую принципиальную инновацию по сравнению со Swing хотели привнести (неужели CSS?) и что не задалось? Почему ноль интереса? Все разочаровались?

— Есть ли какой-то принципиальный затык в реализации кросс-платформенных GUI? У веба вроде бы получается, почему больше ни у кого нет?

— Почему Windows переизобретает свой тулкит в каждой версии, а macOS живет на Cocoa десятилетиями?

— Какое положение занимает QT? Я так понимаю что он C++ и bloated, то есть нацелен больше на энтерпрайз?

— Flutter подход выглядит а) разумно и б) достаточно правдоподобно в) не как говно. То есть поднять свой GUI тулкит с нуля вполне можно и можно даже достаточно убедительно сэмулировать нативный look-and-feel. Почему ни у кого больше такое не получалось?

— Если брать не только кросс-платформенные GUI, то какие есть киллер-фичи, которых больше нигде нет? Что незаменимо и неповторимо?

— UPD 2: Я читаю, что в JavaFX вводится Scene Graph, а в Swing все на JPanel. При этом разница ускользает от меня. Чем принципиально отличаются подходы? (кроме названий классов)

— UPD 3: Я ничего не знаю про tcl/tk, но многие вспоминают его с теплом. Почему?

В общем, интересует история развития мысли и инсайты. Истории вроде «взяли ту же идею и понадеялись что сделаем лучше, а получилось то же самое» — не интересуют. Ну потому что а что вы ожидали? Истории «у фреймворка Х была вООООт такая амбиция (какая?), но он разбился о такую проблему (какую?)» — интересуют очень.

Если вы работали с GUI кроме веба, расскажите, что там у вас была за история?

Пациент умер, выносите

Opera Paper Products как-бы-шутка-но-не-такая уж и шутка
Opera Paper Products как-бы-шутка-но-не-такая уж и шутка

Я занимаюсь веб программированием 15 лет. Когда я начинал работать за деньги (компьютер у меня был и раньше, конечно), IE 6 был самым передовым и инновационным браузером, Firefox должен был вот-вот появиться, разработчики верили, что будущее за XHTML, до первого драфта HTML 5 и запуска StackOverflow оставалось 4 года, а до первого Chrome – пять лет. 

С вебом было связяно много неоправданных надежд, хайпа, завышенных ожиданий. Мы все ждали, когда же он вот все вообще поглотит, заменит, научится всему и вообще останется чуть ли не единственным инструментом, с которым будут работать вообще все. Сейчас ажиотаж спал и можно взглянуть трезво, что он такое есть и что он такое нет.

Получается вот как. Веб хорош для быстрого прототипирования, простого delivery, но масштаб его роста сильно ограничен. Грубо говоря, он подходит только для прототипов и игрушечных задач. Что-то вроде языка Basic, вроде и программы писать на нем можно, но всерьез его никто не берет. Веб, конечно, не пропадет, но в конечном счете займет место какого-нибудь там питона, на котором будут детей в MIT учить и ученые не слишком требовательные графики рисовать.

Почему? Качество. Все, сделанное на вебе, просто не доводится до какого-то сносного качества. Да, на вебе можно начать, и это будет быстрый старт. Но веб нельзя дожать до приемлимого состояния. От слова никак. Обязательно будет смешно, плохо и стыдно, а хорошо и быстро — никогда. Все веб-программисты на самом деле верят, что это они недостаточно стараются, но если было бы время, можно было бы сделать нормально. На этом самообмане вообще вся веб-индустрия держится. Но нет. Нельзя. Ни за какие деньги. Просто физически невозможно.

Ладно, простые статические страницы с текстом — ок, может быть. С адблоком и reader mode жить можно. Хотя и тут есть умельцы, которые умудряются сто слов отрендерить в страницу в 20 мегабайт, потому что технологии, инновации и disruption.

Что-то чуть сложнее — все, говно лезет из всех щелей. Веб-приложения? Интерфейсы? Сразу вешайтесь. Веб не создан для приложений и не развивается в эту сторону даже. Нет ни одного человека, который бы искренне любил веб-версию чего-либо и предпочитал ее нативной. Как только появляется альтернатива, даже иллюзия альтернативы, даже электрон-приложение, — всё, команда с крысами покинула корабль.

Сказать, что веб-приложение работает «нормально» можно только если очень, очень сильно смотреть на какой-то очень и очень частный случай сквозь пальцы, стиснутые настолько сильно, что они превращаются в фейспалм, и только если очень, очень верить в идею веба и хотеть это «нормально» увидеть. В определенных условиях на определенной мощности машине страничка может проскроллиться относительно плавно. В определенном месте экватора сайт может открыться условно быстро, а в определенное время конкретного дня в веб-консоли даже не будет ни одной ошибки.

Но если взять платформу в целом, без сверхподвигов и свехржертв, иллюзия пропадает. Если дать на нее посмотреть человеку, не укушенному веб-пропагандой, иллюзия пропадает. Как только приложение открывает кто-то, отличный от его собственного разработчика на гигабитном интернете и двенадцатиядерном аймаке про, иллюзия пропадает. Начинается бесконечный поток убогостей, шероховатостей, заусенцев, тормозов, проблем, ошибок, которые в принципе не устранить никаким образом. Даже если у разработчика есть внимание и желание возиться с такими глупостями, даже если приложить бесконенчые усилия — нет, оно не исправляется в принципе. Я знаю, я сам такой разработчик, и я пробовал много раз, и много раз обжигался. Хотя когда смотришь издалека, на бумаге, вроде все хорошо. Что может пойти не так? Да все что угодно. И не только может, но и пойдет, причем в самом неожиданном месте. Веб это такой аналог российского автопрома — издалека вроде тоже машина, вроде тоже ездит, че еще надо-то? Но, как мы все прекрасно знаем, есть нюанс.

Существует ли версия этой реальности, где веб вырастает во что-то более значимое? А как же WebAssembly?

А что WebAssebly? Эта чехарда имеет смысл только только для людей, которые думают, что компьютеров нигде кроме браузера не существует. Очнитесь, ребята, это еще один никому ненужный слой абстракции. Мы с радостью себя отбросили на N лет назад и теперь с радостью это преодолеваем. WebAssembly — это попытка запихнуть в веб то, что без веба прекрасно работало уже несколько десятков лет как — С++ приложения. Чтобы что? Я не знаю чтобы что. Чтобы условный Вася все равно качал себе Слак, завернутый в Электрон, зато теперь написаный на WebAssembly. Смотри, мам, он почти как нативный, даже иконочка есть! И почти не тормозит. Почти-почти. Еще раз — попробуйте выкинуть говно веб-пропаганды из головы и взглянуть на это трезво. В чем тут достижение-то?

Не то чтобы я НЕ хотел чтобы веб во что-то превратился. Я хотел, может, даже больше других. И был момент лет десять назад когда многие в это верили и был еще шанс. Просто пора зафиксировать (давно пора, я просто немножко тормоз, конечно) что веб это веб, не больше и не меньше. Все эти глюки, неровности, тормоза, неудобства, несовместимости, интервенции — это не временные мелкие неприятности, которые вот-вот разрешатся со следующим апдейтом Хрома. Это неотъемлемые свойства платформы, она такая сейчас и примерно такой же будет всегда. Надеяться уже в принципе не на что. И не то чтобы у меня было для вас что-то получше, или что я могу сказать, где будущее. Все что я могу сказать что оно точно не здесь.

Распродажа

Привет!

Я тут решил устроить распродажу. Все вещи хорошие, вы же знаете, что я покупаю только новое и качественное, отношусь ко всему бережно. Просто некоторыми вещами — так получилось — почти не пользуюсь. Хочу отдать в хорошие руки, чтобы приносили радость. На все скидки 30-50% от оригинальной цены. Живу в Москве, м. Марьина роща.

P.S. Ссылки ведут на подробные объявления с фотографиями и описаниями

1. Складной велосипед Shulz Krabi ПРОДАЛИ

2. Эргономичное кресло Aeron New размер C на гарантии ПРОДАЛИ

Фотки настоящие, с нашей кухни (ну кот, допустим, прифотошоплен, но и только!). Сейчас, кстати, у оф. дилера такое кресло 120 000+ ₽ стоит.

Для любопытных: погуглите Herman Miller Aeron in movies

3. Очиститель воздуха Xiaomi Mi Air Purifier 2S ПРОДАЛИ

4. Увлажнитель Xiaomi Smartmi Zhimi Air Humidifier 2 ПРОДАЛИ

Оказалась довольно полезная штука в России зимой, где батареи высушивают весь воздух так, что руки сохнут. Покупка Xiaomi решила проблему.

5. Компактная беззеркальная фотокамера Nikon 1 J1

Да, именно на эту камеру сделана классическая фотка с балалайкой и макбуком

6. Беспроводные клавиатура и мышь Microsoft Sculpt ПРОДАЛ

Это лучшая из не-гиковских эргономичных клавиатур, спросите хоть @levwalkin. Служили мне верой и правдой, как и Natural Ergonomic 4000 до них. Ну я что, я гик и упоролся, сейчас моя клавиатура выглядит как-то так.

7. Медиа-плеер Boxee Box ПРОДАЛ

В свое время был шиком, и до сих пор меня удивляет, как удачно тогда у них все сложилось в продукт. Во-первых, выглядит стильно и смело даже сегодня, а не очередная скучная черная коробка. Во-вторых, на пульт они засунули полную QWERTY-клавиатуру, которая когда нужна, тогда ты ну очень будешь благодарен что она есть. Ну и оболочка была довольно милая, видно, старались.

8. Игровой компьютер i5-6500 / DDR4 8 Gb / GTX970 4Gb

Хоть и покупался в 2016, игры от этого хуже идти не стали. Буквально вчера гонял на нем Ведьмака 3 в 1080p. Единственная проблема — я на нем почти не играю, запускаю раз в 2-4 недели может быть. Windows дольше обновляется, чем этот компьютер крутит игры. В остальном все прекрасно.

9. Серое пальто с объемным капюшоном

Юля не носит, мне тоже не подошло. Продаем короче. Вот еще одно:

10. Серое шерстяное пальто с рукавами ¹⁄₂

Как-то так. Пишите напрямую в телеграм @nikitonsky, если вопросы или что-то понравилось.

Тактика

Добрый день, с вами Тонский и рубрика «внезапные озарения по гейм-дизайну, о которых никто не просил».

Да, я все продолжаю залипать на стримы по Героям и делать далекоидущие выводы. Вот что меня какое-то время удивляло: герои 3 и 5 вышли давно, сообщество с тех пор их оценило, погоняло в хвост и в гриву и понаписало патчей и «турнирных» правил, которые делают игру в целом более честной и терпимой. Причем меняется многое — и баланс, и интерфейс, и сетевой код, юниты и герои вводятся и запрещаются. Но что никогда не трогают так это ИИ. И это меня удивляло — почему?

Во-первых заметим, что герои игра исключительно одиночная. Даже в сетевом режиме ты полтора-два часа спокойно возишься у себя в песочнице, соревнуясь сам с собой в наиболее оптимальном разносе компьютерных стеков и обходе природных богатств, и в конце вы на одну короткую битву встречаетесь с оппонентом чтобы сравнить, кто лучше все это время играл против компьютера.

Это было во-первых. Во-вторых, тактический ИИ в героях, который как раз руководит этими нейтральными стеками, довольно тупой. То есть он прямолинейный, предсказуемый, не просчитывает вперед, не строит стратегии или даже плана на битву, совершает из-за этого совсем локально-как-бы-оптимальные-но-уже-на-следующем-ходу-кошмарные ходы. Если сравнить с шахматами, то это примерно уровень «на каждом ходу брать самую дорогую фигуру или двигаться к ней», все. Казалось бы, в чем интерес? Почему это не фиксят, сделать лучше такого даже стараться особо не надо. Значит оно так специально.

Ну и получается что да. Я еще один пример приведу, игра Into the Breach. Такая игра необычная, в которой ты не то что не пытаешься предсказать, как поступил бы «достаточно рациональный противник», в ней следующий ход противника прямо явно вываливается на тебя как часть ситуации. То есть на каждом ходу тебе просто показывают, что будет делать враг. А в чем тогда игра? Игра в том, чтобы обладая этой информацией, сыграть так, что бы у него ничего не вышло. Предотвратить этот самый предсказанный ход, по возможности, на 100%. То есть это такой пазл, в котором, во-первых, ситуация очень несимметричная и к противнику совсем нечестная, а во-вторых, вероятности отсутствуют как класс. Будущее просчитывается, RNG не мешает. И это вполне играбельно и очень даже интересно, зазасывает.

Ну и возвращаясь к героям, штука в том, что тактически Герои как раз такая же игра, хотя может она себя так и не осозновала. Главный шик — зная предсказуемую модель поведения противника, максимально абьюзить ее и получить с этого непропорциональное преимущество. Выманить врага из стен замка, где ему, стратегически, гораздо лучше. Заставить медленный юнит гонять по полю за быстрым, пока лучники его обстреливают. Подойти на столько, чтобы ударить первым. Подставить маленький отряд, чтобы потом безболезненно врубиться большим. Взять юнита ради права первого хода. Заманить на мины. Встать между камнями, чтобы кони не подошли. Обманом растратить ману. Это все вполне тактические задачи, искать решение которых (и находить) вполне себе особый вид удовольствия. Удачно подобранная конфигурация армии (иногда вплоть до плюс-минус одного юнита) кардинально меняет ситуацию и может разносить совсем неожиданные по размеру армии, если придумать как. Герои, как в них играют сейчас, и есть игра про это.

А если ИИ был бы умнее, битвы очень быстро перестали бы быть тактическими и скорее стали бы соревнованием у кого армия толще. Сильный нападает на слабого, слабый обходит сильных. Ну или классика геймдизайна, камень-ножницы-бумага, выбирай то что контрит врага, угадал — будешь в шоколаде, нет — извиняй, дорогой. Не то чтобы таких игр не бывает — бывает, конечно, и не то чтобы они неинтересны — очень даже интересны, но по-своему, по-другому. Если ты любишь тактику, то в стратегических героев ты бы уже не стал играть.

Ну и второй момент — для мультиплеера, конечно, важна симметричность условий для всех. Но герои — игра принципиально не мультиплеерная, и некий дисбаланс в битве умный ты—тупой компьютер, в общем-то, и составляет геймплей. Так что симметричность не очень-то и нужна, и даже с полной информацией о будущем игроку остается о чем подумать. Играть так может быть даже интереснее. Более того, если себе в этом признаться заранее, много новых возможностей для дизайна боев откроется.

Отступаем, нас окружили!

Это в общем-то необязательное дополнение к моему предыдущему посту, не то чтобы оно какие-то покровы для кого-то сорвет, по крайней мере для делающих игры, но все же это мой журнал, а мне интересно, так что пусть будет.

Короче, прикидывая разные способы расстановки юнитов на доске, я понял, почему в героях 1-2-3 сетка была шестигранная. Дело к количестве спрайтов. Смотрите, если сетка вот такая:

...и мы атакуем гоблина с позиций 1, 2 или 3, мы можем в принципе ничего не менять и использовать один и тот же спрайт, бьющий вправо от себя. Такой же, как все ребята, что стоят слева. Форма шестиугольника гарантирует, что враг всегда будет немного правее, так что терпимо.

Для позиций 4, 5 и 6 мы зеркалим спрайт. Вуаля! Нужно рисовать каждый спрайт только в одном (!!!) варианте. А юнитов в героях ого-го сколько!

Кстати, обратите внимание, что если сетку повернуть на 90°, то это свойство пропадет. То есть даже угол поворота неслучаен!

Если взять параллельную квадратную сетку, как тут (wargroove):

то напасть можно слева, сверху и снизу, а это уже три варианта каждой анимации (лево-право зеркалятся, верх-низ не). Три варианта это прям тяжеловато.

Дальше идет сорокапятиградусная изометрия. Как в Into The Breach:

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

В Into the Breach, кстати, решили даже этим не заморачиваться и вообще не крутят юнитов. То есть если надо напасть назад, то бьют жопой. Тоже вариант, решает кстати проблему из предыдущего поста, что не очень хочется разглядывать юнитов со спины. И не такой уж плохой, как кажется — я наиграл 26 часов и понятия не имел, что у них атаки так топорно сделаны, пока не загрузил и не начал изучать специально.

Но вернемся к героям. В четвертых придумали рендерить юнитов исключительно из 3-д моделей, ну и собственно тут же шестиугольную сетку выкинули. Взяли сорокапятиградусную, но уже не из-за количества спрайтов — их они отрендерили во всех четырех вариациях.

Молодцы, что: это позволило сделать консистентное освещение (см. тени на тиграх) и избавило от вопросов «в какой все-таки руке у призрака голова?», которые неизбежно возникли бы в случае трюка с отзеркаливанием.

Ну а в пятый уже было настоящее 3Д, и там можно крутить модели уже как хочешь. И к шестигранной сетке никто возвращаться не стал. Почему? Моя гипотеза — квадратная дает больше тактических возможностей: меньше места, сильнее толпятся юниты, проще закрыться. Правда, это если не разрешать диагональные атаки, а они в пятых были.

Итого: чисто практический аспект производства спрайтов может повлиять на одну из основных механик игры, а именно на вид тактического боя! Такой вот вывод.