Fractal Softworks Forum

Please login or register.

Login with username, password and session length
Advanced search  

News:

Starsector 0.97a is out! (02/02/24); New blog post: Planet Search Overhaul (07/13/24)

Pages: 1 ... 6 7 [8] 9 10 ... 32

Author Topic: Optimizing the Conquest: a Mathematical Model of Space Combat  (Read 28555 times)

Liral

  • Admiral
  • *****
  • Posts: 725
  • Realistic Combat Mod Author
    • View Profile
Re: Optimizing the Conquest: a Mathematical Model of Space Combat
« Reply #105 on: November 17, 2022, 12:27:16 PM »

I fear simulating ship maneuvers would be too difficult and would rather have a fast, simple model of face-to-face firepower.  A target either can or cannot flank faster than enemy turrets can turn but could only rarely dodge a projectile by moving slightly.  Few ships are so maneuverable as to consistently get behind any opponents, which themselves usually have rear-facing or turreted weapons to fight them.  Some ships also have movement abilities, etc., which can decide this question outright.  Answering this question would ultimately entail re-implementing the Starsector combat engine and AI.

CapnHector

  • Admiral
  • *****
  • Posts: 1056
    • View Profile
Re: Optimizing the Conquest: a Mathematical Model of Space Combat
« Reply #106 on: November 18, 2022, 04:40:20 AM »

I don't really think it's as simple as that. The AI almost certainly does not dodge optimally but is under a variety of influences leading to semi-random behavior. I currently run a mixed fleet of Conquests and Brawlers and the Brawlers routinely catch Reapers and other missiles and projectiles like demented pong-bats instead of just doing the reasonable thing and dodging or even just staying course which would have lead to the projectile missing.

Anyway, the reason why the random model would work is not that it accurately simulates the AI, but rather that if it includes roughly every possible movement that is likely to occur in the real game then the results on average would reflect turret tracking ability. Now if we assume there is a huge number of inputs to the AI, then if we don't know anything about what is going on in combat, we may assume the AI's choice of movement is normally distributed. Then we are essentially doing a Monte Carlo simulation of what is happening in combat to get these numbers. An alternative way to look at it is that since the enemy ship movement is independent on any given time interval, then you could just re-arrange the sequence into what is a "reasonable" combat sequence (which there are probably many of if we have 100k sequences). Now if you were to take the average of the result you would end up with the same average as you get from the random sequence.

Like said I am open to improvements here though, but I still feel it would be nice to have a(n optional) parameter to describe turret tracking ability too.

Anyway, lower our speed to 45 (Conquest, no zero flux boost or Maneuvering jets), and add the Conquest's own turn rate of 6. Then let's make the target ship the size of a Dominator (220 px). I'll also lower the number of simulations we are doing because this is one program that again takes a very long time to run. Here are the hit rates (100 simulations of 100 seconds for each combination of turn rate and top speed) per turn rate for turn rate from 0 to 30, in increments of 5, and enemy top speed from 0 to 200, in increments of 10, still using Gauss (spread 0).
Code
x <- 0
y <- 1000
alpha <- 0
xour <- 0
your <- 0
beta <- pi/2
enemytopspeed <- 300
ourtopspeed <- 45
turretrotationrate <- 5*pi/180
mindistance <- 50
SD <- 50
spread <- 0
targetwidth <- 220


G <- function(y) return(y*pnorm(y) + dnorm(y))
fEz <- function(z, a, b) return((1/2/b)*(pnorm(z/a+b/a)-pnorm(z/a-b/a)))
PrEltZ <- function(z, a, b){
  if(b==0) return(pnorm(z,0,a)) else return(a/2/b*(G(z/a+b/a)-G(z/a-b/a)))
}

averages <- data.frame()
for (s in seq(10,200,10)) {
  enemytopspeed <- s
  print(c("enemy top speed is:", s))

 
for (r in seq(0,30,5)) {
  turretrotationrate <- (r+6)*pi/180
  print(c("turret rotation rate is:", r))
 

for (i in 1:100) {
  locationmatrix <- data.frame()
  x <- 0
  y <- 1000
for (t in 1:100) {
 
  #the enemy is not allowed to come within mindistance pixels of our ship in either direction
  deltax <- rnorm(1,0,enemytopspeed)
  deltay <- rnorm(1,0,ourtopspeed)
  while(abs(sqrt((x+deltax-xour)^2+(y+deltay-your)^2)) < mindistance){
     deltax <- rnorm(1,0,enemytopspeed)
     deltay <- rnorm(1,0,enemytopspeed)

  }


 
  #alpha is the angle of directional vector from our ship to enemy
 
 

  x <- x+deltax
  y <- y+deltay
  alpha <- atan2(y-your,x-xour)
 
  range <-sqrt((x-xour)^2+(y-your)^2)
 
  if(range>1000){
  xour=xour+cos(alpha)*ourtopspeed
  your=your+sin(alpha)*ourtopspeed
  }
 
 
  #beta is the angle of our turret
  #rotate beta towards alpha by a maximum of rate turretrotationrate
  beta <- beta + sign(alpha-beta)*min(turretrotationrate,abs(alpha-beta))
 
  #gamma is the angle from our turret facing to the enemy ship
  gamma <- alpha-beta
  prob <- PrEltZ(gamma*range+targetwidth/2, SD, spread)-PrEltZ(gamma*range-targetwidth/2,SD,spread)
  locationmatrix <- rbind(locationmatrix, c(t,x,y,xour,your,prob))
 
}
  names(locationmatrix) <- c("t","x","y","xour","your","hitprobability")

averages <- rbind(averages, c(mean(locationmatrix$hitprobability),s,r,i))
}
}
}
names(averages) <- c("hitprob","topspeed","turnrate","run")
averages
 

