Showing posts with label Combat Simulation. Show all posts
Showing posts with label Combat Simulation. Show all posts

March 10, 2023

Combat Simulation IV

I have made a great deal of process on the combat simulator, to the point where I was able to use it to run a simple combat for my party. That was a useful exercise, as it revealed a couple of places where I needed to clean it up. Two main uses for this tool have emerged more clearly in my mind: running a combat under various conditions to get a better idea of difficulty, and automating the choices of NPCs during a manual combat. Currently, it's not super easy to input PC actions without manually writing JSON - which can be done of course, but is not very scalable.

But it works! I'm trying to avoid premature optimization. I also haven't added some of the more complex effects yet, such as spells or difficult terrain conditions.

Among other benefits, the tool adds up all gained experience (and will work for hirelings and henchmen later on), and provides a useful double-check on the final disposition of health. I encourage players to keep track of their own health, but things slip through the cracks, and more so online.

This fight was rather simple and even blase; an orcish ambush (red) on the party (blue), who was inspecting the aftermath of yet another previous (and successful ambush). With so few combatants and evenly matched in numbers, there is little opportunity for much strategy once melee is met.

True, the display leaves a lot to be desired here. But I don't intend to spend a great deal of time on that, preferring instead to focus on usability and features.

January 6, 2023

Combat Simulation III

Let's continue with movement selection.

We're still only considering melee. I'll address ranged movement next, and then move on to the actual attack.

The following considerations are taken into account:

  1. Distance to target. A closer target is better, or considered a higher threat. For now, I'll consider all enemies to be of equal threat all things considered. I have a planned upgrade to allow creatures of higher intelligence to weight threats based on the enemy's HD
  2. Required AP. Again, closer is better, in this case because the character can move there with AP to spare and possibly attack
  3. Flanking. Could possibly make this available only to higher intelligence creatures also

This generates the following maps. I'm still using the constrained movement but I'm thinking through strategies for a freer (and therefore more efficient) system. The darker the hex, the higher the movement score. Notice in the second image that the preferred move would flank Blue.

Blue guy (right)

Red guy (top right)

This is probably fine for now. There's always more things that come up, but I'm in a move-fast-break-things mood so we'll fix those as they become problems.

January 2, 2023

Combat Simulation II

Previously, I discussed basic, unhindered movement. But movement is rarely unhindered, and so we'll need to add constraints and obstacles.

The trickiest part of this was figuring out how to represent a battle map in memory. I want to use an inefficient format like JSON because its human readable and we can check it into source control easily. As I was going over old combats, I realized that this tool could be very helpful to review both your own historical fights but also those of others, like a quarterback going over old game film.

For now, I'll try to use the simplest possible case. Map hexes are flat-topped and have an equal movement cost. To represent buildings or other structures, one of the sides of the hex is denoted "blocked": that is, no movement may take place through that side. If all 6 sides are blocked, the entire hex is impassable: perhaps a large tree. If two or more sides are blocked, the hex is considered a partial hex and movement/combat buffs may apply.

The following diagram shows two groups of combatants: blue and red. The thick black lines show the outline of a small keep, with several broken walls providing gaps.

Let us say that the blue combatant entering the keep at the bottom wishes to move elsewhere. He'll have to spend 1 AP disengaging from combat, leaving him with 1 or 2 AP for movement. His possible moves are then as follows:

For our purposes here, we'll ignore certain moves that would end in an opponent's hex, such as charging or overbearing.

Later, we can make the map more complex by introducing travel costs for each hex, but this will be fine for now.

December 29, 2022

Combat Simulation I

My party has just run through their first combat. It went well, especially considering this was their first combat in Authentic D&D. Over the holiday, I had some time to think about that combat, and whether or not I could use any algorithms to offload any of the work in running the NPCs, particularly dumb ones with simple motivations. In any case, an exploration of that project is sure to be enlightening in itself.

I'll make the code available here.

Another advantage of a system like this is that we can capture a combat in a repeatable (and version-controllable) way. At least to a degree: the beauty of D&D is that a rule system never fully captures the range of human ingenuity, and so to some extent the rule system must always be fluidly updated to match feedback from actual play.

We can break combat action at its simplest level down into:

  • move somewhere
  • attack something
  • interact with something

These actions can be done more than once per turn in any order, depending on the available action points and circumstances, with the goal of breaking the enemy's will through death or morale collapse.

Every action taken by an active participant in the combat should be in service of this goal. Participants who are more intelligent or better trained will select better options than others. [we can also invert this selection function to simulate the actions of PCs, who will choose the worst option in any possible circumstance]

I'll start by tackling movement, which I thought would be the easiest of the three actions. That turned out to not bode well for the others.

Let's consider a battlemap with no obstacles and two actors. We'll play with the actor on the right, giving it 3 AP and the ability to move according to the Authentic D&D rules. Without considering other constraints, this means that for each AP, the actor can move between 1 and 8 hexes in a straight line. This generates the following possibility space:

Movement possibilities: darker hexes mean more possible paths to reach that hex

However, there are several constraints we must add, which proved to be non-trivial to program. The actor can only change speed once, they can only rotate left or right 60$^\circ$ at the end of each AP, and they can't move through obstacles (in this case, that is only the other actor). That reduces our space to the following:

Possibility space with constraints added

The space is still mostly symmetrical, but we can also see the disruption caused by the presence of another actor. Keep in mind also that this is the possibility space for exactly 3 AP; in many cases our actor would only want to move one or two AP, or perhaps even look ahead multiple turns.

Movement in 1 AP, darker hexes are a higher stride

For example, if the actor on the right wants to attack the actor on the left, they will move at stride 2 for 2 hexes to enter melee and then have 2 AP left to attack. In this way, we can build up a desirability score for each possible hex, and take an optimal or near-optimal combination of actions as a result.

I'm not quite done with movement yet. Right now, we only avoid obstacles of other actors. I'll need to do some thinking on how to add simple static obstacles such as walls or buildings.