Esempio n. 1
0
/**
 * Handle a "-d<dir>=<path>" option.
 *
 * Sets any of angband's special directories to <path>.
 *
 * The "<path>" can be any legal path for the given system, and should
 * not end in any special path separator (i.e. "/tmp" or "~/.ang-info").
 */
static void change_path(const char *info)
{
	char *info_copy = NULL;
	char *path = NULL;
	char *dir = NULL;
	unsigned int i = 0;
	char dirpath[512];

	if (!info || !info[0])
		quit_fmt("Try '-d<dir>=<path>'.", info);

	info_copy = string_make(info);
	path = strtok(info_copy, "=");
	dir = strtok(NULL, "=");

	for (i = 0; i < N_ELEMENTS(change_path_values); i++) {
		if (my_stricmp(path, change_path_values[i].name) == 0) {
#ifdef SETGID
			if (!change_path_values[i].setgid_ok)
				quit_fmt("Can't redefine path to %s dir on multiuser setup",
						 path);
#endif

			string_free(*change_path_values[i].path);
			*change_path_values[i].path = string_make(dir);

			/* the directory may not exist and may need to be created. */
			path_build(dirpath, sizeof(dirpath), dir, "");
			if (!dir_create(dirpath)) quit_fmt("Cannot create '%s'", dirpath);
			return;
		}
	}

	quit_fmt("Unrecognised -d paramater %s", path);
}
Esempio n. 2
0
/*
 * Handle a "-d<what>=<path>" option
 *
 * The "<what>" can be any string starting with the same letter as the
 * name of a subdirectory of the "lib" folder (i.e. "i" or "info").
 *
 * The "<path>" can be any legal path for the given system, and should
 * not end in any special path separator (i.e. "/tmp" or "~/.ang-info").
 */
static void change_path(const char *info)
{
	if (!info || !info[0])
		quit_fmt("Try '-d<path>'.", info);

	string_free(ANGBAND_DIR_USER);
	ANGBAND_DIR_USER = string_make(info);
}
Esempio n. 3
0
/* More angband-specific bits of the parser
 * These require hooks into other parts of the code, and are a candidate for
 * moving elsewhere.
 */
static void print_error(struct file_parser *fp, struct parser *p) {
	struct parser_state s;
	parser_getstate(p, &s);
	msg("Parse error in %s line %d column %d: %s: %s", fp->name,
	           s.line, s.col, s.msg, parser_error_str[s.error]);
	message_flush();
	quit_fmt("Parse error in %s line %d column %d.", fp->name, s.line, s.col);
}
Esempio n. 4
0
/*
 * Handle a "-d<what>=<path>" option
 *
 * The "<what>" can be any string starting with the same letter as the
 * name of a subdirectory of the "lib" folder (i.e. "i" or "info").
 *
 * The "<path>" can be any legal path for the given system, and should
 * not end in any special path separator (i.e. "/tmp" or "~/.ang-info").
 */
static void change_path(cptr info)
{
	if (!info || !info[0])
		quit_fmt("Try '-d<path>'.", info);

	string_free(reposband_DIR_USER);
	reposband_DIR_USER = string_make(info);
}
Esempio n. 5
0
static void print_error(struct file_parser *fp, struct parser *p) {
	struct parser_state s;
	parser_getstate(p, &s);
	msg("Parse error in %s line %d column %d: %s: %s", fp->name,
	           s.line, s.col, s.msg, parser_error_str[s.error]);
	event_signal(EVENT_MESSAGE_FLUSH);
	quit_fmt("Parse error in %s line %d column %d.", fp->name, s.line, s.col);
}
Esempio n. 6
0
/*
 * Process the player name and extract a clean "base name".
 *
 * If "sf" is TRUE, then we initialize "savefile" based on player name.
 *
 * Some platforms (Windows, Macintosh, Amiga) leave the "savefile" empty
 * when a new character is created, and then when the character is done
 * being created, they call this function to choose a new savefile name.
 *
 * This also now handles the turning on and off of the automatic
 * sequential numbering of character names with Roman numerals.  
 */
