Wikia

Wikihack

Source:O init.c

2,032pages on
this wiki
Talk0

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

Top of file Edit

1.    /*	SCCS Id: @(#)o_init.c	3.4	1999/12/09	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
5.    #include "hack.h"
6.    #include "lev.h"	/* save & restore info */
7.    
8.    STATIC_DCL void FDECL(setgemprobs, (d_level*));
9.    STATIC_DCL void FDECL(shuffle,(int,int,BOOLEAN_P));
10.   STATIC_DCL void NDECL(shuffle_all);
11.   STATIC_DCL boolean FDECL(interesting_to_discover,(int));
12.   
13.   
14.   static NEARDATA short disco[NUM_OBJECTS] = DUMMY;
15.   

shuffle_tiles Edit

16.   #ifdef USE_TILES
17.   STATIC_DCL void NDECL(shuffle_tiles);
18.   extern short glyph2tile[];	/* from tile.c */
19.   
20.   /* Shuffle tile assignments to match descriptions, so a red potion isn't
21.    * displayed with a blue tile and so on.
22.    *
23.    * Tile assignments are not saved, and shouldn't be so that a game can
24.    * be resumed on an otherwise identical non-tile-using binary, so we have
25.    * to reshuffle the assignments from oc_descr_idx information when a game
26.    * is restored.  So might as well do that the first time instead of writing
27.    * another routine.
28.    */
29.   STATIC_OVL void
30.   shuffle_tiles()
31.   {
32.   	int i;
33.   	short tmp_tilemap[NUM_OBJECTS];
34.   
35.   	for (i = 0; i < NUM_OBJECTS; i++)
36.   		tmp_tilemap[i] =
37.   			glyph2tile[objects[i].oc_descr_idx + GLYPH_OBJ_OFF];
38.   
39.   	for (i = 0; i < NUM_OBJECTS; i++)
40.   		glyph2tile[i + GLYPH_OBJ_OFF] = tmp_tilemap[i];
41.   }
42.   #endif	/* USE_TILES */
43.   

setgemprobs Edit

44.   STATIC_OVL void
45.   setgemprobs(dlev)
46.   d_level *dlev;
47.   {
48.   	int j, first, lev;
49.   
50.   	if (dlev)
51.   	    lev = (ledger_no(dlev) > maxledgerno())
52.   				? maxledgerno() : ledger_no(dlev);
53.   	else
54.   	    lev = 0;
55.   	first = bases[GEM_CLASS];
56.   
57.   	for(j = 0; j < 9-lev/3; j++)
58.   		objects[first+j].oc_prob = 0;
59.   	first += j;
60.   	if (first > LAST_GEM || objects[first].oc_class != GEM_CLASS ||
61.   	    OBJ_NAME(objects[first]) == (char *)0) {
62.   		raw_printf("Not enough gems? - first=%d j=%d LAST_GEM=%d",
63.   			first, j, LAST_GEM);
64.   		wait_synch();
65.   	    }
66.   	for (j = first; j <= LAST_GEM; j++)
67.   		objects[j].oc_prob = (171+j-first)/(LAST_GEM+1-first);
68.   }
69.   

shuffle Edit

70.   /* shuffle descriptions on objects o_low to o_high */
71.   STATIC_OVL void
72.   shuffle(o_low, o_high, domaterial)
73.   	int o_low, o_high;
74.   	boolean domaterial;
75.   {
76.   	int i, j, num_to_shuffle;
77.   	short sw;
78.   	int color;
79.   
80.   	for (num_to_shuffle = 0, j=o_low; j <= o_high; j++)
81.   		if (!objects[j].oc_name_known) num_to_shuffle++;
82.   	if (num_to_shuffle < 2) return;
83.   
84.   	for (j=o_low; j <= o_high; j++) {
85.   		if (objects[j].oc_name_known) continue;
86.   		do
87.   			i = j + rn2(o_high-j+1);
88.   		while (objects[i].oc_name_known);
89.   		sw = objects[j].oc_descr_idx;
90.   		objects[j].oc_descr_idx = objects[i].oc_descr_idx;
91.   		objects[i].oc_descr_idx = sw;
92.   		sw = objects[j].oc_tough;
93.   		objects[j].oc_tough = objects[i].oc_tough;
94.   		objects[i].oc_tough = sw;
95.   		color = objects[j].oc_color;
96.   		objects[j].oc_color = objects[i].oc_color;
97.   		objects[i].oc_color = color;
98.   
99.   		/* shuffle material */
100.  		if (domaterial) {
101.  			sw = objects[j].oc_material;
102.  			objects[j].oc_material = objects[i].oc_material;
103.  			objects[i].oc_material = sw;
104.  		}
105.  	}
106.  }
107.  