After aggregating the runs and taking the mean of hit probability across runs, we get this data
Spoiler

    topspeed turnrate   hitprob
1         10        0 0.8638403
2         20        0 0.7576896
3         30        0 0.7402694
4         40        0 0.6625848
5         50        0 0.7369327
6         60        0 0.6875313
7         70        0 0.6765392
8         80        0 0.6943154
9         90        0 0.6013359
10       100        0 0.5908593
11       110        0 0.5747073
12       120        0 0.5633436
13       130        0 0.5306272
14       140        0 0.5736074
15       150        0 0.5375646
16       160        0 0.5141144
17       170        0 0.4734542
18       180        0 0.4806974
19       190        0 0.4824674
20       200        0 0.4658784
21        10        5 0.9087731
22        20        5 0.8160650
23        30        5 0.8007856
24        40        5 0.8739375
25        50        5 0.8426129
26        60        5 0.7777419
27        70        5 0.7297531
28        80        5 0.7682660
29        90        5 0.7346132
30       100        5 0.7374037
31       110        5 0.7132191
32       120        5 0.7414817
33       130        5 0.7180191
34       140        5 0.6720560
35       150        5 0.6864451
36       160        5 0.6563502
37       170        5 0.6403787
38       180        5 0.6585675
39       190        5 0.6522295
40       200        5 0.6583766
41        10       10 0.9161702
42        20       10 0.8768744
43        30       10 0.8711839
44        40       10 0.8163568
45        50       10 0.8280426
46        60       10 0.8687802
47        70       10 0.8442793
48        80       10 0.8457214
49        90       10 0.8244319
50       100       10 0.8005428
51       110       10 0.7891478
52       120       10 0.7811752
53       130       10 0.7514515
54       140       10 0.7387135
55       150       10 0.7595159
56       160       10 0.7791199
57       170       10 0.7592434
58       180       10 0.7451520
59       190       10 0.7166897
60       200       10 0.7122592
61        10       15 0.9395805
62        20       15 0.9149204
63        30       15 0.8906036
64        40       15 0.8812045
65        50       15 0.8837285
66        60       15 0.8625697
67        70       15 0.8267144
68        80       15 0.8592025
69        90       15 0.8509674
70       100       15 0.8443408
71       110       15 0.8358114
72       120       15 0.8115829
73       130       15 0.8178224
74       140       15 0.8106944
75       150       15 0.8310698
76       160       15 0.7611141
77       170       15 0.7699804
78       180       15 0.7759956
79       190       15 0.7673662
80       200       15 0.7555627
81        10       20 0.9478558
82        20       20 0.9373705
83        30       20 0.9119520
84        40       20 0.8936612
85        50       20 0.8800513
86        60       20 0.8950729
87        70       20 0.8832973
88        80       20 0.8679177
89        90       20 0.8659575
90       100       20 0.8623654
91       110       20 0.8525335
92       120       20 0.8455205
93       130       20 0.8270614
94       140       20 0.8285563
95       150       20 0.8366158
96       160       20 0.8015315
97       170       20 0.8208051
98       180       20 0.8127251
99       190       20 0.7871574
100      200       20 0.8111585
101       10       25 0.9517321
102       20       25 0.9104478
103       30       25 0.8507284
104       40       25 0.9002465
105       50       25 0.8612552
106       60       25 0.8786419
107       70       25 0.8766353
108       80       25 0.8795814
109       90       25 0.8523118
110      100       25 0.8774695
111      110       25 0.8700940
112      120       25 0.8635090
113      130       25 0.8629561
114      140       25 0.8372481
115      150       25 0.8351283
116      160       25 0.8365642
117      170       25 0.8326198
118      180       25 0.8342032
119      190       25 0.8114680
120      200       25 0.8155941
121       10       30 0.9366022
122       20       30 0.9257401
123       30       30 0.8604539
124       40       30 0.9366947
125       50       30 0.8971899
126       60       30 0.8892408
127       70       30 0.8747965
128       80       30 0.8934654
129       90       30 0.8958007
130      100       30 0.8886172
131      110       30 0.8779249
132      120       30 0.8868961
133      130       30 0.8641212
134      140       30 0.8705663
135      150       30 0.8562662
136      160       30 0.8629481
137      170       30 0.8520315
138      180       30 0.8384351
139      190       30 0.8556037
140      200       30 0.8438437
[close]