void process_player_name(bool sf)
{
	int i;

	/* Process the player name */
	for (i = 0; op_ptr->full_name[i]; i++)
	{
		char c = op_ptr->full_name[i];

		/* No control characters */
		if (iscntrl((unsigned char)c))
		{
			/* Illegal characters */
			quit_fmt("Illegal control char (0x%02X) in player name", c);
		}

		/* Convert all non-alphanumeric symbols */
		if (!isalpha((unsigned char)c) && !isdigit((unsigned char)c)) c = '_';

		/* Build "base_name" */
		op_ptr->base_name[i] = c;
	}

#if defined(WINDOWS)

	/* Max length */
	if (i > 8) i = 8;

#endif

	/* Terminate */
	op_ptr->base_name[i] = '\0';

	/* Require a "base" name */
	if (!op_ptr->base_name[0])
	{
		my_strcpy(op_ptr->base_name, "PLAYER", sizeof(op_ptr->base_name));
	}


	/* Pick savefile name if needed */
	if (sf)
	{
		char temp[128];

#if defined(SET_UID)
		/* Rename the savefile, using the player_uid and base_name */
		strnfmt(temp, sizeof(temp), "%d.%s", player_uid, op_ptr->base_name);
#else
		/* Rename the savefile, using the base name */
		strnfmt(temp, sizeof(temp), "%s", op_ptr->base_name);
#endif

		/* Build the filename */
		path_build(savefile, sizeof(savefile), reposband_DIR_SAVE, temp);
	}
}
Esempio n. 7
0
static struct parser_value *parser_getval(struct parser *p, const char *name) {
	struct parser_value *v;
	for (v = p->fhead; v; v = (struct parser_value *)v->spec.next) {
		if (!strcmp(v->spec.name, name)) {
			return v;
		}
	}
	quit_fmt("parser_getval error: name is %s\n", name);
	return 0; /* Needed to avoid Windows compiler warning */
}
Esempio n. 8
0
/*
 * Create any missing directories. We create only those dirs which may be
 * empty (user/, save/, apex/, info/, help/). The others are assumed 
 * to contain required files and therefore must exist at startup 
 * (edit/, pref/, file/, xtra/).
 *
 * ToDo: Only create the directories when actually writing files.
 */
void create_needed_dirs(void)
{
	char dirpath[512];

	path_build(dirpath, sizeof(dirpath), ANGBAND_DIR_USER, "");
	if (!dir_create(dirpath)) quit_fmt("Cannot create '%s'", dirpath);

	path_build(dirpath, sizeof(dirpath), ANGBAND_DIR_SAVE, "");
	if (!dir_create(dirpath)) quit_fmt("Cannot create '%s'", dirpath);

	path_build(dirpath, sizeof(dirpath), ANGBAND_DIR_APEX, "");
	if (!dir_create(dirpath)) quit_fmt("Cannot create '%s'", dirpath);

	path_build(dirpath, sizeof(dirpath), ANGBAND_DIR_INFO, "");
	if (!dir_create(dirpath)) quit_fmt("Cannot create '%s'", dirpath);

	path_build(dirpath, sizeof(dirpath), ANGBAND_DIR_HELP, "");
	if (!dir_create(dirpath)) quit_fmt("Cannot create '%s'", dirpath);
}
Esempio n. 9
0
static errr finish_parse_r(struct parser *p) {
	struct monster_race *r, *n;
	size_t i;

	/* scan the list for the max id */
	z_info->r_max -= 1;
	/*z_info->r_max = 0; fails to load existing save file because of
	 * too high value in old limits.txt.  Change to this line when save file 
	 * compatibility changes and remove line from limits.txt */ 
	r = parser_priv(p);
	while (r) {
		if (r->ridx > z_info->r_max)
			z_info->r_max = r->ridx;
		r = r->next;
	}

	/* allocate the direct access list and copy the data to it */
	r_info = mem_zalloc((z_info->r_max+1) * sizeof(*r));
	for (r = parser_priv(p); r; r = n) {
		memcpy(&r_info[r->ridx], r, sizeof(*r));
		n = r->next;
		if (n)
			r_info[r->ridx].next = &r_info[n->ridx];
		else
			r_info[r->ridx].next = NULL;

		mem_free(r);
	}
	z_info->r_max += 1;

	/* convert friend names into race pointers */
	for (i = 0; i < z_info->r_max; i++) {
		struct monster_race *r = &r_info[i];
		struct monster_friends *f;
		for (f = r->friends; f; f = f->next) {
			if (!my_stricmp(f->name, "same"))
				f->race = r;
			else
				f->race = lookup_monster(f->name);

			if (!f->race)
				quit_fmt("Monster '%s' has friend '%s' but I couldn't find any monster of that name",
						r->name, f->name);

			string_free(f->name);
		}
	}

	eval_r_power(r_info);

	parser_destroy(p);
	return 0;
}
Esempio n. 10
0
const struct magic_realm *lookup_realm(const char *name)
{
	struct magic_realm *realm = realms;
	while (realm) {
		if (!my_stricmp(name, realm->name)) {
			return realm;
		}
		realm = realm->next;
	}

	/* Fail horribly */
	quit_fmt("Failed to find %s magic realm", name);
	return realm;
}
Esempio n. 11
0
/*
 * Display a parser error message.
 */
