Building a character's skill list with respective levels, using individual tiddlers

Hey all!

I’ve been building my tiddlywiki for a tabletop RPG, hoping to achieve a decently user friendly UX.

One element of this is figuring out the best mechanic, inside Tiddlywiki, to navigate tagged tiddlers that describe a skill, spell or trait, and “add/remove” them (for example with a button displaying "+"or “-” at the end of each row of a filtered table) to/from a character tiddler being created.

Since each of these skills, spells or traits can have individual levels specific to the character, this is slightly more tricky than just having a skills, spells or traits field in the character’s tiddler listing them one after the other.

I was wondering how the tiddlywiki tenors in here would approach this structurally?


So far, I haven't solved the question above, but I still had fun making some progress on listing them in a field. However, I'm stumped by a syntax and currentTiddler issue:

I’m using @Mohammad’s super cool Shiraz plugin, and its dynamic lists, because lists of spells, skills, and traits can be humongously long. Let’s take spells for example. What I did so far is add an addspell field on every tiddler tagged “Spell”, that contains a + button:

<$button><$action-listops $tiddler=<<currentTiddler>> $field="spellbook" $subfilter="+[toggle[<$link/>]]" />+</$button>

Then, I have a Character tiddler that features the dynamic-list of the spells like so (see demo/dynamic-tables/searchable for the plugin’s demo page):

<$macrocall $name=table-dynamic filter="[tag[Spell]search{$:/temp/demo/dtable/search}]" class="w-100" fields="tbl-expand title college class prerequisites notes addspell"  caption="" stateTiddler="20200213/0928"/>

… which renders my spells with the fields I want, and thus, in this use case, the button in the addspell field (filtered for one spell below):

When the button is clicked, it is supposed to add or remove the link to the spell tiddler in the spellbook field of the tiddler containing the list. But of course, when the button is used inside another tiddler listing the spells (let’s say its title is “Character”), it adds a link to the Character tiddler instead of a link to the spell - because, well, it is the <currentTiddle> (clicked once below):

And I wonder if the use of @Mohammad 's plugin makes the behaviour I’m seeking impossible with the architecture I described above?

Finally, it would be cool to have the button change to a “-” if the field already contains the Spell we’re trying to add…

3 Likes

Oh! I am definitely watching this thread! I use TW to run my current DnD campaign, and this is an intriguing idea. :slight_smile:

Just in case you didn’t know, there’s a nice DnD plugin already by Ben Webber (it’s doesn’t include the functionality I’m after, but since DnD is much simpler in terms of rules than GURPS, which I’m using…), which was further customized (visually especially) by “midasp”.

I can think of three general options here:

  1. On each skill/spell/trait tiddler, add a field corresponding to each character who has that skill, with field value equal to their current level in that skill.
  2. On each character tiddler, add a field corresponding to each skill the character has. Again, the field value is their current level in that skill. Optionally, give each field a prefix describing the category to which it belongs, e.g. skill-acrobatics vs. spell-fireball. This would a) guarantee that members of the same category appear in the same section of the field list, and b) make it easy to filter for a certain category of fields (and their contents).
  3. For each character, store the skills/levels as matched pairs separated by some divider character(s) that won’t otherwise appear in the skill names.

Personally, I’d tend to favor this third option. You could do this either within fields on the character’s tiddler (use an <$edit-text field="field-name" tag=textarea /> widget for a multi-line field editor), e.g.

title: Character's Name

skills: acrobatics = 1
athletics = 5

spells: fireball = 3
wall of wind = 6

and split the field value first by line (splitregexp[\n]), then at your divider character (=):

<$list filter="[{!!title}get[skills]splitregexp[\n]]" variable="line">
<$let
	skill={{{ [<line>split[ = ]first[]] }}}
	level={{{ [<line>split[ = ]butfirst[]] }}}
>
	<$link to=<<skill>> />: <<level>><br>
</$let>
</$list>

IMO, this would be the best option if you want to keep all the data pertaining to a particular character in the same tiddler.

On the other hand, if you don’t mind having some associated data tiddlers/subtiddlers, you could use dictionary tiddlers, which are a special type of tiddler specifically designed for storing paired values. This would let you make, for instance, Character Name/Skills, Character Name/Spells, and Character Name/Traits, all as stand-alone tiddlers with type: application/x-tiddler-dictionary and text fields containing paired values:

