xref: /openbsd-src/games/hack/hack.o_init.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: hack.o_init.c,v 1.2 2001/01/28 23:41:44 niklas Exp $	*/
2 
3 /*
4  * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
5  */
6 
7 #ifndef lint
8 static char rcsid[] = "$OpenBSD: hack.o_init.c,v 1.2 2001/01/28 23:41:44 niklas Exp $";
9 #endif /* not lint */
10 
11 #include	"config.h"		/* for typedefs */
12 #include	"def.objects.h"
13 #include	"hack.onames.h"		/* for LAST_GEM */
14 #include	<string.h>
15 
16 int
17 letindex(let) register char let; {
18 register int i = 0;
19 register char ch;
20 	while((ch = obj_symbols[i++]) != 0)
21 		if(ch == let) return(i);
22 	return(0);
23 }
24 
25 init_objects(){
26 register int i, j, first, last, sum, end;
27 register char let, *tmp;
28 	/* init base; if probs given check that they add up to 100,
29 	   otherwise compute probs; shuffle descriptions */
30 	end = SIZE(objects);
31 	first = 0;
32 	while( first < end ) {
33 		let = objects[first].oc_olet;
34 		last = first+1;
35 		while(last < end && objects[last].oc_olet == let
36 				&& objects[last].oc_name != NULL)
37 			last++;
38 		i = letindex(let);
39 		if((!i && let != ILLOBJ_SYM) || bases[i] != 0)
40 			error("initialization error");
41 		bases[i] = first;
42 
43 		if(let == GEM_SYM)
44 			setgemprobs();
45 	check:
46 		sum = 0;
47 		for(j = first; j < last; j++) sum += objects[j].oc_prob;
48 		if(sum == 0) {
49 			for(j = first; j < last; j++)
50 			    objects[j].oc_prob = (100+j-first)/(last-first);
51 			goto check;
52 		}
53 		if(sum != 100)
54 			error("init-prob error for %c", let);
55 
56 		if(objects[first].oc_descr != NULL && let != TOOL_SYM){
57 			/* shuffle, also some additional descriptions */
58 			while(last < end && objects[last].oc_olet == let)
59 				last++;
60 			j = last;
61 			while(--j > first) {
62 				i = first + rn2(j+1-first);
63 				tmp = objects[j].oc_descr;
64 				objects[j].oc_descr = objects[i].oc_descr;
65 				objects[i].oc_descr = tmp;
66 			}
67 		}
68 		first = last;
69 	}
70 }
71 
72 probtype(let) register char let; {
73 register int i = bases[letindex(let)];
74 register int prob = rn2(100);
75 	while((prob -= objects[i].oc_prob) >= 0) i++;
76 	if(objects[i].oc_olet != let || !objects[i].oc_name)
77 		panic("probtype(%c) error, i=%d", let, i);
78 	return(i);
79 }
80 
81 setgemprobs()
82 {
83 	register int j,first;
84 	extern xchar dlevel;
85 
86 	first = bases[letindex(GEM_SYM)];
87 
88 	for(j = 0; j < 9-dlevel/3; j++)
89 		objects[first+j].oc_prob = 0;
90 	first += j;
91 	if(first >= LAST_GEM || first >= SIZE(objects) ||
92 	    objects[first].oc_olet != GEM_SYM ||
93 	    objects[first].oc_name == NULL)
94 		printf("Not enough gems? - first=%d j=%d LAST_GEM=%d\n",
95 			first, j, LAST_GEM);
96 	for(j = first; j < LAST_GEM; j++)
97 		objects[j].oc_prob = (20+j-first)/(LAST_GEM-first);
98 }
99 
100 oinit()			/* level dependent initialization */
101 {
102 	setgemprobs();
103 }
104 
105 extern long *alloc();
106 
107 savenames(fd) register fd; {
108 register int i;
109 unsigned len;
110 	bwrite(fd, (char *) bases, sizeof bases);
111 	bwrite(fd, (char *) objects, sizeof objects);
112 	/* as long as we use only one version of Hack/Quest we
113 	   need not save oc_name and oc_descr, but we must save
114 	   oc_uname for all objects */
115 	for(i=0; i < SIZE(objects); i++) {
116 		if(objects[i].oc_uname) {
117 			len = strlen(objects[i].oc_uname)+1;
118 			bwrite(fd, (char *) &len, sizeof len);
119 			bwrite(fd, objects[i].oc_uname, len);
120 		}
121 	}
122 }
123 
124 restnames(fd) register fd; {
125 register int i;
126 unsigned len;
127 	mread(fd, (char *) bases, sizeof bases);
128 	mread(fd, (char *) objects, sizeof objects);
129 	for(i=0; i < SIZE(objects); i++) if(objects[i].oc_uname) {
130 		mread(fd, (char *) &len, sizeof len);
131 		objects[i].oc_uname = (char *) alloc(len);
132 		mread(fd, objects[i].oc_uname, len);
133 	}
134 }
135 
136 dodiscovered()				/* free after Robert Viduya */
137 {
138     extern char *typename();
139     register int i, end;
140     int	ct = 0;
141 
142     cornline(0, "Discoveries");
143 
144     end = SIZE(objects);
145     for (i = 0; i < end; i++) {
146 	if (interesting_to_discover (i)) {
147 	    ct++;
148 	    cornline(1, typename(i));
149 	}
150     }
151     if (ct == 0) {
152 	pline ("You haven't discovered anything yet...");
153 	cornline(3, (char *) 0);
154     } else
155 	cornline(2, (char *) 0);
156 
157     return(0);
158 }
159 
160 interesting_to_discover(i)
161 register int i;
162 {
163     return(
164 	objects[i].oc_uname != NULL ||
165 	 (objects[i].oc_name_known && objects[i].oc_descr != NULL)
166     );
167 }
168