Load Packages & Data

Subject-level Data

subj_data_raw <- read.csv(file = paste0(data_path, "subject_data.csv"))

subj_data <- subj_data_raw %>%
  filter(is_valid == "True") %>%
  filter(duplicates_percentage < 25) %>%
  filter(valid_group_size >= 4 | condition_signaling == 'A') %>% 
  mutate(
    Participant = as.factor(player_id),
    Group = as.factor(group),
    SignalingType = as.factor(condition_signaling),
    SignalingType = factor(SignalingType, levels = c('A', 'NP', 'VP', 'FP')),
    ResourceSpeed = as.factor(condition_resource),
    ResourceSpeed = relevel(ResourceSpeed, ref = "fast"),
    Score = as.numeric(final_score),
    ScoreFirstHalf = as.numeric(score_first_half),
    ScoreSecondHalf = Score - ScoreFirstHalf,
    PCS = as.numeric(points_collection_speed) / 60,  # convert to seconds
    PCR = PCS,
    TrackingTime = as.numeric(time_on_resource),
    SignalingPercentageOthers = as.numeric(others_signaling_percentage),
    SignalingPercentageOwn = as.numeric(own_signaling_percentage),
    ResourceEncounters = as.numeric(resource_encounters),
    IsInFullGroup = (SignalingType == 'A') | (valid_group_size == 5)
  )

head(subj_data)
subj_data %>%
  group_by(condition_signaling, condition_resource, group) %>%
  summarise(n_participants = n(), .groups = "drop") %>%
  group_by(condition_signaling, condition_resource) %>%
  summarise(
    N_participants = sum(n_participants),
    N_groups = n(),
    N_groups_5 = sum(n_participants == 5),
    N_groups_4 = sum(n_participants == 4),
    .groups = "drop"
  )
colnames(subj_data)

[1] “player_id” “condition_signaling” “condition_resource” “starting_time_in_condition_minutes”
[5] “group” “time_in_experiment” “nan_percentage” “duplicates”
[9] “duplicates_percentage” “duplicates_resource_percentage” “is_valid” “average_distance_from_resource”
[13] “final_score” “score_first_half” “resource_encounters” “average_tracking_length”
[17] “time_on_resource” “points_collection_speed” “others_signaling_count” “others_signaling_percentage”
[21] “own_signaling_count” “own_signaling_percentage” “others_on_resource_signaling_count” “others_on_resource_signaling_percentage” [25] “mean_visible_participants” “mean_visible_participants_tracking” “mean_visible_participants_not_tracking” “Total.approvals”
[29] “Age” “Sex” “Ethnicity.simplified” “Nationality”
[33] “Student.status” “Employment.status” “valid_group_size” “Participant”
[37] “Group” “SignalingType” “ResourceSpeed” “Score”
[41] “ScoreFirstHalf” “ScoreSecondHalf” “PCS” “PCR”
[45] “TrackingTime” “SignalingPercentageOthers” “SignalingPercentageOwn” “ResourceEncounters”
[49] “IsInFullGroup”

Time Series Data

time_series_data_raw <- read.csv(file = paste0(data_path, "time_series_data.csv"))

