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  "kobold's finger",
130  "use magic item",
131  NULL,
132  };
133  cf_srandom(94);
134  treasurelist *list = find_treasurelist("c_knight");
135  fail_unless(list, "missing list 'c_knight'");
136  object *k = create_archetype("kobold");
137  fail_unless(k, "missing kobold");
139  create_treasure(list, k, 0, 0, 0);
140  check_treasure_inv(k, items);
141 }
142 END_TEST
143 
144 static bool check_treasure_arch(object *op, const char **first, const char **last) {
145  object *inv = op->inv;
146  fail_unless(inv, "missing inv");
147  fail_unless(inv->below == NULL, "unexpected below");
148  while (first != last) {
149  if (strcmp(*first, inv->arch->name) == 0) {
150  return true;
151  }
152  ++first;
153  }
154  return false;
155 }
156 
157 const char *allTraps[] = {
158  // magical traps
159  "rune_medium_fireball",
160  "rune_burning_hands",
161  "rune_poison_cloud",
162  "rune_create_bomb",
163  "rune_paralysis",
164  "rune_shock",
165  "rune_confusion",
166  "rune_icestorm",
167  "rune_drain_magic",
168  "rune_blast",
169  "rune_fire",
170  "rune_frost",
171  // nastier traps
172  "rune_summon_air_elemental",
173  "rune_dragonbreath",
174  "rune_large_icestorm",
175  "rune_large_fireball",
176  "rune_ball_lightning",
177  "rune_summon_devil",
178  "rune_summon_earth_elemental",
179  "rune_summon_fire_elemental",
180  "rune_summon_water_elemental",
181  "rune_death",
182  NULL};
183 
184 
185 START_TEST(test_magic_limit) {
186  cf_srandom(19);
187  treasurelist *list = find_treasurelist("magical_traps");
188  fail_unless(list, "missing list");
189  for (int i = 0; i < 1000; i++) {
190  object *k = create_archetype("kobold");
191  create_treasure(list, k, GT_INVISIBLE, 0, 0);
192  if (!k->inv) {
193  continue;
194  }
195  fail_unless(check_treasure_arch(k, allTraps, allTraps + 12), "wrong inv %s", k->inv->arch->name);
196  }
197 
198  int nastier = 0;
199  for (int i = 0; i < 1000; i++) {
200  object *k = create_archetype("kobold");
201  create_treasure(list, k, GT_INVISIBLE, 6, 0);
202  if (check_treasure_arch(k, allTraps + 12, allTraps + 22)) {
203  nastier++;
204  }
205  }
206  fail_unless(nastier > 0, "should get a nastier trap");
207 }
208 END_TEST
209 
210 static void do_magic(int difficulty, uint8_t value, int8_t adjustment) {
211  cf_srandom(57);
212  treasurelist *list = find_treasurelist("magical_traps");
213  fail_unless(list, "missing list");
214 
215  treasure t;
216  memset(&t, 0, sizeof(t));
217  t.chance = 1;
218  t.name = add_string(list->name);
219  t.list_magic_value = value;
220  t.list_magic_adjustment = adjustment;
221  treasurelist tl;
222  memset(&tl, 0, sizeof(tl));
223  tl.items = &t;
224  tl.total_chance = 1;
225 
226  int nastier = 0;
227  for (int i = 0; (i < 1000) && (nastier == 0); i++) {
228  object *k = create_archetype("kobold");
229  create_treasure(&tl, k, GT_INVISIBLE, difficulty, 0);
230  if (!k->inv) {
231  continue;
232  }
233  if (check_treasure_arch(k, allTraps + 12, allTraps + 22)) {
234  nastier++;
235  break;
236  }
237  }
238  fail_unless(nastier > 0, "should get a nastier trap");
239 }
240 
241 START_TEST(test_magic_set) {
242  do_magic(0, 6, 0);
243 }
244 END_TEST
245 
246 START_TEST(test_magic_adjustment) {
247  do_magic(3, 0, 3);
248 }
249 END_TEST
250 
251 static object *do_artifact(const char *name) {
252  treasure t;
253  memset(&t, 0, sizeof(t));
254  t.chance = 1;
255  t.item = try_find_archetype("dagger");
256  fail_unless(t.item, "missing dagger");
257  t.artifact = add_string(name);
258  treasurelist tl;
259  memset(&tl, 0, sizeof(tl));
260  tl.items = &t;
261  tl.total_chance = 1;
262  object *k = create_archetype("kobold");
263  create_treasure(&tl, k, 0, 30, 0);
264  return k;
265 }
266 
267 START_TEST(test_artifact_valid) {
268  sstring p = add_string("Poisoning");
269  object *k = do_artifact(p);
270  fail_unless(k->inv, "nothing generated");
271  fail_unless(k->inv->artifact == p, "artifact not generated");
272 }
273 END_TEST
274 
275 START_TEST(test_artifact_invalid) {
276  object *k = do_artifact("Xebinon");
277  fail_unless(k->inv == NULL, "something was generated");
278 }
279 END_TEST
280 
281 START_TEST(test_artifact_not_existing) {
282  object *k = do_artifact("garbage");
283  fail_unless(k->inv == NULL, "something was generated");
284 }
285 END_TEST
286 
287 static Suite *treasure_suite(void) {
288  Suite *s = suite_create("treasure");
289  TCase *tc_core = tcase_create("Core");
290 
291  /*setup and teardown will be called before each test in testcase 'tc_core' */
292  tcase_add_checked_fixture(tc_core, setup, teardown);
293 
294  suite_add_tcase(s, tc_core);
295  tcase_add_test(tc_core, test_add_treasure_in_list);
296  tcase_add_test(tc_core, test_treasure_remove_item);
297  tcase_add_test(tc_core, test_create_treasure_one);
298  tcase_add_test(tc_core, test_create_treasure_all);
299  tcase_add_test(tc_core, test_magic_limit);
300  tcase_add_test(tc_core, test_magic_set);
301  tcase_add_test(tc_core, test_magic_adjustment);
302  tcase_add_test(tc_core, test_artifact_valid);
303  tcase_add_test(tc_core, test_artifact_invalid);
304  tcase_add_test(tc_core, test_artifact_not_existing);
305 
306  return s;
307 }
308 
309 int main(void) {
310  int nf;
311  Suite *s = treasure_suite();
312  SRunner *sr = srunner_create(s);
313 
314 
315  /* to debug, uncomment this line */
316  srunner_set_fork_status(sr, CK_NOFORK);
317 
318  srunner_set_xml(sr, LOGDIR "/unit/common/treasure.xml");
319  srunner_set_log(sr, LOGDIR "/unit/common/treasure.out");
320  srunner_run_all(sr, CK_ENV); /*verbosity from env variable*/
321  nf = srunner_ntests_failed(sr);
322  srunner_free(sr);
323  return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
324 }
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:144
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:251
obj::artifact
sstring artifact
Definition: object.h:320
guildoracle.list
list
Definition: guildoracle.py:87
commongive.inv
inv
Definition: commongive.py:28
find_treasurelist
treasurelist * find_treasurelist(const char *name)
Definition: assets.cpp:253
create_treasure
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
Definition: treasure.cpp:256
treasurestruct
Definition: treasure.h:63
allTraps
const char * allTraps[]
Definition: check_treasure.cpp:157
toolkit_common.h
cctk_setlog
void cctk_setlog(const char *logfile)
Definition: toolkit_common.cpp:64
GT_INVISIBLE
@ GT_INVISIBLE
Definition: treasure.h:32
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
sstring
const typedef char * sstring
Definition: global.h:43
treasure_suite
static END_TEST Suite * treasure_suite(void)
Definition: check_treasure.cpp:287
empty
const char * empty[]
Definition: check_treasure.cpp:107
treasure_remove_item
void treasure_remove_item(treasurelist *list, int position)
Definition: treasure.cpp:1433
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:279
treasureliststruct::total_chance
int16_t total_chance
Definition: treasure.h:87
obj::arch
struct archt * arch
Definition: object.h:420
treasureliststruct::items
struct treasurestruct * items
Definition: treasure.h:92
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
give.op
op
Definition: give.py:33
autojail.value
value
Definition: autojail.py:6
main
int main(void)
Definition: check_treasure.cpp:309
treasure_insert
treasure * treasure_insert(treasurelist *list, int position)
Definition: treasure.cpp:1410
treasurestruct::next
struct treasurestruct * next
Definition: treasure.h:69
try_find_archetype
archetype * try_find_archetype(const char *name)
Definition: assets.cpp:274
archt::name
sstring name
Definition: object.h:473
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:210
treasureliststruct
Definition: treasure.h:85
obj::inv
struct obj * inv
Definition: object.h:296
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