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
object::map
struct mapstruct * map
Definition: object.h:305
Ice.tmp
int tmp
Definition: Ice.py:207
FAIL_UNLESS
#define FAIL_UNLESS(expr,...)
Definition: toolkit_common.h:11
toolkit_common.h
disinfect.map
map
Definition: disinfect.py:4
Settings::debug
LogLevel debug
Definition: global.h:243
FLAG_FREED
#define FLAG_FREED
Definition: define.h:233
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
living::food
int32_t food
Definition: living.h:48
sproto.h
map_find_by_flag
object * map_find_by_flag(mapstruct *map, int x, int y, int flag)
Definition: map.cpp:2621
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:2100
object::other_arch
struct archetype * other_arch
Definition: object.h:425
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
object::name
sstring name
Definition: object.h:319
mapstruct
Definition: map.h:313
give.op
op
Definition: give.py:33
find_archetype
archetype * find_archetype(const char *name)
Definition: assets.cpp:266
init
void init(int argc, char **argv)
Definition: init.cpp:1087
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
object::stats
living stats
Definition: object.h:378
setup
static void setup(void)
Definition: check_monster_change.cpp:40
change_suite
static Suite * change_suite(void)
Definition: check_monster_change.cpp:159