├── vignettes ├── .gitignore ├── games │ ├── slots.Rmd │ ├── blackjack.Rmd │ └── poker.Rmd └── persistent_player_profiles.Rmd ├── LICENSE ├── .gitignore ├── docs ├── logo.png ├── favicon.ico ├── reference │ ├── figures │ │ ├── logo.png │ │ └── plot-history-1.png │ ├── play.html │ ├── delete.html │ ├── play_blackjack.html │ ├── play_slots.html │ ├── play_poker.html │ ├── players.html │ ├── setup.html │ ├── play_sound.html │ ├── Player.html │ ├── index.html │ ├── Blackjack.html │ ├── Slots.html │ ├── Poker.html │ └── Deck.html ├── pkgdown.yml ├── link.svg ├── sitemap.xml ├── docsearch.js ├── pkgdown.js ├── pkgdown.css ├── LICENSE-text.html ├── authors.html ├── articles │ ├── index.html │ └── blackjack.html └── news │ └── index.html ├── man ├── figures │ ├── logo.png │ └── plot-history-1.png ├── play.Rd ├── delete.Rd ├── play_blackjack.Rd ├── play_slots.Rd ├── play_poker.Rd ├── players.Rd ├── setup.Rd ├── Player.Rd ├── play_sound.Rd ├── Slots.Rd ├── Poker.Rd ├── Blackjack.Rd └── Deck.Rd ├── .Rbuildignore ├── R ├── delete.R ├── play_sound.R ├── players.R ├── setup.R ├── Deck.R ├── play.R ├── Slots.R ├── Blackjack.R ├── Poker.R └── Player.R ├── _pkgdown.yml ├── NAMESPACE ├── casino.Rproj ├── NEWS.md ├── cran-comments.md ├── DESCRIPTION ├── readme.Rmd └── readme.md /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.R 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2018 2 | COPYRIGHT HOLDER: Anthony Pileggi -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | inst/doc 2 | .Rproj.user 3 | .Rhistory 4 | .RData 5 | .Ruserdata 6 | -------------------------------------------------------------------------------- /docs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anthonypileggi/casino/HEAD/docs/logo.png -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anthonypileggi/casino/HEAD/docs/favicon.ico -------------------------------------------------------------------------------- /man/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anthonypileggi/casino/HEAD/man/figures/logo.png -------------------------------------------------------------------------------- /man/figures/plot-history-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anthonypileggi/casino/HEAD/man/figures/plot-history-1.png -------------------------------------------------------------------------------- /docs/reference/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anthonypileggi/casino/HEAD/docs/reference/figures/logo.png -------------------------------------------------------------------------------- /docs/reference/figures/plot-history-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anthonypileggi/casino/HEAD/docs/reference/figures/plot-history-1.png -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^CRAN-RELEASE$ 2 | ^docs$ 3 | ^_pkgdown\.yml$ 4 | ^.*\.Rproj$ 5 | ^\.Rproj\.user$ 6 | ^README\.Rmd$ 7 | ^README-.*\.png$ 8 | ^cran-comments\.md$ 9 | ^.*\.casino$ 10 | -------------------------------------------------------------------------------- /R/delete.R: -------------------------------------------------------------------------------- 1 | 2 | #' Delete all player history and re-lock the casino 3 | #' @export 4 | delete <- function() { 5 | file <- Sys.getenv("CASINO_FILE") 6 | if (file.exists(file)) 7 | unlink(file) 8 | Sys.unsetenv("CASINO_FILE") 9 | } 10 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | url: https://anthonypileggi.github.io/casino 2 | 3 | authors: 4 | Anthony Pileggi: 5 | href: https://blog.sqwerl.life 6 | 7 | 8 | template: 9 | params: 10 | bootswatch: united 11 | ganalytics: UA-114744558-2 12 | -------------------------------------------------------------------------------- /man/play.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/play.R 3 | \name{play} 4 | \alias{play} 5 | \title{Play in the casino} 6 | \usage{ 7 | play() 8 | } 9 | \description{ 10 | Play in the casino 11 | } 12 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(Blackjack) 4 | export(Deck) 5 | export(Player) 6 | export(Poker) 7 | export(Slots) 8 | export(delete) 9 | export(play) 10 | export(players) 11 | export(setup) 12 | import(ggplot2) 13 | importFrom(magrittr,"%>%") 14 | -------------------------------------------------------------------------------- /R/play_sound.R: -------------------------------------------------------------------------------- 1 | 2 | #' Play a sound (if possible) 3 | #' @param sound character string or number specifying the sound (see \code{\link[beepr]{beep}}) 4 | #' @note requires the `beepr` package 5 | play_sound <- function(sound = "fanfare") { 6 | if ("beepr" %in% utils::installed.packages()[, 1]) 7 | beepr::beep(sound) 8 | } -------------------------------------------------------------------------------- /man/delete.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/delete.R 3 | \name{delete} 4 | \alias{delete} 5 | \title{Delete all player history and re-lock the casino} 6 | \usage{ 7 | delete() 8 | } 9 | \description{ 10 | Delete all player history and re-lock the casino 11 | } 12 | -------------------------------------------------------------------------------- /man/play_blackjack.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/play.R 3 | \name{play_blackjack} 4 | \alias{play_blackjack} 5 | \title{Play blackjack} 6 | \usage{ 7 | play_blackjack(name) 8 | } 9 | \arguments{ 10 | \item{name}{player name} 11 | } 12 | \description{ 13 | Play blackjack 14 | } 15 | -------------------------------------------------------------------------------- /man/play_slots.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/play.R 3 | \name{play_slots} 4 | \alias{play_slots} 5 | \title{Play the slot machine} 6 | \usage{ 7 | play_slots(name) 8 | } 9 | \arguments{ 10 | \item{name}{player name} 11 | } 12 | \description{ 13 | Play the slot machine 14 | } 15 | -------------------------------------------------------------------------------- /R/players.R: -------------------------------------------------------------------------------- 1 | 2 | #' List all player profiles 3 | #' @param file full path to file containing player profiles 4 | #' @export 5 | players <- function(file = Sys.getenv("CASINO_FILE")) { 6 | p <- switch(file.exists(file) + 1, NULL, readRDS(file)) 7 | tibble::tibble( 8 | name = purrr::map_chr(p, "name"), 9 | balance = purrr::map_chr(p, "balance") 10 | ) 11 | } -------------------------------------------------------------------------------- /man/play_poker.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/play.R 3 | \name{play_poker} 4 | \alias{play_poker} 5 | \title{Play poker} 6 | \usage{ 7 | play_poker(name, type) 8 | } 9 | \arguments{ 10 | \item{name}{player name} 11 | 12 | \item{type}{game type ('draw' or 'stud')} 13 | } 14 | \description{ 15 | Play poker 16 | } 17 | -------------------------------------------------------------------------------- /man/players.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/players.R 3 | \name{players} 4 | \alias{players} 5 | \title{List all player profiles} 6 | \usage{ 7 | players(file = Sys.getenv("CASINO_FILE")) 8 | } 9 | \arguments{ 10 | \item{file}{full path to file containing player profiles} 11 | } 12 | \description{ 13 | List all player profiles 14 | } 15 | -------------------------------------------------------------------------------- /docs/pkgdown.yml: -------------------------------------------------------------------------------- 1 | pandoc: 1.19.2.1 2 | pkgdown: 1.2.0 3 | pkgdown_sha: ~ 4 | articles: 5 | blackjack: games/blackjack.html 6 | poker: games/poker.html 7 | slots: games/slots.html 8 | persistent_player_profiles: persistent_player_profiles.html 9 | urls: 10 | reference: https://anthonypileggi.github.io/casino/reference 11 | article: https://anthonypileggi.github.io/casino/articles 12 | 13 | -------------------------------------------------------------------------------- /man/setup.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/setup.R 3 | \name{setup} 4 | \alias{setup} 5 | \title{Allow casino to store player profiles in a local file} 6 | \usage{ 7 | setup(file = file.path(getwd(), ".casino")) 8 | } 9 | \arguments{ 10 | \item{file}{full path to file} 11 | } 12 | \description{ 13 | Allow casino to store player profiles in a local file 14 | } 15 | -------------------------------------------------------------------------------- /man/Player.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/Player.R 3 | \docType{data} 4 | \name{Player} 5 | \alias{Player} 6 | \title{Player R6 Class} 7 | \format{An object of class \code{R6ClassGenerator} of length 24.} 8 | \usage{ 9 | Player 10 | } 11 | \description{ 12 | Player R6 Class 13 | } 14 | \examples{ 15 | setup("my_profile") 16 | Player$new("Player 1") 17 | Player$new("Player 2") 18 | delete() 19 | } 20 | \keyword{datasets} 21 | -------------------------------------------------------------------------------- /casino.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: XeLaTeX 14 | 15 | StripTrailingWhitespace: Yes 16 | 17 | BuildType: Package 18 | PackageUseDevtools: Yes 19 | PackageInstallArgs: --no-multiarch --with-keep.source 20 | PackageRoxygenize: rd,collate,namespace,vignette 21 | -------------------------------------------------------------------------------- /man/play_sound.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/play_sound.R 3 | \name{play_sound} 4 | \alias{play_sound} 5 | \title{Play a sound (if possible)} 6 | \usage{ 7 | play_sound(sound = "fanfare") 8 | } 9 | \arguments{ 10 | \item{sound}{character string or number specifying the sound (see \code{\link[beepr]{beep}})} 11 | } 12 | \description{ 13 | Play a sound (if possible) 14 | } 15 | \note{ 16 | requires the `beepr` package 17 | } 18 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # casino 0.1.0.9000 2 | 3 | 4 | # casino 0.1.0 5 | 6 | ## New games 7 | - Blackjack 8 | - Slot machine 9 | - Poker (5-card) 10 | - Stud 11 | - Draw 12 | 13 | ## New features 14 | - New `Blackjack`, `Poker`, and `Slots` R6 classes for playing games. 15 | - New `Player` R6 class is used for storing player information and history. 16 | - New `Deck` R6 class is used for playing card games. 17 | - Interactively `play()` casino games. 18 | - Run `setup()` to specify where player information is stored locally. -------------------------------------------------------------------------------- /man/Slots.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/Slots.R 3 | \docType{data} 4 | \name{Slots} 5 | \alias{Slots} 6 | \title{Slots R6 Class} 7 | \format{An object of class \code{R6ClassGenerator} of length 24.} 8 | \usage{ 9 | Slots 10 | } 11 | \description{ 12 | Slots R6 Class 13 | } 14 | \examples{ 15 | set.seed(101315) 16 | setup() 17 | 18 | # start the slot machine 19 | x <- Slots$new(who = "Player 1", bet = 10) 20 | 21 | # play 1 game 22 | x$play() 23 | 24 | # play >1 game at a time 25 | x$play(spins = 3) 26 | 27 | # clean-up 28 | delete() 29 | } 30 | \keyword{datasets} 31 | -------------------------------------------------------------------------------- /man/Poker.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/Poker.R 3 | \docType{data} 4 | \name{Poker} 5 | \alias{Poker} 6 | \title{Poker R6 Class} 7 | \format{An object of class \code{R6ClassGenerator} of length 24.} 8 | \usage{ 9 | Poker 10 | } 11 | \description{ 12 | Poker R6 Class 13 | } 14 | \examples{ 15 | set.seed(101315) 16 | setup() 17 | 18 | # draw poker 19 | x <- Poker$new(who = "Player 1", type = "draw", bet = 10) 20 | x$play() 21 | x$hold(1, 2, 5) 22 | x$draw() 23 | 24 | # stud poker (bet 20) 25 | x <- Poker$new(who = "Player 1", type = "stud", bet = 20) 26 | x$play() 27 | 28 | # clean-up 29 | delete() 30 | } 31 | \keyword{datasets} 32 | -------------------------------------------------------------------------------- /man/Blackjack.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/Blackjack.R 3 | \docType{data} 4 | \name{Blackjack} 5 | \alias{Blackjack} 6 | \title{Blackjack R6 Class} 7 | \format{An object of class \code{R6ClassGenerator} of length 24.} 8 | \usage{ 9 | Blackjack 10 | } 11 | \description{ 12 | Blackjack R6 Class 13 | } 14 | \examples{ 15 | set.seed(101315) 16 | setup() 17 | 18 | # sit at the blackjack table 19 | x <- Blackjack$new(who = "Player 1", bet = 10) 20 | 21 | # play a hand 22 | x$play() 23 | 24 | x$hit() 25 | 26 | x$stand() 27 | 28 | # play a hand blind w/out drawing 29 | x$play()$stand() 30 | 31 | # clean-up 32 | delete() 33 | } 34 | \keyword{datasets} 35 | -------------------------------------------------------------------------------- /man/Deck.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/Deck.R 3 | \docType{data} 4 | \name{Deck} 5 | \alias{Deck} 6 | \title{Deck R6 Class} 7 | \format{An object of class \code{R6ClassGenerator} of length 24.} 8 | \usage{ 9 | Deck 10 | } 11 | \description{ 12 | Deck R6 Class 13 | } 14 | \examples{ 15 | # create a new deck 16 | x <- Deck$new() 17 | x 18 | 19 | # draw a card 20 | x$draw(1) 21 | x 22 | 23 | # draw 10 cards 24 | x$draw(10) 25 | 26 | # check how many cards are left 27 | x$cards_left() 28 | 29 | # reset the deck 30 | x$shuffle() 31 | x 32 | 33 | # create a deck composed of 5 decks 34 | x <- Deck$new(decks = 5) 35 | x 36 | } 37 | \keyword{datasets} 38 | -------------------------------------------------------------------------------- /R/setup.R: -------------------------------------------------------------------------------- 1 | 2 | #' Allow casino to store player profiles in a local file 3 | #' @param file full path to file 4 | #' @export 5 | setup <- function(file = file.path(getwd(), ".casino")) { 6 | 7 | # create file for storing player profiles (if it doesn't exist) 8 | if (file.exists(file)) { 9 | message("Found an existing record of players at '", file, "'") 10 | } else { 11 | message("No records found.\nStoring player records at '", file, "'") 12 | saveRDS(NULL, file) 13 | } 14 | 15 | # set the CASINO_FILE environment variable to this file 16 | file <- normalizePath(file) 17 | if (Sys.getenv("CASINO_FILE") != file) { 18 | message("Updating value for environment variable 'CASINO_FILE'.") 19 | Sys.setenv(CASINO_FILE = file) 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## Resubmission 2 | This is a resubmission. In this version I have: 3 | 4 | * Removed the redundant "in R" in the Title 5 | * Converted `beepr` to a Suggested dependency. 6 | * Updated all functions to only play sounds when the `beepr` package is available. 7 | 8 | ## Test environments 9 | * local OS X install, R 3.5.2 10 | * win-builder (devel and release) 11 | * r-hub builder (devel and release) 12 | 13 | ## R CMD check results 14 | There were no ERRORs or WARNINGs. 15 | 16 | There was 1 NOTE: 17 | 18 | * checking CRAN incoming feasibility ... NOTE 19 | Maintainer: 'Anthony Pileggi ' 20 | 21 | New submission 22 | 23 | This is the first submission of this package. 24 | 25 | ## Downstream dependencies 26 | There are no downstream dependencies for this package. -------------------------------------------------------------------------------- /docs/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: casino 2 | Type: Package 3 | Title: Play Casino Games 4 | Version: 0.1.0.9000 5 | Authors@R: c( 6 | person("Anthony", "Pileggi", , "apileggi20@gmail.com", c("aut", "cre")) 7 | ) 8 | Description: Play casino games in the R console, 9 | including poker, blackjack, and a slot machine. 10 | Try to build your fortune before you succumb to the gambler's ruin! 11 | License: MIT + file LICENSE 12 | URL: https://anthonypileggi.github.io/casino, 13 | https://github.com/anthonypileggi/casino 14 | BugReports: https://github.com/anthonypileggi/casino/issues 15 | Encoding: UTF-8 16 | LazyData: true 17 | RoxygenNote: 6.1.1 18 | Imports: 19 | magrittr, 20 | dplyr, 21 | tibble, 22 | tidyr, 23 | purrr, 24 | crayon, 25 | R6, 26 | ggplot2, 27 | utils 28 | Suggests: 29 | knitr, 30 | rmarkdown, 31 | beepr 32 | VignetteBuilder: knitr 33 | -------------------------------------------------------------------------------- /vignettes/games/slots.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Slot Machine" 3 | author: "Anthony Pileggi" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Slot Machine} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | ```{r setup, include = FALSE} 13 | knitr::opts_chunk$set( 14 | collapse = TRUE, 15 | comment = "#>" 16 | ) 17 | 18 | set.seed(101315) 19 | ``` 20 | 21 | 22 | ## Example 23 | 24 | ```{r} 25 | library(casino) 26 | 27 | # Setup a new casino 28 | setup(".mgm") 29 | 30 | # Sit at a slot machine with default bet of 5 31 | x <- Slots$new(who = "Gritty", bet = 5) 32 | 33 | # Play a game 34 | x$play() 35 | 36 | # Play 5 games 37 | x$play(spins = 5) 38 | ``` 39 | 40 | 41 | ## Payouts 42 | 43 | ```{r, echo = FALSE, results = "asis"} 44 | # get payout table (based on betting 25) 45 | knitr::kable(x$get_payout()) 46 | ``` 47 | 48 | ```{r, include = FALSE} 49 | # delete records 50 | delete() 51 | ``` 52 | 53 | -------------------------------------------------------------------------------- /vignettes/games/blackjack.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Blackjack" 3 | author: "Anthony" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Blackjack} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | ```{r setup, include = FALSE} 13 | knitr::opts_chunk$set( 14 | collapse = TRUE, 15 | comment = "#>" 16 | ) 17 | 18 | set.seed(101315) 19 | ``` 20 | 21 | You can play Blackjack against the dealer. 22 | 23 | ## Payouts 24 | 25 | Outcome | Multiplier 26 | --- | --- 27 | Dealer Wins | 0x 28 | Player Wins | 2x 29 | 30 | 31 | ## Example 32 | 33 | ```{r} 34 | library(casino) 35 | 36 | # Setup a new casino 37 | setup(".wynn") 38 | 39 | # Sit at the blackjack table with default bet of 25 40 | x <- Blackjack$new(who = "Gritty", bet = 25) 41 | 42 | # Play a hand 43 | x$play() 44 | 45 | x$hit() 46 | 47 | x$stand() 48 | 49 | # Play another 50 | x$play() 51 | 52 | x$stand() 53 | 54 | # Play one last hand, and bet it all! 55 | x$play(bet = 100) 56 | 57 | x$hit() 58 | 59 | x$stand() 60 | ``` 61 | 62 | ![](https://media.giphy.com/media/1rK7WULnc8YgdmVIBz/giphy.gif) 63 | 64 | ```{r, include = FALSE} 65 | # delete records 66 | delete() 67 | ``` 68 | -------------------------------------------------------------------------------- /vignettes/games/poker.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Poker" 3 | author: "Anthony Pileggi" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Poker} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | ```{r setup, include = FALSE} 13 | knitr::opts_chunk$set( 14 | collapse = TRUE, 15 | comment = "#>" 16 | ) 17 | 18 | set.seed(101315) 19 | ``` 20 | 21 | ## Variants 22 | 23 | There are two poker variants available: 24 | 25 | - 5-card Draw Poker 26 | - 5-card Stud Poker 27 | 28 | 29 | ## Example 30 | 31 | ```{r} 32 | library(casino) 33 | 34 | # Setup a new casino 35 | setup(".paris") 36 | ``` 37 | 38 | 39 | ### 5-card Draw 40 | 41 | ```{r} 42 | x <- Poker$new(who = "Gritty", type = "draw", bet = 20) 43 | 44 | # play one hand 45 | x$play() 46 | 47 | x$hold(1, 2, 5) # hold cards in positions {1, 2, 5} 48 | 49 | x$draw() # draw new cards for positions {3, 4} 50 | ``` 51 | 52 | 53 | ### 5-card Stud 54 | 55 | ```{r} 56 | 57 | x <- Poker$new(who = "Gritty", type = "stud", bet = 10) 58 | 59 | # play one hand 60 | x$play() 61 | 62 | # play 2 hands back-to-back 63 | x$play()$play(bet = 5) 64 | 65 | ``` 66 | 67 | ## Payouts 68 | 69 | ```{r, echo = FALSE, results = "asis"} 70 | # get payout table (based on betting 25) 71 | knitr::kable(x$get_payout()) 72 | ``` 73 | 74 | ```{r, include = FALSE} 75 | # delete records 76 | delete() 77 | ``` 78 | -------------------------------------------------------------------------------- /vignettes/persistent_player_profiles.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Persistent Player Profiles" 3 | author: "Anthony Pileggi" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Persistent Player Profiles} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | ```{r setup, include = FALSE} 13 | knitr::opts_chunk$set( 14 | collapse = TRUE, 15 | comment = "#>" 16 | ) 17 | ``` 18 | 19 | # Introduction 20 | Player information is stored in a local file. By default, this file is call `.casino` 21 | and it is placed in the current working directory. 22 | 23 | ```{r} 24 | library(casino) 25 | 26 | # create a new file to store player profiles 27 | setup() 28 | 29 | # create some players 30 | Player$new("Player 1") 31 | 32 | # check the available players 33 | players() 34 | ``` 35 | 36 | 37 | # Multiple Players 38 | You can store multiple players in the same profile file. 39 | 40 | ```{r} 41 | # create more players 42 | Player$new("Player 2") 43 | Player$new("Player 3") 44 | 45 | # check the available players 46 | players() 47 | ``` 48 | 49 | 50 | # Multiple Profile Files 51 | If you want to store multiple player profiles, you can specify the filename. 52 | 53 | ```{r} 54 | # first profile 55 | setup(".bellagio") 56 | Player$new("Player 1") 57 | Player$new("Player 2") 58 | players() 59 | 60 | # second profile 61 | setup(".caesars") 62 | Player$new("Player 3") 63 | Player$new("Player 4") 64 | players() 65 | 66 | # now switch back to the first one 67 | setup(".bellagio") 68 | players() 69 | ``` 70 | 71 | 72 | # Delete Profiles 73 | If you want to delete all players in the current profile and reset the `casino` package, use the `delete()` function. 74 | 75 | ```{r} 76 | # delete current profile (.bellagio) 77 | delete() 78 | 79 | # delete a different profile (.caesars) 80 | setup(".caesars") 81 | delete() 82 | 83 | # delete the default profile (.casino) 84 | setup() 85 | delete() 86 | ``` -------------------------------------------------------------------------------- /docs/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | https://anthonypileggi.github.io/casino/index.html 5 | 6 | 7 | https://anthonypileggi.github.io/casino/reference/Blackjack.html 8 | 9 | 10 | https://anthonypileggi.github.io/casino/reference/Deck.html 11 | 12 | 13 | https://anthonypileggi.github.io/casino/reference/Player.html 14 | 15 | 16 | https://anthonypileggi.github.io/casino/reference/Poker.html 17 | 18 | 19 | https://anthonypileggi.github.io/casino/reference/Slots.html 20 | 21 | 22 | https://anthonypileggi.github.io/casino/reference/delete.html 23 | 24 | 25 | https://anthonypileggi.github.io/casino/reference/play.html 26 | 27 | 28 | https://anthonypileggi.github.io/casino/reference/play_blackjack.html 29 | 30 | 31 | https://anthonypileggi.github.io/casino/reference/play_poker.html 32 | 33 | 34 | https://anthonypileggi.github.io/casino/reference/play_slots.html 35 | 36 | 37 | https://anthonypileggi.github.io/casino/reference/play_sound.html 38 | 39 | 40 | https://anthonypileggi.github.io/casino/reference/players.html 41 | 42 | 43 | https://anthonypileggi.github.io/casino/reference/setup.html 44 | 45 | 46 | https://anthonypileggi.github.io/casino/articles/games/blackjack.html 47 | 48 | 49 | https://anthonypileggi.github.io/casino/articles/games/poker.html 50 | 51 | 52 | https://anthonypileggi.github.io/casino/articles/games/slots.html 53 | 54 | 55 | https://anthonypileggi.github.io/casino/articles/persistent_player_profiles.html 56 | 57 | 58 | -------------------------------------------------------------------------------- /R/Deck.R: -------------------------------------------------------------------------------- 1 | #' Deck R6 Class 2 | #' @importFrom magrittr "%>%" 3 | #' @examples 4 | #' # create a new deck 5 | #' x <- Deck$new() 6 | #' x 7 | #' 8 | #' # draw a card 9 | #' x$draw(1) 10 | #' x 11 | #' 12 | #' # draw 10 cards 13 | #' x$draw(10) 14 | #' 15 | #' # check how many cards are left 16 | #' x$cards_left() 17 | #' 18 | #' # reset the deck 19 | #' x$shuffle() 20 | #' x 21 | #' 22 | #' # create a deck composed of 5 decks 23 | #' x <- Deck$new(decks = 5) 24 | #' x 25 | #' @export 26 | Deck <- R6::R6Class("Deck", 27 | public = list( 28 | 29 | decks = NULL, 30 | deck = NULL, 31 | discard = NULL, 32 | 33 | # -- create a new deck 34 | initialize = function(decks = 1) { 35 | self$decks <- decks 36 | private$create() 37 | self$shuffle() 38 | }, 39 | 40 | # -- print method 41 | print = function(...) { 42 | cat("Deck: \n") 43 | cat(" Decks: ", self$decks, "\n", sep = "") 44 | cat(" Cards: ", 52 * self$decks, "\n", sep = "") 45 | cat(" Cards dealt: ", 52 * self$decks - nrow(self$deck), "\n", sep = "") 46 | cat(" Cards left: ", nrow(self$deck), "\n", sep = "") 47 | cat(" Next card: ", self$deck$value[1], " ", self$deck$suit[1], "s\n", sep = "") 48 | invisible(self) 49 | }, 50 | 51 | # -- reset deck and shuffle 52 | shuffle = function() { 53 | private$create() 54 | self$deck <- dplyr::sample_n(self$deck, nrow(self$deck)) 55 | invisible(self) 56 | }, 57 | 58 | # -- draw 'n' cards from the top of the deck 59 | draw = function(n = 1) { 60 | # TODO: shuffling in the middle of a game is probably not okay! 61 | if (self$cards_left() < n) 62 | self$shuffle() 63 | cards <- self$deck[1:n, ] 64 | self$deck <- self$deck[-(1:n), ] 65 | cards 66 | }, 67 | 68 | # -- how many cards are left in the deck? 69 | cards_left = function() { 70 | nrow(self$deck) 71 | } 72 | 73 | ), 74 | 75 | 76 | private = list( 77 | 78 | # create a new set of decks 79 | create = function() { 80 | deck <- 81 | tidyr::crossing( 82 | value = c(2:10, "J", "Q", "K", "A"), 83 | #suit = c("heart", "diamond", "spade", "club") 84 | suit = c("\u2665", "\u2666", "\u2660", "\u2663") 85 | ) 86 | self$deck <- purrr::map_df(1:self$decks, ~deck) 87 | } 88 | 89 | ) 90 | ) -------------------------------------------------------------------------------- /docs/docsearch.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // register a handler to move the focus to the search bar 4 | // upon pressing shift + "/" (i.e. "?") 5 | $(document).on('keydown', function(e) { 6 | if (e.shiftKey && e.keyCode == 191) { 7 | e.preventDefault(); 8 | $("#search-input").focus(); 9 | } 10 | }); 11 | 12 | $(document).ready(function() { 13 | // do keyword highlighting 14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ 15 | var mark = function() { 16 | 17 | var referrer = document.URL ; 18 | var paramKey = "q" ; 19 | 20 | if (referrer.indexOf("?") !== -1) { 21 | var qs = referrer.substr(referrer.indexOf('?') + 1); 22 | var qs_noanchor = qs.split('#')[0]; 23 | var qsa = qs_noanchor.split('&'); 24 | var keyword = ""; 25 | 26 | for (var i = 0; i < qsa.length; i++) { 27 | var currentParam = qsa[i].split('='); 28 | 29 | if (currentParam.length !== 2) { 30 | continue; 31 | } 32 | 33 | if (currentParam[0] == paramKey) { 34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); 35 | } 36 | } 37 | 38 | if (keyword !== "") { 39 | $(".contents").unmark({ 40 | done: function() { 41 | $(".contents").mark(keyword); 42 | } 43 | }); 44 | } 45 | } 46 | }; 47 | 48 | mark(); 49 | }); 50 | }); 51 | 52 | /* Search term highlighting ------------------------------*/ 53 | 54 | function matchedWords(hit) { 55 | var words = []; 56 | 57 | var hierarchy = hit._highlightResult.hierarchy; 58 | // loop to fetch from lvl0, lvl1, etc. 59 | for (var idx in hierarchy) { 60 | words = words.concat(hierarchy[idx].matchedWords); 61 | } 62 | 63 | var content = hit._highlightResult.content; 64 | if (content) { 65 | words = words.concat(content.matchedWords); 66 | } 67 | 68 | // return unique words 69 | var words_uniq = [...new Set(words)]; 70 | return words_uniq; 71 | } 72 | 73 | function updateHitURL(hit) { 74 | 75 | var words = matchedWords(hit); 76 | var url = ""; 77 | 78 | if (hit.anchor) { 79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; 80 | } else { 81 | url = hit.url + '?q=' + escape(words.join(" ")); 82 | } 83 | 84 | return url; 85 | } 86 | -------------------------------------------------------------------------------- /R/play.R: -------------------------------------------------------------------------------- 1 | 2 | #' Play in the casino 3 | #' @export 4 | play <- function() { 5 | 6 | # Create/Load player profile 7 | name <- readline(prompt = "Enter your name: ") 8 | Player$new(name) 9 | 10 | # Start playing 11 | again <- "y" 12 | while (tolower(again) %in% c("1", "y")) { 13 | game <- readline(prompt = "Available Games:\n\t1. Blackjack\n\t2. Poker\n\t3. Slots\n\t4. Quit\n\nWhat game do you want to play? ") 14 | if (tolower(game) %in% c("1", "blackjack")) { 15 | play_blackjack(name) 16 | } else if (tolower(game) %in% c("2", "poker")) { 17 | type <- readline(prompt = "Options:\n\t1. Draw\n\t2. Stud\n\nWhat game do you want to play? ") 18 | if (tolower(type) %in% c("1", "draw")) { 19 | play_poker(name, type = "draw") 20 | } else if (tolower(type) %in% c("2", "stud")) { 21 | play_poker(name, type = "stud") 22 | } 23 | } else if (tolower(game) %in% c("3", "slots")) { 24 | play_slots(name) 25 | } else if (tolower(game) %in% c("4", "quit")) { 26 | again <- "n" 27 | } else { 28 | message("Invalid selection! Please choose from options [1-4].") 29 | } 30 | } 31 | 32 | return("Thanks for playing!") 33 | } 34 | 35 | 36 | #' Play poker 37 | #' @param name player name 38 | #' @param type game type ('draw' or 'stud') 39 | play_poker <- function(name, type) { 40 | g <- Poker$new(who = name, type = type) 41 | keep_playing <- "" 42 | while (keep_playing == "") { 43 | g$play() 44 | while (g$turn != 0) { 45 | action <- readline(prompt = "Choose [1-5] to HOLD, or press [ENTER] to DRAW. ") 46 | if (action %in% as.character(1:5)) { 47 | g$hold(as.numeric(action)) 48 | } else { 49 | g$draw() 50 | } 51 | } 52 | keep_playing <- readline(prompt = "Press [Enter] to play again, or type anything to stop. ") 53 | } 54 | } 55 | 56 | #' Play blackjack 57 | #' @param name player name 58 | play_blackjack <- function(name) { 59 | g <- Blackjack$new(who = name) 60 | keep_playing <- "" 61 | while (keep_playing == "") { 62 | g$play() 63 | while (g$active) { 64 | act <- readline(prompt = "Options:\n\t1. Hit\n\t2. Stand ") 65 | if (tolower(act) %in% c("1", "hit")) 66 | g$hit() 67 | if (tolower(act) %in% c("2", "stand")) 68 | g$stand() 69 | } 70 | keep_playing <- readline(prompt = "Press [Enter] to play again, or type anything to stop. ") 71 | } 72 | } 73 | 74 | #' Play the slot machine 75 | #' @param name player name 76 | play_slots <- function(name) { 77 | g <- Slots$new(who = name) 78 | keep_playing <- "" 79 | while (keep_playing == "") { 80 | g$play() 81 | keep_playing <- readline(prompt = "Press [Enter] to spin again, or anything else to stop. ") 82 | } 83 | } -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | /* http://gregfranko.com/blog/jquery-best-practices/ */ 2 | (function($) { 3 | $(function() { 4 | 5 | $("#sidebar") 6 | .stick_in_parent({offset_top: 40}) 7 | .on('sticky_kit:bottom', function(e) { 8 | $(this).parent().css('position', 'static'); 9 | }) 10 | .on('sticky_kit:unbottom', function(e) { 11 | $(this).parent().css('position', 'relative'); 12 | }); 13 | 14 | $('body').scrollspy({ 15 | target: '#sidebar', 16 | offset: 60 17 | }); 18 | 19 | $('[data-toggle="tooltip"]').tooltip(); 20 | 21 | var cur_path = paths(location.pathname); 22 | var links = $("#navbar ul li a"); 23 | var max_length = -1; 24 | var pos = -1; 25 | for (var i = 0; i < links.length; i++) { 26 | if (links[i].getAttribute("href") === "#") 27 | continue; 28 | var nav_path = paths(links[i].pathname); 29 | 30 | var length = prefix_length(nav_path, cur_path); 31 | if (length > max_length) { 32 | max_length = length; 33 | pos = i; 34 | } 35 | } 36 | 37 | // Add class to parent
  • , and enclosing
  • if in dropdown 38 | if (pos >= 0) { 39 | var menu_anchor = $(links[pos]); 40 | menu_anchor.parent().addClass("active"); 41 | menu_anchor.closest("li.dropdown").addClass("active"); 42 | } 43 | }); 44 | 45 | function paths(pathname) { 46 | var pieces = pathname.split("/"); 47 | pieces.shift(); // always starts with / 48 | 49 | var end = pieces[pieces.length - 1]; 50 | if (end === "index.html" || end === "") 51 | pieces.pop(); 52 | return(pieces); 53 | } 54 | 55 | function prefix_length(needle, haystack) { 56 | if (needle.length > haystack.length) 57 | return(0); 58 | 59 | // Special case for length-0 haystack, since for loop won't run 60 | if (haystack.length === 0) { 61 | return(needle.length === 0 ? 1 : 0); 62 | } 63 | 64 | for (var i = 0; i < haystack.length; i++) { 65 | if (needle[i] != haystack[i]) 66 | return(i); 67 | } 68 | 69 | return(haystack.length); 70 | } 71 | 72 | /* Clipboard --------------------------*/ 73 | 74 | function changeTooltipMessage(element, msg) { 75 | var tooltipOriginalTitle=element.getAttribute('data-original-title'); 76 | element.setAttribute('data-original-title', msg); 77 | $(element).tooltip('show'); 78 | element.setAttribute('data-original-title', tooltipOriginalTitle); 79 | } 80 | 81 | if(ClipboardJS.isSupported()) { 82 | $(document).ready(function() { 83 | var copyButton = ""; 84 | 85 | $(".examples, div.sourceCode").addClass("hasCopyButton"); 86 | 87 | // Insert copy buttons: 88 | $(copyButton).prependTo(".hasCopyButton"); 89 | 90 | // Initialize tooltips: 91 | $('.btn-copy-ex').tooltip({container: 'body'}); 92 | 93 | // Initialize clipboard: 94 | var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', { 95 | text: function(trigger) { 96 | return trigger.parentNode.textContent; 97 | } 98 | }); 99 | 100 | clipboardBtnCopies.on('success', function(e) { 101 | changeTooltipMessage(e.trigger, 'Copied!'); 102 | e.clearSelection(); 103 | }); 104 | 105 | clipboardBtnCopies.on('error', function() { 106 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); 107 | }); 108 | }); 109 | } 110 | })(window.jQuery || window.$) 111 | -------------------------------------------------------------------------------- /R/Slots.R: -------------------------------------------------------------------------------- 1 | #' Slots R6 Class 2 | #' @importFrom magrittr "%>%" 3 | #' @examples 4 | #' set.seed(101315) 5 | #' setup() 6 | #' 7 | #' # start the slot machine 8 | #' x <- Slots$new(who = "Player 1", bet = 10) 9 | #' 10 | #' # play 1 game 11 | #' x$play() 12 | #' 13 | #' # play >1 game at a time 14 | #' x$play(spins = 3) 15 | #' 16 | #' # clean-up 17 | #' delete() 18 | #' @export 19 | Slots <- R6::R6Class("Slots", 20 | public = list( 21 | 22 | bet = NULL, 23 | who = NULL, 24 | reel = NULL, 25 | reels = NULL, 26 | turn = NULL, 27 | 28 | verbose = NULL, 29 | sound = NULL, 30 | 31 | # -- setup machine 32 | initialize = function(who = NA, bet = 10, verbose = TRUE, sound = TRUE) { 33 | self$who <- Player$new(who) 34 | self$bet <- bet 35 | self$verbose <- verbose 36 | self$sound <- sound 37 | private$make_reel() 38 | }, 39 | 40 | # -- print 41 | print = function(...) { 42 | if (self$turn == 0) { 43 | cat("Slot Machine: \n") 44 | cat("Player: ", self$who$name, "\n", sep = "") 45 | cat("Bank: ", self$who$balance, "\n", sep = "") 46 | cat(" Start a new game with `play().", "\n", sep = "") 47 | } else if (self$turn == 1) { 48 | score <- tail(self$who$history, 1) 49 | cat(" Reels: ", self$print_reels(), "\n", sep = "") 50 | cat(" You ", ifelse(score$net >= 0, "won", "lost"), " ", score$net, "!\n", sep = "") 51 | cat(" Now you have ", self$who$balance, " in your account.\n", sep = "") 52 | } 53 | invisible(self) 54 | }, 55 | 56 | # -- print reel in terminal using crayon highlighting 57 | print_reels = function() { 58 | reels <- crayon::bold(paste(self$reels, collapse = " ")) 59 | switch(length(unique(self$reels)), 60 | crayon::bgGreen(reels), 61 | crayon::bgYellow(reels), 62 | crayon::bgRed(reels) 63 | ) 64 | }, 65 | 66 | # -- gameplay 67 | play = function(bet = self$bet, spins = 1) { 68 | for (i in 1:spins) { 69 | self$bet <- self$who$bet(bet) 70 | private$spin() 71 | private$end_game() 72 | } 73 | cat(crayon::italic("Do you want to `play()` again?", "\n", sep = "")) 74 | invisible(self) 75 | }, 76 | 77 | # -- see payout table 78 | get_payout = function(bet = self$bet) { 79 | dplyr::mutate( 80 | private$payout(), 81 | win = bet * multiplier 82 | ) 83 | } 84 | ), 85 | 86 | private = list( 87 | 88 | # -- create a reel 89 | make_reel = function() { 90 | reel <- c("!", "@", "#", "$", "%", "^", "&", "*") 91 | self$reel <- sample(rep(reel, (1:length(reel)) ^ 3)) 92 | self$turn <- 0 93 | }, 94 | 95 | # -- spin reels 96 | spin = function() { 97 | self$reels <- sample(self$reel, 3) 98 | invisible(self) 99 | }, 100 | 101 | # -- payout structure 102 | payout = function() { 103 | freq <- table(self$reel) 104 | tibble::tibble( 105 | outcome = purrr::map_chr(names(freq), ~paste(rep(.x, 3), collapse = " ")), 106 | multiplier = as.numeric(floor(1 / ((freq / sum(freq)) ^ 3))) 107 | ) %>% 108 | dplyr::arrange(desc(multiplier)) 109 | }, 110 | 111 | # -- score of a single game/spin 112 | score = function() { 113 | dplyr::left_join( 114 | tibble::tibble(outcome = paste(self$reels, collapse = " ")), 115 | private$payout(), 116 | by = "outcome" 117 | ) %>% 118 | dplyr::mutate( 119 | multiplier = ifelse(is.na(multiplier), 0, multiplier), 120 | bet = self$bet, 121 | win = bet * multiplier, 122 | net = win - bet 123 | ) 124 | }, 125 | 126 | # -- end game and record results 127 | end_game = function() { 128 | score <- private$score() 129 | self$who$record(game = "Slots", outcome = score$outcome, bet = score$bet, win = score$win, net = score$net) 130 | self$turn <- 1 131 | if (self$sound && score$win > 0) 132 | play_sound() 133 | if (self$verbose) 134 | print(self) 135 | } 136 | 137 | ) 138 | ) -------------------------------------------------------------------------------- /readme.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r, echo = FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | comment = "#>", 11 | fig.path = "man/figures/" 12 | ) 13 | 14 | set.seed(101315) 15 | ``` 16 | 17 | 18 | # casino 19 | 20 | > Welcome to the casino, we've got fun and games 21 | > 22 | > We got everything you want and we know your name 23 | > 24 | > We are a place where you can find whatever you may need 25 | > 26 | > And if you got no money, don't worry! You can play for "free"! 27 | 28 | 29 | [![CRAN status](https://www.r-pkg.org/badges/version-last-release/casino)](https://cran.r-project.org/package=casino) 30 | [![CRAN downloads](http://cranlogs.r-pkg.org/badges/casino)](https://cran.r-project.org/package=casino) 31 | 32 | 33 | ## Overview 34 | 35 | Play casino games in the R console! 36 | 37 | Available games: 38 | 39 | - Poker (5-card draw/stud) 40 | - Blackjack 41 | - Slot machine 42 | 43 | 44 | ## Installation 45 | 46 | ```{r, eval = FALSE} 47 | # Install the CRAN version 48 | install.packages("casino") 49 | 50 | # Install development version from GitHub 51 | devtools::install_github("anthonypileggi/casino") 52 | ``` 53 | 54 | 55 | ## Quick Start 56 | Are you getting impatient already? Then use `play()` to get started immediately. 57 | 58 | ```{r, eval = FALSE} 59 | casino::play() 60 | ``` 61 | 62 | 63 | ## Setup (`.casino`) 64 | All players must agree to our policies on recording activity. 65 | If you do not agree, you cannot play. House rules! 66 | 67 | ```{r} 68 | library(casino) 69 | 70 | # create a local file for storing persisent player data 71 | setup() 72 | ``` 73 | 74 | This allows us to store player information persistently between games and R sessions. 75 | 76 | 77 | ## Create a Player 78 | You can create a new player manually. 79 | 80 | ```{r} 81 | 82 | # Create a new player 83 | Player$new(name = "Player 1") 84 | 85 | # View all available player profiles 86 | players() 87 | ``` 88 | 89 | Or just start playing, and one will automatically be created for you. 90 | 91 | ```{r} 92 | # Start a new game (this will auto-create a player) 93 | Blackjack$new(who = "Player 2") 94 | 95 | # View all available player profiles (again) 96 | players() 97 | ``` 98 | 99 | 100 | ## Play Casino Games 101 | 102 | Now it's time to head off to the casino! 103 | What do you want to play first?! 104 | 105 | 106 | ### Poker (5-card stud) 107 | ```{r} 108 | x <- Poker$new(who = "Player 1", type = "stud", bet = 10) 109 | 110 | # play a game 111 | x$play() 112 | 113 | # specify a different bet for this game 114 | x$play(bet = 5) 115 | ``` 116 | 117 | 118 | ### Poker (5-card draw) 119 | ```{r} 120 | x <- Poker$new(who = "Player 1", type = "draw", bet = 20) 121 | 122 | # play a game 123 | x$play() 124 | 125 | x$hold(1, 2, 5) # hold cards in positions {1, 2, 5} 126 | 127 | x$draw() # draw new cards for positions {3, 4} 128 | ``` 129 | 130 | ### Blackjack 131 | ```{r} 132 | x <- Blackjack$new(who = "Player 1", bet = 25) 133 | 134 | x$play()$stand() 135 | ``` 136 | 137 | ### Slot Machine 138 | ```{r} 139 | x <- Slots$new(who = "Player 1", bet = 1) 140 | 141 | x$play() 142 | 143 | # set the `spins` argument to play > 1 game at a time 144 | x$play(spins = 2) 145 | ``` 146 | 147 | 148 | ## I think I have a gambling problem 149 | 150 | If you want to play a lot of games, you can write a script. 151 | Just make sure to silence the output (`verbose = FALSE`) and sounds (`sound = FALSE`). 152 | 153 | ```{r, messages = FALSE} 154 | # poker (stud) 155 | x <- Poker$new(who = "Player 1", type = "stud", bet = 10, verbose = FALSE, sound = FALSE) 156 | for (i in 1:50) 157 | suppressMessages(x$play()) 158 | 159 | # blackjack (blind) 160 | x <- Blackjack$new(who = "Player 1", bet = 5, verbose = FALSE, sound = FALSE) 161 | for (i in 1:50) { 162 | suppressMessages(x$play()) 163 | if (x$active) 164 | x$stand() 165 | } 166 | 167 | # penny slots 168 | x <- Slots$new(who = "Player 1", bet = 1, verbose = FALSE, sound = FALSE) 169 | suppressMessages(x$play(spins = 50)) 170 | ``` 171 | 172 | 173 | ## Ok, now I lost everything... 174 | 175 | If you run out of money, the Bank will immediately loan you 100. 176 | 177 | > You: "So, what's the interest rate on this loan?" 178 | > Bank: "Oh, don't worry. It's very reasonable..." 179 | 180 | 181 | ## Wait, how much did you say I owe? 182 | 183 | ```{r} 184 | # player profile is stored in `$who` of a game object 185 | player <- x$who 186 | 187 | player$debt() 188 | ``` 189 | 190 | 191 | ## It's closing time... 192 | 193 | What a fun day at the casino! Or, was it? 194 | ```{r} 195 | # player profile is stored in `$who` of a game object 196 | player <- x$who 197 | 198 | # Overall 199 | player$summary() 200 | 201 | # By Game 202 | player$summary(game) 203 | ``` 204 | 205 | Let's relive the excitement! 206 | ```{r plot-history, fig.height = 4, fig.width = 8} 207 | player$plot() 208 | ``` 209 | 210 | Well, I guess we'll you'll be back tomorrow. See you then! 211 | 212 | ```{r, echo = FALSE, include = FALSE} 213 | # clean-up player information created while compiling readme 214 | delete() 215 | ``` -------------------------------------------------------------------------------- /docs/pkgdown.css: -------------------------------------------------------------------------------- 1 | /* Sticky footer */ 2 | 3 | /** 4 | * Basic idea: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/ 5 | * Details: https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/site.css 6 | * 7 | * .Site -> body > .container 8 | * .Site-content -> body > .container .row 9 | * .footer -> footer 10 | * 11 | * Key idea seems to be to ensure that .container and __all its parents__ 12 | * have height set to 100% 13 | * 14 | */ 15 | 16 | html, body { 17 | height: 100%; 18 | } 19 | 20 | body > .container { 21 | display: flex; 22 | height: 100%; 23 | flex-direction: column; 24 | 25 | padding-top: 60px; 26 | } 27 | 28 | body > .container .row { 29 | flex: 1 0 auto; 30 | } 31 | 32 | footer { 33 | margin-top: 45px; 34 | padding: 35px 0 36px; 35 | border-top: 1px solid #e5e5e5; 36 | color: #666; 37 | display: flex; 38 | flex-shrink: 0; 39 | } 40 | footer p { 41 | margin-bottom: 0; 42 | } 43 | footer div { 44 | flex: 1; 45 | } 46 | footer .pkgdown { 47 | text-align: right; 48 | } 49 | footer p { 50 | margin-bottom: 0; 51 | } 52 | 53 | img.icon { 54 | float: right; 55 | } 56 | 57 | img { 58 | max-width: 100%; 59 | } 60 | 61 | /* Fix bug in bootstrap (only seen in firefox) */ 62 | summary { 63 | display: list-item; 64 | } 65 | 66 | /* Typographic tweaking ---------------------------------*/ 67 | 68 | .contents h1.page-header { 69 | margin-top: calc(-60px + 1em); 70 | } 71 | 72 | /* Section anchors ---------------------------------*/ 73 | 74 | a.anchor { 75 | margin-left: -30px; 76 | display:inline-block; 77 | width: 30px; 78 | height: 30px; 79 | visibility: hidden; 80 | 81 | background-image: url(./link.svg); 82 | background-repeat: no-repeat; 83 | background-size: 20px 20px; 84 | background-position: center center; 85 | } 86 | 87 | .hasAnchor:hover a.anchor { 88 | visibility: visible; 89 | } 90 | 91 | @media (max-width: 767px) { 92 | .hasAnchor:hover a.anchor { 93 | visibility: hidden; 94 | } 95 | } 96 | 97 | 98 | /* Fixes for fixed navbar --------------------------*/ 99 | 100 | .contents h1, .contents h2, .contents h3, .contents h4 { 101 | padding-top: 60px; 102 | margin-top: -40px; 103 | } 104 | 105 | /* Static header placement on mobile devices */ 106 | @media (max-width: 767px) { 107 | .navbar-fixed-top { 108 | position: absolute; 109 | } 110 | .navbar { 111 | padding: 0; 112 | } 113 | } 114 | 115 | 116 | /* Sidebar --------------------------*/ 117 | 118 | #sidebar { 119 | margin-top: 30px; 120 | } 121 | #sidebar h2 { 122 | font-size: 1.5em; 123 | margin-top: 1em; 124 | } 125 | 126 | #sidebar h2:first-child { 127 | margin-top: 0; 128 | } 129 | 130 | #sidebar .list-unstyled li { 131 | margin-bottom: 0.5em; 132 | } 133 | 134 | .orcid { 135 | height: 16px; 136 | vertical-align: middle; 137 | } 138 | 139 | /* Reference index & topics ----------------------------------------------- */ 140 | 141 | .ref-index th {font-weight: normal;} 142 | 143 | .ref-index td {vertical-align: top;} 144 | .ref-index .icon {width: 40px;} 145 | .ref-index .alias {width: 40%;} 146 | .ref-index-icons .alias {width: calc(40% - 40px);} 147 | .ref-index .title {width: 60%;} 148 | 149 | .ref-arguments th {text-align: right; padding-right: 10px;} 150 | .ref-arguments th, .ref-arguments td {vertical-align: top;} 151 | .ref-arguments .name {width: 20%;} 152 | .ref-arguments .desc {width: 80%;} 153 | 154 | /* Nice scrolling for wide elements --------------------------------------- */ 155 | 156 | table { 157 | display: block; 158 | overflow: auto; 159 | } 160 | 161 | /* Syntax highlighting ---------------------------------------------------- */ 162 | 163 | pre { 164 | word-wrap: normal; 165 | word-break: normal; 166 | border: 1px solid #eee; 167 | } 168 | 169 | pre, code { 170 | background-color: #f8f8f8; 171 | color: #333; 172 | } 173 | 174 | pre code { 175 | overflow: auto; 176 | word-wrap: normal; 177 | white-space: pre; 178 | } 179 | 180 | pre .img { 181 | margin: 5px 0; 182 | } 183 | 184 | pre .img img { 185 | background-color: #fff; 186 | display: block; 187 | height: auto; 188 | } 189 | 190 | code a, pre a { 191 | color: #375f84; 192 | } 193 | 194 | a.sourceLine:hover { 195 | text-decoration: none; 196 | } 197 | 198 | .fl {color: #1514b5;} 199 | .fu {color: #000000;} /* function */ 200 | .ch,.st {color: #036a07;} /* string */ 201 | .kw {color: #264D66;} /* keyword */ 202 | .co {color: #888888;} /* comment */ 203 | 204 | .message { color: black; font-weight: bolder;} 205 | .error { color: orange; font-weight: bolder;} 206 | .warning { color: #6A0366; font-weight: bolder;} 207 | 208 | /* Clipboard --------------------------*/ 209 | 210 | .hasCopyButton { 211 | position: relative; 212 | } 213 | 214 | .btn-copy-ex { 215 | position: absolute; 216 | right: 0; 217 | top: 0; 218 | visibility: hidden; 219 | } 220 | 221 | .hasCopyButton:hover button.btn-copy-ex { 222 | visibility: visible; 223 | } 224 | 225 | /* mark.js ----------------------------*/ 226 | 227 | mark { 228 | background-color: rgba(255, 255, 51, 0.5); 229 | border-bottom: 2px solid rgba(255, 153, 51, 0.3); 230 | padding: 1px; 231 | } 232 | 233 | /* vertical spacing after htmlwidgets */ 234 | .html-widget { 235 | margin-bottom: 10px; 236 | } 237 | -------------------------------------------------------------------------------- /docs/LICENSE-text.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | License • casino 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 48 | 49 | 50 | 51 | 52 | 59 | 60 | 61 | 62 | 63 |
    64 |
    65 | 129 | 130 | 131 |
    132 | 133 |
    134 |
    135 | 138 | 139 |
    YEAR: 2018
    140 | COPYRIGHT HOLDER: Anthony Pileggi
    141 | 
    142 | 143 |
    144 | 145 |
    146 | 147 | 148 |
    149 | 152 | 153 |
    154 |

    Site built with pkgdown 1.2.0.

    155 |
    156 |
    157 |
    158 | 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /docs/authors.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Authors • casino 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 48 | 49 | 50 | 51 | 52 | 59 | 60 | 61 | 62 | 63 |
    64 |
    65 | 129 | 130 | 131 |
    132 | 133 |
    134 |
    135 | 138 | 139 | 145 | 146 |
    147 | 148 |
    149 | 150 | 151 |
    152 | 155 | 156 |
    157 |

    Site built with pkgdown 1.2.0.

    158 |
    159 |
    160 |
    161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /docs/articles/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Articles • casino 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 48 | 49 | 50 | 51 | 52 | 59 | 60 | 61 | 62 | 63 |
    64 |
    65 | 129 | 130 | 131 |
    132 | 133 |
    134 |
    135 | 138 | 139 |
    140 |

    All vignettes

    141 |

    142 | 143 | 149 |
    150 |
    151 |
    152 | 153 |
    154 | 157 | 158 |
    159 |

    Site built with pkgdown 1.2.0.

    160 |
    161 |
    162 |
    163 | 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /docs/reference/play.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Play in the casino — play • casino 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 50 | 51 | 52 | 53 | 54 | 61 | 62 | 63 | 64 | 65 |
    66 |
    67 | 131 | 132 | 133 |
    134 | 135 |
    136 |
    137 | 142 | 143 |
    144 | 145 |

    Play in the casino

    146 | 147 |
    148 | 149 |
    play()
    150 | 151 | 152 |
    153 | 159 |
    160 | 161 |
    162 | 165 | 166 |
    167 |

    Site built with pkgdown 1.2.0.

    168 |
    169 |
    170 |
    171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /docs/reference/delete.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Delete all player history and re-lock the casino — delete • casino 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 50 | 51 | 52 | 53 | 54 | 61 | 62 | 63 | 64 | 65 |
    66 |
    67 | 131 | 132 | 133 |
    134 | 135 |
    136 |
    137 | 142 | 143 |
    144 | 145 |

    Delete all player history and re-lock the casino

    146 | 147 |
    148 | 149 |
    delete()
    150 | 151 | 152 |
    153 | 159 |
    160 | 161 |
    162 | 165 | 166 |
    167 |

    Site built with pkgdown 1.2.0.

    168 |
    169 |
    170 |
    171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /docs/reference/play_blackjack.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Play blackjack — play_blackjack • casino 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 50 | 51 | 52 | 53 | 54 | 61 | 62 | 63 | 64 | 65 |
    66 |
    67 | 131 | 132 | 133 |
    134 | 135 |
    136 |
    137 | 142 | 143 |
    144 | 145 |

    Play blackjack

    146 | 147 |
    148 | 149 |
    play_blackjack(name)
    150 | 151 |

    Arguments

    152 | 153 | 154 | 155 | 156 | 157 | 158 |
    name

    player name

    159 | 160 | 161 |
    162 | 169 |
    170 | 171 |
    172 | 175 | 176 |
    177 |

    Site built with pkgdown 1.2.0.

    178 |
    179 |
    180 |
    181 | 182 | 183 | 184 | 185 | 186 | 187 | -------------------------------------------------------------------------------- /docs/reference/play_slots.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Play the slot machine — play_slots • casino 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 50 | 51 | 52 | 53 | 54 | 61 | 62 | 63 | 64 | 65 |
    66 |
    67 | 131 | 132 | 133 |
    134 | 135 |
    136 |
    137 | 142 | 143 |
    144 | 145 |

    Play the slot machine

    146 | 147 |
    148 | 149 |
    play_slots(name)
    150 | 151 |

    Arguments

    152 | 153 | 154 | 155 | 156 | 157 | 158 |
    name

    player name

    159 | 160 | 161 |
    162 | 169 |
    170 | 171 |
    172 | 175 | 176 |
    177 |

    Site built with pkgdown 1.2.0.

    178 |
    179 |
    180 |
    181 | 182 | 183 | 184 | 185 | 186 | 187 | -------------------------------------------------------------------------------- /docs/reference/play_poker.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Play poker — play_poker • casino 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 50 | 51 | 52 | 53 | 54 | 61 | 62 | 63 | 64 | 65 |
    66 |
    67 | 131 | 132 | 133 |
    134 | 135 |
    136 |
    137 | 142 | 143 |
    144 | 145 |

    Play poker

    146 | 147 |
    148 | 149 |
    play_poker(name, type)
    150 | 151 |

    Arguments

    152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 |
    name

    player name

    type

    game type ('draw' or 'stud')

    163 | 164 | 165 |
    166 | 173 |
    174 | 175 |
    176 | 179 | 180 |
    181 |

    Site built with pkgdown 1.2.0.

    182 |
    183 |
    184 |
    185 | 186 | 187 | 188 | 189 | 190 | 191 | -------------------------------------------------------------------------------- /R/Blackjack.R: -------------------------------------------------------------------------------- 1 | #' Blackjack R6 Class 2 | #' @importFrom magrittr "%>%" 3 | #' @examples 4 | #' set.seed(101315) 5 | #' setup() 6 | #' 7 | #' # sit at the blackjack table 8 | #' x <- Blackjack$new(who = "Player 1", bet = 10) 9 | #' 10 | #' # play a hand 11 | #' x$play() 12 | #' 13 | #' x$hit() 14 | #' 15 | #' x$stand() 16 | #' 17 | #' # play a hand blind w/out drawing 18 | #' x$play()$stand() 19 | #' 20 | #' # clean-up 21 | #' delete() 22 | #' @export 23 | Blackjack <- R6::R6Class("Blackjack", 24 | 25 | public = list( 26 | 27 | decks = NULL, 28 | bet = NULL, 29 | who = NULL, 30 | 31 | verbose = NULL, 32 | sound = NULL, 33 | 34 | # TODO: make the 'dealer' object private (so player cannot see the first card!!) 35 | player = NULL, 36 | dealer = NULL, 37 | 38 | active = FALSE, 39 | 40 | # setup blackjack table 41 | initialize = function(who = NA, decks = 1, bet = 10, verbose = TRUE, sound = TRUE) { 42 | self$decks <- decks 43 | private$deck <- Deck$new(decks) 44 | self$who <- Player$new(who) 45 | self$bet <- bet 46 | self$verbose <- verbose 47 | self$sound <- sound 48 | }, 49 | 50 | # print method 51 | print = function(...) { 52 | if (!self$active) { 53 | cat("Blackjack (w/ ", self$decks, " decks): \n") 54 | cat("Player: ", self$who$name, "\n", sep = "") 55 | cat("Bank: ", self$who$balance, "\n", sep = "") 56 | cat("Start a new game with `play()`.", "\n", sep = "") 57 | } else { 58 | p <- private$score_hand("player")$total 59 | d <- private$score_hand("dealer")$total 60 | cat(" Player Hand: {", paste(self$player$value, collapse = ", "), "} = ", p, "\n", sep = "") 61 | cat(private$print_dealer()) 62 | cat("Will you `hit()` or `stand()`?", "\n", sep = "") 63 | } 64 | # TODO: print outcome of a game 65 | invisible(self) 66 | }, 67 | 68 | # -- start a new game 69 | play = function(bet = self$bet) { 70 | if (self$active) 71 | stop("You already started a game!") 72 | self$bet <- self$who$bet(bet) 73 | self$player <- self$dealer <- NULL 74 | if (private$deck$cards_left() < 15) 75 | private$deck$shuffle() 76 | for (i in 1:2) { 77 | private$deal("player") 78 | private$deal("dealer") 79 | } 80 | self$active <- TRUE 81 | private$check_scores() # check if anyone has 21 yet 82 | if (self$verbose) 83 | print(self) 84 | invisible(self) 85 | }, 86 | 87 | # -- hit 88 | hit = function() { 89 | if (self$active) 90 | private$deal("player") 91 | private$check_scores() 92 | if (self$verbose) 93 | print(self) 94 | invisible(self) 95 | }, 96 | 97 | # -- stand 98 | stand = function() { 99 | private$end_game() 100 | } 101 | ), 102 | 103 | active = list(), 104 | 105 | private = list( 106 | 107 | deck = NULL, 108 | 109 | # -- print-helper: print the dealer's hand 110 | print_dealer = function() { 111 | paste(" Dealer Hand: {?, ", paste(self$dealer$value[-1], collapse = ", "), "} = ?\n", sep = "") 112 | }, 113 | 114 | # -- deal a card to player/dealer 115 | deal = function(to = "player") { 116 | self[[to]] <- dplyr::bind_rows(self[[to]], private$deck$draw()) 117 | }, 118 | 119 | # -- end the game 120 | end_game = function() { 121 | private$play_dealer() 122 | result <- private$score() 123 | self$who$record(game = "Blackjack", outcome = result$outcome, bet = result$bet, win = result$win, net = result$net) 124 | self$active <- FALSE 125 | if (self$sound && result$win > 0) 126 | play_sound() 127 | if (self$verbose) { 128 | cat("Game over! ", result$outcome, "\n", sep = "") 129 | cat(" You ", ifelse(result$net >= 0, "won", "lost"), " ", result$net, "!\n", sep = "") 130 | cat(" Now you have ", self$who$balance, " in your account.\n", sep = "") 131 | } 132 | }, 133 | 134 | # -- finish the dealers turn 135 | play_dealer = function() { 136 | keep_going <- TRUE 137 | while (keep_going) { 138 | total <- private$score_hand("dealer")$total 139 | if (total > 16) { 140 | keep_going <- FALSE 141 | } else { 142 | private$deal("dealer") 143 | } 144 | } 145 | }, 146 | 147 | # Scoring 148 | # -- get all possible ace totals for a hand 149 | ace_totals = function(to = "player") { 150 | n_aces <- sum(self[[to]] == "A") 151 | if (n_aces == 0) 152 | return(0) 153 | ace_combos <- combn(rep(c(1, 11), n_aces), n_aces) 154 | sort( 155 | unique( 156 | apply(ace_combos, 2, sum) 157 | ) 158 | ) 159 | }, 160 | # -- score a single hand (player or dealer) 161 | score_hand = function(to = "player") { 162 | score <- self[[to]] %>% 163 | dplyr::mutate( 164 | value = dplyr::case_when( 165 | value %in% c("J", "Q", "K") ~ 10, 166 | value != "A" ~ suppressWarnings(as.numeric(value)) 167 | ) 168 | ) %>% 169 | dplyr::summarise( 170 | cards = dplyr::n(), 171 | total = sum(value, na.rm = TRUE) 172 | ) 173 | # get all score possiblities (based on Aces) 174 | scores <- purrr::map_df( 175 | private$ace_totals(to), 176 | ~dplyr::mutate(score, total = total + .x) 177 | ) 178 | # return the 'best' score among all options 179 | if (all(scores$total > 21)) { 180 | head(scores, 1) 181 | } else { 182 | scores %>% 183 | dplyr::filter(total <= 21) %>% 184 | tail(1) 185 | } 186 | }, 187 | 188 | # -- get the result of a single game 189 | score = function() { 190 | p <- private$score_hand("player")$total 191 | d <- private$score_hand("dealer")$total 192 | tibble::tibble( 193 | player = p, 194 | dealer = d, 195 | outcome = dplyr::case_when( 196 | p > 21 ~ "player bust", # player bust 197 | d > 21 ~ "dealer bust", # dealer bust 198 | p == d ~ "push", # tie 199 | p > d ~ "player wins", # player wins 200 | p < d ~ "dealer wins" # dealer wins 201 | ), 202 | bet = self$bet, 203 | win = dplyr::case_when( 204 | outcome %in% c("player wins", "dealer bust") ~ self$bet * 2, 205 | outcome %in% c("dealer wins", "player bust") ~ 0, 206 | outcome %in% "push" ~ self$bet 207 | ), 208 | net = win - bet 209 | ) 210 | }, 211 | 212 | # -- check for blackjack and/or 21, and if found end the game 213 | check_scores = function() { 214 | score <- private$score() 215 | if (score$player == 21 & nrow(self$player) == 2) 216 | message("You got Blackjack!\n") 217 | if (score$dealer == 21 & nrow(self$dealer) == 2) 218 | message("Dealer got Blackjack!\n") 219 | if (score$player >= 21) 220 | private$end_game() 221 | } 222 | ) 223 | ) 224 | -------------------------------------------------------------------------------- /docs/reference/players.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | List all player profiles — players • casino 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 50 | 51 | 52 | 53 | 54 | 61 | 62 | 63 | 64 | 65 |
    66 |
    67 | 131 | 132 | 133 |
    134 | 135 |
    136 |
    137 | 142 | 143 |
    144 | 145 |

    List all player profiles

    146 | 147 |
    148 | 149 |
    players(file = Sys.getenv("CASINO_FILE"))
    150 | 151 |

    Arguments

    152 | 153 | 154 | 155 | 156 | 157 | 158 |
    file

    full path to file containing player profiles

    159 | 160 | 161 |
    162 | 169 |
    170 | 171 |
    172 | 175 | 176 |
    177 |

    Site built with pkgdown 1.2.0.

    178 |
    179 |
    180 |
    181 | 182 | 183 | 184 | 185 | 186 | 187 | -------------------------------------------------------------------------------- /docs/reference/setup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Allow casino to store player profiles in a local file — setup • casino 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 50 | 51 | 52 | 53 | 54 | 61 | 62 | 63 | 64 | 65 |
    66 |
    67 | 131 | 132 | 133 |
    134 | 135 |
    136 |
    137 | 142 | 143 |
    144 | 145 |

    Allow casino to store player profiles in a local file

    146 | 147 |
    148 | 149 |
    setup(file = file.path(getwd(), ".casino"))
    150 | 151 |

    Arguments

    152 | 153 | 154 | 155 | 156 | 157 | 158 |
    file

    full path to file

    159 | 160 | 161 |
    162 | 169 |
    170 | 171 |
    172 | 175 | 176 |
    177 |

    Site built with pkgdown 1.2.0.

    178 |
    179 |
    180 |
    181 | 182 | 183 | 184 | 185 | 186 | 187 | -------------------------------------------------------------------------------- /docs/reference/play_sound.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Play a sound (if possible) — play_sound • casino 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 50 | 51 | 52 | 53 | 54 | 61 | 62 | 63 | 64 | 65 |
    66 |
    67 | 131 | 132 | 133 |
    134 | 135 |
    136 |
    137 | 142 | 143 |
    144 | 145 |

    Play a sound (if possible)

    146 | 147 |
    148 | 149 |
    play_sound(sound = "fanfare")
    150 | 151 |

    Arguments

    152 | 153 | 154 | 155 | 156 | 157 | 158 |
    sound

    character string or number specifying the sound (see beep)

    159 | 160 |

    Note

    161 | 162 |

    requires the `beepr` package

    163 | 164 | 165 |
    166 | 175 |
    176 | 177 |
    178 | 181 | 182 |
    183 |

    Site built with pkgdown 1.2.0.

    184 |
    185 |
    186 |
    187 | 188 | 189 | 190 | 191 | 192 | 193 | -------------------------------------------------------------------------------- /docs/news/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Changelog • casino 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 48 | 49 | 50 | 51 | 52 | 59 | 60 | 61 | 62 | 63 |
    64 |
    65 | 129 | 130 | 131 |
    132 | 133 |
    134 |
    135 | 139 | 140 |
    141 |

    142 | casino 0.1.0

    143 |
    144 |

    145 | New games

    146 |
      147 |
    • Blackjack
    • 148 |
    • Slot machine
    • 149 |
    • Poker (5-card) 150 |
        151 |
      • Stud
      • 152 |
      • Draw
      • 153 |
      154 |
    • 155 |
    156 |
    157 |
    158 |

    159 | New features

    160 |
      161 |
    • New Blackjack, Poker, and Slots R6 classes for playing games.
    • 162 |
    • New Player R6 class is used for storing player information and history.
    • 163 |
    • New Deck R6 class is used for playing card games.
    • 164 |
    • Interactively play() casino games.
    • 165 |
    • Run setup() to specify where player information is stored locally.
    • 166 |
    167 |
    168 |
    169 |
    170 | 171 | 179 | 180 |
    181 | 182 |
    183 | 186 | 187 |
    188 |

    Site built with pkgdown 1.2.0.

    189 |
    190 |
    191 |
    192 | 193 | 194 | 195 | 196 | 197 | 198 | -------------------------------------------------------------------------------- /R/Poker.R: -------------------------------------------------------------------------------- 1 | #' Poker R6 Class 2 | #' @importFrom magrittr "%>%" 3 | #' @examples 4 | #' set.seed(101315) 5 | #' setup() 6 | #' 7 | #' # draw poker 8 | #' x <- Poker$new(who = "Player 1", type = "draw", bet = 10) 9 | #' x$play() 10 | #' x$hold(1, 2, 5) 11 | #' x$draw() 12 | #' 13 | #' # stud poker (bet 20) 14 | #' x <- Poker$new(who = "Player 1", type = "stud", bet = 20) 15 | #' x$play() 16 | #' 17 | #' # clean-up 18 | #' delete() 19 | #' @export 20 | Poker <- R6::R6Class("Poker", 21 | public = list( 22 | 23 | decks = NULL, 24 | type = NULL, 25 | bet = NULL, 26 | deck = NULL, 27 | who = NULL, 28 | 29 | hand = NULL, 30 | keep = NULL, 31 | turn = NULL, 32 | 33 | verbose = NULL, 34 | sound = NULL, 35 | 36 | initialize = function(decks = 1, type = c("draw", "stud"), who = NA, bet = 10, verbose = TRUE, sound = TRUE) { 37 | self$decks <- decks 38 | self$deck <- Deck$new(decks) 39 | self$type <- type[1] 40 | self$who <- Player$new(who) 41 | self$bet <- bet 42 | self$turn <- 0 43 | self$verbose <- verbose 44 | self$sound <- sound 45 | }, 46 | print = function(...) { 47 | if (self$turn == 0) { 48 | cat("Game: Poker (w/ ", self$decks, " decks): \n") 49 | cat("Player: ", self$who$name, "\n", sep = "") 50 | cat("Bank: ", self$who$balance, "\n", sep = "") 51 | cat(" Start a new game with `play().", "\n", sep = "") 52 | } else if (self$turn == 1) { 53 | cat(" Hand: ", self$print_hand(), "\n", sep = "") 54 | cat("Choose cards to `hold()`` and then `draw()`.", "\n", sep = "") 55 | } else if (self$turn == 2) { 56 | score <- tail(self$who$history, 1) 57 | cat(" Hand: ", paste(self$hand$value, self$hand$suit, collapse = ", "), "\n", sep = "") 58 | cat(" Result: ", score$outcome, "\n", sep = "") 59 | #cat(" You ", ifelse(score$net >= 0, "won", "lost"), " ", score$net, "!\n", sep = "") 60 | self$print_outcome() 61 | cat(" Now you have ", self$who$balance, " in your account.\n", sep = "") 62 | cat("Do you want to `play()` again?", "\n", sep = "") 63 | } 64 | invisible(self) 65 | }, 66 | 67 | # print helpers (for adding color to terminal output) 68 | print_outcome = function() { 69 | score <- tail(self$who$history, 1) 70 | color_f <- switch(1 + (score$net >= 0), crayon::red, crayon::green) 71 | cat(color_f(" You ", ifelse(score$net >= 0, "won", "lost"), " ", score$net, "!\n", sep = "")) 72 | }, 73 | print_hand = function() { 74 | paste( 75 | purrr::map_chr( 76 | 1:nrow(self$hand), 77 | function(i) { 78 | card <- paste(self$hand$value[i], self$hand$suit[i]) 79 | if (self$keep[i]) 80 | card <- crayon::underline(crayon::bold(card)) 81 | card 82 | } 83 | ), 84 | collapse = ", " 85 | ) 86 | }, 87 | # -- prep 88 | deal = function(n) { 89 | self$hand <- dplyr::bind_rows(self$hand, self$deck$draw(n)) 90 | self$turn <- self$turn + 1 91 | }, 92 | # -- gameplay 93 | play = function(bet = self$bet) { 94 | if (self$turn != 0) 95 | stop("You already started a game!") 96 | #self$bet <- bet 97 | self$bet <- self$who$bet(bet) 98 | self$hand <- NULL 99 | if (self$deck$cards_left() < 10) 100 | self$deck$shuffle() 101 | self$deal(5) 102 | self$keep <- rep(FALSE, 5) 103 | if (self$type == "draw") { 104 | self$turn <- 1 105 | if (self$verbose) 106 | print(self) 107 | } else if (self$type == "stud") { 108 | self$turn <- 2 109 | self$end_game() 110 | } 111 | invisible(self) 112 | }, 113 | 114 | # -- select cards to HOLD 115 | hold = function(...) { 116 | id <- c(...) 117 | self$keep[id] <- TRUE 118 | if (self$verbose) 119 | print(self) 120 | invisible(self) 121 | }, 122 | 123 | # -- draw more cards (pending ones with HOLD status) 124 | draw = function() { 125 | if (self$turn == 1) { 126 | n <- sum(!self$keep) 127 | self$hand <- self$hand[self$keep, ] 128 | self$deal(n) 129 | self$end_game() 130 | } else { 131 | message("The game is over. Start a new game with `play()`.") 132 | } 133 | invisible(self) 134 | }, 135 | 136 | # -- end a poker game; determine outcome; record results 137 | end_game = function() { 138 | score <- self$score() 139 | self$who$record(game = "Poker", outcome = score$outcome, bet = score$bet, win = score$win, net = score$net) 140 | if (self$sound && score$win > 0) 141 | play_sound() 142 | if (self$verbose) 143 | print(self) 144 | self$turn <- 0 145 | }, 146 | 147 | # -- score a poker hand 148 | score = function() { 149 | self$hand %>% 150 | dplyr::mutate( 151 | old_value = value, 152 | value = dplyr::case_when( 153 | value == "J" ~ 11, 154 | value == "Q" ~ 12, 155 | value == "K" ~ 13, 156 | value == "A" & all(2:5 %in% value) ~ 1, # make A==1 if hand includes 2,3,4,5 157 | value == "A" ~ 14, 158 | TRUE ~ suppressWarnings(as.numeric(value)) 159 | ) 160 | ) %>% 161 | dplyr::summarize( 162 | is_straight = all(diff(sort(value)) == 1), 163 | is_flush = length(unique(suit)) == 1, 164 | uniques = length(table(value)), 165 | n_pairs = sum(table(value) == 2), 166 | n_kind = max(table(value)), 167 | mode = tail(as.numeric(names(sort(table(value)))), 1), 168 | outcome = 169 | dplyr::case_when( 170 | all(value %in% 10:14) & is_flush ~ "royal flush", 171 | is_straight & is_flush ~ "straight flush", 172 | n_kind == 4 ~ "4-of-a-kind", 173 | n_kind == 3 & n_pairs == 2 ~ "full house", 174 | is_flush ~ "flush", 175 | is_straight ~ "straight", 176 | max(table(value)) == 3 ~ "3-of-a-kind", 177 | n_pairs == 2 & n_kind == 2 ~ "two pair", 178 | n_pairs == 1 & n_kind == 2 & mode > 10 ~ "one pair (jacks or better)", 179 | n_pairs == 1 & n_kind == 2 & mode <= 10 ~ "one pair", 180 | TRUE ~ paste(old_value[which.max(value)], "high") 181 | ) 182 | ) %>% 183 | dplyr::left_join( 184 | private$payout, 185 | by = "outcome" 186 | ) %>% 187 | dplyr::mutate( 188 | multiplier = ifelse(is.na(multiplier), 0, multiplier), 189 | bet = self$bet, 190 | win = bet * multiplier, 191 | net = win - bet 192 | ) %>% 193 | dplyr::select(outcome, bet, win, net) 194 | }, 195 | 196 | # -- see payout table 197 | get_payout = function(bet = self$bet) { 198 | dplyr::mutate( 199 | private$payout, 200 | win = bet * multiplier 201 | ) 202 | } 203 | ), 204 | 205 | private = list( 206 | 207 | # -- payout table 208 | payout = dplyr::tribble( 209 | ~outcome, ~multiplier, 210 | "royal flush", 800, 211 | "straight flush", 200, 212 | "4-of-a-kind", 25, 213 | "full house", 10, 214 | "flush", 7, 215 | "straight", 5, 216 | "3-of-a-kind", 3, 217 | "two pair", 2, 218 | "one pair (jacks or better)", 1 219 | ) 220 | 221 | ) 222 | 223 | ) -------------------------------------------------------------------------------- /R/Player.R: -------------------------------------------------------------------------------- 1 | #' Player R6 Class 2 | #' @importFrom magrittr "%>%" 3 | #' @import ggplot2 4 | #' @examples 5 | #' setup("my_profile") 6 | #' Player$new("Player 1") 7 | #' Player$new("Player 2") 8 | #' delete() 9 | #' @export 10 | Player <- R6::R6Class("Player", 11 | 12 | public = list( 13 | 14 | # -- player name 15 | name = NULL, 16 | 17 | # -- create/load player profile (via local '.casino' file) 18 | initialize = function(name = NA) { 19 | if (is.na(name)) 20 | stop("You must choose a name for your player!") 21 | self$name <- name 22 | private$recover() # check for (and load) existing player history, or create a new profile 23 | }, 24 | 25 | # -- print method (player info) 26 | print = function(...) { 27 | cat("Player: \n") 28 | cat(" Name: ", self$name, "\n", sep = "") 29 | cat(" Balance: ", private$.balance, "\n", sep = "") 30 | cat(" Level: ", private$.level, "\n", sep = "") 31 | cat(" Played: ", nrow(private$.history), "\n", sep = "") 32 | cat(" Debt: ", self$debt(), "\n", sep = "") 33 | invisible(self) 34 | }, 35 | 36 | # -- list existing player profiles 37 | players = function() { 38 | p <- private$load() 39 | tibble::tibble( 40 | name = purrr::map_chr(p, "name"), 41 | balance = purrr::map_chr(p, "balance") 42 | ) 43 | }, 44 | 45 | # -- reset player profile 46 | reset = function(keep_history = FALSE) { 47 | private$.balance <- 0 48 | if (!keep_history) { 49 | message("Reseting profile for ", self$name, "...\n", sep = "") 50 | private$.history <- private$.history[-(1:nrow(private$.history)), ] 51 | private$.level <- 1 52 | } 53 | private$add_funds(100) 54 | private$update() 55 | invisible(self) 56 | }, 57 | 58 | # -- place a bet 59 | bet = function(amount) { 60 | # loan funds if balance is currently at 0 61 | if (private$.balance == 0) 62 | private$add_funds(100) 63 | if (amount > private$.balance) { 64 | message(paste0("You cannot bet ", amount, "; you only have ", private$.balance, "!")) 65 | amount <- private$.balance 66 | } 67 | if (amount > 0) { 68 | private$.balance <- private$.balance - amount 69 | message(paste0("You bet ", amount, "; you have ", private$.balance, " left.")) 70 | private$update() 71 | } 72 | invisible(amount) 73 | }, 74 | 75 | # -- record the outcome of a single game played; update 'amount' in account 76 | record = function(game, outcome, bet, win, net) { 77 | new_game <- tibble::tibble(date = Sys.time(), game = game, outcome = outcome, bet = bet, win = win, net = net) 78 | private$.history <- dplyr::bind_rows(private$.history, new_game) 79 | private$.balance <- private$.balance + win 80 | private$set_level() 81 | private$update() 82 | }, 83 | 84 | # -- total bank debt 85 | debt = function() { 86 | sum(private$.history$win[private$.history$game == "Bank"]) 87 | }, 88 | 89 | # -- summarize player gameplay history 90 | summary = function(...) { 91 | groups <- rlang::quos(...) 92 | private$.history %>% 93 | dplyr::filter(game != "Bank") %>% 94 | dplyr::group_by(!!!groups) %>% 95 | dplyr::summarize( 96 | games = dplyr::n(), 97 | bet = sum(bet), 98 | win = sum(win), 99 | net = sum(net) 100 | ) 101 | }, 102 | 103 | # -- plot player history 104 | plot = function() { 105 | private$.history %>% 106 | dplyr::mutate(balance = cumsum(net)) %>% 107 | ggplot(aes(x = date, y = balance)) + 108 | geom_step() + 109 | geom_point(aes(color = game)) + 110 | geom_hline(yintercept = 0, linetype = "dashed", color = "red") + 111 | labs(x = "Date", y = "Balance", color = NULL) + 112 | theme_bw() 113 | } 114 | ), 115 | 116 | active = list( 117 | balance = function(value) { 118 | if (missing(value)) { 119 | private$.balance 120 | } else { 121 | cat(crayon::red("Oh, you want more money? LOL Nice try! :-)")) 122 | stop("Oh, you want more money? LOL Nice try! :-)", call. = FALSE) 123 | } 124 | }, 125 | level = function(value) { 126 | if (missing(value)) { 127 | private$.level 128 | } else { 129 | cat(crayon::red("If you want more skill levels, you'll need to actually play!\n")) 130 | #stop("Oh, you want more skills? LOL Nice try! :-)", call. = FALSE) 131 | } 132 | }, 133 | history = function(value) { 134 | if (missing(value)) { 135 | dplyr::mutate(private$.history, balance = cumsum(net)) 136 | } else { 137 | cat(crayon::red("Nice try Marty McFly, but you cannot change the past!\n")) 138 | #stop("Are you Marty McFly?! You cannot change the past.", call. = FALSE) 139 | } 140 | } 141 | ), 142 | 143 | private = list( 144 | 145 | # everyone starts with a Level 1 w/ a balance of 100 146 | .balance = 0, 147 | .level = 1, 148 | .history = tibble::tibble(date = Sys.time()[-1], game = character(), outcome = character(), bet = numeric(), win = numeric(), net = numeric()), 149 | 150 | # level progression 151 | levels = tibble::tibble(level = 0:99, threshold = (2 ^ level) - 1), 152 | set_level = function() { 153 | gains <- sum(private$.history$win[private$.history$game != "Bank"], na.rm = TRUE) 154 | private$.level <- tail(dplyr::filter(private$levels, threshold <= gains)$level, 1) 155 | }, 156 | 157 | # check balance; reload if empty 158 | check_balance = function() { 159 | if (private$.balance == 0) { # if player has 0 balance 160 | message("You have no money!") 161 | private$add_funds(100) 162 | } 163 | }, 164 | 165 | # add funds to a player's balance 166 | add_funds = function(value) { 167 | self$record(game = "Bank", outcome = "Loan", bet = 0, win = value, net = value) 168 | }, 169 | 170 | # load an existing '.casino' file with all player histories 171 | load = function() { 172 | file <- Sys.getenv("CASINO_FILE") 173 | if (!file.exists(file)) 174 | stop("No '.casino' file was found. Run `setup()` to create one.") 175 | readRDS(file) 176 | }, 177 | 178 | # save a list of players in '.casino' 179 | save = function(players) { 180 | saveRDS(players, Sys.getenv("CASINO_FILE")) 181 | }, 182 | 183 | # delete a player profile 184 | delete = function() { 185 | p <- private$load() 186 | if (!is.null(p)) { 187 | id <- which(purrr::map_chr(p, "name") == self$name) 188 | if (length(id) == 1) 189 | private$save(p[-id]) 190 | } 191 | }, 192 | 193 | # add a player profile 194 | add = function() { 195 | p <- private$load() 196 | p <- c(p, self) 197 | private$save(p) 198 | }, 199 | 200 | # update existing information for current player in '.casino' file 201 | update = function() { 202 | private$delete() 203 | private$add() 204 | }, 205 | 206 | # load past info for the player 207 | recover = function() { 208 | p <- private$load() 209 | if (!is.null(p)) { 210 | id <- which(purrr::map_chr(p, "name") == self$name) 211 | if (length(id) == 1) { 212 | message("Loading player profile...\n") 213 | private$.balance <- p[[id]]$balance 214 | private$.level <- p[[id]]$level 215 | private$.history <- p[[id]]$history 216 | } 217 | } 218 | private$check_balance() # if no player was found, this will create a new one 219 | } 220 | 221 | ) 222 | ) -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # casino 5 | 6 | > Welcome to the casino, we’ve got fun and games 7 | > 8 | > We got everything you want and we know your name 9 | > 10 | > We are a place where you can find whatever you may need 11 | > 12 | > And if you got no money, don’t worry\! You can play for “free”\! 13 | 14 | 15 | 16 | [![CRAN 17 | status](https://www.r-pkg.org/badges/version-last-release/casino)](https://cran.r-project.org/package=casino) 18 | [![CRAN 19 | downloads](http://cranlogs.r-pkg.org/badges/casino)](https://cran.r-project.org/package=casino) 20 | 21 | 22 | ## Overview 23 | 24 | Play casino games in the R console\! 25 | 26 | Available games: 27 | 28 | - Poker (5-card draw/stud) 29 | - Blackjack 30 | - Slot machine 31 | 32 | ## Installation 33 | 34 | ``` r 35 | # Install the CRAN version 36 | install.packages("casino") 37 | 38 | # Install development version from GitHub 39 | devtools::install_github("anthonypileggi/casino") 40 | ``` 41 | 42 | ## Quick Start 43 | 44 | Are you getting impatient already? Then use `play()` to get started 45 | immediately. 46 | 47 | ``` r 48 | casino::play() 49 | ``` 50 | 51 | ## Setup (`.casino`) 52 | 53 | All players must agree to our policies on recording activity. If you do 54 | not agree, you cannot play. House rules\! 55 | 56 | ``` r 57 | library(casino) 58 | 59 | # create a local file for storing persisent player data 60 | setup() 61 | #> No records found. 62 | #> Storing player records at '/Users/anthony/Documents/casino/.casino' 63 | #> Updating value for environment variable 'CASINO_FILE'. 64 | ``` 65 | 66 | This allows us to store player information persistently between games 67 | and R sessions. 68 | 69 | ## Create a Player 70 | 71 | You can create a new player manually. 72 | 73 | ``` r 74 | 75 | # Create a new player 76 | Player$new(name = "Player 1") 77 | #> You have no money! 78 | #> Player: 79 | #> Name: Player 1 80 | #> Balance: 100 81 | #> Level: 0 82 | #> Played: 1 83 | #> Debt: 100 84 | 85 | # View all available player profiles 86 | players() 87 | #> # A tibble: 1 x 2 88 | #> name balance 89 | #> 90 | #> 1 Player 1 100.000000 91 | ``` 92 | 93 | Or just start playing, and one will automatically be created for you. 94 | 95 | ``` r 96 | # Start a new game (this will auto-create a player) 97 | Blackjack$new(who = "Player 2") 98 | #> You have no money! 99 | #> Blackjack (w/ 1 decks): 100 | #> Player: Player 2 101 | #> Bank: 100 102 | #> Start a new game with `play()`. 103 | 104 | # View all available player profiles (again) 105 | players() 106 | #> # A tibble: 2 x 2 107 | #> name balance 108 | #> 109 | #> 1 Player 1 100.000000 110 | #> 2 Player 2 100.000000 111 | ``` 112 | 113 | ## Play Casino Games 114 | 115 | Now it’s time to head off to the casino\! What do you want to play 116 | first?\! 117 | 118 | ### Poker (5-card stud) 119 | 120 | ``` r 121 | x <- Poker$new(who = "Player 1", type = "stud", bet = 10) 122 | #> Loading player profile... 123 | 124 | # play a game 125 | x$play() 126 | #> You bet 10; you have 90 left. 127 | #> Hand: 2 ♦, 3 ♦, A ♠, 3 ♥, K ♦ 128 | #> Result: one pair 129 | #> You lost -10! 130 | #> Now you have 90 in your account. 131 | #> Do you want to `play()` again? 132 | 133 | # specify a different bet for this game 134 | x$play(bet = 5) 135 | #> You bet 5; you have 85 left. 136 | #> Hand: 10 ♦, J ♣, J ♠, Q ♠, 9 ♣ 137 | #> Result: one pair (jacks or better) 138 | #> You won 0! 139 | #> Now you have 90 in your account. 140 | #> Do you want to `play()` again? 141 | ``` 142 | 143 | ### Poker (5-card draw) 144 | 145 | ``` r 146 | x <- Poker$new(who = "Player 1", type = "draw", bet = 20) 147 | #> Loading player profile... 148 | 149 | # play a game 150 | x$play() 151 | #> You bet 20; you have 70 left. 152 | #> Hand: 2 ♠, 3 ♥, 3 ♠, 6 ♦, 8 ♦ 153 | #> Choose cards to `hold()`` and then `draw()`. 154 | 155 | x$hold(1, 2, 5) # hold cards in positions {1, 2, 5} 156 | #> Hand: 2 ♠, 3 ♥, 3 ♠, 6 ♦, 8 ♦ 157 | #> Choose cards to `hold()`` and then `draw()`. 158 | 159 | x$draw() # draw new cards for positions {3, 4} 160 | #> Hand: 2 ♠, 3 ♥, 8 ♦, K ♦, 7 ♣ 161 | #> Result: K high 162 | #> You lost -20! 163 | #> Now you have 70 in your account. 164 | #> Do you want to `play()` again? 165 | ``` 166 | 167 | ### Blackjack 168 | 169 | ``` r 170 | x <- Blackjack$new(who = "Player 1", bet = 25) 171 | #> Loading player profile... 172 | 173 | x$play()$stand() 174 | #> You bet 25; you have 45 left. 175 | #> Player Hand: {7, A} = 18 176 | #> Dealer Hand: {?, A} = ? 177 | #> Will you `hit()` or `stand()`? 178 | #> Game over! push 179 | #> You won 0! 180 | #> Now you have 70 in your account. 181 | ``` 182 | 183 | ### Slot Machine 184 | 185 | ``` r 186 | x <- Slots$new(who = "Player 1", bet = 1) 187 | #> Loading player profile... 188 | 189 | x$play() 190 | #> You bet 1; you have 69 left. 191 | #> Reels: & & * 192 | #> You lost -1! 193 | #> Now you have 69 in your account. 194 | #> Do you want to `play()` again? 195 | 196 | # set the `spins` argument to play > 1 game at a time 197 | x$play(spins = 2) 198 | #> You bet 1; you have 68 left. 199 | #> Reels: * & ^ 200 | #> You lost -1! 201 | #> Now you have 68 in your account. 202 | #> You bet 1; you have 67 left. 203 | #> Reels: * ^ % 204 | #> You lost -1! 205 | #> Now you have 67 in your account. 206 | #> Do you want to `play()` again? 207 | ``` 208 | 209 | ## I think I have a gambling problem 210 | 211 | If you want to play a lot of games, you can write a script. 212 | Just make sure to silence the output (`verbose = FALSE`) and sounds 213 | (`sound = FALSE`). 214 | 215 | ``` r 216 | # poker (stud) 217 | x <- Poker$new(who = "Player 1", type = "stud", bet = 10, verbose = FALSE, sound = FALSE) 218 | #> Loading player profile... 219 | for (i in 1:50) 220 | suppressMessages(x$play()) 221 | 222 | # blackjack (blind) 223 | x <- Blackjack$new(who = "Player 1", bet = 5, verbose = FALSE, sound = FALSE) 224 | #> Loading player profile... 225 | for (i in 1:50) { 226 | suppressMessages(x$play()) 227 | if (x$active) 228 | x$stand() 229 | } 230 | 231 | # penny slots 232 | x <- Slots$new(who = "Player 1", bet = 1, verbose = FALSE, sound = FALSE) 233 | #> Loading player profile... 234 | suppressMessages(x$play(spins = 50)) 235 | #> Do you want to `play()` again? 236 | ``` 237 | 238 | ## Ok, now I lost everything… 239 | 240 | If you run out of money, the Bank will immediately loan you 100. 241 | 242 | > You: “So, what’s the interest rate on this loan?” 243 | > Bank: “Oh, don’t worry. It’s very reasonable…” 244 | 245 | ## Wait, how much did you say I owe? 246 | 247 | ``` r 248 | # player profile is stored in `$who` of a game object 249 | player <- x$who 250 | 251 | player$debt() 252 | #> [1] 300 253 | ``` 254 | 255 | ## It’s closing time… 256 | 257 | What a fun day at the casino\! Or, was it? 258 | 259 | ``` r 260 | # player profile is stored in `$who` of a game object 261 | player <- x$who 262 | 263 | # Overall 264 | player$summary() 265 | #> # A tibble: 1 x 4 266 | #> games bet win net 267 | #> 268 | #> 1 157 739 566 -173 269 | 270 | # By Game 271 | player$summary(game) 272 | #> # A tibble: 3 x 5 273 | #> game games bet win net 274 | #> 275 | #> 1 Blackjack 51 275 245 -30 276 | #> 2 Poker 53 411 204 -207 277 | #> 3 Slots 53 53 117 64 278 | ``` 279 | 280 | Let’s relive the excitement\! 281 | 282 | ``` r 283 | player$plot() 284 | ``` 285 | 286 | ![](man/figures/plot-history-1.png) 287 | 288 | Well, I guess we’ll you’ll be back tomorrow. See you then\! 289 | -------------------------------------------------------------------------------- /docs/reference/Player.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Player R6 Class — Player • casino 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 50 | 51 | 52 | 53 | 54 | 61 | 62 | 63 | 64 | 65 |
    66 |
    67 | 131 | 132 | 133 |
    134 | 135 |
    136 |
    137 | 142 | 143 |
    144 | 145 |

    Player R6 Class

    146 | 147 |
    148 | 149 |
    Player
    150 | 151 |

    Format

    152 | 153 |

    An object of class R6ClassGenerator of length 24.

    154 | 155 | 156 |

    Examples

    157 |
    setup("my_profile")
    #> No records found. 158 | #> Storing player records at 'my_profile'
    #> Updating value for environment variable 'CASINO_FILE'.
    Player$new("Player 1")
    #> You have no money!
    #> Player: 159 | #> Name: Player 1 160 | #> Balance: 100 161 | #> Level: 0 162 | #> Played: 1 163 | #> Debt: 100
    Player$new("Player 2")
    #> You have no money!
    #> Player: 164 | #> Name: Player 2 165 | #> Balance: 100 166 | #> Level: 0 167 | #> Played: 1 168 | #> Debt: 100
    169 |
    170 | 180 |
    181 | 182 |
    183 | 186 | 187 |
    188 |

    Site built with pkgdown 1.2.0.

    189 |
    190 |
    191 |
    192 | 193 | 194 | 195 | 196 | 197 | 198 | -------------------------------------------------------------------------------- /docs/reference/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Function reference • casino 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 48 | 49 | 50 | 51 | 52 | 59 | 60 | 61 | 62 | 63 |
    64 |
    65 | 129 | 130 | 131 |
    132 | 133 |
    134 |
    135 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 153 | 154 | 155 | 156 | 159 | 160 | 161 | 162 | 165 | 166 | 167 | 168 | 171 | 172 | 173 | 174 | 177 | 178 | 179 | 180 | 183 | 184 | 185 | 186 | 189 | 190 | 191 | 192 | 195 | 196 | 197 | 198 | 201 | 202 | 203 | 204 | 207 | 208 | 209 | 210 | 213 | 214 | 215 | 216 | 219 | 220 | 221 | 222 | 225 | 226 | 227 | 228 | 231 | 232 | 233 | 234 |
    150 |

    All functions

    151 |

    152 |
    157 |

    Blackjack

    158 |

    Blackjack R6 Class

    163 |

    Deck

    164 |

    Deck R6 Class

    169 |

    Player

    170 |

    Player R6 Class

    175 |

    Poker

    176 |

    Poker R6 Class

    181 |

    Slots

    182 |

    Slots R6 Class

    187 |

    delete()

    188 |

    Delete all player history and re-lock the casino

    193 |

    play()

    194 |

    Play in the casino

    199 |

    play_blackjack()

    200 |

    Play blackjack

    205 |

    play_poker()

    206 |

    Play poker

    211 |

    play_slots()

    212 |

    Play the slot machine

    217 |

    play_sound()

    218 |

    Play a sound (if possible)

    223 |

    players()

    224 |

    List all player profiles

    229 |

    setup()

    230 |

    Allow casino to store player profiles in a local file

    235 |
    236 | 237 | 243 |
    244 | 245 |
    246 | 249 | 250 |
    251 |

    Site built with pkgdown 1.2.0.

    252 |
    253 |
    254 |
    255 | 256 | 257 | 258 | 259 | 260 | 261 | -------------------------------------------------------------------------------- /docs/reference/Blackjack.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Blackjack R6 Class — Blackjack • casino 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 50 | 51 | 52 | 53 | 54 | 61 | 62 | 63 | 64 | 65 |
    66 |
    67 | 131 | 132 | 133 |
    134 | 135 |
    136 |
    137 | 142 | 143 |
    144 | 145 |

    Blackjack R6 Class

    146 | 147 |
    148 | 149 |
    Blackjack
    150 | 151 |

    Format

    152 | 153 |

    An object of class R6ClassGenerator of length 24.

    154 | 155 | 156 |

    Examples

    157 |
    set.seed(101315) 158 | setup()
    #> No records found. 159 | #> Storing player records at '/Users/anthony/Documents/casino/docs/reference/.casino'
    #> Updating value for environment variable 'CASINO_FILE'.
    160 | # sit at the blackjack table 161 | x <- Blackjack$new(who = "Player 1", bet = 10)
    #> You have no money!
    162 | # play a hand 163 | x$play()
    #> You bet 10; you have 90 left.
    #> Player Hand: {8, 2} = 10 164 | #> Dealer Hand: {?, 6} = ? 165 | #> Will you `hit()` or `stand()`?
    166 | x$hit()
    #> Player Hand: {8, 2, 8} = 18 167 | #> Dealer Hand: {?, 6} = ? 168 | #> Will you `hit()` or `stand()`?
    169 | x$stand()
    #> Game over! dealer wins 170 | #> You lost -10! 171 | #> Now you have 90 in your account.
    172 | # play a hand blind w/out drawing 173 | x$play()$stand()
    #> You bet 10; you have 80 left.
    #> Player Hand: {6, K} = 16 174 | #> Dealer Hand: {?, Q} = ? 175 | #> Will you `hit()` or `stand()`? 176 | #> Game over! dealer bust 177 | #> You won 10! 178 | #> Now you have 100 in your account.
    179 | # clean-up 180 | delete()
    181 |
    182 | 192 |
    193 | 194 |
    195 | 198 | 199 |
    200 |

    Site built with pkgdown 1.2.0.

    201 |
    202 |
    203 |
    204 | 205 | 206 | 207 | 208 | 209 | 210 | -------------------------------------------------------------------------------- /docs/reference/Slots.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Slots R6 Class — Slots • casino 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 50 | 51 | 52 | 53 | 54 | 61 | 62 | 63 | 64 | 65 |
    66 |
    67 | 131 | 132 | 133 |
    134 | 135 |
    136 |
    137 | 142 | 143 |
    144 | 145 |

    Slots R6 Class

    146 | 147 |
    148 | 149 |
    Slots
    150 | 151 |

    Format

    152 | 153 |

    An object of class R6ClassGenerator of length 24.

    154 | 155 | 156 |

    Examples

    157 |
    set.seed(101315) 158 | setup()
    #> No records found. 159 | #> Storing player records at '/Users/anthony/Documents/casino/docs/reference/.casino'
    #> Updating value for environment variable 'CASINO_FILE'.
    160 | # start the slot machine 161 | x <- Slots$new(who = "Player 1", bet = 10)
    #> You have no money!
    162 | # play 1 game 163 | x$play()
    #> You bet 10; you have 90 left.
    #> Reels: ^ $ # 164 | #> You lost -10! 165 | #> Now you have 90 in your account. 166 | #> Do you want to `play()` again? 167 | #>
    168 | # play >1 game at a time 169 | x$play(spins = 3)
    #> You bet 10; you have 80 left.
    #> Reels: ^ & & 170 | #> You lost -10! 171 | #> Now you have 80 in your account.
    #> You bet 10; you have 70 left.
    #> Reels: # & * 172 | #> You lost -10! 173 | #> Now you have 70 in your account.
    #> You bet 10; you have 60 left.
    #> Reels: # & * 174 | #> You lost -10! 175 | #> Now you have 60 in your account. 176 | #> Do you want to `play()` again? 177 | #>
    178 | # clean-up 179 | delete()
    180 |
    181 | 191 |
    192 | 193 |
    194 | 197 | 198 |
    199 |

    Site built with pkgdown 1.2.0.

    200 |
    201 |
    202 |
    203 | 204 | 205 | 206 | 207 | 208 | 209 | -------------------------------------------------------------------------------- /docs/articles/blackjack.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Blackjack • casino 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 26 | 27 | 28 |
    29 |
    92 | 93 | 94 | 95 |
    96 |
    97 | 107 | 108 | 109 | 110 |

    You can play Blackjack against the dealer.

    111 |
    112 |

    113 | Payouts

    114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 |
    OutcomeMultiplier
    Dealer Wins0x
    Player Wins2x
    130 |
    131 |
    132 |

    133 | Example

    134 |
    library(casino)
    135 | 
    136 | # Setup a new casino
    137 | setup(".wynn")
    138 | #> No records found.
    139 | #> Storing player records at '.wynn'
    140 | #> Updating value for environment variable 'CASINO_FILE'.
    141 | 
    142 | # Sit at the blackjack table with default bet of 25
    143 | x <- Blackjack$new(who = "Gritty", bet = 25)
    144 | #> You have no money!
    145 | 
    146 | # Play a hand
    147 | x$play()
    148 | #> You bet 25; you have 75 left.
    149 | #>  Player Hand: {8, 2} = 10
    150 | #>  Dealer Hand: {?, 6} = ?
    151 | #> Will you `hit()` or `stand()`?
    152 | 
    153 | x$hit()
    154 | #>  Player Hand: {8, 2, 8} = 18
    155 | #>  Dealer Hand: {?, 6} = ?
    156 | #> Will you `hit()` or `stand()`?
    157 | 
    158 | x$stand()
    159 | #> Game over! dealer wins
    160 | #>   You lost -25!
    161 | #>   Now you have 75 in your account.
    162 | 
    163 | # Play another
    164 | x$play()
    165 | #> You bet 25; you have 50 left.
    166 | #>  Player Hand: {6, K} = 16
    167 | #>  Dealer Hand: {?, Q} = ?
    168 | #> Will you `hit()` or `stand()`?
    169 | 
    170 | x$stand()
    171 | #> Game over! dealer bust
    172 | #>   You won 25!
    173 | #>   Now you have 100 in your account.
    174 | 
    175 | # Play one last hand, and bet it all!
    176 | x$play(bet = 100)
    177 | #> You bet 100; you have 0 left.
    178 | #>  Player Hand: {4, 6} = 10
    179 | #>  Dealer Hand: {?, 5} = ?
    180 | #> Will you `hit()` or `stand()`?
    181 | 
    182 | x$hit()
    183 | #>  Player Hand: {4, 6, Q} = 20
    184 | #>  Dealer Hand: {?, 5} = ?
    185 | #> Will you `hit()` or `stand()`?
    186 | 
    187 | x$stand()
    188 | #> Game over! dealer wins
    189 | #>   You lost -100!
    190 | #>   Now you have 0 in your account.
    191 |
    192 | 193 |
    194 |
    195 |
    196 | 197 | 207 | 208 |
    209 | 210 | 211 | 220 |
    221 | 222 | 223 | 224 | 225 | 226 | -------------------------------------------------------------------------------- /docs/reference/Poker.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Poker R6 Class — Poker • casino 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 50 | 51 | 52 | 53 | 54 | 61 | 62 | 63 | 64 | 65 |
    66 |
    67 | 131 | 132 | 133 |
    134 | 135 |
    136 |
    137 | 142 | 143 |
    144 | 145 |

    Poker R6 Class

    146 | 147 |
    148 | 149 |
    Poker
    150 | 151 |

    Format

    152 | 153 |

    An object of class R6ClassGenerator of length 24.

    154 | 155 | 156 |

    Examples

    157 |
    set.seed(101315) 158 | setup()
    #> No records found. 159 | #> Storing player records at '/Users/anthony/Documents/casino/docs/reference/.casino'
    #> Updating value for environment variable 'CASINO_FILE'.
    160 | # draw poker 161 | x <- Poker$new(who = "Player 1", type = "draw", bet = 10)
    #> You have no money!
    x$play()
    #> You bet 10; you have 90 left.
    #> Hand: 8 ♥, 3 ♥, 2 ♠, 6 ♦, 8 ♠ 162 | #> Choose cards to `hold()`` and then `draw()`.
    x$hold(1, 2, 5)
    #> Hand: 8 ♥, 3 ♥, 2 ♠, 6 ♦, 8 ♠ 163 | #> Choose cards to `hold()`` and then `draw()`.
    x$draw()
    #> Hand: 8 ♥, 3 ♥, 8 ♠, J ♣, 6 ♥ 164 | #> Result: one pair 165 | #> You lost -10! 166 | #> Now you have 90 in your account. 167 | #> Do you want to `play()` again?
    168 | # stud poker (bet 20) 169 | x <- Poker$new(who = "Player 1", type = "stud", bet = 20)
    #> Loading player profile...
    x$play()
    #> You bet 20; you have 70 left.
    #> Hand: 2 ♦, 3 ♦, A ♠, 3 ♥, K ♦ 170 | #> Result: one pair 171 | #> You lost -20! 172 | #> Now you have 70 in your account. 173 | #> Do you want to `play()` again?
    174 | # clean-up 175 | delete()
    176 |
    177 | 187 |
    188 | 189 |
    190 | 193 | 194 |
    195 |

    Site built with pkgdown 1.2.0.

    196 |
    197 |
    198 |
    199 | 200 | 201 | 202 | 203 | 204 | 205 | -------------------------------------------------------------------------------- /docs/reference/Deck.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Deck R6 Class — Deck • casino 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 50 | 51 | 52 | 53 | 54 | 61 | 62 | 63 | 64 | 65 |
    66 |
    67 | 131 | 132 | 133 |
    134 | 135 |
    136 |
    137 | 142 | 143 |
    144 | 145 |

    Deck R6 Class

    146 | 147 |
    148 | 149 |
    Deck
    150 | 151 |

    Format

    152 | 153 |

    An object of class R6ClassGenerator of length 24.

    154 | 155 | 156 |

    Examples

    157 |
    # create a new deck 158 | x <- Deck$new() 159 | x
    #> Deck: 160 | #> Decks: 1 161 | #> Cards: 52 162 | #> Cards dealt: 0 163 | #> Cards left: 52 164 | #> Next card: 2 ♦s
    165 | # draw a card 166 | x$draw(1)
    #> # A tibble: 1 x 2 167 | #> value suit 168 | #> <chr> <chr> 169 | #> 1 2 ♦
    x
    #> Deck: 170 | #> Decks: 1 171 | #> Cards: 52 172 | #> Cards dealt: 1 173 | #> Cards left: 51 174 | #> Next card: 3 ♦s
    175 | # draw 10 cards 176 | x$draw(10)
    #> # A tibble: 10 x 2 177 | #> value suit 178 | #> <chr> <chr> 179 | #> 1 3 ♦ 180 | #> 2 A ♠ 181 | #> 3 3 ♥ 182 | #> 4 K ♦ 183 | #> 5 10 ♦ 184 | #> 6 J ♣ 185 | #> 7 J ♠ 186 | #> 8 Q ♠ 187 | #> 9 9 ♣ 188 | #> 10 A ♣
    189 | # check how many cards are left 190 | x$cards_left()
    #> [1] 41
    191 | # reset the deck 192 | x$shuffle() 193 | x
    #> Deck: 194 | #> Decks: 1 195 | #> Cards: 52 196 | #> Cards dealt: 0 197 | #> Cards left: 52 198 | #> Next card: 2 ♠s
    199 | # create a deck composed of 5 decks 200 | x <- Deck$new(decks = 5) 201 | x
    #> Deck: 202 | #> Decks: 5 203 | #> Cards: 260 204 | #> Cards dealt: 0 205 | #> Cards left: 260 206 | #> Next card: 9 ♥s
    207 |
    208 | 218 |
    219 | 220 | 229 |
    230 | 231 | 232 | 233 | 234 | 235 | 236 | --------------------------------------------------------------------------------