* Attempt to revive the given corpse, return the revived monster if * successful. Note: this does NOT use up the corpse if it fails. * If corpse->quan is more than 1, only one corpse will be affected * and only one monster will be resurrected. */
| 881 | * and only one monster will be resurrected. |
| 882 | */ |
| 883 | struct monst * |
| 884 | revive(struct obj *corpse, boolean by_hero) |
| 885 | { |
| 886 | struct monst *mtmp = 0; |
| 887 | struct permonst *mptr; |
| 888 | struct obj *container; |
| 889 | coord xy; |
| 890 | coordxy x, y; |
| 891 | boolean one_of; |
| 892 | mmflags_nht mmflags = NO_MINVENT | MM_NOWAIT | MM_NOMSG; |
| 893 | int montype, cgend, container_nesting = 0; |
| 894 | boolean is_zomb; |
| 895 | |
| 896 | if (corpse->otyp != CORPSE) { |
| 897 | impossible("Attempting to revive %s?", xname(corpse)); |
| 898 | return (struct monst *) 0; |
| 899 | } |
| 900 | montype = corpse->corpsenm; |
| 901 | /* treat buried auto-reviver (troll, Rider?) like a zombie |
| 902 | so that it can dig itself out of the ground if it revives */ |
| 903 | is_zomb = mons[montype].mlet == S_ZOMBIE |
| 904 | || (corpse->where == OBJ_BURIED && is_reviver(&mons[montype])); |
| 905 | |
| 906 | /* if this corpse is being eaten, stop doing that; this should be done |
| 907 | after makemon() succeeds and skipped if it fails, but waiting until |
| 908 | we know the result for that would be too late */ |
| 909 | cant_finish_meal(corpse); |
| 910 | |
| 911 | x = y = 0; |
| 912 | if (corpse->where != OBJ_CONTAINED) { |
| 913 | int locflags = is_zomb ? BURIED_TOO : 0; |
| 914 | |
| 915 | /* only for invent, minvent, or floor, or if zombie, buried */ |
| 916 | container = 0; |
| 917 | (void) get_obj_location(corpse, &x, &y, locflags); |
| 918 | } else { |
| 919 | /* deal with corpses in [possibly nested] containers */ |
| 920 | struct monst *carrier; |
| 921 | int holder = OBJ_FREE; |
| 922 | |
| 923 | container = corpse->ocontainer; |
| 924 | carrier = |
| 925 | get_container_location(container, &holder, &container_nesting); |
| 926 | switch (holder) { |
| 927 | case OBJ_MINVENT: |
| 928 | x = carrier->mx, y = carrier->my; |
| 929 | break; |
| 930 | case OBJ_INVENT: |
| 931 | x = u.ux, y = u.uy; |
| 932 | break; |
| 933 | case OBJ_FLOOR: |
| 934 | (void) get_obj_location(corpse, &x, &y, CONTAINED_TOO); |
| 935 | break; |
| 936 | default: |
| 937 | break; /* x,y are 0 */ |
| 938 | } |
| 939 | } |
| 940 | if (x) /* update corpse's location now that we're sure where it is */ |
no test coverage detected