Concise code becomes more and more of a necessity the longer the project becomes. While you can wade through inefficient code when there is only a small amount of it, doing so when the project is immense is something you do not want to do. The latter wastes time and makes the code difficult to understand, which impedes finishing the game and makes debugging a nightmare. To cut to the chase, to make long games, you must use concise code, and to make concise code, you must leverage the expressivity of logical constructs.
Now, to make concise code, you must first notice something about the expressivity of the logical constructs provided to you by the language that you are using. INFORM and many others provide booleans, which can take two possible states. Booleans are easily readable but not very expressive, for that reason.
Integer variables are multi-state; that is, they can take on the range of values that belong to integer numbers. These variables can express far more than two states, which makes them more expressive. However, some readability is lost when using them. Compare two implementations of a wand that must be turned, expanded, and charged prior to use:
if (self.turned && self.expanded && self.charged) ...
!-- 1 = turned
!-- 2 = 1 and expanded
!-- 3 = 2 and charged
if (self.state = 3) ...
Let's leave aside the difference between the two, where in the boolean example the states can be wholly independent of one another and in the second, they are presumed to be part of a sequence. I've found that a sequence generally mirrors the real world of objects more closely than a situation where everything can be done in any order at all. For example: driving a car. You can't put the key into the ignition before you get in.
However, note that the integer variable is less readable. This loss of readability may be why languages such as C, C++, Java, and so forth came up with enumerated variable, which allows you to define the states that a variable can take. I really wish INFORM had this.
The only thing you can do in INFORM to approximate enumerated variables is to define constants for each value in a range, and then use that range ONLY with certain variables (or at least use them where there is no confusion amongst variables). For example:
Constant red 1;
Constant blue 2;
Constant green 3;
Object button "button" nowhererm
if (self.color == red) "It is red.";
if (self.color == blue) "It is blue.";
if (self.color == green) "It is sea-green.";
You still have to unpack the meaning of self.color for the user, as the language has no concept of green, blue, or red, except as integer values.
The language should handle these difficulties, rather than making the programmer program to fit what is simple for the parser or interpreter. For INFORM, I wonder if the enumerated type is something that could be bolted on to the language, but defining constants comes close enough for now. I suppose that a regular expression pre-processor could be written to handle such things, and that could be part of the build process, too. INFORM 7 has something like enumerated types, and it’s just a preprocessor for INFORM.
So what have I been up to these last two months?
I’ve spent most of my free time working on Seasons. It took me a few days to get back into it, but now I’m usually cranking out 2+ hours a night. So what progress have I made?
I started on winter first, and made puzzles work there. After tacking back and forth, I decided to finish up summer, since it was further along already. Specifically I’m in the fair area. However, in the fair, there are tickets. Tickets means handling parsing problems like ‘give 5 tickets’. That gave me a headache for a while, but it now works.
Besides that, it’s the usual stitching things together and making sure that there is a way to complete all the puzzles for that season. I’d say on that front I’m over half done.
On the horizon some is some clean-up and optimization work. I can’t afford to leave that until the game is all working, because then I will forget how certain parts work. I think this kind of program/optimize cycle is a good way to work, because when you do get done, your overall project is functional as well as lean. And leanness is important, because in a work of sufficient size, every little bit of complexity makes the entire project that much harder to understand. I’m convinced that the only way to achieve a truly complex (and engrossing) work is to have the components be as simple as they possibly can be.
Ever since I downloaded TextMate, I’ve been living in coding Cloud 9. Coding DEX = Coding DEX + 5! I even bought the product. That’s how awesome it is.
However, the Inform bundle was way out of date and rather limited. I sure wasn’t going to stand for a regress in my working environment! Must have syntax coloring. Must have function listing/navigation! So I went to work, delving into the madness of regex and fiddled around a bit until the power of the Inform bundle exceeded the power of my old BBEdit Inform bundle.
Now the TextMate folks have this in source control, so it may be a while before it passes their process and becomes official. However, if you want it now, pssst…over here! Unzip this to your ~/Library/Application Support/Textmate/Bundles directory and enjoy!
Beyond posts relating to New Cat, this is my last I7-related post. I felt it necessary to state the origins of its failures and to rail against what it says about the process of creation, those who create, and humanity itself. With this, I lay it upon the bier, set it aflame, and walk away.
Beyond the usability problems of forcing people to put all of their code into one file (a convention that I7 hypocritically fails to follow), such a convention presumes that all game designers use a linear, top-to-bottom, design process. I think of fusing smaller parts into a greater whole. The latter process groups like things together to be dealt with in their own area, limiting bleed and spillover into other topics, which creates a meta-level separation of function and data based upon internal similarity. That is, all functionality and data relating to topic/idea A is placed in the A file; the same goes for topic/idea B, topic/idea C, and so forth. This has parallels to traditional object-oriented language (and even functional programming), in that it minimizes the number of interface points. If you don’t do that, then it quickly becomes hard, if not impossible, to tell what your code is doing. So, you define the interface points and keep them as few as possible; separate files work in an analogous manner. And furthermore, they work this way because they reflect a typically human organizational scheme. People don’t heap everything into one common storage area. No, for they have waste baskets, refrigerators, and soap dishes — all different areas of containment for different things. Thus, if I declaim being forced into a single file for my code, it stems from a natural tendency to separate like objects into separate groupings.
That aside, I7′s story paradigm fails due to the output of the language itself. If what I7 produced was something that could be read from top to bottom, linearly, like a novel, then the need to group related materials together would be eliminated. The content is the issue, and the code is the issue. I7 output does NOT read straight through like a novel, and it never could, because a game is not a novel. While the needs of a game itself provide the first hurdle, the next hurdle is something that I7 sets up for itself: how rulebooks function.
The paradigm of the rulebook is that all like rules governing an object go in the same rulebook — or is it that all actions relating to all objects go into a rulebook? No matter which you choose, things quickly get out of hand. It would be wise to do both; however, if you do that, then your code cannot read straight through. It makes more sense to group together rules that affect multiple objects in a place divorced from any object (like in a separate file), or at the beginning of some section. But in order to refer to that section, you must return to it, or skip forward to it, breaking the processing flow of the game from top of page to bottom of page. I7 assumes that we’re all writing from top of page to bottom of page, writing as if we had only an old Selectrac typewriter, dutifully punching out one row after another.
That is an amazingly restrictive assumption, and it caters only to those who design puzzle-based games; it does not work well for most creative types. Editing on a typewriter is a painful and laborious process. What do you do when the ideas keep coming and have to improved or revised or discarded altogether? Clearly, you must brainstorm and edit elsewhere, and use the typewriter only to capture the finished idea, and you must be correct about that finished idea or else you begin the process anew. I could not write on a typewriter. I can write on paper, because although the paper has lines, I am not forced to use them. I can erase, write over, draw arrows, scratch things out, or even turn the page sideways. A text editor captured most of the creative capacities of paper, and naturally I seek out systems that allow me the same freedom in design. Like goes with like.
I7 imposes a harsh, utilitarian, one-size-fits-all unencouraging, unforgiving framework that in no way respects the creative process. It really is probably the worst possible tool for the job at hand, and the same people who have created this monstrosity are ever deaf, dumb, and blind, to all the pain, angst, and problems that they have created. They do not learn; they do not improve. Their reaction? Let the documentation fix it. However, no documentation can correct the erroneous worldview of I7. I7 fails to be usable.
The first step in making a usable product is to understand humanity; the first interface of I7 is between the language and the humans using it, and that is where it fails. From that set of wrong axioms, it descends, slowly and twistingly, into a dark valley of flawed assumptions that in the end, shuts out all light from the sky.
Inspiration is unpredictable, haphazard, wild, beautiful, and unrestrained. It is not logical, orderly, or predictable. Thus, in order to harness these wild winds, the creative type needs a flexible tool. I7 is not flexible. The creative type needs a tool that gets out of his way. I7 handholds you, even during the error messages. The creative type needs something that is not so obsessed with structure or details, but something that allows him to capture the thought, the moment, the spirit of things. Not that I6 is a great tool for doing that, but it gets in the way a lot less than I7 does. I6 lets you indent all you want, but I7 punishes you for hitting the tab an extra time.
The one-size-fits-all process requirement is completely at odds with human nature, and violently at odds with the creative nature. The people who lie down and wear the chains of I7 are probably accustomed to wearing the chains in other areas as well. I strongly suspect, that beyond politics, that people who are used to doing things in a top-down, logically straitjacketed, order from begin to end with no deviations are not in fact conservative, as some might think. However, they do desire a world that can be perfectly controlled as they perfectly control their games, their writing, their relationships, and so on. They have a command economy sort of life. Like the gargantuan hubris that produces such monstrosities of economic failure such as Kensianism and Socialism, we have I7 in the realm of game design — a command-economy manacle manufacturer for the mind, that produces a world where everyone is the same, everyone wears the same dirty tweed pants, marches in line to the same bread lines and sings the same forced songs, while the rifle butts of the soldiers collapse ribcages and kill the will to live free.
A fundamental misunderstanding of the human nature coupled with the mad hubris of the self-righteous leads to horrors (Hitler, Lenin, Stalin, Pol Pot, Mao, Mohammed). While I have no suspicion that I7 will lead to the gulags, the gas chambers, or the minarets, it has done its part in adding to the dominion of evil, for it lies about how people think, lies about how artists think, and tries to force us all into a restrictive mindset.
It will fail like a spectacle, like the Hindenburg.
It took me some time to puzzle through how exactly to create graphics and sound in Glulx for Seasons. I’m using I6 + ORLib + Gwindows which makes me insane already, right? Anyways, it turns out to my benefit that graphics and sound really aren’t touched by any of those aforementioned libraries, so there weren’t any weird conflicts to puzzle through. However, neither do any of these really cover or describe how to do sound and/or graphics (Gwindow’s optional GSound is extra-bulky and really doesn’t explain what it’s doing). So, I’m left on my own, trying to figure all this out. Long story short: I did, but not without running into five annoying things along the way.
Annoying discovery #1: MacGlulxe (for OS 8.x-9.x) does not support sound. Although that initially enraged me, I quickly accepted it as typical. I already knew that it didn’t support Unicode. I guess the designer just figured to skimp on something as unnecessary as sound, too. Sigh. This means that my design platform must be OS X, to be specific OS X 10.5, on the fastest 17″ iMac that Apple ever sold. What can I say? I <3 the screen size and the form factor.
Annoying discovery #2: How you name files is critical. Yes, I’d read Roger Firth’s Glulx page, and Doe’s Glulx for Dunces, and even Emily Short’s Glulx page (I was desperate), but it still took me a lot of trial and effort to figure this out.
In short: if you are not going to Blorb your game on the Mac, the filenames must be EXACTLY like this: PIC# and SND#, where # is a number. Also, you must start with number zero for whichever resource you use first. On Mac OS X, this means that you must do a Command-I to remove the extension from the file. On the Mac side, the resources cannot have extensions! Roger Firth’s advice was dead wrong.
As for sound, I had read that the only files supported are OGG, MOD, and 8-bit AIFF files. AIFFs definitely work, although I think that all Glulx interpreters downsample all AIFFs to 8 bits. Even if that is happening, it sounds good. You still have to do Command-I to remove the extension, though. Going forward, I’ll probably use OGG to save space.
Annoying discovery #3: Zoom doesn’t support sound. This one blew my mind. Zoom was my favorite interpreter, due to its interface and design. However, none of its Glulx interpreters support sound. Why? I don’t see any reason for Zoom to be crippled this way. That resulted in me switching over to Gargoyle for my interpreter of choice. It’s the best cross-platform interpreter out there, and it will make distro of Seasons a bit easier as well (one interpreter to rule them and all). In short, the interpreter designed for the Mac does not support Glulx sound, but the cross-platform one does. Weird.
Annoying discovery #4: No-one gives an example of a Glulx game that is not Blorbified. Yeah. Everyone assumes that your first intro to Glulx means that you will be going through all the extra steps to create a RES file and Blorb things up. Geez, people, why just not assume your intro to Calculus means that you’re playing around with Fermi’s equations, too? Talk about infuriating.
PEOPLE DO NOT LEARN by choosing the most difficult task in a new area. If you present information this way, they give up in frustration because they simply don’t have the experience or the knowledge to get anywhere. People learn by mastering smaller tasks, which gives them the confidence and understanding to master the difficult task.
What I’m going to do is to put the sample game that I created out on the Web complete with a sound/graphics resource so that you can compile it to Glulx and it will run — no questions asked. Then you can see exactly what you have to do to make it work.
Annoying discovery #5: The best Blorb tools are Windows-only. There is no tool that allows you to give your resources names other than SND# and PIC# on the Mac side. The only reasonable tool that I found for creating Blorb files was gBlorb. It does work and it is cross-platform, but your source code still can’t use identifiers like “autumn_sound”, like Doe does in Just a Dream. Sigh.
Now someone will say, “There is source code available!” Yes, and if you’ve ever tried to compile source code, then you know the nightmare that awaits you. You can spend days setting up your environment and building the thing only to have it fail due to an assumption in the code that prevents it from compiling on your platform. I’ve been there many times, which is why those words don’t work on me!
Still, I threw a few minutes at it. iBlorb needs dos.h, which is a collection of DOS functions that can’t be ported to other platforms, unless “porting” = “write equivalent OS-dependent code from scratch.” Loverly.
That leaves cBlorb, which as part of I7, is wholly undocumented. I guess I’ll see if I can deduce how it blorbifies a game with pictures and sound and go from there. Sigh.
I’ve always been torn about the “no thanks” list, whether it’s in the liner notes of an album, in the documentation for a game, or elsewhere. It has usually struck me as petty, childish, immature, and small. However, lately I have come to reconsider my position as regards such a list for an IF game.
Haters are a real problem in IF. By “haters”, I mean irresponsible people who eviscerate games for no justifiable reason; these are people who have nothing eternal to stand on, but simply attack games according to the fashion wheel of their feelings. Worse yet, these people band together and excrete their venom anonymously, feeling as brave as Klansmen. They never submit bug reports; they never have anything constructive to say; they exist to tear down what they could not even attempt.
I have recently experienced the haters and I am coming to think that for them, a special place is reserved in my releases; although I can think up many ways to immortalize them, a simple list should suffice. And really, why shouldn’t I? I praise those who aided me; should I not expose those who were unkind?
I am beginning to think that someone must call out these worthless individuals, expose them, and shame them, so that they would change and not be worthless. That would be the purpose of a “no thanks” list — not something personal and petty, but rather something that gave a public warning about certain individuals — to provoke them to change and in the meantime, to help everyone else to steer clear of them.
I was out cruising the IFdb lately and I noticed that a new Speed IF competition had occurred. Interesting, thought I. It wasn’t announced on any of the newsgroups. Why not?
- No-one uses the newsgroups anymore! I know that’s the perspective of certain IF luminaries, who attempt to shuffle newbies off to the new hangout of the Old Ones. Maybe it just never occurred to them to announce it on R*IF.
- I had killfiltered the person that announced it.
- These people met in a sewer of the Old Ones, and used it to promulgate this idea, without really caring if anyone else wanted to enter. If so, this would make this comp just another incestuous little soirée, not headed by the Old Ones, but using their methods and possibly obtaining their blessing.
- The creators realized that SpeedIF is a degenerate art form, created by people who love to flood the IF scene with broken, incomplete, mindless trash, and so they hid their efforts until someone else discovered them.
Sadly, as much as I would have loved for #4 to be the case, I realize that it wasn’t. Most likely it was #3, or a combination of #1 and #3. The IF community still doesn’t have the power to shame people from littering the landscape with shoddy works, and as a result, the albatross of IF lives on.
There is a strange current in IF where games propose something impossible and dare the player to actually do it; I say strange because such actions are clearly impossible, so why would anyone try? Is there some kind of bravado necessary here, where frustrated males yell “I’ll show THAT game designer”? Folks, the game designer isn’t even laughing up his sleeve at you. He’s shouting his derision at you using a megaphone.
For instance, take the game Square Circle. The intro asks if you can square a circle. Obviously, you cannot, so why bother torturing yourself?
Fate is another one. Can you change your fate? Obviously, if you can change your fate, it is not fate. The definition of the word fate removes all hope and all choice. To try to change your fate is futile.
I understand the self-torturing appeal of self-hate, but I’ve never understood the sure call to failure. Back in college, I had a comp sci professor who said something like, “Here is the fastest sort algorithm ever. Try to beat it.” I looked at him and thought, “You just said it was the fastest, and so therefore it is logically impossible for me to try to beat it. I think I’ll make the worst sort algorithm possible instead, since my failure has been guaranteed.”
Yesterday, I realized that Inform7 will not be fixed; the public bug-tracker and the suggestion board are nothing more than the usual smoke and mirrors, the customary shell game conducted by people who wish to appear open and committed to principle, but who in reality, are not. It’s a whitewash, and the developers (and their coterie) remain wedded to their own particularities instead of a consistent vision.
Although the problems I reported inevitably ended up being classed as “cosmetic” rather than design flaws, I still had hope.
Although I saw no action on the ideas I had suggested on the suggestion board, I still had hope.
I lost hope when the justification for not fixing a bug was, “that will break existing games!” That one moment revealed a deep-seated resistance to consistency, and then I knew that the gig was up.
What Inform 7 is, in the end, is nothing more than a petulant toy that bears the imprint of all the idiosyncrasies of its designers. It is not serious; it will not be serious; it cannot be a world-class language. It is, and forever will be, just another oddity. That this is a shame goes without saying, but it is a shame because the designers of the language refuse to commit to principles of design.
Yet another bad design decision, courtesy of the modern artists over at I7:
You are one ugly dude. [if DirtyHands is true] Your hands are dirty.[end if][if WetHands is true] Your hands still smell like pomegranate.[end if][if BathCat is true]Your hands are scarred due to misadventures in cat-bathing.[end if]
Instead of one status paragraph, the above code produces one paragraph for each condition that is true. This doesn’t make sense, as nothing in the paragraph clues you in that the language will behave like this. I filed a bug on this and it was rejected because “It’s been that way since the beginning.”
It doesn’t matter what GAMES will be broken; it matters whether this makes the LANGUAGE more consistent, more English-like, and easier to learn. How many revisions of Inform have broken games, anyways? Just about every other one, right? Yet this won’t be fixed. *facepalm*
Inform 7 itself has become a grande example of how NOT to design a language; either you live up to your goal of making code that reads like English, or you design yet another halfbreed language that requires users to learn specifics instead of principles. This all feels like I voted for “hope and change” and got $4.00/gal for gas, 10% unemployment, a crushing debt, union violence, and my health care in the hands of government.
Anyways, this is a bad decision because:
- The functionality is invisible. Nothing in the code informs the author that a line break is included after each sentence.
- The functionality is illogical. Why does a period indicate a new paragraph? It doesn’t in English, and yet Inform 7 claims to generate code that reads like English.
- The workaround makes no sense. The answer is to put a period in the next part of the condition instead of the first part, yet why would anyone naturally do that? It’s silly to have to break up complete sentences because the Inform 7 preprocessor will automatically throw in line breaks if you don’t! Again, the author is forced to know the particularities of the preprocessor in order to write the game. So much for that Natural Language Programming thing, I guess.
Again, Inform 7 is like natural language, only when it isn’t. I can’t wait to get done with New Cat so that I can turn my back on this mess once and for all.