Перейти к содержимому
FredoNook

Макроязык IronMacros

Рекомендуемые сообщения

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

S1# select 1st slot
R020C# make 2
R060B# 6 cubes
R0502# x5 cubes planes
P0M# place cube go up
>^<WWWWW#move next stripe
S2# select pickaxe
R0502
XFM
<^>WWWWW
XFM<^>#star cut U
R030A
R0402
XFM
<^>WWWW
WXF<^>
R0502
XFM#star cut R
W<^>XF
WWXFWW
<^>
R030C
XFMXFMMXF
<^>WWW
<^>
R0502
XFM

Можно одной строкой (жесть):

S1R020CR060BR0502P0M>^<WWWWWS2R0502XFM<^>WWWWWXFM<^>R030AR0402XFM<^>WWWWWXF<^>R0502XFMW<^>XFWWXFWW<^>R030CXFMXFMMXF<^>WWW<^>R0502XFM

Результат:

 

 

2d8qmvq.png

 

29m679z.png

 

svl16g.png

 

kain7o.png

 

258cy89.png

 

2rhrbqx.png

 

 

 

Сама библиотека/интерпритатор:

 

-- ====================
-- IronMacros.lua
-- Created by FredoNook
-- ====================
 
local rb = require("robot")
local sh = require("shell")
 
-- module table
local im = {}
-- symbols restricted to unregister
local restrictedSymbols = {"#"}
-- macros queue
local macros = {}
-- macros execution register
im.pc = {["x"] = 1, ["y"] = 1}
-- registred macro commands
local macroses = {}
 
-- ===========================
-- MACROS MANAGEMENT FUNCTIONS
-- ===========================
 
-- Register an macro symbol with func
function im.registerMacros(symbol, func)
  if #symbol > 1 then
    error("Macro command can't be longer then one symbol")
  end
  if isSymbolRestricted(symbol) then
    error("Symbol \""..symbol.."\" is restricted")
    return
  end
  macroses[tostring(symbol)] = func
end
 
-- unregister an macro symbol
function im.unregisterMacros(symbol)
  if #symbol > 1 then
    error("Macro command can't be longer then one symbol")
  end
  if isSymbolRestricted(symbol) then
    error("Symbol \""..symbol.."\" is restricted")
    return
  end
  macroses[tostring(symbol)] = nil
end
 
-- ====================
-- PC REGISTER FUNCTION
-- ====================
 
-- register x step forward
im.pc.fstep = function(count)
  if count == nil then im.pc.x = im.pc.x + 1
  else im.pc.x =  im.pc.x + count end
end
 
-- register y step down
im.pc.dstep = function(count)
  if count == nil then im.pc.y = im.pc.y + 1
  else im.pc.y = im.pc.y + count end
  im.pc.x = 1
end
 
-- set register reg to value val
im.pc.set = function(reg, val)
  if reg == "x" then im.pc.x = val
  elseif reg == "y" then im.pc.y = val
  else error("Wrong register idintificator")
  end
end
 
-- ===================
-- EXECUTION FUNCTIONS
-- ===================
 
-- run macro file with filename
function im.run(filename)
  local file = io.open(filename)
  local i = 1
  for line in file:lines() do
    macros[i] = line
        i = i + 1
  end
  file:close()
  local cmd = " "
  while cmd do
    cmd = im.readCmd()
    if cmd == nil then break end
    im.exec(cmd)
  end
end
 
-- exec macro command cmd
function im.exec(cmd)
  if cmd ~= nil then macroses[cmd]() end
end
 
-- read command from registers position
function im.readCmd()
  local cmd
  if im.pc.x == #macros[im.pc.y] + 1 then
    if #macros == im.pc.y then
      io.write("MACROS COMPLETED")
      return nil
    else
          im.pc.dstep()
      cmd = macros[im.pc.y]:sub(im.pc.x, im.pc.x)
      im.pc.fstep()
      io.write("CURRENT CMD: "..cmd.."\n")
      return cmd
    end
  end
  cmd = macros[im.pc.y]:sub(im.pc.x, im.pc.x)
  im.pc.fstep()
  io.write("CURRENT CMD: "..cmd.."\n")
  return cmd
end
 
-- ================
-- MODULE FUNCTIONS
-- ================
 
-- check symbol for restriction
local function isSymbolRestricted(symbol)
  for key, value in pairs(restrictedSymbols) do
    if value == symbol then return true end
  end
end
 
-- =========================
-- REGISTER DEFAULT MACROSES
-- =========================
 
-- set # as commentary command
macroses["#"] = function()
  if #macros == im.pc.y then
    im.pc.x = #macros[im.pc.y] + 1
  else
    im.pc.dstep()
  end
end
-- set " " as NOP command
macroses[" "] = function() end
-- set ^ as forward command
macroses["^"] = function() rb.forward() end
-- set > as turn right command
macroses[">"] = function() rb.turnRight() end
-- set V as backward command
macroses["V"] = function() rb.back() end
-- set < as turn left command
macroses["<"] = function() rb.turnLeft() end
-- set M as up command
macroses["M"] = function() rb.up() end
-- set W as down command
macroses["W"] = function() rb.down() end
-- set R as repeat command.
-- format: RXXYY where
-- XX loop count in hex
-- YY count of forward command to repeat
-- except # " " and parameters of other commands
macroses["R"] = function()
  local cycleCount = tonumber(im.readCmd()..im.readCmd(), 16)
  local cmdCount = tonumber(im.readCmd()..im.readCmd(), 16)
  local cycleStartPoint = {["x"] = im.pc.x, ["y"] = im.pc.y}
  local cycc, cmdc = 1, 1
  while cycc < cycleCount do
    while cmdc <= cmdCount do
      local cmd = im.readCmd()
      if cmd == "#" then cmdc = cmdc - 1 end
      if cmd == " " then cmdc = cmdc - 1 end
      im.exec(cmd)
      cmdc = cmdc + 1
    end
    cmdc = 1
    im.pc.x = cycleStartPoint.x
    im.pc.y = cycleStartPoint.y
    cycc = cycc + 1
  end