static void display_parse_error(cptr filename, errr err, cptr buf)
{
	cptr oops;

	/* Error string */
	oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");

	/* Oops */
	msg_format("Error at line %d of '%s.txt'.", error_line, filename);
	msg_format("Record %d contains a '%s' error.", error_idx, oops);
	msg_format("Parsing '%s'.", buf);
	message_flush();

	/* Quit */
	quit_fmt("Error in '%s.txt' file.", filename);
}
Esempio n. 12
0
/**
 * Find a terrain feature index by name
 */
static int lookup_feat(const char *name)
{
	int i;

	/* Look for it */
	for (i = 0; i < z_info->f_max; i++) {
		struct feature *feat = &f_info[i];
		if (!feat->name)
			continue;

		/* Test for equality */
		if (streq(name, feat->name))
			return i;
	}

	/* Fail horribly */
	quit_fmt("Failed to find terrain feature %s", name);
	return -1;
}
Esempio n. 13
0
bool flag_has_dbg(const bitflag *flags, const size_t size, const int flag, const char *fi, const char *fl)
{
	const size_t flag_offset = FLAG_OFFSET(flag);
	const int flag_binary = FLAG_BINARY(flag);

	if (flag == FLAG_END) return FALSE;

	if (flag_offset >= size)
	{
		quit_fmt("Error in flag_has(%s, %s): FlagID[%d] Size[%u] FlagOff[%u] FlagBV[%d]\n",
		         fi, fl, flag, (unsigned int) size, (unsigned int) flag_offset, flag_binary);
	}

	assert(flag_offset < size);

	if (flags[flag_offset] & flag_binary) return TRUE;

	return FALSE;
}
Esempio n. 14
0
/**
 * Move an object from a floor pile to the player's gear
 */
static void player_pickup_aux(struct object *obj, bool domsg)
{
	/* Confirm the object can be picked up*/
	if (!inven_carry_okay(obj))
		quit_fmt("Failed pickup of %s", obj->kind->name);

	/* Set ignore status */
	player->upkeep->notice |= PN_IGNORE;

	/* Automatically sense artifacts */
	object_sense_artifact(obj);

	/* Log artifacts if found */
	if (obj->artifact)
		history_add_artifact(obj->artifact, object_is_known(obj), TRUE);

	/* Carry the object */
	square_excise_object(cave, player->py, player->px, obj);
	inven_carry(player, obj, domsg);
}
Esempio n. 15
0
bool flag_on_dbg(bitflag *flags, const size_t size, const int flag, const char *fi, const char *fl)
{
	const size_t flag_offset = FLAG_OFFSET(flag);
	const int flag_binary = FLAG_BINARY(flag);

	/* EFG this assert needs to be in most functions, or else the need for
	 * it removed.  Without it, got a crash with no ability to backtrace. */
	assert (flag >= FLAG_START);

	if (flag_offset >= size)
	{
		quit_fmt("Error in flag_on(%s, %s): FlagID[%d] Size[%u] FlagOff[%u] FlagBV[%d]\n",
		         fi, fl, flag, (unsigned int) size, (unsigned int) flag_offset, flag_binary);
	}

	assert(flag_offset < size);

	if (flags[flag_offset] & flag_binary) return FALSE;

	flags[flag_offset] |= flag_binary;

	return TRUE;
}
Esempio n. 16
0
static enum parser_error parse_rb_f(struct parser *p) {
	struct monster_base *rb = parser_priv(p);
	char *flags;
	char *s;

