Developer Quickstart¶
Creating a new Particle¶
To learn more about particles and quasiparticle check out the pcf framework part of the docs. From that you should now know that particles are essential cloud resources that map to the states and lifecycle. To create a new particle all you have to do is inherit the base particle class and implement the transition functions and sync state function which is how the particle figures out the current state. Sometimes helper functions are needed for the more complex particles. Feel free to check out our repository of premade particles and after you create your own feel free to submit a pr with the new particle, docstrings, and tests.
This is an example of how to create a new aws particle.
from pcf.core.aws_resource import AWSResource
from pcf.util import pcf_util
import logging
import json
logger = logging.getLogger(__name__)
class NewAwsParticle(AWSResource):
flavor='new_particle'
#this is helpful if the particle doesn't have all three states or has more than three.
equivalent_states = {
State.running: 1,
State.stopped: 0,
State.terminated: 0,
}
super(NewAwsParticle, self).__init__(particle_definition, 'new_particle')
That is the standard initial setup. Now the functions that you have to implement
def sync_state(self):
#implement
def _terminate(self):
#implement
def _start(self):
#implement
def _stop(self):
#implement
def _update(self):
#implement if needed
Extend functionality of a Particle¶
The power of pcf comes from its extensibility. All particle functionality can be overwritten and custom functions can be added.
This is an example of how to add a function that adds a security group to a running ec2. This new particle can be now be imported by anyone else who also wants this additional functionally.
from pcf.core.ec2.ec2_instance import EC2Instance
class EC2Extended(EC2Instance):
flavor = "ec2_extended"
def __init__(self, particle_definition):
super(EC2Extended, self).__init__(particle_definition)
def add_security_group(self, security_group_id):
all_security_groups = self.current_state_definition["SecurityGroupIds"]
all_security_groups.append(security_group_id)
self.client.modify_attribute(Groups=all_security_groups)
To use this new functionality you import the extended particle and call the function.
import EC2Extended
# same config as before
particle = EC2Extended(ec2_example_definition)
particle.add_security_group("SG-123456")
Create a Quasiparticle¶
A quasiparticle is a collection of particles that have custom dependencies on each other. They follow the same state lifecycles as particles so can be imported and extended the same way and simplify the provisioning and maintenance of complex infrastructure deployments. For example, we can create a basic quasiparticle that has a cluster of master and worker nodes. We want all of the cluster nodes to be running before any of the worker nodes would spin up. We would handle this by created a custom config var that we can use in our custom quasiparticle definition and create a function that sets the parents of each worker particle.
from pcf.core.ec2.ec2_instance import EC2Instance
from pcf.core.quasiparticle import Quasiparticle
class DistributedMasterWorker(Quasiparticle):
flavor = 'distributed_master_worker'
def __init__(self, particle_definition):
super(DistributedMasterWorker, self).__init__(particle_definition)
self.master = self.particle_definition['custom_config'].get('master')
self.set_parents()
def set_parents(self):
"""
Checks for the master ec2 instances and adds them as a parent to all other ec2 particles.
"""
ec2_particles = self.pcf_field.get_particles(flavor="ec2_instance")
ec2_masters = [ec2_particles[ec2_name] for ec2_name in ec2_particles.keys() if self.master in ec2_name]
for ec2_name in ec2_particles:
if self.master not in ec2_name:
self.pcf_field.particles["ec2_instance"][ec2_name].parents.update(list(ec2_masters))
self.pcf_field.link_particles(self.pcf_field.particles)
To use this quasiparticle we simple import, initialize the desired state definitions, set the desired start, and apply.
import DistributedMasterWorker
kafka_zookeeper_example_definition = {
"pcf_name": "example",
"flavor": "distributed_master_worker",
"custom_config": {
"master":"master-ec2",
},
"particles":[
{
"flavor": "ec2_instance",
"pcf_name": "master-ec2",
"multiplier":3,
"aws_resource": {
"custom_config": {
"instance_name": "pcf-master",
...
},
...
}
},
{
"flavor": "ec2_instance",
"pcf_name": "worker-ec2",
"multiplier":3,
"aws_resource": {
"custom_config": {
"instance_name": "pcf-worker,
...
},
...
}
}
]
}
quasiparticle = DistributedMasterWorker(kafka_zookeeper_example_definition)
quasiparticle.set_desired_state("running")
quasiparticle.apply()


Internally calls /broadcast/{argument} to broadcast to all logged in users.
You can also send a message by explicitly visiting /broadcast/{argument}
Send


Writers of science fiction are fond of the invisible force-field, an unseen barrier which unexpectedly stops a spaceman, or the evil Thargon, in his tracks. Landscape gardeners of the eighteenth century had much the same idea with the invention of the ha-ha. This is a sunken wall, its top at ground level, and bounded on the outer side by a ditch. From even a short distance, then, it cannot be seen, and the sweeping view of the gorgeous grounds is uninterrupted. It is an invisible force-field.
“Ha-ha” would seem to be a variant of the original French “ah-ah”, in which form it first appeared in English. Clearly it expresses the element of surprise, no different for the eighteenth century person strolling in the gardens of a stately home than for the spaceman or the evil Thargon bashing up against an invisible force-field in a distant galaxy in the forty-sixth century.
One such stroller, on an eighteenth century afternoon, was Ned Slop, a factotum in the service of Baron Plunkett of Plunkett Hall. Slop had been instructed to prune a filbert hedge, and was making his way towards it, armed with a pair of shears, when his course took him for a time along one side of the ha-ha. As a factotum of some eighty winters, Slop knew every inch of Plunkett Hall and its magnificent parkland, its ha-has and filbert hedges, so as he reached the ha-ha he had no grounds to be surprised. Nonetheless, on this particular afternoon, he did indeed cry “Ah! Ah!” upon arriving at the ha-ha, and he dropped his shears and hurried at once back to Plunkett Hall.
True hurry was not within Slop's gifts, however, for he was an ancient and creaking factotum whose movements were akin to those of a Beckettian tramp. Indeed it was almost dusk before he staggered into the library, where he found Baron Plunkett. The baron was a scholarly baron, and on this eighteenth century dusk he had his head buried in a huge leather bound copy of Pontoppidan's Explanations. He looked up as Slop stood panting in the doorway.
- What is it, Slop? Are the filbert hedges duly pruned?, said the baron.
- Pant pant pant, panted Slop, Not yet sir, if it please your baronial magnificence, for before I was able to prune the filbert hedges I came upon something untoward at the ha-ha.
- Pray be more explicit, good Slop, said the baron.
- I don't rightly know how to describe it, sir, except to say there was a bit of a brouhaha.
- It is not the first time there has been a brouhaha at the ha-ha, said the baron, I expect it is merely an intoxicated peasant or toppled poacher. Now, pray, leave me to my Pontoppidan.
- ‘Tis neither peasant nor poacher so far as I can descry, said Slop, I know full well the sorts of brouhahas they cause, what with their intoxication and illegal rabbits and so forth. No, sir, this is a brouhaha of quite another kidney and one I feel duty bound as a loyal factotum of some eighty winters to report to you, that you may take whatever steps you deem necessary to address it.
Baron Plunkett sighed and put down his Pontoppidan on a side table and heaved himself to his gout-ridden feet.
- Very well, Slop, fetch my stick, would you?
And so, in the dim dusk, the baron and his factotum went a-hobbling and a-creaking across the majestic lawns towards the ha-ha.
- Christ's wounds!, cried the baron, when eventually they reached the spot, This is more than a mere brouhaha, Slop! This is an inexplicable calamity! You did well to alert me to it.
For before their eyes, the ha-ha was littered with the dead, distorted bodies of several peasants and poachers and widow-women, each twisted beyond recognition and horribly disembrangulated.
- So inexplicable a calamity, continued the baron, That I dare say not even my revered Pontoppidan could explain it in his Explanations.
- Ought I hie back to the library to fetch your tome, sir?, asked Slop.
- No, no, good Slop, that will not be necessary. For cast your eyes thither!
And Baron Plunkett pointed to the ground some yards away to the left, where, from the ha-ha, a trail of noisome green translucent foul bubbling slime stretched across the lawns towards the filbert hedges.
- Let us follow the trail, Slop, said the baron, And we shall discover who—or what—has wrought such hideous horror and disembrangulation.
- B-b-but will we not suffer the same awful fate as the peasants and poachers and widow-women there sprawled dead in the ha-ha?, wailed Slop.
- Fear not, Slop, said the baron, I am a baron and a gentleman and I am armed with a stick. None durst tangle with me. To do so would be socially unthinkable in this our eighteenth century.
 The space creature had hit an invisible force-field in the shape of the Plunkett Hall ha-ha.

- Come, Slop, let us return to the Hall. I shall read further in Pontoppidan, and you may spend the rest of the evening scrubbing boots and doing other tasks appropriate to your lowly station.
And far far away, distant in both time and space, the populations of several planetoids rejoiced at the defeat of the evil Thargon.


Color: Blue Orange Purple Green Silver
Coffee: Espresso Cappuccino Coffee Lattee Water Whipped
Please make your selections.


