Skip to content

Commit 3a0437b

Browse files
committed
Various updates:
- Add roll counting func - php doc comments - syntax to drop multiple dice
1 parent 979dc63 commit 3a0437b

4 files changed

Lines changed: 79 additions & 12 deletions

File tree

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ You don't have to use composer to include EZDice in your project, but you can:
4444

4545
### roll($diceStr)
4646

47-
Parse **$diceStr** as dice notation then roll those dice. Returns *(int)* total of all rolls and modifiers, or *false* if none were found.
47+
Parse **$diceStr** as dice notation, then roll those dice. Returns *(int)* total of all rolls and modifiers, or *false* if none were found.
4848

4949
The parser is very forgiving, ignoring whitespace and anything else it doesn't recognise. It is also case-insensitive. Dice notation is briefly documented below.
5050

@@ -66,13 +66,17 @@ Returns a *(string)* representing the total of all modifiers in the last roll. I
6666

6767
e.g. if you rolled `1d8+10+1d4-2` this method would return `+8`.
6868

69+
### strContainsDice($diceStr)
70+
71+
Parse **$diceStr** and returns true if it contains at least one dice roll, otherwise returns false. Useful for verifying user input. Modifiers without dice don't count.
72+
6973
## Dice Notation
7074

7175
- Dice notation is in the form (number of dice)**d**(dice sides). e.g. `2d10`.
7276
- Additional dice can be chained with **+** and **-** operators. e.g. `2d10+1d6`.
7377
- Modifiers can also be specified. e.g. `2d10-5`
7478
- d% can be used as a shorthand for a percentile dice. `1d%` and `1d100` are equivalent.
75-
- Append a roll with -L to drop the lowest dice in that group, or -H to drop the highest. Dropped dice are excluded from the total. e.g. `2d20-L` will roll 2 twenty sided dice and drop the lowest.
79+
- Append a roll with -L to drop the lowest dice in that group, or -H to drop the highest. Dropped dice are excluded from the total. e.g. `2d20-L` will roll 2 twenty sided dice and drop the lowest. You can also specify a number of dice to drop e.g. `6d6-H3` will drop the highest 3 rolls.
7680
- No notation is currently provided for fudge dice. You can use `1d3-2` instead.
7781
- Whitespace, and anything else not recognised as a dice or a modifier, is treated like a **+** operator. e.g. `foo10 1d4bar1d4 5` is equivalent to `5+1d4+1d4+10`, or simply `2d4+15`.
7882

