1 /**
2  * \file player-spell.c
3  * \brief Spell and prayer casting/praying
4  *
5  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
6  *
7  * This work is free software; you can redistribute it and/or modify it
8  * under the terms of either:
9  *
10  * a) the GNU General Public License as published by the Free Software
11  *    Foundation, version 2, or
12  *
13  * b) the "Angband licence":
14  *    This software may be copied and distributed for educational, research,
15  *    and not for profit purposes provided that this copyright and statement
16  *    are included in all such copies.  Other copyrights may also apply.
17  */
18 
19 #include "angband.h"
20 #include "cave.h"
21 #include "cmd-core.h"
22 #include "effects.h"
23 #include "init.h"
24 #include "monster.h"
25 #include "obj-gear.h"
26 #include "obj-tval.h"
27 #include "obj-util.h"
28 #include "object.h"
29 #include "player-calcs.h"
30 #include "player-spell.h"
31 #include "player-timed.h"
32 #include "player-util.h"
33 #include "project.h"
34 #include "target.h"
35 
36 /**
37  * Stat Table (INT/WIS) -- Minimum failure rate (percentage)
38  */
39 static const int adj_mag_fail[STAT_RANGE] =
40 {
41 	99	/* 3 */,
42 	99	/* 4 */,
43 	99	/* 5 */,
44 	99	/* 6 */,
45 	99	/* 7 */,
46 	50	/* 8 */,
47 	30	/* 9 */,
48 	20	/* 10 */,
49 	15	/* 11 */,
50 	12	/* 12 */,
51 	11	/* 13 */,
52 	10	/* 14 */,
53 	9	/* 15 */,
54 	8	/* 16 */,
55 	7	/* 17 */,
56 	6	/* 18/00-18/09 */,
57 	6	/* 18/10-18/19 */,
58 	5	/* 18/20-18/29 */,
59 	5	/* 18/30-18/39 */,
60 	5	/* 18/40-18/49 */,
61 	4	/* 18/50-18/59 */,
62 	4	/* 18/60-18/69 */,
63 	4	/* 18/70-18/79 */,
64 	4	/* 18/80-18/89 */,
65 	3	/* 18/90-18/99 */,
66 	3	/* 18/100-18/109 */,
67 	2	/* 18/110-18/119 */,
68 	2	/* 18/120-18/129 */,
69 	2	/* 18/130-18/139 */,
70 	2	/* 18/140-18/149 */,
71 	1	/* 18/150-18/159 */,
72 	1	/* 18/160-18/169 */,
73 	1	/* 18/170-18/179 */,
74 	1	/* 18/180-18/189 */,
75 	1	/* 18/190-18/199 */,
76 	0	/* 18/200-18/209 */,
77 	0	/* 18/210-18/219 */,
78 	0	/* 18/220+ */
79 };
80 
81 /**
82  * Stat Table (INT/WIS) -- failure rate adjustment
83  */
84 static const int adj_mag_stat[STAT_RANGE] =
85 {
86 	-5	/* 3 */,
87 	-4	/* 4 */,
88 	-3	/* 5 */,
89 	-3	/* 6 */,
90 	-2	/* 7 */,
91 	-1	/* 8 */,
92 	 0	/* 9 */,
93 	 0	/* 10 */,
94 	 0	/* 11 */,
95 	 0	/* 12 */,
96 	 0	/* 13 */,
97 	 1	/* 14 */,
98 	 2	/* 15 */,
99 	 3	/* 16 */,
100 	 4	/* 17 */,
101 	 5	/* 18/00-18/09 */,
102 	 6	/* 18/10-18/19 */,
103 	 7	/* 18/20-18/29 */,
104 	 8	/* 18/30-18/39 */,
105 	 9	/* 18/40-18/49 */,
106 	10	/* 18/50-18/59 */,
107 	11	/* 18/60-18/69 */,
108 	12	/* 18/70-18/79 */,
109 	15	/* 18/80-18/89 */,
110 	18	/* 18/90-18/99 */,
111 	21	/* 18/100-18/109 */,
112 	24	/* 18/110-18/119 */,
113 	27	/* 18/120-18/129 */,
114 	30	/* 18/130-18/139 */,
115 	33	/* 18/140-18/149 */,
116 	36	/* 18/150-18/159 */,
117 	39	/* 18/160-18/169 */,
118 	42	/* 18/170-18/179 */,
119 	45	/* 18/180-18/189 */,
120 	48	/* 18/190-18/199 */,
121 	51	/* 18/200-18/209 */,
122 	54	/* 18/210-18/219 */,
123 	57	/* 18/220+ */
124 };
125 
126 /**
127  * Initialise player spells
128  */
player_spells_init(struct player * p)129 void player_spells_init(struct player *p)
130 {
131 	int i, num_spells = p->class->magic.total_spells;
132 
133 	/* None */
134 	if (!num_spells) return;
135 
136 	/* Allocate */
137 	p->spell_flags = mem_zalloc(num_spells * sizeof(byte));
138 	p->spell_order = mem_zalloc(num_spells * sizeof(byte));
139 
140 	/* None of the spells have been learned yet */
141 	for (i = 0; i < num_spells; i++)
142 		p->spell_order[i] = 99;
143 }
144 
145 /**
146  * Free player spells
147  */
player_spells_free(struct player * p)148 void player_spells_free(struct player *p)
149 {
150 	mem_free(p->spell_flags);
151 	mem_free(p->spell_order);
152 }
153 
154 /**
155  * Make a list of the spell realms the player's class has books from
156  */
class_magic_realms(const struct player_class * c,int * count)157 struct magic_realm *class_magic_realms(const struct player_class *c, int *count)
158 {
159 	int i;
160 	struct magic_realm *r = mem_zalloc(sizeof(struct magic_realm));
161 
162 	*count = 0;
163 
164 	if (!c->magic.total_spells) {
165 		mem_free(r);
166 		return NULL;
167 	}
168 
169 	for (i = 0; i < c->magic.num_books; i++) {
170 		struct magic_realm *r_test = r;
171 		struct class_book *book = &c->magic.books[i];
172 		bool found = false;
173 
174 		/* Test for first realm */
175 		if (r->name == NULL) {
176 			memcpy(r, book->realm, sizeof(struct magic_realm));
177 			r->next = NULL;
178 			(*count)++;
179 			continue;
180 		}
181 
182 		/* Test for already recorded */
183 		while (r_test) {
184 			if (streq(r_test->name, book->realm->name)) {
185 				found = true;
186 			}
187 			r_test = r_test->next;
188 		}
189 		if (found) continue;
190 
191 		/* Add it */
192 		r_test = mem_zalloc(sizeof(struct magic_realm));
193 		r_test->next = r;
194 		r = r_test;
195 		(*count)++;
196 	}
197 
198 	return r;
199 }
200 
201 
202 /**
203  * Get the spellbook structure from any object which is a book
204  */
object_kind_to_book(const struct object_kind * kind)205 const struct class_book *object_kind_to_book(const struct object_kind *kind)
206 {
207 	struct player_class *class = classes;
208 	while (class) {
209 		int i;
210 
211 		for (i = 0; i < class->magic.num_books; i++)
212 		if ((kind->tval == class->magic.books[i].tval) &&
213 			(kind->sval == class->magic.books[i].sval)) {
214 			return &class->magic.books[i];
215 		}
216 		class = class->next;
217 	}
218 
219 	return NULL;
220 }
221 
222 /**
223  * Get the spellbook structure from an object which is a book the player can
224  * cast from
225  */
player_object_to_book(struct player * p,const struct object * obj)226 const struct class_book *player_object_to_book(struct player *p,
227 											   const struct object *obj)
228 {
229 	int i;
230 
231 	for (i = 0; i < p->class->magic.num_books; i++)
232 		if ((obj->tval == p->class->magic.books[i].tval) &&
233 			(obj->sval == p->class->magic.books[i].sval))
234 			return &p->class->magic.books[i];
235 
236 	return NULL;
237 }
238 
spell_by_index(int index)239 const struct class_spell *spell_by_index(int index)
240 {
241 	int book = 0, count = 0;
242 	const struct class_magic *magic = &player->class->magic;
243 
244 	/* Check index validity */
245 	if (index < 0 || index >= magic->total_spells)
246 		return NULL;
247 
248 	/* Find the book, count the spells in previous books */
249 	while (count + magic->books[book].num_spells - 1 < index)
250 		count += magic->books[book++].num_spells;
251 
252 	/* Find the spell */
253 	return &magic->books[book].spells[index - count];
254 }
255 
256 /**
257  * Collect spells from a book into the spells[] array, allocating
258  * appropriate memory.
259  */
spell_collect_from_book(const struct object * obj,int ** spells)260 int spell_collect_from_book(const struct object *obj, int **spells)
261 {
262 	const struct class_book *book = player_object_to_book(player, obj);
263 	int i, n_spells = 0;
264 
265 	if (!book) {
266 		return n_spells;
267 	}
268 
269 	/* Count the spells */
270 	for (i = 0; i < book->num_spells; i++)
271 		n_spells++;
272 
273 	/* Allocate the array */
274 	*spells = mem_zalloc(n_spells * sizeof(*spells));
275 
276 	/* Write the spells */
277 	for (i = 0; i < book->num_spells; i++)
278 		(*spells)[i] = book->spells[i].sidx;
279 
280 	return n_spells;
281 }
282 
283 
284 /**
285  * Return the number of castable spells in the spellbook 'obj'.
286  */
spell_book_count_spells(const struct object * obj,bool (* tester)(int spell))287 int spell_book_count_spells(const struct object *obj,
288 		bool (*tester)(int spell))
289 {
290 	const struct class_book *book = player_object_to_book(player, obj);
291 	int i, n_spells = 0;
292 
293 	if (!book) {
294 		return n_spells;
295 	}
296 
297 	for (i = 0; i < book->num_spells; i++)
298 		if (tester(book->spells[i].sidx))
299 			n_spells++;
300 
301 	return n_spells;
302 }
303 
304 
305 /**
306  * True if at least one spell in spells[] is OK according to spell_test.
307  */
spell_okay_list(bool (* spell_test)(int spell),const int spells[],int n_spells)308 bool spell_okay_list(bool (*spell_test)(int spell),
309 		const int spells[], int n_spells)
310 {
311 	int i;
312 	bool okay = false;
313 
314 	for (i = 0; i < n_spells; i++)
315 		if (spell_test(spells[i]))
316 			okay = true;
317 
318 	return okay;
319 }
320 
321 /**
322  * True if the spell is castable.
323  */
spell_okay_to_cast(int spell)324 bool spell_okay_to_cast(int spell)
325 {
326 	return (player->spell_flags[spell] & PY_SPELL_LEARNED);
327 }
328 
329 /**
330  * True if the spell can be studied.
331  */
spell_okay_to_study(int spell_index)332 bool spell_okay_to_study(int spell_index)
333 {
334 	const struct class_spell *spell = spell_by_index(spell_index);
335 	if (!spell) return false;
336 	return (spell->slevel <= player->lev) &&
337 			!(player->spell_flags[spell_index] & PY_SPELL_LEARNED);
338 }
339 
340 /**
341  * True if the spell is browsable.
342  */
spell_okay_to_browse(int spell_index)343 bool spell_okay_to_browse(int spell_index)
344 {
345 	const struct class_spell *spell = spell_by_index(spell_index);
346 	if (!spell) return false;
347 	return (spell->slevel < 99);
348 }
349 
350 /**
351  * Spell failure adjustment by casting stat level
352  */
fail_adjust(struct player * p,const struct class_spell * spell)353 static int fail_adjust(struct player *p, const struct class_spell *spell)
354 {
355 	int stat = spell->realm->stat;
356 	return adj_mag_stat[p->state.stat_ind[stat]];
357 }
358 
359 /**
360  * Spell minimum failure by casting stat level
361  */
min_fail(struct player * p,const struct class_spell * spell)362 static int min_fail(struct player *p, const struct class_spell *spell)
363 {
364 	int stat = spell->realm->stat;
365 	return adj_mag_fail[p->state.stat_ind[stat]];
366 }
367 
368 /**
369  * Returns chance of failure for a spell
370  */
spell_chance(int spell_index)371 s16b spell_chance(int spell_index)
372 {
373 	int chance = 100, minfail;
374 
375 	const struct class_spell *spell;
376 
377 	/* Paranoia -- must be literate */
378 	if (!player->class->magic.total_spells) return chance;
379 
380 	/* Get the spell */
381 	spell = spell_by_index(spell_index);
382 	if (!spell) return chance;
383 
384 	/* Extract the base spell failure rate */
385 	chance = spell->sfail;
386 
387 	/* Reduce failure rate by "effective" level adjustment */
388 	chance -= 3 * (player->lev - spell->slevel);
389 
390 	/* Reduce failure rate by casting stat level adjustment */
391 	chance -= fail_adjust(player, spell);
392 
393 	/* Not enough mana to cast */
394 	if (spell->smana > player->csp)
395 		chance += 5 * (spell->smana - player->csp);
396 
397 	/* Get the minimum failure rate for the casting stat level */
398 	minfail = min_fail(player, spell);
399 
400 	/* Non zero-fail characters never get better than 5 percent */
401 	if (!player_has(player, PF_ZERO_FAIL) && minfail < 5) {
402 		minfail = 5;
403 	}
404 
405 	/* Necromancers are punished by being on lit squares */
406 	if (player_has(player, PF_UNLIGHT) && square_islit(cave, player->grid)) {
407 		chance += 25;
408 	}
409 
410 	/* Fear makes spells harder (before minfail) */
411 	/* Note that spells that remove fear have a much lower fail rate than
412 	 * surrounding spells, to make sure this doesn't cause mega fail */
413 	if (player_of_has(player, OF_AFRAID)) chance += 20;
414 
415 	/* Minimal and maximal failure rate */
416 	if (chance < minfail) chance = minfail;
417 	if (chance > 50) chance = 50;
418 
419 	/* Stunning makes spells harder (after minfail) */
420 	if (player->timed[TMD_STUN] > 50) {
421 		chance += 25;
422 	} else if (player->timed[TMD_STUN]) {
423 		chance += 15;
424 	}
425 
426 	/* Amnesia makes spells very difficult */
427 	if (player->timed[TMD_AMNESIA]) {
428 		chance = 50 + chance / 2;
429 	}
430 
431 	/* Always a 5 percent chance of working */
432 	if (chance > 95) {
433 		chance = 95;
434 	}
435 
436 	/* Return the chance */
437 	return (chance);
438 }
439 
440 
441 /**
442  * Learn the specified spell.
443  */
spell_learn(int spell_index)444 void spell_learn(int spell_index)
445 {
446 	int i;
447 	const struct class_spell *spell = spell_by_index(spell_index);
448 
449 	/* Learn the spell */
450 	player->spell_flags[spell_index] |= PY_SPELL_LEARNED;
451 
452 	/* Find the next open entry in "spell_order[]" */
453 	for (i = 0; i < player->class->magic.total_spells; i++)
454 		if (player->spell_order[i] == 99) break;
455 
456 	/* Add the spell to the known list */
457 	player->spell_order[i] = spell_index;
458 
459 	/* Mention the result */
460 	msgt(MSG_STUDY, "You have learned the %s of %s.", spell->realm->spell_noun,
461 		 spell->name);
462 
463 	/* One less spell available */
464 	player->upkeep->new_spells--;
465 
466 	/* Message if needed */
467 	if (player->upkeep->new_spells)
468 		msg("You can learn %d more %s%s.", player->upkeep->new_spells,
469 			spell->realm->spell_noun, PLURAL(player->upkeep->new_spells));
470 
471 	/* Redraw Study Status */
472 	player->upkeep->redraw |= (PR_STUDY | PR_OBJECT);
473 }
474 
beam_chance(void)475 static int beam_chance(void)
476 {
477 	int plev = player->lev;
478 	return (player_has(player, PF_BEAM) ? plev : (plev / 2));
479 }
480 
481 /**
482  * Cast the specified spell
483  */
spell_cast(int spell_index,int dir,struct command * cmd)484 bool spell_cast(int spell_index, int dir, struct command *cmd)
485 {
486 	int chance;
487 	bool *ident = mem_zalloc(sizeof(*ident));
488 	int beam  = beam_chance();
489 
490 	/* Get the spell */
491 	const struct class_spell *spell = spell_by_index(spell_index);
492 
493 	/* Spell failure chance */
494 	chance = spell_chance(spell_index);
495 
496 	/* Fail or succeed */
497 	if (randint0(100) < chance) {
498 		event_signal(EVENT_INPUT_FLUSH);
499 		msg("You failed to concentrate hard enough!");
500 	} else {
501 		/* Cast the spell */
502 		if (!effect_do(spell->effect, source_player(), NULL, ident, true, dir,
503 					   beam, 0, cmd)) {
504 			mem_free(ident);
505 			return false;
506 		}
507 
508 		/* Reward COMBAT_REGEN with small HP recovery */
509 		if (player_has(player, PF_COMBAT_REGEN)) {
510 			convert_mana_to_hp(player, spell->smana << 16);
511 		}
512 
513 		/* A spell was cast */
514 		sound(MSG_SPELL);
515 
516 		if (!(player->spell_flags[spell_index] & PY_SPELL_WORKED)) {
517 			int e = spell->sexp;
518 
519 			/* The spell worked */
520 			player->spell_flags[spell_index] |= PY_SPELL_WORKED;
521 
522 			/* Gain experience */
523 			player_exp_gain(player, e * spell->slevel);
524 
525 			/* Redraw object recall */
526 			player->upkeep->redraw |= (PR_OBJECT);
527 		}
528 	}
529 
530 	/* Sufficient mana? */
531 	if (spell->smana <= player->csp) {
532 		/* Use some mana */
533 		player->csp -= spell->smana;
534 	} else {
535 		int oops = spell->smana - player->csp;
536 
537 		/* No mana left */
538 		player->csp = 0;
539 		player->csp_frac = 0;
540 
541 		/* Over-exert the player */
542 		player_over_exert(player, PY_EXERT_FAINT, 100, 5 * oops + 1);
543 		player_over_exert(player, PY_EXERT_CON, 50, 0);
544 	}
545 
546 	/* Redraw mana */
547 	player->upkeep->redraw |= (PR_MANA);
548 
549 	mem_free(ident);
550 	return true;
551 }
552 
553 
spell_needs_aim(int spell_index)554 bool spell_needs_aim(int spell_index)
555 {
556 	const struct class_spell *spell = spell_by_index(spell_index);
557 	assert(spell);
558 	return effect_aim(spell->effect);
559 }
560 
append_random_value_string(char * buffer,size_t size,random_value * rv)561 static size_t append_random_value_string(char *buffer, size_t size,
562 										 random_value *rv)
563 {
564 	size_t offset = 0;
565 
566 	if (rv->base > 0) {
567 		offset += strnfmt(buffer + offset, size - offset, "%d", rv->base);
568 
569 		if (rv->dice > 0 && rv->sides > 0) {
570 			offset += strnfmt(buffer + offset, size - offset, "+");
571 		}
572 	}
573 
574 	if (rv->dice == 1 && rv->sides > 0) {
575 		offset += strnfmt(buffer + offset, size - offset, "d%d", rv->sides);
576 	} else if (rv->dice > 1 && rv->sides > 0) {
577 		offset += strnfmt(buffer + offset, size - offset, "%dd%d", rv->dice,
578 						  rv->sides);
579 	}
580 
581 	return offset;
582 }
583 
spell_effect_append_value_info(const struct effect * effect,char * p,size_t len)584 static void spell_effect_append_value_info(const struct effect *effect,
585 										   char *p, size_t len)
586 {
587 	random_value rv;
588 	const char *type = NULL;
589 	const char *special = NULL;
590 	size_t offset = strlen(p);
591 
592 	type = effect_info(effect);
593 
594 	if (effect->dice != NULL)
595 		dice_roll(effect->dice, &rv);
596 
597 	/* Handle some special cases where we want to append some additional info */
598 	switch (effect->index) {
599 		case EF_HEAL_HP:
600 			/* Append percentage only, as the fixed value is always displayed */
601 			if (rv.m_bonus) special = format("/%d%%", rv.m_bonus);
602 			break;
603 		case EF_TELEPORT:
604 			/* m_bonus means it's a weird random thing */
605 			if (rv.m_bonus) special = "random";
606 			break;
607 		case EF_SPHERE:
608 			/* Append radius */
609 			if (effect->radius) {
610 				int rad = effect->radius;
611 				special = format(", rad %d", rad);
612 			} else {
613 				special = ", rad 2";
614 			}
615 			break;
616 		case EF_BALL:
617 			/* Append radius */
618 			if (effect->radius) {
619 				int rad = effect->radius;
620 				if (effect->other) {
621 					rad += player->lev / effect->other;
622 				}
623 				special = format(", rad %d", rad);
624 			} else {
625 				special = "rad 2";
626 			}
627 			break;
628 		case EF_STRIKE:
629 			/* Append radius */
630 			if (effect->radius) {
631 				special = format(", rad %d", effect->radius);
632 			}
633 			break;
634 		case EF_SHORT_BEAM: {
635 			/* Append length of beam */
636 			int len = effect->radius;
637 			if (effect->other) {
638 				len += player->lev / effect->other;
639 			}
640 			special = format(", len %d", len);
641 			break;
642 		}
643 		case EF_SWARM:
644 			/* Append number of projectiles. */
645 			special = format("x%d", rv.m_bonus);
646 			break;
647 		default:
648 			break;
649 	}
650 
651 	if (type == NULL)
652 		return;
653 
654 	if (offset) {
655 		offset += strnfmt(p + offset, len - offset, ";");
656 	}
657 
658 	if ((rv.base > 0) || (rv.dice > 0 && rv.sides > 0)) {
659 		offset += strnfmt(p + offset, len - offset, " %s ", type);
660 		offset += append_random_value_string(p + offset, len - offset, &rv);
661 
662 		if (special != NULL)
663 			strnfmt(p + offset, len - offset, "%s", special);
664 	}
665 }
666 
get_spell_info(int spell_index,char * p,size_t len)667 void get_spell_info(int spell_index, char *p, size_t len)
668 {
669 	struct effect *effect = spell_by_index(spell_index)->effect;
670 
671 	p[0] = '\0';
672 
673 	while (effect) {
674 		spell_effect_append_value_info(effect, p, len);
675 		effect = effect->next;
676 	}
677 }
678 
spell_value_base_spell_power(void)679 static int spell_value_base_spell_power(void)
680 {
681 	int power = 0;
682 
683 	/* Check the reference race first */
684 	if (ref_race)
685 	   power = ref_race->spell_power;
686 	/* Otherwise the current monster if there is one */
687 	else if (cave->mon_current > 0)
688 		power = cave_monster(cave, cave->mon_current)->race->spell_power;
689 
690 	return power;
691 }
692 
spell_value_base_player_level(void)693 static int spell_value_base_player_level(void)
694 {
695 	return player->lev;
696 }
697 
spell_value_base_dungeon_level(void)698 static int spell_value_base_dungeon_level(void)
699 {
700 	return cave->depth;
701 }
702 
spell_value_base_max_sight(void)703 static int spell_value_base_max_sight(void)
704 {
705 	return z_info->max_sight;
706 }
707 
spell_value_base_weapon_damage(void)708 static int spell_value_base_weapon_damage(void)
709 {
710 	struct object *obj = player->body.slots[slot_by_name(player, "weapon")].obj;
711 	if (!obj) {
712 		return 0;
713 	}
714 	return (damroll(obj->dd, obj->ds) + obj->to_d);
715 }
716 
spell_value_base_player_hp(void)717 static int spell_value_base_player_hp(void)
718 {
719 	return player->chp;
720 }
721 
spell_value_base_monster_percent_hp_gone(void)722 static int spell_value_base_monster_percent_hp_gone(void)
723 {
724 	/* Get the targeted monster, fail horribly if none */
725 	struct monster *mon = target_get_monster();
726 
727 	return mon ? (((mon->maxhp - mon->hp) * 100) / mon->maxhp) : 0;
728 }
729 
spell_value_base_by_name(const char * name)730 expression_base_value_f spell_value_base_by_name(const char *name)
731 {
732 	static const struct value_base_s {
733 		const char *name;
734 		expression_base_value_f function;
735 	} value_bases[] = {
736 		{ "SPELL_POWER", spell_value_base_spell_power },
737 		{ "PLAYER_LEVEL", spell_value_base_player_level },
738 		{ "DUNGEON_LEVEL", spell_value_base_dungeon_level },
739 		{ "MAX_SIGHT", spell_value_base_max_sight },
740 		{ "WEAPON_DAMAGE", spell_value_base_weapon_damage },
741 		{ "PLAYER_HP", spell_value_base_player_hp },
742 		{ "MONSTER_PERCENT_HP_GONE", spell_value_base_monster_percent_hp_gone },
743 		{ NULL, NULL },
744 	};
745 	const struct value_base_s *current = value_bases;
746 
747 	while (current->name != NULL && current->function != NULL) {
748 		if (my_stricmp(name, current->name) == 0)
749 			return current->function;
750 
751 		current++;
752 	}
753 
754 	return NULL;
755 }
756