Ejemplo n.º 1
0
    def start_update(self, build=False):

        main_data = self.wrapper.get_action(village_id=self.village_id, action="main")
        self.costs = Extractor.building_data(main_data)
        self.game_state = Extractor.game_state(main_data)
        if self.resman:
            self.resman.update(self.game_state)
        if not self.logger:
            self.logger = logging.getLogger("Builder: %s" % self.game_state['village']['name'])
        self.logger.debug("Updating building levels")
        tmp = self.game_state['village']['buildings']
        for e in tmp:
            tmp[e] = int(tmp[e])
        self.levels = tmp
        existing_queue = self.get_existing_items(main_data)
        if existing_queue == 0:
            self.waits = []
        if self.is_queued():
            self.logger.info("No build operation was executed: queue full, %d left" % len(self.queue))
        if not build:
            return False

        if existing_queue != 0 and existing_queue != len(self.waits):
            self.logger.warning("Building queue out of sync, waiting until %d manual actions are finished!" % existing_queue)
            return False

        for x in range(self.max_queue_len):
            result = self.get_next_building_action()
            if not result:
                self.logger.info("No build operation was executed %d left" % len(self.queue))
                return False
        return True
Ejemplo n.º 2
0
    def get_map(self):
        if self.last_fetch + (self.fetch_delay * 3600) > time.time():
            return
        self.last_fetch = time.time()
        res = self.wrapper.get_action(village_id=self.village_id, action="map")
        game_state = Extractor.game_state(res)
        self.map_data = Extractor.map_data(res)
        if self.map_data:
            for tile in self.map_data:
                data = tile['data']
                x = int(data['x'])
                y = int(data['y'])
                for lon in data['villages']:
                    try:
                        for lat in data['villages'][lon]:
                            coords = [x + int(lon), y + int(lat)]
                            entry = data['villages'][lon][lat]
                            if entry[0] == str(self.village_id):
                                self.my_location = coords

                            self.build_cache_entry(location=coords,
                                                   entry=entry)
                    except:
                        continue
                if not self.my_location:
                    self.my_location = [
                        game_state['village']['x'], game_state['village']['y']
                    ]
        if not self.map_data or not self.villages:
            return self.get_map_old(game_state=game_state)
        return True
Ejemplo n.º 3
0
    def update_totals(self):
        main_data = self.wrapper.get_action(action="overview",
                                            village_id=self.village_id)
        self.game_data = Extractor.game_state(main_data)
        if not self.logger:
            self.logger = logging.getLogger("Recruitment: %s" %
                                            self.game_data['village']['name'])
        self.troops = {}
        for u in Extractor.units_in_village(main_data):
            k, v = u
            self.troops[k] = v

        self.logger.debug("Units in village: %s" % str(self.troops))

        if not self.can_recruit:
            return

        get_all = "game.php?village=%s&screen=place&mode=units&display=units" % self.village_id
        result_all = self.wrapper.get_url(get_all)
        self.total_troops = {}
        for u in Extractor.units_in_total(result_all):
            k, v = u
            if k in self.total_troops:
                self.total_troops[k] = self.total_troops[k] + int(v)
            else:
                self.total_troops[k] = int(v)
        self.logger.debug("Village units total: %s" % str(self.total_troops))
Ejemplo n.º 4
0
    def attack(self, vid, troops=None):
        url = "game.php?village=%s&screen=place&target=%s" % (self.village_id,
                                                              vid)
        pre_attack = self.wrapper.get_url(url)
        pre_data = {}
        for u in Extractor.attack_form(pre_attack):
            k, v = u
            pre_data[k] = v
        if troops:
            pre_data.update(troops)
        else:
            pre_data.update(self.troopmanager.troops)

        if vid not in self.map.map_pos:
            return False

        x, y = self.map.map_pos[vid]
        post_data = {
            'x': x,
            'y': y,
            'target_type': 'coord',
            'attack': 'Aanvallen'
        }
        pre_data.update(post_data)

        confirm_url = "game.php?village=%s&screen=place&try=confirm" % self.village_id
        conf = self.wrapper.post_url(url=confirm_url, data=pre_data)
        if '<div class="error_box">' in conf.text:
            return False
        duration = Extractor.attack_duration(conf)
        self.logger.info("[Attack] %s -> %s duration %f.1 h" %
                         (self.village_id, vid, duration / 3600))

        confirm_data = {}
        for u in Extractor.attack_form(conf):
            k, v = u
            if k == "support":
                continue
            confirm_data[k] = v
        new_data = {
            'building': 'main',
            'h': self.wrapper.last_h,
        }
        confirm_data.update(new_data)
        result = self.wrapper.get_api_action(village_id=self.village_id,
                                             action="popup_command",
                                             params={"screen": "place"},
                                             data=confirm_data)

        return result