title: Character Name/Skills

acrobatics: 1
athletics: 5

title: Character Name/Spells

fireball: 3
wall of wind: 6

The nice thing about working with data tiddlers is that we have a couple of operators, indexes and getindex, specifically for retrieving values. In this case, your character template might look more like this:

<$tiddler tiddler=`$(currentTiddler)$/Skills`> <!-- see "Substituted Attribute Values" -->
<$list filter="[<currentTiddler>indexes[]]" variable="skill">
<$let level={{{ [<currentTiddler>getindex<skill>] }}}>
	<$link to=<<skill>> />: <<level>><br>
</$let>
</$list>
</$tiddler>

IIRC Mohammad’s dynamic tables are also designed to accommodate data tiddler indexes (that is, as an alternative to tiddler fields) so that might be another advantage of this approach… though if you want to display both the current character’s level in a skill and info about that skill taken from the skill’s tiddler, you’d need to make some custom column templates in any case.

Of course, with any of these approaches, you can also make buttons to expedite adding the appropriate fields/indexes to a character. :slight_smile:

IIRC, within a dynamic table row, Mohammad uses the variable <<currentRecord>> to refer to the “title” tiddler for that row. You might try using that in place of <<currentTiddler>> and see if that produces the desired behavior.

Oh, and if you got Shiraz from the public site, you’re probably using 2.9.7… but Mohammad’s working on a rewritten Shiraz 3.0 in which he’s done a lot of work simplifying and updating the dynamic table code in particular. I’ve done a fair bit of dynamic table tinkering myself and found the new version much easier to work with, so if you haven’t done too much work already, this might be a good time to switch!

The author of that edition, @intrinsical, is also around here on Talk, but he’s a lot more active on the TW Discord — and currently working on a modernized remake which will support the 2024 ruleset. IMO he did a beautiful job with the 2014 edition, and it’s worth examining for inspiration even if you’re building a wiki for a different game.

In a similar vein, I also like to direct people to Eberron TW (not D&D, but D&D-adjacent) for some more great examples of what you can do with TW as a TTRPG helper.

2 Likes

I’m well aware, I started fiddling with TW from it a few days ago :slight_smile: I also saw the Eberron one, which is impressive, but there’s a ton of stuff on it I can’t really see or dissect well enough to understand (one of them is his dice roller, the way he displays alerts, and finally the integration of Leaflet that I will dig into later once I’m done with my current predicaments ;P)

Thanks for the detailed answer! I’m using Shiraz 3.0.5. (but the doc isn’t updated yet, so still 2.9.7 on that front). The currentRecord macro may help, but I’m lost as to the how to call it in my current button syntax:

<$button><$action-listops $tiddler=<<currentTiddler>> $field="spellbook" $subfilter="+[toggle[<$macrocall name='currentRecord'>]]" />+</$button>

I think I might be too tired to figure it out myself -_-

Looking at your suggestions, the data tiddler option may be the most promising to me. I have to think about it and investigate :slight_smile:

Sorry, I didn’t make it contextually clear: <<currentRecord>> isn’t a macro, it’s a variable like <<currentTiddler>>. In this case, the list that generates the dynamic table rows assigns each result of the filter you supply to the variable currentRecord, so <<currentTiddler>> remains unchanged and continues to refer to the tiddler in which the dynamic table appears. I was suggesting you replace any instance of <<currentTiddler>> in your button code with <<currentRecord>> instead.

But I admit I hadn’t looked at your current code closely, and…

<$button>
<$action-listops $tiddler=<<currentTiddler>> $field="spellbook" $subfilter="+[toggle[<$link/>]]" />
+
</$button>

(line-breaks added for better legibility)

What this will do is add or remove the literal value <$link/> from the spellbook field of the tiddler where the dynamic table appears — not what you really want to happen, I assume! As a stand-alone widget, <$link/> will always give you a link to the <<currentTiddler>>… and equally importantly, it’s a wikitext widget, whereas $action-listops assumes that the field it’s modifying contains a title list.

If your goal is to add/remove the title of the current row from the spellbook field, try using "+[toggle<currentRecord>]" instead.

  • Notice that I’m not using any square brackets [] around <currentRecord>: this is because, within a filter, [] indicate a literal string. (For anyone looking for a cheatsheet or just a bit of review, Those Pesky Brackets has a good overview of how to use each type of bracket.)

