All right so it turns out I was wrong, you cannot expect the damage dealt to armor to be equal to decrease in armor HP even for the first shot (in the sense of calculating a total armor HP as if we were to distribute it equally to get the same average armor cell value). It's just not the way it works. I'm going to delete the posts above so as not to confuse people.
Instead, the test calculation that you can make is that, for the first shot, it should be the case that the expected damage you are going to distribute over the armor should be the same as you would get from calculating the whole thing in bulk, because armor is uniform and probs sum to 1. Ie. sum of damage distributed over armor = damage * hit strength/(hit strength + armor). But this is accurate for the first shot only, since after that considering the armor in bulk is no longer accurate and there is no simple way to restore a full armor hp as a description of the armor!
An armor HP gauge should still exist for comparisons with real life data, it just must be understood that it does not accurately reflect the state of the armor but rather what the enemy ship captain would see (armor can be at half and ship still be taking hull damage as we all know).
Anyway I created this "dumb" and very verbose version of the basic naive armor damage code for a "reference". All the operations are implemented using loops and elementary operations, so it should be quite easy to see that they are correct.
It seems like damage is indeed much higher in your code than it should be. Question: when you write
ship.armor_grid.cells[0:5,i:i+5] -= damage * ArmorGrid.WEIGHTS
are you accounting for the fact that when distributing damage, the weights should be 1/15th of those used to pool armor? So that it sums up to 1 and not 15. (because for armor we have already applied the 1/15th when generating the armor matrix, so if we sum it to a total of 15 we get back the starting armor, but we haven't done that for damage so if we use the 1/2 and 1 weights we end up with 15 x too high damage)
damage <- 20
hitstrength <- 40
startingarmor <- 100
hitstrengthcalc <- function(hitstrength, armor) return(max(0.15,hitstrength/(hitstrength+max(armor,0.05*startingarmor))))
shipcells <- 10
probabilities <- c(0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1)
norounds <- 3
weights <- matrix(c(0,0.5,0.5,0.5,0,0.5,1,1,1,0.5,0.5,1,1,1,0.5,0.5,1,1,1,0.5,0,0.5,0.5,0.5,0),5,5)
weights
poolarmor <- function(armormatrix, index) {
sum <- 0
for(i in 1:5)for(j in 1:5) sum <- sum + weights[i,j]*armormatrix[i,index-3+j]
return(sum)
}
print("Starting armor matrix")
print(armormatrix <- matrix(startingarmor / 15, 5, shipcells+4))
print("Equivalent armor hp:")
fullarmorhp <- (sum(armormatrix[2:4,])+sum(armormatrix[1,2:13])+sum(armormatrix[5,2:13]))/(5*14-4)*15
print(fullarmorhp)
for(r in 1:norounds){
armordamagereductions <- vector(shipcells, mode="double")
for (x in 1:length(armordamagereductions)) {
armordamagereductions[x] <- hitstrengthcalc(hitstrength,poolarmor(armormatrix,x+2))
}
print("Armor damage expected based on full armor hp:")
print(damage*hitstrength/(hitstrength+fullarmorhp))
armordamagesatmiddlecells <- armordamagereductions*damage
print("Armor damage at middle cells given full shot:")
print(armordamagesatmiddlecells)
print("Probability adjusted armor damage at middle cells:")
for(x in 1:length(armordamagesatmiddlecells)) {
armordamagesatmiddlecells[x] <- armordamagesatmiddlecells[x]*probabilities[x]
}
print(armordamagesatmiddlecells)
print("Total armor damage incoming at middle cells:")
print(sum(armordamagesatmiddlecells))
for (i in 1:length(armordamagesatmiddlecells)){
for (j in 1:5){
for (k in 1:5){
armormatrix[j,i+k-1] <- armormatrix[j,i+k-1] - armordamagesatmiddlecells[i]*weights[j,k]/15
}
}
}
print("New armor matrix:")
print(round(armormatrix,2))
print("Equivalent armor hp:")
fullarmorhp <- (sum(armormatrix[2:4,])+sum(armormatrix[1,2:13])+sum(armormatrix[5,2:13]))/(5*14-4)*15
print(fullarmorhp)
}
Output: using
damage <- 20
hitstrength <- 40
startingarmor <- 100
shipcells <- 10
probabilities <- c(0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1)
norounds <- 3
[1] "Starting armor matrix"
> print(armormatrix <- matrix(startingarmor / 15, 5, shipcells+4))
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
[1,] 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667
[2,] 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667
[3,] 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667
[4,] 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667
[5,] 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667
[,12] [,13] [,14]
[1,] 6.666667 6.666667 6.666667
[2,] 6.666667 6.666667 6.666667
[3,] 6.666667 6.666667 6.666667
[4,] 6.666667 6.666667 6.666667
[5,] 6.666667 6.666667 6.666667
>
> print("Equivalent armor hp:")
[1] "Equivalent armor hp:"
> fullarmorhp <- (sum(armormatrix[2:4,])+sum(armormatrix[1,2:13])+sum(armormatrix[5,2:13]))/(5*14-4)*15
> print(fullarmorhp)
[1] 100
[1] "Armor damage expected based on full armor hp:"
[1] 5.714286
[1] "Armor damage at middle cells given full shot:"
[1] 5.714286 5.714286 5.714286 5.714286 5.714286 5.714286 5.714286 5.714286 5.714286 5.714286
[1] "Probability adjusted armor damage at middle cells:"
[1] 0.5714286 0.5714286 0.5714286 0.5714286 0.5714286 0.5714286 0.5714286 0.5714286 0.5714286 0.5714286
[1] "Total armor damage incoming at middle cells:"
[1] 5.714286
[1] "New armor matrix:"
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14]
[1,] 6.67 6.65 6.63 6.61 6.61 6.61 6.61 6.61 6.61 6.61 6.61 6.63 6.65 6.67
[2,] 6.65 6.61 6.57 6.53 6.51 6.51 6.51 6.51 6.51 6.51 6.53 6.57 6.61 6.65
[3,] 6.65 6.61 6.57 6.53 6.51 6.51 6.51 6.51 6.51 6.51 6.53 6.57 6.61 6.65
[4,] 6.65 6.61 6.57 6.53 6.51 6.51 6.51 6.51 6.51 6.51 6.53 6.57 6.61 6.65
[5,] 6.67 6.65 6.63 6.61 6.61 6.61 6.61 6.61 6.61 6.61 6.61 6.63 6.65 6.67
[1] "Equivalent armor hp:"
[1] 98.7013
[1] "Armor damage expected based on full armor hp:"
[1] 5.76779
[1] "Armor damage at middle cells given full shot:"
[1] 5.764875 5.780745 5.791107 5.795901 5.797101 5.797101 5.795901 5.791107 5.780745 5.764875
[1] "Probability adjusted armor damage at middle cells:"
[1] 0.5764875 0.5780745 0.5791107 0.5795901 0.5797101 0.5797101 0.5795901 0.5791107 0.5780745 0.5764875
[1] "Total armor damage incoming at middle cells:"
[1] 5.785946
[1] "New armor matrix:"
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14]
[1,] 6.67 6.63 6.59 6.55 6.55 6.55 6.55 6.55 6.55 6.55 6.55 6.59 6.63 6.67
[2,] 6.63 6.55 6.48 6.40 6.36 6.36 6.36 6.36 6.36 6.36 6.40 6.48 6.55 6.63
[3,] 6.63 6.55 6.48 6.40 6.36 6.36 6.36 6.36 6.36 6.36 6.40 6.48 6.55 6.63
[4,] 6.63 6.55 6.48 6.40 6.36 6.36 6.36 6.36 6.36 6.36 6.40 6.48 6.55 6.63
[5,] 6.67 6.63 6.59 6.55 6.55 6.55 6.55 6.55 6.55 6.55 6.55 6.59 6.63 6.67
[1] "Equivalent armor hp:"
[1] 97.38631
[1] "Armor damage expected based on full armor hp:"
[1] 5.822996
[1] "Armor damage at middle cells given full shot:"
[1] 5.816955 5.849598 5.871049 5.881035 5.883560 5.883560 5.881035 5.871049 5.849598 5.816955
[1] "Probability adjusted armor damage at middle cells:"
[1] 0.5816955 0.5849598 0.5871049 0.5881035 0.5883560 0.5883560 0.5881035 0.5871049 0.5849598 0.5816955
[1] "Total armor damage incoming at middle cells:"
[1] 5.860439
[1] "New armor matrix:"
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14]
[1,] 6.67 6.61 6.55 6.49 6.49 6.49 6.49 6.49 6.49 6.49 6.49 6.55 6.61 6.67
[2,] 6.61 6.49 6.38 6.26 6.20 6.20 6.20 6.20 6.20 6.20 6.26 6.38 6.49 6.61
[3,] 6.61 6.49 6.38 6.26 6.20 6.20 6.20 6.20 6.20 6.20 6.26 6.38 6.49 6.61
[4,] 6.61 6.49 6.38 6.26 6.20 6.20 6.20 6.20 6.20 6.20 6.26 6.38 6.49 6.61
[5,] 6.67 6.61 6.55 6.49 6.49 6.49 6.49 6.49 6.49 6.49 6.49 6.55 6.61 6.67
[1] "Equivalent armor hp:"
[1] 96.05439
Using
damage <- 100
hitstrength <- 100
startingarmor <- 100
shipcells <- 10
probabilities <- c(0.00,0.05,0.10,0.15,0.20,0.20,0.15,0.10,0.05,0.00)
norounds <- 3
Output
[1] "Starting armor matrix"
> print(armormatrix <- matrix(startingarmor / 15, 5, shipcells+4))
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
[1,] 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667
[2,] 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667
[3,] 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667
[4,] 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667
[5,] 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667 6.666667
[,12] [,13] [,14]
[1,] 6.666667 6.666667 6.666667
[2,] 6.666667 6.666667 6.666667
[3,] 6.666667 6.666667 6.666667
[4,] 6.666667 6.666667 6.666667
[5,] 6.666667 6.666667 6.666667
>
> print("Equivalent armor hp:")
[1] "Equivalent armor hp:"
> fullarmorhp <- (sum(armormatrix[2:4,])+sum(armormatrix[1,2:13])+sum(armormatrix[5,2:13]))/(5*14-4)*15
> print(fullarmorhp)
[1] 100
[1] "Armor damage expected based on full armor hp:"
[1] 50
[1] "Armor damage at middle cells given full shot:"
[1] 50 50 50 50 50 50 50 50 50 50
[1] "Probability adjusted armor damage at middle cells:"
[1] 0.0 2.5 5.0 7.5 10.0 10.0 7.5 5.0 2.5 0.0
[1] "Total armor damage incoming at middle cells:"
[1] 50
[1] "New armor matrix:"
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14]
[1,] 6.67 6.67 6.58 6.42 6.17 5.92 5.75 5.75 5.92 6.17 6.42 6.58 6.67 6.67
[2,] 6.67 6.58 6.33 5.92 5.33 4.75 4.42 4.42 4.75 5.33 5.92 6.33 6.58 6.67
[3,] 6.67 6.58 6.33 5.92 5.33 4.75 4.42 4.42 4.75 5.33 5.92 6.33 6.58 6.67
[4,] 6.67 6.58 6.33 5.92 5.33 4.75 4.42 4.42 4.75 5.33 5.92 6.33 6.58 6.67
[5,] 6.67 6.67 6.58 6.42 6.17 5.92 5.75 5.75 5.92 6.17 6.42 6.58 6.67 6.67
[1] "Equivalent armor hp:"
[1] 88.63636
[1] "Armor damage expected based on full armor hp:"
[1] 53.01205
[1] "Armor damage at middle cells given full shot:"
[1] 51.50215 52.93339 54.75702 56.55042 57.70618 57.70618 56.55042 54.75702 52.93339 51.50215
[1] "Probability adjusted armor damage at middle cells:"
[1] 0.000000 2.646670 5.475702 8.482564 11.541236 11.541236 8.482564 5.475702 2.646670 0.000000
[1] "Total armor damage incoming at middle cells:"
[1] 56.29234
[1] "New armor matrix:"
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14]
[1,] 6.67 6.67 6.50 6.15 5.61 5.07 4.70 4.70 5.07 5.61 6.15 6.50 6.67 6.67
[2,] 6.67 6.50 5.97 5.09 3.84 2.58 1.85 1.85 2.58 3.84 5.09 5.97 6.50 6.67
[3,] 6.67 6.50 5.97 5.09 3.84 2.58 1.85 1.85 2.58 3.84 5.09 5.97 6.50 6.67
[4,] 6.67 6.50 5.97 5.09 3.84 2.58 1.85 1.85 2.58 3.84 5.09 5.97 6.50 6.67
[5,] 6.67 6.67 6.50 6.15 5.61 5.07 4.70 4.70 5.07 5.61 6.15 6.50 6.67 6.67
[1] "Equivalent armor hp:"
[1] 75.84265
[1] "Armor damage expected based on full armor hp:"
[1] 56.86902
[1] "Armor damage at middle cells given full shot:"
[1] 53.26066 56.62906 61.31532 66.40800 69.97700 69.97700 66.40800 61.31532 56.62906 53.26066
[1] "Probability adjusted armor damage at middle cells:"
[1] 0.000000 2.831453 6.131532 9.961200 13.995401 13.995401 9.961200 6.131532 2.831453 0.000000
[1] "Total armor damage incoming at middle cells:"
[1] 65.83917
[1] "New armor matrix:"
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14]
[1,] 6.67 6.67 6.40 5.85 4.98 4.06 3.43 3.43 4.06 4.98 5.85 6.40 6.67 6.67
[2,] 6.67 6.40 5.58 4.16 2.11 0.01 -1.22 -1.22 0.01 2.11 4.16 5.58 6.40 6.67
[3,] 6.67 6.40 5.58 4.16 2.11 0.01 -1.22 -1.22 0.01 2.11 4.16 5.58 6.40 6.67
[4,] 6.67 6.40 5.58 4.16 2.11 0.01 -1.22 -1.22 0.01 2.11 4.16 5.58 6.40 6.67
[5,] 6.67 6.67 6.40 5.85 4.98 4.06 3.43 3.43 4.06 4.98 5.85 6.40 6.67 6.67
[1] "Equivalent armor hp:"
[1] 60.8792