Initial commit

This commit is contained in:
Joel Therrien 2019-03-18 20:56:07 -07:00
commit 6ec0094fb4
21 changed files with 673 additions and 0 deletions

2
.Rbuildignore Normal file
View file

@ -0,0 +1,2 @@
^.*\.Rproj$
^\.Rproj\.user$

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*.Rproj
.Rproj.user

14
DESCRIPTION Normal file
View file

@ -0,0 +1,14 @@
Package: DndDice
Type: Package
Title: What the Package Does (Title Case)
Version: 0.1.0
Author: Who wrote it
Maintainer: The package maintainer <yourself@somewhere.net>
Description: More about what it does (maybe more than one line)
Use four spaces when indenting paragraphs within the Description.
License: What license is it under?
Encoding: UTF-8
LazyData: true
Imports:
ggplot2 (>= 3.1.0)
RoxygenNote: 6.1.1

24
NAMESPACE Normal file
View file

@ -0,0 +1,24 @@
# Generated by roxygen2: do not edit by hand
S3method("*",Die)
S3method("+",Die)
S3method("<",Die)
S3method("<=",Die)
S3method("==",Die)
S3method(">",Die)
S3method(">=",Die)
S3method(mean,Die)
S3method(plot,Die)
S3method(print,Die)
S3method(summary,Die)
export(advantage)
export(d10)
export(d12)
export(d20)
export(d4)
export(d6)
export(d8)
export(disadvantage)
export(makeDie)
export(roll)
import(ggplot2)

102
R/disadvantage_advantage.R Normal file
View file

@ -0,0 +1,102 @@
#'
#' Disadvantage
#'
#' Disadvantage a die roll, which means that when both die are rolled, the result
#' is the lower number.
#'
#' @param x A die to roll.
#' @param y A die to roll. If not specified, then x is disadvantaged against itself.
#' @return A die representing the minimum of both die
#' @examples
#' disadvantage(d20,d20)
#'
#' @export
disadvantage <- function(x, y=NULL){
if(is.null(y)){
y = x
}
minX = min(x$numbers)
minY = min(y$numbers)
maxX = max(x$numbers)
maxY = max(y$numbers)
range_z_min = pmin(minX, minY)
range_z_max = pmin(maxX, maxY)
z_numbers = c()
probabilities = c()
for(num in range_z_min:range_z_max){
prob_x_eq_num = getProbabilitiy(x, num)
prob_y_eq_num = getProbabilitiy(y, num)
y_geq_nums = y$numbers[y$numbers >= num] # >= not a mistake
x_ge_nums = x$numbers[x$numbers > num]
prob_y_geq_nums = sum(getProbabilitiy(y, y_geq_nums))
prob_x_ge_nums = sum(getProbabilitiy(x, x_ge_nums))
prob_num = prob_x_eq_num*prob_y_geq_nums + prob_x_ge_nums*prob_y_eq_num
if(prob_num > 0){
z_numbers = c(z_numbers, num)
probabilities = c(probabilities, prob_num)
}
}
z = makeDie(z_numbers, probabilities)
return(z)
}
#'
#' Advantage
#'
#' Advantage a die roll, which means that when both die are rolled, the result
#' is the higher number.
#'
#' @param x A die to roll.
#' @param y A die to roll. If not specified, then x is advantaged against itself.
#' @return A die representing the maximum of both die
#' @examples
#' advantage(d20,d20)
#'
#' @export
advantage <- function(x, y=NULL){
if(is.null(y)){
y = x
}
minX = min(x$numbers)
minY = min(y$numbers)
maxX = max(x$numbers)
maxY = max(y$numbers)
range_z_min = pmax(minX, minY)
range_z_max = pmax(maxX, maxY)
z_numbers = c()
probabilities = c()
for(num in range_z_min:range_z_max){
prob_x_eq_num = getProbabilitiy(x, num)
prob_y_eq_num = getProbabilitiy(y, num)
y_leq_nums = y$numbers[y$numbers <= num] # <= not a mistake
x_le_nums = x$numbers[x$numbers < num]
prob_y_leq_nums = sum(getProbabilitiy(y, y_leq_nums))
prob_x_le_nums = sum(getProbabilitiy(x, x_le_nums))
prob_num = prob_x_eq_num*prob_y_leq_nums + prob_x_le_nums*prob_y_eq_num
if(prob_num > 0){
z_numbers = c(z_numbers, num)
probabilities = c(probabilities, prob_num)
}
}
z = makeDie(z_numbers, probabilities)
return(z)
}

