- #!/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()