	if (!rb)
		return PARSE_ERROR_MISSING_RECORD_HEADER;
	if (!parser_hasval(p, "flags"))
		return PARSE_ERROR_NONE;
	flags = string_make(parser_getstr(p, "flags"));
	s = strtok(flags, " |");
	while (s) {
		if (grab_flag(rb->flags, RF_SIZE, r_info_flags, s)) {
			mem_free(flags);
			quit_fmt("bad f-flag: %s", s);
			return PARSE_ERROR_INVALID_FLAG;
		}
		s = strtok(NULL, " |");
	}

	mem_free(flags);
	return PARSE_ERROR_NONE;
}
Esempio n. 17
0
/**
 * List all savefiles this player can access.
 */
static void list_saves(void)
{
	char fname[256];
	ang_dir *d = my_dopen(ANGBAND_DIR_SAVE);

#ifdef SETGID
	char uid[10];
	strnfmt(uid, sizeof(uid), "%d.", player_uid);
#endif

	if (!d) quit_fmt("Can't open savefile directory");

	printf("Savefiles you can use are:\n");

	while (my_dread(d, fname, sizeof fname)) {
		char path[1024];
		const char *desc;

#ifdef SETGID
		/* Check that the savefile name begins with the user'd ID */
		if (strncmp(fname, uid, strlen(uid)))
			continue;
#endif

		path_build(path, sizeof path, ANGBAND_DIR_SAVE, fname);
		desc = savefile_get_description(path);

		if (desc)
			printf(" %-15s  %s\n", fname, desc);
		else
			printf(" %-15s\n", fname);
	}

	my_dclose(d);

	printf("\nUse angband -u<name> to use savefile <name>.\n");
}
Esempio n. 18
0
static enum parser_error parse_r_s(struct parser *p) {
	struct monster_race *r = parser_priv(p);
	char *flags;
	char *s;
	int pct;
	int ret = PARSE_ERROR_NONE;

	if (!r)
		return PARSE_ERROR_MISSING_RECORD_HEADER;
	flags = string_make(parser_getstr(p, "spells"));
	s = strtok(flags, " |");
	while (s) {
		if (1 == sscanf(s, "1_IN_%d", &pct)) {
			if (pct < 1 || pct > 100) {
				ret = PARSE_ERROR_INVALID_SPELL_FREQ;
				break;
			}
			r->freq_spell = 100 / pct;
			r->freq_innate = r->freq_spell;
		} else {
			if (grab_flag(r->spell_flags, RSF_SIZE, r_info_spell_flags, s)) {
				quit_fmt("bad sf-flag: %s", s);
				ret = PARSE_ERROR_INVALID_FLAG;
				break;
			}
		}
		s = strtok(NULL, " |");
	}

	/* Add the "base monster" flags to the monster */
	if (r->base)
		rsf_union(r->spell_flags, r->base->spell_flags);

	mem_free(flags);
	return ret;
}
Esempio n. 19
0
/*
 * Read a Win32 BMP file.
 *
 * Assumes that the bitmap has a size such that no padding is needed in
 * various places.  Currently only handles bitmaps with 3 to 256 colors.
 */