69
R/internal_functions.R Normal file
View file

@ -0,0 +1,69 @@
getProbabilitiy <- function(x, numbers){
positions = match(numbers, x$numbers)
probs = x$probs[positions]
probs[is.na(probs)] = 0
return(probs)
}
sumTwoDie <- function(x, y){
range_z_min = min(x$numbers) + min(y$numbers)
range_z_max = max(x$numbers) + max(y$numbers)
z_numbers = c()
probabilities = c()
for(num in range_z_min:range_z_max){
prob_num = sum(x$probs * getProbabilitiy(y, num - x$numbers))
if(prob_num > 0){
z_numbers = c(z_numbers, num)
probabilities = c(probabilities, prob_num)
}
}
z = makeDie(z_numbers, probabilities)
return(z)
}
# comparerFun(x, y); which both x & y as Die, or one of them as numeric
compareDie <- function(x, y, comparerFun){
if(class(x) == "Die" & class(y) == "Die"){
jointProbs = expand.grid(x$probs, y$probs)
jointProbs = jointProbs[,1]*jointProbs[,2]
jointNumbers = expand.grid(x$numbers, y$numbers)
matchResults = comparerFun(jointNumbers[,1], jointNumbers[,2])
probTrue = sum(jointProbs[matchResults])
z = makeDie(c(F,T), probs=c(1-probTrue, probTrue))
return(z)
}
if(class(x) %in% c("numeric", "integer")){
die = y
constant = x
xNumbers = constant
yNumbers = die$numbers
} else if(class(y) %in% c("numeric", "integer")){
die = x
constant = y
xNumbers = die$numbers
yNumbers = constant
} else{
stop("Can only compare two die or a die and a number")
}
if(length(constant) != 1){
stop("Length of constant must be 1")
}
matchResults = comparerFun(xNumbers, yNumbers)
probTrue = sum(die$probs[matchResults])
z = makeDie(c(F,T), probs=c(1-probTrue, probTrue))
}

25
R/makeDie.R Normal file
View file

@ -0,0 +1,25 @@
#'
#' Create a custom die.
#'
#' @param numbers A vector of the numbers that the die can roll on
#' @param probs A vecor of the probabilities for the numbers that the die can
#' roll on. By default the probabilities are assumed to be equal.
#' @return A \code{Die} object containing a vector of numbers the die can roll
#' on, as well as a vector of probabilities. It also has a text label set.
#' @seealso \code{\link{mean.Die}}, \code{\link{plot.Die}},
#' \code{\link{summary.Die}}, and \code{\link{print.Die}}.
#' @examples
#' stealth <- makeDie(1:20+3)
#' summary(stealth)
#'
#' @export
makeDie <- function(numbers, probs=NULL){
if(is.null(probs)){
probs = rep(1 / length(numbers), times=length(numbers))
}
die = list(numbers=numbers, probs=probs)
class(die) <- "Die"
return(die)
}

View file

@ -0,0 +1,65 @@
#'
#' Calculate the mean of a die.
#'
#' Calculate the mean.
#'
#' @param x A die
#' @return The expected value of the die.
#' @examples
#' mean(d20)
#'
#' @export
mean.Die <- function(x){
return(sum(x$numbers*x$probs))
}
#'
#' Print a die.
#'
#' Rolls a die a single time.
#'
#' @param x A die to roll.
#' @param ... Other parameters to pass to \code{\link{roll}}
#' @examples
#' print(d20)
#'
#' @export
print.Die <- function(x, ...){
print(roll(x, ...))
}
#'
#' Print a die's summary.
#'
#' Return the probabilities of a die for different rolls.
#'
#' @param x A die
#' @return A vector of named probabilities for each outcome of the die.
#' @examples
#' summary(advantage(d20,d20))
#' @export
summary.Die <- function(x){
probs <- x$probs
names(probs) <- x$numbers
return(probs)
}
#'
#' Plot a die's summary.
#'
#' Plot the probabilities of a die for different rolls.
#'
#' @param x A die
#' @return A ggplot2 plot.
#' @examples
#' plot(advantage(d20,d20))
#'
#' @export
plot.Die <- function(x){
data = data.frame(Number=x$numbers, Probability=x$probs)
plt = ggplot(data, aes(x=Number, y=Probability)) + geom_col()
return(plt)
}

