#0. define ship, distribution matrix X, and probability matrix.
#dominator
ship <- c(14000, 500, 10000, 1500, 220, 12, 440, 1.0, 200)
#damage
d <- 500
h <- 500
#constants
omega <- 0.05
kappa <- 0.15
a_0 <- ship[4]
n <- ship[6]
#X
x <- matrix(c(0,1/30,1/30,1/30,0,1/30,1/15,1/15,1/15,1/30,1/30,1/15,1/15,1/15,1/30,1/30,1/15,1/15,1/15,1/30,0,1/30,1/30,1/30,0),5,5)
#draw a random cell from a custom cumulative distribution function
custrandom <- function(dist){
return(which(dist > runif(1,0,1))[1])
}
range <- 1000
#basic calculations
#this computes a weighted average but can be defined using linear algebra due to what we're working with
poolarmor <- function(matrix, index){
pooledarmor <- 0
for(i in 1:5) pooledarmor <- pooledarmor + 15* (x[i,] %*% matrix[,index+i-3])
return(pooledarmor[[1]])
}
#compute armor damage reduction factor
chi <- function(matrix, index) return(max(kappa,h/(h+max(a_0*omega,poolarmor(matrix,index)))))
#deal damage, the linear algebra way
#for some ungodly reason R insists on transposing the vector
#i refers to row of armor cell, j to column, r to counterfactual vector (star)
damage <- function(damagematrix,i,j,r) return((d * x[i,] %*% damagematrix[(j-2):(j+2),r])[[1]])
create_b_star <- function(armormatrix){
B_star_vector <- vector(mode="double",length=(n+8))
for (i in 1:n) {
B_star_vector[4+i] <- chi(A,4+i)
}
B_star <- diag(B_star_vector)
return(B_star)
}
B_star
A
star_matrix <- function(matrixA,matrixB,r) {
A_star <- matrix(0,nrow=length(matrixA[,1]),ncol=length(matrixA[1,]))
for (i in 5:(length(matrixA[1,])-5)){
for (j in 1:(length(matrixA[,1]))){
print(c(i,j))
A_star[i,j] <- max(0, matrixA[i,j] - damage(matrixB, i, j
, r))
}
}
return(A_star)
}
star_matrix_wonky_hull_dmg <- function(matrixA,matrixB,r) {
A_star <- matrix(0,nrow=length(A[,1]),ncol=length(matrixA[1,]))
hulldamage <- 0
for (j in 5:(length(matrixB[1,])-2)){
for (i in 1:(length(matrixA[,1]))){
print(c("i:",i,"j:",j,"r:",r))
hulldamage <- hulldamage + max(0, damage(matrixB, i, j, r) - matrixA[i,j])
A_star[i,j] <- max(0, matrixA[i,j] - damage(matrixB, i, j, r))
}
}
A_star[1,1] <- hulldamage
return(A_star)
}
A
star_matrix_wonky_hull_dmg(A,B_star,10)
#sd
serror <- 50
#spread
spread <- 10
#how much is the visual arc of the ship in rad?
shipangle <- ship[5]/(2* pi *range)
#how much is the visual arc of a single cell of armor in rad?
cellangle <- shipangle/ship[6]
#distribution
anglerangevector <- 0
anglerangevector <- vector(mode="double", length = ship[6]+1)
anglerangevector[1] <- -shipangle/2
for (i in 1:(length(anglerangevector)-1)) anglerangevector[i+1] <- anglerangevector[i]+cellangle
#now convert it to pixels
anglerangevector <- anglerangevector*2*pi*range
# this function generates the shot distribution (a bhattacharjee distribution for the
#non-trivial case)
hit_distribution <- function(upperbounds, standard_deviation, spread){
vector <- vector(mode="double", length = length(upperbounds)+1)
if (standard_deviation == 0){
if (spread == 0){
vector[1] <- 0
for (j in 2:(length(upperbounds))) {
#if both spread and standard deviation are 0 then all shots hit 1 cell. this should be so even if
#the ship has an even number of cells to prevent ships with even no. cells appearing tougher which is not
#the case in the real game most likely
if ((upperbounds[j] >= 0) & (upperbounds[j-1] < 0)) vector[j] <- 1
}
#return part of a box
} else {
vector[1] <- min(1,max(0,(upperbounds[1]+spread))/(2*spread))
for (j in 2:(length(upperbounds))) vector[j] <- min(1,max(0,(upperbounds[j]+spread))/(2*spread)) - min(1,max(0,(upperbounds[j-1]+spread))/(2*spread))
vector[length(upperbounds)+1] <- 1-min(1,max(0,(upperbounds[length(upperbounds)]+spread))/(2*spread))
}
} else {
if (spread != 0){
vector[1] <- hit_probability_coord_lessthan_x(upperbounds[1], standard_deviation, spread)
for (j in 2:(length(upperbounds))) vector[j] <- (hit_probability_coord_lessthan_x(upperbounds[j], standard_deviation, spread)-hit_probability_coord_lessthan_x(upperbounds[j-1], standard_deviation, spread))
vector[length(upperbounds)+1] <- (1-hit_probability_coord_lessthan_x(upperbounds[length(upperbounds)], standard_deviation, spread))
} else {
#if spread is 0 but standard deviation is not 0 we have a normal distribution
vector[1] <- pnorm(upperbounds[1],0,standard_deviation)
for (j in 2:(length(upperbounds))) vector[j] <- pnorm(upperbounds[j],0,standard_deviation) - pnorm(upperbounds[j-1], mean=0, sd=standard_deviation)
vector[length(upperbounds)+1] <- 1-pnorm(upperbounds[length(upperbounds)], mean=0, sd=standard_deviation)
}
}
return(vector)
}
G <- function(y) return(y*pnorm(y) + dnorm(y))
#a is the SD of the normal distribution and b is the parameter of the uniform distribution
hit_probability_coord_lessthan_x <- function(z, a, b) return(a/2/b*(G(z/a+b/a)-G(z/a-b/a)))
p <- hit_distribution(anglerangevector,serror,spread)
A <- matrix(ship[4]/15,5,ship[6]+4)
#pad A
A <- cbind(A,c(0,0,0,0,0))
A <- cbind(A,c(0,0,0,0,0))
A <- cbind(c(0,0,0,0,0),A)
A <- cbind(c(0,0,0,0,0),A)
B_star <- create_b_star(A)
A
B_star
p
p_cum <- vector(mode = "double", length=length(p))
p_cum[1] <- p[1]
for (i in 2:length(p)) p_cum[i] <- sum(p[1:i])
generatetestdata <-0
if(generatetestdata == 1){
#generate simulated data using 100 models
testresults <- data.frame(hullhp=double(),shot=integer(),series=integer())
for (i in 1:100){
A <- matrix(ship[4]/15,5,ship[6]+4)
#pad A
A <- cbind(A,c(0,0,0,0,0))
A <- cbind(A,c(0,0,0,0,0))
A <- cbind(c(0,0,0,0,0),A)
A <- cbind(c(0,0,0,0,0),A)
B_star <- create_b_star(A)
hullhp <- ship[1]
shot <- 0
while (hullhp > 0){
shot <- shot+1
A<-star_matrix_wonky_hull_dmg(A,B_star,custrandom(p_cum))
hullhp <- hullhp - A[1,1]
B_star <- create_b_star(A)
testresults <-rbind(testresults, c(hullhp, shot, i))
}
}
colnames(testresults) <- c("hullhp","shot","series")
}
library(ggplot2)
ggplot(testresults,aes(x=shot,y=hullhp,group=series,col=series))+
geom_line()
#now the simple model
A <- matrix(ship[4]/15,5,ship[6]+4)
#pad A
A <- cbind(A,c(0,0,0,0,0))
A <- cbind(A,c(0,0,0,0,0))
A <- cbind(c(0,0,0,0,0),A)
A <- cbind(c(0,0,0,0,0),A)
B_star <- create_b_star(A)
hullhp <- ship[1]
shot <- 0
p
matrixlist <- list()
modelresults <- data.frame(hullhp=double(),shot=integer(),series=integer())
while (hullhp > 0){
shot <- shot+1
#2 rows of zeroes and 2 rows of padding
for(r in 1:n) matrixlist[[r]] <-star_matrix_wonky_hull_dmg(A,B_star,r+4)
hulldamage <- 0
#probability list has list item 1 as missing
for(r in 1:n) hulldamage <- hulldamage + matrixlist[[r]][1,1]*p[r+1]
hullhp <- hullhp - hulldamage
A <- A*(p[1]+p[length(p)])
for(r in 1:n) A <- A + matrixlist[[r]]*p[r+1]
for(i in 1:length(A[1,]))for(j in 1:length(A[,1])) A[j,i] <- max(A[j,i],0)
B_star <- create_b_star(A)
modelresults <-rbind(modelresults, c(hullhp, shot, i))
}
matrixlist
star_matrix(A,B_star,10)
colnames(modelresults) <- c("hullhp","shot","series")
modelresults$series <- 999
testresults <- rbind(testresults, modelresults)
matrixlist[[1]]
print(matrixlist[[r]])
ggplot(testresults,aes(x=shot,y=hullhp,group=series,col=series))+
geom_line()