place object randomly, returns False if it's gone (eg broken) */
| 2099 | |
| 2100 | /* place object randomly, returns False if it's gone (eg broken) */ |
| 2101 | boolean |
| 2102 | rloco(struct obj *obj) |
| 2103 | { |
| 2104 | coordxy tx, ty, otx, oty; |
| 2105 | boolean restricted_fall; |
| 2106 | int try_limit = 4000; |
| 2107 | |
| 2108 | if (obj->otyp == CORPSE && is_rider(&mons[obj->corpsenm])) { |
| 2109 | if (revive_corpse(obj)) |
| 2110 | return FALSE; |
| 2111 | } |
| 2112 | |
| 2113 | obj_extract_self(obj); |
| 2114 | otx = obj->ox; |
| 2115 | oty = obj->oy; |
| 2116 | restricted_fall = (otx == 0 && svd.dndest.lx); |
| 2117 | do { |
| 2118 | tx = rn1(COLNO - 3, 2); |
| 2119 | ty = rn2(ROWNO); |
| 2120 | if (!--try_limit) |
| 2121 | break; |
| 2122 | } while (!goodpos(tx, ty, (struct monst *) 0, 0) |
| 2123 | || (restricted_fall |
| 2124 | && (!within_bounded_area(tx, ty, |
| 2125 | svd.dndest.lx, svd.dndest.ly, |
| 2126 | svd.dndest.hx, svd.dndest.hy) |
| 2127 | || (svd.dndest.nlx |
| 2128 | && within_bounded_area(tx, ty, |
| 2129 | svd.dndest.nlx, svd.dndest.nly, |
| 2130 | svd.dndest.nhx, svd.dndest.nhy)))) |
| 2131 | /* on the Wizard Tower levels, objects inside should |
| 2132 | stay inside and objects outside should stay outside */ |
| 2133 | || (svd.dndest.nlx && On_W_tower_level(&u.uz) |
| 2134 | && within_bounded_area(tx, ty, |
| 2135 | svd.dndest.nlx, svd.dndest.nly, |
| 2136 | svd.dndest.nhx, svd.dndest.nhy) |
| 2137 | != within_bounded_area(otx, oty, |
| 2138 | svd.dndest.nlx, svd.dndest.nly, |
| 2139 | svd.dndest.nhx, svd.dndest.nhy))); |
| 2140 | |
| 2141 | if (flooreffects(obj, tx, ty, "fall")) { |
| 2142 | /* update old location (if any) since flooreffects() couldn't; |
| 2143 | unblock_point() for boulder handled by obj_extract_self() */ |
| 2144 | if (!(otx == 0 && oty == 0)) |
| 2145 | newsym(otx, oty); |
| 2146 | return FALSE; |
| 2147 | } else if (otx == 0 && oty == 0) { |
| 2148 | ; /* fell through a trap door; no update of old loc needed */ |
| 2149 | } else { |
| 2150 | struct monst *shkp = find_objowner(obj, otx, oty); |
| 2151 | boolean objinshop = shkp && costly_spot(otx, oty), |
| 2152 | onboundary = shkp && costly_adjacent(shkp, otx, oty); |
| 2153 | |
| 2154 | /* |
| 2155 | * If object starts inside shop or is unpaid and on shop boundary: |
| 2156 | * if hero is outside the shop, treat this as theft; |
| 2157 | * otherwise, if it arrives inside same shop, remove it from bill; |
| 2158 | * otherwise, if it arrives on the boundary, add it to bill; |
no test coverage detected