Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - Vint

Pages: 1 [2] 3 4
16
Ошибки / Сломались спойлеры
« on: April 23, 2018, 06:05:40 PM »
На сайте. Кнопка пропала. Видать вместе с капчей.

17
http://crapware.aidf.org/

Для тех кто не понимает, что нужно в адресной строке стереть forum/... чтобы попасть на основу сайта.
Там расположено описание, ссылка на скачивание, данные для пожертвований и ссылки на группу ВКонтакте и Twitter.

http://crapware.aidf.org/

18
В жизни каждого школьника наступает момент, когда он узнаёт о "суперсекретном", малоизвестном (Стратегия Мартингейла) и "новом" (середина XVIII века) алгоритме для игры в рулетку. Ну тот, где при проигрыше нужно повышать ставку в 2 раза.
Внимательно вчитавшись и подумав 10 минут, становится ясным как божий день что алгоритм прекрасен и непобедим. Рождаются грандиозные планы обогащения. Всё это застилает глаза и мешает подумать дальше. О том что всё это известно давно и с этим удачно борются там где нужно. Ну как борются... им выгодно чтобы прИбывали  новые жертвы просветлённые.

А, о чём это я?... А, так вот. Нужно быстро заказать автоматизацию всего этого дела и самому ехать уже на Мальдивы в конце концов.
И ни в коем случае не раскрывать "секретный" алгоритм. Рекомендуется употреблять фразы "определенный алгоритм" или "заданный мной алгоритм" и т.п.
Для безопасности и нераскрытия агента, страницу ВК создать новую желательно анонимизировать, удалив все фото и информацию о себе.
Забыв удалить из друзей родственников и близких знакомых и сообщения от них на стене. Никто же не перейдёт к ним на страницу и не увидит фото с вами... Ай, всё это не важно.

P.S. Алгоритм может быть не этот. Есть ещё кучка таких же по ценности. Иногда они объединены в наборы "16 стратегий позволяющих выигрывать в рулетку", "22 стратегии позволяющих выигрывать в рулетку" и т.д.

P.S.S. Да не иссякнет поток рулеточников во веки веков. Аминь.

19
Оно как бы правильное, если просто считать, но в условии считает неправильно

Code: (clickermann) [Select]
IF((11.2 - 11) = 0.2)
    LOGWRITE("равно")
ELSE
    LOGWRITE("НЕ равно")
END_IF
HALT

Code: [Select]
15:07:33 НЕ равно
После 100500 проверок удалось выяснить, что так происходит, если в результате вычисления получается меньше -1 < x < 1
Так происходит в версиях 4.10, 4.11, 4.12, 4.13
4.9 и ниже - такой проблемы нет.

20
Прочее / Наши желания
« on: March 12, 2017, 10:07:40 PM »
'Компьютер делает не то что вы хотите чтобы он делал, а что вы ему сказали делать' ©

21
Простое тестовое задание 1

Предлагаю простое тестовое задание для новичков. В процессе его выполнения можно подучиться писать скрипты на Clickermann и повысить свой скилл.
Задание НЕ игровое. НЕ на поиск изображений или работе с экраном. Просто вычисления, циклы, работа со строками и вводом информации.

Алгоритм Луна — алгоритм вычисления контрольной цифры номера пластиковой карты в соответствии со стандартом ISO/IEC 7812
[spoiler]Не является криптографическим средством, а предназначен в первую очередь для выявления ошибок, вызванных непреднамеренным искажением данных (например, при ручном вводе номера карты, при приёме данных о номере социального страхования по телефону). Позволяет лишь с некоторой степенью достоверности судить об отсутствии ошибок в блоке цифр, но не даёт возможности нахождения и исправления обнаруженной неточности.

Наиболее распространённые применения для подсчёта контрольной цифры:
•   Номера всех банковских карт
•   Номера некоторых дисконтных карт
•   Коды социального страхования
•   IMEI-коды.
•   Расчёт контрольного знака единого 8-значного номера железнодорожного вагона на РЖД.
•   Расчёт ICCID (от англ. Integrated Circuit Card Id) — уникальный серийный номер SIM-карты.[/spoiler]
Оригинальный алгоритм, описанный разработчиком
[spoiler]1. Цифры проверяемой последовательности нумеруются справа налево.
2. Цифры, оказавшиеся на нечётных местах, остаются без изменений.
3. Цифры, стоящие на чётных местах, умножаются на 2.
4. Если в результате такого умножения возникает число больше 9, оно заменяется суммой цифр получившегося произведения — однозначным числом, то есть цифрой.
5. Все полученные в результате преобразования цифры складываются. Если сумма кратна 10, то исходные данные верны.
В примере: последняя цифра — контрольная. Для того, чтобы номер был верен в соответствии с алгоритмом Луна, контрольная цифра должна быть равна 7.
4  5  6  1     2  6  1  2     1  2  3  4     5  4  6  7
8     12       4     2        2     6        10    12
8     3        4     2        2     6        1     3

