3 заметки с тегом

lua

99 бутылок: Lua

Пока ещё помню язык Луа, который я использовал для написания «Морского боя» в азбуке Морзе, надо бы продолжить им сериал о «99 бутылках пива на стене».

73. Lua — скриптовый язык, который чаще всего применяют для встраивания, например — нередко используют для описания сценариев в играх. Объектная модель прототипная, напоминает ДжаваСкрипт, но в Луа она мощнее.

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

А вот стандартная библиотека подкачала, простой пример — в ней нет функции задержки, когда она мне понадобилась, пришлось её импортировать из Си. Или есть модуль, который хоть как-то позволяет работать с ЮТФ-8, но в нём даже нет простого способа получить символ по его номеру или поменять регистр строки.

function beer(b)
    if b == 1 then
        return '1 bottle'
    else
        return (b == 0 and 'no' or b) .. ' bottles'
    end
end

b = beer(99)

for i = 99, 1, -1 do
    print(b .. ' of beer on the wall, ' .. b .. ' of beer.')
    b = beer(i - 1)
    print('Take one down and pass it around, ' .. b .. ' of beer on the wall.\n')
end

print([[No more bottles of beer on the wall, no more bottles of beer.
Go to the store and buy some more, 99 bottles of beer on the wall.]])

День Радио

Сегодня, 7 мая в России отмечают День радио — в этот день, 125 лет назад российский физик Александр Степанович Попов на заседании Русского физико-химического общества продемонстрировал «прибор, предназначенный для показывания быстрых колебаний в атмосферном электричестве».

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

Отладочный режим получившегося «Морского боя», в обычном режиме видно только мигание светодиода

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

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

Обёртка и некоторые функции (мигание светодиодом, опрос «Шифта» и функция задержки) написаны на Си, остальная часть — на языке «Лу́а» (Lua). Давно хотелось изучить этот странноватый язык поглубже, а тут ещё удалось поучиться встраивать его в Си.

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

Диграфы в Си немного запутывают и вносят в код толику безумия

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

Для тех безумцев, которые захотят попробовать скопмилировать этот вариант «Морского боя» и сыграть, ещё раз привожу репозиторий проекта (только под «МакОСь») — https://github.com/bolknote/battleship.

Чудесный Lua

Язык программирования Lua (переводится с португальского как «луна»), в целом, мне нравится — очень гибкий, красивый, целостный. Программировать на нём приятно, а модель, заложенная в основу, настолько гибкая, что позволяет создавать ООП-конструкции без нативной поддержки их языком.

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

mt = {}

function mt.__add (a,b) 
    return { x = a.x + b.x, y = a.y + b.y }
end

Задаётся метатаблица (mt) у которой ключ __add (функция, отвечающая за сложение) определена как функция сложения вектора с двумя координатами. Например, в следующем примере (все примеры взяты из статьи «Язык Lua и использование скриптов на нём в программах на Си++») я устанавливаю заданную метатаблицу «mt» для переменной «u», причём сложение «u» и «v» работает правильно — поскольку Lua ищет обработчик сложения сначала у второго оператора, в случае неудачи — у следующего.

u = { x = 1, y = 2 }
v = { x = 0, y = 1 }

setmetatable ( u, mt )   -- установить для таблицы u метатаблицу

w = u + v                -- осуществить сложение таблиц
print ( w.x, w.y )

Самое интересное — дальше. Тут мой мозг не ломается, но без руководства я бы не догадался. Дело в том, что метатаблица «mt», точнее её операция «__add» определена некорректно. Сложение пройдёт великолепно, но у переменной «w» новой операции сложения не будет — метатаблица «mt» для этой переменной не установлена. Правильный способ определения вот такой:

function mt.__add (a,b) 
    return setmetatable ( { x = a.x + b.x, y = a.y + b.y }, mt )
end

Т. е. таблица устанавливается ещё и для получившегося выражения.

Для тех, кто уже ничего не понимает, но знает PHP. Запись { x = a.x + b.x, y = a.y + b.y } на PHP выглядела бы как array('x'=>$a['x']+$b['x'], 'y'=>$a['y']+$b['y']).