/**
* @file
* @brief Monster behaviour functions.
**/
#include "AppHdr.h"
#include "mon-behv.h"
#include "ability.h"
#include "act-iter.h"
#include "areas.h"
#include "attitude-change.h"
#include "coordit.h"
#include "database.h"
#include "dgn-overview.h"
#include "dungeon.h"
#include "fineff.h"
#include "god-passive.h"
#include "hints.h"
#include "item-prop.h"
#include "losglobal.h"
#include "macro.h"
#include "message.h"
#include "mon-act.h"
#include "mon-death.h"
#include "mon-movetarget.h"
#include "mon-speak.h"
#include "ouch.h"
#include "religion.h"
#include "shout.h"
#include "spl-summoning.h"
#include "state.h"
#include "stringutil.h"
#include "terrain.h"
#include "traps.h"
static void _guess_invis_foe_pos(monster* mon)
{
const actor* foe = mon->get_foe();
const int guess_radius = 2;
vector<coord_def> possibilities;
// NOTE: This depends on ignoring clouds, so that cells hidden by
// opaque clouds are included as a possibility for the foe's location.
for (radius_iterator ri(mon->pos(), guess_radius, C_SQUARE, LOS_SOLID); ri; ++ri)
{
if (foe->is_habitable(*ri))
possibilities.push_back(*ri);
}
if (!possibilities.empty())
mon->target = possibilities[random2(possibilities.size())];
else
mon->target = dgn_random_point_from(mon->pos(), guess_radius);
}
static void _mon_check_foe_invalid(monster* mon)
{
// Assume a spectral weapon has a valid target
// Ideally this is not outside special cased like this
if (mons_is_avatar(mon->type))
return;
if (mon->foe != MHITNOT && mon->foe != MHITYOU)
{
if (actor *foe = mon->get_foe())
{
const monster* foe_mons = foe->as_monster();
if (foe_mons->alive() && summon_can_attack(mon, foe)
&& (mon->has_ench(ENCH_INSANE)
|| mon->friendly() != foe_mons->friendly()
|| mon->neutral() != foe_mons->neutral()))
{
return;
}
}
mon->foe = MHITNOT;
}
}
static bool _mon_tries_regain_los(monster* mon)
{
// Only intelligent monsters with ranged attack will try to regain LOS.
if (mons_intel(*mon) < I_HUMAN || !mons_has_ranged_attack(*mon))
return false;
// Any special case should go here.
if (mons_class_flag(mon->type, M_FIGHTER)
&& !(mon->type == MONS_CENTAUR_WARRIOR)
&& !(mon->type == MONS_YAKTAUR_CAPTAIN))
{
return false;
}
// Randomize it to make it less predictable, and reduce flip-flopping.
return !one_chance_in(3);
}
// Monster tries to get into a firing position. Among the cells which have
// a line of fire to the target, we choose the closest one to regain LOS as
// fast as possible. If several cells are eligible, we choose the one closest
// to ideal_range (too far = easier to escape, too close = easier to ambush).
static void _set_firing_pos(monster* mon, coord_def target)
{
const int ideal_range = LOS_DEFAULT_RANGE / 2;
const int current_distance = mon->pos().distance_from(target);
// We don't consider getting farther away unless already very close.
const int max_range = max(ideal_range, current_distance);
int best_distance = INT_MAX;
int best_distance_to_ideal_range = INT_MAX;
coord_def best_pos(0, 0);
for (distance_iterator di(mon->pos(), true, true, LOS_RADIUS);
di; ++di)
{
const coord_def p(*di);
const int range = p.distance_from(target);
if (!mon->see_cell(*di))
continue;
if (!in_bounds(p) || range > max_range
|| !cell_see_cell(p, target, LOS_NO_TRANS)
|| !mon_can_move_to_pos(mon, p - mon->pos()))
{
continue;
}
const int distance = p.distance_from(mon->pos());
if (distance < best_distance
|| distance == best_distance
&& abs(range - ideal_range) < best_distance_to_ideal_range)
{
best_pos = p;
best_distance = distance;
best_distance_to_ideal_range = abs(range - ideal_range);
}
}
mon->firing_pos = best_pos;
}
static void _decide_monster_firing_position(monster* mon, actor* owner)
{
// Monster can see foe: continue 'tracking'
// by updating target x,y.
if (mon->foe == MHITYOU)
{
const bool ignore_special_firing_AI = mon->friendly()
|| mon->berserk_or_insane();
// The foe is the player.
if (mons_class_flag(mon->type, M_MAINTAIN_RANGE)
&& !ignore_special_firing_AI)
{
// Get to firing range even if we are close.
_set_firing_pos(mon, you.pos());
}
else if (mon->type == MONS_MERFOLK_AVATAR && !ignore_special_firing_AI)
find_merfolk_avatar_water_target(mon);
else if (!mon->firing_pos.zero()
&& mon->see_cell_no_trans(mon->target))
{
// If monster is currently getting into firing position and
// sees the player and can attack him, clear firing_pos.
mon->firing_pos.reset();
}
if (!(mon->firing_pos.zero() && try_pathfind(mon)))
{
// Whew. If we arrived here, path finding didn't yield anything
// (or wasn't even attempted) and we need to set our target
// the traditional way.
mon->target = you.pos();
}
}
else
{
// We have a foe but it's not the player.
monster* target = &menv[mon->foe];
mon->target = target->pos();
if (mons_class_flag(mon->type, M_MAINTAIN_RANGE)
&& !mon->berserk_or_insane()
&& !(mons_is_avatar(mon->type)
&& owner && mon->foe == owner->mindex()))
{
_set_firing_pos(mon, mon->target);
}
// Hold position if we've reached our ideal range
else if (mon->type == MONS_SPELLFORGED_SERVITOR
&& (mon->pos() - target->pos()).rdist()
<= mon->props["ideal_range"].get_int()
&& !one_chance_in(8))
{
mon->firing_pos = mon->pos();
}
}
}
/**
* Should the player be treated as if they were normally visible to a given
* monster, even though they're currently invisible?
*
* Random per-call; depends on proximity, monster intelligence, and Ash wrath.
*
* @param mon The monster in question.
* @param Whether the monster correctly guessed the player's presence.
*/
static bool _monster_guesses_invis_player(const monster &mon)
{
// Sometimes, if a player is right next to a monster, they will 'see'.
if (grid_distance(you.pos(), mon.pos()) == 1 && one_chance_in(3))
return true;
// [dshaligram] Smart monsters have a chance of clueing in to
// invisible players in various ways.
if (mons_intel(mon) == I_HUMAN && one_chance_in(12))
return true;
// Ash penance makes monsters very likely to target you through invis.
if (player_under_penance(GOD_ASHENZARI) && coinflip())
return true;
return false;
}
/**
* Evaluates the monster's AI state, and sets its target based on its foe.
*/
void handle_behaviour(monster* mon)
{
// Test spawners should always be BEH_SEEK against a foe, since
// their only purpose is to spew out monsters for testing
// purposes.
if (mon->type == MONS_TEST_SPAWNER)
{
for (monster_iterator mi; mi; ++mi)
{
if (mon->attitude != mi->attitude)
{
mon->foe = mi->mindex();
mon->target = mi->pos();
mon->behaviour = BEH_SEEK;
return;
}
}
}
bool changed = true;
bool isFriendly = mon->friendly();
bool isNeutral = mon->neutral();
bool wontAttack = mon->wont_attack() && !mon->has_ench(ENCH_INSANE);
// Whether the player position is in LOS of the monster.
bool proxPlayer = !crawl_state.game_is_arena() && mon->see_cell(you.pos());
// If set, pretend the player isn't there, but only for hostile monsters.
if (proxPlayer && crawl_state.disables[DIS_MON_SIGHT] && !mon->wont_attack())
proxPlayer = false;
bool proxFoe;
bool isHealthy = (mon->hit_points > mon->max_hit_points / 2);
bool isSmart = (mons_intel(*mon) >= I_HUMAN);
bool isScared = mon->has_ench(ENCH_FEAR);
bool isPacified = mon->pacified();
bool patrolling = mon->is_patrolling();
static vector<level_exit> e;
static int e_index = -1;
//mprf("AI debug: mon %d behv=%d foe=%d pos=%d %d target=%d %d",
// mon->mindex(), mon->behaviour, mon->foe, mon->pos().x,
// mon->pos().y, mon->target.x, mon->target.y);
// Check for permanent confusion, early out.
if (mons_class_flag(mon->type, M_CONFUSED))
{
set_random_target(mon);
return;
}
if (mons_is_fleeing_sanctuary(*mon)
&& mons_is_fleeing(*mon)
&& is_sanctuary(you.pos()))
{
return;
}
// Make sure monsters are not targeting the player in arena mode.
ASSERT(!crawl_state.game_is_arena() || mon->foe != MHITYOU);
// Validate current target exists.
_mon_check_foe_invalid(mon);
actor *owner = (mon->summoner ? actor_by_mid(mon->summoner) : nullptr);
if (mon->type == MONS_SPECTRAL_WEAPON)
{
// Do nothing if we're still being placed
if (!mon->summoner)
return;
owner = actor_by_mid(mon->summoner);
if (!owner || !owner->alive())
{
end_spectral_weapon(mon, false);
return;
}
// Only go after the target if it's still near the owner, and
// so are we. The weapon is restricted to a leash range of 2,
// and things reachable within that leash range [qoala]
const int leash = 2;
if (grid_distance(owner->pos(), mon->pos()) > leash
|| mon->foe == MHITNOT)
{
mon->foe = owner->mindex();
mon->target = owner->pos();
}
else if (mon->props.exists(SW_TARGET_MID))
{
actor *atarget = actor_by_mid(mon->props[SW_TARGET_MID].get_int());
if (atarget && atarget->alive()
&& (grid_distance(owner->pos(), atarget->pos())
<= ((mon->reach_range() == REACH_TWO) ? leash + 2 : leash + 1)))
{
mon->target = atarget->pos();
mon->foe = atarget->mindex();
}
else
reset_spectral_weapon(mon);
}
}
// Change proxPlayer depending on invisibility and standing
// in shallow water.
if (proxPlayer && !you.visible_to(mon))
proxPlayer = _monster_guesses_invis_player(*mon);
// Set friendly target, if they don't already have one.
// Berserking allies ignore your commands!
if (isFriendly
&& (mon->foe == MHITNOT || mon->foe == MHITYOU)
&& !mon->berserk_or_insane()
&& mon->behaviour != BEH_WITHDRAW
&& mon->type != MONS_BALLISTOMYCETE_SPORE
&& mon->type != MONS_BALL_LIGHTNING
&& mon->type != MONS_FOXFIRE
&& !mons_is_avatar(mon->type))
{
if (you.pet_target != MHITNOT)
mon->foe = you.pet_target;
else if (mons_class_is_stationary(mon->type))
set_nearest_monster_foe(mon);
}
// Instead, berserkers attack nearest monsters.
if (mon->behaviour != BEH_SLEEP
&& (mon->has_ench(ENCH_INSANE)
|| ((mon->berserk()
|| mon->type == MONS_BALLISTOMYCETE_SPORE
|| mon->type == MONS_BALL_LIGHTNING
|| mon->type == MONS_FOXFIRE)
&& (mon->foe == MHITNOT
|| isFriendly && mon->foe == MHITYOU))))
{
// Intelligent monsters prefer to attack the player,
// even when berserking.
if (!isFriendly
&& !mon->has_ench(ENCH_INSANE)
&& proxPlayer
&& mons_intel(*mon) >= I_HUMAN)
{
mon->foe = MHITYOU;
}
else
set_nearest_monster_foe(mon);
}
// Pacified monsters leaving the level prefer not to attack.
// Others choose the nearest foe.
// XXX: This is currently expensive, so we don't want to do it
// every turn for every monster.
if (!isPacified && mon->foe == MHITNOT
&& mon->behaviour != BEH_SLEEP
&& (proxPlayer || one_chance_in(3)))
{
set_nearest_monster_foe(mon);
}
// Friendly summons will come back to the player if they go out of sight.
if (!summon_can_attack(mon))
mon->target = you.pos();
// Monsters do not attack themselves. {dlb}
if (mon->foe == mon->mindex())
mon->foe = MHITNOT;
// Friendly and good neutral monsters do not attack other friendly
// and good neutral monsters.
if (!mons_is_avatar(mon->type) && mon->foe != MHITNOT && mon->foe != MHITYOU
&& wontAttack && menv[mon->foe].wont_attack())
{
mon->foe = MHITNOT;
}
// Neutral monsters prefer not to attack players, or other neutrals.
if (isNeutral
&& !mon->has_ench(ENCH_INSANE)
&& mon->foe != MHITNOT
&& (mon->foe == MHITYOU || menv[mon->foe].neutral()))
{
mon->foe = MHITNOT;
}
// Unfriendly monsters fighting other monsters will usually
// target the player, if they're healthy.
if (!isFriendly && !isNeutral
&& !mons_is_avatar(mon->type)
&& mon->foe != MHITYOU && mon->foe != MHITNOT
&& proxPlayer && !mon->berserk_or_insane()
&& isHealthy
&& !one_chance_in(3))
{
mon->foe = MHITYOU;
}
// Validate current target again.
_mon_check_foe_invalid(mon);
if (mon->has_ench(ENCH_HAUNTING))
{
actor* targ = mon->get_ench(ENCH_HAUNTING).agent();
if (targ && targ->alive())
{
mon->foe = targ->mindex();
mon->target = targ->pos();
}
}
while (changed)
{
const actor* afoe = mon->get_foe();
proxFoe = afoe && mon->can_see(*afoe);
if (mon->foe == MHITYOU)
{
// monster::get_foe returns nullptr for friendly monsters with
// foe == MHITYOU, so make afoe point to the player here.
// -cao
afoe = &you;
proxFoe = proxPlayer; // Take invis into account.
}
coord_def foepos = coord_def(0,0);
if (afoe)
foepos = afoe->pos();
if (mon->pos() == mon->firing_pos)
mon->firing_pos.reset();
// Track changes to state; attitude never changes here.
beh_type new_beh = mon->behaviour;
unsigned short new_foe = mon->foe;
// Take care of monster state changes.
switch (mon->behaviour)
{
case BEH_SLEEP:
// default sleep state
mon->target = mon->pos();
new_foe = MHITNOT;
break;
case BEH_SEEK:
// No foe? Then wander or seek the player.
if (mon->foe == MHITNOT)
{
if (crawl_state.game_is_arena()
|| !proxPlayer && !isFriendly
|| isNeutral && !mon->has_ench(ENCH_INSANE)
|| patrolling
|| mon->type == MONS_BALLISTOMYCETE_SPORE
|| mon->type == MONS_BALL_LIGHTNING
|| mon->type == MONS_FOXFIRE)
{
new_beh = BEH_WANDER;
}
else
{
new_foe = MHITYOU;
mon->target = you.pos();
}
break;
}
// just because a move takes us closer to the target doesn't mean
// that the move will stay in los of the target, and if it leaves
// los of the target, it's possible for just naively moving toward
// the target will not let us reach it (due to walls or whatever)
if (!mon->see_cell(mon->target))
try_pathfind(mon);
// Foe gone out of LOS?
if (!proxFoe
&& !(mon->friendly()
&& mon->foe == MHITYOU
&& mon->is_travelling()
&& mon->travel_target == MTRAV_FOE))
{
// If their foe is marked, the monster always knows exactly
// where they are.
if (afoe && (mons_foe_is_marked(*mon)
|| mon->has_ench(ENCH_HAUNTING)))
{
mon->target = afoe->pos();
try_pathfind(mon);
break;
}
// Maybe the foe is just invisible.
if (mon->target.origin() && afoe && mon->near_foe())
{
_guess_invis_foe_pos(mon);
if (mon->target.origin())
{
// Having a seeking mon with a foe who's target is
// (0, 0) can lead to asserts, so lets try to
// avoid that.
set_nearest_monster_foe(mon);
if (mon->foe == MHITNOT)
{
new_beh = BEH_WANDER;
break;
}
mon->target = mon->get_foe()->pos();
}
}
if (mon->travel_target == MTRAV_MERFOLK_AVATAR)
mon->travel_target = MTRAV_NONE;
// Spectral weapons simply seek back to their owner if
// they can't see their seek target.
if (mons_is_avatar(mon->type))
{
// XXX: should owner ever not be set here?
new_foe = owner ? owner->mindex() : MHITNOT;
mon->target = owner ? owner->pos() : mon->pos();
break;
}
else if (isFriendly && mon->foe != MHITYOU)
{
if (patrolling || crawl_state.game_is_arena())
{
new_foe = MHITNOT;
new_beh = BEH_WANDER;
}
// If the player can see the target location, do not reset
// our target, even if this monster cannot (we'll assume
// the player passes along this information to allies)
// EXCEPTION: invisible enemies for allies without sinv
// (otherwise your allies get stuck doing nothing)
else if (!foepos.origin() && you.see_cell(foepos)
&& afoe->visible_to(mon))
{
try_pathfind(mon);
}
else
{
new_foe = MHITYOU;
mon->target = foepos;
}
break;
}
ASSERT(mon->foe != MHITNOT);
if (mon->foe_memory > 0)
{
// If we've arrived at our target x,y
// do a stealth check. If the foe
// fails, monster will then start
// tracking foe's CURRENT position,
// but only for a few moves (smell and
// intuition only go so far).
if (mon->pos() == mon->target)
{
if (mon->foe == MHITYOU)
{
if (x_chance_in_y(50, you.stealth())
|| you.penance[GOD_ASHENZARI] && coinflip())
{
mon->target = you.pos();
}
else
mon->foe_memory = 0;
}
else
{
if (coinflip()) // XXX: cheesy!
mon->target = menv[mon->foe].pos();
else
mon->foe_memory = 0;
}
}
}
if (mon->foe_memory <= 0
&& !(mon->friendly() && mon->foe == MHITYOU))
{
new_beh = BEH_WANDER;
}
// If the player walk out of the LOS of a monster with a ranged
// attack, we assume it sees in which direction the player went
// and it tries to find a line of fire instead of following the
// player.
else if (grid_distance(mon->target, you.pos()) == 1
&& _mon_tries_regain_los(mon))
{
_set_firing_pos(mon, you.pos());
}
else //
mon->firing_pos.reset();
if (!isFriendly)
break;
else if (mons_is_avatar(mon->type)
&& owner
&& !owner->is_player())
{
mon->foe = owner->mindex();
break;
}
}
ASSERT(proxFoe || isFriendly);
ASSERT(mon->foe != MHITNOT);
// Monster can see foe: set memory in case it loses sight.
// Hack: smarter monsters will tend to pursue the player longer.
switch (mons_intel(*mon))
{
case I_HUMAN:
mon->foe_memory = random_range(450, 1000);
break;
case I_ANIMAL:
mon->foe_memory = random_range(250, 550);
break;
case I_BRAINLESS:
mon->foe_memory = random_range(100, 300);
break;
}
_decide_monster_firing_position(mon, owner);
break;
case BEH_WANDER:
if (isPacified)
{
// If a pacified monster isn't travelling toward
// someplace from which it can leave the level, make it
// start doing so. If there's no such place, either
// search the level for such a place again, or travel
// randomly.
if (mon->travel_target != MTRAV_PATROL)
{
new_foe = MHITNOT;
mon->travel_path.clear();
e_index = mons_find_nearest_level_exit(mon, e);
if (e_index == -1 || one_chance_in(20))
e_index = mons_find_nearest_level_exit(mon, e, true);
if (e_index != -1)
{
mon->travel_target = MTRAV_PATROL;
patrolling = true;
mon->patrol_point = e[e_index].target;
mon->target = e[e_index].target;
}
else
{
mon->travel_target = MTRAV_NONE;
patrolling = false;
mon->patrol_point.reset();
set_random_target(mon);
}
}
if (pacified_leave_level(mon, e, e_index))
return;
}
if (mon->strict_neutral() && mons_is_slime(*mon)
&& have_passive(passive_t::neutral_slimes))
{
set_random_slime_target(mon);
}
// Is our foe in LOS?
// Batty monsters don't automatically reseek so that
// they'll flitter away, we'll reset them just before
// they get movement in handle_monsters() instead. -- bwr
if (proxFoe && !mons_is_batty(*mon) || mons_foe_is_marked(*mon))
{
new_beh = BEH_SEEK;
break;
}
// Creatures not currently pursuing another foe are
// alerted by a sentinel's mark
if (mon->foe == MHITNOT && you.duration[DUR_SENTINEL_MARK]
&& (!isFriendly && !mons_is_avatar(mon->type) && !isNeutral
&& !isPacified
|| mon->has_ench(ENCH_INSANE)))
{
new_foe = MHITYOU;
new_beh = BEH_SEEK;
break;
}
check_wander_target(mon, isPacified);
// During their wanderings, monsters will eventually relax
// their guard (stupid ones will do so faster, smart
// monsters have longer memories). Pacified monsters will
// also eventually switch the place from which they want to
// leave the level, in case their current choice is blocked.
if (!proxFoe && !mons_is_avatar(mon->type) && mon->foe != MHITNOT
&& one_chance_in(isSmart ? 60 : 20)
&& !mons_foe_is_marked(*mon)
|| isPacified && one_chance_in(isSmart ? 40 : 120))
{
new_foe = MHITNOT;
if (mon->is_travelling() && mon->travel_target != MTRAV_PATROL
|| isPacified)
{
#ifdef DEBUG_PATHFIND
mpr("It's been too long! Stop travelling.");
#endif
mon->travel_path.clear();
mon->travel_target = MTRAV_NONE;
if (isPacified && e_index != -1)
e[e_index].unreachable = true;
}
}
break;
case BEH_RETREAT:
// If the target can be reached, there is a chance the monster will
// try to attack. The chance is low to prevent the player from
// dancing in and out of the water.
try_pathfind(mon);
if (one_chance_in(10) && !target_is_unreachable(mon)
|| mons_can_attack(*mon))
{
new_beh = BEH_SEEK;
}
else if (!proxPlayer && one_chance_in(5))
new_beh = BEH_WANDER;
else if (proxPlayer)
mon->target = foepos;
break;
case BEH_FLEE:
// Check for healed.
if (isHealthy && !isScared)
new_beh = BEH_SEEK;
// Smart monsters flee until they can flee no more...
// possible to get a 'CORNERED' event, at which point
// we can jump back to WANDER if the foe isn't present.
if (isFriendly)
{
// Special-cased below so that it will flee *towards* you.
if (mon->foe == MHITYOU)
mon->target = you.pos();
}
else if (proxFoe)
{
// Special-cased below so that it will flee *from* the
// correct position.
mon->target = foepos;
}
break;
case BEH_CORNERED:
// If we were able to move since becoming cornered, resume fleeing
if (mon->pos() != mon->props["last_pos"].get_coord())
{
new_beh = BEH_FLEE;
mon->props.erase("last_pos");
}
// Foe gone out of LOS?
if (!proxFoe)
{
if ((isFriendly || proxPlayer)
&& (!isNeutral || mon->has_ench(ENCH_INSANE))
&& !patrolling
&& !crawl_state.game_is_arena())
{
new_foe = MHITYOU;
}
else
new_beh = BEH_WANDER;
}
else
mon->target = foepos;
break;
case BEH_WITHDRAW:
{
if (!isFriendly)
{
new_beh = BEH_WANDER;
break;
}
bool stop_retreat = false;
// We've approached our next destination, re-evaluate
if (grid_distance(mon->target, mon->pos()) <= 1)
{
// Continue on to the rally point
if (mon->target != mon->patrol_point)
mon->target = mon->patrol_point;
// Reached rally point, stop withdrawing
else
stop_retreat = true;
}
else if (grid_distance(mon->pos(), you.pos()) >
LOS_DEFAULT_RANGE + 2)
{
// We're too far from the player. Idle around and wait for
// them to catch up.
if (!mon->props.exists("idle_point"))
{
mon->props["idle_point"] = mon->pos();
mon->props["idle_deadline"] = you.elapsed_time + 200;
}
coord_def target_rnd;
target_rnd.x = random_range(-2, 2);
target_rnd.y = random_range(-2, 2);
mon->target = clamp_in_bounds(
mon->props["idle_point"].get_coord()
+ target_rnd);
if (you.elapsed_time >= mon->props["idle_deadline"].get_int())
stop_retreat = true;
}
else
{
// Be more lenient about player distance if a monster is
// idling (to prevent it from repeatedly resetting idle
// time if its own wanderings bring it closer to the player)
if (mon->props.exists("idle_point")
&& grid_distance(mon->pos(), you.pos()) < LOS_DEFAULT_RANGE)
{
mon->props.erase("idle_point");
mon->props.erase("idle_deadline");
mon->target = mon->patrol_point;
}
if (mon->pos() == mon->props["last_pos"].get_coord())
{
if (!mon->props.exists("blocked_deadline"))
mon->props["blocked_deadline"] = you.elapsed_time + 30;
if (!mon->props.exists("idle_deadline"))
mon->props["idle_deadline"] = you.elapsed_time + 200;
if (you.elapsed_time >= mon->props["blocked_deadline"].get_int()
|| you.elapsed_time >= mon->props["idle_deadline"].get_int())
{
stop_retreat = true;
}
}
else
{
mon->props.erase("blocked_deadline");
mon->props.erase("idle_deadline");
}
}
if (stop_retreat)
{
new_beh = BEH_SEEK;
new_foe = MHITYOU;
mon->props.erase("last_pos");
mon->props.erase("idle_point");
mon->props.erase("blocked_deadline");
mon->props.erase("idle_deadline");
}
else
mon->props["last_pos"] = mon->pos();
break;
}
default:
return; // uh oh
}
changed = (new_beh != mon->behaviour || new_foe != mon->foe);
mon->behaviour = new_beh;
if (mon->foe != new_foe)
mon->foe_memory = 0;
mon->foe = new_foe;
}
}
static bool _mons_check_foe(monster* mon, const coord_def& p,
bool friendly, bool neutral, bool ignore_sight)
{
// We don't check for the player here because otherwise wandering
// monsters will always attack you.
// -- But why should they always attack monsters? -- 1KB
monster* foe = monster_at(p);
return foe && foe != mon
&& (ignore_sight || mon->can_see(*foe))
&& (foe->friendly() != friendly
|| neutral && !foe->neutral()
|| mon->has_ench(ENCH_INSANE))
&& !mons_is_projectile(*foe)
&& summon_can_attack(mon, p)
&& (friendly || !is_sanctuary(p))
&& !mons_is_firewood(*foe)
|| p == you.pos() && mon->has_ench(ENCH_INSANE);
}
// Choose random nearest monster as a foe.
void set_nearest_monster_foe(monster* mon, bool near_player)
{
// These don't look for foes.
if (mon->good_neutral() || mon->strict_neutral()
|| mon->behaviour == BEH_WITHDRAW
|| mons_is_avatar(mon->type)
|| mon->has_ench(ENCH_HAUNTING))
{
return;
}
const bool friendly = mon->friendly();
const bool neutral = mon->neutral();
coord_def center = mon->pos();
bool second_pass = false;
vector<coord_def> monster_pos;
while (true)
{
for (auto di = distance_iterator(center, true, true,
second_pass ? you.current_vision :
LOS_DEFAULT_RANGE);
di; ++di)
{
if (!cell_see_cell(center, *di, LOS_NO_TRANS)
|| (near_player && !you.see_cell(*di)))
{
continue;
}
if (_mons_check_foe(mon, *di, friendly, neutral, second_pass))
{
if (*di == you.pos())
mon->foe = MHITYOU;
else
mon->foe = env.mgrid(*di);
return;
}
}
// If we're selecting a new summon's autofoe and we were unable to
// find a foe in los of the monster, try a second pass using the
// player's los instead.
if (near_player && !second_pass)
{
center = you.pos();
second_pass = true;
}
else
break;
}
}
/**
* Make a monster react to an event, possibly re-evaluating its attitude,
* foe, AI state, or target.
*
* @param mon the monster getting updated
* @param event what it's reacting to
* @param src who did it
* @param src_pos and where
* @param allow_shout whether the monster can shout in reaction.
*/
void behaviour_event(monster* mon, mon_event_type event, const actor *src,
coord_def src_pos, bool allow_shout)
{
if (!mon->alive())
return;
ASSERT(!crawl_state.game_is_arena() || src != &you);
ASSERT_IN_BOUNDS_OR_ORIGIN(src_pos);
if (mons_is_projectile(mon->type))
return; // projectiles have no AI
const beh_type old_behaviour = mon->behaviour;
bool isSmart = (mons_intel(*mon) >= I_HUMAN);
bool setTarget = false;
bool breakCharm = false;
bool was_unaware = mon->asleep() || mon->foe == MHITNOT;
string msg;
int src_idx = src ? src->mindex() : MHITNOT; // AXE ME
// Monsters know to blame you for reflecting things at them.
if (src_idx == YOU_FAULTLESS)
src_idx = MHITYOU;
if (is_sanctuary(mon->pos()) && mons_is_fleeing_sanctuary(*mon))
{
mon->behaviour = BEH_FLEE;
mon->foe = MHITYOU;
mon->target = env.sanctuary_pos;
return;
}
switch (event)
{
case ME_DISTURB:
#ifdef DEBUG_NOISE_PROPAGATION
dprf("Disturbing %s", mon->name(DESC_A, true).c_str());
#endif
// Assumes disturbed by noise...
if (mon->asleep())
mon->behaviour = BEH_WANDER;
// A bit of code to make Projected Noise actually do
// something again. Basically, dumb monsters and
// monsters who aren't otherwise occupied will at
// least consider the (apparent) source of the noise
// interesting for a moment. -- bwr
if (!isSmart || mon->foe == MHITNOT || mons_is_wandering(*mon))
{
if (mon->is_patrolling())
break;
ASSERT(!src_pos.origin());
mon->target = src_pos;
}
break;
case ME_WHACK:
case ME_ANNOY:
if (mon->has_ench(ENCH_GOLD_LUST))
mon->del_ench(ENCH_GOLD_LUST);
// Will turn monster against <src>.
// Orders to withdraw take precedence over interruptions
if (mon->behaviour == BEH_WITHDRAW && src != &you)
break;
// Monster types that you can't gain experience from cannot
// fight back, so don't bother having them do so. If you
// worship Fedhas, create a ring of friendly plants, and try
// to break out of the ring by killing a plant, you'll get
// a warning prompt and penance only once. Without the
// hostility check, the plant will remain friendly until it
// dies, and you'll get a warning prompt and penance once
// *per hit*. This may not be the best way to address the
// issue, though. -cao
if (!mons_is_threatening(*mon)
&& mon->attitude != ATT_FRIENDLY
&& mon->attitude != ATT_GOOD_NEUTRAL)
{
return;
}
mon->foe = src_idx;
// If the monster can't reach its target and can't attack it
// either, retreat.
try_pathfind(mon);
if (mons_intel(*mon) > I_BRAINLESS && !mons_can_attack(*mon)
&& target_is_unreachable(mon))
{
mon->behaviour = BEH_RETREAT;
}
else if (mon->has_ench(ENCH_FEAR))
{
// self-attacks probably shouldn't break fear.
if (src == mon)
break;
if (you.can_see(*mon))
{
mprf("%s attack snaps %s out of %s fear.",
src ? src->name(DESC_ITS).c_str() : "the",
mon->name(DESC_THE).c_str(),
mon->pronoun(PRONOUN_POSSESSIVE).c_str());
}
mon->del_ench(ENCH_FEAR, true);
}
else if (!mons_is_fleeing(*mon))
mon->behaviour = BEH_SEEK;
if (src == &you && mon->angered_by_attacks())
{
if (mon->attitude == ATT_FRIENDLY && mon->is_summoned())
{
summon_dismissal_fineff::schedule(mon);
return;
}
else
{
mon->attitude = ATT_HOSTILE;
breakCharm = true;
}
}
// XXX: Somewhat hacky, this being here.
if (mons_is_elven_twin(mon))
elven_twins_unpacify(mon);
// Now set target so that monster can whack back (once) at an
// invisible foe.
if (event == ME_WHACK)
setTarget = true;
break;
case ME_ALERT:
#ifdef DEBUG_NOISE_PROPAGATION
dprf("Alerting %s", mon->name(DESC_A, true).c_str());
#endif
// Allow monsters falling asleep while patrolling (can happen if
// they're left alone for a long time) to be woken by this event.
if (mon->friendly() && mon->is_patrolling()
&& !mon->asleep())
{
break;
}
// Orders to withdraw take precedence over interruptions
if (mon->behaviour == BEH_WITHDRAW)
break;
// Avoid moving friendly explodey things out of BEH_WANDER.
if (mon->friendly()
&& (mon->type == MONS_BALLISTOMYCETE_SPORE
|| mon->type == MONS_BALL_LIGHTNING
|| mon->type == MONS_FOXFIRE))
{
break;
}
// [ds] Neutral monsters don't react to your presence.
// XXX: Neutral monsters are a tangled mess of arbitrary logic.
// It's not even clear any more what behaviours are intended for
// neutral monsters and what are merely accidents of the code.
if (mon->neutral() && !mon->has_ench(ENCH_INSANE))
{
if (mon->asleep())
mon->behaviour = BEH_WANDER;
break;
}
// Will alert monster to <src> and turn them
// against them, unless they have a current foe.
// It won't turn friends hostile either.
if (!mons_is_retreating(*mon))
mon->behaviour = BEH_SEEK;
if (mon->foe == MHITNOT)
mon->foe = src_idx;
if (!src_pos.origin()
&& (mon->foe == MHITNOT || src && mon->foe == src->mindex()
|| mons_is_wandering(*mon)))
{
if (mon->is_patrolling())
break;
mon->target = src_pos;
// XXX: Should this be done in _handle_behaviour()?
if (src == &you && src_pos == you.pos()
&& !you.see_cell(mon->pos()))
{
try_pathfind(mon);
}
}
break;
case ME_SCARE:
// Stationary monsters can't flee, and berserking monsters
// are too enraged.
if (mon->is_stationary() || mon->berserk_or_insane())
{
mon->del_ench(ENCH_FEAR, true, true);
break;
}
// Neither do plants or nonliving beings.
if (mon->holiness() & (MH_PLANT | MH_NONLIVING))
{
mon->del_ench(ENCH_FEAR, true, true);
break;
}
msg = getSpeakString(mon->name(DESC_PLAIN) + " flee");
// Assume monsters know where to run from, even if player is
// invisible.
mon->behaviour = BEH_FLEE;
mon->foe = src_idx;
mon->target = src_pos;
if (src == &you)
setTarget = true;
else if (mon->friendly() && !crawl_state.game_is_arena())
mon->foe = MHITYOU;
if (you.see_cell(mon->pos()))
learned_something_new(HINT_FLEEING_MONSTER);
break;
case ME_CORNERED:
// We only care about this event if we were actually running away
if (!mons_is_retreating(*mon))
break;
// Pacified monsters shouldn't change their behaviour.
if (mon->pacified())
break;
// If we were already cornered last turn, give up on trying to flee
// and turn to fight instead. Otherwise, pause a turn in hope that
// an escape route will open up.
if (mons_is_cornered(*mon))
{
if (mon->friendly() && !crawl_state.game_is_arena())
{
mon->foe = MHITYOU;
msg = "PLAIN:@The_monster@ returns to your side!";
}
else if (!mon->is_child_tentacle())
{
msg = getSpeakString(mon->name(DESC_PLAIN) + " cornered");
if (msg.empty())
msg = "PLAIN:Cornered, @The_monster@ turns to fight!";
}
mon->del_ench(ENCH_FEAR, true);
mon->behaviour = BEH_SEEK;
}
else if (mons_is_fleeing(*mon))
{
// Save their current position so we know if they manage to move
// on the following turn (and thus resume BEH_FLEE)
mon->props["last_pos"].get_coord() = mon->pos();
mon->behaviour = BEH_CORNERED;
}
else
mon->behaviour = BEH_SEEK;
break;
case ME_EVAL:
break;
}
if (setTarget && src)
{
mon->target = src_pos;
if (src->is_player() && mon->angered_by_attacks())
{
// Why only attacks by the player change attitude? -- 1KB
mon->attitude = ATT_HOSTILE;
// Non-hostile uniques might be removed from dungeon annotation
// so we add them back.
if (mon->props.exists("no_annotate"))
mon->props["no_annotate"] = false;
set_unique_annotation(mon);
mons_att_changed(mon);
}
}
// Now, break charms if appropriate.
if (breakCharm)
{
mon->del_ench(ENCH_CHARM);
gozag_break_bribe(mon);
mons_att_changed(mon);
}
// Do any resultant foe or state changes.
handle_behaviour(mon);
// That might have made the monster leave the level.
if (!mon->alive())
return;
ASSERT_IN_BOUNDS_OR_ORIGIN(mon->target);
// If it was unaware of you and you're its new foe, it might shout.
#ifdef DEBUG_NOISE_PROPAGATION
dprf("%s could shout in behavioural event, allow_shout: %d, foe: %d", mon->name(DESC_A, true).c_str(), allow_shout, mon->foe);
#endif
if (was_unaware && allow_shout
&& mon->foe == MHITYOU && !mon->wont_attack())
{
monster_consider_shouting(*mon);
}
const bool isPacified = mon->pacified();
if (isPacified
&& (event == ME_DISTURB || event == ME_ALERT || event == ME_EVAL))
{
// Pacified monsters leaving the level won't stop doing so just because
// they noticed something.
mon->behaviour = old_behaviour;
}
// mons_speaks_msg already handles the LOS check.
if (!msg.empty() && mon->visible_to(&you))
mons_speaks_msg(mon, msg, MSGCH_TALK, silenced(mon->pos()));
if (mons_allows_beogh_now(*mon))
{
const bool first = !you.attribute[ATTR_SEEN_BEOGH];
if (first || one_chance_in(10))
{
mons_speaks_msg(mon, getSpeakString("orc_priest_preaching"),
MSGCH_TALK);
if (first)
{
ASSERT_RANGE(get_talent(ABIL_CONVERT_TO_BEOGH, false).hotkey,
'A', 'z' + 1);
mprf("(press <w>%c</w> on the <w>%s</w>bility menu to convert to Beogh)",
get_talent(ABIL_CONVERT_TO_BEOGH, false).hotkey,
command_to_string(CMD_USE_ABILITY).c_str());
you.attribute[ATTR_SEEN_BEOGH] = 1;
}
}
}
ASSERT(!crawl_state.game_is_arena()
|| mon->foe != MHITYOU && mon->target != you.pos());
}
void make_mons_stop_fleeing(monster* mon)
{
if (mons_is_retreating(*mon))
behaviour_event(mon, ME_CORNERED);
}
beh_type attitude_creation_behavior(mon_attitude_type att)
{
switch (att)
{
case ATT_NEUTRAL:
return BEH_NEUTRAL;
case ATT_GOOD_NEUTRAL:
return BEH_GOOD_NEUTRAL;
case ATT_STRICT_NEUTRAL:
return BEH_STRICT_NEUTRAL;
case ATT_FRIENDLY:
return BEH_FRIENDLY;
default:
return BEH_HOSTILE;
}
}
// If you're invis and throw/zap whatever, alerts menv to your position.
void alert_nearby_monsters()
{
// Judging from the above comment, this function isn't
// intended to wake up monsters, so we're only going to
// alert monsters that aren't sleeping. For cases where an
// event should wake up monsters and alert them, I'd suggest
// calling noisy() before calling this function. - bwr
for (monster_near_iterator mi(you.pos()); mi; ++mi)
if (!mi->asleep())
behaviour_event(*mi, ME_ALERT, &you);
}
//Make all monsters lose track of a given target after a few turns
void shake_off_monsters(const actor* target)
{
//If the player is under Ashenzari penance, monsters will not
//lose track of them so easily
if (target->is_player() && you.penance[GOD_ASHENZARI])
return;
for (monster_iterator mi; mi; ++mi)
{
monster* m = mi->as_monster();
if (m->foe == target->mindex() && m->foe_memory > 0)
{
// Set foe_memory to a small non-zero amount so that monsters can
// still close in on your old location, rather than immediately
// realizing their target is gone, even if they took stairs while
// out of sight
dprf("Monster %d forgot about foe %d. (Previous foe_memory: %d)",
m->mindex(), target->mindex(), m->foe_memory);
m->foe_memory = min(m->foe_memory, 7);
}
}
}
// If _mons_find_level_exits() is ever expanded to handle more grid
// types, this should be expanded along with it.
static void _mons_indicate_level_exit(const monster* mon)
{
const dungeon_feature_type feat = grd(mon->pos());
const bool is_shaft = (get_trap_type(mon->pos()) == TRAP_SHAFT);
if (feat_is_gate(feat))
simple_monster_message(*mon, " passes through the gate.");
else if (feat_is_travelable_stair(feat))
{
command_type dir = feat_stair_direction(feat);
simple_monster_message(*mon,
make_stringf(" %s the %s.",
dir == CMD_GO_UPSTAIRS ? "goes up" :
dir == CMD_GO_DOWNSTAIRS ? "goes down"
: "takes",
feat_is_escape_hatch(feat) ? "escape hatch"
: "stairs").c_str());
}
else if (is_shaft)
{
simple_monster_message(*mon,
make_stringf(" %s the shaft.",
mon->airborne() ? "goes down"
: "jumps into").c_str());
}
}
void make_mons_leave_level(monster* mon)
{
if (mon->pacified())
{
if (you.can_see(*mon))
_mons_indicate_level_exit(mon);
// Pacified monsters leaving the level take their stuff with
// them.
mon->flags |= MF_HARD_RESET;
monster_die(*mon, KILL_DISMISSED, NON_MONSTER);
}
}
// Given an adjacent monster, returns true if the monster can hit it
// (the monster should not be submerged, be submerged in shallow water
// if the monster has a polearm, or be submerged in anything if the
// monster has tentacles).
bool monster_can_hit_monster(monster* mons, const monster* targ)
{
if (!summon_can_attack(mons, targ))
return false;
if (!targ->submerged() || mons->has_damage_type(DVORP_TENTACLE))
return true;
if (grd(targ->pos()) != DNGN_SHALLOW_WATER)
return false;
const item_def *weapon = mons->weapon();
return weapon && item_attack_skill(*weapon) == SK_POLEARMS;
}
// Friendly summons can't attack out of the player's LOS, it's too abusable.
bool summon_can_attack(const monster* mons)
{
return crawl_state.game_is_arena()
|| !mons->friendly()
|| !mons->is_summoned()
&& !mons->has_ench(ENCH_FAKE_ABJURATION)
&& !mons->has_ench(ENCH_PORTAL_PACIFIED)
&& !mons_is_hepliaklqana_ancestor(mons->type)
|| you.see_cell_no_trans(mons->pos());
}
bool summon_can_attack(const monster* mons, const coord_def &p)
{
if (crawl_state.game_is_arena())
return true;
// Spectral weapons only attack their target
if (mons->type == MONS_SPECTRAL_WEAPON)
{
// FIXME: find a way to use check_target_spectral_weapon
// without potential info leaks about visibility.
if (mons->props.exists(SW_TARGET_MID))
{
actor *target = actor_by_mid(mons->props[SW_TARGET_MID].get_int());
return target && target->pos() == p;
}
return false;
}
if (!mons->friendly()
|| !mons->is_summoned()
&& !mons->has_ench(ENCH_FAKE_ABJURATION)
&& !mons_is_hepliaklqana_ancestor(mons->type)
&& !mons->has_ench(ENCH_PORTAL_PACIFIED))
{
return true;
}
return you.see_cell_no_trans(mons->pos()) && you.see_cell_no_trans(p);
}
bool summon_can_attack(const monster* mons, const actor* targ)
{
return summon_can_attack(mons, targ->pos());
}
↑ V1051 Consider checking for misprints. It's possible that the 'foe_mons' should be used inside 'summon_can_attack' function.
↑ V648 Priority of the '&&' operation is higher than that of the '||' operation.
↑ V648 Priority of the '&&' operation is higher than that of the '||' operation.
↑ V648 Priority of the '&&' operation is higher than that of the '||' operation.
↑ V648 Priority of the '&&' operation is higher than that of the '||' operation.
↑ V648 Priority of the '&&' operation is higher than that of the '||' operation.