It seems like there is a separate effect for both turn rate and enemy top speed. Also, the effect seems reasonably linear.



So we might fit a linear model here and use the coefficients to adjust hit probability for enemy top speed and turret turn rate. Note that the graphs show that turn rate really does not matter that much vs the real Dominator (top speed 30). This graph has me thinking Advanced turret gyros should be worth taking almost routinely.

Here is a plot for Glimmer (width 78 px). Broadly similar but with a floor as there comes a point where we can no longer hit with an immobile weapon just by rotating the Conquest.



Incidentally, if you are wondering whether the minimum distance and our ship keeping distance assumptions are necessary, the model behaves pretty badly without them
Spoiler
Without a minimum distance and without our ship keeping distance

[close]
The weird curves are likely simply due to the enemy ship passing through or behind our ship a lot, throwing aim completely off, if we can catch up to it and we don't have assumptions about minimum distance the enemy can't pass through or a distance our ship is trying to keep.

So what kind of an equation would this be? Let's use the dominator data and find out.


df$hitprob <- df$hitprob/max(df$hitprob)
library(interactions)

lm <- lm(hitprob ~ topspeed*turnrate,data = df)
png("interactplot.png")
interact_plot(lm, pred = topspeed, modx = turnrate, linearity.check = TRUE,
              plot.points = TRUE)
dev.off()
summary(lm)



interaction plot
[close]
output
 summary(lm)

Call:
lm(formula = hitprob ~ topspeed * turnrate, data = df)

Residuals:
     Min       1Q   Median       3Q      Max
-0.11553 -0.03131  0.01024  0.03508  0.07836

Coefficients:
                    Estimate Std. Error t value Pr(>|t|)   
(Intercept)        8.835e-01  1.451e-02  60.877  < 2e-16 ***
topspeed          -1.688e-03  1.211e-04 -13.931  < 2e-16 ***
turnrate           3.583e-03  8.050e-04   4.452 1.76e-05 ***
topspeed:turnrate  4.657e-05  6.720e-06   6.930 1.53e-10 ***
---
Signif. codes:  0 %u2018***%u2019 0.001 %u2018**%u2019 0.01 %u2018*%u2019 0.05 %u2018.%u2019 0.1 %u2018 %u2019 1

Residual standard error: 0.04585 on 136 degrees of freedom
Multiple R-squared:  0.8453,   Adjusted R-squared:  0.8418
F-statistic: 247.6 on 3 and 136 DF,  p-value: < 2.2e-16

[close]
So let's plot the function 8.835e-01-1.688e-03*s+3.583e-03*t+4.657e-05*s*t


plot code

functionplot <- data.frame()
8.835e-01-1.688e-03*s+3.583e-03*t+4.657e-05*s*t
for (s in seq(0,200,1)){
  for (t in seq(0,30,0.5)){
    y <- 8.835e-01-1.688e-03*s+3.583e-03*t+4.657e-05*s*t
    print(s)
    functionplot <- rbind(functionplot, c(y,s,t))
}
}
functionplot
names(functionplot) <- c("y","s","t")
ggplot(functionplot,aes(x=s,y=y,col=t))+
  geom_point()+
  scale_color_viridis_c()
[close]


s speed, t turn rate, y factor of hit probability

So that is a suggestion based on the model of a factor that should be included as a multiplier of the default hit rate vs. Dominator-sized ships based on enemy ship top speed and turret turn rate.
« Last Edit: November 18, 2022, 06:47:17 AM by CapnHector »
Logged
5 ships vs 5 Ordos: Executor · Invictus · Paragon · Astral · Legion · Onslaught · Odyssey | Video LibraryHiruma Kai's Challenge

intrinsic_parity

  • Admiral
  • *****
  • Posts: 3080
    • View Profile
Re: Optimizing the Conquest: a Mathematical Model of Space Combat
« Reply #107 on: November 18, 2022, 08:47:30 AM »

I mean, you aren't considering shot travel time/projectile velocity (which is huge if not primary factor in missing), so it definitely isn't that complicated. It's really just asking at each simulation step if the turret rotation rate is fast enough to track the instantaneous angular velocity of the target (more or less). The proportion of time that is true is approximately the modifier on the hit rate.

You're then claiming that the proportion of time in this simulation that is true/false is the same as the proportion in the game. I just don't see why that would be necessarily true. It seems very plausible that could be quite different in the game.

« Last Edit: November 18, 2022, 09:22:33 AM by intrinsic_parity »
Logged

CapnHector

  • Admiral
  • *****
  • Posts: 1056
    • View Profile
Re: Optimizing the Conquest: a Mathematical Model of Space Combat
« Reply #108 on: November 18, 2022, 09:05:10 AM »

