Topic: IFData
Format of the gamejson.txt file
The current name of my IFData file is gamejson.txt. It uses UTF-8 character encoding with a three-byte BOM at the beginning of the file.
The basic structure of the file is JSON, a.k.a. JavaScript Object Notation. I edit the thing with Notepad. Really.
(Historical note: When I first started collecting data about IF games, the data was only about games and there was just one record
line per game. Delimited with or-bars. And it was all in ASCII. The original purpose of the file was to help me create index pages that linked
to my walkthroughs.
It was already getting rather unwieldy when I finally discovered JSON and switched over as soon as possible.)
The main data object has the following key-value pairs:
{
"languages":[ array of language records ],
"urlabbrs":[ array of abbreviation-definition records ],
"lists":[ array of gamelist-definition records ],
"tags-info":{ the tags-info object },
"authsystems":{ hash of authoring-system-definition records },
"extensions":{ hash of extension-definition records },
"events":{ hash of event-definition records },
"people":{ hash of person-definition records },
"games":{ hash of game-definition records }
}
languages
The "languages" field takes an array value, an array of language records. It's used for listing which human languages are used by the games.
Language records are very simple. They have two-fields each, both required:
{"lang": language-code, "en": English-name }
For example:
{"lang":"nl", "en":"Dutch"}
- The "lang" field takes a string value; it is required. It must be a 2-letter code representing a human language. In lower-case, please.
- The "en" field takes a string value; it is required. It should contain the common English name of the language that corresponds to the "lang" code.
urlabbrs
The "urlabbrs" field takes an array value, an array of abbreviation-definition records. It's used for defining abbreviations that I use at the
beginning of some URLs. This bit of nonsense lets me shorten some URLs and lets me associate some other information with the URLs.
This may be more trouble than it's worth, but I do it anyway.
Abbreviation-definition records are short, from two to four fields each:
{"as": abbreviation, "url": partial-url, "at": site-name, "by": site-owner}
For example:
{"as":"[dsw]", "url":"www.plover.net/~davidw/", "by":"David Welbourn"}
- The "as" field is required; it takes a string value. It is a code of my own invention, to be used at the beginning of URLs in this file.
These codes all use square-brackets to make them obvious and easy to substitute.
- The "url" field is required; it takes a string value. Its value should be a partial URL; what the "as" field is a substitution for.
- The "at" field is optional; it takes a string value. It names the website that the URL refers to.
- The "by" field is optional; it takes a string value. It names the website owner that URL refers to.
lists
The "lists" field takes an array value, an array of gamelist-definition records. This was invented to help me generate various game lists
for IFWiki; see Category:Game lists.
Gamelist-definition records look like this:
{"h1": shortname, "ifwiki": IFWiki-article-name,
"head": header-text, "foot": footer-text,
"h2s": { hash of subsection records }
}
- The "h1" field is required; it takes a string value. It is a shortname for the gamelist that I can use in individual game records.
- The "ifwiki" field is optional; it takes a string value. It is the name of the corresponding article on IFWiki, if that list exists there
(or I want it to exist there).
- The "head" field is optional; it takes a string value. It is the text I want to display at the beginning of this gamelist.
- The "foot" field is optional; it takes a string value. It is the text I want to display at the end of this gamelist.
- The "h2s" field is optional; it takes a hash of subsection records. Generally, it's not necessary to name the subsections of a list
explicitly here, since the individual game records will declare for themselves which subsection (if any) they want the game listed in.
But sometimes I want to meddle with the mechanics of subsection production, and for those subsections, I need this extra info.
lists / h2s
The "h2s" field takes a hash value, a hash of subsection records. They look like this:
"key": {
"name": replacement-name, "sort": sort-string,
"head": header-text, "foot": footer-text
}
- The key to a subsection record is its name; for example, "Alabama" is a subsection in the US State list, and "Valentine's Day"
is a subsection in the Holiday list.
Use "Other" to refer to games in the list that aren't explicitly given a subsection.
- The "name" field is optional; it takes a string value. Sometimes I want to replace the subsection name with something else,
so I declare that here.
- The "sort" field is optional; it takes a string value. Normally the subsections are sorted alphabetically by their names.
This field lets me use a different value to sort by. For example, I want to sort "PR Congo" as "Congo" in the Country list.
- The "head" field is optional; it takes a string value. It is the text I want to display at the beginning of this subsection.
- The "foot" field is optional; it takes a string value. It is the text I want to display at the end of this subsection.
tags-info
The "tags-info" field takes a hash value of tag-list records. I use a lot of tags elsewhere in the datafile, so
I look at this field when I need to remember what tags I defined and what they all mean. None of my programs makes any direct
use of this.
There's only three subfields: events/tags, extensions/tags, and games/tags. They're all very similar;
events/tags is about tags in event-definition records, extensions/tags is about tags in extension-definition records,
and games/tags is about tags in game-definition records.
"tags-info":{
"events/tags":[ array of tag-definition records ],
"extensions/tags":[ array of tag-definition records ],
"games/tags":[ array of tag-definition records ]
}
A tag-definition record is a simple two-field thing; both fields are required string values:
{"tag": tag-name, "meaning": tag-description}
For example, the "cover" tag for a game is defined thusly:
{"tag":"cover", "meaning":"The game has cover art."}
authsystems
The "authsystems" field takes a hash value of authoring-system-definition records. I've collected very little information for this
section, but sometimes I come across a snippet of info about an authoring system that I want to remember later, so here's where it goes.
An authoring-system definition record looks like this:
"key":{
"by": author,
"ifwiki": IFWiki-article-name,
"links":[ array of link-records ],
"notes":[ array of note-records ]
}
- The key to an authoring-system record is the authoring system's name, eg: "ADRIFT" or "Inform 7".
- The "by" field is optional; it takes a string value: the authoring system's author's name.
- The "ifwiki" field is optional; it takes a string value: the corresponding article name about this system on IFWiki (if different from the key).
- The "links" field is optional; it takes an array value of link-records.
- The "notes" field is optional; it takes an array value of note-records.
extensions
The "extensions" field takes a hash value of extension-definiton records. Again, I've collected very little information for this
section as yet. An extension-definition record looks like this:
"key":{
"by": author,
"tags":[ array of tags ],
"links":[ array of link-records ]
}
- The key to an extension-definition record is the extension's name, eg: "Conversation Framework".
- The "by" field is optional; it takes a string value: the extension author's name, "eg":"Eric Eve".
- The "tags" field is optional; it takes an array of strings, where each string is a tag-name. Valid tag-names should be
defined in the "extensions/tags" subfield of the main "tags-info" field.
- The "links" field is optional; it takes an array of link-records.
events
The "events" field takes a hash value of event-definition records.
They describe IF competitions, mostly, but can include other events related to interactive fiction.
An event-definition record looks like this:
"key":{
"ifwiki": IFWiki-article-name,
"sort": sort-value,
"organizers":[ array of person-ref records ],
"dates":[ array of schedule-event records ],
"links":[ array of link-records ],
"reviews":[ array of link-records ],
"notes":[ array of note-records ],
"year": calendar-year,
"of": number-of-entries,
"h1": event-category,
"h2": event-subcategory,
"tags":[ array of tag-names ]
}
- The key to an event-definition record is the event's name, eg: "XYZZY Awards 2001". It's important that
I refer to the event by the same name everywhere in the file.
- The "ifwiki" field is optional; it takes a string value: the corresponding article name at IFWiki when it's different from my event key.
- The "sort" field is optional; it takes a string value: how I want this event sorted as if the event key's value isn't appropriate.
- The "organizers" field is optional; it takes an array of person-ref records.
It is assumed that the default role for a person is "organizer" within this array.
- The "dates" field is optional; it takes an array of schedule-event records.
This mostly declares what happened when during the event.
- The "links" field is optional; it takes an array of link records.
This can include links to the event's website, links to files to download, and links to other webpages about this event.
- The "reviews" field is optional; it takes an array of link records.
All links within this field ought to refer to reviews about games entered in this event.
- The "notes" field is optional; it takes an array of note records.
(The note type "premise" should probably be replaced with "about".)
- The "year" field is required; it takes a string value. It should be the calendar year of the event if known, or "0000" if unknown.
- The "of" field is optional; it takes an integer value: the number of games that entered into this event, assuming it's a competition.
(The name "of" derived from constructions like "3rd place of 34 entries".)
- The "h1" field is required; it takes a string value. It names the event's main category.
This is an artifical division of events that I find meaningful; I use this value when creating Key & Compass index pages.
The value of "h1" must be one of: "ADRIFT Comps", "AIF Comps", "IF Comp", "Speed-IF", "XYZZY Awards", or "Other Comps/Events".
(This really ought to be an optional field, assuming "Other Comps/Events" when unspecified.)
- The "h2" field is required; it takes a string value. It names the event's subcategory.
For example, IF Comp, the XYZZY Awards, and Speed-IF comps are subcategorized by year; AIF Comps are subcategorized into AIF Mini-comp and Erins;
Other Comps/Events are subcategorizd into groups like "IntroComp" and "French comps"; and ADRIFT Comps have complicated subcategories.
- The "tags" field is optional; it takes an array of string values where each string is a tag-name. Valid tag-names
should be defined in the events/tags subfield of the tags-info main field.
people
The "people" field takes a hash of person-definition records. Basically, if I want to remember something about IF people other than
what events they organized or what games they wrote, it goes here. The info in this section is still rather sparse.
The person-definition record looks like this:
"key":{
"birth": birthdate,
"nicks":[ array of nicknames ],
"links":[ array of link-records ],
"notes":[ array of note-records ]
}
- The key to a person's record is their name. Since this must be a unique name, I try to go with the person's name as it's used on IFWiki.
- The "birth" field is optional; it takes a string value: the person's birthdate. It should be in either "YYYY" or "YYYY-MM-DD" format.
(In time, I'll probably replace this field with a "dates" field similar to what "events" uses.)
- The "nicks" field is optional; it takes an array of string values where each string is one of the person's nicknames.
(Unfortunately, this doesn't give me any context for this nicknames; I'll want to rethink this.)
- The "links" field is optional; it takes an array of link-records.
Primarily, I want the person's website linked from here.
- The "notes" field is optional; it takes an array of note-records.
games
The "games" field takes a hash of game-definition records. This is the bulk of the IFData file, by far, and also the most complicated.
The "titles" and "year" fields are required; all other fields are optional.
The game-definition looks like this:
"key":{
"titles":[ array of titles ],
"ifwiki": IFWiki-article-name,
"authors":[ array of person-ref records ],
"adaptors":[ array of person-ref records ],
"contribs":[ array of person-ref records ],
"publishers":[ array of person-ref records ],
"testers":[ array of person-ref records ],
"genres":[ array of genre-names ],
"license": licence-name,
"color": color-comment,
"graphics": graphics-comment,
"sound": sound-comment,
"cruelty": cruelty-name,
"versions":[ array of version-records ],
"notes":[ array of note-records ],
"seealso":[ array of link-records ],
"reviews":[ array of link-records ],
"spoilers":[ array of link-records ],
"lists":[ array of list-ref records ],
"sline":{ status-line record },
"exts":[ array of extension-ref records ],
"tags":[ list of tag-names ],
"ifro": ifro-code,
"ifratings": ifratings-code,
"baf": baf-code,
"year": calendar-year,
"xayear": calendar-year,
"tuid": tuid,
"series": series-name,
"seriesplace": series-place
}
Yeah, I know. That's a lot of fields. Here's the breakdown:
- The key to a game-definition record is a code that I sometimes refer to as gid (for game-ID) or kacid (for Key and Compass ID).
I needed unique codes for games, and what I came up with was basically this: I take the first five letters or digits from the game title (not counting
certain words like "the", "and", and "of") and ignoring accents and converting to lower case. If the first character is a digit, I preface with 'a'. Trim to 5 characters if that
'a' made it 6. If there's less than 5 characters, pad with underscores. Then add the last two digits of the game's release year; use 'xx' if the year
is unknown. This seven-character code is the key (unless it's not unique, in which case, append a letter to end to make it unique again).
Yes, it's a bit ugly and ad hoc, but it works for me. And I allow myself to change the key of a game if the title changes or the year becomes known.
- The "titles" field is required; it takes an array of strings, each of which should be a title of the game.
The first title in the list is considered the main or primary title of the game (not necessarily the first title that the game was released with).
Titles can be marked up with an or-bar to indicate where sorting should begin (when sorting games by title).
Titles can also be marked up with language-markup codes.
- The "ifwiki" field is optional; it takes a string value: the corresponding article name in IFWiki for this game when different from
the primary title.
- The "authors" field is optional; it takes an array of person-ref records which should list every author of the game.
- The "adaptors" field is optional; it takes an array of person-ref records which should list every adaptor of the game.
(This field is provided for completeness; normally adaptors are listed at the version-record level.)
- The "contribs" field is optional; it takes an array of person-ref records which should list anyone who helped out with the game
in ways not covered by other fields. Typically this means illustrators, cover artists, and musicians.
- The "publishers" field is optional; it takes an array of person-ref records, but the "people" named are companies and organizations
that published or distributed the work.
- The "testers" field is optional; it takes an array of person-ref records which should list all testers of the game. The assumed role
is "beta-tester" if a role isn't declared.
- The "genres" field is optional; it takes an array of strings where each string is genre name in lowercase.
There's a certain amount of standardization I try to enforce on the genres. For example, I use "comedy" instead of "humor" or "humour"
and I use "sci-fi" instead of "sf" or "science fiction".
- The "license" field is optional; it takes a string which should name the game's license. This is currently a freeform field with no
standardization imposed.
- The "color" field is optional; it takes a string that comments on color usage in the game. Comments are typically short like "yes"
or "required". The idea is to indicate if blind players would have a problem playing the game and if so, why.
- The "graphics" field is optional; it takes a string that comments on graphics usage in the game. Similar to the "color" field.
- The "sound" field is optional; it takes a string that comments on sound and music usage in the game.
- The "cruelty" field is optional; it takes a string that ranks the game on Zarf's cruelty scale, labelling it as one of "Merciful",
"Polite", "Tough", "Nasty", or "Cruel".
- The "versions" field is optional, although strongly desired. It takes an array of version records
that share many of the same fields as game-records. Each version-record refers to a version (or versions) of the game.
As far as I know, only I (and IFWiki via my guidance) attempt to break down info about IF games by their versions.
- The "notes" field is optional; it takes an array of note-records.
- The "seealso" field is optional; it takes an array of link-records.
Homepages for a game should be labelled as "Homepage" in the link-record's "as" field.
- The "reviews" field is optional; it takes an array of link-records.
This is reserved for links to reviews about the game. By default, it is assumed that the "as" field of a review-link should be "Review".
- The "spoilers" field is optional; it takes an array of link-records.
This is reserved for spoilery links about the game. This includes links to transcripts, source code, walkthroughs, and maps.
- The "lists" field is optional; it takes an array of list-ref records.
Each list-ref names a game list that this game ought to be listed in and how.
- The "sline" field is optional; it takes a status-line record which describe what the status line (if any)
of the game looks like and what sort of information it displays.
- The "exts" field is optional; it takes an array of extension-ref records, each of which
names an extension used by the game.
- The "tags" field is optional; it takes an array of strings, each of which is a tag-name. Valid tags should be defined by the
"games/tags" field of the main "tags-info" field. Some tags can be dated; the format for a dated tag is "tagname:YYYY-MM-DD".
- The "ifro" field is optional; it takes a string value. It should be the game number that IF Review Org uses for this game.
- The "ifratings" field is optional; it takes a string value. It should be the game number that the ifratings site uses for this game.
(It can also be "x" to indicate that ifratings doesn't and never will have a listing for this game.)
- The "baf" field is optional; it takes a string value. It should be the game number that Baf's Guide uses (used?) for this game.
(It can also be "x" to indicate that Baf's Guide doesn't and never will have a listing for this game.)
- The "year" field is required; it takes a string value. It should be the calendar year that the game was first released.
If the year is unknown, the field value should be "0000".
- The "xayear" field is optional; it takes a string value. It should be the calendar year when this game became eligible for the XYZZY Awards.
If the game is unfinished, use "TBD". If the game is a demo or otherwise will never be eligible, use "0000".
- The "tuid" field is optional; it takes a string value. It should be the TUID that IFDB assigned to the main version of this game.
- The "series" field is optional; it takes a string value. It should name the series that this game belongs to. This field can be marked up
like a title; that is, it can have an or-bar to indicate where sorting begins.
(There is currently no provision for a game belonging to more than one series.)
- The "seriesplace" field is optional; it takes an integer value. It should indicate where in the series this game is placed.
games / versions
Version records are similar to game records in that they share a lot of the same fields. Where fields overlap, version-records inherit their game's
field values and can override them. For example, a version's "title" field overrides the game's "titles" field, so a version can have a different title
than usual.
It is expected that version records are listed in release date order, from earliest version to latest version.
Version records look like this:
{ "vername": version-name,
"title": title,
"headline": headline,
"authors":[ array of person-ref records ],
"adaptors":[ array of person-ref records ],
"contribs":[ array of person-ref records ],
"publishers":[ array of person-ref records ],
"testers":[ array of person-ref records ],
"authsys": authoring-system,
"platform": platform,
"lang": language-code,
"reldate": release-date,
"relline": release-line,
"license": licence-name,
"color": color-comment,
"graphics": graphics-comment,
"sound": sound-comment,
"nrooms": number-of-rooms,
"ifids":[ array of IFIDs ],
"tuid": tuid,
"events":[ array of event-ref records ],
"notes":[ array of note-records ],
"downloads":[ array of link-records ]
}
- The "vername" field is required; it takes a string value. It should uniquely describe the version in a human-friendly way such as "Version 1"
or "Competition release" or "French translation". I use "TBD" or "Version TBD" for games with no obvious version info, or games where I have yet
to research the version info.
- The "headline" field is very optional; it takes a string value. It should contain the headline of the game, when available.
- The "authors" field is the same as in the game-record. It's very rare for the authorship of a game to change within versions.
- The "adaptors" field is the game as in the game-record. Typical roles are "translator" and "porter".
- The "contribs", "publishers", and "testers" fields are same as in the game-record.
- The "authsys" field is optional; it takes a string value that names the authoring system used.
- The "platform" field is optional; it takes a string value that names the platform(s) that the game can be played on.
If multiple platforms must be listed, separate them with commas within the field.
- The "lang" field is optional, although it's really wanted. It takes a string value which is usually a 2-letter code (as per the language-records
seen in the "languages" main field). Sometimes, however, I have to type the language in full, particularly if the game is bilingual.
- The "reldate" field is optional; it takes a string value that indicates the release date of the version.
The date format should be one of "YYYY" or "YYYY-MM" or "YYYY-MM-DD".
- The "relline" field is optional; it takes a string value that shows the release-line from the game. This usually only makes sense for
games written in Inform.
- The "license", "color", "graphics", and "sound" fields are the same as the game-record's fields.
- The "nrooms" field is optional; it takes a string value. The value is usually a number indicating the number of rooms in the game.
Sometimes the value is two numbers separted by a plus-sign; for example: "1+8". This means one real room and eight visitable virtual rooms.
- The "ifids" field is optional; it takes an array of string values where each string is an IFID for this version of the game.
Yes, it's possible for a game version to have two IFIDs. Sometimes I bundle up IFIDs in one version with the intention of redistributing them into the
appropriate version records later. IFIDs should be specified in uppercase.
- The "tuid" field is similar to the game-record "tuid" field. Sometimes, when a game is offered in multiple languages, each language version
of a game gets a different page in IFDB (and thus a different tuid). So this field lets me specify these extra IFDB pages that a game might have.
- The "events" field is optional; it takes an array of event-ref records, each of which describes how the game
version participated at an event (such as a competition).
- The "notes" field is optional; it takes an array of note-records.
- The "downloads" field is optional; it takes an array of link-records, each of which should link
to a downloadable file, or link to a place where a file can be downloaded. Also, "play it online" links are specified here.
games / versions / events
Event-ref records specify which events a version participated in, and how, and what awards (if any) it earned.
An event-ref record has two fields: "event" and "honors", both of which are required:
{ "event": event-name, "honors":[ array of honor-records ] }
The event-name should be specified exactly the same as the key used for that event's event-definition record.
Honor-records have this format:
{ "cat": category, "place": number, "tie": true, "of": number, "rank": rank, "nb": comment }
- The "cat" field is required; it takes a string value. The usual category is "entry", which merely notes that the game participated.
Categories can also refer to event subdivisions and award categories.
- The "place" field is optional; it takes an integer value. A value of 1 means 1st place; a value of 2 means 2nd place, etc.
- The "tie" field is optional; it takes a boolean value. I only specify boolean fields when they're true.
- The "of" field is optional; it takes an integer value: the number of games entered in total for this event.
(I would like to phase this field out, in favour of the "of" field in the event-definition record.)
- The "rank" field is optional; it takes a string value. Typical values are "Winner" or "Runner-up".
- The "nb" field is optional; it takes a string value. Allows me to add a freeform comment about this game in this category.
For example, I might note the game's score or its standard deviation here.
This is also where I note which NPC or puzzle was considered for the XYZZY Awards' Individual NPC and Individual Puzzle categories.
Multi-use records
person-ref records
TODO
link-records
TODO
note-records
TODO