8+5+3+1 + 4+6+2+2 + 2+2+6+4 + 1+4+3+7 = 60
Сумма кратна 10 – значит номер верный.[/spoiler]


Ссылка на описание в википедии. Там же и описан алгоритм. Алгоритм очень простой.

Нужно сделать два скрипта. Или один общий.

1.   Скрипт проверки верности существующей контрольной цифры. Т.е. вводим номер с контрольной цифрой на конце. Результат должен быть в сообщении есть в номере ошибки или нет.
2.   Скрипт вычисления контрольной цифры и вывод номера уже с контрольной цифрой.

Скрипты должны быть не наброском «примерно так», а в уже законченном рабочем виде, чтобы ими можно было пользоваться. Вариант реализации – произвольный. Можно использовать массивы, можно не использовать. Для красоты и визуальной разбивки кода можно использовать деление на подпрограммы.
Понятно, что совсем новичкам достаточно будет сделать базовые функции. Массивы, подпрограммы, и остальное, можно оставить на будущее – на «вырост».


Какие команды Clickermann-а вероятно могут понадобиться (из справки):
[spoiler]Основные конструкции:
IF (expression) ... END_IF - проверяет истинность выражения и выполняет блоки инструкций в зависимости от результата
FOR ($var, expression, [step]) ... END_CYC - организует цикл с параметром
WHILE (expression) ... END_CYC - организует цикл с предусловием
SUB (sub_name, [$par1, ...]) ... END_SUB - описывает подпрограмму
WAITMS (delay) - приостанавливает выполнение сценария на несколько миллисекунд
HALT([close]) - полностью останавливает выполнение сценария

Работа с числами:
INT (num) - числовая функция; возвращает целую часть числа без округления. Так же используется для перевода строки в целое число
INC ($var, [value]) - увеличивает значение переменной

Диалоговые окна ввода/вывода:
INPUTBOX("message", "default", [delay]) - строковая функция; выводит диалоговое окно для ввода строки
DIALOGBOX("message", buttons, icon) - числовая функция; выводит диалоговое окно с текстом и кнопками
RADIOBOX("message", radio1, ...) - числовая функция; выводит диалоговое окно с переключателями

Функции работы со строками:
STRLEN ("str") - числовая функция; возвращает длину строки в символах
STRFILTER ("str", "set", mode) - строковая функция; возвращает отфильтрованную строку
STRCUT ("str", begin, size) - строковая функция; возвращает кусок строки
STRCONCAT ("str1", "str2", ...) - строковая функция; возвращает объединенную строку

Для отладки кода использовать вывод в лог и трей:
LOGSHOW (show, [x, y]) - скрывает/отображает окно лога программы
HINTPOPUP ("message", ["title"]) - выводит всплывающее сообщение в системный трей [/spoiler]
Полное описание команд и функций с примерами  можно посмотреть в справке.


Для примера берём номер из вики

Code: [Select]
4561 2612 1234 5467  - проверить, нет ли в номере ошибок
4561 2612 1234 546   - найти контрольную цифру, в данном случае «7»

Во вложении мой пример реализации Luhn_algorithm.cms. Код пока скрыт, но полностью рабочий.
Для Clickermann версии 4.12 build 001

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

Делайте свои варианты и выкладывайте. Можете и не выкладывать  :D.



22
Сейчас реализованы три варианта. И из них рабочих только два, а по факту один.

1. Через ini.
    +: работает в обе стороны.
    -:  нужно задавать флаг готовности ответа (если разовый ответ) и постоянно читать ini дожидаясь результата. Что напрягает диск. К тому же не
        нулевая вероятность напороться на блокировку файла во время записи другой прогой, а обрабатывать эту ситуацию кликер не умеет, просто
        вываливаемся с ошибкой. Поэтому часто читать нельзя, получаем тормознутую систему. Чем чаще читаем/проверяем тем больше вероятность
        поймать фигу.

2. передать параметром при вызове по EXECUTE.
    +: "туда" всё нормально.
    -:  "обратно" в пролёте. Возвращаемся к первому варианту.

3. написать свой плагин в dll и передавать штатно через CALL
    +: наверно классно!  :D ;D
        Кликер ждет момента как отработки плагина и только потом продолжает работу.
        Возврат в переменную - это хорошо.
    -:  нужно уметь. Хрен знает на чём писать чтоб не учить С++ ради... ради чего?. Да ну его  :)
        Передаёт только целочисленные параметры. Ни float ни str... Хоть разбивай в CHAR и там собирай.
        Фиксированный тип и имя функции "execute". Т.е. вызвать из готового чужого набора уже не выйдет, печалька :'(