I mean with regard to travel time you can just assume that this represents where the turret should be if travel time were accounted for, right? Given the x and y coordinates are not really tied to anything. So I don't really see why that would matter for describing turret rotation. However, Vanshilar found that to be a minor component only earlier in the previous thread so that would be the main reason to not worry too much about it. Essentially shots generally travel only a fraction of a second so most of the time that is not the main issue.

Whether it's the same as in the game - well, if you assume the enemy ship movement is generally described by some normal distribution (in aggregate, even though it might not seem so during one engagement) then this method would tell you the more difficult to calculate quantity of how that would affect hit rate. So it's not "necessarily true" in a logical sense at all. Only an attempt to provide a concise and usable formulation of it, maybe it makes sense and maybe not but it's a theory and was fun to make.

Better ideas for the math?
Logged
5 ships vs 5 Ordos: Executor · Invictus · Paragon · Astral · Legion · Onslaught · Odyssey | Video LibraryHiruma Kai's Challenge

intrinsic_parity

  • Admiral
  • *****
  • Posts: 3080
    • View Profile
Re: Optimizing the Conquest: a Mathematical Model of Space Combat
« Reply #109 on: November 18, 2022, 10:21:05 AM »

I wasn't saying it was wrong, just saying the interaction itself isn't really complicated, and the thing that is actually being analyzed is how frequently the specific random motion generates certain relative velocity conditions, and that frequency is not clearly related to the actual game.

Also, saying 'shots only travel for a fraction of a second' is not evidence that velocity is negligible. Ships can also completely change course in fractions of a second. It's question of the relative values of those things. It's definitely pretty possible (and common) to dodge projectiles at moderate/long range by simply strafing when the enemy fires, which is the effect I am talking about.

The question is 'if I use current velocity to predict the targets future position and aim there, but then the target accelerates after I fire, how far off will my shot be?'.


