Example #1
0
/**
 * Display the monster list statically. This will force the list to be
 * displayed to the provided dimensions. Contents will be adjusted accordingly.
 *
 * In order to support more efficient monster flicker animations, this function
 * uses a shared list object so that it's not constantly allocating and freeing
 * the list.
 *
 * \param height is the height of the list.
 * \param width is the width of the list.
 */
void monster_list_show_subwindow(int height, int width)
{
	textblock *tb;
	monster_list_t *list;
	int i;

	if (height < 1 || width < 1)
		return;

	tb = textblock_new();
	list = monster_list_shared_instance();

	/* Force an update if detected monsters */
	for (i = 1; i < cave_monster_max(cave); i++) {
		if (mflag_has(cave_monster(cave, i)->mflag, MFLAG_MARK)) {
			list->creation_turn = -1;
			break;
		}
	}

	monster_list_reset(list);
	monster_list_collect(list);
	monster_list_get_glyphs(list);
	monster_list_sort(list, monster_list_standard_compare);

	/* Draw the list to exactly fit the subwindow. */
	monster_list_format_textblock(list, tb, height, width, NULL, NULL);
	textui_textblock_place(tb, SCREEN_REGION, NULL);

	textblock_free(tb);
}
Example #2
0
/**
 * Display monster recall modally and wait for a keypress.
 *
 * This is intended to be called when the main window is active (hence the
 * message flushing).
 *
 * \param race is the monster race we are describing.
 * \param lore is the known information about the monster race.
 */
void lore_show_interactive(const monster_race *race, const monster_lore *lore)
{
	textblock *tb;
	assert(race && lore);

	event_signal(EVENT_MESSAGE_FLUSH);

	tb = textblock_new();
	lore_description(tb, race, lore, FALSE);
	textui_textblock_show(tb, SCREEN_REGION, NULL);
	textblock_free(tb);
}
Example #3
0
/**
 * Display the monster list interactively. This will dynamically size the list
 * for the best appearance. This should only be used in the main term.
 *
 * \param height is the height limit for the list.
 * \param width is the width limit for the list.
 */
void monster_list_show_interactive(int height, int width)
{
	textblock *tb;
	monster_list_t *list;
	size_t max_width = 0, max_height = 0;
	int safe_height, safe_width;
	region r;

	if (height < 1 || width < 1)
		return;

	tb = textblock_new();
	list = monster_list_new();

	monster_list_collect(list);
	monster_list_get_glyphs(list);
	monster_list_sort(list, monster_list_standard_compare);

	/* Figure out optimal display rect. Large numbers are passed as the height
	 * and width limit so that we can calculate the maximum number of rows and
	 * columns to display the list nicely. We then adjust those values as
	 * needed to fit in the main term. Height is adjusted to account for the
	 * texblock prompt. The list is positioned on the right side of the term
	 * underneath the status line.
	 */
	monster_list_format_textblock(list, NULL, 1000, 1000, &max_height,
								  &max_width);
	safe_height = MIN(height - 2, (int)max_height + 2);
	safe_width = MIN(width - 13, (int)max_width);
	r.col = -safe_width;
	r.row = 1;
	r.width = safe_width;
	r.page_rows = safe_height;

	/*
	 * Actually draw the list. We pass in max_height to the format function so
	 * that all lines will be appended to the textblock. The textblock itself
	 * will handle fitting it into the region. However, we have to pass
	 * safe_width so that the format function will pad the lines properly so
	 * that the location string is aligned to the right edge of the list.
	 */
	monster_list_format_textblock(list, tb, (int)max_height, safe_width, NULL,
								  NULL);
	region_erase_bordered(&r);
	textui_textblock_show(tb, r, NULL);

	textblock_free(tb);
	monster_list_free(list);
}
Example #4
0
/*
 * Output object information
 */
