Jump to content

Fastest to 300


jonbaer
 Share

Recommended Posts

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.

Link to comment
Share on other sites

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. 

Link to comment
Share on other sites

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 / Lair
6 Drone until 10
10 Double Extractor Trick
12 Overlord
12 Spawning Pool
11 Drone x5
16 Extractor (Put 3 Drones inside immediately upon completion)
15 Drone
16 Queen (Inject Hatchery as soon as she pops out)
18 Overlord
18 Drone x2
20 Roach Warren
19 Overlord
19 Roach x7
33 Drone
34 Overlord
34 Hatchery (Expand)
33 Drone x3
36 Lair
36 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?

Link to comment
Share on other sites

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.*$//'

  • Like 1
Link to comment
Share on other sites

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)

 

 

  • Like 2
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...