PageRenderTime 52ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

C# | 128 lines | 108 code | 19 blank | 1 comment | 3 complexity | 1e9b076d2ba7c881375a646c2876df65 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using NUnit.Framework;
  6. using ArzooSoftware.SpellBinder.spellbinder;
  7. using System.Xml;
  8. namespace ArzooSoftware.SpellBinder.Test
  9. {
  10. [TestFixture]
  11. public class tSpellDescription
  12. {
  13. [Test]
  14. public void ctorSpellDescription()
  15. {
  16. SpellDescription sd = new SpellDescription(norefDescriptionText);
  17. Assert.IsNotNull(sd);
  18. }
  19. private const string norefDescriptionText = @"A confused creature will not be able to coordinate his actions with anyone else. (In the case of player characters, the players may not consult, and must submit orders in writing.) In addition there is a 1/3 chance each round that the creature will not be able to decide what to do that round, and thus will do absolutely nothing at all. Those creatures controlled by some outside source will not be affected, unless the controlling force also fails to save or fails to make other relevant control check. Only those of 4 HD or more will get saving throws. Those of 2 HD or less are affected immediately; others get a delay of d6 minus the level of the caster rounds.";
  20. private const string refDescriptionText = @"This spell will summon a single being, which will appear next to the caster in the powers phase of the round after the spell is cast. The creature will be inclined to serve the caster, under conditions similar to those specified for the 3rd level spell Suggestion (page 71). The creature is real and has been transported here from elsewhere in the general region. At the end of the spell's duration, it will return, alive or dead, whence it came, along with everything it brought with it. The spell's duration begins when the monster appears, so the monster will return after 13 rounds. A base spell of level N allows the summoning of one monster of level N, 1d3 of level N-1, or 1d6 of level N-2. The caster may choose the monster from the Monster Summoning Table (see page 84) or from other tables as supplied by the GM. Attempts to summon unique individuals or of monsters into inappropriate terrain (as a non-flying creature in midair) generally has no effect. Attempting to summon a monster that is appropriate but doesn't happen to exist in the vicinity will result in the arrival of a plausible substitute at the GM's discretion. ";
  21. private const string multiWordNameRefDescriptionText = @"This spell can be cast only to negate a known spell in the process of being cast. The caster must recognize the target's spell as it is being declared during Declarations phase: this requires that the caster already have Analyze Spell (page 68) running, or else make a Spellcraft check against 15 + (base level of spell being cast). Counterspell may be declared after other spellcasting has been declared, even if the caster is abandoning a spell preparation of his own in order to Counterspell, an exception to the usual rule that declarations are simultaneous. The base level at which Counterspell is cast must equal the base level of the spell being countered (modifiers need not match). Another special property of Counterspell is that it is resolved, in the spell phase sequence, as though it cost 0 points to cast: thus it will always go off before the spell it is countering is completed. The target (the caster of the spell being countered) and the caster of the Counterspell engage in a contest of levels, with the Counterspell having a +3 level bonus (net +9 to the d20 roll). If the counterspell wins, the targeted spell fails, although the caster still pays full spell points. Clerical prayers cannot be Counterspelled. Spells cast as Power Words cannot be counterspelled unless the Counterspell is cast as a Power Word also; Analyze Spell will give warning at the beginning of the Powers phase when a caster is about to speak a Power Word, or a second Spellcraft check against 18 + (base level of spell being cast) will alert the Counterspell caster that a Power Word is needed. If the Counterspell caster cannot or chooses not to match the original caster's Power Word, the Counterspell may simply be dropped at no cost, as with any spell. ";
  22. private const string multirefDescriptionText = @"This spell attunes the mage to an object creating a magic bond between the mage and the object. The target of the spell may be a literal object, or a place or a person. If the object is a person, that person must either drop their saving throw or fail to save twice for the attunement to work. Once attuned to the target, the mage enjoys a connection which enhances the operation of some spells: Locate (page 59) works better with attuned objects. Message (page 64) works at much greater range with attuned persons. ESP (page 66) works at greater range and effectiveness with attuned persons. Clairsentience (page 69) works at greater range and effectiveness with attuned persons. Telepathy (page 74) may be forced on attuned targets and used at greater range than normal. Summon (page 78) only works with attuned objects. Teleport (page 78) to distant locations is only safe with attuned places or objects. Aside from these specific spell effects, any spell cast on an attuned target allows the target only half its normal saving throw bonus. Attuning to a literal object or a place is a Level 1 base spell. Attuning to a person is a Level 2 base spell. It takes an hour to attune to an object. A mage can be attuned to a maximum of 7 objects without penalty. Attuning to more objects makes the spell more difficult: attempting to attune an 8th object requires a +1 2 modifier, the 9th attunement requires +1, etc. Note that these modifiers are not required if the mage drops one of his existing attunements in the process of casting the new one, which is the standard action for a mage already holding 7 attunements and requires no extra time or casting cost. Attuning to an object which another mage has already attuned breaks the other mage's bond to the object, but it requires a Level Contest with the previously attuned mage, who gets a 2 level bonus. Players should keep track of the objects their mages are attuned to on their character sheet. It is assumed that every mage is attuned to their home unless otherwise specified. ";
  23. [Test]
  24. public void testNoRef()
  25. {
  26. SpellDescription sd = new SpellDescription(norefDescriptionText);
  27. Assert.IsNotNull(sd);
  28. IList<SpellDescription.Reference> ref_list = sd.FindReferences();
  29. Assert.IsNotNull(ref_list);
  30. Assert.AreEqual(0, ref_list.Count);
  31. }
  32. [Test]
  33. public void testRef()
  34. {
  35. SpellDescription sd = new SpellDescription(refDescriptionText);
  36. Assert.IsNotNull(sd);
  37. IList<SpellDescription.Reference> ref_list = sd.FindReferences();
  38. Assert.IsNotNull(ref_list);
  39. Assert.AreEqual(1, ref_list.Count);
  40. SpellDescription.Reference spell_ref = ref_list[0];
  41. Assert.AreEqual("Suggestion", spell_ref.SpellName);
  42. Assert.AreEqual("Suggestion", refDescriptionText.Substring(spell_ref.Start, spell_ref.End - spell_ref.Start));
  43. }
  44. [Test]
  45. public void testMultiWordSpellName()
  46. {
  47. SpellDescription sd = new SpellDescription(multiWordNameRefDescriptionText);
  48. Assert.IsNotNull(sd);
  49. IList<SpellDescription.Reference> ref_list = sd.FindReferences();
  50. Assert.IsNotNull(ref_list);
  51. Assert.AreEqual(1, ref_list.Count);
  52. SpellDescription.Reference spell_ref = ref_list[0];
  53. Assert.AreEqual("Analyze Spell", spell_ref.SpellName);
  54. Assert.AreEqual("Analyze Spell", multiWordNameRefDescriptionText.Substring(spell_ref.Start, spell_ref.End - spell_ref.Start));
  55. }
  56. [Test]
  57. public void testSpecialSpellRef()
  58. {
  59. SpellDescription sd = new SpellDescription(attundedRefDescriptionText);
  60. Assert.IsNotNull(sd);
  61. IList<SpellDescription.Reference> ref_list = sd.FindReferences();
  62. Assert.IsNotNull(ref_list);
  63. Assert.AreEqual(1, ref_list.Count);
  64. SpellDescription.Reference spell_ref = ref_list[0];
  65. Assert.AreEqual("Attune", spell_ref.SpellName);
  66. }
  67. private const string attundedRefDescriptionText = @"This spell veils the target from various magical means of detection. Once veiled, a target can only be affected by spells that it is veiled against, if the opposing caster wins a Level Contest against the adjusted level of the mage that cast the Veil. If the target has been Attuned (page 56) by either the mage who cast the Veil, or the mage attempting to detect it, that mage receives a 3 level bonus for purposes of the Level Contest. Veil takes 10 rounds to cast and is automatically Concealed, so the spell only radiates magic only if two Level Contests are lost. Target Base Level Protection Cost Self 1 Detect Magic, ESP, Infravision, Range Finder, See Invisible +0 Other 2 Above + Locate, Clairsentience, Trace Summoning +1 Object 2 Above + Summon, Teleport +2 House 3 Attune +2 Castle 4 Clerical Detects +1 Space 3 Magic Item 3 Targets are defined as follows: Self is the caster plus the caster's non-magical possessions. Other is another living animal or plant. Object is one object or group of related objects weighing up to 1000 lbs. and of volume up to 1 cubic yard. House is any house sized structure of up to 3000 square feet of internal space. Castle is any structure larger than a house. Space is an area of up to 3000 square feet. Magic Item is any magic item Related objects must be very similar, like a group of coins, or objects in a container, such as a pack full of gear. Veiled structures and spaces do not protect occupants inside. They are just veiled from these spells themselves. So if a house was made Invisible and then veiled against See Invisible, it could not be detected by a see invisible but its invisible occupants could be unless they were also veiled against See Invisible. Protection is defined as follows: Detect Magic through Trace Sending: the target is Veiled from these spells. Summon: A mage attempting to Summon the target must win a Level Contest first. Teleport: A mage attempting to Teleport to an attuned object must win a Level Contest first. Attune: the target is veiled against a mage attempting to attune to it. The mage attempting to Attune to such an object must first win a Level Contest against the Veil then overcome any defenses the target has as described in the Attune spell. Clerical Detects: the target is veiled against all generic detect type prayers. ";
  68. [Test]
  69. public void testMultiRef()
  70. {
  71. SpellDescription sd = new SpellDescription(multirefDescriptionText);
  72. Assert.IsNotNull(sd);
  73. IList<SpellDescription.Reference> ref_list = sd.FindReferences();
  74. Assert.IsNotNull(ref_list);
  75. Assert.AreEqual(6, ref_list.Count);
  76. SpellDescription.Reference spell_ref = ref_list[0];
  77. Assert.AreEqual("Locate", spell_ref.SpellName);
  78. Assert.AreEqual("Locate", multirefDescriptionText.Substring(spell_ref.Start, spell_ref.End - spell_ref.Start));
  79. spell_ref = ref_list[3];
  80. Assert.AreEqual("Telepathy", spell_ref.SpellName);
  81. Assert.AreEqual("Telepathy", multirefDescriptionText.Substring(spell_ref.Start, spell_ref.End - spell_ref.Start));
  82. }
  83. [Test]
  84. public void testSpellBookDescriptions()
  85. {
  86. foreach (ISpell spell in SpellBook.Book.List)
  87. {
  88. string description = spell.Description;
  89. SpellDescription sd = new SpellDescription(description);
  90. Assert.IsNotNull(sd);
  91. IList<SpellDescription.Reference> ref_list = sd.FindReferences();
  92. Assert.IsNotNull(ref_list);
  93. int ref_idx = description.IndexOf("(page");
  94. if (ref_idx >= 0) // do we have a reference?
  95. Assert.IsTrue(ref_list.Count > 0);
  96. else
  97. Assert.IsTrue(ref_list.Count == 0);
  98. // Check spells in spell list
  99. foreach (SpellDescription.Reference spell_ref in ref_list)
  100. {
  101. if (!SpellBook.Book.Contains(spell_ref.SpellName))
  102. {
  103. Console.WriteLine(String.Format("Don't have spell named '{0}' referenced from '{1}'.", spell_ref.SpellName, spell.Name));
  104. }
  105. }
  106. }
  107. }
  108. }
  109. }