Crossfire Server, Trunk
converter.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 
18 #include "global.h"
19 
20 #include <string.h>
21 #include <stdlib.h>
22 
23 #include "ob_methods.h"
24 #include "ob_types.h"
25 #include "shop.h"
26 #include "sounds.h"
27 #include "sproto.h"
28 
29 /*
30  * convert_item() returns 1 if anything was converted, 0 if the item was not
31  * what the converter wants, -1 if the converter is broken.
32  */
33 #define CONV_FROM(xyz) xyz->slaying
34 #define CONV_TO(xyz) xyz->other_arch
35 #define CONV_NR(xyz) (unsigned char)xyz->stats.sp
36 #define CONV_LIMIT(xyz) ((xyz->stats.wc > 0) ? ((unsigned long)xyz->stats.wc) : INT32_MAX)
37 #define CONV_NEED(xyz) (unsigned long)xyz->stats.food
38 #define CONV_FROM_MATCH(xyz,_match) (CONV_FROM(xyz) == (_match) || ((strchr(CONV_FROM(xyz),'*')) && wildcard_match(CONV_FROM(xyz),(_match))))
39 
40 static int convert_item(object *item, object *converter);
41 
45 static int wildcard_match(const char *string,const char *candidate)
46 {
47  bool head=FALSE,tail=FALSE;
48  char *str;
49  char *m;
50  bool ret;
51 
52  if ( string[0]=='*' && string[1]==0 ) return 1; // Trivial match-all case
53  if ( string[0] == '*' ) head=TRUE;
54  if ( string[strlen(string)-1] == '*' ) tail=TRUE;
55  str=strdup(&string[head?1:0]);
56  if ( !str ) return FALSE;
57  if ( tail ) str[strlen(str)-1]=0;
58  /* 'str' is now the text to match without the wildcard */
59  ret=FALSE;
60  if ( head && tail ) {
61  m=strstr(str,candidate);
62  if ( m ) ret=TRUE;
63  } else if ( tail ) {
64  if ( strncmp(str,candidate,strlen(str)) == 0 ) ret=TRUE;
65  } else {
66  if ( strlen(candidate) >= strlen(str) &&
67  strcmp(&candidate[strlen(candidate)-strlen(str)],str) == 0 ) ret=TRUE;
68  }
69  free(str);
70  return ret;
71 }
72 
73 static method_ret converter_type_move_on(object *trap, object *victim, object *originator);
74 
78 void init_type_converter(void) {
80 }
81 
91 static int convert_item(object *item, object *converter) {
92  int nr = 0;
93  uint32_t price_in;
94 
95  /* We make some assumptions - we assume if it takes money as it type,
96  * it wants some amount. We don't make change (ie, if something costs
97  * 3 gp and player drops a platinum, tough luck)
98  */
99  if (!strcmp(CONV_FROM(converter), "money")) {
100  int cost;
101 
102  if (item->type != MONEY)
103  return 0;
104 
105  nr = MIN(CONV_LIMIT(converter), (item->nrof*item->value)/CONV_NEED(converter));
106  if (!nr)
107  return 0;
108 
109  cost = nr*CONV_NEED(converter)/item->value;
110  /* take into account rounding errors */
111  if (nr*CONV_NEED(converter)%item->value)
112  cost++;
114 
115  price_in = cost*item->value;
116  } else {
117  if (item->type == PLAYER
118  || !CONV_FROM_MATCH(converter,item->arch->name)
119  || (CONV_NEED(converter) && CONV_NEED(converter) > item->nrof))
120  return 0;
121 
122  /* silently burn unpaid items (only if they match what we want) */
123  if (QUERY_FLAG(item, FLAG_UNPAID)) {
126  item = create_archetype("burnout");
127  if (item != NULL)
128  object_insert_in_map_at(item, converter->map, converter, 0, converter->x, converter->y);
129  return 1;
130  }
131 
132  if (CONV_NEED(converter)) {
133  nr = MIN(CONV_LIMIT(converter), item->nrof/CONV_NEED(converter));
134  object_decrease_nrof(item, nr*CONV_NEED(converter));
135  price_in = nr*CONV_NEED(converter)*item->value;
136  } else {
137  price_in = item->value;
140  }
141  }
142 
143  if (converter->inv != NULL) {
144  int i;
145  object *ob_to_copy;
146 
147  /* select random object from inventory to copy */
148  ob_to_copy = converter->inv;
149  i = 1;
150  FOR_BELOW_PREPARE(converter->inv, ob) {
151  if (rndm(0, i) == 0)
152  ob_to_copy = ob;
153  i++;
154  } FOR_BELOW_FINISH();
155  item = object_create_clone(ob_to_copy);
158  } else {
159  if (converter->other_arch == NULL) {
160  LOG(llevError, "move_creator: Converter doesn't have other arch set: %s (%s, %d, %d)\n", converter->name ? converter->name : "(null)", converter->map->path, converter->x, converter->y);
161  return -1;
162  }
163  item = object_create_arch(converter->other_arch);
164  fix_generated_item(item, converter, 0, 0, GT_MINIMAL);
165  }
166 
167  if (CONV_NR(converter))
168  item->nrof = CONV_NR(converter);
169  if (nr)
170  item->nrof *= nr;
171  if (item->type != MONEY && shop_contains(converter))
173  else if (price_in < item->nrof*item->value && settings.allow_broken_converters == FALSE) {
174  LOG(llevError, "Broken converter %s at %s (%d, %d) in value %d, out value %d for %s\n", converter->name, converter->map->path, converter->x, converter->y, price_in, item->nrof*item->value, item->name);
176  return -1;
177  }
178  object_insert_in_map_at(item, converter->map, converter, 0, converter->x, converter->y);
179  return 1;
180 }
181 
189 static method_ret converter_type_move_on(object *trap, object *victim, object *originator) {
190  if (common_pre_ob_move_on(trap, victim, originator) == METHOD_ERROR)
191  return METHOD_OK;
192  if (convert_item(victim, trap) < 0) {
193  object *op;
194  char name[MAX_BUF];
195 
196  query_name(trap, name, MAX_BUF);
198  "The %s seems to be broken!", name);
199 
200  op = create_archetype("burnout");
201  if (op != NULL)
202  object_insert_in_map_at(op, trap->map, trap, 0, trap->x, trap->y);
203  }
204  common_post_ob_move_on(trap, victim, originator);
205  return METHOD_OK;
206 }
CONV_FROM
#define CONV_FROM(xyz)
Definition: converter.c:33
PLAYER
@ PLAYER
Definition: object.h:107
global.h
object_remove
void object_remove(object *op)
Definition: object.c:1819
llevError
@ llevError
Definition: logger.h:11
Settings::allow_broken_converters
int allow_broken_converters
Definition: global.h:311
object_create_clone
object * object_create_clone(object *asrc)
Definition: object.c:3880
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
obj::map
struct mapdef * map
Definition: object.h:300
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
FALSE
#define FALSE
Definition: compat.h:14
FOR_BELOW_PREPARE
#define FOR_BELOW_PREPARE(op_, it_)
Definition: define.h:704
METHOD_OK
#define METHOD_OK
Definition: ob_methods.h:15
guildjoin.ob
ob
Definition: guildjoin.py:42
MIN
#define MIN(x, y)
Definition: compat.h:21
FOR_BELOW_FINISH
#define FOR_BELOW_FINISH()
Definition: define.h:711
settings
struct Settings settings
Definition: init.c:39
FLAG_IS_A_TEMPLATE
#define FLAG_IS_A_TEMPLATE
Definition: define.h:366
m
static event_registration m
Definition: citylife.cpp:427
init_type_converter
void init_type_converter(void)
Definition: converter.c:78
object_unset_flag_inv
void object_unset_flag_inv(object *op, int flag)
Definition: object.c:3227
obj::name
sstring name
Definition: object.h:314
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:585
common_pre_ob_move_on
method_ret common_pre_ob_move_on(object *trap, object *victim, object *originator)
Definition: common_apply.c:51
make_face_from_files.str
str
Definition: make_face_from_files.py:24
CONVERTER
@ CONVERTER
Definition: object.h:216
obj::x
int16_t x
Definition: object.h:330
object_create_arch
object * object_create_arch(archetype *at)
Definition: arch.cpp:301
CONV_FROM_MATCH
#define CONV_FROM_MATCH(xyz, _match)
Definition: converter.c:38
register_move_on
void register_move_on(int ob_type, move_on_func method)
Definition: ob_types.c:89
obj::other_arch
struct archt * other_arch
Definition: object.h:418
rndm
int rndm(int min, int max)
Definition: utils.c:162
convert_item
static int convert_item(object *item, object *converter)
Definition: converter.c:91
sproto.h
wildcard_match
static int wildcard_match(const char *string, const char *candidate)
Definition: converter.c:45
converter_type_move_on
static method_ret converter_type_move_on(object *trap, object *victim, object *originator)
Definition: converter.c:189
MAX_BUF
#define MAX_BUF
Definition: define.h:35
fix_generated_item
void fix_generated_item(object *op, object *creator, int difficulty, int max_magic, int flags)
Definition: treasure.c:876
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:281
CONV_NEED
#define CONV_NEED(xyz)
Definition: converter.c:37
CONV_NR
#define CONV_NR(xyz)
Definition: converter.c:35
obj::y
int16_t y
Definition: object.h:330
method_ret
char method_ret
Definition: ob_methods.h:14
ob_types.h
CONV_LIMIT
#define CONV_LIMIT(xyz)
Definition: converter.c:36
sounds.h
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:262
item
Definition: item.py:1
reputation.victim
victim
Definition: reputation.py:14
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
give.op
op
Definition: give.py:33
shop.h
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
MSG_TYPE_APPLY_FAILURE
#define MSG_TYPE_APPLY_FAILURE
Definition: newclient.h:604
object_insert_in_map_at
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.c:2080
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.c:1546
FLAG_UNPAID
#define FLAG_UNPAID
Definition: define.h:236
object_decrease_nrof
object * object_decrease_nrof(object *op, uint32_t i)
Definition: object.c:2652
METHOD_ERROR
#define METHOD_ERROR
Definition: ob_methods.h:17
ob_methods.h
diamondslots.cost
int cost
Definition: diamondslots.py:21
mapdef::path
char path[HUGE_BUF]
Definition: map.h:358
shop_contains
bool shop_contains(object *ob)
Definition: shop.c:1276
TRUE
#define TRUE
Definition: compat.h:11
MSG_TYPE_APPLY
#define MSG_TYPE_APPLY
Definition: newclient.h:408
common_post_ob_move_on
void common_post_ob_move_on(object *trap, object *victim, object *originator)
Definition: common_apply.c:86
GT_MINIMAL
@ GT_MINIMAL
Definition: treasure.h:36
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Definition: main.c:319
MONEY
@ MONEY
Definition: object.h:137
obj::inv
struct obj * inv
Definition: object.h:293
give.name
name
Definition: give.py:27