↓
 ↑
Регистрация
Имя/email

Пароль

 
Войти при помощи
Временно не работает,
как войти читайте здесь!
Asteroid
13 января в 00:41
Aa Aa
#размышления #теория_магии #много_букф
... и ещё немного программирования магии
Вторая часть:

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

Представим заклинание ОгненныйШар. Это заклинание требует уточнения, какого размера шар и какой температуры. Очевидно, что чем выше эти два параметра, тем выше расход магической энергии. Иначе, мы можем опустить параметры, и пусть каждый раз оно жжёт на максимум.
Таким образом мы получаем примерно следующую спецификацию заклинания ОгненныйШар(Радиус = 2, Температура = 1700). Очевидно, что можно задавать любые параметры температуры и радиуса - это может быть весьма удобно, чтобы, например, поджечь врага, но не поплавить стены, или пустить фейерверк, или просто припугнуть кого-то, бросив в него ОгненныйШар(Радиус = 10, Температура = 100)

Но согласитесь, в боевой обстановке зачитывать лишние пару слов очень не хочется. Поэтому маг может создать специальное заклинание для быстрого пользования, которое будет просто вызывать наше заклинание ОгненныйШар и задавать ему стандартные параметры:
Spell ОгнеШар():
{
ОгненныйШар(Радиус = 1, Температура = 1000)
}
Теперь наш маг может просто во время боя крикнуть: "Огнешар!" и во врагов полетит стандартный ОгненныйШар.

Это был пример, когда одна функция вызывает другую. Но это ещё не функциональное программирование, потому что такой метод жестко ограничен.
Например, кроме Огнешара, у нас может быть стандартное заклинание МорозныйВзрыв, и ещё несколько штук для каждой стихии. И мы хотим сделать массовую бомбардировку большой площади, используя в качестве "снарядов" то из этих заклинаний, которое обходит стихийное сопротивление противников. Тогда нам надо сделать несколько новых заклинаний ОгненнаяБомбардирока, МорознаяБомбардировка, и т.д.
Давайте приведу какой-то код одного из таких заклинаний:
Spell ОгненнаяБомбардировка(Радиус: м): // Здесь "м" после радиуса - указание единицы измерения в метрах. А можно было бы и сантиметры указать.
{
Для каждого живого в Радиусе вокруг точки попадания создать ОгнеШар();
}
И у нас от точки попадания ОгненнойБомбардировки полетят Огнешары во всех врагов. Заклинание простенькое, не без недостатков, но как обучающий пример сойдёт. И да, "код" максимально упрощен ради простоты показа концепции.

Замечаете, что, по сути, все стихийные заклинания бомбардировки будут делать одно и тоже, и отличаются только тем, что в одном месте программы вместо вызова ОгнеШара будет вызов какого-то другого заклинания?
Подобная проблема множит код, забивает гримуар лишними заклинаниями. А если мы будем делать артефакт, то вообще беда. И в целом, это как-то не очень красиво. Поэтому есть очень удобный метод - передать заклинанию в качестве параметра другое заклинание:
Spell Бомбардировка(Радиус: м, Снаряд: spl) // "spl - это мы указываем, что Снаряд имеет тип "Заклинание".
{
Для каждого живого в Радиусе вокруг точки попадания создать Снаряд();
}
Теперь, мы можем вызывать хаос с любым типом стихийного урона одним и тем же заклинанием следующим образом Бомбардировка(Радиус = 100, ОгнеШар). Просто подставляем вместо ОгнеШара что хотим, и всё.

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

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

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

Пример, когда заклинание создаёт заклинания я не буду приводить с кодом. Просто примеры использования.
1. Дверь, проходя через которую каждый получает маячок.
2. Заклинание СоздатьЩит, которое проанализирует окружающую обстановку и противника, и создаст новое идеальное в данной ситуации заклинание Щита, с учётом стихий и прочего. Затем, маг может просто когда ему надо кастовать новое заклинание, и вот это новое заклинание всегда будет одинаково. Например, враг лавовый элементаль, СоздатьЩит создаёт заклинание Щит1, которое будет огненным щитом с некоторой кинетической компонентой. И теперь маг может просто раз за разом спамить Щит1.
3. Автоматически генерируемые уведомления от министерства магии в ГП.
(Вы думаете примеры такие себе, и их мало? Но что вы хотите, я функциональным программированием мало занимался, оно для меня непривычно, я в императивном стиле мыслю.))

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

