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

eu_tomat

Модераторы
  • Публикации

    2 666
  • Зарегистрирован

  • Посещение

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

    331

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


  1. 17 часов назад, OMGSEMA сказал:

    Я пытаюсь подключить мои реакторы к авто контролю реакторов на компьютер но ничего не получается

    1 минуту назад, OMGSEMA сказал:

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

    "Ничего не получается" — это бесполезная формулировка, не несущая никакой новой информации. Эта программа по крайней мере запускается и сообщает о несовпадении количества реакторов и контроллеров красного камня.

     

    5 минут назад, OMGSEMA сказал:

    даже менял подключения

    А что значит "менял подключения"?


  2. 1 минуту назад, OMGSEMA сказал:

    Пробовал много разных и не получается, а программа на этом-же форуме есть

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

     

    Что касается именно этой программы, то она сообщает о том, что не совпадет количество реакторов и контроллеров красного камня, а также предлагает проверить подключения.

     

    Что показала проверка? Всё подключено верно?


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

    local _, x, y = event.pull("touch", nil, nil, "Steve")

    Разжёвывание:

    _,   - Означает отбрасыватель или discard. Используется, когда возвращается или генирируется значение, которое не нужно.

    x, y - Переменные в которые записываются координаты, куда тыкнул игрок по монитору. В нашем случае 'nil, nil'

    Никакой это не отбрасыватель. В данном случае _ является таким же именем переменной, как x и y.

     

    1 час назад, dispeloff сказал:

    Если кто-то ищет взаимный обмен опытом, общение на тему программирование и гейм дев, вот мой дискорд: dispeloff#7807

    Добро пожаловать на сервер ComputerCraft.RU в Discord!

    • Нравится 2

  4. @Oleshe Штука, похоже, нужная. Только описание мутноватое.

     

    8 минут назад, Oleshe сказал:

    адаптер к AE 2 обязателен но и его можно обойти

    Что значит обойти? Для чего его обходить? И как?

     

    8 минут назад, Oleshe сказал:

    Фразы при отсутствий компонента или энергий у сети AE 2 тоже можно поменять.

    Что за фразы? Зачем их менять? На что они влияют?

     

    9 минут назад, Oleshe сказал:

    для автоматического с дистанционным управ. и ручного обновления худа

    Что за худо? О чём идёт речь?

     

    10 минут назад, Oleshe сказал:

    Сообщения модема: add -- добавить элемент к фильтру объектов; del -- удалить элемент из фильтра объектов ; get -- получить таблицу фильтра ; fillter -- Переключить будет ли включен фильтр.

    Что за фильтр? На что он влияет? Что здесь называется объектом?


  5. В 26.12.2022 в 22:02, eu_tomat сказал:

    За сутки эта смутная картинка превратилась в более-менее оформленный набор тезисов.

    Алгоритм стал предельно ясным после выбора модели входящих данных. Модель выбрана такая: изменения в списке игроков маловероятны. Поэтому нет смысла использовать какие-либо сложные оптимизации алгоритма. Достаточно выполнять линейное сравнение записей в двух отсортированных таблицах. При обнаружении различий в очередной паре строк нет смысла в использовании сложных алгоритмов поиска совпадения. Достаточно сдвинуть одну из таблиц на одну строку и двигаться дальше. С большой вероятностью следующая пара строк совпадёт.

     

    После всех этих упрощений у меня получился такой код:

    -- старый и новый списки строк
    local old, new = {}, {}
    -- текущие позиции в списках и их размер
    local o, n, oo, nn = 0,0, 0,0
    -- списки добавленных и удалённых строк
    local add, rmv = {}, {}
    -- и их фактические размеры
    local a, r
    
    while true do
      -- обновить список игроков
      old, oo = new, nn
      new = genNextTable()
      nn = #new
      table.sort(new)
      -- установить на первую запись текущие позиции в старом и новом списках
      o, n = 1, 1
      -- очистить списки добавленных и удалённых записей.
      a, r = 0, 0
      -- основной цикл обработки таблиц
      ::_continue::
        -- Если исчерпан старый список, весь остаток записей из нового копируем в добавленные
        if o > oo then
          for n = n, nn do
            a = a + 1
            add[a] = new[n]
          end
          goto _break
        end
        -- Если исчерпан новый список, весь остаток записей из старого копируем в удалённые
        if n > nn then
          for o = o, oo do
            r = r + 1
            rmv[r] = old[o]
          end
          goto _break
        end
        -- Если текущие записи в старом и новом списках совпали, пропускаем их обработку
        if old[o] == new[n] then
          o = o + 1
          n = n + 1
          goto _continue
        end
        -- Если запись в старом списке меньше чем в новом, то её следует скопировать в удалённые
        if old[o] < new[n] then
          r = r + 1
          rmv[r] = old[o]
          o = o + 1
          goto _continue
        -- Если запись в новом списке меньше чем в старом, то ее следует скопировать в добавленные
        else
          a = a + 1
          add[a] = new[n]
          n = n + 1
          goto _continue
        end
      ::_break::
    end

    Переход на линейный алгоритм сравнения таблиц, а также различные мелкие оптимизации позволили ускорить вычисления в 1.5-2 раза, а по итогу (в сравнении с реализацией от @Anon) в 5-6 раз. Для таблиц размером 20 записей.

     

    @prop Вот теперь имеющийся потенциал полностью растанцован, и оснований для дальнейшего значимого улучшения я уже не вижу даже смутно. Возможно, получится сделать ещё какие-либо мелкие оптимизации. Но сейчас у меня глаз замылен, поэтому я с радостью выслушаю любые предложения.

     

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


  6. 5 часов назад, prop сказал:

    Опять какие-то экспериментальные данные, если разговор идет про алгоритмы, то использовать надо нормальные метрики.

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

     

    5 часов назад, prop сказал:

    Переписали O(n^2) в O(2n), малацы

    Нет, не так. Доступ по ключу требует операций побольше чем O(n). Ускорение мы получили как за счёт уже оптимизированных алгоритмов поиска по хэш-таблицам, так и за счёт их реализации на языке низкого уровня. Какая там фактическая метрика, проверять я не планирую.

     

    5 часов назад, prop сказал:

    > в 3-4 раза
    Опять какие-то экспериментальные данные, если разговор идет про алгоритмы, то использовать надо нормальные метрики.

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

     

    5 часов назад, prop сказал:

    > При онлайне 20 игроков для оценки изменений в списке потребуется 800 сравнений строк
    Данные получены экспериментальным способом?

    Нет. Это чисто умозрительная оценка. В эксперименте будет меньшее количество. Скорее всего, в 2 раза, т.к. автор кода останавливает поиск после обнаружения нужного значения. Судя по коду от @Anon, среднее количество составит 20*20/2*2. То есть, 400 сравнений, а не 800. Это я лишку хватил.

     

    5 часов назад, prop сказал:

    Ниче не понял. В особенности как это относится к тому, что я сказал.

    Это я тебя не понял, поэтому возникла путаница. Согласен, копирование таблицы в алгоритме @Anon излишне.

     

    5 часов назад, prop сказал:

    Какой-то потанцевал точно есть потому что ты два раза по списку игроков проходишься.

    Да, замечание верное. Но это мелкая оптимизация и, возможно, даже преждевременная. А танцевать, мне кажется, можно гораздо дальше. Нужен другой алгоритм.

     

    5 часов назад, prop сказал:

    > чисто алгоритмически
    > потанцевал
    Потанцевал существует только алгоритмически или аналитически тоже?

    Алгоритмически, аналитически... Вбрасывая какую-либо идею на форуме, я далеко не всегда погружаюсь в глубокий анализ. Например, когда я делал замечания по коду товарища @Anon, я не имел какого-либо кода. В мыслях у меня был не алгоритм и не код, а нечто смутное вроде: этот процесс заменяем другим и получаем ускорение. И анализа в его привычном смысле также не было. Было стойкое чувство, основанное на опыте использования ассоциативных массивов в Lua.

     

    Говоря же про имеющийся потенциал, я не то что не мог провести анализ, я даже алгоритм не сформулировал. У меня была лишь смутная картинка в виде пляшущих строк из двух таблиц, пытающихся совместиться друг с другом. И видеть эту картинку я мог, лишь находясь в состоянии полусна, когда аналитическое мышление притупляется, но память ещё позволяет что-то запомнить. За сутки эта смутная картинка превратилась в более-менее оформленный набор тезисов. Если ты готов к спокойному восприятию этой ещё не до конца сформулированной идеи, слушай:

     

    В большинстве случаев сравниваемые списки будут полностью идентичны друг другу. И для подтверждения этого факта в случае среднего онлайна 20 игроков будет достаточно выполнить лишь 20 сравнений строк. Правда, при наличии сортировки в таблицах. Скорее всего, ещё быстрее будет работать проверка количества игроков и тупое сравнение результатов table.concat. Но даже если таблицы отличаются, то в большинстве случаев не сильно. При обнаружении отличия надо лишь определить, строки какой из двух таблиц следует сдвинуть, и на сколько. А после вычисления размера сдвига можно продолжить линейное сравнение. Задача чем-то похожа на вывод различий строк двух текстовых файлов. Она, наверное, даже проще, т.к. в текстовые файлы могут быть добавлены огромные блоки строк, а списки игроков не успевают меняться настолько интенсивно.

     

    Что нам может помочь? Для начала надо проверить, не отсортированы ли уже списки игроков, возвращаемые отладочной платой. Даже если сортировка отсутствует, можно воспользоваться встроенной сортировкой Lua. Предполагаю, что она будет выполняться заметно быстрее, чем используемое мной формирование ассоциативного массива в цикле. А он в новом алгоритме не потребуется. Уже хороший размен.


  7. В 24.12.2022 в 17:40, Anon сказал:

    Что ж, замечания у тебя делать получается, а вот твоего варианта программы всё нет. С нетерпением жду эффективный вариант, который, уверен, пригодится ОП, а эффективный метод сравнения таблиц я возьму себе на заметку

    Вот более эффективный вариант сравнения таблиц игроков. При среднем онлайне 20 игроков такой способ сравнения выполняется в 3-4 раза быстрее твоего решения в лоб.

    ---------- конвертация предыдущего списка
    lastPlayers = {}
    for i=1, #players do
      lastPlayers[players[i]] = true
    end
    ---------- получение текущего списка
    players = getPlayers()
    difference = { removed={}, added={} }
    ---------- поиск игроков, зашедших на сервер
    for i, player in ipairs(players) do
      if lastPlayers[player] then
        lastPlayers[player] = nil
      else
        table.insert( difference.added, player )
      end
    end
    ---------- поиск игроков, покинувших сервер
    for player in pairs(lastPlayers) do
      table.insert( difference.removed, player )
    end

    Это, скорее всего, не предел. Чисто алгоритмически потенциал для дальнейшего ускорения имеется, но удастся ли реализовать его именно на языке Lua, на вскидку я сказать не могу.


  8. 9 минут назад, prop сказал:

    Копировать не надо, getPlayers() всегда возвращает новую таблицу

    Вызов component.debug.getPlayers выполняется за один такт времени. И за это время список пользователей может измениться. То есть, действуя таким образом, мы можем терять события.


  9. 7 минут назад, _bongo_ сказал:

    local rad = radar.getPlayers()

    Теперь стало понятнее.

     

    Для поиска ошибки надо задаться вопросом, что делает каждая из операций.

    • #rad >= 2 проверяет количество игроков в зоне действия радара.
    • Но что делает rad.distance <= 7? Ведь поле .distance не существует в таблице rad. Если ты хочешь проверить удалённость игрока от радара, то это надо делать для каждого из игроков. То есть, надо перебрать игроков в таблице (возможно, всех), проверить удалённость каждого из них и посчитать их количество, набрав хотя бы двух. Готовый код может выглядеть, например, таким образом:
    -- получаем список игроков в зоне действия радара
    local players = radar.getPlayers()
    -- вычисляем количество игроков в комнате
    local playersInRange = 0
    -- имеет смысл считать, если найдено не менее двух игроков
    if #players >= 2 then
      -- перебираем всех найденных игроков
      for _,player in ipairs(players) do
        -- считаем только игроков в комнате
        if player.distance <= 7 then
          playersInRange = playersInRange + 1
          -- останавливаем пребор, если значение счётчика достаточно для срабатывания условия
          if playersInRange >= 2 then
            break
          end
        end
      end
    end
    
    -- принимаем окончательное решение и выводим его на экран
    if playersInRange >= 2 then
      ...
    else
      ...
    end

    Работоспособность кода я не проверял, т.к. основной моей целью было показать именно алгоритм.

    • Нравится 2

  10. 2 минуты назад, Anon сказал:

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

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

     

    14 минуты назад, Anon сказал:

    если бы среди задач программы была производительность

    Автор вопроса вообще не ставил никаких задач, он просто спросил, возможно ли это сделать. Я ответил, что теоретических ограничений нет. Ты продемонстрировал, что это возможно практически. Тут всё чётко.

     

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

     

    31 минуту назад, Anon сказал:

    Что ж, замечания у тебя делать получается, а вот твоего варианта программы всё нет. С нетерпением жду эффективный вариант, который, уверен, пригодится ОП, а эффективный метод сравнения таблиц я возьму себе на заметку

    Программы нет потому, что писать её я и не собирался. А для тех, кто вдруг соберётся, я и дал свои замечания. Я допускаю, что недостаточно чётко сформулировал свои мысли. Скажи, что именно тебе не ясно. Как избавиться от двух проходов при сравнении списков, или как уменьшить количество сравнений за счёт использования ассоциативных свойств таблиц? Что из этого нуждается в иллюстрации кодом?


  11. В 23.12.2022 в 03:45, Anon сказал:

    эта программа подойдёт

    В первом приближении, конечно, подойдёт. Но, судя по коду, это лагодром:

    • В лог пишется время с точностью до секунды, хотя программа зачем-то уточняет список игроков 20 раз в секунду.
    • Время сервера зачем-то запрашивается при каждом вызове функции log, хотя она при очередном обновлении списка может вызываться более одного раза.
    • Сравнение списков реализовано крайне неэффективно. При онлайне 20 игроков для оценки изменений в списке потребуется 800 сравнений строк, хотя достаточно было бы лишь 20 раз запросить поле таблицы. Во-первых, два прохода списков не требуются, всё можно сделать за один проход. Во-вторых, ассоциативные свойства таблиц позволяют отказаться от перебора одной из таблиц в длинном цикле, тем самым ускорив поиск нужного значения.

     


  12. 1 час назад, _bongo_ сказал:

    не думаю что тех админ сервера ради меня что-то пойдёт делать

    Зависит от того, как это преподнести. Если это какой-то коммерческий проект, то админ заинтересован в повышении онлайна. Если благодаря новой настройке ты и другие игроки начнёте строить какие-то полезные механизмы, которые сделают игровой мир более интересным, то админ будет рад пойти игрокам на встречу.

     

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

     

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

    • Нравится 1

  13. 3 часа назад, _bongo_ сказал:

    Как задать радиус работы радару из computronics?

    В файле config/computronics.cfg есть такие строки:

    radar {
        # The maximum range of the Radar. [range: 0 ~ 256, default: 8]
        I:maxRange=8

    По умолчанию радиус действия радара задан равным 8 блокам, но здесь можно указать любое значение в диапазоне от 0 до 256.


  14. 1 час назад, kintser31 сказал:

    возможно ли сделать такой список:
    дата. время. игрок зашёл/вышел.
    20.12 20:10:37 n зашёл (Пример)
    Главный аспект это без учета списка чтобы всех подряд писало.

    Теоретически возможно. Практически же ответ зависит от доступных модов и разрешённых на сервере крафтов.


  15. 3 часа назад, _bongo_ сказал:

    В слотах 1-7 находятся одинаковые теплоотводы, но они под разными...( что это )

    Это разные таблицы. Посмотреть их содержимое можно, например, так:

    for k,v in pairs(tbl) do
      print(k,v)
    end

     

    3 часа назад, _bongo_ сказал:

    по возможности укажите на мои ошибки

    • if inv.getStackInInternalSlot(i) == 0x7efff97d9b210 then Этот код работать не будет. Во-первых, при каждом запуске программы адреса таблиц будут новыми. Во-вторых, сравнение таблиц по их адресам в большинстве случаев не имеет смысла, т.к. в первую очередь нас интересует содержимое таблиц, а не их адреса.
    • Желательно максимально отказаться от дублирования тяжёлых вычисления или длительных запросов. getStackInInternalSlot работает медленнно. И совершая этот запрос по два раза, мы в два раза замедляем работу программу.
    • inv.dropIntoSlot(i,7) Тут аргументы набросаны как попало. Первым аргументом должна быть указана сторона робота, с которой относительно его находится реактор. А тут зачем-то указан номер внутреннего слота робота.

    Код можно написать, например, таким образом:

    for i = 1, rob.inventorySize() do
      stack = inv.getStackInInternalSlot(i))
      if stack.name == "IC2:reactorVentDiamond" and stack.damage==1
        rob.select(i)
        inv.dropIntoSlot(3,i)
      end
    end 

    В поле stack.damage хранятся метаданные или износ предмета. Применительно к теплоотводам — их температура, поэтому часть проверки можно выбросить. Достаточно проверять их по имени.


  16. 20 часов назад, Wolframoviy сказал:

    Скриншот обсуждения в дискорде...

    Это оффтопик. Но раз ты считаешь, что он заслуживает внимания, я отвечу.

     

    Ранее от использования интернет-платы ты отказался сам:

    В 26.11.2022 в 20:47, eu_tomat сказал:

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

    Поэтому я не понимаю, чем тебя заинтересовала идея упростить взаимодействие с банком, выбросив сетевой слой и оставив лишь API банка. Продолжая эту логику, можно вообще выбросить слой компов. Пусть игроки работают с банком консольными командами. На крайний случай сбегают на спавн и воспользуются стоящим там компом. Но зачем нам это? Подобные системы и так успешно функционируют. И к заявленной теме отношения они не имеют.

     

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


  17. 3 минуты назад, _bongo_ сказал:

    Может и с помощью robot.select это можно как-то сделать
    но я без понятия как

    Вот оно что, значит! С этого и надо было начинать, а не повторять в каждом сообщении, что надо как-то обойтись без robot.select. Зачем морочить голову себе и другим?

     

    Тогда задача упрощается: с помощью контроллера инвентаря запрашиваем информацию о предметах в каждом из слотов робота. Анализируем информацию. Если обнаружили нужный компонент реактора, то выбираем нужный слот робота, и с помощью контроллера инвентаря переносим предмет в нужный слот реактора. Для этого потребуется:

    • inventory_controller.getStackInInternalSlot(slot:number) для получения информации о предмете.
    • robot.select(slot:number) для выбора этого слота
    • inventory_controller.dropIntoSlot(side:number, slot:number[, count:number]) для перемещения предмета из текущего слота в нужный слот реактора.
    • Нравится 1

  18. @_bongo_ Ты специально что ли не отвечаешь на мой вопрос?

     

    Я задал его три раза:

    2 часа назад, eu_tomat сказал:

    Кстати, а какова причина отказа от robot.select? Существует какая-то практическая цель такого ограничения, или это чисто теоретический интерес?

    25 минут назад, eu_tomat сказал:

    И почему именно без robot.select? Какова цель всего этого?

    14 минуты назад, eu_tomat сказал:

    Но почему без испольозвания robot.select?

    Но ты отвечаешь мне что угодно: какую-то общеизвестную информацию про метаданые, про рандомные компоненты реактора.

     

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

    Что плохого случится при использовании robot.select?


  19. 3 минуты назад, _bongo_ сказал:

    Мне нужно чтобы робот выбрал нужный мне предмет без robot.select, а по id предмета и метаданным

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

     

    И почему именно без robot.select? Какова цель всего этого?

     

    11 минуту назад, _bongo_ сказал:

    у меня всё плохо с объяснениями

    Постарайся сделать хорошо. Иначе с ответами тоже будет плохо.

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