cleanups added by me.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@10442 c06c8d41-db1a-0410-9941-cceddc491573
T3R2D5M4YSC6NFZ6YO3AEG4VWORECX72CHUM5UBADV4UPAAZG7WQC RQUK5MTEO75EINGOW75UCH463UZVCQXJA3WG4YTUGYTDHN2ORYTAC JLPJ6G5QJTAHFF5RINBFO4UBV44WD5FVTPOO5RGLMIRILRKGTA6AC EXPQHDUJDH3J47STNSABE3SNNZWCVRSMANAZVBYQY3W7E2KQUP7AC KIAIGHATPEOUGEWQXS2IR4635E53WPEENC5UJ3I3MASTJ7SHBU5AC FW3PIRSTFPX7VNUAVASCBB7VPYJHGPRSHXC4S6RXCLSLJMGWS6QQC SDZYI64673GM344DHCDQSWOJTX7EVW6VXRYA7DHGFVNYR5J5RYGQC IXO5VNCDYDYI46Y5QWNJMD7TURKYO526CJA4TIMH5PDDAYHMK5YQC MONYKYOVBBZBJQNDH4QNDCC4TKFPTGTDVTYWVSC24K7DGOMJ7MEQC A6DIDV2RENPSX6CQ7NJMTDPPGRLQXMPLX3WXLZUG4QTCZHLUSFIQC 5WVUTEZLEZEML54CKPR6GACQBYY3EMVNXMLJOREN6SSEUZGC47AQC RDS3NSFOLBAEGHBFEQ4TODN5QSJ2DLDM2SIVVUMA6IVRHAZLRVKQC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC PFEJ4LMDNEKLMGRCMWQ7EIRVU4JMYGICI4G7X4WVWOROVXQCBZ7QC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC DKISJVKAJJK2SVZSXGJ37K5SOVTDARVX6RPK3MAKVNGC36Z4YAZQC UU5JLKAKZSTWFQJLUTPQZJ3ZQY7BEU2KROZETUNSKC6LFG6XVSZQC NDKS43E4XVAU3FDY276OF5JW7E5SF6F5EJD2XLV5JLKZ5W6N554QC KHYL5UOMGS7HLVEQNVIOYWNP2ZH2THKZ5CGGIZFI6NN5V2YD3YEAC SA36K3OJ75PNVR2F4QAPNU2LUGFTVHNIAZVSXCBXBT2NLW2RTUPAC NJW656RNYNY7VZVOK52U3U5AVJR2E33N4I4KBEEJY3MZIPG35QCAC SQFABNVS6OSVRBMJAIV6KIIZW2TYIOQ5BZGLPYJ6BPFD2HMRH4MAC UFKLHUYL7WAQ3CI3D42T4C6KBGAUR63DSQAUQTTZG7GJMXSCVJWAC I2ZR5QRPQEDTO5V5ILIJUA5KIEOGJY3BRHRNPXS5BJG7GXTBXJSQC 4A3Y2BLAYXUFAAT6EK5GYT5ZIMQXQX64ZVJCKNPGEZY7IGTUWWIAC ENQRCBNN7MKP6FFQAZ62FYXEVWCRJB5747LTYMZGRGINXQL6HT5AC IGNQ3YSGMW6NG7GPYYXWXW6XPM4YWKNUJ5IU55QCWZ2AEHHO3L3QC GK6AOQQV6RU2F6FQRT6O62FD633MH6SQNPLRL4U3KQ6UMXX6UQLQC B47CVG54WZNP3CQ7HOTKTWQA26GCOIKQADX2EK4ZOEYRRQ4T5W2AC JEW6ECARJC535IBLAUTKDKRRMRX26MRH3PHR3XWICCCBYWRTWLYAC NLQNXH3SVJ52CWXEV35FSSZP32VHC4QFGN3HINF4KO5GZHZMOBKQC CQD3RU44235F3CYFDZBC3JRT2H3AE7PXJNVBBMCRF65Q5LPA3EHQC OWERGKLVPNPGIIS23FZ7ZDOBWUIXCKYAFG3URXU75JAUDX3N5ENAC 6PAG7GHXHIYXJPPTEK4KZQZT4CL2SJDAGTVIUDB4KK66PVSTWUMAC IYMUEJG2VI3TV7HVAZIU2L4DVQY7VNSIFVV4I3QIVP7H66EVJISAC F2X5SIIXWXXEL2FVMYDC4GL2ODZ4O7RA46U66VGJ5K2EZHHAQGUAC U3KGUJJQWQORJIIFH3ADVNIEEX5HOX6KEOXO7DJSL7L3Z6GG3PAQC LOC46PHUFJ3MDWOYUEH4R24TGGE4ADG7C44O2ZNB4EBF2YD6VX7QC 4RWYH3CQPAAOK2OM2POLRTY6A5CPHYZJ4B55VAVSCWTSCOPWMF6AC ASH5CK6CPBKMLGGIRJ5GKTWMS5W3OBVHTL66RTYZIPFM6KFBYA3QC B4YYKEZVHLGRFAHEP5ATEV4MYRPGXQPWTUXGGG7ITZH3ZGV3VMBQC AA5RRYINGLYJHZNRSQUHI6K4GIT4KZBFRFZ43EJJPOMJAMXWULMAC KZWOHH536QBWAPWROR32EOXEK5LRY6I5VHVL7HHI7GOFKCMQTCSQC OONYLF4DAPLIYLBNNRW74IVT5BBTWI4XHQBXSNSPVRX3FTKJBTRAC HIRKGUMNJPWKSVTR6TVBPD3MWNA63CEHCLCIPWEMGDFHVB3NPLDQC UADYVV3UD5ERJTZZJGY4EUQ4NJ2JSBG7YYUJ75ZRBIXRQXQKOJPAC SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC 7YUGK5Q64KG5O7GJGTUBRRLHAHBCJ5YOE23YUPT6UBKUSB67CYAQC TWYB52EBZRZEABTKQ7D6OWKMDKIGACWDUGNH5LP47QX4SKC3SFYAC FAVME2A2U4OUKN2BTISAG5PCI5Y4BN6YVFKCSQQHHZLEVVVF4LKAC S2FTVAH7NLTLI5CEINIAMJIW3PTZUE22APSK633Y4PLDZ4L6UK4QC stop_running();}}}void feawn_neutralise(monsters* monster){if (you.religion == GOD_FEAWN && mons_is_plant(monster)&& !mons_is_summoned(monster)&& !mons_wont_attack(monster)&& !testbits(monster->flags, MF_ATT_CHANGE_ATTEMPT)){if (!player_under_penance()){// We must call remove_auto_exclude before neutralizing the// plant because remove_auto_exclude only removes exclusions// it thinks were caused by auto-exclude, and// auto-exclusions now check for ATT_HOSTILE. Oh, what a// tangled web, etc.remove_auto_exclude(monster, false);monster->flags |= MF_ATT_CHANGE_ATTEMPT;feawn_neutralise_plant(monster);
void corpse_spores()
// Destroy corpses in the player's LOS (first corpse on a stack only)// and make 1 giant spore per corpse. Spores are given the input as// their starting behavior; the function returns the number of corpses// processed.int corpse_spores(beh_type behavior)
// Remove the original plant.// XXX: Why do we destroy the old and create a new plant// rather than simply upgrade the old plant?monster_die(current_plant, KILL_MISC, NON_MONSTER, true);
rc = create_monster(mgen_data(new_species,BEH_FRIENDLY, 0, 0, target_square,MHITNOT, MG_FORCE_PLACE, GOD_FEAWN));
current_plant->upgrade_type(new_species, true, true);current_plant->god = GOD_FEAWN;current_plant->attitude = ATT_FRIENDLY;current_plant->flags |= MF_CREATED_FRIENDLY;
case GOD_ZIN: // in contrast to TSO, who doesn't mind martyrs
case GOD_ZIN:// Converted allies (marked as TSOites) can be martyrs.if (victim->god == GOD_SHINING_ONE)break;case GOD_FEAWN: // plant god only cares about plantsif (!mons_is_plant(victim))break;
// to be implemented -CAO
const god_type god = GOD_FEAWN;// We have 3 forms of retribution, but players under penance will be// spared the 'you are now surrounded by oklob plants, please die' one.const int retribution_options = you.religion == GOD_FEAWN ? 2 : 3;switch (random2(retribution_options)){case 0:// Try and spawn some hostile giant spores, if none are created// fall through to the elemental miscast effects.if (corpse_spores(BEH_HOSTILE)){simple_god_message(" produces spores.", GOD_FEAWN);break;}case 1:{// Elemental miscast effects.simple_god_message(" invokes the elements against you.", GOD_FEAWN);spschool_flag_type stype = SPTYP_NONE;switch (random2(4)){case 0:stype= SPTYP_ICE;break;case 1:stype = SPTYP_EARTH;break;case 2:stype = SPTYP_FIRE;break;case 3:stype = SPTYP_AIR;break;};MiscastEffect(&you, -god, stype, 5 + you.experience_level,random2avg(88, 3), "the wrath of Feawn");break;}case 2:// We are going to spawn some oklobs but first we need to find// out a little about the situation.std::vector<std::vector<coord_def> > radius_points;collect_radius_points(radius_points,you.pos(),env.no_trans_show);unsigned free_thresh = 30;mgen_data temp(MONS_OKLOB_PLANT,BEH_HOSTILE, 0, 0,coord_def(),MHITNOT,MG_FORCE_PLACE,GOD_FEAWN);// If we have a lot of space to work with (the circle with// radius 6 is substantially unoccupied), we can do something// flashy.if (radius_points[5].size() > free_thresh){int seen_count;temp.cls = MONS_PLANT;place_ring(radius_points[0],you.pos(),temp,1, radius_points[0].size(),seen_count);temp.cls = MONS_OKLOB_PLANT;place_ring(radius_points[5],you.pos(),temp,random_range(3, 8), 1,seen_count);}// Otherwise we do something with the nearest neighbors// (assuming the player isn't already surrounded).else if (!radius_points[0].empty()){unsigned target_count = random_range(2, 8);if (target_count < radius_points[0].size())prioritise_adjacent(you.pos(), radius_points[0]);elsetarget_count = radius_points[0].size();unsigned i = radius_points[0].size() - target_count;for(; i < radius_points[0].size(); ++i){temp.pos = radius_points[0].at(i);temp.cls = coinflip() ?MONS_WANDERING_MUSHROOM : MONS_OKLOB_PLANT;create_monster(temp,false);}god_speaks(god, "Plants grow around you in an ominous manner.");return (false);}}
}return (true);}return (false);}static bool _feawn_plants_on_level_hostile(){for (int i = 0; i < MAX_MONSTERS; ++i){monsters *monster = &menv[i];if (monster->alive()&& mons_is_plant(monster)){#ifdef DEBUG_DIAGNOSTICSmprf(MSGCH_DIAGNOSTICS, "Plant hostility: %s on level %d, branch %d",monster->name(DESC_PLAIN).c_str(),static_cast<int>(you.your_level),static_cast<int>(you.where_are_you));#endif// You can potentially turn an oklob or whatever neutral// again by going back to Feawn.if (testbits(monster->flags, MF_ATT_CHANGE_ATTEMPT))monster->flags &= ~MF_ATT_CHANGE_ATTEMPT;monster->attitude = ATT_HOSTILE;monster->del_ench(ENCH_CHARM, true);behaviour_event(monster, ME_ALERT, MHITYOU);// For now WAS_NEUTRAL stays.
static bool _feawn_plants_on_level_neutral(){for (int i = 0; i < MAX_MONSTERS; ++i){monsters *monster = &menv[i];feawn_neutralise_plant(monster);}return (true);}static bool _feawn_plants_neutral(){if (apply_to_all_dungeons(_feawn_plants_on_level_neutral)){mpr("The plants of the dungeon cease their hostilities." , MSGCH_GOD);return (true);}return (false);}
}void feawn_neutralise_plant(monsters *plant){if (plant->type != MONS_OKLOB_PLANT&& plant->type != MONS_WANDERING_MUSHROOM&& !testbits(plant->flags, MF_ATT_CHANGE_ATTEMPT)){return;}if (you.can_see(plant)){mprf(MSGCH_GOD, "%s ignores you.",plant->name(DESC_CAP_THE).c_str());}plant->attitude = ATT_GOOD_NEUTRAL;plant->flags |= MF_WAS_NEUTRAL;
return (mons_genus(species) == MONS_JELLY|| mons_genus(species) == MONS_GIANT_EYEBALL|| species == MONS_GIANT_SPORE|| species == MONS_GIANT_ORANGE_BRAIN);
return (mons_class_is_slime(species));case GOD_FEAWN:return (mons_class_is_plant(species));
// fight back.if (mons_class_flag(mon->type, M_NO_EXP_GAIN))
// fight back, so don't bother having them do so. If you// worship Feawn, create a ring of friendly plants, and try// to break out of the ring by killing a plant, you'll get// a warning prompt and penance only once. Without the// hostility check, the plant will remain friendly until it// dies, and you'll get a warning prompt and penance once// *per hit*. This may not be the best way to address the// issue, though. -caoif (mons_class_flag(mon->type, M_NO_EXP_GAIN)&& mon->attitude != ATT_FRIENDLY){
return (mons_genus(mon->type) == MONS_JELLY|| mons_genus(mon->type) == MONS_GIANT_EYEBALL|| mons_genus(mon->type) == MONS_GIANT_ORANGE_BRAIN);
return (mons_class_is_slime(mon->type));}// Monsters Feawn cares about - plants and fungi except for giant spores// and toadstools.bool mons_class_is_plant(int mc){return (mc != MONS_GIANT_SPORE&& mc != MONS_TOADSTOOL&& (mons_genus(mc) == MONS_PLANT|| mons_genus(mc) == MONS_FUNGUS));}bool mons_is_plant(const monsters *mon){return (mons_class_is_plant(mon->type));
// Place a partial ring of toadstools around the given corpse. returns the// number of mushrooms spawned. A return of 0 indicates no mushrooms were// placed -> some sort of failure mode was reached.static int _mushroom_ring(item_def &corpse, int & seen_count)
int place_ring(std::vector<coord_def> & ring_points,coord_def & origin,mgen_data & prototype,int n_arcs,int arc_occupancy,int & seen_count)
// minimum number of mushrooms spawned on a given ringunsigned min_spawn = 2;
int target_amount = ring_points.size();int spawned_count = 0;seen_count = 0;std::vector<int> arc_counts(n_arcs, arc_occupancy);for (unsigned i = 0;spawned_count < target_amount && i < ring_points.size();i++){int direction = _arc_decomposition(ring_points.at(i)- origin, n_arcs);
// larger radii.// Generally we will visit points in order of distance to the origin// (not path distance) under distance=sqrt(x^2+y^2-1);
// larger radii. We will visit points in order of increasing euclidean// distance from the origin (not path distance).
fringe.pop();int idx = current.first.x + current.first.y * X_WIDTH;if (!visited_indices.insert(idx).second)continue;// we're done here once we hit a point that is farther away from the
// We're done here once we hit a point that is farther away from the
// We don't include radius 0 as an option. This is also a good place// to check if the squares is already occupied since we want to search// past occupied squares but don't want to place toadstools on them.if (bound > 0 && !actor_at(current.first))
while (current.second > current_thresh)
// We don't include radius 0. This is also a good place to check if// the squares are already occupied since we want to search past// occupied squares but don't want to consider them valid targets.if (current.second && !actor_at(current.first))radius_points[current_r - 1].push_back(current.first);
// Don't link to nodes with a smaller absolute distance from the// origin than the current node. This is some sort of connectivity// constraint, in general we don't want parts of a ring to be// connected via a higher radius since rings were supposedly// created by outwards expansion.if (temp.second < max_visited)continue;
temp.second = local.abs();
}// Place a partial ring of toadstools around the given corpse. Returns// the number of mushrooms spawned. A return of 0 indicates no// mushrooms were placed -> some sort of failure mode was reached.static int _mushroom_ring(item_def &corpse, int & seen_count){// minimum number of mushrooms spawned on a given ringunsigned min_spawn = 2;
int chosen_idx = random2(max_radius);// Excluding radius 1 rings because they don't look particularly good// (or at least they don't look good with target_arc_len=2sqrt(2)// they look ok with arc_len=2, but that doesn't seem very good for// higher radii, maybe there should be a more complicated relationship// between radius and target arc length, but whatever).int min_idx=1;for (int i = 2; i < max_radius; i++, chosen_idx++)
unsigned max_size = 0;for (unsigned i = 0; i < LOS_RADIUS; ++i)
int mushrooms_per_arc = 1;std::vector<int> arc_counts(n_arcs, mushrooms_per_arc);for (unsigned i = 0;spawned_count < target_amount && i < radius_points[chosen_idx].size();i++){int direction = _arc_decomposition(radius_points[chosen_idx].at(i)- origin.first, n_arcs);if (arc_counts[direction]-- <= 0)continue;
const int mushroom = create_monster(mgen_data(MONS_TOADSTOOL,BEH_HOSTILE, 0, 0,radius_points[chosen_idx].at(i),MHITNOT,MG_FORCE_PLACE,GOD_NO_GOD,MONS_PROGRAM_BUG,0,corpse.colour),false);
int spawned_count = place_ring(radius_points[chosen_idx], corpse.pos, temp,n_arcs, 1, seen_count);
if (mushroom != -1){spawned_count++;if (see_grid(radius_points[chosen_idx].at(i)))seen_count++;}}return spawned_count;
return (spawned_count);
// Try to spawn 'target_count' mushrooms around the position of 'corpse'.// Returns the number of mushrooms actually spawned.// Mushrooms radiate outwards from the corpse following bfs with 8-connectivity.// Could change the expansion pattern by using a priority queue for// sequencing (priority = distance from origin under some metric).
// Try to spawn 'target_count' mushrooms around the position of// 'corpse'. Returns the number of mushrooms actually spawned.// Mushrooms radiate outwards from the corpse following bfs with// 8-connectivity. Could change the expansion pattern by using a// priority queue for sequencing (priority = distance from origin under// some metric).
// Randomly decide whether or not to spawn a mushroom over the given corpse// Assumption: this is called before the rotting away logic in update_corpses.// Some conditions in this function may set the corpse timer to 0, assuming// that the corpse will be turned into a skeleton/destroyed on this update.
// Randomly decide whether or not to spawn a mushroom over the given// corpse. Assumption: this is called before the rotting away logic in// update_corpses. Some conditions in this function may set the corpse// timer to 0, assuming that the corpse will be turned into a// skeleton/destroyed on this update.
// Worshippers of Feawn may shoot past friendly plants.if (!is_explosion && !is_enchantment()&& this->attitude == ATT_FRIENDLY&& you.religion == GOD_FEAWN&& mons_genus(mon->mons_species()) == MONS_PLANT&& mon->mons_species() != MONS_GIANT_SPORE&& mon->attitude == ATT_FRIENDLY)
// Feawn worshippers can fire through monsters of the same alignment.// This means Feawn-worshipping players can fire through allied plants,// and also means that feawn worshiping oklob plants can fire through// plants with the same attitude.bool originator_worships_feawn=false;// Checking beam_source to decide whether the player or a monster// fired the beam (so we can check their religion). This is complicated// by the fact that this beam may in fact be an explosion caused by a// miscast effect. In that case the value of beam_source may be negative// (god induced miscast) or greater than NON_MONSTER (various other miscast// sources). So we check whether or not this is an explosion, and also the// range of beam_source before attempting to reference env.mons with it.// -caoif (!is_explosion && this->beam_source == NON_MONSTER)originator_worships_feawn = (you.religion == GOD_FEAWN);else if (!is_explosion && beam_source >= 0 && beam_source < MAX_MONSTERS)originator_worships_feawn = (env.mons[beam_source].god == GOD_FEAWN);if (!is_enchantment()&& attitude == mon->attitude&& originator_worships_feawn&& mons_is_plant(mon))
simple_god_message(" protects your plant from harm.", GOD_FEAWN);
{// FIXME: Could use a better message, something about dodging that// doesn't sound excessively weird would be nice.mprf(MSGCH_GOD, "Feawn protects %s plant from harm.",attitude == ATT_FRIENDLY ? "your" : "a");}
// We'll say giant spore explosions don't trigger the ally attack conduct// for Feawn worshipers. Mostly because you can accidentally blow up a// group of 8 plants and get placed under penance until the end of time// otherwise. I'd prefer to do this elsewhere but the beam information// goes out of scope. -caoif (you.religion == GOD_FEAWN && flavour == BEAM_SPORE)conducts[0].enabled = false;