+ Show Spoiler +
Due to the worker pairing in sc2, there is little incentive to expand beyond three bases while building up your first 200/200 army in heart of the swarm (hots). This easily leads to defensive play, where a player quickly claims three bases (well before 10 minutes typically), and then turtle into a maxed army that has to end the game at around 15 minutes into the game. The opponent has mostly free access to the entire map, but cannot use this freedom to increase her income without using up army supply needed in the 15 minute battle.
This dynamic is addressed in the legacy of the void (lotv) by having mineral patches that mine out quickly, with the intention of forcing players to continue expanding to maintain income. There have also been community suggestions, such as bases with 6 mineral patches (FRB) from Barrin, or the now trendy double harvesting (DH) from BlackLilium and Uvantak, expanded by the TL strategy team.
There has been extensive analysis and comparisons between mining efficiency at different number of workers and bases, but it has been hard to compare DH directly to the lotv solution, as they changes are very different in nature. The DH change is a change of the income for a give number of mineral patches and workers, while the lotv change is a change of the number of patches available.
This dynamic is addressed in the legacy of the void (lotv) by having mineral patches that mine out quickly, with the intention of forcing players to continue expanding to maintain income. There have also been community suggestions, such as bases with 6 mineral patches (FRB) from Barrin, or the now trendy double harvesting (DH) from BlackLilium and Uvantak, expanded by the TL strategy team.
There has been extensive analysis and comparisons between mining efficiency at different number of workers and bases, but it has been hard to compare DH directly to the lotv solution, as they changes are very different in nature. The DH change is a change of the income for a give number of mineral patches and workers, while the lotv change is a change of the number of patches available.
Summary
In this post, I introduce a (crude) model of the income and army building in sc2. The model can take different mining efficiencies as input and includes bases mining out, thus covering both the DH and lotv solution. I compare a player that turtle up on three bases, 16 workers on each minerals on each base, until max to a player that goes to 5 bases with the same number of total workers.
I start by reproducing the hots 3-base problem (fig 1), showing that the turtling 3 base player with 16 workers on minerals on each patch has no disadvantage against a player with 5 bases and same total number of workers until the 3 base players lose almost all of her first 200/200 army.
The lotv simulation (fig 2), shows that the first 200/200 max can barely be done on three bases if no trades are done before (composition dependent), with a slowing economy towards the end, while a 5 base player can max out as fast, with a great advantage if the first big trade is even decently even.
In DH (fig 3) the 5-base player max out significantly faster than the three base players with the same number of workers, with a continued advantage after a trade, although not as extreme as in lotv.
The analysis shows that both lotv and DH significantly improve the 3-base turtle problem from hots. Lotv punish the turtling player severely at close to max and and the remax is essentially impossible when the bases are running dry, while DH gives a small disadvantage to the three base player well before the first max but is less punishing than lotv for a remax as the bases don't run out as fast.
The model is far from perfect, but I think it is good enough for what I have shown here. I believe that the model itself has a much greater value than the little preliminary analysis I have done here, so I strongly encourage the developers of the various economies to play with the model. I suggest some ideas in the outlook. I think it can help greatly in bridging the gap between income/minute as function of #workers, and what actually happens in a game, without having to make mods and collect large numbers of replays.
I first describe the results of the preliminary, and then at the end I go in detail about the model and how you can run it (it's easy!). At the end is a discussion on what more can be done with the model.
Results
In this section we assume that each player goes up to a fix number of bases and workers as soon as possible (we disregard early game shenanigans here), and after that builds only army, and I study how income and army supply change over time. I will mainly compare two players that both have 48 (16*3) workers on minerals, one player on 3 bases, the other on 5 bases. I also include a player that goes up to four saturated bases, to have a reference to compare to.
Starting with hots, we see that, as expected, the extra 2 bases does close to nothing in terms of income (blue and orange full lines), apart from a slightly quicker 48 workers from the extra bases. The five base player actually max out slightly slower, due to the extra 800 minerals spent on the last two bases. It is only after the main mines out for the 3 base player at around 18 minutes that the 5-base player gains an economical advantage, and only after the natural is drying up as well that the 5-base player start to really gain a strong advantage. This is all expected, and is mainly a sanity check that the model is doing what it should.
Figure 1: The income and army supply in hots of players that go up to 3 (blue) or 4 (red) bases with 16 workers on minerals per base, compared to a player that goes up to 5 bases (orange) while maintaining only 48 workers, the same as the 3-base player. The full lines are income per minute (scale on the right) and the dashed lines are army supply (scale on the left). An artificial wipe of all the current army supply is inserted at 14 minutes, to study the remaxing capability after a trade.
Second, we have a look at the same three players in lotv, fig 2. We see that the main is semi-depleted at around 9 (hots-) minutes, which slows down the max of the 3-base player, while the 5-base player is unaffected. This seems to more or less exactly cancel out the extra 800 minerals spent on the expansion and the 3-base and 5-base players max out more or less at the same time around 14 (hots-) minutes (blue and orange dotted lines). Around that time though, the second and third are also semi-depleted for the three-base player (drop in solid blue line) and there is no capability for remax (blue dotted line not making it back up after 15 min). The 5-base players happily mines at full efficiency until after 20 minutes though, and can remax np. So it seems that, depending on exact composition, there is some possibility to max on three bases in lotv if you don't trade at all before that. There will not be a remax though, so it is truly a single shot attack, and you are not maxing any faster than a player taking more bases. Only real advantage is relative safety from harass while on fewer bases. Overall, it doesn't seem like a very viable strategy, also because reaching 200/200 without trades doesn't seem realistic to me, in the way lotv is currently played.
Figure 2: The income and army supply in lotv of players that go up to 3 (blue) or 4 (red) bases with 16 workers on minerals per base, compared to a player that goes up to 5 bases (orange) while maintaining only 48 workers, the same as the 3-base player. The full lines are income per minute (scale on the right) and the dashed lines are army supply (scale on the left). An artificial wipe of all the current army supply is inserted at 14 minutes, to study the remaxing capability after a trade.
Last, let the same three players play on DH (fig 3), with the 9-minerals per trip (DH9) that, as I understand, is currently favoured as the best candidate. The model can easily run DH8 and DH10 as well, and I hope people will take my code and do it. We see that the 5-base players income just well above that of the 3-base player (orange solid line vs blue solid line)) as soon as the fourth and fifth bases are down. Income is about 2/3 on the way from 3 to 4 bases (red solid line) with 16 workers per base. This allows the 5-base player to max well before the 3-base player, and even keeping up with the 4-base player. After a trade, the 3-base player will have more bank and wont fall as far down (the dips in orange and blue at 14 minutes) and have more income to remax faster. However, unlike lotv, the 3-base player still has enough resources in her three bases to build up a decent army, altough a full remax is on the limit and probably composition-dependent. It should be noted that the model does NOT include worker transfer time, so the jump in income around 5 minutes for the 5-base player (orange solid line) will be delayed in practice, and associated with a dip during worker travel time. This is something that could factor in to map makers I guess.
Figure 3: The income and army supply in double harvest (DH9) of players that go up to 3 (blue) or 4 (red) bases with 16 workers on minerals per base, compared to a player that goes up to 5 bases (orange) while maintaining only 48 workers, the same as the 3-base player. The full lines are income per minute (scale on the right) and the dashed lines are army supply (scale on the left). An artificial wipe of all the current army supply is inserted at 14 minutes, to study the remaxing capability after a trade.
The model
+ Show Spoiler +
The model works in 1 second ticks, tracking all relevant changes: income, change in mineral patches, decision to build workers/nexuses, finishing workers/nexuses, minerals in the bank, which bases the workers are mining at, etc.
The income is calculated from Barrins google spread sheet found in this post. The workers are assumed to be optimally distributed amongst the existing bases, which is calculated every time a new probe is built, a mineral line runs (semi)-dry or a new nexus is made.
The workers are instantaneously moved to the optimal patch, so worker transfer time is NOT included in the model, which probably will overestimate the value of spreading out workers. This is likely one of the more urgent improvements needed for the model (feel free to add and re-publish anyone), as it is closely related to what we want to study.
Gas is completely ignored. This is the other big gap in the model imo. I would have included it, but as the economy models don't really talk about gas more than in passing, there is no need to have it in a model that compare them. Again, feel free to add it! Shouldn't be too hard! One effect of this though, is that the max army supply gets a bit high, as the workers that normally mine gas doesn't exist in the model.
The "AI" builds probes if there is a free nexus and money available, and a nexus if there is money left after that. Until the set number of probes and nexuses. There are no macro mechanics included, no crono-boost, no injects, no mules. This will slow things down a bit, and partially cancel out the the speed-up from the ignored worker transfer times. I think these two effects canceling out help reproduce decently realistic timings.
There are no pylons included, but the worker cost in increased by 1/8 of the pylon cost, so it averages out over time. As a result, the starting money is increased to 62.5 so that the first worker can be built immediately.
The "army supply" is calculated from the pooled minerals, that will start to accumulate after the target numbers of probes and nexuses are reached. I then use a conversion factor from minerals to supply, that is intended to include not only the units themselves, but also all the infrastructure: gateways, pylons, upgrades, maybe even some static defense and so on. I found that 110 minerals per supply reproduced realistic timings in hots, but this parameter can be tuned in the model as you want (so go change it if you want! ). Note that the choppy behaviour at the very start of the army supply is from the pooled minerals until a nexus is built. So it's not really "real" army supply. There is also a 30 second delay (changeable parameter) from the money is mined until the supply is actually created. This is supposed to be the time it takes to build the infrastructure to actually use the money. In practice this varies wildly, from warpgates that put mined minerals into battle in a few seconds, to increased income that require more barracks, that require more add-ons before you can start building. I felt that 30 seconds was a good compromise, but it doesn't really affect the outcome, it only shifts the army supply curve for all players a little bit.
How to run the code
- Install R. It's easy.
- Download Barrin's data as tab-separated sheet.
- Download the code from model.R (or copy-paste from below).
- Place both barrins spread sheet (should be named "Double Harvest Mining - Sheet1.tsv") and the model.R file in the same (new) folder.
- Open R in the folder, and enter:
- source('model.R')
- main() #this produce the hots plot
- mainLotv() #this produce the lotv plot
- mainDH9() #this produce the DH9 plot
- source('model.R')
- You can then start looking at the short code (the simulations are at the in in the "main" functions), and rerun with other numbers of probes/nexuses easily.
- If you want to run with another ecnomy, for example DH8 or DH10, you need to set up a new startingState (at the beginning of the file), and then call that startingState in the main functions.
The code is written in R, a free and easily installable statistics program on any operating system, and I have taken some effort into making it decently understandable. The model, the starting conditions, the simulations and the plotting for this post as less than 300 lines of codes, including comments and blank lines.
The code:
+ Show Spoiler +
#load data from barrins google spreadsheet, downloaded as tab separated values
#divide by 60 to get minerals per (hots) second
barrinMiningData = read.table('Double Harvest Mining - Sheet1.tsv', fill=T)
hotsMPS = barrinMiningData$V2[-c(1:2)]/60
DH8MPS = barrinMiningData$V4[-c(1:2)]/60
DH9MPS = barrinMiningData$V6[-c(1:2)]/60
DH10MPS = barrinMiningData$V8[-c(1:2)]/60
depletedMPS = hotsMPS*0
#the lotv mining rate at 4 mineral patches
lotvMPS = lotvMPS = hotsMPS[c(2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32, rep(32, 16))]/2
#constants. The probe has 1/8 of a pylon included in the cost
probe = list('time'=17, 'cost'=50 + 100/8)
nexus = list('time'=100, 'cost'=400)
constants = list('probe'=probe, 'nexus'=nexus)
#settings
settings = list(
'defendersAdvantage'=1.2,
'travelTime'=60,
'scoutingLatency'=30)
#setting up the starting state from hots
hotsStartingState=list(
'probe'=6,
'nexus'=1,
'busyNexus'=0,
'minerals'=50+100/8,
'time'=0,
'events'=data.frame('event'=c(), 'complete'=c()),
'baseResources' = rep(12000, 10),
'baseIncomes' = lapply(1:10, function(i) hotsMPS),
'economy'='hots',
'probeDist'=c(6, rep(0,9)))
#lotv starting state
lotvStartingState=list(
'probe'=12,
'nexus'=1,
'busyNexus'=0,
'minerals'=50+100/8,
'time'=0,
'events'=data.frame('event'=c(), 'complete'=c()),
'baseResources' = rep(9000, 10),
'baseIncomes' = lapply(1:10, function(i) hotsMPS),
'economy'='lotv',
'probeDist'=c(12, rep(0,9)))
#DH9 starting state
DH9StartingState=list(
'probe'=12,
'nexus'=1,
'busyNexus'=0,
'minerals'=50+100/8,
'time'=0,
'events'=data.frame('event'=c(), 'complete'=c()),
'baseResources' = rep(12000, 10),
'baseIncomes' = lapply(1:10, function(i) DH9MPS),
'economy'='hots',
'probeDist'=c(12, rep(0,9)))
#This function takes the income rate per base as function of mining workers
#and outputs the amount of probes, nexuses and money spent on army each hots second
simulate = function(mode='greedy', constants=constants, settings=settings,
startingState=hotsStartingState, endTime = 1000, maxProbe=48, maxNexus=3) {
state = startingState
history = list(state)
while ( state$time < endTime ) {
state = chooseActions(state=state, mode=mode, maxProbe=maxProbe, maxNexus=maxNexus)
state = tick(state)
history = c(history, list(state))
}
return(history)
}
#given a state of the game, decide what to build
#return a event data frame with actions
chooseActions = function(state, mode='greedy', maxProbe=Inf, maxNexus=Inf) {
#build a probe if money, free nexus, and unsaturated mineral line
if ( state$nexus - state$busyNexus > 0 &
state$minerals >= constants$probe$cost &
state$probe + sum(state$events$event == 'probe') < maxProbe ) {
state$minerals = state$minerals - constants$probe$cost
state$busyNexus = state$busyNexus+1
event = data.frame('event'='probe', 'complete'=state$time + constants$probe$time)
state$events = rbind(state$events, event)
#iterate
return(chooseActions(state=state, mode=mode, maxProbe=maxProbe, maxNexus=maxNexus))
}
#check if building a nexus
if ( state$minerals >= constants$nexus$cost &
state$nexus + sum(state$events$event == 'nexus') < maxNexus ) {
state$minerals = state$minerals - constants$nexus$cost
event = data.frame('event'='nexus', 'complete'=state$time + constants$nexus$time)
state$events = rbind(state$events, event)
#iterate
return(chooseActions(state=state, mode=mode, maxProbe=maxProbe, maxNexus=maxNexus))
}
#if nothing (more) built, return same state
return(state)
}
#let one second pass
tick = function(state) {
state$time = state$time+1
#income
state$minerals = state$minerals + income(state)
#remove minerals from patches
state = removeResources(state)
#check for finished probes
readyProbes = state$events$complete == state$time & state$events$event == 'probe'
if ( sum(readyProbes) > 0 ) {
for ( i in 1:sum(readyProbes) ) state = addProbe(state)
}
state$busyNexus = state$busyNexus - sum(readyProbes)
state$events = state$events[!readyProbes,]
#check for finished nexuses
readyNexus = state$events$complete == state$time & state$events$event == 'nexus'
state$nexus = state$nexus + sum(readyNexus)
state$events = state$events[!readyNexus,]
if ( any(readyNexus) ) state = redistributeProbes(state)
return(state)
}
#calculates the income per second of a state
income = function(state) {
baseIncome = sapply(1:state$nexus, function(i)
ifelse(state$probeDist[i]==0,0, state$baseIncome[[i]][min(32, state$probeDist[i])]))
return(sum(baseIncome))
}
#remove resources from the bases corresponding to a second of mining
removeResources = function(state) {
baseIncome = sapply(1:state$nexus, function(i)
ifelse(state$probeDist[i]==0,0, state$baseIncome[[i]][min(32, state$probeDist[i])]))
#remove resource from each base
newResources = state$baseResources[1:state$nexus] - baseIncome
#check for bases that mined out the first 4 patches
if ( state$economy == 'lotv' ) {
if ( any(state$baseResources[1:state$nexus] > 3000 & newResources <= 3000) ) {
semiDepleted = which(state$baseResources[1:state$nexus] > 3000 & newResources <= 3000)
state$baseIncomes[[semiDepleted]] = lotvMPS
state = redistributeProbes(state)
}
}
#check for bases that mined out compeletely
if ( any(state$baseResources[1:state$nexus] > 0 & newResources <= 0) ) {
depleted = which(state$baseResources[1:state$nexus] > 0 & newResources <= 0)
state$baseIncomes[[depleted]] = depletedMPS
state = redistributeProbes(state)
}
state$baseResources[1:state$nexus] = newResources
return(state)
}
#adds a probe to the base where it'll get most income
addProbe = function(state) {
state$probe = state$probe + 1
#find best nexus to add the probe to.
improvedIncome = sapply(1:state$nexus, function(i) {
state$baseIncome[[i]][min(32,state$probeDist[i]+1)] -
ifelse(state$probeDist[i] == 0, 0, state$baseIncome[[i]][min(32,state$probeDist[i])])
})
bestBase = which(improvedIncome >= max(improvedIncome)*0.999)[1]
state$probeDist[[bestBase]] = state$probeDist[[bestBase]] + 1
return(state)
}
redistributeProbes = function(state) {
state$probeDist = rep(0, length(state$probeDist))
nProbes = state$probe
state$probe = 0
for ( i in 1:nProbes ) state = addProbe(state)
return(state)
}
#calculates the supply of probes over time for a history of states
ecoSupply = function(history) {
return(pmin(200, sapply(history, function(state) state$probe)))
}
#the amount of army supply
#The delay is the delay from the money is spent until the units are on the field
armySupply = function(history, delay=30, mineralsPerSupply=110, reset=c()) {
ret = rep(0, length(history))
ret[(delay+1):length(ret)] = sapply(history[1:(length(ret)-delay)], function(state) state$minerals/mineralsPerSupply)
nNexus = sapply(history, function(state) state$nexus)
ret = pmin(ret, 200-ecoSupply(history))
for ( t in reset ) {
lost = ret[reset]
ret[(reset):length(ret)] = sapply(history[(reset-delay):(length(ret)-delay)], function(state) state$minerals/mineralsPerSupply)
ret[(reset):length(ret)] = ret[(reset):length(ret)] - lost
ret = pmin(ret, 200-ecoSupply(history))
}
return(ret)
}
#return the time in minute for each state in the history
timeInMinutes = function(history) {
return(sapply(history, function(state) state$time/60))
}
main = function() {
stopAt3 = simulate(endTime=25*60, maxProbe=48, maxNexus=3)
stopAt4 = simulate(endTime=25*60, maxProbe=64, maxNexus=4)
stopAt4.50 = simulate(endTime=25*60, maxProbe=48, maxNexus=5)
plot(timeInMinutes(stopAt3), sapply(stopAt3, income), lwd=2, type='n', col='blue', ylim=c(0,170),
xlab='time in hots minute', ylab='supply', main='HotS')
axis(side=4, at=c(2000/60, 4000/60), labels=c('1000', '2000'))
segments(c(5,10,15,20), rep(0,4), c(5,10,15,20), rep(200, 4), lwd=1, col=rgb(0.9, 0.9, 0.9))
lines(timeInMinutes(stopAt4), 2*sapply(stopAt3, income), lwd=2, col='blue')
lines(timeInMinutes(stopAt4), 2*sapply(stopAt4, income), lwd=2, col='red')
lines(timeInMinutes(stopAt4), 2*sapply(stopAt4.50, income), lwd=2, col='orange')
lines(timeInMinutes(stopAt3), armySupply(stopAt3, reset=16*60), lwd=2, col='blue', lty=2)
lines(timeInMinutes(stopAt3), armySupply(stopAt4, reset=16*60), lwd=2, col='red', lty=2)
lines(timeInMinutes(stopAt3), armySupply(stopAt4.50, reset=16*60), lwd=2, col='orange', lty=2)
legend('topleft', c('3 base, 48 probes', '4 base, 64 probes', '5 base, 48 probes', 'army supply', 'income/min'),
lty=c(1, 1, 1, 2, 1), col=c('blue', 'red', 'orange', 'black', 'black'), lwd=2, bg='white')
}
mainLotv = function() {
stopAt3 = simulate(endTime=25*60, maxProbe=48, maxNexus=3, startingState=lotvStartingState)
stopAt4 = simulate(endTime=25*60, maxProbe=64, maxNexus=4, startingState=lotvStartingState)
stopAt4.50 = simulate(endTime=25*60, maxProbe=48, maxNexus=5, startingState=lotvStartingState)
plot(timeInMinutes(stopAt3), sapply(stopAt3, income), lwd=2, type='n', col='blue', ylim=c(0,170),
xlab='time in hots minute', ylab='supply', main='LotV')
axis(side=4, at=c(2000/60, 4000/60), labels=c('1000', '2000'))
segments(c(5,10,15,20), rep(0,4), c(5,10,15,20), rep(200, 4), lwd=1, col=rgb(0.9, 0.9, 0.9))
lines(timeInMinutes(stopAt4), 2*sapply(stopAt3, income), lwd=2, col='blue')
lines(timeInMinutes(stopAt4), 2*sapply(stopAt4, income), lwd=2, col='red')
lines(timeInMinutes(stopAt4), 2*sapply(stopAt4.50, income), lwd=2, col='orange')
lines(timeInMinutes(stopAt3), armySupply(stopAt3, reset=14*60), lwd=2, col='blue', lty=2)
lines(timeInMinutes(stopAt3), armySupply(stopAt4, reset=14*60), lwd=2, col='red', lty=2)
lines(timeInMinutes(stopAt3), armySupply(stopAt4.50, reset=14*60), lwd=2, col='orange', lty=2)
legend('topleft', c('3 base, 48 probes', '4 base, 64 probes', '5 base, 48 probes', 'army supply', 'income/min'),
lty=c(1, 1, 1, 2, 1), col=c('blue', 'red', 'orange', 'black', 'black'), lwd=2, bg='white')
}
mainDH9 = function() {
stopAt3 = simulate(endTime=25*60, maxProbe=48, maxNexus=3, startingState=DH9StartingState)
stopAt4 = simulate(endTime=25*60, maxProbe=64, maxNexus=4, startingState=DH9StartingState)
stopAt4.50 = simulate(endTime=25*60, maxProbe=48, maxNexus=5, startingState=DH9StartingState)
plot(timeInMinutes(stopAt3), sapply(stopAt3, income), lwd=2, type='n', col='blue', ylim=c(0,170),
xlab='time in hots minute', ylab='supply', main='DH9')
axis(side=4, at=c(2000/60, 4000/60), labels=c('1000', '2000'))
segments(c(5,10,15,20), rep(0,4), c(5,10,15,20), rep(200, 4), lwd=1, col=rgb(0.9, 0.9, 0.9))
lines(timeInMinutes(stopAt4), 2*sapply(stopAt3, income), lwd=2, col='blue')
lines(timeInMinutes(stopAt4), 2*sapply(stopAt4, income), lwd=2, col='red')
lines(timeInMinutes(stopAt4), 2*sapply(stopAt4.50, income), lwd=2, col='orange')
lines(timeInMinutes(stopAt3), armySupply(stopAt3, reset=14*60), lwd=2, col='blue', lty=2)
lines(timeInMinutes(stopAt3), armySupply(stopAt4, reset=14*60), lwd=2, col='red', lty=2)
lines(timeInMinutes(stopAt3), armySupply(stopAt4.50, reset=14*60), lwd=2, col='orange', lty=2)
legend('topleft', c('3 base, 48 probes', '4 base, 64 probes', '5 base, 48 probes', 'army supply', 'income/min'),
lty=c(1, 1, 1, 2, 1), col=c('blue', 'red', 'orange', 'black', 'black'), lwd=2, bg='white')
}
Umm, let's try to use some kind of creative commons or something. that is free for everyone to reuse, change, redistribute etc. Not sure if that even makes sense here, but anyway: please attribute, share alike, and don't copy. Not sure about the commercial use part, as I am fine with blizzard using it, as long as they follow the other three. Also, if someone want's to put it in github or something, go ahead. I don't see myself doing a lot more work on this code, so you guys go ahead.
outlook
There's a lot more that can be done within the framework of this model. Apart from comparing more different caps on number of bases and probes (which can be interesting already), this can help decide between DH8, DH9 and DH10. I intentionally did not do the plots for DH8 and DH10, as I really want someone more involved in these economy projects to take over and use the code. Adding DH8 and DH10 is essentially just changing a few parameters in the code. The mining efficiencies are already there from Barrin's sheet, so it's really just a minutes work to do it.
It would not be hard to add FRB in this framework either, as well as other suggestions such as adding a few gold patches as the natural, and a few more at later bases. All of these can be plugged into the model and compared to the other economical solutions.
it is also very easy to change the amount of minerals in the bases, so you can easily run DH9 on lotv mineral patches or whatnot.
With some more work, there are also possibilities in looking closer at the early game. How much more greedy can I be than my opponent given a certain defenders advantage? When is the optimal point to stop droning for a push at X minutes? When should I stop droning to defend the push?
Anyway, I hope that already the plots in this post have shed some light on how the three economies work in relation to each other.
Happy to take feedback, thanks for your attention (lel).
More simulations
fancyClown:
http://www.teamliquid.net/forum/legacy-of-the-void/483771-modeling-the-impact-of-economy#18
lotv vs DH9 at different number of bases, and 2 vs 4 base in DH9 and lotv.