aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/globals.h1
-rw-r--r--src/hash.c4
-rw-r--r--src/main.c2
-rw-r--r--src/multimap.c14
-rw-r--r--src/obj.c8
-rw-r--r--src/obj.h28
-rw-r--r--src/room.c25
-rw-r--r--src/room.h13
-rw-r--r--src/server.c19
-rw-r--r--src/server.h22
-rw-r--r--src/server_reqs.c79
-rw-r--r--src/server_reqs.h6
-rw-r--r--src/userdb.c37
-rw-r--r--src/userdb.h4
-rw-r--r--src/verb.h3
-rw-r--r--src/world.c7
-rw-r--r--worlds/test.c119
17 files changed, 299 insertions, 92 deletions
diff --git a/src/globals.h b/src/globals.h
index d26dc15..987d382 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -88,6 +88,7 @@
#include "util.h"
#define MSG_MAX PIPE_BUF
+
#ifndef NDEBUG
#define debugf(fmt,...) debugf_real(__func__, __LINE__, __FILE__, fmt, ##__VA_ARGS__)
#else
diff --git a/src/hash.c b/src/hash.c
index eed4846..59c05bf 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -308,12 +308,16 @@ bool hash_remove(void *ptr, const void *key)
last->next = iter->next;
else
map->table[hash] = iter->next;
+
if(map->free_key)
map->free_key((void*)iter->key);
if(map->free_data)
map->free_data((void*)iter->data);
+
--map->n_entries;
+
free(iter);
+
return true;
}
last = iter;
diff --git a/src/main.c b/src/main.c
index 3de3d89..b69ce76 100644
--- a/src/main.c
+++ b/src/main.c
@@ -5,4 +5,6 @@
int main(int argc, char *argv[])
{
server_main(argc, argv);
+
+ error("weird");
}
diff --git a/src/multimap.c b/src/multimap.c
index b958db0..033b511 100644
--- a/src/multimap.c
+++ b/src/multimap.c
@@ -193,11 +193,12 @@ size_t multimap_delete(void *ptr, const void *key, const void *val)
struct multimap_node *node = hash_lookup(map->hash_tab, key);
if(!node)
- return false;
+ return 0;
+
/* iterate over the node's pairs and delete */
size_t deleted = 0;
- struct multimap_list *last = NULL, *iter = node->list, *next;;
+ struct multimap_list *last = NULL, *iter = node->list, *next;
while(iter)
{
next = iter->next;
@@ -209,9 +210,10 @@ size_t multimap_delete(void *ptr, const void *key, const void *val)
map->free_key((void*)iter->key);
if(last)
- last->next = iter->next;
+ last->next = next;
else
- node->list = iter->next;
+ node->list = next;
+
free(iter);
++deleted;
@@ -251,7 +253,9 @@ size_t multimap_delete_all(void *ptr, const void *key)
return ret;
}
- /* fall through */
+
+ /* fall through on failure */
+
}
return 0;
}
diff --git a/src/obj.c b/src/obj.c
index 293aaff..deeb30d 100644
--- a/src/obj.c
+++ b/src/obj.c
@@ -67,7 +67,7 @@ struct object_t *obj_new(const char *class_name)
obj->id = idcounter++;
obj->refcount = 1;
- obj->list = true;
+ obj->hidden = false;
obj->default_article = true;
return obj;
@@ -80,7 +80,7 @@ void obj_write(int fd, struct object_t *obj)
write_uint64(fd, obj->id);
write_string(fd, obj->name);
- write_bool(fd, obj->list);
+ write_bool(fd, obj->hidden);
write_bool(fd, obj->default_article);
struct obj_alias_t *iter = obj->alias_list;
@@ -104,7 +104,7 @@ struct object_t *obj_read(int fd)
obj->id = read_uint64(fd);
obj->name = read_string(fd);
- obj->list = read_bool(fd);
+ obj->hidden = read_bool(fd);
obj->default_article = read_bool(fd);
/* aliases */
@@ -136,7 +136,7 @@ struct object_t *obj_copy(struct object_t *obj)
{
struct object_t *ret = obj_new(obj->class->class_name);
ret->name = strdup(obj->name);
- ret->list = obj->list;
+ ret->hidden = obj->hidden;
if(obj->class->hook_dupdata)
ret->userdata = obj->class->hook_dupdata(obj);
return ret;
diff --git a/src/obj.h b/src/obj.h
index 249f9c1..121e3ab 100644
--- a/src/obj.h
+++ b/src/obj.h
@@ -27,9 +27,9 @@
* internally.
*/
-struct object_t;
+typedef struct child_data user_t;
-typedef struct child_data user_t; // see server.h for the definition
+struct object_t;
struct obj_class_t {
const char *class_name;
@@ -46,11 +46,6 @@ struct obj_class_t {
* no function (NULL) = can take */
bool (*hook_take)(struct object_t*, user_t *user);
- /* called when dropping an object;
- * true: can drop
- * false: can't drop
- * NULL: can drop
- */
bool (*hook_drop)(struct object_t*, user_t *user);
void (*hook_destroy)(struct object_t*); // free resources
const char* (*hook_desc)(struct object_t*, user_t*); // get object description
@@ -65,8 +60,9 @@ struct obj_alias_t {
struct obj_alias_t *next;
};
-/* world modules should not instantiate this directly, use obj_new() instead */
-/* also, members marked with 'protected' should not be modified by the world module */
+/* world modules should not instantiate this directly, use obj_new()
+ * instead also, fields marked with 'protected' should not be modified
+ * by the world module */
struct object_t {
obj_id id; // protected
@@ -75,17 +71,17 @@ struct object_t {
* room */
char *name;
- struct obj_class_t *class;
+ struct obj_class_t *class; // protected
size_t n_alias;
- struct obj_alias_t *alias_list;
+ struct obj_alias_t *alias_list; // protected
- bool list; /* whether to list in room view */
+ bool hidden; /* whether to list in room description */
bool default_article; /* whether or not to use 'a' or 'an' when describing this */
void *userdata;
- unsigned refcount; // private
+ unsigned refcount; // protected
};
/* returns a new object of class 'c' */
@@ -100,10 +96,12 @@ struct object_t *obj_read(int fd);
/* this adds a reference to an object, DOES NOT COPY */
struct object_t *obj_dup(struct object_t *obj);
-/* makes a new object with a new ID, but same data fields as the original */
+/* makes a new object with a new ID, but with the same data fields as
+ * the original */
struct object_t *obj_copy(struct object_t *obj);
-/* this only frees the object if its reference count is zero */
+/* decrements an object's reference count; frees the object if there
+ * are no more references to it */
void obj_free(void*);
/* shut down the obj_* module */
diff --git a/src/room.c b/src/room.c
index 23ea5b7..9cc8c8c 100644
--- a/src/room.c
+++ b/src/room.c
@@ -80,9 +80,15 @@ void room_free(struct room_t *room)
bool room_obj_add(room_id room, struct object_t *obj)
{
+ debugf("ADDING OBJECT %s to ROOM %d\n", obj->name, room);
+
bool status = true;
if(!multimap_insert(room_get(room)->objects, obj->name, obj))
+ {
+ debugf("FAILED TO ADD OBJECT.\n");
status = false;
+ }
+
struct obj_alias_t *iter = obj->alias_list;
while(iter)
{
@@ -94,6 +100,9 @@ bool room_obj_add(room_id room, struct object_t *obj)
}
iter = iter->next;
}
+
+ debugf("ROOM %d now has %d objects\n", room, multimap_size(room_get(room)->objects));
+
return status;
}
@@ -116,16 +125,22 @@ bool room_obj_add_alias(room_id room, struct object_t *obj, char *alias)
iter = iter->next;
}
+ debugf("adding alias '%s' for object '%s'\n", alias, obj->name);
+
+ debugf("ROOM %d now has %d total object names\n", room, multimap_size(room_get(room)->objects));
+
struct obj_alias_t *new = calloc(1, sizeof(struct obj_alias_t));
- new->alias = alias;
+ new->alias = strdup(alias);
new->next = obj->alias_list;
obj->alias_list = new;
++obj->n_alias;
- return multimap_insert(room_get(room)->objects, alias, obj_dup(obj));
+ bool status = multimap_insert(room_get(room)->objects, alias, obj_dup(obj));
+
+ return status;
}
const struct multimap_list *room_obj_iterate(room_id room, void **save, size_t *n_pairs)
@@ -160,6 +175,7 @@ size_t room_obj_count_noalias(room_id id)
bool room_obj_del_by_ptr(room_id room, struct object_t *obj)
{
+ debugf("room_obj_del_by_ptr: deleting object %s\n", obj->name);
struct obj_alias_t *iter = obj->alias_list;
struct object_t tmp;
@@ -167,14 +183,17 @@ bool room_obj_del_by_ptr(room_id room, struct object_t *obj)
while(iter)
{
+ debugf(" deleting alias %s\n", iter->alias);
multimap_delete(room_get(room)->objects, iter->alias, &tmp);
iter = iter->next;
}
+ debugf("After deleting aliases of object: %s:\n", obj->name);
+
return multimap_delete(room_get(room)->objects, obj->name, &tmp);
}
-/* delete all the objects with a matching name, and all their aliases,
+/* delete all the objects with a matching name, and all their aliases
* from a room */
bool room_obj_del(room_id room, const char *name)
diff --git a/src/room.h b/src/room.h
index e02105c..e9e1953 100644
--- a/src/room.h
+++ b/src/room.h
@@ -28,9 +28,9 @@
are added by hooks in rooms, which are provided by the world
module. */
-typedef enum room_id { ROOM_NONE = -1 } room_id;
+typedef struct child_data user_t; // definition of child_data in server.h
-typedef struct child_data user_t;
+typedef enum room_id { ROOM_NONE = -1 } room_id;
enum direction_t { DIR_N = 0, DIR_NE, DIR_E, DIR_SE, DIR_S, DIR_SW, DIR_W, DIR_NW, DIR_UP, DIR_DN, DIR_IN, DIR_OT, NUM_DIRECTIONS };
@@ -46,8 +46,12 @@ struct roomdata_t {
const char * const adjacent[NUM_DIRECTIONS];
void (* const hook_init)(room_id id);
- void (* const hook_enter)(room_id room, user_t *user);
- void (* const hook_leave)(room_id room, user_t *user);
+
+ /* return values indicate permission to enter/leave,
+ * setting to NULL defaults to true.
+ */
+ bool (* const hook_enter)(room_id room, user_t *user);
+ bool (* const hook_leave)(room_id room, user_t *user);
void (* const hook_serialize)(room_id room, int fd);
void (* const hook_deserialize)(room_id room, int fd);
void (* const hook_destroy)(room_id room);
@@ -88,6 +92,7 @@ bool room_obj_add_alias(room_id room, struct object_t *obj, char *alias);
bool room_obj_del(room_id room, const char *name);
bool room_obj_del_alias(room_id room, struct object_t *obj, const char *alias);
+bool room_obj_del_by_ptr(room_id room, struct object_t *obj);
const struct multimap_list *room_obj_get(room_id room, const char *obj);
const struct multimap_list *room_obj_get_size(room_id room, const char *name, size_t *n_objs);
diff --git a/src/server.c b/src/server.c
index 9e2e465..e42483c 100644
--- a/src/server.c
+++ b/src/server.c
@@ -45,12 +45,15 @@ static int server_socket;
/* saves state periodically */
void server_save_state(bool force)
{
- static int n = 0;
- n = (n + 1) % SAVE_INTERVAL;
- if(!n || force)
+ if(!are_child)
{
- world_save(WORLDFILE);
- userdb_write(USERFILE);
+ static int n = 0;
+ n = (n + 1) % SAVE_INTERVAL;
+ if(!n || force)
+ {
+ world_save(WORLDFILE);
+ userdb_write(USERFILE);
+ }
}
}
@@ -119,6 +122,10 @@ static void __attribute__((noreturn)) server_cleanup(void)
close(server_socket);
+ /* save state */
+ if(!are_child)
+ server_save_state(true);
+
/* shut down modules */
client_shutdown();
obj_shutdown();
@@ -152,7 +159,7 @@ static void __attribute__((noreturn)) sigint_handler(int s)
}
static bool autoconfig = false;
-const char *autouser, *autopass;
+static const char *autouser, *autopass;
static void check_userfile(void)
{
diff --git a/src/server.h b/src/server.h
index af7e9fc..95e537a 100644
--- a/src/server.h
+++ b/src/server.h
@@ -26,21 +26,29 @@
#include "server_reqs.h"
#include "room.h"
+/* everything the server needs to manage its children */
struct child_data {
- pid_t pid;
- int readpipe[2];
- int outpipe[2];
+ pid_t pid;
- int state;
- room_id room;
- char *user;
+ /* pipes, packet mode */
+ int readpipe[2];
+ int outpipe[2];
- ev_io *io_watcher;
+ /* user state */
+ int state;
+ room_id room;
+ char *user;
+
+ /* libev watchers */
+ ev_io *io_watcher;
ev_child *sigchld_watcher;
+ /* remote IP */
struct in_addr addr;
};
+typedef struct child_data user_t;
+
extern volatile int num_clients;
extern void *child_map;
extern bool are_child;
diff --git a/src/server_reqs.c b/src/server_reqs.c
index 167331d..fffdee1 100644
--- a/src/server_reqs.c
+++ b/src/server_reqs.c
@@ -157,42 +157,53 @@ static void req_send_desc(unsigned char *data, size_t datalen, struct child_data
room_id id = sender->room;
while(1)
{
- debugf("Iterating over object name...\n");
size_t n_objs;
- const struct multimap_list *iter= room_obj_iterate(id, &save, &n_objs);
+ const struct multimap_list *iter = room_obj_iterate(id, &save, &n_objs);
id = ROOM_NONE;
if(!iter)
break;
const char *name = iter->key;
struct object_t *obj = iter->val;
- if(!strcmp(name, obj->name))
+
+ debugf("*** ITERATING OVER OBJECT IN ROOM ***\n");
+ debugf("hidden: %d\n", obj->hidden);
+ debugf("compare: %s %s\n", obj->name, name);
+
+ buf[0] = '\0';
+
+ if(!obj->hidden)
{
- if(n_objs == 1)
+ if(!strcmp(name, obj->name))
{
- char *article = (is_vowel(name[0])?"an":"a");
- strlcat(buf, "There is ", sizeof(buf));
- if(obj->default_article)
+ if(n_objs == 1)
{
- strlcat(buf, article, sizeof(buf));
- strlcat(buf, " ", sizeof(buf));
+ char *article = (is_vowel(name[0])?"an":"a");
+ strlcat(buf, "There is ", sizeof(buf));
+ if(obj->default_article)
+ {
+ strlcat(buf, article, sizeof(buf));
+ strlcat(buf, " ", sizeof(buf));
+ }
+ strlcat(buf, name, sizeof(buf));
+ strlcat(buf, " here.\n", sizeof(buf));
+ }
+ else
+ {
+ strlcat(buf, "There are ", sizeof(buf));
+ char n[32];
+ snprintf(n, sizeof(n), "%lu ", n_objs);
+ strlcat(buf, n, sizeof(buf));
+ strlcat(buf, name, sizeof(buf));
+ strlcat(buf, "s here.\n", sizeof(buf));
}
- strlcat(buf, name, sizeof(buf));
- strlcat(buf, " here.\n", sizeof(buf));
- }
- else
- {
- strlcat(buf, "There are ", sizeof(buf));
- char n[32];
- snprintf(n, sizeof(n), "%lu ", n_objs);
- strlcat(buf, n, sizeof(buf));
- strlcat(buf, name, sizeof(buf));
- strlcat(buf, "s here.\n", sizeof(buf));
}
+
+ send_msg(sender, "%s", buf);
}
+ else
+ debugf("OBJECT IS HIDDEN\n");
}
-
- send_packet(sender, REQ_BCASTMSG, buf, strlen(buf));
}
static void req_send_roomname(unsigned char *data, size_t datalen, struct child_data *sender)
@@ -333,7 +344,7 @@ static void req_look_at(unsigned char *data, size_t datalen, struct child_data *
if(inv_list)
{
send_msg(sender, "In inventory:\n");
- idx = print_objlist(sender, inv_list, idx, n_objs);
+ print_objlist(sender, inv_list, idx, n_objs);
}
if(!room_list && !inv_list)
@@ -355,10 +366,12 @@ static void req_take(unsigned char *data, size_t datalen, struct child_data *sen
if(obj->class->hook_take && !obj->class->hook_take(obj, sender))
{
send_msg(sender, "You can't take that.\n");
- return;
+ iter = next;
+ continue;
}
userdb_add_obj(sender->user, obj);
+ room_obj_del_by_ptr(sender->room, obj);
send_msg(sender, "Taken.\n");
}
@@ -367,8 +380,6 @@ static void req_take(unsigned char *data, size_t datalen, struct child_data *sen
iter = next;
}
- room_obj_del(sender->room, (const char*)data);
-
server_save_state(false);
}
else
@@ -452,17 +463,21 @@ static void req_drop(unsigned char *data, size_t datalen, struct child_data *sen
while(iter)
{
+ const struct multimap_list *next = iter->next;
struct object_t *obj = iter->val;
- struct object_t *dup = obj_dup(obj);
- room_obj_add(sender->room, dup);
+ if(!obj->class->hook_drop || (obj->class->hook_drop && obj->class->hook_drop(obj, sender)))
+ {
+ send_msg(sender, "Dropped.\n");
+ room_obj_add(sender->room, obj_dup(obj));
+ userdb_del_obj_by_ptr(sender->user, obj);
+ }
+ else
+ send_msg(sender, "You cannot drop that.\n");
- send_msg(sender, "Dropped.\n");
- iter = iter->next;
+ iter = next;
}
- multimap_delete_all(user->objects, (const char*)data);
-
server_save_state(false);
}
diff --git a/src/server_reqs.h b/src/server_reqs.h
index 5137f9d..c77c53a 100644
--- a/src/server_reqs.h
+++ b/src/server_reqs.h
@@ -16,6 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#pragma once
+
+#include "globals.h"
+
+typedef struct child_data user_t;
+
/* child<->master commands */
/* children might not implement all of these */
/* meanings might be different for the server and child, see comments */
diff --git a/src/userdb.c b/src/userdb.c
index dde2693..101b6d0 100644
--- a/src/userdb.c
+++ b/src/userdb.c
@@ -183,7 +183,6 @@ bool userdb_remove(const char *key)
bool userdb_add(struct userdata_t *data)
{
- userdb_dump();
struct userdata_t *new = calloc(1, sizeof(*new)); /* only in C! */
memcpy(new, data, sizeof(*new));
@@ -239,9 +238,6 @@ void userdb_dump(void)
void userdb_shutdown(void)
{
- if(map && db_file && !are_child)
- userdb_write(db_file);
-
if(map)
{
hash_free(map);
@@ -283,6 +279,39 @@ bool userdb_add_obj(const char *name, struct object_t *obj)
return multimap_insert(user->objects, obj->name, obj_dup(obj));
}
+bool userdb_del_obj_by_ptr(const char *username, struct object_t *obj)
+{
+ struct userdata_t *user = userdb_lookup(username);
+
+ struct obj_alias_t *iter = obj->alias_list;
+
+ struct object_t tmp;
+ tmp.id = obj->id;
+
+ while(iter)
+ {
+ multimap_delete(user->objects, iter->alias, &tmp);
+ iter = iter->next;
+ }
+
+ return multimap_delete(user->objects, obj->name, &tmp);
+}
+
+bool userdb_del_obj(const char *username, const char *obj_name)
+{
+ struct userdata_t *user = userdb_lookup(username);
+ const struct multimap_list *iter = multimap_lookup(user->objects, obj_name, NULL);
+ while(iter)
+ {
+ const struct multimap_list *next = iter->next;
+ struct object_t *obj = iter->val;
+ userdb_del_obj_by_ptr(username, obj);
+ iter = next;
+ }
+
+ return true;
+}
+
/*** child request wrappers ***/
/* NOTE: these also work from the master, but it's better to use the
* userdb_* funcs instead */
diff --git a/src/userdb.h b/src/userdb.h
index 52ade12..25bdc7b 100644
--- a/src/userdb.h
+++ b/src/userdb.h
@@ -66,7 +66,9 @@ bool userdb_write(const char*);
/* *save should be set to NULL on the first run */
struct userdata_t *userdb_iterate(void **save);
-bool userdb_add_obj(const char *name, struct object_t *obj);
+bool userdb_add_obj(const char *username, struct object_t *obj);
+bool userdb_del_obj(const char *username, const char *obj_name);
+bool userdb_del_obj_by_ptr(const char *username, struct object_t *obj);
/*** child-only functions ***/
struct userdata_t *userdb_request_lookup(const char *name);
diff --git a/src/verb.h b/src/verb.h
index cdfbe98..348da49 100644
--- a/src/verb.h
+++ b/src/verb.h
@@ -30,6 +30,9 @@
* callbacks.
*/
+struct child_data;
+typedef struct child_data user_t;
+
struct verb_t;
struct verb_class_t {
const char *class_name;
diff --git a/src/world.c b/src/world.c
index 1516b4c..a854e49 100644
--- a/src/world.c
+++ b/src/world.c
@@ -80,6 +80,8 @@ void world_save(const char *fname)
size_t n_objects = room_obj_count_noalias(i);
write(fd, &n_objects, sizeof(n_objects));
+ debugf("Room %d has %d objects.\n", i, n_objects);
+
room_id id = i;
void *save;
while(1)
@@ -95,7 +97,10 @@ void world_save(const char *fname)
break;
const char *name = iter->key;
if(!strcmp(name, obj->name))
- obj_write(fd, obj);
+ {
+ debugf("writing object '%s' in room %d\n", obj->name, i);
+ obj_write(fd, obj);
+ }
iter = iter->next;
}
}
diff --git a/worlds/test.c b/worlds/test.c
index cdcaba9..37a058e 100644
--- a/worlds/test.c
+++ b/worlds/test.c
@@ -7,10 +7,12 @@ static void deadend_init(room_id id)
struct object_t *new = obj_new("/generic");
new->name = strdup("shovel");
new->userdata = strdup("It is a normal shovel with a price tag attached that says $19.99.");
- new->list = true;
room_obj_add(id, new);
+
+#if 0
new = obj_copy(new);
room_obj_add(id, new);
+#endif
}
static void ew_road_init(room_id id)
@@ -18,8 +20,9 @@ static void ew_road_init(room_id id)
struct object_t *new = obj_new("/generic/notake");
new->name = strdup("large boulder");
new->userdata = strdup("It is just a boulder. It cannot be moved.");
- new->list = true;
room_obj_add(id, new);
+ room_obj_add_alias(id, new, "boulder");
+ room_obj_add_alias(id, new, "rock");
}
static void fork_init(room_id id)
@@ -54,12 +57,31 @@ static void fork_destroy(room_id id)
static void senw_init(room_id id)
{
- struct object_t *new = obj_new("/generic");
+ struct object_t *new = obj_new("/generic/dunnet/food");
new->name = strdup("some food");
new->userdata = strdup("It looks like some kind of meat. Smells pretty bad.");
new->default_article = false;
room_obj_add(id, new);
- room_obj_add_alias(id, new, strdup("food"));
+ room_obj_add_alias(id, new, "food");
+ room_obj_add_alias(id, new, "meat");
+}
+
+static void hangout_init(room_id id)
+{
+ struct object_t *new = obj_new("/generic/notake");
+ new->name = strdup("ferocious bear");
+ new->userdata = strdup("It looks like a grizzly to me.");
+ room_obj_add(id, new);
+ room_obj_add_alias(id, new, "bear");
+}
+
+static void hidden_init(room_id id)
+{
+ struct object_t *new = obj_new("/generic");
+ new->name = strdup("emerald bracelet");
+ new->userdata = strdup("I see nothing special about that.");
+ room_obj_add(id, new);
+ room_obj_add_alias(id, new, "bracelet");
}
const struct roomdata_t netcosm_world[] = {
@@ -106,7 +128,7 @@ const struct roomdata_t netcosm_world[] = {
"senw_road",
"SE/NW road",
"You are on a southeast/northwest road.",
- { NONE_N, NONE_NE, NONE_E, NONE_SE, NONE_S, NONE_SW, NONE_W, "fork", NONE_UP, NONE_DN, NONE_IN, NONE_OT },
+ { NONE_N, NONE_NE, NONE_E, "bear_hangout", NONE_S, NONE_SW, NONE_W, "fork", NONE_UP, NONE_DN, NONE_IN, NONE_OT },
senw_init,
NULL,
NULL,
@@ -116,10 +138,49 @@ const struct roomdata_t netcosm_world[] = {
},
{
+ "bear_hangout",
+ "Bear Hangout",
+ "You are standing at the end of a road. A passage leads back to the northwest.",
+ { NONE_N, NONE_NE, NONE_E, NONE_SE, NONE_S, "hidden_area", NONE_W, "senw_road", NONE_UP, NONE_DN, NONE_IN, NONE_OT },
+ hangout_init,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ },
+
+ {
+ "hidden_area",
+ "Hidden Area",
+ "You are in a well-hidden area off to the side of a road. Back to the northeast through the brush you can see the bear hangout.",
+ { NONE_N, "bear_hangout", NONE_E, NONE_SE, NONE_S, NONE_SW, NONE_W, NONE_NW, NONE_UP, NONE_DN, NONE_IN, NONE_OT },
+ hidden_init,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ },
+
+ {
"nesw_road",
"NE/SW road",
"You are on a northeast/southwest road.",
- { NONE_N, NONE_NE, NONE_E, NONE_SE, NONE_S, "fork", NONE_W, NONE_NW, NONE_UP, NONE_DN, NONE_IN, NONE_OT },
+ { NONE_N, "building_front", NONE_E, NONE_SE, NONE_S, "fork", NONE_W, NONE_NW, NONE_UP, NONE_DN, NONE_IN, NONE_OT },
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ },
+
+ {
+ "building_front",
+ "Building Front",
+ "You are at the end of the road. There is a building in front of you to the northeast, and the road leads back to the southwest.",
+ { NONE_N, NONE_NE, NONE_E, NONE_SE, NONE_S, "nesw_road", NONE_W, NONE_NW, NONE_UP, NONE_DN, NONE_IN, NONE_OT },
NULL,
NULL,
NULL,
@@ -166,8 +227,32 @@ static bool no_take(struct object_t *obj, user_t *user)
return false;
}
+static bool food_drop(struct object_t *obj, user_t *user)
+{
+ if(room_obj_get(user->room, "bear"))
+ {
+ send_msg(user, "The bear takes the food and runs away with it. He left something behind.\n");
+
+ struct object_t *new = obj_new("/generic");
+
+ debugf("ADDING OBJECT.\n");
+
+ new->name = strdup("shiny brass key");
+ new->userdata = strdup("I see nothing special about that.");
+
+ room_obj_add(user->room, new);
+ room_obj_add_alias(user->room, new, "key");
+ room_obj_add_alias(user->room, new, "shiny key");
+ room_obj_add_alias(user->room, new, "brass key");
+
+ room_obj_del(user->room, "ferocious bear");
+ }
+
+ return true;
+}
+
const struct obj_class_t netcosm_obj_classes[] = {
- /* a generic, takable object class with userdata as its description */
+ /* a generic, takeable object class with userdata pointing to its description */
{
"/generic",
generic_ser,
@@ -179,7 +264,7 @@ const struct obj_class_t netcosm_obj_classes[] = {
generic_dup,
},
- /* a generic, non-takable object class */
+ /* a generic, non-takeable object class, inherits /generic */
{
"/generic/notake",
generic_ser,
@@ -189,7 +274,19 @@ const struct obj_class_t netcosm_obj_classes[] = {
generic_destroy,
generic_desc,
generic_dup,
- }
+ },
+
+ /* a specialized "food" object for dunnet, inherits /generic */
+ {
+ "/generic/dunnet/food",
+ generic_ser,
+ generic_deser,
+ NULL,
+ food_drop,
+ generic_destroy,
+ generic_desc,
+ generic_dup,
+ },
};
const size_t netcosm_obj_classes_sz = ARRAYLEN(netcosm_obj_classes);
@@ -215,8 +312,10 @@ static void dig_exec(struct verb_t *verb, char *args, user_t *user)
struct object_t *new = obj_new("/generic");
new->name = strdup("CPU card");
new->userdata = strdup("The CPU board has a VAX chip on it. It seems to have 2 Megabytes of RAM onboard.");
- new->list = true;
room_obj_add(user->room, new);
+ room_obj_add_alias(user->room, new, "cpu");
+ room_obj_add_alias(user->room, new, "chip");
+ room_obj_add_alias(user->room, new, "card");
send_msg(user, "I think you found something.\n");
}
else