/* copy the light source(s) attachted to src, and attach it/them to dest */ void obj_split_light_source(struct obj *src, struct obj *dest) { light_source *ls, *new_ls; for (ls = level->lev_lights; ls; ls = ls->next) if (ls->type == LS_OBJECT && ls->id == src) { /* * Insert the new source at beginning of list. This will * never interfere us walking down the list - we are already * past the insertion point. */ new_ls = malloc(sizeof(light_source)); *new_ls = *ls; if (Is_candle(src)) { /* split candles may emit less light than original group */ ls->range = candle_light_range(src); new_ls->range = candle_light_range(dest); vision_full_recalc = 1; /* in case range changed */ } new_ls->id = dest; new_ls->next = level->lev_lights; level->lev_lights = new_ls; dest->lamplit = 1; /* now an active light source */ } }
/* * Create a dummy duplicate to put on shop bill. The duplicate exists * only in the billobjs chain. This function is used when a shop object * is being altered, and a copy of the original is needed for billing * purposes. For example, when eating, where an interruption will yield * an object which is different from what it started out as; the "I x" * command needs to display the original object. * * The caller is responsible for checking otmp->unpaid and * costly_spot(u.ux, u.uy). This function will make otmp no charge. * * Note that check_unpaid_usage() should be used instead for partial * usage of an object. */ void bill_dummy_object(struct obj *otmp) { struct obj *dummy; if (otmp->unpaid) subfrombill(otmp, shop_keeper(level, *u.ushops)); dummy = newobj(otmp->oxlth + otmp->onamelth); *dummy = *otmp; dummy->where = OBJ_FREE; dummy->o_id = flags.ident++; if (!dummy->o_id) dummy->o_id = flags.ident++; /* ident overflowed */ dummy->timed = 0; if (otmp->oxlth) memcpy(dummy->oextra, otmp->oextra, otmp->oxlth); if (otmp->onamelth) strncpy(ONAME(dummy), ONAME(otmp), (int)otmp->onamelth); if (Is_candle(dummy)) dummy->lamplit = 0; addtobill(dummy, FALSE, TRUE, TRUE); otmp->no_charge = 1; otmp->unpaid = 0; return; }
/* Candlelight is proportional to the number of candles; minimum range is 2 rather than 1 for playability. */ int candle_light_range(struct obj *obj) { int radius; if (obj->otyp == CANDELABRUM_OF_INVOCATION) { /* * The special candelabrum emits more light than the * corresponding number of candles would. * 1..3 candles, range 2 (minimum range); * 4..6 candles, range 3 (normal lamp range); * 7 candles, range 4 (bright). */ radius = (obj->spe < 4) ? 2 : (obj->spe < 7) ? 3 : 4; } else if (Is_candle(obj)) { /* * Range is incremented by powers of 7 so that it will take * wizard mode quantities of candles to get more light than * from a lamp, without imposing an arbitrary limit. * 1..6 candles, range 2; * 7..48 candles, range 3; * 49..342 candles, range 4; &c. */ long n = obj->quan; radius = 1; /* always incremented at least once */ do { radius++; n /= 7L; } while (n > 0L); } else { /* we're only called for lit candelabrum or candles */ /* impossible("candlelight for %d?", obj->otyp); */ radius = 3; /* lamp's value */ } return radius; }