How to win a medieval siege with python simulations

Asad Ali
4 min readSep 3, 2022
Photo by Cederic Vandenberghe on Unsplash

The number of soldiers to bring on the battlefield has been a fundamental question involving warfare. There has been a plethora of literature and papers on the topic starting with famous Lancaster Laws from first world ware to mordern high powered discrete event simulations. In this article, let's build a straightforward simulation to simulate two opposing armies one attacker and one defender. I will not be including complex impacts like troops' morale and battlefield logistics, hence the models might be more relevant to pre-modern engagements where numbers mattered a lot.

Let's determine the number of soldiers needed to capture a medieval enemy castle given Na numbers of attackers and Nd numbers of defenders. Obviously, defenders have additional firepower and defense advantage. We will use simple python functions to achieve this task. Let's build up a basic analysis to answer critical questions, how many soldiers are required, and who will win given the force concentration of two armies? I will be using a lot of recursions to build up the function. I guess for wider analysis this has to be replaced with more performant functions

Our two main recursion functions will be attacker_needed, which basically given defenders' numbers and probability of winning of attacking army will recursively call the P_attacker_win recursion function

P_attacker_win function creates a recursion stack tree to calculate the probability of attacker winner given the probability model of

Probability (defender , attacker ) = c1*Probalbity (defender , attacker — 1 ) + c2*Probalbity (defender — 1 , attacker ) + c3*Probalbity (defender+ 1 , attacker — 1 ) , we can create a recurssion function

Supporting Jupyter Notebooks at https://github.com/Asad1287/Awesome-Simulations/blob/main/War_Simulation.ipynb

#Question #1 how many soldiers to bring on battle field#Lets assume attacker army has  firepower of c1 and opposing side has firepower of c2, since defender is well-entrenced lets assume c2>c1. Also lets assume c3 is the chance that POW will be captured and used by defender# Probalbity (defender , attacker ) = c1*Probalbity (defender , attacker - 1 ) + c2*Probalbity (defender - 1 , attacker ) + c3*Probalbity (defender+ 1 , attacker - 1 ) , we can create a recurssion function

For plotting purposes, I will try to fit the simulation results into a second-order polynomial function

Let's plot a table showing different probabilities of winning for attackers given different force ratios

Now let's create a ploting function

We can also plot several functions given different probabilities of winning for the attacking army, showing the number of attacking and defending soldiers required

Similarly, we can also plot the variation in firepower and the change in the number of soldiers required for the attacking army, where 0.4 to 0.6 are varying firepower constants for the attacker.

Who will win the battle

To calculate the final number of remaining soldiers, we can use the python collections counter to calculate the soldier's tally and just use an altered recursive function.

Now lets try the above functions out. Given 0.3 to 0.6, defenders advantage, and given 100 soldiers on each side, defending side is a clear winner with around 50–60 remaining soldiers

The analysis actually supports the time-old claim that an attacker must have a force concentration of around 3 :1 to have a chance of winning. This is however not a rule as in fact seen in the famous 16th century Siege of Malta where even a 8:1 advantage couldn't help the Ottaman side win the battle.

To build a more computationally efficient model we can convert the recurssion-based functional approach to an array-based computational friendly approach. Obviously, the next step can be to add more number of variable and make some of the variables probabilistic and the above analysis more scalable to actually be able to incorporate real-world data.

--

--

Asad Ali

Data Science, Analytics, and Machine Learning Professional.