end
-- set S as select inventory slot command
-- format: SX
-- where X number of slot to select in hex
macroses["S"] = function()
  local item = tonumber(im.readCmd(), 16)
  rb.select(item)
end
-- set P as place command
-- format: PX
-- where X number of placing block side
macroses["P"] = function()
  local side = tonumber(im.readCmd(), 16)
  rb.place(side)
end
-- set X as remove/attack command
-- format: XY
-- where Y number of removing block side
macroses["X"] = function()
  local side = tonumber(im.readCmd(), 16)
  local remfin = true
  while remfin do
    if side == 15 then rb.swing()
        else rb.swing(side) end
        if not rb.detect() then remfin = false end
  end
end
 
 
--- ===========
--- ENTRY POINT
--- ===========
 
-- get execution args
local args = sh.parse(...)
if #args == 0 then
  io.write("Usage: ironmacros <macrosfile> [repeatly(true/false)]")
elseif #args == 1 then
  im.run(args[1])
else
  -- TODO: Repeatly execution
end
 
return im

 


Как использовать:
1. Пишем макрос сохраняем в файл
2. В терминале пишем ironmacros <filename>
    filename это имя нашего макроса
3. Profit
 
Имплементированные макрокоманды
# - комментарий, после символа вся строка пропускается
^ - двигаться вперед 
V - двигаться назад
> - повернуться вправо
< - повернуться влево
M - двигаться вверх
W - двигаться вниз
RXXYY - цикл, где XX количество повторов в 16тиричной системе. YY количество команд, которые следует повторять в 16тиричной системе ( считаются только команды, аргументы, передаваемые командам, упускаются)
SX - выбрать слот инвентаря с номером X, номер X 16тиричный
PX - поставить блок впереди себя X - на какой сайд ставить (аналог place([side]))
XY - махнуть активным слотом (атака/поломка блоков) где Y по какому сайду бить (аналог swing([side]) при передаче в качестве параметра F вызывается подефолту swing()
 
Ну и как вы уже заметили (я надеюсь) сейчас все это заточено исключительно под робота.
 
 
Вкратце о внутренностях:
 
1. функции управления литералами макрокоманд
registerMacros(symbol, func)
unregisterMacros(symbol)
регистрирует или снимает регистрацию заданного символа. func функция обработчик
например так:

im = require("ironmacros")

local func = function() print("ZzzZzzZzzZ") end
im.registerMacros("Z",func)

теперь если записать в макрос Z будет в терминал будет напечатано "ZzzZzzZzzZ"
Эти функции нужны лишь для того что бы расширять язык. Для пользования текущей версией они не нужны.
 
2. функции исполнения
run(filename) - открывает файл в котором записана последовательность макрокоманд и запускает ее. filename - имя файла
readCmd() - читает макрокоманду соответственно значению регистра pc(pc.x pc.y)
exec(cmd) - запускает команду cmd на исполнение. Под командой имеется ввиду макрокоманда "Z" или ">"
Эти функции нужны лишь для того что бы расширять язык. Для пользования текущей версией они не нужны.
 
3. Функции управления регистром
fstep([count]) - функция инкрементирует значение регистра pc.x (если требуется инкрементировать pc.y , pc.x присваивается 1 ). count опционально коллчество шагов
dstep([count]) - функция инкрементирует pc.y присваивает pc.x 1 если больше нет команд на исполнение заканчивает скрипт. count опционально коллчество шагов
set(reg, val) - установить регистр reg ("x" или "y") на значение val
Эти функции нужны лишь для того что бы расширять язык. Для пользования текущей версией они не нужны.
 
4. Добавление своей макро команды
В исходнике все макрокоманды добавлены используя вышеприведенные функции.
Можно ознакомится, там все просто. Раздел REGISTRED DEFAULT MACROSES
 
 
 
PS Да забыл pastebin.com:
 
lib: http://pastebin.com/eBbZrRGi
macros: http://pastebin.com/Q4DRDKDV

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Круто, на CC делал подобное, но теперь там есть http://www.computercraft.info/2015/07/01/introducing-computercraftedu/

 

Интересно, но я не люблю визуальное программирование, если это не behaviour-tree или fsm ну или какой нибудь граф типа диалога или квеста).

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Это сделал человек, который "сегодня утром ничего не знал о Луа"?  :blink:

Не верю!

Изменено пользователем Zer0Galaxy

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Фрэдо, правда, а сделай графический редактор? Пусть эти макросы действительно как в CCedu будут блоками. Объеденись с кем нибудь и замути. Будет ведь суперски.

Изменено пользователем Krutoy

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Фрэдо, правда, а сделай графический редактор? Пусть эти макросы действительно как в CCedu будут блоками. Объеденись с кем нибудь и замути. Будет ведь суперски.

 

Теоретически можно, но сейчас я тут разбираюсь в модах поскольку я ничего о них не знаю, и обживаюсь на сервере. Как маломальски адекватный уровень будет, можно разбираться будет с gpu'ом, как оно там все работает и рисует. Я мельком взглянул на апи не совсем понял что там к чему. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в тему...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


×
×
  • Создать...