WOOD, CLAY, IRON, CROP = range(1, 5) class Resources: idx_to_attr = { WOOD: 'wood', CLAY: 'clay', IRON: 'iron', CROP: 'crop', } # speed=True means that we are not measuring a capacity but a production speed (e.g., crop per hour) def __init__(self, wood=None, clay=None, iron=None, crop=None, speed=False): self.wood = wood self.clay = clay self.iron = iron self.crop = crop self.speed = speed def __getitem__(self, index): name = self.idx_to_attr.get(index) if name is None: raise IndexError else: return getattr(self, name) def __setitem__(self, index, value): name = self.idx_to_attr.get(index) if name is None: raise IndexError else: setattr(self, name, value) def totuple(self): return self.wood, self.clay, self.iron, self.crop def __eq__(self, other): if isinstance(other, tuple): other = self.__class__(*other) return self.totuple() == other.totuple() def __add__(self, other): assert not self.speed and not other.speed t1 = self.totuple() t2 = other.totuple() return self.__class__(*[x+y for x, y in zip(t1, t2)]) def __sub__(self, other): assert not self.speed and not other.speed t1 = self.totuple() t2 = other.totuple() return self.__class__(*[x-y for x, y in zip(t1, t2)]) def __div__(self, other): # compute the time needed for each resource assert not self.speed and other.speed t1 = self.totuple() t2 = other.totuple() time = [] for qty, speed in zip(t1, t2): if qty < 0: # it's already enough time.append(0) else: time.append(float(qty)/speed) return max(time) def __repr__(self): return '%s(%d, %d, %d, %d)' % (self.__class__.__name__, self.wood, self.clay, self.iron, self.crop) class AbstractBot: def login(self): pass def select_town(self, id): pass def send_army(self, x, y, type, name='', **kwds): pass def send_merchant(self, x, y, resources): pass def build_settler(self, residence_id): pass def improve_build(self, id): pass class Town: def __init__(self, bot, id, dorf1): self.bot = bot self.id = id self.name = dorf1.name self.troops = dorf1.troops self.production = dorf1.production self.storage = dorf1.storage self.capacity = dorf1.capacity self.builds = {} # id --> (kind, level) self.kinds = {} # kind --> [(id1, level1), (id2, level2), ...] self._set_builds_dorf1(dorf1) def _set_builds_dorf1(self, dorf1): for kind, builds in dorf1.fields.iteritems(): for id, level in builds.iteritems(): self.builds[id] = (kind, level) self.kinds.setdefault(kind, []).append((id, level)) class SendArmyType: REINFORCE = '2' NORMAL = '3' RAID = '4' class Army(object): ALL = 9999999 (LEGIONNAIRE, PRAETORIAN, IMPERIAN, EQ_LEGATI, EQ_IMPERATORIS, EQ_CAESARIS, RAM, CATAPULT, SENATOR, SETTLER) = range(1, 11) def __init__(self, legionnaire = 0, praetorian = 0, imperian = 0, eq_legati = 0, eq_imperatoris = 0, eq_caesaris = 0, ram = 0, catapult = 0, senator = 0, settler = 0): self.troops = { self.LEGIONNAIRE: legionnaire, self.PRAETORIAN: praetorian, self.IMPERIAN: imperian, self.EQ_LEGATI: eq_legati, self.EQ_IMPERATORIS: eq_imperatoris, self.EQ_CAESARIS: eq_caesaris, self.RAM: ram, self.CATAPULT: catapult, self.SENATOR: senator, self.SETTLER: settler, } def __getattr__(self, attr): index = getattr(self.__class__, attr.upper()) return self.troops[index] def __setattr__(self, attr, value): index = getattr(self.__class__, attr.upper(), None) if index is not None: self.troops[index] = value return object.__setattr__(self, attr, value)