89
R/operators.R Normal file
View file

@ -0,0 +1,89 @@
#' @export
'+.Die' <- function(x, y){
if(class(x) == "Die" & class(y) == "Die"){
return(sumTwoDie(x, y))
}
if(class(x) %in% c("numeric", "integer")){
die = y
constant = x
} else if(class(y) %in% c("numeric", "integer")){
die = x
constant = y
} else{
stop("Can only add two die or a die and a number")
}
if(length(constant) != 1){
stop("Length of constant must be 1")
}
die$numbers <- die$numbers + constant
return(die)
}
#' @export
'>.Die' <- function(x,y){
return(compareDie(x, y, `>`))
}
#' @export
'>=.Die' <- function(x,y){
return(compareDie(x, y, `>=`))
}
#' @export
'<.Die' <- function(x,y){
return(compareDie(x, y, `<`))
}
#' @export
'<=.Die' <- function(x,y){
return(compareDie(x, y, `<=`))
}
#' @export
'==.Die' <- function(x,y){
return(compareDie(x, y, `==`))
}
#' @export
'*.Die' <- function(x, y){
# At least one of the types should be numeric or integer
if(!(class(x) %in% c("numeric", "integer")) & !(class(y) %in% c("numeric", "integer"))){
stop("At least one type must be numeric")
}
if(class(x) == "Die"){
die = x
times = y
}
else{
die = y
times = x
}
times = as.integer(round(times))
if(times < 1){
stop("Cannot multiply a die by less than 1")
}
if(times == 1){
return(die)
}
result = die
for(i in 2:times){
result = result + die
}
return(result)
}

16
R/roll.R Normal file
View file

@ -0,0 +1,16 @@
#'
#' Roll a die.
#'
#' Description.
#'
#' @param x A die to roll.
#' @param times How many times the die should be rolled.
#' @return A numeric vector representing the die rolls.
#' @examples
#' roll(d20)
#' roll(d20, times=10)
#'
#' @export
roll <- function(x, times=1){
return(sample(x$numbers, size=times, replace=TRUE, prob=x$probs))
}

40
R/z_build_in_dice.R Normal file
View file

@ -0,0 +1,40 @@
#' Built in Dice
#'
#' Built in dice available to use. You can create your own using
#' \code{\link{makeDie}}
#'
#' @format
#'
#' @name BuiltInDice
NULL
#' @rdname BuiltInDice
#' @examples roll(d4)
#' @export
d4 = makeDie(1:4)
#' @rdname BuiltInDice
#' @examples roll(d6)
#' @export
d6 = makeDie(1:6)
#' @rdname BuiltInDice
#' @examples roll(d8)
#' @export
d8 = makeDie(1:8)
#' @rdname BuiltInDice
#' @examples roll(d10)
#' @export
d10 = makeDie(1:10)
#' @rdname BuiltInDice
#' @examples roll(d12)
#' @export
d12 = makeDie(1:12)
#' @rdname BuiltInDice
#' @examples roll(d20)
#' @export
d20 = makeDie(1:20)

2
R/zzz.R Normal file
View file

@ -0,0 +1,2 @@
#' @import ggplot2
NULL

39
man/BuiltInDice.Rd Normal file
View file

@ -0,0 +1,39 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/z_build_in_dice.R
\docType{data}
\name{BuiltInDice}
\alias{BuiltInDice}
\alias{d4}
\alias{d6}
\alias{d8}
\alias{d10}
\alias{d12}
\alias{d20}
\title{Built in Dice}
\format{}
\usage{
d4
d6
d8
d10
d12
d20
}
\description{
Built in dice available to use. You can create your own using
\code{\link{makeDie}}
}
\examples{
roll(d4)
roll(d6)
roll(d8)
roll(d10)
roll(d12)
roll(d20)
}
\keyword{datasets}