But like I've said before, by far the most useful thing to add to the simulation IMO is simply the enemy returning fire. DPS checks for shields don't mean much without the associated flux dynamics. I did some analysis of pure shield/flux dynamics a while ago, took me forever to find the thread (https://fractalsoftworks.com/forum/index.php?topic=19099.0)

The actual analysis is a few comments down, not the main topic, and focused on looking at the value of caps vs vents, so I'll just copy paste the gist of it.

Spoiler
Consider two ships engaging one another. We assume that the ships engage and fire until overload but we make no claim that this is a realistic model of combat, merely that it is useful for analyzing who is more capable of winning the engagement in a brawl.  One possible metric that approximates the degree to which ship 1 defeats ship 2 in the flux war is the relative time to overload. Increasing this value indicates improvement in performance for ship 1. The difference between the time to overload of two ships determines who will overload first. Time to overload for a single ship is generally:

TTO = total capacity/flux generation = total capacity/(shield upkeep + Incoming flux from damage + net weapon flux generation)

The terms are all generally functions of ship characteristics like shield efficiencies, weapons, skills and hull mods.

TTO has the general form
TTO = (A + 200*#caps)/(B - 10*#vents)
with
A = the base capacity,
B = a sum of shield upkeep, flux generation due to enemy weapons, flux generation due to friendly weapons, minus base dissipation)
(There's actually a bit more complexity here as if dissipation exceeds soft flux generation, there is no additional benefit. This is easy to simulate, but annoying to write down analytically so I've ignored it here, but it is simulated correctly)
[close]

That was handy because it didn't require discrete simulation of combat like armor does, so I wouldn't say it's directly applicable to this simulation. The point is that what matters in the shield battle is actually the ratio of how much flux you're generating in your own ships vs the opponent along with the capacities of the ships. All the DPS in the world won't matter if you generate more flux so that you still max out first. I think it is very important to consider your own flux levels and your opponent returning fire in any realistic combat simulation, and certainly for any attempt at choosing a good loadout.

Btw, is there a GitHub for the python code? I have zero interest in learning R (I already know enough slow high level languages lol), but I've worked with python before.
« Last Edit: November 18, 2022, 10:28:27 AM by intrinsic_parity »
Logged

CapnHector

  • Admiral
  • *****
  • Posts: 1056
    • View Profile
Re: Optimizing the Conquest: a Mathematical Model of Space Combat
« Reply #110 on: November 18, 2022, 10:36:10 PM »

Liral was talking about making a GitHub and it would definitely be a good idea if multiple people want to contribute. Sadly I haven't had a chance to learn Python yet, maybe later. But you can definitely use whatever models I've put out if it seems worthwhile.
Logged
5 ships vs 5 Ordos: Executor · Invictus · Paragon · Astral · Legion · Onslaught · Odyssey | Video LibraryHiruma Kai's Challenge

Vanshilar

  • Admiral
  • *****
  • Posts: 655
    • View Profile
Re: Optimizing the Conquest: a Mathematical Model of Space Combat
« Reply #111 on: November 19, 2022, 01:26:01 AM »

This graph has me thinking Advanced turret gyros should be worth taking almost routinely.

I'm not seeing much effect of having turret gyros or not.

I took my 5-Conquest fleet (me in flagship Medusa, along with Gryphon as flanker) out and tried a couple of different variations against the 2-Ordos fleet. In all cases, the Conquests had Squall, Locust, Mjolnir, Gauss, HVD, Heavy Mauler, and 2 Harpoons. In each of these cases, the enemy fighters were removed (through modifying ship_data.csv to not have any fighter bays), and hulks were removed as soon as they appeared via repeatedly using the "removehulks" command whenever a ship died. Thus, the reasons for non-hits are misses (ship wasn't where the projectile was headed) and overkill (ship died while projectile was en route), and eliminating fighters and hulks as causes for missing.

The 3 cases were:
1. Without turret gyros. This means the Conquests had 29400 flux capacity each.
2. With turret gyros, which means the Conquests had 27400 instead of 29400 flux capacity (i.e. accounting for the fact that turret gyros take up OP).
3. With turret gyros built-in as a 4th s-mod, essentially getting the turret gyro hullmod for free (i.e. retaining 29400 flux capacity).

The results were as below:

Code
No enemy fighters, remove hulks, no turret gyros (SS 4710)
shield armor hull hits fired hitrate time %squall weapon
150821 8460 18140 853 1560 54.68% 3.380 100.00% squall
47207 10106 52730 3027 5190 58.32% 2.566 75.92% locust
57825 36405 61989 588 747 78.71% 1.868 55.25% mjolnir
78687 13555 34173 247 352 70.17% 2.347 69.43% gauss
39575 3686 13451 287 353 81.30% 2.353 69.63% HVD
9820 19148 14378 330 456 72.37% 2.533 74.95% heavy mauler
38672 23994 51449 233 344 67.73% 0.860 25.44% harpoon

No enemy fighters, remove hulks, with turret gyros costing 10 OP (SS 4748)
shield armor hull hits fired hitrate time %squall weapon
188287 9449 16738 998 1762 56.64% 3.818 100.00% squall
47958 12082 60546 3369 5505 61.20% 2.722 71.30% locust
61259 36099 54801 584 697 83.79% 1.743 45.64% mjolnir
85253 14662 38267 265 386 68.65% 2.573 67.41% gauss
43385 3477 12934 279 337 82.79% 2.247 58.85% HVD
10601 18365 13007 334 441 75.74% 2.450 64.18% heavy mauler
23933 22877 42788 170 292 58.22% 0.730 19.12% harpoon

No enemy fighters, remove hulks, with turret gyros for free (SS 4824)
shield armor hull hits fired hitrate time %squall weapon
183502 10871 18071 994 1660 59.88% 3.597 100.00% squall
49771 10355 61249 3176 5358 59.28% 2.649 73.66% locust
64354 36178 61211 611 748 81.68% 1.870 51.99% mjolnir
84069 14829 43667 270 398 67.84% 2.653 73.77% gauss
46394 3473 14685 290 353 82.15% 2.353 65.43% HVD
8490 22312 16665 341 453 75.28% 2.517 69.97% heavy mauler
24686 13529 35082 154 264 58.33% 0.660 18.35% harpoon

Of note, I realized that in my past data, the reason why Locusts had such a high uptime was because I forgot to account for that they get +50% fire rate due to Missile Spec. I had that factor for the Squalls but not for the Locusts. (Found it weird that even without fighters around, Locusts still had way too high of an uptime.) So some of my past stats for the Locust are incorrect for the time and %squall values, both of which need to be multiplied by 2/3; but the rest are correct.

Note that these values above are *not* valid for the typical Ordos fight, since they're with enemy fighters and hulks removed, so the actual hit rate is lower. The Mjolnir seems to have improved by around 4%, the Gauss got worse by around 2%, the HVD improved by around 1%, and the Heavy Mauler improved by around 3% in terms of their hit rates. So overall, an average of around a 1.6% improvement when the base rate was around 76% hit rate -- so it's small enough that it's unclear if this is just due to random error, since I only ran these fights once each. That the Gauss actually got slightly worse for example might mean that it was "luckier" during the first fight compared to the other two.

So I don't really see taking the hullmod as making a meaningful improvement in this case.

The question then is what is the cause of the remaining misses. The Gauss has the highest projectile velocity out of all of them (1200, compared with 900 for Mjolnir, 1000 for HVD, and 900 for Heavy Mauler), plus no spread, so it should be the most accurate when fired. However, its hit rate is consistently lower than the others. The two biggest factors are its low turn rate and its chargeup. It's the only one here with a chargeup of 1 second before firing, whereas the other weapons have 0 chargeup delay. The reason why this is crucial is that when a weapon isn't firing, its turn rate is 5 times (I think) its normal turn rate. However, when it's firing or when it's charging up to fire or during cooldown, its turn rate is what's given in weapon_data.csv. So the other weapons will have a very fast turn rate just before firing, so the shot will be reasonably accurate. After each shot, if the target has moved too far off-target, they'll simply stop firing and track at the 5x rate before firing again. This means that even the Hellbore, the slowest one of the bunch (other than Gauss) at 5 degrees per second, will be tracking at 25 degrees per second just before it fires. Most weapons will be tracking at 50 degrees per second or higher before they fire.

For the Gauss, it's different. When it thinks it's ready to fire, there'll be a 1-second delay while it's charging up, and it'll be tracking at 3 degrees per second during that time, before firing. So that 3 degrees per second is all the correction it gets during that 1 second delay to account for target movement and the firing ship turning. If a target is 1000 su away, that amounts to 52.4 su. So yeah unless the firing ship is helping the Gauss track a target, it's going to miss quite a bit.

To test for this, I did the above test again, with turret gyros for free (i.e. as the 4th built-in s-mod), but this time, I changed the Gauss's chargeup from 1 to 0 and chargedown from 1 to 2. So it still has a refire delay of 2 seconds, but now it fires right away and then cooldowns for 2 seconds, instead of charging up for a second beforehand then a second after. The result was:

Code
No enemy fighters, remove hulks, with turret gyros for free, Gauss set to chargeup 0, chargedown 2 (SS 4863)
shield armor hull hits fired hitrate time %squall weapon
167454 9635 22689 954 1667 57.23% 3.612 100.00% squall
51496 10317 54776 3137 5460 57.45% 2.700 74.75% locust
55386 32846 56820 540 719 75.10% 1.798 49.77% mjolnir
103068 20057 41243 322 409 78.73% 2.727 75.49% gauss
38429 3629 11576 268 340 78.82% 2.267 62.76% HVD
9416 18399 13521 314 441 71.20% 2.450 67.83% heavy mauler
29587 16313 37348 177 284 62.32% 0.710 19.66% harpoon

The Gauss ended up having one of the best hit rates. So yeah, the chargeup is the reason why its hit rate is lower. Putting turret gyros on won't really help all that much; there's probably something better to do with that 10 OP (put into caps if nothing else).
Logged

CapnHector

  • Admiral
  • *****
  • Posts: 1056
    • View Profile
Re: Optimizing the Conquest: a Mathematical Model of Space Combat
« Reply #112 on: November 19, 2022, 02:09:39 AM »

Oh, I did not know that about turn rates and chargeup. Makes perfect sense! So 1) the model is off, since it assumes we are using base turnrate all the time and 2) seems like Gauss has an entirely different reason for missing that I didn't account for (chargeup)

