1 #include "std.h"
2 #include "tune.h"
3 
4 #undef EXTRA_RESET
5 #define EXTRA_RESET extra_reset(arg);
6 
extra_reset(arg)7 extra_reset(arg) {
8     object ob;
9     if (arg)
10 	return;
11     move_object("obj/book", this_object());
12     move_object(clone_object("obj/bull_board"), this_object());
13     ob = clone_object("obj/quest_obj");
14     call_other(ob, "set_name", "orc_slayer");
15     call_other(ob, "set_hint",
16 "Retrieve the Orc slayer from the evil orc shaman, and give it to Leo.\n");
17     move_object(ob, "room/quest_room");
18 }
19 
20 #undef EXTRA_INIT
21 #define EXTRA_INIT\
22     add_action("cost_for_level", "cost");\
23     add_action("advance", "advance");\
24     add_action("south", "south");\
25     add_action("banish", "banish");\
26     add_action("list_quests", "list");
27 
28 ONE_EXIT("room/vill_road2", "north",
29 	 "The adventurers guild",
30 	 "You have to come here when you want to advance your level.\n" +
31 	 "You can also buy points for a new level.\n" +
32 	 "Commands: cost, advance [level, str, dex, int, con], list (number).\n" +
33 	 "There is an opening to the south, and some shimmering\n" +
34 	 "blue light in the doorway.\n", 1)
35 
36 int next_level;
37 int next_exp;
38 int level;
39 int exp;
40 string title;         /* now with arrays. :) */
41 object player_ob;
42 string banished_by;
43 
44 /* some minor changes by Iggy. */
45 /* get level asks get_next_exp() and  get_next_title() */
46 
get_level(str)47 get_level(str)
48 {
49 	level = str;
50 
51 	next_exp   = get_next_exp(level);
52 	next_level = level + 1 ;
53 	title      = get_new_title(level);
54 }
55 
56 string male_title_str, fem_title_str, neut_title_str;
57 /*xxx  return title */
get_new_title(str)58 get_new_title(str)
59 {
60     if (!male_title_str){
61 	male_title_str = allocate(20);
62 
63 	male_title_str[19]	="the apprentice Wizard";
64 	male_title_str[18]	="the grand master sorcerer";
65 	male_title_str[17]	="the master sorcerer";
66 	male_title_str[16]	="the apprentice sorcerer";
67 	male_title_str[15]	="the warlock";
68 	male_title_str[14]	="the enchanter";
69 	male_title_str[13]	="the magician";
70 	male_title_str[12]	="the apprentice magician";
71 	male_title_str[11]	="the conjurer";
72 	male_title_str[10]	="the champion";
73 	male_title_str[9]	="the warrior";
74 	male_title_str[8]	="the great adventurer";
75 	male_title_str[7]	="the experienced adventurer";
76 	male_title_str[6]	="the small adventurer";
77 	male_title_str[5]	="the experienced fighter";
78 	male_title_str[4]	="the small fighter";
79 	male_title_str[3]	="the master ranger";
80 	male_title_str[2]	="the lowrank ranger";
81 	male_title_str[1]	="the simple wanderer";
82 	male_title_str[0]	="the utter novice";
83 
84 	fem_title_str = allocate(20);
85 
86 	fem_title_str[19]	="the apprentice Wizard";
87 	fem_title_str[18]	="the grand master sorceress";
88 	fem_title_str[17]	="the master sorceress";
89 	fem_title_str[16]	="the apprentice sorceress";
90 	fem_title_str[15]	="the witch";
91 	fem_title_str[14]	="the enchantress";
92 	fem_title_str[13]	="the magicienne";
93 	fem_title_str[12]	="the apprentice magicienne";
94 	fem_title_str[11]	="the conjuress";
95 	fem_title_str[10]	="the deadly amazon";
96 	fem_title_str[9]	="the amazon";
97 	fem_title_str[8]	="the great adventuress";
98 	fem_title_str[7]	="the experienced adventuress";
99 	fem_title_str[6]	="the small adventuress";
100 	fem_title_str[5]	="the charming siren";
101 	fem_title_str[4]	="the siren";
102 	fem_title_str[3]	="the master ranger";
103 	fem_title_str[2]	="the lowrank ranger";
104 	fem_title_str[1]	="the simple wanderer";
105 	fem_title_str[0]	="the utter novice";
106 
107 	neut_title_str = allocate(20);
108 
109 	neut_title_str[19]	="the apprentice Wizard";
110 	neut_title_str[18]	="the ferocious tyrannosaur";
111 	neut_title_str[17]	="the small tyrannosaur";
112 	neut_title_str[16]	="the vicious dragon";
113 	neut_title_str[15]	="the devious dragon";
114 	neut_title_str[14]	="the small dragon";
115 	neut_title_str[13]	="the powerful demon";
116 	neut_title_str[12]	="the small demon";
117 	neut_title_str[11]	="the beholder";
118 	neut_title_str[10]	="the great monster";
119 	neut_title_str[9]	="the experienced monster";
120 	neut_title_str[8]	="the medium monster";
121 	neut_title_str[7]	="the small monster";
122 	neut_title_str[6]	="the threatening shadow";
123 	neut_title_str[5]	="the shadow";
124 	neut_title_str[4]	="the wraith";
125 	neut_title_str[3]	="the bugbear";
126 	neut_title_str[2]	="the furry creature";
127 	neut_title_str[1]	="the simple creature";
128 	neut_title_str[0]	="the utter creature";
129     }
130     if (!player_ob || !player_ob->query_gender())
131 	return neut_title_str[str];
132     else if (player_ob->query_gender() == 1)
133 	return male_title_str[str];
134     else
135 	return fem_title_str[str];
136 }
137 
138 
139 int exp_str;
140 
141 /*  returns the next_exp. */
get_next_exp(str)142 get_next_exp(str) {
143     if(!exp_str){
144 	exp_str = allocate(20);
145 
146 	exp_str[19]	= 1000000;
147 	exp_str[18]	=  666666;
148 	exp_str[17]	=  444444;
149 	exp_str[16]	=  296296;
150 	exp_str[15]	=  197530;
151 	exp_str[14]	=  131687;
152 	exp_str[13]	=   97791;
153 	exp_str[12]	=   77791;
154 	exp_str[11]	=   58527;
155 	exp_str[10]	=   39018;
156 	exp_str[9]	=   26012;
157 	exp_str[8]	=   17341;
158 	exp_str[7]	=   11561;
159 	exp_str[6]	=    7707;
160 	exp_str[5]	=    5138;
161 	exp_str[4]	=    3425;
162 	exp_str[3]	=    2283;
163 	exp_str[2]	=    1522;
164 	exp_str[1]	=    1014;
165 	exp_str[0]	=     676;
166     }
167     return exp_str[str];
168 }
169 
170 /*
171  * This routine is called by monster, to calculate how much they are worth.
172  * This value should not depend on the tuning.
173  */
query_cost(l)174 query_cost(l) {
175     player_ob = this_player();
176     level = l;
177     if (level >= 20)
178 	return 1000000;
179     get_level(level);
180     return next_exp;
181 }
182 
183 /*
184  * Special function for other guilds to call. Arguments are current level
185  * and experience points.
186  */
query_cost_for_level(l,e)187 query_cost_for_level(l, e) {
188     level = l;
189     exp = e;
190     get_level(0);
191     if (next_exp <= exp)
192 	return 0;
193     return (next_exp - exp) * 1000 / EXP_COST;
194 }
195 
cost_for_level()196 cost_for_level()
197 {
198     int cost;
199 
200     player_ob = this_player();
201     level = call_other(player_ob, "query_level", 0);
202 
203     cost = raise_cost(player_ob->query_str(), 0);
204     if (cost)
205 	write("Str: " + cost + " experience points.\n");
206     else
207 	write("Str: Not possible.\n");
208 
209     cost = raise_cost(player_ob->query_con(), 0);
210     if (cost)
211 	write("Con: " + cost + " experience points.\n");
212     else
213 	write("Con: Not possible.\n");
214 
215     cost = raise_cost(player_ob->query_dex(), 0);
216     if (cost)
217 	write("Dex: " + cost + " experience points.\n");
218     else
219 	write("Dex: Not possible.\n");
220 
221     cost = raise_cost(player_ob->query_int(), 0);
222     if (cost)
223 	write("Int: " + cost + " experience points.\n");
224     else
225 	write("Int: Not possible.\n");
226 
227     if (level >= 20) {
228 	write("You will have to seek other ways.\n");
229 	return 1;
230     }
231     exp = call_other(player_ob, "query_exp", 0);
232     get_level(level);
233     if (next_exp <= exp) {
234 	write("It will cost you nothing to be promoted.\n");
235 	return 1;
236     }
237     write("It will cost you "); write((next_exp - exp) * 1000 / EXP_COST);
238     write(" gold coins to advance to level "); write(next_level);
239     write(".\n");
240     return 1;
241 }
242 
advance(arg)243 advance(arg)
244 {
245     string name_of_player;
246     int cost;
247 
248     if (arg == "con")
249     {
250 	raise_con();
251 	return 1;
252     }
253 
254     if (arg == "dex")
255     {
256 	raise_dex();
257 	return 1;
258     }
259 
260     if (arg == "int")
261     {
262 	raise_int();
263 	return 1;
264     }
265 
266     if (arg == "str")
267     {
268 	raise_str();
269 	return 1;
270     }
271 
272     if (arg && arg != "level")
273 	return 0;
274 
275     player_ob = this_player();
276     name_of_player = call_other(player_ob, "query_name", 0);
277     level = call_other(player_ob, "query_level", 0);
278     if (level == -1)
279 	level = 0;
280     exp = call_other(player_ob, "query_exp", 0);
281     title = call_other(player_ob, "query_title", 0);
282     if (level >= 20) {
283 	write("You are still "); write(title); write("\n");
284 	return 1;
285     }
286     get_level(level);
287     if (next_level == 20 && call_other("room/quest_room", "count", 0))
288 	return 1;
289     if (level == 0)
290 	next_exp = exp;
291     cost = (next_exp - exp) * 1000 / EXP_COST;
292     if (next_exp > exp) {
293 	if (call_other(player_ob, "query_money", 0) < cost) {
294 	    write("You don't have enough gold coins.\n");
295 	    return 1;
296 	}
297 	call_other(player_ob, "add_money", - cost);
298     }
299     say(call_other(player_ob, "query_name", 0) + " is now level " +
300 	next_level + ".\n");
301     call_other(player_ob, "set_level", next_level);
302     call_other(player_ob, "set_title", title);
303     if (exp < next_exp)
304         call_other(player_ob, "add_exp", next_exp - exp);
305     if (next_level < 7) {
306 	write("You are now " + name_of_player + " " + title +
307 	      " (level " + next_level + ").\n");
308 	return 1;
309     }
310     if (next_level < 14) {
311 	write("Well done, " + name_of_player + " " + title +
312 	      " (level " + next_level + ").\n");
313 	return 1;
314     }
315     if (next_level < 20) {
316 	write("Welcome to your new class, mighty one.\n" +
317 	      "You are now " + title + " (level " + next_level + ").\n");
318     }
319     if (next_level == 20) {
320 	write("A new Wizard has been born.\n");
321 	shout("A new Wizard has been born.\n");
322 	return 1;
323     }
324     return 1;
325 }
326 
raise_con()327 raise_con()
328 {
329     int lvl;
330 
331     if (too_high_average())
332 	return;
333     lvl = this_player()->query_con();
334     if (lvl >= 20) {
335 	alas("tough and endurable");
336 	return;
337     }
338     if (raise_cost(lvl, 1))
339     {
340 	this_player()->set_con(lvl + 1);
341 	write("Ok.\n");
342     }
343     else
344 	write("You don't have enough experience.\n");
345 }
346 
raise_dex()347 raise_dex()
348 {
349     int lvl;
350 
351     if (too_high_average())
352 	return;
353     lvl = this_player()->query_dex();
354     if (lvl >= 20) {
355 	alas("skilled and vigorous");
356 	return;
357     }
358     if (raise_cost(lvl, 1))
359     {
360 	this_player()->set_dex(lvl + 1);
361 	write("Ok.\n");
362     }
363     else
364 	write("You don't have enough experience.\n");
365 }
366 
raise_int()367 raise_int()
368 {
369     int lvl;
370 
371     if (too_high_average())
372 	return;
373     lvl = this_player()->query_int();
374     if (lvl >= 20) {
375 	alas("knowledgeable and wise");
376 	return;
377     }
378     if (raise_cost(lvl, 1))
379     {
380 	this_player()->set_int(lvl + 1);
381 	write("Ok.\n");
382     }
383     else
384 	write("You don't have enough experience.\n");
385 }
386 
raise_str()387 raise_str()
388 {
389     int lvl;
390 
391     if (too_high_average())
392 	return;
393     lvl = this_player()->query_str();
394     if (lvl >= 20) {
395 	alas("strong and powerful");
396 	return;
397     }
398     if (raise_cost(lvl, 1))
399     {
400 	this_player()->set_str(lvl + 1);
401 	write("Ok.\n");
402     }
403     else
404 	write("You don't have enough experience.\n");
405 }
406 
407 /*
408  * Compute cost for raising a stat one level. 'base' is the level that
409  * you have now, but never less than 1.
410  */
raise_cost(base,action)411 raise_cost(base, action)
412 {
413     int cost, saldo;
414 
415     if (base >= 20)
416 	return 0;
417     cost = (get_next_exp(base) - get_next_exp(base - 1)) / STAT_COST;
418     saldo = this_player()->query_exp() -
419 	get_next_exp(this_player()->query_level()- 1);
420     if (action == 0)
421 	return cost;
422     if (saldo < cost)
423 	return 0;
424     this_player()->add_exp(-cost);
425     return cost;
426 }
427 
428 /*
429  * Banish a monster name from being used.
430  */
banish(who)431 banish(who) {
432     level = call_other(this_player(), "query_level");
433     if (level < 21)
434 	return 0;
435     if (!who) {
436 	write("Who ?\n");
437 	return 1;
438     }
439     if (!call_other(this_player(), "valid_name", who))
440 	return 1;
441     if (restore_object("players/" + who)) {
442 	write("That name is already used.\n");
443 	return 1;
444     }
445     if (restore_object("banish/" + who)) {
446 	write("That name is already banished.\n");
447 	return 1;
448     }
449     banished_by = call_other(this_player(), "query_name");
450     title = call_other(this_player(), "query_title");
451     if (banished_by == "Someone") {
452 	write("You must not be invisible!\n");
453 	return 1;
454     }
455     save_object("banish/" + who);
456     return 1;
457 }
458 
south()459 south() {
460     if (call_other(this_player(), "query_level", 0) < 20) {
461 	write("A strong magic force stops you.\n");
462 	say(call_other(this_player(), "query_name", 0) +
463 	    " tries to go through the field, but fails.\n");
464 	return 1;
465     }
466     write("You wriggle through the force field...\n");
467     call_other(this_player(), "move_player", "south#room/adv_inner");
468     return 1;
469 }
470 
list_quests(num)471 list_quests(num)
472 {
473     int qnumber;
474     if (num && (sscanf(num, "%d", qnumber) == 1))
475 	call_other("room/quest_room", "list", qnumber);
476     else
477 	call_other("room/quest_room", "count", 0);
478     return 1;
479 }
480 
query_drop_castle()481 query_drop_castle() {
482     return 1;
483 }
484 
alas(what)485 alas(what) {
486     write("Sorry " + gnd_prn() + ", but you are already as " + what +
487 	  "\nas any");
488     if (this_player()->query_gender() == 0)
489 	write("thing could possibly hope to get.\n");
490     else
491 	write("one could possibly hope to get.\n");
492 }
493 
494 /*
495  * Check that the player does not have too high average of the stats.
496  */
too_high_average()497 too_high_average() {
498     if ((this_player()->query_con() + this_player()->query_str() +
499 	 this_player()->query_int() + this_player()->query_dex()) / 4 >=
500             this_player()->query_level() + 3) {
501 	write("Sorry " + gnd_prn() +
502 	      ", but you are not of high enough level.\n");
503 	return 1;
504     }
505     return 0;
506 }
507 
gnd_prn()508 gnd_prn() {
509     int gnd;
510 
511     gnd = this_player()->query_gender();
512     if (gnd == 1)
513 	return "sir";
514     else if (gnd == 2)
515 	return "madam";
516     else
517 	return "best creature";
518 }
519