jonbaer Posted May 2, 2017 Report Share Posted May 2, 2017 This would be an interesting game mode, the fastest to 300, it seems like the path to getting there gives a good benchmark for AI and ML learning. Any thoughts? 3 Quote Link to comment Share on other sites More sharing options...
Alekusu Posted May 2, 2017 Report Share Posted May 2, 2017 ahah it's a fun idea. On my next video I explain in detail how I did it (and I do it actually faster, 15:30!) Quote Link to comment Share on other sites More sharing options...
sphyrth Posted May 2, 2017 Report Share Posted May 2, 2017 I actually consider this a significantly great idea. Not only are people bound to learn fast build orders, they're also encouraged to experiment on their own. Quote Link to comment Share on other sites More sharing options...
jonbaer Posted May 2, 2017 Author Report Share Posted May 2, 2017 I guess what I am interested in is if you can reach it faster w/ one particular civ over another and what that ratio % is. I feel like I am getting faster at it but have not timed it so that would be nice to see. I wish something like that was a build to be a bit more portable (0ad engine + 1 random map + 1 civ) @ smaller download (for research). Post back here any progress. Quote Link to comment Share on other sites More sharing options...
jonbaer Posted May 5, 2017 Author Report Share Posted May 5, 2017 For those following this thread ... Quote Link to comment Share on other sites More sharing options...
causative Posted May 5, 2017 Report Share Posted May 5, 2017 I was able to reach 300 pop in 12:22 (from low resources) with Britons using Fertility Festival and making only women. 12:22 is the time at which my population counter read 300/300; the last women finished producing around 13:15. 2 Quote Link to comment Share on other sites More sharing options...
mapkoc Posted May 13, 2017 Report Share Posted May 13, 2017 Dizaka and temple did it in less than 12 using ptos. Try them. Quote Link to comment Share on other sites More sharing options...
fatherbushido Posted May 19, 2017 Report Share Posted May 19, 2017 There was something of the same kind 'planned' "first to reach 10 000 metal" (or any number of a ress). Quote Link to comment Share on other sites More sharing options...
borg- Posted May 20, 2017 Report Share Posted May 20, 2017 Let's start the challenge The time can still be improved, this was my first attempt and the map was bad. 1 Quote Link to comment Share on other sites More sharing options...
sphyrth Posted May 20, 2017 Report Share Posted May 20, 2017 Next thing you know someone would create rules like: "No women allowed!" or something. Quote Link to comment Share on other sites More sharing options...
Lion.Kanzen Posted May 20, 2017 Report Share Posted May 20, 2017 To no sound sexist can be nice "no men allowed" 2 Quote Link to comment Share on other sites More sharing options...
jonbaer Posted May 21, 2017 Author Report Share Posted May 21, 2017 I was originally thinking of this game mode as a challenge to some reinforcement learning algorithms and to examine what the build order was w/ a static map (in other words the layout and the resource locations were always the same). I came across another project similar to what I wanted to create ... https://github.com/santiontanon/microrts ... it is the bare minimum for figuring such a task but of course they based it on the Starcraft conception of a smaller resource pool (there are only 2 in Starcraft right?) ... I think if the map changes and maps are random there can never really be a benchmark. Also (and I think many can agree) is that 300 isn't always 300 strong. So I think looking at not just time but time and strength would be good measurement. Quote Link to comment Share on other sites More sharing options...
jonbaer Posted May 22, 2017 Author Report Share Posted May 22, 2017 I found some interesting metrics in regards to build order optimization over the weekend, question in pertaining to 0ad (as most of the research papers reflect StarCraft to a large extent) is how to view a more common build order benchmark within the game, for example most SC/SC2 orders are grouped to strategies and you can find them all over labelled as such (one example): 7 Roach Rush / Expand / Lair6 Drone until 1010 Double Extractor Trick12 Overlord12 Spawning Pool11 Drone x516 Extractor (Put 3 Drones inside immediately upon completion)15 Drone16 Queen (Inject Hatchery as soon as she pops out)18 Overlord18 Drone x220 Roach Warren19 Overlord19 Roach x733 Drone34 Overlord34 Hatchery (Expand)33 Drone x336 Lair36 Extractor Can something similar be extracted from commands.txt or are there current tools outside of the game which do this? Or are there plans to maybe adding these metric types to the new charts section? Does anyone else here study this type of field/research? Quote Link to comment Share on other sites More sharing options...
leper Posted May 22, 2017 Report Share Posted May 22, 2017 Hacky solution, yes one could merge most of these things, also just doing this in awk might be nicer. The final sed is because some commands (training siege) seem to list the entities this applies to last instead of first (which doesn't matter, but makes this a bit longer than it should be. I'm not sure why you have numbers, then xN in that list, nor do I really care, but yes one can figure that out from a commands.txt file. For a proper solution one would also need to handle cancellations, and possibly parse the json for each command to make sure the order doesn't matter. grep "cmd 1" commands.txt | grep "train" | sed 's/^.*units\///' | sed 's/","count":/ /' | sed 's/}$//' | sed 's/,"entities.*$//' 1 Quote Link to comment Share on other sites More sharing options...
Zeta1127 Posted May 22, 2017 Report Share Posted May 22, 2017 The numbers are worker count. Quote Link to comment Share on other sites More sharing options...
jonbaer Posted May 22, 2017 Author Report Share Posted May 22, 2017 The interesting metric I saw was over a "DBD" for anyone interested ... Quote Link to comment Share on other sites More sharing options...
causative Posted May 22, 2017 Report Share Posted May 22, 2017 I wrote this a long time ago to try to automatically determine fast builds for britons. It's an approximate simulator of playing britons, with functions to evaluate and alter the build order. Note that it's for a19 IIRC so it doesn't handle batch sizes except 1 and 5. Spoiler WOMAN_FARM = 0.38 WOMAN_BERRY = 0.86 WOMAN_WOODCUT = 0.5 MAN_WOODCUT = 0.53 MAN_MINING = 0.45 WOMAN_CHICKEN = 0.66 CAVALRY_CHICKEN = 3.6 CAVALRY_CORRAL_NET = 1.6 TRADE = 0.3 # varies though SUPERTRADE = 0.6 # long distance trade class State: def __init__(self): self.wood = 300 self.food = 300 self.stone = 300 self.metal = 300 self.idleWomen = 4 self.idleMen = 4 self.idleTraders = 0 self.idleHorse = 1 self.champions = 0 self.pop = 9 self.time = 0 self.maxPop = 20 self.idleBarracks = 0 # barracks not producing anything self.idleCC = 1 self.idleStorehouse = 0 self.idleFarmstead = 0 self.idleBlacksmith = 0 self.idleCastle = 0 self.idleCorral = 0 self.idleMarket = 0 self.fields = 0 # total number of fields self.sheepfood = 0 # food from sheep we have (100 per sheep) self.makeSheep = True # make sheep continuously when necessary self.huntfood = 600 # food available for hunting self.berryfood = 980 # food available for gathering self.treewood = 600 # wood available for chopping (without making another storehouse) self.berries = [0,0] # [women on berries, men on berries] self.farm = [0,0] self.chop = [0,0] self.mineStone = [0,0] self.mineMetal = [0,0] self.hunt = 0 # horsemen hunting self.butcher = 0 # horsemen butchering self.timers = [] # each timer is represented by [t, k, u, n]: time remaining until, the kind of timer it is ("barracks" "cc" "trader" "blacksmith" "corral" "castle" "construction"), the unit or upgrade currently being produced, and the number of that unit being produced. self.tradeSetting = "metal" # which resource to get from trade self.tradeTime = 76 self.tradeProfit = 38 self.upgrades = [] # a list of current upgrades, given as strings self.pendingActions = [] # actions that can't start yet (insufficient resources, or production facility is busy). Each time step we check if any action on this list can be started. If it can, we start it. def woodPS(self, isMan): # wood per second if isMan: w = 0.63 else: w = 0.53 if "up_wood2" in self.upgrades: w *= 1.20 elif "up_wood1" in self.upgrades: w *= 1.10 return w def berryPS(self, isMan): # berries per second w = 0.86 if isMan: w *= 0.7 if "up_gather" in self.upgrades: w *= 1.45 return w def farmPS(self, isMan): #farming per second w = 0.38 if isMan: w *= 0.7 if "up_farm3" in self.upgrades: w *= 1.55 elif "up_farm2" in self.upgrades: w *= 1.30 elif "up_farm1" in self.upgrades: w *= 1.15 return w def metalPS(self, isMan): # metal per second w = 0.45 if not isMan: w *= 0.7 if "up_metal2" in self.upgrades: w *= 1.30 elif "up_metal1" in self.upgrades: w *= 1.15 return w def stonePS(self, isMan): # stone per second w = 0.45 if not isMan: w *= 0.7 if "up_stone2" in self.upgrades: w *= 1.30 elif "up_stone1" in self.upgrades: w *= 1.15 return w def huntPS(self): # hunt with cavalry return 3.0 def sheepPS(self): # butcher sheep with cavalry # this assumes you have a sheep - not a net rate return 3.6 def step(self): # advance game time by 1 second # get resources berryget = self.berries[0] * self.berryPS(False) + self.berries[1] * self.berryPS(True) self.berryfood -= berryget if self.berryfood < 0: berryget += self.berryfood self.berryfood = 0 self.idleWomen += self.berries[0] self.idleMen += self.berries[1] self.berries = [0,0] self.food += berryget huntget = self.hunt * self.huntPS() self.huntfood -= huntget if self.huntfood < 0: huntget += self.huntfood self.huntfood = 0 self.idleHorse += self.hunt self.hunt = 0 self.food += huntget sheepget = self.butcher * self.sheepPS() self.sheepfood -= sheepget if self.sheepfood < 0: sheepget += sheepfood self.sheepfood = 0 #self.idleHorse += self.butcher # don't automatically idle, we're still waiting for more sheep to get produced self.food += sheepget if self.makeSheep and (self.sheepfood + self.pendingActions.count(["sheep"])*100) < 150*self.butcher: self.pendingActions = [["sheep"]] + self.pendingActions self.food += self.farm[0] * self.farmPS(False) + self.farm[1] * self.farmPS(True) woodget = self.chop[0] * self.woodPS(False) + self.chop[1] * self.woodPS(True) self.treewood -= woodget if self.treewood < 0: woodget += self.treewood self.treewood = 0 self.wood += woodget self.stone += self.mineStone[0] * self.stonePS(False) + self.mineStone[1] * self.stonePS(True) self.metal += self.mineMetal[0] * self.metalPS(False) + self.mineMetal[1] * self.metalPS(True) # decrease timers idleTraders = 0 newTimers=[] for timer in self.timers: [t, k, u, n] = timer[:4] if t == 0: # idle continue timer[0] -= 1 if timer[0] == 0: #print "Timer", timer, "Time",self.time # produce units if u == "man": self.idleMen += n elif u == "champ": self.champions += n elif u == "woman": self.idleWomen += n elif u == "trader": # production of trader at market newTimers.append([self.tradeTime, "trader", "trade", 1]) elif u == "horse": # worker cavalry self.idleHorse += n elif u == "trade": # countdown until trader reaches market timer[0] = self.tradeTime newTimers.append(timer) # keep trading if self.tradeSetting == "food": self.food += self.tradeProfit elif self.tradeSetting == "wood": self.wood += self.tradeProfit elif self.tradeSetting == "stone": self.stone += self.tradeProfit elif self.tradeSetting == "metal": self.metal += self.tradeProfit elif u == "sheep": self.sheepfood += n * 100 if k == "barracks": self.idleBarracks += 1 elif k == "cc": self.idleCC += 1 elif k == "corral": self.idleCorral += 1 elif k == "storehouse": self.idleStorehouse += 1 elif k == "farmstead": self.idleFarmstead += 1 elif k == "blacksmith": self.idleBlacksmith += 1 elif k == "castle": self.idleCastle += 1 elif k == "market" or u == "market": self.idleMarket += 1 elif k == "construction": (t, k, u, n, men, women) = timer self.idleMen += men self.idleWomen += women if u == "barracks": self.idleBarracks += 1 self.maxPop += 4 elif u == "cc": self.idleCC += 1 self.maxPop += 20 elif u == "corral": self.idleCorral += 1 elif u == "field": self.fields += 1 elif u == "storehouse": self.idleStorehouse += 1 self.maxPop += 2 self.treewood += 5000 elif u == "farmstead": self.idleFarmstead += 1 self.maxPop += 2 elif u == "blacksmith": self.idleBlacksmith += 1 self.maxPop += 4 elif u == "castle": self.idleCastle += 1 self.maxPop += 12 elif u == "market": self.idleMarket += 1 self.maxPop += 12 elif u == "house": self.maxPop += 5 elif u[:3] == "up_": self.upgrades.append(u) idleAttr = "idle" + k[0].upper() + k[1:] idleAttrVal = getattr(self, idleAttr) setattr(self, idleAttr, idleAttrVal + 1) else: # if timer[0] != 0 newTimers.append(timer) self.timers = newTimers # new traders? while idleTraders > 0: self.traders.append([self.tradeTime, "trade", 1]) idleTraders -= 1 moreActions = True # perform any actions that are possible to perform done = False while not done: if len(self.pendingActions) == 0: break else: a = self.pendingActions[0] result = self.tryAction(a) if result: #print "Action", a, "Time",self.time self.pendingActions = self.pendingActions[1:] else: done = True def tryAction(self, a): # do we have enough resources? actionName = a[0] num = 1 if actionName in ["man","woman","horse","champ", "trader", "sheep"]: num = a[1] # if actionName == "wait": _, f, w, s, m = a if self.food < f or self.wood < w or self.stone < s or self.metal < m: return False return True if actionName in actionCosts: [food, wood, stone, metal] = actionCosts[actionName] #if actionName == "storehouse": # print actionName, a[1], a[2], wood, self.wood food *= num wood *= num stone *= num metal *= num ok = True if food > self.food: ok = False if wood > self.wood: ok = False if stone > self.stone: ok = False if metal > self.metal: ok = False if not ok: return False if actionName in ["man","woman","horse","champ", "trader"]: if self.pop + num > self.maxPop: return False if actionName in ["man", "horse", "champ"]: (_, _, fromBarracks) = a if actionName == "man": timeout = 10 if num == 5: timeout = 37 elif actionName == "horse": timeout = 12 if num == 5: timeout = 44 else: # champion (specifically, celtic chariot) if "III" not in self.upgrades: return False timeout = 15 if num == 5: timeout = 55 if fromBarracks: if self.idleBarracks == 0: return False self.timers.append([timeout, "barracks", actionName, num]) self.idleBarracks -= 1 if not fromBarracks: if actionName == "champ": if self.idleCastle == 0: return False self.timers.append([timeout, "castle", "champ", num]) self.idleCastle -= 1 else: if self.idleCC == 0: return False self.timers.append([timeout, "cc", actionName, num]) self.idleCC -= 1 elif actionName == "woman": if self.idleCC == 0: return False timeout = 8 if num == 5: timeout = 29 self.timers.append([timeout, "cc", "woman", num]) self.idleCC -= 1 elif actionName == "trader": if self.idleMarket == 0: return False timeout = 15 if num == 5: timeout = 55 self.timers.append([timeout, "market", "trader", num]) self.idleMarket -= 1 self.pop += num elif actionName == "sheep": timeout = 35 if "up_sheep" in self.upgrades: timeout = 27 if self.idleCorral == 0: return False # don't train sheep 5 at a time self.timers.append([timeout, "corral", "sheep", 1]) self.idleCorral -= 1 elif actionName in ["house", "storehouse", "farmstead", "cc", "corral", "barracks", "temple", "market", "blacksmith", "tower", "field", "castle", "mill"]: if actionName in ["cc", "temple", "market", "blacksmith", "tower"] and not "II" in self.upgrades: return False if actionName in ["castle", "mill"] and not "III" in self.upgrades: return False _, men, women = a # apply all idle men and women to the task if self.idleMen < men or self.idleWomen < women: return False workers = men + women # add 10 seconds for walk time to build site self.timers.append([buildTime(delay[actionName], workers) + 10, "construction", actionName, 1, men, women]) self.idleMen -= men self.idleWomen -= women elif actionName in ["chop", "farm", "stone", "metal", "berries"]: (_, men, women) = a if men > self.idleMen or women > self.idleWomen: return False if actionName == "farm": if self.fields*5 < self.farm[0] + self.farm[1] + men + women: return False act = self.gatherActivity(actionName) #print actionName, "current:", act, "new: [", men, women, "]", "idle: [", self.idleMen, self.idleWomen, "]" act[0] += men act[1] += women self.idleMen -= men self.idleWomen -= women elif actionName == "butcher" or actionName == "hunt": (_, horse) = a if horse > self.idleHorse: return False if actionName == "butcher": self.butcher += horse else: self.hunt += horse self.idleHorse -= horse elif actionName == "un_butcher" or actionName == "un_hunt": (_, horse) = a if actionName == "un_butcher": if self.butcher < horse: return False self.butcher -= horse elif actionName == "hunt": if self.hunt < horse: return False self.hunt -= horse self.idleHorse += horse elif actionName[:3] == "un_": if actionName == "un_": pass (_, men, women) = a activity = actionName[3:] act = self.gatherActivity(activity) if act[0] < men or act[1] < women: return False act[0] -= men act[1] -= women self.idleMen += men self.idleWomen += women elif actionName[:3] == "up_": if actionName in ["up_wood2", "up_stone2", "up_metal2", "up_farm2", "III"] and not "II" in self.upgrades: return False if actionName in ["up_farm3", "up_trade2"] and not "III" in self.upgrades: return False building = actionBuilding[actionName] idleAttr = "idle" + building[0].upper() + building[1:] idleAttrVal = getattr(self,idleAttr) if idleAttrVal == 0: return False self.timers.append([delay[actionName], building, actionName, 1]) setattr(self, idleAttr, idleAttrVal - 1) if actionName in actionCosts: [food, wood, stone, metal] = actionCosts[actionName] food *= num wood *= num stone *= num metal *= num self.food -= food self.wood -= wood self.stone -= stone self.metal -= metal return True def gatherActivity(self,gatherName): if gatherName == "chop": return self.chop elif gatherName == "farm": return self.farm elif gatherName == "stone": return self.stone elif gatherName == "metal": return self.metal elif gatherName == "berries": return self.berries #elif gatherName == "butcher": # return self.butcher #elif gatherName == "hunt": # return self.hunt # return the time to complete all actions # other than sheep production def completeActions(self, maxTime = 200): self.time = 0 idleCCturns = 0 idleWorkerturns = 0 idleHorseturns = 0 while len(self.pendingActions) > 0 and self.time < maxTime: if self.pendingActions.count(["sheep"]) == len(self.pendingActions): break self.step() self.time += 1 output = "" idleCCturns += self.idleCC if self.idleCC > 0: output += "idleCC food=" + str(self.food) + " pop=" + str(self.pop) + " maxpop=" + str(self.maxPop) + "\n" idleWorkerturns += self.idleMen + self.idleWomen if self.idleMen + self.idleWomen > 0: output += "idleWorkers " + str(self.idleMen) + ", " + str(self.idleWomen) + "\n" if self.idleHorse > 0: output += "idleHorse " + str(self.idleHorse) + "\n" idleHorseturns += self.idleHorse if output != "": print "turn",self.time,"actionsleft",self.pendingActions print output.strip() print "idle CC-seconds:",idleCCturns print "idle worker-seconds:",idleWorkerturns print "idle horse-seconds:",idleHorseturns print self print "Total turns:",self.time # evaluate actions # returns a tuple (milturns, idleworker) # milturns is the number of turns needed to # achieve the given milpower (or maxTime, whichever is less) # idleworker is the total number of idle worker-seconds # at which milturns is achieved (or maxTime reached) # milpower is champs + citSoldiers / 4 # (may be adjusted later on for upgrades # or presence of boudicca) def evalActions(self, milpower, maxTime): self.time = 0 idleWorker = 0 while len(self.pendingActions) > 0 and self.time < maxTime: if self.pendingActions.count(["sheep"]) == len(self.pendingActions): break if self.citSoldiers() / 4 + self.champions >= milpower: break self.step() self.time += 1 idleWorker += self.idleMen + self.idleWomen return (self.time, idleWorker) # returns the total number of citizen soldiers def citSoldiers(self): return self.idleMen + self.berries[0] + self.farm[0] +self.chop[0] + self.mineStone[0] + self.mineMetal[0] + self.hunt + self.butcher def __repr__(self): return "{10}/{11}; resources: f{1} w{2} s{3} m{4}; berry{25} farm{26} hunt{30} but{31} chop{27} st{28} met{29}; idleCC{13} idleWomen{5} idleMen{6} idleTraders{7} idleHorse{8} champions{9} idleBarracks{12} idleStorehouse{14} idleFarmstead{15} idleBlacksmith{16} idleCastle{17} idleCorral{18} idleMarket{19} fields{20} sheepfood{21} huntfood{22} berryfood{23} treewood{24} timers{32} tradeTime{33} tradeProfit{34} upgrades{35} pendingActions{36}".format("",self.food, self.wood, self.stone, self.metal, self.idleWomen, self.idleMen, self.idleTraders, self.idleHorse, self.champions, self.pop, self.maxPop, self.idleBarracks, self.idleCC, self.idleStorehouse, self.idleFarmstead, self.idleBlacksmith, self.idleCastle, self.idleCorral, self.idleMarket, self.fields, self.sheepfood, self.huntfood, self.berryfood, self.treewood, self.berries, self.farm, self.chop, self.mineStone, self.mineMetal, self.hunt, self.butcher, self.timers, self.tradeTime, self.tradeProfit, self.upgrades, self.pendingActions) class Barracks: def __init__(self): self.time = 0 # time remaining before it actions = [] # action types: # gathering: # ["chop", men, women] # ["farm", men, women] # ["stone", men, women] # ["metal", men, women] # ["berries", men, women] # ["butcher", horses] # ["hunt", horses] # removing a unit from gathering: "un_" before each of the above # producing units: # ["horse", num, fromBarracks (boolean) ] # ["man", num, fromBarracks (boolean) ] # ["woman", num] # ["champ", num, fromBarracks] # ["sheep", num] # ["trader", num] # buildings: # ["field", men, women] # (all buildings are followed by men + women on construction) # ["house"] # ["barracks"] # ["storehouse"] # ["tower"] # ["corral"] # ["farmstead"] # ["market"] # ["blacksmith"] # ["temple"] # it's assumed that all idle men + women will build the building # upgrades # ["up_wood1"] # ["up_wood2"] # ["up_gather"] # ["up_stone1"] # ["up_stone2"] # ["up_metal1"] # ["up_metal2"] # ["up_farm1"] # ["up_farm2"] # ["up_farm3"] # ["up_sheep"] # ["up_tradewalk"] (walk speed) # ["up_trade1"] (trade amount I) # ["up_trade2"] (trade amount II) # ["up_vision"] (see ally vision, at market) # ["II"] # ["III"] # maps an action to the resources needed for the action. [food, wood, stone, metal] actionCosts = {} delay = {} actionCosts["horse"] = [100,40,0,0] actionCosts["sheep"] = [50,0,0,0] actionCosts["man"] = [50,50,0,0] actionCosts["woman"] = [50,0,0,0] actionCosts["trader"] = [100,0,0,80] actionCosts["champ"] = [200,100,0,75] actionCosts["house"] = [0, 75, 0, 0] delay["house"] = 24 actionCosts["storehouse"] = [0, 100, 0, 0] delay["storehouse"]= 32 actionCosts["farmstead"] = [0, 100, 0, 0] delay["farmstead"] = 36 actionCosts["cc"] = [0, 500, 500, 500] delay["cc"] = 400 actionCosts["corral"] = [0, 100, 0, 0] delay["corral"] = 40 actionCosts["barracks"] = [0, 300, 0, 0] delay["barracks"] = 120 actionCosts["temple"] = [0, 300, 0, 0] delay["temple"] = 160 actionCosts["market"] = [0, 300, 0, 0] delay["market"] = 120 actionCosts["blacksmith"] = [0, 200, 0, 0] delay["blacksmith"] = 160 actionCosts["tower"] = [0, 100, 100, 0] delay["tower"] = 120 actionCosts["field"] = [0,100,0,0] delay["field"] = 40 actionCosts["castle"] = [0, 0, 1000, 0] delay["castle"] = 400 actionCosts["mill"] = [0, 200, 100, 0] delay["mill"] = 80 actionBuilding = {} actionCosts["up_wood1"] = [0, 200, 0, 50] delay["up_wood1"] = 40 actionBuilding["up_wood1"] = "storehouse" actionCosts["up_wood2"] = [0, 250, 0, 50] delay["up_wood2"] = 40 actionBuilding["up_wood2"] = "storehouse" actionCosts["up_gather"] = [0,100,0,0] delay["up_gather"] = 40 actionBuilding["up_gather"] = "farmstead" actionCosts["up_stone1"] = [200,0,0,50] delay["up_stone1"] = 40 actionBuilding["up_stone1"] = "storehouse" actionCosts["up_stone2"] = [250,0,0,50] delay["up_stone2"] = 40 actionBuilding["up_stone2"] = "storehouse" actionCosts["up_metal1"] = [0, 200, 0, 50] delay["up_metal1"] = 40 actionBuilding["up_metal1"] = "storehouse" actionCosts["up_metal2"] = [0, 250, 0, 50] delay["up_metal2"] = 40 actionBuilding["up_metal2"] = "storehouse" actionCosts["up_farm1"] = [0, 200, 0, 100] delay["up_farm1"] = 40 actionBuilding["up_farm1"] = "farmstead" actionCosts["up_farm2"] = [0, 300, 0, 150] delay["up_farm2"] = 40 actionBuilding["up_farm2"] = "farmstead" actionCosts["up_farm3"] = [0, 500, 0, 250] delay["up_farm3"] = 40 actionBuilding["up_farm3"] = "farmstead" actionCosts["up_tradewalk"] = [0, 0, 0, 200] delay["up_tradewalk"] = 40 actionBuilding["up_tradewalk"] = "market" actionCosts["up_trade1"] = [0, 150, 0, 150] delay["up_trade1"] = 40 actionBuilding["up_trade1"] = "market" actionCosts["up_trade2"] = [0, 300, 0, 300] delay["up_trade2"] = 40 actionBuilding["up_trade2"] = "market" actionCosts["up_vision"] = [100, 0, 0, 100] delay["up_vision"] = 40 actionBuilding["up_vision"] = "market" actionCosts["II"] = [500, 500, 0, 0] delay["II"] = 30 actionBuilding["II"] = "cc" actionCosts["III"] = [0,0,750,750] delay["III"] = 60 actionBuilding["III"] = "cc" def buildTime(time, workers): if workers == 1: return time elif workers == 2: return int(time / 1.4) elif workers == 3: return int(time/2) elif workers == 4: return int(time * 5. / 12) elif workers == 5: return int(time * 4. / 12) elif workers == 6: return int(time * 35. / 120) elif workers <= 17: return int((workers - 6.) /11 * (time * 65. / 400) + (17. - workers) / 11 * (time * 35. / 120)) else: return time * 65. / 400 def adjustBuildTime(curTime, curWorkers, newWorkers): origTime = curTime - 10 if origTime <= 0: return curTime oneWorkerTime = float(origTime) / buildTime(100000, curWorkers) * 100000.0 return buildTime(oneWorkerTime, curWorkers + newWorkers) + 10 # multiple builders: # 1 builder = 100% # 2 builder = / sqrt(2) # 3 builder = / 2 # 4 builder = * 5/12 # 5 builder = * 4/12 # 6 builder = * 35/120 # 17 builder = 38/160 or 65/400 # Special Actions: # ["wait",food,wood,stone,metal] wait until we have that amount of resources # ["help",buildingName,men, women] add that number of men and women to the building task actions = [["woman",5],["hunt",1],["chop",3,0],["house",1,0],["farmstead",0,4],["berries",0,4],["up_gather"],["chop",0,5],["woman",1],["chop",1,0],["wait",0,100,0,0],["un_chop",1,0],["storehouse",1,0],["chop",0,1],["woman",1],["chop",0,1],["woman",1],["chop",0,1],["woman",1],["chop",0,1],["woman",1],["chop",0,1],["woman",1],["chop",0,1],["chop",1,0],["woman",1],["house",0,1],["woman",1],["woman",1],["un_chop",0,4],["field",0,5],["woman",1],["chop",0,1],["un_chop",0,5],["field",0,5],["woman",1],["chop",0,1],["farm",0,5],["house",0,1],["chop",0,1],["farm",0,5]] # insert newActions in order into actions, at optimal positions # def insertOptimally(actions,newActions,milpower = 20,maxTime = 600): s = State() best = None bestScore = (0,0) for acts in iterInsert(actions, newActions): s.__init__() s.pendingActions = acts s.makeSheep = False score = s.evalActions(milpower,maxTime) if score < bestScore: bestScore = score best = acts return acts def iterInsert(actions, newActions): if len(newActions) == 0: yield actions return if len(actions) == 0: yield newActions return # insert the first of newActions at the start of actions for ins in iterInsert(actions, newActions[1:]): yield [newActions[0]] + ins # or do not for ins in iterInsert(actions[1:], newActions): yield [actions[0]] + ins s = State() s.pendingActions = actions s.makeSheep = False #s.completeActions(500) 2 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.