Skip to content

Instantly share code, notes, and snippets.

@proflong
Created February 18, 2016 23:40
Show Gist options
  • Save proflong/b660b9d7efaca93433c8 to your computer and use it in GitHub Desktop.
Save proflong/b660b9d7efaca93433c8 to your computer and use it in GitHub Desktop.
# The file contains 2 methods for predicting power stone chance outcomes
# The first gives the expected value. This is the average number of crystals you can expect from any particular map clearing.
# Of course, you may end up getting above or below the average. To give a sense of this, I programmed a simulator (since calculating the joint variance is tough and most probably wouldn't know how to interpret the value).
# The simulator acts like it clears the same map setup a lot of time (default=10,000), and stores every outcome.
# This will give you a sense of how often you'll be very unlucky (e.g. clear your map and receive nothing) and very lucky (e.g. receive 10 crystals in one map clear).
# Note that results don't include the guarenteed stones from Dr. Terror.
# If you just want to know how many crystals to expect on Terror days add the following to your totals
# 2.2245 for tropical terror days and
# 2.3469 for volcano terror days
# Simple building number calculator.
# Both the expected value calculator and simulator use a raw number for headquarters and buildings, since encountering them in separate bases or not doesn't affect the probabilities.
# This function returns the number of headquarters and number of other buildings that can generate power stones. Calculated based on average number of buildings per base. These averages can definitly be made more accurate.
# tropical.terror and volcano.terror indicates how many dr. terror levels you will complete
get.buildings<- function(num.pvp=1, num.npc=1, avg.pvp=62, avg.npc=35, tropical.terror=0, volcano.terror=0){
hq<- num.pvp + num.npc + tropical.terror + volcano.terror
buildings<- (num.pvp * avg.pvp) + (num.npc * avg.npc)
tropical.terror.buildings<-c(5,10,15,20,25,30,35)
volcano.terror.buildings<-c(20,30,30,40,50,60,70)
if(tropical.terror > 0) buildings<- buildings + sum(tropical.terror.buildings[1:tropical.terror])
if(volcano.terror > 0) buildings<- buildings + sum(volcano.terror.buildings[1:volcano.terror])
return(c(num.hq=hq, num.buildings=buildings))
}
# Expected value calculator for Boom Beach Crystals
expected.crystals<- function(num.hq=1, num.buildings=62, psc.bonus=0){
ev.stone<- (.03 * 1) + (.12 * 1/7) + (.85 * 1/49)
p.hq<- .25
p.building<- .02
p.hq.statue<- p.hq * (1 + psc.bonus)
p.building.statue<- p.building * (1 + psc.bonus)
p.hq.boosted<- p.hq * (1 + 2 * psc.bonus)
p.building.boosted<- p.building * (1 + 2 * psc.bonus)
crystals.no.statue<- num.hq * p.hq * ev.stone + num.buildings * p.building * ev.stone
crystals.statue<- num.hq * p.hq.statue * ev.stone + num.buildings * p.building.statue * ev.stone
crystals.boosted<- num.hq * p.hq.boosted * ev.stone + num.buildings * p.building.boosted * ev.stone
names(crystals.no.statue)<- "crystals.no.statue"
names(crystals.statue)<- "crystals.statue"
names(crystals.boosted)<- "crystals.boosted"
return(c(crystals.no.statue, crystals.statue=crystals.statue,crystals.boosted=crystals.boosted))
}
map<- get.buildings(2,1,tropical.terror=7)
expected.crystals(map["num.hq"],map["num.buildings"],.75)
# Simulates how many crystals you will get from clearing your map both without any psc bonus, with psc bonus and with psc boosted bonus. Shards (1/7) and frags (1/49) are converted to crystals.
sim.crystals<- function(num.hq=1, num.buildings=62, psc.bonus=0){
stones.no.statue<- 0
stones<- 0
stones.boosted<- 0
crystals.no.statue<- 0
crystals<- 0
crystals.boosted<- 0
results<-runif(2 * (num.hq + num.buildings),0,1)
for(building in 1:(num.hq + num.buildings)){
if(building <= num.hq) prob<- .25 else prob<- .02
if(results[building] < prob*(1 + 2 * psc.bonus)){
stones.boosted<- stones.boosted + 1
if(results[building] < prob*(1 + psc.bonus)){
stones<- stones + 1
if(results[building] < prob) stones.no.statue<- stones.no.statue + 1
}
}
}
if(stones.boosted == 0) return(c(crystals=0,crystals.boosted=0,crystals.no.statue=0))
for(stone in 1:stones.boosted){
if(stone <= stones) mult<- 1 else mult<- 0
if(stone <= stones.no.statue) mult.2<- 1 else mult.2<- 0
if(results[(num.hq + num.buildings + stone)] < .03){
crystals<- crystals + (1 * mult)
crystals.boosted<- crystals.boosted + 1
crystals.no.statue<- crystals.no.statue + (1 * mult.2)
} else if(results[(num.hq + num.buildings + stone)] < .15){
crystals<- crystals + ( (1/7) * mult)
crystals.boosted<- crystals.boosted + (1/7)
crystals.no.statue<- crystals.no.statue + ( (1/7) * mult.2)
} else {
crystals<- crystals + ( (1/49) * mult)
crystals.boosted<- crystals.boosted + (1/49)
crystals.no.statue<- crystals.no.statue + ( (1/49) * mult.2)
}
}
return(c(crystals=crystals,crystals.boosted=crystals.boosted,crystals.no.statue=crystals.no.statue))
}
# Simulator function
sim.map<- function(n.sims=10000, ...){
crystals<-numeric()
crystals.boosted<-numeric()
crystals.no.statue<-numeric()
for(sim in 1:n.sims){
result<- sim.crystals(...)
crystals<-c(crystals,result["crystals"])
crystals.boosted<-c(crystals.boosted,result["crystals.boosted"])
crystals.no.statue<-c(crystals.no.statue,result["crystals.no.statue"])
}
return(data.frame(crystals=crystals,crystals.boosted=crystals.boosted,crystals.no.statue=crystals.no.statue))
}
## ## ## Implementation example
map<-get.buildings(num.pvp=7,num.npc=7,volcano.terror=7)
result<-sim.map(num.hq=map["num.hq"],num.buildings=map["num.buildings"], psc.bonus=.75)
mean(result$crystals.no.statue)
hist(result$crystals.no.statue,25)
mean(result$crystals)
hist(result$crystals,25)
mean(result$crystals.boosted)
hist(result$crystals.boosted,25)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment