/* File: monster2.c */

/*
 * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
 *
 * 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.  Other copyrights may also apply.
 */

#include "angband.h"

/*
 * Delete a monster by index.
 *
 * When a monster is deleted, all of its objects are deleted.
 */
void delete_monster_idx(int i)
{
	int x, y;

	monster_type *m_ptr = &m_list[i];

	monster_race *r_ptr = &r_info[m_ptr->r_idx];

	s16b this_o_idx, next_o_idx = 0;

	/* Get location */
	y = m_ptr->fy;
	x = m_ptr->fx;

	/* Hack -- Reduce the racial counter */
	r_ptr->cur_num--;

	/* Hack -- count the number of "reproducers" */
	if (r_ptr->flags2 & (RF2_MULTIPLY)) num_repro--;

	/* Hack -- remove target monster */
	if (p_ptr->target_who == i) target_set_monster(0);

	/* Hack -- remove tracked monster */
	if (p_ptr->health_who == i) health_track(0);

	/* Monster is gone */
	cave_m_idx[y][x] = 0;

	/* Delete objects */
	for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx)
	{
		object_type *o_ptr;

		/* Get the object */
		o_ptr = &o_list[this_o_idx];

		/* Get the next object */
		next_o_idx = o_ptr->next_o_idx;

		/* Hack -- efficiency */
		o_ptr->held_m_idx = 0;

		/* Delete the object */
		delete_object_idx(this_o_idx);
	}

	/* Wipe the Monster */
	(void)WIPE(m_ptr, monster_type);

	/* Count monsters */
	m_cnt--;

	/* Visual update */
	lite_spot(y, x);
}

/*
 * Delete the monster, if any, at a given location
 */
void delete_monster(int y, int x)
{
	/* Paranoia */
	if (!in_bounds(y, x)) return;

	/* Delete the monster (if any) */
	if (cave_m_idx[y][x] > 0) delete_monster_idx(cave_m_idx[y][x]);
}

/*
 * Move an object from index i1 to index i2 in the object list
 */
static void compact_monsters_aux(int i1, int i2)
{
	int y, x;

	monster_type *m_ptr;

	s16b this_o_idx, next_o_idx = 0;

	/* Do nothing */
	if (i1 == i2) return;

	/* Old monster */
	m_ptr = &m_list[i1];

	/* Location */
	y = m_ptr->fy;
	x = m_ptr->fx;

	/* Update the cave */
	cave_m_idx[y][x] = i2;

	/* Repair objects being carried by monster */
	for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx)
	{
		object_type *o_ptr;

		/* Get the object */
		o_ptr = &o_list[this_o_idx];

		/* Get the next object */
		next_o_idx = o_ptr->next_o_idx;

		/* Reset monster pointer */
		o_ptr->held_m_idx = i2;
	}

	/* Hack -- Update the target */
	if (p_ptr->target_who == i1) p_ptr->target_who = i2;

	/* Hack -- Update the health bar */
	if (p_ptr->health_who == i1) p_ptr->health_who = i2;

	/* Hack -- move monster */
	COPY(&m_list[i2], &m_list[i1], monster_type);

	/* Hack -- wipe hole */
	(void)WIPE(&m_list[i1], monster_type);
}

/*
 * Compact and Reorder the monster list
 *
 * This function can be very dangerous, use with caution!
 *
 * When actually "compacting" monsters, we base the saving throw
 * on a combination of monster level, distance from player, and
 * current "desperation".
 *
 * After "compacting" (if needed), we "reorder" the monsters into a more
 * compact order, and we reset the allocation info, and the "live" array.
 */
void compact_monsters(int size)
{
	int i, num, cnt;

	int cur_lev, cur_dis, chance;

	/* Message (only if compacting) */
	if (size) msg_print("Compacting monsters...");

	/* Compact at least 'size' objects */
	for (num = 0, cnt = 1; num < size; cnt++)
	{
		/* Get more vicious each iteration */
		cur_lev = 5 * cnt;

		/* Get closer each iteration */
		cur_dis = 5 * (20 - cnt);

		/* Check all the monsters */
		for (i = 1; i < m_max; i++)
		{
			monster_type *m_ptr = &m_list[i];

			monster_race *r_ptr = &r_info[m_ptr->r_idx];

			/* Paranoia -- skip "dead" monsters */
			if (!m_ptr->r_idx) continue;

			/* Hack -- High level monsters start out "immune" */
			if (r_ptr->level > cur_lev) continue;

			/* Ignore nearby monsters */
			if ((cur_dis > 0) && (m_ptr->cdis < cur_dis)) continue;

			/* Saving throw chance */
			chance = 90;

			/* Only compact "Quest" Monsters in emergencies */
			if ((r_ptr->flags1 & (RF1_QUESTOR)) && (cnt < 1000)) chance = 100;

			/* Try not to compact Unique Monsters */
			if (r_ptr->flags1 & (RF1_UNIQUE)) chance = 99;

			/* All monsters get a saving throw */
			if (rand_int(100) < chance) continue;

			/* Delete the monster */
			delete_monster_idx(i);

			/* Count the monster */
			num++;
		}
	}

	/* Excise dead monsters (backwards!) */
	for (i = m_max - 1; i >= 1; i--)
	{
		/* Get the i'th monster */
		monster_type *m_ptr = &m_list[i];

		/* Skip real monsters */
		if (m_ptr->r_idx) continue;

		/* Move last monster into open hole */
		compact_monsters_aux(m_max - 1, i);

		/* Compress "m_max" */
		m_max--;
	}
}

/*
 * Delete/Remove all the monsters when the player leaves the level
 *
 * This is an efficient method of simulating multiple calls to the
 * "delete_monster()" function, with no visual effects.
 */
void wipe_m_list(void)
{
	int i;

	/* Delete all the monsters */
	for (i = m_max - 1; i >= 1; i--)
	{
		monster_type *m_ptr = &m_list[i];

		monster_race *r_ptr = &r_info[m_ptr->r_idx];

		/* Skip dead monsters */
		if (!m_ptr->r_idx) continue;

		/* Mega-Hack -- preserve Unique's XXX XXX XXX */

		/* Hack -- Reduce the racial counter */
		r_ptr->cur_num--;

		/* Monster is gone */
		cave_m_idx[m_ptr->fy][m_ptr->fx] = 0;

		/* Wipe the Monster */
		(void)WIPE(m_ptr, monster_type);
	}

	/* Reset "m_max" */
	m_max = 1;

	/* Reset "m_cnt" */
	m_cnt = 0;

	/* Hack -- reset "reproducer" count */
	num_repro = 0;

	/* Hack -- no more target */
	target_set_monster(0);

	/* Hack -- no more tracking */
	health_track(0);
}

/*
 * Get and return the index of a "free" monster.
 *
 * This routine should almost never fail, but it *can* happen.
 */
s16b m_pop(void)
{
	int i;

	/* Normal allocation */
	if (m_max < z_info->m_max)
	{
		/* Get the next hole */
		i = m_max;

		/* Expand the array */
		m_max++;

		/* Count monsters */
		m_cnt++;

		/* Return the index */
		return (i);
	}

	/* Recycle dead monsters */
	for (i = 1; i < m_max; i++)
	{
		monster_type *m_ptr;

		/* Get the monster */
		m_ptr = &m_list[i];

		/* Skip live monsters */
		if (m_ptr->r_idx) continue;

		/* Count monsters */
		m_cnt++;

		/* Use this monster */
		return (i);
	}

	/* Warn the player (except during dungeon creation) */
	if (character_dungeon) msg_print("Too many monsters!");

	/* Try not to crash */
	return (0);
}

/*
 * Apply a "monster restriction function" to the "monster allocation table"
 */
errr get_mon_num_prep(void)
{
	int i;

	/* Scan the allocation table */
	for (i = 0; i < alloc_race_size; i++)
	{
		/* Get the entry */
		alloc_entry *entry = &alloc_race_table[i];

		/* Accept monsters which pass the restriction, if any */
		if (!get_mon_num_hook || (*get_mon_num_hook)(entry->index))
		{
			/* Accept this monster */
			entry->prob2 = entry->prob1;
		}

		/* Do not use this monster */
		else
		{
			/* Decline this monster */
			entry->prob2 = 0;
		}
	}

	/* Success */
	return (0);
}

/*
 * Choose a monster race that seems "appropriate" to the given level
 *
 * This function uses the "prob2" field of the "monster allocation table",
 * and various local information, to calculate the "prob3" field of the
 * same table, which is then used to choose an "appropriate" monster, in
 * a relatively efficient manner.
 *
 * Note that "town" monsters will *only* be created in the town, and
 * "normal" monsters will *never* be created in the town, unless the
 * "level" is "modified", for example, by polymorph or summoning.
 *
 * There is a small chance (1/50) of "boosting" the given depth by
 * a small amount (up to four levels), except in the town.
 *
 * It is (slightly) more likely to acquire a monster of the given level
 * than one of a lower level.  This is done by choosing several monsters
 * appropriate to the given level and keeping the "hardest" one.
 *
 * Note that if no monsters are "appropriate", then this function will
 * fail, and return zero, but this should *almost* never happen.
 */
s16b get_mon_num(int level)
{
	int i, j, p;

	int r_idx;

	long value, total;

	monster_race *r_ptr;

	alloc_entry *table = alloc_race_table;

	/* Boost the level */
	if (level > 0)
	{
		/* Occasional "nasty" monster */
		if (rand_int(NASTY_MON) == 0)
		{
			/* Pick a level bonus */
			int d = level / 4 + 2;

			/* Boost the level */
			level += ((d < 5) ? d : 5);
		}

		/* Occasional "nasty" monster */
		if (rand_int(NASTY_MON) == 0)
		{
			/* Pick a level bonus */
			int d = level / 4 + 2;

			/* Boost the level */
			level += ((d < 5) ? d : 5);
		}
	}

	/* Reset total */
	total = 0L;

	/* Process probabilities */
	for (i = 0; i < alloc_race_size; i++)
	{
		/* Monsters are sorted by depth */
		if (table[i].level > level) break;

		/* Default */
		table[i].prob3 = 0;

		/* Hack -- No town monsters in dungeon */
		if ((level > 0) && (table[i].level <= 0)) continue;

		/* Get the "r_idx" of the chosen monster */
		r_idx = table[i].index;

		/* Get the actual race */
		r_ptr = &r_info[r_idx];

		/* Hack -- "unique" monsters must be "unique" */
		if ((r_ptr->flags1 & (RF1_UNIQUE)) &&
		    (r_ptr->cur_num >= r_ptr->max_num))
		{
			continue;
		}

		/* Depth Monsters never appear out of depth */
		if ((r_ptr->flags1 & (RF1_FORCE_DEPTH)) && (r_ptr->level > p_ptr->depth))
		{
			continue;
		}

		/* Accept */
		table[i].prob3 = table[i].prob2;

		/* Total */
		total += table[i].prob3;
	}

	/* No legal monsters */
	if (total <= 0) return (0);

	/* Pick a monster */
	value = rand_int(total);

	/* Find the monster */
	for (i = 0; i < alloc_race_size; i++)
	{
		/* Found the entry */
		if (value < table[i].prob3) break;

		/* Decrement */
		value = value - table[i].prob3;
	}

	/* Power boost */
	p = rand_int(100);

	/* Try for a "harder" monster once (50%) or twice (10%) */
	if (p < 60)
	{
		/* Save old */
		j = i;

		/* Pick a monster */
		value = rand_int(total);

		/* Find the monster */
		for (i = 0; i < alloc_race_size; i++)
		{
			/* Found the entry */
			if (value < table[i].prob3) break;

			/* Decrement */
			value = value - table[i].prob3;
		}

		/* Keep the "best" one */
		if (table[i].level < table[j].level) i = j;
	}

	/* Try for a "harder" monster twice (10%) */
	if (p < 10)
	{
		/* Save old */
		j = i;

		/* Pick a monster */
		value = rand_int(total);

		/* Find the monster */
		for (i = 0; i < alloc_race_size; i++)
		{
			/* Found the entry */
			if (value < table[i].prob3) break;

			/* Decrement */
			value = value - table[i].prob3;
		}

		/* Keep the "best" one */
		if (table[i].level < table[j].level) i = j;
	}

	/* Result */
	return (table[i].index);
}

/*
 * Build a string describing a monster in some way.
 *
 * We can correctly describe monsters based on their visibility.
 * We can force all monsters to be treated as visible or invisible.
 * We can build nominatives, objectives, possessives, or reflexives.
 * We can selectively pronominalize hidden, visible, or all monsters.
 * We can use definite or indefinite descriptions for hidden monsters.
 * We can use definite or indefinite descriptions for visible monsters.
 *
 * Pronominalization involves the gender whenever possible and allowed,
 * so that by cleverly requesting pronominalization / visibility, you
 * can get messages like "You hit someone.  She screams in agony!".
 *
 * Reflexives are acquired by requesting Objective plus Possessive.
 *
 * I am assuming that no monster name is more than 65 characters long,
 * so that "char desc[80];" is sufficiently large for any result, even
 * when the "offscreen" notation is added.
 *
 * Note that the "possessive" for certain unique monsters will look
 * really silly, as in "Morgoth, King of Darkness's".  We should
 * perhaps add a flag to "remove" any "descriptives" in the name.
 *
 * Note that "offscreen" monsters will get a special "(offscreen)"
 * notation in their name if they are visible but offscreen.  This
 * may look silly with possessives, as in "the rat's (offscreen)".
 * Perhaps the "offscreen" descriptor should be abbreviated.
 *
 * Mode Flags:
 *   0x01 --> Objective (or Reflexive)
 *   0x02 --> Possessive (or Reflexive)
 *   0x04 --> Use indefinites for hidden monsters ("something")
 *   0x08 --> Use indefinites for visible monsters ("a kobold")
 *   0x10 --> Pronominalize hidden monsters
 *   0x20 --> Pronominalize visible monsters
 *   0x40 --> Assume the monster is hidden
 *   0x80 --> Assume the monster is visible
 *
 * Useful Modes:
 *   0x00 --> Full nominative name ("the kobold") or "it"
 *   0x04 --> Full nominative name ("the kobold") or "something"
 *   0x80 --> Genocide resistance name ("the kobold")
 *   0x88 --> Killing name ("a kobold")
 *   0x22 --> Possessive, genderized if visable ("his") or "its"
 *   0x23 --> Reflexive, genderized if visable ("himself") or "itself"
 */
void monster_desc(char *desc, const monster_type *m_ptr, int mode)
{
	cptr res;

	monster_race *r_ptr = &r_info[m_ptr->r_idx];

	cptr name = (r_name + r_ptr->name);

	bool seen, pron;

	/* Can we "see" it (forced, or not hidden + visible) */
	seen = ((mode & (0x80)) || (!(mode & (0x40)) && m_ptr->ml));

	/* Sexed Pronouns (seen and forced, or unseen and allowed) */
	pron = ((seen && (mode & (0x20))) || (!seen && (mode & (0x10))));

	/* First, try using pronouns, or describing hidden monsters */
	if (!seen || pron)
	{
		/* an encoding of the monster "sex" */
		int kind = 0x00;

		/* Extract the gender (if applicable) */
		if (r_ptr->flags1 & (RF1_FEMALE)) kind = 0x20;
		else if (r_ptr->flags1 & (RF1_MALE)) kind = 0x10;

		/* Ignore the gender (if desired) */
		if (!m_ptr || !pron) kind = 0x00;

		/* Assume simple result */
		res = "it";

		/* Brute force: split on the possibilities */
		switch (kind + (mode & 0x07))
		{
			/* Neuter, or unknown */
			case 0x00: res = "it"; break;
			case 0x01: res = "it"; break;
			case 0x02: res = "its"; break;
			case 0x03: res = "itself"; break;
			case 0x04: res = "something"; break;
			case 0x05: res = "something"; break;
			case 0x06: res = "something's"; break;
			case 0x07: res = "itself"; break;

			/* Male (assume human if vague) */
			case 0x10: res = "he"; break;
			case 0x11: res = "him"; break;
			case 0x12: res = "his"; break;
			case 0x13: res = "himself"; break;
			case 0x14: res = "someone"; break;
			case 0x15: res = "someone"; break;
			case 0x16: res = "someone's"; break;
			case 0x17: res = "himself"; break;

			/* Female (assume human if vague) */
			case 0x20: res = "she"; break;
			case 0x21: res = "her"; break;
			case 0x22: res = "her"; break;
			case 0x23: res = "herself"; break;
			case 0x24: res = "someone"; break;
			case 0x25: res = "someone"; break;
			case 0x26: res = "someone's"; break;
			case 0x27: res = "herself"; break;
		}

		/* Copy the result */
		strcpy(desc, res);
	}

	/* Handle visible monsters, "reflexive" request */
	else if ((mode & 0x02) && (mode & 0x01))
	{
		/* The monster is visible, so use its gender */
		if (r_ptr->flags1 & (RF1_FEMALE)) strcpy(desc, "herself");
		else if (r_ptr->flags1 & (RF1_MALE)) strcpy(desc, "himself");
		else strcpy(desc, "itself");
	}

	/* Handle all other visible monster requests */
	else
	{
		/* It could be a Unique */
		if (r_ptr->flags1 & (RF1_UNIQUE))
		{
			/* Start with the name (thus nominative and objective) */
			strcpy(desc, name);
		}

		/* It could be an indefinite monster */
		else if (mode & 0x08)
		{
			/* XXX Check plurality for "some" */

			/* Indefinite monsters need an indefinite article */
			strcpy(desc, is_a_vowel(name[0]) ? "an " : "a ");
			strcat(desc, name);
		}

		/* It could be a normal, definite, monster */
		else
		{
			/* Definite monsters need a definite article */
			strcpy(desc, "the ");
			strcat(desc, name);
		}

		/* Handle the Possessive as a special afterthought */
		if (mode & 0x02)
		{
			/* XXX Check for trailing "s" */

			/* Simply append "apostrophe" and "s" */
			strcat(desc, "'s");
		}

		/* Mention "offscreen" monsters XXX XXX */
		if (!panel_contains(m_ptr->fy, m_ptr->fx))
		{
			/* Append special notation */
			strcat(desc, " (offscreen)");
		}
	}
}

/*
 * Learn about a monster (by "probing" it)
 */
void lore_do_probe(int m_idx)
{
	monster_type *m_ptr = &m_list[m_idx];
	monster_race *r_ptr = &r_info[m_ptr->r_idx];
	monster_lore *l_ptr = &l_list[m_ptr->r_idx];

	/* Hack -- Memorize some flags */
	l_ptr->r_flags1 = r_ptr->flags1;
	l_ptr->r_flags2 = r_ptr->flags2;
	l_ptr->r_flags3 = r_ptr->flags3;

	/* Update monster recall window */
	if (p_ptr->monster_race_idx == m_ptr->r_idx)
	{
		/* Window stuff */
		p_ptr->window |= (PW_MONSTER);
	}
}

/*
 * Take note that the given monster just dropped some treasure
 *
 * Note that learning the "GOOD"/"GREAT" flags gives information
 * about the treasure (even when the monster is killed for the first
 * time, such as uniques, and the treasure has not been examined yet).
 *
 * This "indirect" method is used to prevent the player from learning
 * exactly how much treasure a monster can drop from observing only
 * a single example of a drop.  This method actually observes how much
 * gold and items are dropped, and remembers that information to be
 * described later by the monster recall code.
 */
void lore_treasure(int m_idx, int num_item, int num_gold)
{
	monster_type *m_ptr = &m_list[m_idx];
	monster_race *r_ptr = &r_info[m_ptr->r_idx];
	monster_lore *l_ptr = &l_list[m_ptr->r_idx];

	/* Note the number of things dropped */
	if (num_item > l_ptr->r_drop_item) l_ptr->r_drop_item = num_item;
	if (num_gold > l_ptr->r_drop_gold) l_ptr->r_drop_gold = num_gold;

	/* Hack -- memorize the good/great flags */
	if (r_ptr->flags1 & (RF1_DROP_GOOD)) l_ptr->r_flags1 |= (RF1_DROP_GOOD);
	if (r_ptr->flags1 & (RF1_DROP_GREAT)) l_ptr->r_flags1 |= (RF1_DROP_GREAT);

	/* Update monster recall window */
	if (p_ptr->monster_race_idx == m_ptr->r_idx)
	{
		/* Window stuff */
		p_ptr->window |= (PW_MONSTER);
	}
}

/*
 * This function updates the monster record of the given monster
 *
 * This involves extracting the distance to the player (if requested),
 * and then checking for visibility (natural, infravision, see-invis,
 * telepathy), updating the monster visibility flag, redrawing (or
 * erasing) the monster when its visibility changes, and taking note
 * of any interesting monster flags (cold-blooded, invisible, etc).
 *
 * Note the new "mflag" field which encodes several monster state flags,
 * including "view" for when the monster is currently in line of sight,
 * and "mark" for when the monster is currently visible via detection.
 *
 * The only monster fields that are changed here are "cdis" (the
 * distance from the player), "ml" (visible to the player), and
 * "mflag" (to maintain the "MFLAG_VIEW" flag).
 *
 * Note the special "update_monsters()" function which can be used to
 * call this function once for every monster.
 *
 * Note the "full" flag which requests that the "cdis" field be updated,
 * this is only needed when the monster (or the player) has moved.
 *
 * Every time a monster moves, we must call this function for that
 * monster, and update the distance, and the visibility.  Every time
 * the player moves, we must call this function for every monster, and
 * update the distance, and the visibility.  Whenever the player "state"
 * changes in certain ways ("blindness", "infravision", "telepathy",
 * and "see invisible"), we must call this function for every monster,
 * and update the visibility.
 *
 * Routines that change the "illumination" of a grid must also call this
 * function for any monster in that grid, since the "visibility" of some
 * monsters may be based on the illumination of their grid.
 *
 * Note that this function is called once per monster every time the
 * player moves.  When the player is running, this function is one
 * of the primary bottlenecks, along with "update_view()" and the
 * "process_monsters()" code, so efficiency is important.
 *
 * Note the optimized "inline" version of the "distance()" function.
 *
 * A monster is "visible" to the player if (1) it has been detected
 * by the player, (2) it is close to the player and the player has
 * telepathy, or (3) it is close to the player, and in line of sight
 * of the player, and it is "illuminated" by some combination of
 * infravision, torch light, or permanent light (invisible monsters
 * are only affected by "light" if the player can see invisible).
 *
 * Monsters which are not on the current panel may be "visible" to
 * the player, and their descriptions will include an "offscreen"
 * reference.  Currently, offscreen monsters cannot be targetted
 * or viewed directly, but old targets will remain set.  XXX XXX
 *
 * The player can choose to be disturbed by several things, including
 * "disturb_move" (monster which is viewable moves in some way), and
 * "disturb_near" (monster which is "easily" viewable moves in some
 * way).  Note that "moves" includes "appears" and "disappears".
 */
void update_mon(int m_idx, bool full)
{
	monster_type *m_ptr = &m_list[m_idx];

	monster_race *r_ptr = &r_info[m_ptr->r_idx];

	monster_lore *l_ptr = &l_list[m_ptr->r_idx];

	int d;

	/* Current location */
	int fy = m_ptr->fy;
	int fx = m_ptr->fx;

	/* Seen at all */
	bool flag = FALSE;

	/* Seen by vision */
	bool easy = FALSE;

	/* Compute distance */
	if (full)
	{
		int py = p_ptr->py;
		int px = p_ptr->px;

		/* Distance components */
		int dy = (py > fy) ? (py - fy) : (fy - py);
		int dx = (px > fx) ? (px - fx) : (fx - px);

		/* Approximate distance */
		d = (dy > dx) ? (dy + (dx>>1)) : (dx + (dy>>1));

		/* Restrict distance */
		if (d > 255) d = 255;

		/* Save the distance */
		m_ptr->cdis = d;
	}

	/* Extract distance */
	else
	{
		/* Extract the distance */
		d = m_ptr->cdis;
	}

	/* Detected */
	if (m_ptr->mflag & (MFLAG_MARK)) flag = TRUE;

	/* Nearby */
	if (d <= MAX_SIGHT)
	{
		/* Basic telepathy */
		if (p_ptr->telepathy)
		{
			/* Empty mind, no telepathy */
			if (r_ptr->flags2 & (RF2_EMPTY_MIND))
			{
				/* Memorize flags */
				l_ptr->r_flags2 |= (RF2_EMPTY_MIND);
			}

			/* Weird mind, occasional telepathy */
			else if (r_ptr->flags2 & (RF2_WEIRD_MIND))
			{
				/* One in ten individuals are detectable */
				if ((m_idx % 10) == 5)
				{
					/* Detectable */
					flag = TRUE;

					/* Memorize flags */
					l_ptr->r_flags2 |= (RF2_WEIRD_MIND);

					/* Hack -- Memorize mental flags */
					if (r_ptr->flags2 & (RF2_SMART)) l_ptr->r_flags2 |= (RF2_SMART);
					if (r_ptr->flags2 & (RF2_STUPID)) l_ptr->r_flags2 |= (RF2_STUPID);
				}
			}

			/* Normal mind, allow telepathy */
			else
			{
				/* Detectable */
				flag = TRUE;

				/* Hack -- Memorize mental flags */
				if (r_ptr->flags2 & (RF2_SMART)) l_ptr->r_flags2 |= (RF2_SMART);
				if (r_ptr->flags2 & (RF2_STUPID)) l_ptr->r_flags2 |= (RF2_STUPID);
			}
		}

		/* Normal line of sight, and not blind */
		if (player_has_los_bold(fy, fx) && !p_ptr->blind)
		{
			bool do_invisible = FALSE;
			bool do_cold_blood = FALSE;

			/* Use "infravision" */
			if (d <= p_ptr->see_infra)
			{
				/* Handle "cold blooded" monsters */
				if (r_ptr->flags2 & (RF2_COLD_BLOOD))
				{
					/* Take note */
					do_cold_blood = TRUE;
				}

				/* Handle "warm blooded" monsters */
				else
				{
					/* Easy to see */
					easy = flag = TRUE;
				}
			}

			/* Use "illumination" */
			if (player_can_see_bold(fy, fx))
			{
				/* Handle "invisible" monsters */
				if (r_ptr->flags2 & (RF2_INVISIBLE))
				{
					/* Take note */
					do_invisible = TRUE;

					/* See invisible */
					if (p_ptr->see_inv)
					{
						/* Easy to see */
						easy = flag = TRUE;
					}
				}

				/* Handle "normal" monsters */
				else
				{
					/* Easy to see */
					easy = flag = TRUE;
				}
			}

			/* Visible */
			if (flag)
			{
				/* Memorize flags */
				if (do_invisible) l_ptr->r_flags2 |= (RF2_INVISIBLE);
				if (do_cold_blood) l_ptr->r_flags2 |= (RF2_COLD_BLOOD);
			}
		}
	}

	/* The monster is now visible */
	if (flag)
	{
		/* It was previously unseen */
		if (!m_ptr->ml)
		{
			/* Mark as visible */
			m_ptr->ml = TRUE;

			/* Draw the monster */
			lite_spot(fy, fx);

			/* Update health bar as needed */
			if (p_ptr->health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);

      /* Update monster list window */
      p_ptr->window |= (PW_MONLIST);

			/* Hack -- Count "fresh" sightings */
			if (l_ptr->r_sights < MAX_SHORT) l_ptr->r_sights++;

			/* Disturb on appearance */
			if (disturb_move) disturb(1, 0);
		}
	}

	/* The monster is not visible */
	else
	{
		/* It was previously seen */
		if (m_ptr->ml)
		{
			/* Mark as not visible */
			m_ptr->ml = FALSE;

			/* Erase the monster */
			lite_spot(fy, fx);

			/* Update health bar as needed */
			if (p_ptr->health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);

      /* Update monster list window */
      p_ptr->window |= (PW_MONLIST);

			/* Disturb on disappearance */
			if (disturb_move) disturb(1, 0);
		}
	}

	/* The monster is now easily visible */
	if (easy)
	{
		/* Change */
		if (!(m_ptr->mflag & (MFLAG_VIEW)))
		{
			/* Mark as easily visible */
			m_ptr->mflag |= (MFLAG_VIEW);

			/* Disturb on appearance */
			if (disturb_near) disturb(1, 0);
		}
	}

	/* The monster is not easily visible */
	else
	{
		/* Change */
		if (m_ptr->mflag & (MFLAG_VIEW))
		{
			/* Mark as not easily visible */
			m_ptr->mflag &= ~(MFLAG_VIEW);

			/* Disturb on disappearance */
			if (disturb_near && !m_ptr->is_friendly) disturb(1, 0);
		}
	}
}

