aboutsummaryrefslogtreecommitdiffstats
path: root/FICS/variable.c
diff options
context:
space:
mode:
Diffstat (limited to 'FICS/variable.c')
-rw-r--r--FICS/variable.c1066
1 files changed, 1066 insertions, 0 deletions
diff --git a/FICS/variable.c b/FICS/variable.c
new file mode 100644
index 0000000..e004eca
--- /dev/null
+++ b/FICS/variable.c
@@ -0,0 +1,1066 @@
+/* variable.c
+ *
+ */
+
+/*
+ fics - An internet chess server.
+ Copyright (C) 1993 Richard V. Nash
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*/
+
+/* Revision history:
+ name email yy/mm/dd Change
+ Richard Nash 93/10/22 Created
+ loon 95/03/17 Added figure_boolean()
+ hersco 95/04/10 Replaced figure_boolean() with
+ set_boolean_var()
+ DAV 95/19/11 Moved variable command to here
+ Added jprivate
+ Markus Uhlin 23/12/27 Fixed the includes
+ Markus Uhlin 24/04/01 Reformatted all functions
+ Markus Uhlin 24/07/08 Added var 'interface'
+ Markus Uhlin 24/11/19 Improved Language()
+ Markus Uhlin 24/11/24 Added var 'seek'.
+*/
+
+#include "stdinclude.h"
+#include "common.h"
+
+#include <err.h>
+#include <stdbool.h>
+
+#include "board.h"
+#include "command.h"
+#include "comproc.h"
+#include "formula.h" /* SetValidFormula() */
+#include "playerdb.h"
+#include "rmalloc.h"
+#include "talkproc.h"
+#include "utils.h"
+#include "variable.h"
+
+#if __linux__
+#include <bsd/string.h>
+#endif
+
+PRIVATE int
+set_boolean_var(int *var, char *val)
+{
+ int v = -1;
+
+ if (val == NULL)
+ return (*var = !*var);
+
+ if (sscanf(val, "%d", &v) != 1) {
+ stolower(val);
+
+ if (!strcmp(val, "off"))
+ v = 0;
+ if (!strcmp(val, "false"))
+ v = 0;
+ if (!strcmp(val, "on"))
+ v = 1;
+ if (!strcmp(val, "true"))
+ v = 1;
+ }
+
+ if (v == 0 || v == 1)
+ return (*var = v);
+ else
+ return (-1);
+}
+
+PRIVATE int
+set_open(int p, char *var, char *val)
+{
+ int v = set_boolean_var(&parray[p].open, val);
+
+ if (v < 0) {
+ return VAR_BADVAL;
+ } else if (v > 0) {
+ pprintf(p, "You are now open to receive match requests.\n");
+ } else {
+ player_decline_offers(p, -1, PEND_MATCH);
+ player_withdraw_offers(p, -1, PEND_MATCH);
+ pprintf(p, "You are no longer receiving match requests.\n");
+ }
+
+ return VAR_OK;
+}
+
+PRIVATE int
+set_sopen(int p, char *var, char *val)
+{
+ int v = set_boolean_var(&parray[p].sopen, val);
+
+ if (v < 0)
+ return VAR_BADVAL;
+
+ pprintf(p, "sopen set to %d.\n", parray[p].sopen);
+
+ if (v > 0)
+ pprintf(p, "You are now open to receive simul requests.\n");
+ else
+ pprintf(p, "You are no longer receiving simul requests.\n");
+
+ player_decline_offers(p, -1, PEND_SIMUL);
+ return VAR_OK;
+}
+
+PRIVATE int
+set_ropen(int p, char *var, char *val)
+{
+ if (set_boolean_var(&parray[p].ropen, val) < 0)
+ return VAR_BADVAL;
+ pprintf(p, "ropen set to %d.\n", parray[p].ropen);
+ return VAR_OK;
+}
+
+/*
+ * If your 'seek' variable is non-zero (whether a number, 'true' or
+ * 'on'), you will be informed of "seek" ads when they are made. zero
+ * ('false' or 'off'), you will not receive these announcements. For
+ * example, to receive ads, type "set seek 1". To stop receiving ads,
+ * type "set seek 0".
+ */
+PRIVATE int
+set_seek(int p, char *var, char *val)
+{
+ int v = set_boolean_var(&parray[p].seek, val);
+
+ if (v < 0)
+ return VAR_BADVAL;
+
+ pprintf(p, "seek set to %d.\n", parray[p].seek);
+
+ if (v > 0) {
+ pprintf(p, "You will be informed of seek ads when they are "
+ "made.\n");
+ } else {
+ pprintf(p, "You are no longer receiving seek ads.\n");
+ }
+
+ return VAR_OK;
+}
+
+PRIVATE int
+set_rated(int p, char *var, char *val)
+{
+ if (!parray[p].registered) {
+ pprintf(p, "You cannot change your rated status.\n");
+ return VAR_OK;
+ }
+ if (set_boolean_var(&parray[p].rated, val) < 0)
+ return VAR_BADVAL;
+ pprintf(p, "rated set to %d.\n", parray[p].rated);
+ return VAR_OK;
+}
+
+PRIVATE int
+set_shout(int p, char *var, char *val)
+{
+ if (set_boolean_var(&parray[p].i_shout, val) < 0)
+ return VAR_BADVAL;
+ if (parray[p].i_shout)
+ pprintf(p, "You will now hear shouts.\n");
+ else
+ pprintf(p, "You will not hear shouts.\n");
+ return VAR_OK;
+}
+
+PRIVATE int
+set_cshout(int p, char *var, char *val)
+{
+ if (set_boolean_var(&parray[p].i_cshout, val) < 0)
+ return VAR_BADVAL;
+ if (parray[p].i_cshout)
+ pprintf(p, "You will now hear cshouts.\n");
+ else
+ pprintf(p, "You will not hear cshouts.\n");
+ return VAR_OK;
+}
+
+PRIVATE int
+set_kibitz(int p, char *var, char *val)
+{
+ if (set_boolean_var(&parray[p].i_kibitz, val) < 0)
+ return VAR_BADVAL;
+ if (parray[p].i_kibitz)
+ pprintf(p, "You will now hear kibitzes.\n");
+ else
+ pprintf(p, "You will not hear kibitzes.\n");
+ return VAR_OK;
+}
+
+PRIVATE int
+set_kiblevel(int p, char *var, char *val)
+{
+ int v = -1;
+
+ if (!val)
+ return VAR_BADVAL;
+ if (sscanf(val, "%d", &v) != 1)
+ return VAR_BADVAL;
+ if (v < 0 || v > 9999)
+ return VAR_BADVAL;
+
+ parray[p].kiblevel = v;
+ pprintf(p, "Kibitz level now set to: %d.\n", v);
+ return VAR_OK;
+}
+
+PRIVATE int
+set_tell(int p, char *var, char *val)
+{
+ if (set_boolean_var(&parray[p].i_tell, val) < 0)
+ return VAR_BADVAL;
+ if (parray[p].i_tell)
+ pprintf(p, "You will now hear tells.\n");
+ else
+ pprintf(p, "You will not hear tells.\n");
+ return VAR_OK;
+}
+
+PRIVATE int
+set_notifiedby(int p, char *var, char *val)
+{
+ if (set_boolean_var(&parray[p].notifiedby, val) < 0)
+ return VAR_BADVAL;
+ if (parray[p].notifiedby) {
+ pprintf(p, "You will now hear if people notify you, "
+ "but you don't notify them.\n");
+ } else {
+ pprintf(p, "You will not hear if people notify you, "
+ "but you don't notify them.\n");
+ }
+ return VAR_OK;
+}
+
+PRIVATE int
+set_pinform(int p, char *var, char *val)
+{
+ if (set_boolean_var(&parray[p].i_login, val) < 0)
+ return VAR_BADVAL;
+ if (parray[p].i_login)
+ pprintf(p, "You will now hear logins/logouts.\n");
+ else
+ pprintf(p, "You will not hear logins/logouts.\n");
+ return VAR_OK;
+}
+
+PRIVATE int
+set_ginform(int p, char *var, char *val)
+{
+ if (set_boolean_var(&parray[p].i_game, val) < 0)
+ return VAR_BADVAL;
+ if (parray[p].i_game)
+ pprintf(p, "You will now hear game results.\n");
+ else
+ pprintf(p, "You will not hear game results.\n");
+ return VAR_OK;
+}
+
+PRIVATE int
+set_private(int p, char *var, char *val)
+{
+ if (set_boolean_var(&parray[p].private, val) < 0)
+ return VAR_BADVAL;
+ if (parray[p].private)
+ pprintf(p, "Your games will be private.\n");
+ else
+ pprintf(p, "Your games may not be private.\n");
+ return VAR_OK;
+}
+
+PRIVATE int
+set_jprivate(int p, char *var, char *val)
+{
+ if (!parray[p].registered) {
+ pprintf(p, "Unregistered players may not keep a journal.\n");
+ return VAR_OK;
+ }
+ if (set_boolean_var(&parray[p].jprivate, val) < 0)
+ return VAR_BADVAL;
+ if (parray[p].jprivate)
+ pprintf(p, "Your journal will be private.\n");
+ else
+ pprintf(p, "Your journal will not be private.\n");
+ return VAR_OK;
+}
+
+PRIVATE int
+set_automail(int p, char *var, char *val)
+{
+ if (set_boolean_var(&parray[p].automail, val) < 0)
+ return VAR_BADVAL;
+ if (parray[p].automail)
+ pprintf(p, "Your games will be mailed to you.\n");
+ else
+ pprintf(p, "Your games will not be mailed to you.\n");
+ return VAR_OK;
+}
+
+PRIVATE int
+set_mailmess(int p, char *var, char *val)
+{
+ if (!parray[p].registered) {
+ pprintf(p, "Unregistered players may not receive messages.\n");
+ return VAR_OK;
+ }
+ if (set_boolean_var(&parray[p].i_mailmess, val) < 0)
+ return VAR_BADVAL;
+ if (parray[p].i_mailmess)
+ pprintf(p, "Your messages will be mailed to you.\n");
+ else
+ pprintf(p, "Your messages will not be mailed to you.\n");
+ return VAR_OK;
+}
+
+PRIVATE int
+set_pgn(int p, char *var, char *val)
+{
+ if (set_boolean_var(&parray[p].pgn, val) < 0)
+ return VAR_BADVAL;
+ if (parray[p].pgn)
+ pprintf(p, "Games will now be mailed to you in PGN.\n");
+ else
+ pprintf(p, "Games will now be mailed to you in FICS format.\n");
+ return VAR_OK;
+}
+
+PRIVATE int
+set_bell(int p, char *var, char *val)
+{
+ if (set_boolean_var(&parray[p].bell, val) < 0)
+ return VAR_BADVAL;
+ if (parray[p].bell)
+ pprintf(p, "Bell on.\n");
+ else
+ pprintf(p, "Bell off.\n");
+ return VAR_OK;
+}
+
+PRIVATE int
+set_highlight(int p, char *var, char *val)
+{
+ int v = -1;
+
+ if (!val)
+ return VAR_BADVAL;
+ if (sscanf(val, "%d", &v) != 1)
+ return VAR_BADVAL;
+ if (v < 0 || v > 15)
+ return VAR_BADVAL;
+
+ if ((parray[p].highlight = v)) {
+ pprintf(p, "Highlight is now style ");
+ pprintf_highlight(p, "%d", v);
+ pprintf(p, ".\n");
+ } else
+ pprintf(p, "Highlight is off.\n");
+ return VAR_OK;
+}
+
+PRIVATE int
+set_style(int p, char *var, char *val)
+{
+ int v = -1;
+
+ if (!val)
+ return VAR_BADVAL;
+ if (sscanf(val, "%d", &v) != 1)
+ return VAR_BADVAL;
+ if (v < 1 || v > MAX_STYLES)
+ return VAR_BADVAL;
+
+ parray[p].style = (v - 1);
+ pprintf(p, "Style %d set.\n", v);
+ return VAR_OK;
+}
+
+PRIVATE int
+set_flip(int p, char *var, char *val)
+{
+ if (set_boolean_var(&parray[p].flip, val) < 0)
+ return VAR_BADVAL;
+ if (parray[p].flip)
+ pprintf(p, "Flip on.\n");
+ else
+ pprintf(p, "Flip off.\n");
+ return VAR_OK;
+}
+
+PRIVATE int
+set_time(int p, char *var, char *val)
+{
+ int v = -1;
+
+ if (!val)
+ return VAR_BADVAL;
+ if (sscanf(val, "%d", &v) != 1)
+ return VAR_BADVAL;
+ if (v < 0 || v > 240)
+ return VAR_BADVAL;
+
+ parray[p].d_time = v;
+ pprintf(p, "Default time set to %d.\n", v);
+ return VAR_OK;
+}
+
+PRIVATE int
+set_inc(int p, char *var, char *val)
+{
+ int v = -1;
+
+ if (!val)
+ return VAR_BADVAL;
+ if (sscanf(val, "%d", &v) != 1)
+ return VAR_BADVAL;
+ if (v < 0 || v > 300)
+ return VAR_BADVAL;
+
+ parray[p].d_inc = v;
+ pprintf(p, "Default increment set to %d.\n", v);
+ return VAR_OK;
+}
+
+PRIVATE int
+set_interface(int p, char *var, char *val)
+{
+ bool truncated = false;
+ char *cp;
+ size_t size;
+
+ if (val == NULL || strcmp(val, "") == 0)
+ return VAR_BADVAL;
+ else if (!printablestring(val)) {
+ pprintf(p, "%s: val not printable\n", __func__);
+ return VAR_BADVAL;
+ }
+
+ cp = &(parray[p].interface[0]);
+ size = ARRAY_SIZE(parray[p].interface);
+
+ if (strlcpy(cp, val, size) >= size)
+ truncated = true;
+
+ pprintf(p, "Interface set to %s.\n", cp);
+
+ if (truncated)
+ pprintf(p, "Interface was truncated!\n");
+ return VAR_OK;
+}
+
+PRIVATE int
+set_height(int p, char *var, char *val)
+{
+ int v = -1;
+
+ if (!val)
+ return VAR_BADVAL;
+ if (sscanf(val, "%d", &v) != 1)
+ return VAR_BADVAL;
+ if (v < 5 || v > 240)
+ return VAR_BADVAL;
+
+ parray[p].d_height = v;
+ pprintf(p, "Height set to %d.\n", v);
+ return VAR_OK;
+}
+
+PRIVATE int
+set_width(int p, char *var, char *val)
+{
+ int v = -1;
+
+ if (!val)
+ return VAR_BADVAL;
+ if (sscanf(val, "%d", &v) != 1)
+ return VAR_BADVAL;
+ if (v < 32 || v > 240)
+ return VAR_BADVAL;
+
+ parray[p].d_width = v;
+ pprintf(p, "Width set to %d.\n", v);
+ return VAR_OK;
+}
+
+PUBLIC const char *
+Language(unsigned int i)
+{
+ static char *Lang[NUM_LANGS] = {
+ "English",
+ "Spanish",
+ "French",
+ "Danish"
+ };
+
+ _Static_assert(ARRAY_SIZE(Lang) == 4, "Unexpected array size");
+
+ if (i >= ARRAY_SIZE(Lang)) {
+ warnx("%s: invalid arg %u (too large)", __func__, i);
+ return Lang[0];
+ }
+ return Lang[i];
+}
+
+PRIVATE int
+set_language(int p, char *var, char *val)
+{
+ int len, gotIt = -1;
+
+ if (!val)
+ return VAR_BADVAL;
+
+ len = strlen(val);
+
+ for (int i = 0; i < NUM_LANGS; i++) {
+ if (strncasecmp(val, Language(i), len))
+ continue;
+ if (gotIt >= 0)
+ return VAR_BADVAL;
+ else
+ gotIt = i;
+ }
+
+ if (gotIt < 0)
+ return VAR_BADVAL;
+
+ parray[p].language = gotIt;
+
+ pprintf(p, "Language set to %s.\n", Language(gotIt));
+ return VAR_OK;
+}
+
+PRIVATE int
+set_promote(int p, char *var, char *val)
+{
+ if (!val)
+ return VAR_BADVAL;
+
+ stolower(val);
+
+ switch (val[0]) {
+ case 'q':
+ parray[p].promote = QUEEN;
+ pprintf(p, "Promotion piece set to QUEEN.\n");
+ break;
+ case 'r':
+ parray[p].promote = ROOK;
+ pprintf(p, "Promotion piece set to ROOK.\n");
+ break;
+ case 'b':
+ parray[p].promote = BISHOP;
+ pprintf(p, "Promotion piece set to BISHOP.\n");
+ break;
+ case 'n':
+ case 'k':
+ parray[p].promote = KNIGHT;
+ pprintf(p, "Promotion piece set to KNIGHT.\n");
+ break;
+ default:
+ return VAR_BADVAL;
+ }
+
+ return VAR_OK;
+}
+
+PRIVATE int
+set_prompt(int p, char *var, char *val)
+{
+ if (!val) {
+ if (parray[p].prompt && parray[p].prompt != def_prompt)
+ rfree(parray[p].prompt);
+ parray[p].prompt = def_prompt;
+ return VAR_OK;
+ }
+
+ if (!printablestring(val))
+ return VAR_BADVAL;
+
+ if (parray[p].prompt != def_prompt)
+ rfree(parray[p].prompt);
+
+ const size_t size = strlen(val) + 2;
+ parray[p].prompt = rmalloc(size);
+
+ strlcpy(parray[p].prompt, val, size);
+ strlcat(parray[p].prompt, " ", size);
+
+ return VAR_OK;
+}
+
+PRIVATE int
+RePartner(int p, int new)
+{
+ int pOld;
+
+ if (p < 0)
+ return -1;
+
+ pOld = parray[p].partner;
+
+ if (parray[pOld].partner == p) {
+ if (new >= 0) {
+ pprintf_prompt(pOld, "Your partner has just chosen "
+ "a new partner.\n");
+ } else {
+ pprintf_prompt(pOld, "Your partner has just unset "
+ "his/her partner.\n");
+ }
+
+ player_withdraw_offers(pOld, -1, PEND_BUGHOUSE);
+ player_decline_offers(pOld, -1, PEND_BUGHOUSE);
+
+ player_withdraw_offers(p, -1, PEND_BUGHOUSE);
+ player_decline_offers(p, -1, PEND_BUGHOUSE);
+ }
+
+ player_withdraw_offers(p, -1, PEND_PARTNER);
+ player_decline_offers(p, -1, PEND_PARTNER);
+
+ parray[pOld].partner = -1;
+ parray[p].partner = new;
+
+ return new;
+}
+
+PUBLIC int
+com_partner(int p, param_list param)
+{
+ int pNew;
+
+ if (param[0].type == TYPE_NULL) {
+ RePartner(p, -1);
+ return COM_OK;
+ }
+
+ // OK, we're trying to set a new partner.
+ pNew = player_find_part_login(param[0].val.word);
+
+ if (pNew < 0 ||
+ parray[pNew].status == PLAYER_PASSWORD ||
+ parray[pNew].status == PLAYER_LOGIN) {
+ pprintf(p, "No user named \"%s\" is logged in.\n",
+ param[0].val.word);
+ return COM_OK;
+ }
+
+ if (pNew == p) {
+ pprintf(p, "You can't be your own bughouse partner.\n");
+ return COM_OK;
+ }
+
+ /*
+ * Now we know a legit partner has been chosen. Is an offer
+ * pending?
+ */
+ if (player_find_pendfrom(p, pNew, PEND_PARTNER) >= 0) {
+ pprintf(p, "You agree to be %s's partner.\n",
+ parray[pNew].name);
+ pprintf_prompt(pNew, "%s agrees to be your partner.\n",
+ parray[p].name);
+ player_remove_request(pNew, p, PEND_PARTNER);
+
+ // Make the switch.
+ RePartner(p, pNew);
+ RePartner(pNew, p);
+
+ return COM_OK;
+ }
+
+ // This is just an offer. Make sure a new partner is needed.
+ if (parray[pNew].partner >= 0) {
+ pprintf(p, "%s already has a partner.\n", parray[pNew].name);
+ return COM_OK;
+ }
+
+ pprintf(pNew, "\n");
+ pprintf_highlight(pNew, "%s", parray[p].name);
+ pprintf(pNew, " offers to be your bughouse partner; ");
+ pprintf_prompt(pNew, "type \"partner %s\" to accept.\n",
+ parray[p].name);
+ pprintf(p, "Making a partnership offer to %s.\n", parray[pNew].name);
+
+ player_add_request(p, pNew, PEND_PARTNER, 0);
+ return COM_OK;
+}
+
+PRIVATE int
+set_partner(int p, char *var, char *val)
+{
+ if (!val)
+ pprintf(p, "Command is obsolete; type \"partner\" to clear "
+ "your partner\n");
+ else
+ pprintf(p, "Command is obsolete; type \"partner %s\" to "
+ "change your partner\n", val);
+ return VAR_OK;
+}
+
+PRIVATE int
+set_busy(int p, char *var, char *val)
+{
+ if (!val) {
+ parray[p].busy[0] = '\0';
+ pprintf(p, "Your \"busy\" string was cleared.\n");
+ return VAR_OK;
+ }
+
+ if (val && !printablestring(val))
+ return VAR_BADVAL;
+
+ if (strlen(val) > 50) {
+ pprintf(p, "That string is too long.\n");
+ return VAR_BADVAL;
+ }
+
+ strlcpy(parray[p].busy, val, sizeof(parray[p].busy));
+
+ pprintf(p, "Your \"busy\" string was set to \" %s\"\n", parray[p].busy);
+ return VAR_OK;
+}
+
+PRIVATE int
+set_plan(int p, char *var, char *val)
+{
+ int i;
+ int which;
+
+ if (val && !printablestring(val))
+ return VAR_BADVAL;
+ if ((which = atoi(var)) > MAX_PLAN)
+ return VAR_BADVAL;
+ if (which > parray[p].num_plan)
+ which = parray[p].num_plan + 1;
+
+ if (which == 0) { // shove from top
+ if (parray[p].num_plan >= MAX_PLAN) // free the bottom string
+ strfree(parray[p].planLines[parray[p].num_plan - 1]);
+
+ if (parray[p].num_plan) {
+ i = (parray[p].num_plan >= MAX_PLAN ? MAX_PLAN - 1 :
+ parray[p].num_plan);
+ for (; i > 0; i--) {
+ parray[p].planLines[i] =
+ parray[p].planLines[i - 1];
+ }
+ }
+
+ if (parray[p].num_plan < MAX_PLAN)
+ parray[p].num_plan++;
+
+ parray[p].planLines[0] = (val == NULL ? NULL : xstrdup(val));
+
+ pprintf(p, "\nPlan variable %d changed to '%s'.\n", (which + 1),
+ parray[p].planLines[which]);
+ pprintf(p, "All other variables moved down.\n");
+ return VAR_OK;
+ }
+
+ if (which > parray[p].num_plan) { // new line at bottom
+ if (parray[p].num_plan >= MAX_PLAN) { // shove the old lines up
+ if (parray[p].planLines[0] != NULL)
+ rfree(parray[p].planLines[0]);
+ for (i = 0; i < parray[p].num_plan; i++) {
+ parray[p].planLines[i] =
+ parray[p].planLines[i + 1];
+ }
+ } else {
+ parray[p].num_plan++;
+ }
+
+ parray[p].planLines[which - 1] = (val == NULL ? NULL :
+ xstrdup(val));
+ pprintf(p, "\nPlan variable %d changed to '%s'.\n", which,
+ parray[p].planLines[which - 1]);
+ return VAR_OK;
+ }
+
+ which--;
+
+ if (parray[p].planLines[which] != NULL)
+ rfree(parray[p].planLines[which]);
+
+ if (val != NULL) {
+ parray[p].planLines[which] = xstrdup(val);
+ pprintf(p, "\nPlan variable %d changed to '%s'.\n",
+ (which + 1),
+ parray[p].planLines[which]);
+ } else {
+ parray[p].planLines[which] = NULL;
+
+ if (which == (parray[p].num_plan - 1)) { // clear nulls
+ // from bottom
+ while (parray[p].num_plan > 0 &&
+ parray[p].planLines[parray[p].num_plan - 1] ==
+ NULL) {
+ parray[p].num_plan--;
+ pprintf(p, "\nPlan variable %d cleared.\n",
+ (which + 1));
+ }
+ } else if (which == 0) { // clear nulls from top
+ while (which < parray[p].num_plan &&
+ parray[p].planLines[which] == NULL)
+ which++;
+
+ if (which != parray[p].num_plan) {
+ for (i = which; i < parray[p].num_plan; i++) {
+ parray[p].planLines[i - which] =
+ parray[p].planLines[i];
+ }
+ }
+
+ parray[p].num_plan -= which;
+ }
+ }
+
+ return VAR_OK;
+}
+
+PRIVATE int
+set_formula(int p, char *var, char *val)
+{
+ int which;
+ player *me = &parray[p];
+
+#ifdef NO_FORMULAS
+ pprintf(p, "Sorry -- not available because of a bug\n");
+ return COM_OK;
+#else
+ if (isdigit(var[1]))
+ which = var[1] - '1';
+ else
+ which = MAX_FORMULA;
+
+ if (val != NULL) {
+ val = eatwhite(val);
+
+ if (val[0] == '\0')
+ val = NULL;
+ }
+
+ if (!SetValidFormula(p, which, val))
+ return VAR_BADVAL;
+
+ if (which < MAX_FORMULA) {
+ if (val != NULL) {
+ while (me->num_formula < which) {
+ me->formulaLines[me->num_formula] = NULL;
+ (me->num_formula)++;
+ }
+
+ if (me->num_formula <= which)
+ me->num_formula = (which + 1);
+
+ pprintf(p, "Formula variable f%d set to %s.\n",
+ (which + 1),
+ me->formulaLines[which]);
+ return VAR_OK;
+ }
+
+ pprintf(p, "Formula variable f%d unset.\n", (which + 1));
+
+ if (which + 1 >= me->num_formula) {
+ while (which >= 0 && me->formulaLines[which] == NULL)
+ which--;
+ me->num_formula = (which + 1);
+ }
+ } else {
+ if (me->formula != NULL)
+ pprintf(p, "Formula set to %s.\n", me->formula);
+ else
+ pprintf(p, "Formula unset.\n");
+ }
+
+ return VAR_OK;
+#endif
+}
+
+PUBLIC var_list variables[] = {
+ {"automail", set_automail},
+ {"bell", set_bell},
+ {"busy", set_busy},
+ {"cshout", set_cshout},
+ {"flip", set_flip},
+ {"ginform", set_ginform},
+ {"height", set_height},
+ {"highlight", set_highlight},
+ {"i_game", set_ginform},
+ {"i_login", set_pinform},
+ {"inc", set_inc},
+ {"interface", set_interface},
+ {"jprivate", set_jprivate},
+ {"kibitz", set_kibitz},
+ {"kiblevel", set_kiblevel},
+ {"language", set_language},
+ {"mailmess", set_mailmess},
+ {"notifiedby", set_notifiedby},
+ {"open", set_open},
+ {"partner", set_partner},
+ {"pgn", set_pgn},
+ {"pinform", set_pinform},
+ {"private", set_private},
+ {"promote", set_promote},
+ {"prompt", set_prompt},
+ {"rated", set_rated},
+ {"ropen", set_ropen},
+ {"seek", set_seek},
+ {"shout", set_shout},
+ {"simopen", set_sopen},
+ {"style", set_style},
+ {"tell", set_tell},
+ {"time", set_time},
+ {"width", set_width},
+ {"0", set_plan},
+ {"1", set_plan},
+ {"2", set_plan},
+ {"3", set_plan},
+ {"4", set_plan},
+ {"5", set_plan},
+ {"6", set_plan},
+ {"7", set_plan},
+ {"8", set_plan},
+ {"9", set_plan},
+ {"10", set_plan},
+ {"f1", set_formula},
+ {"f2", set_formula},
+ {"f3", set_formula},
+ {"f4", set_formula},
+ {"f5", set_formula},
+ {"f6", set_formula},
+ {"f7", set_formula},
+ {"f8", set_formula},
+ {"f9", set_formula},
+ {"formula", set_formula},
+ {NULL, NULL}
+};
+
+PRIVATE int
+set_find(char *var)
+{
+ int gotIt = -1;
+ int i = 0;
+ size_t len = strlen(var);
+
+ while (variables[i].name) {
+ if (!strncmp(variables[i].name, var, len)) {
+ if (len == strlen(variables[i].name))
+ return i;
+ else if (gotIt >= 0)
+ return -VAR_AMBIGUOUS;
+
+ gotIt = i;
+ }
+
+ i++;
+ }
+
+ if (gotIt >= 0)
+ return gotIt;
+ return -VAR_NOSUCH;
+}
+
+PUBLIC int
+var_set(int p, char *var, char *val, int *wh)
+{
+ int which;
+
+ if (!var)
+ return VAR_NOSUCH;
+ if ((which = set_find(var)) < 0)
+ return -which;
+
+ *wh = which;
+
+ return variables[which].var_func(p, (isdigit(*variables[which].name) ?
+ var : variables[which].name), val);
+}
+
+PUBLIC int
+com_variables(int p, param_list param)
+{
+ int i;
+ int p1, connected;
+
+ if (param[0].type == TYPE_WORD) {
+ if (!FindPlayer(p, param[0].val.word, &p1, &connected))
+ return COM_OK;
+ } else {
+ p1 = p;
+ connected = 1;
+ }
+
+ pprintf(p, "Variable settings of %s:\n", parray[p1].name);
+
+ pprintf(p, " time=%-3d inc=%-3d private=%d jprivate=%d "
+ "Lang=%s\n",
+ parray[p1].d_time,
+ parray[p1].d_inc,
+ parray[p1].private,
+ parray[p1].jprivate,
+ Language(parray[p1].language));
+ pprintf(p, " rated=%d ropen=%d open=%d simopen=%d\n",
+ parray[p1].rated,
+ parray[p1].ropen,
+ parray[p1].open,
+ parray[p1].sopen);
+ pprintf(p, " shout=%d cshout=%d kib=%d tell=%d "
+ "notifiedby=%d\n",
+ parray[p1].i_shout,
+ parray[p1].i_cshout,
+ parray[p1].i_kibitz,
+ parray[p1].i_tell,
+ parray[p1].notifiedby);
+ pprintf(p, " pin=%d gin=%d style=%-3d flip=%d "
+ "kiblevel=%d\n",
+ parray[p1].i_login,
+ parray[p1].i_game,
+ (parray[p1].style + 1),
+ parray[p1].flip,
+ parray[p1].kiblevel);
+ pprintf(p, " highlight=%d bell=%d auto=%d mailmess=%d "
+ "pgn=%d\n",
+ parray[p1].highlight,
+ parray[p1].bell,
+ parray[p1].automail,
+ parray[p1].i_mailmess,
+ parray[p1].pgn);
+ pprintf(p, " width=%-3d height=%-3d\n",
+ parray[p1].d_width,
+ parray[p1].d_height);
+
+ if (parray[p1].prompt && parray[p1].prompt != def_prompt)
+ pprintf(p, " Prompt: %s\n", parray[p1].prompt);
+ if (parray[p1].partner >= 0) {
+ pprintf(p, " Bughouse partner: %s\n",
+ parray[parray[p1].partner].name);
+ }
+
+ if (parray[p1].num_formula) {
+ pprintf(p, "\n");
+
+ for (i = 0; i < parray[p1].num_formula; i++) {
+ if (parray[p1].formulaLines[i] != NULL)
+ pprintf(p, " f%d: %s\n", (i + 1),
+ parray[p1].formulaLines[i]);
+ else
+ pprintf(p, " f%d:\n", (i + 1));
+ }
+ }
+
+ if (parray[p1].formula != NULL)
+ pprintf(p, "\nFormula: %s\n", parray[p1].formula);
+ if (!connected)
+ player_remove(p1);
+ return COM_OK;
+}