composer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
"rpg",
1717
"dice-notation",
1818
"die",
19-
"dice-roller"
19+
"dice-roller",
20+
"roller",
21+
"random"
2022
],
2123
"require": {
2224
"php": ">=7.0"

example.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@
33
require 'ezdice.php';
44

55
$ezd = new ezdice\EZDice();
6-
echo($ezd->roll('1d20+2d4-L+6').PHP_EOL);
6+
7+
$diceStr = '1d20+2d4-L+6';
8+
9+
// Validating a dice string
10+
if ($ezd->strContainsDice("$diceStr") {
11+
echo "$diceStr contains dice!";
12+
};
13+
14+
// Rolling dice
15+
echo($ezd->roll($diceStr).PHP_EOL);
716
print_r($ezd->getDiceStates());
817
echo($ezd->getModifier());

ezdice.php

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,28 @@
22

33
namespace ezdice;
44

5+
/**
6+
* EZDice, a dice rolling library
7+
*/
58
class EZDice {
69
// Magic dice & modifier matching regex
7-
private $re = '(?<operator>[\+-])?\s*(?<number>\d+)(?:[dD](?<sides>(?:\d+|%))(?:-(?<variant>[LlHh]))?)?';
10+
private $re = '(?<operator>[\+-])?\s*(?<number>\d+)(?:[dD](?<sides>(?:\d+|%))(?:-(?<drop>[LlHh])(?<dquantity>\d+)?)?)';
811

912
// Stores information on last roll
1013
private $total = 0;
1114
private $states = [];
1215
private $modifier = 0;
1316

17+
/**
18+
* Parse **$diceStr** as dice notation, then roll those dice.
19+
*
20+
* The parser is very forgiving, ignoring whitespace and anything else it doesn't recognise.
21+
* It is also case-insensitive. Dice notation is documented in README.md
22+
*
23+
* @param string $diceStr the string containing the dice rolls.
24+
*
25+
* @return int|false total of all rolls and modifiers, or false if none were found.
26+
*/
1427
public function roll(string $diceStr)
1528
{
1629
// Reset result values
@@ -26,7 +39,8 @@ public function roll(string $diceStr)
2639
}
2740

2841
// Search for dice groups and modifiers
29-
preg_match_all("/{$this->re}/", $diceStr, $matches, PREG_SET_ORDER, 0);
42+
// The extra "?" at the end of the regex allows it to find modifiers too
43+
preg_match_all("/{$this->re}?/", $diceStr, $matches, PREG_SET_ORDER, 0);
3044

3145
// Returning false if no matches found
3246
if (sizeof($matches) == 0) return false;
@@ -39,6 +53,18 @@ public function roll(string $diceStr)
3953
return $this->total;
4054
}
4155

56+
/**
57+
* Parse **$diceStr** and determine if it contains at least one dice roll.
58+
*
59+
* @param string $diceStr the string which may contain dice rolls.
60+
*
61+
* @return bool true if $diceStr contains at least one dice roll, otherwise false.
62+
*/
63+
public function strContainsDice(string $diceStr)
64+
{
65+
return (preg_match_all("/{$this->re}/", $diceStr) > 0);
66+
}
67+
4268
private function addState(int $sides, int $value, bool $dropped = false): void
4369
{
4470
$this->states[] = [
@@ -65,8 +91,8 @@ private function processGroup(array $group): void
6591
return;
6692
}
6793

68-
// Collect variant information from group
69-
$variant = (isset($group['variant']) ? strtoupper($group['variant']) : null);
94+
// Collect drop information from group
95+
$drop = (isset($group['drop']) ? strtoupper($group['drop']) : null);
7096

7197
// 'd%' can be used as shorthand for 'd100'
7298
$sides = $sides=="%" ? 100 : $sides;
@@ -80,15 +106,18 @@ private function processGroup(array $group): void
80106
}
81107

82108
// Dropping dice
83-
if ($variant && $number > 1) {
109+
if ($drop) {
110+
$dropQuantity = min($group['dquantity'] ?? 1, $number);
84111
// Sort low to high
85112
sort($results, SORT_NUMERIC);
86113
// Reverse array if dropping lowest
87-
if ($variant == 'L') {
114+
if ($drop == 'L') {
88115
$results = array_reverse($results);
89116
}
90-
$droppedResult = array_pop($results);
91-
$this->addState($sides, $droppedResult, true);
117+
for ($i=0; $i < $dropQuantity; $i++) {
118+
$droppedResult = array_pop($results);
119+
$this->addState($sides, $droppedResult, true);
120+
}
92121
// Cosmetic re-shuffle of rest of dice
93122
shuffle($results);
94123
}
@@ -101,21 +130,44 @@ private function processGroup(array $group): void
101130
}
102131
}
103132

133+
/**
134+
* Generates the psudo-random number for dice rolls.
135+
*
136+
* @param int $max the highest number on the dice. Roll is 1 - $max (inclusive).
137+
*
138+
* @return int result of the roll.
139+
*/
104140
protected function getRandomNumber(int $max): int
105141
{
106142
return mt_rand(1,$max);
107143
}
108144

145+
/**
146+
* Get the total of the last roll.
147+
*
148+
* @return bool result of test.
149+
*/
109150
public function getTotal(): int
110151
{
111152
return $this->total;
112153
}
113154

155+
/**
156+
* Get the state of the dice after the last roll.
157+
*
158+
* @return array array that describes the state of the dice after the last roll.
159+
*/
114160
public function getDiceStates(): array
115161
{
116162
return $this->states;
117163
}
118164

165+
/**
166+
* Get the combined modifiers of the last roll.
167+
*
168+
* @return string representing the total of all modifiers in the last roll. If there were no modifiers, or they
169+
* cancelled out, an empty string is returned.
170+
*/
119171
public function getModifier(): string
120172
{
121173
if (!$this->modifier) return "";

0 commit comments

Comments
 (0)