Crossfire Server, Trunk
check_monster_change.cpp
Go to the documentation of this file.
1 /*
2  * CrossFire, A Multiplayer game for X-windows
3  *
4  * Copyright (C) 2002-2018 Mark Wedel & Crossfire Development Team
5  * Copyright (C) 1992 Frank Tore Johansen
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  * The authors can be reached via e-mail at crossfire-devel@real-time.com
22  */
23 
24 /*
25  * Test case for monster changing.
26  *
27  * TODO:
28  * Given where change_object is (time.c),
29  * this should be merged into check_time.c
30  */
31 
32 #include <global.h>
33 #include <stdlib.h>
34 #include <check.h>
35 #include <loader.h>
36 #include <toolkit_common.h>
37 #include <sproto.h>
38 
39 
40 static void setup(void) {
41 }
42 
43 static void teardown(void) {
44  /* put any cleanup steps here, they will be run after each testcase */
45 }
46 
47 static object *do_monster_change(object *op, mapstruct *map, short expect, const char *new_name);
48 
49 START_TEST(test_monster_change) {
50  object *monster = NULL, *tmp = NULL;
51  object *floor = NULL;
52  mapstruct *map = NULL;
53  int x, y;
54 
55  map = get_empty_map(5, 5);
56  // Fill the floor
57  for (x = 0; x < 5; ++x)
58  {
59  for (y = 0; y < 5; ++y)
60  {
61  floor = create_archetype("battleground");
62  fail_unless(floor != NULL, "cannot find arch battleground");
63  object_insert_in_map_at(floor, map, NULL, 0, x, y);
64  }
65  }
66  // Add a monster.
67  monster = create_archetype("kobold");
68  fail_unless(monster != NULL, "failed to find arch kobold");
69  // First test: 1-tile to 1-tile conversion.
70  monster->other_arch = find_archetype("ogre");
71  // Ensure we got other_arch
72  fail_unless(monster->other_arch != NULL, "Could not find other_arch to transform object %s.", monster->name);
73  monster->map = map;
74  monster->stats.food = 1; // Tell it to make one of the next unit
75  object_insert_in_map_at(monster, map, NULL, 0 , 0 , 0);
76  tmp = do_monster_change(monster, map, 1, "ogre");
77  fail_unless(monster != tmp, "We got the same object back when we should have gotten a new one!");
78  // Now we do a change to a larger monster as the next test.
79  monster = tmp;
80  monster->other_arch = find_archetype("angel_knight");
81  // Ensure we got other_arch
82  fail_unless(monster->other_arch != NULL, "Could not find other_arch to transform object %s.", monster->name);
83  monster->stats.food = 1; // Tell it to make one of the next unit
84  tmp = do_monster_change(monster, map, 1, "angel_knight");
85  fail_unless(monster != tmp, "We got the same object back when we should have gotten a new one!");
86  // Change from multipart to multipart as the next test.
87  monster = tmp;
88  monster->other_arch = find_archetype("bear");
89  // Ensure we got other_arch
90  fail_unless(monster->other_arch != NULL, "Could not find other_arch to transform object %s.", monster->name);
91  monster->stats.food = 1; // Tell it to make one of the next unit
92  tmp = do_monster_change(monster, map, 1, "bear");
93  fail_unless(monster != tmp, "We got the same object back when we should have gotten a new one!");
94  // Change from multipart back down to one.
95  monster = tmp;
96  monster->other_arch = find_archetype("bee");
97  // Ensure we got other_arch
98  fail_unless(monster->other_arch != NULL, "Could not find other_arch to transform object %s.", monster->name);
99  monster->stats.food = 1; // Tell it to make one of the next unit
100  tmp = do_monster_change(monster, map, 1, "bee");
101  fail_unless(monster != tmp, "We got the same object back when we should have gotten a new one!");
102  // Last test -- Try to change to something way too big for the map.
103  monster = tmp;
104  monster->other_arch = find_archetype("Greater_Demon");
105  // Ensure we got other_arch
106  fail_unless(monster->other_arch != NULL, "Could not find other_arch to transform object %s.", monster->name);
107  monster->stats.food = 1; // Tell it to make one of the next unit
108  tmp = do_monster_change(monster, map, 0, "Greater_Demon");
109  fail_unless(monster == tmp, "We expected to get the same monster, but got a different one.");
110 }
111 END_TEST
112 
128 static object *do_monster_change(object *op, mapstruct *map, short expect, const char *new_name)
129 {
130  change_object(op);
131  if (expect)
132  // Now we make sure our monster is freed or removed.
133  fail_unless(QUERY_FLAG(op, FLAG_FREED) || QUERY_FLAG(op, FLAG_REMOVED), "original object not removed on expected success!");
134  else
135  {
136  // Expect failure and reinsertion of original
137  fail_unless(!QUERY_FLAG(op, FLAG_FREED) && !QUERY_FLAG(op, FLAG_FREED), "Expected failure, was successful in change!");
138  return op;
139  }
140  // And now we have the glorious task of finding the new object. It will not be where the other one was.
141  for (int x = 0; x < 5; ++x)
142  for (int y = 0; y < 5; ++y)
143  {
144  // There should be only one thing on the map.
146  if (op != NULL)
147  {
148  // Found the object! Break from the loops.
149  // Using a goto to break out of two loops. So sue me. :P
150  goto no_more_looping;
151  }
152  }
153 no_more_looping:
154  // Make sure we found the next object
155  fail_unless(op != NULL, "Could not find new object %s in the map.", new_name);
156  return op;
157 }
158 
159 static Suite *change_suite(void) {
160  Suite *s = suite_create("change_monster");
161  TCase *tc_core = tcase_create("Core");
162 
163  /*setup and teardown will be called before each test in testcase 'tc_core' */
164  tcase_add_checked_fixture(tc_core, setup, teardown);
165 
166  suite_add_tcase(s, tc_core);
167  tcase_add_test(tc_core, test_monster_change);
168 
169  return s;
170 }
171 
172 int main(void) {
173  int nf;
174  Suite *s = change_suite();
175  SRunner *sr= srunner_create(s);
176 
177  /* If you wish to debug the program, uncomment this line. */
178  srunner_set_fork_status (sr, CK_NOFORK);
179 
181  cctk_setdatadir(SOURCE_ROOT "lib");
182  init(0, NULL);
183 
184  srunner_set_xml(sr, LOGDIR "/unit/server/monster_change.xml");
185  srunner_set_log(sr, LOGDIR "/unit/server/monster_change.out");
186  srunner_run_all(sr, CK_ENV); /*verbosity from env variable*/
187  nf = srunner_ntests_failed(sr);
188  srunner_free(sr);
189  return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
190 }
global.h
settings
struct Settings settings
Definition: init.cpp:139
llevError
@ llevError
Definition: logger.h:11
get_empty_map
mapstruct * get_empty_map(int sizex, int sizey)
Definition: map.cpp:842
diamondslots.x
x
Definition: diamondslots.py:15
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
cctk_setdatadir
void cctk_setdatadir(const char *datadir)
Definition: toolkit_common.cpp:69
Settings::debug
LogLevel debug
Definition: global.h:243
Ice.tmp
int tmp
Definition: Ice.py:207
monster
the faster the spell may be cast there are several other common only the caster may be affected by the spell The most common spell range is that of touch This denotes that the caster much touch the recipient of the spell in order to release the spell monster
Definition: spell-info.txt:45
toolkit_common.h
disinfect.map
map
Definition: disinfect.py:4
FLAG_FREED
#define FLAG_FREED
Definition: define.h:233
init
pluglist shows those as well as a short text describing each the list will simply appear empty The keyword for the Python plugin is Python plugout< keyword > Unloads a given identified by its _keyword_ So if you want to unload the Python you need to do plugout Python plugin< libname > Loads a given whose _filename_ is libname So in the case of you d have to do a plugin cfpython so Note that all filenames are relative to the default plugin it tries to load all available files in the SHARE plugins directory as plugin libraries It first displays the Initializing the plugin has the opportunity to signal itself by a message on the console Then the server displays an informative message containing both the plugin content and its keyword For the Python the standard load process thus GreenGoblin When a plugin has been it can request to be warned whenever a global event and are named freely by the developer If the directory doesn t nothing will happen< event name > can be init
Definition: plugins.txt:54
do_monster_change
static object * do_monster_change(object *op, mapstruct *map, short expect, const char *new_name)
Definition: check_monster_change.cpp:128
main
int main(void)
Definition: check_monster_change.cpp:172
sproto.h
map_find_by_flag
object * map_find_by_flag(mapstruct *map, int x, int y, int flag)
Definition: map.cpp:2648
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.cpp:2095
FLAG_MONSTER
#define FLAG_MONSTER
Definition: define.h:245
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:278
FLAG_REMOVED
#define FLAG_REMOVED
Definition: define.h:232
START_TEST
START_TEST(test_monster_change)
Definition: check_monster_change.cpp:49
mapstruct
Definition: map.h:314
floor
Magical Runes Runes are magical inscriptions on the dungeon floor
Definition: runes-guide.txt:3
give.op
op
Definition: give.py:33
find_archetype
archetype * find_archetype(const char *name)
Definition: assets.cpp:266
diamondslots.y
y
Definition: diamondslots.py:16
teardown
static void teardown(void)
Definition: check_monster_change.cpp:43
change_object
void change_object(object *op)
Definition: time.cpp:592
loader.h
setup
static void setup(void)
Definition: check_monster_change.cpp:40
change_suite
static Suite * change_suite(void)
Definition: check_monster_change.cpp:159