Ejemplo n.º 5
0
    def start_update(self, build=False, set_village_name=None):

        main_data = self.wrapper.get_action(village_id=self.village_id, action="main")
        if self.complete_actions(main_data.text):
            return self.start_update(build=build, set_village_name=set_village_name)
        self.costs = Extractor.building_data(main_data)
        self.game_state = Extractor.game_state(main_data)
        if self.resman:
            self.resman.update(self.game_state)
            if 'building' in self.resman.requested:
                # new run, remove request
                self.resman.requested['building'] = {}
        vname = self.game_state['village']['name']
        if set_village_name and vname != set_village_name:
            self.wrapper.post_url(
                url="game.php?village=%s&screen=main&action=change_name" % self.village_id,
                data={"name": set_village_name, "h": self.wrapper.last_h}
            )

        if not self.logger:
            self.logger = logging.getLogger("Builder: %s" % vname)
        self.logger.debug("Updating building levels")
        tmp = self.game_state['village']['buildings']
        for e in tmp:
            tmp[e] = int(tmp[e])
        self.levels = tmp
        existing_queue = self.get_existing_items(main_data)
        if existing_queue == 0:
            self.waits = []
            self.waits_building = []
        if self.is_queued():
            self.logger.info("No build operation was executed: queue full, %d left" % len(self.queue))
            return False
        if not build:
            return False

        if existing_queue != 0 and existing_queue != len(self.waits):
            self.logger.warning("Building queue out of sync, waiting until %d manual actions are finished!" %
                                existing_queue)
            return True

        for x in range(self.max_queue_len - len(self.waits)):
            result = self.get_next_building_action()
            if not result:
                self.logger.info("No build more operations where executed (%d current, %d left)" %
                                 (len(self.waits), len(self.queue)))
                return False
        return True
Ejemplo n.º 6
0
    def get_next_building_action(self, index=0):

        if index >= self.max_lookahead:
            self.logger.debug("Not building anything because insufficient resources")
            return False

        queue_check = self.is_queued()
        if queue_check:
            self.logger.debug("Not building because of queued items: %s" % self.waits)
            return False

        if self.resman and self.resman.in_need_of("pop"):
            build_data = 'farm:%d' % (int(self.levels['farm']) + 1)
            if len(self.queue) and "farm" not in [x.split(':')[0] for x in self.queue[0:self.max_lookahead]] \
                    and int(self.levels['farm']) != 30:
                self.queue.insert(0, build_data)
                self.logger.info("Adding farm in front of queue because low on pop")
                return self.get_next_building_action(0)

        if len(self.queue):
            entry = self.queue[index]
            entry, min_lvl = entry.split(':')
            min_lvl = int(min_lvl)
            if min_lvl <= self.levels[entry]:
                self.queue.pop(index)
                return self.get_next_building_action(index=index)
            if entry not in self.costs:
                self.logger.debug("Ignoring %s because not yet available" % entry)
                return self.get_next_building_action(index + 1)
            check = self.costs[entry]
            if 'max_level' in check and min_lvl > check['max_level']:
                self.logger.debug("Removing entry %s because max_level exceeded" % entry)
                self.queue.pop(index)
                return self.get_next_building_action(index=index)
            if check['can_build'] and self.has_enough(check) and 'build_link' in check:
                queue = self.put_wait(check['build_time'])
                self.logger.info("Building %s %d -> %d (finishes: %s)" %
                                 (entry, self.levels[entry], self.levels[entry]+1, self.readable_ts(queue)))
                self.wrapper.reporter.report(self.village_id, "TWB_BUILD",
                                             "Building %s %d -> %d (finishes: %s)" %
                                             (entry, self.levels[entry], self.levels[entry]+1, self.readable_ts(queue)))
                self.levels[entry] += 1
                result = self.wrapper.get_url(check['build_link'].replace('amp;', ''))
                self.game_state = Extractor.game_state(result)
                self.costs = Extractor.building_data(result)
                return True
            else:
                return self.get_next_building_action(index + 1)
Ejemplo n.º 7
0
    def attempt_recruit(self, amount):
        result = self.wrapper.get_action(action="snob", village_id=self.village_id)
        if '"id":"coin"' in result.text:
            self.using_coin_system = True
        game_data = Extractor.game_state(result)
        self.resman.update(game_data)

        can_recruit = re.search(r'(?s)</th><th>(\d+)</th></tr>\s*</table><br />', result.text)
        if not can_recruit or int(can_recruit.group(1)) == 0:
            nres = self.need_reserve(result.text)
            if nres > 0:
                self.logger.debug("Not enough resources available, still %d needed, attempting storage" % nres)
                cres = self.storage_item(result.text) if not self.using_coin_system else self.coin_item(result.text)
                if cres:
                    return self.attempt_recruit(amount)
                else:
                    self.is_incomplete = True
                    self.logger.debug("Not enough resources available")
                    return False
        self.is_incomplete = False
        r_num = int(can_recruit.group(1))
        if r_num == 0:
            self.logger.debug("No more snobs available, awaiting snob creating, snob death or village loss")
            return False
        train_snob_url = "game.php?village=%s&screen=snob&action=train&h=%s" % (self.village_id, self.wrapper.last_h)
        self.wrapper.get_url(train_snob_url)
        return True
Ejemplo n.º 8
0
 def attempt_research(self, unit_type, smith_data=None):
     if not smith_data:
         result = self.wrapper.get_action(village_id=self.village_id,
                                          action="smith")
         smith_data = Extractor.smith_data(result)
     if not smith_data or unit_type not in smith_data['available']:
         self.logger.warning(
             "Unit %s does not appear to be available or smith not built yet"
             % unit_type)
         return
     data = smith_data['available'][unit_type]
     if 'can_research' in data and data['can_research']:
         if 'research_error' in data and data['research_error']:
             return False
         if 'error_buildings' in data and data['error_buildings']:
             return False
         res = self.wrapper.get_api_action(village_id=self.village_id,
                                           action="research",
                                           params={"screen": "smith"},
                                           data={
                                               "tech_id": unit_type,
                                               "source": self.village_id,
                                               'h': self.wrapper.last_h
                                           })
         if res:
             self.logger.info("Started research of %s" % unit_type)
             self.resman.update(res['game_data'])
             return True
     self.logger.info("Research of %s not yet possible" % unit_type)