As a title list, your spellbook field won’t inherently contain any link widgets (though if you transclude it with {{!!spellbook}}, you’ll notice that any multi-word titles will appear as links, as the [[double-bracket format]] does double duty as the title delimiter and the wikitext version of $link). To get a list of links to all the tiddlers included in spellbook, you could do something like this:

<$list filter="[enlist{!!spellbook}]" join="<br>"><$link/></$list>
  • enlist assumes its parameter is a title list and converts it to its component titles by removing any double square brackets. In this case, enlist{!!spellbook} will retrieve and enlist the <<currentTiddler>>'s spellbook field.
  • By default (that is, unless you specify a different variable), each result of a $list redefines <<currentTiddler>> to refer to the current result. This lets us use <$link/> to link to each spell listed in the field, rather than to the tiddler that hosts the list.

So "+toggle[toggle<currentRecord>]" works, and actually keeps the links of the original of the table that were added to the spellbook field. The spellbook field now looks like [[spell1]] [[spell2]] ... [[spelln]] :slight_smile: Progress! Now I have to find a way to change the “+” within <$button>+</$button> to a “-” if the field already contains the currentRecord…

I tried the enlist thing, and it seems to output the exact same thing, only displays the spells one per line because of the <br>, which may be very useful indeed.

Try this out:

<% if [<currentTiddler>contains:spellbook<currentRecord>] %>-<% else %>+<% endif %>

Or, if you prefer, you can do the same thing with a $text widget:

<$text text={{{ [<currentTiddler>contains:spellbook<currentRecord>then[-]] ~[[+]] }}} />

It totally works, you’re a Godsend. That whole thing went into an <<addremovespell>> macro and now I can template it out :stuck_out_tongue_winking_eye:

Onto exploring data tiddlers and look at how to use this mechanism with them to architecture a suitable solution. Yay!

1 Like

First thought: “hmmm, it doesn’t look like DnD…”
Second thought: “Holy cow, that’s for GURPS!”

Would definitely love to see the result!

1 Like

It is indeed :slight_smile: I shamelessly ripped off Midasp’s DnD one as the basis, and am redeveloping everything (but the aesthetics which I feel he nailed) for GURPS, creating specific graphical elements along the way when I’m unable to figure out how to code something in TW…

… and dumping notes for a setting I’m keen on developing.

1 Like

That’s actually sick! That’s what I always thought I needed and was even considering to something similar myself on TiddlyWiki, but never found enough time. Didn’t hope anyone else is going to do GURPS on TiddlyWiki :smiley:

1 Like

So if I’m wrapping my head around the datatiddler option correctly, this would be the architecture I need to do what I want with spells (and skills, that work basically the same), I think, right?

(the question marks show things I’m not sure how to do correctly yet ;P)

If you like the idea of using data tiddlers, I think your architecture would be somewhat simplified by eliminating the spellbook (etc.) field in favor of storing all a character’s known spells in their associated “Character Name/Spellbook” dictionary tiddler. If you already have this index (which contains both known spells and their current levels), there’s no particular value to having a field that only lists known spells; it’s one more thing you’d need to keep in sync, and it doesn’t provide any information you couldn’t access with [[Character Name/Spellbook]indexes[]].

I’ll try to go through your question marks in order and sketch out some possible approaches if you do go the data tiddler route. I’m not familiar with GURPS myself, so I’m not entirely sure how spellbooks are meant to function (does each character have a spellbook? More than one? How do editions factor into it?) So I’m using Character Name/Spellbook as a placeholder title for a character-specific dictionary tiddler, but please adapt as appropriate.

  1. Character view template - largely addressed above. Within a $list widget with the basic form…
<$let spellbook={{{ [<currentTiddler>] [[Spellbook]] +[join[/]] }}}>
<$list filter="[<spellbook>indexes[]]" variable="spell">
<$let level={{{ [<spellbook>getindex<spell>] ~0 }}}> <!-- displays "0" if the <<spell>> index does not exist or is blank -->  

<<spell>>: <<level>>
</$let>
</$list>
</$let>

Here, I first defined the spellbook variable assuming the form <<currentTiddler>>/Spellbook.

You can use whatever formatting you like inside the list; to make a table with one spell per line, add <table>...</table> around the entire $list and put your <tr><td>column content</td></tr> within the list widget. (Header/footer row(s) go outside the $list.)