time_series_data <- time_series_data_raw %>%
  mutate(
    Participant = as.factor(participant),
    SignalingType = as.factor(signaling),
    ResourceSpeed = as.factor(resource),
    State = as.factor(state),
    DetectorChange = as.numeric(distance_change_lag1_cat2),
    SocInfoQualityRaw = round(as.numeric(soc_info_quality_raw), 2),
    SocInfoQuality = factor(ifelse(SocInfoQualityRaw < 0, "1", "-1"), levels = c("-1", "1")),
    SocInfoQualityRawBest = round(as.numeric(soc_info_quality_raw_best), 2),
    VisPlayersDistFromResource = round(as.numeric(best_distance_from_resource_visible_players), 2),
    AllPlayersDistFromResource = round(as.numeric(best_distance_from_resource_all_players), 2),
    OwnDistFromResource = round(as.numeric(first_distance_from_resource), 2),
    OutDegree = as.numeric(out_degree),
    InDegree = as.numeric(in_degree),
    NoMovementTimes = as.numeric(no_movement_times),
    SocialMovementDirection = round(as.numeric(social_movement_direction), 4),
    SocialMovementDirectionBest = round(as.numeric(social_movement_direction_best), 4),
    Rotation = round(as.numeric(rotation_change_mean_raw), 4),
    AlignmentResourceChange = round(as.numeric(res_rotation_change), 4),
    VisPlayersDirection = round(as.numeric(mean_degree_visible_players_first), 4),
    PlayerRank = as.factor(rank_of_player_by_distance_from_resource_first),
    IsSignaling = as.numeric(is_signaling),
    Time = as.numeric(step),
    SocialMovementDirectionCohesion = round(as.numeric(social_movement_direction_cohesion), 4),
    MeanVisibleGroupSpread = round(as.numeric(mean_visible_group_spread), 2),
    MeanDistToVisibleNeighbors = round(as.numeric(mean_distance_to_visible_neighbors), 2)
  ) %>%
  mutate(ResourceSpeed = relevel(ResourceSpeed, ref = "fast")) %>%
  mutate(SignalingType = factor(SignalingType, levels = c('A', 'NP', 'VP', 'FP'))) %>%
  mutate(SocInfoQualityBin = factor(case_when(
    (State == 'tracking') & (SocInfoQualityRawBest < 0) ~ 1,
    (State == 'tracking') & (SocInfoQualityRawBest > 0) ~ 0,
    (State == 'searching') & (VisPlayersDistFromResource < 40) ~ 1,
    (State == 'searching') & (VisPlayersDistFromResource > 40) ~ 0,
    .default = 0
  ), levels = c(0, 1))) %>%
  mutate(IsGoodSocialInfoAvailable = factor(case_when(
    (State == 'tracking') & (OwnDistFromResource > AllPlayersDistFromResource) ~ 1,
    (State == 'tracking') & (OwnDistFromResource <= AllPlayersDistFromResource) ~ 0,
    (State == 'searching') & (AllPlayersDistFromResource < 40) ~ 1,
    (State == 'searching') & (AllPlayersDistFromResource > 40) ~ 0,
    .default = 0
  ), levels = c(0, 1))) %>%
  mutate(RotationDirCorrect = ifelse(AlignmentResourceChange > 0, 1, 0)) %>%
  # mutate(MeanVisibleGroupSpreadStd = as.numeric(scale(log1p(MeanVisibleGroupSpread)))) %>%
  mutate(MeanVisibleGroupSpreadStd = as.numeric(scale(MeanVisibleGroupSpread))) %>%
  group_by(Participant) %>%
  mutate(RotationLag1 = lag(Rotation, order_by=Participant)) %>%
  mutate(DetectorChangeLag1 = lag(DetectorChange, order_by=Participant)) %>%
  ungroup() %>%
  select(Participant, SignalingType, ResourceSpeed, Time, State,
         DetectorChange, DetectorChangeLag1, SocInfoQuality, InDegree, OutDegree,
         SocInfoQualityRaw, SocInfoQualityBin,
         IsGoodSocialInfoAvailable,SocialMovementDirection, Rotation, RotationLag1,
         SocInfoQualityRawBest, VisPlayersDistFromResource, NoMovementTimes,
         SocialMovementDirectionBest, OwnDistFromResource, RotationDirCorrect,
         VisPlayersDirection, PlayerRank, IsSignaling,
         SocialMovementDirectionCohesion, MeanVisibleGroupSpread, MeanVisibleGroupSpreadStd,
         MeanDistToVisibleNeighbors)

head(time_series_data)
colnames(time_series_data)

[1] “Participant” “SignalingType” “ResourceSpeed” “Time” “State”
[6] “DetectorChange” “DetectorChangeLag1” “SocInfoQuality” “InDegree” “OutDegree”
[11] “SocInfoQualityRaw” “SocInfoQualityBin” “IsGoodSocialInfoAvailable” “SocialMovementDirection” “Rotation”
[16] “RotationLag1” “SocInfoQualityRawBest” “VisPlayersDistFromResource” “NoMovementTimes” “SocialMovementDirectionBest”
[21] “OwnDistFromResource” “RotationDirCorrect” “VisPlayersDirection” “PlayerRank” “IsSignaling”
[26] “SocialMovementDirectionCohesion” “MeanVisibleGroupSpread” “MeanVisibleGroupSpreadStd” “MeanDistToVisibleNeighbors”

Resource Discoveries Data

resource_discoveries_data_raw <- read.csv(file = paste0(data_path, "resource_discoveries_data.csv"))

resource_discoveries_data_all <- resource_discoveries_data_raw %>%
  mutate(
      Participant = as.factor(player_id),
      Timepoint = as.numeric(timepoint) - 2,
      Event = as.factor(events),
      PlayerOrder = as.numeric(player_order),
      PlayerOrderCat = as.factor(ifelse(player_order == 1, 'first', 'others')),
      Distance = as.numeric(distance_from_resource),
      IsOnResource = ifelse(Distance <= 40, 1, 0),
      InDegree = as.numeric(in_degree),
      OutDegree = as.numeric(out_degree),
      SignalingType = as.factor(condition_signaling),
      ResourceSpeed = as.factor(condition_resource),
      IsSignaling = as.numeric(signaling)
  ) %>%
  filter(Timepoint >= 0) %>%    # remove 2-seconds offset
  select(Participant, Event, SignalingType, ResourceSpeed, PlayerOrder, PlayerOrderCat, Timepoint, InDegree, OutDegree, Distance, IsOnResource, IsSignaling) %>%
  mutate(SignalingType = factor(SignalingType, levels = c('A', 'NP', 'VP', 'FP')),)