Ejemplo n.º 9
0
    def attempt_recruit(self, amount):
        result = self.wrapper.get_action(action="snob", village_id=self.village_id)
        game_data = Extractor.game_state(result)
        self.resman.update(game_data)
        nres = self.need_reserve(result.text)
        if nres > 0:
            self.logger.debug("Not enough resources available, still %d needed, attempting storage" % nres)
            cres = self.coin(result.text)
            if cres:
                return self.attempt_recruit(amount)
            else:
                self.is_incomplete = True
                self.logger.debug("Not enough resources available")
                return False
        self.is_incomplete = False
        can_recruit = re.search(r'(?s)<th>Er kan nog geproduceerd worden:</th>\s*<th>(\d+)<', result.text)
        if not can_recruit:
            self.logger.warning('Error fetching current snob number')
            return False
        r_num = int(can_recruit.group(1))
        if r_num == 0:
            self.logger.debug("No more snobs available, awaiting snob creating, snob death or village loss")
            return False

        return False
Ejemplo n.º 10
0
 def get_quests(self):
     result = Extractor.get_quests(self.wrapper.last_response)
     if result:
         qres = self.wrapper.get_api_action(action="quest_complete", village_id=self.village_id, params={'quest': result, 'skip': 'false'})
         if qres:
             self.logger.info("Completed quest: %s" % str(result))
             return True
     self.logger.debug("There where no completed quests")
     return False
Ejemplo n.º 11
0
    def attack(self, source, vid, troops=None):
        url = "game.php?village=%s&screen=place&target=%s" % (source, vid)
        pre_attack = self.wrapper.get_url(url)
        pre_data = {}
        for u in Extractor.attack_form(pre_attack):
            k, v = u
            pre_data[k] = v
        if troops:
            pre_data.update(troops)

        if vid not in self.game_map.map_pos:
            return False

        x, y = self.game_map.map_pos[vid]
        post_data = {
            'x': x,
            'y': y,
            'target_type': 'coord',
            'attack': 'Aanvallen'
        }
        pre_data.update(post_data)

        confirm_url = "game.php?village=%s&screen=place&try=confirm" % self.village_id
        conf = self.wrapper.post_url(url=confirm_url, data=pre_data)
        if '<div class="error_box">' in conf.text:
            return False
        duration = Extractor.attack_duration(conf)
        confirm_data = {}
        for u in Extractor.attack_form(conf):
            k, v = u
            if k == "support":
                continue
            confirm_data[k] = v
        new_data = {
            'building': 'main',
            'h': self.wrapper.last_h,
        }
        confirm_data.update(new_data)

        return confirm_data, duration
Ejemplo n.º 12
0
    def read(self, page=0, full_run=False):
        if not self.logger:
            self.logger = logging.getLogger("Reports")

        if len(self.last_reports) == 0:
            self.logger.info("First run, re-reading cache entries")
            self.last_reports = ReportCache.cache_grab()
            self.logger.info("Got %d reports from cache" %
                             len(self.last_reports))
        url = "game.php?village=%s&screen=report&mode=all&from=%d" % (
            self.village_id, page * 12)
        result = self.wrapper.get_url(url)
        self.game_state = Extractor.game_state(result)
        new = 0

        ids = Extractor.report_table(result)
        for report_id in ids:
            if report_id in self.last_reports:
                continue
            new += 1
            url = "game.php?village=%s&screen=report&mode=all&group_id=0&view=%s" % (
                self.village_id, report_id)
            data = self.wrapper.get_url(url)

            get_type = re.search(r'class="report_(\w+)', data.text)
            if get_type:
                report_type = get_type.group(1)
                if report_type == "ReportAttack":
                    self.attack_report(data.text, report_id)
                    continue

                else:
                    res = self.put(report_id, report_type=report_type)
                    self.last_reports[report_id] = res
        if new == 12 or full_run and page < 20:
            page += 1
            self.logger.debug(
                "%d new reports where added, also checking page %d" %
                (new, page))
            return self.read(page, full_run=full_run)
Ejemplo n.º 13
0
    def attempt_upgrade(self):
        self.logger.debug("Managing Upgrades")
        if self._research_wait > time.time():
            self.logger.debug("Smith still busy for %d seconds" %
                              int(self._research_wait - time.time()))
            return
        unit_levels = self.wanted_levels
        if not unit_levels:
            self.logger.debug("Not upgrading because nothing is requested")
            return
        result = self.wrapper.get_action(village_id=self.village_id,
                                         action="smith")
        smith_data = Extractor.smith_data(result)
        if not smith_data:
            self.logger.debug("Error reading smith data")
            return False
        for unit_type in unit_levels:
            if not smith_data or unit_type not in smith_data['available']:
                self.logger.warning(
                    "Unit %s does not appear to be available or smith not built yet"
                    % unit_type)
                continue
            wanted_level = unit_levels[unit_type]
            current_level = int(smith_data['available'][unit_type]['level'])
            data = smith_data['available'][unit_type]

            if current_level < wanted_level and 'can_research' in data and data[
                    'can_research']:
                if 'research_error' in data and data['research_error']:
                    self.logger.debug(
                        "Skipping research of %s because of research error" %
                        unit_type)
                    continue
                if 'error_buildings' in data and data['error_buildings']:
                    self.logger.debug(
                        "Skipping research of %s because of building error" %
                        unit_type)
                    continue

                attempt = self.attempt_research(unit_type,
                                                smith_data=smith_data)
                if attempt:
                    self.logger.info(
                        "Started smith upgrade of %s %d -> %d" %
                        (unit_type, current_level, current_level + 1))
                    self.wrapper.reporter.report(
                        self.village_id, "TWB_UPGRADE",
                        "Started smith upgrade of %s %d -> %d" %
                        (unit_type, current_level, current_level + 1))
                    return True
        return False
