Re: Zombot (Клиент для игры Зомби ферма) [Обсуждение]
Там бывают такие значения:
PHP код:
{"type":"pirateStateRequirement","state":"PIRATE"}, пират, сундук стоит {"type":"pirateStateRequirement","state":"CITIZEN"}, горожанин (сундук на складе) {"type":"pirateStateRequirement","state":"RETURNED"}, вернувшийся (не крутил) {"type":"pirateStateRequirement","state":"DEAD"}]} вышел срок (сундук пропал)
то есть это такие ответы. Но думаю и стата такая же
Re: Zombot (Клиент для игры Зомби ферма) [Обсуждение]
Цитата:
Сообщение от vintets
Там бывают такие значения:
PHP код:
{"type":"pirateStateRequirement","state":"PIRATE"}, пират, сундук стоит
{"type":"pirateStateRequirement","state":"CITIZEN"}, горожанин (сундук на складе)
{"type":"pirateStateRequirement","state":"RETURNED"}, вернувшийся (не крутил)
{"type":"pirateStateRequirement","state":"DEAD"}]} вышел срок (сундук пропал)
да но, еще бывает нет атрибута state это когда не выполнены квесты
Re: Zombot (Клиент для игры Зомби ферма) [Обсуждение]
Форумчане, с недавнего времени заметил , что вылетают ошибки при крутке на пиратских островах.., сначала была ошибка при кручении колодца желаний, сейчас заметил ошибку на пушистом острове...
PHP код:
2014-12-27 02:21:41,421 Крутим рулетку в 'Мачта Желаний' осталось 193/200
2014-12-27 02:21:41,441 user is not valid
2014-12-27 02:21:41,443 Connection : {'crc': '1b8175eac59ff661dc1f5ce913fdcb27',
'data': u'{"user":"18318155742226352457","type":"EVT","id":1419635810971,"sig":
"ac38b31381ce6e5ad309c48181a368d6","events":[{"action":"play","type":"game","obj
Id":-13799,"extraId":"B_MAST_ROULETTE"}]}'}
2014-12-27 02:21:41,443 Response : {u'msg': u'user is not valid', u'cmd': u'ERR'
, u'id': u'1419635810971'}
вот так выглядит ошибка... раньше такого не замечал..
Re: Zombot (Клиент для игры Зомби ферма) [Обсуждение]
Я в саму в ферму уже наверное год не играл, а когда играл, то пользовался своим ботом на autoIt, потом забросил.
Недавно наткнулся случайно на этого бота и появилось желание поковыряться в нем. Считаю, что надо его переделывать основательно.
И вот почему:
- недостаточное разделение лоу левел функционала (отправка сообщений, авторизация) от хай левел (рутинные действия, собсно, сам бот);
- нет нормальной проверки на ошибки;
- трудно править бота при изменениях в протоколе;
- трудно добавлять новый функционал в связи с вышеприведенным.
Надо сначала добиться следующего:
- чтобы бот анализировал всю информацию от сервера на предмет того, поменялось ли чего;
- не выполнял действий, которые могут привести к "ingame error" (т.к. это флажек к жбану);
- добиться лучше абстракции, т.е. сделать нормальный API работы с сервером.
За основу взял оригинального бота с репозитория на гитхабе, сейчас его правлю и рефакторю (хотя питон вообще не знаю, но это для меня не проблема, там все просто).
Re: Zombot (Клиент для игры Зомби ферма) [Обсуждение]
Цитата:
Сообщение от ruslanische
Считаю, что надо его переделывать основательно.
Цитата:
Сообщение от ruslanische
сейчас его правлю и рефакторю
А я что-то считаю, что его надо оставить в покое, пусть гниёт. И вот почему:
У меня было где-то 6 замечаний по поводу существующего бота, по крайней мере того, что мне досталось, 0.9.2 . И прошу простить мне выраженное здесь дальше негодование по поводу кода бота.
Одно замечание было по концепции - очень хочется одну управляющую нитку и остальные пользовательские, по одной на пользователя. С сервером общается пользовательская нитка, а управляющая только предоставляет очередь будущих исходящих событий.
Остальные, наверно, по коду.
Код на питоне должен быть написан на питоне, с соблюдением концепции языка
[Ссылки могут видеть только зарегистрированные пользователи. ] , максимально простым для разработчиков конечных модулей и максимально понятным для остальных. Без дублирования кода, дохлого кода, явных ошибок и костылей
Дальше - по поводу 90кб непонятно мне зачем нужного кода в game_state/game_types.py . Dict as an obj пример, с той же wiki, отменили? [Ссылки могут видеть только зарегистрированные пользователи. ]
и функция dict2obj, которая съедает большинство процессорного времени.
Я, конечно, понимаю, что там куча assertов стоит на случай криворуких доделываетелй или своих ошибок. Но таки - без этой части кода вполне можно обойтись, сделав всё аккуратно.
Дальше, по поводу производительности - я как минимум переписал GameState.get_object_by_id
Код:
class GameLocation():
def __init__(self, item_reader, game_location, game_objects):
self.__item_reader = item_reader
self.__game_location = game_location
self.__game_objects = game_objects
self.__game_objects_dict = {obj.id:obj for obj in game_objects}
self.__pickups = []
def append_object(self, obj):
self.__game_objects_dict[obj.id]=obj
#self.get_game_objects().append(obj)
def get_game_location(self):
return self.__game_location
def get_game_objects(self):
#open("game_location.txt","w").write(str(obj2dict(self.get_game_location())))
#return self.get_game_location().gameObjects
#return self.__game_objects
return (v for k,v in self.__game_objects_dict.iteritems())
def get_location_id(self):
return self.__game_location.id
def get_all_objects_by_types(self, object_types):
objects = []
for game_object in self.get_game_objects():
item = self.__item_reader.get(game_object.item)
if game_object.type in object_types or item.type in object_types:
objects.append(game_object)
#yield game_object
return objects
#return
def get_all_objects_by_items(self, object_items):
objects = []
for game_object in self.get_game_objects():
if hasattr(game_object,'item') and game_object.item.lstrip('@') in object_items:
objects.append(game_object)
#yield game_object
return objects
#return
def get_all_objects_by_type(self, object_type):
return self.get_all_objects_by_types([object_type])
def get_object_by_id(self, obj_id):
if self.__game_objects_dict.has_key(obj_id):
return self.__game_objects_dict[obj_id]
else:
return None
#for game_object in self.get_game_objects():
# if game_object.id == obj_id:
# return game_object
#return None
def log_game_objects(self):
for gameObject in self.get_game_objects():
# if gameObject.type != 'base':
logger.info(obj2dict(gameObject))
def remove_object_by_id(self, obj_id):
if self.__game_objects_dict.has_key(obj_id):
del self.__game_objects_dict[obj_id]
#for game_object in list(self.get_game_objects()):
# if game_object.id == obj_id:
# self.get_game_objects().remove(game_object)
def get_pickups(self):
return tuple(self.__pickups)
def add_pickups(self, pickups):
self.__pickups += pickups
def remove_pickup(self, pickup):
self.__pickups.remove(pickup)
, но код может быть ещё прозрачнее, используя collections defaultdict . Что происходит? При добавлении/удалении объекта по id выполняется одно действие, а не перерывается весь массив объектов локации. Аналогично стоит сделать склад
Это в GameState.__init__
Код:
self.storage = collections.defaultdict(long,((itemid.item,itemid.count) for itemid in self.__game_state.storageItems))
А это вместо существующих функций
Код:
def has_in_storage(self, item_id, count):
return item_id in self.storage and self.storage[item_id]>=count
def count_in_storage(self, item_id):
return self.storage[item_id]
def remove_from_storage(self, item_id, count):
if item_id in self.storage:
self.storage[item_id]-=count
return True
else:
return False
def add_from_storage(self, item_id, count):
self.storage[item_id]+=count
def set_from_storage(self, item_id, count):
self.storage[item_id]=count
class GameItemReader():
def __init__(self):
self.content_dict = {}
self.objects_already = {}
settings = Settings()
self.__ignore_errors = settings.get_ignore_errors()
def get(self, item_id):
item_id = str(item_id).lstrip('@')
if not self.objects_already.has_key(item_id):
self.objects_already[item_id]=dict2obj(self.content_dict[item_id])
return self.objects_already[item_id]
- зачем создавать ещё раз объект из items, если он уже есть? Реально используется из 4000 только пара сотен.
Реализация двух вышеизложенных замечаний позволила мне сократить процессорное время в сотни раз и избавиться от зависаний бота.
Дальше - неодноуровневая инкапсуляция - сильно мешает писать простой код. Как вспоминить, что location_id на самом деле берётся self._get_game_state().get_game_loc().get_location _id()
Дальше - в питоне есть @property , у них есть getter и setter, это очень удобно, вместо всяких _get_
Ну и пару вещей на закуску я наверно в этот раз умолчу, а про события и конфигурацию модулей я говорил выше.
Понятно, что убрав код бота, относящийся к этим замечаниям, у нас останется только авторизация, да, пожалуй наследование от ResourcePicker и TargetSelector, что было приятно читать.
И да, спасибо dark-dragon за провокацию написания этого
Последний раз редактировалось megabyte0; 27.12.2014 в 21:41.
Re: Zombot (Клиент для игры Зомби ферма) [Обсуждение]
megabyte0
Согласен с тобой, у меня такие же чувства вызывает чужой код (который не мой, не родной), хотя чаще всего попадается очень хороший. В данном случае код... так себе он и слишком "сишный" и слишком с++сный, если можно так выразиться - слишком много ООПшных моментов, которые неприемлемы к скриптовому языку. Надо сделать проще. Думаю, что потихоньку я это сделаю, а потом выложу.
Добавлено через 2 минуты
Но автор оригинала сделал большую работу, которая отвечала его требованиям, за что я ему благодарен.
Последний раз редактировалось ruslanische; 28.12.2014 в 22:35.
Причина: Добавлено сообщение
Re: Zombot (Клиент для игры Зомби ферма) [Обсуждение]
Цитата:
Сообщение от ruslanische
Но автор оригинала сделал большую работу, которая отвечала его требованиям, за что я ему благодарен.
О чем и речь. Автор сделал рабочий "фреймворк" для бота. Который пользовали (и пользуют), предположительно, тысячи людей. Насколько я понимаю, его цель была - сделать, чтобы работало. После того, как заработало, он потерял к нему интерес (и, как я понял, и к игре). Можно ли сделать лучше и красивее? Можно. Только почему-то только один человек переписал бота с нуля (и ПРОДАЕТ его использование).
PS. Я тоже раньше модифицировал, дописывал модули и т.д. А сейчас "отпустило" (в плане игры). Крутится где-то там, на Линуксе... Периодически захожу, проверяю обновы, подправлю код под обновления... Но интереса в игре уже нет...