escapeR is a small escape-room game for learning R
through ecological statistics. Each room gives you a thread of the whole
story, a task, and a lock. You solve the task with ordinary R commands,
then submit the answer to move to the next room.
The bundled quest starts with R foundations and moves through data import, visualisation, data manipulation, simple ecological modelling, distance-sampling ideas, and reproducible workflows.
To start playing you simply need to load the package and call
escape():
In an interactive R session, escape() asks for your
player name. Use a short name you can remember, because
escapeR saves your progress under that name.
You can also provide your player name directly:
The first room is then printed in the console. It includes:
The task is solved outside the game prompt. Use R as you normally would: create objects, inspect data, calculate values, make plots, or fit models. When you think you have the answer, submit it.
Use submit() with the answer that should open the
current lock:
If the answer is correct, escapeR shows the success
message and moves you to the next room. If the answer is not correct,
the room remains locked and you can try again.
While numeric answers are submitted as is, text answers should be submitted as character strings:
For simple text locks, escapeR ignores leading and
trailing spaces and is not case-sensitive. Numeric answers are checked
with a small tolerance unless a room uses a custom checker.
If you get stuck, call hint():
Some rooms have more than one hint. Repeated calls reveal the hints in order:
Hints are meant to nudge you toward the R idea rather than simply giving away the answer. In a classroom, it is usually worth trying the task first, asking R what objects you have created, and then requesting a hint if the lock is still not opening.
If the console has filled up with other work, call
play():
play() does not restart the game. It simply prints the
current room again, so you can reread the task and learning goal.
Use status() to see where you are:
This tells you the active player, how many rooms have been solved out of those in the game, and which room is current. It is useful during longer activities or when returning to the game after a break.
Progress is saved automatically for each player using
tools::R_user_dir("escapeR", "data"). To resume, load the
package and call escape() again with the same player
name:
If saved progress exists for that player, the game resumes from the current room. If no saved progress exists, a new quest starts.
To restart the active player’s quest from the beginning, call:
You can also reset a named player:
Or start again directly with escape(reset = TRUE):
Use resetting with care in class: it deliberately starts that player’s progress again from room 1, so all previous progress is lost.
Several rooms ask you to read or inspect files included with the
package. Use escapeR_file() to find them. As an example, if
a data file was called “dataX.csv” you would use
For example, a room might ask you to read a CSV file and then inspect it. One option would then be
The package also provides a separate, small survey data set.
survey_counts() returns this data frame directly; it does
not read or modify dados1.csv. Store the returned data
frame in an object before working with it:
survey <- survey_counts()
names(survey)
#> [1] "site" "habitat" "count" "distance_m" "detected"
head(survey)
#> site habitat count distance_m detected
#> 1 S1 forest 12 15 TRUE
#> 2 S2 forest 15 40 TRUE
#> 3 S3 forest 11 70 TRUE
#> 4 S4 forest 14 95 FALSE
#> 5 S5 scrub 6 20 TRUE
#> 6 S6 scrub 9 55 TRUE
sum(is.na(survey))
#> [1] 2It has five named columns (site, habitat,
count, distance_m, and detected).
Two values in count are NA, included
deliberately for the data quality exercise. By contrast,
dados1.csv has four columns and no missing values. The
survey data set appears in several rooms about data quality, summaries,
modelling, and distance sampling.
Use list_rooms() to inspect the bundled room
sequence:
list_rooms()
#> room id
#> console 1 console
#> vector 2 vector
#> finddata 3 finddata
#> datatab 4 datatab
#> columns 5 columns
#> missing 6 missing
#> plotwin 7 plotwin
#> habitat 8 habitat
#> hidden 9 hidden
#> subset 10 subset
#> sorting 11 sorting
#> model 12 model
#> resid 13 resid
#> predict 14 predict
#> detectp 15 detectp
#> detect 16 detect
#> trunc 17 trunc
#> comment 18 comment
#> webglm 19 webglm
#> quarto 20 quarto
#> en08 21 en08
#> en09 22 en09
#> posprop 23 posprop
#> en10 24 en10
#> en11 25 en11
#> en12 26 en12
#> en13 27 en13
#> bpmean 28 bpmean
#> en14 29 en14
#> en15 30 en15
#> en16 31 en16
#> en17 32 en17
#> en18 33 en18
#> en19 34 en19
#> riskcat 35 riskcat
#> en20 36 en20
#> en21 37 en21
#> en22 38 en22
#> en23 39 en23
#> en24 40 en24
#> en01 41 en01
#> en25 42 en25
#> en02 43 en02
#> en03 44 en03
#> en04 45 en04
#> en05 46 en05
#> en06 47 en06
#> en07 48 en07
#> module
#> console R foundations
#> vector R foundations
#> finddata Data import and inspection
#> datatab Data import and inspection
#> columns Data import and inspection
#> missing Data import and inspection
#> plotwin Visualisation
#> habitat Visualisation
#> hidden Visualisation
#> subset Data manipulation
#> sorting Data manipulation
#> model Ecological modelling
#> resid Ecological modelling
#> predict Ecological modelling
#> detectp Distance sampling
#> detect Distance sampling
#> trunc Distance sampling
#> comment Reproducible workflow
#> webglm Reproducible workflow
#> quarto Reproducible workflow
#> en08 Ecologia Num<U+00E9>rica - Lecture 08: Experimental design and pseudoreplication
#> en09 Ecologia Num<U+00E9>rica - Lecture 09: Exploratory graphics and transformations
#> posprop Medicine
#> en10 Ecologia Num<U+00E9>rica - Lecture 10: Hypothesis testing and p-values
#> en11 Ecologia Num<U+00E9>rica - Lecture 11: Assumptions and the one-sample t-test
#> en12 Ecologia Num<U+00E9>rica - Lecture 12: One- and two-sample tests: signed ranks
#> en13 Ecologia Num<U+00E9>rica - Lecture 13: Paired tests and one-way ANOVA
#> bpmean Medicine
#> en14 Ecologia Num<U+00E9>rica - Lecture 14: Multiple comparisons and factorial ANOVA
#> en15 Ecologia Num<U+00E9>rica - Lecture 15: Blocks, repeated measures, and nested designs
#> en16 Ecologia Num<U+00E9>rica - Lecture 16: Simple and multiple linear regression
#> en17 Ecologia Num<U+00E9>rica - Lecture 17: Factors in regression and model diagnostics
#> en18 Ecologia Num<U+00E9>rica - Lecture 18: GLMs, links, and model selection
#> en19 Ecologia Num<U+00E9>rica - Lecture 19: Generalized additive models
#> riskcat Medicine
#> en20 Ecologia Num<U+00E9>rica - Lecture 20: Correlation and contingency tables
#> en21 Ecologia Num<U+00E9>rica - Lecture 21: Log-linear models and maximum likelihood
#> en22 Ecologia Num<U+00E9>rica - Lecture 22: Multivariate data and classification
#> en23 Ecologia Num<U+00E9>rica - Lecture 23: Distances and hierarchical clustering
#> en24 Ecologia Num<U+00E9>rica - Lecture 24: Non-hierarchical clustering and ordination
#> en01 Ecologia Num<U+00E9>rica - Class 01
#> en25 Ecologia Num<U+00E9>rica - Lecture 25: PCA and other ordination methods
#> en02 Ecologia Num<U+00E9>rica - Lecture 02: Critical thinking and observation filters
#> en03 Ecologia Num<U+00E9>rica - Lecture 03: Scientific questions and falsifiable hypotheses
#> en04 Ecologia Num<U+00E9>rica - Lecture 04: Variable types and probability rules
#> en05 Ecologia Num<U+00E9>rica - Lecture 05: Random variables and distributions
#> en06 Ecologia Num<U+00E9>rica - Lecture 06: Distribution functions in R
#> en07 Ecologia Num<U+00E9>rica - Lecture 07: Sampling and stratification
#> title
#> console The Console Door
#> vector The Vector Cabinet
#> finddata Finding Data
#> datatab The Data Table Hatch
#> columns The Column Scanner
#> missing The Missing Value Mirror
#> plotwin The Plotting Window
#> habitat The Habitat Mosaic
#> hidden The Hidden Data
#> subset The Subsetting Lock
#> sorting The Sorting Staircase
#> model The Model Room
#> resid The Residual Drawer
#> predict The Prediction Lantern
#> detectp The Observation Filter
#> detect The Detection Counter
#> trunc The Truncation Gate
#> comment The Comment Cipher
#> webglm The Web Data Model
#> quarto The Quarto Exit
#> en08 The Aquarium Illusion
#> en09 The Standardisation Mirror
#> posprop The Test Result Board
#> en10 The Sign Test Lock
#> en11 The Reference Growth Chamber
#> en12 The Ranked Shells
#> en13 The Three Meadows
#> bpmean The Clinic Intake
#> en14 The Interaction Trap
#> en15 The Blocked Greenhouse
#> en16 The Regression Staircase
#> en17 The Residual Window
#> en18 The Logistic Gate
#> en19 The Curved Forest
#> riskcat The Risk Label
#> en20 The Independence Table
#> en21 The Likelihood Nest
#> en22 The Community Matrix
#> en23 The Shared Species Lock
#> en24 The Two Shoals
#> en01 The First Practical Class
#> en25 The Final Principal Door
#> en02 The Invisible Birds
#> en03 The River Hypothesis
#> en04 The Two Habitat Gates
#> en05 The Nest Lottery
#> en06 The Temperature Vault
#> en07 The Unequal Habitats
#> learning_goal
#> console Use R as a calculator and learn expression order.
#> vector Create vectors and summarize them with functions.
#> finddata Find and inspect built-in R datasets.
#> datatab Read and inspect a CSV data set.
#> columns Identify variables in a data frame.
#> missing Check data quality before analysis.
#> plotwin Make a basic plot and read a visual pattern.
#> habitat Use tables to summarize categorical variables before plotting.
#> hidden Discover that plotted data can reveal structure hidden in plain text.
#> subset Subset data frames using logical conditions.
#> sorting Order data and inspect extreme observations.
#> model Fit and interpret a simple linear model.
#> resid Understand that fitted models leave residual variation.
#> predict Use a fitted model to predict for a new ecological setting.
#> detectp Connect observed data to an imperfect observation process.
#> detect Summarize detections as observed outcomes.
#> trunc Think about distance cutoffs and retained observations.
#> comment Recognize comments as part of readable R code.
#> webglm Read data from a web link and fit a Poisson GLM.
#> quarto Recognize reproducible reports as part of the analysis workflow.
#> en08 Identify experimental units and avoid counting subsamples as treatment replicates.
#> en09 Centre and scale measurements using the sample standard deviation.
#> posprop Calculate a proportion from counts.
#> en10 Calculate an exact two-sided binomial p-value under a stated null hypothesis.
#> en11 Compute a one-sample t statistic while recognizing independence and Normality assumptions.
#> en12 Calculate the positive-rank sum in a one-sample Wilcoxon signed-rank test.
#> en13 Fit a one-way ANOVA and extract the between-group F statistic.
#> bpmean Create a numeric vector and calculate its mean.
#> en14 Recognize a factorial interaction through a difference of treatment effects.
#> en15 Account for matched blocks by analysing differences within each block.
#> en16 Fit a linear regression and interpret its slope in ecological units.
#> en17 Calculate residuals from a fitted model and identify the largest absolute residual.
#> en18 Transform a binomial GLM linear predictor into a probability on the response scale.
#> en19 Recognize when a smooth ecological response calls for a GAM.
#> riskcat Use a logical comparison to classify a value.
#> en20 Compute an expected contingency-table count under independence.
#> en21 Find a Bernoulli maximum-likelihood estimate using a grid search.
#> en22 Organize sites as rows and species as columns, then summarize each species.
#> en23 Calculate Jaccard dissimilarity for presence-absence data while excluding joint absences.
#> en24 Run k-means with explicit initial centres and interpret a centre independently of its label.
#> en01 Use R arithmetic, square roots, and unit conversion to calculate travel time.
#> en25 Fit a PCA and calculate the proportion of variance explained by its first component.
#> en02 Distinguish observed counts from abundance when detection is imperfect.
#> en03 Translate a falsifiable ecological hypothesis into a numerical prediction.
#> en04 Calculate the probability of a union without double-counting an intersection.
#> en05 Calculate a binomial probability and recognize its assumptions.
#> en06 Use a cumulative distribution function to calculate an upper-tail probability.
#> en07 Weight stratum means by the sizes of the strata.The id column is useful when building a shorter custom
quest, where you can provide a list of rooms to be played as a separate
quest. See next section and the corresponding dedicated vignette for
details on how to create new rooms and quests.
Instructors can build a quest from selected room IDs, as an example here, a mini 3-room quest:
short_quest <- build_escape(c("console", "vector", "plotwin"))
escape(player = "demo_short", reset = TRUE, escape = short_quest)The same escape() command starts the custom sequence.
The only difference is that the escape argument receives an
escape sequence created with build_escape().
If room packs have been registered, list_escapes() shows
named sequences:
list_escapes()
#> id pack_id
#> en2026 en2026 enpack
#> medmini medmini medpack
#> medfull medfull medpack
#> enintro enintro enpack
#> rooms
#> en2026 en01, en02, en03, en04, en05, en06, en07, en08, en09, en10, en11, en12, en13, en14, en15, en16, en17, en18, en19, en20, en21, en22, en23, en24, en25
#> medmini bpmean, riskcat
#> medfull bpmean, riskcat, posprop
#> enintro en01Those named sequences can also be passed to
build_escape().
Here is the core command set while playing:
escape() # start or resume a quest
play() # show the current room again
hint() # request the next hint
submit(70) # submit an answer
status() # check progress
reset_game() # restart the active quest
list_rooms() # inspect available roomsThe most important habit is to solve the room in ordinary R first. The game is the lock; R is the key. Can you get out?
Remove a saved profile with delete_progress("ana") when
it is no longer needed. delete_progress() removes the
active profile and closes that game. Set
options(escapeR.progress_dir = "path") to select a
different directory. For demonstrations, use temporary storage and clean
it up afterwards. Profiles are case-insensitive; punctuation is replaced
by underscores in filenames. Names that map to another player’s saved
file are rejected. An unreadable save can be removed or deliberately
restarted with escape(player, reset = TRUE).