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

Doob

Гуру
  • Публикации

    1 089
  • Зарегистрирован

  • Посещение

  • Победитель дней

    141

Сообщения, опубликованные пользователем Doob


  1. Что-то у меня не выходит вывести функцию, которая из полученного параметра будет вычислять принадлежность блока.

    Если сгенерировать значения шума и для каждого результата сканирования делать обратную операцию

    (result - 1.5) / d / 2 not in noise and (result - 3) / d / 2 in noise

    Тогда получается вот такое распределение:

    QRV6G1A.png

     

    Вероятность угадать руду - 35.848%, вероятность перепутать с камнем - 0.024%

    Если вместо and использовать or, то получается 99.983% на руду и 48.682% на камень.

     

    Если попробовать разделить облака вероятностей линейно, то в лучшем случае будет 71.058% для руды и 28.166% для камня.

     

    Самый быстрый способ определять руду это хеш-таблица. Сгенерировать и хранить в памяти 287889 чисел (количество значений шума * все возможные дистанции). Точность будет 99.998%

     

    Более эффективного метода не придумал. Функция разделения облаков слишком высокочастотная, но должна быть другая, которая может из расстояния до блока и его результата сканирования, выдавать реальную плотность.


  2. 51 минуту назад, eu_tomat сказал:

    Теперь предлагаю подумать над тем, как решить конкретно эту задачу за одно сканирование.

     

    Хм.. Использовать артефакты дискретизации? Я пока не понял, как отсеять значения, без генерирования маски. Но кажется, должно сработать.


  3. 1 час назад, eu_tomat сказал:

    Вопросы: что за блок мы просканировали: это руда или камень? Почему? Какое количество сканирований оказалось достаточным для однозначной идентификации блока?

    • Руда.
    • math.max(3 - 30 * 0.606, 1.5 + 30 * 0.06013) < 3.341
    • Два.

    Накидал простой скрипт на питоне, для наглядного представления сканирований.

    P4v8cL8.png

    import matplotlib.pyplot as plt
    import numpy as np
    
    CONST_A = 0.0601325742900371551513671875
    CONST_B = -0.060606062412261962890625
    
    x, y = np.array([0, 56, 56, 0]), np.array([0, 56 * CONST_A, 56 * CONST_B, 0])
    
    plt.fill(x, y + 1.5, color = 'k', alpha = 0.5)
    plt.fill(x, y + 3, color = 'c', alpha = 0.5)
    
    # scans
    plt.scatter([30, 30, 30], [1.295, 3.341, 1.580], color = 'DarkBlue')
    plt.show()

    В scatter подать список расстояний и список полученных плотностей.

     

    Все-таки я сильно сомневаюсь, что многократное сканирование это рационально. Там ведь распределение равномерное и с расстоянием пересекающаяся область увеличивается до 72%, а это примерно 1.7% на каждый блок

    • Нравится 2

  4. Довольно не очевидно. Для меня, шапочно знакомого с жавой и скалой, казалось, что byte должен быть unsigned char, а оказалось совсем странно.

    Получается, что точная константа для "положительного шума" будет 127 / 128 / 33 * 2

    А для отрицательного -128 / 128 / 33 * 2

    Где 2 - это константа конфига.

    С учетом, что точность float там 32 бита, получаем значения -0.060606062412261962890625 и 0.0601325742900371551513671875

    Разница кажется не очень существенной. 0.0004734881...


  5. Я просто ничего не понял, поэтому прошел весь путь сам. Можно было бы сделать еще понятнее и наглядней. Главное получить константу - многократным сканированием определить максимальную погрешность двух блоков, затем линейной регрессией вычислить множитель.

    Хотя, конфиг сервера вроде-бы всегда копируется клиенту, поэтому если множитель не стандартный, то можно посмотреть в конфиг и подогнать уже известную константу.

     

    Для своей копалки я тупо взял самый дальний блок и прикинул какой у него будет разброс, затем захардкодил константу. Область сканирования 16x16 блоков, поэтому на расстоянии 8 блоков по диагонали +1 смещение слоя, как раз все попадает в чистые 12 блоков.

    Хотя это не очень умный вариант, получается, что при статичном минимуме 2.25, робот загребает всякую шелуху типа досок/заборов/сундуков. Но свинец имеет плотность деревяхи, поэтому тупой подход как нельзя кстати.


  6. Ничего не понятно, но очень интересно.

    Принятие решения сводится к оценке вероятности попадания плотности в нужный диапазон. Сканирование очень затратно по времени.

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

     

    Можно поступить проще.

    Берем минимальную и максимальную плотность для руды и камня, сравниваем их.

    YY3ps3W.png

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

    Нам нужен камень? Вряд-ли. Пока идем до руды, его и так не мало набирается, следовательно, надо исключить попадание возможных плотностей камня в список целей добычи.

     

    Путем нехитрых манипуляций, выводим формулу получения максимального шума из расстояния. N = R * 0.0606

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

     

    Чтобы отнять максимум плотности камня от минимума плотности руды, можно заюзать функцию math.max, в результате имеем возможность с вероятностью примерно в 99.99% не перепутать камень с рудой на любом расстоянии.

     

    Получаем уровень шума: N = math.sqrt(x^2 + y^2 + z^2) * 0.0606

    Вычисляем минимально возможную плотность для текущего расстояния: math.max(3 - N, 1.5 + N)

    Если полученное число меньше результата сканирования, то все норм, этот блок точно плотнее камня и за ним можно ехать.

     

    Для примера я взял предельный случай, который возникает довольно редко. Можно поиграться с параметрами, например уменьшить коэффициент шума при оценке. Или на расстоянии больше 25 блоков устанавливать минимальную плотность на 3.

    • Нравится 5
    • Ха-ха 1

  7. Жесть какая.

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

     

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

    • Нравится 2

  8. Можно восполнить заряд прямо в инвентаре, не отходя от кассы.

     

    Всякие рулетки и однорукие бандиты это да, дело не хитрое. Скинов разных только для слотов нарисовать и дело в шляпе.

    А вот с покером у меня вышел затык, изначально игра была между игроками и одним ботом (бот всегда в игре, поэтому играть всегда есть с кем), но есть ньюанс. Если игроки скооперируются, то легко могут обыграть бота, я взялся писать полное решающее древо с возможностью собирать статистику и анализировать каждого игрока, чтобы против читеров переходить в режим бога. В результате забросил перенос самого покера, а потом и бота тоже.

    Если сделать игру только между игроками, без ботов, то это дело не хитрое, за пару вечеров накидаю. Там логика на 100 строчек и отрисовка на 50. Только надо чтобы игроки приходили со своими планшетами и через клиентские программы подключались к игровому столу, чтобы нельзя было подсматривать карты.

     

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


  9. У меня рулетка была и покер, но это дело надо почти с нуля переписывать, ибо с совместимостью проблемы.

    Куча всяких программулинок на форуме валяется, но их надо либо допиливать напильником, либо переделывать по новой.

     

    Магазин на днях допилю, как одолею лень. Надо пару фич добавить и плотно потестить. Засунул весь функционал в один сервер для упрощения. Работа с очками происходит немного заторможено из-за задержек между действиями, но зато вся информация актуализируется в реальном времени. Удобно будет прямо в шахте сдать добычу, купить еды и копать дальше.

    Можно наверно, даже добавить модуль для работы с инструментами/броней, чтобы не бегать домой на подзарядку, а купить энергию как в банке Тоторы, и продолжить копать.

    3gsENra.png

     

    Финтифлюшки для спавна можно в процессе наделать, тут вдохновение надо поймать.

    • Нравится 1

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

    https://i.imgur.com/Gw9fY2P.png

     

    Могу нарисовать именно по символу на блок или два, чтобы оно сбалансировано смотрелось, а то даже в моноширинных шрифтах кернинг плавает.

    Хотя, в опенкомпах юзается fixedsys или что-то похожее, если его увеличить в два раза, он почти идеально ложится в два блока. Но вид его мне не очень нравится.

    https://i.imgur.com/BDzGG8R.png

     

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


  11. Можно написать прогу, которая будет потреблять любой шрифт и центрировать текст по блокам. Даже можно результатом выдавать команды на получение порезанных 3D моделей.

     

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


  12. Ну этот логотип я сам рисовал для своей торговой площадки.

     

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

    Потом в пеинте набрал, подтянул до нужного размера, в 1-2 блока, выровнял и кинул в магику, из магики в конвертер Крутого.

    • Нравится 1

  13. В 27.03.2020 в 17:16, Alex сказал:

    Требуются решетки, как на мцскилл проекте, и цепи (звено полное, и сверху снизу полузвенья в блоке), то есть решетка и цепь - стыкующийся блок по горизонтали и вертикали соответственно

     

    А почему обязательно цепи и решетки, может что-нибудь более техно-модерновое?

    К тому же, админским шаманством можно обойти ограничение в 24 шейпа и сделать детализацию побольше.


  14. Собственно вот, что я наколдовал. Листву рубит, латекс собирает, но не более. Для стабильной работы надо еще кучу факторов учитывать.

    Функция main принимает количество деревьев в ряду.

    local robot = require('robot')
    
    local function monkey()
      local c = 0
      while robot.detect() do
        robot.use()
        robot.swingUp()
        robot.up()
        c = c + 1
      end
      for i = 1, 3 do
        robot.turnRight()
        robot.swing()
        robot.forward()
        robot.turnLeft()
        robot.swing()
        robot.forward()
        robot.turnLeft()
        for j = 1, c do
          robot.use()
          if i%2 == 0 then
            robot.swingUp()
            robot.up()
          else
            robot.swingDown()
            robot.down()
          end
        end
        robot.use()
      end
      robot.turnRight()
      robot.swing()
      robot.forward()
      robot.turnRight()
    end
    
    local function main(m)
      for n = 1, 2 do
        for i = 1, m do
          robot.turnRight()
          monkey()
          if i < m then
            robot.swing()
            robot.forward()
          else
            robot.turnAround()
          end
          robot.swing()
          robot.forward()
        end
      end
    end
    
    main(6)

     

    • Нравится 2

  15. Защита от бряка программы никуда не делась, просто она теперь не такая топорная, да и кликать по монитору можно без клавиатуры.

     

    Вот пара моделей переключателей.

     

    Скрытый текст

    MQUrlOJ.png

     

    {label="ff1",emitRedstone=true,shapes={{7,5,14,9,11,15,texture="redstone_block",state=true},{6,6,15,10,10,16,texture="emerald_block",state=true},{6,6,15,10,10,16,texture="emerald_block"},{5,7,14,11,9,15,texture="lapis_block"}}}
    
    
    
    {label="ff2",emitRedstone=true,shapes={{6,6,13,9,9,15,texture="stone"},{5,7,14,6,8,15,texture="planks_oak"},{9,7,14,10,8,15,texture="planks_oak"},{4,7,14,5,13,15,texture="planks_oak"},{10,7,14,11,13,15,texture="planks_oak"},{5,12,14,10,13,15,texture="redstone_block"},{6,6,13,9,9,15,texture="stone",state=true},{5,7,14,6,8,15,texture="planks_oak",state=true},{9,7,14,10,8,15,texture="planks_oak",state=true},{4,2,14,5,8,15,texture="planks_oak",state=true},{10,2,14,11,8,15,texture="planks_oak",state=true},{5,2,14,10,3,15,texture="redstone_block",state=true}}}
    
    
    
    {label="ff3",emitRedstone=true,shapes={{7,6,14,9,8,16,texture="emerald_block"},{7,8,15,9,10,16,texture="redstone_block"},{6,5,15,10,6,16,texture="obsidian"},{6,6,15,7,10,16,texture="obsidian"},{9,6,15,10,10,16,texture="obsidian"},{6,10,15,10,11,16,texture="obsidian"},{7,6,15,9,8,16,texture="emerald_block",state=true},{7,8,14,9,10,16,texture="redstone_block",state=true},{6,5,15,10,6,16,texture="obsidian",state=true},{6,6,15,7,10,16,texture="obsidian",state=true},{9,6,15,10,10,16,texture="obsidian",state=true},{6,10,15,10,11,16,texture="obsidian",state=true}}}

     

    Библиотека такая себе, это больше редактор. Надо чтобы на одной страничке рендерились превьюшки и небольшое описание. Хотя и то будет лишним, любую модельку можно за несколько минут слепить и распечатать самостоятельно.

     

    • Нравится 1

  16. 6 часов назад, Premier_Prince сказал:

    "Ванильные кнопочки и рычажки" не могут быть использованы в привате другими игроками, не являющимися его членами

    А напечатанные на 3D принтере? Помню, мои конструкции постоянно прохожие шатали. Хотя, может это плагин такой дырявый был.


  17. @vx13, @NEO, в рот мне ноги, да вы волшебники! world_interface даже через getAllStacks может теги показывать. Все очень удобно организовано.

    А дебага по функционалу теперь на уровне ванильного комблока.

    • Нравится 1

  18. Cобственно только так и можно, просто в OpenOS это красиво завернуто в io с буферами.

    В самом простом случае можно писать так:

    local function fs_write(path, mode, data)
      local handle = filesystem.open(path, mode)
      filesystem.write(handle, data)
      filesystem.close(handle)
    end

    И читать:

    local function fs_read(path)
      local handle = filesystem.open(path)
      local buffer = ''
      repeat
        local data, reason = filesystem.read(handle, math.huge)
        if not data and reason then
          return nil, reason
        end
        buffer = buffer .. (data or "")
      until not data
      filesystem.close(handle)
      return buffer
    end

     


  19. Это да, проблема. Если данные не затирать, а мержить по разнице, то игрок может случайно изменить то же значение. Я так подозреваю, что в команде /data merge это и происходит.

    А что если посылать не точные значения, а саму разницу? Например, +10 блоков в слоте или -10 ед. опыта, при несовпадении значений просто игнорить.

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