Loading

Paste #psklsp44o

  1. #!/usr/bin/env python3
  2.  
  3. # Programme to calculate the best build strategy for a ressource with N given fields
  4.  
  5. import numpy as np
  6. import argparse
  7. import math
  8.  
  9. #parser = argparse.ArgumentParser(description='Show best build strategy for ressource fields')
  10. #parser.add_argument('integer', metavar='N fields', type=int, nargs=1, dest=n_fields, help='number of fields for that ress')
  11. #args = parser.parse_args()
  12.  
  13. # Storage needed without normal storage and 1st level 20 great storage:
  14. #needed_storage = 600000
  15. # Build slots dedicated to great storages beyond the 1st level 20 great storage:
  16.  
  17.  
  18. # Data for the great storage levels (w/o plus account)
  19. # level, time*4 [minutes], storage capacity
  20. holz = np.array(
  21.     [
  22.     [0,     0,      0,          0,      0,          0,              0,  0,  0],
  23.     [1,     40,     100,        50,     60,         25,             2,  1,  5],
  24.     [2,     65,     165,        85,     100,        60+50,          1,  1,  9],
  25.     [3,     110,    280,        140,    165,        6*60,           1,  2,  15],
  26.     [4,     185,    465,        235,    280,        24*60,          1,  2,  22],
  27.     [5,     310,    780,        390,    465,        48*60,          1,  2,  33],
  28.     [6,     520,    1300,       650,    780,        1*3600+36*60,   2,  3,  50],
  29.     [7,     870,    2170,       1085,   1300,       2*3600+25*60,   2,  4,  70],
  30.     [8,     1450,   3625,       1810,   2175,       4*3600+50*60,   2,  4,  100],
  31.     [9,     2420,   6050,       3025,   3630,       7*3600+10*60,   2,  5,  145],
  32.     [10,    4040,   10105,      5050,   6060,       10*3600+50*60,  2,  6,  200],
  33.     [11,    6750,   16870,      8435,   10125,      14*3600+25*60,  2,  7,  280],
  34.     [12,    11270,  28175,      14090,  16905,      18*3600,        2,  9,  375],
  35.     [13,    18820,  47055,      23525,  28230,      21*3600+35*60,  2,  11, 495],
  36.     [14,    31430,  78580,      39290,  47150,      26*3600+25*60,  2,  13, 635],
  37.     [15,    52490,  131230,     65615,  78740,      30*3600,        2,  15, 800],
  38.     [16,    87660,  219155,     109575, 131490,     36*3600,        3,  18, 1000],
  39.     [17,    146395, 365985,     182995, 219590,     48*3600,        3,  22, 1300],
  40.     [18,    244480, 611195,     305600, 366715,     60*3600,        3,  27, 1600],
  41.     [19,    408280, 1020695,    510350, 612420,     72*3600,        3,  32, 2000],
  42.     [20,    681825, 1704565,    852280, 1022740,    96*3600,        3,  38, 2500]
  43. ])
  44.    
  45. lehm = np.array(
  46.     [
  47.     [0, 0,  0,  0,  0,  0,  0,  0,  2],
  48.     [1, 80, 40, 80, 50, 20, 2,  1,  5],
  49.     [2, 135,    65, 135,    85, 1*60+40,    1,  1,  9],
  50.     [3, 225,    110,    225,    140,    5*60+30,    1,  2,  15],
  51.     [4, 375,    185,    375,    235,    22*60,  1,  2,  22],
  52.     [5, 620,    310,    620,    390,    44*60,  1,  2,  33],
  53.     [6, 1040,   520,    1040,   650,    1*3600+28*60,   2,  3,  50],
  54.     [7, 1735,   870,    1735,   1085,   2*3600+10*60,   2,  4,  70],
  55.     [8, 2900,   1450,   2900,   1810,   4*3600+25*60,   2,  4,  100],
  56.     [9, 4840,   2420,   4840,   3025,   6*3600+35*60,   2,  5,  145],
  57.     [10,    8080,   4040,   8080,   5050,   9*3600+55*60,   2,  6,  200],
  58.     [11,    13500,  6750,   13500,  8435,   13*3600+10*60,  2,  7,  280],
  59.     [12,    22540,  11270,  22540,  14090,  16*3600+30*60,  2,  9,  375],
  60.     [13,    37645,  18820,  37645,  23525,  19*3600+50*60,  2,  11, 495],
  61.     [14,    62865,  31430,  62865,  39290,  24*3600+10*60,  2,  13, 635],
  62.     [15,    104985, 52490,  104985, 65615,  27*3600+30*60,  2,  15, 800],
  63.     [16,    175320, 87660,  175320, 109575, 33*3600,    3,  18, 1000],
  64.     [17,    292790, 146395, 292790, 182995, 44*3600,    3,  22, 1300],
  65.     [18,    488955, 244480, 488955, 305600, 55*3600,    3,  27, 1600],
  66.     [19,    816555, 408280, 816555, 510350, 66*3600,    3,  32, 2000],
  67.     [20,    1363650,    681825, 1363650,    852280, 88*3600,    3,  38, 2500]
  68. ])
  69.    
  70. eisen = np.array([
  71.     [0, 0,  0,  0,  0,  0,  0,  0,  2],
  72.     [1, 100,    80, 30, 60, 30, 3,  1,  5],
  73.     [2, 165,    135,    50, 100,    2*60+15,    2,  1,  9],
  74.     [3, 280,    225,    85, 165,    7*60+30,    2,  2,  15],
  75.     [4, 465,    375,    140,    280,    30*60,  2,  2,  22],
  76.     [5, 780,    620,    235,    465,    1*3600, 2,  2,  33],
  77.     [6, 1300,   1040,   390,    780,    2*3600, 2,  3,  50],
  78.     [7, 2170,   1735,   650,    1300,   3*3600, 2,  4,  70],
  79.     [8, 3625,   2900,   1085,   2175,   6*3600, 2,  4,  100],
  80.     [9, 6050,   4840,   1815,   3630,   9*3600, 2,  5,  145],
  81.     [10,    10105,  8080,   3030,   6060,   13*3600+30*60,  2,  6,  200],
  82.     [11,    16870,  13500,  5060,   10125,  18*3600,    3,  7,  280],
  83.     [12,    28175,  22540,  8455,   16905,  22*3600+30*60,  3,  9,  375],
  84.     [13,    47055,  37645,  14115,  28230,  27*3600,    3,  11, 495],
  85.     [14,    78580,  62865,  23575,  47150,  33*3600,    3,  13, 635],
  86.     [15,    131230, 104985, 39370,  78740,  37*3600+30*60,  3,  15, 800],
  87.     [16,    219155, 175320, 65745,  131490, 45*3600,    3,  18, 1000],
  88.     [17,    365985, 292790, 109795, 219590, 60*3600,    3,  22, 1300],
  89.     [18,    611195, 488955, 183360, 366715, 75*3600,    3,  27, 1600],
  90.     [19,    1020695,    816555, 306210, 612420, 90*3600,    3,  32, 2000],
  91.     [20,    1704565,    1363650,    511370, 1022740,    120*3600,   3,  38, 2500]
  92. ])
  93.  
  94. korn = np.array([
  95.     [1, 75, 90, 85, 0,  20, 0,  1,  5],
  96.     [2, 125,    150,    140,    0,  1*60+30,    0,  1,  9],
  97.     [3, 210,    250,    235,    0,  5*60,   0,  2,  15],
  98.     [4, 350,    420,    395,    0,  20*60,  0,  2,  22],
  99.     [5, 585,    700,    660,    0,  40*60,  0,  2,  33],
  100.     [6, 975,    1170,   1105,   0,  1*3600+20*60,   1,  3,  50],
  101.     [7, 1625,   1950,   1845,   0,  2*3600, 1,  4,  70],
  102.     [8, 2715,   3260,   3080,   0,  4*3600, 1,  4,  100],
  103.     [9, 4535,   5445,   5140,   0,  6*3600, 1,  5,  145],
  104.     [10,    7575,   9095,   8590,   0,  9*3600, 1,  6,  200],
  105.     [11,    12655,  15185,  14340,  0,  12*3600,    1,  7,  280],
  106.     [12,    21130,  25360,  23950,  0,  15*3600,    1,  9,  375],
  107.     [13,    35290,  42350,  39995,  0,  18*3600,    1,  11, 495],
  108.     [14,    58935,  70720,  66795,  0,  22*3600,    1,  13, 635],
  109.     [15,    98420,  118105, 111545, 0,  25*3600,    1,  15, 800],
  110.     [16,    164365, 197240, 186280, 0,  30*3600,    2,  18, 1000],
  111.     [17,    274490, 329385, 311085, 0,  40*3600,    2,  22, 1300],
  112.     [18,    458395, 550075, 519515, 0,  50*3600,    2,  27, 1600],
  113.     [19,    765520, 918625, 867590, 0,  60*3600,    2,  32, 2000],
  114.     [20,    1278420,    1534105,    1448880,    0,  80*3600,    2,  38, 2500]
  115. ])
  116.  
  117. muehle = np.array([
  118.     [0, 0,  0,  0,  0,  0,  0,  0,  0],
  119.     [1, 500,    440,    380,    1240,   8*60,   3,  1,  5],
  120.     [2, 900,    790,    685,    2230,   25*60,  2,  1,  10],
  121.     [3, 1620,   1425,   1230,   4020,   55*60,  2,  2,  15],
  122.     [4, 2915,   2565,   2215,   7230,   2*3600+20*60,   2,  2,  20],
  123.     [5, 5250,   4620,   3990,   13015,  4*3600, 2,  2,  25]
  124. ])
  125.  
  126. baeckerei = np.array([
  127.     [0, 0,  0,  0,  0,  0,  0,  0,  0],
  128.     [1, 1200,   1480,   870,    1600,   13*60,  4,  1,  5],
  129.     [2, 2160,   2665,   1565,   2880,   30*60,  2,  1,  10],
  130.     [3, 3890,   4795,   2820,   5185,   1*3600, 2,  2,  15],
  131.     [4, 7000,   8630,   5075,   9330,   2*3600+25*60,   2,  2,  20],
  132.     [5, 12595,  15535,  9135,   16795,  4*3600+5*60,    2,  2,  25]
  133. ])
  134.  
  135. saegewerk = np.array([
  136.     [0, 0,  0,  0,  0,  0,  0,  0,  0],
  137.     [1, 520,    380,    290,    90, 8*60,   4,  1,  5],
  138.     [2, 935,    685,    520,    160,    25*60,  2,  1,  10],
  139.     [3, 1685,   1230,   940,    290,    55*60,  2,  2,  15],
  140.     [4, 3035,   2215,   1690,   525,    2*3600+20*60,   2,  2,  20],
  141.     [5, 5460,   3990,   3045,   945,    4*3600, 2,  2,  25]
  142. ])
  143.  
  144. lehmbrennerei = np.array([
  145.     [0, 0,  0,  0,  0,  0,  0,  0,  0],
  146.     [1, 440,    480,    320,    50, 8*60,   3,  1,  5],
  147.     [2, 790,    865,    575,    90, 25*60,  2,  1,  10],
  148.     [3, 1425,   1555,   1035,   160,    55*60,  2,  2,  15],
  149.     [4, 2565,   2800,   1865,   290,    2*3600+20*60,   2,  2,  20],
  150.     [5, 4620,   5040,   3360,   525,    4*3600, 2,  2,  25]
  151. ])
  152.  
  153. eisengiesserei = np.array([
  154.     [0, 0,  0,  0,  0,  0,  0,  0,  0],
  155.     [1, 200,    450,    510,    120,    8*60,   6,  1,  5],
  156.     [2, 360,    810,    920,    215,    25*60,  3,  1,  10],
  157.     [3, 650,    1460,   1650,   390,    55*60,  3,  2,  15],
  158.     [4, 1165,   2625,   2975,   700,    2*3600+20*60,   3,  2,  20],
  159.     [5, 2100,   4725,   5355,   1260,   4*3600, 3,  2,  25]
  160. ])
  161.  
  162. houseDict = {}
  163. houseDict['holz'] = holz
  164. houseDict['lehm'] = lehm
  165. houseDict['eisen']= eisen
  166. houseDict['korn'] = korn
  167. houseDict['saegewerk'] = saegewerk
  168. houseDict['lehmbrennerei'] = lehmbrennerei
  169. houseDict['eisengiesserei'] = eisengiesserei
  170. houseDict['muehle'] = muehle
  171. houseDict['baeckerei'] = baeckerei
  172.  
  173. MaxDict = {}
  174. MaxDict['holz']  = 10
  175. MaxDict['eisen'] = 10
  176. MaxDict['lehm']  = 10
  177. MaxDict['korn']  = 10
  178. MaxDict['saegewerk']      = 5
  179. MaxDict['lehmbrennerei']  = 5
  180. MaxDict['eisengiesserei'] = 5
  181. MaxDict['muehle']         = 5
  182. MaxDict['baeckerei']      = 5
  183.  
  184. BonusDict = {}
  185. BonusDict['holz']  = ['saegewerk']
  186. BonusDict['lehm']  = ['lehmbrennerei']
  187. BonusDict['eisen'] = ['eisengiesserei']
  188. BonusDict['korn']  = ['muehle','baeckerei']
  189.  
  190. Felder = ['holz','lehm','eisen','korn']
  191.  
  192. Index = {}
  193. Index['holz']  = 0
  194. Index['lehm']  = 1
  195. Index['eisen'] = 2
  196. Index['korn']  = 3
  197.  
  198. max_prod = np.zeros((4,))
  199. fortschritt = 0
  200. configs = {}
  201.  
  202. Requirements = {}
  203. Requirements[('saegewerk',1)]       = [('holz', 10)]
  204. Requirements[('lehmbrennerei',1)]   = [('lehm', 10)]
  205. Requirements[('eisengiesserei', 1)] = [('eisen', 10)]
  206. Requirements[('muehle', 1)]         = [('korn', 5)]
  207. Requirements[('baeckerei', 1)]      = [('muehle', 5), ('korn', 10)]
  208.  
  209. def get_build_cost(itemtype, level):
  210.     data = houseDict[itemtype]
  211.     if data is not None:
  212.         return data[level,1:5]
  213.     return np.zeros((4,))
  214.  
  215. def get_build_time(itemtype, level):
  216.     data = houseDict[itemtype]
  217.     if data is not None:
  218.         return data[level,5] / 2 # time is for HG1, we want for HG20
  219.     return 0
  220.  
  221. def get_production(item):
  222.     itemtype = item[0]
  223.     level    = item[1]
  224.     if itemtype not in Felder:
  225.         return 0
  226.     data = houseDict[itemtype]
  227.     return data[level, 8]
  228.  
  229. class RessVillage:
  230.     def __init__(self, levels, max_levels, production=np.zeros((4,)), buildtime=0, cost=np.zeros((4,)), build_sequence=[]):
  231.         self.levels = levels
  232.         self.max_levels = max_levels
  233.         self.production = production
  234.         self.buildtime = buildtime
  235.         self.cost = cost # holz, lehm, eisen, korn
  236.         self.build_sequence = build_sequence
  237.  
  238.     def get_bonus(self, fieldtype):
  239.         if fieldtype not in Felder:
  240.             return 0
  241.         haeuser = BonusDict[fieldtype]
  242.         bonus = 0
  243.         for haus in haeuser:
  244.             for item in self.levels:
  245.                 if item[0] == haus:
  246.                     bonus += 5 * item[1]
  247.         return bonus
  248.  
  249.     def get_total_production(self):
  250.         global fortschritt
  251.         production = np.zeros((4,))
  252.         bonus = {}
  253.         for fieldtype in Felder:
  254.             bonus[fieldtype] = self.get_bonus(fieldtype)
  255.        
  256.         for item in self.levels:
  257.             if item[0] not in Felder:
  258.                 continue
  259.             item_type  = item[0]
  260.             item_level = item[1]
  261.             prod = get_production(item)
  262.             bonus_prod = round(prod * bonus[item_type] / 100)
  263.             if fortschritt == 1:
  264.                 print("Item: ",item_type)
  265.                 print("Bonus: ",bonus)
  266.                 print("Level: ",self.levels)
  267.             prod = prod + bonus_prod
  268.             production[Index[item_type]] += prod
  269.  
  270.         return production
  271.    
  272.     def can_build_item(self, item):
  273.         if item not in Requirements:
  274.             return True
  275.        
  276.         requirements = Requirements[item]
  277.         ok = np.zeros(len(requirements))
  278.         for i,requirement in enumerate(requirements):
  279.             if requirement in self.levels:
  280.                 ok[i] = 1
  281.  
  282.         return ok.prod() == 1
  283.        
  284.    
  285.     def build_item(self, index):
  286.         item = self.levels[index]
  287.         item_type  = item[0]
  288.         item_level = item[1]
  289.        
  290.         if not self.can_build_item((item_type, item_level+1)):
  291.             return
  292.  
  293.         time       = get_build_time(item_type, item_level+1)
  294.         cost       = get_build_cost(item_type, item_level+1)
  295.         production = self.get_total_production() * time/3600 # production is in hours, build time in seconds
  296.         build_sequence = [item_type, item_level+1]
  297. #        print(item)
  298.        
  299.         newlevels = self.levels.copy()
  300.         newlevels[index]  = (item_type, item_level+1)
  301.         #print(newlevels)
  302.         #print(cost, self.cost)
  303.         build_sequence = self.build_sequence.copy()
  304.         build_sequence.append((item_type,item_level+1))
  305.         NewVillage = RessVillage(newlevels,
  306.                                 self.max_levels,
  307.                                 self.production + production,
  308.                                 self.buildtime + time,
  309.                                 self.cost + cost,
  310.                                 build_sequence
  311.                                 )
  312.         NewVillage.build()
  313.  
  314.     def build(self):
  315.         global max_prod, fortschritt, max_fortschritt, configs
  316.         self.levels.sort(reverse=False)
  317.        
  318.         # If we had the very same configuration already, but with a higher overall production,
  319.         # then that was the better way to reach that setup. We need not proceed then here anymore
  320.         # Otherwise: we found a possibly better way to reach the setup and we use this henceforth
  321.         # as the better solution.
  322.         str_levels = str(self.levels)
  323.         if str_levels not in configs:
  324.             configs[str_levels] = self.production
  325.  
  326.         else:
  327.             if configs[str_levels].sum() >= self.production.sum():
  328.                 return
  329.            
  330.             else:
  331.                 configs[str_levels] = self.production
  332.  
  333.         # For identical buildings (type AND level) we only need to test building one instead of each
  334.         old_items = []
  335.         num_max = 0
  336.         for index, item in enumerate(self.levels):
  337.             # No need to change the same thing twice
  338.             if item in old_items:
  339.                 continue
  340.  
  341.             level    = item[1]
  342.             itemtype = item[0]
  343.             #print(self.max_levels[itemtype])
  344.             # Don't try to increase the level of a building already at max level
  345.             if self.max_levels[itemtype] <= level:
  346.                 num_max += 1
  347.                 continue
  348.            
  349.             old_items.append(item)
  350.             self.build_item(index)
  351.        
  352.         if num_max == len(self.levels):
  353.             fortschritt += 1
  354.             #if fortschritt == 1:
  355.                 #print("Bau-Reihenfolge: ",self.build_sequence)
  356.                 #print("Produktion: ",self.get_total_production())
  357.                 #exit()
  358.             if self.production.sum() > max_prod.sum():
  359.                 max_prod = self.production
  360.                 print("Test %i / %i:" % (fortschritt, max_fortschritt))
  361.                 print("".join('{0:s}: {1:5d}; '.format(Felder[k],int(self.production[k])) for k in range(len(self.production)))) #,self.production)
  362.                 print(self.build_sequence)
  363.                 print("\n")
  364.  
  365. # initialize with worst case values
  366. field_levels = [1,1,1,1,1,1]
  367. MyList = []
  368. for item in field_levels:
  369.     MyList.append(('korn', item))
  370.  
  371. MyList.append(('muehle', 0))
  372. MyList.append(('baeckerei', 0))
  373.  
  374. left_levels = np.zeros((len(MyList),))
  375. for n,item in enumerate(MyList):
  376.     max_level = MaxDict[item[0]]
  377.     left_levels[n] = max_level - item[1]
  378.  
  379. max_fortschritt = left_levels.prod()    
  380.  
  381. Village = RessVillage(MyList, MaxDict, 0, 0, np.zeros((4,)), [])
  382. Village.build()

Comments