/*
 * This function simply updates all the (non-dead) monsters (see above).
 */
void update_monsters(bool full)
{
	int i;

	/* Update each (live) monster */
	for (i = 1; i < m_max; i++)
	{
		monster_type *m_ptr = &m_list[i];

		/* Skip dead monsters */
		if (!m_ptr->r_idx) continue;

		/* Update the monster */
		update_mon(i, full);
	}
}

/*
 * Make a monster carry an object
 */
s16b monster_carry(int m_idx, object_type *j_ptr)
{
	s16b o_idx;

	s16b this_o_idx, next_o_idx = 0;

	monster_type *m_ptr = &m_list[m_idx];

	/* Scan objects already being held for combination */
	for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx)
	{
		object_type *o_ptr;

		/* Get the object */
		o_ptr = &o_list[this_o_idx];

		/* Get the next object */
		next_o_idx = o_ptr->next_o_idx;

		/* Check for combination */
		if (object_similar(o_ptr, j_ptr))
		{
			/* Combine the items */
			object_absorb(o_ptr, j_ptr);

			/* Result */
			return (this_o_idx);
		}
	}

	/* Make an object */
	o_idx = o_pop();

	/* Success */
	if (o_idx)
	{
		object_type *o_ptr;

		/* Get new object */
		o_ptr = &o_list[o_idx];

		/* Copy object */
		object_copy(o_ptr, j_ptr);

		/* Forget mark */
		o_ptr->marked = FALSE;

		/* Forget location */
		o_ptr->iy = o_ptr->ix = 0;

		/* Link the object to the monster */
		o_ptr->held_m_idx = m_idx;

		/* Link the object to the pile */
		o_ptr->next_o_idx = m_ptr->hold_o_idx;

		/* Link the monster to the object */
		m_ptr->hold_o_idx = o_idx;
	}

	/* Result */
	return (o_idx);
}

/*
 * Swap the players/monsters (if any) at two locations XXX XXX XXX
 */
void monster_swap(int y1, int x1, int y2, int x2)
{
	int m1, m2;

	monster_type *m_ptr;

	/* Monsters */
	m1 = cave_m_idx[y1][x1];
	m2 = cave_m_idx[y2][x2];

	/* Update grids */
	cave_m_idx[y1][x1] = m2;
	cave_m_idx[y2][x2] = m1;

	/* Monster 1 */
	if (m1 > 0)
	{
		m_ptr = &m_list[m1];

		/* Move monster */
		m_ptr->fy = y2;
		m_ptr->fx = x2;

		/* Update monster */
		update_mon(m1, TRUE);
	}

	/* Player 1 */
	else if (m1 < 0)
	{
		/* Move player */
		p_ptr->py = y2;
		p_ptr->px = x2;

		/* Update the panel */
		p_ptr->update |= (PU_PANEL);

		/* Update the visuals (and monster distances) */
		p_ptr->update |= (PU_UPDATE_VIEW | PU_DISTANCE);

		/* Update the flow */
		p_ptr->update |= (PU_UPDATE_FLOW);

		/* Window stuff */
		p_ptr->window |= (PW_OVERHEAD);
	}

	/* Monster 2 */
	if (m2 > 0)
	{
		m_ptr = &m_list[m2];

		/* Move monster */
		m_ptr->fy = y1;
		m_ptr->fx = x1;

		/* Update monster */
		update_mon(m2, TRUE);
	}

	/* Player 2 */
	else if (m2 < 0)
	{
		/* Move player */
		p_ptr->py = y1;
		p_ptr->px = x1;

		/* Update the panel */
		p_ptr->update |= (PU_PANEL);

		/* Update the visuals (and monster distances) */
		p_ptr->update |= (PU_UPDATE_VIEW | PU_DISTANCE);

		/* Update the flow */
		p_ptr->update |= (PU_UPDATE_FLOW);

		/* Window stuff */
		p_ptr->window |= (PW_OVERHEAD);
	}

	/* Redraw */
	lite_spot(y1, x1);
	lite_spot(y2, x2);
}

/*
 * Place the player in the dungeon XXX XXX
 */
s16b player_place(int y, int x)
{
	/* Paranoia XXX XXX */
	if (cave_m_idx[y][x] != 0) return (0);

	/* Save player location */
	p_ptr->py = y;
	p_ptr->px = x;

	/* Mark cave grid */
	cave_m_idx[y][x] = -1;

	/* Success */
	return (-1);
}

/*
 * Place a copy of a monster in the dungeon XXX XXX
 */
s16b monster_place(int y, int x, monster_type *n_ptr)
{
	s16b m_idx;

	monster_type *m_ptr;
	monster_race *r_ptr;

	/* Paranoia XXX XXX */
	if (cave_m_idx[y][x] != 0) return (0);

	/* Get a new record */
	m_idx = m_pop();

	/* Oops */
	if (m_idx)
	{
		/* Make a new monster */
		cave_m_idx[y][x] = m_idx;

		/* Get the new monster */
		m_ptr = &m_list[m_idx];

		/* Copy the monster XXX */
		COPY(m_ptr, n_ptr, monster_type);

		/* Location */
		m_ptr->fy = y;
		m_ptr->fx = x;

		/* Update the monster */
		update_mon(m_idx, TRUE);

		/* Get the new race */
		r_ptr = &r_info[m_ptr->r_idx];

		/* Hack -- Notice new multi-hued monsters */
		if (r_ptr->flags1 & (RF1_ATTR_MULTI)) shimmer_monsters = TRUE;

		/* Hack -- Count the number of "reproducers" */
		if (r_ptr->flags2 & (RF2_MULTIPLY)) num_repro++;

		/* Count racial occurances */
		r_ptr->cur_num++;
	}

	/* Result */
	return (m_idx);
}

/*
 * Attempt to place a monster of the given race at the given location.
 *
 * To give the player a sporting chance, any monster that appears in
 * line-of-sight and is extremely dangerous can be marked as
 * "FORCE_SLEEP", which will cause them to be placed with low energy,
 * which often (but not always) lets the player move before they do.
 *
 * This routine refuses to place out-of-depth "FORCE_DEPTH" monsters.
 *
 * XXX XXX XXX Use special "here" and "dead" flags for unique monsters,
 * remove old "cur_num" and "max_num" fields.
 *
 * XXX XXX XXX Actually, do something similar for artifacts, to simplify
 * the "preserve" mode, and to make the "what artifacts" flag more useful.
 *
 * This is the only function which may place a monster in the dungeon,
 * except for the savefile loading code.
 */
static bool place_monster_one(int y, int x, int r_idx, bool slp, bool pet)
{
	int i;

	monster_race *r_ptr;

	monster_type *n_ptr;
	monster_type monster_type_body;

	cptr name;

	/* Paranoia */
	if (!in_bounds(y, x)) return (FALSE);

	/* Require empty space */
	if (!terrain_empty_bold(y, x)) return (FALSE);

	/* Hack -- no creation on glyph of warding */
	if (cave_feat[y][x] == FEAT_GLYPH) return (FALSE);

	/* Paranoia */
	if (!r_idx) return (FALSE);

	/* Race */
	r_ptr = &r_info[r_idx];

	/* Paranoia */
	if (!r_ptr->name) return (FALSE);

	/* Name */
	name = (r_name + r_ptr->name);

	/* Hack -- "unique" monsters must be "unique" */
	if ((r_ptr->flags1 & (RF1_UNIQUE)) && (r_ptr->cur_num >= r_ptr->max_num))
	{
		/* Cannot create */
		return (FALSE);
	}

	/* Handle water terrain */
	if ((r_ptr->flags2 & (RF2_AQUATIC)) &&
	    (cave_feat[y][x] != FEAT_SHAL_WATER) &&
	    (cave_feat[y][x] != FEAT_DEEP_WATER))
	{
		/* Cannot create */
		return (FALSE);
	}
	if ((!(r_ptr->flags2 & (RF2_AQUATIC))) &&
	    (cave_feat[y][x] == FEAT_SHAL_WATER) &&
	    (cave_feat[y][x] == FEAT_DEEP_WATER))
	{
		/* Cannot create */
		return (FALSE);
	}

	/* Depth monsters may NOT be created out of depth */
	if ((r_ptr->flags1 & (RF1_FORCE_DEPTH)) && (p_ptr->depth < r_ptr->level))
	{
		/* Cannot create */
		return (FALSE);
	}

	/* Powerful monster */
	if (r_ptr->level > p_ptr->depth)
	{
		/* Unique monsters */
		if (r_ptr->flags1 & (RF1_UNIQUE))
		{
			/* Message for cheaters */
			if (cheat_hear) msg_format("Deep Unique (%s).", name);

			/* Boost rating by twice delta-depth */
			rating += (r_ptr->level - p_ptr->depth) * 2;
		}

		/* Normal monsters */
		else
		{
			/* Message for cheaters */
			if (cheat_hear) msg_format("Deep Monster (%s).", name);

			/* Boost rating by delta-depth */
			rating += (r_ptr->level - p_ptr->depth);
		}
	}

	/* Note the monster */
	else if (r_ptr->flags1 & (RF1_UNIQUE))
	{
		/* Unique monsters induce message */
		if (cheat_hear) msg_format("Unique (%s).", name);
	}

	/* Get local monster */
	n_ptr = &monster_type_body;

	/* Clean out the monster */
	(void)WIPE(n_ptr, monster_type);

	/* Save the race */
	n_ptr->r_idx = r_idx;

	/* Enforce sleeping if needed */
	if (slp && r_ptr->sleep)
	{
		int val = r_ptr->sleep;
		n_ptr->csleep = ((val * 2) + randint(val * 10));
	}

	/* Assign maximal hitpoints */
	if (r_ptr->flags1 & (RF1_FORCE_MAXHP))
	{
		n_ptr->maxhp = maxroll(r_ptr->hdice, r_ptr->hside);
	}
	else
	{
		n_ptr->maxhp = damroll(r_ptr->hdice, r_ptr->hside);
	}

	/* And start out fully healthy */
	n_ptr->hp = n_ptr->maxhp;

	/* Extract the monster base speed */
	n_ptr->mspeed = r_ptr->speed;

	/* Hack -- small racial variety */
	if (!(r_ptr->flags1 & (RF1_UNIQUE)))
	{
		/* Allow some small variation per monster */
		i = extract_energy[r_ptr->speed] / 10;
		if (i) n_ptr->mspeed += rand_spread(0, i);
	}

	/* Give a random starting energy */
	n_ptr->energy = (byte)rand_int(100);

	/* Set to be friendly, if applicable */
	if (r_ptr->flags2 & RF2_FRIENDLY)
	{
		n_ptr->is_friendly = TRUE;
	}

	/* Set to be a pet, if applicable (no uniques) */
	if ((pet) && !(r_ptr->flags1 & (RF1_UNIQUE)))
	{
		n_ptr->is_friendly = TRUE;
		n_ptr->is_pet = TRUE;
	}

	/* Force monster to wait for player */
	if (r_ptr->flags1 & (RF1_FORCE_SLEEP))
	{
		/* Monster is still being nice */
		n_ptr->mflag |= (MFLAG_NICE);

		/* Optimize -- Repair flags */
		repair_mflag_nice = TRUE;
	}

	/* Monster is still being born */
	n_ptr->mflag |= (MFLAG_BORN);

	/* Optimize -- Repair flags */
	repair_mflag_born = TRUE;

	/* Place the monster in the dungeon */
	if (!monster_place(y, x, n_ptr)) return (FALSE);

	/* Success */
	return (TRUE);
}