init_objects Edit

108.  void
109.  init_objects()
110.  {
111.  register int i, first, last, sum;
112.  register char oclass;
113.  #ifdef TEXTCOLOR
114.  # define COPY_OBJ_DESCR(o_dst,o_src) \
115.  			o_dst.oc_descr_idx = o_src.oc_descr_idx,\
116.  			o_dst.oc_color = o_src.oc_color
117.  #else
118.  # define COPY_OBJ_DESCR(o_dst,o_src) o_dst.oc_descr_idx = o_src.oc_descr_idx
119.  #endif
120.  
121.  	/* bug fix to prevent "initialization error" abort on Intel Xenix.
122.  	 * reported by mikew@semike
123.  	 */
124.  	for (i = 0; i < MAXOCLASSES; i++)
125.  		bases[i] = 0;
126.  	/* initialize object descriptions */
127.  	for (i = 0; i < NUM_OBJECTS; i++)
128.  		objects[i].oc_name_idx = objects[i].oc_descr_idx = i;
129.  	/* init base; if probs given check that they add up to 1000,
130.  	   otherwise compute probs */
131.  	first = 0;
132.  	while( first < NUM_OBJECTS ) {
133.  		oclass = objects[first].oc_class;
134.  		last = first+1;
135.  		while (last < NUM_OBJECTS && objects[last].oc_class == oclass) last++;
136.  		bases[(int)oclass] = first;
137.  
138.  		if (oclass == GEM_CLASS) {
139.  			setgemprobs((d_level *)0);
140.  
141.  			if (rn2(2)) { /* change turquoise from green to blue? */
142.  			    COPY_OBJ_DESCR(objects[TURQUOISE],objects[SAPPHIRE]);
143.  			}
144.  			if (rn2(2)) { /* change aquamarine from green to blue? */
145.  			    COPY_OBJ_DESCR(objects[AQUAMARINE],objects[SAPPHIRE]);
146.  			}
147.  			switch (rn2(4)) { /* change fluorite from violet? */
148.  			    case 0:  break;
149.  			    case 1:	/* blue */
150.  				COPY_OBJ_DESCR(objects[FLUORITE],objects[SAPPHIRE]);
151.  				break;
152.  			    case 2:	/* white */
153.  				COPY_OBJ_DESCR(objects[FLUORITE],objects[DIAMOND]);
154.  				break;
155.  			    case 3:	/* green */
156.  				COPY_OBJ_DESCR(objects[FLUORITE],objects[EMERALD]);
157.  				break;
158.  			}
159.  		}
160.  	check:
161.  		sum = 0;
162.  		for(i = first; i < last; i++) sum += objects[i].oc_prob;
163.  		if(sum == 0) {
164.  			for(i = first; i < last; i++)
165.  			    objects[i].oc_prob = (1000+i-first)/(last-first);
166.  			goto check;
167.  		}
168.  		if(sum != 1000)
169.  			error("init-prob error for class %d (%d%%)", oclass, sum);
170.  		first = last;
171.  	}
172.  	/* shuffle descriptions */
173.  	shuffle_all();
174.  #ifdef USE_TILES
175.  	shuffle_tiles();
176.  #endif
177.  }
178.  

shuffle_all Edit

179.  STATIC_OVL void
180.  shuffle_all()
181.  {
182.  	int first, last, oclass;
183.  
184.  	for (oclass = 1; oclass < MAXOCLASSES; oclass++) {
185.  		first = bases[oclass];
186.  		last = first+1;
187.  		while (last < NUM_OBJECTS && objects[last].oc_class == oclass)
188.  			last++;
189.  
190.  		if (OBJ_DESCR(objects[first]) != (char *)0 &&
191.  				oclass != TOOL_CLASS &&
192.  				oclass != WEAPON_CLASS &&
193.  				oclass != ARMOR_CLASS &&
194.  				oclass != GEM_CLASS) {
195.  			int j = last-1;
196.  
197.  			if (oclass == POTION_CLASS)
198.  			    j -= 1;  /* only water has a fixed description */
199.  			else if (oclass == AMULET_CLASS ||
200.  				 oclass == SCROLL_CLASS ||
201.  				 oclass == SPBOOK_CLASS) {
202.  			    while (!objects[j].oc_magic || objects[j].oc_unique)
203.  				j--;
204.  			}
205.  
206.  			/* non-magical amulets, scrolls, and spellbooks
207.  			 * (ex. imitation Amulets, blank, scrolls of mail)
208.  			 * and one-of-a-kind magical artifacts at the end of
209.  			 * their class in objects[] have fixed descriptions.
210.  			 */
211.  			shuffle(first, j, TRUE);
212.  		}
213.  	}
214.  
215.  	/* shuffle the helmets */
216.  	shuffle(HELMET, HELM_OF_TELEPATHY, FALSE);
217.  
218.  	/* shuffle the gloves */
219.  	shuffle(LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY, FALSE);
220.  
221.  	/* shuffle the cloaks */
222.  	shuffle(CLOAK_OF_PROTECTION, CLOAK_OF_DISPLACEMENT, FALSE);
223.  
224.  	/* shuffle the boots [if they change, update find_skates() below] */
225.  	shuffle(SPEED_BOOTS, LEVITATION_BOOTS, FALSE);
226.  }
227.  

