Files
nethack/src/twitch.c

245 lines
6.4 KiB
C

#include "hack.h"
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
static int twitch_in_fd = -1;
static int twitch_out_fd = -1;
static char twitch_buf[1024];
static int twitch_buf_size;
static char infile[SAVESIZE + 3];
static char outfile[SAVESIZE + 4];
static time_t last_check = 0;
staticfn void process_twitch_cmd(char*);
staticfn boolean has_out_file(void);
staticfn void failed_effect(char*);
staticfn void successful_effect(char*);
staticfn void grant_object(char*);
void open_twitch(void) {
snprintf(infile, SAVESIZE + 3, "%s.in", gs.SAVEF);
snprintf(outfile, SAVESIZE + 4, "%s.out", gs.SAVEF);
twitch_in_fd = open(infile, O_RDONLY | O_NONBLOCK);
if (twitch_in_fd >= 0) {
twitch_out_fd = open(outfile, O_WRONLY | O_NONBLOCK);
}
}
void check_twitch(void) {
if (twitch_in_fd < 0) {
return;
}
time_t now = getnow();
if (timet_delta(now, last_check) < 5) {
return;
}
last_check = now;
int size;
size = read(twitch_in_fd, &twitch_buf[twitch_buf_size], 1024 - twitch_buf_size);
if (size < 0) {
if (errno == EAGAIN) {
return;
}
return;
}
if (size > 0) {
twitch_buf_size += size;
int i;
boolean done;
done = FALSE;
while (!done) {
done = TRUE;
for (i = 0; i < twitch_buf_size; i++) {
if (twitch_buf[i] == '\r' || twitch_buf[i] == '\n') {
twitch_buf[i] = '\0';
if (i > 0) {
process_twitch_cmd(twitch_buf);
}
int j;
for (j = 0; j + i + 1 < twitch_buf_size; j++) {
twitch_buf[j] = twitch_buf[j + i + 1];
}
twitch_buf_size -= i + 1;
done = FALSE;
break;
}
}
}
}
}
staticfn void process_twitch_cmd(char *cmd) {
char *id = strtok(cmd, " ");
char *effect = strtok(NULL, " ");
if (effect == NULL) {
return;
}
if (!strcmp(effect, "create_monster")) {
create_critters(1, NULL, FALSE);
successful_effect(id);
} else if (!strcmp(effect, "identify")) {
identify_pack(1, TRUE);
successful_effect(id);
} else if (!strcmp(effect, "teleport")) {
/* Temporarily stun the player, if they are not already, to prevent teleport control */
boolean removestun = FALSE;
if (!Stunned) {
removestun = TRUE;
make_stunned(1L, FALSE);
}
tele();
if (removestun) {
make_stunned(0L, FALSE);
}
successful_effect(id);
} else if (!strcmp(effect, "level_teleport")) {
if (u.uhave.amulet || In_endgame(&u.uz) || In_sokoban(&u.uz)) {
failed_effect(id);
} else {
/* Temporarily stun the player, if they are not already, to prevent teleport control */
boolean removestun = FALSE;
if (!Stunned) {
removestun = TRUE;
make_stunned(1L, FALSE);
}
level_tele();
if (removestun) {
make_stunned(0L, FALSE);
}
successful_effect(id);
}
} else if (!strcmp(effect, "healing")) {
You_feel("better.");
healup(8 + d(4, 4), 0, FALSE, FALSE);
successful_effect(id);
} else if (!strcmp(effect, "extra_healing")) {
You_feel("much better.");
healup(16 + d(4, 8), 0, FALSE, FALSE);
successful_effect(id);
} else if (!strcmp(effect, "full_healing")) {
You_feel("completely healed.");
healup(400, 0, FALSE, FALSE);
successful_effect(id);
} else if (!strcmp(effect, "curse_inventory")) {
if (!Blind) {
You("notice a %s glow surrounding you.", hcolor(NH_BLACK));
}
rndcurse();
successful_effect(id);
} else if (!strcmp(effect, "reduce_luck")) {
You_feel("unlucky.");
change_luck(-1);
successful_effect(id);
} else if (!strcmp(effect, "fix_trouble")) {
int trouble = in_trouble();
if (trouble != 0) {
fix_worst_trouble(trouble);
successful_effect(id);
} else {
failed_effect(id);
}
} else if (!strcmp(effect, "darkness")) {
litroom(FALSE, NULL);
successful_effect(id);
} else if (!strcmp(effect, "confuse")) {
if (!Confusion) {
if (Hallucination) {
pline("What a trippy feeling!");
} else {
pline("Huh, What? Where am I?");
}
}
make_confused(itimeout_incr(HConfusion, rn1(7, 16)), FALSE);
successful_effect(id);
} else if (!strcmp(effect, "hallucinate")) {
(void) make_hallucinated(itimeout_incr(HHallucination, d(10, 12)), TRUE, 0L);
successful_effect(id);
} else if (!strcmp(effect, "stun")) {
make_stunned(itimeout_incr(HStun, rn1(10, 10)), TRUE);
successful_effect(id);
} else if (!strcmp(effect, "blind")) {
make_blinded(itimeout_incr(BlindedTimeout, d(10, 12)), (boolean) !Blind);
successful_effect(id);
} else if (!strcmp(effect, "sleep")) {
if (Sleep_resistance) {
You("yawn.");
failed_effect(id);
} else {
You("suddenly fall asleep!");
fall_asleep(-rn1(10, 13), TRUE);
successful_effect(id);
}
} else if (!strcmp(effect, "grant_object")) {
char *object = strtok(NULL, "\n");
grant_object(object);
successful_effect(id);
}
}
staticfn void grant_object(char *objname) {
struct obj *otmp;
otmp = readobjnam(objname, NULL);
if (!otmp) {
otmp = readobjnam((char *) 0, (struct obj *) 0);
} else if (otmp == &hands_obj) {
return;
}
if (otmp->oartifact) {
pline("For a moment, you feel %s in your %s, but it disappears!",
something, makeplural(body_part(HAND)));
return;
}
const char *verb = ((Is_airlevel(&u.uz) || u.uinwater) ? "slip" : "drop"),
*oops_msg = (u.uswallow
? "Oops! %s out of your reach!"
: (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
|| levl[u.ux][u.uy].typ < IRONBARS
|| levl[u.ux][u.uy].typ >= ICE)
? "Oops! %s away from you!"
: "Oops! %s to the floor!");
(void) hold_another_object(otmp, oops_msg, The(aobjnam(otmp, verb)), (const char *) 0);
}
staticfn boolean has_out_file(void) {
if (twitch_out_fd >= 0) {
return TRUE;
}
twitch_out_fd = open(outfile, O_WRONLY | O_NONBLOCK);
return twitch_out_fd >= 0;
}
staticfn void failed_effect(char *id) {
if (has_out_file()) {
write(twitch_out_fd, "failure ", 8);
write(twitch_out_fd, id, strlen(id));
write(twitch_out_fd, "\n", 1);
}
}
staticfn void successful_effect(char *id) {
if (has_out_file()) {
write(twitch_out_fd, "success ", 8);
write(twitch_out_fd, id, strlen(id));
write(twitch_out_fd, "\n", 1);
}
}