И что имеем в ЛизуРтате? Туда-сюда, только ini.
Раньше, вроде, писал предложение сделать обмен, но способов не видел. В голову лезли только всякие варианты с стандартным потоком вывода STDOUT. Может это вариант?

Сегодня в очередной раз глядя на утилиту AGClient очередной раз "прозрел". Можно же "туда" передавать через PostMessage. Главное, чтоб "там" ждали. Вот только опять не хватает обратки.

Предложение:
Сделать возможность приёма Кликермэном инфы, переданной по WinAPI типа PostMessage. Как ждёт и обрабатывает AGClient.
типа PostMessage($hwnd, 0x666, wParam, lParam)
Если нагрузка лишняя, то сделать команды "слушать/не слушать" и включать по надобности.
Как пришло сообщение окну, допустим 0x666 пишем wParam, lParam в переменные $_return1/2, а лучше в $_return3/4 или $_in1, $_in2

Минусы: опять только целые числа, но можно сообщением передавать только сигналы. Типа "данные обработаны, можно забирать-читать из файла".


Ну или сделать расширенный вариант - группу команд.
К примеру при получении  0x777, в wParam приходит количество последующих передаваемых кодов CHR которые нужно собрать в строку.
Допустим, получили
PostMessage($hwnd, 0x777, 5, 0) кликер ждёт следующие 5 запросов  и собирает из них строку. lParam = 0, значит передано общее количество.

PostMessage($hwnd, 0x777, 1, 65)   # A
PostMessage($hwnd, 0x777, 2, 66)   # B
PostMessage($hwnd, 0x777, 3, 67)   # C
PostMessage($hwnd, 0x777, 4, 67)   # D
PostMessage($hwnd, 0x777, 5, 67)   # E
После получения последнего выдаём в $_in1 = "ABCDE".  Можно ещё в $_in2 оповестить флагом 1, что получено и можно читать.

Понятно, что вся работа по 0x777 со стороны кликермэна не видна, просто получаем в итоге строку.

Возможно есть вариант попроще и я нагородил здесь хрень. Может можно напрямую передавать назад в кликер инфу, как в варианте с плагинами.

23
Ошибки / Неправильное вычисление
« on: December 08, 2016, 04:16:13 PM »
Ну собственно вот. Без скобок считает неправильно.
Code: (clickermann) [Select]
LOGWRITE(10 - 2*2 - 3)
LOGWRITE(10 - (2*2) - 3)
LOGWRITE(10 - (2*2 + 3))

Лог
Code: [Select]
16:15:23 9
16:15:23 3
16:15:23 3

Для полноты понимания
Code: (clickermann) [Select]
LOGWRITE(100 - 20*1 - 30*1 - 50)или
Code: (clickermann) [Select]
LOGWRITE(100 - 20 - 30*1 - 50)вместо нуля получаем 60 и 100
При чём умножение последнего операнда и первого не влияет, только в середине

24
Нужно куда нибудь прикрутить GetKeyState из win API для получения состояний таких клавиш, как NumLock, CapsLock и всякие ScrollLock
Ну или запилить спец команды для получения состояния хотя бы первых двух.
Типа GETNUMLOCK, GETCAPSLOCK

25
Ошибка во всех функциях поиска.

Ну собственно вот человек наткнулся
http://crapware.aidf.org/forum/index.php?topic=2580.msg16242#msg16242

Уж сколько её тестили и вдоль, блин и поперёк... Как так? ХЗ.

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

Пример:
Увеличенный образец (попиксельно), зелёным помечены не учитываемые пикселы.


Что проверял.
Пересохранял форматы. Создавал новые. Версии от 4.7 до 4.12. SCANPICTURE и IF_PIXEL_IN. GETSCREEN с параметрами и без.

Поковыряйте ещё, может где напортачил.

Я же так много тестировал, когда был баг с уменьшенным полем GETSCREEN(...) с параметрами. Но резал полосками в 1 пиксел. А этот одиночный нижниий угловой всё портил.

26
Зависание при попытке чтения из файла строки
(ABS)
В версии 4.12b тоже виснет.

Code: (clickermann) [Select]
$Slovo = TFREAD("текст.txt", 3)
print ($Slovo)
$L = strlen($Slovo)
print($L)
HALT

хотя если задано напрямую в переменную, то всё нормально
Code: (clickermann) [Select]
$Slovo = "5-/-Акрилонитрилбутадиенстирол (ABS)"
print($Slovo)
$L = strlen($Slovo)
print($L)
HALT
если в (ABS) убрать хоть одну скобку или букву, то всё нормально.

27
Предлагаю вернуть если была или добавить функцию
IF_NOT_PIXEL_IN (x, y, x2, y2, color1, ...) - производит поиск пикселя НЕ СОВПАДАЮЩЕГО с заданными цветами в прямоугольной области буфера анализа.