Ejemplo n.º 14
0
    def get_overview(self, config):
        result_get = self.wrapper.get_url("game.php?screen=overview_villages")
        result_villages = None
        if 'add_new_villages' in config['bot'] and config['bot'][
                'add_new_villages']:
            result_villages = Extractor.village_ids_from_overview(result_get)
            for found_vid in result_villages:
                if found_vid not in config['villages']:
                    print(
                        "Village %s was found but no config entry was found. Adding automatically"
                        % found_vid)
                    self.add_village(vid=found_vid)
                    return self.get_overview(self.config())

        return result_villages, result_get
Ejemplo n.º 15
0
 def attempt_upgrade(self, unit_levels):
     self.logger.debug("Managing Upgrades")
     result = self.wrapper.get_action(village_id=self.village_id,
                                      action="smith")
     smith_data = Extractor.smith_data(result)
     for unit_type in unit_levels:
         if not smith_data or unit_type not in smith_data['available']:
             self.logger.warning(
                 "Unit %s does not appear to be available or smith not built yet"
                 % unit_type)
             continue
         wanted_level = unit_levels[unit_type]
         current_level = int(smith_data['available'][unit_type]['level'])
         if current_level < wanted_level:
             attempt = self.attempt_research(unit_type,
                                             smith_data=smith_data)
             if attempt:
                 self.logger.info(
                     "Started smith upgrade of %s %d -> %d" %
                     (unit_type, current_level, current_level + 1))
                 return True
     return False
Ejemplo n.º 16
0
    def do_premium_stuff(self):
        gpl = self.get_plenty_off()
        if gpl and self.do_premium_trade:
            url = "game.php?village=%s&screen=market&mode=exchange" % self.village_id
            res = self.wrapper.get_url(url=url)
            data = Extractor.premium_data(res.text)
            if not data:
                self.logger.warning("Error reading premium data!")
            price_fetch = ["wood", "stone", "iron"]
            prices = {}
            for p in price_fetch:
                prices[p] = data['stock'] * data['rates']
            self.logger.info("Actual premium prices: %s" % prices)

            if gpl in prices and prices[gpl] * 1.1 < self.actual[gpl]:
                self.logger.info(
                    "Attempting trade of %d %s for premium point" %
                    (prices[gpl], gpl))
                self.wrapper.get_api_action(self.village_id,
                                            action="exchange_begin",
                                            params={'screen': "market"},
                                            data={"sell_%s" % gpl: "1"})
Ejemplo n.º 17
0
 def get_existing_items(self, text):
     waits = Extractor.active_building_queue(text)
     return waits
Ejemplo n.º 18
0
    def recruit(self,
                unit_type,
                amount=10,
                wait_for=False,
                building="barracks"):
        data = self.wrapper.get_action(action=building,
                                       village_id=self.village_id)

        existing = Extractor.active_recruit_queue(data)
        if existing:
            self.logger.warning(
                "Building Village %s %s recruitment queue out-of-sync" %
                (self.village_id, building))
            if not self.can_fix_queue:
                return True
            for entry in existing:
                self.cancel(building=building, id=entry)
                self.logger.info("Canceled recruit item %s on building %s" %
                                 (entry, building))
            return self.recruit(unit_type, amount, wait_for, building)

        self.recruit_data = Extractor.recruit_data(data)
        self.game_data = Extractor.game_state(data)
        self.logger.info("Attempting recruitment of %d %s" %
                         (amount, unit_type))

        if amount > self.max_batch_size:
            amount = self.max_batch_size

        if unit_type not in self.recruit_data:
            self.logger.warning(
                "Recruitment of %d %s failed because it is not researched" %
                (amount, unit_type))
            self.attempt_research(unit_type)
            return False

        resources = self.recruit_data[unit_type]
        if not resources:
            self.logger.warning(
                "Recruitment of %d %s failed because invalid identifier" %
                (amount, unit_type))
            return False
        if not resources['requirements_met']:
            self.logger.warning(
                "Recruitment of %d %s failed because it is not researched" %
                (amount, unit_type))
            self.attempt_research(unit_type)
            return False

        get_min = self.get_min_possible(resources)
        if get_min == 0:
            self.logger.info(
                "Recruitment of %d %s failed because of not enough resources" %
                (amount, unit_type))
            return False
        if get_min < amount:
            if wait_for:
                self.logger.warning(
                    "Recruitment of %d %s failed because of not enough resources"
                    % (amount, unit_type))
                return False
            if get_min > 0:
                self.logger.info(
                    "Recruitment of %d %s was set to %d because of resources" %
                    (amount, unit_type, get_min))
                amount = get_min
        result = self.wrapper.get_api_action(
            village_id=self.village_id,
            action="train",
            params={
                "screen": building,
                "mode": "train"
            },
            data={"units[%s]" % unit_type: str(amount)})
        if 'game_data' in result:
            self.resman.update(result['game_data'])
            self.wait_for[self.village_id][building] = int(
                time.time()) + (amount * int(resources['build_time']))
            # self.troops[unit_type] = str((int(self.troops[unit_type]) if unit_type in self.troops else 0) + amount)
            self.logger.info("Recruitment of %d %s started (%s idle till %d)" %
                             (amount, unit_type, building,
                              self.wait_for[self.village_id][building]))
            self.wrapper.reporter.report(
                self.village_id, "TWB_RECRUIT",
                "Recruitment of %d %s started (%s idle till %d)" %
                (amount, unit_type, building,
                 self.wait_for[self.village_id][building]))
            return True
        return False
