(Acest articol a fost publicat pentru prima dată pe R – TomazTsqlși cu amabilitate a contribuit la R-bloggeri). (Puteți raporta problema legată de conținutul acestei pagini aici)
Doriți să vă distribuiți conținutul pe R-bloggeri? dați clic aici dacă aveți un blog, sau aici dacă nu aveți.
De data aceasta, vom crea un simulator de plante Desk. Și pentru asta avem nevoie de un set de funcții diferite 


Da, vom crește o plantă R într-un joc de simulare cu o mulțime de twerks și pietre prețioase ascunse și artă ASCII 
Și cum funcționează cu adevărat acest set de funcții?
Stocarea progresului zilnic într-un RDS. Înainte de a rula un set de funcții, veți pregăti o locație pentru a stoca fișierul RDS (variabilele de mediu și jocul)
Arta ASCII a fost realizată de GPT pentru toate etapele și este atât de drăguță 

plant_art <- list( # Stage 0: Seed seed = c( " ", " ", " ", " ", " . ", " (.) ", " ----- ", " | | ", " |~~~~~| ", " |_____| " ), # Stage 1: Sprout sprout = c( " ", " ", " ", " , ", " (') ", " | ", " ----- ", " | | ", " |~~~~~| ", " |_____| " ), # Stage 2: Seedling seedling = c( " ", " ", " \|/ ", " \|||/ ", " ||| ", " ||| ", " ----- ", " | | ", " |~~~~~| ", " |_____| " ), # Stage 3: Young plant young = c( " ", " \~~/ ", " \\|// ", " \|/ ", " ||| ", " ||| ", " ----- ", " | | ", " |~~~~~| ", " |_____| " ),......
Apoi veți avea la dispoziție funcții de ajutor și principale. Codul complet este disponibil în depozitul meu Github.
Pentru a rula jocul, va trebui să plantezi o nouă plantă, să o udați, să verificați starea plantei și multe altele.


Iată un extras din cod:
hline <- function(char = "═", n = 40) strrep(char, n)
# get current status of a plant / game play
get_plant <- function(file = .plant_file) {
if (file.exists(file)) { readRDS(file) }
}
# Save plant in RDS and all game play!
save_plant <- function(plant, file = .plant_file) {
saveRDS(plant, file)
}
# get growth info
get_stage <- function(points) {
stage_idx <- max(which(growth_stages$min_points <= points))
growth_stages(stage_idx, )
}
# get appropriate ASCII art plant
get_plant_art <- function(plant) {
if (plant$health <= 0) {
return(plant_art$dead)
}
if (plant$health < 30) {
return(plant_art$wilted)
}
stage <- get_stage(plant$points)
plant_art((stage$art_name))
}
days_since <- function(date) {
as.integer(Sys.Date() - as.Date(date))
}
# Messages for encouragement - Done with help of chatGPT
get_encouragement <- function() {
messages <- c(
"Your plant appreciates you!",
"Keep up the great work!",
"You're a natural plant parent!",
"Your R sessions make the plant happy!",
"Photosynthesis in progress... ",
"Growing strong, just like your R skills!",
"The plant sends positive vibes!",
"Another day, another leaf!",
"Your dedication is blooming!",
"Keep coding, keep growing!"
)
sample(messages, 1)
}
# General health
get_health_message <- function(health) {
if (health >= 90) {
return("Thriving! Your plant is radiantly healthy!")
} else if (health >= 70) {
return("Healthy! Looking good!")
} else if (health >= 50) {
return("Okay. Could use some attention.")
} else if (health >= 30) {
return("Struggling. Please water me!")
} else if (health > 0) {
return("Critical! Water immediately or I'll die!")
} else {
return("Your plant has died. Start a new one with PlantNew()")
}
}
# ---- main functions
PlantNew <- function(name = NULL, file = .plant_file) {
existing <- get_plant(file)
if (!is.null(existing) && existing$health > 0) {
cat(" You already have a plant named '", existing$name, "'!n", sep = "")
cat(" Health: ", existing$health, "% | Stage: ",
get_stage(existing$points)$name, "nn", sep = "")
cat(" Are you sure you want to replace it? (yes/no): ")
response <- tolower(readline())
if (response != "yes") {
cat(" Keeping your existing plant. nn")
}
}
# Get plant name
if (is.null(name)) {
suggestions <- c("Fernie Bennes", "Morgan Treeman", "Leaf Seinfeld",
"Plantonio Banderas", "Elvis Parsley", "Kramerofern",
"Snake Costanza", "Aloe NewmanVera", "Jungle Tribbiani")
cat("n")
cat(" NEW PLANT!n")
cat(" Some name suggestions:n")
for (i in seq_along(suggestions)) {
cat(sprintf(" %d. %sn", i, suggestions(i)))
}
cat("n Enter a name (or number, or press Enter for random): ")
input <- readline()
if (input == "") {
name <- sample(suggestions, 1)
} else if (grepl("^(0-9)+$", input)) {
idx <- as.integer(input)
if (idx >= 1 && idx <= length(suggestions)) {
name <- suggestions(idx)
} else {
name <- input
}
} else {
name <- input
}
}
# Create new plant
plant <- list(
name = name,
species = "R-Plant (Programmus enthusiasticus)",
planted_date = Sys.Date(),
last_watered = Sys.Date(),
last_visited = Sys.time(),
points = 0,
health = 100,
times_watered = 0,
sessions = 0,
achievements = character(0)
)
save_plant(plant, file)
cat("n")
cat(" ╔", hline("═", 44), "╗n", sep = "")
cat(" ║ NEW PLANT CREATED! ║n")
cat(" ╚", hline("═", 44), "╝n", sep = "")
cat("n")
art <- plant_art$seed
for (line in art) {
cat(" ", line, "n", sep = "")
}
cat("n")
cat("Name: ", name, "n", sep = "")
cat("Species: ", plant$species, "n", sep = "")
cat("Planted: ", format(Sys.Date(), "%B %d, %Y"), "n", sep = "")
cat("n")
cat("Tips:n")
cat(" --> Use WaterPlant() to water your plantn")
cat(" --> Use CheckPlant() to see its statusn")
cat(" --> Visit often - your R sessions help it grow!n")
cat("n")
}
# -- Water planting
WaterPlant <- function(file = .plant_file) {
plant <- get_plant(file)
if (is.null(plant)) {
cat("n No plant found! Start one with PlantNew()nn")
}
if (plant$health <= 0) {
cat("n Your plant has died. Start a new one with PlantNew()nn")
}
# Check if already watered today
last_water_date <- as.Date(plant$last_watered)
today <- Sys.Date()
if (last_water_date == today) {
cat("n")
cat(" Already watered today!n")
cat(" Your plant doesn't want to drown. n")
cat(" Come back tomorrow!nn")
return(invisible(plant))
}
# Calculate bonus for consecutive days
days_since_water <- days_since(plant$last_watered)
water_points <- 15
health_gain <- 20
if (days_since_water == 1) {
water_points <- water_points + 5 # Consecutive day bonus
plant$achievements <- union(plant$achievements, "daily_waterer")
}
plant$last_watered <- today
plant$points <- plant$points + water_points
plant$health <- min(100, plant$health + health_gain)
plant$times_watered <- plant$times_watered + 1
plant$last_visited <- Sys.time()
# Check for achievements
if (plant$times_watered == 10 && !"10_waters" %in% plant$achievements) {
plant$achievements <- c(plant$achievements, "10_waters")
}
if (plant$times_watered == 50 && !"50_waters" %in% plant$achievements) {
plant$achievements <- c(plant$achievements, "50_waters")
}
save_plant(plant, file)
# Get stage info
old_stage <- get_stage(plant$points - water_points)
new_stage <- get_stage(plant$points)
leveled_up <- new_stage$stage > old_stage$stage
# Display
cat("n")
cat(" ╔", hline("═", 44), "╗n", sep = "")
cat(" ║ WATERING TIME! ║n")
cat(" ╚", hline("═", 44), "╝n", sep = "")
cat("n")
cat(" Watering '", plant$name, "'...nn", sep = "")
art <- get_plant_art(plant)
for (line in art) {
cat(" ", line, "n", sep = "")
}
cat(sprintf(" +%d growth points! (Total: %d)n", water_points, plant$points))
cat(sprintf(" Health: %d%% %sn", plant$health, strrep("█", plant$health %/% 10)))
if (leveled_up) {
cat("n")
cat(" ╔", hline("═", 44), "╗n", sep = "")
cat(" LEVEL UP! Your plant is now: ", new_stage$emoji, " ", new_stage$name, "n", sep = "")
cat(" ╔", hline("═", 44), "╗n", sep = "")
}
cat("n ", get_encouragement(), "nn", sep = "")
}
# -- Check on your desk plant
CheckPlant <- function(file = .plant_file) {
plant <- get_plant(file)
if (is.null(plant)) {
cat("n No plant found! Start one with PlantNew()nn")
}
days_without_water <- days_since(plant$last_watered)
if (days_without_water > 1 && plant$health > 0) {
# Lose health for each day without water (after first day)
health_loss <- (days_without_water - 1) * 10
plant$health <- max(0, plant$health - health_loss)
}
session_start <- Sys.getenv("R_SESSION_TMPDIR") # Unique per session
visit_points <- 2
plant$points <- plant$points + visit_points
plant$sessions <- plant$sessions + 1
plant$last_visited <- Sys.time()
if (plant$sessions == 100 && !"100_sessions" %in% plant$achievements) {
plant$achievements <- c(plant$achievements, "100_sessions")
}
save_plant(plant, file)
# Get stage info
stage <- get_stage(plant$points)
days_alive <- days_since(plant$planted_date)
# Display
cat("n")
cat(" ╔", hline("═", 44), "╗n", sep = "")
cat(" ║ PLANT STATUS REPORT ║n")
cat(" ╚", hline("═", 44), "╝n", sep = "")
cat("n")
# Show art
art <- get_plant_art(plant)
for (line in art) {
cat(" ", line, "n", sep = "")
}
cat("n")
cat(" ", hline("─", 44), "n", sep = "")
cat(sprintf(" Name: %sn", plant$name))
cat(sprintf(" Age: %d day%s oldn", days_alive, if(days_alive != 1) "s" else ""))
cat(sprintf(" Stage: %s %sn", stage$emoji, stage$name))
cat(sprintf(" Points: %d / %d (next stage)n",
plant$points,
ifelse(stage$stage < 7, growth_stages$min_points(stage$stage + 2), "MAX")))
cat(" ", hline("─", 44), "n", sep = "")
# Health bar
health_bar <- paste0(
strrep("█", plant$health %/% 10),
strrep("░", 10 - plant$health %/% 10)
)
cat(sprintf(" Health: (%s) %d%%n", health_bar, plant$health))
cat(sprintf(" Status: %sn", get_health_message(plant$health)))
cat(" ", hline("─", 44), "n", sep = "")
# Water status
days_since_water <- days_since(plant$last_watered)
if (days_since_water == 0) {
water_status <- " Watered today!"
} else if (days_since_water == 1) {
water_status <- " Watered yesterday"
} else {
water_status <- sprintf(" %d days without water!", days_since_water)
}
cat(sprintf(" Last water: %sn", water_status))
cat(" ", hline("─", 44), "n", sep = "")
# Stats
cat(sprintf(" Waterings: %d totaln", plant$times_watered))
cat(sprintf(" Visits: %d R sessionsn", plant$sessions))
# Achievements
if (length(plant$achievements) > 0) {
cat(" ", hline("─", 44), "n", sep = "")
cat(" Achievements:n")
achievement_names <- list(
"daily_waterer" = "Daily Waterer - Watered on consecutive days",
"10_waters" = "Hydration Helper - Watered 10 times",
"50_waters" = "Water Master - Watered 50 times",
"100_sessions" = "Dedicated Parent - 100 R sessions"
)
for (ach in plant$achievements) {
if (ach %in% names(achievement_names)) {
cat(sprintf(" %sn", achievement_names((ach))))
}
}
}
if (days_since_water >= 1 && plant$health > 0) {
cat(" Don't forget to WaterPlant()!nn")
}
}
# Quick status - just show the plant
Plant <- function(file = .plant_file) {
plant <- get_plant(file)
if (is.null(plant)) {
cat("n No plant! Use PlantNew() to start.nn")
}
# Update health decay silently
days_without_water <- days_since(plant$last_watered)
if (days_without_water > 1 && plant$health > 0) {
health_loss <- (days_without_water - 1) * 10
plant$health <- max(0, plant$health - health_loss)
save_plant(plant, file)
}
stage <- get_stage(plant$points)
art <- get_plant_art(plant)
cat("n")
for (line in art) {
cat(" ", line, "n", sep = "")
}
cat("n")
cat(sprintf(" %s %s | Day %d | %d%% healthn",
stage$emoji, plant$name,
days_since(plant$planted_date),
plant$health))
cat("n")
}
PlantDelete <- function(file = .plant_file, confirm = TRUE) {
plant <- get_plant(file)
if (is.null(plant)) {
cat("n No plant to delete.nn")
return(invisible(FALSE))
}
if (confirm) {
cat("n Are you sure you want to delete '", plant$name, "'?n", sep = "")
cat(" This cannot be undone! (yes/no): ")
response <- tolower(readline())
if (response != "yes") {
cat(" Keeping your plant safe. nn")
}
}
file.remove(file)
cat("n Goodbye, ", plant$name, "...n", sep = "")
cat(" Use PlantNew() to start fresh.nn")
}
#optional
.onAttach <- function() {
plant <- get_plant()
if (!is.null(plant) && plant$health > 0) {
stage <- get_stage(plant$points)
message(sprintf(" Your plant '%s' (%s) is waiting! Use CheckPlant() to visit.",
plant$name, stage$name))
}
}
# Run welcome check
local({
plant <- get_plant()
if (!is.null(plant) && plant$health > 0) {
days_without_water <- days_since(plant$last_watered)
stage <- get_stage(plant$points)
cat(sprintf("n '%s' says hello! (%s, Day %d)n",
plant$name, stage$name, days_since(plant$planted_date)))
if (days_without_water >= 2) {
cat(sprintf("It's been %d days without water!n", days_without_water))
}
cat("n")
}
})
Sfaturi PRO:
- Apă zilnic pentru puncte bonus
- Doar rularea CheckPlant() oferă puncte mici de creștere
- Nu uitați să udați sau planta se va ofili!
- Sănătate sub 30% = ofilit, Sănătate 0% = mort
Verificați depozitul pentru actualizări viitoare!
Rămâi sănătos și fericit cu codificarea R!
Disclaimer: toată arta ASCII a fost realizată de GPT, precum și numele plantelor și progresul jocului ASCII.
