added, with the shaft traps changed as per comments on SF; shafts aren't randomly generated yet, so this doesn't change gameplay. Changed DNGN_TRAP_III to DNGN_TRAP_NATURAL, of which trap type the shaft traps are the only current member.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@2328 c06c8d41-db1a-0410-9941-cceddc491573
AVCMVFA3MKCXHO6H44UK5KJNIHTGQV7UA7GYXM26VI6TXXU5ZN6QC RC5SAVDRSD6X75HG3SEEFC444LXYMHASQFLOJMH6D6VTYHBQAJEQC WDEFQ6YABDQIGJXW5KT3OGR3EO6FZHXZELIRVIXQ4XDYTVOV5V6AC TTHOIZMSG2GWUO5IQWOPYK5V5DS6HIPD7ULFI6P6E7LQ6MMKPMHAC IVVRQ52VA3MAD25ZMPID3GCRBBFYR54CH33DKXYTRAGUBLTRAZNAC FMSYEPHQUC3RGEOEJ77OZ43JTIFITY56SOOKYPU4CKAVB4VP65FAC JM7UAK777RAVDAVLQLEOBRTGNW2B47S5G55XITJXO243IUNZHVYQC Z6Q7JVMFQ32SC7FRGOB7CE7JS2HEOPAO3B2VLU3YR3UCUDZFIPFQC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC 5ASC3STDYCNLZFEBN6UTMUCGDETHBR2OCBZCF5VIAZ5RRWLOTDYQC 7AMQN7MITMXBNVDAK5VOXTQ4TZIAOD6ZLOFJG7GQMBTY23Y2BKSAC DOZORMA366M4HB5JKSS27BMCR6ET7QNZNND2B7KV3NVEEPR5H7EAC QDTVLBRGHDTRUVT7I3O72K6TMOYAUSAJBZUHGOEFU2RKJNUPWZSQC R22TTMI6WXWULC7ODKFF3QCB7MOTETQQ6IR4BUCUPOCQKQNCTT5AC I2B33Z7NZGC33AMDSSK446AZZYWKPHWLAGULVHKKZU4MVB4BNJOAC P2ZCF3BBG523ZEOD6XQA4X5YEHBTWH3IM33YVHXP2SQ5POXZIH4QC SJOTTUZMA3UTGT5D6LKUTBDP2CZFXT24FB5IAWCUFHSHLLACM75QC 6RJVKSL7RVZIZIZIC4TWIYJQ24RUSB346ODS3NYGDHUIRTC4Z5FQC 7ZMJTRJP6PQW4OLFDNTYLMVAZLYQ3IEBIQZVBZN2BSRJEADHUZ7AC PM2AFCUMNJD4UBWQ4GQPETHSE4T2C75JB5B4RHN3DBD6KTX3VBLQC PTB7I4WQ3NTF7BE3O6WKXDSJD6QRWSZIEWPBSZGCJJZVNKT4OL5AC 5UVDIVD4NSXA52U4QMQIVST3GSZJ2A2YZK3RUEXKPM43YVQ7LI5AC 7Y5HSDFKA5TPLS2TWTRFMQVX6UXUDHXU5MUMXQSDFAIY4THQ3BIQC GACH6PWPGGUBEE7PFEPQMOZKSR7HTQGL2WLGF2AQPJD3FCCSKZNQC FLKXPXQ7SRFZPJPDM35D5CG6M52WP4SL32QNEZNSHGBNZYTKYGYAC ILOED4VB4I6VPAUTR75ZWX6MXDYXB5DO2EDK2UH67O3HNKWV23RQC NNG27Y5ZQAZX6UD7F7M4F6KEZBEDFXPEEC3LFUSX4ESKT7K6UJQAC T2AYVN57EFJQLFUFLAZDXKDAFDGTDLQIEQWQZNYFWJZBYSTYH4QQC UZ6N6HOUPGVSPC5NQROEEDWMEGJA5XUWUY2AKH5QG65AZ25PVXDAC 3PY3L3A4QRW3Z5Y7SHO4TMVOOP2VNCO27X2MX4DTOP2SADLBQUOAC T4IH76FA5TWHFOZUJFHLQXQJENJHWTUZZP4EGNA7D4GTZY7D4ZKAC W5VEC2PBIM5DMU5233HOWAZUEPTGWJRZZIA3H35YYQQW6BTP6XUAC GQL5SIGBHLU3FMCE54XVGLRY5AZHRM6DUEB722REA2DPLGJSN6EQC UDYVF65OZSNPANLHDI3ODBEGUAKAVZ4KH4OZFAKR2CQJPO4AXU6QC AUXHSGS4EFOPZ6TVZYWNVOUDO7NYKUKE3HBKGQQWTALSVFOE3HAAC IVVTHLTTLOP5TSULXJWUSSXHOKYWVU3OWKYVK45A7RIB6V34MYQAC ZP2KE7A2LE7Z2S7AC45WE4CXDSEVDTWIMV2EM4IBUKXYJIDU6R7QC KFULGQQOHWUTXOM3BXCCYPGGVGGY4Z6265XUFRCBPNLTZAEHJZSQC 7KWDC7XFNMBLSUO2HISIROBINZBX5T67LJEEXTAORXW2YZ7VWFGAC HH3HFWVXABJ4IRMN22PPJCREMULZSN6DA7VYKOGECGMNUQTZ5QNQC CDKRLJIGVWQE2PMHCSLJBLYQEK7JYC4LQM7H2X3O6NMJMCCDRVIAC IIN7AVA6JYRBXH6ZYRR7BY7TV6PW7ANAQ2A3PD55FKBKKQFEEF2AC TLO257LZSB6ZO36STDUEWJBO2LETXFKTFGXELA6Y4BZBVAEIIINAC 4UXFU3FZOCBSLDQ4S7MJKAE2H7VUHCNRDQMIY6NJ3PHYXWNGISDQC JDM27QE4HR52AYFSQE763BFF57ANOTF5MXKMO377PP5EXMN7SAOAC I7QLYOTE6DLQZM7YWUWYLKHRJRB2A3STQ42ALSRGQICEWKD2QTEQC 6HG6JFO47Y3BZLU7Y6G3R2CX6JFGN4X5PKK6S5IGUXUYQ5GVZYFQC KKROXTUPBNEXXEUUDJNADATK3BCQPSQWFZ6L4VTKBPTYXJLYUHDQC TZ55IZNANEJO2WDTKYWVLY2W2VV6BR7WKIN7XLNISAMMFT6LG2WQC WWR4IDWLXP4XLBWDZBA5GFG7CRKUJQNRK7FFUFOISK6OJTMYQPFQC 77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC 3YK4G4IQBXW63HPGU5WRTV6L2FCMKAK4DOTCHFK2FNSB5B3Y3PVQC // If we don't trigger the shaft, and the player doesn't// already know about it, don't let him/her notice it.case TRAP_SHAFT:{// Paranoiaif (!is_valid_shaft_level()){if (trap_known);mpr("The shaft disappears in a puff of logic!");grd[env.trap[i].x][env.trap[i].y] = DNGN_FLOOR;env.trap[i].type = TRAP_UNASSIGNED;return;}if (!you.will_trigger_shaft()){if (trap_known && !you.airborne())mpr("You fail to trigger the shaft.");if (!trap_known)grd[you.x_pos][you.y_pos] = DNGN_UNDISCOVERED_TRAP;return;}if (!you.do_shaft())if (!trap_known){grd[you.x_pos][you.y_pos] = DNGN_UNDISCOVERED_TRAP;return;}break;}
{}bool actor::will_trigger_shaft() const{return (!airborne() && total_weight() >= 300&& is_valid_shaft_level());}level_id actor::shaft_dest() const{if (you.level_type != LEVEL_DUNGEON)return level_id::current();level_id lev = level_id::current();int curr_depth = subdungeon_depth(you.where_are_you, you.your_level);lev.depth += ((pos().x + pos().y) % 3) + 1;if (lev.depth > your_branch().depth)lev.depth = your_branch().depth;if (lev.depth == curr_depth)return lev;// Only shafts on the level immediately above a dangeorus branch// bottom will take you to that dangerous bottom, and shafts can't// be created during level generation time.if (your_branch().dangerous_bottom_level&& lev.depth == your_branch().depth&& (your_branch().depth - curr_depth) > 1){lev.depth--;}return lev;}bool actor::airborne() const
return (attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON ||attribute[ATTR_TRANSFORMATION] == TRAN_BAT ||duration[DUR_LEVITATION]);
return (duration[DUR_LEVITATION]);
}int player::body_weight() const{if (attribute[ATTR_TRANSFORMATION] == TRAN_AIR)return 0;int weight;switch(body_size(PSIZE_BODY)){case SIZE_TINY:weight = 150;break;case SIZE_LITTLE:weight = 300;break;case SIZE_SMALL:weight = 425;break;case SIZE_MEDIUM:weight = 550;break;case SIZE_LARGE:weight = 1300;break;case SIZE_BIG:weight = 1500;break;case SIZE_GIANT:weight = 1800;break;case SIZE_HUGE:weight = 2200;break;default:mpr("ERROR: invalid player body weight");perror("player::body_weight(): invalid player body weight");end(0);}switch(attribute[ATTR_TRANSFORMATION]){case TRAN_STATUE:weight *= 2;break;case TRAN_LICH:weight /= 2;break;default:break;}return (weight);}int player::total_weight() const{return (body_weight() + burden);
if ( !is_levitating() )return (FL_NONE);else
if (attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON ||attribute[ATTR_TRANSFORMATION] == TRAN_BAT){return FL_FLY;}else if (is_levitating())
if (!is_valid_shaft_level())return (false);// Handle instances of do_shaft() being invoked magically when// the player isn't standing over a shaft.if (trap_type_at_xy(x_pos, y_pos) != TRAP_SHAFT){switch(grd[x_pos][y_pos]){case DNGN_FLOOR:case DNGN_OPEN_DOOR:case DNGN_TRAP_MECHANICAL:case DNGN_TRAP_MAGICAL:case DNGN_TRAP_NATURAL:case DNGN_UNDISCOVERED_TRAP:case DNGN_ENTER_SHOP:break;default:return (false);}if (airborne() || total_weight() == 0){mpr("A shaft briefly opens up underneath you!");return (true);}force_stair = DNGN_TRAP_NATURAL;}down_stairs(your_level, force_stair);return (true);}
///////////////////////////////////////////////////////////void set_level_annotation(std::string str,level_id li = level_id::current());void clear_level_annotation(level_id li = level_id::current());std::string get_level_annotation(level_id li = level_id::current());bool level_annotation_has(std::string str,level_id li = level_id::current());
}bool notes_exist = false;bool has_notes[NUM_BRANCHES];for (int i = 0; i < NUM_BRANCHES; ++i){Branch branch = branches[i];has_notes[i] = false;for (int depth = 1; depth <= branch.depth; depth++){const level_id li(branch.id, depth);if (get_level_annotation(li).length() > 0){notes_exist = true;has_notes[i] = true;break;}}
if (notes_exist){disp += "\n\n <white>Level Annotations</white>\n" ;for (int i = 0; i < NUM_BRANCHES; ++i){if (!has_notes[i])continue;Branch branch = branches[i];disp += "\n<yellow>";disp += branch.shortname;disp += "</yellow>\n";for (int depth = 1; depth <= branch.depth; depth++){const level_id li(branch.id, depth);if (get_level_annotation(li).length() > 0){char depth_str[3];sprintf(depth_str, "%2d", depth);disp += "<white>";disp += depth_str;disp += ":</white> ";disp += get_level_annotation(li);disp += + "\n";}}}}
////////////////////////////////////////////////////////////////////////void set_level_annotation(std::string str,level_id li){if (str == ""){clear_level_annotation(li);return;}level_annotations[li] = str;}void clear_level_annotation(level_id li){level_annotations.erase(li);}std::string get_level_annotation(level_id li){annotation_map_type::const_iterator i = level_annotations.find(li);if (i == level_annotations.end())return "";return (i->second);}bool level_annotation_has(std::string find,level_id li){std::string str = get_level_annotation(li);return (str.find(find) != std::string::npos);}void annotate_level(){level_id li = level_id::current();level_id li2 = level_id::current();if (is_stair(grd[you.x_pos][you.y_pos])){li2 = level_id::get_next_level_id(you.pos());if (li2.level_type != LEVEL_DUNGEON || li2.depth <= 0)li2 = level_id::current();}if (you.level_type != LEVEL_DUNGEON && li2.level_type != LEVEL_DUNGEON){mpr("You can't annotate this level.");return;}if (you.level_type != LEVEL_DUNGEON)li = li2;else if (li2 != level_id::current()){if (yesno("Annotate level on other end of current stairs?"))li = li2;}if (get_level_annotation(li).length() > 0){mpr("Current level annotation is:", MSGCH_PROMPT);mpr(get_level_annotation(li).c_str() );}mpr( "Set level annotation to what? ", MSGCH_PROMPT );char buf[77];get_input_line( buf, sizeof(buf) );if (strlen(buf) == 0){if (get_level_annotation(li).length() > 0){if (!yesno("Really clear the annotation?"))return;}else{canned_msg(MSG_OK);return;}}set_level_annotation(buf, li);}
break;case TRAP_SHAFT:{// Paranoiaif (!is_valid_shaft_level()){if (trapKnown && monsterNearby)mpr("The shaft disappears in a puff of logic!");grd[env.trap[which_trap].x][env.trap[which_trap].y] = DNGN_FLOOR;env.trap[which_trap].type = TRAP_UNASSIGNED;return;}if (!monster->will_trigger_shaft()){if (trapKnown && !monster->airborne())simple_monster_message(monster," fails to trigger the shaft.");return;}revealTrap = monster->do_shaft();
}static bool can_place_on_trap(int mon_type, trap_type trap){if (trap == TRAP_TELEPORT)return (false);if (trap == TRAP_SHAFT){if (mon_type == RANDOM_MONSTER)return (false);return (mons_class_flag(mon_type, M_FLIES)|| mons_class_flag(mon_type, M_LEVITATE)|| get_monster_data(mon_type)->size == SIZE_TINY);}return (true);
int monsters::body_weight() const{int mclass = type;switch(mclass){case MONS_SPECTRAL_THING:case MONS_SPECTRAL_WARRIOR:case MONS_ELECTRIC_GOLEM:case MONS_RAKSHASA_FAKE:return 0;case MONS_ZOMBIE_SMALL:case MONS_ZOMBIE_LARGE:case MONS_SKELETON_SMALL:case MONS_SKELETON_LARGE:case MONS_SIMULACRUM_SMALL:case MONS_SIMULACRUM_LARGE:mclass = number;break;default:break;}int weight = mons_weight(mclass);// Water elementals are "insubstantial", but still have weight.if (weight == 0 && type == MONS_WATER_ELEMENTAL)weight = 1500;// weight == 0 in the monster entry indicates "no corpse". Can't// use CE_NOCORPSE, because the corpse-effect field is used for// corpseless monsters to indicate what happens if their blood// is sucked. Grrrr.if (weight == 0 && !mons_is_insubstantial(type)){const monsterentry *entry = get_monster_data(mclass);switch(entry->size){case SIZE_TINY:weight = 150;break;case SIZE_LITTLE:weight = 300;break;case SIZE_SMALL:weight = 425;break;case SIZE_MEDIUM:weight = 550;break;case SIZE_LARGE:weight = 1300;break;case SIZE_BIG:weight = 1500;break;case SIZE_GIANT:weight = 1800;break;case SIZE_HUGE:weight = 2200;break;default:mpr("ERROR: invalid monster body weight");perror("monsters::body_weight(): invalid monster body weight");end(0);}
switch(mclass){case MONS_IRON_DEVIL:weight += 550;break;case MONS_STONE_GOLEM:case MONS_EARTH_ELEMENTAL:case MONS_CRYSTAL_GOLEM:weight *= 2;break;case MONS_IRON_DRAGON:case MONS_IRON_GOLEM:weight *= 3;break;case MONS_QUICKSILVER_DRAGON:case MONS_SILVER_STATUE:weight *= 4;break;case MONS_WOOD_GOLEM:weight *= 2;weight /= 3;break;case MONS_FLYING_SKULL:case MONS_CURSE_SKULL:case MONS_SKELETAL_DRAGON:case MONS_SKELETAL_WARRIOR:weight /= 2;break;case MONS_SHADOW_FIEND:case MONS_SHADOW_IMP:case MONS_SHADOW_DEMON:weight /= 3;break;}switch(monster_symbols[mclass].glyph){case 'L':weight /= 2;break;case 'p':weight = 0;break;}}if (type == MONS_SKELETON_SMALL || type == MONS_SKELETON_LARGE)weight /= 2;return (weight);}int monsters::total_weight() const{int burden = 0;for (int i = 0; i < NUM_MONSTER_SLOTS; i++)if (inv[i] != NON_ITEM)burden += item_mass(mitm[inv[i]]) * mitm[inv[i]].quantity;return (body_weight() + burden);}
bool monsters::do_shaft(){if (!is_valid_shaft_level())return (false);bool nearby = mons_near(this);bool vis = player_monster_visible(this);// Handle instances of do_shaft() being invoked magically when// the monster isn't standing over a shaft.if (trap_type_at_xy(x, y) != TRAP_SHAFT){switch(grd[x][y]){case DNGN_FLOOR:case DNGN_OPEN_DOOR:case DNGN_TRAP_MECHANICAL:case DNGN_TRAP_MAGICAL:case DNGN_TRAP_NATURAL:case DNGN_UNDISCOVERED_TRAP:case DNGN_ENTER_SHOP:break;default:return (false);}if (airborne() || total_weight() == 0){if (nearby){if (vis)mprf("A shaft briefly opens up underneath %s!",name(DESC_NOCAP_THE).c_str());elsempr("A shaft briefly opens up in the floor!");}return (true);}}level_id lev = shaft_dest();if (lev == level_id::current())return (false);set_transit(lev);if (nearby){if (vis)mprf("%s falls through a shaft!",name(DESC_CAP_THE).c_str());elsempr("A shaft briefly opens up in the floor!");}// Monster is no longer on this leveldestroy_inventory();monster_cleanup(this);return true;}
}level_id old_level_id = level_id::current();LevelInfo &old_level_info = travel_cache.get_level_info(old_level_id);// Does the next level have a warning annotation?coord_def pos(you.x_pos, you.y_pos);level_id next_level_id = level_id::get_next_level_id(pos);crawl_state.level_annotation_shown = false;if (level_annotation_has("WARN", next_level_id)&& next_level_id != level_id::current()&& next_level_id.level_type == LEVEL_DUNGEON && !force_stair){mpr("Warning: level annotation for next level is:", MSGCH_PROMPT);mpr(get_level_annotation(next_level_id).c_str(), MSGCH_PROMPT);if (!yesno("Enter next level anyways?", true, 0, true, false)){interrupt_activity( AI_FORCE_INTERRUPT );return;}crawl_state.level_annotation_shown = true;
}if (shaft){bool known_trap = (grd[you.x_pos][you.y_pos] != DNGN_UNDISCOVERED_TRAP&& !force_stair);if (you.airborne() && !known_trap && !force_stair){mpr("You can't go down here!");return;}if (you.airborne() && you.flies() != FL_FLY && !force_stair){if (known_trap)mpr("You must have controlled flight to dive through ""a shaft.");return;}if (!is_valid_shaft_level()){if (known_trap)mpr("Strange, the shaft doesn't seem to lead anywhere.");return;}shaft_dest = you.shaft_dest();if (shaft_dest == level_id::current()){if (known_trap)mpr("Strange, the shaft doesn't seem to lead anywhere.");return;}shaft_level = absdungeon_depth(shaft_dest.branch,shaft_dest.depth);if (you.flies() != FL_FLY || force_stair)mpr("You fall through a shaft!");
return;}}// Does the next level have a warning annotation?coord_def pos = you.pos();level_id next_level_id = level_id::get_next_level_id(pos);crawl_state.level_annotation_shown = false;if (level_annotation_has("WARN", next_level_id)&& next_level_id != level_id::current()&& next_level_id.level_type == LEVEL_DUNGEON && !force_stair){mpr("Warning: level annotation for next level is:", MSGCH_PROMPT);mpr(get_level_annotation(next_level_id).c_str(), MSGCH_PROMPT);if (!yesno("Enter next level anyways?", true, 0, true, false)){interrupt_activity( AI_FORCE_INTERRUPT );
bool is_valid_shaft_level(){if (you.level_type != LEVEL_DUNGEON)return (false);// Don't generate shafts in branches where teleport control// is prevented. Prevents player from going down levels without// reaching stairs, and also keeps player from getting stuck// on lower levels with the innability to use teleport control to// get back up.if (testbits(get_branch_flags(), LFLAG_NO_TELE_CONTROL)){return (false);}int depth = subdungeon_depth(you.where_are_you, you.your_level);// When generating levels, don't place a shaft on the level// immediately above the bottom of a branch if that branch is// significantly more dangerous than normal.int min_delta = 1;if (env.turns_on_level == -1 && your_branch().dangerous_bottom_level)min_delta = 2;
if (spec_type == TRAP_RANDOM)spec_type = static_cast<trap_type>( random2(NUM_TRAPS) );
if (spec_type == TRAP_RANDOM || spec_type == TRAP_NONTELEPORT){trap_type forbidden1 = NUM_TRAPS;trap_type forbidden2 = NUM_TRAPS;if (spec_type == TRAP_NONTELEPORT){forbidden1 = TRAP_SHAFT;forbidden2 = TRAP_TELEPORT;}else if (!is_valid_shaft_level())forbidden1 = TRAP_SHAFT;do{spec_type = static_cast<trap_type>( random2(NUM_TRAPS) );} while (spec_type == forbidden1 || spec_type == forbidden2);}
}static bool can_go_down_shaft(){// Not a shaftif (trap_type_at_xy(you.x_pos, you.y_pos) != TRAP_SHAFT)return (false);// Undiscovered shaftif (grd[you.x_pos][you.y_pos] == DNGN_UNDISCOVERED_TRAP)return (false);// Have to fly to dive through it.if (you.flies() != FL_FLY)return (false);return (true);