/*
 * Maximum size of a group of monsters
 */
#define GROUP_MAX	32

/*
 * Attempt to place a "group" of monsters around the given location
 */
static bool place_monster_group(int y, int x, int r_idx, bool slp, bool pet)
{
	monster_race *r_ptr = &r_info[r_idx];

	int old, n, i;
	int total, extra = 0;

	int hack_n;

	byte hack_y[GROUP_MAX];
	byte hack_x[GROUP_MAX];

	/* Pick a group size */
	total = randint(13);

	/* Hard monsters, small groups */
	if (r_ptr->level > p_ptr->depth)
	{
		extra = r_ptr->level - p_ptr->depth;
		extra = 0 - randint(extra);
	}

	/* Easy monsters, large groups */
	else if (r_ptr->level < p_ptr->depth)
	{
		extra = p_ptr->depth - r_ptr->level;
		extra = randint(extra);
	}

	/* Hack -- limit group reduction */
	if (extra > 12) extra = 12;

	/* Modify the group size */
	total += extra;

	/* Minimum size */
	if (total < 1) total = 1;

	/* Maximum size */
	if (total > GROUP_MAX) total = GROUP_MAX;

	/* Save the rating */
	old = rating;

	/* Start on the monster */
	hack_n = 1;
	hack_x[0] = x;
	hack_y[0] = y;

	/* Puddle monsters, breadth first, up to total */
	for (n = 0; (n < hack_n) && (hack_n < total); n++)
	{
		/* Grab the location */
		int hx = hack_x[n];
		int hy = hack_y[n];

		/* Check each direction, up to total */
		for (i = 0; (i < 8) && (hack_n < total); i++)
		{
			int mx = hx + ddx_ddd[i];
			int my = hy + ddy_ddd[i];

			/* Walls and Monsters block flow */
			if (!cave_empty_bold(my, mx)) continue;

			/* Attempt to place another monster */
			if (place_monster_one(my, mx, r_idx, slp, pet))
			{
				/* Add it to the "hack" set */
				hack_y[hack_n] = my;
				hack_x[hack_n] = mx;
				hack_n++;
			}
		}
	}

	/* Hack -- restore the rating */
	rating = old;

	/* Success */
	return (TRUE);
}

/*
 * Hack -- help pick an escort type
 */
static int place_monster_idx = 0;

/*
 * Hack -- help pick an escort type
 */
static bool place_monster_okay(int r_idx)
{
	monster_race *r_ptr = &r_info[place_monster_idx];

	monster_race *z_ptr = &r_info[r_idx];

	/* Require similar "race" */
	if (z_ptr->d_char != r_ptr->d_char) return (FALSE);

	/* Skip more advanced monsters */
	if (z_ptr->level > r_ptr->level) return (FALSE);

	/* Skip unique monsters */
	if (z_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);

	/* Paranoia -- Skip identical monsters */
	if (place_monster_idx == r_idx) return (FALSE);

	/* Okay */
	return (TRUE);
}

/*
 * Attempt to place a monster of the given race at the given location
 *
 * Note that certain monsters are now marked as requiring "friends".
 * These monsters, if successfully placed, and if the "grp" parameter
 * is TRUE, will be surrounded by a "group" of identical monsters.
 *
 * Note that certain monsters are now marked as requiring an "escort",
 * which is a collection of monsters with similar "race" but lower level.
 *
 * Some monsters induce a fake "group" flag on their escorts.
 *
 * Note the "bizarre" use of non-recursion to prevent annoying output
 * when running a code profiler.
 *
 * Note the use of the new "monster allocation table" code to restrict
 * the "get_mon_num()" function to "legal" escort types.
 */
bool place_monster_aux(int y, int x, int r_idx, bool slp, bool grp, bool pet)
{
	int i;

	monster_race *r_ptr = &r_info[r_idx];

	/* Place one monster, or fail */
	if (!place_monster_one(y, x, r_idx, slp, pet)) return (FALSE);

	/* Require the "group" flag */
	if (!grp) return (TRUE);

	/* Friends for certain monsters */
	if (r_ptr->flags1 & (RF1_FRIENDS))
	{
		/* Attempt to place a group */
		(void)place_monster_group(y, x, r_idx, slp, pet);
	}

	/* Escorts for certain monsters */
	if (r_ptr->flags1 & (RF1_ESCORT))
	{
		/* Try to place several "escorts" */
		for (i = 0; i < 50; i++)
		{
			int nx, ny, z, d = 3;

			/* Pick a location */
			scatter(&ny, &nx, y, x, d, 0);

			/* Require empty grids */
			if (!cave_empty_bold(ny, nx)) continue;

			/* Set the escort index */
			place_monster_idx = r_idx;

			/* Set the escort hook */
			get_mon_num_hook = place_monster_okay;

			/* Prepare allocation table */
			get_mon_num_prep();

			/* Pick a random race */
			z = get_mon_num(r_ptr->level);

			/* Remove restriction */
			get_mon_num_hook = NULL;

			/* Prepare allocation table */
			get_mon_num_prep();

			/* Handle failure */
			if (!z) break;

			/* Place a single escort */
			(void)place_monster_one(ny, nx, z, slp, pet);

			/* Place a "group" of escorts if needed */
			if ((r_info[z].flags1 & (RF1_FRIENDS)) ||
			    (r_ptr->flags1 & (RF1_ESCORTS)))
			{
				/* Place a group of monsters */
				(void)place_monster_group(ny, nx, z, slp, pet);
			}
		}
	}

	/* Success */
	return (TRUE);
}

/*
 * Hack -- attempt to place a monster at the given location
 *
 * Attempt to find a monster appropriate to the "monster_level"
 */
bool place_monster(int y, int x, bool slp, bool grp)
{
	int r_idx;

	/* Pick a monster */
	r_idx = get_mon_num(monster_level);

	/* Handle failure */
	if (!r_idx) return (FALSE);

	/* Attempt to place the monster */
	if (place_monster_aux(y, x, r_idx, slp, grp, 0)) return (TRUE);

	/* Oops */
	return (FALSE);
}

/*
 * XXX XXX XXX Player Ghosts are such a hack, they have been completely
 * removed until Angband 2.8.0, in which there will actually be a small
 * number of "unique" monsters which will serve as the "player ghosts".
 * Each will have a place holder for the "name" of a deceased player,
 * which will be extracted from a "bone" file, or replaced with a
 * "default" name if a real name is not available.  Each ghost will
 * appear exactly once and will not induce a special feeling.
 *
 * Possible methods:
 *   (s) 1 Skeleton
 *   (z) 1 Zombie
 *   (M) 1 Mummy
 *   (G) 1 Polterguiest, 1 Spirit, 1 Ghost, 1 Shadow, 1 Phantom
 *   (W) 1 Wraith
 *   (V) 1 Vampire, 1 Vampire Lord
 *   (L) 1 Lich
 *
 * Possible change: Lose 1 ghost, Add "Master Lich"
 *
 * Possible change: Lose 2 ghosts, Add "Wraith", Add "Master Lich"
 *
 * Possible change: Lose 4 ghosts, lose 1 vampire lord
 *
 * Note that ghosts should never sleep, should be very attentive, should
 * have maximal hitpoints, drop only good (or great) items, should be
 * cold blooded, evil, undead, immune to poison, sleep, confusion, fear.
 *
 * Base monsters:
 *   Skeleton
 *   Zombie
 *   Mummy
 *   Poltergeist
 *   Spirit
 *   Ghost
 *   Vampire
 *   Wraith
 *   Vampire Lord
 *   Shadow
 *   Phantom
 *   Lich
 *
 * This routine will simply extract ghost names from files, and
 * attempt to allocate a player ghost somewhere in the dungeon,
 * note that normal allocation may also attempt to place ghosts,
 * so we must work with some form of default names.
 *
 * XXX XXX XXX
 */

/*
 * Attempt to allocate a random monster in the dungeon.
 *
 * Place the monster at least "dis" distance from the player.
 *
 * Use "slp" to choose the initial "sleep" status
 *
 * Use "monster_level" for the monster level
 */
bool alloc_monster(int dis, bool slp)
{
	int py = p_ptr->py;
	int px = p_ptr->px;

	int y, x;
	int	attempts_left = 10000;

	/* Find a legal, distant, unoccupied, space */
	while (--attempts_left)
	{
		/* Pick a location */
		y = rand_int(DUNGEON_HGT);
		x = rand_int(DUNGEON_WID);

		/* Require "naked" floor grid */
		if (!cave_naked_bold(y, x)) continue;

		/* Accept far away grids */
		if (distance(y, x, py, px) > dis) break;
	}

	if (!attempts_left)
	{
		if (cheat_xtra || cheat_hear)
		{
			msg_print("Warning! Could not allocate a new monster.");
		}

		return FALSE;
	}

	/* Attempt to place the monster, allow groups */
	if (place_monster(y, x, slp, TRUE)) return (TRUE);

	/* Nope */
	return (FALSE);
}

/*
 * Hack -- help decide if a monster race is "okay" to summon
 */
static bool place_aquatic_okay(int r_idx)
{
	monster_race *r_ptr = &r_info[r_idx];

	bool okay = ((r_ptr->d_char == 'l') &&
	             (r_ptr->flags2 & (RF2_AQUATIC)));

	/* Result */
	return (okay);
}

/*
 * Hack -- attempt to place a monster at the given location
 *
 * Attempt to find a monster appropriate to the "monster_level"
 */
bool place_aquatic_monster(int y, int x, bool slp, bool grp)
{
	int r_idx;

	/* Require "okay" monsters */
	get_mon_num_hook = place_aquatic_okay;

	/* Prepare allocation table */
	get_mon_num_prep();

	/* Pick a monster */
	r_idx = get_mon_num(monster_level);

	/* Remove restriction */
	get_mon_num_hook = NULL;

	/* Prepare allocation table */
	get_mon_num_prep();

	/* Handle failure */
	if (!r_idx) return (FALSE);

	/* Attempt to place the monster */
	if (place_monster_aux(y, x, r_idx, slp, grp, 0)) return (TRUE);

	/* Oops */
	return (FALSE);
}

/*
 * Attempt to allocate a random monster in the dungeon.
 *
 * Place the monster at least "dis" distance from the player.
 *
 * Use "slp" to choose the initial "sleep" status
 *
 * Use "monster_level" for the monster level
 */
bool alloc_aquatic_monster(int dis, bool slp)
{
	int py = p_ptr->py;
	int px = p_ptr->px;

	int y, x;
	int	attempts_left = 10000;

	/* Find a legal, distant, unoccupied, space */
	while (--attempts_left)
	{
		/* Pick a location */
		y = rand_int(DUNGEON_HGT);
		x = rand_int(DUNGEON_WID);

		/* Require "naked" floor grid */
		if (!water_naked_bold(y, x)) continue;

		/* Accept far away grids */
		if (distance(y, x, py, px) > dis) break;
	}

	if (!attempts_left)
	{
		if (cheat_xtra || cheat_hear)
		{
			msg_print("Warning! Could not allocate an aquatic monster.");
		}

		return FALSE;
	}

	/* Attempt to place the monster, allow groups */
	if (place_aquatic_monster(y, x, slp, TRUE)) return (TRUE);

	/* Nope */
	return (FALSE);
}

/*
 * Hack -- the "type" of the current "summon specific"
 */
static int summon_specific_type = 0;

/*
 * Hack -- help decide if a monster race is "okay" to summon
 */
