Atrinik Server  4.0
shop.c
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
25 #include <global.h>
26 #include <check.h>
27 #include <checkstd.h>
28 #include <check_proto.h>
29 #include <toolkit/string.h>
30 #include <arch.h>
31 #include <object.h>
32 #include <object_methods.h>
33 
34 START_TEST(test_shop_get_cost)
35 {
36  object *money = arch_get("coppercoin");
37  ck_assert_int_eq(1, shop_get_cost(money, COST_BUY));
38  ck_assert_int_eq(1, shop_get_cost(money, COST_SELL));
39  ck_assert_int_eq(1, shop_get_cost(money, COST_TRUE));
40  money->nrof = 72;
41  ck_assert_int_eq(72, shop_get_cost(money, COST_BUY));
42  ck_assert_int_eq(72, shop_get_cost(money, COST_SELL));
43  ck_assert_int_eq(72, shop_get_cost(money, COST_TRUE));
44  money->nrof = 0;
46  ck_assert_int_eq(1, shop_get_cost(money, COST_BUY));
47  ck_assert_int_eq(1, shop_get_cost(money, COST_SELL));
48  ck_assert_int_eq(1, shop_get_cost(money, COST_TRUE));
49  object_destroy(money);
50 
51  money = arch_get("silvercoin");
52  ck_assert_int_eq(100, shop_get_cost(money, COST_BUY));
53  ck_assert_int_eq(100, shop_get_cost(money, COST_SELL));
54  ck_assert_int_eq(100, shop_get_cost(money, COST_TRUE));
55  money->nrof = 72;
56  ck_assert_int_eq(7200, shop_get_cost(money, COST_BUY));
57  ck_assert_int_eq(7200, shop_get_cost(money, COST_SELL));
58  ck_assert_int_eq(7200, shop_get_cost(money, COST_TRUE));
59  object_destroy(money);
60 
61  object *sword = arch_get("sword");
62  SET_FLAG(sword, FLAG_IDENTIFIED);
63  ck_assert_int_eq(sword->value, shop_get_cost(sword, COST_BUY));
64  ck_assert_int_eq(sword->value * 0.2, shop_get_cost(sword, COST_SELL));
65  ck_assert_int_eq(sword->value, shop_get_cost(sword, COST_TRUE));
66  sword->nrof = 5;
67  ck_assert_int_eq(sword->value * 5, shop_get_cost(sword, COST_BUY));
68  ck_assert_int_eq(sword->value * 5 * 0.2, shop_get_cost(sword, COST_SELL));
69  ck_assert_int_eq(sword->value * 5, shop_get_cost(sword, COST_TRUE));
70  SET_FLAG(sword, FLAG_CURSED);
71  ck_assert_int_eq(0, shop_get_cost(sword, COST_BUY));
72  ck_assert_int_eq(0, shop_get_cost(sword, COST_SELL));
73  ck_assert_int_eq(0, shop_get_cost(sword, COST_TRUE));
74  CLEAR_FLAG(sword, FLAG_DAMNED);
75  SET_FLAG(sword, FLAG_DAMNED);
76  ck_assert_int_eq(0, shop_get_cost(sword, COST_BUY));
77  ck_assert_int_eq(0, shop_get_cost(sword, COST_SELL));
78  ck_assert_int_eq(0, shop_get_cost(sword, COST_TRUE));
79  object_destroy(sword);
80 }
81 END_TEST
82 
83 START_TEST(test_shop_get_cost_string)
84 {
85  ck_assert_str_eq(shop_get_cost_string(0), "nothing");
86  ck_assert_str_eq(shop_get_cost_string(1), "1 copper coin");
87  ck_assert_str_eq(shop_get_cost_string(2), "2 copper coins");
88  ck_assert_str_eq(shop_get_cost_string(100), "1 silver coin");
89  ck_assert_str_eq(shop_get_cost_string(501),
90  "5 silver coins and 1 copper coin");
91  ck_assert_str_eq(shop_get_cost_string(10000), "1 gold coin");
92  ck_assert_str_eq(shop_get_cost_string(30000), "3 gold coins");
93  ck_assert_str_eq(shop_get_cost_string(6849602841), "68 amber coins, "
94  "4 mithril coins, 9 jade coins, 60 gold coins, 28 silver coins "
95  "and 41 copper coins");
96 }
97 END_TEST
98 
99 START_TEST(test_shop_get_cost_string_item)
100 {
101  object *sword = arch_get("sword");
102  SET_FLAG(sword, FLAG_IDENTIFIED);
103  sword->value = 0;
104  ck_assert_str_eq(shop_get_cost_string_item(sword, COST_BUY), "nothing");
105  ck_assert_str_eq(shop_get_cost_string_item(sword, COST_SELL), "nothing");
106  ck_assert_str_eq(shop_get_cost_string_item(sword, COST_TRUE), "nothing");
107  sword->value = 1;
108  ck_assert_str_eq(shop_get_cost_string_item(sword, COST_BUY),
109  "1 copper coin");
110  ck_assert_str_eq(shop_get_cost_string_item(sword, COST_SELL),
111  "1 copper coin");
112  ck_assert_str_eq(shop_get_cost_string_item(sword, COST_TRUE),
113  "1 copper coin");
114  sword->value = 11101;
115  ck_assert_str_eq(shop_get_cost_string_item(sword, COST_BUY),
116  "1 gold coin, 11 silver coins and 1 copper coin");
117  ck_assert_str_eq(shop_get_cost_string_item(sword, COST_SELL),
118  "22 silver coins and 20 copper coins");
119  ck_assert_str_eq(shop_get_cost_string_item(sword, COST_TRUE),
120  "1 gold coin, 11 silver coins and 1 copper coin");
121  object_destroy(sword);
122 }
123 END_TEST
124 
125 START_TEST(test_shop_get_money)
126 {
127  mapstruct *map;
128  object *pl;
129  check_setup_env_pl(&map, &pl);
130  object *sack = arch_get("sack");
131  sack = object_insert_into(sack, pl, 0);
132  object *money = object_insert_into(arch_get("coppercoin"), sack, 0);
133  money->nrof = 50;
134  money = object_insert_into(arch_get("silvercoin"), sack, 0);
135  money->nrof = 3;
136  ck_assert_uint_eq(shop_get_money(pl), 350);
137  ck_assert_uint_eq(shop_get_money(sack), 350);
138  money = object_insert_into(arch_get("goldcoin"), pl, 0);
139  money->nrof = 1;
140  ck_assert_uint_eq(shop_get_money(pl), 10350);
141  ck_assert_uint_eq(shop_get_money(sack), 350);
142  money = object_insert_into(arch_get("silvercoin"), pl, 0);
143  money->nrof = 30;
144  ck_assert_uint_eq(shop_get_money(pl), 13350);
145  ck_assert_uint_eq(shop_get_money(sack), 350);
146  money = object_insert_into(arch_get("coppercoin"), pl, 0);
147  money->nrof = 800;
148  ck_assert_uint_eq(shop_get_money(pl), 14150);
149  ck_assert_uint_eq(shop_get_money(sack), 350);
150  int64_t value;
151  bank_deposit(pl, "50 copper", &value);
152  ck_assert_uint_eq(value, 50);
153  ck_assert_uint_eq(bank_get_balance(pl), 50);
154  ck_assert_uint_eq(shop_get_money(pl), 14150);
155 }
156 END_TEST
157 
158 START_TEST(test_shop_pay)
159 {
160  mapstruct *map;
161  object *pl;
162  check_setup_env_pl(&map, &pl);
163  ck_assert(shop_pay(pl, 0));
164  object *sack = arch_get("sack");
165  sack = object_insert_into(sack, pl, 0);
166  object *money = object_insert_into(arch_get("coppercoin"), sack, 0);
167  money->nrof = 50;
168  money = object_insert_into(arch_get("silvercoin"), sack, 0);
169  money->nrof = 3;
170  money = object_insert_into(arch_get("goldcoin"), sack, 0);
171  money->nrof = 15;
172  money = object_insert_into(arch_get("goldcoin"), pl, 0);
173  money->nrof = 1;
174  money = object_insert_into(arch_get("coppercoin"), pl, 0);
175  money->nrof = 800;
176  money = object_insert_into(arch_get("ambercoin"), pl, 0);
177  money->nrof = 1;
178  int64_t value;
179  bank_deposit(pl, "500 copper", &value);
180  ck_assert_uint_eq(value, 500);
181  ck_assert_uint_eq(bank_get_balance(pl), 500);
182  int64_t total = 100161150;
183  ck_assert_uint_eq(shop_get_money(pl), total);
184  ck_assert(shop_pay(pl, 0));
185  ck_assert_uint_eq(shop_get_money(pl), total);
186  int64_t to_pay = 1;
187  ck_assert(shop_pay(pl, to_pay));
188  total -= to_pay;
189  ck_assert_uint_eq(shop_get_money(pl), total);
190  to_pay = 5009;
191  ck_assert(shop_pay(pl, to_pay));
192  total -= to_pay;
193  ck_assert_uint_eq(shop_get_money(pl), total);
194  ck_assert(!shop_pay(pl, 10000000000));
195  ck_assert(!shop_pay(pl, 5436565469565));
196  to_pay = 596079;
197  ck_assert(shop_pay(pl, to_pay));
198  total -= to_pay;
199  ck_assert_uint_eq(shop_get_money(pl), total);
200  to_pay = 11111;
201  ck_assert(shop_pay(pl, to_pay));
202  total -= to_pay;
203  ck_assert_uint_eq(shop_get_money(pl), total);
204  to_pay = total - 50;
205  ck_assert(shop_pay(pl, to_pay));
206  total -= to_pay;
207  ck_assert_uint_eq(shop_get_money(pl), total);
208  ck_assert(shop_pay(pl, total));
209  total = 0;
210  ck_assert_uint_eq(shop_get_money(pl), total);
211  ck_assert(!shop_pay(pl, 43534));
212  ck_assert(!shop_pay(pl, 1));
213  ck_assert(shop_pay(pl, 0));
214 }
215 END_TEST
216 
217 START_TEST(test_shop_pay_item)
218 {
219  mapstruct *map;
220  object *pl;
221  check_setup_env_pl(&map, &pl);
222  ck_assert(shop_pay(pl, 0));
223  object *sack = arch_get("sack");
224  sack = object_insert_into(sack, pl, 0);
225  object *sack2 = arch_get("sack");
226  sack2 = object_insert_into(sack2, sack, 0);
227  object *money = object_insert_into(arch_get("coppercoin"), sack, 0);
228  money->nrof = 50;
229  money = object_insert_into(arch_get("silvercoin"), sack, 0);
230  money->nrof = 3;
231  money = object_insert_into(arch_get("goldcoin"), sack, 0);
232  money->nrof = 15;
233  money = object_insert_into(arch_get("silvercoin"), sack2, 0);
234  money->nrof = 38;
235  money = object_insert_into(arch_get("goldcoin"), sack2, 0);
236  money->nrof = 168;
237  money = object_insert_into(arch_get("goldcoin"), pl, 0);
238  money->nrof = 1;
239  money = object_insert_into(arch_get("coppercoin"), pl, 0);
240  money->nrof = 800;
241  money = object_insert_into(arch_get("ambercoin"), pl, 0);
242  money->nrof = 1;
243  int64_t value;
244  bank_deposit(pl, "3 gold 1 silver 18 copper", &value);
245  ck_assert_uint_eq(value, 30118);
246  ck_assert_uint_eq(bank_get_balance(pl), 30118);
247  int64_t total = 101844950;
248  ck_assert_uint_eq(shop_get_money(pl), total);
249  object *sword = arch_get("sword");
250  SET_FLAG(sword, FLAG_IDENTIFIED);
251  sword->value = 0;
252  ck_assert(shop_pay_item(pl, sword));
253  ck_assert_uint_eq(shop_get_money(pl), total);
254  int64_t to_pay = 1;
255  sword->value = to_pay;
256  ck_assert(shop_pay_item(pl, sword));
257  total -= to_pay;
258  ck_assert_uint_eq(shop_get_money(pl), total);
259  to_pay = 8402;
260  sword->value = to_pay;
261  ck_assert(shop_pay_item(pl, sword));
262  total -= to_pay;
263  ck_assert_uint_eq(shop_get_money(pl), total);
264  sword->value = 10000000000;
265  ck_assert(!shop_pay_item(pl, sword));
266  sword->value = 10000000000;
267  ck_assert(!shop_pay_item(pl, sword));
268  to_pay = 683921;
269  sword->value = to_pay;
270  ck_assert(shop_pay_item(pl, sword));
271  total -= to_pay;
272  ck_assert_uint_eq(shop_get_money(pl), total);
273  to_pay = 38392;
274  sword->value = to_pay;
275  ck_assert(shop_pay_item(pl, sword));
276  total -= to_pay;
277  ck_assert_uint_eq(shop_get_money(pl), total);
278  to_pay = total - 50;
279  sword->value = to_pay;
280  ck_assert(shop_pay_item(pl, sword));
281  total -= to_pay;
282  ck_assert_uint_eq(shop_get_money(pl), total);
283  to_pay = total;
284  sword->value = to_pay;
285  ck_assert(shop_pay_item(pl, sword));
286  total -= total;
287  ck_assert_uint_eq(shop_get_money(pl), total);
288  sword->value = 40394;
289  ck_assert(!shop_pay_item(pl, sword));
290  sword->value = 1;
291  ck_assert(!shop_pay_item(pl, sword));
292  sword->value = 0;
293  ck_assert(shop_pay_item(pl, sword));
294  object_destroy(sword);
295 }
296 END_TEST
297 
298 START_TEST(test_shop_pay_items)
299 {
300  mapstruct *map;
301  object *pl;
302  check_setup_env_pl(&map, &pl);
303  ck_assert(shop_pay_items(pl));
304  object *sword = arch_get("sword");
305  SET_FLAG(sword, FLAG_IDENTIFIED);
306  SET_FLAG(sword, FLAG_UNPAID);
307  sword->value = 500;
308  sword = object_insert_into(sword, pl, 0);
309  object *sword2 = arch_get("sword");
310  SET_FLAG(sword2, FLAG_IDENTIFIED);
311  SET_FLAG(sword2, FLAG_UNPAID);
312  sword2->value = 200;
313  sword2 = object_insert_into(sword2, pl, 0);
314  ck_assert(!shop_pay_items(pl));
315  object *money = object_insert_into(arch_get("coppercoin"), pl, 0);
316  money->nrof = 38;
317  ck_assert(!shop_pay_items(pl));
318  ck_assert(QUERY_FLAG(sword, FLAG_UNPAID));
319  ck_assert(QUERY_FLAG(sword2, FLAG_UNPAID));
320  money = object_insert_into(arch_get("coppercoin"), pl, 0);
321  money->nrof = 210;
322  ck_assert(!shop_pay_items(pl));
323  ck_assert(QUERY_FLAG(sword, FLAG_UNPAID));
324  ck_assert(!QUERY_FLAG(sword2, FLAG_UNPAID));
325  money = object_insert_into(arch_get("coppercoin"), pl, 0);
326  money->nrof = 710;
327  ck_assert(shop_pay_items(pl));
328  ck_assert(!QUERY_FLAG(sword, FLAG_UNPAID));
329  ck_assert(!QUERY_FLAG(sword2, FLAG_UNPAID));
330 }
331 END_TEST
332 
333 START_TEST(test_shop_sell_item)
334 {
335  mapstruct *map;
336  object *pl;
337  check_setup_env_pl(&map, &pl);
338  object *sword = arch_get("sword");
339  sword->value = 0;
340  shop_sell_item(pl, sword);
341  ck_assert(QUERY_FLAG(sword, FLAG_IDENTIFIED));
342  ck_assert(QUERY_FLAG(sword, FLAG_UNPAID));
343  int64_t total = sword->arch->clone.value * 0.2;
344  ck_assert_uint_eq(shop_get_money(pl), total);
345  object_destroy(sword);
346  sword = arch_get("sword");
347  sword->value = 100;
348  shop_sell_item(pl, sword);
349  ck_assert(QUERY_FLAG(sword, FLAG_IDENTIFIED));
350  ck_assert(QUERY_FLAG(sword, FLAG_UNPAID));
351  total += sword->arch->clone.value * 0.2;
352  ck_assert_uint_eq(shop_get_money(pl), total);
353  object_destroy(sword);
354  sword = arch_get("sword");
355  SET_FLAG(sword, FLAG_IDENTIFIED);
356  sword->value = 0;
357  shop_sell_item(pl, sword);
358  ck_assert(QUERY_FLAG(sword, FLAG_IDENTIFIED));
359  ck_assert(QUERY_FLAG(sword, FLAG_UNPAID));
360  ck_assert_uint_eq(shop_get_money(pl), total);
361  object_destroy(sword);
362  sword = arch_get("sword");
363  SET_FLAG(sword, FLAG_IDENTIFIED);
364  FREE_AND_COPY_HASH(sword->custom_name, "xxx");
365  sword->value = 100;
366  shop_sell_item(pl, sword);
367  ck_assert(QUERY_FLAG(sword, FLAG_IDENTIFIED));
368  ck_assert(QUERY_FLAG(sword, FLAG_UNPAID));
369  total += sword->value * 0.2;
370  ck_assert_uint_eq(shop_get_money(pl), total);
371  ck_assert_ptr_eq(sword->custom_name, NULL);
372  object_destroy(sword);
373 }
374 END_TEST
375 
376 START_TEST(test_shop_insert_coins)
377 {
378  mapstruct *map;
379  object *pl;
380  check_setup_env_pl(&map, &pl);
381  int64_t total = 0;
382  shop_insert_coins(pl, 0);
383  ck_assert_uint_eq(shop_get_money(pl), total);
384  int64_t to_insert = 1;
385  shop_insert_coins(pl, to_insert);
386  total += to_insert;
387  ck_assert_uint_eq(shop_get_money(pl), total);
388  to_insert = 1203940;
389  shop_insert_coins(pl, to_insert);
390  total += to_insert;
391  ck_assert_uint_eq(shop_get_money(pl), total);
392  object *sack = arch_get("sack");
393  FREE_AND_COPY_HASH(sack->race, "gold");
394  sack = object_insert_into(sack, pl, 0);
395  object_apply(sack, pl, 0);
396  ck_assert(QUERY_FLAG(sack, FLAG_APPLIED));
397  to_insert = 1;
398  shop_insert_coins(pl, to_insert);
399  total += to_insert;
400  ck_assert_uint_eq(shop_get_money(pl), total);
401  ck_assert_ptr_ne(sack->inv, NULL);
402  ck_assert_str_eq(sack->inv->arch->name, "coppercoin");
403  object_apply(sack, pl, 0);
404  to_insert = 69302;
405  shop_insert_coins(pl, to_insert);
406  total += to_insert;
407  ck_assert_uint_eq(shop_get_money(pl), total);
408  ck_assert_ptr_ne(sack->inv, NULL);
409  ck_assert_ptr_ne(sack->inv->below, NULL);
410  ck_assert_str_eq(sack->inv->below->arch->name, "goldcoin");
411  ck_assert_uint_eq(sack->inv->below->nrof, 6);
412  object_apply(sack, pl, 0);
413  ck_assert(!QUERY_FLAG(sack, FLAG_APPLIED));
414 
415  for (int i = 0; i < 10000; i++) {
416  shop_insert_coins(pl, 99);
417  }
418 
419  ck_assert_ptr_ne(GET_MAP_OB(pl->map, pl->x, pl->y), NULL);
420  ck_assert_str_eq(GET_MAP_OB(pl->map, pl->x, pl->y)->arch->name,
421  "coppercoin");
422 }
423 END_TEST
424 
425 static Suite *suite(void)
426 {
427  Suite *s = suite_create("shop");
428  TCase *tc_core = tcase_create("Core");
429 
430  tcase_add_unchecked_fixture(tc_core, check_setup, check_teardown);
431  tcase_add_checked_fixture(tc_core, check_test_setup, check_test_teardown);
432 
433  suite_add_tcase(s, tc_core);
434  tcase_add_test(tc_core, test_shop_get_cost);
435  tcase_add_test(tc_core, test_shop_get_cost_string);
436  tcase_add_test(tc_core, test_shop_get_cost_string_item);
437  tcase_add_test(tc_core, test_shop_get_money);
438  tcase_add_test(tc_core, test_shop_pay);
439  tcase_add_test(tc_core, test_shop_pay_item);
440  tcase_add_test(tc_core, test_shop_pay_items);
441  tcase_add_test(tc_core, test_shop_sell_item);
442  tcase_add_test(tc_core, test_shop_insert_coins);
443 
444  return s;
445 }
446 
447 void check_server_shop(void)
448 {
449  check_run_suite(suite(), __FILE__);
450 }
int64_t shop_get_cost(object *op, int mode)
Definition: shop.c:43
#define FREE_AND_COPY_HASH(_sv_, _nv_)
Definition: global.h:100
void object_destroy(object *ob)
Definition: object.c:1441
const char * shop_get_cost_string(int64_t cost)
Definition: shop.c:178
const char * shop_get_cost_string_item(object *op, int mode)
Definition: shop.c:238
bool shop_pay(object *op, int64_t to_pay)
Definition: shop.c:428
const char * race
Definition: object.h:174
#define FLAG_CURSED
Definition: define.h:1154
bool shop_pay_items(object *op)
Definition: shop.c:542
object * arch_get(const char *name)
Definition: arch.c:430
int bank_deposit(object *op, const char *text, int64_t *value)
Definition: bank.c:300
#define QUERY_FLAG(xyz, p)
Definition: define.h:761
struct archetype * arch
Definition: object.h:225
int object_apply(object *op, object *applier, int aflags)
#define FLAG_DAMNED
Definition: define.h:1158
int16_t y
Definition: object.h:276
#define COST_BUY
Definition: define.h:1370
#define COST_TRUE
Definition: define.h:1374
int64_t shop_get_money(object *op)
Definition: shop.c:251
object * object_insert_into(object *op, object *where, int flag)
Definition: object.c:2158
struct mapdef * map
Definition: object.h:139
#define FLAG_UNPAID
Definition: define.h:1251
#define SET_FLAG(xyz, p)
Definition: define.h:741
struct obj * below
Definition: object.h:114
void shop_sell_item(object *op, object *item)
Definition: shop.c:554
uint32_t nrof
Definition: object.h:264
#define COST_SELL
Definition: define.h:1372
int16_t x
Definition: object.h:273
void shop_insert_coins(object *op, int64_t value)
Definition: shop.c:587
#define FLAG_APPLIED
Definition: define.h:1182
#define CLEAR_FLAG(xyz, p)
Definition: define.h:751
shstr * name
More definite name, like "kobold".
Definition: arch.h:46
bool shop_pay_item(object *op, object *item)
Definition: shop.c:465
struct obj * inv
Definition: object.h:123
shstr * custom_name
Definition: object.h:190
Definition: map.h:536
int64_t value
Definition: object.h:240
object clone
An object from which to do object_copy().
Definition: arch.h:47
#define FLAG_IDENTIFIED
Definition: define.h:980
int64_t bank_get_balance(object *op)
Definition: bank.c:278