Crossfire Server, Trunk  R21017
shop_inventory.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
19 #include "global.h"
20 
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include "ob_methods.h"
25 #include "ob_types.h"
26 #include "sounds.h"
27 #include "sproto.h"
28 
29 static method_ret shop_inventory_type_apply(ob_methods *context, object *lighter, object *applier, int aflags);
30 
36 }
37 
41 typedef struct shopinv {
42  char *item_sort;
43  char *item_real;
46 } shopinv;
47 
61 static int shop_sort(const void *a1, const void *a2) {
62  const shopinv *s1 = (const shopinv *)a1, *s2 = (const shopinv *)a2;
63 
64  if (s1->type < s2->type)
65  return -1;
66  if (s1->type > s2->type)
67  return 1;
68  /* the type is the same (what atoi gets), so do a strcasecmp to sort
69  * via alphabetical order
70  */
71  return strcasecmp(s1->item_sort, s2->item_sort);
72 }
73 
83 static void add_shop_item(object *tmp, shopinv *items, size_t *numitems) {
84  /* clear unpaid flag so that doesn't come up in query
85  * string. We clear nrof so that we can better sort
86  * the object names.
87  */
88  char name[MAX_BUF];
89 
90  CLEAR_FLAG(tmp, FLAG_UNPAID);
91  items[*numitems].nrof = tmp->nrof;
92  /* Non mergable items have nrof of 0, but count them as one
93  * so the display is properly.
94  */
95  if (tmp->nrof == 0)
96  items[*numitems].nrof++;
97  items[*numitems].type = tmp->type;
98  query_base_name(tmp, 0, name, MAX_BUF);
99  items[*numitems].item_sort = strdup_local(name);
100  query_base_name(tmp, 1, name, MAX_BUF);
101  items[*numitems].item_real = strdup_local(name);
102  (*numitems)++;
103 
104  SET_FLAG(tmp, FLAG_UNPAID);
105 }
106 
121 static method_ret shop_inventory_type_apply(ob_methods *context, object *lighter, object *applier, int aflags) {
122  size_t i, j, numitems = 0, numallocated = 0;
123  object *stack;
124  shopinv *items;
125 
126  if (applier->type != PLAYER)
127  return METHOD_UNHANDLED;
128 
130  "\nThe shop contains:");
131 
132  items = malloc(40*sizeof(shopinv));
133  numallocated = 40;
134 
135  /* Find all the appropriate items */
136  for (i = 0; i < MAP_WIDTH(applier->map); i++) {
137  for (j = 0; j < MAP_HEIGHT(applier->map); j++) {
138  stack = GET_MAP_OB(applier->map, i, j);
139 
140  while (stack) {
141  if (QUERY_FLAG(stack, FLAG_UNPAID)) {
142  if (numitems == numallocated) {
143  items = realloc(items, sizeof(shopinv)*(numallocated+10));
144  numallocated += 10;
145  }
146  add_shop_item(stack, items, &numitems);
147  }
148  stack = stack->above;
149  }
150  }
151  }
152  if (numitems == 0) {
154  "The shop is currently empty.\n");
155  free(items);
156  return METHOD_OK;
157  }
158  qsort(items, numitems, sizeof(shopinv), (int (*)(const void *, const void *))shop_sort);
159 
160  for (i = 0; i < numitems; i++) {
161  /* Collapse items of the same name together */
162  if ((i+1) < numitems && !strcmp(items[i].item_real, items[i+1].item_real)) {
163  items[i+1].nrof += items[i].nrof;
164  free(items[i].item_sort);
165  free(items[i].item_real);
166  } else {
168  "%d %s",
169  items[i].nrof ? items[i].nrof : 1,
170  items[i].nrof == 1 ? items[i].item_sort : items[i].item_real);
171  free(items[i].item_sort);
172  free(items[i].item_real);
173  }
174  }
175  free(items);
176  return METHOD_OK;
177 }
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Definition: main.c:315
#define FLAG_UNPAID
Definition: define.h:236
#define MSG_TYPE_SHOP_LISTING
Definition: newclient.h:486
#define SET_FLAG(xyz, p)
Definition: define.h:223
#define strdup_local
Definition: compat.h:25
uint16_t type
void query_base_name(const object *op, int plural, char *buf, size_t size)
Definition: item.c:723
#define MAP_HEIGHT(m)
Definition: map.h:80
struct obj * above
Definition: object.h:288
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Definition: main.c:310
char method_ret
Definition: ob_methods.h:14
struct shopinv shopinv
#define METHOD_OK
Definition: ob_methods.h:15
struct mapdef * map
Definition: object.h:297
static method_ret shop_inventory_type_apply(ob_methods *context, object *lighter, object *applier, int aflags)
char * item_sort
uint32_t nrof
Definition: object.h:333
void register_apply(int ob_type, apply_func method)
Definition: ob_types.c:62
uint32_t nrof
#define MSG_TYPE_SHOP
Definition: newclient.h:378
static int shop_sort(const void *a1, const void *a2)
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define CLEAR_FLAG(xyz, p)
Definition: define.h:224
#define MAX_BUF
Definition: define.h:35
#define METHOD_UNHANDLED
Definition: ob_methods.h:16
static void add_shop_item(object *tmp, shopinv *items, size_t *numitems)
unsigned short uint16_t
Definition: win32.h:163
Definition: object.h:107
unsigned int uint32_t
Definition: win32.h:162
#define MAP_WIDTH(m)
Definition: map.h:78
void init_type_shop_inventory(void)
uint8_t type
Definition: object.h:338
#define GET_MAP_OB(M, X, Y)
Definition: map.h:172
int strcasecmp(const char *s1, const char *s2)
Definition: porting.c:256
#define NDI_UNIQUE
Definition: newclient.h:245
char * item_real