commit 96978f737a38b5587e04360ebd78684ec26346f5
parent 82618ad625d4d97f4ac7eaa61acd67e3aa4a9eb5
Author: William Casarin <jb55@jb55.com>
Date:   Fri,  3 Jul 2020 08:32:59 -0700
cleanups, word helpers
Diffstat:
| M | describe.c | | | 99 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------- | 
1 file changed, 78 insertions(+), 21 deletions(-)
diff --git a/describe.c b/describe.c
@@ -2,6 +2,8 @@
 #include "describe.h"
 #include <assert.h>
 #include <stdio.h>
+#include <ctype.h>
+#include <string.h>
 
 #define ADJ_PUSHED 1
 #define ADJ_NOT_PUSHED 2
@@ -14,6 +16,26 @@ struct describe {
 	struct cursor *strs;
 };
 
+static int push_sized_word(struct cursor *strs, const char *str, int len)
+{
+	int ok;
+
+	if (strs->p-1 >= strs->start && !isspace(*(strs->p-1))) {
+		ok = push_str(strs, " ");
+		if (!ok) return 0;
+	}
+
+	ok = push_sized_str(strs, str, len);
+	if (!ok) return 0;
+
+	return 1;
+}
+
+static int push_word(struct cursor *strs, const char *str)
+{
+	return push_sized_word(strs, str, strlen(str));
+}
+
 static int push_adjective(struct cursor *strs, struct attribute *attr)
 {
 	int ok;
@@ -73,7 +95,7 @@ static int push_adjectives(struct describe *desc)
 
 		if (adjs > 0) {
 			if (adjs == adj_count-1)
-				push_str(desc->strs, " and");
+				push_word(desc->strs, "and");
 			else if (adjs != adj_count-1)
 				push_str(desc->strs, ",");
 
@@ -87,29 +109,38 @@ static int push_adjectives(struct describe *desc)
 	return 1;
 }
 
-static int push_made_of(struct describe *desc)
+static int find_attr(struct cursor *attrs, struct cell *cell,
+		     enum attribute_type type, struct attribute **attr)
 {
-	struct attribute *attr;
-	int i, ok;
-
-	for (i = 0; i < desc->cell->n_attributes; i++) {
-		attr = get_attr(desc->parsed->attributes,
-				desc->cell->attributes[i]);
-		assert(attr);
+	int i;
 
-		if (attr->type == A_MATERIAL) {
-			ok = push_str(desc->strs, " made of ");
-			if (!ok) return 0;
+	for (i = 0; i < cell->n_attributes; i++) {
+		*attr = get_attr(attrs, cell->attributes[i]);
+		assert(*attr);
 
-			ok = push_sized_str(desc->strs,
-					    attr->data.str.ptr,
-					    attr->data.str.len);
-			if (!ok) return 0;
+		if ((*attr)->type == type)
 			return 1;
-		}
 	}
 
-	return 2;
+	return 0;
+}
+
+static int push_made_of(struct describe *desc)
+{
+	struct attribute *attr;
+	int ok;
+
+	ok = find_attr(desc->parsed->attributes, desc->cell,
+		       A_MATERIAL, &attr);
+	if (!ok) return 2;
+
+	ok = push_word(desc->strs, "made of");
+	if (!ok) return 0;
+
+	ok = push_sized_word(desc->strs, attr->data.str.ptr,
+			       attr->data.str.len);
+	if (!ok) return 0;
+	return 1;
 }
 
 static int push_named(struct describe *desc)
@@ -123,15 +154,38 @@ static int push_named(struct describe *desc)
 	if (name_len == 0)
 		return 1;
 
-	ok = push_str(desc->strs, " named ");
+	ok = push_word(desc->strs, "named");
 	if (!ok) return 0;
 
-	ok = push_sized_str(desc->strs, name, name_len);
+	ok = push_sized_word(desc->strs, name, name_len);
 	if (!ok) return 0;
 
 	return 1;
 }
 
+static int push_shape(struct describe *desc)
+{
+	struct attribute *attr;
+	int ok;
+
+	ok = find_attr(desc->parsed->attributes, desc->cell, A_SHAPE, &attr);
+	if (!ok) return 2;
+
+	switch (attr->data.shape) {
+	case SHAPE_RECTANGLE:
+		push_word(desc->strs, "rectangular");
+		break;
+	case SHAPE_CIRCLE:
+		push_word(desc->strs, "circular");
+		break;
+	case SHAPE_SQUARE:
+		push_word(desc->strs, "square");
+		break;
+	}
+
+	return 1;
+}
+
 static int describe_room(struct describe *desc)
 {
 	int ok;
@@ -143,7 +197,10 @@ static int describe_room(struct describe *desc)
 	ok = push_adjectives(desc);
 	if (!ok) return 0;
 
-	ok = push_str(desc->strs, " room");
+	ok = push_shape(desc);
+	if (!ok) return 0;
+
+	ok = push_word(desc->strs, "room");
 	if (!ok) return 0;
 
 	ok = push_made_of(desc);