static textblock *object_info_out(const object_type *o_ptr, oinfo_detail_t mode)
{
	bool something = FALSE;

	bool full = mode & OINFO_FULL;
	bool terse = mode & OINFO_TERSE;
	bool subjective = mode & OINFO_SUBJ;
	bool ego = mode & OINFO_EGO;
	bool dummy = mode & OINFO_DUMMY;

	textblock *tb = textblock_new();

	if (subjective) describe_origin(tb, o_ptr);
	if (!terse) describe_flavor_text(tb, o_ptr);

	if (describe_set(tb, o_ptr, mode)) something = TRUE;
	if (describe_stats(tb, o_ptr, mode)) something = TRUE;
	if (describe_bonus(tb, o_ptr, mode)) something = TRUE;
	if (describe_slays(tb, o_ptr, mode)) something = TRUE;
	if (describe_brands(tb, o_ptr, mode)) something = TRUE;
	if (describe_immune(tb, o_ptr, mode)) something = TRUE;
	if (describe_sustains(tb, o_ptr, mode)) something = TRUE;
	if (describe_misc_magic(tb, o_ptr, mode)) something = TRUE;
	if (ego && describe_ego(tb, o_ptr)) something = TRUE;
	if (describe_ignores(tb, o_ptr, mode)) something = TRUE;
	if (describe_curses(tb, o_ptr, mode)) something = TRUE;
	if (describe_effect(tb, o_ptr, mode)) something = TRUE;
	
	if (subjective && describe_combat(tb, o_ptr, mode))
	{
		something = TRUE;
		textblock_append(tb, "\n");
	}

	if (!terse && describe_food(tb, o_ptr, subjective, full)) something = TRUE;
	if (describe_light(tb, o_ptr, terse)) something = TRUE;
	if (!terse && subjective && describe_digger(tb, o_ptr, mode)) something = TRUE;

	//if (!something)
	//	textblock_append(tb, "\n");
	if (!terse && !dummy) {
	    textblock_append(tb, "\n");
	    textblock_append(tb, obj_class_info[o_ptr->tval]);
	    textblock_append(tb, "\n");
	}
	return tb;
}
Example #5
0
/**
 * Display monster recall statically.
 *
 * This is intended to be called in a subwindow, since it clears the entire
 * window before drawing, and has no interactivity.
 *
 * \param race is the monster race we are describing.
 * \param lore is the known information about the monster race.
 */
void lore_show_subwindow(const monster_race *race, const monster_lore *lore)
{
	int y;
	textblock *tb;

	assert(race && lore);

	/* Erase the window, since textui_textblock_place() only clears what it
	 * needs */
	for (y = 0; y < Term->hgt; y++)
		Term_erase(0, y, 255);

	tb = textblock_new();
	lore_description(tb, race, lore, FALSE);
	textui_textblock_place(tb, SCREEN_REGION, NULL);
	textblock_free(tb);
}
Example #6
0
/**
 * Display the object list statically. This will force the list to be displayed
 * to the provided dimensions. Contents will be adjusted accordingly.
 *
 * In order to be more efficient, this function uses a shared list object so
 * that it's not constantly allocating and freeing the list.
 *
 * \param height is the height of the list.
 * \param width is the width of the list.
 */
void object_list_show_subwindow(int height, int width)
{
	textblock *tb;
	object_list_t *list;

	if (height < 1 || width < 1)
		return;

	tb = textblock_new();
	list = object_list_shared_instance();

	object_list_reset(list);
	object_list_collect(list);
	object_list_sort(list, object_list_standard_compare);

	/* Draw the list to exactly fit the subwindow. */
	object_list_format_textblock(list, tb, height, width, NULL, NULL);
	textui_textblock_place(tb, SCREEN_REGION, NULL);

	textblock_free(tb);
}
Example #7
0
/*
 * Output object information
 */