Anyway, should then use 5 x t if you want to compare to graph above, so the prediction becomes different: we should only see significant differences when the enemy is routinely moving at 100 px/sec or more. (Since even Gauss, the slowest, will be on the t=15 curve for tracking the enemy - but of course, the model applies poorly to Gauss due to chargeup.) Obviously that makes turret gyros much more relative.

Thanks for the data, it's been invaluable on several occasions.

Edit to add: is there a way to get movement speed data out of those simulations?

If we assume the AI movement is distributed normally over a large number of moves, then we can use the above model to model weapon accuracy due to it drawing samples of movement from the same distribution as the AI. So that will let us model weapon accuracy vs moving ships via process above. But we can only make educated guesses about what the parameters of the normal distribution of AI moves across a very large number of moves are and above I guessed sd=topspeed/2 (based on the idea that it should be rare for the ship to move above its top speed). But that might be wrong and that would of course mean the model is not accurate because of that too.

Is there a way to get an answer to the question: during an average combat, what is the distribution of the AI's movement speed compared to top speed? Is it moving at an average of 1/3, 1/4, 1/2 of top speed?

(E2: re-read table and your post)
« Last Edit: November 19, 2022, 07:14:13 PM by CapnHector »
Logged
5 ships vs 5 Ordos: Executor · Invictus · Paragon · Astral · Legion · Onslaught · Odyssey | Video LibraryHiruma Kai's Challenge

Liral

  • Admiral
  • *****
  • Posts: 725
  • Realistic Combat Mod Author
    • View Profile
Re: Optimizing the Conquest: a Mathematical Model of Space Combat
« Reply #113 on: November 19, 2022, 06:32:01 PM »

Btw, is there a GitHub for the python code?

Liral was talking about making a GitHub and it would definitely be a good idea if multiple people want to contribute.

A GitHub is useful only if CapnHector writes research code in Python because I don't know anyone else willing to contribute unless intrinsic_party has hereby volunteered; else, I suppose each will post code to the thread.

Python Data Loading Code
import os
import csv
import json
from sys import platform


def vanilla_data_path():
    """
    Return the path from the mods folder to to the
    vanilla data folder.
   
    Path depends on OS.
    """
    if platform == "linux": return #linux path
    elif platform == "darwin": return #OS X path
    elif platform == "win32": return #windows path