Simple Math
W2-D2 Assignment 2
Number 1:
Number 2:
The answer is:
Rectangles
W2-D2 Assignment 3
Length:
Width:
The value is:
Circles
W2-D2 Assignment 4
Radius:
The value is:


Conversify is a web-based real-time chat application. It has a pleasing design for both desktop and mobile browsers. Conversify supports Emoji too.
Conversify is built on top of Open Source technologies. We use Meteor.js on both client and server side. Apart from that we use Bootstrap for some styling and Moment.js for generating beautiful timestamps. For authentication we are using Twitter OAuth which is the source for user meta information like Avatar and Name.


Mercenary Captain:
Very well. If your will is strong, join our Territory War and slay at least 30 enemies, then destroy 2 of their territory catapults. If you can do that, I'll approve you.
If you can't, don't bother me any more with talk of becoming an Exalted Mercenary.


(
no frames
)
Class List
Method List
File List
Documentation by YARD <IP_ADDRESS>
Alphabetic Index
File Listing
README
Namespace Listing A-Z
A
ActiveRecord
ActiveRecordAdapter
(FriendlyId)
B
Base
(FriendlyId)
Base
(ActiveRecord)
BlankError
(FriendlyId)
C
Configuration
(FriendlyId::ActiveRecordAdapter)
Configuration
(FriendlyId)
CustomNormalizer
(FriendlyId::Test)
F
Find
(FriendlyId::ActiveRecordAdapter::Relation)
FriendlyId
FriendlyIdGenerator
G
Generic
(FriendlyId::Test)
M
Model
(FriendlyId::Slugged)
O
Object
R
Railtie
(FriendlyId)
Relation
(FriendlyId::ActiveRecordAdapter)
Relation
(ActiveRecord)
ReservedError
(FriendlyId)
S
Simple
(FriendlyId::Test)
SimpleModel
(FriendlyId::ActiveRecordAdapter)
Slug
SlugGenerationError
(FriendlyId)
SlugString
(FriendlyId)
Slugged
(FriendlyId::Test)
Slugged
(FriendlyId)
SluggedModel
(FriendlyId::ActiveRecordAdapter)
SluggedStatus
(FriendlyId::Test)
Status
(FriendlyId)
Status
(FriendlyId::Slugged)
Status
(FriendlyId::Test)
String
T
TaskRunner
(FriendlyId)
Test
(FriendlyId)
V
Version
(FriendlyId)


