Crossfire Server, Trunk  1.75.0
shop_inventory.cpp
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(object *lighter, object *applier, int aflags);
30 
36 }
37 
41 struct shopinv {
42  char *item_sort;
43  char *item_real;
44  uint16_t type;
45  uint32_t nrof;
46 };
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 
119 static method_ret shop_inventory_type_apply(object *lighter, object *applier, int aflags) {
120  size_t i, j, numitems = 0, numallocated = 0;
121  object *stack;
122  shopinv *items;
123  (void)lighter;
124  (void)aflags;
125 
126  if (applier->type != PLAYER)
127  return METHOD_UNHANDLED;
128 
129  // By using a buffer, we can make the shop inventory send all at once.
130  // This will make the GTK client behave better when printing the shop inventory.
132 
133  stringbuffer_append_string(buf, "\nThe shop contains:\n");
134 
135  items = static_cast<shopinv *>(malloc(40*sizeof(shopinv)));
136  numallocated = 40;
137 
138  /* Find all the appropriate items */
139  for (i = 0; i < MAP_WIDTH(applier->map); i++) {
140  for (j = 0; j < MAP_HEIGHT(applier->map); j++) {
141  stack = GET_MAP_OB(applier->map, i, j);
142 
143  while (stack) {
144  if (QUERY_FLAG(stack, FLAG_UNPAID)) {
145  if (numitems == numallocated) {
146  items = static_cast<shopinv *>(realloc(items, sizeof(shopinv)*(numallocated+10)));
147  if (!items) {
148  LOG(llevError, "shop_inventory: couldn't allocate memory!\n");
150  }
151  numallocated += 10;
152  }
153  add_shop_item(stack, items, &numitems);
154  }
155  stack = stack->above;
156  }
157  }
158  }
159  if (numitems == 0) {
160  stringbuffer_append_string(buf, "The shop is currently empty.\n");
161  // Print before we clean and exit
162  const char *str = stringbuffer_finish(buf);
164  free((char *)str);
165  free(items);
166  return METHOD_OK;
167  }
168  qsort(items, numitems, sizeof(shopinv), (int (*)(const void *, const void *))shop_sort);
169 
170  for (i = 0; i < numitems; i++) {
171  /* Collapse items of the same name together */
172  if ((i+1) < numitems && !strcmp(items[i].item_real, items[i+1].item_real)) {
173  items[i+1].nrof += items[i].nrof;
174  free(items[i].item_sort);
175  free(items[i].item_real);
176  } else {
178  "%d %s\n",
179  items[i].nrof ? items[i].nrof : 1,
180  items[i].nrof == 1 ? items[i].item_sort : items[i].item_real);
181  free(items[i].item_sort);
182  free(items[i].item_real);
183  }
184  }
185  // Okay, we've got the shop inventory, now we can send it over all at once.
186  const char *str = stringbuffer_finish(buf);
188  free((char *)str);
189  free(items);
190  return METHOD_OK;
191 }
GET_MAP_OB
#define GET_MAP_OB(M, X, Y)
Gets the bottom object on a map.
Definition: map.h:170
PLAYER
@ PLAYER
Definition: object.h:112
global.h
llevError
@ llevError
Error, serious thing.
Definition: logger.h:11
shopinv::item_sort
char * item_sort
Singular name.
Definition: shop_inventory.cpp:42
LOG
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:58
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
strdup_local
#define strdup_local
Definition: compat.h:29
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Append a formatted string to a string buffer instance.
Definition: stringbuffer.cpp:138
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
Definition: stringbuffer.cpp:57
register_apply
void register_apply(int ob_type, apply_func method)
Registers the apply method for the given type.
Definition: ob_types.cpp:62
METHOD_OK
#define METHOD_OK
Definition: ob_methods.h:15
object::map
struct mapstruct * map
Pointer to the map in which this object is present.
Definition: object.h:305
shopinv
One item to list on the sign.
Definition: shop_inventory.cpp:41
shopinv::nrof
uint32_t nrof
Count of this items.
Definition: shop_inventory.cpp:45
buf
StringBuffer * buf
Definition: readable.cpp:1565
object::above
object * above
Pointer to the object stacked above this one.
Definition: object.h:296
name
Plugin animator file specs[Config] name
Definition: animfiles.txt:4
draw_ext_info
vs only yadda is in because all tags get reset on the next draw_ext_info In the second since it is all in one draw_ext_info
Definition: media-tags.txt:61
METHOD_UNHANDLED
#define METHOD_UNHANDLED
Definition: ob_methods.h:16
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
Definition: stringbuffer.cpp:76
add_shop_item
static void add_shop_item(object *tmp, shopinv *items, size_t *numitems)
Insert the item in the list.
Definition: shop_inventory.cpp:83
object::type
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:348
sproto.h
shopinv::type
uint16_t type
Item type.
Definition: shop_inventory.cpp:44
stringbuffer_append_string
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Append a string to a string buffer instance.
Definition: stringbuffer.cpp:95
MSG_TYPE_SHOP
#define MSG_TYPE_SHOP
Definition: newclient.h:407
shop_sort
static int shop_sort(const void *a1, const void *a2)
Sort routine for shopinv.
Definition: shop_inventory.cpp:61
fatal
void fatal(enum fatal_error err)
fatal() is meant to be called whenever a fatal signal is intercepted.
Definition: utils.cpp:590
MAP_WIDTH
#define MAP_WIDTH(m)
Map width.
Definition: map.h:73
MAX_BUF
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
StringBuffer
A buffer that will be expanded as content is added to it.
Definition: stringbuffer.cpp:25
init_type_shop_inventory
void init_type_shop_inventory(void)
Initializer for the SHOP_INVENTORY object type.
Definition: shop_inventory.cpp:34
method_ret
char method_ret
Define some standard return values for callbacks which don't need to return any other results.
Definition: ob_methods.h:14
ob_types.h
sounds.h
NDI_UNIQUE
#define NDI_UNIQUE
Print immediately, don't buffer.
Definition: newclient.h:266
shopinv::item_real
char * item_real
Plural name.
Definition: shop_inventory.cpp:43
SHOP_INVENTORY
@ SHOP_INVENTORY
Mark Wedel (mark@pyramid.com) Shop inventories.
Definition: object.h:243
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
MSG_TYPE_SHOP_LISTING
#define MSG_TYPE_SHOP_LISTING
Shop listings - inventory, what it deals in.
Definition: newclient.h:512
MAP_HEIGHT
#define MAP_HEIGHT(m)
Map height.
Definition: map.h:75
strcasecmp
int strcasecmp(const char *s1, const char *s2)
FLAG_UNPAID
#define FLAG_UNPAID
Object hasn't been paid for yet.
Definition: define.h:236
object::nrof
uint32_t nrof
Number of objects.
Definition: object.h:342
ob_methods.h
query_base_name
void query_base_name(const object *op, int plural, char *buf, size_t size)
Query a short name for the item.
Definition: item.cpp:695
shop_inventory_type_apply
static method_ret shop_inventory_type_apply(object *lighter, object *applier, int aflags)
Apply a shop inventory.
Definition: shop_inventory.cpp:119
OUT_OF_MEMORY
@ OUT_OF_MEMORY
Definition: define.h:48