The Lattice-Glass of Magister Orsolde
The Collegium of Wrenfall posts a commission for a binding-spirit to keep Magister Orsolde's lattice-glass, the crystal in which she carries her prepared battle-spells into the field. The glass holds only so many spells. When it is full and a new spell is pressed in, one of the old ones is lost. Spells the Magister has sealed are never lost this way. The Collegium wants the keeping written down exactly, so that no spell is ever lost by mistake.
Write the class SpellLattice.
Constructor: takes capacity, an integer >= 0. This is the largest number of spells the glass may hold at once. The glass starts empty.
Each held spell has: - a name, a non-empty case-sensitive string, - a number of charges, a positive integer, - a sealed flag, - a place in the order of recent use.
A use of a spell is one of two things: a successful inscribe of that spell, or a cast of it that leaves it still held. Nothing else counts as a use.
Methods:
- inscribe(name, charges) takes an integer charges >= 1 and returns a string or null (None in Python). The first rule that applies decides the result: 1. If name is already held, set its charges to charges. This counts as a use, and its sealed flag is unchanged. Return null. 2. Otherwise, if fewer than capacity spells are held, add the spell, unsealed, as a use. Return null. 3. Otherwise, if at least one held spell is unsealed, remove one unsealed spell. Choose the one with the fewest charges. If several are tied, choose the one whose most recent use is earliest. Then add the new spell, unsealed, as a use. Return the removed spell's name. 4. Otherwise every held spell is sealed. This includes the case capacity = 0. The glass is unchanged and the new spell is not held. Return name.
cast(name)returns an integer.- If
nameis not held, return-1and change nothing. - Otherwise reduce its charges by 1.
- If its charges reach 0, remove the spell entirely, whether it is sealed or not, and return
0. - If its charges do not reach 0, the cast counts as a use. Return the remaining charges.
seal(name)marks the spell as sealed and returnstrue. If the spell is not held, it returnsfalse. This is not a use.
unseal(name)marks the spell as unsealed and returnstrue. If the spell is not held, it returnsfalse. This is not a use.
charges(name)returns the spell's current charges, or-1if it is not held. This is not a use.
A spell that has been removed and is later inscribed again comes back as a new, unsealed spell.
examples
- case 1
capacity 2; inscribe Fireball with 3 charges, inscribe Frost with 1, inscribe Blink with 2The third inscribe returns "Frost", the spell with the fewest charges. Fireball and Blink remain. - case 2
capacity 2; inscribe Blink with 1, inscribe Veil with 1, check the charges of Blink (1), then inscribe Shock with 3The last inscribe returns "Blink". Blink and Veil are tied on charges, and checking charges is not a use, so Blink's last use is still the earliest. - case 3
capacity 1; inscribe Oath with 2, seal Oath, inscribe Bane with 9The last inscribe returns "Bane". The only held spell is sealed, so Bane is never held and Oath keeps its 2 charges. - case 4
capacity 0; inscribe Spark with 3, then cast SparkThe inscribe returns "Spark" because the glass cannot hold it. The cast returns -1.
- reward
- 540 XP
- signature
SpellLattice
TypeScript, run as ES2022 — types are stripped, not checked. If a JS engine would run it, so will we.
- evicts the spell with fewest charges
- ties broken by least recent use, re-inscribe refreshes
- checking charges does not refresh
- sealed spells are spared
- all sealed refuses the new spell until unsealed
- capacity zero holds nothing
- exhausted spell frees its slot and loses its seal
- casting refreshes and re-inscribing replaces charges
- re-inscribing keeps the seal