::p_load(
pacman
tidyverse,
here,
rio )
PokéRogue Random Team Selector in R
Introduction
Welcome to the PokéRogue Random Team Selector project!
PokéRogue is a fan-made roguelike game where players can select a team of up to 6 Starter Pokémon at the beginning of any run. Players have a total budget of either 10 or 15 points, depending on the game mode, to spend on these initial Starters. The more powerful the Pokémon, the more points they cost. Additionally, three random Starter Pokémon receive Pokérus each day, a condition that allows for faster experience gain and leveling up. Shiny Pokémon variants improve the player’s luck in obtaining better items. You can play PokéRogue for free here.
In this project, we will use R to create functions that randomly generate Pokémon teams based on the criteria mentioned above. We’ll start by loading the necessary libraries and data, then proceed to define various helper functions and main team creation functions. Finally, we’ll demonstrate how to create different teams using these functions.
Loading Libraries
We start by loading the necessary libraries using pacman::p_load
. This ensures that all required packages are installed and loaded.
Loading Data
Next, we load the dataset containing the list of available Pokémon. The data is imported from an Excel file using the rio::import
function. This dataset includes information on whether the Pokémon has been caught, if it has a Shiny version, or if it has Pokérus.
<- import(here("posts", "pokerogue_team", "Pokerogue starters list.xlsx"))
data_raw
<- data_raw |>
data_catched filter(Catched == "Yes") |>
select(Starter, Gen, Dex, Cost, Shiny, Pokerus)
Let’s take a quick look at the imported data using glimpse
.
glimpse(data_catched)
Rows: 459
Columns: 6
$ Starter <chr> "Bulbasaur", "Charmander", "Squirtle", "Caterpie", "Weedle", "…
$ Gen <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
$ Dex <dbl> 1, 4, 7, 10, 13, 16, 19, 21, 23, 25, 27, 29, 32, 37, 39, 41, 4…
$ Cost <dbl> 3, 3, 3, 1, 1, 2, 1, 1, 2, 4, 2, 3, 3, 3, 4, 2, 2, 1, 2, 3, 4,…
$ Shiny <dbl> NA, NA, NA, NA, NA, NA, 1, 1, NA, NA, NA, NA, NA, NA, NA, NA, …
$ Pokerus <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
Creating Functions
We define several helper functions to handle different aspects of the team selection process.
Select Random Pokémon
The select_random_pokemon
function is designed to select a Pokémon from the available dataset based on specific criteria such as budget points, Pokérus status, cost, or exact cost.
<- function(df, points, pokerus = FALSE, expensive = FALSE, exact = FALSE) {
select_random_pokemon
# Selects an affordable Pokémon with Pokérus
if (pokerus == TRUE){
<- df |> filter(Cost <= points, Pokerus == "Yes")
data_filtered
}
# Selects an expensive Pókemon (all available points)
else if (expensive == TRUE) {
<- df |> filter(Cost == min(points, max(Cost)))
data_filtered
}
# Selects a Pokémon with an exact cost
else if (exact == TRUE) {
<- df |> filter(Cost == points)
data_filtered
}
else {
<- df |> filter(Cost <= points)
data_filtered
}
<- slice_sample(data_filtered)
pokemon_selected
pokemon_selected }
Count Shiny Pokémon
The count_shiny_pokemon
function counts the number of available shiny Pokémon in the dataset.
<- function(df) {
count_shiny_pokemon <- df |> filter(!is.na(Shiny))
data_filtered <- nrow(data_filtered)
n_shiny
n_shiny }
Update Available Pokémon
The update_available_pokemon
function updates the list of available Pokémon by removing the ones that have already been selected.
<- function(data_available, list_pokemon, already_chosen, current_pokemon) {
update_available_pokemon <- list_pokemon[[current_pokemon]]$Starter
new_pokemon_name <- c(already_chosen, new_pokemon_name)
already_chosen <- data_available |> filter(!Starter %in% already_chosen)
data_available
data_available }
Update Budget
The update_budget
function updates the remaining budget after selecting a Pokémon.
<- function(budget_points, list_pokemon, current_pokemon) {
update_budget <- sum(list_pokemon[[current_pokemon]]$Cost)
points_spent <- budget_points - points_spent
budget_points }
Select Shiny Pokémon
The select_shiny_pokemon
function selects a shiny Pokémon based on the budget. It can prioritize rarer shiny Pokémon if specified.
<- function(df, points, best_shiny = TRUE) {
select_shiny_pokemon <- df |> filter(Cost <= points, !is.na(Shiny))
data_filtered
if (best_shiny == TRUE) {
<- data_filtered |>
data_filtered mutate(random_number = rnorm(nrow(data_filtered))) |>
arrange(desc(Shiny), Cost, random_number) |>
select(-random_number)
<- data_filtered |> slice_head(n = 1)
pokemon_selected else {
} <- data_filtered |> slice_sample(n = 1)
pokemon_selected
} }
Distribute Points
The distribute_points
function distributes the available points among the team members.
<- function(points, n_pokemon = 6) {
distribute_points <- rep(1, n_pokemon)
distribution <- points - n_pokemon
points_left
if (points_left > 0) {
for (i in 1:points_left) {
<- sample(1:n_pokemon, 1)
pokemon_slot <- distribution[pokemon_slot] + 1
distribution[pokemon_slot]
}
}
<- sort(distribution, decreasing = TRUE)
distribution
distribution }
Creating Teams
With the helper functions defined, we now create the main team selection functions.
Create Team
The create_team
function creates a team based on the specified budget and criteria such as Pokérus and shiny Pokémon.
<- function(points, pokerus = FALSE, shiny = 0, best_shiny = TRUE, arrange = FALSE) {
create_team # Set the starting budget
<- points
budget_points
# Initialize empty lists and parameters
<- list()
list_pokemon <- 1
current_pokemon <- c()
already_chosen <- data_catched
data_available
# First Pókemon, that may or may not be forced to be a Pokérus Pokémon
<- select_random_pokemon(data_available, budget_points, pokerus = pokerus)
list_pokemon[[current_pokemon]]
# Update already chosen pokemon
<- update_available_pokemon(data_available, list_pokemon, already_chosen, current_pokemon)
data_available
# Update disposible budget
<- update_budget(budget_points, list_pokemon, current_pokemon)
budget_points
# Update current pókemon slot
<- current_pokemon + 1
current_pokemon
# Find shiny Pókemon
if (shiny > 0) {
# Force a maximum of 6 Pókemon in the team, and calculate the number of shiny Pókemon to add
<- count_shiny_pokemon(data_available)
total_shiny_available <- min(shiny, total_shiny_available)
number_of_shinies <- min(6, number_of_shinies + current_pokemon - 1)
end_loop
# Fill team with shiny Pókemon
for (i in current_pokemon:end_loop) {
<- select_shiny_pokemon(data_available, budget_points, best_shiny)
list_pokemon[[i]]
# Update already chosen pokemon
<- update_available_pokemon(data_available, list_pokemon, already_chosen, current_pokemon)
data_available
# Update disposible budget
<- update_budget(budget_points, list_pokemon, current_pokemon)
budget_points
<- current_pokemon + 1
current_pokemon
}
# Update current pókemon slot
<- list_rbind(list_pokemon)
team_after_shiny <- nrow(team_after_shiny) + 1
current_pokemon
}
# Check if there are still places to fill in the team (until the 5th place)
if (current_pokemon <= 5 & budget_points > 0) {
# Loop for rest of max 6 Pókemon
for (i in current_pokemon:5) {
<- select_random_pokemon(data_available, budget_points)
list_pokemon[[i]]
# Update already chosen pokemon
<- update_available_pokemon(data_available, list_pokemon, already_chosen, current_pokemon)
data_available
# Update disposible budget
<- update_budget(budget_points, list_pokemon, current_pokemon)
budget_points <- current_pokemon + 1
current_pokemon
}
}
# Ensure the last Pókemon spend all available points
if (current_pokemon == 6 & budget_points > 0) {
<- select_random_pokemon(data_available, budget_points, expensive = TRUE)
list_pokemon[[current_pokemon]]
}
# Bind all Pókemon, in order of Generation and Dex number
<- list_rbind(list_pokemon)
final_team
if (arrange == TRUE) {
|>
final_team arrange(Gen, Dex)
else {
}
final_team
} }
Create Expensive Team
The create_expensive_team
function creates a team that maximizes the use of the available budget by selecting the most expensive Pokémon possible.
<- function(points, arrange = FALSE) {
create_expensive_team # Set the starting budget
<- points
budget_points
# Initialize empty lists and parameters
<- list()
list_pokemon <- 1
current_pokemon <- c()
already_chosen <- data_catched
data_available
# Loop for rest of max 6 Pókemon
for (i in current_pokemon:6) {
<- select_random_pokemon(data_available, budget_points, expensive = TRUE)
list_pokemon[[i]]
# Update already chosen pokemon
<- update_available_pokemon(data_available, list_pokemon, already_chosen, current_pokemon)
data_available
# Update disposible budget
<- update_budget(budget_points, list_pokemon, current_pokemon)
budget_points
<- current_pokemon + 1
current_pokemon
}
# Bind all Pókemon, in order of Generation and Dex number
<- list_rbind(list_pokemon)
final_team
if (arrange == TRUE) {
|>
final_team arrange(Gen, Dex)
else {
}
final_team
} }
Create Random 6 Team
The create_random_6_team
function creates a team with a random distribution of points among the six Pokémon, optionally including a Pokérus Pokémon.
<- function(points, arrange = TRUE, pokerus = FALSE) {
create_random_6_team
# Set the starting budget
<- points
budget_points
# Initialize empty lists and parameters
<- list()
list_pokemon <- 1
current_pokemon <- c()
already_chosen <- data_catched
data_available
# Create a random distribution of points
<- distribute_points(points, n_pokemon = 6)
distribution
# Coerce a Pokérus Pókemon
if (pokerus == TRUE){
<- data_available |>
pokerus_pokemon filter(Pokerus == "Yes") |>
slice_sample(n = 1)
<- pokerus_pokemon
list_pokemon[[current_pokemon]]
# Update available
<- update_available_pokemon(data_available, list_pokemon, already_chosen, current_pokemon)
data_available <- update_budget(budget_points, list_pokemon, current_pokemon)
budget_points <- current_pokemon + 1
current_pokemon
# Generate another distribution of points among the remaining 5 Pókemon
<- c("NA", distribute_points(budget_points, n_pokemon = 5))
distribution
}
for (i in current_pokemon:6) {
# Find random pókemon according to the point distribution
<- select_random_pokemon(data_available, distribution[i], exact = TRUE)
list_pokemon[[i]]
# Update
<- update_available_pokemon(data_available, list_pokemon, already_chosen, current_pokemon)
data_available <- update_budget(budget_points, list_pokemon, current_pokemon)
budget_points <- current_pokemon + 1
current_pokemon
}
# Bind all Pókemon, in order of Generation and Dex number
<- list_rbind(list_pokemon)
final_team
if (arrange == TRUE) {
|> arrange(Gen, Dex)
final_team else {
}
final_team
} }
Random Team Examples
Now that we have our functions defined, let’s see them in action. Here are some examples of creating random Pokémon teams using different criteria.
Example 1: Basic Team with a Budget of 10 Points
This example creates a team with a budget of 10 points, without considering Pokérus or shiny variants, and arranges the team by Generation and Dex number.
create_team(10, pokerus = FALSE, arrange = TRUE)
Starter Gen Dex Cost Shiny Pokerus
1 Hoothoot 2 163 1 NA <NA>
2 Hoppip 2 187 1 NA <NA>
3 Yveltal 6 717 8 NA <NA>
Example 2: Enhanced Team with a Budget of 15 Points
In this example, we create a team with a budget of 15 points, including Pokémon with Pokérus and up to 4 shiny Pokémon, prioritizing the best shiny variants. The team is also arranged by Generation and Dex number.
create_team(15, pokerus = TRUE, shiny = 4, best_shiny = TRUE, arrange = TRUE)
Starter Gen Dex Cost Shiny Pokerus
1 Drowzee 1 96 3 NA Yes
2 Unown 2 201 1 1 <NA>
3 Bidoof 4 399 1 2 <NA>
4 Burmy 4 412 1 1 <NA>
5 Uxie 4 480 7 NA <NA>
6 Petilil 5 548 2 2 <NA>
Example 3: Most Expensive Team with a Budget of 15 Points
Here, we create a team that maximizes the use of the budget by selecting the most expensive Pokémon available, with a total budget of 15 points.
create_expensive_team(15)
Starter Gen Dex Cost Shiny Pokerus
1 Giratina 4 487 8 NA <NA>
2 Iron Crown 9 1023 7 NA <NA>
Example 4: Random Team with a Budget of 10 Points
This example creates a random team with a budget of 10 points, including at least one Pokémon with Pokérus, and distributes the points randomly among the six Pokémon.
create_random_6_team(10, pokerus = TRUE)
Starter Gen Dex Cost Shiny Pokerus
1 Weedle 1 13 1 NA <NA>
2 Spearow 1 21 1 1 <NA>
3 Zubat 1 41 2 NA <NA>
4 Drowzee 1 96 3 NA Yes
5 Poochyena 3 261 2 NA <NA>
6 Bidoof 4 399 1 2 <NA>
These examples demonstrate the flexibility and power of our team creation functions, allowing you to generate a variety of Pokémon teams tailored to your preferences and game mode. Whether you want a balanced team, a team with specific conditions, or the most powerful team possible within your budget, these functions can help you achieve that.
Conclusion
With these functions, you can generate a variety of Pokémon teams for your PokéRogue adventures. Whether you want a balanced team, a team with the most expensive Pokémon, or a team with specific conditions like Pokérus or shiny variants, these functions have you covered.
Happy PokéRoguing!