1 <!DOCTYPE HTML PUBLIC
"-//W3O//DTD W3 HTML 2.0//EN">
4 <link rev=
"owner" href=
"mailto:scs@eskimo.com">
5 <link rev=
"made" href=
"mailto:scs@eskimo.com">
6 <title>Assignment #
4</title>
15 <B>Intermediate C Programming
18 UW Experimental College
23 </B></p><p><a href=
"PS4.html">Assignment #
4</a>
24 <br><a href=
"PS3a.html">Assignment #
3 Answers
</a>
25 <br><a href=
"http://www.eskimo.com/~scs/cclass/int/sx6.html">Class Notes, Chapter
20</a>
27 </B></p><OL><li>This week we're going to add containers
28 (so that objects can be put inside of other objects)
30 so that we can remember things about objects
31 (such as whether they're containers, whether they're open, etc.).
34 The code to implement this changes is scattered,
36 in the distribution directories.
37 You'll have to type some of this new code in yourself.
40 Here is the modified object structure,
41 along with a few definitions:
47 struct object *contents; /* contents (if container) */
48 struct object *lnext; /* next in list of contained objects */
49 /* (i.e. in this object's container) */
50 char *desc; /* long description */
53 #define CONTAINER
0x0001
54 #define CLOSABLE
0x0002
64 #define TRANSPARENT
0x0800
65 #define IMMOBILE
0x1000
67 #define Iscontainer(o) ((o)-
>attrs
& CONTAINER)
68 #define Isopen(o) ((o)-
>attrs
& OPEN)
70 (This code is in the file
<TT>game.xh
</TT> in the
<TT>week4
</TT> subdirectory,
71 although the copy there is missing the new
<TT>desc
</TT> field for objects.)
75 for
<TT>commands.c
</TT>,
76 to implement new ``open,'' ``close,''
77 and ``put (in)'' commands:
79 else if(strcmp(verb,
"open") ==
0)
83 printf(
"You must tell me what to open.\n");
88 printf(
"The %s is already open.\n", objp-
>name);
91 if(!(objp-
>attrs
& CLOSABLE))
93 printf(
"You can't open the %s.\n", objp-
>name);
96 objp-
>attrs |= OPEN;
97 printf(
"The %s is now open.\n", objp-
>name);
100 else if(strcmp(verb,
"close") ==
0)
104 printf(
"You must tell me what to close.\n");
107 if(!(objp-
>attrs
& CLOSABLE))
109 printf(
"You can't close the %s.\n", objp-
>name);
114 printf(
"The %s is already closed.\n", objp-
>name);
117 objp-
>attrs
&= ~OPEN;
118 printf(
"The %s is now closed.\n", objp-
>name);
121 else if(strcmp(verb,
"put") ==
0)
125 printf(
"You must tell me what to put.\n");
128 if(!contains(player-
>contents, objp))
130 printf(
"You don't have the %s.\n", objp-
>name);
133 if(cmd-
>preposition == NULL || strcmp(cmd-
>preposition,
"in") !=
0 ||
134 cmd-
>xobject == NULL)
136 printf(
"You must tell me where to put the %s.\n",
140 if(!Iscontainer(cmd-
>xobject))
142 printf(
"You can't put things in the %s.\n",
143 cmd-
>xobject-
>name);
146 if((cmd-
>xobject-
>attrs
& CLOSABLE)
&& !Isopen(cmd-
>xobject))
148 printf(
"The %s is closed.\n", cmd-
>xobject-
>name);
151 if(!putobject(player, objp, cmd-
>xobject))
153 /* shouldn't happen */
154 printf(
"You can't put the %s in the %s!\n",
155 objp-
>name, cmd-
>xobject-
>name);
158 printf(
"Now the %s is in the %s.\n",
159 objp-
>name, cmd-
>xobject-
>name);
162 (This code is in the file
<TT>week4/commands.xc
</TT>.)
165 Here is a new version of
<TT>newobject
</TT>, for
<TT>object.c
</TT>,
166 that initializes the new object attribute and contents fields.
167 (It's also missing any required initialization
168 of the new long description field;
169 make sure you preserve yours.)
172 newobject(char *name)
176 if(nobjects
>= MAXOBJECTS)
178 fprintf(stderr,
"too many objects\n");
182 objp =
&objects[nobjects++];
184 strcpy(objp-
>name, name);
185 objp-
>lnext = NULL;
187 objp-
>contents = NULL;
192 Here is the new
<TT>putobject
</TT> function, for
<TT>object.c
</TT>.
193 (It's in
<TT>week4/object.xc
</TT>.)
195 /* transfer object from actor to container */
197 putobject(struct actor *actp, struct object *objp, struct object *container)
200 struct object *prevlp = NULL;
202 for(lp = actp-
>contents; lp != NULL; lp = lp-
>lnext)
204 if(lp == objp) /* found it */
206 /* splice out of actor's list */
208 if(lp == actp-
>contents) /* head of list */
209 actp-
>contents = lp-
>lnext;
210 else prevlp-
>lnext = lp-
>lnext;
212 /* splice into container's list */
214 lp-
>lnext = container-
>contents;
215 container-
>contents = lp;
223 /* didn't find it (error) */
228 Here is new code for the
<TT>parsedatafile
</TT> function
230 to read attributes for objects:
232 else if(strcmp(av[
0],
"attribute") ==
0)
234 if(currentobject == NULL)
236 if(strcmp(av[
1],
"container") ==
0)
237 currentobject-
>attrs |= CONTAINER;
238 else if(strcmp(av[
1],
"closable") ==
0)
239 currentobject-
>attrs |= CLOSABLE;
240 else if(strcmp(av[
1],
"open") ==
0)
241 currentobject-
>attrs |= OPEN;
242 else if(strcmp(av[
1],
"heavy") ==
0)
243 currentobject-
>attrs |= HEAVY;
244 else if(strcmp(av[
1],
"soft") ==
0)
245 currentobject-
>attrs |= SOFT;
246 else if(strcmp(av[
1],
"sharp") ==
0)
247 currentobject-
>attrs |= SHARP;
250 (This code is incomplete;
251 at some point you'll have to add cases for the other attributes
256 Here are the ``break'' and ``cut'' commands
257 from
<TT>commands.c
</TT>,
258 modified to make use of a few attributes:
260 else if(strcmp(verb,
"break") ==
0)
264 printf(
"You must tell me what to break.\n");
267 if(cmd-
>preposition == NULL || strcmp(cmd-
>preposition,
"with") !=
0 ||
268 cmd-
>xobject == NULL)
270 printf(
"You must tell me what to break with.\n");
273 if(!contains(player-
>contents, cmd-
>xobject))
275 printf(
"You have no %s.\n", cmd-
>xobject-
>name);
278 if(!(cmd-
>xobject-
>attrs
& HEAVY))
280 printf(
"I don't think the %s is heavy enough to break things with.\n",
281 cmd-
>xobject-
>name);
284 objp-
>attrs |= BROKEN;
285 printf(
"Oh, dear. Now the %s is broken.\n", objp-
>name);
288 else if(strcmp(verb,
"cut") ==
0)
292 printf(
"You must tell me what to cut.\n");
295 if(cmd-
>preposition == NULL || strcmp(cmd-
>preposition,
"with") !=
0 ||
296 cmd-
>xobject == NULL)
298 printf(
"You must tell me what to cut with.\n");
301 if(!contains(player-
>contents, cmd-
>xobject))
303 printf(
"You have no %s.\n", cmd-
>xobject-
>name);
306 if(!(cmd-
>xobject-
>attrs
& SHARP))
308 printf(
"I don't think the %s is sharp enough to cut things with.\n",
309 cmd-
>xobject-
>name);
312 if(!(objp-
>attrs
& SOFT))
314 printf(
"I don't think you can cut the %s with the %s.\n",
315 objp-
>name, cmd-
>xobject-
>name);
318 printf(
"The %s is now cut in two.\n", objp-
>name);
321 Try to get all of this code integrated, compiled, and working.
322 You will probably have to add a few prototypes to
<TT>game.h
</TT>.
326 before you can play with the new features,
327 you will have to make some changes to the data file,
328 <TT>dungeon.dat
</TT>, too.
329 Make the hammer heavy by adding the line
337 Make the kettle a container by adding the line
345 Add a knife object by adding the lines
351 Add a box object by adding the lines
356 Now you should be able to break things with the hammer,
357 and put things into the kettle or box
358 (once you open the box).
359 The knife won't cut things unless they're soft,
360 so add an object with
364 and try cutting it with the knife.
365 Once you put things into containers,
366 they'll seem to disappear;
367 we'll fix that in the next two exercises.
370 With these changes, the game suddenly explodes in potential complexity.
371 There are lots and lots of features you'll be able to add,
372 limited only by your own creativity and the amount of time you
374 I've suggested several changes and improvements below,
375 although you don't have to make all of them,
376 and you're not limited to these suggestions, either.
377 (You won't be able to add too many more attributes, though,
378 without possibly running out of bits in an int.
379 We'll start using a more open-ended scheme for implementing
380 attributes next time.
381 In the mean time, you could make
382 the
<TT>attrs
</TT> field
383 an
<TT>unsigned long int
</TT>
384 if you were desperate to add more attributes.)
385 <li>Modify the
<TT>findobject
</TT> function in
<TT>object.c
</TT> so
386 that it can find objects when they're inside containers
387 (both in the actor's possession and sitting in the room).
388 The original implementation of
<TT>findobject
</TT>
389 has separate loops for searching the actor's list of objects
390 and the room's list of objects.
391 But now, when an object
394 we'll need to search through
<em>its
</em> list of
397 It will be easiest if you add a new function,
400 which searches for an object in any list of objects.
401 The code in
<TT>findobj2
</TT> will be just like
402 the old code in
<TT>findobject
</TT>
403 for searching the actor's and room's lists;
404 in fact, once you write
<TT>findobj2
</TT>,
405 you'll be able to replace the actor- and room-searching code
408 findobj2(actp-
>contents, name);
412 findobj2(actp-
>location-
>contents, name);
415 your scheme should work even to find objects within objects
418 this will involve recursive calls to
<TT>findobj2
</TT>.
419 <li>Modify the
<TT>takeobject
</TT> function in
<TT>object.c
</TT>
420 so that it can also take objects which are sitting in containers
421 (both in the actor's possession and sitting in the room).
422 If a container is
<TT>CLOSABLE
</TT>, make sure it's
<TT>OPEN
</TT>!
423 <li>Rewrite the ``examine'' command
424 (in
<TT>commands.c
</TT>)
425 to mention some of the relevant attributes
426 (
<TT>OPEN
</TT>,
<TT>BROKEN
</TT>, etc.)
427 of the object being examined.
428 (Hint: this is a good opportunity to use the conditional or
429 <TT>?:
</TT> operator.)
430 <li>Modify the
<TT>listobjects
</TT> function in
<TT>object.c
</TT> to
431 list the contents (if any) of objects which are containers.
432 Should it print the contents of closed containers?
433 (In a more complicated game, we might worry about transparency...)
434 <li>Implement objects which can be locked
435 (if they have the
<TT>LOCK
</TT> attribute).
436 Add a ``lock'' command to lock them
437 (i.e. to set the
<TT>LOCKED
</TT> attribute)
438 and an ``unlock'' command to unlock them.
439 Both ``lock'' and ``unlock'' should require
440 that the user use a tool which has the
<TT>KEY
</TT> attribute.
441 (In other words, ``lock strongbox with key'' should
443 but ``lock strongbox with broom'' should not work.
444 But don't worry about trying to make certain keys fit only certain locks.)
445 Don't let objects be opened if they have the
<TT>LOCK
</TT> attribute
447 (You'll have to update the attribute-reading code in
<TT>io.c
</TT>
448 to handle the
<TT>LOCK
</TT>,
<TT>KEY
</TT>, and
<TT>LOCKED
</TT> attributes.)
449 <li>Implement a ``fix'' command which will let the user
451 as long as the preposition ``with'' appears and the
452 implement is an object with the
<TT>TOOL
</TT> attribute.
453 (You'll have to update the attribute-reading code in
<TT>io.c
</TT>
454 to handle the
<TT>TOOL
</TT> attribute.)
455 <li>Implement immobile objects that can't be picked up.
456 (You'll have to update the attribute-reading code in
<TT>io.c
</TT>
457 to handle the
<TT>IMMOBILE
</TT> attribute.)
461 This page by
<a href=
"http://www.eskimo.com/~scs/">Steve Summit
</a>
462 //
<a href=
"copyright.html">Copyright
</a> 1995-
9
463 //
<a href=
"mailto:scs@eskimo.com">mail feedback
</a>