patterncsharpMinor
Statistical Analysis of X-Wing Game Dice
Viewed 0 times
analysisgamestatisticaldicewing
Problem
I was in a discussion about mechanics of the X-Wing miniatures game where we were discussing a couple of the ways to improve attacks and I put together this small C# console application to determine which method was move effective. The program rolls a specified number of the game's attack dice and then compares if a Focus token (converting all dice rolled onto to the Focus face to hits) or a Target Lock (re-rolling any number of dice) would result in a better attack, on average. It does this for a range of number of attack dice being rolled, and for a configurable number of trials.
Program.cs
```
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace XWingDice
{
class Program
{
// Bounds for number of dice to test
const int MIN_DICE = 1;
const int MAX_DICE = 5;
// Number of trials for each number of dice
const int NUM_TRIALS = 1000000;
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
List results = new List();
for (int numDice = MIN_DICE; numDice dice = new List();
// Initialize a list of dice for the current number of dice
for (int i = 0; i focusDice = dice.CloneDice();
// Convert the focus dies to hits
focusDice.UseFocus();
#endregion Focus
#region Target Lock
// Clone the list of dice
List targetLockDice = dice.CloneDice();
// Get the current hits and crits
List goodDice = targetLockDice.Where(d => d.state == DieState.Crit || d.state == DieState.Hit).ToList();
// Get the focus and miss dice
List badDice = targetLockDice.Where(d => d.state == DieState.Focus || d.state == DieState.Miss).ToList();
// R
Program.cs
```
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace XWingDice
{
class Program
{
// Bounds for number of dice to test
const int MIN_DICE = 1;
const int MAX_DICE = 5;
// Number of trials for each number of dice
const int NUM_TRIALS = 1000000;
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
List results = new List();
for (int numDice = MIN_DICE; numDice dice = new List();
// Initialize a list of dice for the current number of dice
for (int i = 0; i focusDice = dice.CloneDice();
// Convert the focus dies to hits
focusDice.UseFocus();
#endregion Focus
#region Target Lock
// Clone the list of dice
List targetLockDice = dice.CloneDice();
// Get the current hits and crits
List goodDice = targetLockDice.Where(d => d.state == DieState.Crit || d.state == DieState.Hit).ToList();
// Get the focus and miss dice
List badDice = targetLockDice.Where(d => d.state == DieState.Focus || d.state == DieState.Miss).ToList();
// R
Solution
public int FocusBetter { get; set; } = 0;
...You don't need to initialize your
int properties to zero. They are default(int) (zero) by default.You implement
ICloneable but if your only use of it is as shown above, then you really don't need the interface so can create your own Clone() method which returns your actual object type, rather than returning object and then casting it.I really dislike the extension methods. It feels wrong to have extension methods that perform application logic on a
List containing objects of your type. Maybe it's just me. But I would much rather see you either implementing your own collection object and then expose the methods from that object, or have those methods part of whatever class holds the lists.Code Snippets
public int FocusBetter { get; set; } = 0;
...Context
StackExchange Code Review Q#136464, answer score: 3
Revisions (0)
No revisions yet.