static byte *ReadBMP(char *Name, int *bw, int *bh)
{
	FILE *f;

	BITMAPFILEHEADER fileheader;
	BITMAPINFOHEADER infoheader;

	byte *Data;

	int ncol;

	int total;

	int i;

	u16b x, y;

	/* Open the BMP file */
	f = fopen(Name, "r");

	/* No such file */
	if (!f)
	{
		quit ("No bitmap to load!");
	}

	/* Read the "BITMAPFILEHEADER" */
	rd_u16b(f, &(fileheader.bfType));
	rd_u32b(f, &(fileheader.bfSize));
	rd_u16b(f, &(fileheader.bfReserved1));
	rd_u16b(f, &(fileheader.bfReserved2));
	rd_u32b(f, &(fileheader.bfOffBits));

	/* Read the "BITMAPINFOHEADER" */
	rd_u32b(f, &(infoheader.biSize));
	rd_u32b(f, &(infoheader.biWidth));
	rd_u32b(f, &(infoheader.biHeight));
	rd_u16b(f, &(infoheader.biPlanes));
	rd_u16b(f, &(infoheader.biBitCount));
	rd_u32b(f, &(infoheader.biCompresion));
	rd_u32b(f, &(infoheader.biSizeImage));
	rd_u32b(f, &(infoheader.biXPelsPerMeter));
	rd_u32b(f, &(infoheader.biYPelsPerMeter));
	rd_u32b(f, &(infoheader.biClrUsed));
	rd_u32b(f, &(infoheader.biClrImportand));

	/* Verify the header */
	if (feof(f) ||
	                (fileheader.bfType != 19778) ||
	                (infoheader.biSize != 40))
	{
		quit_fmt("Incorrect BMP file format %s", Name);
	}

	/* The two headers above occupy 54 bytes total */
	/* The "bfOffBits" field says where the data starts */
	/* The "biClrUsed" field does not seem to be reliable */
	/* Compute number of colors recorded */
	ncol = (fileheader.bfOffBits - 54) / 4;

	for (i = 0; i < ncol; i++)
	{
		RGBQUAD clrg;

		/* Read an "RGBQUAD" */
		rd_byte(f, &(clrg.b));
		rd_byte(f, &(clrg.g));
		rd_byte(f, &(clrg.r));
		rd_byte(f, &(clrg.filler));

		/* Analyze the color */
		pal[i * 3] = clrg.b;
		pal[i * 3 + 1] = clrg.g;
		pal[i * 3 + 2] = clrg.r;
	}

	/* Look for illegal bitdepths. */
	if ((infoheader.biBitCount == 1) || (infoheader.biBitCount == 24))
	{
		quit_fmt("Illegal biBitCount %d in %s",
		         infoheader.biBitCount, Name);
	}

	/* Determine total bytes needed for image */
	total = infoheader.biWidth * (infoheader.biHeight + 2);

	/* Allocate image memory */
	C_MAKE(Data, total, byte);

	for (y = 0; y < infoheader.biHeight; y++)
	{
		int y2 = infoheader.biHeight - y - 1;

		for (x = 0; x < infoheader.biWidth; x++)
		{
			int ch = getc(f);

			/* Verify not at end of file XXX XXX */
			if (feof(f)) quit_fmt("Unexpected end of file in %s", Name);

			if (infoheader.biBitCount == 8)
			{
				Data[x + y2 * infoheader.biWidth] = ch;
			}
			else if (infoheader.biBitCount == 4)
			{
				Data[x + y2 * infoheader.biWidth] = ch / 16;
				x++;
				Data[x + y2 * infoheader.biWidth] = ch % 16;
			}
		}
	}

	fclose(f);

	/* Save the size for later */
	*bw = infoheader.biWidth;
	*bh = infoheader.biHeight;

	return (Data);
}
Esempio n. 20
0
/*
 * Handle a "-d<what>=<path>" option
 *
 * The "<what>" can be any string starting with the same letter as the
 * name of a subdirectory of the "lib" folder (i.e. "i" or "info").
 *
 * The "<path>" can be any legal path for the given system, and should
 * not end in any special path separator (i.e. "/tmp" or "~/.ang-info").
 */