static textblock *object_info_out(const object_type *o_ptr, oinfo_detail_t mode)
{
	bitflag flags[OF_SIZE];
	bitflag pval_flags[MAX_PVALS][OF_SIZE];
	bool something = FALSE;
	bool known = object_is_known(o_ptr);

	bool full = mode & OINFO_FULL;
	bool terse = mode & OINFO_TERSE;
	bool subjective = mode & OINFO_SUBJ;
	bool ego = mode & OINFO_EGO;

	textblock *tb = textblock_new();

	/* Grab the object flags */
	if (full) {
		object_flags(o_ptr, flags);
		object_pval_flags(o_ptr, pval_flags);
	} else {
		object_flags_known(o_ptr, flags);
		object_pval_flags_known(o_ptr, pval_flags);
	}

	if (subjective) describe_origin(tb, o_ptr);
	if (!terse) describe_flavor_text(tb, o_ptr);

	if (!full && !known)
	{
		textblock_append(tb, "You do not know the full extent of this item's powers.\n");
		if (SENSING_REVEALS_FLAG_COUNT) {
			if (object_was_sensed(o_ptr)) {
				int unlearned = object_num_unlearned_flags(o_ptr);
				switch(unlearned) {
					case 0:
						textblock_append(tb, "It has no unknown flags.\n");
						break;
					case 1:
						textblock_append(tb, "It has 1 unknown flag.\n", unlearned);
						break;
					default:
						textblock_append(tb, "It has %d unknown flags.\n", unlearned);
						break;
				}
			}
		}

		something = TRUE;
	}

	if (describe_curses(tb, o_ptr, flags)) something = TRUE;
	if (describe_stats(tb, o_ptr, pval_flags, mode)) something = TRUE;
	if (describe_slays(tb, flags, o_ptr->tval)) something = TRUE;
	if (describe_immune(tb, flags)) something = TRUE;
	if (describe_ignores(tb, flags)) something = TRUE;
	if (describe_sustains(tb, flags)) something = TRUE;
	if (describe_misc_magic(tb, flags)) something = TRUE;
	if (ego && describe_ego(tb, o_ptr->ego)) something = TRUE;
	if (something) textblock_append(tb, "\n");

	if (describe_effect(tb, o_ptr, full, terse, subjective))
	{
		something = TRUE;
		textblock_append(tb, "\n");
	}

	if (subjective && describe_combat(tb, o_ptr, mode))
	{
		something = TRUE;
		textblock_append(tb, "\n");
	}

	if (!terse && describe_food(tb, o_ptr, subjective, full)) something = TRUE;
	if (describe_light(tb, o_ptr, flags, terse)) something = TRUE;
	if (!terse && subjective && describe_digger(tb, o_ptr, mode)) something = TRUE;

	if (!something)
		textblock_append(tb, "\n\nThis item does not seem to possess any special abilities.");

	return tb;
}
Example #8
0
/*
 * Output object information
 */
static textblock *object_info_out(const object_type *o_ptr, oinfo_detail_t mode)
{
	bitflag flags[OF_SIZE];
	bitflag pval_flags[MAX_PVALS][OF_SIZE];
	bool something = FALSE;
	bool known = object_is_known(o_ptr);

	bool full = mode & OINFO_FULL;
	bool terse = mode & OINFO_TERSE;
	bool subjective = mode & OINFO_SUBJ;
	bool ego = mode & OINFO_EGO;

	textblock *tb = textblock_new();

	/* Grab the object flags */
	if (full) {
		object_flags(o_ptr, flags);
		object_pval_flags(o_ptr, pval_flags);
	} else {
		object_flags_known(o_ptr, flags);
		object_pval_flags_known(o_ptr, pval_flags);
	}

	if (subjective) describe_origin(tb, o_ptr);
	if (!terse) describe_flavor_text(tb, o_ptr, mode);

	if (!full && !known)
	{
		textblock_append(tb, "You do not know the full extent of this item's powers.\n");
		something = TRUE;
	}

	if (describe_curses(tb, o_ptr, flags)) something = TRUE;
	if (describe_stats(tb, o_ptr, pval_flags, mode)) something = TRUE;
	if (describe_slays(tb, flags, o_ptr->tval)) something = TRUE;
	if (describe_immune(tb, flags)) something = TRUE;
	if (describe_ignores(tb, flags)) something = TRUE;
	dedup_hates_flags(flags);
	if (describe_hates(tb, flags)) something = TRUE;
	if (describe_sustains(tb, flags)) something = TRUE;
	if (describe_misc_magic(tb, flags)) something = TRUE;
	if (ego && describe_ego(tb, o_ptr->ego)) something = TRUE;
	if (something) textblock_append(tb, "\n");

	if (!ego && describe_effect(tb, o_ptr, full, terse, subjective)) {
		something = TRUE;
		textblock_append(tb, "\n");
	}

	if (subjective && describe_combat(tb, o_ptr, mode)) {
		something = TRUE;
		textblock_append(tb, "\n");
	}

	if (!terse && describe_food(tb, o_ptr, subjective, full)) something = TRUE;
	if (describe_light(tb, o_ptr, flags, mode)) something = TRUE;
	if (!terse && subjective && describe_digger(tb, o_ptr, mode)) something = TRUE;

	if (!something)
		textblock_append(tb, "\n\nThis item does not seem to possess any special abilities.");

	return tb;
}
Example #9
0
/**
 * Output object information
 */
