Приветствую, читатели!
Сегодня я хочу рассказать вам про сервис, который обнаружил буквально недавно — Dripstat. Он позволяет установить на локальную JVM специальный java-агент который собирает статистику работы сервера приложений и отправляет на сайт, где с ней можно детальнее ознакомиться.
— Ну какие сервисы мониторинга? Сегодня суббота! — скажете вы, и будете правы. Более того, я даже поддержу эту мысль и в данной заметке расскажу как раз об обратной, развлекательной, стороне медали, и чуть-чуть о программировании на JS.
Итак, приглашаю дочитать тех кто заинтересовался.
Сразу же идем по ссылке на страничку игры — dripstat.com/game/. Над интерфейсом разработчики не заморачивались, но это и к лучшему — все интуитивно понятно и разобраться можно за 5 минут.
Потратив немного времени на кликанье чашки и сбрасываение накликаного в «кошелек» (capacity) и по ходу дела осмотревшись в интерфейсе стает ясна основная цель игры — «накапать» (drip) побольше памяти. Справа видно оранжевый progress-bar, который показывает текущую цель, но не стоит пугаться столь большому числу, над его достижением работают все участники (ниже видно небольшой рейтинг и диаграмму активности), а не один игрок.
Но капать по 1 байту не интересно. Что же у нас есть для того что бы прокачаться? По мере завершения обучения стают доступными средства которые позволяют как генерировать память вместо вас так и улучшать показатели ручной генерации.
Я не буду дублировать информацию и перечислять их все — лучше увидеть самим (все они перечислены в правой панели, первая строка — доступные улучшения, а последующие строки — перечень самих генераторов памяти).
Ну вот собственно и все что касается самой игрушки.
Но на этом я не остановился, ведь инстинкт программиста заиграл внутри и потребовал проболжения банкета. Поэтому я решил все таки попробовать ломануть автоматизировать процесс.
1. Поверхностный анализ протокола обмена сообщениями между сервером и клиентом показал что подмену сообщений произвести не получится — сервер имеет внутренние механизмы верификации. Ковыряться детальнее желания не было, поэтому я пошел другим путем — со стороны клиента.
2. Можно конечно обойтись автокликером, но это не так интересно да и браузер должен быть постоянно в фокусе, плюс кроме чашки кофе кликать нужно и по другим элементам страницы. Первое что пришло в голову как дешевое и эффективное решение — userscript (ну и firebug естественно, ведь без него в разы сложнее смотреть на внутренности странички). Рассказывать про то как установить необходимый плагин и запустить сам скрипт я не буду, этой информации полно на просторах интернета да и на хабре тоже. Но самим скриптом, конечно же поделюсь.
Основная идея была в следующем:
0) Кликаем-кликаем-кликаем!
1) Пробуем закупать апгрейды, ибо они дают целых 10% мощности для генератора.
2) Далее ищем самый дорогой генератор и покупаем его. Сначала порядок был обратный и постоянные закупки курсора очень вяло влияли на прогресс, поэтому порядок был изменен.
3) Если накликали 90% памяти, то сбрасываем ее расширяя capacity. Этот пункт выполняется в случае когда все что можно было купить уже куплено и для дальнейших закупок нужен кошелек побольше. К примеру и генераторы и апгрейды уже по цене превзошли capacity и единственное что остается — Drip Memory.
Реализация:
// ==UserScript==
// @name dripstat_clicker
// @namespace x_lab.ice
// @include https://dripstat.com/game/
// @version 1
// @grant GM_openInTab
// ==/UserScript==
unsafeWindow.document.hasFocus = function () {return true;}; // в игрушке есть проверка на наличие фокуса у документа,
// и как только фокус теряется мы уже не можем жать на чашку, соответственно требуется грязный хак
(function (window, undefined) {
if (window.top != window.self) { return; } // избегаем запусков нашего скрипта в iframe
window.addEventListener("load", LocalMain, false); // как только страница прогрузилась запускам нашего бота
function LocalMain() {
setInterval(function() { Shopping(); }, 10000); // покупаем улучшения и генераторы 1 раз в 10 сек
setInterval(function() { Clicker(); }, 10); // а кликаем по чашке 100 раз в сек
// (ну или пытаемся, ведь поток JS занят и другими делами, поэтому непрерывной генерации не получим)
}
function Clicker() {
$('#btn-addMem').click(); // собственно жмем на чашку
if(localStats.byteCount > localStats.memoryCapacity * 0.9) { // если накликали уже около 90% а потратить некуда
$('#btn-addGlobalMem').click(); // то увеличиваем capacity
}
}
function Shopping() { // идем за покупками
var evt = document.createEvent("MouseEvents"); // готовим фиктивную мышку
evt.initEvent("click", true, true);
var upgrades = document.querySelector('#upgrades'); // сначала глянем что можно проапгрейдить
var upgChildren = upgrades.childNodes;
for(var j=0; j < upgChildren.length; j++) { // проходимся по витрине начиная с самого дешевого
var upgChild = upgChildren[j];
if(upgChild.className == 'upgcontainer') { // как раз по имени класса можно определить отключен ли элемент
upgChild.dispatchEvent(evt); // и если он включен - покупаем
}
}
var store = document.querySelector('#powerupstore'); // далее идем к генераторам памяти
var children = store.childNodes;
for(var i=(children.length-1); i >= 0; i--) { // но смотрим самое дорогое
var child = children[i];
if(child.className == 'storeItem') { // нашли!
child.dispatchEvent(evt); // покупаем!
}
}
}
})(window); // вот так и живем :)
На данный момент (чистого времени работы кликера прошло не так и много), мой результат такой
Алгоритм не идеален но это и не было целью. Главное удовольствие, да и
Айда устроим турнир между AI!
P.S. Скажи печенкам — Нет! (если кто не знал — orteil.dashnet.org/cookieclicker/)
Автор: icepro