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 - Johnny

Pages: [1]
1
Учебные статьи / Потоки
« on: October 25, 2014, 09:32:54 AM »
Актуально для версии 4.11+

Многопоточность в Clickermann

Как все знают со школы, Windows – многозадачная операционная система. Впрочем, как и большинство современных ОС, за исключением особо специализированных. Это значит, что на машине под управлением ОС могут одновременно выполняться несколько задач, в нашем случае приложений. Можно долго рассуждать на тему, что одно неудачное действие повесит все намертво и что задачи выполняются не параллельно, а просто быстро переключаются друг между другом. Но примем это за аксиому.
Подобно этому, в составе приложения можно организовать несколько потоков (нитей, англ. thread). И они точно так же могут выполняться параллельно, как и сами приложения. С рядом оговорок. Во-первых, потоки могут свободно использовать общие данные своего родительского приложения. Во-вторых (хотя косвенно это вытекает из первого) потоки могут останавливать друг друга, снова запускать и так далее.
Для чего нужны потоки? Для оптимизации работы. Если взять за догмат то, что две параллельные задачи выполняются по крайней мере не медленнее, чем две последовательные (хотя это спорное утверждение), то целесообразно наиболее ресурсоемкие выделять в отдельные потоки. Это позволит выиграть в общем логическом быстродействии. Поясню почему. Если один какой-то поток повиснет, серьезно задумается или в нем произойдет сбой, это не убьет (замедлит) приложение целиком. Это вы можете наблюдать например в браузере Хром, где повисание одной вкладки не парализует весь браузер. Огнелиса так не умеет…
Существует лишь одна особенность – разделение ресурсов. При прочих, равных нельзя знать в какой момент начнет и бросит выполняться поток, помещать в них стоит относительно автономные задачи. Плохая идея в одном потоке наращивать переменную, а в другом записывать ее значение в файл столбиком. Пропуски значений и наоборот повторяющиеся – обычное дело при данном некорректном логическом подходе. Для решения этой задачи используются общие переменные флаги – «семафоры», анализируя которые потоки понимают, какой из них отработал и чья очередь теперь выполнить свою задачу.
Перейдем наконец к коду. Поток в кликермане объявляется следующим, похожим на подпрограмму, образом.
Code: (clickermann) [Select]
Thread(thr_name)
// тело потока
End_thread

Данный поток с именем thr_name начнет крутиться сразу после старта скрипта. Если вы хотите что бы поток запустился позже, то необходимо в шапке после имени добавить 0. То есть
Code: (clickermann) [Select]
Thread(thr_name, 0)
// тело потока
End_thread

Теперь данный поток можно запустить лишь из самого скрипта специальной процедурой контроля потоков setThread:
Code: (clickermann) [Select]
setThread(thr_name, 1)в которой thr_name – имя потока, а 1 – присваиваемое состояние «запущен», заменив которое на 0 можно так же приостановить поток. Потоки могут невозбранно контролировать друг друга.

Каждый поток обладает собственным адресным пространством, поэтому задержка wait() в одном ни коим образом не влияет на остальные потоки. При этом, потоки имеют доступ к общим переменным и графическому буферу. Стоит отметить, что из-за особенностей архитектуры кликера, подпрограммы Sub() не могут разделяться потоками, поэтому для каждого они индивидуальны и должны быть объявлены внутри потока. Другими словами, подпрограммы описанные внутри одного потока не могут быть вызваны другим потоком.
Основное (абстрактно) тело скрипта, даже если оно описано без thread() .. end_thread так же является отдельным потоком, поэтому для него справедливо все вышесказанное. Поэтому фактически, сценарии вида
Code: (clickermann) [Select]
Thread(thr1)
   Wait(1)
End_thread

Print("Hello")
Wait(3)
И
Code: (clickermann) [Select]
Thread(thr1)
   Wait(1)
End_thread

Thread(thr2)
   Print("Hello")
