ARM General Maintainence Functions. More...
#include <stdint.h>
#include <ti/csl/arch/a53/csl_a53v8misc.h>
#include <ti/csl/arch/a53/csl_a53v8cache.h>
Macros | |
| #define | CSL_A53_CPUID_CLUSTER0_CORE0 (0ul) |
| CPU definitions. | |
ARM General Maintainence Functions.
(C) Copyright 2015 Texas Instruments Incorporated
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of Texas Instruments Incorporated nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

Code derived from ARM LTD examples and documentation found in the following documents.
ARM® Cortex® -A53 MPCore Processor Revision: r0p4 Technical Reference Manual
ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture profile Beta
| void CSL_a53CleanDcacheMvaPoC | ( | uint64_t | mva | ) |
CSL_a53CleanDcacheMvaPoC
Description
Invalidates D Cache Line by Virtual Address to POC(v8), L1&L2(v7)
Arguments
None
Return Value
None
Pre Condition
None
Post Condition </n>
None
Reads
None
Example
* * uint64_t mva; * * * CSL_a53CleanDcacheMvaPoC(mva); *
| void CSL_a53CleanDcacheMvaPoU | ( | uint64_t | mva | ) |
CSL_a53InvalidateDcacheMvaPoC
Description
Invalidates D Cache Line by Virtual Address to POC(v8), L1&L2(v7)
Arguments
None
Return Value
None
Pre Condition
None
Post Condition </n>
None
Reads
None
Example
* * uint64_t mva; * * * CSL_a53InvalidateDcacheMvaPoC(mva); *
| void CSL_a53CleanL1DCache | ( | ) |
CSL_a53CleanL1DCache
Description
Cleans the L1D Cache
Arguments
None
Return Value
None
Pre Condition
None
Post Condition </n>
None
Reads
None
Example
* * * CSL_a53CleanL1DCache(); *
| void CSL_a53CleanL2Cache | ( | ) |
CSL_a53CleanL2Cache
Description
Cleans the L2 Cache
Arguments
None
Return Value
None
Pre Condition
None
Post Condition </n>
None
Reads
None
Example
* * * CSL_a53CleanL2Cache(); *
| void CSL_a53CleanL3Cache | ( | ) |
CSL_a53CleanL3Cache
Description
Cleans the L3 Cache
Arguments
None
Return Value
None
Pre Condition
None
Post Condition </n>
None
Reads
None
Example
* * * CSL_a53CleanL3Cache(); *
| void CSL_a53InvalidateL1DCache | ( | ) |
CSL_a53InvalidateL1Dcache
Description
Invalidates L1D Cache
Arguments
None
Return Value
None
Pre Condition
None
Post Condition </n>
None
Reads
None
Example
* * * CSL_a53InvalidateL1DCache(); *
| void CSL_a53InvalidateL2Cache | ( | ) |
CSL_a53InvalidateL2cache
Description
Invalidates L2 Cache
Arguments
None
Return Value
None
Pre Condition
None
Post Condition </n>
None
Reads
None
Example
* * * CSL_a53InvalidateL2Cache(); *
| void CSL_a53InvalidateL3Cache | ( | ) |
CSL_a53InvalidateL3cache
Description
Invalidates L3 Cache
Arguments
None
Return Value
None
Pre Condition
None
Post Condition </n>
None
Reads
None
Example
* * * CSL_a53InvalidateL3Cache(); *


SIGN UP
SIGN IN
Please enter the URL of your LinkedIn profile!
Co-Founder
<EMAIL_ADDRESS><EMAIL_ADDRESS>sneha.rohra99@gmail.com


Toggle navigation
Jus Remedium
About
Practice Areas
Articles
Contact
Articles
Articles
Amendments in Companies Act
Clarification on FDI Policy on Single Brand Retail Trading
Morbi leo risus
Porta ac consectetur ac
Vestibulum at eros


Event Reports
Last Updated: 2021-03-30
SCL6.html
Spooky Invitational.html
Summer Cup 2019 Secret Awards.html
Summer Cup 2019.html
Winter Cup 2020.html


---
layout: archive
title: Lean Prover Zulip Chat Archive
permalink: 113488general/32793CastingfromProptoTypeu.html
---
The archive URL format has changed. Please find this page at:
https://leanprover-community.github.io/archive/stream/113488-general/topic/Casting.20from.20Prop.20to.20Type.20u.html


