intfiction.org

The Interactive Fiction Community Forum
It is currently Sat May 18, 2013 10:57 am

All times are UTC - 6 hours [ DST ]




Post new topic Reply to topic  [ 17 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Thu Apr 05, 2012 4:59 am 
Offline

Joined: Sun Aug 14, 2011 6:21 am
Posts: 127
I've taken the Treaty of Babel code from Grotesque, cleaned it up greatly, packaged it nicely and made it available separately so other developers can put it to use. This is a pure-Python implementation of the Treaty of Babel, which you can use to identify (ie find the IFID) of any story file covered by the Treaty. It also handles metadata and cover art extraction for the story formats (tads2/tads3) and wrappers (blorb) that support it. It is, of course, a bit slower than the official C API, but the code is (hopefully) a bit more Pythonic than bindings to the C API would be. For my purposes, at least, the speed isn't a problem.

The package includes a script called pyIFBabel which replicates the `babel` commandline utility distributed on the official Treaty page. It's mostly for demonstration purposes, though I suppose you could use it if you want to.

This is a beta release, so expect future releases to possibly make some small API changes.

Version 0.2.2
What works:
- all story format and wrapper handlers
- IFiction XML parsing and creation
- blorb extraction
- IFDB IFiction retrieval

What doesn't work:
- IFiction XML verification/lint, sparse file completion
- blorb creation
- Python 3 support

Download & Install
Source: download
To install: extract the archive and run `python setup.py install` in the package directory

PyPi: pyIFBabel is available on PyPi so you can install it via `pip install pyIFBabel`.

Arch Linux: pyIFBabel is available in the AUR.

Development
You can fork my git repository at Gitorious.


Note:
Most of the code was written from scratch but some of it was admittedly translated directly from the original C code so credit must be given to L. Ross Raszewski for that.

_________________
Grotesque: an interactive fiction library manager for Linux
PyIFBabel: a Treaty of Babel library for Python


Last edited by jakobcreutzfeldt on Wed May 23, 2012 2:34 pm, edited 7 times in total.

Top
 Profile Send private message  
 
PostPosted: Thu Apr 05, 2012 5:05 am 
Offline

Joined: Sun Aug 14, 2011 6:21 am
Posts: 127
Example:

Code:
Python 2.7.2 (default, Jan 31 2012, 13:19:49)
[GCC 4.6.2 20120120 (prerelease)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from treatyofbabel import babel
>>> babel.get_ifids("tests/glulx/FerrousRing.ulx")
['GLULX-1-070928-AD26C29D']
>>> babel.deduce_format("tests/glulx/FerrousRing.ulx")
'glulx'
>>> babel.get_ifids("tests/blorb/AnchorheadDemo.gblorb")
[u'F76B2529-27F8-44ED-B643-C5F03492881D']
>>> print babel.get_meta("tests/blorb/AnchorheadDemo.gblorb")
<?xml version="1.0" encoding="UTF-8"?>
<ifindex version="1.0" xmlns="http://babel.ifarchive.org/protocol/iFiction/">
    <story>
        <identification>
            <ifid>F76B2529-27F8-44ED-B643-C5F03492881D</ifid>
            <format>glulx</format>
        </identification>
        <bibliographic>
            <title>Anchorhead: Special Edition Demo</title>
            <author>Michael Gentry</author>
            <headline>prelude to a tale of horror</headline>
            <genre>Horror</genre>
            <firstpublished>2007</firstpublished>
            <description>This is the demo version for Anchorhead: Special Edition, to be released in November 2007. It is not a complete game.</description>
            <language>en</language>
            <group>Inform</group>
        </bibliographic>
        <releases>
            <attached>
                <release>
                    <releasedate>2007-02-02</releasedate>
                    <version>3</version>
                    <compiler>Inform 7</compiler>
                    <compilerversion>4K41</compilerversion>
                </release>
            </attached>
        </releases>
        <colophon>
            <generator>Inform 7</generator>
            <generatorversion>4K41</generatorversion>
            <originated>2007-02-02</originated>
        </colophon>
        <glulx>
            <serial>070202</serial>
            <release>3</release>
            <compiler>Inform 7 build 4K41</compiler>
        </glulx>
    </story>
</ifindex>

>>> babel.deduce_format("tests/blorb/AnchorheadDemo.gblorb")
'blorbed glulx'


The pyIFBabel commandline tool:
Code:
$ ./pyIFBabel --identify tests/tads/Banana.t3
"The Quest of the Golden Banana" by Eric Eve
IFID: TADS3-C2DAA2AFED843DA41084EA1031BDF250
tads3, 709k, no cover

_________________
Grotesque: an interactive fiction library manager for Linux
PyIFBabel: a Treaty of Babel library for Python


Top
 Profile Send private message  
 
PostPosted: Thu Apr 05, 2012 10:00 am 
Offline

Joined: Tue Apr 27, 2010 1:02 pm
Posts: 797
Excellent, thanks for making this!


Top
 Profile Send private message  
 
PostPosted: Thu Apr 05, 2012 12:04 pm 
Offline

Joined: Sat Jan 23, 2010 4:56 pm
Posts: 2081
Sweet.


Top
 Profile Send private message  
 
PostPosted: Sat May 05, 2012 7:29 am 
Offline

Joined: Sun Aug 14, 2011 6:21 am
Posts: 127
I've released version 0.2 today (see the original post for updated links).

This release includes some bug fixes in the `treatyofbabel.ifiction` module, which should work a bit more smoothly now. Additionally, I've fixed up the previously non-functional `treatyofbabel.ifstory` module and the `IFStory` class that it defines. This module gives you an object-oriented means of working with story files and is the recommended way of working with the library.

I still haven't written proper documentation, but here is something like a tutorial:

-----

There are two primary ways to use this library. The first way is via the treatyofbabel.babel and treatyofbabel.ifiction modules. The babel module contains functions for extracting metadata from interactive fiction story files. Until proper documentation is written, it is best to use Python’s introspection capabilities to view the available functions (dir(treatyofbabel.babel)). In general, you will pass these functions a string referring to the file’s location. So, for example, to determine the format of the file (ie glulx, tads2, etc.), you would do:
Code:
>>> babel.deduce_format("path/to/file")

To calculate the IFID(s) of a file, you would do:
Code:
>>> babel.get_ifids("path/to/file")

The ifiction module contains functions for working with IFiction files. These are simply XML files, so the module essentially just consists of IFiction-specific convenience functions. The functions typically return objects belonging to the built-in Python module xml.dom.minidom, though you generally won’t have to do anything with these other than pass them between ifiction functions. One can build up an IFiction file manually:
Code:
>>> ifdom = ifiction.create_ifiction_dom()
>>> story = ifiction.add_story(ifdom)
>>> ifiction.add_identification(ifdom, story, list_of_ifids, story_format, story_bafn)
>>> ifiction.add_bibliographic(ifdom, story, truncate=False, title="My Story",
    author="Pat Smith")

…and so on. Alternatively, given an IFiction file, you can extract information from it:
Code:
>>> ifdom = ifiction.get_ifiction_dom("path/to/file.ifiction")
>>> assert ifiction.is_ifiction(ifdom)
>>> stories = ifiction.get_all_stories(ifdom)
>>> story = stories[0]
>>> ident = ifiction.get_identification(story)

…and so on.

There is another, object-oriented means of doing this, contained in the treatyofbabel.ifstory module. This module defines the IFStory class, which has fields corresponding to the information contained in an IFiction file. There are various ways you can use this class. You can build up a story description manually:
Code:
>>> story = ifstory.IFStory()
>>> story.ifid_list = ["ZCODE-88-840726-A129"]
>>> story.bibliographic["title"] = "Zork I"

This is tedious, though, so better options are available. If you have an IFiction file, you can use that to fill in all of the fields:
Code:
>>> ifdom = ifiction.get_ifiction_dom("path/to/file.ifiction")
>>> story_node = ifiction.get_all_stories(ifdom)[0]
>>> story = ifstory.IFStory(ific_story_node=story_node)
>>> print story.bibliographic["title"]
"Zork I"

You can use the capabilities provided by the treatyofbabel.babel module to automatically fill in some information (note that for most formats, this will only be able to generate an IFID and determine the story format):
Code:
>>> story = ifstory.IFStory(story_file="path/to/storyfile")
>>> story.load_from_story_file()
>>> print story.ifid_list
["ZCODE-88-840726-A129"]

Given an IFID, you may fill in the rest of the fields and optionally fetch cover art by remotely querying the IFDB (http://ifdb.tads.org) [continuing from the last example]:
Code:
>>> story.load_from_ifdb()
>>> print story.bibliographic["title"]
"Zork I'
>>> print story.cover.img_format
"jpg"
>>> with open("ZorkI.jpg", "wb") as img_handle:
...     img_handle.write(story.cover.data)
>>> with open("ZorkI.ifiction", "w") as ific_handle:
...     ific_handle.write(story.to_ifiction())

Once again, until proper documentation has been written, it is recommended to use introspection or to read the (hopefully readable) code to see all of the functions available.

_________________
Grotesque: an interactive fiction library manager for Linux
PyIFBabel: a Treaty of Babel library for Python


Top
 Profile Send private message  
 
PostPosted: Sat May 05, 2012 8:56 am 
Offline
User avatar

Joined: Sun May 02, 2010 8:27 am
Posts: 126
Location: London
Quest isn't part of this so-called "treaty", but if anyone's interested then since v5.1 each game gets its own GUID.

The .quest file is simply a ZIP file, and the GUID can be found in the contained game.aslx file. This file is XML and the id can be found within the <gameid> tag which appears inside <game>.

There's other info inside the <game> tag too. Not sure what other info would be needed but if anyone is interested at all then let me know.

_________________
Quest - create and play text adventure games in your browser


Top
 Profile Send private message  
 
PostPosted: Sat May 05, 2012 9:18 am 
Offline

Joined: Sun Aug 14, 2011 6:21 am
Posts: 127
Well, I can't speak for the anybody from the official treaty and the original C tool, but I'd certainly like to add a Quest handler to pyIFBabel (selfishly, it will help with my other project Grotesque, so people can also manage their Quest games with it)! I can implement it similar to the TADS handler, which takes metadata from the embedded gameinfo text file and coverts it to use the standard Treaty terminology.

Is the full .aslx XML specification online anywhere?

Thanks!

_________________
Grotesque: an interactive fiction library manager for Linux
PyIFBabel: a Treaty of Babel library for Python


Top
 Profile Send private message  
 
PostPosted: Sat May 05, 2012 9:27 am 
Offline
User avatar

Joined: Sun May 02, 2010 8:27 am
Posts: 126
Location: London
Info on the format is here: http://quest5.net/wiki/ASLX_Elements

Let me know if I can help with anything.

_________________
Quest - create and play text adventure games in your browser


Top
 Profile Send private message  
 
PostPosted: Sat May 05, 2012 11:27 am 
Offline

Joined: Sun Aug 14, 2011 6:21 am
Posts: 127
Ok thanks! I think I've already got something going for it. I'll download some story files to test it out.

Is the gameid guaranteed to be defined in the file? If not, is there an algorithm to calculate the gameid for a given file?

I couldn't find it in the wiki, but are these all the metadata fields that might appear in the aslx file: version, author, gameid, description, category, start?

_________________
Grotesque: an interactive fiction library manager for Linux
PyIFBabel: a Treaty of Babel library for Python


Top
 Profile Send private message  
 
PostPosted: Sat May 05, 2012 6:50 pm 
Offline
User avatar

Joined: Sun May 02, 2010 8:27 am
Posts: 126
Location: London
Gameid is not guaranteed - it won't be there for games created with 5.0.x, and also I suppose there's nothing to stop it from being deleted (though that's unlikely). In its absence there's nothing defined that would uniquely identify a game though you could always use some kind of hash.

Those metafields look correct to me (not "start" though - don't know where that's come from?). It looks like some of those are indeed missing from the wiki (they were added in 5.1 and looks like I forgot to add them to the wiki).

_________________
Quest - create and play text adventure games in your browser


Top
 Profile Send private message  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 17 posts ]  Go to page 1, 2  Next

All times are UTC - 6 hours [ DST ]


Who is online

Users browsing this forum: Bing [Bot] and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group