resource_discoveries_data <- resource_discoveries_data_all %>% 
  filter(Timepoint >= 0)   # remove 2-seconds offset
  

head(resource_discoveries_data)
colnames(resource_discoveries_data)

[1] “Participant” “Event” “SignalingType” “ResourceSpeed” “PlayerOrder” “PlayerOrderCat” “Timepoint” “InDegree” “OutDegree” “Distance” “IsOnResource”
[12] “IsSignaling”

Resource Discoveries Data: Voluntary Payoff condition

Session Information

sessionInfo()
## R version 4.5.3 (2026-03-11)
## Platform: x86_64-pc-linux-gnu
## Running under: Debian GNU/Linux 13 (trixie)
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.29.so;  LAPACK version 3.12.0
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8     LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8    LC_PAPER=en_US.UTF-8      
##  [8] LC_NAME=C                  LC_ADDRESS=C               LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
## 
## time zone: Europe/Berlin
## tzcode source: system (glibc)
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] Hmisc_5.2-5            scales_1.4.0           cowplot_1.1.3          ggthemes_5.1.0         extrafont_0.19         marginaleffects_0.25.1 gtools_3.9.5           gtExtras_0.5.0        
##  [9] gt_1.0.0               viridis_0.6.5          viridisLite_0.4.2      NISTunits_1.0.1        units_0.8-7            svglite_2.2.1          ggpubr_0.6.0           metR_0.18.1           
## [17] cmdstanr_0.9.0         invgamma_1.1           kableExtra_1.4.0       jtools_2.3.0           hrbrthemes_0.8.7       interactions_1.2.0     bayesplot_1.12.0       brms_2.22.0           
## [25] Rcpp_1.0.14            emmeans_1.11.1         coda_0.19-4.1          modelr_0.1.11          tidybayes_3.0.7        lubridate_1.9.4        forcats_1.0.0          stringr_1.5.1         
## [33] dplyr_1.1.4            purrr_1.0.4            readr_2.1.5            tidyr_1.3.1            tibble_3.2.1           ggplot2_3.5.2          tidyverse_2.0.0        pacman_0.5.1          
## 
## loaded via a namespace (and not attached):
##  [1] RColorBrewer_1.1-3      tensorA_0.36.2.1        rstudioapi_0.17.1       jsonlite_2.0.0          magrittr_2.0.3          estimability_1.5.1      farver_2.1.2            rmarkdown_2.29         
##  [9] vctrs_0.6.5             memoise_2.0.1           paletteer_1.6.0         base64enc_0.1-3         rstatix_0.7.2           htmltools_0.5.8.1       distributional_0.5.0    broom_1.0.8            
## [17] Formula_1.2-5           sass_0.4.10             parallelly_1.44.0       bslib_0.9.0             htmlwidgets_1.6.4       fontawesome_0.5.3       cachem_1.1.0            lifecycle_1.0.4        
## [25] pkgconfig_2.0.3         Matrix_1.7-4            R6_2.6.1                fastmap_1.2.0           future_1.49.0           digest_0.6.37           colorspace_2.1-2        furrr_0.3.1            
## [33] rematch2_2.1.2          ps_1.9.1                textshaping_1.0.1       timechange_0.3.0        abind_1.4-8             compiler_4.5.3          fontquiver_0.2.1        withr_3.0.2            
## [41] pander_0.6.6            htmlTable_2.4.3         backports_1.5.0         carData_3.0-5           Rttf2pt1_1.3.12         broom.mixed_0.2.9.6     ggsignif_0.6.4          loo_2.8.0              
## [49] tools_4.5.3             foreign_0.8-91          extrafontdb_1.0         nnet_7.3-20             glue_1.8.0              nlme_3.1-168            grid_4.5.3              checkmate_2.3.2        
## [57] cluster_2.1.8.2         generics_0.1.4          gtable_0.3.6            tzdb_0.5.0              data.table_1.17.2       hms_1.1.3               xml2_1.3.8              car_3.1-3              
## [65] pillar_1.10.2           ggdist_3.3.3            posterior_1.6.1         splines_4.5.3           lattice_0.22-9          tidyselect_1.2.1        fontLiberation_0.1.0    knitr_1.50             
## [73] fontBitstreamVera_0.1.1 arrayhelpers_1.1-0      gridExtra_2.3           bookdown_0.44           xfun_0.52               bridgesampling_1.1-2    matrixStats_1.5.0       stringi_1.8.7          
## [81] yaml_2.3.10             evaluate_1.0.3          codetools_0.2-20        gdtools_0.4.2           cli_3.6.5               rpart_4.1.24            RcppParallel_5.1.10     xtable_1.8-4           
## [89] systemfonts_1.2.3       processx_3.8.6          jquerylib_0.1.4         globals_0.18.0          svUnit_1.0.6            parallel_4.5.3          rstantools_2.4.0        Brobdingnag_1.2-9      
## [97] listenv_0.9.1           mvtnorm_1.3-3           rlang_1.1.6