def sub_directory_paths(path):
    """
    Return a list of the relative paths of the
    directories within this one.
    """
    return [f.path for f in os.scandir(path) if f.is_dir()]


def csv_dictionary(path):
    """
    Return a nested dictionary representation of
    the csv at the path.
    """
    with open(path) as f:
        reader = csv.reader(f)
        return {row[0] : {reader[0] : v for i, v in enumerate(row)}
                         for row in reader[1:] if row[0] != ""}


def dictionary(path):
    """
    Return the data of the ships and weapons of this
    source, organized by origin.
    """
    dictionary = {}
    os.chdir("weapons")
    dictionary["weapon_data.csv"] = csv_dictionary("weapon_data.csv")
    os.chdir("../hulls")
    dictionary["ship_data.csv"] = csv_dictionary("weapon_data.csv")
    dictionary[".ship"] = {ship_id : json.load(ship_id + ".ship") for
                          ship_id in dictionary[path]["ship_data.csv"]}
    return dictionary
   

def data():
    """
    Consolidate the ship and weapon data of vanilla
    (and every mod selected by the user) into one
    dictionary for simulation and calculation use.

    The structure of this dictionary is

    {
        "sourceId":{
            "ships":{
                "shipId":{
                    "attributeId":value
                }
            },
            "weapons" : {
                "weaponId":{
                    "attributeId":value
                }
            }
        }
    }

    where sourceId is "vanilla" or the
    corresponding mod id and every shipId, weaponId,
    and attributeId is taken from the game or mod
    files.
    """
    data = {}
    root = os.path.abspath(os.getcwd())
    os.chdir("..")
    for path in sub_directory_paths():
        os.chdir(path)
        data[path] = dictionary(path)
        os.chdir("..")
    os.chdir(vanilla_data_path())
    add_data(mod_path, data)
[close]

Quote
I have zero interest in learning R (I already know enough slow high level languages lol), but I've worked with python before.

Sadly I haven't had a chance to learn Python yet, maybe later. But you can definitely use whatever models I've put out if it seems worthwhile.

I knew Python but not R when I started and no interest in learning it, either, but learned R in one sitting because R and Python have almost the same syntax.  I've even posted a handy guide to the handful of differences to this thread.  Our language barrier is trivially surmounted.  8)
« Last Edit: November 19, 2022, 07:16:57 PM by Liral »
Logged

intrinsic_parity

  • Admiral
  • *****
  • Posts: 3080
    • View Profile
Re: Optimizing the Conquest: a Mathematical Model of Space Combat
« Reply #114 on: November 19, 2022, 06:55:11 PM »

I figure GitHub might be nice if the ultimate goal is making something more broadly useful to the community. I wouldn't mind contributing either.
Logged

CapnHector

  • Admiral
  • *****
  • Posts: 1056
    • View Profile
Re: Optimizing the Conquest: a Mathematical Model of Space Combat
« Reply #115 on: November 19, 2022, 10:03:00 PM »

Don't we basically have all the pieces now? Since we now have methods to calculate damage, a method to generate discrete sequences of shots/sec from basic values for beams and guns (my posts before the accuracy thing). The turn rate thing can be skipped for now since the output of that analysis - if any is reached - will be 1 straightforward multiplier to apply to hitrate based on enemy top speed and turret turn rate.

So to make the tool, what's needed now are tools to import the relevant values e.g. ship width, and a few minor improvements to the damage code (beam weapons, soft flux) - right? What's the most up to date version of the damage code?
Logged
5 ships vs 5 Ordos: Executor · Invictus · Paragon · Astral · Legion · Onslaught · Odyssey | Video LibraryHiruma Kai's Challenge

Liral

  • Admiral
  • *****
  • Posts: 725
  • Realistic Combat Mod Author
    • View Profile
Re: Optimizing the Conquest: a Mathematical Model of Space Combat
« Reply #116 on: November 20, 2022, 06:20:04 AM »

Don't we basically have all the pieces now? Since we now have methods to calculate damage, a method to generate discrete sequences of shots/sec from basic values for beams and guns (my posts before the accuracy thing). The turn rate thing can be skipped for now since the output of that analysis - if any is reached - will be 1 straightforward multiplier to apply to hitrate based on enemy top speed and turret turn rate.

So to make the tool, what's needed now are tools to import the relevant values e.g. ship width, and a few minor improvements to the damage code (beam weapons, soft flux) - right? What's the most up to date version of the damage code?

The Python code I wrote imports all the values as a giant dictionary, sorted by
{
    mod_id:{
        weapon_data.csv:{
            weapon_id:{
                column_id:value
            }
        },
        ship_data.csv:{
            ship_id:{
                column_id:value
            }
        },
        some_ship.ship:{
            #ship file contents
        },
        other_ship.ship:{
            #ship file contents
        },
        ...
    }
}

Access the dictionary by writing data[mod_id][origin][ship_or_weapon_id][attribute_id], with the same .ship file being further nested as in the .ship file itself.  Note that all the values are strings.  I could write a wrapper class with accessor methods if desired.