static bool summon_specific_okay(int r_idx)
{
	monster_race *r_ptr = &r_info[r_idx];

	bool okay = FALSE;

	/* Hack -- no specific type specified */
	if (!summon_specific_type) return (TRUE);

	/* Check our requirements */
	switch (summon_specific_type)
	{
		case SUMMON_ANT:
		{
			okay = ((r_ptr->d_char == 'a') &&
			        !(r_ptr->flags1 & (RF1_UNIQUE)));
			break;
		}

		case SUMMON_SPIDER:
		{
			okay = ((r_ptr->d_char == 'S') &&
			        !(r_ptr->flags1 & (RF1_UNIQUE)));
			break;
		}

		case SUMMON_HOUND:
		{
			okay = (((r_ptr->d_char == 'C') || (r_ptr->d_char == 'Z')) &&
			        !(r_ptr->flags1 & (RF1_UNIQUE)));
			break;
		}

		case SUMMON_HYDRA:
		{
			okay = ((r_ptr->d_char == 'M') &&
			        !(r_ptr->flags1 & (RF1_UNIQUE)));
			break;
		}

		case SUMMON_ANGEL:
		{
			okay = ((r_ptr->d_char == 'A') &&
			        !(r_ptr->flags1 & (RF1_UNIQUE)));
			break;
		}

		case SUMMON_DEMON:
		{
			okay = ((r_ptr->flags3 & (RF3_DEMON)) &&
			        !(r_ptr->flags1 & (RF1_UNIQUE)));
			break;
		}

		case SUMMON_UNDEAD:
		{
			okay = ((r_ptr->flags3 & (RF3_UNDEAD)) &&
			        !(r_ptr->flags1 & (RF1_UNIQUE)));
			break;
		}

		case SUMMON_DRAGON:
		{
			okay = ((r_ptr->flags3 & (RF3_DRAGON)) &&
			        !(r_ptr->flags1 & (RF1_UNIQUE)));
			break;
		}

		case SUMMON_KIN:
		{
			okay = ((r_ptr->d_char == summon_kin_type) &&
			        !(r_ptr->flags1 & (RF1_UNIQUE)));
			break;
		}

		case SUMMON_HI_UNDEAD:
		{
			okay = ((r_ptr->d_char == 'L') ||
			        (r_ptr->d_char == 'V') ||
			        (r_ptr->d_char == 'W'));
			break;
		}

		case SUMMON_HI_DRAGON:
		{
			okay = (r_ptr->d_char == 'D');
			break;
		}

		case SUMMON_HI_DEMON:
		{
			okay = (r_ptr->d_char == 'U');
			break;
		}

		case SUMMON_WRAITH:
		{
			okay = ((r_ptr->d_char == 'W') &&
			        (r_ptr->flags1 & (RF1_UNIQUE)));
			break;
		}

		case SUMMON_UNIQUE:
		{
			okay = (r_ptr->flags1 & (RF1_UNIQUE)) ? TRUE : FALSE;
			break;
		}

		case SUMMON_WOLVES:
		{
			okay = ((r_ptr->d_char == 'C') &&
			        (r_idx == 186));
			break;
		}

		case SUMMON_SHADOWS:
		{
			okay = ((r_ptr->d_char == 'G') &&
			        !(r_ptr->flags1 & (RF1_UNIQUE)));
			break;
		}

		case SUMMON_ELEMENTAL:
		{
			okay = ((r_ptr->d_char == 'E') &&
			        !(r_ptr->flags1 & (RF1_UNIQUE)));
			break;
		}

		case SUMMON_ANIMALS:
		{
			okay = ((r_ptr->flags3 & (RF3_ANIMAL)) &&
			        !(r_ptr->flags1 & (RF1_UNIQUE)));
			break;
		}
	}

	/* Result */
	return (okay);
}

/*
 * Place a monster (of the specified "type") near the given
 * location.  Return TRUE iff a monster was actually summoned.
 *
 * We will attempt to place the monster up to 10 times before giving up.
 *
 * Note: SUMMON_UNIQUE and SUMMON_WRAITH (XXX) will summon Uniques
 * Note: SUMMON_HI_UNDEAD and SUMMON_HI_DRAGON may summon Uniques
 * Note: None of the other summon codes will ever summon Uniques.
 *
 * This function has been changed.  We now take the "monster level"
 * of the summoning monster as a parameter, and use that, along with
 * the current dungeon level, to help determine the level of the
 * desired monster.  Note that this is an upper bound, and also
 * tends to "prefer" monsters of that level.  Currently, we use
 * the average of the dungeon and monster levels, and then add
 * five to allow slight increases in monster power.
 *
 * Note that we use the new "monster allocation table" creation code
 * to restrict the "get_mon_num()" function to the set of "legal"
 * monsters, making this function much faster and more reliable.
 *
 * Note that this function may not succeed, though this is very rare.
 */
bool summon_specific(int y1, int x1, int lev, int type, bool pet)
{
	int i, x, y, r_idx;

	/* Look for a location */
	for (i = 0; i < 20; ++i)
	{
		/* Pick a distance */
		int d = (i / 15) + 1;

		/* Pick a location */
		scatter(&y, &x, y1, x1, d, 0);

		/* Require "empty" floor grid */
		if (!cave_empty_bold(y, x)) continue;

		/* Hack -- no summon on glyph of warding */
		if (cave_feat[y][x] == FEAT_GLYPH) continue;

		/* Okay */
		break;
	}

	/* Failure */
	if (i == 20) return (FALSE);

	/* Save the "summon" type */
	summon_specific_type = type;

	/* Require "okay" monsters */
	get_mon_num_hook = summon_specific_okay;

	/* Prepare allocation table */
	get_mon_num_prep();

	/* Pick a monster, using the level calculation */
	r_idx = get_mon_num((p_ptr->depth + lev) / 2 + 5);

	/* Remove restriction */
	get_mon_num_hook = NULL;

	/* Prepare allocation table */
	get_mon_num_prep();

	/* Handle failure */
	if (!r_idx) return (FALSE);

	/* Attempt to place the monster (awake, allow groups) */
	if (!place_monster_aux(y, x, r_idx, FALSE, TRUE, pet)) return (FALSE);

	/* Success */
	return (TRUE);
}

/*
 * Summon a monster - from Kamband
 */
void summon_monster(int sumtype)
{
	if (summon_specific(p_ptr->py, p_ptr->px, p_ptr->depth + randint(5),
		 sumtype, TRUE))
	{
		msg_print("You summon some help.");
	}
	else
	{
		msg_print("You called, but no help came.");
	}
}

/*
 * Let the given monster attempt to reproduce.
 *
 * Note that "reproduction" REQUIRES empty space.
 */
bool multiply_monster(int m_idx)
{
	monster_type *m_ptr = &m_list[m_idx];

	int i, y, x;

	bool result = FALSE;

	/* Pets/friendlies breed pets. (Evil grin) */
	bool make_pets = (m_ptr->is_friendly ? TRUE : FALSE);

	/* Try up to 18 times */
	for (i = 0; i < 18; i++)
	{
		int d = 1;

		/* Pick a location */
		scatter(&y, &x, m_ptr->fy, m_ptr->fx, d, 0);

		/* Require an "empty" floor grid */
		if (!cave_empty_bold(y, x)) continue;

		/* Create a new monster (awake, no groups) */
		result = place_monster_aux(y, x, m_ptr->r_idx, FALSE, FALSE,
					   make_pets);

		/* Done */
		break;
	}

	/* Result */
	return (result);
}

/*
 * Dump a message describing a monster's reaction to damage
 *
 * Technically should attempt to treat "Beholder"'s as jelly's
 */
void message_pain(int m_idx, int dam)
{
	long oldhp, newhp, tmp;
	int percentage;

	monster_type *m_ptr = &m_list[m_idx];
	monster_race *r_ptr = &r_info[m_ptr->r_idx];

	char m_name[80];

	/* Get the monster name */
	monster_desc(m_name, m_ptr, 0);

	/* Notice non-damage */
	if (dam == 0)
	{
		msg_format("%^s is unharmed.", m_name);
		return;
	}

	/* Note -- subtle fix -CFT */
	newhp = (long)(m_ptr->hp);
	oldhp = newhp + (long)(dam);
	tmp = (newhp * 100L) / oldhp;
	percentage = (int)(tmp);

	/* Jelly's, Mold's, Vortex's, Quthl's */
	if (strchr("jmvQ", r_ptr->d_char))
	{
		if (percentage > 95)
			msg_format("%^s barely notices.", m_name);
		else if (percentage > 75)
			msg_format("%^s flinches.", m_name);
		else if (percentage > 50)
			msg_format("%^s squelches.", m_name);
		else if (percentage > 35)
			msg_format("%^s quivers in pain.", m_name);
		else if (percentage > 20)
			msg_format("%^s writhes about.", m_name);
		else if (percentage > 10)
			msg_format("%^s writhes in agony.", m_name);
		else
			msg_format("%^s jerks limply.", m_name);
	}

	/* Dogs and Hounds */
	else if (strchr("CZ", r_ptr->d_char))
	{
		if (percentage > 95)
			msg_format("%^s shrugs off the attack.", m_name);
		else if (percentage > 75)
			msg_format("%^s snarls with pain.", m_name);
		else if (percentage > 50)
			msg_format("%^s yelps in pain.", m_name);
		else if (percentage > 35)
			msg_format("%^s howls in pain.", m_name);
		else if (percentage > 20)
			msg_format("%^s howls in agony.", m_name);
		else if (percentage > 10)
			msg_format("%^s writhes in agony.", m_name);
		else
			msg_format("%^s yelps feebly.", m_name);
	}

	/* One type of monsters (ignore,squeal,shriek) */
	else if (strchr("FIKMRSXabclqrst", r_ptr->d_char))
	{
		if (percentage > 95)
			msg_format("%^s ignores the attack.", m_name);
		else if (percentage > 75)
			msg_format("%^s grunts with pain.", m_name);
		else if (percentage > 50)
			msg_format("%^s squeals in pain.", m_name);
		else if (percentage > 35)
			msg_format("%^s shrieks in pain.", m_name);
		else if (percentage > 20)
			msg_format("%^s shrieks in agony.", m_name);
		else if (percentage > 10)
			msg_format("%^s writhes in agony.", m_name);
		else
			msg_format("%^s cries out feebly.", m_name);
	}

	/* Another type of monsters (shrug,cry,scream) */
	else
	{
		if (percentage > 95)
			msg_format("%^s shrugs off the attack.", m_name);
		else if (percentage > 75)
			msg_format("%^s grunts with pain.", m_name);
		else if (percentage > 50)
			msg_format("%^s cries out in pain.", m_name);
		else if (percentage > 35)
			msg_format("%^s screams in pain.", m_name);
		else if (percentage > 20)
			msg_format("%^s screams in agony.", m_name);
		else if (percentage > 10)
			msg_format("%^s writhes in agony.", m_name);
		else
			msg_format("%^s cries out feebly.", m_name);
	}
}

/*
 * Learn about an "observed" resistance.
 */
void update_smart_learn(int m_idx, int what)
{

#ifdef DRS_SMART_OPTIONS

	monster_type *m_ptr = &m_list[m_idx];

	monster_race *r_ptr = &r_info[m_ptr->r_idx];

	/* Too stupid to learn anything */
	if (r_ptr->flags2 & (RF2_STUPID)) return;

	/* Not intelligent, only learn sometimes */
	if (!(r_ptr->flags2 & (RF2_SMART)) && (rand_int(100) < 50)) return;

	/* XXX XXX XXX */

	/* Analyze the knowledge */
	switch (what)
	{
		case DRS_FREE:
		{
			if (p_ptr->free_act) m_ptr->smart |= (SM_IMM_FREE);
			break;
		}

		case DRS_MANA:
		{
			if (!p_ptr->msp) m_ptr->smart |= (SM_IMM_MANA);
			break;
		}

		case DRS_RES_ACID:
		{
			if (p_ptr->resist_acid) m_ptr->smart |= (SM_RES_ACID);
			if (p_ptr->oppose_acid) m_ptr->smart |= (SM_OPP_ACID);
			if (p_ptr->immune_acid) m_ptr->smart |= (SM_IMM_ACID);
			break;
		}

		case DRS_RES_ELEC:
		{
			if (p_ptr->resist_elec) m_ptr->smart |= (SM_RES_ELEC);
			if (p_ptr->oppose_elec) m_ptr->smart |= (SM_OPP_ELEC);
			if (p_ptr->immune_elec) m_ptr->smart |= (SM_IMM_ELEC);
			break;
		}

		case DRS_RES_FIRE:
		{
			if (p_ptr->resist_fire) m_ptr->smart |= (SM_RES_FIRE);
			if (p_ptr->oppose_fire) m_ptr->smart |= (SM_OPP_FIRE);
			if (p_ptr->immune_fire) m_ptr->smart |= (SM_IMM_FIRE);
			break;
		}

		case DRS_RES_COLD:
		{
			if (p_ptr->resist_cold) m_ptr->smart |= (SM_RES_COLD);
			if (p_ptr->oppose_cold) m_ptr->smart |= (SM_OPP_COLD);
			if (p_ptr->immune_cold) m_ptr->smart |= (SM_IMM_COLD);
			break;
		}

		case DRS_RES_POIS:
		{
			if (p_ptr->resist_pois) m_ptr->smart |= (SM_RES_POIS);
			if (p_ptr->oppose_pois) m_ptr->smart |= (SM_OPP_POIS);
			break;
		}

		case DRS_RES_FEAR:
		{
			if (p_ptr->resist_fear) m_ptr->smart |= (SM_RES_FEAR);
			break;
		}

		case DRS_RES_LITE:
		{
			if (p_ptr->resist_lite) m_ptr->smart |= (SM_RES_LITE);
			if (p_ptr->oppose_ld) m_ptr->smart2 |= (SM2_OPP_LITE);
			break;
		}

		case DRS_RES_DARK:
		{
			if (p_ptr->resist_dark) m_ptr->smart |= (SM_RES_DARK);
			if (p_ptr->oppose_ld) m_ptr->smart2 |= (SM2_OPP_DARK);
			break;
		}

		case DRS_RES_BLIND:
		{
			if (p_ptr->resist_blind) m_ptr->smart |= (SM_RES_BLIND);
			break;
		}

		case DRS_RES_CONFU:
		{
			if (p_ptr->resist_confu) m_ptr->smart |= (SM_RES_CONFU);
			if (p_ptr->oppose_cc) m_ptr->smart2 |= (SM2_OPP_CONFU);
			break;
		}

		case DRS_RES_SOUND:
		{
			if (p_ptr->resist_sound) m_ptr->smart |= (SM_RES_SOUND);
			if (p_ptr->oppose_ss) m_ptr->smart2 |= (SM2_OPP_SOUND);
			break;
		}

		case DRS_RES_SHARD:
		{
			if (p_ptr->resist_shard) m_ptr->smart |= (SM_RES_SHARD);
			if (p_ptr->oppose_ss) m_ptr->smart2 |= (SM2_OPP_SHARD);
			break;
		}

		case DRS_RES_NEXUS:
		{
			if (p_ptr->resist_nexus) m_ptr->smart |= (SM_RES_NEXUS);
			if (p_ptr->oppose_nexus) m_ptr->smart2 |= (SM2_OPP_NEXUS);
			break;
		}

		case DRS_RES_NETHR:
		{
			if (p_ptr->resist_nethr) m_ptr->smart |= (SM_RES_NETHR);
			if (p_ptr->oppose_nethr) m_ptr->smart2 |= (SM2_OPP_NETHR);
			break;
		}

		case DRS_RES_CHAOS:
		{
			if (p_ptr->resist_chaos) m_ptr->smart |= (SM_RES_CHAOS);
			if (p_ptr->oppose_cc) m_ptr->smart2 |= (SM2_OPP_CHAOS);
			break;
		}

		case DRS_RES_DISEN:
		{
			if (p_ptr->resist_disen) m_ptr->smart |= (SM_RES_DISEN);
			break;
		}
	}

#endif /* DRS_SMART_OPTIONS */

}