static void change_path(cptr info)
{
	cptr s;

	/* Find equal sign */
	s = strchr(info, '=');

	/* Verify equal sign */
	if (!s) quit_fmt("Try '-d<what>=<path>' not '-d%s'", info);

	/* Analyze */
	switch (tolower(info[0]))
	{
		case 'a':
		{
			string_free(ANGBAND_DIR_APEX);
			ANGBAND_DIR_APEX = string_make(s+1);
			break;
		}

		case 'f':
		{
			string_free(ANGBAND_DIR_FILE);
			ANGBAND_DIR_FILE = string_make(s+1);
			break;
		}

		case 'h':
		{
			string_free(ANGBAND_DIR_HELP);
			ANGBAND_DIR_HELP = string_make(s+1);
			break;
		}

		case 'i':
		{
			string_free(ANGBAND_DIR_INFO);
			ANGBAND_DIR_INFO = string_make(s+1);
			break;
		}

		case 'u':
		{
			string_free(ANGBAND_DIR_USER);
			ANGBAND_DIR_USER = string_make(s+1);
			break;
		}

		case 'x':
		{
			string_free(ANGBAND_DIR_XTRA);
			ANGBAND_DIR_XTRA = string_make(s+1);
			break;
		}

#ifdef VERIFY_SAVEFILE

		case 'b':
		case 'd':
		case 'e':
		case 's':
		{
			quit_fmt("Restricted option '-d%s'", info);
		}

#else /* VERIFY_SAVEFILE */

		case 'b':
		{
			string_free(ANGBAND_DIR_BONE);
			ANGBAND_DIR_BONE = string_make(s+1);
			break;
		}

		case 'd':
		{
			string_free(ANGBAND_DIR_DATA);
			ANGBAND_DIR_DATA = string_make(s+1);
			break;
		}

		case 'e':
		{
			string_free(ANGBAND_DIR_EDIT);
			ANGBAND_DIR_EDIT = string_make(s+1);
			break;
		}

		case 's':
		{
			string_free(ANGBAND_DIR_SAVE);
			ANGBAND_DIR_SAVE = string_make(s+1);
			break;
		}

		case 'z':
		{
			string_free(ANGBAND_DIR_SCRIPT);
			ANGBAND_DIR_SCRIPT = string_make(s+1);
			break;
		}

#endif /* VERIFY_SAVEFILE */

		default:
		{
			quit_fmt("Bad semantics in '-d%s'", info);
		}
	}
}
Esempio n. 21
0
/*
 * Process the player name and extract a clean "base name".
 *
 * If "sf" is TRUE, then we initialize "savefile" based on player name.
 *
 * Some platforms (Windows, Macintosh, Amiga) leave the "savefile" empty
 * when a new character is created, and then when the character is done
 * being created, they call this function to choose a new savefile name.
 */
void process_player_name(bool sf)
{
	int i;


	/* Process the player name */
	for (i = 0; op_ptr->full_name[i]; i++)
	{
		char c = op_ptr->full_name[i];

		/* No control characters */
		if (iscntrl((unsigned char)c))
		{
			/* Illegal characters */
			quit_fmt("Illegal control char (0x%02X) in player name", c);
		}

		/* Convert all non-alphanumeric symbols */
		if (!isalpha((unsigned char)c) && !isdigit((unsigned char)c)) c = '_';

		/* Build "base_name" */
		op_ptr->base_name[i] = c;
	}

#if defined(WINDOWS) || defined(MSDOS)

	/* Max length */
	if (i > 8) i = 8;

#endif

	/* Terminate */
	op_ptr->base_name[i] = '\0';

	/* Require a "base" name */
	if (!op_ptr->base_name[0])
	{
		strcpy(op_ptr->base_name, "PLAYER");
	}


	/* Pick savefile name if needed */
	if (sf)
	{
		char temp[128];

#ifdef SAVEFILE_USE_UID
		/* Rename the savefile, using the player_uid and base_name */
		strnfmt(temp, sizeof(temp), "%d.%s", player_uid, op_ptr->base_name);
#else
		/* Rename the savefile, using the base name */
		strnfmt(temp, sizeof(temp), "%s", op_ptr->base_name);
#endif

#ifdef VM
		/* Hack -- support "flat directory" usage on VM/ESA */
		strnfmt(temp, sizeof(temp), "%s.sv", op_ptr->base_name);
#endif /* VM */

		/* Build the filename */
		path_build(savefile, sizeof(savefile), ANGBAND_DIR_SAVE, temp);
	}
}
Esempio n. 22
0
/**
 * Generate a random level.
 *
 * Confusingly, this function also generate the town level (level 0).
 * \param c is the level we're going to end up with, in practice the global cave
 * \param p is the current player struct, in practice the global player
 */
