[MIRROR] We love word games (#11552)

Co-authored-by: eghughguhhhhhh <Hawoogabooga@gmail.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-08-31 17:00:41 -07:00
committed by GitHub
parent 03653c4d73
commit 74d68be7e3
11 changed files with 2596 additions and 3 deletions

View File

@@ -1,6 +1,7 @@
///Protects a datum from being VV'd ///Protects a datum from being VV'd
#define GENERAL_PROTECT_DATUM(Path)\ #define GENERAL_PROTECT_DATUM(Path)\
##Path/can_vv_get(var_name){\ ##Path/can_vv_get(var_name){\
.=..();\
return FALSE;\ return FALSE;\
}\ }\
##Path/vv_edit_var(var_name, var_value){\ ##Path/vv_edit_var(var_name, var_value){\

View File

@@ -98,6 +98,19 @@ GLOBAL_LIST_EMPTY(refined_chems_sold)
end_dols = FLOOR(end_dols * 100,1) / 100 // Truncate decimals end_dols = FLOOR(end_dols * 100,1) / 100 // Truncate decimals
valid_stats_list.Add("For a total of: [points] points, or [end_dols] [end_dols > 1 ? "thalers" : "thaler"]!") valid_stats_list.Add("For a total of: [points] points, or [end_dols] [end_dols > 1 ? "thalers" : "thaler"]!")
if(SSnerdle)
var/word_export = "This shift's nerdle Was: [SSnerdle.target_word]! <br>"
word_export += "There were [SSnerdle.total_players] players this shift!<br>"
var/list/splashes = list("We know what you are!", "That's how we do!", "Basically free!", "Hear them roar!", "The streak is alive!","Don't fall for them tricks!")
for(var/i in 1 to SSnerdle.player_attempts.len)
if(SSnerdle.player_attempts[i] > 0)
if(i < 7)
word_export += "There were [SSnerdle.player_attempts[i]] people who got it in [i]! [splashes[i]]<br>"
else
word_export += "And there were [SSnerdle.player_attempts[i]] losers who couldn't quite get it. You'll get em next time!<br>"
valid_stats_list.Add(word_export)
if(LAZYLEN(valid_stats_list)) if(LAZYLEN(valid_stats_list))
to_chat(world, span_world("Shift trivia!")) to_chat(world, span_world("Shift trivia!"))

View File

@@ -0,0 +1,29 @@
//KEEP THE STREAK ALIVE
SUBSYSTEM_DEF(nerdle)
name = "nerdle"
priority = FIRE_PRIORITY_APPRECIATE
runlevels = RUNLEVEL_GAME
flags = SS_BACKGROUND | SS_NO_FIRE
var/target_word = "fuckd"
var/list/player_attempts = list(0,0,0,0,0,0,0)//serialized, index = count of people who win/lose with that many guesses, 7 is for all the losers
var/total_players = 0
/datum/controller/subsystem/nerdle/Initialize()
var/list/l = world.file2list("strings/nerdle_dict.txt")
target_word = pick(l)
l = null
return SS_INIT_SUCCESS
/datum/controller/subsystem/nerdle/proc/report_winner_or_loser(var/guesses, var/failure = FALSE)
guesses = clamp(guesses,1,7)
if(failure)
guesses = 7 //fail
player_attempts[guesses] = player_attempts[guesses]+1
total_players ++
/datum/controller/subsystem/nerdle/can_vv_get(var_name) //the sancity of nerdle shall not be infringed by man or any of the gods above them.
if(var_name == NAMEOF(src, target_word))
return FALSE
return ..()

View File

@@ -2,6 +2,7 @@
return TRUE return TRUE
/datum/proc/can_vv_get(var_name) /datum/proc/can_vv_get(var_name)
SHOULD_CALL_PARENT(TRUE)
if(var_name == NAMEOF(src, vars)) if(var_name == NAMEOF(src, vars))
return FALSE return FALSE
return TRUE return TRUE

View File

@@ -1,8 +1,10 @@
/client /client
var/datum/managed_browser/feedback_form/feedback_form = null var/datum/managed_browser/feedback_form/feedback_form = null
/client/can_vv_get(var_name) /client/can_vv_get(var_name)//no snooping but doesn't break shit
return var_name != NAMEOF(src, feedback_form) // No snooping. if(var_name == NAMEOF(src, feedback_form))
return FALSE
return ..()
GENERAL_PROTECT_DATUM(/datum/managed_browser/feedback_form) GENERAL_PROTECT_DATUM(/datum/managed_browser/feedback_form)