The most up to date Python version of the damage code has none of these features you have mentioned.  I have been awaiting your R version to translate.
« Last Edit: November 20, 2022, 06:23:24 AM by Liral »
Logged

CapnHector

  • Admiral
  • *****
  • Posts: 1056
    • View Profile
Re: Optimizing the Conquest: a Mathematical Model of Space Combat
« Reply #117 on: November 20, 2022, 07:36:57 AM »

Whoops, sorry, didn't realize I was the hold-up. Try to add asap. I have one more question, does anybody know the answer? If a ship has x hard flux and y soft flux and lowers shields, regenerating z flux, then how is z proportioned among hard flux and soft flux? After 1 second, is it
a) x <- x-z, y <- y, if x > z, else x -> 0 and y -> y-(z-x) (ie. hard flux goes first)
b) x <- x-z(x/(x+y)), y <- y-z(y/(x+y)) (ie. dissipated proportionally)
c) y <- y-z, x <- x, if y > z, else y -> 0 and x -> x-(z-y) (ie. soft flux goes first)
something else entirely?

List of features to implement
- Code must include a parameter for shield radius
- Beams: beams hit with dps/2 hit str but do damage according to their shot distribution, and always in 1 shot
- Soft flux: dissipate only soft on turns when using shields, else hard also

I am also thinking beams shouldn't have the SD error thing unlike ballistics, because beams seem to have perfect tracking when no spread. Edit: maybe they still should cause it includes enemy rotation, too.

Comments?
« Last Edit: November 20, 2022, 08:55:28 AM by CapnHector »
Logged
5 ships vs 5 Ordos: Executor · Invictus · Paragon · Astral · Legion · Onslaught · Odyssey | Video LibraryHiruma Kai's Challenge

Vanshilar

  • Admiral
  • *****
  • Posts: 655
    • View Profile
Re: Optimizing the Conquest: a Mathematical Model of Space Combat
« Reply #118 on: November 20, 2022, 09:39:09 AM »

I have one more question, does anybody know the answer? If a ship has x hard flux and y soft flux and lowers shields, regenerating z flux, then how is z proportioned among hard flux and soft flux?

Soft flux is always dissipated before any hard flux is dissipated. So if there's any soft flux, it gets counted first. Only what's left over goes toward hard flux, and only if the shields are down. (If the shields are up, then no hard flux gets removed.) If the target has Field Modulation, then it's that once there's only hard flux left, if shields are up, then 15% of the flux dissipation goes toward hard flux, instead of 0%.
Logged

Liral

  • Admiral
  • *****
  • Posts: 725
  • Realistic Combat Mod Author
    • View Profile
Re: Optimizing the Conquest: a Mathematical Model of Space Combat
« Reply #119 on: November 20, 2022, 03:03:04 PM »

Whoops, sorry, didn't realize I was the hold-up. Try to add asap. I have one more question, does anybody know the answer? If a ship has x hard flux and y soft flux and lowers shields, regenerating z flux, then how is z proportioned among hard flux and soft flux? After 1 second, is it
a) x <- x-z, y <- y, if x > z, else x -> 0 and y -> y-(z-x) (ie. hard flux goes first)
b) x <- x-z(x/(x+y)), y <- y-z(y/(x+y)) (ie. dissipated proportionally)
c) y <- y-z, x <- x, if y > z, else y -> 0 and x -> x-(z-y) (ie. soft flux goes first)
something else entirely?

List of features to implement
- Code must include a parameter for shield radius
- Beams: beams hit with dps/2 hit str but do damage according to their shot distribution, and always in 1 shot
- Soft flux: dissipate only soft on turns when using shields, else hard also

I am also thinking beams shouldn't have the SD error thing unlike ballistics, because beams seem to have perfect tracking when no spread. Edit: maybe they still should cause it includes enemy rotation, too.

Comments?

I think you're adding necessary features, and I want modders to be able to limit execution time enough for iterative workflow: run the tool, comprehend the output, evaluate balance accordingly, try something to improve the balance, repeat.  Immediately displaying understandable, quantitative consequences of balance decisions across many matchups could reduce the time and effort modders need to find the ship or weapon attribute values that would leave users with diverse and interesting choices and flag some counterintuitive or simply-neglected potential problems before release.  If we included a flag that would limit iteration to variants, I bet the tool could run fast enough for these purposes.

Here's an example: testing the variants 10 ships from a mod against the variants of a 'standard group' of 100 ships would entail (4 variants x 10 mod ships) x (4 variants x 100 group ships) = 40 x 400 = 16,000 matchups.  If each matchup ran in one millisecond, then one worker would need just 16 seconds to run the test.  Four workers could do it in 4 seconds—fast enough for modders to tolerate repeatedly.  We have nearly made something useful!  ;D
Pages: 1 ... 6 7 [8] 9 10 ... 32