Параметры
x, y - числовые координаты левого верхнего угла области поиска
x2, y2 - числовые координаты правого нижнего угла области поиска
color1, ... - цвета, игнорируемые фунуцией (цвета фона).

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

28
Прочее / О логике
« on: October 02, 2015, 12:22:44 PM »
Парадокс парикмахера.
Предположим, что существует город с одним мужским парикмахером, и что каждый мужчина в городе бреется налысо: некоторые самостоятельно, некоторые с помощью парикмахера. Кажется разумным предположить, что процесс подчиняется следующему правилу: парикмахер бреет всех мужчин и только тех, кто не бреется сам.
Согласно этому сценарию, мы можем задать следующий вопрос: парикмахер бреет себя сам? Однако, спрашивая это, мы понимаем, что ответить на него правильно невозможно:
— если парикмахер не бреется сам, он должен соблюдать правила и брить себя сам;
— если он бреет себя сам, то по тем же правилам он не должен брить себя сам.

29
Очередная интересная задача до которой дошли руки.

Решил реализовать известный алгоритм поиска пути A*. Принципы и описание брал здесь.

Упоминание началось в темах:
http://crapware.aidf.org/forum/index.php?topic=1837.0
http://crapware.aidf.org/forum/index.php?topic=1878.0

Хотелось посмотреть как со скоростью на Clickermann, реально ли на нём использовать, ну и заодно неплохая тренировка создания кода. Ограничился как в примере полем разбитым на квадраты. Произвольные графы пока не делал, с этим стоит заморачиваться, если нужно, только под конкретную задачу когда такая появится.

Определился со способом хранения карты, а так же рабочей инфы: открытого и закрытого списков, стоимости F (G и H решил расчитывать по надобности на лету).
Для удобства создания сделал себе шаблончик как в источнике

Код под спойлером и во вложении
[spoiler]
Code: (clickermann) [Select]
#name "Алгоритм A*"
// Author: Vint
// Version: 0.0.4 (08.05.2015)
// Скрипт для Clickermann v4.11 003
#logfile

//===== ОПЦИИ ==========================//
//////////////////////////////////////////

// вывод лога
$log0 = 1
// вывод отладочного лога
$log = 0
// вывод отладочного лога 2 уровня
$log2 = 0

// имя файла карты
$map_name = "map.txt"

// Обходить углы 0 - нет, 1 - да
$bypass_angle = 1

// Старт (маркер)
$start = 4
// Финиш (маркер)
$ending = 5

//////////////////////////////////////////

//==============================================================================
//===  Расчёт H для клетки  ====================================================
SUB(calc_H, $th_X, $th_Y)
   $H = (ABS($endY - $th_Y) + ABS($endX - $th_X)) * 10
END_SUB

//==============================================================================
//===  Добавляем в открытый список  ============================================
SUB(add_open, $tt_X, $tt_Y, $tt_P, $tt_G)
   IF(($tt_X = $endX) & ($tt_Y = $endY))
      $check_end = 1
   END_IF
   calc_H($tt_X, $tt_Y)
   ARRPUSH($open, $tt_X)
   ARRPUSH($open, $tt_Y)
   ARRPUSH($open, $tt_P)
   ARRPUSH($open, $tt_G + $H)
   IF($log = 1)
      LOGWRITE ("Add open:  ", $tt_X, ":", $tt_Y, ":", $tt_P, ":", $tt_G + $H, "    G:", $tt_G, " $H:", $H)
   END_IF
END_SUB

//==============================================================================
//===  Добавляем в закрытый список  ============================================
SUB(add_close, $tt_X, $tt_Y, $tt_P)
   ARRPUSH($close, STRCONCAT($tt_X, ":", $tt_Y, "P", $tt_P))
   IF($log = 1)
      LOGWRITE ("Add close:  ", $tt_X, ":", $tt_Y, "P", $tt_P)
   END_IF
END_SUB

//==============================================================================
//===  Удаляем из открытого списока  ===========================================
SUB(del_open, $best)
   IF($log=1)
      LOGWRITE ("del open ", $best, "   ", $open[$best-3], ":", $open[$best-2], ":", $open[$best-1], ":", $open[$best])
   END_IF
   
   $size_open = ARRSIZE($open)
   IF($size_open > 4)
      FOR($i=$best-3, $i < ($size_open - 4))
         $open[$i] = $open[$i+4]
      END_CYC
   END_IF
   
   $nul = ARRPOP($open)
   $nul = ARRPOP($open)
   $nul = ARRPOP($open)
   $nul = ARRPOP($open)
END_SUB