pyrfm.random_feature.SubsampledRandomHadamard¶
-
class
pyrfm.random_feature.
SubsampledRandomHadamard
(n_components=100, distribution='rademacher', random_state=None)[source]¶ Bases:
sklearn.base.BaseEstimator
,sklearn.base.TransformerMixin
Approximates feature maps of the product between random matrix and feature vectors by Subsampled Randomized Hadamard Transform.
This class can be used as a sub-routine for approximating the product between random matrix and feature vectors in some random features. Subsampled Randomized Hadamard Transform uses diagonal matrices, the Walsh-Hadamard matrix, and submatrix of the identity matrix for approximating the matrix-vector product.
- Parameters
n_components (int (default=100)) – Number of Monte Carlo samples per original features. Equals the dimensionality of the computed (mapped) feature space.
distribution (str or function (default="rademacher")) – A function for sampling random bases. Its arguments must be random_state and size. For str, “gaussian” (or “normal”), “rademacher”, “laplace”, or “uniform” can be used.
random_state (int, RandomState instance or None, optional (default=None)) – If int, random_state is the seed used by the random number generator; If np.RandomState instance, random_state is the random number generator; If None, the random number generator is the RandomState instance used by np.random.
-
random_weights_
¶ The sampled basis. It is sampled by using self.distribution, which is the rademacher distribution default.
- Type
array, shape (n_features)
-
random_indices_rows_
¶ The indices of rows sampled from [0, ldots, n_features_padded-1] uniformly, where n_features_padded is the smallest power of two number that is bigger than n_features.
- Type
array, shape (n_components)
References
[1] Improved Analysis of the Subsampled Randomized Hadamard Transform. Joel A Tropp. Advances in Adaptive Data Analysis, (https://arxiv.org/pdf/1011.1595.pdf)
-
fit
(X, y=None)[source]¶ Generate random weights according to n_features.
- Parameters
X ({array-like, sparse matrix}, shape (n_samples, n_features)) – Training data, where n_samples is the number of samples and n_features is the number of features.
- Returns
self – Returns the transformer.
- Return type
object
-
fit_transform
(X, y=None, **fit_params)¶ Fit to data, then transform it.
Fits transformer to X and y with optional parameters fit_params and returns a transformed version of X.
- Parameters
X (numpy array of shape [n_samples, n_features]) – Training set.
y (numpy array of shape [n_samples]) – Target values.
- Returns
X_new – Transformed array.
- Return type
numpy array of shape [n_samples, n_features_new]
-
get_params
(deep=True)¶ Get parameters for this estimator.
- Parameters
deep (boolean, optional) – If True, will return the parameters for this estimator and contained subobjects that are estimators.
- Returns
params – Parameter names mapped to their values.
- Return type
mapping of string to any
-
set_params
(**params)¶ Set the parameters of this estimator.
The method works on simple estimators as well as on nested objects (such as pipelines). The latter have parameters of the form
<component>__<parameter>
so that it’s possible to update each component of a nested object.- Returns
- Return type
self
-
transform
(X)[source]¶ Apply the approximate feature map to X.
- Parameters
X ({array-like, sparse matrix}, shape (n_samples, n_features)) – New data, where n_samples is the number of samples and n_features is the number of features.
- Returns
X_new
- Return type
array-like, shape (n_samples, n_components)


User(s) of the Angebotsmanager are generally the system accessors of the tool. These are the entities who can log into the system and make use of the various features provided. They can be assigned to Projects and Offers. They are also the entities whose email addresses are used in Email communication. Basically, there are three types of User(s) in Offer tool who have been briefly described below -
Admin User - Admin user(s) are the major user(s) of Offer tool. Basically, they have the right to view all the data(s) inserted, edit the existing data(s), assign contacts and also delete any entity (provided they have no dependencies). They are able to set roles for other users.
General User - A general user is the secondary user of the offer tool. A secondary user does not mean that the General User has lesser priority as compared to that of an Admin User, but its just that he/she will not have access to some features which are available to an Admin user. For instance, he/she is not able to delete anything. They can only view the Project(s) and Offer(s) which are assigned to them, unlike the Admin Users who can view all the details. They can add the following entities - Offers, Placements, Partners and Contacts. However, they do not have the right to add a Project, Channel, Offer-Offer types and Email templates. Though they can edit and view these modules (provided they have been assigned to these modules). A general user does not have the right to add other user(s)
Viewer - A viewer is a user who can view only certain portions of all Offers. This type of User is basically just a spectator with almost no functionality except that of viewing data of an Offer. He/She is not able to add/edit/delete anything
* Click to enlarge
User(s) can be added only by an Admin user. To add a User into the system, click on Additional Information -> Users -> Add User on the left hand navigation menu. Enter the appropriate details in the fields and click Add button. Below described are the fields seen in the Add User page.
The fields seen when adding User(s) are
First Name (Required) - First name of the user is to be inserted in this field
Last Name (Required) - Last name of the user is to be inserted in this field
Email (Required) - Provide appropriate email address for the user in this field. The provided email address will be used to log into the system and also in email communication
Telephone (Optional) - A field to insert the telephone number of the User
User Type - A single select dropdown field to select the User type. User type as mentioned above are of three types - Admin, General and a Viewer
Username (Required) - A field to enter the Username for the particular user
Password - A field for inserting the password. This is particularly significant as the email address and password of the users are required to log into the system
Confirm Password - A field for inserting the password again for measures of extra security and to ensure that the password inserted by the user is deliberate and has not mispelled it. If the two password fields do not match, this page cannot be submitted.
* Click to enlarge
This page lists all the users that have been added to the system. This page is in tabular form whose columns have been briefly discussed below -
The Columns that appear in the List Users page are
First Name - Displays the first name of the User(s)
Last Name - Displays the last name of the User(s)
Email - Displays the email addresses of the User(s). Note that clicking on these email addresses will show the User Details Summary Page
User Type - Displays the User Type of the User(s)
Project - Displays the names of the Project(s) that the user is assigned to. A single user maybe associated with multiple Projects
Users can see two icons under the Action column whose description have been mentioned below
The edit button is used to edit the existing User details. Same validation rules are applied while editing User as that of adding User except for the two fields of Password. When editing an existing User, the password field is not populated allowing the admin users to reset the password. Note that only an admin user can edit the user details.
The delete button is used to delete a User. However, do note that if a User is being used in other modules such as Project, then he/she cannot be deleted. Only an admin user possesses the right to delete a user.
* Click to enlarge
Please note that a User can be created by an Admin User only. a General User and a Viewer do not have access to these features. Also these users cannot view the User(s) list directly. A General User has the ability to Select the existing User list when adding Project and Offers.


TitleSubtitle #1 #2 #3 #4 #5 #6 Instructions Code Input Your code here... Code Output Your code here... Next


bool player::missile_repulsion() const
{
return get_mutation_level(MUT_DISTORTION_FIELD) == 3
|| you.wearing_ego(EQ_ALL_ARMOUR, SPARM_REPULSION)
|| scan_artefacts(ARTP_RMSL, true)
|| have_passive(passive_t::upgraded_storm_shield);
}
/**
* What's the base value of the penalties the player receives from their
* body armour?
*
* Used as the base for adjusted armour penalty calculations, as well as for
* stealth penalty calculations.
*
* @return The player's body armour's PARM_EVASION, if any, taking into account
* the sturdy frame mutation that reduces encumbrance.
*/
int player::unadjusted_body_armour_penalty() const
{
const item_def *body_armour = slot_item(EQ_BODY_ARMOUR, false);
if (!body_armour)
return 0;
// PARM_EVASION is always less than or equal to 0
return max(0, -property(*body_armour, PARM_EVASION) / 10
- get_mutation_level(MUT_STURDY_FRAME) * 2);
}
/**
* The encumbrance penalty to the player for their worn body armour.
*
* @param scale A scale to multiply the result by, to avoid precision loss.
* @return A penalty to EV based quadratically on body armour
* encumbrance.
*/
int player::adjusted_body_armour_penalty(int scale) const
{
const int base_ev_penalty = unadjusted_body_armour_penalty();
// New formula for effect of str on aevp: (2/5) * evp^2 / (str+3)
return 2 * base_ev_penalty * base_ev_penalty * (450 - skill(SK_ARMOUR, 10))
* scale / (5 * (strength() + 3)) / 450;
}
/**
* The encumbrance penalty to the player for their worn shield.
*
* @param scale A scale to multiply the result by, to avoid precision loss.
* @return A penalty to EV based on shield weight.
*/
int player::adjusted_shield_penalty(int scale) const
{
const item_def *shield_l = slot_item(EQ_SHIELD, false);
if (!shield_l)
return 0;
const int base_shield_penalty = -property(*shield_l, PARM_EVASION);
return max(0, ((base_shield_penalty * scale) - skill(SK_SHIELDS, scale)
/ player_shield_racial_factor() * 10) / 10);
}
float player::get_shield_skill_to_offset_penalty(const item_def &item)
{
int evp = property(item, PARM_EVASION);
return -1 * evp * player_shield_racial_factor() / 10.0;
}
int player::armour_tohit_penalty(bool random_factor, int scale) const
{
return maybe_roll_dice(1, adjusted_body_armour_penalty(scale), random_factor);
}
int player::shield_tohit_penalty(bool random_factor, int scale) const
{
return maybe_roll_dice(1, adjusted_shield_penalty(scale), random_factor);
}
/**
* Get the player's skill level for sk.
*
* @param scale a scale factor to multiply by.
* @param real whether to return the real value, or modified value.
* @param drained whether to include modification by draining.
* @param temp whether to include modification by other temporary factors (e.g. heroism)
*/
int player::skill(skill_type sk, int scale, bool real, bool drained, bool temp) const
{
// If you add another enhancement/reduction, be sure to change
// SkillMenuSwitch::get_help() to reflect that
// wizard racechange, or upgraded old save
if (is_useless_skill(sk))
return 0;
// skills[sk] might not be updated yet if this is in the middle of
// skill training, so make sure to use the correct value.
int actual_skill = skills[sk];
unsigned int effective_points = skill_points[sk];
if (!real)
effective_points += get_crosstrain_points(sk);
effective_points = min(effective_points, skill_exp_needed(MAX_SKILL_LEVEL, sk));
actual_skill = calc_skill_level_change(sk, actual_skill, effective_points);
int level = actual_skill * scale
+ get_skill_progress(sk, actual_skill, effective_points, scale);
if (real)
return level;
if (drained && you.attribute[ATTR_XP_DRAIN])
{
// skill = base * (3000 - drain) / 3000 - drain / 100
// base - ((drain * base / 3000) + drain / 100)
int drain_scale = max(0, (30 * 100 - you.attribute[ATTR_XP_DRAIN]) * scale);
level = skill(sk, drain_scale, real, false);
return max(0, (level - 30 * scale * you.attribute[ATTR_XP_DRAIN]) / (30 * 100));
}
if (penance[GOD_ASHENZARI])
{
if (temp)
level = max(level - 4 * scale, level / 2);
}
else if (ash_has_skill_boost(sk))
level = ash_skill_boost(sk, scale);
if (temp && duration[DUR_HEROISM] && sk <= SK_LAST_MUNDANE)
level = min(level + 5 * scale, MAX_SKILL_LEVEL * scale);
return level;
}
int player_icemail_armour_class()
{
if (!you.has_mutation(MUT_ICEMAIL))
return 0;
return you.duration[DUR_ICEMAIL_DEPLETED] ? 0 : ICEMAIL_MAX;
}
/**
* How many points of AC does the player get from their sanguine armour, if
* they have any?
*
* @return The AC bonus * 100. (For scaling.)
*/
int sanguine_armour_bonus()
{
if (!you.duration[DUR_SANGUINE_ARMOUR])
return 0;
const int mut_lev = you.get_mutation_level(MUT_SANGUINE_ARMOUR);
// like iridescent, but somewhat moreso (when active)
return 300 + mut_lev * 300;
}
/**
* How much AC does the player get from an unenchanted version of the given
* armour?
*
* @param armour The armour in question.
* @param scale A value to multiply the result by. (Used to avoid integer
* rounding.)
* @return The AC from that armour, including armour skill, mutations
* & divine blessings, but not enchantments or egos.
*/
int player::base_ac_from(const item_def &armour, int scale) const
{
const int base = property(armour, PARM_AC) * scale;
// [ds] effectively: ac_value * (22 + Arm) / 22, where Arm = Armour Skill.
const int AC = base * (440 + skill(SK_ARMOUR, 20)) / 440;
// The deformed don't fit into body armour very well.
// (This includes nagas and centaurs.)
if (get_armour_slot(armour) == EQ_BODY_ARMOUR
&& (get_mutation_level(MUT_DEFORMED)
|| get_mutation_level(MUT_PSEUDOPODS)))
{
return AC - base / 2;
}
return AC;
}
/**
* What bonus AC are you getting from your species?
*
* Does not account for any real mutations, such as scales or thick skin, that
* you may have as a result of your species.
* @param temp Whether to account for transformations.
* @returns how much AC you are getting from your species "fake mutations" * 100
*/
int player::racial_ac(bool temp) const
{
// drac scales suppressed in all serious forms, except dragon
if (species_is_draconian(species)
&& (!player_is_shapechanged() || form == transformation::dragon
|| !temp))
{
int AC = 400 + 100 * (experience_level / 3); // max 13
if (species == SP_GREY_DRACONIAN) // no breath
AC += 500;
return AC;
}
if (!(player_is_shapechanged() && temp))
{
if (species == SP_NAGA)
return 100 * experience_level / 3; // max 9
else if (species == SP_GARGOYLE)
{
return 200 + 100 * experience_level * 2 / 5 // max 20
+ 100 * max(0, experience_level - 7) * 2 / 5;
}
}
return 0;
}
// Each instance of this class stores a mutation which might change a
// player's AC and how much their AC should change if the player has
// said mutation.
class mutation_ac_changes{
public:
/**
* The AC a player gains from a given mutation. If the player
* lacks said mutation, return 0.
*
* @return How much AC to give the player for the handled
* mutation.
*/
int get_ac_change_for_mutation(){
int ac_change = 0;
int mutation_level = you.get_mutation_level(mut, mutation_activation_threshold);
switch (mutation_level){
case 0:
ac_change = 0;
break;
case 1:
case 2:
case 3:
ac_change = ac_changes[mutation_level - 1];
break;
}
// The output for this function is scaled differently than the UI.
return ac_change * 100;
}
mutation_ac_changes(mutation_type mut_aug,
mutation_activity_type mutation_activation_threshold_aug,
vector<int> ac_changes_aug)
: mut (mut_aug),
mutation_activation_threshold (mutation_activation_threshold_aug),
ac_changes (ac_changes_aug)
{
}
private:
mutation_type mut;
mutation_activity_type mutation_activation_threshold;
vector<int> ac_changes;
};
// Constant vectors for the most common mutation ac results used in
// all_mutation_ac_changes
const vector<int> ONE_TWO_THREE = {1,2,3};
const vector<int> TWO_THREE_FOUR = {2,3,4};
vector<mutation_ac_changes> all_mutation_ac_changes = {
mutation_ac_changes(MUT_GELATINOUS_BODY, mutation_activity_type::PARTIAL, ONE_TWO_THREE)
,mutation_ac_changes(MUT_TOUGH_SKIN, mutation_activity_type::PARTIAL, ONE_TWO_THREE)
,mutation_ac_changes(MUT_SHAGGY_FUR, mutation_activity_type::PARTIAL, ONE_TWO_THREE)
,mutation_ac_changes(MUT_PHYSICAL_VULNERABILITY, mutation_activity_type::PARTIAL, {-5,-10,-15})
// Scale mutations are more easily disabled (forms etc.). This appears to be for flavour reasons.
// Preserved behaviour from before mutation ac was turned to data.
,mutation_ac_changes(MUT_IRIDESCENT_SCALES, mutation_activity_type::FULL, {2, 4, 6})
,mutation_ac_changes(MUT_RUGGED_BROWN_SCALES, mutation_activity_type::FULL, ONE_TWO_THREE)
,mutation_ac_changes(MUT_ICY_BLUE_SCALES, mutation_activity_type::FULL, TWO_THREE_FOUR)
,mutation_ac_changes(MUT_MOLTEN_SCALES, mutation_activity_type::FULL, TWO_THREE_FOUR)
,mutation_ac_changes(MUT_SLIMY_GREEN_SCALES, mutation_activity_type::FULL, TWO_THREE_FOUR)
,mutation_ac_changes(MUT_THIN_METALLIC_SCALES, mutation_activity_type::FULL, TWO_THREE_FOUR)
,mutation_ac_changes(MUT_YELLOW_SCALES, mutation_activity_type::FULL, TWO_THREE_FOUR)
};
/**
* The AC changes the player has from mutations.
*
* Mostly additions from things like scales, but the physical vulnerability
* mutation is also accounted for.
*
* @return The player's AC gain from mutation, with 100 scaling (i.e,
* the returned result 100 times the UI shows as of Jan 2020)
*/
int player::ac_changes_from_mutations() const
{
int AC = 0;
for (vector<mutation_ac_changes>::iterator it =
all_mutation_ac_changes.begin();
it != all_mutation_ac_changes.end(); ++it)
{
AC += it->get_ac_change_for_mutation();
}
return AC;
}
/**
* Get a vector with the items of armour the player is wearing.
*
* @return A vector of non-null pointers to all armour the player has equipped.
*/
vector<const item_def *> player::get_armour_items() const
{
vector<const item_def *> armour_items;
for (int eq = EQ_MIN_ARMOUR; eq <= EQ_MAX_ARMOUR; ++eq)
{
if (!slot_item(static_cast<equipment_type>(eq)))
continue;
armour_items.push_back(&inv[equip[eq]]);
}
return armour_items;
}
/**
* Get a vector with the items of armour the player would be wearing
* if they put on a specific piece of armour
*
* @param The item which the player would be wearing in this theoretical
* situation.
* @return A vector of non-null pointers to all armour the player would have
* equipped.
*/
vector<const item_def *> player::get_armour_items_one_sub(const item_def& sub) const
{
vector<const item_def *> armour_items = get_armour_items_one_removal(sub);
armour_items.push_back(&sub);
return armour_items;
}
/**
* Get a vector with the items of armour the player would be wearing
* if they removed a specific piece of armour
*
* @param The item which the player would be remove in this theoretical
* situation.
* @return A vector of non-null pointers to all armour the player would have
* equipped after removing the item passed in.
*/
vector<const item_def *> player::get_armour_items_one_removal(const item_def& remove) const
{
vector<const item_def *> armour_items;
for (int eq = EQ_MIN_ARMOUR; eq <= EQ_MAX_ARMOUR; ++eq)
{
if (get_armour_slot(remove) == eq)
continue;
if (!slot_item(static_cast<equipment_type>(eq)))
continue;
armour_items.push_back(&inv[equip[eq]]);
}
return armour_items;
}
/**
* Get the players "base" ac, assuming they are wearing a particular set of
* armour items (which isn't necessarily the set of armour items they are
* currently wearing.)
*
* @param A scale by which the player's base AC is multiplied.
* @param A list of items to assume the player is wearing.
* @return The player's AC, multiplied by the given scale.
*/
int player::base_ac_with_specific_items(int scale,
vector<const item_def *> armour_items) const
{
int AC = 0;
for (auto item : armour_items)
{
// Shields give SH instead of AC
if (get_armour_slot(*item) != EQ_SHIELD)
{
AC += base_ac_from(*item, 100);
AC += item->plus * 100;
}
if (get_armour_ego_type(*item) == SPARM_PROTECTION)
AC += 300;
}
AC += wearing(EQ_RINGS_PLUS, RING_PROTECTION) * 100;
//XXX: This doesn't take into account armour_items, so an unrand shield
// with +AC would have a buggy display.
AC += scan_artefacts(ARTP_AC) * 100;
AC += get_form()->get_ac_bonus();
AC += racial_ac(true);
AC += ac_changes_from_mutations();
return AC * scale / 100;
}
/**
* The player's "base" armour class, before transitory buffs are applied.
*
* (This is somewhat arbitrarily defined - forms, for example, are considered
* to be long-lived for these purposes.)
*
* @param A scale by which the player's base AC is multiplied.
* @return The player's AC, multiplied by the given scale.
*/
int player::base_ac(int scale) const
{
vector<const item_def *> armour_items = get_armour_items();
return base_ac_with_specific_items(scale, armour_items);
}
int player::armour_class(bool /*calc_unid*/) const
{
return armour_class_with_specific_items(get_armour_items());
}
int player::armour_class_with_one_sub(item_def sub) const
{
return armour_class_with_specific_items(
get_armour_items_one_sub(sub));
}
int player::armour_class_with_one_removal(item_def removed) const
{
return armour_class_with_specific_items(
get_armour_items_one_removal(removed));
}
int player::armour_class_with_specific_items(vector<const item_def *> items) const
{
const int scale = 100;
int AC = base_ac_with_specific_items(scale, items);
if (duration[DUR_ICY_ARMOUR])
AC += 500 + you.props[ICY_ARMOUR_KEY].get_int() * 8;
if (has_mutation(MUT_ICEMAIL))
AC += 100 * player_icemail_armour_class();
if (duration[DUR_QAZLAL_AC])
AC += 300;
if (duration[DUR_SPWPN_PROTECTION])
AC += 700;
if (duration[DUR_CORROSION])
AC -= 400 * you.props["corrosion_amount"].get_int();
AC += sanguine_armour_bonus();
return AC / scale;
}
/**
* Guaranteed damage reduction.
*
* The percentage of the damage received that is guaranteed to be reduced
* by the armour. As the AC roll is done before GDR is applied, GDR is only
* useful when the AC roll is inferior to it. Therefore a higher GDR means
* more damage reduced, but also more often.
*
* \f[ GDR = 14 \times (base\_AC - 2)^\frac{1}{2} \f]
*
* \return GDR as a percentage.
**/
int player::gdr_perc() const
{
switch (form)
{
case transformation::dragon:
return 34; // base AC 8
case transformation::statue:
return 39; // like plate (AC 10)
case transformation::tree:
return 48;
default:
break;
}
const item_def *body_armour = slot_item(EQ_BODY_ARMOUR, false);
int body_base_AC = (species == SP_GARGOYLE ? 5 : 0);
if (body_armour)
body_base_AC += property(*body_armour, PARM_AC);
// We take a sqrt here because damage prevented by GDR is
// actually proportional to the square of the GDR percentage
// (assuming you have enough AC).
int gdr = 14 * sqrt(max(body_base_AC - 2, 0));
return gdr;
}
/**
* What is the player's actual, current EV, possibly relative to an attacker,
* including various temporary penalties?
*
* @param evit Penalty types which should be excluded from the calculation.
* @param act The creature that the player is attempting to evade, if any.
* May be null.
* @return The player's relevant EV.
*/
int player::evasion(ev_ignore_type evit, const actor* act) const
{
const int base_evasion = _player_evasion(evit);
const int constrict_penalty = is_constricted() ? 3 : 0;
const bool attacker_invis = act && !act->visible_to(this);
const int invis_penalty
= attacker_invis && !testbits(evit, ev_ignore::helpless) ? 10 : 0;
return base_evasion - constrict_penalty - invis_penalty;
}
bool player::heal(int amount)
{
::inc_hp(amount);
return true; /* TODO Check whether the player was healed. */
}
/**
* What is the player's (current) mon_holy_type category?
* Stays up to date with god for evil/unholy
* Nonliving (statues, etc), undead, or alive.
*
* @param temp Whether to consider temporary effects: forms,
* petrification...
* @return The player's holiness category.
*/
mon_holy_type player::holiness(bool temp) const
{
mon_holy_type holi;
// Lich form takes precedence over a species' base holiness
// Alive Vampires are MH_NATURAL
if (is_lifeless_undead(temp))
holi = MH_UNDEAD;
else if (species == SP_GARGOYLE)
holi = MH_NONLIVING;
else
holi = MH_NATURAL;
// Petrification takes precedence over base holiness and lich form
if (temp && (form == transformation::statue
|| form == transformation::wisp
|| petrified()))
{
holi = MH_NONLIVING;
}
if (is_good_god(religion))
holi |= MH_HOLY;
if (is_evil_god(religion)
|| species == SP_DEMONSPAWN || species == SP_VAMPIRE)
{
holi |= MH_EVIL;
}
// possible XXX: Monsters get evil/unholy bits set on spell selection
// should players?
return holi;
}
bool player::undead_or_demonic() const
{
// This is only for TSO-related stuff, so demonspawn are included.
return undead_state() || species == SP_DEMONSPAWN;
}
bool player::is_holy(bool /*check_spells*/) const
{
return bool(holiness() & MH_HOLY);
}
bool player::is_nonliving(bool temp) const
{
return bool(holiness(temp) & MH_NONLIVING);
}
// This is a stub. Check is used only for silver damage. Worship of chaotic
// gods should probably be checked in the non-existing player::is_unclean,
// which could be used for something Zin-related (such as a priestly monster).
int player::how_chaotic(bool /*check_spells_god*/) const
{
return 0;
}
/**
* Does the player need to breathe?
*
* Pretty much only matters for mephitic clouds, & confusing spores, & curare.
*
* @return Whether the player has no need to breathe.
*/
bool player::is_unbreathing() const
{
return !get_form()->breathes || petrified()
|| get_mutation_level(MUT_UNBREATHING);
}
bool player::is_insubstantial() const
{
return form == transformation::wisp;
}
int player::res_acid(bool calc_unid) const
{
return player_res_acid(calc_unid);
}
int player::res_fire() const
{
return player_res_fire();
}
int player::res_steam() const
{
return player_res_steam();
}
int player::res_cold() const
{
return player_res_cold();
}
int player::res_elec() const
{
return player_res_electricity();
}
int player::res_water_drowning() const
{
int rw = 0;
if (is_unbreathing()
|| species_can_swim(species) && !form_changed_physiology()
|| form == transformation::ice_beast
|| form == transformation::hydra)
{
rw++;
}
return rw;
}
int player::res_poison(bool temp) const
{
return player_res_poison(true, temp);
}
rot_resistance player::res_rotting(bool temp) const
{
if (get_mutation_level(MUT_ROT_IMMUNITY)
|| is_nonliving(temp)
|| temp && get_form()->res_rot())
{
return ROT_RESIST_FULL;
}
const item_def *armour = slot_item(EQ_BODY_ARMOUR);
const bool embraced = armour && is_unrandom_artefact(*armour, UNRAND_EMBRACE);
const rot_resistance base_res = embraced ? ROT_RESIST_MUNDANE : ROT_RESIST_NONE;
switch (undead_state(temp))
{
default:
case US_ALIVE:
return base_res;
case US_HUNGRY_DEAD:
return ROT_RESIST_MUNDANE; // rottable by Zin, not by necromancy
case US_SEMI_UNDEAD:
if (temp && !you.vampire_alive)
return ROT_RESIST_MUNDANE;
return base_res;
case US_UNDEAD:
return ROT_RESIST_FULL;
}
}
bool player::res_sticky_flame() const
{
return player_res_sticky_flame();
}
int player::res_holy_energy() const
{
if (undead_or_demonic())
return -1;
if (is_holy())
return 3;
return 0;
}
int player::res_negative_energy(bool intrinsic_only) const
{
return player_prot_life(!intrinsic_only, true, !intrinsic_only);
}
bool player::res_torment() const
{
return player_res_torment();
}
bool player::res_tornado() const
{
// Full control of the winds around you can negate a hostile tornado.
return duration[DUR_TORNADO] ? 1 : 0;
}
bool player::res_petrify(bool temp) const
{
return get_mutation_level(MUT_PETRIFICATION_RESISTANCE)
|| temp && get_form()->res_petrify();
}
int player::res_constrict() const
{
if (is_insubstantial())
return 3;
if (get_mutation_level(MUT_SPINY))
return 3;
return 0;
}
int player::res_magic(bool /*calc_unid*/) const
{
return player_res_magic();
}
int player_res_magic(bool calc_unid, bool temp)
{
if (temp && you.form == transformation::shadow)
return MAG_IMMUNE;
int rm = you.experience_level * species_mr_modifier(you.species);
// randarts
rm += MR_PIP * you.scan_artefacts(ARTP_MAGIC_RESISTANCE, calc_unid);
// body armour
const item_def *body_armour = you.slot_item(EQ_BODY_ARMOUR);
if (body_armour)
rm += armour_type_prop(body_armour->sub_type, ARMF_RES_MAGIC) * MR_PIP;
// ego armours
rm += MR_PIP * you.wearing_ego(EQ_ALL_ARMOUR, SPARM_MAGIC_RESISTANCE,
calc_unid);
// rings of magic resistance
rm += MR_PIP * you.wearing(EQ_RINGS, RING_PROTECTION_FROM_MAGIC, calc_unid);
// Mutations
rm += MR_PIP * you.get_mutation_level(MUT_MAGIC_RESISTANCE);
rm -= MR_PIP * you.get_mutation_level(MUT_MAGICAL_VULNERABILITY);
// transformations
if (you.form == transformation::lich && temp)
rm += MR_PIP;
// Trog's Hand
if (you.duration[DUR_TROGS_HAND] && temp)
rm += MR_PIP * 2;
// Enchantment effect
if (you.duration[DUR_LOWERED_MR] && temp)
rm /= 2;
if (rm < 0)
rm = 0;
return rm;
}
/**
* Is the player prevented from teleporting? If so, why?
*
* @param calc_unid Whether to identify unknown items that prevent tele
* (probably obsolete)
* @param blinking Are you blinking or teleporting?
* @return Why the player is prevented from teleporting, if they
* are; else, the empty string.
*/
string player::no_tele_reason(bool calc_unid, bool blinking) const
{
if (!blinking)
{
if (crawl_state.game_is_sprint())
return "Long-range teleportation is disallowed in Dungeon Sprint.";
else if (player_in_branch(BRANCH_GAUNTLET))
{
return "A magic seal in the Gauntlet prevents long-range "
"teleports.";
}
}
if (stasis())
return "Your stasis prevents you from teleporting.";
vector<string> problems;
if (duration[DUR_DIMENSION_ANCHOR])
problems.emplace_back("locked down by a dimension anchor");
if (form == transformation::tree)
problems.emplace_back("held in place by your roots");
vector<const item_def *> notele_items;
if (has_notele_item(calc_unid, ¬ele_items))
{
vector<string> worn_notele;
bool found_nonartefact = false;
for (const auto item : notele_items)
{
if (item->base_type == OBJ_WEAPONS)
{
problems.push_back(make_stringf("wielding %s",
item->name(DESC_A).c_str()));
}
else
worn_notele.push_back(item->name(DESC_A));
}
if (worn_notele.size() > (problems.empty() ? 3 : 1))
{
problems.push_back(
make_stringf("wearing %s %s preventing teleportation",
number_in_words(worn_notele.size()).c_str(),
found_nonartefact ? "items": "artefacts"));
}
else if (!worn_notele.empty())
{
problems.push_back(
make_stringf("wearing %s",
comma_separated_line(worn_notele.begin(),
worn_notele.end()).c_str()));
}
}
if (problems.empty())
return ""; // no problem
return make_stringf("You cannot %s because you are %s.",
blinking ? "blink" : "teleport",
comma_separated_line(problems.begin(),
problems.end()).c_str());
}
/**
* Is the player prevented from teleporting/blinking right now? If so,
* print why.
*
* @param calc_unid Whether to identify unknown items that prevent tele
* (probably obsolete)
* @param blinking Are you blinking or teleporting?
* @return Whether the player is prevented from teleportation.
*/
bool player::no_tele_print_reason(bool calc_unid, bool blinking) const
{
const string reason = no_tele_reason(calc_unid, blinking);
if (reason.empty())
return false;
mpr(reason);
return true;
}
/**
* Is the player prevented from teleporting/blinking right now?
*
* @param calc_unid Whether to identify unknown items that prevent tele
* (probably obsolete)
* @param permit_id Unused for players.
* @param blinking Are you blinking or teleporting?
* @return Whether the player is prevented from teleportation.
*/
bool player::no_tele(bool calc_unid, bool /*permit_id*/, bool blinking) const
{
return !no_tele_reason(calc_unid, blinking).empty();
}
bool player::fights_well_unarmed(int heavy_armour_penalty)
{
return x_chance_in_y(skill(SK_UNARMED_COMBAT, 10), 200)
&& x_chance_in_y(2, 1 + heavy_armour_penalty);
}
bool player::cancellable_flight() const
{
return duration[DUR_FLIGHT] && !permanent_flight()
&& !attribute[ATTR_FLIGHT_UNCANCELLABLE];
}
bool player::permanent_flight() const
{
return attribute[ATTR_PERM_FLIGHT];
}
bool player::racial_permanent_flight() const
{
return get_mutation_level(MUT_TENGU_FLIGHT)
|| get_mutation_level(MUT_BIG_WINGS);
}
bool player::tengu_flight() const
{
// Only Tengu get perks for flying.
return species == SP_TENGU && airborne();
}
/**
* Returns true if player spellcasting is considered unholy.
*
* Checks to see if the player is wielding the Majin-Bo.
*
* @return Whether player spellcasting is an unholy act.
*/
bool player::spellcasting_unholy() const
{
return player_equip_unrand(UNRAND_MAJIN);
}
/**
* What is the player's (current) place on the Undead Spectrum?
* (alive, hungry undead (ghoul), semi-undead (vampire), or very dead (mummy,
* lich)
*
* @param temp Whether to consider temporary effects (lichform)
* @return The player's undead state.
*/
undead_state_type player::undead_state(bool temp) const
{
if (temp && you.form == transformation::lich)
return US_UNDEAD;
return species_undead_type(you.species);
}
bool player::nightvision() const
{
return have_passive(passive_t::nightvision);
}
reach_type player::reach_range() const
{
const item_def *wpn = weapon();
if (wpn)
return weapon_reach(*wpn);
return REACH_NONE;
}
monster_type player::mons_species(bool /*zombie_base*/) const
{
return player_species_to_mons_species(species);
}
bool player::poison(actor *agent, int amount, bool force)
{
return ::poison_player(amount, agent? agent->name(DESC_A, true) : "", "",
force);
}
void player::expose_to_element(beam_type element, int _strength,
bool slow_cold_blood)
{
::expose_player_to_element(element, _strength, slow_cold_blood);
}
void player::blink()
{
cast_blink();
}
void player::teleport(bool now, bool wizard_tele)
{
ASSERT(!crawl_state.game_is_arena());
if (now)
you_teleport_now(wizard_tele);
else
you_teleport();
}
int player::hurt(const actor *agent, int amount, beam_type flavour,
kill_method_type kill_type, string source, string aux,
bool /*cleanup_dead*/, bool /*attacker_effects*/)
{
// We ignore cleanup_dead here.
if (!agent)
{
// FIXME: This can happen if a deferred_damage_fineff does damage
// to a player from a dead monster. We should probably not do that,
// but it could be tricky to fix, so for now let's at least avoid
// a crash even if it does mean funny death messages.
ouch(amount, kill_type, MID_NOBODY, aux.c_str(), false, source.c_str());
}
else
{
ouch(amount, kill_type, agent->mid, aux.c_str(),
agent->visible_to(this), source.c_str());
}
if ((flavour == BEAM_DEVASTATION || flavour == BEAM_DISINTEGRATION)
&& can_bleed())
{
blood_spray(pos(), type, amount / 5);
}
return amount;
}
void player::drain_stat(stat_type s, int amount)
{
lose_stat(s, amount);
}
bool player::rot(actor */*who*/, int amount, bool quiet, bool /*no_cleanup*/)
{
ASSERT(!crawl_state.game_is_arena());
if (amount <= 0)
return false;
if (res_rotting() || duration[DUR_DEATHS_DOOR])
{
mpr("You feel terrible.");
return false;
}
if (duration[DUR_DIVINE_STAMINA] > 0)
{
mpr("Your divine stamina protects you from decay!");
return false;
}
rot_hp(amount);
if (!quiet)
mprf(MSGCH_WARN, "You feel your flesh rotting away!");
learned_something_new(HINT_YOU_ROTTING);
if (one_chance_in(4))
sicken(50 + random2(100));
return true;
}
bool player::corrode_equipment(const char* corrosion_source, int degree)
{
// rCorr protects against 50% of corrosion.
if (res_corr())
{
degree = binomial(degree, 50);
if (!degree)
{
dprf("rCorr protects.");
return false;
}
}
// always increase duration, but...
increase_duration(DUR_CORROSION, 10 + roll_dice(2, 4), 50,
make_stringf("%s corrodes you!",
corrosion_source).c_str());
// the more corrosion you already have, the lower the odds of more
int prev_corr = props["corrosion_amount"].get_int();
bool did_corrode = false;
for (int i = 0; i < degree; i++)
if (!x_chance_in_y(prev_corr, prev_corr + 7))
{
props["corrosion_amount"].get_int()++;
prev_corr++;
did_corrode = true;
}
if (did_corrode)
{
redraw_armour_class = true;
wield_change = true;
}
return true;
}
/**
* Attempts to apply corrosion to the player and deals acid damage.
*
* @param evildoer the cause of this acid splash.
* @param acid_strength The strength of the acid.
* @param allow_corrosion Whether to try and apply the corrosion debuff.
* @param hurt_msg A message to display when dealing damage.
*/
void player::splash_with_acid(const actor* evildoer, int acid_strength,
bool allow_corrosion, const char* /*hurt_msg*/)
{
if (allow_corrosion && binomial(3, acid_strength + 1, 30))
corrode_equipment();
const int dam = roll_dice(4, acid_strength);
const int post_res_dam = resist_adjust_damage(&you, BEAM_ACID, dam);
mprf("You are splashed with acid%s%s",
post_res_dam > 0 ? "" : " but take no damage",
attack_strength_punctuation(post_res_dam).c_str());
if (post_res_dam > 0)
{
if (post_res_dam < dam)
canned_msg(MSG_YOU_RESIST);
ouch(post_res_dam, KILLED_BY_ACID,
evildoer ? evildoer->mid : MID_NOBODY);
}
}
bool player::drain_exp(actor */*who*/, bool quiet, int pow)
{
return drain_player(pow, !quiet);
}
void player::confuse(actor */*who*/, int str)
{
confuse_player(str);
}
/**
* Paralyse the player for str turns.
*
* Duration is capped at 13.
*
* @param who Pointer to the actor who paralysed the player.
* @param str The number of turns the paralysis will last.
* @param source Description of the source of the paralysis.
*/
void player::paralyse(actor *who, int str, string source)
{
ASSERT(!crawl_state.game_is_arena());
if (stasis())
{
mpr("Your stasis prevents you from being paralysed.");
return;
}
// The who check has an effect in a few cases, most notably making
// Death's Door + Borg's paralysis unblockable.
if (who && (duration[DUR_PARALYSIS] || duration[DUR_PARALYSIS_IMMUNITY]))
{
mpr("You shrug off the repeated paralysis!");
return;
}
int ¶lysis(duration[DUR_PARALYSIS]);
const bool use_actor_name = source.empty() && who != nullptr;
if (use_actor_name)
source = who->name(DESC_A);
if (!paralysis && !source.empty())
{
take_note(Note(NOTE_PARALYSIS, str, 0, source));
// use the real name here even for invisible monsters
props[PARALYSED_BY_KEY] = use_actor_name ? who->name(DESC_A, true)
: source;
}
if (asleep())
you.awaken();
mpr("You suddenly lose the ability to move!");
paralysis = min(str, 13) * BASELINE_DELAY;
stop_directly_constricting_all(false);
end_searing_ray();
}
void player::petrify(actor *who, bool force)
{
ASSERT(!crawl_state.game_is_arena());
if (res_petrify() && !force)
{
canned_msg(MSG_YOU_UNAFFECTED);
return;
}
if (duration[DUR_DIVINE_STAMINA] > 0)
{
mpr("Your divine stamina protects you from petrification!");
return;
}
// Petrification always wakes you up
if (asleep())
you.awaken();
if (petrifying())
{
mpr("Your limbs have turned to stone.");
duration[DUR_PETRIFYING] = 1;
return;
}
if (petrified())
return;
duration[DUR_PETRIFYING] = 3 * BASELINE_DELAY;
if (who)
props[PETRIFIED_BY_KEY] = who->name(DESC_A, true);
redraw_evasion = true;
mprf(MSGCH_WARN, "You are slowing down.");
}
bool player::fully_petrify(actor */*foe*/, bool /*quiet*/)
{
duration[DUR_PETRIFIED] = 6 * BASELINE_DELAY
+ random2(4 * BASELINE_DELAY);
redraw_evasion = true;
mpr("You have turned to stone.");
end_searing_ray();
return true;
}
void player::slow_down(actor */*foe*/, int str)
{
::slow_player(str);
}
int player::has_claws(bool allow_tran) const
{
if (allow_tran)
{
// these transformations bring claws with them
if (form == transformation::dragon)
return 3;
// blade hands override claws
if (form == transformation::blade_hands)
return 0;
}
return get_mutation_level(MUT_CLAWS, allow_tran);
}
bool player::has_usable_claws(bool allow_tran) const
{
return !slot_item(EQ_GLOVES) && has_claws(allow_tran);
}
int player::has_talons(bool allow_tran) const
{
// XXX: Do merfolk in water belong under allow_tran?
if (fishtail)
return 0;
return get_mutation_level(MUT_TALONS, allow_tran);
}
bool player::has_usable_talons(bool allow_tran) const
{
return !slot_item(EQ_BOOTS) && has_talons(allow_tran);
}
int player::has_hooves(bool allow_tran) const
{
// XXX: Do merfolk in water belong under allow_tran?
if (fishtail)
return 0;
return get_mutation_level(MUT_HOOVES, allow_tran);
}
bool player::has_usable_hooves(bool allow_tran) const
{
return has_hooves(allow_tran)
&& (!slot_item(EQ_BOOTS)
|| wearing(EQ_BOOTS, ARM_CENTAUR_BARDING, true));
}
int player::has_fangs(bool allow_tran) const
{
if (allow_tran)
{
// these transformations bring fangs with them
if (form == transformation::dragon)
return 3;
}
return get_mutation_level(MUT_FANGS, allow_tran);
}
int player::has_usable_fangs(bool allow_tran) const
{
return has_fangs(allow_tran);
}
int player::has_tail(bool allow_tran) const
{
if (allow_tran)
{
// these transformations bring a tail with them
if (form == transformation::dragon)
return 1;
// Most transformations suppress a tail.
if (!form_keeps_mutations())
return 0;
}
// XXX: Do merfolk in water belong under allow_tran?
if (species_is_draconian(species)
|| fishtail
|| get_mutation_level(MUT_STINGER, allow_tran))
{
return 1;
}
return 0;
}
int player::has_usable_tail(bool allow_tran) const
{
return has_tail(allow_tran);
}
// Whether the player has a usable offhand for the
// purpose of punching.
bool player::has_usable_offhand() const
{
if (get_mutation_level(MUT_MISSING_HAND))
return false;
if (shield())
return false;
const item_def* wp = slot_item(EQ_WEAPON);
return !wp || hands_reqd(*wp) != HANDS_TWO;
}
bool player::has_usable_tentacle() const
{
return usable_tentacles();
}
int player::usable_tentacles() const
{
int numtentacle = has_usable_tentacles();
if (numtentacle == 0)
return false;
int free_tentacles = numtentacle - num_constricting();
if (shield())
free_tentacles -= 2;
const item_def* wp = slot_item(EQ_WEAPON);
if (wp)
{
hands_reqd_type hands_req = hands_reqd(*wp);
free_tentacles -= 2 * hands_req + 2;
}
return free_tentacles;
}
int player::has_pseudopods(bool allow_tran) const
{
return get_mutation_level(MUT_PSEUDOPODS, allow_tran);
}
int player::has_usable_pseudopods(bool allow_tran) const
{
return has_pseudopods(allow_tran);
}
int player::has_tentacles(bool allow_tran) const
{
if (allow_tran)
{
// Most transformations suppress tentacles.
if (!form_keeps_mutations())
return 0;
}
if (species == SP_OCTOPODE && get_mutation_level(MUT_MISSING_HAND))
return 7;
else if (species == SP_OCTOPODE)
return 8;
return 0;
}
int player::has_usable_tentacles(bool allow_tran) const
{
return has_tentacles(allow_tran);
}
bool player::sicken(int amount)
{
ASSERT(!crawl_state.game_is_arena());
if (res_rotting() || amount <= 0)
return false;
if (duration[DUR_DIVINE_STAMINA] > 0)
{
mpr("Your divine stamina protects you from disease!");
return false;
}
mpr("You feel ill.");
disease += amount * BASELINE_DELAY;
if (disease > 210 * BASELINE_DELAY)
disease = 210 * BASELINE_DELAY;
return true;
}
/// Can the player see invisible things?
bool player::can_see_invisible(bool calc_unid) const
{
if (crawl_state.game_is_arena())
return true;
if (wearing(EQ_RINGS, RING_SEE_INVISIBLE, calc_unid)
// armour: (checks head armour only)
|| wearing_ego(EQ_HELMET, SPARM_SEE_INVISIBLE)
// randart gear
|| scan_artefacts(ARTP_SEE_INVISIBLE, calc_unid) > 0)
{
return true;
}
return innate_sinv();
}
/// Can the player see invisible things without needing items' help?
bool player::innate_sinv() const
{
// Possible to have both with a temp mutation.
if (has_mutation(MUT_ACUTE_VISION)
&& !has_mutation(MUT_BLURRY_VISION))
{
return true;
}
// antennae give sInvis at 3
if (get_mutation_level(MUT_ANTENNAE) == 3)
return true;
if (get_mutation_level(MUT_EYEBALLS) == 3)
return true;
if (have_passive(passive_t::sinv))
return true;
return false;
}
bool player::invisible() const
{
return (duration[DUR_INVIS] || form == transformation::shadow)
&& !backlit();
}
bool player::visible_to(const actor *looker) const
{
if (crawl_state.game_is_arena())
return false;
const bool invis_to = invisible() && !looker->can_see_invisible()
&& !in_water();
if (this == looker)
return !invis_to;
const monster* mon = looker->as_monster();
return mon->friendly()
|| (!mon->has_ench(ENCH_BLIND) && !invis_to);
}
/**
* Is the player backlit?
*
* @param self_halo If true, ignore the player's self-halo.
* @returns True if the player is backlit.
*/
bool player::backlit(bool self_halo) const
{
return player_severe_contamination()
|| duration[DUR_CORONA]
|| duration[DUR_LIQUID_FLAMES]
|| duration[DUR_QUAD_DAMAGE]
|| !umbraed() && haloed() && (self_halo || halo_radius() == -1);
}
bool player::umbra() const
{
return !backlit() && umbraed() && !haloed();
}
// This is the imperative version.
void player::backlight()
{
if (!duration[DUR_INVIS] && form != transformation::shadow)
{
if (duration[DUR_CORONA])
mpr("You glow brighter.");
else
mpr("You are outlined in light.");
increase_duration(DUR_CORONA, random_range(15, 35), 250);
}
else
{
mpr("You feel strangely conspicuous.");
increase_duration(DUR_CORONA, random_range(3, 5), 250);
}
}
bool player::can_mutate() const
{
return true;
}
/**
* Can the player be mutated without rotting instead?
*
* @param temp Whether to consider temporary modifiers (lichform)
* @return Whether the player will mutate when mutated, instead of rotting.
*/
bool player::can_safely_mutate(bool temp) const
{
if (!can_mutate())
return false;
return undead_state(temp) == US_ALIVE
|| undead_state(temp) == US_SEMI_UNDEAD;
}
// Is the player too undead to bleed, rage, or polymorph?
bool player::is_lifeless_undead(bool temp) const
{
if (undead_state() == US_SEMI_UNDEAD)
return temp ? !you.vampire_alive : false;
else
return undead_state(temp) != US_ALIVE;
}
bool player::can_polymorph() const
{
return !(transform_uncancellable || is_lifeless_undead());
}
bool player::can_bleed(bool allow_tran) const
{
// XXX: Lich and statue forms are still caught by the holiness checks below.
if (allow_tran && !form_can_bleed(form))
return false;
if (is_lifeless_undead() || is_nonliving())
{ // demonspawn and demigods have a mere drop of taint
return false;
}
return true;
}
bool player::is_stationary() const
{
return form == transformation::tree;
}
bool player::malmutate(const string &reason)
{
ASSERT(!crawl_state.game_is_arena());
if (!can_mutate())
return false;
const mutation_type mut_quality = one_chance_in(5) ? RANDOM_MUTATION
: RANDOM_BAD_MUTATION;
if (mutate(mut_quality, reason))
{
learned_something_new(HINT_YOU_MUTATED);
return true;
}
return false;
}
bool player::polymorph(int pow, bool allow_immobile)
{
ASSERT(!crawl_state.game_is_arena());
if (!can_polymorph())
return false;
transformation f = transformation::none;
vector<transformation> forms = {
transformation::bat,
transformation::wisp,
transformation::pig,
};
if (allow_immobile)
{
forms.emplace_back(transformation::tree);
forms.emplace_back(transformation::fungus);
}
for (int tries = 0; tries < 3; tries++)
{
f = forms[random2(forms.size())];
// need to do a dry run first, as Zin's protection has a random factor
if (transform(pow, f, true, true))
break;
f = transformation::none;
}
if (f != transformation::none && transform(pow, f))
{
transform_uncancellable = true;
return true;
}
return false;
}
bool player::is_icy() const
{
return form == transformation::ice_beast;
}
bool player::is_fiery() const
{
return false;
}
bool player::is_skeletal() const
{
return false;
}
void player::shiftto(const coord_def &c)
{
crawl_view.shift_player_to(c);
set_position(c);
clear_invalid_constrictions();
}
bool player::asleep() const
{
return duration[DUR_SLEEP];
}
bool player::cannot_act() const
{
return asleep() || cannot_move();
}
bool player::can_throw_large_rocks() const
{
return species_can_throw_large_rocks(species);
}
bool player::can_smell() const
{
return species != SP_MUMMY;
}
bool player::can_sleep(bool holi_only) const
{
return !you.duration[DUR_SLEEP_IMMUNITY] && actor::can_sleep(holi_only);
}
/**
* Attempts to put the player to sleep.
*
* @param power The power of the effect putting the player to sleep.
* @param hibernate Whether the player is being put to sleep by 'ensorcelled
* hibernation' (doesn't affect characters with rC, ignores
* power), or by a normal sleep effect.
*/
void player::put_to_sleep(actor*, int power, bool hibernate)
{
ASSERT(!crawl_state.game_is_arena());
const bool valid_target = hibernate ? can_hibernate() : can_sleep();
if (!valid_target)
{
canned_msg(MSG_YOU_UNAFFECTED);
return;
}
if (duration[DUR_SLEEP_IMMUNITY])
{
mpr("You can't fall asleep again this soon!");
return;
}
if (duration[DUR_PARALYSIS]
|| duration[DUR_PETRIFIED]
|| duration[DUR_PETRIFYING])
{
mpr("You can't fall asleep in your current state!");
return;
}
mpr("You fall asleep.");
stop_directly_constricting_all(false);
end_searing_ray();
stop_delay();
flash_view(UA_MONSTER, DARKGREY);
// As above, do this after redraw.
const int dur = hibernate ? 3 + random2avg(5, 2) :
5 + random2avg(power/10, 5);
set_duration(DUR_SLEEP, dur);
}
void player::awaken()
{
ASSERT(!crawl_state.game_is_arena());
duration[DUR_SLEEP] = 0;
set_duration(DUR_SLEEP_IMMUNITY, random_range(3, 5));
mpr("You wake up.");
flash_view(UA_MONSTER, BLACK);
}
void player::check_awaken(int disturbance)
{
if (asleep() && x_chance_in_y(disturbance + 1, 50))
{
awaken();
dprf("Disturbance of intensity %d awoke player", disturbance);
}
}
int player::beam_resists(bolt &beam, int hurted, bool doEffects, string source)
{
return check_your_resists(hurted, beam.flavour, source, &beam, doEffects);
}
// Used for falling into traps and other bad effects, but is a slightly
// different effect from the player invokable ability.
bool player::do_shaft()
{
if (!is_valid_shaft_level()
|| !feat_is_shaftable(grd(pos()))
|| duration[DUR_SHAFT_IMMUNITY])
{
return false;
}
// Ensure altars, items, and shops discovered at the moment
// the player gets shafted are correctly registered.
maybe_update_stashes();
duration[DUR_SHAFT_IMMUNITY] = 1;
down_stairs(DNGN_TRAP_SHAFT);
return true;
}
bool player::can_do_shaft_ability(bool quiet) const
{
if (attribute[ATTR_HELD])
{
if (!quiet)
mprf("You can't shaft yourself while %s.", held_status());
return false;
}
if (feat_is_shaftable(grd(pos())))
{
if (!is_valid_shaft_level())
{
if (!quiet)
mpr("You can't shaft yourself on this level.");
return false;
}
}
else
{
if (!quiet)
mpr("You can't shaft yourself on this terrain.");
return false;
}
return true;
}
// Like do_shaft, but forced by the player.
// It has a slightly different set of rules.
bool player::do_shaft_ability()
{
if (can_do_shaft_ability(true))
{
mpr("A shaft appears beneath you!");
down_stairs(DNGN_TRAP_SHAFT, true);
return true;
}
else
{
canned_msg(MSG_NOTHING_HAPPENS);
redraw_screen();
return false;
}
}
bool player::did_escape_death() const
{
return escaped_death_cause != NUM_KILLBY;
}
void player::reset_escaped_death()
{
escaped_death_cause = NUM_KILLBY;
escaped_death_aux = "";
}
void player::add_gold(int delta)
{
set_gold(gold + delta);
}
void player::del_gold(int delta)
{
set_gold(gold - delta);
}
void player::set_gold(int amount)
{
ASSERT(amount >= 0);
if (amount != gold)
{
const int old_gold = gold;
gold = amount;
shopping_list.gold_changed(old_gold, gold);
// XXX: this might benefit from being in its own function
if (you_worship(GOD_GOZAG))
{
for (const auto& power : get_god_powers(you.religion))
{
const int cost = get_gold_cost(power.abil);
if (gold >= cost && old_gold < cost)
power.display(true, "You now have enough gold to %s.");
else if (old_gold >= cost && gold < cost)
power.display(false, "You no longer have enough gold to %s.");
}
you.redraw_title = true;
}
}
}
void player::increase_duration(duration_type dur, int turns, int cap,
const char* msg)
{
if (msg)
mpr(msg);
cap *= BASELINE_DELAY;
duration[dur] += turns * BASELINE_DELAY;
if (cap && duration[dur] > cap)
duration[dur] = cap;
}
void player::set_duration(duration_type dur, int turns,
int cap, const char * msg)
{
duration[dur] = 0;
increase_duration(dur, turns, cap, msg);
}
void player::goto_place(const level_id &lid)
{
where_are_you = static_cast<branch_type>(lid.branch);
depth = lid.depth;
ASSERT_RANGE(depth, 1, brdepth[where_are_you] + 1);
}
bool player::attempt_escape(int attempts)
{
monster *themonst;
if (!is_constricted())
return true;
themonst = monster_by_mid(constricted_by);
ASSERT(themonst);
escape_attempts += attempts;
const bool direct = is_directly_constricted();
const string object = direct ? themonst->name(DESC_ITS, true)
: "the roots'";
// player breaks free if (4+n)d13 >= 5d(8+HD/4)
const int escape_score = roll_dice(4 + escape_attempts, 13);
if (escape_score
>= roll_dice(5, 8 + div_rand_round(themonst->get_hit_dice(), 4)))
{
mprf("You escape %s grasp.", object.c_str());
// Stun the monster to prevent it from constricting again right away.
if (direct)
themonst->speed_increment -= 5;
stop_being_constricted(true);
return true;
}
else
{
mprf("%s grasp on you weakens, but your attempt to escape fails.",
object.c_str());
turn_is_over = true;
return false;
}
}
void player::sentinel_mark(bool trap)
{
if (duration[DUR_SENTINEL_MARK])
{
mpr("The mark upon you grows brighter.");
increase_duration(DUR_SENTINEL_MARK, random_range(20, 40), 180);
}
else
{
mprf(MSGCH_WARN, "A sentinel's mark forms upon you.");
increase_duration(DUR_SENTINEL_MARK, trap ? random_range(25, 40)
: random_range(35, 60),
250);
}
}
/*
* Is the player too terrified to move (because of fungusform)?
*
* @return true iff there is an alarming monster anywhere near a fungusform player.
*/
bool player::is_nervous()
{
if (form != transformation::fungus)
return false;
for (monster_near_iterator mi(&you); mi; ++mi)
{
if (made_nervous_by(*mi))
return true;
}
return false;
}
/*
* Does monster `mons` make the player nervous (in fungusform)?
*
* @param mons the monster to check
* @return true iff mons is non-null, player is fungal, and `mons` is a threatening monster.
*/
bool player::made_nervous_by(const monster *mons)
{
if (form != transformation::fungus)
return false;
if (!mons)
return false;
if (!mons_is_wandering(*mons)
&& !mons->asleep()
&& !mons->confused()
&& !mons->cannot_act()
&& mons_is_threatening(*mons)
&& !mons->wont_attack()
&& !mons->neutral())
{
return true;
}
return false;
}
void player::weaken(actor */*attacker*/, int pow)
{
if (!duration[DUR_WEAK])
mprf(MSGCH_WARN, "You feel your attacks grow feeble.");
else
mprf(MSGCH_WARN, "You feel as though you will be weak longer.");
increase_duration(DUR_WEAK, pow + random2(pow + 3), 50);
}
/**
* Check if the player is about to die from flight/form expiration.
*
* Check whether the player is on a cell which would be deadly if not for some
* temporary condition, and if such condition is expiring. In that case, we
* give a strong warning to the player. The actual message printing is done
* by the caller.
*
* @param dur the duration to check for dangerous expiration.
* @param p the coordinates of the cell to check. Defaults to player position.
* @return whether the player is in immediate danger.
*/
bool need_expiration_warning(duration_type dur, dungeon_feature_type feat)
{
if (!is_feat_dangerous(feat, true) || !dur_expiring(dur))
return false;
if (dur == DUR_FLIGHT)
return true;
else if (dur == DUR_TRANSFORMATION
&& (form_can_swim()) || form_can_fly())
{
return true;
}
return false;
}
bool need_expiration_warning(duration_type dur, coord_def p)
{
return need_expiration_warning(dur, env.grid(p));
}
bool need_expiration_warning(dungeon_feature_type feat)
{
return need_expiration_warning(DUR_FLIGHT, feat)
|| need_expiration_warning(DUR_TRANSFORMATION, feat);
}
bool need_expiration_warning(coord_def p)
{
return need_expiration_warning(env.grid(p));
}
static string _constriction_description()
{
string cinfo = "";
vector<string> c_name;
const int num_free_tentacles = you.usable_tentacles();
if (num_free_tentacles)
{
cinfo += make_stringf("You have %d tentacle%s available for constriction.",
num_free_tentacles,
num_free_tentacles > 1 ? "s" : "");
}
if (you.is_directly_constricted())
{
const monster * const constrictor = monster_by_mid(you.constricted_by);
ASSERT(constrictor);
if (!cinfo.empty())
cinfo += "\n";
cinfo += make_stringf("You are being %s by %s.",
constrictor->constriction_does_damage(true) ?
"held" : "constricted",
constrictor->name(DESC_A).c_str());
}
if (you.is_constricting())
{
for (const auto &entry : *you.constricting)
{
monster *whom = monster_by_mid(entry.first);
ASSERT(whom);
if (!whom->is_directly_constricted())
continue;
c_name.push_back(whom->name(DESC_A));
}
if (!c_name.empty())
{
if (!cinfo.empty())
cinfo += "\n";
cinfo += "You are constricting ";
cinfo += comma_separated_line(c_name.begin(), c_name.end());
cinfo += ".";
}
}
return cinfo;
}
/**
* The player's radius of monster detection.
* @return the radius in which a player can detect monsters.
**/
int player_monster_detect_radius()
{
int radius = you.get_mutation_level(MUT_ANTENNAE) * 2;
if (player_equip_unrand(UNRAND_HOOD_ASSASSIN))
radius = max(radius, 4);
if (have_passive(passive_t::detect_montier))
radius = max(radius, you.piety / 20);
return min(radius, LOS_DEFAULT_RANGE);
}
/**
* Return true if the player has angered Pandemonium by picking up or moving
* the Orb of Zot.
*/
bool player_on_orb_run()
{
return you.chapter == CHAPTER_ESCAPING
|| you.chapter == CHAPTER_ANGERED_PANDEMONIUM;
}
/**
* Return true if the player has the Orb of Zot.
* @return True if the player has the Orb, false otherwise.
*/
bool player_has_orb()
{
return you.chapter == CHAPTER_ESCAPING;
}
bool player::form_uses_xl() const
{
// No body parts that translate in any way to something fisticuffs could
// matter to, the attack mode is different. Plus, it's weird to have
// users of one particular [non-]weapon be effective for this
// unintentional form while others can just run or die. I believe this
// should apply to more forms, too. [1KB]
return form == transformation::wisp || form == transformation::fungus
|| form == transformation::pig
|| form == transformation::bat && you.species != SP_VAMPIRE;
}
static int _get_potion_heal_factor()
{
// healing factor is expressed in thirds, so default is 3/3 -- 100%.
int factor = 3;
// start with penalties
factor -= player_equip_unrand(UNRAND_VINES) ? 3 : 0;
factor -= you.mutation[MUT_NO_POTION_HEAL];
// then apply bonuses - Kryia's doubles potion healing
factor *= player_equip_unrand(UNRAND_KRYIAS) ? 2 : 1;
// make sure we don't turn healing negative.
return max(0, factor);
}
void print_potion_heal_message()
{
// Don't give multiple messages in weird cases with both enhanced
// and reduced healing.
if (_get_potion_heal_factor() > 3)
{
if (player_equip_unrand(UNRAND_KRYIAS))
{
item_def* item = you.slot_item(EQ_BODY_ARMOUR);
mprf("%s enhances the healing.",
item->name(DESC_THE, false, false, false).c_str());
}
else
mpr("The healing is enhanced."); // bad message, but this should
// never be possible anyway
}
else if (_get_potion_heal_factor() == 0)
mpr("Your system rejects the healing.");
else if (_get_potion_heal_factor() < 3)
mpr("Your system partially rejects the healing.");
}
bool player::can_potion_heal()
{
return _get_potion_heal_factor() > 0;
}
int player::scale_potion_healing(int healing_amount)
{
return div_rand_round(healing_amount * _get_potion_heal_factor(), 3);
}
void player_open_door(coord_def doorpos)
{
// Finally, open the closed door!
set<coord_def> all_door;
find_connected_identical(doorpos, all_door);
const char *adj, *noun;
get_door_description(all_door.size(), &adj, &noun);
const string door_desc_adj =
env.markers.property_at(doorpos, MAT_ANY, "door_description_adjective");
const string door_desc_noun =
env.markers.property_at(doorpos, MAT_ANY, "door_description_noun");
if (!door_desc_adj.empty())
adj = door_desc_adj.c_str();
if (!door_desc_noun.empty())
noun = door_desc_noun.c_str();
if (!you.confused())
{
string door_open_prompt =
env.markers.property_at(doorpos, MAT_ANY, "door_open_prompt");
bool ignore_exclude = false;
if (!door_open_prompt.empty())
{
door_open_prompt += " (y/N)";
if (!yesno(door_open_prompt.c_str(), true, 'n', true, false))
{
if (is_exclude_root(doorpos))
canned_msg(MSG_OK);
else
{
if (yesno("Put travel exclusion on door? (Y/n)",
true, 'y'))
{
// Zero radius exclusion right on top of door.
set_exclude(doorpos, 0);
}
}
interrupt_activity(activity_interrupt::force);
return;
}
ignore_exclude = true;
}
if (!ignore_exclude && is_exclude_root(doorpos))
{
string prompt = make_stringf("This %s%s is marked as excluded! "
"Open it anyway?", adj, noun);
if (!yesno(prompt.c_str(), true, 'n', true, false))
{
canned_msg(MSG_OK);
interrupt_activity(activity_interrupt::force);
return;
}
}
}
const int skill = 8 + you.skill_rdiv(SK_STEALTH, 4, 3);
string berserk_open = env.markers.property_at(doorpos, MAT_ANY,
"door_berserk_verb_open");
string berserk_adjective = env.markers.property_at(doorpos, MAT_ANY,
"door_berserk_adjective");
string door_open_creak = env.markers.property_at(doorpos, MAT_ANY,
"door_noisy_verb_open");
string door_airborne = env.markers.property_at(doorpos, MAT_ANY,
"door_airborne_verb_open");
string door_open_verb = env.markers.property_at(doorpos, MAT_ANY,
"door_verb_open");
if (you.berserk())
{
// XXX: Better flavour for larger doors?
if (silenced(you.pos()))
{
if (!berserk_open.empty())
{
berserk_open += ".";
mprf(berserk_open.c_str(), adj, noun);
}
else
mprf("The %s%s flies open!", adj, noun);
}
else
{
if (!berserk_open.empty())
{
if (!berserk_adjective.empty())
berserk_open += " " + berserk_adjective;
else
berserk_open += ".";
mprf(MSGCH_SOUND, berserk_open.c_str(), adj, noun);
}
else
mprf(MSGCH_SOUND, "The %s%s flies open with a bang!", adj, noun);
noisy(15, you.pos());
}
}
else if (one_chance_in(skill) && !silenced(you.pos()))
{
if (!door_open_creak.empty())
mprf(MSGCH_SOUND, door_open_creak.c_str(), adj, noun);
else
{
mprf(MSGCH_SOUND, "As you open the %s%s, it creaks loudly!",
adj, noun);
}
noisy(10, you.pos());
}
else
{
const char* verb;
if (you.airborne())
{
if (!door_airborne.empty())
verb = door_airborne.c_str();
else
verb = "You reach down and open the %s%s.";
}
else
{
if (!door_open_verb.empty())
verb = door_open_verb.c_str();
else
verb = "You open the %s%s.";
}
mprf(verb, adj, noun);
}
vector<coord_def> excludes;
for (const auto &dc : all_door)
{
if (cell_is_runed(dc))
explored_tracked_feature(grd(dc));
dgn_open_door(dc);
set_terrain_changed(dc);
dungeon_events.fire_position_event(DET_DOOR_OPENED, dc);
// Even if some of the door is out of LOS, we want the entire
// door to be updated. Hitting this case requires a really big
// door!
if (env.map_knowledge(dc).seen())
{
env.map_knowledge(dc).set_feature(grd(dc));
#ifdef USE_TILE
env.tile_bk_bg(dc) = tileidx_feature_base(grd(dc));
#endif
}
if (is_excluded(dc))
excludes.push_back(dc);
}
update_exclusion_los(excludes);
viewwindow();
you.turn_is_over = true;
}
void player_close_door(coord_def doorpos)
{
// Finally, close the opened door!
string berserk_close = env.markers.property_at(doorpos, MAT_ANY,
"door_berserk_verb_close");
const string berserk_adjective = env.markers.property_at(doorpos, MAT_ANY,
"door_berserk_adjective");
const string door_close_creak = env.markers.property_at(doorpos, MAT_ANY,
"door_noisy_verb_close");
const string door_airborne = env.markers.property_at(doorpos, MAT_ANY,
"door_airborne_verb_close");
const string door_close_verb = env.markers.property_at(doorpos, MAT_ANY,
"door_verb_close");
const string door_desc_adj = env.markers.property_at(doorpos, MAT_ANY,
"door_description_adjective");
const string door_desc_noun = env.markers.property_at(doorpos, MAT_ANY,
"door_description_noun");
set<coord_def> all_door;
find_connected_identical(doorpos, all_door);
const auto door_vec = vector<coord_def>(all_door.begin(), all_door.end());
const char *adj, *noun;
get_door_description(all_door.size(), &adj, &noun);
const string waynoun_str = make_stringf("%sway", noun);
const char *waynoun = waynoun_str.c_str();
if (!door_desc_adj.empty())
adj = door_desc_adj.c_str();
if (!door_desc_noun.empty())
{
noun = door_desc_noun.c_str();
waynoun = noun;
}
for (const coord_def& dc : all_door)
{
if (monster* mon = monster_at(dc))
{
const bool mons_unseen = !you.can_see(*mon);
if (mons_unseen || mons_is_object(mon->type))
{
mprf("Something is blocking the %s!", waynoun);
// No free detection!
if (mons_unseen)
you.turn_is_over = true;
}
else
mprf("There's a creature in the %s!", waynoun);
return;
}
if (igrd(dc) != NON_ITEM)
{
if (!has_push_spaces(dc, false, &door_vec))
{
mprf("There's something jamming the %s.", waynoun);
return;
}
}
// messaging with gateways will be inconsistent if this isn't last
if (you.pos() == dc)
{
mprf("There's a thick-headed creature in the %s!", waynoun);
return;
}
}
const int you_old_top_item = igrd(you.pos());
bool items_moved = false;
for (const coord_def& dc : all_door)
items_moved |= push_items_from(dc, &door_vec);
// TODO: if only one thing moved, use that item's name
// TODO: handle des-derived strings. (Better yet, find a way to not have
// format strings in des...)
const char *items_msg = items_moved ? ", pushing everything out of the way"
: "";
const int skill = 8 + you.skill_rdiv(SK_STEALTH, 4, 3);
if (you.berserk())
{
if (silenced(you.pos()))
{
if (!berserk_close.empty())
{
berserk_close += ".";
mprf(berserk_close.c_str(), adj, noun);
}
else
mprf("You slam the %s%s shut%s!", adj, noun, items_msg);
}
else
{
if (!berserk_close.empty())
{
if (!berserk_adjective.empty())
berserk_close += " " + berserk_adjective;
else
berserk_close += ".";
mprf(MSGCH_SOUND, berserk_close.c_str(), adj, noun);
}
else
{
mprf(MSGCH_SOUND, "You slam the %s%s shut with a bang%s!",
adj, noun, items_msg);
}
noisy(15, you.pos());
}
}
else if (one_chance_in(skill) && !silenced(you.pos()))
{
if (!door_close_creak.empty())
mprf(MSGCH_SOUND, door_close_creak.c_str(), adj, noun);
else
{
mprf(MSGCH_SOUND, "As you close the %s%s%s, it creaks loudly!",
adj, noun, items_msg);
}
noisy(10, you.pos());
}
else
{
if (you.airborne())
{
if (!door_airborne.empty())
mprf(door_airborne.c_str(), adj, noun);
else
mprf("You reach down and close the %s%s%s.", adj, noun, items_msg);
}
else
{
if (!door_close_verb.empty())
mprf(door_close_verb.c_str(), adj, noun);
else
mprf("You close the %s%s%s.", adj, noun, items_msg);
}
}
vector<coord_def> excludes;
for (const coord_def& dc : all_door)
{
// Once opened, formerly runed doors become normal doors.
dgn_close_door(dc);
set_terrain_changed(dc);
dungeon_events.fire_position_event(DET_DOOR_CLOSED, dc);
// Even if some of the door is out of LOS once it's closed
// (or even if some of it is out of LOS when it's open), we
// want the entire door to be updated.
if (env.map_knowledge(dc).seen())
{
env.map_knowledge(dc).set_feature(grd(dc));
#ifdef USE_TILE
env.tile_bk_bg(dc) = tileidx_feature_base(grd(dc));
#endif
}
if (is_excluded(dc))
excludes.push_back(dc);
}
update_exclusion_los(excludes);
// item pushing may have moved items under the player
if (igrd(you.pos()) != you_old_top_item)
item_check();
you.turn_is_over = true;
}
/**
* Return a string describing the player's hand(s) taking a given verb.
*
* @param plural_verb A plural-agreeing verb. ("Smoulders", "are", etc.)
* @return A string describing the action.
* E.g. "tentacles smoulder", "paw is", etc.
*/
string player::hands_verb(const string &plural_verb) const
{
bool plural;
const string hand = hand_name(true, &plural);
return hand + " " + conjugate_verb(plural_verb, plural);
}
// Is this a character that would not normally have a preceding space when
// it follows a word?
static bool _is_end_punct(char c)
{
switch (c)
{
case ' ': case '.': case '!': case '?':
case ',': case ':': case ';': case ')':
return true;
}
return false;
}
/**
* Return a string describing the player's hand(s) (or equivalent) taking the
* given action (verb).
*
* @param plural_verb The plural-agreeing verb corresponding to the action to
* take. E.g., "smoulder", "glow", "gain", etc.
* @param object The object or predicate complement of the action,
* including any sentence-final punctuation. E.g. ".",
* "new energy.", etc.
* @return A string describing the player's hands taking the
* given action. E.g. "Your tentacle gains new energy."
*/
string player::hands_act(const string &plural_verb,
const string &object) const
{
const bool space = !object.empty() && !_is_end_punct(object[0]);
return "Your " + hands_verb(plural_verb) + (space ? " " : "") + object;
}
int player::inaccuracy() const
{
int degree = 0;
if (wearing(EQ_AMULET, AMU_INACCURACY))
degree++;
if (get_mutation_level(MUT_MISSING_EYE))
degree++;
return degree;
}
/**
* Handle effects that occur after the player character stops berserking.
*/
void player_end_berserk()
{
// Sometimes berserk leaves us physically drained.
//
// Chance of passing out:
// - mutation gives a large plus in order to try and
// avoid the mutation being a "death sentence" to
// certain characters.
if (one_chance_in(10 + you.get_mutation_level(MUT_BERSERK) * 25))
{
// Note the beauty of Trog! They get an extra save that
// goes up to 100% at 6 stars of piety.
if (have_passive(passive_t::extend_berserk)
&& x_chance_in_y(you.piety, piety_breakpoint(5)))
{
mpr("Trog's vigour flows through your veins.");
}
else
{
mprf(MSGCH_WARN, "You pass out from exhaustion.");
you.increase_duration(DUR_PARALYSIS, roll_dice(1, 4));
you.stop_directly_constricting_all(false);
}
}
if (!you.duration[DUR_PARALYSIS] && !you.petrified())
mprf(MSGCH_WARN, "You are exhausted.");
you.berserk_penalty = 0;
const int dur = 12 + roll_dice(2, 12);
// Slow durations are multiplied by haste_mul (3/2), exhaustion lasts
// slightly longer.
you.increase_duration(DUR_BERSERK_COOLDOWN, dur * 2);
// Don't trigger too many hints mode messages.
const bool hints_slow = Hints.hints_events[HINT_YOU_ENCHANTED];
Hints.hints_events[HINT_YOU_ENCHANTED] = false;
slow_player(dur);
//Un-apply Berserk's +50% Current/Max HP
calc_hp(true, false);
learned_something_new(HINT_POSTBERSERK);
Hints.hints_events[HINT_YOU_ENCHANTED] = hints_slow;
you.redraw_quiver = true; // Can throw again.
}
/**
* Does the player have the Sanguine Armour mutation (not suppressed by a form)
* while being at a low enough HP (<67%) for its benefits to trigger?
*
* @return Whether Sanguine Armour should be active.
*/
bool sanguine_armour_valid()
{
// why does this need to specify the activity type explicitly?
return you.hp <= you.hp_max * 2 / 3
&& you.get_mutation_level(MUT_SANGUINE_ARMOUR, mutation_activity_type::FULL);
}
/// Trigger sanguine armour, updating the duration & messaging as appropriate.
void activate_sanguine_armour()
{
const bool was_active = you.duration[DUR_SANGUINE_ARMOUR];
you.duration[DUR_SANGUINE_ARMOUR] = random_range(60, 100);
if (!was_active)
{
mpr("Your blood congeals into armour.");
you.redraw_armour_class = true;
}
}
/**
* Refreshes the protective aura around the player after striking with
* a weapon of protection. The duration is very short.
*/
void refresh_weapon_protection()
{
if (!you.duration[DUR_SPWPN_PROTECTION])
mpr("Your weapon exudes an aura of protection.");
you.increase_duration(DUR_SPWPN_PROTECTION, 3 + random2(2), 5);
you.redraw_armour_class = true;
}
// Is the player immune to a particular hex because of their
// intrinsic properties?
bool player::immune_to_hex(const spell_type hex) const
{
switch (hex)
{
case SPELL_PARALYSIS_GAZE:
case SPELL_PARALYSE:
case SPELL_SLOW:
return stasis();
case SPELL_CONFUSE:
case SPELL_CONFUSION_GAZE:
case SPELL_MASS_CONFUSION:
return clarity() || you.duration[DUR_DIVINE_STAMINA] > 0;
case SPELL_TELEPORT_OTHER:
case SPELL_BLINK_OTHER:
case SPELL_BLINK_OTHER_CLOSE:
return no_tele();
case SPELL_MESMERISE:
case SPELL_AVATAR_SONG:
case SPELL_SIREN_SONG:
return clarity() || berserk();
case SPELL_CAUSE_FEAR:
return clarity() || !(holiness() & MH_NATURAL) || berserk();
case SPELL_PETRIFY:
return res_petrify();
case SPELL_PORKALATOR:
return is_lifeless_undead();
case SPELL_VIRULENCE:
return res_poison() == 3;
// don't include the hidden "sleep immunity" duration
case SPELL_SLEEP:
case SPELL_DREAM_DUST:
return !actor::can_sleep();
case SPELL_HIBERNATION:
return !can_hibernate();
default:
return false;
}
}
// Activate DUR_AGILE.
void player::be_agile(int pow)
{
const bool were_agile = you.duration[DUR_AGILITY] > 0;
mprf(MSGCH_DURATION, "You feel %sagile all of a sudden.",
were_agile ? "more " : "");
you.increase_duration(DUR_AGILITY, 35 + random2(pow), 80);
if (!were_agile)
you.redraw_evasion = true;
}
↑ 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.
↑ V547 Expression '!attrib.empty()' is always true.
↑ V768 The expression 'you.undead_state()' is of enum type. It is odd that it is used as an expression of a Boolean-type.
↑ V560 A part of conditional expression is always true: !quiet.
↑ V768 The expression 'undead_state()' is of enum type. It is odd that it is used as an expression of a Boolean-type.
↑ 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.
↑ V547 Expression 'found_nonartefact' is always false.
↑ V648 Priority of the '&&' operation is higher than that of the '||' operation.


(An Alan Smithee Film--) Burn Hollywood Burn (R) no stars (out of ****)
The wildly overpaid screenwriter Joe Eszterhas has written so many masturbatory fantasies for the movies that it was only a matter of time before he himself jacked off onscreen. And that's exactly what he does in his absolutely atrocious "inside Hollywood satire," which cannot even decide what its title is. Originally billed simply as An Alan Smithee Film, its "official" title is An Alan Smithee Film Burn Hollywood Burn. However, in the opening titles, the "An Alan Smithee Film" appears more as a possessory credit and Burn Hollywood Burn is given the showcase title treatment, not to mention that numerous sources refer to it as simply Burn Hollywood Burn. However, a dash (--) curiously appears after "Film," so I'll call this self-indulgent waste of celluloid is (An Alan Smithee Film--) Burn Hollywood Burn.
As far as I'm concerned, Eszterhas is a comic genius. It takes a certain gift to not only pen the notorious laff riot Showgirls but to also liken the lapdancing extravaganza as "a religious experience." But his comedic talent only shines through when he's blissfully, hilariously unaware--that is, when he's dead serious. Burn Hollywood Burn is written and conceived as a comedy, and this sorry excuse for a satire just proves the opposite point: "funny" Eszterhas is not only unfunny, but excruciatingly so.
"Structured" (using that term _very_ loosely) as a mockumentary in three haphazardly labeled acts (titled "Missionary Position," "Whips and Chains," and "Doggie Style"--are we laughing yet?), the film details the disastrous making of the most expensive film in Hollywood history, the (fictional) action extravaganza Trio, starring Sylvester Stallone, Whoopi Goldberg, and Jackie Chan (all of whom appear in cameos--and undoubtedly regret it). The film's unctious producer (Ryan O'Neal) wrests control of the final edit from its director (Eric Idle), who wants his name removed from the project. The problem is, his name is Alan Smithee, and Alan Smithee is the Directors Guild-required pseudonym used for the director's credit whenever the true helmer wants his name removed. Apparently at a loss for options, Alan steals the only existing negative. What does he do with it? Three guesses (if you need a hint, read the movie's title again).
That's it. There's barely enough plot to fill the worst of Saturday Night Live sketches, let alone this movie's running time, which, at 83 minutes, is overlong by at least 82. But plot, or, for that matter, characters or witty dialogue, is of little concern to Eszterhas. Burn Hollywood Burn only exists to serve Eszterhas's own personal agenda, badmouthing just about everyone in the business (it's hard to tell who are his friends and who are his enemies--or is it that he just has no friends?). While this is certainly fun for Eszterhas, it is a torturous bore for the audience--unless there are some people who delight in the figurative sight of a shaggy, oversexed middle-aged man pleasuring himself. I'm all for wicked, mean-spirited humor--when it's funny. But nothing in Burn Hollywood Burn reaches even the snicker level. His idea of a running gag is identifying all the women as a "feminist" in the docu-style on-screen labels and repetitive jabs at former Creative Artists Agency head Michael Ovitz. And while I have never minded the inclusion of outtakes during a film's end credits, the blooper reel that closes Burn Hollywood Burn is so pointless and unamusing that I am seriously reconsidering my position on the practice.
(An Alan Smithee Film--) Burn Hollywood Burn is now truly an Alan Smithee film after director Arthur Hiller had his name removed. The scariest part of this story is that his original version of the film tested _worse_ than this final edit cobbled together by Eszterhas himself. Eszterhas has joked that this Burn Hollywood Burn is "the most expensive home movie ever made," and like all of his intentially humorous comments, it comes off as far from a joke. Burn Hollywood Burn plays just as he facetiously said--as an extended home movie that may be fun for its makers, "stars," and their friends and family to watch, but a leaden bore to anyone outside the circle. Burn, Eszterhas, burn.
Michael Dequina<EMAIL_ADDRESS>|<EMAIL_ADDRESS>|<EMAIL_ADDRESS><EMAIL_ADDRESS>|<EMAIL_ADDRESS><EMAIL_ADDRESS>|<EMAIL_ADDRESS>Mr. Brown's Movie Site: http://welcome.to/mrbrown Personal Page: http://welcome.to/w3md CinemaReview Magazine: http://www.CinemaReview.com
Michael Jordan Beyond the Court: http://fly.to/michaeljordan A Michael Jordan Fan's Heartbreak: http://fly.to/mj23
"I didn't know what to expect. It's like something you chase for so long, but then you don't know how to react when you get it. I still don't know how to react." --Michael Jordan, on winning his first championship in 1991 ...or, my thoughts after meeting Michael on November 21, 1997
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


We're sorry but templates doesn't work properly without JavaScript enabled. Please enable it to continue.


Part 1 showcases how to create a Ruby on Rails web stack for serving Rails pages. The tutorial is done with a Ubuntu 18.04 LTS Google Cloud virtual machine in mind
Stack tutorialOnce a virtual machine has all the necessary components installed, creating a Ruby application is a piece of cake!
Ruby Tutorial


Array Covariance in C#
When we first learn about inheritance, we’re given some plain-English examples with an emphasis on the phrase “is-a”. A car is-a vehicle, so a Car
class would inherit from a Vehicle
class. The idea that class inheritance can so directly map to English is seriously misleading and can get you into trouble.
In English, it’s fair to say that a bag of apples is-a bag of objects. It may have an odd sound to it, but it’s true. This makes it very tempting to say that in C#, a List<Apple>
should be assignable to a List<Object>
, since all Apple
instances are also Object
instances:
The sample above won’t compile. The compiler is protecting us from potential runtime type exceptions. If this compiled, we could get into trouble like so:
If this compiled, we would be able to attempt to put a string into a collection that simply does not support that operation. The English metaphor for inheritence (is-a) just doesn’t adequately match the actual constraints of the type system. We’re trying to violate the Liskov Substitution Principle. If we declared that List<Apple>
is a subtype of List<Object>
, we’d be saying that every operation that acts on a List<Object>
could be given a List<Apple>
, and that’s simply not true. In our example, the operations performed on the List<Object>
included putting new arbitrary objects into the list, and you just can’t do that to a List<Apple>
.
Because List<Apple>
has more constraints than List<Object>
, List<Apple>
is not assignment-compatible with List<Object>
.
Unfortunately, the previous example does compile when you replace List<T>
with supposedly-strongly-typed arrays. Instead of knowing that you’ve done something wrong at compile time, you get an exception at runtime:
Because TChild[]
can be assigned to TParent[]
for any TChild
inheriting from TParent
, we can say “arrays in C# are covariant”.
To sum up, List<Apple>
can’t be treated as List<Object>
because of the operations that List<T>
provides. The question, then, is could we ever safely take advantage of this convenient funky-casting for other generic types? The answer to this question falls under the category of “Covariance and Contravariance” and is provided by the C# 4 keywords in
and out
. In my next post, we’ll cover an example where this funky-casting is both convenient and safe.
Subscribe to our blog feed for the freshest content.


[Obsolete] Car factory by Matison55557
This is from a graphic that I did actually a while ago, but I just now made it a plugin.
It's a big car factory.
Very simple, because these big industrial buildings like this one usually don't have any details. I was inspired by a VW factory on the outskirts of my hometown.
It is 7x7, so if you will place the default 6x6 blocks of zones, it will not spawn. You have to make a zone of 7x7 square or bigger.
It is level 3 (TTT) and can give job to a whopping 2444 workers. I think it's way too much, to be honest. But what do you think about the building?
carfactory.png (31.8 KiB) Viewed 943 times
Google drive, because I can't upload the zip file for some reason:
Download


| test_dir {testthat} | R Documentation |
This function is the low-level workhorse that powers test_local()
and
test_package()
. Generally, you should not call this function directly.
In particular, you are responsible for ensuring that the functions to test
are available in the test env
(e.g. via load_package
).
test_dir( path, filter = NULL, reporter = NULL, env = NULL, ..., load_helpers = TRUE, stop_on_failure = TRUE, stop_on_warning = FALSE, wrap = lifecycle::deprecated(), package = NULL, load_package = c("none", "installed", "source") )
path |
Path to directory containing tests. |
filter |
If not |
reporter |
Reporter to use to summarise output. Can be supplied
as a string (e.g. "summary") or as an R6 object
(e.g. See Reporter for more details and a list of built-in reporters. |
env |
Environment in which to execute the tests. Expert use only. |
... |
Additional arguments passed to |
load_helpers |
Source helper files before running the tests?
See |
stop_on_failure |
If |
stop_on_warning |
If |
wrap |
DEPRECATED |
package |
If these tests belong to a package, the name of the package. |
load_package |
Strategy to use for load package code:
|
A list (invisibly) containing data about the test results.
There are two types of .R
file that have special behaviour:
Test files start with test
and are executed in alphabetical order.
Setup files start with setup
and are executed before tests. If
clean up is needed after all tests have been run, you can use
withr::defer(clean_up(), teardown_env())
. See vignette("test-fixtures")
for more details.
There are two other types of special file that we no longer recommend using:
Helper files start with helper
and are executed before tests are
run. They're also loaded by devtools::load_all()
, so there's no
real point to them and you should just put your helper code in R/
.
Teardown files start with teardown
and are executed after the tests
are run. Now we recommend interleave setup and cleanup code in setup-
files, making it easier to check that you automatically clean up every
mess that you make.
All other files are ignored by testthat.
Each test is run in a clean environment to keep tests as isolated as possible. For package tests, that environment that inherits from the package's namespace environment, so that tests can access internal functions and objects.


Before Change
switch_conf = config.get("switches", [config])
for switch in switch_conf:
if switch.get("host") is None:
_LOGGER.error("Missing required variable: host")
continue
host = switch.get("host")
After Change
switches = []
switch_conf = config.get(CONF_SWITCHES, [config])
if config.get(CONF_DISCOVERY):
_LOGGER.info("Discovering S20 switches ...")
switch_data.update(discover())
for switch in switch_conf:
switch_data[switch.get(CONF_HOST)] = switch
for host, data in switch_data.items():


--- layout: document title: Corporate Contributor License Agreement active: community body_class: cla permalink: cla/corporate/ ---


We are sorry to say, but the server has an error! If this persists longer that few minutes, please contact us:


--- title: Plotting of Pole Figures sidebar: documentation_sidebar permalink: PoleFigurePlot.html folder: documentation toc: false ---
This section describes various possibilities to visualize pole figure data. Lets start by loading some XRD data
{% highlight matlab %} mtexdata ptx {% endhighlight %} {% highlight plaintext %} saving data to /home/hielscher/mtex/master/data/ptx.mat pf = PoleFigure (xyz) crystal symmetry : mmm h = (104), r = 72 x 17 points h = (110), r = 72 x 17 points h = (202), r = 72 x 17 points {% endhighlight %}By default MTEX plots pole figures by drawing a circle at every measurement position of a pole figure and coloring it corresponding to the measured intensity.
{% highlight matlab %} plot(pf) mtexColorbar {% endhighlight %}MTEX tries to guess the right size of the circle in order to produce a pleasing result. However, you can adjust this size using the option MarkerSize.
{% highlight matlab %} plot(pf,'MarkerSize',4) mtexColorbar {% endhighlight %}Some people like to have their raw pole figures to be drawn as contour plots. This feature is not yet generally supported by MTEX. Note that measured pole figure may be given at a very irregular grid which would make it necessary to interpolate before drawing contours. In this case, however, it seems to be more reasonable to first compute an ODF and than to draw contour plots of the recalculated pole figures.
Nevertheless, MTEX offers basic contour plots in the case of regular measurement grids.
{% highlight matlab %} plot(pf,'contourf') mtexColorbar mtexColorMap parula {% endhighlight %}When drawing a colorbar next to the pole figure plots it is necessary to have the same color coding in all plots. This can be done as following
{% highlight matlab %} mtexColorbar % remove colorbars CLim(gcm,'equal'); mtexColorbar % add a single colorbar {% endhighlight %}In order to draw recalculated one first needs to compute an ODF.
{% highlight matlab %} odf = calcODF(pf,'silent') {% endhighlight %} {% highlight plaintext %} odf = SO3FunRBF (mmm → xyz) multimodal components kernel: de la Vallee Poussin, halfwidth 5° center: 29772 orientations, resolution: 5° weight: 1 {% endhighlight %}Now smooth pole figures can be plotted for arbitrary crystallographic directions.
{% highlight matlab %} plotPDF(odf,pf.h,'antipodal') mtexColorMap parula {% endhighlight %}


Juan Marin
- Open Source geospatial developer
- CTO @ OpenGeo
- Twitter: @jmarinotero
What is QGIS?
Q: So what can I do with it?
A: Pretty much everything you have been doing so far with your expensive proprietary software
Editing
Mapping
Data Management
Publish
OpenGeo Suite QGIS plugin
- Works with QGIS 2.0
- Integrates with:
- GeoServer
- GeoWebcache
- PostGIS
- Completely free and open source
- Available at http://qgis.opengeo.org/
Demo Time
(be gentle, this is cutting edge stuff)
We are hiring
QA Engineer
Android Software Engineer


BIOL 101/102/103/104 comprises the introductory biology sequence. Each course is half of a semester, and the general structure varies slightly depending on the professor. This sequence may be taken on-sequence (101/102 in the fall with 103/104 in the spring) or off-sequence (101/102 in the spring with 103/104 in the fall). In general, there are weekly problem sets, but quiz and exam structure depends on the professor.
{MB&B 300} It is expected that you have taken general chemistry and have general biology background prior to this course. It is often assumed that you have previous knowledge of organic chemistry. There are three midterms and a final exam. Make sure to utilize peer tutor sessions and office hours and take advantage of the study guides when reviewing for an exam.
There are no strict guidelines on which labs to take in correspondence to the biology courses, unlike chemistry courses and labs. There are a variety of biology labs that you can take at any time during your time at Yale, and all three biology majors (MCDB, MB&B, E&EB) host different labs that students can take to satisfy the biology lab requirement.
~ Use peer tutor office hours
~ Sign up for enrichment during the intro bio sequence if you feel like you have an inadequate biology background
~ Try to take at least one biology lab course in your freshman year (two if you can) to satisfy the requirement early and allow yourself more room and flexibility in your schedule in the future.
Royce Lee (PC21), Jaida Morgan (ES23)


Developer group
Get involved
If you are a developer interested in making code contributions, the easiest way to do so is to obtain a GIthub account, fork the source code of the specific component you would like to contribute to, and submit pull requests with any changes. Sana is an open source platform and community contributions are highly encouraged and appreciated.
You may also contact us directly at<EMAIL_ADDRESS>if you are interested in participating.


Check-In\Check-Out App
*EMPLOYEE CHECK-OUT
Name:
Find User
User has not checked in Yet
Name
Manager
contact
Location
Time In
{{siso.fname}} {{siso.mname}}, {{siso.lname}}
{{siso.mfname}}, {{siso.mlname}}
{{siso.contact}}
{{siso.location}}
{{siso.time}}
Check-Out
User has checked out


npm install dataway
yarn add dataway
Dataway
is a datastructure representing the four possible states of a remote datasource fetching result.
This aims to solve a classic data management issue often handled either through booleans or complex, unwanted and polluted states. With one entry point and only 4 strongly-typed states, remote data handling becomes much cleaner.
Dataway also provides a great api to manipulate, transform and aggregate Dataway values in a safe and optimistic way. This reduces bug and crash occurence while making your code simpler to read.
Imagine that our application relies on a webservice that provides us with a list of elements, and that our job is to both store the number of elements in the application state for future usage and to display it.
import { fold, notAsked, loading, failure, success } from "dataway";
import stateManager from "./statemanager";
const appElement = document.getElementById("list");
const loadButton = document.getElementById("load-button");
const view = state => {
appElement.innerHTML = fold(
() => "
Click on the load button
",
() => "
Loading
",
error => `<p>something wrong did happen : ${error}</p>`,
success => `<ul>${success.map(post => `
${post.title}
`)}</ul>`,
state
);
};
const setState = stateManager(view, notAsked);
loadButton.onclick = event => {
setState(loading);
setTimeout(
() =>
fetch("https://jsonplaceholder.typicode.com/posts")
.then(response => {
if (response.ok) {
return response.json();
} else {
return Promise.reject(
`Request rejected with status ${response.status}`
);
}
})
.then(json => setState(success(json)))
.catch(error => setState(failure(error))),
2000
);
};
First you have to create some Dataway
values using notAsked
, loading
, failure(error)
, success(value)
import { notAsked, failure, success } from 'dataway'
const foo = success('Mr Wilson');
const bar = failure('any suited error value');
const baz = notAsked;
Then we can use the provided map
api to apply a function on any Success
variance of Dataway
, wrapping automatically the result in a new Success
.
If the provided variance of Dataway
is not a Success
, it will be returned without change, and without executing the function.
As a developper it means you do not have to check for Dataway
variance before applying a function to its Success
value.
const { notAsked, failure, success, map } = require('dataway');
map(value => value.toUpperCase())(success('Mr Wilson'));
// => Success "MR WILSON"
map(value => value.toUpperCase())(failure('any suited error value'));
// => Failure "any suited error value"
map(value => value.toUpperCase())(notAsked);
// => NotAsked
Rewrapping the transformed value in a Success
or returning the other variance untouched, allows to transform a Dataway
value in multiple distinct step wihout risking runtime error due to unexistant values (null | undefined
) while keeping the variance of Dataway
intact.
const { notAsked, success, map } = require('dataway');
const upperCasedSuccess = map(value => value.toUpperCase())(success('Mr Wilson'));
map(value => value.split(' '))(upperCasedSuccess);
// => Success ['MR', 'WILSON']
const foo = map(value => value.toUpperCase())(notAsked);
map(value => value.split(' '))(foo);
// => NotAsked
To extract and use the Success
value you must use the fold
API.
The following example illustrates how this forces you to consider the four different UIs each state implies.
const { success, failure, notAsked, loading, map, fold } = require('dataway');
// => Success ['MR', 'WILSON']
const render = dataway => fold(
() => "
Click on the load button
",
() => "
Loading
",
error => `<p>something wrong did happen : ${error}</p>`,
success => `<p>${success}</p>`,
dataway
);
render(success('Mr Wilson'));
// =>
Mr Wilson

render(failure('Ooops failed to fetch Mr Wilson data'));
// =>
something wrong did happen : Ooops failed to fetch Mr Wilson data

render(notAsked);
// => '
Click on the load button
'
render(loading);
// => '
Loading
'
This is really great to easily create consistent UIs.
Dataway
offers a rich API to aggregate multiple "dataways" or to handle computation failure on your dataway values.
Dataway
is written in typescript with thoughtful type description, enabling you to use it in a typescript environnement without hassle while keeping great type safety.
Dataway
also offers compatibility with great libraries such as Ramda, and fp-ts
You can check and play with several examples
Generated using TypeDoc