From a793607b11f3630dffb97f4430006557495564a0 Mon Sep 17 00:00:00 2001 From: kinther Date: Sat, 30 Aug 2025 19:26:06 -0700 Subject: [PATCH] Feel command for RP --- src/act.comm.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++ src/act.h | 1 + src/interpreter.c | 1 + 3 files changed, 95 insertions(+) diff --git a/src/act.comm.c b/src/act.comm.c index e662ae4..45ace62 100644 --- a/src/act.comm.c +++ b/src/act.comm.c @@ -21,6 +21,9 @@ #include "dg_scripts.h" #include "act.h" #include "modify.h" +#include +#include +#include /* for strncasecmp on POSIX */ static bool legal_communication(char * arg); @@ -37,6 +40,76 @@ static bool legal_communication(char * arg) return TRUE; } +static int is_boundary_char(char c) { + return c == '\0' || isspace((unsigned char)c) || ispunct((unsigned char)c); +} + +/* Convert first-person phrases to second-person for self-facing messages. */ +static void to_second_person_self(const char *in, char *out, size_t outlen) { + struct { const char *from; const char *to; } map[] = { + /* Longer patterns first to avoid partial matches */ + {"i'm", "you're"}, + {"i’ve", "you’ve"}, + {"i've", "you've"}, + {"i’d", "you’d"}, + {"i'd", "you'd"}, + {"i’ll", "you’ll"}, + {"i'll", "you'll"}, + {"myself","yourself"}, + {"mine", "yours"}, + {"my", "your"}, + {"me", "you"}, + {"i", "you"} + }; + const size_t nmap = sizeof(map)/sizeof(map[0]); + + size_t i = 0, o = 0; + out[0] = '\0'; + + while (in[i] && o + 1 < outlen) { + int replaced = 0; + + if (i == 0 || is_boundary_char(in[i - 1])) { + for (size_t k = 0; k < nmap; k++) { + size_t lf = strlen(map[k].from); + if (strncasecmp(in + i, map[k].from, lf) == 0 && is_boundary_char(in[i + lf])) { + /* write replacement */ + size_t lt = strlen(map[k].to); + if (o + lt < outlen) { + memcpy(out + o, map[k].to, lt); + o += lt; + i += lf; + replaced = 1; + } + break; + } + } + } + + if (!replaced) { + out[o++] = in[i++]; + } + } + + /* NUL-terminate */ + if (o >= outlen) o = outlen - 1; + out[o] = '\0'; + + /* Trim trailing spaces */ + while (o && isspace((unsigned char)out[o - 1])) out[--o] = '\0'; + + /* Ensure trailing sentence punctuation */ + if (o) { + char last = out[o - 1]; + if (!(last == '.' || last == '!' || last == '?')) { + if (o + 1 < outlen) { + out[o++] = '.'; + out[o] = '\0'; + } + } + } +} + ACMD(do_say) { skip_spaces(&argument); @@ -105,6 +178,26 @@ ACMD(do_ooc) speech_wtrigger(ch, argument); } +ACMD(do_feel) +{ + char raw[MAX_INPUT_LENGTH]; + char rendered[MAX_INPUT_LENGTH * 2]; + + skip_spaces(&argument); + + if (!*argument) { + send_to_char(ch, "Feel what?\r\n"); + return; + } + + /* Keep user casing; just copy and convert perspective */ + strlcpy(raw, argument, sizeof(raw)); + to_second_person_self(raw, rendered, sizeof(rendered)); + + /* Self-only echo */ + send_to_char(ch, "You feel %s\r\n", rendered); +} + static void perform_tell(struct char_data *ch, struct char_data *vict, char *arg) { char buf[MAX_STRING_LENGTH], *msg; diff --git a/src/act.h b/src/act.h index fc32587..affb474 100644 --- a/src/act.h +++ b/src/act.h @@ -38,6 +38,7 @@ ACMD(do_spec_comm); /* functions without subcommands */ ACMD(do_say); ACMD(do_ooc); +ACMD(do_feel); ACMD(do_page); ACMD(do_reply); ACMD(do_tell); diff --git a/src/interpreter.c b/src/interpreter.c index 2ebd735..0798bca 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -142,6 +142,7 @@ cpp_extern const struct command_info cmd_info[] = { { "examine" , "exa" , POS_SITTING , do_examine , 0, 0 }, { "export" , "export" , POS_DEAD , do_export_zone, LVL_IMPL, 0 }, + { "feel" , "fee" , POS_SLEEPING, do_feel , 0, 0 }, { "force" , "force" , POS_SLEEPING, do_force , LVL_GOD, 0 }, { "fill" , "fil" , POS_STANDING, do_pour , 0, SCMD_FILL }, { "file" , "file" , POS_SLEEPING, do_file , LVL_GOD, 0 },