Menu
News
All News
Dungeons & Dragons
Level Up: Advanced 5th Edition
Pathfinder
Starfinder
Warhammer
2d20 System
Year Zero Engine
Industry News
Reviews
Dragon Reflections
White Dwarf Reflections
Columns
Weekly Digests
Weekly News Digest
Freebies, Sales & Bundles
RPG Print News
RPG Crowdfunding News
Game Content
ENterplanetary DimENsions
Mythological Figures
Opinion
Worlds of Design
Peregrine's Nest
RPG Evolution
Other Columns
From the Freelancing Frontline
Monster ENcyclopedia
WotC/TSR Alumni Look Back
4 Hours w/RSD (Ryan Dancey)
The Road to 3E (Jonathan Tweet)
Greenwood's Realms (Ed Greenwood)
Drawmij's TSR (Jim Ward)
Community
Forums & Topics
Forum List
Latest Posts
Forum list
*Dungeons & Dragons
Level Up: Advanced 5th Edition
D&D Older Editions, OSR, & D&D Variants
*TTRPGs General
*Pathfinder & Starfinder
EN Publishing
*Geek Talk & Media
Search forums
Chat/Discord
Resources
Wiki
Pages
Latest activity
Media
New media
New comments
Search media
Downloads
Latest reviews
Search resources
EN Publishing
Store
EN5ider
Adventures in ZEITGEIST
Awfully Cheerful Engine
What's OLD is NEW
Judge Dredd & The Worlds Of 2000AD
War of the Burning Sky
Level Up: Advanced 5E
Events & Releases
Upcoming Events
Private Events
Featured Events
Socials!
EN Publishing
Twitter
BlueSky
Facebook
Instagram
EN World
BlueSky
YouTube
Facebook
Twitter
Twitch
Podcast
Features
Top 5 RPGs Compiled Charts 2004-Present
Adventure Game Industry Market Research Summary (RPGs) V1.0
Ryan Dancey: Acquiring TSR
Q&A With Gary Gygax
D&D Rules FAQs
TSR, WotC, & Paizo: A Comparative History
D&D Pronunciation Guide
Million Dollar TTRPG Kickstarters
Tabletop RPG Podcast Hall of Fame
Eric Noah's Unofficial D&D 3rd Edition News
D&D in the Mainstream
D&D & RPG History
About Morrus
Log in
Register
What's new
Search
Search
Search titles only
By:
Forums & Topics
Forum List
Latest Posts
Forum list
*Dungeons & Dragons
Level Up: Advanced 5th Edition
D&D Older Editions, OSR, & D&D Variants
*TTRPGs General
*Pathfinder & Starfinder
EN Publishing
*Geek Talk & Media
Search forums
Chat/Discord
Menu
Log in
Register
Install the app
Install
Upgrade your account to a Community Supporter account and remove most of the site ads.
Community
General Tabletop Discussion
*Dungeons & Dragons
The math of the GWF Fighting Style and why its as good as a +1 (and possibly better than defense)
JavaScript is disabled. For a better experience, please enable JavaScript in your browser before proceeding.
You are using an out of date browser. It may not display this or other websites correctly.
You should upgrade or use an
alternative browser
.
Reply to thread
Message
<blockquote data-quote="Asisreo" data-source="post: 9452110" data-attributes="member: 7019027"><p>OK, fine. How about this:</p><p></p><p>I made a simulation that takes two fighters, both level 20. They are fighting an enemy. We assume the fighters have a 65% chance to hit the enemy. One fighter deals 2d6 + 6 damage to represent the fighter with GWF and the other does 2d6+5 as a defense-fighter. The enemy has a 65% chance to hit the first fighter while they have a 60% chance to hit the second fighter.</p><p></p><p>The fighters are purely going to attack 4 times each before the enemy gets a chance to attack and deal anywhere from 30 - 70 damage. This approximates the damage that each fighter could be expected to take at level 20 in a single turn, its somewhat low because of situations where the enemy decides to do less damage but AoE, the enemy attacks somewhat else, the enemy is stunned, the fighter gets healed, etc.</p><p></p><p>The fighter's hp is set to 224. The enemy's HP is randomly chosen between 1 and 169 to represent uncertainty of their health from mooks to bosses (169 is the tarrasque's health divided by 4, to represent each other player pulling their weight).</p><p></p><p>The simulation outputs the number of times the fighter dies and the average number of turns each fighter needs to defeat the enemy per combat when they don't die.</p><p></p><p>I iterated this simulation 10,000 times. The output I got was:</p><p></p><p>Number of deaths for Fighter 1 (2d6+6 damage, 65% hit probability): 5616</p><p>Number of deaths for Fighter 2 (2d6+5 damage, 60% hit probability): 5475</p><p>Average turns for Fighter 1 (2d6+6 damage, 65% hit probability): 4.76</p><p>Average turns for Fighter 2 (2d6+5 damage, 60% hit probability): 5.15</p><p></p><p>The difference between the fighter's death are 141 deaths. Out of the 10,000 enemies, the +1 AC bonus mattered for 1.41% of them. In contrast, the +1 damage reduces the average turns needed to kill by 0.39, meaning that after 3 combats, you killed an enemy quicker than you would have without GWF.</p><p></p><p>I don't know about you, but I don't think I'll make it to 10,000 enemies in a campaign, and if I do, I don't think it wise to take the extra 1% extra death insurance rather than saving 333 rounds against an enemy. If not for survival purposes, it end the combat quicker.</p><p></p><p>If you have a problem with my assumptions and think that your assumptions would be more realistic, be my guest.</p><p></p><p>[CODE=c]#include <stdio.h></p><p>#include <stdlib.h></p><p>#include <time.h></p><p></p><p>#define NUM_SIMULATIONS 10000</p><p>#define HP 224</p><p></p><p>// Function to simulate rolling two dice and adding the damage with a bonus</p><p>int roll_damage(int bonus) {</p><p> int roll1 = rand() % 6 + 1;</p><p> int roll2 = rand() % 6 + 1;</p><p> return roll1 + roll2 + bonus;</p><p>}</p><p></p><p>// Function to simulate the probability of getting hit</p><p>int is_hit(double probability) {</p><p> return (rand() % 100) < (probability * 100);</p><p>}</p><p></p><p>// Function to simulate the number of attacks before getting hit</p><p>int attacks_before_hit(double attack_probability) {</p><p> int attacks = 0;</p><p> while (attacks < 4 && is_hit(attack_probability)) {</p><p> attacks++;</p><p> }</p><p> return attacks;</p><p>}</p><p></p><p>// Function to simulate a single fighter's attempt to reach the target damage threshold</p><p>int simulate_fighter(int target_damage, int damage_bonus, double hit_probability) {</p><p> int current_damage = 0;</p><p> int turns = 0;</p><p> int hp = HP;</p><p></p><p> while (current_damage < target_damage && hp > 0) {</p><p> // Determine the number of attacks before the fighter is hit</p><p> int num_attacks = attacks_before_hit(0.65); // Both fighters attack with 65% probability</p><p></p><p> // Apply the attacks</p><p> for (int i = 0; i < num_attacks; i++) {</p><p> // Roll damage</p><p> int damage = roll_damage(damage_bonus);</p><p> current_damage += damage;</p><p> turns++;</p><p></p><p> // Check if the fighter gets hit after each attack</p><p> if (is_hit(hit_probability)) {</p><p> int attack_damage = rand() % 41 + 30; // Attack damage from 30 to 70</p><p> hp -= attack_damage;</p><p> if (hp <= 0) {</p><p> return -1; // Fighter lost all HP before reaching the target</p><p> }</p><p> }</p><p> }</p><p> }</p><p></p><p> if (hp > 0) {</p><p> return turns; // Return the number of turns required if the fighter survived</p><p> } else {</p><p> return -1; // Return -1 if the fighter died</p><p> }</p><p>}</p><p></p><p>int main() {</p><p> srand(time(NULL)); // Seed the random number generator</p><p></p><p> int deaths_fighter1 = 0;</p><p> int deaths_fighter2 = 0;</p><p> double total_turns_fighter1 = 0;</p><p> double total_turns_fighter2 = 0;</p><p> int survivals_fighter1 = 0;</p><p> int survivals_fighter2 = 0;</p><p></p><p> for (int i = 0; i < NUM_SIMULATIONS; i++) {</p><p> int target_damage = rand() % 169 + 1; // Random target damage between 1 and 169</p><p></p><p> // Simulate Fighter 1</p><p> int result1 = simulate_fighter(target_damage, 6, 0.65);</p><p> if (result1 == -1) {</p><p> deaths_fighter1++;</p><p> } else {</p><p> total_turns_fighter1 += result1;</p><p> survivals_fighter1++;</p><p> }</p><p></p><p> // Simulate Fighter 2</p><p> int result2 = simulate_fighter(target_damage, 5, 0.60); // Updated hit probability to 60%</p><p> if (result2 == -1) {</p><p> deaths_fighter2++;</p><p> } else {</p><p> total_turns_fighter2 += result2;</p><p> survivals_fighter2++;</p><p> }</p><p> }</p><p></p><p> // Calculate average turns for each fighter</p><p> double avg_turns_fighter1 = survivals_fighter1 > 0 ? total_turns_fighter1 / survivals_fighter1 : 0;</p><p> double avg_turns_fighter2 = survivals_fighter2 > 0 ? total_turns_fighter2 / survivals_fighter2 : 0;</p><p></p><p> // Print the results</p><p> printf("Number of deaths for Fighter 1 (2d6+6 damage, 65%% hit probability): %d\n", deaths_fighter1);</p><p> printf("Number of deaths for Fighter 2 (2d6+5 damage, 60%% hit probability): %d\n", deaths_fighter2);</p><p> printf("Average turns for Fighter 1 (2d6+6 damage, 65%% hit probability): %.2f\n", avg_turns_fighter1);</p><p> printf("Average turns for Fighter 2 (2d6+5 damage, 60%% hit probability): %.2f\n", avg_turns_fighter2);</p><p></p><p> return 0;</p><p>}</p><p>[/CODE]</p><p></p><p>And if my code looks kinda like spaghetti, it is. I wanted to write in python, but it would take far too long for the code to run, so its in C which I barely know how to code. I got assistance from ChatGPT, so also feel free to scrutinize the code itself, but it seems passable from my review. </p><p></p><p>And yeah, I know, whiteboard analysis, but I think the results are dramatic enough and the simulation takes enough cases into account that we can at least use it as a rough guide to our thinking.</p><p></p><p>Edit: 1.41% not .014% and 10,000 instead of 1,000</p></blockquote><p></p>
[QUOTE="Asisreo, post: 9452110, member: 7019027"] OK, fine. How about this: I made a simulation that takes two fighters, both level 20. They are fighting an enemy. We assume the fighters have a 65% chance to hit the enemy. One fighter deals 2d6 + 6 damage to represent the fighter with GWF and the other does 2d6+5 as a defense-fighter. The enemy has a 65% chance to hit the first fighter while they have a 60% chance to hit the second fighter. The fighters are purely going to attack 4 times each before the enemy gets a chance to attack and deal anywhere from 30 - 70 damage. This approximates the damage that each fighter could be expected to take at level 20 in a single turn, its somewhat low because of situations where the enemy decides to do less damage but AoE, the enemy attacks somewhat else, the enemy is stunned, the fighter gets healed, etc. The fighter's hp is set to 224. The enemy's HP is randomly chosen between 1 and 169 to represent uncertainty of their health from mooks to bosses (169 is the tarrasque's health divided by 4, to represent each other player pulling their weight). The simulation outputs the number of times the fighter dies and the average number of turns each fighter needs to defeat the enemy per combat when they don't die. I iterated this simulation 10,000 times. The output I got was: Number of deaths for Fighter 1 (2d6+6 damage, 65% hit probability): 5616 Number of deaths for Fighter 2 (2d6+5 damage, 60% hit probability): 5475 Average turns for Fighter 1 (2d6+6 damage, 65% hit probability): 4.76 Average turns for Fighter 2 (2d6+5 damage, 60% hit probability): 5.15 The difference between the fighter's death are 141 deaths. Out of the 10,000 enemies, the +1 AC bonus mattered for 1.41% of them. In contrast, the +1 damage reduces the average turns needed to kill by 0.39, meaning that after 3 combats, you killed an enemy quicker than you would have without GWF. I don't know about you, but I don't think I'll make it to 10,000 enemies in a campaign, and if I do, I don't think it wise to take the extra 1% extra death insurance rather than saving 333 rounds against an enemy. If not for survival purposes, it end the combat quicker. If you have a problem with my assumptions and think that your assumptions would be more realistic, be my guest. [CODE=c]#include <stdio.h> #include <stdlib.h> #include <time.h> #define NUM_SIMULATIONS 10000 #define HP 224 // Function to simulate rolling two dice and adding the damage with a bonus int roll_damage(int bonus) { int roll1 = rand() % 6 + 1; int roll2 = rand() % 6 + 1; return roll1 + roll2 + bonus; } // Function to simulate the probability of getting hit int is_hit(double probability) { return (rand() % 100) < (probability * 100); } // Function to simulate the number of attacks before getting hit int attacks_before_hit(double attack_probability) { int attacks = 0; while (attacks < 4 && is_hit(attack_probability)) { attacks++; } return attacks; } // Function to simulate a single fighter's attempt to reach the target damage threshold int simulate_fighter(int target_damage, int damage_bonus, double hit_probability) { int current_damage = 0; int turns = 0; int hp = HP; while (current_damage < target_damage && hp > 0) { // Determine the number of attacks before the fighter is hit int num_attacks = attacks_before_hit(0.65); // Both fighters attack with 65% probability // Apply the attacks for (int i = 0; i < num_attacks; i++) { // Roll damage int damage = roll_damage(damage_bonus); current_damage += damage; turns++; // Check if the fighter gets hit after each attack if (is_hit(hit_probability)) { int attack_damage = rand() % 41 + 30; // Attack damage from 30 to 70 hp -= attack_damage; if (hp <= 0) { return -1; // Fighter lost all HP before reaching the target } } } } if (hp > 0) { return turns; // Return the number of turns required if the fighter survived } else { return -1; // Return -1 if the fighter died } } int main() { srand(time(NULL)); // Seed the random number generator int deaths_fighter1 = 0; int deaths_fighter2 = 0; double total_turns_fighter1 = 0; double total_turns_fighter2 = 0; int survivals_fighter1 = 0; int survivals_fighter2 = 0; for (int i = 0; i < NUM_SIMULATIONS; i++) { int target_damage = rand() % 169 + 1; // Random target damage between 1 and 169 // Simulate Fighter 1 int result1 = simulate_fighter(target_damage, 6, 0.65); if (result1 == -1) { deaths_fighter1++; } else { total_turns_fighter1 += result1; survivals_fighter1++; } // Simulate Fighter 2 int result2 = simulate_fighter(target_damage, 5, 0.60); // Updated hit probability to 60% if (result2 == -1) { deaths_fighter2++; } else { total_turns_fighter2 += result2; survivals_fighter2++; } } // Calculate average turns for each fighter double avg_turns_fighter1 = survivals_fighter1 > 0 ? total_turns_fighter1 / survivals_fighter1 : 0; double avg_turns_fighter2 = survivals_fighter2 > 0 ? total_turns_fighter2 / survivals_fighter2 : 0; // Print the results printf("Number of deaths for Fighter 1 (2d6+6 damage, 65%% hit probability): %d\n", deaths_fighter1); printf("Number of deaths for Fighter 2 (2d6+5 damage, 60%% hit probability): %d\n", deaths_fighter2); printf("Average turns for Fighter 1 (2d6+6 damage, 65%% hit probability): %.2f\n", avg_turns_fighter1); printf("Average turns for Fighter 2 (2d6+5 damage, 60%% hit probability): %.2f\n", avg_turns_fighter2); return 0; } [/CODE] And if my code looks kinda like spaghetti, it is. I wanted to write in python, but it would take far too long for the code to run, so its in C which I barely know how to code. I got assistance from ChatGPT, so also feel free to scrutinize the code itself, but it seems passable from my review. And yeah, I know, whiteboard analysis, but I think the results are dramatic enough and the simulation takes enough cases into account that we can at least use it as a rough guide to our thinking. Edit: 1.41% not .014% and 10,000 instead of 1,000 [/QUOTE]
Insert quotes…
Verification
Post reply
Community
General Tabletop Discussion
*Dungeons & Dragons
The math of the GWF Fighting Style and why its as good as a +1 (and possibly better than defense)
Top