Ejemplo n.º 19
0
    def attack_report(self, report, report_id):
        from_village = None
        from_player = None

        to_village = None
        to_player = None

        extra = {}

        losses = {}

        attacker = re.search(r'(?s)(<table id="attack_info_att".+?</table>)',
                             report)
        if attacker:
            attacker_data = re.search(r'data-player="(\d+)" data-id="(\d+)"',
                                      attacker.group(1))
            if attacker_data:
                from_player = attacker_data.group(1)
                from_village = attacker_data.group(2)
                units = re.search(
                    r'(?s)<table id="attack_info_att_units"(.+?)</table>',
                    attacker.group(1))
                if units:
                    sent_units = re.findall('(?s)<tr>(.+?)</tr>',
                                            units.group(1))
                    extra['units_sent'] = self.re_unit(
                        Extractor.units_in_total(sent_units[0]))
                    if len(sent_units) == 2:
                        extra['units_losses'] = self.re_unit(
                            Extractor.units_in_total(sent_units[1]))
                        if from_player == self.game_state['player']['id']:
                            losses = extra['units_losses']

        defender = re.search(r'(?s)(<table id="attack_info_def".+?</table>)',
                             report)
        if defender:
            defender_data = re.search(r'data-player="(\d+)" data-id="(\d+)"',
                                      defender.group(1))
            if defender_data:
                to_player = defender_data.group(1)
                to_village = defender_data.group(2)
                units = re.search(
                    r'(?s)<table id="attack_info_def_units"(.+?)</table>',
                    defender.group(1))
                if units:
                    def_units = re.findall('(?s)<tr>(.+?)</tr>',
                                           units.group(1))
                    extra['defence_units'] = self.re_unit(
                        Extractor.units_in_total(def_units[0]))
                    if len(def_units) == 2:
                        extra['defence_losses'] = self.re_unit(
                            Extractor.units_in_total(def_units[1]))
                        if to_player == self.game_state['player']['id']:
                            losses = extra['defence_losses']
        results = re.search(r'(?s)(<table id="attack_results".+?</table>)',
                            report)
        report = report.replace('<span class="grey">.</span>', '')
        if results:
            loot = {}
            for loot_entry in re.findall(
                    r'<span class="icon header (wood|stone|iron)".+?</span>(\d+)',
                    report):
                loot[loot_entry[0]] = loot_entry[1]
            extra['loot'] = loot
            self.logger.info("attack report %s -> %s" %
                             (from_village, to_village))

        scout_results = re.search(
            r'(?s)(<table id="attack_spy_resources".+?</table>)', report)
        if scout_results:
            self.logger.info("scout report %s -> %s" %
                             (from_village, to_village))
            scout_buildings = re.search(
                r'(?s)<input id="attack_spy_building_data" type="hidden" value="(.+?)"',
                report)
            if scout_buildings:
                raw = scout_buildings.group(1).replace('&quot;', '"')
                extra['buildings'] = self.re_building(json.loads(raw))
            loot = {}
            for loot_entry in re.findall(
                    r'<span class="icon header (wood|stone|iron)".+?</span>(\d+)',
                    report):
                loot[loot_entry[0]] = loot_entry[1]
            extra['resources'] = loot
            units_away = re.search(
                r'(?s)(<table id="attack_spy_away".+?</table>)', report)
            if units_away:
                data_away = self.re_unit(
                    Extractor.units_in_total(units_away.group(1)))
                extra['units_away'] = data_away

        attack_type = "scout" if scout_results and not results else "attack"
        res = self.put(report_id,
                       attack_type,
                       from_village,
                       to_village,
                       data=extra,
                       losses=losses)
        self.last_reports[report_id] = res
        return True
