Crossfire Server, Trunk
check_treasure.cpp
Go to the documentation of this file.
1 /*
2  * static char *rcsid_check_treasure_c =
3  * "$Id$";
4  */
5 
6 /*
7  * CrossFire, A Multiplayer game for X-windows
8  *
9  * Copyright (C) 2002,2011 Mark Wedel & Crossfire Development Team
10  * Copyright (C) 1992 Frank Tore Johansen
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  *
26  * The authors can be reached via e-mail at crossfire-devel@real-time.com
27  */
28 
29 /*
30  * This is the unit tests file for common/treasure.c
31  */
32 
33 #include <stdlib.h>
34 #include <check.h>
35 #include <global.h>
36 #include <toolkit_common.h>
37 
38 static void setup(void) {
39  cctk_setdatadir(SOURCE_ROOT "lib");
40  cctk_setlog(LOGDIR "/unit/common/treasure.out");
42 }
43 
44 static void teardown(void) {
45  /* put any cleanup steps here, they will be run after each testcase */
46 }
47 
48 START_TEST(test_add_treasure_in_list) {
50  list.items = NULL;
51  treasure *first = treasure_insert(&list, 10);
52  FAIL_UNLESS(list.items == first, "First not inserted in first place");
53 
54  treasure *new_first = treasure_insert(&list, -1);
55  FAIL_UNLESS(list.items == new_first, "First not replaced");
56  FAIL_UNLESS(new_first->next == first, "List not correctly linked");
57 
58  treasure *second = treasure_insert(&list, 11);
59  FAIL_UNLESS(first->next == second, "Second not inserted at end");
60  FAIL_UNLESS(second->next == NULL, "Second should be the last");
61 
62  treasure *between = treasure_insert(&list, 2);
63  FAIL_UNLESS(first->next == between, "Between should be after first");
64  FAIL_UNLESS(between->next == second, "Between should be before second");
65 
66  treasure *other_first = treasure_insert(&list, 0);
67  FAIL_UNLESS(list.items == other_first, "Other first should be first item");
68  FAIL_UNLESS(other_first->next == new_first, "Other first should be before new first");
69 }
70 END_TEST
71 
72 START_TEST(test_treasure_remove_item) {
74  memset(&list, 0, sizeof(list));
75  /*treasure *first =*/ treasure_insert(&list, 0);
76  treasure *second = treasure_insert(&list, 1);
77  /*treasure *third =*/ treasure_insert(&list, 2);
78  treasure *fourth = treasure_insert(&list, 3);
79  /*treasure *fifth =*/ treasure_insert(&list, 4);
80 
82  FAIL_UNLESS(list.items == second, "first not removed");
84  FAIL_UNLESS(second->next == fourth, "third not removed");
86  FAIL_UNLESS(fourth->next == NULL, "fifth not removed");
87 }
88 END_TEST
89 
90 static void check_treasure_inv(object *op, const char **items) {
91  object *inv = op->inv;
92  while ((*items) != NULL) {
93  FAIL_UNLESS(inv != NULL, "missing item %s", *items);
94  FAIL_UNLESS(strcmp(inv->name, *items) == 0, "got %s instead of %s", inv->name, *items);
95  ++items;
96  inv = inv->below;
97  }
98  if (inv) {
99  while (inv) {
100  printf(" => unexpected inv %s\n", inv->name);
101  inv = inv->below;
102  }
103  FAIL_UNLESS(inv != NULL, "got extra inv");
104  }
105 }
106 
107 const char *empty[] = {NULL};
108 
109 START_TEST(test_create_treasure_one) {
110  const char *items[] = {"kobold's heart", NULL};
111  cf_srandom(145);
112  treasurelist *list = find_treasurelist("ape_parts");
113  FAIL_UNLESS(list, "missing list 'ape_parts'");
114  object *k = create_archetype("kobold");
115  FAIL_UNLESS(k, "missing kobold");
117  create_treasure(list, k, 0, 0, 0);
118  check_treasure_inv(k, items);
119 }
120 END_TEST
121 
122 START_TEST(test_create_treasure_all) {
123  const char *items[] = {
124  "arrow",
125  "bow",
126  "ring",
127  "plate mail",
128  "long sword",
129  "use magic item",
130  NULL,
131  };
132  cf_srandom(94);
133  treasurelist *list = find_treasurelist("c_knight");
134  FAIL_UNLESS(list, "missing list 'c_knight'");
135  object *k = create_archetype("kobold");
136  FAIL_UNLESS(k, "missing kobold");
138  create_treasure(list, k, 0, 0, 0);
139  check_treasure_inv(k, items);
140 }
141 END_TEST
142 
143 static bool check_treasure_arch(object *op, const char **first, const char **last) {
144  object *inv = op->inv;
145  FAIL_UNLESS(inv, "missing inv");
146  FAIL_UNLESS(inv->below == NULL, "unexpected below");
147  while (first != last) {
148  if (strcmp(*first, inv->arch->name) == 0) {
149  return true;
150  }
151  ++first;
152  }
153  return false;
154 }
155 
156 const char *allTraps[] = {
157  // magical traps
158  "rune_medium_fireball",
159  "rune_burning_hands",
160  "rune_poison_cloud",
161  "rune_create_bomb",
162  "rune_paralysis",
163  "rune_shock",
164  "rune_confusion",
165  "rune_icestorm",
166  "rune_drain_magic",
167  "rune_blast",
168  "rune_fire",
169  "rune_frost",
170  // nastier traps
171  "rune_summon_air_elemental",
172  "rune_dragonbreath",
173  "rune_large_icestorm",
174  "rune_large_fireball",
175  "rune_ball_lightning",
176  "rune_summon_devil",
177  "rune_summon_earth_elemental",
178  "rune_summon_fire_elemental",
179  "rune_summon_water_elemental",
180  "rune_death",
181  NULL};
182 
183 
184 START_TEST(test_magic_limit) {
185  cf_srandom(19);
186  treasurelist *list = find_treasurelist("magical_traps");
187  FAIL_UNLESS(list, "missing list");
188  for (int i = 0; i < 1000; i++) {
189  object *k = create_archetype("kobold");
190  create_treasure(list, k, GT_INVISIBLE, 0, 0);
191  if (!k->inv) {
192  continue;
193  }
194  FAIL_UNLESS(check_treasure_arch(k, allTraps, allTraps + 12), "wrong inv %s", k->inv->arch->name);
195  }
196 
197  int nastier = 0;
198  for (int i = 0; i < 1000; i++) {
199  object *k = create_archetype("kobold");
200  create_treasure(list, k, GT_INVISIBLE, 6, 0);
201  if (check_treasure_arch(k, allTraps + 12, allTraps + 22)) {
202  nastier++;
203  }
204  }
205  FAIL_UNLESS(nastier > 0, "should get a nastier trap");
206 }
207 END_TEST
208 
209 static void do_magic(int difficulty, uint8_t value, int8_t adjustment) {
210  cf_srandom(57);
211  treasurelist *list = find_treasurelist("magical_traps");
212  FAIL_UNLESS(list, "missing list");
213 
214  treasure t;
215  memset(&t, 0, sizeof(t));
216  t.chance = 1;
217  t.name = add_string(list->name);
218  t.list_magic_value = value;
219  t.list_magic_adjustment = adjustment;
220  treasurelist tl;
221  memset(&tl, 0, sizeof(tl));
222  tl.items = &t;
223  tl.total_chance = 1;
224 
225  int nastier = 0;
226  for (int i = 0; (i < 1000) && (nastier == 0); i++) {
227  object *k = create_archetype("kobold");
228  create_treasure(&tl, k, GT_INVISIBLE, difficulty, 0);
229  if (!k->inv) {
230  continue;
231  }
232  if (check_treasure_arch(k, allTraps + 12, allTraps + 22)) {
233  nastier++;
234  break;
235  }
236  }
237  FAIL_UNLESS(nastier > 0, "should get a nastier trap");
238 }
239 
240 START_TEST(test_magic_set) {
241  do_magic(0, 6, 0);
242 }
243 END_TEST
244 
245 START_TEST(test_magic_adjustment) {
246  do_magic(3, 0, 3);
247 }
248 END_TEST
249 
250 static object *do_artifact(const char *name) {
251  treasure t;
252  memset(&t, 0, sizeof(t));
253  t.chance = 1;
254  t.item = try_find_archetype("dagger");
255  FAIL_UNLESS(t.item, "missing dagger");
256  t.artifact = add_string(name);
257  treasurelist tl;
258  memset(&tl, 0, sizeof(tl));
259  tl.items = &t;
260  tl.total_chance = 1;
261  object *k = create_archetype("kobold");
262  create_treasure(&tl, k, 0, 30, 0);
263  return k;
264 }
265 
266 START_TEST(test_artifact_valid) {
267  sstring p = add_string("Poisoning");
268  object *k = do_artifact(p);
269  FAIL_UNLESS(k->inv, "nothing generated");
270  FAIL_UNLESS(k->inv->artifact == p, "artifact not generated");
271 }
272 END_TEST
273 
274 START_TEST(test_artifact_invalid) {
275  object *k = do_artifact("Xebinon");
276  FAIL_UNLESS(k->inv == NULL, "something was generated");
277 }
278 END_TEST
279 
280 START_TEST(test_artifact_not_existing) {
281  object *k = do_artifact("garbage");
282  FAIL_UNLESS(k->inv == NULL, "something was generated");
283 }
284 END_TEST
285 
286 static Suite *treasure_suite(void) {
287  Suite *s = suite_create("treasure");
288  TCase *tc_core = tcase_create("Core");
289 
290  /*setup and teardown will be called before each test in testcase 'tc_core' */
291  tcase_add_checked_fixture(tc_core, setup, teardown);
292 
293  suite_add_tcase(s, tc_core);
294  tcase_add_test(tc_core, test_add_treasure_in_list);
295  tcase_add_test(tc_core, test_treasure_remove_item);
296  tcase_add_test(tc_core, test_create_treasure_one);
297  tcase_add_test(tc_core, test_create_treasure_all);
298  tcase_add_test(tc_core, test_magic_limit);
299  tcase_add_test(tc_core, test_magic_set);
300  tcase_add_test(tc_core, test_magic_adjustment);
301  tcase_add_test(tc_core, test_artifact_valid);
302  tcase_add_test(tc_core, test_artifact_invalid);
303  tcase_add_test(tc_core, test_artifact_not_existing);
304 
305  return s;
306 }
307 
308 int main(void) {
309  int nf;
310  Suite *s = treasure_suite();
311  SRunner *sr = srunner_create(s);
312 
313 
314  /* to debug, uncomment this line */
315  srunner_set_fork_status(sr, CK_NOFORK);
316 
317  srunner_set_xml(sr, LOGDIR "/unit/common/treasure.xml");
318  srunner_set_log(sr, LOGDIR "/unit/common/treasure.out");
319  srunner_run_all(sr, CK_ENV); /*verbosity from env variable*/
320  nf = srunner_ntests_failed(sr);
321  srunner_free(sr);
322  return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
323 }
global.h
START_TEST
START_TEST(test_add_treasure_in_list)
Definition: check_treasure.cpp:48
check_treasure_arch
static END_TEST bool check_treasure_arch(object *op, const char **first, const char **last)
Definition: check_treasure.cpp:143
object::inv
object * inv
Definition: object.h:298
treasurelist::items
treasure * items
Definition: treasure.h:92
cctk_setdatadir
void cctk_setdatadir(const char *datadir)
Definition: toolkit_common.cpp:69
do_artifact
static END_TEST object * do_artifact(const char *name)
Definition: check_treasure.cpp:250
object::arch
struct archetype * arch
Definition: object.h:424
treasurelist::total_chance
int16_t total_chance
Definition: treasure.h:87
guildoracle.list
list
Definition: guildoracle.py:87
commongive.inv
inv
Definition: commongive.py:29
find_treasurelist
treasurelist * find_treasurelist(const char *name)
Definition: assets.cpp:249
create_treasure
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
Definition: treasure.cpp:263
FAIL_UNLESS
#define FAIL_UNLESS(expr,...)
Definition: toolkit_common.h:11
allTraps
const char * allTraps[]
Definition: check_treasure.cpp:156
toolkit_common.h
cctk_setlog
void cctk_setlog(const char *logfile)
Definition: toolkit_common.cpp:64
GT_INVISIBLE
@ GT_INVISIBLE
Definition: treasure.h:32
treasurelist
Definition: treasure.h:85
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
treasure_suite
static END_TEST Suite * treasure_suite(void)
Definition: check_treasure.cpp:286
empty
const char * empty[]
Definition: check_treasure.cpp:107
treasure::next
treasure * next
Definition: treasure.h:69
treasure_remove_item
void treasure_remove_item(treasurelist *list, int position)
Definition: treasure.cpp:1451
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:278
cctk_init_std_archetypes
void cctk_init_std_archetypes(void)
Definition: toolkit_common.cpp:83
Floor.t
t
Definition: Floor.py:62
cf_srandom
void cf_srandom(unsigned long seed)
Definition: cf_random.cpp:9
teardown
static void teardown(void)
Definition: check_treasure.cpp:44
object::artifact
sstring artifact
Definition: object.h:322
sstring
const typedef char * sstring
Definition: sstring.h:2
give.op
op
Definition: give.py:33
autojail.value
value
Definition: autojail.py:6
main
int main(void)
Definition: check_treasure.cpp:308
treasure_insert
treasure * treasure_insert(treasurelist *list, int position)
Definition: treasure.cpp:1428
try_find_archetype
archetype * try_find_archetype(const char *name)
Definition: assets.cpp:270
archetype::name
sstring name
Definition: object.h:484
treasure
Definition: treasure.h:63
setup
static void setup(void)
Definition: check_treasure.cpp:38
do_magic
static END_TEST void do_magic(int difficulty, uint8_t value, int8_t adjustment)
Definition: check_treasure.cpp:209
check_treasure_inv
static END_TEST void check_treasure_inv(object *op, const char **items)
Definition: check_treasure.cpp:90
give.name
name
Definition: give.py:27