Wait(3)
End_thread
Абсолютно одинаковы.
Последнее что вам необходимо знать, это то, что как и основной скрипт, потоки должны «давать передохнуть» процессору, поэтому потрудитесь разместить внутри них wait’ы, на которые он обязательно наткнется, иначе ваш сценарий будет серьезно нагружать процессор в ряде случаев.

Несколько показательных примеров
Первый случай, о котором иногда спрашивают – это нажатие клавиш (да и вообще действия) по интервалу. Например, каждые 3 секунды жмем A, каждые 5 секунд – B. В обычном случае нам бы потребовался единичный интервал (секунда) и два счетчика, которые наращиваются. Затем в двух условиях проверяются их значения и если счетчик достиг 3 (или 5) то выполняются действия и счетчик обнуляется. Два счетчика нужны, потому что действия независимы друг от друга. Сам скрипт выглядит так (для удобства сами нажатия заменены на вывод в лог)
Code: (clickermann) [Select]
wait(1)
$cnt1 = $cnt1 + 1
$cnt2 = $cnt2 + 1

if($cnt1 = 3)
   print("A")
   $cnt1 = 0
end_if

if($cnt2 = 5)
   print("B")
   $cnt2 = 0
end_if

При этом, если внутри условия будет ряд других затратных инструкций или упаси Боже задержка – в классическом решении реализовать такое было бы весьма затратно (приходилось бы вычислять временные затраты на каждое действие, вводить поправки на разницу и т.д.)
Реализуем тот же самый скрипт на потоках
Code: (clickermann) [Select]
thread(th1)
   print("A")
   wait(3)
end_thread

thread(th2)
   print("B")
   wait(5)
end_thread

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

Второе распространенное решение –  реализация псевдо хоткеев через iskeydown(). Как вы знаете эта функция проверяет нажата ли клавиша. Но проверить это она может только в момент собственного выполнения. То есть если у вас есть два условия с iskeydown() и первое сработало, то в том случае если внутри него будут пресловутые задержки и долгие действия, проверить нажатие второй клавиши удастся только когда первое условие отработает целиком.
Пример старого образца. Два последовательных условия, которые в случае нажатия клавиши печатают ее в лог каждые 3 секунды наши любимые буквы A и B. Поскольку задержка в каждом условии составляет 3 секунды, то у вас не получится вывести в протокол сразу обе буквы даже если вы зажмете обе клавиши одновременно.