find_skates Edit

228.  /* find the object index for snow boots; used [once] by slippery ice code */
229.  int
230.  find_skates()
231.  {
232.      register int i;
233.      register const char *s;
234.  
235.      for (i = SPEED_BOOTS; i <= LEVITATION_BOOTS; i++)
236.  	if ((s = OBJ_DESCR(objects[i])) != 0 && !strcmp(s, "snow boots"))
237.  	    return i;
238.  
239.      impossible("snow boots not found?");
240.      return -1;	/* not 0, or caller would try again each move */
241.  }
242.  

oinit Edit

243.  void
244.  oinit()			/* level dependent initialization */
245.  {
246.  	setgemprobs(&u.uz);
247.  }
248.  

savenames Edit

249.  void
250.  savenames(fd, mode)
251.  int fd, mode;
252.  {
253.  	register int i;
254.  	unsigned int len;
255.  
256.  	if (perform_bwrite(mode)) {
257.  	    bwrite(fd, (genericptr_t)bases, sizeof bases);
258.  	    bwrite(fd, (genericptr_t)disco, sizeof disco);
259.  	    bwrite(fd, (genericptr_t)objects,
260.  		   sizeof(struct objclass) * NUM_OBJECTS);
261.  	}
262.  	/* as long as we use only one version of Hack we
263.  	   need not save oc_name and oc_descr, but we must save
264.  	   oc_uname for all objects */
265.  	for (i = 0; i < NUM_OBJECTS; i++)
266.  	    if (objects[i].oc_uname) {
267.  		if (perform_bwrite(mode)) {
268.  		    len = strlen(objects[i].oc_uname)+1;
269.  		    bwrite(fd, (genericptr_t)&len, sizeof len);
270.  		    bwrite(fd, (genericptr_t)objects[i].oc_uname, len);
271.  		}
272.  		if (release_data(mode)) {
273.  		    free((genericptr_t)objects[i].oc_uname);
274.  		    objects[i].oc_uname = 0;
275.  		}
276.  	    }
277.  }
278.  

restnames Edit

279.  void
280.  restnames(fd)
281.  register int fd;
282.  {
283.  	register int i;
284.  	unsigned int len;
285.  
286.  	mread(fd, (genericptr_t) bases, sizeof bases);
287.  	mread(fd, (genericptr_t) disco, sizeof disco);
288.  	mread(fd, (genericptr_t) objects, sizeof(struct objclass) * NUM_OBJECTS);
289.  	for (i = 0; i < NUM_OBJECTS; i++)
290.  	    if (objects[i].oc_uname) {
291.  		mread(fd, (genericptr_t) &len, sizeof len);
292.  		objects[i].oc_uname = (char *) alloc(len);
293.  		mread(fd, (genericptr_t)objects[i].oc_uname, len);
294.  	    }
295.  #ifdef USE_TILES
296.  	shuffle_tiles();
297.  #endif
298.  }
299.  

discover_object Edit

300.  void
301.  discover_object(oindx, mark_as_known, credit_hero)
302.  register int oindx;
303.  boolean mark_as_known;
304.  boolean credit_hero;
305.  {
306.      if (!objects[oindx].oc_name_known) {
307.  	register int dindx, acls = objects[oindx].oc_class;
308.  
309.  	/* Loop thru disco[] 'til we find the target (which may have been
310.  	   uname'd) or the next open slot; one or the other will be found
311.  	   before we reach the next class...
312.  	 */
313.  	for (dindx = bases[acls]; disco[dindx] != 0; dindx++)
314.  	    if (disco[dindx] == oindx) break;
315.  	disco[dindx] = oindx;
316.  
317.  	if (mark_as_known) {
318.  	    objects[oindx].oc_name_known = 1;
319.  	    if (credit_hero) exercise(A_WIS, TRUE);
320.  	}
321.  	if (moves > 1L) update_inventory();
322.      }
323.  }
324.  