View File

@@ -389,7 +389,7 @@
/mob/living/carbon/human/can_fall() /mob/living/carbon/human/can_fall()
if(..()) if(..())
return species.can_fall(src) return species?.can_fall(src)
// Another check that we probably can just merge into can_fall exept for messing up overrides // Another check that we probably can just merge into can_fall exept for messing up overrides
/atom/movable/proc/can_fall_to(turf/landing) /atom/movable/proc/can_fall_to(turf/landing)

114
code/modules/pda/nerdle.dm Normal file
View File

@@ -0,0 +1,114 @@
#define NERDLE_NO 0
#define NERDLE_YES 1
#define NERDLE_CLOSE 2
/datum/data/pda/app/nerdle
name = "Nerdle"
icon = "child-reaching" //yipee!
notify_icon = "child-combatant"
title = "Nerdle™ V0.8"
template = "pda_nerdle"
var/target_word
var/list/guesses = list() //raw text input for guesses
var/list/serialized_guesses = list() //shortcut for tgui serialization
var/max_guesses = 6
var/completed = FALSE
var/failure = FALSE
/datum/data/pda/app/nerdle/start()
. = ..()
target_word = SSnerdle.target_word
/datum/data/pda/app/nerdle/proc/try_guess(var/guess)
if(completed)
return FALSE
if(LAZYLEN(guess) != 5)
return FALSE
var/actual_guess = lowertext(guess)
serialize_guess(actual_guess)
LAZYADD(guesses,actual_guess)
if(actual_guess == target_word)
pda.audible_message("[pda] says, \"congratulations! You WON! A real NERDLE™ Champ!\"")
playsound(pda, 'sound/arcade/win.ogg', 50, 1, extrarange = -3, falloff = 0.1, ignore_walls = FALSE)
report_guesses()
return TRUE
if(LAZYLEN(guesses) >= max_guesses)
pda.audible_message("[pda] says, \"Sorry! You lose! Try again next shift!\"")
failure = TRUE
playsound(pda, 'sound/arcade/lose.ogg', 50, 1, extrarange = -3, falloff = 0.1, ignore_walls = FALSE)
report_guesses()
return FALSE
return TRUE
/datum/data/pda/app/nerdle/proc/report_guesses()
SSnerdle.report_winner_or_loser(LAZYLEN(guesses),failure)
/datum/data/pda/app/nerdle/proc/serialize_guess(var/guess)
// We assume that there's 5 letters here, both for the guess and the target word.
// If we're getting runtimes and someone forwarded "butt" to here I'm going to smite them down.
var/list/out[5]
var/list/letter_counts = list() // Track occurrences of each letter in the target word
// Count count of each letter in the target word
for(var/i in 1 to 5)
var/them = target_word[i]
letter_counts[them] = (letter_counts[them] || 0) + 1
// First pass: Mark exact matches (NERDLE_YES)
for(var/i in 1 to 5)
var/us = guess[i]
var/them = target_word[i]
if(us == them)
out[i] = NERDLE_YES
letter_counts[them] -= 1 // Reduce the count for this letter
// Second pass: Mark close matches (NERDLE_CLOSE) and invalid matches (NERDLE_NO)
for(var/i in 1 to 5)
if(out[i]) // Skip already marked letters
continue
var/us = guess[i]
if(letter_counts[us] && letter_counts[us] > 0)
out[i] = NERDLE_CLOSE
letter_counts[us] -= 1 // Reduce the count for this letter
else
out[i] = NERDLE_NO
LAZYADD(serialized_guesses, list(out)) // Wrap it in a list so it stays a list
/datum/data/pda/app/nerdle/update_ui(mob/user as mob, list/data)
data["guesses"] = serialized_guesses
data["guesses_raw"] = guesses
data["max"] = max_guesses
data["used_guesses"] = LAZYLEN(guesses)
data["target_word"] = target_word //if people fuck around with tgui to cheat at nerdle then I can't really be assed enough to care. we'll know who you are.
/datum/data/pda/app/nerdle/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
unnotify()
. = TRUE
if(action == "guess")
var/guess = params["lastword"]
var/did_we_guess = try_guess(guess)
return did_we_guess
#undef NERDLE_YES
#undef NERDLE_NO
#undef NERDLE_CLOSE

