Declaring a new table to be populated

I have seen lots of topics about defining constants with tables, but I have seen nothing about defining a thing with a table. I want to create an empty table that I can populate at runtime. The table is contained in a thing, a spell book.

A spell book is a kind of readable thing. 
A spell book has a Table of Known Spells.

Table of Known Spells
Name	Cost	Notes
"spell name"	"1"	"desc"
with 40 blank rows

I’ve found nothing in the docs. I get the error on defining a spell book. I’ve tried has a table..., is defined by Table, contains a Table, etc.

How do I declare a thing with a table in it? Later, I will copy data from a ref table into this table, but I have to have the table exist first.

btw, Do I really need the first line to contain placeholders, like I’ve done here?

Unfortunately, you can’t create tables automatically (without resorting to some I6 hacking). But you can define an empty table like this:

A spell book has a table name called the known spells.
The known spells of the grimoire is the Table of Grimoire Spells.

Table of Grimoire Spells
name (text)    cost (number)    notes (text)
with 10 blank rows.
1 Like

That should work. Let me consider this.
A spell book contains a LINK to a the table with the link-name of known spells.
Now, I want to call the table Table of Known Spells, so that would change your code to

A spell book has a table name called the known spells.
The known spells of the [grimoire??} is the Table of Known Spells.

Table of Known Spells
name (text)    cost (number)    notes (text)
with 10 blank rows.

Does the text in parentheses tell the parser what type (kind) to expect: text, number, and text?
Is grimoire take a kind (spell book) and make it a specific object? (which I don’t want).

I haven’t tried it yet, but would this work?

A spell book has a table name called the known spells, called Table of Known Spells.

If the intention is that all spell books by default share the same table, it would look like this.

A spell book has a table name called the known spells.
The known spells of a spell book is usually the Table of Known Spells.

But if they always have the same table, there’s really no point in making this link at all. Just define the table and reference it directly when needed.

1 Like

No, I have a two ref tables from which a unique spell book would draw. The player has this unique spell book–and spells are transferred to it from the ref tables–but other spell books are available to buy or find.

Let me explain. I want a spell book to contain a table of spells and their attributes.
I don’t know how to create a table within a book. This post has received some suggestions but I don’t know if I got it right. I want to put a table row into the spell book from a ref table (called LEARN). Later, I want to read the spells listed in the spell book (called READ). Here is what I have so far.

A spell book is a kind of readable thing. 
A spell book has a table name called known spells.
The known spells of the spell book is the Table of Learned Spells.
Description of spell book is "A thick tome for recording all the spells you know. Its title letters almost glow. Currently, it contains only [number of rows in Table of Learned Spells], but has many pages for new spells to be learned. Of course, you will need magic ink to add more spells to your spell book.".

Table of Learned Spells
Name (text)	Cost (number)	Notes (text)
with 40 blank rows

to learn (spell - text) in (book - spell book):
	add name entry to known spells;
	add cost entry to known spells;
	add notes entry to known spells;

Carry out reading: 
	if noun is spell book:
		say "[name entry of noun][line break]";
		say "[cost entry of noun][line break]";
		say "[notes entry of noun][line break]";
	otherwise:
		say "[inscription-text of noun]";	
	now noun is read;

What am I doing wrong?

It sounds like you want to copy a row from one table to another, so maybe something like this?