You should also be able to use this base list filter (though not the <<spell>> variable) with a Shiraz dynamic table as part of a character tiddler view template; you’ll just need to make some custom /body/... cell templates to display the columns you want. Dynamic table columns do not need to correspond to fields on the tiddler where the table will be displayed; they’re just an ordered list of column “types”. So if you have a “spell” column, it will look for a tiddler with the tag $:/tags/Table/BodyTemplate which contains spell in its tbl-column-list field and use this tiddler as the cell template.

In this case, that template could look like

<td class="shiraz-dtable-title"><$link to=<<currentRecord>> /></td>

and a spell-level cell template could look like

<td class="shiraz-dtable-title"><$text text={{{ [[Character Name/Spellbook]getindex<currentRecord>] }}} /></td>

You can use additional columns to pull information from the tiddler corresponding to that spell, e.g. <$transclude tiddler=<<currentRecord>> field="college" /> to transclude the contents of that spell’s college field.

  1. Character edit template - I’m not sure I understand this one on a conceptual level, but generally speaking, to make a dropdown containing all tiddlers with the Spellbook tag, you could use a $select widget something like this:
<$select tiddler="..." field="...">
<$list filter="[tag[Spellbook]]">
<option>{{!!title}}</option>
</$list>
</$select>

You’ll notice that I left the tiddler and field attributes blank; what goes there will depend on how you want to use this.

  • If each character has one spellbook (or only one active at a time), you could use tiddler=<<currentTiddler>> (assuming <<currentTiddler>> = character tiddler) and field="spellbook" or "current-spellbook".
  • If a character can have multiple spellbooks, you’ll want the $select widget to invoke an $action-listops widget that modifies a field. In this case, you’ll need to save the selection to a temporary field (or the text field of a temporary tiddler, if you prefer), use it in the $action-listops subfilter, and then delete the temporary field if desired.
\procedure add-spellbook()
<$action-listops $field="spellbooks" $subfilter="+[toggle{!!temp-spellbook}]" />
<$action-deletefield temp-spellbook />
\end

<$select field="temp-spellbook" actions=<<add-spellbook>>>
<$list filter="[tag[Spellbook]]">
<option>{{!!title}}</option>
</$list>
</$select>
  1. Spellbook view template - this may be part of point #1? No need to deal with a “spellbook” field containing a list of spells; the data tiddler itself is our sole source of truth. (This is a good TW practice, generally speaking: don’t duplicate information that’s already available elsewhere in your wiki, when you can retrieve it with a filter instead!)

  2. Spellbook edit template - this could look a lot like your view template, but with an $edit-text widget in place of the index value.

<$let spellbook={{{ [<currentTiddler>] [[Spellbook]] +[join[/]] }}}>
<$list filter="[<spellbook>indexes[]]" variable="spell">

<<spell>>: <$edit-text tiddler=<<spellbook>> index=<<spell>> type=number default="0" size=2 />
</$list>
</$let>

And a general note on adding spells (since the $action-listops solution we worked out earlier assumes a single field, not a data tiddler):

  • To make a comparable button that adds/removes <<currentRecord>> from the <<spellbook>> data tiddler:
<% if [<spellbook>has:index<currentRecord>] %>
<!-- DELETE THIS SPELL FROM THE DATA TIDDLER -->
<$action-setfield $tiddler=<<spellbook>> $index=<<currentRecord>> />
<% else %>
<!-- ADD THIS SPELL TO THE DATA TIDDLER -->
<$action-setfield $tiddler=<<spellbook>> $index=<<currentRecord>> $value="0" />
<% endif %>

Despite the name, the $action-setfield widget is the simplest way to modify an index.

  • Assuming <<spellbook>> has already been defined to refer to the appropriate data tiddler…
    • If the data tiddler has an index corresponding to <<currentRecord>>, delete it.
      • For whatever reason, $action-deletefield does not work with indexes! Instead, to delete an index, we need to use the slightly unintuitive workaround of using $action-setfield without a $value.
    • If not, add an index for <<currentRecord>> with a starting value (level) of 0.

I could also imagine adding a spell to a character’s spellbook from, say, that spell’s tiddler; in this case, you’d probably want to use

  1. a $select (storing its value to the text field of $:/temp-prefixed tiddler) to choose the character
  2. a $let widget defining the data tiddler to be modified based on the character selection, e.g. <$let spellbook={{{ [[$:/temp/character]get[text]] [[Spellbook]] +[join[/]] }}}>, wrapping
  3. a button that adds/removes a <<currentTiddler>> index (rather than <<currentRecord>>) from the chosen data tiddler.

