1 | /* |
1 | /* |
2 | * CrossFire, A Multiplayer game for X-windows |
2 | * CrossFire, A Multiplayer game |
3 | * |
3 | * |
4 | * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team |
4 | * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team |
5 | * Copyright (C) 2002 Mark Wedel & Crossfire Development Team |
5 | * Copyright (C) 2002 Mark Wedel & Crossfire Development Team |
6 | * Copyright (C) 1992 Frank Tore Johansen |
6 | * Copyright (C) 1992 Frank Tore Johansen |
7 | * |
7 | * |
… | |
… | |
248 | * the rest will come from the level in bargaining skill |
248 | * the rest will come from the level in bargaining skill |
249 | */ |
249 | */ |
250 | const double cha_ratio = 0.40; |
250 | const double cha_ratio = 0.40; |
251 | |
251 | |
252 | diff = no_bargain ? 1.0 : 1. - pow (lev_bargain / (double) settings.max_level, 0.25); |
252 | diff = no_bargain ? 1.0 : 1. - pow (lev_bargain / (double) settings.max_level, 0.25); |
253 | |
|
|
254 | diff = (1. - cha_ratio) * diff + cha_ratio * (cha_bonus[who->stats.Cha] - 1.) / (cha_bonus[who->stats.Cha] + 1.); |
253 | diff = (1. - cha_ratio) * diff + cha_ratio * (cha_bonus[who->stats.Cha] - 1.) / (cha_bonus[who->stats.Cha] + 1.); |
255 | |
|
|
256 | diff = .02 + (.80 - .02) * diff; |
254 | diff = .02 + (.80 - .02) * diff; |
257 | |
255 | |
258 | if (flag == F_BUY) |
256 | if (flag == F_BUY) |
259 | val += (val * diff); |
257 | val += val * diff; |
260 | else if (flag == F_SELL) |
258 | else if (flag == F_SELL) |
261 | val -= (val * diff); |
259 | val -= val * diff; |
262 | |
260 | |
263 | // now find a price range. the less good we can judge, the larger the range is |
261 | // now find a price range. the less good we can judge, the larger the range is |
264 | // then the range is adjusted randomly around the correct value |
262 | // then the range is adjusted randomly around the correct value |
265 | if (approximate) |
263 | if (approximate) |
266 | approx_range = sint64 (val / sqrt (lev_identify * 3 + 1)); |
264 | approx_range = sint64 (val / sqrt (lev_identify * 3 + 1)); |
267 | } |
265 | } |
268 | |
266 | |
269 | /* I don't think this should really happen - if it does, it indicates and |
267 | /* I don't think this should really happen - if it does, it indicates and |
270 | * overflow of diff above. That shoudl only happen if |
268 | * overflow of diff above. That should only happen if |
271 | * we are selling objects - in that case, the person just |
269 | * we are selling objects - in that case, the person just |
272 | * gets no money. |
270 | * gets no money. |
273 | */ |
271 | */ |
274 | if ((sint64) val < 0) |
272 | if ((sint64) val < 0) |
275 | val = 0; |
273 | val = 0; |
… | |
… | |
303 | if (QUERY_FLAG (tmp, FLAG_PLAYER_SOLD)) |
301 | if (QUERY_FLAG (tmp, FLAG_PLAYER_SOLD)) |
304 | val = (val * shop_greed (who->map) * shop_specialisation_ratio (tmp, who->map) / shopkeeper_approval (who->map, who)); |
302 | val = (val * shop_greed (who->map) * shop_specialisation_ratio (tmp, who->map) / shopkeeper_approval (who->map, who)); |
305 | else |
303 | else |
306 | val = (val * shop_greed (who->map) / (shop_specialisation_ratio (tmp, who->map) * shopkeeper_approval (who->map, who))); |
304 | val = (val * shop_greed (who->map) / (shop_specialisation_ratio (tmp, who->map) * shopkeeper_approval (who->map, who))); |
307 | } |
305 | } |
|
|
306 | |
308 | /* we will also have an extra 0-5% variation between shops of the same type |
307 | /* we will also have an extra 0-5% variation between shops of the same type |
309 | * for valuable items (below a value of 50 this effect wouldn't be very |
308 | * for valuable items (below a value of 50 this effect wouldn't be very |
310 | * pointful, and could give fun with rounding. |
309 | * pointful, and could give fun with rounding. |
311 | */ |
310 | */ |
|
|
311 | //TODO: why use cosf at all, just % and scale linearly, gives more even distribution |
312 | if (val > 50) |
312 | if (val > 50) |
313 | val += float (val) * .05f * cosf ((tmp->uuid.seq & 0xffff) * float (M_PI * 2. / 0x10000)); |
313 | val += float (val) * .05f * cosf ((tmp->uuid.seq & 0xffff) * float (M_PI * 2. / 0x10000)); |
314 | } |
314 | } |
315 | |
315 | |
316 | return (sint64) val; |
316 | return (sint64) val; |
… | |
… | |
541 | |
541 | |
542 | for (pouch = pl->inv; pouch && to_pay; pouch = pouch->below) |
542 | for (pouch = pl->inv; pouch && to_pay; pouch = pouch->below) |
543 | if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && (pouch->race == NULL || strstr (pouch->race, "gold"))) |
543 | if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && (pouch->race == NULL || strstr (pouch->race, "gold"))) |
544 | pay_from_container (pl, pouch, to_pay); |
544 | pay_from_container (pl, pouch, to_pay); |
545 | |
545 | |
546 | if (settings.real_wiz == FALSE && QUERY_FLAG (pl, FLAG_WAS_WIZ)) |
|
|
547 | SET_FLAG (op, FLAG_WAS_WIZ); |
|
|
548 | |
|
|
549 | pl->update_stats (); |
546 | pl->update_stats (); |
|
|
547 | |
550 | return 1; |
548 | return 1; |
551 | } |
549 | } |
552 | |
550 | |
553 | /* This pays for the item, and takes the proper amount of money off |
551 | /* This pays for the item, and takes the proper amount of money off |
554 | * the player. |
552 | * the player. |
… | |
… | |
1194 | } |
1192 | } |
1195 | SET_FLAG (tmp, FLAG_UNPAID); |
1193 | SET_FLAG (tmp, FLAG_UNPAID); |
1196 | } |
1194 | } |
1197 | |
1195 | |
1198 | void |
1196 | void |
1199 | shop_listing (object *op) |
1197 | shop_listing (object *sign, object *op) |
1200 | { |
1198 | { |
1201 | int i, j, numitems = 0, numallocated = 0, nx, ny; |
1199 | int i, j, numitems = 0, numallocated = 0, x1, x2, y1, y2; |
1202 | char *map_mark = (char *) calloc (MAGIC_MAP_SIZE * MAGIC_MAP_SIZE, 1); |
1200 | const char *shop_coords = get_ob_key_value (sign, "shop_coords"); |
1203 | object *stack; |
1201 | object *stack; |
1204 | shopinv *items; |
1202 | shopinv *items; |
1205 | |
1203 | |
1206 | /* Should never happen, but just in case a monster does apply a sign */ |
1204 | /* Should never happen, but just in case a monster does apply a sign */ |
1207 | if (op->type != PLAYER) |
1205 | if (op->type != PLAYER) |
1208 | return; |
1206 | return; |
1209 | |
1207 | |
1210 | new_draw_info (NDI_UNIQUE, 0, op, "\nThe shop contains:"); |
1208 | if (!(shop_coords && sscanf (shop_coords, "%d,%d,%d,%d", &x1, &y1, &x2, &y2))) |
|
|
1209 | { |
|
|
1210 | x1 = 0; |
|
|
1211 | y1 = 0; |
|
|
1212 | x2 = op->map->width - 1; |
|
|
1213 | y2 = op->map->height - 1; |
|
|
1214 | } |
1211 | |
1215 | |
1212 | magic_mapping_mark (op, map_mark, 3); |
|
|
1213 | items = (shopinv *) malloc (40 * sizeof (shopinv)); |
1216 | items = (shopinv *) malloc (40 * sizeof (shopinv)); |
1214 | numallocated = 40; |
1217 | numallocated = 40; |
1215 | |
1218 | |
1216 | /* Find all the appropriate items */ |
1219 | /* Find all the appropriate items */ |
1217 | for (i = 0; i < op->map->width; i++) |
1220 | for (i = x1; i <= x2; i++) |
1218 | { |
1221 | { |
1219 | for (j = 0; j < op->map->height; j++) |
1222 | for (j = y1; j < y2; j++) |
1220 | { |
1223 | { |
1221 | // magic map code now centers the map on the object at MAGIC_MAP_HALF. |
1224 | if (is_in_shop (op->map, i, j)) |
1222 | nx = i - op->x + MAGIC_MAP_HALF; |
|
|
1223 | ny = j - op->y + MAGIC_MAP_HALF; |
|
|
1224 | /* unlikely, but really big shops could run into this issue */ |
|
|
1225 | if (nx < 0 || ny < 0 || nx > MAGIC_MAP_SIZE || ny > MAGIC_MAP_SIZE) |
|
|
1226 | continue; |
|
|
1227 | |
|
|
1228 | if (map_mark[nx + MAGIC_MAP_SIZE * ny] & FACE_FLOOR) |
|
|
1229 | { |
1225 | { |
1230 | stack = GET_MAP_OB (op->map, i, j); |
1226 | stack = GET_MAP_OB (op->map, i, j); |
1231 | |
1227 | |
1232 | while (stack) |
1228 | while (stack) |
1233 | { |
1229 | { |
… | |
… | |
1246 | } |
1242 | } |
1247 | } |
1243 | } |
1248 | } |
1244 | } |
1249 | } |
1245 | } |
1250 | |
1246 | |
1251 | free (map_mark); |
|
|
1252 | |
|
|
1253 | if (numitems == 0) |
1247 | if (numitems == 0) |
1254 | { |
1248 | { |
1255 | new_draw_info (NDI_UNIQUE, 0, op, "The shop is currently empty.\n"); |
1249 | new_draw_info (NDI_UNIQUE, 0, op, "The shop is currently empty.\n"); |
1256 | free (items); |
1250 | free (items); |
1257 | return; |
1251 | return; |
1258 | } |
1252 | } |
1259 | |
1253 | |
1260 | qsort (items, numitems, sizeof (shopinv), (int (*)(const void *, const void *)) shop_sort); |
1254 | qsort (items, numitems, sizeof (shopinv), (int (*)(const void *, const void *)) shop_sort); |
|
|
1255 | |
|
|
1256 | new_draw_info (NDI_UNIQUE, 0, op, "\nThe shop contains:"); |
1261 | |
1257 | |
1262 | for (i = 0; i < numitems; i++) |
1258 | for (i = 0; i < numitems; i++) |
1263 | { |
1259 | { |
1264 | /* Collapse items of the same name together */ |
1260 | /* Collapse items of the same name together */ |
1265 | if ((i + 1) < numitems && !strcmp (items[i].item_real, items[i + 1].item_real)) |
1261 | if ((i + 1) < numitems && !strcmp (items[i].item_real, items[i + 1].item_real)) |