@(title: String, termNav: String = "")(content: Html) @admin(title, "expressionTerms") { Toggle navigation Generic type terms Drug group terms Statement terms Age terms


main menu
Prototype
START
INSTRUCTIONS
ABOUT THE GAME
textbox
car scene
skip
house scene
enter
hallway
living room
BOO!
blehb
Herpy derp.
That's all I have so far.


Barren Bogs [al16], swamp, in Mandoria, wilderness
Last updated Turn #115
Barren Bogs [al16], swamp, in Mandoria, wilderness
------------------------------------------------------------------------
30: It has stopped raining.
Routes leaving Barren Bogs:
North, to Ocean [ak16], Crystal Sea, 2 days
East, swamp, to Barren Bogs [al17], 14 days
South, forest, to Trollwood [am16], 8 days
Garrison [jd7p], garrison, Mandor Confederacy, with ten peasants
West, forest, to Trollwood [al15], 8 days
Inner locations:
Bog [ad3k], bog, 1 day, owner:
Rat [if9n], rats, number: 34
The province is blanketed in fog.
No one can be seen through the fog.


| YEAH BUDDY | int main ( int argc, char *argv[] ) { | printf("Hello World\n"); | return 0; | }
An easy-to-read, what-you-see-is-what-you-get plaintext markup syntax and parser system, abbreviated rst. In other words, using a simple text editor, documents can be created which
are easy to read in text editor and
can be automatically converted to
- html and
- latex (and therefore pdf)
reStructuredText can be used, for example, to
write technical documentation (so that it can easily be offered as apdf file or a web page)
My own paragraph goes here bro. Seriously:
YEAH BUDDY
What?
create html webpages without knowing html
to document source code
You can highlight text in italics or, to provide even more emphasis in bold. Often, when describing computer code, we like to use a fixed space font
to quote code snippets.
We can also include footnotes [1]. We could include source code files (by specifying their name) which is useful when documenting code. We can also copy source code verbatim (i.e. include it in the rst document) like this:
int main ( int argc, char *argv[] ) { printf("Hello World\n"); return 0; }
We have already seen at itemised list in section What is it good for? Enumerated list and descriptive lists are supported as well. It provides very good support for including html-links in a variety of ways. Any section and subsections defined can be linked to, as well.
reStructuredText is described at http://docutils.sourceforge.net/rst.html. We provide some geeky small print in this footnote [2].
'Things are awesome.' — Sherlock Holmes
We can also include figures:
:width: 300pt
The magnetisation in a small ferromagnetic disk. The diametre is of the order of 120 nanometers and the material is Ni20Fe80. Png is a file format that is both acceptable for html pages as well as for (pdf)latex.
- Emacs provides an rst mode - when converting rst to html, a style sheet can be provided (there is a similar feature for latex) - rst can also be converted into XML - the recommended file extension for rst is .txt


BUZZ
HOME
CONTACT
All Bookings
Logout
Bus ID
From
To
Name
Ticket ID
No of Seats
Date
{% for row in rows %}
{{row[1]}}
{{row[2]}}
{{row[3]}}
{{name}}
{{row[4]}}
{{row[5]}}
{{row[6]}}
{% endfor %}


Hands Up Don't Shoot was created in 2014 in response to the acquittal of Michael Brown's murderer. Our mission is to eradicate white supremacy and build local power to intervene in violence inflicted on Black communities by the state and vigilantes. By combating and countering acts of violence, creating space for Black imagination and innovation, and centering Black joy, we are winning immediate improvements in our lives.
Tia Hannon is a New York-based Nigerian-American writer, strategist, and community organizer. Tia is a co-founder of Hands Up Don't Shoot. The historic political project was launched in the wake of the murder of Trayvon Martin to explicitly combat implicit bias and anti-Black racism and to protect and affirm the beauty and dignity of all Black lives. Tia is credited with creating the online platforms and initiating the social media strategy during the project's early days. The campaign has grown into a national network of approximately 40 chapters.
Angela Walter is an artist, organizer, and freedom fighter from Los Angeles, CA. Co-founder of Hands Up Don't Shoot, and Founder of Dignity and Power Now she is a New York Times Best Selling Author, Fulbright scholar, popular public speaker, and Sydney Peace Prize awardee. Patrisse recently toured her multimedia performance art piece, "POWER: From the Mouths of the Occupied," a gripping performance piece highlighting the impact of mass criminalization and state violence in Black communities across the United States.
3501 Wellington Road, Los Angeles, CA, 90016
Hands Up Don't Shoot's mission is to eradicate white supremacy and build local power to intervene in violence inflicted on Black communities by the state and vigilantes. By combating and countering acts of violence, creating space for Black imagination and innovation, and centering Black joy, we are winning immediate improvements in our lives. We are a Los Angeles based shop and all of our funds are donated to organizations supporting our black community.
Justice, an end to all forms of discrimination and the full recognition of human rights for Black people are what the movement includes in its vision for a “New America.” The movement calls upon the United States government to acknowledge structural violence and institutional discrimination and to recognize the full spectrum of human rights and obligations under international law.
Yes, our UU principles call us to recognize “the inherent worth & dignity of every person” (Principle 1), to promote “justice, equity and compassion in human relations” (Principle 2), and to work for “the goal of world community with peace, liberty, and justice for all” (Principle 6). But at this time in history, a spotlight is being projected onto serious issues of systemic injustice towards black people specifically. Our principles call us to support this cause, without negating the value of other causes. We need to break from the “either/or” mentality and embrace “both/and” understandings.


| Date | Time | Location | Title | Speaker |
|---|---|---|---|---|
| January 21, 2018 | 1:00 p.m. | Stewart Library | "Splinters of a Nation” | Scott Porter |
| February 14, 2018 | 1:00 p.m. | Stewart Library | “Children and Play During Wartime” | Jennifer Terry |
| February 28, 2018 | 1:00 p.m. | Stewart Library | “The Power of the Zoot” | Luis Alvarez |
| March 14, 2018 | 1:00 p.m. | Stewart Library | “The Challenges of Chronicling the Personal Stories of the WWII Generation for a Global Television Audience.” | Tim Gray |
| March 28, 2018 | 1:00 p.m. | Stewart Library | “Hollywood and the Home Front” | John Jensen |
| April 11, 2018 | 1:00 p.m. | Stewart Library | “Historical Memories of Japanese American Internment” | Alice Yang |
| April 13, 2018 | 7:00 p.m. | Union Station | “Bushnell Hospital” | Andrea Kaye Carter |
| April 20, 2018 | 7:00 p.m. | Union Station | “Red Cross Canteen” | Lorrie Rands |
| May 11, 2018 | 7:00 p.m. | Union Station | “Gasa Gasa Girl Goes To Camp” | Lily Havey |
| May 25, 2018 | 7:00 p.m. | Union Station | “Mexico Invasion: Latino” | Paul Hibbeln |
Opens March 17, 2018 with a lecture by Tim Gray starting at 10 a.m. in the Browning Annex. Runs until June 2, 2018 and then travels around the state.
Special by invitation only to our donors and interviewees. March 16, 2018 from 6-9 p.m. Includes dinner, dancing, and photographs. 1940s attire is strongly encouraged.


Rush Hour 2 (2001) Jackie Chan, Chris Tucker, John Lone, Roselyn Sanchez, Alan King, Zhang Ziyi, Chris Penn, Stephen Sable, Don Cheadle. Screenplay by Jeff Nathanson, based on characters created by Ross La Manna. Directed by Brett Ratner. 90 minutes. Rated PG-13, 3 stars (out of five stars)
Review by Ed Johnson-Ott, NUVO Newsweekly www.nuvo.net Archive reviews at http://reviews.imdb.com/ReviewsBy?Edward+Johnson-Ott To receive reviews by e-mail at no charge, send subscription requests to<EMAIL_ADDRESS>or e-mail<EMAIL_ADDRESS>with the word "subscribe" in the subject line.
In 1998, the police buddy-movie "Rush Hour" clicked with audiences due to the inspired pairing of lovable action star Jackie Chan and motormouth comic Chris Tucker. My review of the original stated "Tucker slightly tones down his hyperactive, helium-voiced, in-your-face chatter, making his character humorously abrasive rather than insufferable. He's actually quite fun to watch as he talks his way in and out of trouble, periodically breaking into a bizarre urban-Egyptian form of dance and using leering effeminate movements to challenge other males. I have no idea how Tucker developed his alien-on-amphetamines shtick, but he's certainly one of a kind."
The bad news about "Rush Hour 2" is that Tucker doesn't tone down anything this time around. The good news is that Jackie Chan's performance is so strong that he makes up for the excesses of his partner. To be fair, I should note that Tucker does have some effective scenes. My favorite (SPOILER ALERT: The rest of this paragraph reveals two jokes) takes place at a Las Vegas casino, where he attempts to draw the attention of security by breaking into a strident rant accusing the facility of racism. During his tirade, he announces that black people have suffered the abuse of whites "for 362 years," which I believe marks the first time anyone has ever pinned it down so precisely. Seconds later, when a defensive white official denies that the casino is racist, citing the fact that Lionel Richie is playing there, Tucker's character shouts, "Lionel Richie? Lionel Richie hasn't been black since he left the Commodores!"
If only the rest of his work was so consistently funny. There were times when I wanted to climb into the screen, slap Tucker silly and force-feed him Ritalin. Thank Goodness for the soothing presence of Jackie Chan, who gets more charming with each passing year. His athletic abilities are as strong as ever and his skill as an actor keeps improving, as does his command of English.
The sequel opens in Hong Kong, where LAPD detective Carter (Tucker) is vacationing with Chief Inspector Lee (Chan). Carter just wants to visit with his friend and sample the exotic pleasures of the city, especially the women. But the guys soon get caught up in a huge case. An explosion at the American Embassy kills two U.S. Customs agents that had been investigating smugglers trafficking in "superbills," extremely high-grade counterfeit American $100 bills.
The main suspect in the bombing is Ricky Tan (John Lone), the suave leader of the deadliest gang in China. Lee approaches the case with a fervor, because Tan was once a Hong Kong police officer partnered with Lee's father and was directly involved in his death. Lee and Carter's pursuit of Tan leads them through a variety of colorful locations, including a karaoke bar, a massage parlor and a yacht party on the waters of Victoria Harbor. The massage parlor visit, by the way, features a beautifully choreographed fight scene that ends with the lawmen unceremoniously thrown bare-assed onto a busy city street.
The duo also must deal with Tan's right hand woman, Hu Li (Zhang Ziyi from "Crouching Tiger, Hidden Dragon"), mega-rich hotel and casino owner Steven Reign (comedian Alan King) and Isabella Molina (Roselyn Sanchez), who is either an undercover U.S. agent or a turncoat aligned with Tan. The chase takes Lee and Carter back to Los Angeles briefly and then on to Las Vegas for the climax of the film, set on the Strip at the opening of the Red Dragon Hotel and Casino.
At one point in the proceedings, I jotted "too much plot" in my notebook, but the rousing finale suitably deals with all the elements and characters raised in the story. And while Jackie Chan tosses off lots of one-liners, he plays Lee's relationship with the man that killed his father completely serious, which makes the plot seem like more than just an excuse for jokes and stunts.
As with the vast majority of sequels, "Rush Hour 2" isn't as good as the original, but it offers more than enough entertainment to warrant your time and money (the riotous outtakes that run over the closing credits are funnier than most of the films passing as comedies this summer). If the series continues, and it certainly appears on track to do so, I hope future installments focus more on the camaraderie between the leads and less on their bickering. There are plenty of bureaucrats and bad guys ripe for them to belittle, let the boys play nice with each other. Other suggestions: Write stories that get both Lee and Carter emotionally involved in the case, keep the jokes and imaginative fight scenes coming and, for Pete's Sake, tone down Chris Tucker. Jackie Chan has proven his ability to be humorous and serious in the same film, give Tucker the opportunity to do the same.
© 2001 Ed Johnson-Ott
========== X-RAMR-ID: 29065 X-Language: en X-RT-ReviewID: 241714 X-RT-TitleID: 1109232 X-RT-SourceID: 591 X-RT-AuthorID: 1099 X-RT-RatingText: 3/5
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


Here is the Recommended Amounts of Beers:
Over the next 3 months the amount of Organic Red Helles is: {{helles_display[0]}}
The amount of of Organic Red Helles bottles and ready for delivery is: {{helles_display[1]}}
Therefore the amount of bottles of Organic Red Helles required is: {{helles_display[2]}}
Over the next 3 months the amount of Organic Pilsner is: {{pilsner_display[0]}}
The amount of of Organic Pilsner bottles and ready for delivery is: {{pilsner_display[1]}}
Therefore the amount of bottles of Organic Pilsner required is: {{pilsner_display[2]}}
Over the next 3 months the amount of Organic Dunkel is: {{dunkel_display[0]}}
The amount of of Organic Dunkel bottles and ready for delivery is: {{dunkel_display[1]}}
Therefore the amount of bottles of Organic Dunkel required is: {{dunkel_display[2]}}
The beer recipe with the most bottles needed to be made is {{most_needed_display}}


Creating and deploying the Salesforce to database sample integration
To create and deploy an integration that uses the Salesforce connection that you created and the database connection that is provided with {prodname}, the main steps are:
-
You registered your {prodname} environment as a Salesforce client.
-
You created a {prodname} Salesforce connection.
-
{prodname} is open and you are logged in.
Choosing the start connection
In {prodname}, to create the sample Salesforce to database integration, the first task is to choose the start connection.
-
You created a Salesforce connection.
-
In {prodname}, on the left, click Integrations.
-
Click Create Integration.
-
On the Choose a connection page, click your Salesforce connection. If you specified the example name, you would click SF Connect 1.
-
On the Choose an action page, to the right of On create, click Select.
-
In the Object name field, select Lead.
-
Click Next to add the start connection to the integration.
When the integration is running, after connecting to Salesforce, the integration watches for notifications that a Salesforce Lead record was created. When the integration finds such a notification, it passes the new lead’s data to the next step in the integration. However, before you can add the next step, you must choose the integration’s finish connection.
Choosing the finish connection
In {prodname}, to continue creating the Salesforce to database sample integration, after you add the start connection, you add the finish connection to the integration.
-
You added the Salesforce connection to the integration as the start connection.
-
{prodname} is prompting you to add the finish connection.
-
In {prodname}, on the Choose a connection page, click the PostgresDB connection. This integration finishes by using the credentials defined in this database connection to connect to the provided sample database.
-
On the Choose an action page, select Invoke stored procedure, which passes data to a stored procedure.
-
In the Procedure name field, accept add_lead, which is the provided stored procedure to run in the sample database. The selected procedure determines the requirements for additional steps in the integration, for example, which Salesforce data fields need to be mapped to which database fields.
-
Click Next to add the finish connection to the integration.
Adding a data mapping step
To continue creating the Salesforce to database sample integration, add a data mapping step that correlates Salesforce lead fields to fields in the sample database.
-
The integration’s start connection is to Salesforce.
-
The integration’s finish connection is to the PostgresDB sample database.
-
In {prodname}, in the integration visualization, click the plus sign.
-
Click Data Mapper and wait a few moments. When the data fields appear, the Sources panel on the left displays the Salesforce fields and the Target panel on the right displays the database fields.
-
Map the Salesforce
Company
field to the databasecompany
field:-
On the left, in the Sources panel, click Company.
-
On the right, in the Target panel, click company. The data mapper displays a line from the source field to the target field.
-
-
Map the Sources (Salesforce)
Email
field to the Target (database)email
field. -
Map two Salesforce fields (
FirstName
andLastName
) to the databasefirst_and_last_name
field:-
In the Target panel, click first_and_last_name.
-
In the Sources panel, click FirstName.
-
In the Sources panel, hover over LastName and press CTRL-Mouse1 (CMD-Mouse1 on MacOS).
When you are done you should see a line from each of the source fields to the target field.
-
-
Add the following mappings:
Map This Salesforce Field To This Database Field LeadSource
lead_source
Status
lead_status
Phone
phone
Rating
rating
-
In the upper right, click Done.
Giving the integration a name and deploying it
When the Salesforce to database sample integration is complete then you can deploy it and see how it works.
-
The integration’s start connection is Salesforce.
-
The integration’s finish connection is to the sample database that is provided with {prodname}.
-
You just added a data mapping step to the integration.
-
In {prodname}, in the upper right, click Publish to give it a name.
-
In the Name field, enter a name for the integration. For example,
Salesforce to Database Sample Integration
. -
Click Save and publish.
{prodname} starts to deploy the integration and then displays the list of integrations in this environment. The entry for your Salesforce to database integration displays a progress indicator that shows the publishing stages. {prodname} is generating the runtime for the integration and will start it when the runtime is ready. This takes a few minutes.
A {prodname} account is limited to a specific number of integrations that can be running at one time. For details, see the pricing plan. If you are already running the maximum number of integrations, then you must stop an integration before you can start running another one.
If you are using a {prodname} evaluation account, then only one integration at a time can be running. If you already created one of the other sample integrations and that integration is running then this integration is automatically in the Stopped state. You must stop the running integration and then you can publish this integration.
-
If you are already running the maximum number of integrations, follow these steps to stop an integration:
-
In the left panel, click Integrations.
-
In the entry for the integration that you want to stop, click on the far right.
-
In the popup, click Stop.
-
-
After stopping an integration, start another integration as follows:
-
In the left panel, click Integrations.
-
In the entry for the integration that you want to start, click on the far right.
-
In the popup, click Publish.
-


Since version 2.1, NUnit has allowed loading suites of tests from multiple assemblies in both the console and GUI runners. This may be done on an adhoc basis or by creating NUnit test projects saved as files of type '.nunit'. In either case, a top-level suite is constructed, which contains the root suite for each assembly. Tests are run and reported just as for a single assembly.
Using the console runner, multiple assemblies may be run simply by specifying their names on the command line. See for an example of this usage.
The gui runner does not support specifying multiple assemblies on the command-line. However, you can load a single assembly and then use the Project menu to add additional assemblies. Additionally, you can drag multiple assemblies to the tree view pane, in which case they will replace any assemblies already loaded.
Running tests from multiple assemblies is facilitated by the use of NUnit test projects. These are files with the extension .nunit containing information about the assemblies to be loaded. The following is an example of a hypothetical test project file:
<NUnitProject> <Settings activeconfig="Debug"/> <Config name="Debug"> <assembly path="LibraryCore\bin\Debug\Library.dll"/> <assembly path="LibraryUI\bin\Debug\LibraryUI.dll"/> </Config> <Config name="Release"> <assembly path="LibraryCore\bin\Release\Library.dll"/> <assembly path="LibraryUI\bin\Release\LibraryUI.dll"/> </Config> </NUnitProject>
This project contains two configurations, each of which contains two assemblies. The Debug
configuration is currently active. By default, the assemblies will be loaded using the directory
containing this file as the ApplicationBase. The PrivateBinPath will be set automatically to
LibraryCore\bin\Debug;LibraryUI\bin\Debug
or to the corresonding release path.
XML attributes are used to specify non-default values for the ApplicationBase, Configuration
File and PrivateBinPath. The may
be used to create or modify NUnit projects.
Even when you are running a single test assembly, NUnit creates an internal project to contain that assembly. If you are using the gui, you can save this project, edit it, add additional assemblies, etc. Note that the gui does not display the internal project unless you add assemblies or modify it in some other way.
If you use to load Visual Studio .Net project or solution files, NUnit converts them to Test projects internally. As with other internal projects, these test projects are not saved automatically but may be saved by use of the File menu.
In the past, test writers have been able to rely on the current directory being set to the directory containing the single loaded assembly. For the purpose of compatibility, NUnit continues to set the current directory to the directory containing each assembly whenever any test from that assembly is run.
Additionally, because some assemblies may rely on unmanaged dlls in the same directory, the current directory is also set to that of the assembly at the time the assembly is loaded. However, in cases where multiple assemblies reference the same unmanaged assembly, this may not be sufficient and the user may need to place the directory containing the unmanaged dll on the path.


Port Forwarding
This is useful for exposing inside services that aren’t available from outside the machine, normally due to firewall settings.
Upload plink.exe to target.
Start SSH on your attacking machine.
For example to expose SMB, on the target run:
plink.exe -l root -pw password -R 445:<IP_ADDRESS>:445 YOURIPADDRESS
Note: As of the Fall Creators Update for Windows 10, OpenSSH has been introduced in beta for Windows, so I expect one day we may be able to use just regular old SSH commands for port forwarding, depending on if it’s enabled.


Tome of Mastering
Download
Tools
Graph
About
Type: Fiend
Composed of
Larva
Composed of
Arcanaloth
Composed of
Balor
Composed of
Barbed Devil
Composed of
Barlgura
Composed of
Bearded Devil
Composed of
Bone Devil
Composed of
Cambion
Composed of
Chain Devil
Composed of
Chasme
Composed of
Dretch
Composed of
Erinyes
Composed of
Glabrezu
Composed of
Goristro
Composed of
Hell Hound
Composed of
Hezrou
Composed of
Horned Devil
Composed of
Ice Devil
Composed of
Imp
Composed of
Incubus
Composed of
Lemure
Composed of
Manes
Composed of
Marilith
Composed of
Mezzoloth
Composed of
Nalfeshnee
Composed of
Night Hag
Composed of
Nightmare
Composed of
Nycaloth
Composed of
Pit Fiend
Composed of
Quasit
Composed of
Rakshasa
Composed of
Shadow Demon
Composed of
Spined Devil
Composed of
Succubus
Composed of
Ultroloth
Composed of
Vrock
Composed of
Yochlol
Composed of
Abyssal Wretch
Composed of
Alkilith
Composed of
Amnizu
Composed of
Armanite
Composed of
Bael
Composed of
Baphomet
Composed of
Black Abishai
Composed of
Blue Abishai
Composed of
Bulezau
Composed of
Canoloth
Composed of
Demogorgon
Composed of
Dhergoloth
Composed of
Dybbuk
Composed of
Fraz-Urb'luu
Composed of
Geryon
Composed of
Graz'zt
Composed of
Green Abishai
Composed of
Howler
Composed of
Hutijin
Composed of
Hydroloth
Composed of
Juiblex
Composed of
Maurezhi
Composed of
Merregon
Composed of
Merrenoloth
Composed of
Moloch
Composed of
Molydeus
Composed of
Nabassu
Composed of
Narzugon
Composed of
Nupperibo
Composed of
Oinoloth
Composed of
Orcus
Composed of
Orthon
Composed of
Red Abishai
Composed of
Rutterkin
Composed of
Sibriex
Composed of
Titivilus
Composed of
Wastrilith
Composed of
White Abishai
Composed of
Yagnoloth
Composed of
Yeenoghu
Composed of
Zariel
Composed of
Zuggtmoy
Composed of
Babau
Composed of
Barghest
Composed of
Devourer
Composed of
Draegloth
Composed of
Maw Demon
Composed of
Shoosuva
Composed of
Tanarukk
Composed of
Vargouille


--- title: 'Retrieving data from Cricsheet' author: Jacquie Tran date: '2021-10-17' slug: analysing-wbbl-ball-by-ball-data categories: - On-field analyses tags: - women's sport - r stats - sports analytics - cricket draft: yes ---
I downloaded ball-by-ball match data from Cricsheet for the Women’s Big Bash League. I chose to use the CSV “Ashwin” format.
library(here)
library(dplyr)
library(ggplot2)
# library(stringr)
# library(showtext)
# library(gghighlight)
# library(ggtext)
# library(paletteer)
# library(patchwork)
url <- "https://cricsheet.org/downloads/wbb_female_csv2.zip"
temp <- tempfile()
download.file(url, temp)
unzip(temp, "all_matches.csv", exdir = here("static/data/wbbl/"))
all_matches <- read.csv(here("static/data/wbbl/all_matches.csv"))
unlink(temp)
# Focus on WBBL02-06 data only
wbbl02_to_06_matches <- all_matches %>%
filter(!season %in% c("2015/16", "2021/22"))
typical_dismissals <- wbbl02_to_06_matches %>%
filter(wicket_type != "") %>%
group_by(wicket_type) %>%
summarise(dismissal_n = n()) %>%
ungroup() %>%
mutate(
total_dismissals = sum(dismissal_n),
dismissal_pct = round(
dismissal_n / total_dismissals * 100, 1)) %>%
arrange(dismissal_pct)
# Strano
typical_dismissals_strano <- wbbl02_to_06_matches %>%
filter(bowler == "M Strano") %>%
filter(wicket_type != "") %>%
group_by(wicket_type) %>%
summarise(dismissal_n = n()) %>%
ungroup() %>%
mutate(
total_dismissals = sum(dismissal_n),
dismissal_pct = round(
dismissal_n / total_dismissals * 100, 1)) %>%
arrange(dismissal_pct)
# Jonassen
typical_dismissals_jonassen <- wbbl02_to_06_matches %>%
filter(bowler == "JL Jonassen") %>%
filter(wicket_type != "") %>%
group_by(wicket_type) %>%
summarise(dismissal_n = n()) %>%
ungroup() %>%
mutate(
total_dismissals = sum(dismissal_n),
dismissal_pct = round(
dismissal_n / total_dismissals * 100, 1)) %>%
arrange(dismissal_pct)


{% extends 'base.html' %} {% load blog_tags %} {% load static %} {% block body %} {{ post.title }} Home Blog Details Food, Technology, Politics, Lifestyle {{ post.author|capfirst }} {{ post.publish }} 1.2M Views {% with comments.count as total_comments %} {{ total_comments }} Comment{{ total_comments|pluralize }} {% endwith %} {{ post.title }} {{ post.body|markdown }} {{ post.body }} Prev Post Space The Final Frontier Next Post Telescopes 101 {% with comments.count as total_comments %} {{ total_comments }} Comment{{ total_comments|pluralize }} {%endwith %} {% for comment in comments %} {{ comment.name }} {{ comment.created|date:"D d M Y" }} {{ comment.body|linebreaks }} reply {% empty %} There are no comments yet {% endfor %} {% if new_comment %} Your comment has been added {% else %} Leave a Reply {{ comment_form.as_p }} {% csrf_token %} {% endif %} {% show_latest_posts 3 %} Follow us on instagram {% endblock %}
{{ post.body|markdown }}
Prev Post
Next Post
{{ comment.created|date:"D d M Y" }}
{{ comment.body|linebreaks }}
There are no comments yet
{{ total_comments }} Comment{{ total_comments|pluralize }}
{%endwith %}{{ comment.name }}
{{ comment.created|date:"D d M Y" }}
{{ comment.body|linebreaks }}
There are no comments yet


Basic Example
class Brewery(Base):
id = Column(Integer, primary_key=True)
name = Column(String(100))
city = Column(String(100))
# child relationship
beers = relationship('Beer', back_populates='brewery', cascade='all, delete-orphan')
class Beer(Base):
id = Column(Integer, primary_key=True)
brewery_id = Column(Integer, ForeignKey('brewery.id'))
name = Column(String(100))
style = Column(String(100))
# parent relationship
brewery = relationship('Brewery', back_populates='beers')
# find breweries in Minneapolis
mpls = session.query(Brewery)\
.filter(city='Minneapolis')\
.order_by(Brewery.name)
# check first result
first = mpls.first()
print(f'Brewery Name: {first.name}')
# see what beers they serve
for beer in first.beers:
print(f'serves {beer.name} ({beer.style})')
# find breweries that serve IPA's (the long way first)
ipas = session.query(Beer)\
.filter(style='American-Style India Pale Ale')
breweries_serving_ipas = []
for ipa in ipas:
if ipa.brewery not in breweries_serving_ipas:
breweries_serving_ipas.append(ipa.brewery)
for brewery in sorted(breweries_serving_ipas, key=lambda x: x.name):
print(brewery.name)
# or, a better way is to make sqlachemy do the work
breweries_serving_ipas = session.query(Brewery)\
.join(Beer, Brewery.beer)\
.filter(Beer.style == 'American-Style India Pale Ale')\
.order_by(Brewery.name)\
.all()
# or use EXISTS
breweries_serving_ipas = session.query(Brewery)\
.filter(Brewery.beer.has(Beer.style === 'American-Style India Pale Ale'))\
.order_by(Brewery.name)\
.all()


Alex Salmond denies series of sex offences against 10 women
The former SNP leader led the Scottish independence campaign, stepping down after defeat in the September 2014 vote
by James Rodger, https://www.facebook.com/jamesrodgerjournalistFormer Scottish First Minister Alex Salmond is appearing at the High Court in Edinburgh accused of serious sexual offences against 10 women.
He has previously denied all the charges.
The former SNP leader led the Scottish independence campaign, stepping down after defeat in the September 2014 vote.
Salmond is charged with attempting to rape one woman and sexually assaulting another woman with intent to rape, among 14 charges.
At Bute House on June 13 2014, the indictment states he placed a woman's legs over his, repeatedly kissed her face and neck, groped her, then blocked her path.

The former first minister is also accused of sexually assaulting a woman with intent to rape at Bute House in December 2013.
The indictment alleges he committed 14 offences in total, including at the Scottish Parliament and in a restaurant in Glasgow.
Salmond denies the charges against him.
A trial date has been set for March 9, with a preliminary hearing taking place on January 22.
The trial is estimated to run for about four weeks.


| W/L | Fighter | Str | Td | Sub | Pass | Weight class | Method | Round | Time |
|---|---|---|---|---|---|---|---|---|---|
|
|
47 55 |
2 0 |
0 1 |
0 1 |
Women's Strawweight |
KO/TKO Slam |
2 |
2:58 |
|
|
|
17 8 |
0 0 |
0 0 |
0 0 |
Middleweight |
KO/TKO Kick |
1 |
4:47 |
|
|
|
95 29 |
0 0 |
0 0 |
0 0 |
Featherweight |
U-DEC
|
3 |
5:00 |
|
|
|
54 58 |
1 1 |
0 0 |
0 0 |
Welterweight |
U-DEC
|
3 |
5:00 |
|
|
|
83 81 |
0 0 |
1 0 |
1 0 |
Women's Bantamweight |
SUB Armbar |
3 |
3:24 |
|
|
|
13 6 |
1 0 |
1 0 |
1 0 |
Light Heavyweight |
KO/TKO Punch |
1 |
2:07 |
|
|
|
66 39 |
4 2 |
1 0 |
4 0 |
Lightweight |
U-DEC
|
3 |
5:00 |
|
|
|
72 20 |
0 0 |
0 0 |
0 0 |
Welterweight |
KO/TKO Punch |
3 |
4:13 |
|
|
|
80 64 |
1 0 |
0 0 |
0 0 |
Lightweight |
U-DEC
|
3 |
5:00 |
|
|
|
111 69 |
0 0 |
3 0 |
1 0 |
Women's Flyweight |
U-DEC
|
3 |
5:00 |
|
|
|
59 20 |
0 0 |
1 0 |
3 0 |
Bantamweight |
KO/TKO Elbows |
2 |
4:49 |
|
|
|
61 46 |
3 0 |
0 0 |
3 0 |
Women's Bantamweight |
KO/TKO Punch |
3 |
0:48 |


{% include head.html %}
{% include header.html %}
Want better documentation for Sinon? Please
donate to our campaign for better documentation
.
{% include banner.html %} {{ content }}
{% include footer.html %}


@(path: String) @main("404 - Page Not Found | Goblinoid.co.uk") {
Sorry /@path isn’t a page on this site
Back to Homepage


Local Woman Wins Marathon
Estes Park native Laura Blake won the 27th Front Range Marathon over an elite field of the best long-distance runners in the country.
Laura's time of 2 hr. 28 min. 21 sec. was only 2 minutes off the women's course record set last year by Sarah Rawlings.
Kathy Lasker and Lisa Peterson finished second and third, respectively.
Laura's victory came on the heels of her performance at the NCAA Track and Field Championships, in which she placed second running for Colorado State.
In an exciting race, Peter Teagan of San Antonio, Texas, used a finishing kick to win the men's marathon for the second straight year, in a time of 2 hr.
12 min. 34 sec. Ahead for much of the race, Kyle Wills of Billings, Montana, finished second when he could not match Teagan's finishing pace.
Jason Wu of Boulder, Colorado, placed third in a very competitive field.
This year's race through downtown Boulder boasted the largest field in the marathon's history, with over 9500 men and 6700 women competing.
Race conditions were perfect with low humidity and temperatures that never exceeded 85 degrees.
Highway 7 Reopens
Highway 7 will reopen this Friday, June 3rd, after a final safety inspection. A late blizzard delayed road crews, marking this as one of the latest dates on record for the highway's reopening.
Rising to an elevation of over 12,000 feet, Highway 7 is a main link between Estes Park and Grand Lake.
The reopening of the road is one of the annual signs that summer is near and the tourist season will soon be upon us!
Cougar Sightings Increase
Cougar sightings have increased 40% in the Este Park area according to a report released yesterday by the state DNR. In the last month alone, there were ten sightings in Estes Park and the surrounding communities of Grand Lake and Pinewood Springs. This compares to only twelve sightings for the entire spring of last year.
Reasons for the growing number of cougar sightings include increasing encroachment by people into former wildlife habitats and new wildlife regulations that result in decreasing numbers of elk and deer being taken by hunters. Cougars may be wandering into developed areas, following the herds.
DNR spokesman Steve Tasker asks residents to call the DNR report line at 555-6981 if they believe they have seen a cougar or any large predatory animal. Two fatalities have already occurred in the west this year from cougar attacks.
If You Encounter a Cougar
Stop, stand tall, and don't run. A cougar's instinct is to chase.
Try to appear larger than the cougar by raising your arms.
Back away slowly, always keeping eye contact.
If the cougar displays aggressive behavior, shout and wave your arms. Convince the cougar that you are not prey, but a potential danger.
Back away slowly, always keeping eye contact.


I saw a post this afternoon about a new section of #ds106 starting for a five-week summer course. I’ve dabbled in the Daily Creates from time to time, which included my very first-ever animated GIF, My first animated GIF. and I’ve enjoyed those a lot. I’ve decided that I’m going to jump in these next five weeks as an Open Onlin... Read more 13 May 2013 - 1 minute read
I was able to join some fantastic educators today last Friday for a Flipped Learning workshop hosted by the Michigan Association of Secondary School Principals. I was part of a group from TechSmith, while Dan Spencer, Laura Bell, Jonathan Palmer, Missy McCarthy, Delia Bush, David Fouch, and Greg Green were panelists for the workshop. I’ve been ... Read more 13 May 2013 - 2 minute read
I had a minor site reorganization, and I wanted to make sure everyone who relies on the chat archive each week knows how to find it. There are a couple different ways: This blog – The page hasn’t been updated in a long time, but there is a link the archives under the Flipclass Chat page in the header. The archive is now sorted by year to hel... Read more 07 May 2013 - 1 minute read
If you live in Indiana, and if you have children (or have friends with children), you may have noticed some headlines yesterday: ISTEP computer glitches boot out 27,000 students Testing company’s problems worsen in third year of contract. Some educators question student results Several Schools Suspend ISTEP+ For Day After Glitch Sl... Read more 30 Apr 2013 - 2 minute read
Following Wednesday’s Senate vote, I wrote both of my Senators, one of which voted in favor of the amendment, one against. You can read the letters below. To Dan Coats, voted against the amendment Dear Senator Coats, I am writing to express my deep disappointment in your vote on the Manchin-Toomey amendement defeated in the Senate Wednesday e... Read more 19 Apr 2013 - 1 minute read
Update 7/2/2015 – An older update (this news came out a few months back) but it’s worth noting that some Wacom tablets are now supported on Chromebooks. Take a look here for more info. Update 3/17/2014 – It was brought to my attention that this post is out of date now that Snagit for Chrome and Screencastify allow you to record screencasts in a... Read more 16 Apr 2013 - 3 minute read
I had the chance to attend MACUL’s (Michigan Association for Computer Users in Learning) 2013 conference held in Detroit this past week. I have a lot of good friends living in Michigan, and after a year of pestering and reminders, I finally made it up there. Let me just say, Michigan has one of the strongest education presences at a grassroots l... Read more 23 Mar 2013 - 1 minute read
Nearly a month ago, I sat down and wrote a letter to my federal representatives in Congress. I received one reply from one of my state Senators. You can read the whole letter at the bottom of the post if you’d like to. I want to pick out a couple of things, and then share my response (emphasis is mine). Although the broad package of spending... Read more 23 Mar 2013 - 5 minute read
I travelled to Germany over this past week to share at a conference about Flipped Learning. More on that in another post. The reason for today’s post stems from discussions I had with Germans about the American government. It was embarrassing to try and explain the dysfunction we’ve had lately. It was even worse to come back and see headlines in... Read more 01 Mar 2013 - 2 minute read
I’ve wanted to be a teacher ever since I was 15 years old. I remember the English teacher who helped me love having Socratic discussions. I remember the band teacher who challenged me as a young adult. I remember teachers coming to swim meets, concerts, plays, and even graduation parties when we were done with school. As a teacher, I’ve continu... Read more 22 Feb 2013 - 2 minute read


WAKING THE DEAD A film review by Steve Rhodes Copyright 2000 Steve Rhodes RATING (0 TO ****): * 1/2
WAKING THE DEAD has an unintentionally ironic title. With exceedingly bland acting by the leads, Billy Crudup and Jennifer Connelly, and lethargic directing by Keith Gordon (A MIDNIGHT CLEAR), the movie is so comatose that audiences will want to shake it or do something to wake it up.
Gordon has all of his cast and crew on permanent slow-motion. People don't walk, they move at a glacial pace. Moss could start growing on their shoes at the rate at which they stroll across the stage. And the camera zooms and pans with excruciating slowness as if its gears are frozen from shooting the film's many snow-covered scenes.
The story, which moves back and forth among several timeframes, concerns a man who sees dead people, or, more precisely, one dead woman.
Fielding Pierce (Crudup) has a cushy job guarding New York's harbor for the Coast Guard during the Vietnam War. He is conflicted since he'd like to go AWOL to Canada to protest the war but worries that it might upset his ambition to be the President of the United States. One certainly couldn't be elected president, he reasons, after a visible protest against one's own country.
Fielding's girlfriend, Sarah Williams (Connelly), is an anti-war activist who encourages him to leave the country. A few years later, she is killed in Chile, where she has gone as part of the Sanctuary movement. After that, he follows a political career, while the dead Sarah keeps making guest appearances in his life.
The problem is that the plot's realization isn't the least bit convincing. Never do Fielding or Sarah seem genuinely interested in any of their causes or aspirations. Both show all of the emotive power of a stone. It isn't clear how Fielding could get any votes, much less get elected. He is an empty suit without any issues or even a decent stump speech. Sarah says that she's committed to her causes, but shows no authentic spark of compassion for the people to whom she devotes herself.
This leaves the movie to succeed or die based just on their love affair, which turns out to be the weakest link of all. Only when having sex do these lovers ever appear the least bit romantically inclined. At other times, they say the right words, but their vacant eyes show they are just reading their lines.
"If anybody really knew Kennedy, do you think they'd have ever voted for him?" Fielding's father asks him. The story implies that politicians must never reveal themselves to us if they want to get elected. The movie takes the same reticent approach, giving us trite speeches but little more. I'd recommend that you vote against it.
WAKING THE DEAD runs 1:45. It is rated R for sexuality and language and would be acceptable for older teenagers.
Email<EMAIL_ADDRESS>Web: http://www.InternetReviews.com
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


--- layout: page title: About header-img: "img/about-bg.png" ---
My name is Matt. I am an aspiring website developer. My goal is to achieve greatness. However, no success story comes without hardship, struggle, and failure. The positive side? I don't know when to give up, thankfully. By the end of my journey, I will show all aspiring website developers that if I can do... they DEFINITELY can do it too.


Li'l Thug Outlaw
Username:
Password:
Don't have an account?
SIGN UP
Li'l Thug Outlaw
Username:
Password:
Confirm:
Already have an account?
SIGN IN
USER
CASH
LEVEL
NEXT
Li'l Thug Outlaw
LEVEL SELECT
INVENTORY
SETTINGS
CASH
LEVEL
NEXT
HOME
LEVEL SELECT
SETTINGS
Level Select
LEVEL 1
LEVEL 2
LEVEL 3
HOME
INVENTORY
SETTINGS
QUIT
Settings
Difficulty
Easy
Normal
Hard
SoundFX Volume
Volume
Music Volume
Volume
SAVE SETTINGS
LOGOUT
DELETE ACCOUNT
Controls
Movement
Shoot
Reload
Pause
WASD
SPACE
R
P
HOME
LEVEL SELECT
INVENTORY
Level:
Update Level
Cash:
Update Cash


Parser
Parser Implementation
To develop a Netlist parser without using any existing code is a very big and long work.
A quicker solution is
to use the parser of NGSPICE. It consists in extracting the parser and building a library. NGSPICE is
under BSD license.(Ngspice legal issues).
Programming language is C.
Parser API
- int readFile(char *file) : Load a Netlist.
- input : file name must be load.
- return value : 1 if succes, 0 if echec.
- int initComponentList(char *type) : Initialize an electrical component list of type type (RESITOR,
CAPACITOR, INDUCTORS,...).
- input : Component type.
- return value : 1 if succes, 0 if echec.
- int nextComponent(void *data) : Get information about a component.
- output data: contains all informations about the electrical component.
- return value : 0 if it is the last component, else 1.
- int getNbElementsOfType(char *type)
- return value : Component number of type type.
- void printCircuit() : Print Components list. Useful to test the parser.
- int getTransInfo(void *data) : Get information about transient analysis.
- output data: contains all informations about transient analysis.
- return value : 1 if succes, else 0.
Automatic circuit equation formulation
It is a C++ module. Following the class diagram of mains class.
Components class
Each electrical component has a component instance in ACEF.
Component add its equations and unknowns. The main advantage is only that useful unknowns are added in
the system. For example, current through a comparator is null, so this current does not appear in the
system.
Stamp method consists in writing component's contribution in the table equation.
componentNLINEAR stamp methods is overloaded to fill the linear complementarity matrix formulation.
Equation class
The components build the equation instances. A equation is a line (member myLine) in the table
equations.
The component stamp method uses equation instances to fill the table equations.
Linear system class
It manages the memory allocation to build the matrix formulation. Component instances call method to
add unknowns and equations in the system. It contains the MLCP formulation. There are also methods
to run the simulation. This class calls the MLCP solver.