Sorry, this got quite long! Let me know if you’d me to expand on anything.

Damn your help is is highly appreciated, you’re a godsend :slight_smile:

So here’s a bit more context.

  • “spellbook” is more of a term I use to describe a set of known spells, and a category of tiddlers (so basically, all spellbooks will be tagged with “GURPS Spellbook”).
  • Any character can have a spellbook, if they are a magic user.
  • Non-magic users won’t have a spellbook.
  • A character tiddler will be composed with different subtiddlers for different aspects a character can have:
    • base stats (strength, Intellect, etc.),
    • background (story elements),
    • basics (name, eye color, etc.),
    • skillbook (all the skills a character has and their level),
    • spellbook (all the spells a character knows and their level)
    • advantages (those are traits like ambidextrous, fast learner, etc., can have levels as well),
    • disadantages (the opposite, like poor social status, inability to smell, etc., can have levels as well).
  • The particular game system used (GURPS) features very extensive lists of possible skills, spells, advantages and disadvantages you can get to build a character (up to hundreds of them, that’s why I’ll use searchable lists as much as possible to articulate the UX of selecting the individual elements one wants to attach to a character definition). When you build a character, you have a set number of points. Positive stuff (knowing a skill or spell, picking up and advantage, above average base stat) costs points, negative stuff (below average base stat, disadvantages) gives you extra points
  • I thought about allowing characters to have more than one spellbook, in order to have an easier character building experience where I could have predefined spellbooks shared across different characters archetypes. It would be very cool, and probably save some time, but it’s OK if spellbooks are unique to a character.

Now to your very detailed and helpful answer:

  • I am going to use data tiddlers, this seems like the best approach.
  • Ditching the intermediary of the spellbook field as previously defined is fine by me, you raise good points.
  • Ideally, one could edit every aspect of a character directly from the character tiddler. If that’s troublesome for complex definitions like skills and spells (as opposed to base stats that ultimately will just be a field in a character tiddler), it should be ok to have to open the spellbook / skillbook to edit it.
  • I plan on representing the aspects of a character through tabs of skills, spells, advantages and disadvantages calling the correct lists for that character
  • Since most characters will be unique, I want to refrain from using character name tags to filter stuff relevant only to one character (having tags that are used only a few times seems like bad TW design), so I like the idea of using the titles and a nomenclature like you are suggesting (character name/spellbook, character name/skill book, character name/advantages, etc.). In the following material I use to test all this, I just created a character named “character” and tagged with “char”.

The (2) character edit template (and editing mechanisms in general) are important to me because I don’t want users to have to understand the underlying principles of TW or those of the TW I’m building to navigate and use it - for example, to have to edit by hand a spellbook datatiddler presupposes that you understand their format of key/value pairs written in plaintext. But everybody understand an input field with a number, or “add/remove” buttons in a searchable list of spells/skills displayed while editing the relevant section of a character.

I changed the add/remove macro and buttons to accomodate the spellbook data tiddler rather than field structure:

Each spell currently has an addremovetospellbook field that simply has the following <<addremovespelltospellbook>> macro:

\define addremovespelltospellbook()
<$button><% if [<currentTiddler>has:index<currentRecord>] %>
<!-- DELETE THIS SPELL FROM THE DATA TIDDLER -->
<$action-setfield $tiddler=<<currentTiddler>> $index=<<currentRecord>> />
<% else %>
<!-- ADD THIS SPELL TO THE DATA TIDDLER -->
<$action-setfield $tiddler=<<currentTiddler>> $index=<<currentRecord>> $value="0" />
<% endif %><% if [<currentTiddler>has:index<currentRecord>] %>–<% else %>+<% endif %></$button>
\end

When a spellbook is being edited, I’m adding the searchable list of spells with that button column active, displayed after the $:/core/ui/EditTemplate/body, as defined in the GURPSSpellbookEditViewTemplate (tagged with $:/tags/EditTemplate) below:

<$list filter="[all[current]tag[GURPS spellbook]]">
<$let spellbook={{{ [<currentTiddler>] [[Spellbook]] +[join[/]] }}}>
<$list filter="[<spellbook>indexes[]]" variable="spell">