Code: (clickermann) [Select]
if (iskeydown(#A)=1)
   print("A")
   wait(3)
end_if

if (iskeydown(#B)=1)
   print("B")
   wait(3)
end_if

waitms(10)

Безусловно, можно попробовать добавить третье условие двойной проверки обоих нажатий iskeydown() & iskeydown(), но тогда будут срабатывать и одиночные условия, ведь клавиша то зажата. Неразрешимая для неискушенного программиста задача элементарно решается введением потоков под каждый хоткей.
Code: (clickermann) [Select]
thread(th1)
   if (iskeydown(#A)=1)
      print("A")
      wait(3)
   end_if
   waitms(10)
end_thread


thread(th2)
   if (iskeydown(#B)=1)
      print("B")
      wait(3)
   end_if
   waitms(10)
end_thread

Визуально код стал более объемным, однако не стоит забывать, что в отличие от первого, этот – работает. Вы легко можете зажимать клавиши хоть одновременно, хоть как – такты не собьются.
Таким образом, потоки позволяют легко решить ряд прикладных задач, которые до этого решались если не запущенными копиями кликера, то как минимум жуткими костылями. И их потенциал неограничен приведенными примерами, конечно же.

2
Если программа не запускается на Windows 8 и еще ряде ОС, при этом вам выдается сообщение, похожее на это:



Вы должны попробовать сделать следующее:

1. Откройте Свойства системы, вкладку Дополнительно

2. Нажмите на кнопку Параметры области Быстродействие, перейдите на вкладку Предотвращение выполнения данных в открывшемся окне

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

4. Воспользовавшись открывшейся кнопкой Добавить, добавьте Clickermann.exe в список исключений, нажмите ОК

5. Перезагрузите машину

После этого проблема должна исчезнуть

3
Приведенная информация актуальна только для версии 4.10, находящейся на тестировании

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

[Spoiler="Информация для тех кто уже использовал в условиях and,or,xor"]
На самом деле отчасти вы уже знакомы с битовыми операциями. Это уже знакомые нам И, ИЛИ и ИСКЛЮЧАЮЩЕЕ ИЛИ (далее and, or, xor). Несмотря на то, что эти операторы мы использовали лишь в логических условиях, на самом деле с помощью них так же можно производить операции над величинами, как это делается на самом низком уровне – уровне железа ПК.
Ранее, подразумевалось что операндами могут быть лишь 0 и 1. Ну вы помните, 0 and 1 = 0, 0 or 1 = 1 и все такое. И даже когда писалось выражение типа (5 > 3) and (4 < 2), это в конечном итоге после вычисления отношений в скобках превращалось в тоже (1) and (0)
Теперь, начиная с версии 4.10 вместе с изменением работы логики появилась возможность производить битовые операции ВЕЗДЕ. Как в условиях, так и в вычислениях.
[/spoiler]

Перед началом я напомню, что в компьютере все – в двоичном виде, потому что это исключительно удобно в плане электроники. В математике же любое число может быть представлено в любом виде, в десятичном, в двоичном, в шестнадцатеричном. В каком бы виде число не было представлено, это по прежнему то же число. Несмотря на то, что мы с детства привыкли работать в десятеричной системе счисления, а компьютер понимает лишь нули и единицы.
Так же, говоря "истина" я имею ввиду "1",а говоря "1" я имею ввиду "истина". "0" это "ложь". Такой подход обусловлен тем, что битовые операции неотделимы от логических высказываний.
Битовые операции возможны лишь с целыми положительными числами. И нулем.
Так же я напоминаю что "and", "or" и "xor" являются синонимами операций "&","|" и "^" соответственно. При этом с точки зрения кликера, "роднее" ему именно знаковые обознаения операций и поэтому я рекомендовал бы использовать именно их (меньше шанс что парсер "споткнется" в каком либо "особом случае"). Однако поскольку это учебная статья, в примерах я буду использовать первый набор, потому что для новичков он нагляднее.

Итак приступим. Бросаемся в бой сразу с готовым скриптом. Я напоминаю что версия должна быть не ниже 4.10
Code: (Clickermann) [Select]
$var = 15 and 6
print($var)
Выполнив этот код, вы получите в результате 6. То есть ничего не изменится. Рассмотрим как получается данный результат.
"15" это десятичное представление числа. Это же число представленное в двоичном виде будет выглядеть как 00001111 (для соблюдения стандарта будет оперировать одним байтом, т.е. восьми битами; незначащие разряды забьем нулями). Вы можете убедиться что это так, включив калькулятор в Win7 и переведя его в режим "Программист" (этот удобный калькулятор одна из причин моего окончательного перехода на семерку). "6" в двоичном виде это 00000110.
Выполняем операцию. Для удобства восприятия запишет одно число под другим.
Code: [Select]
00001111
00000110
И теперь просто вертикально (сверху вниз, по столбцам) проверяем привычное нам условие. Если вверху и внизу 1, то и в результате будет 1. В другом случае будет 0. Так работает операция AND и вы об этом уже знаете, если хоть раз писали комплексное условие.
Code: [Select]
00001111  // 15
          // and
00000110  // 6
00000110  // Результат 6
Повторим опыт с другими числами. Возьмем 51 и 60. Результатом будет 48. Смотрим как получилось.
Code: [Select]
76543210  // Биты, No
--------
00110011  // 51
00111100  // 60
00110000  // 48
Таким образом истину образует только пара битов 4 и 5 (биты считаются справа налево, первый бит имеет индекс 0), в которых в обоих числах единицы.
Стоит отметить, что правило про "перемену мест" справедливо для всех битовых операций. Вы легко можете проверить это простым примером на основе предыдущей задачи
Code: (Clickermann) [Select]
$var = 51 and 60
print($var)
$var = 60 and 51
print($var)
Имея эти базовые знания быстро освоим операции OR и XOR
Если для операции AND нужно для истины чтобы оба бита были 1, то для OR хватит и одного из них. Перепишем пример с 51 и 60.
Code: [Select]
00110011  // 51
00111100  // 60
00111111  // 63
Как вы видите «единички спустились» почти во все разряды кроме последних двух (6-ого и 7-ого). Для тех кто не понял почему, я напомню что и 1 or 0 = 1 и 1 or 1 = 1. Лишь 0 or 0 = 0
И завершим нашу лекцию наиболее интересной (и по этому редко используемой) операцией XOR. Это нечто среднее между AND и OR. Для того что бы XOR вернул истину, нужно что бы ЛИШЬ ОДИН из пары был истиной. Таким образом 1 xor 1 = 0 и 0 xor 0 = 0. А вот 1 xor 0 = 1.
Снова вернемся к нашим крайне удачным числам 51 и 60.
Code: [Select]
00110011  // 51
00111100  // 60
00001111  // 15
Как вы видите "разномастными" являются первые четыре пары бит (0..3). Все остальные являются одинаковыми и несмотря на 0 или 1, для xor важно лишь различие.
У операции xor есть еще одно свойство если два раза подрояд произвести операцию xor при помощи одного и того же числа, то вы получите исходное число. Иллюстрирует это простой пример
Code: (Clickermann) [Select]
$var = 51
$key = 60

$var = $var xor $key
print("xor: ", $var)

$var = $var xor $key
print("xor again: ", $var)
Поэтому XOR является самым простым (и одновременно быстрым) алгоритмом шифрования. Не знаю как вам это пригодится для написания скриптов на линейку…
Поздравляю. Вы освоили битовые операции.

Теперь, не отрываясь от чтения, рассмотрим специфику работы логических высказываний.
В версии 4.10 считается, что операции отношения  >, <, = (если речь не идет о присваивании значения) являются такими же операциями как сложение или вычитание (или битовые операции). Однако в зависимости от истинности результатом будет 0 или 1.
Рассмотрим пример.

Code: [Select]
$var = 5 > 3
При этом $var = 1, потому что 5 очевидно больше 3. Если бы было меньше, то результат был бы 0.
Более сложный случай
Code: [Select]
$var = (5 > 3) and (2 > 3)
Результат $var = 0, потому что получается (1) and (0), ведь 2 не больше 3. Ну а 1 and 0, как вы уже знаете дадут 0. Если бы это было в условии if
Code: (Clickermann) [Select]
if ((5 > 3) and (2 > 3) )
  print("ok")
end_if
То условие бы не выполнилось, потому что результат логического высказывания (состоящего из сравнений и их битового произведения – and) будет 0. Для того что бы "if выполнился" он должен быть больше нуля. Стоит заметить что не обязательно "1" а именно больше нуля.

Простые примеры для понимания
Code: (Clickermann) [Select]
// высказывание истинно ( > 0 ), условие выполняется
if(100)
  print("ok")
end_if
// высказывание ложно ( < 0 ), условие не выполняется
if(-100)
  print("ok")
end_if
// высказывание ложно (= 0), условие не выполняется
if ( 1 and 0 )
  print("ok")
end_if
// высказывание истинно (> 0, помните же пример из битовых операций?), условие выполняется
if ( 51 and 60 )
  print("ok")
end_if
// высказывание истинно, условие выполняется, приоритетные скобки поддерживаются
if ( (51 and 60) or 1 )
  print("ok")
end_if
Важно отметить важность приоритетных скобок. Дело в том что и у битовых операций есть свои приоритеты: операция AND (ее еще называют битовым произведением) выполняется первой. Если порядок действий не обозначен скобками. Пример
Code: (Clickermann) [Select]
// пример 1
$var = 3 or 15 and 12
print($var) // 15

// пример 2
$var = (3 or 15) and 12
print($var) // 12
Разберем пример 1
3 or 15 and 12 // первым по приоритету выполняется операция and получаем
3 or 12 // так как 15 and 12 = 12
И в результате будет 15, так как 3 or 12 = 15
Разберем пример 2
(3 or 15) and 12 // первым как и везде идет операция в скобках получаем
(15) and 12 // и в результате 12

Напоследок приведем совершенно дикий для новичка пример
Code: (Clickermann) [Select]
if( ((10 + (2 > 1)) and 8 + 2) or 3 )
  print("true")
else
  print("nope")
end_if
Выполнится ли условие? Да, потому что результат высказывания будет 11, а это явно больше 0, чего достаточно для выполнения блока условия, соответствующего истине. Если вы сможете самостоятельно просчитать это выражение (и запомнить что условия считаются истинными когда они больше 0) то вы способный программист.

5
Учебные статьи / Массивы
« on: October 08, 2013, 12:44:28 PM »
последняя редакция: 21.03.2014

Вводная часть

В версии 4.8 были введены массивы. Для начала классическое школьное определение. Массив (англ. Array) – это набор однотипных данных, расположенных в памяти друг за другом. При этом, благодаря этому «друг за другом», каждый элемент массива имеет свой порядковый номер (индекс, смещение). По сути, этот номер определяет смещение элемента массива в памяти относительно его (массива) начала, но вам не стоит вникать во все эти сложности, потому что как обычно, все нюансы «сложного программирования» Clickermann обрабатывает сам.

Итак массив, как и переменная, имеет собственное имя. Правила для имен массивов такие же как и для переменных. При этом, после указания имени массива, в квадратных скобках задается индекс элемента для получения его значения (или соотв. присвоения).

Рассмотрим пример

Code: (clickermann) [Select]
$arr[0] = 1
$arr[1] = 2
$arr[2] = 3
$arr[3] = 4
$arr[4] = 5

Здесь мы разместили в массиве $arr пять элементов. Обратите внимание что индексация массива начинается (как и в С++) с нуля.
Теперь, к примеру, если мы сделаем следующую операцию

Code: (clickermann) [Select]
Print( $arr[1] )
То в лог выведется «2». По аналогии с переменными, элементы массива могут становиться аргументами функций и процедур, участниками условий и вычислений. Вы можете спросить в чем же тогда удобство? Ну, например, вышеозначенный массив имеет пять элементов, которые мы могли бы заменить переменными $arr1($arr2, …). Тогда их вывод имел бы вид

Code: (clickermann) [Select]
Print($arr1)
Print($arr2)
Print($arr3)
Print($arr4)
Print($arr5)

Уже смотрится не очень. А если бы переменных было штук пятьдесят?
Однако в случае с массивом все намного проще. Мы просто прогоним весь массив в цикле

Code: (clickermann) [Select]
For($i, $i<5)
  Print( $arr[ $i ] )
End_cyc

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


Объявление и доступ

Что будет если выскочить за пределы массива? В том же С++ программа при работе выдала бы ошибку доступа к виртуальной памяти. Однако в нашем случае это просто вернуло бы «0» (не уверен, что всегда).

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

Вы можете например задать массив на семь элементов таким образом

Code: (clickermann) [Select]
$arr[6] = 5
При этом элементы массива 0,1,2,3,4,5 будут содержать т.н. мусор, то есть данные, лежащие в оперативной памяти до выполнения нашего кода. Это происходит потому что память массиву присваивается, но никакие значения в нее пока не кладутся и там хранится старая мусорная информация. Данный массив так же можно растянуть еще до десяти элементов

Code: (clickermann) [Select]
$arr[8] = 32
$arr[9] = 43

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

Функции работы с массивом

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

Функция arrsize($arr)

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

Code: (clickermann) [Select]
$arr[0] = 12
$arr[5] = 123

Print( arrsize($arr) ) // вернет «6»

К слову сказать, если размерность массива 1, то это по сути переменная. И с ним можно работать как с переменной (запись «$arr[0]» в данном случае будет эквивалента «$arr»)

Процедура arrpush($arr, value)

Данная процедура добавляет новый элемент в конец массива. Каждый ее вызов соответственно увеличивает размер массива на 1. Вот пример

Code: (clickermann) [Select]
Arrpush($arr, 1)
Arrpush($arr, 2)
Arrpush($arr, 3)

Print( $arr[1] ) // вернет «2»
Print( arrsize($arr) ) // вернет «3»

Таким образом, можно особо и не возиться с индексами чтобы заполнить массив

Функция arrpop($arr)

Данная функция возвращает последний элемент массива, при этом удаляя его из массива, уменьшая, таким образом, его размерность на 1. Да, именно так можно обрезать (или целиком вообще вычистить) массив. Стоит понимать, что эта функция выдает элементы в обратном порядке (т.к. после удаления последним элементом становится предыдущий).

Code: (clickermann) [Select]
Arrpush($arr, 1)
Arrpush($arr, 2)

Print( arrpop($arr) ) // «2»
Print( arrpop($arr) ) // «1»

Но самое главное, что с помощью этих двух функций – arrpush и arrpop – можно без труда организовать самый натуральный стэк. Это тема отдельной беседы, потому что стэк (и регистры) фундаментальные понятия микропрограммирования. Нам же нужно помнить, что стэк, это стопка. Если положить то только сверху. Если взять, то только сверху. Если нужен предпоследний элемент, извольте сначала «снять с него» последний. Можете почитать Вики, если интересно, http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D0%B5%D0%BA

Процедуры scanpicture и scanpxl

Ну и наконец две самые вкусные функции, призванные, наконец, если не заменить, то дополнить два самых старейших костыля if_pixel_in и if_picture_in. Они конечно работают и на них построено огромное количество скриптов, однако у них есть один существенный недостаток – они находят только один элемент. Точнее первый. Например, как только наличие картинки на экране будет установлено, дальнейший анализ прекращается. Продвинутые пользователи конечно выходили из ситуации, играясь с координатами поиска, но это все не то (хотя безусловно полезно для общего развития).

Теперь разберем рассмотрим следующий скрипт

Code: (clickermann) [Select]
getscreen

scanpicture($var, 0,0, 1250,959, "pict.bmp")

while (arrsize($var) > 0)
  $y = arrpop($var)
  $x = arrpop($var)
  lclick($x, $y)
end_cyc

Этот короткий скрипт реализует очень большой геморрой. Он ищет в заданной области все экземпляры картинки pict.bmp и последовательно кликает на каждую из них. Разберем его по порядку. Прежде всего обратите внимание на новую процедуру scanpicture. Ее синтаксис схож с if_picture_in за тем исключением, что первым параметром идет массив. В этот массив процедура последовательно добавляет (через внутренний вызов arrpush) координаты каждого найденного экземпляра искомого изображения. Таким образом после выполнения scanpicture, входной массив $var будет содержать N пар координат x,y, где N количество найденных картинок.

Полученный массив можно представить схематически так:
[x1, y1, x2, y2, … , xN, yN] где x,y – пара координат

Далее необходимо всю эту кучу пробежать. Удобнее всего, как известно, перебирать массивы в цикле. Организуем цикл while с условием arrsize($var) > 0. Это будет оптимально по тому что позволит сразу проскочить тело цикла, если ничего не найдено. Стоит заметить что arrsize вернет значение N * 2, потому что эта функция возвращает длину массива и ее не волнует наше представление данных (в данном случае имеется ввиду что i – это координата X, i+1 – координата Y).
Далее мы в теле цикла вызываем arrpop($var) таким образом выдергивая последнюю координату Y и уменьшая длину цикла на 1. Следующий вызов arrpop вернет уже координату X последней пары (про работу стэка я уже рассказывал выше, вот это типичный пример). Таким образом в координатах $x, $y у нас лежат координаты последней найденной картинки. А поскольку arrpop уже удалил эту пару из массива, то сейчас там в самом конце лежат уже координаты предыдущей картинки. Таким образом извлекаются все координаты найденных картинок. И когда будет извлечена последняя пара, arrsize вернет 0 и цикл закончится.

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

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

Стоит добавить, что массивы, как и переменные хранят свои значения. Поэтому последовательный вызов двух scanpicture (например) без извлечения элементов через arrpop приведет к тому что у вас будет двойная очередь координат. Поэтому если вам для работы необходим «чистый» массив, то не забывайте высвобождать память, путем вызова undefine($var). Тут все как для переменных.

Такие дела. Я как мог подробно разжевал основные моменты работы с массивами в общем и тонкости их использования непосредственно в Clickermann. Надеюсь что данный материал поможет вам легко и быстро освоить новые способы программирования.

6
Дискус

7
В этой теме предлагается обсудить очередное мое поделие AntiGate Client (просто AGClient, еще проще AGC). Проект собранный на коленке из примера, взятого с сайта antigate.

Для тех кто не в курсе, антигейт (http://antigate.com) - это сервис для распознавания капчи с привлечением "китайцев". Вы шлете картинку с капчей, китайцы ее смотрят, набирают капчу и сервис шлет ее обратно.

Сервис платный. Одна капча стоит $0.001 (около 3 копеек). Можно повысить цену, тогда китайцы будут еще более рьяно разбирать ваши капчи, но оно работает и так довольно быстро. Вам понадобится свой аккаунт в системе антигейта.

AGClient v1.2 доступен на нашем сайте http://crapware.aidf.org/page/clickermann

8

9
Давайте что ли хоть историй порассказывайте

10
Ошибки / Правила раздела
« on: October 13, 2012, 06:36:38 AM »
Правила раздела:
  • Это раздел для сбора ошибок, обнаруженных в последней версии кликера
  • Ошибкой не является некорректная работа кликера в каком-то конкретном приложении. С подобными вопросами в раздел "Использование"
  • Перед тем как создать тему, внимательно изучите уже имеющиеся. Возможно, об имеющийся ошибке уже было заявлено
  • Если вы все же решили создать тему, укажите в названии конкретно проблему (Например "Ошибка в функции pxl()"), в самой теме укажите вашу ОС и версию кликера
  • Если ошибка связана с языком сценариев, приводите код, который работает некорректно

11
Использование / Правила раздела
« on: October 12, 2012, 05:58:43 PM »
Правила раздела:
  • Это раздел для прояснения частных случаев использования кликера
  • Перед тем как создать тему, внимательно изучите уже имеющиеся. Возможно, вы найдете ответ на ваш вопрос
  • Если вы все же решили создать тему, укажите в названии целевую программу (Например "Clickermann в приложении Зомби Ферма")
  • Если у вас есть вопрос касательно работоспособности, укажите версию операционной системы, версию кликера, версию приложения

12
Общие вопросы / Правила раздела
« on: October 12, 2012, 05:54:41 PM »
Правила раздела:
  • Это раздел для прояснения общих случаев использования кликера. Использование кликера в конкретных приложениях обсуждается в разделе "Использование"
  • Перед тем как создать тему, внимательно изучите уже имеющиеся. Возможно вы найдете ответ на ваш вопрос
  • Если вы все же решили создать тему, дайте ей внятное название, отражающее суть вопроса. (Крайне плохой идеей будет назвать тему "Помогите!!!1" или "Вопрос")
  • Если у вас есть вопрос по какой-то конкретной команде или группе команд, укажите это в названии ("Вопрос по поводу чтения файлов", "Помогите с pxl()")

13
Предложения / Правила раздела
« on: October 12, 2012, 05:46:43 PM »
Требования:
  • У вас должна быть последняя версия программы. Согласитесь глупо просить то, что уже было реализовано
  • Объясняйте зачем нужно предлагаемое нововведение
  • Первые два пункта повышают шанс на реализацию вашего предложения
  • Если у вас предложение по расширению языка сценариев, можете не ломать голову над синтаксисом, а просто описать что должна делать команда
  • Свои предложения оформляйте в отдельную тему, чтобы их могли обсудить участники форума

Рассмотрению не подлежат:
  • Просьбы интеграции со сторонним софтом (Вопросы взаимодействия обсуждаются в разделе "Использование")
  • Абстрактные просьбы типа "Сделайте обход Game Guard в Lineage II"

Pages: [1]