undiscover_object Edit

325.  /* if a class name has been cleared, we may need to purge it from disco[] */
326.  void
327.  undiscover_object(oindx)
328.  register int oindx;
329.  {
330.      if (!objects[oindx].oc_name_known) {
331.  	register int dindx, acls = objects[oindx].oc_class;
332.  	register boolean found = FALSE;
333.  
334.  	/* find the object; shift those behind it forward one slot */
335.  	for (dindx = bases[acls];
336.  	      dindx < NUM_OBJECTS && disco[dindx] != 0
337.  		&& objects[dindx].oc_class == acls; dindx++)
338.  	    if (found)
339.  		disco[dindx-1] = disco[dindx];
340.  	    else if (disco[dindx] == oindx)
341.  		found = TRUE;
342.  
343.  	/* clear last slot */
344.  	if (found) disco[dindx-1] = 0;
345.  	else impossible("named object not in disco");
346.  	update_inventory();
347.      }
348.  }
349.  

interesting_to_discover Edit

350.  STATIC_OVL boolean
351.  interesting_to_discover(i)
352.  register int i;
353.  {
354.  	/* Pre-discovered objects are now printed with a '*' */
355.      return((boolean)(objects[i].oc_uname != (char *)0 ||
356.  	    (objects[i].oc_name_known && OBJ_DESCR(objects[i]) != (char *)0)));
357.  }
358.  

dodiscovered Edit

359.  /* items that should stand out once they're known */
360.  static short uniq_objs[] = {
361.  	AMULET_OF_YENDOR,
362.  	SPE_BOOK_OF_THE_DEAD,
363.  	CANDELABRUM_OF_INVOCATION,
364.  	BELL_OF_OPENING,
365.  };
366.  
367.  int
368.  dodiscovered()				/* free after Robert Viduya */
369.  {
370.      register int i, dis;
371.      int	ct = 0;
372.      char *s, oclass, prev_class, classes[MAXOCLASSES];
373.      winid tmpwin;
374.  	char buf[BUFSZ];
375.  
376.      tmpwin = create_nhwindow(NHW_MENU);
377.      putstr(tmpwin, 0, "Discoveries");
378.      putstr(tmpwin, 0, "");
379.  
380.      /* gather "unique objects" into a pseudo-class; note that they'll
381.         also be displayed individually within their regular class */
382.      for (i = dis = 0; i < SIZE(uniq_objs); i++)
383.  	if (objects[uniq_objs[i]].oc_name_known) {
384.  	    if (!dis++)
385.  		putstr(tmpwin, iflags.menu_headings, "Unique Items");
386.  		Sprintf(buf, "  %s", OBJ_NAME(objects[uniq_objs[i]]));
387.  	    putstr(tmpwin, 0, buf);
388.  	    ++ct;
389.  	}
390.      /* display any known artifacts as another pseudo-class */
391.      ct += disp_artifact_discoveries(tmpwin);
392.  
393.      /* several classes are omitted from packorder; one is of interest here */
394.      Strcpy(classes, flags.inv_order);
395.      if (!index(classes, VENOM_CLASS)) {
396.  	s = eos(classes);
397.  	*s++ = VENOM_CLASS;
398.  	*s = '\0';
399.      }
400.  
401.      for (s = classes; *s; s++) {
402.  	oclass = *s;
403.  	prev_class = oclass + 1;	/* forced different from oclass */
404.  	for (i = bases[(int)oclass];
405.  	     i < NUM_OBJECTS && objects[i].oc_class == oclass; i++) {
406.  	    if ((dis = disco[i]) && interesting_to_discover(dis)) {
407.  		ct++;
408.  		if (oclass != prev_class) {
409.  		    putstr(tmpwin, iflags.menu_headings, let_to_name(oclass, FALSE));
410.  		    prev_class = oclass;
411.  		}
412.  		Sprintf(buf, "%s %s",(objects[dis].oc_pre_discovered ? "*" : " "),
413.  				obj_typename(dis));
414.  		putstr(tmpwin, 0, buf);
415.  	    }
416.  	}
417.      }
418.      if (ct == 0) {
419.  	You("haven't discovered anything yet...");
420.      } else
421.  	display_nhwindow(tmpwin, TRUE);
422.      destroy_nhwindow(tmpwin);
423.  
424.      return 0;
425.  }
426.  
427.  /*o_init.c*/

Around Wikia's network

Random Wiki