diff options
Diffstat (limited to 'src/squeltch.c')
-rw-r--r-- | src/squeltch.c | 553 |
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; + } + } +} |