static textblock *object_info_out(const struct object *obj, int mode)
{
	bitflag flags[OF_SIZE];
	struct element_info el_info[N_ELEMENTS(elements)];
	bool something = false;
	bool known = object_all_but_flavor_is_known(obj);

	bool terse = mode & OINFO_TERSE ? true : false;
	bool subjective = mode & OINFO_SUBJ ? true : false;
	bool ego = mode & OINFO_EGO ? true : false;
	textblock *tb = textblock_new();
	const struct object *known_obj = obj->known ? obj->known : obj;

	/* Unaware objects get simple descriptions */
	if (obj->kind != known_obj->kind) {
		textblock_append(tb, "\n\nYou do not know what this is.\n");
		return tb;
	}

	/* Grab the object flags */
	get_known_flags(obj, mode, flags);

	/* Grab the element info */
	get_known_elements(obj, mode, el_info);

	if (subjective) describe_origin(tb, obj, terse);
	if (!terse) describe_flavor_text(tb, obj, ego);

	if (!known)	{
		textblock_append(tb, "You do not know the full extent of this item's powers.\n");
		something = true;
	}

	if (describe_curses(tb, obj, flags)) something = true;
	if (describe_stats(tb, obj, mode)) something = true;
	if (describe_slays(tb, obj)) something = true;
	if (describe_brands(tb, obj)) something = true;
	if (describe_elements(tb, el_info)) something = true;
	if (describe_protects(tb, flags)) something = true;
	if (describe_ignores(tb, el_info)) something = true;
	if (describe_hates(tb, el_info)) something = true;
	if (describe_sustains(tb, flags)) something = true;
	if (describe_misc_magic(tb, flags)) something = true;
	if (describe_light(tb, obj, mode)) something = true;
	if (ego && describe_ego(tb, obj->ego)) something = true;
	if (something) textblock_append(tb, "\n");

	/* Skip all the very specific information where we are giving general
	   ego knowledge rather than for a single item - abilities can vary */
	if (!ego) {
		if (describe_effect(tb, obj, terse, subjective)) {
			something = true;
			textblock_append(tb, "\n");
		}
		
		if (subjective && describe_combat(tb, obj)) {
			something = true;
			textblock_append(tb, "\n");
		}
		
		if (!terse && subjective && describe_digger(tb, obj)) something = true;
	}

	/* Don't append anything in terse (for chararacter dump) */
	if (!something && !terse)
		textblock_append(tb, "\n\nThis item does not seem to possess any special abilities.");

	return tb;
}
Example #10
0
/**
 * Create a spoiler file for monsters (-SHAWN-)
 */
