Skip to content

Пишем компас

В качестве примера разберём модуль, реализующий простой компас. Наш компас будет представлен ссылками С/Ю/В/З в инвентаре. При нажатии на одну из ссылок, будет осуществляться переход по атрибуту комнаты: to_n, to_s, to_e, to_w соответственно.

Начнём с того, что создадим файл compass.lua, в котором создадим объект @compass:

lua
local std = stead

obj {
	nam = '@compass';
}

Наш компас -- это фактически набор ссылок: C, Ю, В, З. При нажатии на ссылку, мы должны выполнить walk. Как отобразить ссылки в инвентаре?

Мы можем поступить двумя способами:

  1. создать для каждого направления свой объект;
  2. воспользоваться подстановками.

Первый способ плох тем, что не позволяет нам произвольно форматировать вывод (а мы хотим, чтобы компас был похож на компас), поэтому подстановки, в данном случае, будут удобнее.

lua
obj {
	nam = '@compass';
	disp = false; -- не показывать объект @compass
}:with {
	obj {
		nam = '$compass';
		act = function(s, w)
			std.p(fmt.c ("{@compass n| С}\n{@compass w|З} {@compass e|В}\n{@compass s|Ю}"))
		end;
	}
}

В объект @compass (который стал невидимым, см disp = false), мы вложили объект $compass. Как вы помните, это подстановки. Движок, встретив ссылки вида {$compass} (а именно такая ссылка будет в инвентаре, если мы поместим туда объект компас), вызовет act у объекта $compass и его результат отобразит в выводе. Мы и воспользовались этим! Функция act у $compass формирует строку ссылок: С, З, В, Ю. Причём в качестве объекта реакции выступает @compass. Это значит, что, добавив обработчик inv в @compass, мы получим вызов этого метода как реакцию на нажатие ссылки:

lua
obj {
	nam = '@compass';
	disp = false;
	inv = function(s)
	     p [[Вы нажали на ссылку.]]
	end;
}:with { ...

Но как определить, в какую сторону мы хотим идти? Ссылки нашего компаса имеют вид:

lua
{@compass n|С}

Это значит, что движок, при нажатии на такую ссылку, сформирует команду:

lua
use @compass,n

Которая и приведёт к вызову метода inv у объекта @compass. Но как получить второй параметр, в данном случае n? К сожалению, у обработчика inv не предусмотрены дополнительные параметры, но если вы вспомните, что команда STEAD3 раскладывается на компоненты при её обработке, то поймёте следующий код:

lua
obj {
	nam = '@compass';
	disp = false;
	inv = function(s)
		local dir = std.cmd[3]
		p("Вы хотите идти по направлению: ", dir)
	end;
}:with {

Теперь в переменной dir мы получим; n, s, w или e! Действительно, в std.cmd[1] будет записан 'use', в std.cmd[2] -- объект, а в std.cmd[3] -- параметр.

Если бы мы вставляли подстановку в тело вывода сцены, команда была бы такой:

lua
act @compass,n

И был бы вызван обработчик act. В обработчике act предусмотрены дополнительные аргументы, поэтому в таком случае мы могли бы просто взять параметр из списка параметров к обработчику act. Впрочем, способ с массивом std.cmd сработал бы тоже.

Теперь нам осталось написать код, который делает переход по локации, заданной атрибутом to_направление:

lua
obj {
	nam = '@compass';
	disp = false;
	inv = function(s)
		local dir = std.cmd[3]
		local r = std.call(std.here(), 'to_'..dir)
		if not r then
			std.p ([[Нет прохода.]])
		else
			std.walk(r)
		end
	end;
}:with {

Теперь нам осталось только сделать так, чтобы компас попадал в инвентарь и предоставить объект compass для настроек (которые могут в нем появиться при дальнейшем развитии модуля):

lua
local std = stead
require "fmt"

obj {
	nam = '@compass';
	disp = false;
	inv = function(s)
		local dir = std.cmd[3]
		local r = std.call(std.here(), dir..'_to')
		if not r then
			std.p ([[Нет прохода]])
		else
			std.walk(r)
		end
	end;
}:with {
	obj {
		nam = '$compass';
		act = function(s, w)
			std.p(fmt.c ("{@compass n| С}\n{@compass w|З} {@compass e|В}\n{@compass s|Ю}"))
		end;
	}
}

std.mod_start(function(load)
	take '@compass'
end)
compass = _'@compass'

Дальнейшие улучшения компаса могут включать в себя:

  • не показывать ссылками те направления, которые недоступны. Для этого надо изменить код $compass.act;
  • оформить вывод компаса в виде изображения. Для этого можно с помощью pixels сформировать изображение компаса, разрезать изображение на 9 квадратных изображений, преобразовать из в спрайты и выводить ссылки на них из act.

Данные улучшения предлагается выполнить самостоятельно.