to learn (spell - text) in (book - spell book):
	choose the row with a spell of the spell in the Table of Existing Spells;
	let cost be the cost entry;
	let notes be the notes entry; [or omit this if it's meant to be something the player fills in for themself?]
	choose a blank row in the Table of Learned Spells;
	now the name entry is spell;
	now the cost entry is cost;
	now the notes entry is notes; [or omit this if it's meant to be something the player fills in for themself?]

I’m not sure what you’re trying to do with reading.

1 Like

If your goal is to make a new table for each spellbook, I’m afraid you’ll have to do it manually. The only way to create a table in I7 (without I6 trickery) is by giving it an explicit name and schema. Which means you can’t ever create multiple tables at once.

1 Like

Tables are often not the best solution, and using a text as they main lookup key is almost never the right idea.

Instead this seems like something where relations would be an easy solution.

Have a kind for spells, and a kind of spellbooks. One relation to relate spells and spellbooks, and one relation for people and the spells they know.

Here’s a very rough start:

You can then give spells any additional properties you want (such as various kinds of costs and requirements), and use them in any actions you like. You could make a new action for each spell or use a generic casting action if you like. This also lets any NPC have their own spell repertoire.

2 Likes

Before I continue…

Dannii is correct and relations would probably help you quite a bit here.

In fact, tying the traits you want to a spell would be rather easy. Like so!

(Ignore my bizarre choice of testing methods with the wait command, ehe.)

…That being said, in the service of the questions about tables you asked I still thought I’d take the time to help you out with your table questions!

Table Stuff

So as Celtic suggested up there, using tables like that typically involves telling Inform to “choose” a row, which then tells it what you mean by “[thing] entry“. Even tying a table name to a thing I’m pretty sure that you still have to do this… otherwise, how would it know which row in the list of rows you’re asking for?

A couple of things here:

  1. I’m assuming you want to read through the list of spells in a spell book, one after the other. This example otherwise cleaves close to what you gave us, like using text for the lookup (I second Dannii in not recommending this) and the formatting on the say statement.
  2. You’ll notice that the first example had some formatting on the output and this doesn’t. I’m not sure what your desired behaviour is, but placing your entries within a single “say” statement like I did in the first example might help you out!
  3. If you aren’t careful you could output absolutely nothing. I’m sure you won’t include any completely empty spell books, but if you would for whatever reason then I recommend putting a condition which reacts to it like I have up there (outputting the “sadly bereft of spells” line). Also a check rule, but again I don’t know what your code looks like outside of the example!
  4. Side note, but don’t use “number of rows” in your description. That INCLUDES blank rows. Since it’s talking about known spells you want to use “number of filled rows“.

Regarding the inscribing, that’s another reason why going with Dannii’s option might be helpful for you. Messing with tables often involves a lot of choosing rows and seeing if rows are empty and etc. etc. without much wiggle room provided to you by Inform.

That.

Being.

Said.

My Awful Just-Woke-Up Choices

A thing can be readable.
A thing has some text called inscription-text.
A spell book is a kind of readable thing. 
A spell book has a table name called known spells.
The known spells of a spell book is usually the Table of Learned Spells.
Description of spell book is "A thick tome for recording all the spells you know. Its title letters almost glow. Currently, it contains only [number of filled rows in Table of Learned Spells], but has many pages for new spells to be learned. Of course, you will need magic ink to add more spells to your spell book.".

A spell is a kind of value. The spells are the First Testing Spell and the Second Testing Spell.

Table of Learned Spells
Name (a spell)	Cost (number)	Notes (text)
First testing spell	1	"This is just for testing!"
with 39 blank rows

Table of Also Learned Spells
Name (a spell)	Cost (number)	Notes (text)
Second testing spell	20	"This is also just for testing!"
with 39 blank rows

[==========]
	
Reading is an action applying to one thing. Understand "read [a spell book]" as reading.
[^By default "read [something]" feeds into the examine action, so my personal recommendation would be to remove that from it. For the purposes of not getting into that now, I have specified that this takes a spell book so that the command parses to this action instead.]

Check reading:
	if the noun is not readable:
		say "[We] [cannot] read that.";
		stop the action;
[^A spell book will always be readable but once again, usually this would accept more than spellbooks.]

Carry out reading:
	if the noun is a spell book:
		if the number of filled rows in the known spells of the noun is greater than 0:
			repeat through the known spells of the noun:
				say "[bold type][Name entry] ([cost entry]):[roman type] [notes entry][line break]";
		otherwise:
			say "[The noun] [are] sadly bereft of spells.";
	otherwise:
		say "[inscription-text of noun]";

[==========]

Inscribing it in is an action applying to two things. Understand "inscribe [something] in/into [something]" as inscribing it in.

Check inscribing it in:
	if the second noun is not a spell book:
		say "[The second noun] [aren't] very receptive to spells.";
		stop the action;

Check inscribing it in:
	if the noun is not a spell book:
		say "[The noun] [aren't] much help.";
		stop the action;

Check inscribing it in:
	if the number of filled rows in the known spells of the noun is 0:
		say "[The noun] [aren't] much help, empty as [they] [are].";
		stop the action;
		
Check inscribing it in:
	if the number of blank rows in the known spells of the second noun is 0:
		say "[The second noun] [may] hold no more spells.";
		stop the action;
[^You should definitely name all of these check rules, and in fact all of the rules you create. But I'm a touch exhausted right now and this works in the meantime.]
[These checks basically see if either of these aren't a valid source of spells, then if the noun has spells to give or the second noun can even take any. Basic stuff.]
	
		
Carry out inscribing it in:
	let inscribing-count be a number;
	repeat through the known spells of the noun:
		if there is a name of name entry in the known spells of the second noun:
			do nothing; [Sadly "if there is not a name" doesn't work. We don't want to write duplicate spells, though. Hence the check.]
		otherwise:
			let name-item be the name entry;
			let cost-item be the cost entry;
			let notes-item be the notes entry;
			choose a blank row in the known spells of the second noun; [We saved all of those values as temporary variables before because I'm pretty sure the moment we choose this new row to write to we wouldn't be able to directly reference the row-to-write in the table anymore!]
			now the name entry is the name-item;
			now the cost entry is the cost-item;
			now the notes entry is the notes-item;
			increment inscribing-count; [We use this to keep track of how many spells have been inscribed... as well as whether any have, at all!]
			if the number of blank rows in the known spells of the second noun is 0:
				say "[The second noun] [have] no more space after adding [name-item].";
				break;
	if inscribing-count is 0:
		say "Hmm! [The noun] [have] nothing to offer [the second noun]."; [This could have been a check rule, certainly, but I didn't like the idea of running through the tables to compare them twice when I could try being more efficient.]
	otherwise:
		say "[The second noun] thrums with [inscribing-count] new [if inscribing-count is 1]spell[otherwise]spells[end if]!"; [Thrums should be a verb substitution situation but let's not get into defining those now.]

[==========]	

The Garden is a room. 

The test spell book is a spell book in the garden. 

The helpful transfer grimoire is a spell book in the garden. The known spells of the helpful transfer grimoire is the Table of Also Learned Spells.

Running this code, we can see the results are…

So what (I think) you want is definitely doable! And semi-reasonably! But once again: you’ll notice all of the extra work I had to do to keep everything nice and orderly and not potentially throwing errors. (Case in point: I accidentally swapped “noun” and “second noun” somewhere when writing this and it was… just absolute chaos.)

I hope all of this helps in some way! And feel free to ask any followup questions. Apologies if I made any weird choices/errors in this or if I failed to explain something adequately. I’m exhausted from my own endeavors.

Well, you guys/gals went to a lot of work for me! I appreciate that. Let me recap what I think I learned.
[1] Relations may be a better choice instead of creating a table inside a spell book. However, despite some study, I never did understand relations, and I may be moving into deep water there. I would like to understand them though. I’ll take another look at how to use them.
[2] Instead of using the spell name (text) as lookup for a spell, make spell an object for lookup. I’m not sure why that is better, but I like the idea that spell as object can contain its own properties, and CAST [spell] would work easier. I did plan on building a CASTing rule. The problem with a spell as object is that it must exist in the ref table and the player’s table at the same time, so spell must be a kind, and kinds cannot be put into tables.
[3] Draconis thought I was going to make a new table for each spell book. That is partially correct. I will have a single reference table to define the spells, and then as the player “learns” a spell, a spell will be copied into the player’s spell book. The player only has one spell book (and table) but there can be multiple EMPTY spell books for sale. The player can buy another empty spell book if he/she loses it, or it gets stolen.

Thanks to all. Lots of grist for the mill.

1 Like

(Clarifying to the best of my abilities in case it helps you in the future.)

The errors it would throw should be more helpful. I imagine that matching objects/things is more efficient than matching text, as well. The parser would also play more nicely with your spells when it comes time for players to CAST them.

An object can appear in multiple tables at once; it just can’t be in multiple places in the world at once.

Like how, in real life, I could be listed in a table of employees at the university, and a table of library card holders, and a table of people renting from my landlord; but at any given time I can only be in the office, or in the library, or at my apartment.

Well, no, not exactly. There are 5 different ways to reference a table entry (this is from my reference manual, which is currently down):

«column» name [column] entry
«column» name [column] in row «number» of «table name»
«column» name [column] listed in «table name»
«column» name [column] corresponding to «column name» of «value» in «table name»
«column» name [column] of «value» in «table name»

The first form requires you to use choose row first. The third I think only works in an if. However, I think the other three can be used just like a value, for example:

now the spell column of Fireball in the Table of Spells is Enhanced Fireball.
now the level column corresponding to a spell column of Fireball in the Table of Spells is 2.
now the notes column in row 3 of the Table of Spells is "Hello World".

I haven’t tested though.

You could either use Some spells are defined by the Table of All Spells., which would translate each column to a property on the spell, or you could use the following undocumented feature:

Table of All Spells
spell (a spell) col2 (a text)
with blank rows for each spell.

Might need an actual data row in there as well for that to compile, not sure.

2 Likes

Oh yeah, no, I was just talking about the first sort there: raw entries without those kind of qualifiers. The sort which showed up in the presented code.

This is very interesting, though! I’ll keep it in mind. Shame it’s undocumented.

Indeed! The standard library uses it for locale entries; I had no idea it could be done for any arbitrary kind.

1 Like

Great! That will probably solve that problem. Thanks!

Ok. Good. Important difference. Thanks.

Worth checking out, though.

If I created a spell with attributes, e.g., spell (spell object), with properties Cost and Notes, couldn’t I just use a spell list? The properties Cost and Notes would be contained therein.

1 Like