I submitted Healer Quest for approval by Apple (iOS App Store), and I’ve been refused for the following reason :
« We noticed that Game Center has been enabled for your app but there are no Game Center features within the app.
Specifically, the app has GC enabled and leaderboards and achievements have been submitted for review. However, no GC achievements or leaderboards were found in the app. »
Well… I can swear there IS Game Center in my code. Actually it’s the exact same events that I am using with CranberryGames « Phonegap Game » on the Android version, where achievements and leaderboards are working perfectly. I’ve just replaced the PhonegapGame plugin with C2’s GameCenter equivalent, i.e. :
« Authenticate user » at the start of the first layout.
« report achievement "achievementID"» when the player unlocks an achievement.
« Submit score N to leaderboard "leaderboardID" »
« Show Leaderboard "leaderboardID" » on the title screen to check the different leaderboards
« request Achievements » to show the list of achievements unlocked by the player on the title screen.
I’m using Phonegap Build to export to iOS platform, while the Android version is exported with Intel XDK.
Do I need to use other conditions / actions in order to make GC to work?
Is there something I’m missing ?
Any difference with the use of PhonegapGame plugin for Android / Intel XDK ?
Should the IDs be types within " " ?
Thanks a lot for any idea about what could be wrong!
Develop games in your browser. Powerful, performant & highly capable.
Rable hey I'm encountering the same problem as you now, I exported my game using Cordova Project settings and convert the .IPA file using IntelXDK but it seems that the only thing that's working is the In-App Purchase (Even though it's giving me error) whereas the Game Center won't authenticate.
I even created a "Log In" button to Game Center and the action is to "Authenticate User" but nothing showed up.
Is there anyone out there who can help us? Would be greatly appreciated.
From the moment I posted the message, I still don't have Apple's approval yet (it's pending), but I'm confident GC wil work on the build I submitted. At the very least the Leaderboards and achievements are working fine in Sandbox environment (I even can see the scores of the reviewers) so I guess it should be okay.
Did you try your app in sandbox environment? Does it gives you a message "Welcome back, (...)" when you ask for authetification?
Rable game center won't even authenticate. I don't get any message saying that the GC plugin works on my end.
It should work. Is everything ok with your events? Do you authenticate on the start of layout?
Maybe re-read the manual refrence entry to see if everything is correct on this side:
Did you try to create events that trigger on auth fails or on auth success, to see whether authentification fails or gets no response at all?
Solved, turns out that I have to install the testflight app and enable the sandbox mode, it works now.
Where did u do that, man? Changed test to sandbox? i can't find in


In some applications, a complete characterization of the entire downlink RF spectrum conditions is desired. The Autonomous Mobile Collection Kit enables users to place fixed probes at various places to monitor all downlink cellular network spectrum blocks and automatically collect base station identification data and RF measurements on all carriers for all 2G/3G/4G technologies.
The diagram below shows the Autonomous Collection Dataflow via Cloud Drive.
This diagram below shows a simple workflow for the remote collection operator.
Comfortable form-fitting back plate
Light-weight frame and backpack enclosure increases comfort during long operations
In addition, the Autonomous Mobile Collection Kit can transfer files using a USB memory in place of the cloud drive as shown above.
Rugged internal frame with receiver, power supply, controller, and ventilation fans


I know there is a lot of written stuff about the establishing the connection from OH2 to the gateway I already read a lot of not only on OH forums. I recently got my devce delivered and have attached it to my network and can get the date on the mobile app.
But I’m in no way able to configure the gateway in the way as described in the bindings docs.
OH2 version 2.5.5
Xiaomi Home app: 5.8.16
Plugin version: 1.5.2
Gateway firmware: 1.4.6_0012
I’ve read also the thread about soldering UART to the gateway in order to access the system with serial connection. Honestly I would try to prevent this. I don’t want to risk damaging the case. My device is a flat one and Micro-USB powered. Not as others shown in the thread [SOLVED] Openhab2 - Xiaomi Mi Gateway - does not respond with build in 230v plug.
I bought the xiaomi hub and some sensors recently and didn’t get it to work either. I tried pretty much everything…
To fix this I bought a Conbee II stick from Deconz https://www.phoscon.de/de/conbee2. It’s 40€. The stick then gets connected to openhab via the Deconz binding
Thanks @Felix_Schneider that’s at least an alternative idea. However my four USB ports on the server are already used and there are also three of them attached to the openHAB bindings. At some point it becomes difficult to use USB connections to control everything.
I mean there is huge amount of people working on SmartHome initiatives but there is still to much own box thinking.
I can access the gateway even through the outher space, beeing on the road, but I’m not able include it into the central control unit. Seems somehow weird…
As far as I understand, its due to a specific port beeing closed in the firmware. You´ll need to open that for the openhab bindig to find it, second there are some permission settings which I think needs to be altered. And last, you´ll need the token.
I dont think its possible to du beside going in hard-wired (serial interface). Why Xiaomi chose to do it like this, and not like the older gateway version is still in question. I have on of the older ones, and I have to admit, I have had thoughts about going away from these gateways, simply because I cant count on the one I have now will work forever. And changing to a newer version will end in the same situation you´re in.
python-miio is able to control the devices, without the restriction on firmware as far as I can see.
Hence don’t see why miio binding would not be able to communicate with the device as it uses same communication method
I will give it a try with my gateway, Marcel. I first need to get some debug logging for the modbus binding up running first, cause there seem to be some serious issue with it. Then I´ll return to try the miio binding with my gateway.
Next step is to find out how to activate port 9898 on the device or find another approach to do the same.
I can see that 9898 is not active listening…
As on other pages written, the system on this version of Mi Smarthome hub (gateway) also referred as v4 works differently. And there seems to be no way to get a developer key from somewhere. Further more I cannot identify which service on the device would be related to to port 9898.


I’ve just posted my review of “EJB 3.1 Cookbook” over on Develop In Java.
EJB 3.1 Cookbook is an excellent resource in an EJB developer’s library. It’s not the sort of book you pick up and read from cover to cover rather a useful resource that you pick up when you think “How do I do xxx in EJB?”. With over 100 recipes this book is recommended to developers using EJB technologies.
I very much liked this book and can imagine using it frequently. You can read the whole review here.
James Sutherland has published a blog post showing how to significantly increase JPA performance.
In the post, he provides 11 different optimizations, such as pagination and query caching that can be applied to JPA. The EclipseLink JPA 3.2 implementation of JPA is used throughout the post.
This is a good article and well worth reading by anyone that develops database systems using JPA.
Packt Publishing have recently released two new books of interest to Java EE developers.
EJB 3.1 Cookbook and Java EE6 With NetBeans 7 both look like good reads and Packt have graciously agreed to send me a copy of each of these books for review, which I’ll post on the site as soon as I’ve reviewed them.
Thanks to Nicole for sorting this out for me.


The other day I was editing a httpd.conf file and wanted to comment a large section. On the server I was using the comment syntax wasn’t setup for these types of files.
So, to quickly accomplish I just needed to set the comment-start variable to “#”.
M-: (setq comment-start "#") RET
Then with the block marked, a comment-region worked perfectly.


We have developed a simple managment and analysis tool, called Dr.Bookings.
Its OpenSource and free-of-charge.
For our needs it is already working very good, but we would like to get some more feedback if it is suited for a more general audience.
If you are interested, just download the latest release and give it a try!
Free technical support guaranteed in exchange for feedback!


i am interested in learning kufic script.
I am amazed with the work and its heart touching and eye catching.
It surely deserves recognition and its appreciable in all its styles.
Can anybody suggest some reading work for me to start learning?
There are some teaching books from our website You may provide it for your learning.
Your email address will not be published. Required fields are marked *
Current ye@r *
Leave this field empty


Peter Myers has been working with Microsoft database and development products since 1997. Today he specializes in Microsoft Business Intelligence and provides mentoring, technical training and course content authoring for Microsoft SQL Server and Microsoft Office. Specifically, he works with SQL Server Integration Services, SQL Server Analysis Services (data modeling and data mining), SQL Server Reporting Services, Microsoft Excel, PowerPivot and PerformancePoint Services.
He has a broad business background supported by a Bachelor degree in applied economics, and he extends this with current MCITP and MCT certifications. He has been a SQL Server MVP since 2007.
Peter is an established presenter and enjoys sharing his enthusiasm for Microsoft products by presenting in classrooms and at user group meetings, technical events and conferences.


We can't find the page you are looking...
MOST LIKELY CAUSES:
There might be a typing error in the web address
If you clicked on a link, it may be out of date
THINGS YOU COULD TRY:
Retype the address Go back to the previous page
Go to our Home page and look for the information you want


Ansgar Burchardt dijo [Sun, Jun 10, 2012 at 01:57:49PM +0200]: > Hi, > > (Please send followup messages to -project.) > > The ftp team wants to change how allowing Debian Maintainers to upload > packages works. The current approach with the DM-Upload-Allowed field > has a few issues we would like to address: > (...) Hi, Hmm, this looks interesting, and useful. I'd like to add a bit as a wishlist item: Having this DB easily queriable (i.e. a webpage where you can query by key to see all the packages uploadable by a given key). And just thinking about possible complications: I *hope* we don't see any such behaviour, but this format would allow a DD to "censor" a given DM's activity. If I send "Deny" actions with somebody's key, it ends up blocking that person until somebody else is convinced to send corresponding "Allow" commands. Of course, if we see any such behaviour (repeatedly?), I might be reprehended and maybe even locked out of sending requests to this subsystem. Thoughts on this? Finally, it's interesting to me (as keyring-maint) that you are specifying the fingerprint. Of course, it makes sense. But it can make key migration (i.e. a DM moving from a 1024D to a 4096R key, or reacting to a key being compromised) as a more difficult thing, as the new key would first have to be inserted by us into the live keyring and only then the old key denied and the new one allowed. I guess we could automate this procedure when performing the keyring push... Anyway, and modulo the time it takes to implement all the needed bits (and discussion), thanks for a nice new idea, and hope to see it go forward!
Description: Digital signature


You are given a book with $$$n$$$ chapters.

Each chapter has a specified list of other chapters that need to be understood in order to understand this chapter. To understand a chapter, you must read it after you understand every chapter on its required list.

Currently you don't understand any of the chapters. You are going to read the book from the beginning till the end repeatedly until you understand the whole book. Note that if you read a chapter at a moment when you don't understand some of the required chapters, you don't understand this chapter.

Determine how many times you will read the book to understand every chapter, or determine that you will never understand every chapter no matter how many times you read the book.


Keystore not initialized RemoteException in Method: getLocalJ2EEKeyStore
I'm running into a weird error which reads -
The keystore service_ssl has not been initialized(loaded) -
RemoteException in Method: getLocalJ2EEKeyStore(). The JNDI Look-Up for the Keystore failed.
I followed all instructions to create a Key value pair and have placed it under service_ssl view in Key Storage under Cluster in Visual Admin.
I checked accessing the https url for XI server to test if the CA was working fine and that worked fine.
I'm trying to do a File to RNIF scenario (for testing RNIF adapter)..and running into this issue.
Have anybody come across this error? How do I activate Key storage view?
Thanks in advance.
You need to assign the role for that.Do the following.
security provider--keystore.default--securityroles--in users add xiafuser,xiappluser security provider--sap.com/tc~sec~wssec~app*wssprocess.jar--securityroles--in users add xiafuser,xiappluser


Information about upgrading
All releases can be found on GitHub.
Upgrading from 0.2.0 to 0.2.1
In this version, a more generic custom template functionality has been introduced. This deprecated the
template-xyz.twig. More information about this new template feature can be found here.
Upgrading from 0.1.0 to 0.2.0
Important note when upgrading to 0.2.0
- Removal of loading theme specific directory via
- Autoloading Core and Theme
- No more
In 0.2.0. we implemented autoloading (spl_autoload_register) on the
wordpress-objects directory within the Clarkson Core plugin and your Clarkson Theme. One should also do this within your own theme, so we highly suggest using Composer or another autoloading in your theme.
One breaking change is that the old glob’ing method of all your themes (
taxonomies directory) by Clarkson Core is removed.
We’ve build-in a quick-fix to maintain backwards compatiblity, but it’s disabled by default. To enable it add this in a file within your
Enable via theme autoload filter
<?php // Add to mu-plugins/clarkson-core-deprecated.php add_filter('clarkson_core_autoload_theme_pre_020', '__return_true');


(Chicago Tribune photo by Bill Hogan, plucked from The Huffington Post–great link to the back story on the Tribune’s social media evolution)
One thing that irks me about most newspapers is their poor understanding on how to utilise Twitter as a social media tool for disseminating their news. Sure, a newspaper could look “cool and hip” by adding Twitter on their list, but it gets annoying fast when all the Twitter account does is spew out RSS feeds like a bot.
So far, local news orgs have been treating it like another channel of news alerts: @tm_insider, @thenutgraph, @thestar_rage, mostly employ it as a one-way communication tool. (If you ask me, @msiakini is the biggest irritant in this regard–the tweets are often cut short as headlines stretch over 140 characters- – with no link! WTF, seriously) Granted, while @nikicheong is getting there with The Star’s Rage in being human by putting more than headlines and a link in its Twitter post, there’s hardly a relationship built there. Read the rest of this entry »


CTAN Update: PT Serif
This package contains LaTeX support for the font PT Sans. - Added several Cyrillic letters that were missing in the encoding files but present in the fonts (some Cyrillic letters are not in Unicode or Adobe Glyph List). - The encoding files have more descriptive names now. Related package: ptsans
This package is located at http://mirror.ctan.org/fonts/ptserif . More information is at http://tug.ctan.org/info/?id=ptserif (if the package is new it may take a day for that information to appear). We are supported by the TeX Users Group http://www.tug.org . Please join a users group; see http://www.tug.org/usergroups.html . Thanks for the upload. For the CTAN Team Rainer Schöpf
ptserif – PT Serif font and LaTeX support
This package contains LaTeX support for the font PT Serif developed by ParaType for the project “Public Types of the Russian Federation”, and released under an open user license.
The fonts are included in this distribution, in TrueType format and as converted Type 1 format (as kindly allowed by ParaType). The fonts provide coverage of the T2* and X2 encodings, and partial coverage of T1 OT1, TS1 and IL2 (sufficient for typesetting text in Czech and Slovak languages — the purpose of encoding IL2).
This package is now obsolete; users should seek the paratype bundle in its place.
- 2011-03-11 CTAN Update: ptserif
- 2011-03-01 CTAN Update: PT Serif
- 2011-02-16 CTAN Update: PT Serif
- 2011-02-10 CTAN Update: PT Serif
- 2011-02-03 New CTAN package: ptserif


I was able to import one zipped file (filled with one of the tutorial data) and am trying to import another, but I can't seem to get the same result. It's not importing the second zipped file and expanding out the folders like it did the first time. Is there something I'm doing wrong?
Importing a zipped archive project via the 'import archive' unzips the file and copies the content (the actual project) in the currently active workspace. Doing this for multiple projects should do the same for each zip file.
Can you maybe show a few screenshots with each step and what happens ?


You are given an array $$$a$$$ of length $$$2n$$$, consisting of each integer from $$$1$$$ to $$$n$$$ exactly twice.

You are also given an integer $$$k$$$ ($$$1 \leq k \leq \lfloor \frac{n}{2} \rfloor $$$).

You need to find two arrays $$$l$$$ and $$$r$$$ each of length $$$\mathbf{2k}$$$ such that:

- $$$l$$$ is a subset$$$^\dagger$$$ of $$$[a_1, a_2, \ldots a_n]$$$
- $$$r$$$ is a subset of $$$[a_{n+1}, a_{n+2}, \ldots a_{2n}]$$$
- bitwise XOR of elements of $$$l$$$ is equal to the bitwise XOR of elements of $$$r$$$; in other words, $$$l_1 \oplus l_2 \oplus \ldots \oplus l_{2k} = r_1 \oplus r_2 \oplus \ldots \oplus r_{2k}$$$

It can be proved that at least one pair of $$$l$$$ and $$$r$$$ always exists. If there are multiple solutions, you may output any one of them.

$$$^\dagger$$$ A sequence $$$x$$$ is a subset of a sequence $$$y$$$ if $$$x$$$ can be obtained by deleting several (possibly none or all) elements of $$$y$$$ and rearranging the elements in any order. For example, $$$[3,1,2,1]$$$, $$$[1, 2, 3]$$$, $$$[1, 1]$$$ and $$$[3, 2]$$$ are subsets of $$$[1, 1, 2, 3]$$$ but $$$[4]$$$ and $$$[2, 2]$$$ are not subsets of $$$[1, 1, 2, 3]$$$.


Re: Firewalls and CU-Seeme
Richard Cogger (R.Cogger@cornell.edu)
Fri, 23 Sep 1994 12:01:07 -0400
At 10:20 AM 9/23/94, <firstname.lastname@example.org> wrote:
>Has anybody written (or considered writing) a proxy server for CU-Seeme?
>My request to have UDP port 7648 turned on was turned down; I enjoy the
>use of CU-SeeME at work - but only when I'm on the other side of our firewall.
What you might try doing is to get your security admins to run a reflector
on the same machine (or in parallel) as the firewall. That wouldn't allow
you to connect out, but you could get others to connect in to you. In a
future version, we may provide the means to have a reflector establish
connections when stimulated by an appropriately identified participant.
Anyway, you can point out to the security folks that the reflector is
available in source, so they can inspect it to be sure it doesn't do
anything they don't want done.


Vladimir wants to modernize partitions in his office. To make the office more comfortable he decided to remove a partition and plant several bamboos in a row. He thinks it would be nice if there are n bamboos in a row, and the i-th from the left is ai meters high.

Vladimir has just planted n bamboos in a row, each of which has height 0 meters right now, but they grow 1 meter each day. In order to make the partition nice Vladimir can cut each bamboo once at any height (no greater that the height of the bamboo), and then the bamboo will stop growing.

Vladimir wants to check the bamboos each d days (i.e. d days after he planted, then after 2d days and so on), and cut the bamboos that reached the required height. Vladimir wants the total length of bamboo parts he will cut off to be no greater than k meters.

What is the maximum value d he can choose so that he can achieve what he wants without cutting off more than k meters of bamboo?


Pari wants to buy an expensive chocolate from Arya. She has n coins, the value of the i-th coin is ci. The price of the chocolate is k, so Pari will take a subset of her coins with sum equal to k and give it to Arya.

Looking at her coins, a question came to her mind: after giving the coins to Arya, what values does Arya can make with them? She is jealous and she doesn't want Arya to make a lot of values. So she wants to know all the values x, such that Arya will be able to make x using some subset of coins with the sum k.

Formally, Pari wants to know the values x such that there exists a subset of coins with the sum k such that some subset of this subset has the sum x, i.e. there is exists some way to pay for the chocolate, such that Arya will be able to make the sum x using these coins.


The "ip access-group" command will block someone from connecting to that network but not from the route appearing in the routing table.
As I understand it, you want to prevent the route from appearing in the routing table (which would ultimately prevent all access to the network, even without an ip access-group statement).
To do this, block it when you redistribute it using a route-map or you block it when it comes into a router, downstream, using the distrbute-list command.
Either way, the ip access-group statement doesn't keep the route from appearing in the routing table.
I know you said that you don't want to use a distribute list or route-map (I don't see that you need tags in this case) but that seems like the best way to do it.
Is this from some kind of test question? (when you say that you don't want to use the obviously best method, that hints to me that it is from a test question).
If you still have more questions, please post and maybe we can figure it out together.
Keep Up with TechRepublic


Polycarp has a rectangular field of $$$n \times m$$$ cells (the size of the $$$n \cdot m$$$ field does not exceed $$$10^6$$$ cells, $$$m \ge 2$$$), in each cell of which there can be candy. There are $$$n$$$ rows and $$$m$$$ columns in the field.

Let's denote a cell with coordinates $$$x$$$ vertically and $$$y$$$ horizontally by $$$(x, y)$$$. Then the top-left cell will be denoted as $$$(1, 1)$$$, and the bottom-right cell will be denoted as $$$(n, m)$$$.

If there is candy in the cell, then the cell is marked with the symbol '1', otherwise — with the symbol '0'.

Polycarp made a Robot that can collect candy. The Robot can move from $$$(x, y)$$$ either to $$$(x+1, y+1)$$$, or to $$$(x+1, y-1)$$$. If the Robot is in a cell that contains candy, it takes it.

While there is at least one candy on the field, the following procedure is executed:

- Polycarp puts the Robot in an arbitrary cell on the topmost row of the field. He himself chooses in which cell to place the Robot. It is allowed to put the Robot in the same cell multiple times.
- The Robot moves across the field and collects candies. He controls the Robot.
- When the Robot leaves the field, Polycarp takes it. If there are still candies left, Polycarp repeats the procedure.

Find the minimum number of times Polycarp needs to put the Robot on the topmost row of the field in order to collect all the candies. It is guaranteed that Polycarp can always collect all the candies.


For me, this (lag) can be split into 4 different areas:
Efficiency of the transport protocol: At the moment the game uses TCP. We’ve discussed internally exploring using UDP for some data packages. But the trade off isn’t a trivial selection. If there is time later in development we’ll look at UDP as an optimisation step for some data.
Overhead of the client and server dispatch and receiving services: There isn’t much we can do about the OS network stacks (beyond server configuration) but there are likely opportunities for making the client and server handle networking more efficiently. (Speed up SSL, compression, reduce bundling of data, synchronise more intelligently during the frame, etc) Often with online games simply getting networking working is the priority. But I think we have some decent head room to improve this area.
Physical distance between client and server: Sorry, we can’t do anything about the speed of light. + = +
Mechanism for hiding latency: This is our biggest opportunity. As we’ve discussed in other threads the client does extensive prediction to try and hide the latency. Hopefully the client predicts correctly and when the server finally responds with the actual outcome, no correction is required. If the server responds with a different outcome, the client again does its best to hide the correction. Sometimes the correction is hard to spot, for example, a creature’s position is gradually corrected over subsequent frames. Sometimes the correction is binary, you either did or didn’t die, whoopsie the client got it wrong and snap you’re dead.
Interestingly the client is often able to work with the server and make predictive predictions about entities. The following configurations exist:
Unknown simulation of another player: the client doesn’t know anything about what another player will do. It only knows what it did in the past. So the client can only extrapolate their future position based on their recent movement. A running player is likely to continue running. But the client can’t predict when they’ll stop, or jump, or shoot. (This is why player-player grappling hooks, player-player collision, etc, are latency bound.)
Local simulation: the client can also run a simulation of the entities locally. If the simulation is deterministic, than the client can predict what an entity will do next by duplicating the servers simulation locally. This gives the client a good prediction. But other players can introduce noise into the system that will alter the entities actions on the server. (See #1). But in general if the player is roughly alone, the prediction hides the latency. Blocks will appear in your inventory before the server allows them. Creatures will die before they’re dead. Etc.
Temporal Announcements: the most stable prediction is when the server actually tells the client in advance what will happen. This is a special case where we can (kindof) run the simulation ahead on the server. The server then communicates to the client, the future movement + actions of the entity. This means that when the client is making predictions it already knows that will happen on the server. We can do this for certain larger entities that the players can’t really effect. (Go ahead and read between the lines here - @tahru cough )
In short - we’ve made a big effort on hiding the lag - explicitly because the game is played online. Servers all around the world wouldn’t be possible without attempting to hide the latency. Whilst we know there are still some issues (rubber banding reported by players) - if we were ever to turn off the prediction you would instantly notice the difference, especially on remote servers.
Concurrent players is mainly limited by the simulation cost of the players and the entities surrounding them, and the CPU performance of the server. (So nothing really to do with latency.) Interestingly there is a trade off here, because we want the creatures to do cool things, but this often means more expensive entity code.
However, we’ve designed the game to mainly scale by having more worlds (ie. more servers), rather than by having (fewer) more powerful servers. This is an extremely common model for large scalability online.
At the moment, it’s hard to predict the # of concurrent players because 1. we’re still making the game, 2. we’ve not defined what hardware we’re benchmarking against. I’ve set the team an initial target of having over 100 players per core. Later in development, we’ll share some more metrics about server performance because this will be important for modders and hosts.
UPDATE: Additional important point here. When players (and potential players) beat the development progress of the game up as being too slow - it’s often stuff like this that they don’t see. It would have been waaaaay quicker to not include any prediction. All the combat, ranged combat, block damage + placement, (basically everything) would have been much simpler to implement. But then the game wouldn’t have been scalable to play around the world. You’d not be able to seamlessly walk between servers in EU, NA and Aus. Lots of stuff is going on under the covers.
Thanks for the thorough answer! I realize I snuck in many questions on that one. 100 users per server is more than respectable. Plus, you are deploying on AWS, which can scale geographically as well as in several hardware and network ways.
I can only imagine the technical challenges as lag is not something I have had to deal with beyond slow consumer issues.
I guess this is a good a time as any to ask whether the immense lag is exclusive to me. I may have a 1mbps connection, but it still functions in most games. But I’ve literally not been able to play Oort due to lag.
I switch to an item in my hotbar and it goes back to the previous one, I open my inventory and it instantly closes or I try to close my inventory and it opens back up again, I try to build and everything disappears, or I may try to walk but I get stuck/get put back.
Is it just a problem with network optimization, or is it my location? (Arizona, USA)
If the server doesn’t respond to the client within 500ms (0.5 seconds) then the client assumes the response isn’t coming and reverts the prediction. (Placing blocks, switching item, movement - are all predicted.)
As many players can play without this issue (and given the information above explaining that the game is still in development) - I would initially suspect your connection.
Firstly, try playing on the servers closest to you. (Sorry - obvious I know.)
Are you playing via Wireless? This will add latency.
Well I seem to be experiencing the issues on all servers, including ones closest to me. I haven’t tested it lately, but maybe I do get less lag on servers closer to me. Unfortunately, I can’t test the game as I don’t have a PSU for my PC, but my computer was previously wired into a router, so I guess you could say I’m not playing wireless.
I’ll conduct some more tests when I have my computer back, so I’ll see to informing you whenever that happens.


They say that Berland has exactly two problems, fools and roads. Besides, Berland has n cities, populated by the fools and connected by the roads. All Berland roads are bidirectional. As there are many fools in Berland, between each pair of cities there is a path (or else the fools would get upset). Also, between each pair of cities there is no more than one simple path (or else the fools would get lost).

But that is not the end of Berland's special features. In this country fools sometimes visit each other and thus spoil the roads. The fools aren't very smart, so they always use only the simple paths.

A simple path is the path which goes through every Berland city not more than once.

The Berland government knows the paths which the fools use. Help the government count for each road, how many distinct fools can go on it.

Note how the fools' paths are given in the input.


Polycarp studies in Berland State University. Soon he will have to take his exam. He has to pass exactly $$$n$$$ exams.

For the each exam $$$i$$$ there are known two days: $$$a_i$$$ — day of the first opportunity to pass the exam, $$$b_i$$$ — day of the second opportunity to pass the exam ($$$a_i < b_i$$$). Polycarp can pass at most one exam during each day. For each exam Polycarp chooses by himself which day he will pass this exam. He has to pass all the $$$n$$$ exams.

Polycarp wants to pass all the exams as soon as possible. Print the minimum index of day by which Polycarp can pass all the $$$n$$$ exams, or print -1 if he cannot pass all the exams at all.


You are given a permutation $$$a_1, a_2, \dots, a_n$$$ of numbers from $$$1$$$ to $$$n$$$. Also, you have $$$n$$$ sets $$$S_1,S_2,\dots, S_n$$$, where $$$S_i=\{a_i\}$$$. Lastly, you have a variable $$$cnt$$$, representing the current number of sets. Initially, $$$cnt = n$$$.

We define two kinds of functions on sets:

$$$f(S)=\min\limits_{u\in S} u$$$;

$$$g(S)=\max\limits_{u\in S} u$$$.

You can obtain a new set by merging two sets $$$A$$$ and $$$B$$$, if they satisfy $$$g(A)<f(B)$$$ (Notice that the old sets do not disappear).

Formally, you can perform the following sequence of operations:

- $$$cnt\gets cnt+1$$$;
- $$$S_{cnt}=S_u\cup S_v$$$, you are free to choose $$$u$$$ and $$$v$$$ for which $$$1\le u, v < cnt$$$ and which satisfy $$$g(S_u)<f(S_v)$$$.

You are required to obtain some specific sets.

There are $$$q$$$ requirements, each of which contains two integers $$$l_i$$$,$$$r_i$$$, which means that there must exist a set $$$S_{k_i}$$$ ($$$k_i$$$ is the ID of the set, you should determine it) which equals $$$\{a_u\mid l_i\leq u\leq r_i\}$$$, which is, the set consisting of all $$$a_i$$$ with indices between $$$l_i$$$ and $$$r_i$$$.

In the end you must ensure that $$$cnt\leq 2.2\times 10^6$$$. Note that you don't have to minimize $$$cnt$$$. It is guaranteed that a solution under given constraints exists.


Kawashiro Nitori is a girl who loves competitive programming. One day she found a rooted tree consisting of $$$n$$$ vertices. The root is vertex $$$1$$$. As an advanced problem setter, she quickly thought of a problem.

Kawashiro Nitori has a vertex set $$$U=\{1,2,\ldots,n\}$$$. She's going to play a game with the tree and the set. In each operation, she will choose a vertex set $$$T$$$, where $$$T$$$ is a partial virtual tree of $$$U$$$, and change $$$U$$$ into $$$T$$$.

A vertex set $$$S_1$$$ is a partial virtual tree of a vertex set $$$S_2$$$, if $$$S_1$$$ is a subset of $$$S_2$$$, $$$S_1 \neq S_2$$$, and for all pairs of vertices $$$i$$$ and $$$j$$$ in $$$S_1$$$, $$$\operatorname{LCA}(i,j)$$$ is in $$$S_1$$$, where $$$\operatorname{LCA}(x,y)$$$ denotes the lowest common ancestor of vertices $$$x$$$ and $$$y$$$ on the tree. Note that a vertex set can have many different partial virtual trees.

Kawashiro Nitori wants to know for each possible $$$k$$$, if she performs the operation exactly $$$k$$$ times, in how many ways she can make $$$U=\{1\}$$$ in the end? Two ways are considered different if there exists an integer $$$z$$$ ($$$1 \le z \le k$$$) such that after $$$z$$$ operations the sets $$$U$$$ are different.

Since the answer could be very large, you need to find it modulo $$$p$$$. It's guaranteed that $$$p$$$ is a prime number.


To kill a process on Ubuntu, you can use the kill command or the pkill command. Here’s a brief overview of both methods:
1. Using the kill command:
To terminate a process, follow these steps:
Find the process ID (PID) of the process you want to terminate. You can use the ps command to list processes. For example, to find the PID of a process named “example_process,” use the following command:
ps aux | grep example_process
Once you have the PID, use the kill command to terminate the process. Replace PID with the actual process ID:
If the process does not terminate gracefully, you can use the -9 option to forcefully kill the process:
kill -9 PID
2. Using the pkill command:
The pkill command allows you to kill a process by its name. To kill a process named “example_process,” use the following command:
Similar to the kill command, you can use the -9 option with pkill for a forceful termination:
pkill -9 example_process
Please exercise caution when forcefully terminating processes using the -9 option. It may lead to data corruption or other issues if the process is performing critical operations. It is generally recommended to try a regular kill first and only resort to the -9 option if necessary.
Remember that killing processes should be done carefully, especially if they are essential for the system’s stability or if they belong to system-critical services.


Job ikke fundet
Beklager, vi kunne ikke finde jobbet du ledte efter.
Find de seneste jobs her:
Let me know if the following interests you: “Revolutionising the way people use personal secretaries/assistants by automating the their jobs” We are looking to build a mobile software which lets anyone outsource their PA tasks (attending calls, managing calendars & appointments etc.) Please go through the following use case for a better understanding:- Use case : [log ind for a...
Desarrollar ecommerce para venta de electrónica (celulares).
Guide needs to have screenshots for necessary steps and the wording needs to be different than the video, but capture the same concepts. So the video can be used as a guide, but cannot be copied word for word. [log ind for at se URL] Add "I read the project description" to the first time of your proposal so I know you read it.
Collate and submit personal tax return
Sip to native dialer app Features 1. this app need to be working in the background 2. the app file will have with all configuration user password to register to our sip server so client do not need to use user and password 3. the app register it self with a remote sip server 4. the result for this app will be , our remote server send a c...
I have IntPtr video stream. I need to play in WPF MediaElement. I found solution here [log ind for at se URL] I need someone can undestand well of video rendering and help me to build also for my solution something like this : [log ind for at se URL]
I need a new website. I need you to design and build a website for my small business.
An iOS and Android App to change your stuff with the tinder swipe modus. give the worth of your product and swap it with everyone in your near.
i need a trendy and cute outro for my youtube channell
We have a great long-term business to work with North America or Northern European Candidates at the moment. If you are based in this area, this job is right for you. If not, please don't apply. We don't want to wast of our time. We will immediately move forward to next step. Thanks.


So I have been training myself to write different letters, words, drawings and thoughts with both hands simultaneously and I am making a fair amount of progress.
I made this page to record how I am learning this skill before I forget how I learned it.
- Start by drawing a circle with one hand and square with the other.
- Think of the motions of the two hands as one motion.
- Experiment with different pressure at different parts of the stroke.
- Improve fine motor skills in left hand by writing without having the hand touch the paper. Also, practice writing on vertical surfaces.
- Characters with subtle differences are good practice. Try drawing an S with one hand and a 5 with the other.
- Think about formatting/alignment too.
- Move your arms when you write! Both of them.
- Learn to anticipate potential pencil slips so you know where to adjust.
- Don’t press to hard.
- Don’t hesitate to focus.
Right now I am working on applying this with more abstract thoughts:
I am starting with characters as the units to write simulateously, then graduate to words, sentences…
When I try to hold two different thoughts in my mind at the same time the two thoughts become one thought. I want to continue practicing this to see where it takes me.


//
//  FXMainCompositionBuilder.h
//  FXVideoEdit
//
//  Created by xunni zou on 2020/7/28.
//  Copyright © 2020 xunni zou. All rights reserved.
//

#import <Foundation/Foundation.h>

@class FXTimelineDescribe;
@class FXMainComposition;

@interface FXMainCompositionBuilder : NSObject

- (id)initWithTimeline:(FXTimelineDescribe *)timelineDescribe;

- (FXMainComposition *)buildComposition;

- (FXMainComposition *)buildCompositionForExport;

@end


Running the BitBoxBase means connecting to other Bitcoin and Lightning Network peers. If done over the regular internet protocol (IPv4), your IP address is visible to all your communication partners. As IP addresses can be located geographically, this means revealing your physical location, from the general area down to individual city blocks (the granularity depends on how your internet service provider manages IP addresses). You can easily locate yourself using services like https://iplocation.io or http://www.infosniper.net.
Revealing your location with the information that you are using Bitcoin is not a good idea. This is why the BitBoxBase uses The Onion Router (Tor) to communicate to other Bitcoin peers privately and without revealing your real IP address.
By creating “hidden services”, Tor can also be used to securely access your BitBoxBase from outside your local network without having to configure any networking devices, such as port-forwarding on your router.
Please not that only Bitcoin-related communication is routed over Tor.
Tor is installed using signed Debian packages from the official repository at
The Tor configuration is application-specific:
- Bitcoin Core
bitcoindis not configured to listen to other Tor nodes.
- To connect to other Bitcoin nodes, all communication is routed over the Tor SOCKS proxy. This configuration is set in
/etc/bitcoin/bitcoin.confwith the option
proxy=127.0.0.1:9050. Peers will see a regular IP address, but one that belongs to the Tor network and not your own.
lightningdis configured to use the Tor SOCKS proxy, as specified in
- It can be reached from the outside using Tor hidden services, that are specified in
HiddenServiceDir /var/lib/tor/hidden_service_lightningd/ HiddenServiceVersion 3 HiddenServicePort 9375 127.0.0.1:9735
- Electrs does not include advanced networking features and relies on other applications for these, e.g. on NGINX to provide SSL encryption, or a correctly configured Tor hidden service.
- Access to
electrsis configured in
HiddenServiceDir /var/lib/tor/hidden_service_electrs/ HiddenServiceVersion 3 HiddenServicePort 50002 127.0.0.1:50002
- Middleware The Base Middleware API is also accessible as a Tor hidden service, configured in
HiddenServiceDir /var/lib/tor/hidden_service_bbbmiddleware/ HiddenServiceVersion 3 HiddenServicePort 9375 127.0.0.1:8845
- SSH If enabled (off by default), SSH login is also available using a Tor hidden service, configured in
HiddenServiceDir /var/lib/tor/hidden_service_ssh/ HiddenServiceVersion 3 HiddenServicePort 22 127.0.0.1:22
Each hidden service is represented as a directory in
/var/lib/tor/ that contains files storing public and secret keys as well as a dedicated hostname (ending in
The individual hostnames are stored in the file
hostname and can also be queried from Redis:
tor:lightningd:onion tor:electrs:onion tor:bbbmiddleware:onion tor:ssh:onion
Tor is started and managed by systemd, but no manual configuration of the unit is required, as the standard configuration activated at package installation is used.