Hi, I am trying to turn a piece of code into a shiny app. The original script runs fine but not when I try to turn it into an app. It is meant to simulate dice rolls in a board game, where the user can input the number of dice each side rolls. Therefore I need to use some user defined input to tell the server how many times to iterate certain loops. I have tried this all sorts of ways but always get an error when running the app when I click the action button I've created.
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput(inputId = "grey_p",
label = "Player grey dice",
choices = c(0,1,2,3,4,5,6),
selected = 0),
selectInput(inputId = "tan_p",
label = "Player tan dice",
choices = c(0,1,2,3,4,5,6),
selected = 0),
#and the demon?
selectInput(inputId = "grey_d",
label = "Demon grey dice",
choices = c(0,1,2,3,4,5,6),
selected = 0),
selectInput(inputId = "tan_d",
label = "Demon tan dice",
choices = c(0,1,2,3,4,5,6),
selected = 0),
#define health, strength defence and other relevant stats here
selectInput(inputId = "player_health",
label = "Player Health",
choices = c(1,2,3,4,5,6,7,8,9,10),
selected = 10),
selectInput(inputId = "demon_health",
label = "Demon Health",
choices = c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20),
selected = 10),
selectInput(inputId = "player_defence",
label = "Player Defence",
choices = c(0,1,2,3,4,5,6,7),
selected = 0),
selectInput(inputId = "demon_defence",
label = "Demon Defence",
choices = c(0,1,2,3,4,5,6,7),
selected = 0)
), #Close sidebarpanel, comma is for sidebarlayout further arguments
#Add player strength
####################################################################################################
#Mainpanel for output
mainPanel(
actionButton("run_button", "Run"),
textOutput("txt_output")
) #close mainpanel
) #Close sidebarylayout
) # close fluidpage
#define dice sides
grey <- c(0,1,1,2,2,3)
tan <- c(0,0,0,2,3,4)
red <- c(0,1,2,3,3,4)
black <- c(1,2,2,3,3,4)
gold <- c(0,0,0,0,6,6)
special <- list(2,2,3,3,4,"Death")
server <- function(input, output) {
observeEvent(input$run_button, {
#I am experimenting with these values, they are created so that they can be used in the server code below only,
#there may be a better way to do this.
d_health_serv <-
as.numeric(input$demon_health)
p_health_serv <-
as.numeric(input$player_health)
#These will be used to reset health values after each battle
demon_health_start <- as.numeric(input$demon_health)
player_health_start <- as.numeric(input$player_health)
big_i <- 1
demon_wins <- 0
player_wins <- 0
number_of_turns_taken <- list()
#list out the user input values for numbers of dice to roll here
grey_p_serv <- as.numeric(input$grey_p)
tan_p_serv <- as.numeric(input$tan_p)
grey_d_serv <- as.numeric(input$grey_d)
tan_d_serv <- as.numeric(input$tan_d)
#big_i represents each battle, increments by 1 after each battle and goes to 100 battles
while(big_i <= 100) {
#small_i is each roll within each battle
small_i <- 0
while(d_health_serv > 0 && p_health_serv > 0) {
small_i <- small_i + 1
#Get grey dice role for this roll, the for loop makes it roll the grey dice the number of times the user has specified
if (grey_p_serv > 0) {
grey_score_p_ <- list()
random_player_ <- list()
for (i in 1:grey_p_serv) {
random_player_[[i]] <- floor(runif(1, min=1, max=6))
grey_score_p_[[i]] <- grey[random_player_[[i]][1]]
} #end for loop
} #end if
#repeat for tan
if (tan_p_serv > 0) {
tan_score_p_ <- list()
random_player_ <- list()
for (i in 1:tan_p_serv) {
random_player_[[i]] <- floor(runif(1, min=1, max=6))
tan_score_p_[[i]] <- tan[random_player_[[i]][1]]
}
}
#sum the results of each dice colour
sum_grey <- Reduce("+", grey_score_p_)
sum_tan <- Reduce("+", tan_score_p_)
#Then sum all dice to get the final result for the player
#Need to add strength!!
final_score_p <- sum_grey + sum_tan
###########################################################################################################
#Now do the same for the demon and create final score d
grey_score_d_ <- list()
random_demon_ <- list()
if (grey_d_serv > 0) {
for (i in 1:grey_d_serv) {
random_demon_[[i]] <- floor(runif(1, min=1, max=6))
grey_score_d_[[i]] <- grey[random_demon_[[i]][1]]
}
}
tan_score_d_ <- list()
random_demon_ <- list()
if (tan_d_serv > 0) {
for (i in 1:tan_d_serv) {
random_demon_[[i]] <- floor(runif(1, min=1, max=6))
tan_score_d_[[i]] <- tan[random_demon_[[i]][1]]
}
}
sum_grey <- Reduce("+", grey_score_d_)
sum_tan <- Reduce("+", tan_score_d_)
final_score_d <- sum_grey + sum_tan
#then iterate the whole process out many times
damage = final_score_p - final_score_d
if(damage > 0) {
damage <- abs(damage) - as.numeric(input$demon_defence)
if(damage > 0) {
d_health_serv <- d_health_serv - damage
}
}
if(damage < 0) {
damage <- abs(damage) - as.numeric(input$player_defence)
if(damage > 0) {
p_health_serv <- p_health_serv - abs(damage)
}
}
if(p_health_serv <= 0) {
demon_wins <- demon_wins + 1
}
if(d_health_serv <= 0) {
player_wins <- player_wins + 1
}
} #end small while loop
number_of_turns_taken[big_i] <- small_i
big_i <- big_i + 1 #each time a winner is found, iterate the whole thing again to find who wins the next round, do this 100 times
#reset demon and player health to original values
d_health_serv <- demon_health_start
p_health_serv <- player_health_start
} #end big while loop
avg_number_rolls_to_win <- mean(unlist(number_of_turns_taken))
output$txt_output <- renderText(print(paste("The player has won ", player_wins, " battles,", "but the demon won ", demon_wins, " barttles.",
"On average it took ", avg_number_rolls_to_win, "rolls to win each battle.")))
}) # observeEvent close
} # server function close
The error I get from this is:
Warning: Error in if: argument is of length zero