//==============================================================================
//===  Проверка на вхождение в $close  =========================================
SUB(check_closed, $tc_X, $tc_Y)
   $closed_on = 0
   $sample = STRCONCAT($tc_X, ":", $tc_Y)
   $size_close = ARRSIZE($close)
   FOR($i=0, $i < $size_close)
      $cut_close = STRCUT2($close[$i], 1, STRPOS($close[$i], "P") - 1)
      //LOGWRITE ("close[$i] ", $close[$i], " cut_close ", $cut_close, "  sample ", $sample)
      IF($cut_close = $sample)
         $closed_on = 1
         $P_res = STRCUT2($close[$i], STRPOS($close[$i], "P") + 1, 30)
         $i = $size_close + 1
         IF($log = 1)
            LOGWRITE ($tc_X, "/", $tc_Y, "   входит в $close")
         END_IF
      END_IF
   END_CYC
END_SUB

//==============================================================================
//===  Проверка на вхождение в $open  ==========================================
SUB(check_open, $to_X, $to_Y)
   IF($log = 1)
      LOGWRITE ("проверяем  ",  $to_X, "/", $to_Y)
   END_IF
   
   IF(($to_X > -1) & ($to_Y > -1) & ($to_X < ($width)) & ($to_Y < ($height)))
      $no_filed = 0
      check_closed($to_X, $to_Y)
      IF($closed_on = 0)
         $opened_on = 0
         $size_open = ARRSIZE($open)
         FOR($i=0, $i < $size_open, 4)
            IF(($open[$i] = $to_X) & ($open[$i+1] = $to_Y))
               $opened_on = 1
               $ind_open = $i
               calc_H($to_X, $to_Y)
               $H_old = $H
               $G_old = $open[$i+3] - $H_old
               
               $P_res = $open[$i+2]
               $i = $size_open + 1
               IF($log = 1)
                  LOGWRITE ($to_X, "/", $to_Y, "   входит в $open")
               END_IF
            END_IF
         END_CYC
      END_IF
   ELSE
      $no_filed = 1
      IF($log = 1)
         LOGWRITE ($to_X, "/", $to_Y, "   за пределами поля")
      END_IF
   END_IF
END_SUB

//==============================================================================
//===  Чтение состояния клетки  ================================================
SUB(read, $tt_X, $tt_Y)
   //check_closed($tt_X, $tt_Y)
   IF(($closed_on = 1) | ($tt_X < 0) | ($tt_Y < 0) | ($tt_X = $width) | ($tt_Y = $height))
      $state = 1
   ELSE
      $state = INT(STRCUT($map[$tt_Y], $tt_X + 1, 1))
      //IF($state = $ending)
      //   $check_end = 1
      //END_IF
   END_IF
   
   IF($log2 = 1)
      LOGWRITE ("$state=", $state, "   ",$tt_X, "/", $tt_Y)
   END_IF
END_SUB

//==============================================================================
//===  Если уже входит в $open  ================================================
SUB(already_open, $ta_P, $ta_G)
   IF($ta_G < $G_old)
      $open[$ind_open+2] = $ta_P
      $ta_X = $open[$ind_open]
      $ta_Y = $open[$ind_open+1]
      calc_H($ta_X, $ta_Y)
      $open[$ind_open+3] = $ta_G + $H
     
      IF($log = 1)
         LOGWRITE ("Update open:  ", $ta_X, ":", $ta_Y, ":", $ta_P, ":", $ta_G + $H)
      END_IF
   ELSE
      IF($log = 1)
         LOGWRITE ("не обновляем в $open")
      END_IF
   END_IF
END_SUB

//==============================================================================
//===  Вывод в лог $open  ======================================================
SUB(log_open)
   IF($log = 1)
      $size_open = ARRSIZE($open)
      LOGWRITE ("$open:")
      FOR($i=0, $i < $size_open, 4)
         LOGWRITE ($open[$i], ":", $open[$i+1], ":", $open[$i+2], ":", $open[$i+3])
      END_CYC
   END_IF
END_SUB

