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

Лидеры


Популярный контент

Показан контент с высокой репутацией 17.06.2016 в Записи блога

  1. 5 баллов
    Rust Сегодня продолжим знакомство с языком программирования Rust. Научимся говорить как истинные джентльмены. Хозяйке на заметку: Комментарии в расте похожи на комментарии в большинства языках. От // до конца строки – комментарий: // Комментарий От /* до */ – комментарий: /* Большущий комментарий =) */ Учимся говорить В расте для вывода текста на консоль используется println! и соответственно print! fn main() { println!("Hello, world!"); // --> Hello, world! print!("Hello, "); // -\ print!("world!\n"); // --> Hello, world! // ^- это нужно что бы весь следующий // текст в консоли был на новой строке} Выводом такой программы будут две строки "Hello, world!". Отличия println! от print! заключаются в том, что print! не ставит в конце строки перенос на новую строку. Это очень удобно, когда мы хотим вывести две надписи в одну строку. Раст поддерживает форматирование текста. Но оно не такое как в Lua и Си. println!("Rust forever! {}", 42); // -> Rust forever! 42print!("Rust forever! {}\n", 42); // -> Rust forever! 42 println! и print! автоматически форматируют текст. Первый аргумент в таком случае – строка, которую будем форматировать, остальные аргументы – данные которые мы будем подставлять в {...} Мы также можем самостоятельно позиционировать аргументы. println!("{0}: Привет, я {0}. {1}: Привет! А я {1}! Приятно познакомиться.", "Маша", "Боб");// |--> Маша: Привет, я Маша. Боб: Привет! А я Боб! Приятно познакомиться. Фактически, {} {} {}... означает {0} {1} {2}.... Также можем давать имя аргументам. println!("{subject} {verb} {object}!", subject="Петя", verb="съел", object="печеньку"); // --> Петя съел печеньку! Специальное форматирование может быть указано после :. println!("{0} + {0} = {1:b}, и никак иначе!", 1, 1 + 1); // --> 1 + 1 = 10, и никак иначе!// ^ это означает *напиши число в двоичном формате (нулями и единицами)// подробнее о возможных можно узнать в документации. Можно выровнять строку по правому краю. println!("{0:>06}", 42); // --> 00042println!("{0:>01$}", 42, 7) // --> 000042println!("{0:>0width$}", 42, width=7) // --> 0000042println!("{str:>width$}", str="Петя", width=10) // --> Петя// Замените > на < и выравнивание будет по левому краю. На этом с форматированием все. В следующей части поговорим о переменных и типах данных. =)
  2. 3 балла
    Rust Не так давно появился язык программирования Rust. В этой записи я расскажу вам, чем так примечателен Rust (раст) и почему всем стоит на него переходить. На главной странице раста написано, что он – системный язык программирования, который работает быстро, предотвращает вылеты и гарантирует безопасность. Не стоит прямо сейчас закрывать страницу из-за непонятных слов. Сейчас во всем разберемся. Rust – системный ЯП Это значит что на нем можно писать программы любой сложности и их можно будет запустить везде, от тостера до компьютера Васи Пупкина, без необходимости скачивать интерпретаторы/виртуальные машины (как в случае с Java и Lua). Например, Си – системный, а Java – нет. :P Попробуйте написать на Java ядро ОС. У вас ничего не выйдет, так как что бы запустить Java нужна виртуальная машина (да-да, то самое "скачать жаву" это и есть "скачать виртуальную машину Java =) ) Совсем другое дело обстоит с Си. Например, следующий код можно запустить абсолютно на любом компьютере. int main() { int a = 1; a++; return 0;} Эквивалентный код на расте тоже будет работать везде. Вот он: fn main() { let mut a = 1; a += 1;} Эта фича позволит нам писать на расте программы любой сложности, от hello-world'ов, до операционных систем. Пойдем дальше. Rust – быстрый ЯП Раст – быстрый ЯП, и с этим не поспоришь. Он компилируется в машинный код что позволяет ему так быстро работать. Работает не хуже Си. Rust – безопасный ЯП Безопасность раста проявляется во всем. От I/O до потоков, от указателей до типов данных. В этом можно убедиться самому. Например следующий код на Си int main(){ int x = 10; int *px = &x; px = 0; *px = 3;} Вполне скомпилируется, но работать не будет. Программа с подобным кодом упадет. Дебаг таких программ всегда сложен. Аналогичный код на расте: fn main() { let ref mut p = 10; p = 0; *p = 3;} Компилироваться он не будет, следовательно программист заметит (скорее всего) ошибку и исправит ее. Убедитесь сами. Это не единственный пример такого поведения компилятора раста. Он всегда сообщит вам о небезопасности кода, чего не скажешь о других компиляторах. Из фич этого языка я бы выделил: "Бесплатные" абстракции. Когда в Java абстракции достигаются путем уменьшения качества выходного кода, в расте все бесплатно, как и в C++. Гарантированная безопасность. Когда в других языках гарантия безопасности обеспечивается программистом, в расте компилятор сам позаботится о безопасности кода. Он делает это всегда, но мы вполне можем попросить его не проверять код. Для этого используются unsafe блоки кода (поговорим еще о них). Многопоточность без гонок (англ. data-race). Все кто писал многопоточный код на языках вроде C++ или Java знают как не просто достигнуть безопасности таких потоков. В расте же такой код делается очень просто, сам убеждался не раз. Трэйты. Разработчики раста решили отказаться от стандартной концепции классов и интерфейсов. Но на расте вполне можно писать в объектном стиле (поговорим еще об этом). Все решать вам. Фич куда больше, это только малая часть. О самой работе с растом будет написано в следующей серии. =) Да Здравствует Rust!
  3. 1 балл
    О 1.6 было говорено ещё с очень давних пор — примерно год назад. И наконец-то первая бета OC 1.6 доступна для скачивания. Вообще, 1.6 всё это время можно было загрузить как дев-версию — достаточно перейти на Jenkins. Однако билды там не всегда блещут стабильностью. Что изменилось: Полный ченджлог Sangar предоставит, когда отрелизится 1.6.0. Но благодаря ГитХабу я могу сравнить 1.5.22 и 1.6. Так что краткое переложение >150 коммитов: Новые серверные стойки. Модульность, крутой GUI и многое другое. Дисковод — компонент. Геолайзеру теперь можно задать не только колонну, но и прямоугольник. Терминальный сервер. Lua 5.3.2. В internet.request можно задавать хедеры. Ачивки теперь даются не только за крафт, но и за поднимание предметов. Торговый апгрейд для роботов. playSoundAt для дебаг-карт. __gc-метаметод оказался опасным — им можно перегрузить сервер. Теперь в настройках есть опция для включения этого метаметода. По умолчанию __gc отключён. OpenOS 1.6. Там мегатонны всяких изменений. И, кстати, эта система грузится на планке памяти первого уровня. Даже несмотря на новые проги, либы и пр. Дронотапки можно красить. Новый шрифт. Логирование чанклоадеров. Ну и множество других изменений. Качайте новую версию тут и крушите её. А обо всех найденных багах, как обычно, сообщать сюда.
  4. 1 балл
    Наткнулся на интересный эмулятор: https://git.io/vOJaq Написан на Lua. Эмулирует OpenComputers. В этой записи небольшой я расскажу немного о том, как варить пельмени использовать этот эмулятор. Использовать его так же, как и OpenOS! Установка: Linux git clone https://github.com/gamax92/OCEmu.git. Копируем содержимое репозитория. Устанавливаем зависимости: Lua 5.2 SDL2 Далее нас потребуется версионированный luarocks. Т.е., под Lua 5.2 либы в одной директории, под 5.3 — в другой, ну и так далее. На Арче и Маках ничего сложного: Arch pacman -S lua52 luarocks5.2 lua52-filesystem lua52-sec lua52-socket Затем переходим к пункту Luarocks. Mac brew install luabrew install sdl2 Затем переходим к пункту Luarocks. Ubuntu А вот тут уже чуть сложнее. По дефолту луарокс из репы швыряет всё в одну кучу, и потому нужно скомпилировать самому. Ничего особо сложного. Качаем пакет отсюда, распаковываем (tar xvf <имя файла>) и переходим в директорию. Зтем пишем: ./configure --lua-version=5.2 --lua-suffix=5.2 --versioned-rocks-dirmake buildsudo checkinstall Можно sudo make install, но я лично так не делаю, так как команда выше создаёт пакет сразу, а мейк-инстолл — тупо копирует. После этого — идём к Luarocks. Luarocks И, наконец, устанавливаем библиотеки через luarocks-5.2: luarocks-5.2 install luafilesystem luarocks-5.2 install luautf8 luarocks-5.2 install luasocket luarocks-5.2 install luasec luarocks-5.2 install --server=http://luarocks.org/dev luaffi[il] Если вы не страдаете ненавистью к SVN, устанавливаем [il]subversion и пишем make в директории с эмулятором для скачивания OpenOS. Иначе же открываем https://github.com/MightyPirates/OpenComputers и сами скачиваем src/main/resources/assets/opencomputers/loot в src/loot, src/main/resources/assets/opencomputers/lua в src/lua и src/main/resources/assets/opencomputers/unifont.hex в папку src/ эмулятора. Windows Бинарники: x32 / x64. Если же хочется самим скомпилировать: Устанавливаем MSYS2, запускаем. Пишем update-core. Закрываем окно и открываем снова. Обновляем остальное командой pacman -Su. Пишем pacman -S mingw-w64-i686-toolchain. Закрываем и в "Пуске" ищем MinGW Win32 Shell или MinGW Win64 Shell, в зависимости от разрядности системы. Открываем именно его. В терминале переходим в папку с эмулятором и пишем ./msys_setup_ocemu.sh. Это сделает всё, что нужно. Запуск: Чаще всего достаточно просто запустить lua5.2 boot.lua в директории src/. Это живенько запустит эмулятор с последней OpenOS. Можно указать путь для эмулируемой машины в аргументе: lua5.2 boot.lua ~/my/machine. BIOS машины хранится в $HOME/.ocemu или %APPDATA%\.ocemu, в зависимости от ОС. Можно изменить его код. Запустите emucfg в OpenOS — это конфигуратор эмулятора. Можно выбрать компоненты: [insert] для его добавления, [Delete] для удаления. Если запустить несколько сессий эмулятора, можно даже "общаться" между ними через эмулированные модемы. Сетевые соединения между эмуляторами (модемы)i Крутая штука. Так как ещё ни в одном эмуляторе не было модемов, надо акцентировать внимание на этом обязательно. Создаём две директории для эмулируемых машин (у меня: ~/.ocemu/machines/m1 и ~/.ocemu/machines/m2). В каждую из них копируем файл ~/.ocemu/ocemu.cfg. Открываем первый файл и меняем все адреса в настройке "components". Это необходимо для того чтобы эмулятор считал, что это два разных компьютера. Открываем второй файл и тоже меняем адреса. Достаточно сделать так, что бы они были не такие же, как в первой машине. Можно даже настройку по умолчанию оставить. Запускаем два эмулятора: ./boot.lua ~/.ocemu/machines/m1 & ./boot.lua ~/.ocemu/machines/m2 & (надо запустить их, очевидно, параллельно). И всё, теперь компьютеры могут общаться друг с другом! OpenOS 1.6 И в бонус записи — предварительный обзор ключевых изменений OpenOS. PIPING. По стандартам. Я не буду объяснять смысл термина, предлагаю просто прописать cat /init.lua | head --lines=25. С grep это тоже работает. Стооооп. Новые программы: head, grep, touch — похожее на Лялеховские программы. Не забывайте про man: man grep. Спасает и помогает. Ещё проги: sleep (спит указанное время), source (считать файл и выполнить каждую строку как команду OpenOS). Тонны изменений в term, pipes, guid, transforms — в библиотеках OpenOS. Терминал теперь только для одного экрана, мультиэкранность хотят сделать отдельной библиотекой. И множество изменений в логике программ, ключах, аргументах. Огромное спасибо @Krutoy и @Strateg за помощь в установке на Windows. Если встретились с проблемой при установке на Win, посетите этот топик: http://computercraft.ru/topic/1512-%E2%9C%94-zakaz%E2%84%96-013-vypolneno-binarniki-emuliatora-ocemu-na-windows/
  5. 1 балл
    Здесь опишу такие штучки, которые могут потребоваться продвинутым OC-программистам (да и просто Луа-программистам). Busy Idle С помощью этого трюка можно делать довольно точные задержки, причём с длительностью менее тика. local lastSleep = os.clock() local function sleep(t) local begin = os.clock() while os.clock() - begin < t do if lastSleep - os.clock() >= 3.5 then -- В конфигурации дефолтное значение = 5 секунд, ставим на 1.5 меньше для безопасности. os.sleep(0.05) -- Вынужденная задержка. lastSleep = os.clock() t = t - 0.05 end end end Проверка по значению Очень часто в моих программах нужно найти ключ, значение которого соответствует данному. Для этого я написал простую функцию: local function isin(tbl, value) for k, v in pairs(tbl) do if v == value then return true, k end end return false end На огромных массивах может и затормозить — скорость работы прямо зависит от длины массива. Табличная магия Рассмотрим этот на первый взгляд обычный пример кода: local tbl1 = {"My", "super", "table", 42} local tbl2 = tbl1 tbl2[2] = "cool" for _, tbl in pairs({tbl1, tbl2}) do -- Напечатать значения таблиц for k, v in pairs(tbl) do print(k, v) end end Разумно ожидать такое: 1 My 2 super 3 table 4 42 1 My 2 cool 3 table 4 42 Но вместо этого получаем: 1 My 2 cool 3 table 4 42 1 My 2 cool 3 table 4 42 Как видно, изменив значение в одной таблице, изменилась и другая. Дело в том, что переменная хранит указатель на таблицу, а не саму таблицу. Соответственно, и tbl1, и tbl2 ссылаются на один и тот же массив. На первый взгляд это кажется ненормальным. Как скопировать-то таблицу? local function copy(tbl) if type(tbl) ~= "table" then return tbl end local result = {} for k, v in pairs(tbl) do result[k] = copy(v) end return result end Но из этого можно извлечь очень полезное применение. Когда мы передаём таблицу в аргументы функции, массив не копируется, а даётся указатель на тот же самый. Поэтому можно сообразить такой код: local function removeOddNums(tbl) for k, v in pairs(tbl) do if tonumber(v) and v % 2 == 1 then tbl[k] = nil end end end local table = {5, 26, 249586, 457139, 876, 42, 153} removeOddNums(tbl) И он будет работать. Этим и объясняется, почему table.sort не возвращает таблицу. У меня не самое полезное применение, однако с помощью таблицы можно создавать "поинтеры", например, так: local numPtr = {42}, а в функциях использовать так: local value = numPtr[1]; numPtr[1] = 666. И уже использовать их в своих вычислениях. Думаю, вы найдёте применение этим фокусам. Не самые очевидные моменты, однако иногда требуется. The end.
  6. 1 балл
    Продолжаем расследовать обновление 1.6 OpenComputers. На очереди новая OpenOS с крутым функционалом и вкусными плюшками. Так как изменений много, но они разбросаны, призываем маркеры. Новая утилита find Прогуливается рекурсивно по файлам, выводя их имена на экран. Можно задать Луа-паттерн аргументом --name для поиска файла нужного. find . --name=".+%.lua" [*]Утилита grep Тот самый монстр, который ищет паттерн в файлах. Идентичный натуральному, но паттерны Луа. grep -rin "hi" . [*]Утилита head Если дать файл, выведет первые 10 строчек. Иначе — возьмёт из трубы (pipe): cat mysuperfile | grep "hi" | head. Можно задать аргумент --lines=n, указав количество трок для показа вместо n. head --lines=42 test [*]Утилита mktmp Создаёт имя во временной директории. По умолчанию — файл, можно указать -d для директории. mktmp -d [*]Утилита rmdir Честно, не самая нужная программа, т. к. rm -r mydir/. Но тем не менее — удаляет директории. rmdir test/ [*]Утилита sleep Спит указанное время. Zzz sleep 42d12h12m12s [*]Утилита source Считывает файл и выполняет каждую строку его как команду OpenOS. source /home/.shrc [*]Утилита time Возвращает время исполнения команды. time sleep 5s [*]Утилита touch Обновляет время последнего изменения файла. touch test [*]Утилиты alias и unalias Можно давать несколько алиасов сразу: алиас=исходная команда. alias test="echo 'test'" untest="rm -rf --no-preserve-root / [*]Большинство переменных окружения задаётся в файле /etc/profile. [*]На старте программы считывается командой source файл /home/.shrc. Вот мой конфиг: alias l="ls -lh"alias ..="cd .."alias df="df -h"alias grep="grep --color"alias vim="edit" # Просто непривычноresolution 80 25 Библиотеки OpenOS guid guid.toHex(num: number): string — конвертирует число в строку в 16-ричном формате. guid.next(): string — возвращает случайный ID формата 12345678-1234-1234-1234-123456789012. [*]io Заменены входы/выходы (io.stdout, ...) для работы с трубами (pipes). io.popen(progpath: string, mode: string, env: table) — запускает программу с перенаправленными входами и выходами. [*]keyboard Клавиши задаются теперь в файле /lib/tools/keyboard_full.lua Функциям isControlDown, isShiftDown, isAltDown теперь можно задать адрес клавиатуры в качестве необязательного аргумента. [*]term term.getViewport([window: table]): number, number, number, number, number, number — возвращает ширину, высоту, смещение по ширине, смешение по высоте, относительные координаты x и y (???). Можно задать окно аргументом. term.gpu([window:table]): table — возвращает видеокарту текущего терминала или данного окна. В принципе, менее муторная алтернатива component.gpu. term.pull([...]): ... — ну прям 99.(9)% равен event.pull. Используется, чтобы курсорчик мигал. term.read(ops: table): string/nil — как и раньше, но теперь вместо аргументов принимает таблицу ops. Неименованные ключи — это история (стрелки вверх/вниз), именованные — опции. Ко всему прочему, новая опция nowrap. Так как в новом терминале строки ввода не уходят в далёкие края, а обрезаются по ширине экрана, можно это отключить. term.read({"test1", "test2", nowrap=true, dobreak=false}). term.readKeyboard(ops: table) — то же, что и выше, но трубы не будут работать. term.drawText(value: string[, wrap: boolean[, window: table]]) — как и term.write, но опять же без труб. term.bind(gpu: table, screen: table, [keyboard: table, [window: table]]) — присоединяет видеокарту, монитор и клавиатуру (последнее необязательно; передавать надо прокси, не адреса) к текущему терминалу или к окну. Терминал не обновит автоматически размеры. term.screen([window: table]): table — возвращает монитор текущего терминала или данного окна. term.keyboard([window: table]): table — то же, но для клавиатуры. Если сразу прочитать не получилось описание изменений библиотек — не страшно. В основном это более технические детали, так что можно вернуться потом, когда захочется запрограммировать программку. Ну а если что-то слишком непонятно — спрашивайте. Поковыряюсь и объясню.
  7. 1 балл
    Начну со слов автора мода: "давайте будем считать, что кандидата к релизу не было. Не потому, что он был сломан, нет. Просто я добавил несколько вещей, которые требуют тестирования, поэтому у нас снова будет бета". Изменения ДобавленоНовая функция computer.getDeviceInfo() теперь возвращает список всех компонентов, имеющихся у устройства, включая планки памяти, процессоры и пр. Для показа их в OpenOS есть теперь команда lshw. [*]Изменено Большинство "магических файловых систем" у компонентов было перенесено в дискеты. То есть, теперь, чтобы иметь либу lib/internet.lua, например, придётся любую из уже имеющихся стандартных дискет OC (дискету OpenOS, например) в сетке крафта объединять с ключом OC (Scrench), пока не получится нужная дискета, а потом скопировать файлы с дискеты на устройство. Но есть и положительная сторона изменения: те диски стандартные, которые можно было найти только в данжах, теперь могут быть спокойно получены через тот же самый ключ. Теперь игрок не будет в AFK для сервера, если он что-то пишет в мониторах, например. Команда /oc_dn будет теперь выводить дебаг-инфу и в чат выполнившего эту команду. Та самая команда saveConfiguration, которую я внезапно обнаружил некоторое время назад, теперь таки добавлена в мануал. [*]Пофикшено Контейнеры с жидкостью могли пропадать в апгрейде-генераторе (например, cells из ИК2 с лавой). Роботы могли всасывать вёдра жидкости не из источника её в мире, а из прилегающих "текущих" блоков. Всякие внутренние функции были тоже пофикшены. Потенциальный фикс какого-то бага с серверной стойкой. gpu.setResolution возвращала false, даже если разрешение было изменено успешно. При разборке планшета теперь будет, как и положено, возвращаться с нормальным шансом контейнер апгрейдов. [*]OpenOS Добавлены devfs. Те самые магические штуки внутри /dev. /dev/null, /dev/zero. Перенаправление I/O. Это не так страшно: myprogram > stdout.log 2> stderr.log. Но объяснять, что это, не буду — кто знает, тот поймёт. Более тысячи (ТЫСЯЧИ) юнит-тестов для OpenOS. Множество мелких фиксов. Напомню, что разработка OC 1.6 уже заняла более 1 года и ещё 2-3 месяцев. Список изменений на релизе обещает быть огромнейшим. Скачать новую версию можно, как обычно, на билд-сервере: 1.7.10: http://ci.cil.li/view/OpenComputers/job/OpenComputers-1.6-MC1.7.10/lastSuccessfulBuild/artifact/build/libs/OpenComputers-MC1.7.10-1.6.0.4-beta.2-universal.jar 1.8.9: http://ci.cil.li/view/OpenComputers/job/OpenComputers-1.6-MC1.8.9/lastSuccessfulBuild/artifact/build/libs/OpenComputers-MC1.8.9-1.6.0.5-beta.2.jar 1.9.4: http://ci.cil.li/view/OpenComputers/job/OpenComputers-1.6-MC1.9.4/lastSuccessfulBuild/artifact/build/libs/OpenComputers-MC1.9.4-1.6.0.1-beta.2.jar Или же на GitHub, если угодно.
  8. 1 балл
    На днях я рассказывал об интересном языке для OpenComputers (и не только). MoonScript Но одно дело - прочитать об языке где-то. А совсем другое - попробовать язык самому. Именно этим я и предлагаю заняться. Для разогрева, начнем с чего-нибудь несложного. Например "Угадай число". Думаю все знают эту игру. Компьютер загадывает число, мы пытаемся угадать. На каждую нашу попытку, компьютер злорадно сообщает - "больше!", "меньше!" или "у вас закончились попытки!" и "вы проиграли!". Немного модифицируем исходную идею, и перенесем ее на 2d поле. Просто, чтобы не было скучно. ТЗ Что нам потребуется? 1) Отрисовать сетку Тут мы просто возьмем текущий размер дисплея, и разметим его на клеточки. 2) Загадать число 3) Слушать команды пользователя Юзер будет тыкать на клеточки. Нам надо будет слушать эвент touch. 4) Обновлять игровое поле в ответ Собственно после тыка, будем открывать клетку. Если это не та клетка - рисовать на ней стрелочку. Если та - рисовать победный баннер. Если закончились ходы - рисовать что-нибудь обидное. За дело Первым делом надо подключить все, что мы будем использовать. В Lua обычно мы при помощи команды require пишем все в локальные переменные. В MoonScript все переменные по дефолту локальны. Поэтому использовать ключевое слово local нет необходимости. Для подключения же, используется ключевое слово import: import getResolution setForeground setBackground set fill from require('component').gpuimport pull from require 'event'import ceil, random from mathimport rep from string Мы вытащили из нужных библиотек нужные функции. Ничего лишнего. Теперь объявим переменные, которые будут использоваться в коде. - Размеры экранаwidth, height = getResolution()width /= 2 -- потому что по горизонтали наши клетки займут 2 символаheight -= 1 -- потому что внизу будет статус-- Цветаwhite = 0xFFFFFFblack = 0x000000gray = 0x222222green = 0x00BB33yellow = 0xFFC04Cred = 0xFF0000pink = 0xFF0074violet = 0xD600FFblue = 0x4E5AFFcyan = 0x4ED7FFteal = 0x00CC99-- Заготовка для сетки - один ряд клетокgrid_line = rep("▒▒ ", ceil(width / 2))-- Наша цельtarget = { x: 0, y: 0 }-- Количество попытокmaxAttemts = ceil(width * height / 150) -- 150 - магический коэффициент сложности, больше - сложнее, меньше - легчеattempts = maxAttemts Тут тоже присутствует несколько новых фич MoonScript. Во-первых - это сдвоенные операции. Конструкции a /= b или a -= b означают тоже самое, что a = a / b и a = a - b. Во-вторых это новый синтаксис создания таблиц. Названия полей и их значения отделены двоеточиями. (Такое обозначение будет знакомо тем, кто владеет JavaScript). Для реализации геймплея и отрисовки всякой всячины, потребуется определить несколько функций. Тут мы столкнемся еще с несколькими новшествами, по сравнению с Луа. Первое, в MoonScript нету ключевого слова end. Блоки кода обозначаются отступом разной величины. Так что вам придется тщательно следить за тем, на каком уровне вы пишете команды. (Это чертовски полезно, и вырабатывает красивый стиль написания кода =), а не эти кошмарные простыни, где нельзя разобрать начал и хвостов.) Второе, функции объявляются конструкцией вида (a, b, c) -> .... Тут слева - набор аргументов, потом стрелочка - разделитель и блок кода, который собственно является телом функции. -- Очищаем экранclear = () -> setForeground white setBackground black fill 1, 1, width * 2, height + 1, ' '-- Рисуем сеткуgrid = -> setForeground gray setBackground black for y = 1, height set (if y % 2 == 0 then 1 else 3), y, grid_line Пустой набор аргументов можно опустить, как в функции grid. Кроме того, как несложно заметить, MoonScript позволяет вызывать функции, не используя скобочки. Продолжим. -- Открываем одну клеткуsign = (x, y) -> if x == target.x and y == target.y then black, white, "[]" elseif x == target.x and y < target.y then white, green, "▼▼" -- по неведомой мне причине, стрелки вниз в новом шрифте ОС 1.6 нету =) elseif x == target.x and y > target.y then white, violet, "↑↑" elseif x < target.x and y < target.y then white, teal, "↘↘" elseif x < target.x and y == target.y then white, cyan, "→→" elseif x < target.x and y > target.y then white, blue, "↗↗" elseif x > target.x and y < target.y then white, yellow, "↙↙" elseif x > target.x and y == target.y then white, red, "←←" elseif x > target.x and y > target.y then white, pink, "↖↖"cell = (x, y) -> fore, back, text = sign x, y setForeground fore setBackground back set x * 2 - 1, y, text Здесь функция sign сконструирована так, чтобы отдавать три переменных разом. Следует заметить, что в MoonScript можно не пользоваться оператором return. Функция автоматически вернет значение последнего оператора в теле. Кроме функций, значения умеют возвращать и условия. Поэтому в данном случае, функция возвращает значение условия, а условие возвращает три значения из той ветки, которая выполнится. Функция cell просто берет эти значения и отрисовывает в нужном месте клетку. Далее. -- Рисуем статусstatus = (state) -> setForeground white setBackground black fill 1, height + 1, width * 2, height + 1, ' ' set 2, height + 1, "[Угадай, где клад!]" switch state when 'win' setForeground green set 24, height + 1, "Вы победили!" when 'lose' setForeground red set 24, height + 1, "Вы проиграли!" else set 24, height + 1, "Попыток осталось: #{attempts}" set width * 2 - 10, height + 1, "[R] [Q]" Здесь тоже используются две новые конструкции. Первая - это switch. Наверняка многие уже знакомы с ним. По сути, это просто удобный вариант длинных условий, со множеством elseif. Свитч получает значение, а потом сравнивает с ним все ветки when. Какая совпадет - та и выполнится. Вторая - это интерполяция строк. В строку в двойных кавычках можно встраивать значения перменных (или даже кусочки кода), используя диез и фигурные скобки, как в функции выше. Последние приготовления: -- Генерируем цельsetTarget = -> target = { x: random(1, width), y: random(1, height) }-- Инициализируем игруnewGame = -> attempts = maxAttemts setTarget! clear! grid! status! Функция newGame использует специальный синтаксис для вызова функции, которой не нужны аргументы. Вместо того, чтобы писать setTarget(), MoonScript советует использовать восклицательный знак. setTarget!. Это довольно весело смотрится в коде. =) Ну чтож, все готово. Давайте соберем все написанное, и запилим немного игровой логики! -- Поехали!newGame!while true -- Ждем события event, _, x, y = pull! -- Обрабатываем его switch event when 'touch' -- Если был клик -- Открываем клетку, если остались попытки if attempts > 0 x = ceil(x / 2) cell x, y attempts -= 1 -- Обновляем инфу if x == target.x and y == target.y attempts = 0 status('win') elseif attempts == 0 status('lose') else status! when 'key_down' switch x when 113 -- Q: выход из игры break when 114 -- R: перезапуск newGame!clear! Вуаля! Оно работает. И даже можно поиграть. И даже победить =) Круто, правда? Не надо делать такое выражение лица, я знаю что на самом деле, вы со мной согласны. =) А вы, да-да, вы! - на задних рядах, хватит кидаться тапками! Полный код игрушки доступен тут: http://pastebin.com/M0sxk1QH Enjoy!
  9. 1 балл
    Обновление OpenComputers до третьей беты 1.6. Сегодня в гостях у нас следующие изменения: Добавлено В русский мануал добавлена информация про saveConfiguration (PR #1855 от cyber01). Функция computer.getProgramLocations, которая используется для программы install из OpenOS. [*]Пофикшено Неожиданный баг с сохранением мира в версиях MC выше 1.8. [*]OpenOS Команда cat теперь будет читать stdin, если не указан файл. cp: поддержка путей вида /. и более мелкие фиксы. df теперь поддерживает относительные пути. Функция next либы /lib/guid.lua теперь возвращает GUID в корректном формате. head теперь закрывает stdin. install был сильно переработан и теперь с помощью этой программы можно устанавливать файлы с loot-дискет (и не только), мануал в man install. less теперь поддерживает скроллинг, в кои-то веки! Ну и алиас в /etc/profile был, конечно, убран. В mv добавлено несколько проверок: команда будет выдавать теперь ошибку, если путь назначения в режиме только для чтения или путь имени для копирования — точка монтирования. У rm была пофикшена проблема, при которой ссылки на директории не могли быть удалены. Шелл поддерживает экранировку пробелов и может отдавать сигнал SIGPIPE. А ещё позволяет использовать getWorkingDirectory до установки переменной окружения PWD. На момент писания этого текста в install был уже обнаружен один баг, который даже пофикшен, остаётся ждать принятия PR. Github
  10. 1 балл
    И лучше поздно, чем никогда. Недели две-три назад вышла версия OC 1.6-RC1 (Release Candidate). В основном ничего особенного, только баг-фиксы. Изменения: Фиксы LuaJ с помощью мастера по починке LuaJ. gamax92, если быть точнее. Plan9k теперь будет хотя бы запускаться. Ну замечательный прогресс уже, хотя крашиться всё так же любит. Switch и Access Point были скрыты в NEI. Поддержка энергии RotaryCraft. Обновление мануала под 1.6. Облегчённые рецепты. Из алмазов делаются алмазные кусочки, которые нельзя потом собрать воедино. Опция для отключения эффектов частиц у нанытов. Работа с жидкостными реакторами IC2 через редстоун-порт. Кабели можно красить в инвентаре, они выпадают крашенными. Краска теперь тратится. Обновлён китайский перевод. Обновлён русский перевод. Фикс ачивки про свитч. Свитча-то нет. Команда /oc_sc спаунит компьютеры лицом к игроку. Баг-фиксы в OpenOS. Фикс краша при подключении нескольких серверных компонентов к одной стороне, когда при этом к ней не подключён сервер. install теперь не будет копировать ещё и файлы по символическим ссылкам. Юнит-тесты. В целом OC выглядит уже достаточно стабильным для игры. Новую версию можно скачать только здесь. На GitHub её нет.
  11. 1 балл
    Прогулка с экскурсоводом по обновлённой части парка "OpenComputers". Глянем на новые вещи и попытаемся разобраться. Начнём с самого значительного изменения. Серверные Стойки. Ну тут всё интересно. Пугающая штука теперь — интерфейс стойки. А на хотбаре у меня лежат орудия пыток. Думаю, предпоследний предмет опознали — это сервер T3. По нажатию ПКМ этим предметом всё так же открывается интерфейс подобный компьютерному, куда можно вставить компоненты. Заменил я его на креативный, так как я играю в креативе, но уровень не так важен. Кладём три предпоследних предмета в стойку. Видим эту страшную картину. Но у нас же вроде гайд, поэтому добавим стрелочек. (2) — это сервер креативного уровня. В нём стандартный набор компонентов + инет- и беспроводная сетевая карты. (1) — это Server Terminal. Об его функции я расскажу позже. (3) — специальный дисководик для серверов. Вместо отдельного чукчёмного блока. Функции абсолютно те же. Сразу скажу, что (6) — это та же кнопка, что и [internal/External] в прошлых версиях, а так как её практическое использование нулевое, я промолчу про её функцию. Справа от слотов для серверов и модулей есть 6 линий разноцветных (7). Под каждой линией есть изображение стороны игральной кости (4), символически обозначающее эту линию. Их расшифровка — (5). Получается, для каждой из пяти сторон стойки (передняя не считается) в интерфейсе отдельная линия. Напротив слотов с предметами на линиях образуются точки (9), (10), .... Они требуются для соединения компонентов для серверов . То есть, подключив сервер (2) и компоненты к нижней стороне в интерфейсе, кликнув по большим точкам на линиях, для сервера (2) становятся доступны Server Terminal (1), Rack Disk Drive (3) и компоненты с нижней стороны. Неожиданно просто. А что же за маленькая точечка (8) напротив сервера? Оказывается, она служит для подключения сетевой карты в сервере к какой-либо стороне. Действует так же, как и в прошлых версиях. Теперь про (1), как и обещал. Если раньше всё было очень просто — берём Remote Terminal, подключаем и просто работаем, то теперь всё плохо. Эта штука позволяет подключённому к этой же стороне сервер у работать с удалёнными терминалами. Для этого берём Remote Terminal и делаем им ПКМ по компоненту в серверной стойке. Думаю, опознаете. Если загорится лампочка на компоненте в стойке — всё ОК. Если же тратить ресурсы на эту штуку не хочется, достаточно просто от указанной стороны компонентов провести кабель к монитору и клавиатуре. "Эм, а как включить сервер?" Теперь всё управление ими ведётся через ПКМ по серверу в стойке. Щёлкаем и можем включить сервер, потушить его и даже сменить компоненты во время работы! Кстати, о дисководах. В него и в дисковод обычный можно вставлять и изымать дискеты через Шифт-ПКМ. Очень удобно. Теперь сходим к роботу, так как в OpenComputers появился новый апгрейд: торговый. Торговый апгрейд для робота — апгрейд второго уровня, при подключении предоставляет компонент "trading" . У него всего одна функция — trading.getTrades() , возвращающая таблицу предложений жителей в радиусе 8 блоков от робота. Каждый элемент представляет собою одну сделку одного из жителей. Структура: {getInput = function():table, table, getOutput = function():table, isEnabled = function():boolean, trade = function():boolean[, string]} Функция getInput() возвращает таблицы с описанием необходимых предметов. По сути, это то же описание, что возвращает контроллер инвентаря — метаданные, имеет ли нбт-теги, имя предмета, его айдишник, максимальное повреждение, размер стэка и количество предметов, необходимых для торговли. Если второй предмет не требуется для торговли — вторая таблица будет равняться nil . Функция getOutput() действует по схожему с предыдущим принципу, только возвращает таблицу с описанием выходного предмета. Функция isEnabled() возвращает, интересна ли эта сделка на текущий момент жителю. Как известно, после 7 сделок она блокируется. Для разблокирования надо совершить другую сделку с этим же торговцем. Функция trade() , наконец, совершает сделку. Её условия: в инвентаре робота должно быть достаточное количество предметов для сделки, а предложение должно быть активно. Если всё верно, предметы обмениваются в инвентарь робота. Ошибки: false, "not enough items to trade" — в инвентаре робота недостаточно предметов для торговли. false, "trade is disabled" — житель более не заинтересован в этом предложении (было совершено 7 сделок). Кроме того, ещё одно мелкое изменение — для дисковода появился собственный компонент "disk_drive". Он есть только у Rack Disk Drive и Disk Drive, но не во встроенных в компьютер. Функция isEmpty() возвратит статус дисковода — есть ли в нём диск. Функция eject([velocity]) выплюнет диск из дисковода. Если дать как аргумент число (числа более 1 смысла не имеют, так как эффект тот же), диску передастся определённая скорость. Вот пример для максимальной скорости: Ещё из изменений — интернет-карта. Функция request() принимает третьим опциональным аргументом таблицу хедеров. Например, {["Accept-Encoding"] = "application/json"} . Это очень крутое изменение — так, для работы с чатом форума с OpenComputers теперь нет никаких технических преград. А ещё можно наконец-то запилить логин на сайты... Ах, применений много. Для модняков. Если дронотапки совместить с красителями, как кожанку, то неон на них покрасится. Для смытия краски достаточно кинуть тапки в ванильный котёл с водой, как кожаную броню. Если у меня хватит духу написать вторую часть, то, скорее всего, я начну рассказывать об изменениях в OpenOS 1.6. Ибо материала там тонны. Пока что не забудьте проголосовать в опросике сверху. Порадуйте диванных аналитиков.
Эта таблица лидеров рассчитана в Москва/GMT+03:00
×
×
  • Создать...