summaryrefslogtreecommitdiff
path: root/src/squeltch.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/squeltch.c')
-rw-r--r--src/squeltch.c553
1 files changed, 553 insertions, 0 deletions
diff --git a/src/squeltch.c b/src/squeltch.c
new file mode 100644
index 00000000..603eaa0e
--- /dev/null
+++ b/src/squeltch.c
@@ -0,0 +1,553 @@
+/* File: squeltch.c */
+
+/* Purpose: Automatizer */
+
+/*
+ * Copyright (c) 2002 DarkGod
+ *
+ * This software may be copied and distributed for educational, research, and
+ * not for profit purposes provided that this copyright and statement are
+ * included in all such copies.
+ */
+
+#include "angband.h"
+#include "lua/lua.h"
+#include "tolua.h"
+
+extern lua_State *L;
+
+/*
+ * The functions here use direct lua stack manipulation for calls instead of
+ * exec_lua(format()) because string manipulations are too slow for such
+ * functions
+ */
+
+/* Check the floor for "crap" */
+void squeltch_grid(void)
+{
+ int oldtop;
+ s16b this_o_idx, next_o_idx = 0;
+
+ if (!automatizer_enabled) return;
+
+ oldtop = lua_gettop(L);
+
+ /* Scan the pile of objects */
+ for (this_o_idx = cave[p_ptr->py][p_ptr->px].o_idx; this_o_idx; this_o_idx = next_o_idx)
+ {
+ /* Acquire object */
+ object_type * o_ptr = &o_list[this_o_idx];
+
+ /* We've now seen one of these */
+ if (!k_info[o_ptr->k_idx].flavor)
+ {
+ object_aware(o_ptr);
+ }
+
+ /* Acquire next object */
+ next_o_idx = o_ptr->next_o_idx;
+
+ /* Push the function */
+ lua_settop(L, oldtop);
+ lua_getglobal(L, "apply_rules");
+
+ /* Push the args */
+ tolua_pushusertype(L, o_ptr, tolua_tag(L, "object_type"));
+ tolua_pushnumber(L, -this_o_idx);
+
+ /* Call the function */
+ if (lua_call(L, 2, 0))
+ {
+ cmsg_format(TERM_VIOLET, "ERROR in lua_call while calling 'apply_rules'.");
+ lua_settop(L, oldtop);
+ return;
+ }
+ }
+ lua_settop(L, oldtop);
+}
+
+
+/* Check the inventory for "crap" */
+void squeltch_inventory(void)
+{
+ int oldtop;
+ int i;
+ int num_iter = 0;
+ bool_ found = TRUE;
+
+ if (!automatizer_enabled) return;
+
+ oldtop = lua_gettop(L);
+ while (found && num_iter ++ < 100)
+ {
+ /* Sometimes an index in the inventory is skipped */
+ found = FALSE;
+
+ for (i = 0; i < INVEN_PACK; i++)
+ {
+ object_type *o_ptr = &p_ptr->inventory[i];
+
+ /* Push the function */
+ lua_settop(L, oldtop);
+ lua_getglobal(L, "apply_rules");
+
+ /* Push the args */
+ tolua_pushusertype(L, o_ptr, tolua_tag(L, "object_type"));
+ tolua_pushnumber(L, i);
+
+ /* Call the function */
+ if (lua_call(L, 2, 1))
+ {
+ cmsg_format(TERM_VIOLET, "ERROR in lua_call while calling 'apply_rules'.");
+ lua_settop(L, oldtop);
+ return;
+ }
+
+ /* Did it return TRUE */
+ if (tolua_getnumber(L, -(lua_gettop(L) - oldtop), 0))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+ if (num_iter >= 100)
+ {
+ cmsg_format(TERM_VIOLET, "'apply_rules' ran too often.");
+ }
+ lua_settop(L, oldtop);
+}
+
+/********************** The interface **********************/
+static cptr *get_rule_list(int *max)
+{
+ cptr *list;
+ int i;
+
+ *max = exec_lua("return __rules_max");
+ C_MAKE(list, *max, cptr);
+
+ for (i = 0; i < *max; i++)
+ {
+ list[i] = string_exec_lua(format("return __rules[%d].table.args.name", i));
+ }
+
+ return list;
+}
+
+static cptr types_list[] =
+{
+ "and",
+ "or",
+ "not",
+ "name",
+ "contain",
+ "inscribed",
+ "discount",
+ "symbol",
+ "state",
+ "status",
+ "tval",
+ "sval",
+ "race",
+ "subrace",
+ "class",
+ "level",
+ "skill",
+ "ability",
+ "inventory",
+ "equipment",
+ "comment",
+ NULL,
+};
+
+/* Create a new rule */
+static int automatizer_new_rule()
+{
+ int wid, hgt, max, begin = 0, sel = 0;
+ char c;
+
+ /* Get the number of types */
+ max = 0;
+ while (types_list[max] != NULL)
+ max++;
+
+ while (1)
+ {
+ Term_clear();
+ Term_get_size(&wid, &hgt);
+
+ display_list(0, 0, hgt - 1, 15, "Rule types", types_list, max, begin, sel, TERM_L_GREEN);
+
+ exec_lua(format("auto_aux:display_desc('%s')", types_list[sel]));
+ c_prt(TERM_YELLOW, "Example:", 5, 17);
+ exec_lua(format("xml.write_out_y = 6; xml.write_out_x = 16; xml.write_out_h = %d; xml.write_out_w = %d; xml.write_y = 0; xml.write_x = 0; xml:display_xml(auto_aux.types_desc['%s'][2][1], '')", hgt - 3 - 5, wid - 1 - 15 - 1, types_list[sel]));
+
+ c = inkey();
+
+ if (c == ESCAPE) break;
+ else if (c == '8')
+ {
+ sel--;
+ if (sel < 0)
+ {
+ sel = max - 1;
+ begin = max - hgt;
+ if (begin < 0) begin = 0;
+ }
+ if (sel < begin) begin = sel;
+ }
+ else if (c == '2')
+ {
+ sel++;
+ if (sel >= max)
+ {
+ sel = 0;
+ begin = 0;
+ }
+ if (sel >= begin + hgt - 1) begin++;
+ }
+ else if (c == '\r')
+ {
+ return sel;
+ }
+ }
+ return -1;
+}
+
+static void adjust_begin(int *begin, int *sel, int max, int hgt)
+{
+ if (*sel < 0)
+ {
+ *sel = max - 1;
+ *begin = *sel - hgt + 3;
+ if (*begin < 0) *begin = 0;
+ }
+ if (*sel < *begin) *begin = *sel;
+
+ if (*sel >= max)
+ {
+ *sel = 0;
+ *begin = 0;
+ }
+ if (*sel >= *begin + hgt - 2) (*begin)++;
+}
+
+#define ACTIVE_LIST 0
+#define ACTIVE_RULE 1
+void do_cmd_automatizer()
+{
+ int wid = 0, hgt = 0;
+ char c;
+ cptr *list = NULL;
+ int max, begin = 0, sel = 0;
+ int active = ACTIVE_LIST;
+ cptr keys;
+ cptr keys2;
+ cptr keys3;
+
+ Term_get_size(&wid, &hgt);
+
+ if (!automatizer_enabled)
+ {
+ if (msg_box("Automatizer is currently disabled, enable it? (y/n)", hgt / 2, wid / 2) == 'y')
+ {
+ automatizer_enabled = TRUE;
+ }
+ else
+ return;
+ }
+
+ screen_save();
+
+ exec_lua(format("auto_aux:adjust_current(%d)", sel));
+
+ while (1)
+ {
+ Term_clear();
+ Term_get_size(&wid, &hgt);
+
+ list = get_rule_list(&max);
+ display_list(0, 0, hgt - 1, 15, "Rules", list, max, begin, sel, (active == ACTIVE_LIST) ? TERM_L_GREEN : TERM_GREEN);
+ C_FREE(list, max, cptr);
+
+ draw_box(0, 15, hgt - 4, wid - 1 - 15);
+ if (active == ACTIVE_RULE)
+ {
+ keys = "#Bup#W/#Bdown#W/#Bleft#W/#Bright#W to navitage rule, #B9#W/#B3#W/#B7#W/#B1#W to scroll";
+ keys2 = "#Btab#W for switch, #Ba#Wdd clause, #Bd#Welete clause/rule";
+ keys3 = "#Bx#W to toggle english/xml, #G?#W for Automatizer help";
+ exec_lua("xml.write_active = not nil");
+ }
+ else
+ {
+ keys = "#Bup#W/#Bdown#W to scroll, #Btab#W to switch to the rule window";
+ keys2 = "#Bu#W/#Bd#W to move rules, #Bn#Wew rule, #Br#Wename rule, #Bs#Wave rules";
+ keys3 = "#Rk#W to #rdisable#W the automatizer, #G?#W for Automatizer help";
+ exec_lua("xml.write_active = nil");
+ }
+ display_message(17, hgt - 3, strlen(keys), TERM_WHITE, keys);
+ display_message(17, hgt - 2, strlen(keys2), TERM_WHITE, keys2);
+ display_message(17, hgt - 1, strlen(keys3), TERM_WHITE, keys3);
+
+ if (max) exec_lua(format("xml.write_out_y = 1; xml.write_out_x = 16; xml.write_out_h = %d; xml.write_out_w = %d; xml.write_y = 0; xml.write_x = 0; xml:display_xml(__rules[%d].table, '')", hgt - 4 - 1, wid - 1 - 15 - 1, sel));
+
+ c = inkey();
+
+ if (c == ESCAPE) break;
+ if (active == ACTIVE_LIST)
+ {
+ if (c == '?')
+ {
+ screen_save();
+ show_file("automat.txt", "Automatizer help", 0, 0);
+ screen_load();
+ }
+ else if (c == '8')
+ {
+ if (!max) continue;
+ sel--;
+ adjust_begin(&begin, &sel, max, hgt);
+ exec_lua(format("auto_aux:adjust_current(%d)", sel));
+ }
+ else if (c == '2')
+ {
+ if (!max) continue;
+ sel++;
+ adjust_begin(&begin, &sel, max, hgt);
+ exec_lua(format("auto_aux:adjust_current(%d)", sel));
+ }
+ else if (c == 'u')
+ {
+ if (!max) continue;
+ sel = exec_lua(format("return auto_aux:move_up(%d)", sel));
+ adjust_begin(&begin, &sel, max, hgt);
+ exec_lua(format("auto_aux:adjust_current(%d)", sel));
+ }
+ else if (c == 'd')
+ {
+ if (!max) continue;
+ sel = exec_lua(format("return auto_aux:move_down(%d)", sel));
+ adjust_begin(&begin, &sel, max, hgt);
+ exec_lua(format("auto_aux:adjust_current(%d)", sel));
+ }
+ else if (c == 'n')
+ {
+ char name[20] = { '\0' };
+ char typ;
+
+ sprintf(name, "No name");
+ if (input_box("Name?", hgt / 2, wid / 2, name, sizeof(name)+1))
+ {
+ cptr styp = "nothing";
+ typ = msg_box("[D]estroy, [P]ickup, [I]nscribe, [N]othing rule?", hgt / 2, wid / 2);
+ if ((typ == 'd') || (typ == 'D')) styp = "destroy";
+ else if ((typ == 'p') || (typ == 'P')) styp = "pickup";
+ else if ((typ == 'i') || (typ == 'I')) styp = "inscribe";
+ exec_lua(format("auto_aux:new_rule(%d, '%s', '%s', ''); auto_aux:adjust_current(%d)", sel, name, styp, sel));
+ active = ACTIVE_RULE;
+ }
+ }
+ else if (c == 's')
+ {
+ char name[30] = { '\0' };
+
+ sprintf(name, "automat.atm");
+ if (input_box("Save name?", hgt / 2, wid / 2, name, sizeof(name)+1))
+ {
+ char buf[1025];
+ char ch;
+
+ /* Build the filename */
+ path_build(buf, 1024, ANGBAND_DIR_USER, name);
+
+ /* File type is "TEXT" */
+ FILE_TYPE(FILE_TYPE_TEXT);
+
+ if (file_exist(buf))
+ {
+ c_put_str(TERM_WHITE, "File exists, continue?[y/n]", hgt / 2, wid / 2 - 14);
+ ch = inkey();
+ if ((ch != 'Y') && (ch != 'y'))
+ continue;
+ }
+
+ /* Open the non-existing file */
+ hook_file = my_fopen(buf, "w");
+
+ /* Invalid file */
+ if (!hook_file)
+ {
+ /* Message */
+ c_put_str(TERM_WHITE, "Saving rules failed! ", hgt / 2, wid / 2 - 14);
+ (void) inkey();
+
+ /* Error */
+ continue;
+ }
+
+
+
+ exec_lua("auto_aux:save_ruleset()");
+ my_fclose(hook_file);
+ /* Overwrite query message */
+ c_put_str(TERM_WHITE, "Saved rules in file ", hgt / 2, wid / 2 - 14);
+ (void) inkey();
+ }
+ }
+ else if (c == 'r')
+ {
+ char name[20];
+
+ if (!max) continue;
+
+ sprintf(name, "%s", string_exec_lua(format("return __rules[%d].table.args.name", sel)));
+ if (input_box("New name?", hgt / 2, wid / 2, name, 15))
+ {
+ exec_lua(format("auto_aux:rename_rule(%d, '%s')", sel, name));
+ }
+
+ continue;
+ }
+ else if (c == 'k')
+ {
+ automatizer_enabled = FALSE;
+ break;
+ }
+ else if (c == '\t')
+ {
+ if (!max) continue;
+ active = ACTIVE_RULE;
+ }
+ else if (c == 'x')
+ {
+ exec_lua("xml.display_english = not xml.display_english");
+ }
+ }
+ else if (active == ACTIVE_RULE)
+ {
+ if (c == '?')
+ {
+ screen_save();
+ show_file("automat.txt", "Automatizer help", 0, 0);
+ screen_load();
+ }
+ else if (c == '8')
+ {
+ exec_lua("auto_aux:go_up()");
+ }
+ else if (c == '2')
+ {
+ exec_lua("auto_aux:go_down()");
+ }
+ else if (c == '6')
+ {
+ exec_lua("auto_aux:go_right()");
+ }
+ else if (c == '4')
+ {
+ exec_lua(format("auto_aux:go_left(%d)", sel));
+ }
+ else if (c == '9')
+ {
+ exec_lua("auto_aux:scroll_up()");
+ }
+ else if (c == '3')
+ {
+ exec_lua("auto_aux:scroll_down()");
+ }
+ else if (c == '7')
+ {
+ exec_lua("auto_aux:scroll_left()");
+ }
+ else if (c == '1')
+ {
+ exec_lua("auto_aux:scroll_right()");
+ }
+ else if (c == 'a')
+ {
+ int s = automatizer_new_rule();
+ if (s == -1) continue;
+ exec_lua(format("auto_aux:add_child('%s')", types_list[s]));
+ }
+ else if (c == 'd')
+ {
+ if (max)
+ {
+ int new_sel;
+
+ new_sel = exec_lua(format("return auto_aux:del_self(%d)", sel));
+ if ((sel != new_sel) && (new_sel >= 0))
+ {
+ sel = new_sel;
+ adjust_begin(&begin, &sel, max, hgt);
+ exec_lua(format("auto_aux:adjust_current(%d)", sel));
+ }
+ else if (new_sel == -1)
+ {
+ active = ACTIVE_LIST;
+ }
+ }
+ }
+ else if (c == '\t')
+ {
+ active = ACTIVE_LIST;
+ }
+ else if (c == 'x')
+ {
+ exec_lua("xml.display_english = not xml.display_english");
+ }
+ }
+ }
+
+ /* Recalculate the rules */
+ exec_lua("auto_aux.regen_ruleset()");
+
+ screen_load();
+}
+
+/* Add a new rule in an easy way */
+bool_ automatizer_create = FALSE;
+void automatizer_add_rule(object_type *o_ptr, bool_ destroy)
+{
+ char ch;
+ bool_ do_status = FALSE;
+ cptr type = "destroy";
+
+ if (!destroy)
+ {
+ type = "pickup";
+ }
+
+ while (TRUE)
+ {
+ if (!get_com(format("%s all of the same [T]ype, [F]amily or [N]ame, also use [S]tatus (%s)? ", (destroy) ? "Destroy" : "Pickup", (do_status) ? "Yes" : "No"), &ch))
+ {
+ break;
+ }
+
+ if (ch == 'S' || ch == 's')
+ {
+ do_status = !do_status;
+ continue;
+ }
+
+ if (ch == 'T' || ch == 't')
+ {
+ call_lua("easy_add_rule", "(s,s,d,O)", "", type, "tsval", do_status, o_ptr);
+ break;
+ }
+
+ if (ch == 'F' || ch == 'f')
+ {
+ call_lua("easy_add_rule", "(s,s,d,O)", "", type, "tval", do_status, o_ptr);
+ break;
+ }
+
+ if (ch == 'N' || ch == 'n')
+ {
+ call_lua("easy_add_rule", "(s,s,d,O)", "", type, "name", do_status, o_ptr);
+ break;
+ }
+ }
+}