Ejemplo n.º 20
0
    def run(self, config=None, first_run=False):
        # setup and check if village still exists / is accessible
        self.config = config
        self.wrapper.delay = self.get_config(section="bot",
                                             parameter="delay_factor",
                                             default=1.0)
        if not self.village_id:
            data = self.wrapper.get_url("game.php?screen=overview&intro")
            if data:
                self.game_data = Extractor.game_state(data)
            if self.game_data:
                self.village_id = str(self.game_data['village']['id'])
                self.logger = logging.getLogger(
                    "Village %s" % self.game_data['village']['name'])
                self.logger.info("Read game state for village")
        else:
            data = self.wrapper.get_url("game.php?village=%s&screen=overview" %
                                        self.village_id)
            if data:
                self.game_data = Extractor.game_state(data)
                self.logger = logging.getLogger(
                    "Village %s" % self.game_data['village']['name'])
                self.logger.info("Read game state for village")
                self.wrapper.reporter.report(
                    self.village_id, "TWB_START",
                    "Starting run for village: %s" %
                    self.game_data['village']['name'])

        if not self.game_data:
            self.logger.error("Error reading game data for village %s" %
                              self.village_id)
            return None

        if self.village_set_name and self.game_data['village'][
                'name'] != self.village_set_name:
            self.logger.name = "Village %s" % self.village_set_name

        if not self.get_config(section="villages", parameter=self.village_id):
            return None
        if self.get_config(section="server",
                           parameter="server_on_twplus",
                           default=False):
            self.twp.run(
                world=self.get_config(section="server", parameter="world"))

        vdata = self.get_config(section="villages", parameter=self.village_id)
        if not self.get_village_config(
                self.village_id, parameter="managed", default=False):
            return False
        if not self.game_data:
            return False
        if not self.resman:
            self.resman = ResourceManager(wrapper=self.wrapper,
                                          village_id=self.village_id)

        self.resman.update(self.game_data)
        self.wrapper.reporter.report(self.village_id, "TWB_PRE_RESOURCE",
                                     str(self.resman.actual))

        if not self.rep_man:
            self.rep_man = ReportManager(wrapper=self.wrapper,
                                         village_id=self.village_id)
        self.rep_man.read(full_run=False)

        if not self.def_man:
            self.def_man = DefenceManager(wrapper=self.wrapper,
                                          village_id=self.village_id)
            self.def_man.map = self.area

        if not self.def_man.units:
            self.def_man.units = self.units

        last_attack = self.def_man.under_attack
        self.def_man.manage_flags_enabled = self.get_config(
            section="world", parameter="flags_enabled", default=False)
        self.def_man.support_factor = self.get_village_config(
            self.village_id, "support_others_factor", default=0.25)

        self.def_man.allow_support_send = self.get_village_config(
            self.village_id, parameter="support_others", default=False)
        self.def_man.allow_support_recv = self.get_village_config(
            self.village_id,
            parameter="request_support_on_attack",
            default=False)
        self.def_man.auto_evacuate = self.get_village_config(
            self.village_id,
            parameter="evacuate_fragile_units_on_attack",
            default=False)
        self.def_man.update(data.text,
                            with_defence=self.get_config(
                                section="units",
                                parameter="manage_defence",
                                default=False))

        disabled_units = []
        if not self.get_config(
                section="world", parameter="archers_enabled", default=True):
            disabled_units.extend(["archer", "marcher"])

        if not self.get_config(section="world",
                               parameter="building_destruction_enabled",
                               default=True):
            disabled_units.extend(["ram", "catapult"])

        if self.def_man.under_attack and not last_attack:
            self.logger.warning("Village under attack!")
            self.wrapper.reporter.report(
                self.village_id, "TWB_ATTACK",
                "Village: %s under attack" % self.game_data['village']['name'])

        # setup and check if village still exists / is accessible
        if self.get_config(section="world",
                           parameter="quests_enabled",
                           default=False):
            if self.get_quests():
                self.logger.info(
                    "There where completed quests, re-running function")
                self.wrapper.reporter.report(self.village_id, "TWB_QUEST",
                                             "Completed quest")
                return self.run(config=config)

        if not self.builder:
            self.builder = BuildingManager(wrapper=self.wrapper,
                                           village_id=self.village_id)
            self.builder.resman = self.resman
            # manage buildings (has to always run because recruit check depends on building levels)
        build_config = self.get_village_config(self.village_id,
                                               parameter="building",
                                               default=None)
        if not build_config:
            self.logger.warning(
                "Village %d does not have 'building' config override!" %
                self.village_id)
            build_config = self.get_config(section="building",
                                           parameter="default",
                                           default="purple_predator")
        new_queue = TemplateManager.get_template(category="builder",
                                                 template=build_config)
        if not self.builder.raw_template or self.builder.raw_template != new_queue:
            self.builder.queue = new_queue
            self.builder.raw_template = new_queue
            if not self.get_config(section="world",
                                   parameter="knight_enabled",
                                   default=False):
                self.builder.queue = [
                    x for x in self.builder.queue if "statue" not in x
                ]
        self.builder.max_lookahead = self.get_config(section="building",
                                                     parameter="max_lookahead",
                                                     default=2)
        self.builder.max_queue_len = self.get_config(
            section="building", parameter="max_queued_items", default=2)
        self.builder.start_update(build=self.get_config(
            section="building", parameter="manage_buildings", default=True),
                                  set_village_name=self.village_set_name)

        if not self.units:
            self.units = TroopManager(wrapper=self.wrapper,
                                      village_id=self.village_id)
            self.units.resman = self.resman
        self.units.max_batch_size = self.get_config(section="units",
                                                    parameter="batch_size",
                                                    default=25)

        # set village templates
        unit_config = self.get_village_config(self.village_id,
                                              parameter="units",
                                              default=None)
        if not unit_config:
            self.logger.warning(
                "Village %d does not have 'building' config override!" %
                self.village_id)
            unit_config = self.get_config(section="units",
                                          parameter="default",
                                          default="basic")
        self.units.template = TemplateManager.get_template(
            category="troops", template=unit_config, output_json=True)
        entry = self.units.get_template_action(self.builder.levels)

        if entry and self.units.wanted != entry["build"]:
            # update wanted units if template has changed
            self.logger.info("%s as wanted units for current village" %
                             (str(entry["build"])))
            self.units.wanted = entry["build"]

        if self.units.wanted_levels != {}:
            self.logger.info("%s as wanted upgrades for current village" %
                             (str(self.units.wanted_levels)))

        # get total amount of troops in village
        self.units.update_totals()
        if self.get_config(section="units", parameter="upgrade",
                           default=False) and self.units.wanted_levels != {}:
            self.units.attempt_upgrade()

        if self.get_village_config(
                self.village_id, parameter="snobs",
                default=None) and self.builder.levels['snob'] > 0:
            if not self.snobman:
                self.snobman = SnobManager(wrapper=self.wrapper,
                                           village_id=self.village_id)
                self.snobman.troop_manager = self.units
                self.snobman.resman = self.resman
            self.snobman.wanted = self.get_village_config(self.village_id,
                                                          parameter="snobs",
                                                          default=0)
            self.snobman.building_level = self.builder.get_level("snob")
            self.snobman.run()

        # recruitment management
        if self.get_config(section="units", parameter="recruit",
                           default=False):
            self.units.can_fix_queue = self.get_config(
                section="units",
                parameter="remove_manual_queued",
                default=False)
            self.units.randomize_unit_queue = self.get_config(
                section="units",
                parameter="randomize_unit_queue",
                default=True)
            # prioritize_building: will only recruit when builder has sufficient funds for queue items
            if self.get_village_config(
                    self.village_id,
                    parameter="prioritize_building",
                    default=False) and not self.resman.can_recruit():
                self.logger.info(
                    "Not recruiting because builder has insufficient funds")
            elif self.get_village_config(
                    self.village_id, parameter="prioritize_snob", default=False
            ) and self.snobman and self.snobman.can_snob and self.snobman.is_incomplete:
                self.logger.info(
                    "Not recruiting because snob has insufficient funds")
            else:
                # do a build run for every
                for building in self.units.wanted:
                    if not self.builder.get_level(building):
                        self.logger.debug(
                            "Recruit of %s will be ignored because building is not (yet) available"
                            % building)
                        continue
                    self.units.start_update(building)

        self.logger.debug("Current resources: %s" % str(self.resman.actual))
        self.logger.debug("Requested resources: %s" %
                          str(self.resman.requested))
        # attack management
        if self.units.can_attack:
            if not self.area:
                self.area = Map(wrapper=self.wrapper,
                                village_id=self.village_id)
            self.area.get_map()
            if self.area.villages:
                self.units.can_scout = self.get_config(
                    section="farms",
                    parameter="force_scout_if_available",
                    default=True)
                self.logger.info(
                    "%d villages from map cache, (your location: %s)" %
                    (len(self.area.villages), ':'.join(
                        [str(x) for x in self.area.my_location])))
                if not self.attack:
                    self.attack = AttackManager(wrapper=self.wrapper,
                                                village_id=self.village_id,
                                                troopmanager=self.units,
                                                map=self.area)
                    self.attack.repman = self.rep_man
                self.attack.target_high_points = self.get_config(
                    section="farms",
                    parameter="attack_higher_points",
                    default=False)
                self.attack.farm_minpoints = self.get_config(
                    section="farms", parameter="min_points", default=24)
                self.attack.farm_maxpoints = self.get_config(
                    section="farms", parameter="max_points", default=1080)

                self.attack.farm_default_wait = self.get_config(
                    section="farms",
                    parameter="default_away_time",
                    default=1200)
                self.attack.farm_high_prio_wait = self.get_config(
                    section="farms",
                    parameter="full_loot_away_time",
                    default=1800)
                self.attack.farm_low_prio_wait = self.get_config(
                    section="farms",
                    parameter="low_loot_away_time",
                    default=7200)
                if entry:
                    self.attack.template = entry['farm']
                if self.get_config(
                        section="farms", parameter="farm",
                        default=False) and not self.def_man.under_attack:
                    self.attack.extra_farm = self.get_village_config(
                        self.village_id,
                        parameter="additional_farms",
                        default=[])
                    self.attack.max_farms = self.get_config(
                        section="farms", parameter="max_farms", default=25)
                    self.attack.run()

        self.units.can_gather = self.get_village_config(
            self.village_id, parameter="gather_enabled", default=False)
        if not self.def_man or not self.def_man.under_attack:
            self.units.gather(selection=self.get_village_config(
                self.village_id, parameter="gather_selection", default=1),
                              disabled_units=disabled_units)
        # market management
        if self.get_config(section="market",
                           parameter="auto_trade",
                           default=False) and self.builder.get_level("market"):
            self.logger.info("Managing market")
            self.resman.trade_max_per_hour = self.get_config(
                section="market", parameter="trade_max_per_hour", default=1)
            self.resman.trade_max_duration = self.get_config(
                section="market", parameter="max_trade_duration", default=1)
            if self.get_config(section="market",
                               parameter="trade_multiplier",
                               default=False):
                self.resman.trade_bias = self.get_config(
                    section="market",
                    parameter="trade_multiplier_value",
                    default=1.0)
            self.resman.manage_market(drop_existing=self.get_config(
                section="market", parameter="auto_remove", default=True))

        res = self.wrapper.get_action(village_id=self.village_id,
                                      action="overview")
        self.game_data = Extractor.game_state(res)
        self.resman.update(self.game_data)
        if self.get_config(section="world",
                           parameter="trade_for_premium",
                           default=False) and self.get_village_config(
                               self.village_id,
                               parameter="trade_for_premium",
                               default=False):
            self.resman.do_premium_stuff()
        self.set_cache_vars()
        self.logger.info("Village cycle done, returning to overview")
        self.wrapper.reporter.report(self.village_id, "TWB_POST_RESOURCE",
                                     str(self.resman.actual))
        self.wrapper.reporter.add_data(self.village_id,
                                       data_type="village.resources",
                                       data=json.dumps(self.resman.actual))
        self.wrapper.reporter.add_data(self.village_id,
                                       data_type="village.buildings",
                                       data=json.dumps(self.builder.levels))
        self.wrapper.reporter.add_data(self.village_id,
                                       data_type="village.troops",
                                       data=json.dumps(
                                           self.units.total_troops))
        self.wrapper.reporter.add_data(self.village_id,
                                       data_type="village.config",
                                       data=json.dumps(vdata))
