| 996 | } |
| 997 | |
| 998 | staticfn void |
| 999 | give_spell(void) |
| 1000 | { |
| 1001 | struct obj *otmp; |
| 1002 | char spe_let; |
| 1003 | int spe_knowledge, trycnt = u.ulevel + 1; |
| 1004 | |
| 1005 | /* not yet known spells and forgotten spells are given preference over |
| 1006 | usable ones; also, try to grant spell that hero could gain skill in |
| 1007 | (even though being restricted doesn't prevent learning and casting) */ |
| 1008 | otmp = mkobj(SPBOOK_no_NOVEL, TRUE); |
| 1009 | while (--trycnt > 0) { |
| 1010 | if (otmp->otyp != SPE_BLANK_PAPER) { |
| 1011 | if (known_spell(otmp->otyp) <= spe_Unknown |
| 1012 | && !P_RESTRICTED(spell_skilltype(otmp->otyp))) |
| 1013 | break; /* forgotten or not yet known */ |
| 1014 | } else { |
| 1015 | /* blank paper is acceptable if not discovered yet or |
| 1016 | if hero has a magic marker to write something on it |
| 1017 | (doesn't matter if marker is out of charges); it will |
| 1018 | become discovered (below) without needing to be read */ |
| 1019 | if (!objects[SPE_BLANK_PAPER].oc_name_known |
| 1020 | || carrying(MAGIC_MARKER)) |
| 1021 | break; |
| 1022 | } |
| 1023 | otmp->otyp = rnd_class(svb.bases[SPBOOK_CLASS], SPE_BLANK_PAPER); |
| 1024 | } |
| 1025 | /* |
| 1026 | * 25% chance of learning the spell directly instead of |
| 1027 | * receiving the book for it, unless it's already well known. |
| 1028 | * The chance is not influenced by whether hero is illiterate. |
| 1029 | */ |
| 1030 | if (otmp->otyp != SPE_BLANK_PAPER && !rn2(4) |
| 1031 | && (spe_knowledge = known_spell(otmp->otyp)) != spe_Fresh) { |
| 1032 | /* force_learn_spell() should only return '\0' if the book |
| 1033 | is blank paper or the spell is known and has retention |
| 1034 | of spe_Fresh, so no 'else' case is needed here */ |
| 1035 | if ((spe_let = force_learn_spell(otmp->otyp)) != '\0') { |
| 1036 | /* for spellbook class, OBJ_NAME() yields the name of |
| 1037 | the spell rather than "spellbook of <spell-name>" */ |
| 1038 | const char *spe_name = OBJ_NAME(objects[otmp->otyp]); |
| 1039 | |
| 1040 | if (spe_knowledge == spe_Unknown) /* prior to learning */ |
| 1041 | /* appending "spell 'a'" seems slightly silly but |
| 1042 | is similar to "added to your repertoire, as 'a'" |
| 1043 | and without any spellbook on hand a novice player |
| 1044 | might not recognize that 'spe_name' is a spell */ |
| 1045 | pline("Divine knowledge of %s fills your mind! Spell '%c'.", |
| 1046 | spe_name, spe_let); |
| 1047 | else |
| 1048 | Your("knowledge of spell '%c' - %s is %s.", |
| 1049 | spe_let, spe_name, |
| 1050 | (spe_knowledge == spe_Forgotten) ? "restored" |
| 1051 | : "refreshed"); |
| 1052 | } |
| 1053 | obfree(otmp, (struct obj *) 0); /* discard the book */ |
| 1054 | } else { |
| 1055 | observe_object(otmp); |
no test coverage detected