|
#размышления #теория_магии #много_букф
... и ещё немного программирования магии Вторая часть: В прошлый раз я не стал говорить о функциональном программировании - надо было освежить память. Сегодня о нём. И будет немного сложнее. Примеры в конце. Если кратко: функциональное программирование - это когда одна функция может иметь в качестве параметра другую функцию, и создаёт в качестве результата третью. Сложно? Сейчас будем разбираться. Представим заклинание ОгненныйШар. Это заклинание требует уточнения, какого размера шар и какой температуры. Очевидно, что чем выше эти два параметра, тем выше расход магической энергии. Иначе, мы можем опустить параметры, и пусть каждый раз оно жжёт на максимум. Таким образом мы получаем примерно следующую спецификацию заклинания ОгненныйШар(Радиус = 2, Температура = 1700). Очевидно, что можно задавать любые параметры температуры и радиуса - это может быть весьма удобно, чтобы, например, поджечь врага, но не поплавить стены, или пустить фейерверк, или просто припугнуть кого-то, бросив в него ОгненныйШар(Радиус = 10, Температура = 100) Но согласитесь, в боевой обстановке зачитывать лишние пару слов очень не хочется. Поэтому маг может создать специальное заклинание для быстрого пользования, которое будет просто вызывать наше заклинание ОгненныйШар и задавать ему стандартные параметры: Spell ОгнеШар(): Теперь наш маг может просто во время боя крикнуть: "Огнешар!" и во врагов полетит стандартный ОгненныйШар. { ОгненныйШар(Радиус = 1, Температура = 1000) } Это был пример, когда одна функция вызывает другую. Но это ещё не функциональное программирование, потому что такой метод жестко ограничен. Например, кроме Огнешара, у нас может быть стандартное заклинание МорозныйВзрыв, и ещё несколько штук для каждой стихии. И мы хотим сделать массовую бомбардировку большой площади, используя в качестве "снарядов" то из этих заклинаний, которое обходит стихийное сопротивление противников. Тогда нам надо сделать несколько новых заклинаний ОгненнаяБомбардирока, МорознаяБомбардировка, и т.д. Давайте приведу какой-то код одного из таких заклинаний: Spell ОгненнаяБомбардировка(Радиус: м): // Здесь "м" после радиуса - указание единицы измерения в метрах. А можно было бы и сантиметры указать. И у нас от точки попадания ОгненнойБомбардировки полетят Огнешары во всех врагов. Заклинание простенькое, не без недостатков, но как обучающий пример сойдёт. И да, "код" максимально упрощен ради простоты показа концепции.{ Для каждого живого в Радиусе вокруг точки попадания создать ОгнеШар(); } Замечаете, что, по сути, все стихийные заклинания бомбардировки будут делать одно и тоже, и отличаются только тем, что в одном месте программы вместо вызова ОгнеШара будет вызов какого-то другого заклинания? Подобная проблема множит код, забивает гримуар лишними заклинаниями. А если мы будем делать артефакт, то вообще беда. И в целом, это как-то не очень красиво. Поэтому есть очень удобный метод - передать заклинанию в качестве параметра другое заклинание: Spell Бомбардировка(Радиус: м, Снаряд: spl) // "spl - это мы указываем, что Снаряд имеет тип "Заклинание". Теперь, мы можем вызывать хаос с любым типом стихийного урона одним и тем же заклинанием следующим образом Бомбардировка(Радиус = 100, ОгнеШар). Просто подставляем вместо ОгнеШара что хотим, и всё.{ Для каждого живого в Радиусе вокруг точки попадания создать Снаряд(); } Заметьте, заклинание бомбардировки не знает, чем именно оно будет бомбардировать. Это может быть что угодно, что мы ему подадим, и что сработает. Мы можем вызвать бомбардировку бумажными конфети, котятами или тухлыми яйцами. И вот это уже и есть начало функционального программирования. Очень важна поправка "что сработает". В нашем примере, у нас в одной точке создаются летящие снаряды. Если мы создадим что-то, что останется на месте, то возникнет коллизия - заклинание попытается создать что-то в том же месте, где уже существует другой созданный обьект. Так что если мы подадим в качестве параметра заклинание, которое сработает как-то не так, то оно сработает "не так" очень много раз. Потенциал факапа тут очень высок. Поэтому, такое знание будут держать подальше от неофитов - и себя взорвут, и окружающих. Мерлин, я посмотрел, сколько уже написал, обьясняя простейшее. На иммутабельность даже не буду замахиваться. Она не так уж и принципиальна, и не факт, что совоглобусна для магии. Пример, когда заклинание создаёт заклинания я не буду приводить с кодом. Просто примеры использования. 1. Дверь, проходя через которую каждый получает маячок. 2. Заклинание СоздатьЩит, которое проанализирует окружающую обстановку и противника, и создаст новое идеальное в данной ситуации заклинание Щита, с учётом стихий и прочего. Затем, маг может просто когда ему надо кастовать новое заклинание, и вот это новое заклинание всегда будет одинаково. Например, враг лавовый элементаль, СоздатьЩит создаёт заклинание Щит1, которое будет огненным щитом с некоторой кинетической компонентой. И теперь маг может просто раз за разом спамить Щит1. 3. Автоматически генерируемые уведомления от министерства магии в ГП. (Вы думаете примеры такие себе, и их мало? Но что вы хотите, я функциональным программированием мало занимался, оно для меня непривычно, я в императивном стиле мыслю.)) Если внимательно присмотреться, то только процедурное программирование вносит революцию в мир магии. Обьектное и функциональное программирование можно повторить просто используя процедурное. По сути, они этакие надстройки, упрощающие процесс и логику, делающие код изящнее и читаемее. Полные преимущества этих надстроек в нашем мире проявляются в больших проектах, где логика процедурного кода становится слишком размытой и не очевидной. В мире магии же, более короткий код может быть суперважен в рунической магии - поверхность не безгранична. Ну, и преимущество заклинания СоздатьЩит думаю очевидно. По большому счёту, разница в парадигме мышления. 1. Процедурное - это рецепт, чёткая последовательность действий, необходимая для достижения результата. "Делай это." 2. Объектное - это создание набора взаимодействующих обьектов/сущностей, у каждой из которых своя роль. "Будь этим." 3. Функциональное - это поток действий, через который проходят данные и другие потоки действий. "Преобразуй это." Ваши мысли? П.С. Это было сложна! П.П.С. Попробую написать следующий пост об инкапсуляции, иммутабельности и магических кругах. И комбинации с магией намеренья. Не уверен, что вложусь в формат. 13 января в 00:41
|
|
MonkAlex
Экономим то мы что? О чём ты? И кого спрашиваешь?Вообще непонятно, как коммент относится к обсуждению. Промахнулся вкладкой? |
|
|
Asteroid
в тему. Ты подразумеваешь что магу нужно "произносить" заклинание поэтому он хочет это упростить: Теперь наш маг может просто во время боя крикнуть: "Огнешар!" и во врагов полетит стандартный ОгненныйШар. А в итоге приходишь к: Бомбардировка(Радиус = 100, ОгнеШар). И это ещё учитывая Подобная проблема множит код, забивает гримуар лишними заклинаниями. Но цель то какая? Ты сам придумал проблему с забиванием гримуара, сам её решил усложнением когнитивным, а в чём проблема я так и не понял. Типа я как разработчик вижу типичный оверинжениринг, когда хочется красивых решений наклепать, но без проблемы клепать решения - это просто трата времени и денег =) |
|
|
Asteroid
Это скорость Нет, это скорость по объёму (емнип, "поток" в физике, но не уверен). Ну и вообще да, я накосячил, там же без разницы, за сколько. Просто кб/м^3. Для каждого момента времени показатель может быть своим, да.А вот разрешающая способность камеры в смартфоне, она какая есть, такая есть. И изменяя скорость вайфая ты её не улучшишь. Наверное, магия Потока ведёт себя не так, как твой смартфон?В магах. Ведь не все маги равны. Система складывается из того, в чём и как они не равны, и как это меняется с временем. Ну и тут равенства нет, не понимаю, что тебе не нравится. Просто имеющуюся силу можно более гибко употреблять, но это никак тебе не поможет делать то же, что и архимаг, будучи слабеньким магом. |
|
|
MonkAlex
Показать полностью
Ты подразумеваешь что магу нужно "произносить" заклинание поэтому он хочет это упростить: А в итоге приходишь к: Нужно оптимизировать не только по параметру скорости произношения. Если у тебя куча похожих заклинаний, то можно запутаться. Понятное дело, что опытный маг может прийти к системе из кучи процедурных заклинаний, где названия компилируются в систему. Но это всё равно будет не таким гибким.Бомбардировка(Радиус = 100, ОгнеШар). Также отмечу, что это огнешару надо быть максимально коротким - это заклинание для битвы впритык. Если же ты хочешь устроить армагедон на некой площади, то обычно стоишь не на этой площади, и пару секунд на выбор радиуса действия и эффекта у тебя есть. Более того, ОгненнаяБомбардировка не сильно быстрее произносится чем Бомбардировка(ОгнеШар). А параметр радиуса и там и там нужен. Но цель то какая? Ты сам придумал проблему с забиванием гримуара, сам её решил усложнением когнитивным, а в чём проблема я так и не понял. Типа я как разработчик вижу типичный оверинжениринг, когда хочется красивых решений наклепать, но без проблемы клепать решения - это просто трата времени и денег =) А ты думаешь, проблемы вообще никогда нет? Если у мага по странице на заклинание, и пара тысяч заклинаний, то во что превращается гриммуар? А если ты хочешь хитроумный гриммуар, которые скрывает большинство страниц в каком-нибудь подространстве, то тебе всё равно придётся делать его на функциональной магии.И как бы, обычно гриммуар не из простой бумаги сделан, а заклинания не простыми чернилами пишутся. Экономия ресурсов - это важно. |
|