Ejemplo n.º 21
0
    def run(self, config=None):
        # setup and check if village still exists / is accessible
        self.config = config
        if not self.village_id:
            data = self.wrapper.get_url("game.php?screen=overview&intro")
            if data:
                self.game_data = Extractor.game_state(data)
            if self.game_data:
                self.village_id = str(self.game_data['village']['id'])
                self.logger = logging.getLogger("Village %s" % self.game_data['village']['name'])
                self.logger.info("Read game state for village")
        else:
            data = self.wrapper.get_url("game.php?village=%s&screen=overview" % self.village_id)
            if data:
                self.game_data = Extractor.game_state(data)
                self.logger = logging.getLogger("Village %s" % self.game_data['village']['name'])
                self.logger.info("Read game state for village")

        if str(self.village_id) not in self.config['villages']:
            return False

        self.twp.run(world=self.config['server']['world'])

        vdata = self.config['villages'][str(self.village_id)]
        if not vdata['managed']:
            return False
        if not self.game_data:
            return False

        # setup modules
        if not self.resman:
            self.resman = ResourceManager(wrapper=self.wrapper, village_id=self.village_id)

        self.resman.update(self.game_data)

        if not self.rep_man:
            self.rep_man = ReportManager(wrapper=self.wrapper, village_id=self.village_id)
        self.rep_man.read(full_run=False)

        if not self.def_man:
            self.def_man = DefenceManager(wrapper=self.wrapper, village_id=self.village_id)

        self.def_man.update(data.text)
        if self.def_man.under_attack:
            self.logger.warning("Village under attack!")

        # setup and check if village still exists / is accessible
        if self.config['world']['quests_enabled']:
            if self.get_quests():
                self.logger.info("There where completed quests, re-running function")
                return self.run()

        if not self.builder:
            self.builder = BuildingManager(wrapper=self.wrapper, village_id=self.village_id)
            self.builder.resman = self.resman
            # manage buildings (has to always run because recruit check depends on building levels)
            build_config = vdata['building'] if vdata['building'] else self.config['building']['default']

            self.builder.queue = TemplateManager.get_template(category="builder", template=build_config)
        self.builder.max_lookahead = self.config['building']['max_lookahead']
        self.builder.max_queue_len = self.config['building']['max_queued_items']
        self.builder.start_update(build=self.config['building']['manage_buildings'])

        if not self.units:
            self.units = TroopManager(wrapper=self.wrapper, village_id=self.village_id)
            self.units.max_batch_size = self.config['units']['batch_size']
            self.units.resman = self.resman

        # set village templates
        unit_config = vdata['units'] if vdata['units'] else self.config['units']['default']
        self.units.template = TemplateManager.get_template(category="troops", template=unit_config, output_json=True)
        entry = self.units.get_template_action(self.builder.levels)

        if entry and self.units.wanted != entry["build"]:
            # update wanted units if template has changed
            self.logger.info("%s as wanted units for current village" % (str(entry["build"])))
            self.units.wanted = entry["build"]

        if entry and 'upgrades' in entry and self.units.wanted_levels != entry['upgrades']:
            self.logger.info("%s as wanted upgrades for current village" % (str(entry["upgrades"])))
            self.units.wanted_levels = entry['upgrades']

        # get total amount of troops in village
        self.units.update_totals()
        if self.config['units']['upgrade'] and self.units.wanted_levels != {}:
            self.units.attempt_upgrade(self.units.wanted_levels)

        if 'snobs' in vdata and self.builder.levels['snob'] > 0:
            if not self.snobman:
                self.snobman = SnobManager(wrapper=self.wrapper, village_id=self.village_id)
                self.snobman.troop_manager = self.units
                self.snobman.resman = self.resman
            self.snobman.wanted = vdata['snobs']
            self.snobman.building_level = self.builder.levels['snob']
            self.snobman.run()

        if self.config['units']['recruit']:
            # prioritize_building: will only recruit when builder has sufficient funds for queue items
            if vdata['prioritize_building'] and not self.resman.can_recruit():
                self.logger.info("Not recruiting because builder has insufficient funds")
            elif vdata['prioritize_snob'] and self.snobman and self.snobman.can_snob and self.snobman.is_incomplete:
                self.logger.info("Not recruiting because snob has insufficient funds")
            else:
                # do a build run for every
                for building in self.units.wanted:
                    if building not in self.builder.levels or self.builder.levels[building] == 0:
                        self.logger.debug("Recruit of %s will be ignored because building is not available" % building)
                        continue
                    self.units.start_update(building)

        self.logger.debug("Current resources: %s" % str(self.resman.actual))
        self.logger.debug("Requested resources: %s" % str(self.resman.requested))

        if self.units.can_attack:
            if not self.area:
                self.area = Map(wrapper=self.wrapper, village_id=self.village_id)
                self.area.get_map()
            if self.area.villages:
                self.logger.info("%d villages from map cache, (your location: %s)" % (
                len(self.area.villages), ':'.join([str(x) for x in self.area.my_location])))
                if not self.attack:
                    self.attack = AttackManager(wrapper=self.wrapper, village_id=self.village_id,
                                                troopmanager=self.units, map=self.area)
                    self.attack.repman = self.rep_man
                if entry:
                    self.attack.template = entry['farm']
                if self.config['farms']['farm']:
                    self.attack.extra_farm = vdata['additional_farms']
                    self.attack.max_farms = self.config['farms']['max_farms']
                    self.attack.run()
        if not self.def_man.under_attack:
            self.units.gather()
        if self.config['market']['auto_trade'] and "market" in self.builder.levels and self.builder.levels["market"] > 0:
            self.logger.info("Managing market")
            self.resman.trade_max_per_hour = self.config['market']['trade_max_per_hour']
            self.resman.trade_max_duration = self.config['market']['max_trade_duration']
            if self.config['market']['trade_multiplier']:
                self.resman.trade_bias = self.config['market']['trade_multiplier_value']
            self.resman.manage_market(drop_existing=self.config['market']['auto_remove'])
        self.logger.info("Village cycle done, returning to overview")
        res = self.wrapper.get_action(village_id=self.village_id, action="overview")
        self.game_data = Extractor.game_state(res)
        self.resman.update(self.game_data)