/* File: borg1.c */ /* Purpose: Low level stuff for the Borg -BEN- */ #include "angband.h" #include "borg.h" #ifdef ALLOW_BORG /* * This file contains various low level variables and routines. */ /* * Control variables */ bool borg_active; /* Actually active */ bool borg_cancel; /* Being cancelled */ u16b borg_step = 0; /* Step count (if any) */ char *borg_key_queue; /* Keypress queue */ s16b borg_key_head; /* Head of queue */ s16b borg_key_tail; /* Tail of queue */ FILE *borg_fff = NULL; /* Log file */ char borg_match_string[128] = ""; /* Search string */ /* * Optional strategy flags */ bool borg_flag_save = FALSE; /* Save savefile at each level */ bool borg_flag_dump = FALSE; /* Save savefile at each death */ /* * Optional cheating flags */ bool borg_flag_cheat_equip; /* Cheat for "equip mode" */ bool borg_flag_cheat_inven; /* Cheat for "inven mode" */ bool borg_flag_cheat_spell; /* Cheat for "browse mode" */ bool borg_flag_cheat_panel; /* Cheat for "panel mode" */ /* * Internal random number generator */ bool borg_rand_quick; /* Save system setting */ u32b borg_rand_value; /* Save system setting */ u32b borg_rand_local; /* Save personal setting */ /* * Time variables */ s16b borg_time = 0L; /* Current "time" */ s16b borg_when_began; /* When this level began */ s16b borg_when_call_lite; /* When we last did call light */ s16b borg_when_wizard_lite; /* When we last did wizard light */ s16b borg_when_detect_traps; /* When we last detected traps */ s16b borg_when_detect_doors; /* When we last detected doors */ s16b borg_when_detect_walls; /* When we last detected walls */ /* * Some information */ s16b borg_task; /* Current goal type */ s16b borg_avoid; /* Current danger avoidance */ bool borg_rising; /* Currently returning to town */ bool borg_leaving; /* Currently leaving the level */ bool borg_fleeing; /* Currently fleeing the level */ bool borg_ignoring; /* Currently ignoring monsters */ bool borg_recalling; /* Currently waiting for recall */ bool borg_completed; /* Currently bored with dungeon */ bool borg_stair_less; /* Use the next "up" staircase */ bool borg_stair_more; /* Use the next "down" staircase */ s16b borg_goal_shop = -1; /* Next shop to visit */ s16b borg_goal_ware = -1; /* Next item to buy there */ s16b borg_goal_item = -1; /* Next item to sell there */ s16b borg_exam_item = -1; /* Hack -- examine item -- index */ char borg_exam_note[32]; /* Hack -- examine item -- note */ /* * Various "amounts" (for the player) */ s16b amt_fuel; s16b amt_food; s16b amt_ident; s16b amt_recall; s16b amt_phase; s16b amt_escape; s16b amt_teleport; s16b amt_cure_critical; s16b amt_cure_serious; s16b amt_detect_trap; s16b amt_detect_door; s16b amt_missile; s16b amt_book[9]; s16b amt_add_stat[6]; s16b amt_fix_stat[6]; s16b amt_fix_exp; s16b amt_enchant_to_a; s16b amt_enchant_to_d; s16b amt_enchant_to_h; /* * Various "amounts" (for the home) */ s16b num_fuel; s16b num_food; s16b num_ident; s16b num_recall; s16b num_phase; s16b num_escape; s16b num_teleport; s16b num_cure_critical; s16b num_cure_serious; s16b num_missile; s16b num_book[9]; s16b num_fix_stat[6]; s16b num_fix_exp; s16b num_enchant_to_a; s16b num_enchant_to_d; s16b num_enchant_to_h; /* * State variables extracted from various places */ int borg_base_depth; /* Actual dungeon "level" */ int borg_base_level; /* Actual player level */ s32b borg_base_exp; /* Actual experience */ s32b borg_base_au; /* Actual gold */ int borg_base_pspeed; /* Actual speed */ int borg_base_ac; /* Actual ac */ int borg_base_chp; /* Actual current hitpoints */ int borg_base_mhp; /* Actual maximum hitpoints */ int borg_base_csp; /* Actual current spell points */ int borg_base_msp; /* Actual maximum spell points */ int borg_base_stat[6]; /* Actual stat values XXX XXX */ int borg_base_book[9]; /* Actual book slots XXX XXX */ int borg_base_shop = -1; /* Actual shop index */ int borg_base_wgt; /* Actual weight */ bool borg_base_is_weak; /* Actual flag -- weak */ bool borg_base_is_hungry; /* Actual flag -- hungry/weak */ bool borg_base_is_full; /* Actual flag -- full/gorged */ bool borg_base_is_gorged; /* Actual flag -- gorged */ bool borg_base_is_blind; /* Actual flag -- blind */ bool borg_base_is_afraid; /* Actual flag -- afraid */ bool borg_base_is_confused; /* Actual flag -- confused */ bool borg_base_is_poisoned; /* Actual flag -- poisoned */ bool borg_base_is_cut; /* Actual flag -- bleeding */ bool borg_base_is_stun; /* Actual flag -- stunned */ bool borg_base_is_image; /* Actual flag -- hallucinating */ bool borg_base_is_study; /* Actual flag -- may learn spells */ bool borg_base_fix_lev; /* Actual flag -- Drained LEV */ bool borg_base_fix_exp; /* Actual flag -- Drained EXP */ bool borg_base_fix_stat[6]; /* Actual flags -- Drained Stats XXX XXX */ int borg_feeling; /* Recent level "feeling" */ int borg_happy_depth; /* Favorite dungeon depth */ int borg_happy_count; /* Number of completions */ s32b borg_base_power; /* Hack -- base power */ bool borg_failure; /* Notice failure */ bool borg_simulate; /* Simulation flag */ bool borg_expected; /* Expected danger */ /* * Some global structures */ static player_type borg_player_type_body; player_type *b_ptr = &borg_player_type_body; static player_xtra borg_player_xtra_body; player_xtra *xb_ptr = &borg_player_xtra_body; player_race *rb_ptr; /* Player race info */ player_class *cb_ptr; /* Player class info */ player_magic *mb_ptr; /* Player magic info */ player_anal *ab_ptr; /* Player anal info */ auto_dungeon *db_ptr; /* Dungeon info */ /* * Hack -- message memory */ s16b borg_msg_len; s16b borg_msg_siz; char *borg_msg_buf; s16b borg_msg_num; s16b borg_msg_max; s16b *borg_msg_pos; s16b *borg_msg_use; /* * Hack -- the detection arrays */ bool borg_detect_wall[6][6]; bool borg_detect_trap[6][6]; bool borg_detect_door[6][6]; /* * Track shops */ byte *borg_track_shop_x; byte *borg_track_shop_y; /* * Track stairs up */ s16b borg_track_less_num; byte *borg_track_less_x; byte *borg_track_less_y; /* * Track stairs down */ s16b borg_track_more_num; byte *borg_track_more_x; byte *borg_track_more_y; /* * Track interesting grids */ s16b borg_wank_num = 0; auto_wank *borg_wanks; /* * Track interesting objects */ s16b borg_takes_cnt; s16b borg_takes_nxt; auto_take borg_takes[BORG_MAX_TAKE]; /* * Track interesting monsters */ s16b borg_kills_cnt; s16b borg_kills_nxt; auto_kill borg_kills[BORG_MAX_KILL]; /* * Hack -- extra fear per "region" */ u16b borg_fear_region[6][18]; /* * Hack -- count racial appearances per level */ s16b *borg_race_count; /* * Hack -- count racial kills (for uniques) */ s16b *borg_race_death; /* * Classification of map symbols */ bool borg_char_is_take[256]; /* Symbol may be an object */ bool borg_char_is_kill[256]; /* Symbol may be a monster */ /* * Maintain a set of grids marked as "BORG_LITE" */ s16b borg_lite_n = 0; byte borg_lite_x[AUTO_LITE_MAX]; byte borg_lite_y[AUTO_LITE_MAX]; /* * Maintain a set of grids marked as "BORG_VIEW" */ s16b borg_view_n = 0; byte borg_view_x[AUTO_VIEW_MAX]; byte borg_view_y[AUTO_VIEW_MAX]; /* * Maintain a temporary set of grids */ s16b borg_temp_n = 0; byte borg_temp_x[AUTO_TEMP_MAX]; byte borg_temp_y[AUTO_TEMP_MAX]; /* * Strategy flags -- recalculate things */ bool borg_do_wipe_danger = FALSE; /* Recalculate danger */ bool borg_do_update_view = FALSE; /* Recalculate view */ bool borg_do_update_lite = FALSE; /* Recalculate lite */ /* * Strategy flags -- examine the world */ bool borg_do_inven = TRUE; /* Acquire "inven" info */ bool borg_do_equip = TRUE; /* Acquire "equip" info */ bool borg_do_panel = TRUE; /* Acquire "panel" info */ bool borg_do_frame = TRUE; /* Acquire "frame" info */ bool borg_do_spell = TRUE; /* Acquire "spell" info */ byte borg_do_spell_aux = 0; /* Hack -- book for "borg_do_spell" */ bool borg_do_browse = 0; /* Acquire "store" info */ byte borg_do_browse_what = 0; /* Hack -- store for "borg_do_browse" */ byte borg_do_browse_more = 0; /* Hack -- pages for "borg_do_browse" */ /* * Strategy flags -- run certain functions */ bool borg_do_crush_junk = FALSE; bool borg_do_crush_hole = FALSE; bool borg_do_crush_slow = FALSE; /* * Inventory and shops */ auto_item *borg_items; /* Current "inventory" */ auto_shop *borg_shops; /* Current "shops" */ /* * Safety arrays for simulating possible worlds */ auto_item *borg_safe_items; /* Safety "inventory" */ auto_shop *borg_safe_shops; /* Safety "shops" */ /* * Spell/Prayer info */ auto_magic borg_magics[9][9]; /* Magic info, by book/what */ /* * Query the "attr/char" at a given location on the screen * We return "zero" if the given location was legal * * We assume the given location is legal XXX XXX XXX */ errr borg_what_char(int x, int y, byte *a, char *c) { /* Direct access XXX XXX XXX */ (*a) = (Term->scr->a[y][x]); (*c) = (Term->scr->c[y][x]); /* Success */ return (0); } /* * Query the "attr/chars" at a given location on the screen * * Note that "a" points to a single "attr", and "s" to an array * of "chars", into which the attribute and text at the given * location are stored. * * We will not grab more than "ABS(n)" characters for the string. * If "n" is "positive", we will grab exactly "n" chars, or fail. * If "n" is "negative", we will grab until the attribute changes. * * We automatically convert all "blanks" and "invisible text" into * spaces, and we ignore the attribute of such characters. * * We do not strip final spaces, so this function will very often * read characters all the way to the end of the line. * * We succeed only if a string of some form existed, and all of * the non-space characters in the string have the same attribute, * and the string was long enough. * * We assume the given location is legal XXX XXX XXX */ errr borg_what_text(int x, int y, int n, byte *a, char *s) { int i; byte t_a; char t_c; byte *aa; char *cc; /* Current attribute */ byte d_a = 0; /* Max length to scan for */ int m = ABS(n); /* Hack -- Do not run off the screen */ if (x + m > 80) m = 80 - x; /* Direct access XXX XXX XXX */ aa = &(Term->scr->a[y][x]); cc = &(Term->scr->c[y][x]); /* Grab the string */ for (i = 0; i < m; i++) { /* Access */ t_a = *aa++; t_c = *cc++; /* Handle spaces */ if ((t_c == ' ') || !t_a) { /* Save space */ s[i] = ' '; } /* Handle real text */ else { /* Attribute ready */ if (d_a) { /* Verify the "attribute" (or stop) */ if (t_a != d_a) break; } /* Acquire attribute */ else { /* Save it */ d_a = t_a; } /* Save char */ s[i] = t_c; } } /* Terminate the string */ s[i] = '\0'; /* Save the attribute */ (*a) = d_a; /* Too short */ if ((n > 0) && (i != n)) return (1); /* Success */ return (0); } /* * Steal info from the game -- inventory weight info */ void borg_steal_inventory_weight(char *buf) { /* Create a fake description string */ sprintf(buf, "Inventory (carrying %d.%d pounds)", p_ptr->total_weight / 10, p_ptr->total_weight % 10); } /* * Steal info from the game -- inventory object description */ void borg_steal_inventory_desc(char *buf, int item) { /* Default to "nothing" */ buf[0] = '\0'; /* Describe a real item */ if (inventory[item].k_idx) { /* Describe it (fully) */ object_desc(buf, &inventory[item], TRUE, 3); } } /* * Steal info from the game -- spell/prayer description * * Note the use of "as->cheat" to optimize the spell index extraction */ void borg_steal_spell_info(char *buf, int book, int what) { int spell; int num = 0; magic_type *s_ptr; auto_magic *as; cptr comment; char info[80]; /* Default (20 spaces) */ strcpy(buf, " "); /* Access the spell */ as = &borg_magics[book][what]; /* Skip illegible spells */ if (as->status == BORG_MAGIC_ICKY) return; /* Access the index */ spell = as->cheat; /* Access the spell */ s_ptr = &mp_ptr->info[spell]; /* Illegible spells */ if (s_ptr->slevel >= 99) return; /* Get extra info */ spell_info(info, spell); /* Use that info */ comment = info; /* Analyze the spell */ if ((spell < 32) ? ((p_ptr->spell_forgotten1 & (1L << spell))) : ((p_ptr->spell_forgotten2 & (1L << (spell - 32))))) { comment = " forgotten"; } else if (!((spell < 32) ? (p_ptr->spell_learned1 & (1L << spell)) : (p_ptr->spell_learned2 & (1L << (spell - 32))))) { comment = " unknown"; } else if (!((spell < 32) ? (p_ptr->spell_worked1 & (1L << spell)) : (p_ptr->spell_worked2 & (1L << (spell - 32))))) { comment = " untried"; } /* Extract the spell info */ sprintf(buf, "%2d %4d %3d%%%s", s_ptr->slevel, s_ptr->smana, spell_chance(spell), comment); } /* * Steal info from the game -- current dungeon panel info */ void borg_steal_panel_info(char *buf) { /* Create a fake screen buffer */ sprintf(buf, "Map sector [%d,%d]", (dungeon_wy / PANEL_HGT), (dungeon_wx / PANEL_WID)); } /* * Log a message to a file */ void borg_info(cptr what) { /* Dump a log file message */ if (borg_fff) fprintf(borg_fff, "%s\n", what); } /* * Memorize a message, Log it, Search it, and Display it in pieces */ void borg_note(cptr what) { int j, n, i, k; int w, h, x, y; term *old = Term; /* Memorize it */ message_add(what); /* Log the message */ borg_info(what); /* Mega-Hack -- Check against the search string */ if (borg_match_string[0] && strstr(what, borg_match_string)) { /* Clean cancel */ borg_cancel = TRUE; } /* Scan windows */ for (j = 0; j < 8; j++) { if (!angband_term[j]) continue; /* Check flag */ if (!(op_ptr->window_flag[j] & PW_BORG_1)) continue; /* Activate */ Term_activate(angband_term[j]); /* Access size */ Term_get_size(&w, &h); /* Access cursor */ Term_locate(&x, &y); /* Erase current line */ Term_erase(0, y, 255); /* Total length */ n = strlen(what); /* Too long */ if (n > w - 2) { char buf[1024]; /* Split */ while (n > w - 2) { /* Default */ k = w - 2; /* Find a split point */ for (i = w / 2; i < w - 2; i++) { /* Pre-emptive split point */ if (isspace(what[i])) k = i; } /* Copy over the split message */ for (i = 0; i < k; i++) { /* Copy */ buf[i] = what[i]; } /* Indicate split */ buf[i++] = '\\'; /* Terminate */ buf[i] = '\0'; /* Show message */ Term_addstr(-1, TERM_WHITE, buf); /* Advance (wrap) */ if (++y >= h) y = 0; /* Erase next line */ Term_erase(0, y, 255); /* Advance */ what += k; /* Reduce */ n -= k; } /* Show message tail */ Term_addstr(-1, TERM_WHITE, what); /* Advance (wrap) */ if (++y >= h) y = 0; /* Erase next line */ Term_erase(0, y, 255); } /* Normal */ else { /* Show message */ Term_addstr(-1, TERM_WHITE, what); /* Advance (wrap) */ if (++y >= h) y = 0; /* Erase next line */ Term_erase(0, y, 255); } /* Flush output */ Term_fresh(); /* Use correct window */ Term_activate(old); } } /* * Add a keypress to the "queue" (fake event) */ errr borg_keypress(char k) { /* Hack -- Refuse to enqueue "nul" */ if (!k) return (-1); /* Hack -- note the keypress */ if (borg_fff) borg_info(format("& Key <%c>", k)); /* Store the char, advance the queue */ borg_key_queue[borg_key_head++] = k; /* Circular queue, handle wrap */ if (borg_key_head == BORG_KEY_SIZE) borg_key_head = 0; /* Hack -- Catch overflow (forget oldest) */ if (borg_key_head == borg_key_tail) borg_oops("overflow"); /* Hack -- Overflow may induce circular queue */ if (borg_key_tail == BORG_KEY_SIZE) borg_key_tail = 0; /* Success */ return (0); } /* * Add a keypress to the "queue" (fake event) */ errr borg_keypresses(cptr str) { cptr s; /* Enqueue them */ for (s = str; *s; s++) borg_keypress(*s); /* Success */ return (0); } /* * Get the next Borg keypress */ char borg_inkey(bool take) { int i; /* Nothing ready */ if (borg_key_head == borg_key_tail) return (0); /* Extract the keypress */ i = borg_key_queue[borg_key_tail]; /* Do not advance */ if (!take) return (i); /* Advance the queue */ borg_key_tail++; /* Circular queue requires wrap-around */ if (borg_key_tail == BORG_KEY_SIZE) borg_key_tail = 0; /* Return the key */ return (i); } /* * Get the next Borg keypress */ void borg_flush(void) { /* Simply forget old keys */ borg_key_tail = borg_key_head; } /* * Abort the Borg, noting the reason */ void borg_oops(cptr what) { /* Stop processing */ borg_active = FALSE; /* Give a warning */ borg_note(format("# Aborting (%s).", what)); /* Forget borg keys */ borg_flush(); } #else #ifdef MACINTOSH static int HACK = 0; #endif /* MACINTOSH */ #endif /* ALLOW_BORG */