| 1031 | } |
| 1032 | |
| 1033 | void |
| 1034 | bc_sanity_check(void) |
| 1035 | { |
| 1036 | int otyp, freeball, freechain; |
| 1037 | const char *onam; |
| 1038 | |
| 1039 | if (Punished && (!uball || !uchain)) { |
| 1040 | impossible("Punished without %s%s%s?", |
| 1041 | !uball ? "iron ball" : "", |
| 1042 | (!uball && !uchain) ? " and " : "", |
| 1043 | !uchain ? "attached chain" : ""); |
| 1044 | } else if (!Punished && (uball || uchain)) { |
| 1045 | impossible("Attached %s%s%s without being Punished?", |
| 1046 | uchain ? "chain" : "", |
| 1047 | (uchain && uball) ? " and " : "", |
| 1048 | uball ? "iron ball" : ""); |
| 1049 | } |
| 1050 | /* ball is free when swallowed, when changing levels or during air bubble |
| 1051 | management on Plane of Water (both of which start and end in between |
| 1052 | sanity checking cycles, so shouldn't be relevant), other times? */ |
| 1053 | freechain = (!uchain || uchain->where == OBJ_FREE); |
| 1054 | freeball = (!uball || uball->where == OBJ_FREE |
| 1055 | /* lie to simplify the testing logic */ |
| 1056 | || (freechain && uball->where == OBJ_INVENT)); |
| 1057 | if (uball && (uball->otyp != HEAVY_IRON_BALL |
| 1058 | || (uball->where != OBJ_FLOOR |
| 1059 | && uball->where != OBJ_INVENT |
| 1060 | && uball->where != OBJ_FREE) |
| 1061 | || (freeball ^ freechain) |
| 1062 | || (uball->owornmask & W_BALL) == 0L |
| 1063 | || (uball->owornmask & ~(W_BALL | W_WEAPONS)) != 0L)) { |
| 1064 | otyp = uball->otyp; |
| 1065 | onam = safe_typename(otyp); |
| 1066 | impossible("uball: type %d (%s), where %d, wornmask=0x%08lx", |
| 1067 | otyp, onam, uball->where, uball->owornmask); |
| 1068 | } |
| 1069 | /* similar check to ball except can't be in inventory */ |
| 1070 | if (uchain && (uchain->otyp != IRON_CHAIN |
| 1071 | || (uchain->where != OBJ_FLOOR |
| 1072 | && uchain->where != OBJ_FREE) |
| 1073 | || (freechain ^ freeball) |
| 1074 | /* [could simplify this to owornmask != W_CHAIN] */ |
| 1075 | || (uchain->owornmask & W_CHAIN) == 0L |
| 1076 | || (uchain->owornmask & ~W_CHAIN) != 0L)) { |
| 1077 | otyp = uchain->otyp; |
| 1078 | onam = safe_typename(otyp); |
| 1079 | impossible("uchain: type %d (%s), where %d, wornmask=0x%08lx", |
| 1080 | otyp, onam, uchain->where, uchain->owornmask); |
| 1081 | } |
| 1082 | if (uball && uchain && !(freeball && freechain)) { |
| 1083 | int bx, by, cx, cy, bdx, bdy, cdx, cdy; |
| 1084 | |
| 1085 | /* non-free chain should be under or next to the hero; |
| 1086 | non-free ball should be on or next to the chain or else carried */ |
| 1087 | cx = uchain->ox, cy = uchain->oy; |
| 1088 | cdx = cx - u.ux, cdy = cy - u.uy; |
| 1089 | cdx = abs(cdx), cdy = abs(cdy); |
| 1090 | if (uball->where == OBJ_INVENT) /* carried(uball) */ |
no test coverage detected