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;
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 }
player::next
player * next
Definition: player.h:106
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:422
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
name
Plugin animator file specs[Config] name
Definition: animfiles.txt:4
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
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
Floor.t
t
Definition: Floor.py:62
main
int main(void)
Definition: check_treasure.cpp:308
treasure_insert
treasure * treasure_insert(treasurelist *list, int position)
Definition: treasure.cpp:1428
first
Crossfire Protocol most of the time after the actual code was already omit certain important and possibly make life miserable any new developer or curious player should be able to find most of the relevant information here If inconsistencies are found or this documentation proves to be consider the latest server side protocol code in the public source code repository as the authoritative reference Introduction If you were ever curious enough to telnet or netcat to a Crossfire chances are you were sorely disappointed While the protocol may seem to use plain text at first
Definition: protocol.txt:20
try_find_archetype
archetype * try_find_archetype(const char *name)
Definition: assets.cpp:270
archetype::name
sstring name
Definition: object.h:475
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