Thanks for confirming, CapnHector. I hope this code reflects my understanding accurately.

import numpy as np

PADDING = 2

MAXIMUM_DAMAGE_REDUCTION = 0.85

MINIMUM_ARMOR_FACTOR = 0.05

POOLING_FACTORS = np.array([

[0.0, 0.5, 0.5, 0.5, 0.0],

[0.5, 1.0, 1.0, 1.0, 0.5],

[0.5, 1.0, 1.0, 1.0, 0.5],

[0.5, 1.0, 1.0, 1.0, 0.5],

[0.0, 0.5, 0.5, 0.5, 0.0]

])

def padded_grid(row_width):

"""

Return a padded grid around a row of some width.

"""

grid_width = row_width + 2 * PADDING

grid_height = 1 + 2 * PADDING

#cell_ids are just so you, the reader, can tell the cells apart

#I will replace them with armor_rating / 15

cell_ids = np.arange(grid_width * grid_height, dtype = 'float64')

return np.reshape(cell_ids, (grid_width, grid_height))

def square_grids(padded_grid):

"""

Return one square grid for each cell along the middle

row of a padded grid, less the padding to either side.

"""

return np.array([padded_grid[i - PADDING - 1 : i + PADDING] for i in

range(PADDING + 1, len(padded_grid) - 1)])

def pool(armor_grids):

"""

Return the pooled armor value of the cells of each

of several armor grids.

"""

return np.array([np.sum(POOLING_FACTORS * grid) for grid in armor_grids])

def armor_damage_factor(hit_strength, pooled_armor):

"""

Return the factor multiplying the damage of a hit to

armor cells.

"""

damage_factor = hit_strength / (hit_strength + pooled_armor)

damage_factor[np.less(MAXIMUM_DAMAGE_REDUCTION, damage_factor)] = (

MAXIMUM_DAMAGE_REDUCTION)

return damage_factor

def hull_damage_factor(hit_strength, pooled_armor, armor_rating):

"""

Return the factor multiplying the damage of a hit to

the hitpoints of a ship.

"""

pooled_armor[np.less(pooled_armor, armor_rating * MINIMUM_ARMOR_FACTOR)] = (

armor_rating * MINIMUM_ARMOR_FACTOR)

return hit_strength / (hit_strength + pooled_armor)

def armor_damage(hit_strength, pooled_armor):

"""

Return the maximum damage to a hit inflicts upon

cells of a pooled armor value.

"""

return hit_strength * armor_damage_factor(hit_strength, pooled_armor)

def hull_damage(hit_strength, pooled_armor, armor_rating):

"""

Return the damage a hit inflicts upon the hitpoints of a ship.

"""

return hit_strength * hull_damage_factor(hit_strength, pooled_armor,

armor_rating)

def main():

"""

Demonstrate the above functions.

"""

#target

hull = 1000

armor_rating = 500

armor_per_cell = 100

armor_row_width = 10

#shooter

hit_probabilities = np.array([0.1 for _ in range(armor_row_width)])

hit_strength = 100

armor_row = np.full(armor_row_width, armor_per_cell)

print("armor row")

print(armor_row, "\n")

armor_grid = padded_grid(armor_row_width)

print("armor grid")

print(armor_grid, "\n")

virtual_armor_grids = square_grids(armor_grid)

print("virtual armor grids")

print(virtual_armor_grids,"\n")

pooled_armor = pool(virtual_armor_grids)

print("pooled armor")

print(pooled_armor, "\n")

damage_to_armor = armor_damage(hit_strength, pooled_armor)

print("damage to armor")

print(damage_to_armor, "\n")

damage_to_hull = hull_damage(hit_strength, pooled_armor, armor_rating)

print("damage to hull")

print(damage_to_hull, "\n")

main()

output

armor row

[100 100 100 100 100 100 100 100 100 100]

armor grid

[[ 0. 1. 2. 3. 4.]

[ 5. 6. 7. 8. 9.]

[10. 11. 12. 13. 14.]

[15. 16. 17. 18. 19.]

[20. 21. 22. 23. 24.]

[25. 26. 27. 28. 29.]

[30. 31. 32. 33. 34.]

[35. 36. 37. 38. 39.]

[40. 41. 42. 43. 44.]

[45. 46. 47. 48. 49.]

[50. 51. 52. 53. 54.]

[55. 56. 57. 58. 59.]

[60. 61. 62. 63. 64.]

[65. 66. 67. 68. 69.]]

virtual armor grids

[[[ 0. 1. 2. 3. 4.]

[ 5. 6. 7. 8. 9.]

[10. 11. 12. 13. 14.]

[15. 16. 17. 18. 19.]

[20. 21. 22. 23. 24.]]

[[ 5. 6. 7. 8. 9.]

[10. 11. 12. 13. 14.]

[15. 16. 17. 18. 19.]

[20. 21. 22. 23. 24.]

[25. 26. 27. 28. 29.]]

[[10. 11. 12. 13. 14.]

[15. 16. 17. 18. 19.]

[20. 21. 22. 23. 24.]

[25. 26. 27. 28. 29.]

[30. 31. 32. 33. 34.]]

[[15. 16. 17. 18. 19.]

[20. 21. 22. 23. 24.]

[25. 26. 27. 28. 29.]

[30. 31. 32. 33. 34.]

[35. 36. 37. 38. 39.]]

[[20. 21. 22. 23. 24.]

[25. 26. 27. 28. 29.]

[30. 31. 32. 33. 34.]

[35. 36. 37. 38. 39.]

[40. 41. 42. 43. 44.]]

[[25. 26. 27. 28. 29.]

[30. 31. 32. 33. 34.]

[35. 36. 37. 38. 39.]

[40. 41. 42. 43. 44.]

[45. 46. 47. 48. 49.]]

[[30. 31. 32. 33. 34.]

[35. 36. 37. 38. 39.]

[40. 41. 42. 43. 44.]

[45. 46. 47. 48. 49.]

[50. 51. 52. 53. 54.]]

[[35. 36. 37. 38. 39.]

[40. 41. 42. 43. 44.]

[45. 46. 47. 48. 49.]

[50. 51. 52. 53. 54.]

[55. 56. 57. 58. 59.]]

[[40. 41. 42. 43. 44.]

[45. 46. 47. 48. 49.]

[50. 51. 52. 53. 54.]

[55. 56. 57. 58. 59.]

[60. 61. 62. 63. 64.]]

[[45. 46. 47. 48. 49.]

[50. 51. 52. 53. 54.]

[55. 56. 57. 58. 59.]

[60. 61. 62. 63. 64.]

[65. 66. 67. 68. 69.]]]

pooled armor

[180. 255. 330. 405. 480. 555. 630. 705. 780. 855.]

damage to armor

[35.71428571 28.16901408 23.25581395 19.8019802 17.24137931 15.26717557

13.69863014 12.42236025 11.36363636 10.47120419]

damage to hull

[35.71428571 28.16901408 23.25581395 19.8019802 17.24137931 15.26717557

13.69863014 12.42236025 11.36363636 10.47120419]