//==============================================================================
//===  Вывод результата  =======================================================
SUB(result)
   $r_X = $endX
   $r_Y = $endY
   $temp = $log
   $log = 0
   LOGWRITE ("result:")
   check_open($r_X, $r_Y)  // $closed_on = 1  $opened_on = 1
   
   WHILE($P_res > 0)
      SWITCH($P_res)
      CASE(1)
         $direction = "вверх"
         INC($r_Y)
      CASE(2)
         $direction = "вверх-вправо"
         INC($r_Y)
         INC($r_X, -1)
      CASE(3)
         $direction = "вправо"
         INC($r_X, -1)
      CASE(4)
         $direction = "вних-вправо"
         INC($r_Y, -1)
         INC($r_X, -1)
      CASE(5)
         $direction = "вниз"
         INC($r_Y, -1)
      CASE(6)
         $direction = "вниз-влево"
         INC($r_Y, -1)
         INC($r_X)
      CASE(7)
         $direction = "влево"
         INC($r_X)
      CASE(8)
         $direction = "вверх-влево"
         INC($r_Y)
         INC($r_X)
      END_SWITCH
     
      ARRPUSH($preresult, $r_X)
      ARRPUSH($preresult, $r_Y)
      ARRPUSH($preresult, $P_res)
      ARRPUSH($preresult, $direction)
      ARRPUSH($preresult, STRCONCAT($r_X, "/", $r_Y, "  ", $P_res, " - ",$direction))
      check_open($r_X, $r_Y)
   END_CYC
   $log = $temp
   UNDEFINE($result)
   
   // переворачиваем ответ, делаем от старт к финиш
   WHILE(ARRSIZE($preresult) > 0)
      $text = ARRPOP($preresult)
      $direction = ARRPOP($preresult)
      $P_res = ARRPOP($preresult)
      $r_Y = ARRPOP($preresult)
      $r_X = ARRPOP($preresult)
     
      ARRPUSH($result, $r_X)
      ARRPUSH($result, $r_Y)
      ARRPUSH($result, $P_res)
      ARRPUSH($result, $direction)
      ARRPUSH($result, $text)
   END_CYC
   
   // вывод ответа в лог
   IF(ARRSIZE($result) > 0)
      $asize = ARRSIZE($result)
      FOR($i=4, $i < $asize, 5)
         LOGWRITE ($result[$i])   
      END_CYC
   END_IF
END_SUB

//==============================================================================
//===  Добавление соседей в открытый  ==========================================
SUB(vicinage, $t_X, $t_Y, $t_Fprev)
   calc_H($t_X, $t_Y)
   $H_cur = $H
   $G_cur = $t_Fprev - $H_cur
   
   // вверх, 1
   check_open($t_X, $t_Y-1)
   IF($no_filed = 0)
      IF(($opened_on = 0) & ($closed_on = 0))
         read($t_X, $t_Y-1)
         IF($state ! 1)
            add_open($t_X, $t_Y-1, 1, $G_cur + 10)
         END_IF
      ELSE
         IF($closed_on ! 1)
            already_open(1, $G_cur + 10)
         END_IF
      END_IF
   END_IF
   
   // вверх-вправо, 2
   IF($check_end = 0)
      check_open($t_X+1, $t_Y-1)
      IF($no_filed = 0)
         IF(($opened_on = 0) & ($closed_on = 0))
            read($t_X+1, $t_Y-1)
            IF($state ! 1)
               read($t_X, $t_Y-1)
               $state1 = $state
               read($t_X+1, $t_Y)
               IF(($state = 1) & ($state1 = 1))
               ELSE
                  IF(($bypass_angle = 1) & (($state = 1) | ($state1 = 1)))
                  ELSE
                     add_open($t_X+1, $t_Y-1, 2, $G_cur + 14)
                  END_IF
               END_IF
            END_IF
         ELSE
            IF($closed_on ! 1)
               already_open(2, $G_cur + 14)
            END_IF
         END_IF
      END_IF
   END_IF
   
   // вправо, 3
   IF($check_end = 0)
      check_open($t_X+1, $t_Y)
      IF($no_filed = 0)
         IF(($opened_on = 0) & ($closed_on = 0))
            read($t_X+1, $t_Y)
            IF($state ! 1)
               add_open($t_X+1, $t_Y, 3, $G_cur + 10)
            END_IF
         ELSE
            IF($closed_on ! 1)
               already_open(3, $G_cur + 10)
            END_IF
         END_IF
      END_IF
   END_IF
   
   // вниз-вправо, 4
   IF($check_end = 0)
      check_open($t_X+1, $t_Y+1)
      IF($no_filed = 0)
         IF(($opened_on = 0) & ($closed_on = 0))
            read($t_X+1, $t_Y+1)
            IF($state ! 1)
               read($t_X+1, $t_Y)
               $state1 = $state
               read($t_X, $t_Y+1)
               IF(($state = 1) & ($state1 = 1))
               ELSE
                  IF(($bypass_angle = 1) & (($state = 1) | ($state1 = 1)))
                  ELSE
                     add_open($t_X+1, $t_Y+1, 4, $G_cur + 14)
                  END_IF
               END_IF
            END_IF
         ELSE
            IF($closed_on ! 1)
               already_open(4, $G_cur + 14)
            END_IF
         END_IF
      END_IF
   END_IF
   
   // вниз, 5
   IF($check_end = 0)
      check_open($t_X, $t_Y+1)
      IF($no_filed = 0)
         IF(($opened_on = 0) & ($closed_on = 0))
            read($t_X, $t_Y+1)
            IF($state ! 1)
               add_open($t_X, $t_Y+1, 5, $G_cur + 10)
            END_IF
         ELSE
            IF($closed_on ! 1)
               already_open(5, $G_cur + 10)
            END_IF
         END_IF
      END_IF
   END_IF
   
   // вниз-влево, 6
   IF($check_end = 0)
      check_open($t_X-1, $t_Y+1)
      IF($no_filed = 0)
         IF(($opened_on = 0) & ($closed_on = 0))
            read($t_X-1, $t_Y+1)
            IF($state ! 1)
               read($t_X, $t_Y+1)
               $state1 = $state
               read($t_X-1, $t_Y)
               IF(($state = 1) & ($state1 = 1))
               ELSE
                  IF(($bypass_angle = 1) & (($state = 1) | ($state1 = 1)))
                  ELSE
                     add_open($t_X-1, $t_Y+1, 6, $G_cur + 14)
                  END_IF
               END_IF
            END_IF
         ELSE
            IF($closed_on ! 1)
               already_open(6, $G_cur + 14)
            END_IF
         END_IF
      END_IF
   END_IF
   
   // влево, 7
   IF($check_end = 0)
      check_open($t_X-1, $t_Y)
      IF($no_filed = 0)
         IF(($opened_on = 0) & ($closed_on = 0))
            read($t_X-1, $t_Y)
            IF($state ! 1)
               add_open($t_X-1, $t_Y, 7, $G_cur + 10)
            END_IF
         ELSE
            IF($closed_on ! 1)
               already_open(7, $G_cur + 10)
            END_IF
         END_IF
      END_IF
   END_IF
   
   // вверх-влево, 8
   IF($check_end = 0)
      check_open($t_X-1, $t_Y-1)
      IF($no_filed = 0)
         IF(($opened_on = 0) & ($closed_on = 0))
            read($t_X-1, $t_Y-1)
            IF($state ! 1)
               read($t_X-1, $t_Y)
               $state1 = $state
               read($t_X, $t_Y-1)
               IF(($state = 1) & ($state1 = 1))
               ELSE
                  IF(($bypass_angle = 1) & (($state = 1) | ($state1 = 1)))
                  ELSE
                     add_open($t_X-1, $t_Y-1, 8, $G_cur + 14)
                  END_IF
               END_IF
            END_IF
         ELSE
            IF($closed_on ! 1)
               already_open(8, $G_cur + 14)
            END_IF
         END_IF
      END_IF
   END_IF
