DnD Polyhedral Dice

A simple implementation of DnD dice mechanic.

Share

This uses the FastRandom class which you can find on the linked page.

        using System.Collections.Generic;

namespace GameDice
{
	public enum DiceSides
	{
		d4 = 4,
		d6 = 6,
		d8 = 8,
		d10 = 10,
		d12 = 12,
		d20 = 20
	}

	public class DiceRoll
	{
		FastRandom rand = new FastRandom();
		//The game uses polyhedral dice with different numbers of
		//sides.You can find dice like these in game stores and in
		//many bookstores.
		//In these rules, the different dice are referred to by the
		//letter d followed by the number of sides: d4, d6, d8, d10,
		//d12, and d20. For instance, a d6 is a six-sided die (the
		//typical cube that many games use).
		public int Roll(DiceSides side)
		{
			return rand.Next((int)side);
		}

		//Percentile dice, or d100, work a little differently.You
		//generate a number between 1 and 100 by rolling two
		//different ten-sided dice numbered from 0 to 9. One die
		//(designated before you roll) gives the tens digit, and
		//the other gives the ones digit.If you roll a 7 and a 1, for 
		//example, the number rolled is 71. Two 0s represent 100.
		//Some ten-sided dice are numbered in tens (00, 10, 20,
		//and so on), making it easier to distinguish the tens digit
		//from the ones digit.In this case, a roll of 70 and 1 is 71,
		//and 00 and 0 is 100.
		//When you need to roll dice, the rules tell you how many
		//dice to roll of a certain type, as well as what modifiers to
		//add. For example, “3d8 + 5” means you roll three eightsided dice, 
		//add them together, and add 5 to the total.
		//The same d notation appears in the expressions “1d3”
		//and “1d2.” To simulate the roll of 1d3, roll a d6 and divide
		//the number rolled by 2 (round up). To simulate the roll of
		//1d2, roll any die and assign a 1 or 2 to the roll depending
		//on whether it was odd or even. (Alternatively, if the number rolled is 
		//more than half the number of sides on the
		//die, it’s a 2.)
		public int PercentileRoll()
		{
			var value1 = rand.Next(10);
			var value2 = rand.Next(10);
			if (value1 == 0 && value2 == 0) return 100;
			return value1 * 10 + value2;
		}
	}

	public enum Advantages
	{
		Advantage,
		Disadvantage,
		None
	}

	public class D20
	{
		DiceRoll dr = new DiceRoll();
		bool TestMode;

		public D20(bool testMode)
		{
			TestMode = testMode;
		}

		private int GetRandomNumber(bool firstNumber)
		{
			if (TestMode)
			{
				if (firstNumber)
				{
					return 1;
				}
				else
				{
					return 2;
				}
			}
			return dr.Roll(DiceSides.d20);
		}

		public bool Roll(Advantages Advantage, List<int> Modifiers, int targetNumber)
		{
			int result;

			//1. Roll the die and add a modifier.Roll a d20 and add
			//the relevant modifier.This is typically the modifier derived from one of the six ability scores, and it sometimes
			//includes a proficiency bonus to reflect a character’s particular skill. (See chapter 1 for details on each ability and
			//how to determine an ability’s modifier.)
			result = GetRandomNumber(true);

			//Sometimes an ability check, attack roll, or saving throw
			//is modified by special situations called advantage and disadvantage. Advantage reflects the positive circumstances
			//surrounding a d20 roll, while disadvantage reflects the
			//opposite.When you have either advantage or disadvantage, you roll a second d20 when you make the roll. Use
			//the higher of the two rolls if you have advantage, and use
			//the lower roll if you have disadvantage. For example, if
			//you have disadvantage and roll a 17 and a 5, you use the
			//5.If you instead have advantage and roll those numbers,
			//you use the 17
			if (Advantage == Advantages.Advantage || Advantage == Advantages.Disadvantage)
			{
				var result2 = GetRandomNumber(false);
				if (Advantage == Advantages.Advantage)
				{
					if (result2 > result)
					{
						result = result2;
					}
				}
				else
				{
					if (result2 < result)
					{
						result = result2;
					}
				}
			}

			//2. Apply circumstantial bonuses and penalties.A
			//class feature, a spell, a particular circumstance, or some
			//other effect might give a bonus or penalty to the check.
			foreach (var m in Modifiers)
			{
				result += m;
			}

			//3. Compare the total to a target number.If the total
			//equals or exceeds the target number, the ability check,
			//attack roll, or saving throw is a success. Otherwise, it’s a
			//failure.The DM is usually the one who determines target
			//numbers and tells players whether their ability checks,
			//attack rolls, and saving throws succeed or fail.
			if (result >= targetNumber)
			{
				return true;
			}
			return false;
		}

	}
}