По большому счёту, разница в парадигме мышления.
1. Процедурное - это рецепт, чёткая последовательность действий, необходимая для достижения результата. "Делай это."
2. Объектное - это создание набора взаимодействующих обьектов/сущностей, у каждой из которых своя роль. "Будь этим."
3. Функциональное - это поток действий, через который проходят данные и другие потоки действий. "Преобразуй это."

Ваши мысли?

П.С. Это было сложна!
П.П.С. Попробую написать следующий пост об инкапсуляции, иммутабельности и магических кругах. И комбинации с магией намеренья. Не уверен, что вложусь в формат.
13 января в 00:41
5 комментариев из 19
Экономим то мы что?
Потому что несмотря на упрощение программирования, это усложнение когнитивное. Т.е. хорошо чтобы писать и читать (в целом), но плохо чтобы думать.
Это уже не магия, а бюрократия получилась.
MonkAlex
Экономим то мы что?
О чём ты? И кого спрашиваешь?
Вообще непонятно, как коммент относится к обсуждению. Промахнулся вкладкой?
Asteroid
в тему. Ты подразумеваешь что магу нужно "произносить" заклинание поэтому он хочет это упростить:
Теперь наш маг может просто во время боя крикнуть: "Огнешар!" и во врагов полетит стандартный ОгненныйШар.
А в итоге приходишь к:
Бомбардировка(Радиус = 100, ОгнеШар).

И это ещё учитывая
Подобная проблема множит код, забивает гримуар лишними заклинаниями.
Но цель то какая? Ты сам придумал проблему с забиванием гримуара, сам её решил усложнением когнитивным, а в чём проблема я так и не понял. Типа я как разработчик вижу типичный оверинжениринг, когда хочется красивых решений наклепать, но без проблемы клепать решения - это просто трата времени и денег =)
Asteroid
Это скорость
Нет, это скорость по объёму (емнип, "поток" в физике, но не уверен). Ну и вообще да, я накосячил, там же без разницы, за сколько. Просто кб/м^3. Для каждого момента времени показатель может быть своим, да.

А вот разрешающая способность камеры в смартфоне, она какая есть, такая есть. И изменяя скорость вайфая ты её не улучшишь.
Наверное, магия Потока ведёт себя не так, как твой смартфон?

В магах. Ведь не все маги равны. Система складывается из того, в чём и как они не равны, и как это меняется с временем.
Ну и тут равенства нет, не понимаю, что тебе не нравится. Просто имеющуюся силу можно более гибко употреблять, но это никак тебе не поможет делать то же, что и архимаг, будучи слабеньким магом.
MonkAlex
Ты подразумеваешь что магу нужно "произносить" заклинание поэтому он хочет это упростить:
А в итоге приходишь к:
Бомбардировка(Радиус = 100, ОгнеШар).
Нужно оптимизировать не только по параметру скорости произношения. Если у тебя куча похожих заклинаний, то можно запутаться. Понятное дело, что опытный маг может прийти к системе из кучи процедурных заклинаний, где названия компилируются в систему. Но это всё равно будет не таким гибким.
Также отмечу, что это огнешару надо быть максимально коротким - это заклинание для битвы впритык. Если же ты хочешь устроить армагедон на некой площади, то обычно стоишь не на этой площади, и пару секунд на выбор радиуса действия и эффекта у тебя есть.
Более того, ОгненнаяБомбардировка не сильно быстрее произносится чем Бомбардировка(ОгнеШар). А параметр радиуса и там и там нужен.

Но цель то какая? Ты сам придумал проблему с забиванием гримуара, сам её решил усложнением когнитивным, а в чём проблема я так и не понял. Типа я как разработчик вижу типичный оверинжениринг, когда хочется красивых решений наклепать, но без проблемы клепать решения - это просто трата времени и денег =)
А ты думаешь, проблемы вообще никогда нет? Если у мага по странице на заклинание, и пара тысяч заклинаний, то во что превращается гриммуар? А если ты хочешь хитроумный гриммуар, которые скрывает большинство страниц в каком-нибудь подространстве, то тебе всё равно придётся делать его на функциональной магии.
И как бы, обычно гриммуар не из простой бумаги сделан, а заклинания не простыми чернилами пишутся. Экономия ресурсов - это важно.
Показать полностью
ПОИСК
ФАНФИКОВ













Закрыть
Закрыть
Закрыть