static void _character_dump(doc_ptr doc) { int ct = _count_open_terrain(); bool disrupt = heavy_armor(); if (!disrupt && p_ptr->lev >= 5) { spell_info spells[MAX_SPELLS]; int ct = _get_spells(spells, MAX_SPELLS); py_display_spells(doc, spells, ct); } doc_printf(doc, "<topic:Abilities>================================== <color:keypress>A</color>bilities ==================================\n\n"); /* Hack: Heavy Armor negates advantages of being in the open, and actually incurs penalties for being entrenched! */ if (disrupt) { doc_printf(doc, " * Your talents are disrupted by the weight of your armor.\n"); ct = 0; } else { if (ct >= 6) doc_printf(doc, " * You are out in the open (%d adjacent open squares).\n", ct); else if (ct >= 3) doc_printf(doc, " * You are somewhat confined (%d adjacent open squares).\n", ct); else doc_printf(doc, " * You are very confined (%d adjacent open squares).\n", ct); } /* Unfettered Body */ if (p_ptr->lev >= 1) { int amt = _unfettered_body(ct); if (amt > 0) doc_printf(doc, " * You gain %+d to your AC being out in the open.\n", amt); else if (amt < 0) doc_printf(doc, " * You lose %+d to your AC being so confined.\n", amt); } /* Unfettered Mind */ if (p_ptr->lev >= 1) { int amt = _unfettered_mind(ct); if (amt > 0) doc_printf(doc, " * You gain %+d to your Saving Throws being out in the open.\n", amt); else if (amt < 0) doc_printf(doc, " * You lose %+d to your Saving Throws being so confined.\n", amt); } if (!disrupt && p_ptr->lev >= 20) doc_printf(doc, " * You ambush sleeping monsters for extra damage.\n"); if (!disrupt && p_ptr->lev >= 50) doc_printf(doc, " * You have Peerless Stealth and will never aggravate monsters.\n"); doc_newline(doc); }
void display_shooter_info(doc_ptr doc) { object_type *bow_ptr = NULL; int slot = equip_find_object(TV_BOW, SV_ANY); char o_name[MAX_NLEN]; int mult; int num_fire = 0; int to_h = 0; int to_d = 0; int i, j; if (!slot || prace_is_(RACE_MON_JELLY) || p_ptr->shooter_info.tval_ammo == TV_NO_AMMO) return; bow_ptr = equip_obj(slot); assert(bow_ptr); mult = bow_mult(bow_ptr); if (p_ptr->shooter_info.num_fire) num_fire = p_ptr->shooter_info.num_fire * 100 * 100 / bow_energy(bow_ptr->sval); if (object_is_known(bow_ptr)) { to_h = bow_ptr->to_h; to_d = bow_ptr->to_d; if (weaponmaster_is_(WEAPONMASTER_CROSSBOWS) && p_ptr->lev >= 15) to_d += 1 + p_ptr->lev/10; } /* Shooter */ object_desc(o_name, bow_ptr, OD_OMIT_INSCRIPTION | OD_COLOR_CODED); doc_printf(doc, " <color:y>Shooting</color>: <indent><style:indent>%s</style></indent>\n", o_name); doc_printf(doc, " %-8.8s: %d'\n", "Range", (bow_range(bow_ptr) + 1) * 10); doc_printf(doc, " %-8.8s: %d.%02d\n", "Shots", num_fire/100, num_fire%100); doc_printf(doc, " %-8.8s: %d.%02dx\n", "Mult", mult/100, mult%100); doc_printf(doc, " %-8.8s: %d + %d = %d\n", "To Hit", to_h, p_ptr->shooter_info.dis_to_h, to_h + p_ptr->shooter_info.dis_to_h); doc_printf(doc, " %-8.8s: %d (%s)\n", "To Dam", to_d, "Multiplier Applies"); doc_printf(doc, " %-8.8s: %d (%s)\n", "Xtra Dam", p_ptr->shooter_info.dis_to_d, "Multiplier Does Not Apply"); doc_newline(doc); /* Ammo */ j = 0; for (i = 0; i < INVEN_PACK; i++) { if (inventory[i].tval == p_ptr->shooter_info.tval_ammo) _shooter_info_aux(doc, bow_ptr, &inventory[i], ++j); } }
static void _character_dump(doc_ptr doc) { int i; spell_info spells[MAX_SPELLS]; int ct = _get_spells_imp(spells, MAX_SPELLS, 0, _MAX_TALENTS - 1); for (i = 0; i < ct; i++) { spell_info* current = &spells[i]; current->cost += get_spell_cost_extra(current->fn); current->fail = MAX(current->fail, get_spell_fail_min(current->fn)); } if (ct > 0) { int i; variant name, info; var_init(&name); var_init(&info); doc_printf(doc, "<topic:WildTalent>================================= <color:keypress>W</color>ild Talents ================================\n\n"); doc_printf(doc, "<color:G>%-23.23s Lv Stat Cost Fail Info</color>\n", ""); for (i = 0; i < ct; ++i) { spell_info *spell = &spells[i]; (spell->fn)(SPELL_NAME, &name); (spell->fn)(SPELL_INFO, &info); doc_printf(doc, "%-23.23s %2d %4.4s %4d %3d%% %s\n", var_get_string(&name), spell->level, stat_abbrev_true[_which_stat(i)], spell->cost, spell->fail, var_get_string(&info)); } var_clear(&name); var_clear(&info); doc_newline(doc); } }
static void msg_line_display(byte color, cptr msg) { int len = strlen(msg); /* Quick and dirty test for -more- ... This means _msg_line_display_rect is just a suggested limit, and we'll surpass this for long messages. */ if (doc_cursor(_msg_line_doc).y >= _msg_line_rect.cy && len > 1) msg_line_flush(); /* Append this message to the last? */ else if (!_msg_append && !msg_line_is_empty() && doc_cursor(_msg_line_doc).x > 0) doc_newline(_msg_line_doc); if (doc_cursor(_msg_line_doc).x > 0 && len > 1) doc_insert_char(_msg_line_doc, TERM_WHITE, ' '); doc_insert_text(_msg_line_doc, color, msg); msg_line_sync(); }
doc_pos_t doc_insert_doc(doc_ptr dest_doc, doc_ptr src_doc, int indent) { doc_pos_t src_pos = doc_pos_create(0, 0); doc_pos_t dest_pos; if (dest_doc->cursor.x > 0) doc_newline(dest_doc); dest_pos = dest_doc->cursor; while (src_pos.y <= src_doc->cursor.y) { doc_char_ptr src = doc_char(src_doc, src_pos); doc_char_ptr dest; int count = src_doc->width; int i; dest_pos.x += indent; dest = doc_char(dest_doc, dest_pos); if (count > dest_doc->width - dest_pos.x) count = dest_doc->width - dest_pos.x; if (src_pos.y == src_doc->cursor.y && count > src_doc->cursor.x) count = src_doc->cursor.x; for (i = 0; i < count; i++) { dest->a = src->a; dest->c = src->c; dest++; src++; } dest_pos.x = 0; dest_pos.y++; src_pos.x = 0; src_pos.y++; } dest_doc->cursor = dest_pos; return dest_doc->cursor; }
doc_pos_t doc_insert_char(doc_ptr doc, byte a, char c) { doc_char_ptr cell = doc_char(doc, doc->cursor); doc_style_ptr style = doc_current_style(doc); cell->a = a; cell->c = c; if (doc->cursor.x >= style->right - 1) { if (!(style->options & DOC_STYLE_NO_WORDWRAP)) doc_newline(doc); } else doc->cursor.x++; assert(0 <= doc->cursor.x && doc->cursor.x < doc->width); return doc->cursor; }
void _character_dump(doc_ptr doc) { int i; bool first = TRUE; for (i = 0; i < _MAX_FORMS; i++) { if (_forms[i]) { if (first) { doc_printf(doc, "<topic:LearnedForms>================================ <color:keypress>L</color>earned Forms ================================\n\n"); first = FALSE; } doc_printf(doc, " %s\n", r_name + r_info[_forms[i]].name); } } doc_newline(doc); possessor_character_dump(doc); }
void monk_display_attack_info(doc_ptr doc, int hand) { _attack_t counts[MAX_MA]; int i; const int tot = 1000; int tot_dam = 0; /* Scaled by 10 */ int tot_mul = 0; int tot_to_d = 0; /* Scaled by 10 */ int blows = NUM_BLOWS(hand); /* Scaled by 100: 100 = 1.00 blows, 275 = 2.75 blows, etc */ int to_d = p_ptr->weapon_info[hand].to_d * 10; critical_t crit; doc_ptr cols[2] = {0}; cols[0] = doc_alloc(45); cols[1] = doc_alloc(35); /* First Column */ doc_printf(cols[0], "<color:G>%-14.14s %6s %5s %6s</color>\n", "Attack", "Dice", "Pct", "Dam"); _get_attack_counts(tot, counts, hand); for (i = 0; i < MAX_MA; i++) { martial_arts *ma_ptr = &ma_blows[i]; int dd = ma_ptr->dd + p_ptr->weapon_info[hand].to_dd; int ds = ma_ptr->ds + p_ptr->weapon_info[hand].to_ds; char tmp[20]; int dam = dd * (ds + 1) * 10 * counts[i].count / (2 * tot); if (counts[i].count == 0) continue; tot_dam += dam; tot_mul += counts[i].mul; tot_to_d += counts[i].to_d; sprintf(tmp, "%dd%d", dd, ds); doc_printf(cols[0], "%-14.14s %6s %3d.%1d%% %3d.%1d\n", ma_ptr->name, tmp, counts[i].count/10, counts[i].count%10, dam/10, dam%10); } doc_printf(cols[0], "<tab:8>%20s %3d.%1d\n", "Total:", tot_dam/10, tot_dam%10); crit.mul = tot_mul/tot; crit.to_d = tot_to_d*10/tot; doc_printf(cols[0], "<tab:8>%20s %3d.%02dx\n", "Criticals:", crit.mul/100, crit.mul%100); /* Account for criticals in all that follows ... */ tot_dam = tot_dam * crit.mul/100; to_d += crit.to_d; doc_printf(cols[0], "<tab:8>%20s %3d.%1d +%3d\n", "One Strike:", tot_dam/10, tot_dam%10, to_d/10); /* Second Column */ doc_insert(cols[1], "<color:y>Your Fists</color>\n"); doc_printf(cols[1], "Number of Blows: %d.%2.2d\n", blows/100, blows%100); doc_printf(cols[1], "To Hit: 0 50 100 150 200 (AC)\n"); doc_printf(cols[1], " %2d %2d %2d %2d %2d (%%)\n", hit_chance(0, 0, 0), hit_chance(0, 0, 50), hit_chance(0, 0, 100), hit_chance(0, 0, 150), hit_chance(0, 0, 200) ); doc_newline(cols[1]); doc_insert(cols[1], "<color:y>Average Damage:</color>\n"); doc_printf(cols[1], " One Strike: %d.%1d\n", (tot_dam + to_d)/10, (tot_dam + to_d)%10); /* Note: blows are scaled by 100. tot_dam and to_d by 10. So we divide by 1000 to recover the integer part ... */ doc_printf(cols[1], " One Attack: %d.%1d\n", blows*(tot_dam + to_d)/1000, ((blows*(tot_dam + to_d))/100)%10); if (display_weapon_mode == MYSTIC_ACID) { doc_printf(cols[1], " <color:r> Acid</color>: %d.%1d\n", blows*(tot_dam*20/10 + to_d + 50)/1000, ((blows*(tot_dam*20/10 + to_d + 50))/100)%10); } else if (have_flag(p_ptr->weapon_info[hand].flags, OF_BRAND_ACID)) { doc_printf(cols[1], " <color:r> Acid</color>: %d.%1d\n", blows*(tot_dam*17/10 + to_d)/1000, ((blows*(tot_dam*17/10 + to_d))/100)%10); } if (display_weapon_mode == MYSTIC_FIRE) { doc_printf(cols[1], " <color:r> Fire</color>: %d.%1d\n", blows*(tot_dam*17/10 + to_d + 30)/1000, ((blows*(tot_dam*17/10 + to_d + 30))/100)%10); } else if (have_flag(p_ptr->weapon_info[hand].flags, OF_BRAND_FIRE)) { doc_printf(cols[1], " <color:r> Fire</color>: %d.%1d\n", blows*(tot_dam*17/10 + to_d)/1000, ((blows*(tot_dam*17/10 + to_d))/100)%10); } if (display_weapon_mode == MYSTIC_COLD) { doc_printf(cols[1], " <color:r> Cold</color>: %d.%1d\n", blows*(tot_dam*17/10 + to_d + 30)/1000, ((blows*(tot_dam*17/10 + to_d + 30))/100)%10); } else if (have_flag(p_ptr->weapon_info[hand].flags, OF_BRAND_COLD)) { doc_printf(cols[1], " <color:r> Cold</color>: %d.%1d\n", blows*(tot_dam*17/10 + to_d)/1000, ((blows*(tot_dam*17/10 + to_d))/100)%10); } if (display_weapon_mode == MYSTIC_ELEC) { doc_printf(cols[1], " <color:r> Elec</color>: %d.%1d\n", blows*(tot_dam*25/10 + to_d + 70)/1000, ((blows*(tot_dam*25/10 + to_d + 70))/100)%10); } else if (have_flag(p_ptr->weapon_info[hand].flags, OF_BRAND_ELEC)) { doc_printf(cols[1], " <color:r> Elec</color>: %d.%1d\n", blows*(tot_dam*17/10 + to_d)/1000, ((blows*(tot_dam*17/10 + to_d))/100)%10); } if (display_weapon_mode == MYSTIC_POIS) { doc_printf(cols[1], " <color:r> Pois</color>: %d.%1d\n", blows*(tot_dam*17/10 + to_d + 30)/1000, ((blows*(tot_dam*17/10 + to_d + 30))/100)%10); } else if (have_flag(p_ptr->weapon_info[hand].flags, OF_BRAND_POIS)) { doc_printf(cols[1], " <color:r> Pois</color>: %d.%1d\n", blows*(tot_dam*17/10 + to_d)/1000, ((blows*(tot_dam*17/10 + to_d))/100)%10); } doc_insert_cols(doc, cols, 2, 0); doc_free(cols[0]); doc_free(cols[1]); }
static void _dump_book(doc_ptr doc, int realm, int book) { int k_idx = lookup_kind(realm2tval(realm), book); int i, increment = 64; caster_info *caster_ptr = get_caster_info(); if ((p_ptr->pclass == CLASS_SORCERER) || (p_ptr->pclass == CLASS_RED_MAGE)) increment = 0; else if (realm == p_ptr->realm1) increment = 0; else if (realm == p_ptr->realm2) increment = 32; if (realm == REALM_HISSATSU) { doc_printf(doc, "<color:G> %-25.25s Lvl SP %-15.15s Cast</color>\n", k_name + k_info[k_idx].name, "Desc"); } else { if (caster_ptr && (caster_ptr->options & CASTER_USE_HP)) doc_printf(doc, "<color:G> %-23.23s Profic Lvl HP Fail %-15.15s Cast Fail</color>\n", k_name + k_info[k_idx].name, "Desc"); else doc_printf(doc, "<color:G> %-23.23s Profic Lvl SP Fail %-15.15s Cast Fail</color>\n", k_name + k_info[k_idx].name, "Desc"); } for (i = 0; i < 8; i++) { int s_idx = book * 8 + i; magic_type *s_ptr; int cost; bool max = FALSE; char proficiency[10]; char info[80]; cptr comment; char line[160]; char color = 'w'; if (is_magic(realm)) s_ptr = &mp_ptr->info[realm - 1][s_idx]; else s_ptr = &technic_info[realm - MIN_TECHNIC][s_idx]; if (s_ptr->slevel >= 99) continue; if (realm == REALM_HISSATSU) cost = s_ptr->smana; else { s16b exp = experience_of_spell(s_idx, realm); int exp_level = spell_exp_level(exp); cost = mod_need_mana(s_ptr->smana, s_idx, realm); max = FALSE; if (!increment && (exp_level == EXP_LEVEL_MASTER)) max = TRUE; else if ((increment == 32) && (exp_level >= EXP_LEVEL_EXPERT)) max = TRUE; else if ((p_ptr->pclass == CLASS_RED_MAGE) && (exp_level >= EXP_LEVEL_SKILLED)) max = TRUE; strncpy(proficiency, exp_level_str[exp_level], 4); proficiency[3] = ']'; proficiency[4] = '\0'; } strcpy(info, do_spell(realm, s_idx, SPELL_INFO)); comment = info; if (p_ptr->pclass == CLASS_SORCERER || p_ptr->pclass == CLASS_RED_MAGE) { if (s_ptr->slevel > p_ptr->max_plv) { comment = "unknown"; color = 'D'; } else if (s_ptr->slevel > p_ptr->lev) { comment = "forgotten"; color = 'y'; } } else if ((realm == p_ptr->realm1) ? ((p_ptr->spell_forgotten1 & (1L << s_idx))) : ((p_ptr->spell_forgotten2 & (1L << s_idx)))) { comment = "forgotten"; color = 'y'; } else if (!((realm == p_ptr->realm1) ? (p_ptr->spell_learned1 & (1L << s_idx)) : (p_ptr->spell_learned2 & (1L << s_idx)))) { comment = "unknown"; if (s_ptr->slevel > p_ptr->lev) color = 'D'; else color = 'B'; } else if (!((realm == p_ptr->realm1) ? (p_ptr->spell_worked1 & (1L << s_idx)) : (p_ptr->spell_worked2 & (1L << s_idx)))) { comment = "untried"; } sprintf(line, " %c) ", I2A(i)); if (realm == REALM_HISSATSU) { spell_stats_ptr stats = spell_stats_old(realm, s_idx); strcat( line, format( "<color:%c>%-25s %3d %3d %-15.15s %5d</color>", color, do_spell(realm, s_idx, SPELL_NAME), s_ptr->slevel, cost, comment, stats->ct_cast ) ); } else { spell_stats_ptr stats = spell_stats_old(realm, s_idx); strcat( line, format( "<color:%c>%-25s%c%-4s %3d %3d %3d%% %-15.15s %5d %4d %3d%%</color>", color, do_spell(realm, s_idx, SPELL_NAME), (max ? '!' : ' '), proficiency, s_ptr->slevel, cost, spell_chance(s_idx, realm), comment, stats->ct_cast, stats->ct_fail, spell_stats_fail(stats) ) ); } doc_printf(doc, "%s\n", line); } doc_newline(doc); }
doc_pos_t doc_insert(doc_ptr doc, cptr text) { doc_token_t token; doc_token_t queue[10]; int qidx = 0; cptr pos = text; int i, j, cb; doc_style_ptr style = NULL; for (;;) { pos = doc_lex(pos, &token); if (token.type == DOC_TOKEN_EOF) break; assert(pos != token.pos); if (token.type == DOC_TOKEN_TAG) { _doc_process_tag(doc, &token.tag); continue; } if (token.type == DOC_TOKEN_NEWLINE) { doc_newline(doc); continue; } if (token.type == DOC_TOKEN_WHITESPACE) { doc_insert_space(doc, token.size); continue; } assert(token.type == DOC_TOKEN_WORD); assert(token.size > 0); /* Queue Complexity is for "<color:R>difficult</color>!" which is actually a bit common! */ qidx = 0; cb = token.size; queue[qidx++] = token; while (qidx < 10) { cptr peek = doc_lex(pos, &token); if (token.type == DOC_TOKEN_WORD) { cb += token.size; } else if ( token.type == DOC_TOKEN_TAG && (token.tag.type == DOC_TAG_COLOR || token.tag.type == DOC_TAG_CLOSE_COLOR) ) { } else { break; } queue[qidx++] = token; pos = peek; } style = doc_current_style(doc); /* be careful ... this changes on <color:_> tags! */ if ( doc->cursor.x + cb >= style->right && !(style->options & DOC_STYLE_NO_WORDWRAP) ) { doc_newline(doc); if (style->indent) doc_insert_space(doc, style->indent); } for (i = 0; i < qidx; i++) { doc_token_ptr current = &queue[i]; if (current->type == DOC_TOKEN_TAG) { assert(current->tag.type == DOC_TAG_COLOR || current->tag.type == DOC_TAG_CLOSE_COLOR); _doc_process_tag(doc, ¤t->tag); style = doc_current_style(doc); } else if (doc->cursor.x < style->right) { doc_char_ptr cell = doc_char(doc, doc->cursor); assert(current->type == DOC_TOKEN_WORD); assert(cell); for (j = 0; j < current->size; j++) { cell->a = style->color; cell->c = current->pos[j]; if (cell->c == '\t') cell->c = ' '; if (doc->cursor.x == style->right - 1) { if (style->options & DOC_STYLE_NO_WORDWRAP) break; doc_newline(doc); if (style->indent) doc_insert_space(doc, style->indent); cell = doc_char(doc, doc->cursor); } else { doc->cursor.x++; cell++; } } } } } assert(0 <= doc->cursor.x && doc->cursor.x < doc->width); return doc->cursor; }
doc_pos_t doc_insert_cols(doc_ptr dest_doc, doc_ptr src_cols[], int col_count, int spacing) { int src_y = 0; int max_src_y = 0; doc_pos_t dest_pos; int i; if (dest_doc->cursor.x > 0) doc_newline(dest_doc); dest_pos = dest_doc->cursor; for (i = 0; i < col_count; i++) { doc_ptr src_col = src_cols[i]; max_src_y = MAX(src_col->cursor.y, max_src_y); } while (src_y <= max_src_y) { for (i = 0; i < col_count; i++) { doc_ptr src_col = src_cols[i]; int count = src_col->width; if (count > dest_doc->width - dest_pos.x) count = dest_doc->width - dest_pos.x; if (src_y <= src_col->cursor.y && count > 0) { doc_char_ptr dest = doc_char(dest_doc, dest_pos); doc_char_ptr src = doc_char(src_col, doc_pos_create(0, src_y)); int j; for (j = 0; j < count; j++) { /* Hack: Attempt to prevent trailing spaces. For some reason, this is causing oook to not display character dumps properly from Windows builds. Interestingly, oook displays files correctly from Linux even without this hack, which is puzzling since the files seem identical on both platforms.*/ if (i == col_count - 1 && !src->c) { count = j; break; } dest->a = src->a; dest->c = src->c; if (!dest->c) dest->c = ' '; dest++; src++; } } dest_pos.x += count; if (i == col_count - 1) break; /* Spacing between columns */ count = spacing; if (count > dest_doc->width - dest_pos.x) count = dest_doc->width - dest_pos.x; if (count > 0) { doc_char_ptr dest = doc_char(dest_doc, dest_pos); int j; for (j = 0; j < count; j++) { dest->a = TERM_WHITE; dest->c = ' '; dest++; } } dest_pos.x += count; } dest_pos.x = 0; dest_pos.y++; src_y++; } dest_doc->cursor = dest_pos; return dest_doc->cursor; }
/********************************************************************** * Private Helpers **********************************************************************/ static void _character_dump(doc_ptr doc) { doc_printf(doc, "<topic:Spells>==================================== <color:keypress>S</color>pells ===================================\n\n"); _list_spells(doc, _SHOW_INFO | _SHOW_STATS); doc_newline(doc); }