View File

@@ -47,6 +47,7 @@
new/datum/data/pda/app/messenger, new/datum/data/pda/app/messenger,
new/datum/data/pda/app/manifest, new/datum/data/pda/app/manifest,
new/datum/data/pda/app/atmos_scanner, new/datum/data/pda/app/atmos_scanner,
new/datum/data/pda/app/nerdle,
new/datum/data/pda/utility/scanmode/notes, new/datum/data/pda/utility/scanmode/notes,
new/datum/data/pda/utility/flashlight) new/datum/data/pda/utility/flashlight)
var/list/shortcut_cache = list() var/list/shortcut_cache = list()

2348
strings/nerdle_dict.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,82 @@
import { useBackend } from 'tgui/backend';
import { Box, Input, Section, Stack } from 'tgui-core/components';
type Data = {
guesses: number[][]; // Serialized guesses (NERDLE_YES, NERDLE_CLOSE, NERDLE_NO)
guesses_raw: string[]; // Raw guesses (letters)
max: number; // Maximum number of guesses
used_guesses: number; // Number of guesses used
target_word: string; // Target word for debugging (optional)
};
export const pda_nerdle = (props) => {
const { act, data } = useBackend<Data>();
const { guesses, guesses_raw, max, used_guesses, target_word } = data;
const gameOver = used_guesses >= max || guesses_raw.includes(target_word);
return (
<Box>
<Section title="Nerdle V0.8 - A Bingle Collaboration Product">
<Box>
Guess the 5-letter word! You have {max - used_guesses} attempts left.
</Box>
{!gameOver && (
<Box>
<Input
placeholder="Enter your guess"
onEnter={(value) => act('guess', { lastword: value })}
/>
</Box>
)}
{gameOver && (
<Box color="good" bold>
{guesses_raw.includes(target_word)
? 'You win!'
: `Nice try! Today's word was ${target_word}`}
</Box>
)}
</Section>
<Section title="Guesses">
<Stack vertical align="center">
{guesses.length > 0 ? (
guesses.map((guess, index) => (
<Box key={index}>
<Stack.Item align="center">
<Stack width="100%">
{guess.map((result, i) => (
<Box
key={i}
color={
result === 1
? 'good'
: result === 2
? 'average'
: 'bad'
}
textAlign="center"
bold
backgroundColor={
result === 1
? 'rgba(0, 255, 0, 0.2)'
: result === 2
? 'rgba(255, 255, 0, 0.2)'
: 'rgba(255, 0, 0, 0.2)'
}
>
{guesses_raw[index][i]}
</Box>
))}
</Stack>
</Stack.Item>
</Box>
))
) : (
<Box>No guesses yet!</Box>
)}
</Stack>
</Section>
</Box>
);
};

View File

@@ -466,6 +466,7 @@
#include "code\controllers\subsystems\media_tracks.dm" #include "code\controllers\subsystems\media_tracks.dm"
#include "code\controllers\subsystems\mobs.dm" #include "code\controllers\subsystems\mobs.dm"
#include "code\controllers\subsystems\motion_tracker.dm" #include "code\controllers\subsystems\motion_tracker.dm"
#include "code\controllers\subsystems\nerdle.dm"
#include "code\controllers\subsystems\nightshift.dm" #include "code\controllers\subsystems\nightshift.dm"
#include "code\controllers\subsystems\overlays_ch.dm" #include "code\controllers\subsystems\overlays_ch.dm"
#include "code\controllers\subsystems\overmap_renamer_vr.dm" #include "code\controllers\subsystems\overmap_renamer_vr.dm"
@@ -4085,6 +4086,7 @@
#include "code\modules\pda\core_apps.dm" #include "code\modules\pda\core_apps.dm"
#include "code\modules\pda\messenger.dm" #include "code\modules\pda\messenger.dm"
#include "code\modules\pda\messenger_plugins.dm" #include "code\modules\pda\messenger_plugins.dm"
#include "code\modules\pda\nerdle.dm"
#include "code\modules\pda\pda.dm" #include "code\modules\pda\pda.dm"
#include "code\modules\pda\pda_subtypes.dm" #include "code\modules\pda\pda_subtypes.dm"
#include "code\modules\pda\pda_tgui.dm" #include "code\modules\pda\pda_tgui.dm"