void cave_generate(struct chunk **c, struct player *p) {
	const char *error = "no generation";
	int y, x, tries = 0;
	struct chunk *chunk;

	assert(c);

	/* Generate */
	for (tries = 0; tries < 100 && error; tries++) {
		struct dun_data dun_body;

		error = NULL;

		/* Mark the dungeon as being unready (to avoid artifact loss, etc) */
		character_dungeon = FALSE;

		/* Allocate global data (will be freed when we leave the loop) */
		dun = &dun_body;
		dun->cent = mem_zalloc(z_info->level_room_max * sizeof(struct loc));
		dun->door = mem_zalloc(z_info->level_door_max * sizeof(struct loc));
		dun->wall = mem_zalloc(z_info->wall_pierce_max * sizeof(struct loc));
		dun->tunn = mem_zalloc(z_info->tunn_grid_max * sizeof(struct loc));

		/* Choose a profile and build the level */
		dun->profile = choose_profile(p->depth);
		chunk = dun->profile->builder(p);
		if (!chunk) {
			error = "Failed to find builder";
			mem_free(dun->cent);
			mem_free(dun->door);
			mem_free(dun->wall);
			mem_free(dun->tunn);
			continue;
		}

		/* Ensure quest monsters */
		if (is_quest(chunk->depth)) {
			int i;
			for (i = 1; i < z_info->r_max; i++) {
				monster_race *r_ptr = &r_info[i];
				int y, x;
				
				/* The monster must be an unseen quest monster of this depth. */
				if (r_ptr->cur_num > 0) continue;
				if (!rf_has(r_ptr->flags, RF_QUESTOR)) continue;
				if (r_ptr->level != chunk->depth) continue;
	
				/* Pick a location and place the monster */
				find_empty(chunk, &y, &x);
				place_new_monster(chunk, y, x, r_ptr, TRUE, TRUE, ORIGIN_DROP);
			}
		}

		/* Clear generation flags. */
		for (y = 0; y < chunk->height; y++) {
			for (x = 0; x < chunk->width; x++) {
				sqinfo_off(chunk->squares[y][x].info, SQUARE_WALL_INNER);
				sqinfo_off(chunk->squares[y][x].info, SQUARE_WALL_OUTER);
				sqinfo_off(chunk->squares[y][x].info, SQUARE_WALL_SOLID);
				sqinfo_off(chunk->squares[y][x].info, SQUARE_MON_RESTRICT);
			}
		}

		/* Regenerate levels that overflow their maxima */
		if (cave_monster_max(chunk) >= z_info->level_monster_max)
			error = "too many monsters";

		if (error) ROOM_LOG("Generation restarted: %s.", error);

		mem_free(dun->cent);
		mem_free(dun->door);
		mem_free(dun->wall);
		mem_free(dun->tunn);
	}

	if (error) quit_fmt("cave_generate() failed 100 times!");

	/* Free the old cave, use the new one */
	if (*c)
		cave_free(*c);
	*c = chunk;

	/* Place dungeon squares to trigger feeling (not in town) */
	if (player->depth)
		place_feeling(*c);

	/* Save the town */
	else if (!chunk_find_name("Town")) {
		struct chunk *town = chunk_write(0, 0, z_info->town_hgt,
										 z_info->town_wid, FALSE, FALSE, FALSE);
		town->name = string_make("Town");
		chunk_list_add(town);
	}

	(*c)->feeling = calc_obj_feeling(*c) + calc_mon_feeling(*c);

	/* Validate the dungeon (we could use more checks here) */
	chunk_validate_objects(*c);

	/* The dungeon is ready */
	character_dungeon = TRUE;

	/* Free old and allocate new known level */
	if (cave_k)
		cave_free(cave_k);
	cave_k = cave_new(cave->height, cave->width);
	if (!cave->depth)
		cave_known();

	(*c)->created_at = turn;
}
Esempio n. 23
0
/*
 * Initialize a term_data
 */