static void spoil_mon_info(const char *fname)
{
	char buf[1024];
	int i, n;
	u16b *who;
	int count = 0;
	textblock *tb = NULL;

	/* Open the file */
	path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
	fh = file_open(buf, MODE_WRITE, FTYPE_TEXT);

	if (!fh) {
		msg("Cannot create spoiler file.");
		return;
	}

	/* Dump the header */
	tb = textblock_new();
	textblock_append(tb, "Monster Spoilers for %s\n", buildid);
	textblock_append(tb, "------------------------------------------\n\n");
	textblock_to_file(tb, fh, 0, 75);
	textblock_free(tb);
	tb = NULL;

	/* Allocate the "who" array */
	who = mem_zalloc(z_info->r_max * sizeof(u16b));

	/* Scan the monsters */
	for (i = 1; i < z_info->r_max; i++) {
		struct monster_race *race = &r_info[i];

		/* Use that monster */
		if (race->name) who[count++] = (u16b)i;
	}

	sort(who, count, sizeof(*who), cmp_monsters);

	/* List all monsters in order. */
	for (n = 0; n < count; n++) {
		int r_idx = who[n];
		const struct monster_race *race = &r_info[r_idx];
		const struct monster_lore *lore = &l_list[r_idx];
		tb = textblock_new();

		/* Line 1: prefix, name, color, and symbol */
		if (rf_has(race->flags, RF_QUESTOR))
			textblock_append(tb, "[Q] ");
		else if (rf_has(race->flags, RF_UNIQUE))
			textblock_append(tb, "[U] ");
		else
			textblock_append(tb, "The ");

		/* As of 3.5, race->name and race->text are stored as UTF-8 strings;
		 * there is no conversion from the source edit files. */
		textblock_append_utf8(tb, race->name);
		textblock_append(tb, "  (");	/* ---)--- */
		textblock_append(tb, attr_to_text(race->d_attr));
		textblock_append(tb, " '%c')\n", race->d_char);

		/* Line 2: number, level, rarity, speed, HP, AC, exp */
		textblock_append(tb, "=== ");
		textblock_append(tb, "Num:%d  ", r_idx);
		textblock_append(tb, "Lev:%d  ", race->level);
		textblock_append(tb, "Rar:%d  ", race->rarity);

		if (race->speed >= 110)
			textblock_append(tb, "Spd:+%d  ", (race->speed - 110));
		else
			textblock_append(tb, "Spd:-%d  ", (110 - race->speed));

		textblock_append(tb, "Hp:%d  ", race->avg_hp);
		textblock_append(tb, "Ac:%d  ", race->ac);
		textblock_append(tb, "Exp:%ld\n", (long)(race->mexp));

		/* Normal description (with automatic line breaks) */
		lore_description(tb, race, lore, true);
		textblock_append(tb, "\n");

		textblock_to_file(tb, fh, 0, 75);
		textblock_free(tb);
		tb = NULL;
	}

	/* Free the "who" array */
	mem_free(who);

	/* Check for errors */
	if (!file_close(fh)) {
		msg("Cannot close spoiler file.");
		return;
	}

	msg("Successfully created a spoiler file.");
}
Example #11
0
int edit_text(char *buffer, int buflen) {
	int len = strlen(buffer);
	bool done = FALSE;
	int cursor = 0;

	while (!done) {
		int x, y;
		struct keypress ke;

		region area = { 1, HIST_INSTRUCT_ROW + 1, 71, 5 };
		textblock *tb = textblock_new();

		size_t *line_starts = NULL, *line_lengths = NULL;
		size_t n_lines;

		/* Display on screen */
		clear_from(HIST_INSTRUCT_ROW);
		textblock_append(tb, buffer);
		textblock_append(tb, "\n"); /* XXX This shouldn't be necessary */
		textui_textblock_place(tb, area, NULL);

		n_lines = textblock_calculate_lines(tb,
				&line_starts, &line_lengths, area.width);

		/* Set cursor to current editing position */
		get_screen_loc(cursor, &x, &y, n_lines, line_starts, line_lengths);
		Term_gotoxy(1 + x, 19 + y);

		ke = inkey();
		switch (ke.code) {
			case ESCAPE:
				return -1;

			case KC_ENTER:
				done = TRUE;
				break;

			case ARROW_LEFT:
				if (cursor > 0) cursor--;
				break;

			case ARROW_RIGHT:
				if (cursor < len) cursor++;
				break;

			case ARROW_DOWN: {
				int add = line_lengths[y] + 1;
				if (cursor + add < len) cursor += add;
				break;
			}

			case ARROW_UP:
				if (y > 0) {
					int up = line_lengths[y - 1] + 1;
					if (cursor - up >= 0) cursor -= up;
				}
				break;

			case KC_END:
				cursor = MAX(0, len);
				break;

			case KC_HOME:
				cursor = 0;
				break;

			case KC_BACKSPACE:
			case KC_DELETE: {
				/* Refuse to backspace into oblivion */
				if ((ke.code == KC_BACKSPACE && cursor == 0) ||
						(ke.code == KC_DELETE && cursor >= len))
					break;

				/* Move the string from k to nul along to the left by 1 */
				if (ke.code == KC_BACKSPACE)
					memmove(&buffer[cursor - 1], &buffer[cursor], len - cursor);
				else
					memmove(&buffer[cursor], &buffer[cursor + 1], len - cursor - 1);

				/* Decrement */
				if (ke.code == KC_BACKSPACE)
					cursor--;
				len--;

				/* Terminate */
				buffer[len] = '\0';

				break;
			}
			
			default: {
				bool atnull = (buffer[cursor] == 0);

				if (!isprint(ke.code))
					break;

				if (atnull) {
					/* Make sure we have enough room for a new character */
					if ((cursor + 1) >= buflen) break;
				} else {
					/* Make sure we have enough room to add a new character */
					if ((cursor + 1) >= buflen) break;

					/* Move the rest of the buffer along to make room */
					memmove(&buffer[cursor + 1], &buffer[cursor], len - cursor);
				}

				/* Insert the character */
				buffer[cursor++] = (char)ke.code;
				len++;

				/* Terminate */
				buffer[len] = '\0';

				break;
			}
		}

		textblock_free(tb);
	}

	return 0;
}