#!/usr/bin/env python3 # Programme to calculate the best build strategy for a ressource with N given fields import numpy as np import argparse import math #parser = argparse.ArgumentParser(description='Show best build strategy for ressource fields') #parser.add_argument('integer', metavar='N fields', type=int, nargs=1, dest=n_fields, help='number of fields for that ress') #args = parser.parse_args() # Storage needed without normal storage and 1st level 20 great storage: #needed_storage = 600000 # Build slots dedicated to great storages beyond the 1st level 20 great storage: # Data for the great storage levels (w/o plus account) # level, time*4 [minutes], storage capacity holz = np.array( [ [0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 40, 100, 50, 60, 25, 2, 1, 5], [2, 65, 165, 85, 100, 60+50, 1, 1, 9], [3, 110, 280, 140, 165, 6*60, 1, 2, 15], [4, 185, 465, 235, 280, 24*60, 1, 2, 22], [5, 310, 780, 390, 465, 48*60, 1, 2, 33], [6, 520, 1300, 650, 780, 1*3600+36*60, 2, 3, 50], [7, 870, 2170, 1085, 1300, 2*3600+25*60, 2, 4, 70], [8, 1450, 3625, 1810, 2175, 4*3600+50*60, 2, 4, 100], [9, 2420, 6050, 3025, 3630, 7*3600+10*60, 2, 5, 145], [10, 4040, 10105, 5050, 6060, 10*3600+50*60, 2, 6, 200], [11, 6750, 16870, 8435, 10125, 14*3600+25*60, 2, 7, 280], [12, 11270, 28175, 14090, 16905, 18*3600, 2, 9, 375], [13, 18820, 47055, 23525, 28230, 21*3600+35*60, 2, 11, 495], [14, 31430, 78580, 39290, 47150, 26*3600+25*60, 2, 13, 635], [15, 52490, 131230, 65615, 78740, 30*3600, 2, 15, 800], [16, 87660, 219155, 109575, 131490, 36*3600, 3, 18, 1000], [17, 146395, 365985, 182995, 219590, 48*3600, 3, 22, 1300], [18, 244480, 611195, 305600, 366715, 60*3600, 3, 27, 1600], [19, 408280, 1020695, 510350, 612420, 72*3600, 3, 32, 2000], [20, 681825, 1704565, 852280, 1022740, 96*3600, 3, 38, 2500] ]) lehm = np.array( [ [0, 0, 0, 0, 0, 0, 0, 0, 2], [1, 80, 40, 80, 50, 20, 2, 1, 5], [2, 135, 65, 135, 85, 1*60+40, 1, 1, 9], [3, 225, 110, 225, 140, 5*60+30, 1, 2, 15], [4, 375, 185, 375, 235, 22*60, 1, 2, 22], [5, 620, 310, 620, 390, 44*60, 1, 2, 33], [6, 1040, 520, 1040, 650, 1*3600+28*60, 2, 3, 50], [7, 1735, 870, 1735, 1085, 2*3600+10*60, 2, 4, 70], [8, 2900, 1450, 2900, 1810, 4*3600+25*60, 2, 4, 100], [9, 4840, 2420, 4840, 3025, 6*3600+35*60, 2, 5, 145], [10, 8080, 4040, 8080, 5050, 9*3600+55*60, 2, 6, 200], [11, 13500, 6750, 13500, 8435, 13*3600+10*60, 2, 7, 280], [12, 22540, 11270, 22540, 14090, 16*3600+30*60, 2, 9, 375], [13, 37645, 18820, 37645, 23525, 19*3600+50*60, 2, 11, 495], [14, 62865, 31430, 62865, 39290, 24*3600+10*60, 2, 13, 635], [15, 104985, 52490, 104985, 65615, 27*3600+30*60, 2, 15, 800], [16, 175320, 87660, 175320, 109575, 33*3600, 3, 18, 1000], [17, 292790, 146395, 292790, 182995, 44*3600, 3, 22, 1300], [18, 488955, 244480, 488955, 305600, 55*3600, 3, 27, 1600], [19, 816555, 408280, 816555, 510350, 66*3600, 3, 32, 2000], [20, 1363650, 681825, 1363650, 852280, 88*3600, 3, 38, 2500] ]) eisen = np.array([ [0, 0, 0, 0, 0, 0, 0, 0, 2], [1, 100, 80, 30, 60, 30, 3, 1, 5], [2, 165, 135, 50, 100, 2*60+15, 2, 1, 9], [3, 280, 225, 85, 165, 7*60+30, 2, 2, 15], [4, 465, 375, 140, 280, 30*60, 2, 2, 22], [5, 780, 620, 235, 465, 1*3600, 2, 2, 33], [6, 1300, 1040, 390, 780, 2*3600, 2, 3, 50], [7, 2170, 1735, 650, 1300, 3*3600, 2, 4, 70], [8, 3625, 2900, 1085, 2175, 6*3600, 2, 4, 100], [9, 6050, 4840, 1815, 3630, 9*3600, 2, 5, 145], [10, 10105, 8080, 3030, 6060, 13*3600+30*60, 2, 6, 200], [11, 16870, 13500, 5060, 10125, 18*3600, 3, 7, 280], [12, 28175, 22540, 8455, 16905, 22*3600+30*60, 3, 9, 375], [13, 47055, 37645, 14115, 28230, 27*3600, 3, 11, 495], [14, 78580, 62865, 23575, 47150, 33*3600, 3, 13, 635], [15, 131230, 104985, 39370, 78740, 37*3600+30*60, 3, 15, 800], [16, 219155, 175320, 65745, 131490, 45*3600, 3, 18, 1000], [17, 365985, 292790, 109795, 219590, 60*3600, 3, 22, 1300], [18, 611195, 488955, 183360, 366715, 75*3600, 3, 27, 1600], [19, 1020695, 816555, 306210, 612420, 90*3600, 3, 32, 2000], [20, 1704565, 1363650, 511370, 1022740, 120*3600, 3, 38, 2500] ]) korn = np.array([ [1, 75, 90, 85, 0, 20, 0, 1, 5], [2, 125, 150, 140, 0, 1*60+30, 0, 1, 9], [3, 210, 250, 235, 0, 5*60, 0, 2, 15], [4, 350, 420, 395, 0, 20*60, 0, 2, 22], [5, 585, 700, 660, 0, 40*60, 0, 2, 33], [6, 975, 1170, 1105, 0, 1*3600+20*60, 1, 3, 50], [7, 1625, 1950, 1845, 0, 2*3600, 1, 4, 70], [8, 2715, 3260, 3080, 0, 4*3600, 1, 4, 100], [9, 4535, 5445, 5140, 0, 6*3600, 1, 5, 145], [10, 7575, 9095, 8590, 0, 9*3600, 1, 6, 200], [11, 12655, 15185, 14340, 0, 12*3600, 1, 7, 280], [12, 21130, 25360, 23950, 0, 15*3600, 1, 9, 375], [13, 35290, 42350, 39995, 0, 18*3600, 1, 11, 495], [14, 58935, 70720, 66795, 0, 22*3600, 1, 13, 635], [15, 98420, 118105, 111545, 0, 25*3600, 1, 15, 800], [16, 164365, 197240, 186280, 0, 30*3600, 2, 18, 1000], [17, 274490, 329385, 311085, 0, 40*3600, 2, 22, 1300], [18, 458395, 550075, 519515, 0, 50*3600, 2, 27, 1600], [19, 765520, 918625, 867590, 0, 60*3600, 2, 32, 2000], [20, 1278420, 1534105, 1448880, 0, 80*3600, 2, 38, 2500] ]) muehle = np.array([ [0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 500, 440, 380, 1240, 8*60, 3, 1, 5], [2, 900, 790, 685, 2230, 25*60, 2, 1, 10], [3, 1620, 1425, 1230, 4020, 55*60, 2, 2, 15], [4, 2915, 2565, 2215, 7230, 2*3600+20*60, 2, 2, 20], [5, 5250, 4620, 3990, 13015, 4*3600, 2, 2, 25] ]) baeckerei = np.array([ [0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1200, 1480, 870, 1600, 13*60, 4, 1, 5], [2, 2160, 2665, 1565, 2880, 30*60, 2, 1, 10], [3, 3890, 4795, 2820, 5185, 1*3600, 2, 2, 15], [4, 7000, 8630, 5075, 9330, 2*3600+25*60, 2, 2, 20], [5, 12595, 15535, 9135, 16795, 4*3600+5*60, 2, 2, 25] ]) saegewerk = np.array([ [0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 520, 380, 290, 90, 8*60, 4, 1, 5], [2, 935, 685, 520, 160, 25*60, 2, 1, 10], [3, 1685, 1230, 940, 290, 55*60, 2, 2, 15], [4, 3035, 2215, 1690, 525, 2*3600+20*60, 2, 2, 20], [5, 5460, 3990, 3045, 945, 4*3600, 2, 2, 25] ]) lehmbrennerei = np.array([ [0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 440, 480, 320, 50, 8*60, 3, 1, 5], [2, 790, 865, 575, 90, 25*60, 2, 1, 10], [3, 1425, 1555, 1035, 160, 55*60, 2, 2, 15], [4, 2565, 2800, 1865, 290, 2*3600+20*60, 2, 2, 20], [5, 4620, 5040, 3360, 525, 4*3600, 2, 2, 25] ]) eisengiesserei = np.array([ [0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 200, 450, 510, 120, 8*60, 6, 1, 5], [2, 360, 810, 920, 215, 25*60, 3, 1, 10], [3, 650, 1460, 1650, 390, 55*60, 3, 2, 15], [4, 1165, 2625, 2975, 700, 2*3600+20*60, 3, 2, 20], [5, 2100, 4725, 5355, 1260, 4*3600, 3, 2, 25] ]) houseDict = {} houseDict['holz'] = holz houseDict['lehm'] = lehm houseDict['eisen']= eisen houseDict['korn'] = korn houseDict['saegewerk'] = saegewerk houseDict['lehmbrennerei'] = lehmbrennerei houseDict['eisengiesserei'] = eisengiesserei houseDict['muehle'] = muehle houseDict['baeckerei'] = baeckerei MaxDict = {} MaxDict['holz'] = 10 MaxDict['eisen'] = 10 MaxDict['lehm'] = 10 MaxDict['korn'] = 10 MaxDict['saegewerk'] = 5 MaxDict['lehmbrennerei'] = 5 MaxDict['eisengiesserei'] = 5 MaxDict['muehle'] = 5 MaxDict['baeckerei'] = 5 BonusDict = {} BonusDict['holz'] = ['saegewerk'] BonusDict['lehm'] = ['lehmbrennerei'] BonusDict['eisen'] = ['eisengiesserei'] BonusDict['korn'] = ['muehle','baeckerei'] Felder = ['holz','lehm','eisen','korn'] Index = {} Index['holz'] = 0 Index['lehm'] = 1 Index['eisen'] = 2 Index['korn'] = 3 max_prod = np.zeros((4,)) fortschritt = 0 configs = {} Requirements = {} Requirements[('saegewerk',1)] = [('holz', 10)] Requirements[('lehmbrennerei',1)] = [('lehm', 10)] Requirements[('eisengiesserei', 1)] = [('eisen', 10)] Requirements[('muehle', 1)] = [('korn', 5)] Requirements[('baeckerei', 1)] = [('muehle', 5), ('korn', 10)] def get_build_cost(itemtype, level): data = houseDict[itemtype] if data is not None: return data[level,1:5] return np.zeros((4,)) def get_build_time(itemtype, level): data = houseDict[itemtype] if data is not None: return data[level,5] / 2 # time is for HG1, we want for HG20 return 0 def get_production(item): itemtype = item[0] level = item[1] if itemtype not in Felder: return 0 data = houseDict[itemtype] return data[level, 8] class RessVillage: def __init__(self, levels, max_levels, production=np.zeros((4,)), buildtime=0, cost=np.zeros((4,)), build_sequence=[]): self.levels = levels self.max_levels = max_levels self.production = production self.buildtime = buildtime self.cost = cost # holz, lehm, eisen, korn self.build_sequence = build_sequence def get_bonus(self, fieldtype): if fieldtype not in Felder: return 0 haeuser = BonusDict[fieldtype] bonus = 0 for haus in haeuser: for item in self.levels: if item[0] == haus: bonus += 5 * item[1] return bonus def get_total_production(self): global fortschritt production = np.zeros((4,)) bonus = {} for fieldtype in Felder: bonus[fieldtype] = self.get_bonus(fieldtype) for item in self.levels: if item[0] not in Felder: continue item_type = item[0] item_level = item[1] prod = get_production(item) bonus_prod = round(prod * bonus[item_type] / 100) if fortschritt == 1: print("Item: ",item_type) print("Bonus: ",bonus) print("Level: ",self.levels) prod = prod + bonus_prod production[Index[item_type]] += prod return production def can_build_item(self, item): if item not in Requirements: return True requirements = Requirements[item] ok = np.zeros(len(requirements)) for i,requirement in enumerate(requirements): if requirement in self.levels: ok[i] = 1 return ok.prod() == 1 def build_item(self, index): item = self.levels[index] item_type = item[0] item_level = item[1] if not self.can_build_item((item_type, item_level+1)): return time = get_build_time(item_type, item_level+1) cost = get_build_cost(item_type, item_level+1) production = self.get_total_production() * time/3600 # production is in hours, build time in seconds build_sequence = [item_type, item_level+1] # print(item) newlevels = self.levels.copy() newlevels[index] = (item_type, item_level+1) #print(newlevels) #print(cost, self.cost) build_sequence = self.build_sequence.copy() build_sequence.append((item_type,item_level+1)) NewVillage = RessVillage(newlevels, self.max_levels, self.production + production, self.buildtime + time, self.cost + cost, build_sequence ) NewVillage.build() def build(self): global max_prod, fortschritt, max_fortschritt, configs self.levels.sort(reverse=False) # If we had the very same configuration already, but with a higher overall production, # then that was the better way to reach that setup. We need not proceed then here anymore # Otherwise: we found a possibly better way to reach the setup and we use this henceforth # as the better solution. str_levels = str(self.levels) if str_levels not in configs: configs[str_levels] = self.production else: if configs[str_levels].sum() >= self.production.sum(): return else: configs[str_levels] = self.production # For identical buildings (type AND level) we only need to test building one instead of each old_items = [] num_max = 0 for index, item in enumerate(self.levels): # No need to change the same thing twice if item in old_items: continue level = item[1] itemtype = item[0] #print(self.max_levels[itemtype]) # Don't try to increase the level of a building already at max level if self.max_levels[itemtype] <= level: num_max += 1 continue old_items.append(item) self.build_item(index) if num_max == len(self.levels): fortschritt += 1 #if fortschritt == 1: #print("Bau-Reihenfolge: ",self.build_sequence) #print("Produktion: ",self.get_total_production()) #exit() if self.production.sum() > max_prod.sum(): max_prod = self.production print("Test %i / %i:" % (fortschritt, max_fortschritt)) print("".join('{0:s}: {1:5d}; '.format(Felder[k],int(self.production[k])) for k in range(len(self.production)))) #,self.production) print(self.build_sequence) print("\n") # initialize with worst case values field_levels = [1,1,1,1,1,1] MyList = [] for item in field_levels: MyList.append(('korn', item)) MyList.append(('muehle', 0)) MyList.append(('baeckerei', 0)) left_levels = np.zeros((len(MyList),)) for n,item in enumerate(MyList): max_level = MaxDict[item[0]] left_levels[n] = max_level - item[1] max_fortschritt = left_levels.prod() Village = RessVillage(MyList, MaxDict, 0, 0, np.zeros((4,)), []) Village.build()