END_SUB

//==============================================================================
//===  Поиск индекса в open с наилучшим F  =====================================
SUB(find_best)
   $min = 100000
   $size_open = ARRSIZE($open)
   FOR($i=$size_open-1, $i > 0, -4)
      IF($open[$i] < $min)
         $min = $open[$i]
         $best = $i
      END_IF
   END_CYC
   
   IF($log = 1)
      LOGWRITE ("best: ", $open[$best-3], "/", $open[$best-2], "  значение: ", $min, " поз. ", $best)
   END_IF
END_SUB

//==============================================================================
//===  Чтение карты  ===========================================================
SUB(read_map)
   IF($log0 = 1)
      LOGWRITE("--- читаем карту ---")
   END_IF
   TFREADARR ($map_name, $map)
   $size_arrmap = ARRSIZE($map)
   FOR($i=0, $i < ($size_arrmap - 1))
      $map[$i] = $map[$i+1]
   END_CYC
   $nul = ARRPOP($map)
   
   //   $i = 1
   //   $count_line = TFCOUNT($map_name)
   //   WHILE($i < ($count_line + 1))
   //      ARRPUSH($map, TFREAD($map_name, $i))
   //      INC($i)
   //   END_CYC
   
   // находим стартовую и конечную позиции
   $exit = 0
   $size_arrmap = ARRSIZE($map)
   IF($log0 = 1)
      //LOGWRITE ("$size_arrmap: ", $size_arrmap)
      FOR($i=0, $i < $size_arrmap)
         LOGWRITE($map[$i])
      END_CYC
   END_IF
   
   FOR($i=0, $i < $size_arrmap)
      $str = $map[$i]
      $pos_start = STRPOS($str, $start)
      IF($pos_start > 0)
         $start_X = $pos_start - 1
         $start_Y = $i
         IF($endX > -1)
            $exit = 1
         END_IF
      END_IF
      $pos_end = STRPOS($str, $ending)
      IF($pos_end > 0)
         $endX = $pos_end - 1
         $endY = $i
         IF($start_X > -1)
            $exit = 1
         END_IF
      END_IF
      IF($exit = 1)
         $i = $size_arrmap + 1
      END_IF
   END_CYC
   // ширина карты
   $width = STRLEN($map[0])
   // высота карты
   $height = ARRSIZE($map)
   
   IF($log0 = 1)
      LOGWRITE ("start: ", $start_X, "/", $start_Y)
      LOGWRITE ("end:   ", $endX, "/", $endY)
      LOGWRITE ("width/height ", $width, "/", $height)
      LOGWRITE (" ")
   END_IF
END_SUB

