Source:NetHack 3.1.0/o init.c

From NetHackWiki
Revision as of 06:58, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.1.0/o init.c moved to Source:NetHack 3.1.0/o init.c: Robot: moved page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Below is the full text to o_init.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.0/o_init.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

1.    /*	SCCS Id: @(#)o_init.c	3.1	92/12/11	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #include	"hack.h"		/* for typedefs */
6.    
7.    static void NDECL(setgemprobs);
8.    static void FDECL(shuffle,(int,int,BOOLEAN_P));
9.    static boolean FDECL(interesting_to_discover,(int));
10.   
11.   /* note that NROFOBJECTS is the number of legal objects, which does not count
12.    * the strange object and null object that take up positions 0 and NROFOBJECTS+1
13.    * in the objects array
14.    */
15.   #define TOTAL_OBJS	(NROFOBJECTS+2)
16.   
17.   const char obj_symbols[] = {
18.   	ILLOBJ_CLASS, AMULET_CLASS, GOLD_CLASS, FOOD_CLASS, WEAPON_CLASS,
19.   	TOOL_CLASS, BALL_CLASS, CHAIN_CLASS, ROCK_CLASS, ARMOR_CLASS,
20.   	POTION_CLASS, SCROLL_CLASS, WAND_CLASS,
21.   	SPBOOK_CLASS, RING_CLASS, GEM_CLASS, 0 };
22.   
23.   static short NEARDATA disco[TOTAL_OBJS] = DUMMY;
24.   
25.   int
26.   letindex(acls) register char acls; {
27.   register int i = 0;
28.   register char ch;
29.   	while ((ch = obj_symbols[i++]) != 0)
30.   		if (ch == acls) return(i);
31.   	return(0);
32.   }
33.   
34.   static void
35.   setgemprobs()
36.   {
37.   	register int j, first;
38.   	int lev = (ledger_no(&u.uz) > maxledgerno())
39.   				? maxledgerno() : ledger_no(&u.uz);
40.   
41.   	first = bases[letindex(GEM_CLASS)];
42.   
43.   	for(j = 0; j < 9-lev/3; j++)
44.   		objects[first+j].oc_prob = 0;
45.   	first += j;
46.   	if (first > LAST_GEM || objects[first].oc_class != GEM_CLASS ||
47.   	    OBJ_NAME(objects[first]) == NULL) {
48.   		raw_printf("Not enough gems? - first=%d j=%d LAST_GEM=%d",
49.   			first, j, LAST_GEM);
50.   		wait_synch();
51.   	    }
52.   	for (j = first; j <= LAST_GEM; j++)
53.   		objects[j].oc_prob = (184+j-first)/(LAST_GEM+1-first);
54.   }
55.   
56.   /* shuffle descriptions on objects o_low to o_high */
57.   static void
58.   shuffle(o_low, o_high, domaterial)
59.   	register int o_low, o_high;
60.   	register boolean domaterial;
61.   {
62.   	register int i, j;
63.   #ifdef TEXTCOLOR
64.   	int color;
65.   #endif /* TEXTCOLOR */
66.   	register short sw;
67.   
68.   	for (j=o_low; j <= o_high; j++) {
69.   		i = o_low + rn2(j+1-o_low);
70.   		sw = objects[j].oc_descr_idx;
71.   		objects[j].oc_descr_idx = objects[i].oc_descr_idx;
72.   		objects[i].oc_descr_idx = sw;
73.   #ifdef TEXTCOLOR
74.   		color = objects[j].oc_color;
75.   		objects[j].oc_color = objects[i].oc_color;
76.   		objects[i].oc_color = color;
77.   #endif /* TEXTCOLOR */
78.   		/* shuffle material */
79.   		if (domaterial) {
80.   			sw = objects[j].oc_material;
81.   			objects[j].oc_material = objects[i].oc_material;
82.   			objects[i].oc_material = sw;
83.   		}
84.   	}
85.   }
86.   
87.   void
88.   init_objects(){
89.   register int i, j, first, last, sum, end;
90.   register char acls;
91.   #ifdef TEXTCOLOR
92.   # define COPY_OBJ_DESCR(o_dst,o_src) \
93.   			o_dst.oc_descr_idx = o_src.oc_descr_idx,\
94.   			o_dst.oc_color = o_src.oc_color
95.   #else
96.   # define COPY_OBJ_DESCR(o_dst,o_src) o_dst.oc_descr_idx = o_src.oc_descr_idx
97.   #endif
98.   
99.   	/* bug fix to prevent "initialization error" abort on Intel Xenix.
100.  	 * reported by mikew@semike
101.  	 */
102.  	for (i = 0; i < sizeof(obj_symbols); i++)
103.  		bases[i] = 0;
104.  	/* initialize object descriptions */
105.  	for (i = 0; i < TOTAL_OBJS; i++)
106.  		objects[i].oc_name_idx = objects[i].oc_descr_idx = i;
107.  	init_artifacts();
108.  	/* init base; if probs given check that they add up to 1000,
109.  	   otherwise compute probs; shuffle descriptions */
110.  	end = TOTAL_OBJS;
111.  	first = 0;
112.  	while( first < end ) {
113.  		acls = objects[first].oc_class;
114.  		last = first+1;
115.  		while (last < end && objects[last].oc_class == acls) last++;
116.  		i = letindex(acls);
117.  		if ((!i && acls != ILLOBJ_CLASS && acls != VENOM_CLASS) ||
118.  								bases[i] != 0)
119.  			error("initialization error for object class %d", acls);
120.  		bases[i] = first;
121.  
122.  		if (acls == GEM_CLASS) setgemprobs();
123.  	check:
124.  		sum = 0;
125.  		for(j = first; j < last; j++) sum += objects[j].oc_prob;
126.  		if(sum == 0) {
127.  			for(j = first; j < last; j++)
128.  			    objects[j].oc_prob = (1000+j-first)/(last-first);
129.  			goto check;
130.  		}
131.  		if(sum != 1000)
132.  			error("init-prob error for %d (%d%%)", acls, sum);
133.  
134.  		if (OBJ_DESCR(objects[first]) != NULL &&
135.  		   acls != TOOL_CLASS && acls != WEAPON_CLASS && acls != ARMOR_CLASS) {
136.  
137.  		    /* shuffle, also some additional descriptions */
138.  		    while (last < end && objects[last].oc_class == acls)
139.  			last++;
140.  		    j = last;
141.  		    if (acls == GEM_CLASS) {
142.  			if (rn2(2)) { /* change turquoise from green to blue? */
143.  			    COPY_OBJ_DESCR(objects[TURQUOISE],objects[SAPPHIRE]);
144.  			}
145.  			if (rn2(2)) { /* change aquamarine from green to blue? */
146.  			    COPY_OBJ_DESCR(objects[AQUAMARINE],objects[SAPPHIRE]);
147.  			}
148.  			switch (rn2(4)) { /* change fluorite from violet? */
149.  			    case 0:  break;
150.  			    case 1:	/* blue */
151.  				COPY_OBJ_DESCR(objects[FLUORITE],objects[SAPPHIRE]);
152.  				break;
153.  			    case 2:	/* white */
154.  				COPY_OBJ_DESCR(objects[FLUORITE],objects[DIAMOND]);
155.  				break;
156.  			    case 3:	/* green */
157.  				COPY_OBJ_DESCR(objects[FLUORITE],objects[EMERALD]);
158.  				break;
159.  			}
160.  		    } else {
161.  			if (acls == POTION_CLASS)
162.  			    j--;  /* only water has a fixed description */
163.  			else if (acls == AMULET_CLASS ||
164.  				 acls == SCROLL_CLASS ||
165.  				 acls == SPBOOK_CLASS)
166.  			    do { j--; }
167.  			    while (!objects[j].oc_magic || objects[j].oc_unique);
168.  			/* non-magical amulets, scrolls, and spellbooks
169.  			 * (ex. imitation Amulets, blank, scrolls of mail)
170.  			 * and one-of-a-kind magical artifacts at the end of
171.  			 * their class in objects[] have fixed descriptions.
172.  			 */
173.  			shuffle(first, --j, TRUE);
174.  		    }
175.  		}
176.  		first = last;
177.  	}
178.  
179.  	/* shuffle the helmets */
180.  	shuffle(HELMET, HELM_OF_TELEPATHY, FALSE);
181.  
182.  	/* shuffle the gloves */
183.  	shuffle(LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY, FALSE);
184.  
185.  	/* shuffle the cloaks */
186.  	shuffle(CLOAK_OF_PROTECTION, CLOAK_OF_DISPLACEMENT, FALSE);
187.  
188.  	/* shuffle the boots [if they change, update find_skates() below] */
189.  	shuffle(SPEED_BOOTS, LEVITATION_BOOTS, FALSE);
190.  }
191.  
192.  /* find the object index for snow boots; used [once] by slippery ice code */
193.  int
194.  find_skates()
195.  {
196.      register int i;
197.      register const char *s;
198.  
199.      for (i = SPEED_BOOTS; i <= LEVITATION_BOOTS; i++)
200.  	if ((s = OBJ_DESCR(objects[i])) != 0 && !strcmp(s, "snow boots"))
201.  	    return i;
202.  
203.      impossible("snow boots not found?");
204.      return -1;	/* not 0, or caller would try again each move */
205.  }
206.  
207.  void
208.  oinit()			/* level dependent initialization */
209.  {
210.  	setgemprobs();
211.  }
212.  
213.  void
214.  savenames(fd)
215.  register int fd;
216.  {
217.  	register int i;
218.  	unsigned int len;
219.  
220.  	bwrite(fd, (genericptr_t)bases, MAXOCLASSES * sizeof *bases);
221.  	bwrite(fd, (genericptr_t)disco, sizeof disco);
222.  	bwrite(fd, (genericptr_t)objects, sizeof(struct objclass) * TOTAL_OBJS);
223.  	/* as long as we use only one version of Hack we
224.  	   need not save oc_name and oc_descr, but we must save
225.  	   oc_uname for all objects */
226.  	for(i=0; i < TOTAL_OBJS; i++) {
227.  		if(objects[i].oc_uname) {
228.  			len = strlen(objects[i].oc_uname)+1;
229.  			bwrite(fd, (genericptr_t)&len, sizeof len);
230.  			bwrite(fd, (genericptr_t)objects[i].oc_uname, len);
231.  		}
232.  	}
233.  }
234.  
235.  void
236.  restnames(fd)
237.  register int fd;
238.  {
239.  	register int i;
240.  	unsigned int len;
241.  
242.  	mread(fd, (genericptr_t) bases, MAXOCLASSES * sizeof *bases);
243.  	mread(fd, (genericptr_t) disco, sizeof disco);
244.  	mread(fd, (genericptr_t) objects, sizeof(struct objclass) * TOTAL_OBJS);
245.  	for(i=0; i < TOTAL_OBJS; i++) {
246.  		if (objects[i].oc_uname) {
247.  			mread(fd, (genericptr_t) &len, sizeof len);
248.  			objects[i].oc_uname = (char *) alloc(len);
249.  			mread(fd, (genericptr_t)objects[i].oc_uname, len);
250.  		}
251.  	}
252.  }
253.  
254.  void
255.  discover_object(oindx, mark_as_known)
256.  register int oindx;
257.  boolean mark_as_known;
258.  {
259.      if (!objects[oindx].oc_name_known) {
260.  	register int dindx, acls = objects[oindx].oc_class;
261.  
262.  	/* Loop thru disco[] 'til we find the target (which may have been
263.  	   uname'd) or the next open slot; one or the other will be found
264.  	   before we reach the next class...
265.  	 */
266.  	for (dindx = bases[letindex(acls)]; disco[dindx] != 0; dindx++)
267.  	    if (disco[dindx] == oindx) break;
268.  	disco[dindx] = oindx;
269.  
270.  	if (mark_as_known) {
271.  	    objects[oindx].oc_name_known = 1;
272.  	    exercise(A_WIS, TRUE);
273.  	}
274.      }
275.  }
276.  
277.  /* if a class name has been cleared, we may need to purge it from disco[] */
278.  void
279.  undiscover_object(oindx)
280.  register int oindx;
281.  {
282.      if (!objects[oindx].oc_name_known) {
283.  	register int dindx, acls = objects[oindx].oc_class;
284.  	register boolean found = FALSE;
285.  
286.  	/* find the object; shift those behind it forward one slot */
287.  	for (dindx = bases[letindex(acls)];
288.  	      dindx <= NROFOBJECTS && disco[dindx] != 0
289.  		&& objects[dindx].oc_class == acls; dindx++)
290.  	    if (found)
291.  		disco[dindx-1] = disco[dindx];
292.  	    else if (disco[dindx] == oindx)
293.  		found = TRUE;
294.  
295.  	/* clear last slot */
296.  	if (found) disco[dindx-1] = 0;
297.  	else impossible("named object not in disco");
298.      }
299.  }
300.  
301.  static boolean
302.  interesting_to_discover(i)
303.  register int i;
304.  {
305.      return objects[i].oc_uname != NULL ||
306.  		(objects[i].oc_name_known && OBJ_DESCR(objects[i]) != NULL);
307.  }
308.  
309.  int
310.  dodiscovered()				/* free after Robert Viduya */
311.  {
312.      register int i, dis;
313.      int	ct = 0;
314.      char class = -1;
315.      winid tmpwin;
316.  
317.      tmpwin = create_nhwindow(NHW_MENU);
318.      putstr(tmpwin, 0, "Discoveries");
319.      putstr(tmpwin, 0, "");
320.  
321.      for (i = 0; i <= NROFOBJECTS; i++) {
322.  	if ((dis = disco[i]) && interesting_to_discover(dis)) {
323.  	    ct++;
324.  	    if (objects[dis].oc_class != class) {
325.  		class = objects[dis].oc_class;
326.  		putstr(tmpwin, ATR_INVERSE, let_to_name(class, FALSE));
327.  	    }
328.  	    putstr(tmpwin, 0, typename(dis));
329.  	}
330.      }
331.      if (ct == 0) {
332.  	You("haven't discovered anything yet...");
333.      } else
334.  	display_nhwindow(tmpwin, TRUE);
335.      destroy_nhwindow(tmpwin);
336.  
337.      return 0;
338.  }
339.  
340.  /*o_init.c*/