static errr term_data_init(term_data *td, int i)
{
	term *t = &td->t;

	cptr name = angband_term_name[i];

	cptr font;

	int x = 0;
	int y = 0;

	int cols = 80;
	int rows = 24;

	int ox = 1;
	int oy = 1;

	int wid, hgt, num;

	char buf[80];

	cptr str;

	int val;

	XClassHint *ch;

	char res_name[20];
	char res_class[20];

	XSizeHints *sh;

	/* Get default font for this term */
	font = get_default_font(i);

	/* Window specific location (x) */
	sprintf(buf, "ANGBAND_X11_AT_X_%d", i);
	str = getenv(buf);
	x = (str != NULL) ? atoi(str) : -1;

	/* Window specific location (y) */
	sprintf(buf, "ANGBAND_X11_AT_Y_%d", i);
	str = getenv(buf);
	y = (str != NULL) ? atoi(str) : -1;

	/* Window specific cols */
	sprintf(buf, "ANGBAND_X11_COLS_%d", i);
	str = getenv(buf);
	val = (str != NULL) ? atoi(str) : -1;
	if (val > 0) cols = val;

	/* Window specific rows */
	sprintf(buf, "ANGBAND_X11_ROWS_%d", i);
	str = getenv(buf);
	val = (str != NULL) ? atoi(str) : -1;
	if (val > 0) rows = val;

	/* Hack the main window must be at least 80x24 */
	if (!i)
	{
		if (cols < 80) cols = 80;
		if (rows < 24) rows = 24;
	}

	/* Window specific inner border offset (ox) */
	sprintf(buf, "ANGBAND_X11_IBOX_%d", i);
	str = getenv(buf);
	val = (str != NULL) ? atoi(str) : -1;
	if (val > 0) ox = val;

	/* Window specific inner border offset (oy) */
	sprintf(buf, "ANGBAND_X11_IBOY_%d", i);
	str = getenv(buf);
	val = (str != NULL) ? atoi(str) : -1;
	if (val > 0) oy = val;


	/* Prepare the standard font */
	MAKE(td->fnt, infofnt);
	Infofnt_set(td->fnt);
	if (Infofnt_init_data(font)) quit_fmt("Couldn't load the requested font. (%s)", font);

	/* Hack -- key buffer size */
	num = ((i == 0) ? 1024 : 16);

	/* Assume full size windows */
	wid = cols * td->fnt->wid + (ox + ox);
	hgt = rows * td->fnt->hgt + (oy + oy);

	/* Create a top-window */
	MAKE(td->win, infowin);
	Infowin_set(td->win);
	Infowin_init_top(x, y, wid, hgt, 0,
	                 Metadpy->fg, Metadpy->bg);

	/* Ask for certain events */
	Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask);

	/* Set the window name */
	Infowin_set_name(name);

	/* Save the inner border */
	Infowin->ox = ox;
	Infowin->oy = oy;

	/* Make Class Hints */
	ch = XAllocClassHint();

	if (ch == NULL) quit("XAllocClassHint failed");

	my_strcpy(res_name, name, sizeof(res_name));
	res_name[0] = FORCELOWER(res_name[0]);
	ch->res_name = res_name;

	strcpy(res_class, "Angband");
	ch->res_class = res_class;

	XSetClassHint(Metadpy->dpy, Infowin->win, ch);

	/* Make Size Hints */
	sh = XAllocSizeHints();

	/* Oops */
	if (sh == NULL) quit("XAllocSizeHints failed");

	/* Main window has a differing minimum size */
	if (i == 0)
	{
		/* Main window min size is 80x24 */
		sh->flags = PMinSize | PMaxSize;
		sh->min_width = 80 * td->fnt->wid + (ox + ox);
		sh->min_height = 24 * td->fnt->hgt + (oy + oy);
		sh->max_width = 255 * td->fnt->wid + (ox + ox);
		sh->max_height = 255 * td->fnt->hgt + (oy + oy);
	}

	/* Other windows can be shrunk to 1x1 */
	else
	{
		/* Other windows */
		sh->flags = PMinSize | PMaxSize;
		sh->min_width = td->fnt->wid + (ox + ox);
		sh->min_height = td->fnt->hgt + (oy + oy);
		sh->max_width = 255 * td->fnt->wid + (ox + ox);
		sh->max_height = 255 * td->fnt->hgt + (oy + oy);
	}

	/* Resize increment */
	sh->flags |= PResizeInc;
	sh->width_inc = td->fnt->wid;
	sh->height_inc = td->fnt->hgt;

	/* Base window size */
	sh->flags |= PBaseSize;
	sh->base_width = (ox + ox);
	sh->base_height = (oy + oy);

	/* Use the size hints */
	XSetWMNormalHints(Metadpy->dpy, Infowin->win, sh);

	/* Map the window */
	Infowin_map();


	/* Move the window to requested location */
	if ((x >= 0) && (y >= 0)) Infowin_impell(x, y);


	/* Initialize the term */
	term_init(t, cols, rows, num);

	/* Use a "soft" cursor */
	t->soft_cursor = TRUE;

	/* Erase with "white space" */
	t->attr_blank = TERM_WHITE;
	t->char_blank = ' ';

	/* Hooks */
	t->xtra_hook = Term_xtra_x11;
	t->curs_hook = Term_curs_x11;
	t->bigcurs_hook = Term_bigcurs_x11;
	t->wipe_hook = Term_wipe_x11;
	t->text_hook = Term_text_x11;

	/* Save the data */
	t->data = td;

	/* Activate (important) */
	Term_activate(t);

	/* Success */
	return (0);
}