//==============================================================================
//===  Включение окна лога  ====================================================
SUB(initial)
   LOGCLEAR
   WAITMS(500)
   MOVE($_xmax,0)
   WAITMS(50)
   IF($log=1)
      LOGSHOW (1,$_xmax-335,28) // отображение окна лога
      WNDSIZE(WNDFIND("Clickermann - Лог"),336,560) // изменения размеров окна лога 260
   END_IF
END_SUB

//==============================================================================


initial()

// карта
$map = 0
// флаг завершения
$check_end = 0
// индекс в open клетки с лучшим F
$best = -1
// Старт
$start_X = -1
$start_Y = -1
// Финиш
$endX = -1
$endY = -1
// открытый список
//$open = 0
// закрытый список
//$close = 0

read_map()

// Добавляем стартовую в открытый список
add_open($start_X, $start_Y, 0, 0)

WHILE((ARRSIZE($open) > 3) & ($check_end = 0))
   log_open()
   find_best()
   
   // Текущая обрабатываемая
   $cur_F = $open[$best] // стоимость F текущей
   $cur_parent = $open[$best-1]   // направление на родителя
   $cur_Y = $open[$best-2] // позиция Y
   $cur_X = $open[$best-3] // позиция X
   
   del_open($best)
   add_close($cur_X, $cur_Y, $cur_parent)
   vicinage($cur_X, $cur_Y, $cur_F)
   IF($log=1)
      LOGWRITE (" ")
   END_IF
END_CYC

IF($check_end = 0)
   LOGWRITE ("Решения нет")
   HALT
END_IF

result()
LOGWRITE ("===============  финита ля комедия  ===============")
LOGWRITE (" ")
HALT
[/spoiler]

Итоги.
Опробовал на трёх небольших картах (во вложении).
Самая маленькая из разработки вычисляется меньше секунды



Следующая побольше. Здесь глубокая засада-карман из которого алгоритму долго выбираться. На рабочем компе считалось аж 9 минут  :o



И последняя, размером как вторая, но с лабиринтом. Здесь решилось за 1 мин. 20 сек. В принципе неплохо. Пришлось скрин разбить на 2, решение длинное.




Вот и всё.
Учитесь и развивайтесь.

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


30
Обнаружился один баг, или недочёт.

Вопросом, как будут работать функции поиска, если заданная область будет выходить за пределы экрана я интересовался давно. Тогда же провёл эксперименты и выяснил, что никакого негативного влияния это не оказывает на функцию IF_PICTURE_IN и ей подобные.
Это было нужно, когда мы ищем различные картинки, отталкиваясь от уже существующих. Например герой передвигается по экрану и на определённом расстоянии от него нужно искать предметы/мобов.
Ситуация довольно распространённая. И каждый раз проверять не вышла ли область за экран и не нужно ли её корректировать не очень улыбалась. К счастью это и не понадобилось, всё работало по умолчанию нормально.

Правда, это ещё было на версии, наверно, 4.5, когда не было области ни у GETSCREEN ни у COLORMODE.
Недавно столкнулся с ситуацией где долго не мог найти проблему, оказывается если область COLORMODE выходит за экран (по крайней мере в отрицательную сторону) цветокоррекция не срабатывает совсем.
Понятное дело что можно её проверить и скорректить парой доп. условий, но это такое фи.

Вот тест демонстрирующий проблему.
Code: (clickermann) [Select]
GETSCREEN
COLORMODE(7)
SCREENSHOT

GETSCREEN(-100,0, 100,250)
COLORMODE(7)
SCREENSHOT

GETSCREEN(-100,0, 100,250)
COLORMODE(7, -100,0, 100,250)
SCREENSHOT

HALT

Столкнулся и решал в таком месте
Code: (clickermann) [Select]
GETSCREEN
COLORMODE(7)
IF_PICTURE_IN (0,0,$_xmax,$_ymax, "hero.bmp", 65280, 90)
   $vX1 = $_return1 - 350
   $vY1 = $_return2 - 200 + 64
   $vX2 = $_return1 + 350
   $vY2 = $_return2 + 200 + 64
   IF($vX1 < 0)
      $vX1 = 0
   END_IF
   IF($vY1 < 0)
      $vX1 = 0
   END_IF
   IF($vX2 > $_xmax)
      $vX2 = $_xmax
   END_IF
   IF($vY2 > $_ymax)
      $vX2 = $_ymax
   END_IF
END_IF

// ну и дальше шла куча поисков типа
GETSCREEN($vX1,$vY1,$vX2,$vY2)
COLORMODE(6,$vX1,$vY1,$vX2,$vY2)
SCANPICTURE($arr, $vX1,$vY1,$vX2,$vY2, STRCONCAT($mob, $n, "_", $i, ".bmp"), -1, 90)
...
...

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

Pages: 1 [2] 3 4