<<spell>>: <$edit-text tiddler=<<spellbook>> index=<<spell>> type=number default="0" size=2 />
</$list>
</$let>
All spells: filter and search <$edit-text tiddler="$:/temp/demo/dtable/search" filed=text tag=input default=""/> <$button set="$:/temp/demo/dtable/search" setTo="" tooltip="clear searchbox">x</$button>

<$macrocall $name=table-dynamic filter="[tag[GURPS Spell]search{$:/temp/demo/dtable/search}]" class="w-100" fields="tbl-expand title college class prerequisites notes addremovespelltospellbook"  caption="" stateTiddler="20200213/0928"/>
</$list>

The button system works, however, I haven’t yet gotten your code correctly figured out and added so that each key/value pair is displayed for edition as a link to the spell, and an editable field of its level for that specific spellbook. (I just pasted it inside the first <$list filter> as you can see)

1 Like

This discussion is very helpful. And it’s probably 30 years ago that I last played GURPS.

I will probably use Data tiddlers now too.

Do you plan to include alternate forms of magic too, for example Rune Magic, as you can improvise spells there?

I don’t know yet. I can tell you I will focus first on what I indend to use of course, but I still want that work to be available to others who run GURPS settings in some way shape of form, as it’s a notoriously poorly digitally represented system. I have a fair bit to go before the basics are presentable in a usable way, I’ve started using TW only a couple of weeks ago, and progressing slowly in my understanding of it :stuck_out_tongue_winking_eye:

I integrated your code a bit further.

GURPSSpellbookEditTemplate (i.e. template tiddler for editing spellbooks):

<$list filter="[all[current]tag[GURPS Spellbook]]">

<$let spellbook={{{ [<currentTiddler>] [[spellbook]] +[join[/]] }}}>
<$list filter="[<spellbook>indexes[]]" variable="spell">

<<spell>>: <$edit-text tiddler=<<spellbook>> index=<<spell>> type=number default="0" size=2 />
</$list>
</$let>

All spells: filter and search <$edit-text tiddler="$:/temp/demo/dtable/search" filed=text tag=input default=""/> <$button set="$:/temp/demo/dtable/search" setTo="" tooltip="clear searchbox">x</$button>

<$macrocall $name=table-dynamic filter="[tag[GURPS Spell]search{$:/temp/demo/dtable/search}]" class="w-100" fields="tbl-expand title college class prerequisites notes addremovespelltospellbook"  caption="" stateTiddler="20200213/0928"/>
</$list>

… which doesn’t seem to provide the *Link to spell*: *input field to adjust level*:

But works with adding and removing spells through the list displayed with buttons!

GURPSCharEditTemplate (i.e. template tiddler for editing characters):

<$list filter="[all[current]tag[Char]]">

|!''Spellbook'' |<<selectspellbook>> |Button to create new spellbook |

</$list>

Where the <<selectspellbook>> global macro is defined like you coded:

\define selectspellbook()
<$select tiddler="<<currentTiddler>>" field="spellbook">
    <$list filter="[tag[GURPS Spellbook]]">
      <option>{{!!title}}</option>
    </$list>
  </$select>
\end

Which does show the dropdown for spellbook selection, but doesn’t populate a spellbook field with the title of the desired spellbook, nor changes what spellbook is displayed for the character (I’m confused actually whether or not in your thinking, the spellbook attached to a character is indeed saved in a field, or if it is simply matched from the use of the CharacterName/spellbook nomenclature as a tiddler title for a given spellbook):

GURPSCharViewTemplate (i.e. template tiddler for viewing characters):

<$list filter="[all[current]tag[Char]]">
<$let spellbook={{{ [<currentTiddler>] [[spellbook]] +[join[/]] }}}>
''Spellbook'': <$link to=<<spellbook>>/>

<table><tr>
    <th>Spell</th>
    <th>Level</th>
  </tr><$list filter="[<spellbook>indexes[]]" variable="spell">
<$let level={{{ [<spellbook>getindex<spell>] ~0 }}}> <!-- displays "0" if the <<spell>> index does not exist or is blank -->  
<tr><td><$link to=<<spell>>/></td><td> <<level>></td></tr>

</$let>
</$list></table>
</$let>
</$list>

Which currently displays the Character/spellbook in the Character tiddler as such:

I’m a bit confused as to what my next steps should be to get the levels edition and the spellbook selection/association working.