24
man/advantage.Rd Normal file
View file

@ -0,0 +1,24 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/disadvantage_advantage.R
\name{advantage}
\alias{advantage}
\title{Advantage}
\usage{
advantage(x, y = NULL)
}
\arguments{
\item{x}{A die to roll.}
\item{y}{A die to roll. If not specified, then x is advantaged against itself.}
}
\value{
A die representing the maximum of both die
}
\description{
Advantage a die roll, which means that when both die are rolled, the result
is the higher number.
}
\examples{
advantage(d20,d20)
}

24
man/disadvantage.Rd Normal file
View file

@ -0,0 +1,24 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/disadvantage_advantage.R
\name{disadvantage}
\alias{disadvantage}
\title{Disadvantage}
\usage{
disadvantage(x, y = NULL)
}
\arguments{
\item{x}{A die to roll.}
\item{y}{A die to roll. If not specified, then x is disadvantaged against itself.}
}
\value{
A die representing the minimum of both die
}
\description{
Disadvantage a die roll, which means that when both die are rolled, the result
is the lower number.
}
\examples{
disadvantage(d20,d20)
}

30
man/makeDie.Rd Normal file
View file

@ -0,0 +1,30 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/makeDie.R
\name{makeDie}
\alias{makeDie}
\title{Create a custom die.}
\usage{
makeDie(numbers, probs = NULL)
}
\arguments{
\item{numbers}{A vector of the numbers that the die can roll on}
\item{probs}{A vecor of the probabilities for the numbers that the die can
roll on. By default the probabilities are assumed to be equal.}
}
\value{
A \code{Die} object containing a vector of numbers the die can roll
on, as well as a vector of probabilities. It also has a text label set.
}
\description{
Create a custom die.
}
\examples{
stealth <- makeDie(1:20+3)
summary(stealth)
}
\seealso{
\code{\link{mean.Die}}, \code{\link{plot.Die}},
\code{\link{summary.Die}}, and \code{\link{print.Die}}.
}

21
man/mean.Die.Rd Normal file
View file

@ -0,0 +1,21 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/mean_print_summary_plot.R
\name{mean.Die}
\alias{mean.Die}
\title{Calculate the mean of a die.}
\usage{
\method{mean}{Die}(x)
}
\arguments{
\item{x}{A die}
}
\value{
The expected value of the die.
}
\description{
Calculate the mean.
}
\examples{
mean(d20)
}

21
man/plot.Die.Rd Normal file
View file

@ -0,0 +1,21 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/mean_print_summary_plot.R
\name{plot.Die}
\alias{plot.Die}
\title{Plot a die's summary.}
\usage{
\method{plot}{Die}(x)
}
\arguments{
\item{x}{A die}
}
\value{
A ggplot2 plot.
}
\description{
Plot the probabilities of a die for different rolls.
}
\examples{
plot(advantage(d20,d20))
}

20
man/print.Die.Rd Normal file
View file

@ -0,0 +1,20 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/mean_print_summary_plot.R
\name{print.Die}
\alias{print.Die}
\title{Print a die.}
\usage{
\method{print}{Die}(x, ...)
}
\arguments{
\item{x}{A die to roll.}
\item{...}{Other parameters to pass to \code{\link{roll}}}
}
\description{
Rolls a die a single time.
}
\examples{
print(d20)
}

24
man/roll.Rd Normal file
View file

@ -0,0 +1,24 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/roll.R
\name{roll}
\alias{roll}
\title{Roll a die.}
\usage{
roll(x, times = 1)
}
\arguments{
\item{x}{A die to roll.}
\item{times}{How many times the die should be rolled.}
}
\value{
A numeric vector representing the die rolls.
}
\description{
Description.
}
\examples{
roll(d20)
roll(d20, times=10)
}

20
man/summary.Die.Rd Normal file
View file

@ -0,0 +1,20 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/mean_print_summary_plot.R
\name{summary.Die}
\alias{summary.Die}
\title{Print a die's summary.}
\usage{
\method{summary}{Die}(x)
}
\arguments{
\item{x}{A die}
}
\value{
A vector of named probabilities for each outcome of the die.
}
\description{
Return the probabilities of a die for different rolls.
}
\examples{
summary(advantage(d20,d20))
}