Wikihack
Advertisement

Below is the full text to o_init.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/o_init.c#line123]], for example.

The latest source code for vanilla NetHack is at Source code.


The NetHack General Public License applies to screenshots, source code and other content from NetHack.
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.    
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.   static NEARDATA short disco[NUM_OBJECTS] = DUMMY;
14.   
15.   #ifdef USE_TILES
16.   STATIC_DCL void NDECL(shuffle_tiles);
17.   extern short glyph2tile[];	/* from tile.c */
18.   
19.   /* Shuffle tile assignments to match descriptions, so a red potion isn't
20.    * displayed with a blue tile and so on.
21.    *
22.    * Tile assignments are not saved, and shouldn't be so that a game can
23.    * be resumed on an otherwise identical non-tile-using binary, so we have
24.    * to reshuffle the assignments from oc_descr_idx information when a game
25.    * is restored.  So might as well do that the first time instead of writing
26.    * another routine.
27.    */
28.   STATIC_OVL void
29.   shuffle_tiles()
30.   {
31.   	int i;
32.   	short tmp_tilemap[NUM_OBJECTS];
33.   
34.   	for (i = 0; i < NUM_OBJECTS; i++)
35.   		tmp_tilemap[i] =
36.   			glyph2tile[objects[i].oc_descr_idx + GLYPH_OBJ_OFF];
37.   
38.   	for (i = 0; i < NUM_OBJECTS; i++)
39.   		glyph2tile[i + GLYPH_OBJ_OFF] = tmp_tilemap[i];
40.   }
41.   #endif	/* USE_TILES */
42.   
43.   #ifdef PROXY_GRAPHICS
44.   STATIC_DCL void NDECL(shuffle_proxy_glyphs);
45.   extern short glyph2proxy[];	/* from glyphmap.c */
46.   
47.   /* Shuffle proxy glyph assignments for the same reason as tiles
48.    * (internal glyphs are based on object numbers, proxy glyphs
49.    * are based on object descriptions).
50.    */
51.   STATIC_OVL void
52.   shuffle_proxy_glyphs()
53.   {
54.   	int i;
55.   	short tmp_glyphmap[NUM_OBJECTS];
56.   
57.   	for (i = 0; i < NUM_OBJECTS; i++)
58.   		tmp_glyphmap[i] =
59.   			glyph2proxy[objects[i].oc_descr_idx + GLYPH_OBJ_OFF];
60.   
61.   	for (i = 0; i < NUM_OBJECTS; i++)
62.   		glyph2proxy[i + GLYPH_OBJ_OFF] = tmp_glyphmap[i];
63.   }
64.   #endif	/* USE_TILES */
65.   
66.   STATIC_OVL void
67.   setgemprobs(dlev)
68.   d_level *dlev;
69.   {
70.   	int j, first, lev;
71.   
72.   	if (dlev)
73.   	    lev = (ledger_no(dlev) > maxledgerno())
74.   				? maxledgerno() : ledger_no(dlev);
75.   	else
76.   	    lev = 0;
77.   	first = bases[GEM_CLASS];
78.   
79.   	for(j = 0; j < 9-lev/3; j++)
80.   		objects[first+j].oc_prob = 0;
81.   	first += j;
82.   	if (first > LAST_GEM || objects[first].oc_class != GEM_CLASS ||
83.   	    OBJ_NAME(objects[first]) == (char *)0) {
84.   		raw_printf("Not enough gems? - first=%d j=%d LAST_GEM=%d",
85.   			first, j, LAST_GEM);
86.   		wait_synch();
87.   	    }
88.   	for (j = first; j <= LAST_GEM; j++)
89.   		/* KMH, balance patch -- valuable gems now sum to 171 */
90.   		objects[j].oc_prob = (171+j-first)/(LAST_GEM+1-first);
91.   }
92.   
93.   /* shuffle descriptions on objects o_low to o_high */
94.   STATIC_OVL void
95.   shuffle(o_low, o_high, domaterial)
96.   	int o_low, o_high;
97.   	boolean domaterial;
98.   {
99.   	int i, j, num_to_shuffle;
100.  	short sw;
101.  	int color;
102.  
103.  	for (num_to_shuffle = 0, j=o_low; j <= o_high; j++)
104.  		if (!objects[j].oc_name_known) num_to_shuffle++;
105.  	if (num_to_shuffle < 2) return;
106.  
107.  	for (j=o_low; j <= o_high; j++) {
108.  		if (objects[j].oc_name_known) continue;
109.  		do
110.  			i = j + rn2(o_high-j+1);
111.  		while (objects[i].oc_name_known);
112.  		sw = objects[j].oc_descr_idx;
113.  		objects[j].oc_descr_idx = objects[i].oc_descr_idx;
114.  		objects[i].oc_descr_idx = sw;
115.  		sw = objects[j].oc_tough;
116.  		objects[j].oc_tough = objects[i].oc_tough;
117.  		objects[i].oc_tough = sw;
118.  		color = objects[j].oc_color;
119.  		objects[j].oc_color = objects[i].oc_color;
120.  		objects[i].oc_color = color;
121.  
122.  		/* shuffle material */
123.  		if (domaterial) {
124.  			sw = objects[j].oc_material;
125.  			objects[j].oc_material = objects[i].oc_material;
126.  			objects[i].oc_material = sw;
127.  		}
128.  	}
129.  }
130.  
131.  void
132.  init_objects()
133.  {
134.  register int i, first, last, sum;
135.  register char oclass;
136.  #ifdef TEXTCOLOR
137.  # define COPY_OBJ_DESCR(o_dst,o_src) \
138.  			o_dst.oc_descr_idx = o_src.oc_descr_idx,\
139.  			o_dst.oc_color = o_src.oc_color
140.  #else
141.  # define COPY_OBJ_DESCR(o_dst,o_src) o_dst.oc_descr_idx = o_src.oc_descr_idx
142.  #endif
143.  
144.  	/* bug fix to prevent "initialization error" abort on Intel Xenix.
145.  	 * reported by mikew@semike
146.  	 */
147.  	for (i = 0; i < MAXOCLASSES; i++)
148.  		bases[i] = 0;
149.  	/* initialize object descriptions */
150.  	for (i = 0; i < NUM_OBJECTS; i++)
151.  		objects[i].oc_name_idx = objects[i].oc_descr_idx = i;
152.  	/* init base; if probs given check that they add up to 1000,
153.  	   otherwise compute probs */
154.  	first = 0;
155.  	while( first < NUM_OBJECTS ) {
156.  		oclass = objects[first].oc_class;
157.  		last = first+1;
158.  		while (last < NUM_OBJECTS && objects[last].oc_class == oclass) last++;
159.  		bases[(int)oclass] = first;
160.  
161.  		if (oclass == GEM_CLASS) {
162.  			setgemprobs((d_level *)0);
163.  
164.  			if (rn2(2)) { /* change turquoise from green to blue? */
165.  			    COPY_OBJ_DESCR(objects[TURQUOISE],objects[SAPPHIRE]);
166.  			}
167.  			if (rn2(2)) { /* change aquamarine from green to blue? */
168.  			    COPY_OBJ_DESCR(objects[AQUAMARINE],objects[SAPPHIRE]);
169.  			}
170.  			switch (rn2(4)) { /* change fluorite from violet? */
171.  			    case 0:  break;
172.  			    case 1:	/* blue */
173.  				COPY_OBJ_DESCR(objects[FLUORITE],objects[SAPPHIRE]);
174.  				break;
175.  			    case 2:	/* white */
176.  				COPY_OBJ_DESCR(objects[FLUORITE],objects[DIAMOND]);
177.  				break;
178.  			    case 3:	/* green */
179.  				COPY_OBJ_DESCR(objects[FLUORITE],objects[EMERALD]);
180.  				break;
181.  			}
182.  		}
183.  	check:
184.  		sum = 0;
185.  		for(i = first; i < last; i++) sum += objects[i].oc_prob;
186.  		if(sum == 0) {
187.  			for(i = first; i < last; i++)
188.  			    objects[i].oc_prob = (1000+i-first)/(last-first);
189.  			goto check;
190.  		}
191.  		if(sum != sum)
192.  			error("init-prob error for class %d (%d%%)", oclass, sum);
193.  		first = last;
194.  	}
195.  	/* shuffle descriptions */
196.  	shuffle_all();
197.  #ifdef USE_TILES
198.  	shuffle_tiles();
199.  #endif
200.  #ifdef PROXY_GRAPHICS
201.  	shuffle_proxy_glyphs();
202.  #endif
203.  }
204.  
205.  STATIC_OVL void
206.  shuffle_all()
207.  {
208.  	int first, last, oclass;
209.  
210.  	for (oclass = 1; oclass < MAXOCLASSES; oclass++) {
211.  		first = bases[oclass];
212.  		last = first+1;
213.  		while (last < NUM_OBJECTS && objects[last].oc_class == oclass)
214.  			last++;
215.  
216.  		if (OBJ_DESCR(objects[first]) != (char *)0 &&
217.  				oclass != TOOL_CLASS &&
218.  				oclass != WEAPON_CLASS &&
219.  				oclass != ARMOR_CLASS &&
220.  				oclass != GEM_CLASS) {
221.  			int j = last-1;
222.  
223.  			if (oclass == POTION_CLASS)
224.  			    /* water and following have fixed descriptions */
225.  			    j = POT_WATER - 1;
226.  			else if (oclass == AMULET_CLASS ||
227.  				 oclass == SCROLL_CLASS ||
228.  				 oclass == SPBOOK_CLASS) {
229.  			    while (!objects[j].oc_magic || objects[j].oc_unique)
230.  				j--;
231.  			}
232.  
233.  			/* non-magical amulets, scrolls, and spellbooks
234.  			 * (ex. imitation Amulets, blank, scrolls of mail)
235.  			 * and one-of-a-kind magical artifacts at the end of
236.  			 * their class in objects[] have fixed descriptions.
237.  			 */
238.  			shuffle(first, j, TRUE);
239.  		}
240.  	}
241.  
242.  	/* shuffle the helmets */
243.  	shuffle(HELMET, HELM_OF_TELEPATHY, FALSE);
244.  
245.  	/* shuffle the gloves */
246.  	shuffle(LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY, FALSE);
247.  
248.      /* shuffle the robes */
249.      shuffle(ROBE, ROBE_OF_WEAKNESS, FALSE);
250.  
251.  	/* shuffle the cloaks */
252.  	shuffle(CLOAK_OF_PROTECTION, CLOAK_OF_DISPLACEMENT, FALSE);
253.  
254.  	/* shuffle the boots [if they change, update find_skates() below] */
255.  	shuffle(SPEED_BOOTS, LEVITATION_BOOTS, FALSE);
256.  }
257.  
258.  /* find the object index for snow boots; used [once] by slippery ice code */
259.  int
260.  find_skates()
261.  {
262.      register int i;
263.      register const char *s;
264.  
265.      for (i = SPEED_BOOTS; i <= LEVITATION_BOOTS; i++)
266.  	if ((s = OBJ_DESCR(objects[i])) != 0 && !strcmp(s, "snow boots"))
267.  	    return i;
268.  
269.      impossible("snow boots not found?");
270.      return -1;	/* not 0, or caller would try again each move */
271.  }
272.  
273.  void
274.  oinit()			/* level dependent initialization */
275.  {
276.  	setgemprobs(&u.uz);
277.  }
278.  
279.  void
280.  savenames(fd, mode)
281.  int fd, mode;
282.  {
283.  	register int i;
284.  	unsigned int len;
285.  
286.  	if (perform_bwrite(mode)) {
287.  	    bwrite(fd, (genericptr_t)bases, sizeof bases);
288.  	    bwrite(fd, (genericptr_t)disco, sizeof disco);
289.  	    bwrite(fd, (genericptr_t)objects,
290.  		   sizeof(struct objclass) * NUM_OBJECTS);
291.  	}
292.  	/* as long as we use only one version of Hack we
293.  	   need not save oc_name and oc_descr, but we must save
294.  	   oc_uname for all objects */
295.  	for (i = 0; i < NUM_OBJECTS; i++)
296.  	    if (objects[i].oc_uname) {
297.  		if (perform_bwrite(mode)) {
298.  		    len = strlen(objects[i].oc_uname)+1;
299.  		    bwrite(fd, (genericptr_t)&len, sizeof len);
300.  		    bwrite(fd, (genericptr_t)objects[i].oc_uname, len);
301.  		}
302.  		if (release_data(mode)) {
303.  		    free((genericptr_t)objects[i].oc_uname);
304.  		    objects[i].oc_uname = 0;
305.  		}
306.  	    }
307.  }
308.  
309.  void
310.  restnames(fd)
311.  register int fd;
312.  {
313.  	register int i;
314.  	unsigned int len;
315.  
316.  	mread(fd, (genericptr_t) bases, sizeof bases);
317.  	mread(fd, (genericptr_t) disco, sizeof disco);
318.  	mread(fd, (genericptr_t) objects, sizeof(struct objclass) * NUM_OBJECTS);
319.  	for (i = 0; i < NUM_OBJECTS; i++)
320.  	    if (objects[i].oc_uname) {
321.  		mread(fd, (genericptr_t) &len, sizeof len);
322.  		objects[i].oc_uname = (char *) alloc(len);
323.  		mread(fd, (genericptr_t)objects[i].oc_uname, len);
324.  	    }
325.  #ifdef USE_TILES
326.  	shuffle_tiles();
327.  #endif
328.  #ifdef PROXY_GRAPHICS
329.  	shuffle_proxy_glyphs();
330.  #endif
331.  }
332.  
333.  void
334.  discover_object(oindx, mark_as_known, credit_hero)
335.  register int oindx;
336.  boolean mark_as_known;
337.  boolean credit_hero;
338.  {
339.  	/* KMH -- If we are hallucinating, we aren't sure of the object description */
340.  	if (Hallucination) return;
341.  
342.      if (!objects[oindx].oc_name_known) {
343.  	register int dindx, acls = objects[oindx].oc_class;
344.  
345.  	/* Loop thru disco[] 'til we find the target (which may have been
346.  	   uname'd) or the next open slot; one or the other will be found
347.  	   before we reach the next class...
348.  	 */
349.  	for (dindx = bases[acls]; disco[dindx] != 0; dindx++)
350.  	    if (disco[dindx] == oindx) break;
351.  	disco[dindx] = oindx;
352.  
353.  	if (mark_as_known) {
354.  	    objects[oindx].oc_name_known = 1;
355.  	    if (credit_hero) exercise(A_WIS, TRUE);
356.  	}
357.  	if (moves > 1L) update_inventory();
358.      }
359.  }
360.  
361.  /* if a class name has been cleared, we may need to purge it from disco[] */
362.  void
363.  undiscover_object(oindx)
364.  register int oindx;
365.  {
366.      if (!objects[oindx].oc_name_known) {
367.  	register int dindx, acls = objects[oindx].oc_class;
368.  	register boolean found = FALSE;
369.  
370.  	/* find the object; shift those behind it forward one slot */
371.  	for (dindx = bases[acls];
372.  	      dindx < NUM_OBJECTS && disco[dindx] != 0
373.  		&& objects[dindx].oc_class == acls; dindx++)
374.  	    if (found)
375.  		disco[dindx-1] = disco[dindx];
376.  	    else if (disco[dindx] == oindx)
377.  		found = TRUE;
378.  
379.  	/* clear last slot */
380.  	if (found) disco[dindx-1] = 0;
381.  	else impossible("named object not in disco");
382.  	update_inventory();
383.      }
384.  }
385.  
386.  STATIC_OVL boolean
387.  interesting_to_discover(i)
388.  register int i;
389.  {
390.  	/* Pre-discovered objects are now printed with a '*' */
391.      return((boolean)(objects[i].oc_uname != (char *)0 ||
392.  	    (objects[i].oc_name_known && OBJ_DESCR(objects[i]) != (char *)0)));
393.  }
394.  
395.  /* items that should stand out once they're known */
396.  static short uniq_objs[] = {
397.  	AMULET_OF_YENDOR,
398.  	SPE_BOOK_OF_THE_DEAD,
399.  	CANDELABRUM_OF_INVOCATION,
400.  	BELL_OF_OPENING,
401.  };
402.  
403.  int
404.  dodiscovered()				/* free after Robert Viduya */
405.  {
406.      register int i, dis;
407.      int	ct = 0;
408.      char *s, oclass, prev_class, classes[MAXOCLASSES];
409.      char buf[BUFSZ];    /* WAC */
410.      winid tmpwin;
411.      anything any;
412.      menu_item *selected;
413.  
414.      tmpwin = create_nhwindow(NHW_MENU);
415.      /*
416.       * Use the add_menu() interface so that eg., GTK windowing port
417.       * can display the relevant glyphs --ALI
418.       */
419.      start_menu(tmpwin);
420.  
421.      any.a_void = 0;
422.      add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_BOLD, "Discoveries",
423.        MENU_UNSELECTED);
424.      add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "",
425.        MENU_UNSELECTED);
426.  
427.      /* gather "unique objects" into a pseudo-class; note that they'll
428.         also be displayed individually within their regular class */
429.      for (i = dis = 0; i < SIZE(uniq_objs); i++)
430.  	if (objects[uniq_objs[i]].oc_name_known) {
431.  	    if (!dis++)
432.  		add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
433.  		  "Unique Items", MENU_UNSELECTED);
434.  		Sprintf(buf, "  %s", OBJ_NAME(objects[uniq_objs[i]]));
435.  	    add_menu(tmpwin, objnum_to_glyph(uniq_objs[i]), &any,
436.  	      0, 0, ATR_NONE, buf, MENU_UNSELECTED);
437.  	    ++ct;
438.  	}
439.      /* display any known artifacts as another pseudo-class */
440.      ct += disp_artifact_discoveries(tmpwin);
441.  
442.      /* several classes are omitted from packorder; one is of interest here */
443.      Strcpy(classes, flags.inv_order);
444.      if (!index(classes, VENOM_CLASS)) {
445.  	s = eos(classes);
446.  	*s++ = VENOM_CLASS;
447.  	*s = '\0';
448.      }
449.  
450.      for (s = classes; *s; s++) {
451.  	oclass = *s;
452.  	prev_class = oclass + 1;	/* forced different from oclass */
453.  	for (i = bases[(int)oclass];
454.  	     i < NUM_OBJECTS && objects[i].oc_class == oclass; i++) {
455.  	    if ((dis = disco[i]) && interesting_to_discover(dis)) {
456.  		ct++;
457.  		if (oclass != prev_class) {
458.  		    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
459.  		      let_to_name(oclass, FALSE), MENU_UNSELECTED);
460.  		    prev_class = oclass;
461.  		}
462.  		Sprintf(buf, "%s %s",(objects[dis].oc_pre_discovered ? "*" : " "),
463.  				obj_typename(dis));
464.  		add_menu(tmpwin, objnum_to_glyph(dis), &any, 0, 0,
465.  		  ATR_NONE, buf, MENU_UNSELECTED);
466.  	    }
467.  	}
468.      }
469.      end_menu(tmpwin, (char *) 0);
470.      if (ct == 0) {
471.  	You("haven't discovered anything yet...");
472.      } else
473.  	(void) select_menu(tmpwin, PICK_NONE, &selected);
474.      destroy_nhwindow(tmpwin);
475.  
476.      return 0;
477.  }
478.  
479.  /*o_init.c*/
Advertisement