/*
********************************************************************************
mIRC Script for the D6 System
by Jeremy T. Gibson
********************************************************************************
This script is designed to provide a simple "!d6" function which takes a
sentence and reads any and all dice codes and pips from that statement. It
then converts all of the numbers into a single dice throw, which it rolls
automatically.
The dice thrower deliberately does not roll any dice other than six-sided dice.
This is because the snippet is designed for West End Games' D6 System, which has
very specific rules on how the dice work.
If the first die (the wild die, marked with an asterisk) comes up as a 6, it
automatically adds the bonus throws to the total.
It also uses the standard complication rule for throwing a 1 on the wild die: if
throwing a 6 on 1D, a complication occurs -- otherwise a standard penalty occurs
equal to subtracting the wild die (1) and the highest die already thrown.
It matches all strings of the following formats:
1 - adds one pip
+1 - adds one pip
-1 - subtracts one pip
P1 - adds one pip
P+1 - adds one pip
P-1 - subtracts one pip
1D - adds three pips (1D)
+1D - adds three pips (1D)
-1D - subtracts three pips (1D)
(D can be uppercase or lowercase, and can be followed by a 6 (which is ignored))
1D+1 - adds four pips (1D+1)
1D-1 - adds two pips (0D+2)
+1D+1 - adds four pips (1D+1)
+1D-1 - adds two pips (0D+2)
-1D+1 - subtracts four pips (1D+1)
-1D-1 - subtracts two pips (0D+2)
Each die is worth three pips, and pips are always converted into dice if it is
possible to do so. Adding 1D+1 plus 2D+2 comes to a total of 4D, not 3D+3!
"Bonus ranks" can also be added. Unlike pips, these are added/subtracted
directly to/from the final total. Just don't forget that you MUST use either
a leading B or a leading R to denote a bonus; otherwise it's assumed it's a
pip!
B1 - adds one bonus
B+1 - adds one bonus
B-1 - subtracts one bonus
R1 - adds one bonus
R+1 - adds one bonus
R-1 - subtracts one bonus
Example: !d6 5D+1 2D +1 +1 R+10
Parses: 5D+1, 2D, +2 pips, +10 bonus
Resulting roll: 8D+10.
********************************************************************************
Here is a mock sample of the script's use and output:
#OOC <Plae-Yer> !d6 Okay, I'm shooting my blaster at him. I have 5D+1 to hit...
#OOC <D6Bot> (Plae-Yer) Your 5D+1 roll comes to: 21 [3*,6,5,1,5]+1
#OOC <Djee-Em> That's good enough for me, and he wasn't dodging, either... Roll
for damage!
#OOC <Plae-Yer> !d6 Smack that bugger with 5D!
#OOC <D6Bot> (Plae-Yer) Your 5D roll comes to: 17 [3*,5,6,2,1]
#OOC <Djee-Em> Even if he had armour, that guy doesn't have much of a chance, so
I'm not gonna bother rolling.
#RP <Djee-Em> ACTION: The blaster strikes the bounty hunter square in the chest.
He slumps over pathetically, a smoking ruin where his internal organs
should be.
#RP <Plae-Yer> May the Force be with you. ::spits in the bounty hunter's eye::
#OOC <Djee-Em> LOL! Should that count as a Dark Side Point? ;-)
********************************************************************************
Here are all of the functions you can use:
(In a public channel)
!d6 [sentence]
Totals all of the dice codes in the sentence and causes the bot/script owner
to say them out loud.
!privd6 [sentence]
Totals all of the dice codes in the sentence and obviously shares the
sentence itself in the channel, but sends the results to you via a notice.
Generally only the gamemaster should use this command.
(In a query window to the bot/script owner -- even if you are the script owner!)
!d6 [sentence] (or !privd6 [sentence] in case you accidentally use it instead)
Totals all of the dice codes in the sentence and returns the results in the
private window, with no redundant echoing if talking to yourself!
********************************************************************************
Known issues:
* Whenever a match is not found for a string that looks like a dice string, mIRC
will interpret the "0" of "return 0" in the $pipsgained proc as a command for
whatever reason, producing "unknown command: 0" in mIRC's status window. The
reason this is so strange is because the value is clearly being assigned to
the %pips variable, so there's no way it should be evaluating as a command.
I am convinced this is a bug with mIRC. Because of some refactoring of the
program's logic, this bug should almost never appear and is relatively
harmless when it does. It may generally be regarded as a non-issue.
********************************************************************************
*/
alias d6 {
;Ignore if not provided enough messages
if ( $0 == 0 ) {
return
}
var %i = 0
%d6.piptotal = 0
%d6.bonus = 0
var %matches = 0
;Loop through every parameter, checking to see if that parameter contains a die
; code.
:d6loopstart
inc %i
var %param = $gettok($1-, %i, 32)
var %match = $regex(%param, \b[BPRbpr]?[\+\-]?\d+[Dd]?6?[\+\-]?\d*\b )
if ( %match == 1 ) {
;/echo Matched param %i $+ !
var %pips = $pipsgained(%param)
;/echo DBG: matched %param with value of %pips
if ( %pips != 0 ) {
%d6.piptotal = $calc(%d6.piptotal + %pips)
inc %matches
}
else {
var %bonuses = $bonus(%param)
if ( %bonuses > 0 || %bonuses < 0 ) {
;/echo DBG: Adding bonus %bonuses
%d6.bonus = $calc(%d6.bonus + %bonuses)
inc %matches
}
}
}
if ( %i < $0 ) goto d6loopstart
if ( %matches == 0 ) {
$reportmsg( ( $+ $nick $+ ) Um... there were no dice there. )
halt
}
if ( %d6.piptotal <= 0 && %d6.bonus <= 0 ) {
$reportmsg( ( $+ $nick $+ ) Total is less than 0D! Automatic failure! )
halt
}
elseif ( %d6.piptotal > 150 ) {
;Sanity check
$reportmsg( ( $+ $nick $+ ) You're kidding $+ $chr(44) right? )
halt
}
/rolld6 %d6.piptotal
$reportmsg( ( $+ $nick $+ ) Your %d6.string roll comes to: %d6.total $&
%d6.results $+ %d6.bonus )
var %complication = 0
if ( %d6.wild == 6 ) {
$rollwild()
%d6.total = %d6.total + %d6.wildtotal
$reportmsg( ( $+ $nick $+ ) The wild die gives you a bonus of $&
%d6.wildtotal %d6.wildresults $+ ! Final score is %d6.total $+ ! )
}
elseif ( %d6.wild == 1 ) {
if ( $rollforcomplication() ) {
$reportmsg( ( $+ $nick $+ ) Uh oh! There's a complication! )
}
else {
var %penalty
%penalty = $calc(%d6.highroll + 1)
if ( %penalty <= 1 ) halt
%d6.total = %d6.total - %penalty
$reportmsg( ( $+ $nick $+ ) Uh oh! There's a %penalty point penalty! $&
...Final score is %d6.total $+ ! )
}
}
}
alias bonus {
var %string = $1
;Check as a negative rank bonus:
var %match = $regex(penalty, $1, \b[BRbr]\-(\d+)\b )
if ( %match == 1 ) {
;/echo DBG: $1 matched a negative rank penalty
return $calc(0 - $regml(penalty, 1))
}
;Check as a positive rank bonus:
var %match = $regex(bonus, $1, \b[BRbr]\+?(\d+)\b )
if ( %match == 1 ) {
;/echo DBG: $1 matched a positive rank bonus
return $regml(bonus, 1)
}
}
alias pipsgained {
var %string = $1
;Check as a positive dice bonus with additional pips:
var %match = $regex(posdicewithpips, %string, \b\+?(\d+)[Dd]6?([\+|\-])(\d+)\b )
if ( %match == 1 ) {
;/echo DBG: $1 matched a positive number of dice with a bonus/penalty
var %dice = $regml(posdicewithpips, 1)
var %operand = $regml(posdicewithpips, 2)
var %pips = $regml(posdicewithpips, 3)
;Operand is a plus symbol?
if ( %operand == $chr(43) ) {
var %piptotal = $calc( [ %dice * 3 ] + %pips)
return %piptotal
}
else {
var %piptotal = $calc( [ %dice * 3 ] - %pips)
return %piptotal
}
} ;end if %match != 0
;Check as a negative dice bonus with additional pips:
var %match = $regex(negdicewithpips, %string, \b\-(\d+)[Dd]6?([\+|\-])(\d+)\b )
if ( %match == 1 ) {
;/echo DBG: $1 matched a negative number of dice with a bonus/penalty
var %dice = $regml(negdicewithpips, 1)
var %operand = $regml(negdicewithpips, 2)
var %pips = $regml(negdicewithpips, 3)
;Operand is a plus symbol?
if ( %operand == $chr(43) ) {
var %piptotal = $calc( [ %dice * -3 ] - %pips)
return %piptotal
}
else {
var %piptotal = $calc( [ %dice * -3 ] + %pips)
return %piptotal
}
} ;end if %match != 0
;Check as a positive dice bonus:
var %match = $regex(posdice, %string, \b\+?(\d+)[Dd]6?\b )
if ( %match == 1 ) {
;/echo DBG: $1 matched a positive number of dice
return $calc($regml(posdice, 1) * 3)
}
;Check as a negative dice penalty:
var %match = $regex(negdice, %string, \b\-(\d+)[Dd]6?\b )
if ( %match == 1 ) {
;/echo DBG: $1 matched a negative number of dice
return $calc($regml(negdice, 1) * -3)
}
%match = $regex(rankbonus, %string, \b[BRbr]\+?\-?(\d+)\b )
if ( %match == 1 ) {
;/echo DBG: $1 matched a rank bonus/penalty -- aborting pipsgained
return 0
}
;Check as a negative pip penalty:
%match = $regex(penalty, %string, [/\\\[\]\.\|\*\(\)\{\}\!\?"'`~\+]*[Pp]?-(\d+)\b )
if ( %match == 1 ) {
;/echo DBG: $1 matched a negative penalty
return $calc( 0 - $regml(penalty, 1) )
}
;Check as a positive pip bonus:
var %match = $regex(bonus, %string, [/\\\[\]\.\|\*\(\)\{\}\-\!\?"'`~\-]*[Pp]?\+?(\d+)\b )
if ( %match == 1 ) {
;/echo DBG: $1 matched a positive bonus
return $regml(bonus, 1)
}
if ( %match == 0 ) {
/echo DBG: No match found for $1!
return 0
}
}
alias rolld6 {
if ( $1 > 0 ) {
var %fp = $1 / 3
var %dice = $int(%fp)
var %bonus = $1 % 3
%bonus = $calc(%bonus + %d6.bonus)
}
else {
%d6.string = %d6.bonus
%d6.total = %d6.bonus
return
}
%d6.string = %dice $+ D
if ( %bonus > 0 ) { %d6.string = %d6.string $+ $chr(43) $+ %bonus }
elseif ( %bonus < 0 ) { %d6.string = %d6.string $+ %bonus }
unset %d6.total
unset %d6.results
unset %d6.wildtotal
unset %d6.bonus
%d6.highroll = 0
%d6.wild = 0
%d6.results = $chr(91)
if ( %dice > 0 ) {
;/msg $chan DBG: rolling wild die
%d6.wild = $rand(1,6)
%d6.results = %d6.results $+ %d6.wild $+ $chr(42)
%d6.total = %d6.wild
;/msg $chan DBG: finished wild die with ( %d6.wild %d6.results %d6.total %i )
var %i = 1
if ( %dice < 2 ) goto cancel
:nextd6
inc %i ;i should be 2 now
;/msg $chan DBG: rolling die %i
var %roll = $rand(1,6)
if ( %roll > %d6.highroll ) {
%d6.highroll = %roll
}
%d6.results = %d6.results $+ $chr(44)
%d6.results = %d6.results $+ %roll
%d6.total = %d6.total + %roll
if ( %i < %dice ) goto nextd6
:cancel
;/msg $chan DBG: completed goto loop with %i (of %dice $+ )
} ;end if %dice > 0
%d6.results = %d6.results $+ $chr(93)
if ( %bonus > 0 ) {
%d6.bonus = $chr(43) $+ %bonus
%d6.total = %d6.total + %bonus
}
else if ( %bonus < 0 ) {
%d6.bonus = %bonus
%d6.total = $calc(%d6.total + %bonus)
}
}
/*
If the /d6 procedure determines that the wild die has come up as a 6, then this
procedure is called to roll the bonus di(c)e.
There are two variables that are computed here: %d6.wildresults is a text string
consisting of an opening bracket, a series of comma-separated numbers, and a
closing bracket; %d6.wildtotal is a single integer that is the total of all of
the numbers in the brackets.
*/
alias rollwild {
;This acts as a "do-while".
;Roll the first bonus!
var %roll = $rand(1,6)
;Instantiate: an opening bracket and the rolled number as a string...
%d6.wildresults = $chr(91) $+ %roll
;...And the rolled number by itself as an integer.
%d6.wildtotal = %roll
;If the first bonus came up as a six,
; loop until we come up with a roll that isn't a 6.
while ( %roll == 6 ) {
%roll = $rand(1,6)
;Append a comma and the roll to the results string.
%d6.wildresults = %d6.wildresults $+ $chr(44) $+ %roll
;Add the the number to the total integer.
%d6.wildtotal = %d6.wildtotal + %roll
}
;Append the final closing bracket.
%d6.wildresults = %d6.wildresults $+ $chr(93)
}
/*
This makes a simple roll to check to see whether a complication occurs,
returning "1" to mean "yes" or "0" to mean "no". This value is checked by the
calling function (/d6) and a message is reported if the value is 1.
*/
alias rollforcomplication {
if ( $rand(1,6) == 6 ) {
return 1
}
return 0
}
/*
This script controls the "privacy codes" that the event handlers use. Though it
should be obvious from reading the function itself, here is the extended
description.
Privacy 0 (default): Message is spoken aloud in the channel it was seen in.
Privacy 1 (private): Message is sent as a private message to the triggerer.
Privacy 2 (notice): Message is sent as a private notice to the triggerer.
Privacy 3 (self): Message is echoed to the window for the script owner only.
*/
alias reportmsg {
if ( %d6.private == 3 ) /echo -t # %p $1-
elseif ( %d6.private == 2 ) /notice $nick $1-
elseif ( %d6.private == 1 ) /msg $nick $1-
else /msg $chan $1-
}
; === EVENT HANDLERS ===
;Receiving an open statement -- say the result
on *:TEXT:!d6 *:#:{
if ( %d6.enabled != 1 ) {
/halt
}
%d6.private = 0
/d6 $2-
unset %d6.private
}
;Receiving a private statement said publicly -- send the result as a notice
on *:TEXT:!privd6 *:#:{
if ( %d6.enabled != 1 ) {
/halt
}
%d6.private = 2
/d6 $2-
unset %d6.private
}
;Receiving a statement in a private message -- send the result as a private message
on *:TEXT:!d6 *:?:{
if ( %d6.enabled != 1 ) {
/halt
}
%d6.private = 1
/d6 $2-
unset %d6.private
}
;Receiving a direct notice -- send a notice back
on *:NOTICE:!d6 *:#:{
if ( %d6.enabled != 1 ) {
/halt
}
%d6.private = 2
/d6 $2-
unset %d6.private
}
on *:NOTICE:!privd6 *:#:{
if ( %d6.enabled != 1 ) {
/halt
}
%d6.private = 2
/d6 $2-
unset %d6.private
}
on *:INPUT:#:{
;Using !d6 when in a channel -- say what was typed and share result
if ( $1 == !d6 ) {
%d6.private = 0
/say !d6 $2-
/d6 $2-
unset %d6.private
/halt
}
;Using !privd6 when in a channel -- say what was typed and echo result to myself
elseif ( $1 == !privd6 ) {
%d6.private = 3
/say !privd6 $2-
/d6 $2-
unset %d6.private
/halt
}
}
;Using !d6 in a private window -- echo what was typed and echo result (no double-feedback)
on *:INPUT:?:{
if ( $1 == !d6 ) {
%d6.private = 3
$reportmsg( ( $+ $nick $+ ) !d6 $2- )
/d6 $2-
unset %d6.private
/halt
}
elseif ( $1 == !privd6 ) {
%d6.private = 3
$reportmsg( ( $+ $nick $+ ) !privd6 $2- )
/d6 $2-
unset %d6.private
/halt
}
}