Inform 7 WTF



  • This is part of a translation of Dungeon (Zork) to Inform 7 from FORTRAN 77. FORTRAN code:

    C ENCRYP-- Encrypt password
    C
    C Declarations
    C
    SUBROUTINE ENCRYP(INW,OUTW)
    IMPLICIT INTEGER (A-Z)
    INCLUDE 'dparam.for'
    CHARACTER*8 INW,OUTW,KEYW
    INTEGER UINW(8),UKEYW(8)
    DATA KEYW/'ECOVXRMS'/

    ICHARA=ICHAR('A')-1 ! character base.
    UINWS=0 ! unbiased inw sum.
    UKEYWS=0 ! unbiased keyw sum.
    J=1 ! pointer in keyword.
    DO 100 I=1,8 ! unbias, compute
    sums.
    UKEYW(I)=ICHAR(KEYW(I:I))-ICHARA ! strip ascii.
    IF(ICHAR(INW(J:J)).LE.ICHARA) J=1 ! recycle on bad.
    UINW(I)=ICHAR(INW(J:J))-ICHARA
    UKEYWS=UKEYWS+UKEYW(I)
    UINWS=UINWS+UINW(I)
    J=J+1
    100 CONTINUE

    USUM=MOD(UINWS,8)+(8*MOD(UKEYWS,8)) ! compute mask.
    DO 200 I=1,8
    J=(UINW(I).XOR.UKEYW(I).XOR.USUM).AND.31
    USUM=MOD(USUM+1,32)
    IF(J.GT.26) J=MOD(J,26)
    OUTW(I:I)=CHAR(MAX0(1,J)+ICHARA)
    200 CONTINUE
    RETURN

    END

    New Inform 7 code
    To decide what indexed text is the encryption of (x - an indexed text):
    let keyw be {5, 3, 15, 22, 24, 18, 13, 19};
    let outw be an indexed text;
    let uinws be 0;
    let usum be 0;
    let inw be a list of numbers;
    let i be 1;
    let j be 1;
    change outw to "[8 spaces]";
    let len be the number of characters in x;
    while i is at most 8 begin;
      if j is greater than len, change j to 1;
      let a be character number j in x;
      if a matches the regular expression "<^A-Z>", change j to 1;
      let a be character number j in x;
      let b be the alphabet position of a;
      add b to inw;
      increase uinws by b;
      increase i by 1;
      increase j by 1;
    end while;
    change usum to (the remainder after dividing uinws by 8) + 56;
    change i to 1;
    while i is at most 8 begin;
      let c be entry i of inw;
      let b be entry i of keyw;
      change j to the twiddle of c and b and usum;
      change j to the remainder after dividing j by 32;
      if j is greater than 26, change j to the remainder after dividing j by 26;
      change a to character number j in the alphabet;
      replace character number i in outw with a;
      change usum to the remainder after dividing (usum + 1) by 32;
      increase i by 1;
    end while;
    decide on outw.
    

    To decide what number is the twiddle of (a - a number) and (b - a number) and (c - a number):
    (- xor(xor({a},{b}),{c}) -).

    To decide which number is the alphabet position of (n - an indexed text):
    if n is "A", decide on 1;
    if n is "B", decide on 2;
    if n is "C", decide on 3;
    if n is "D", decide on 4;
    if n is "E", decide on 5;
    if n is "F", decide on 6;
    if n is "G", decide on 7;
    if n is "H", decide on 8;
    if n is "I", decide on 9;
    if n is "J", decide on 10;
    if n is "K", decide on 11;
    if n is "L", decide on 12;
    if n is "M", decide on 13;
    if n is "N", decide on 14;
    if n is "O", decide on 15;
    if n is "P", decide on 16;
    if n is "Q", decide on 17;
    if n is "R", decide on 18;
    if n is "S", decide on 19;
    if n is "T", decide on 20;
    if n is "U", decide on 21;
    if n is "V", decide on 22;
    if n is "W", decide on 23;
    if n is "X", decide on 24;
    if n is "Y", decide on 25;
    if n is "Z", decide on 26.

    The alphabet is an indexed text variable. The alphabet is always "ABCDEFGHIJKLMNOPQRSTUVWXYZ".

    Incanting is an action applying to one topic. Understand "incant [text]" as incanting.
    Check incanting:
    if endgame flag is true, say "[one of]Sorry, only one incantation to a customer.[or]Incantations are useless once you have gotten this far[at random]" instead.

    Carry out incanting:
    let i be the number of words in the topic understood;
    let a be word number one in the topic understood;
    change a to "[a in upper case]";
    let b be word number two in the topic understood;
    change b to "[b in upper case]";
    if i is 1 begin;
    if the player is not in Crypt of the Implementors, say "That spell has no obvious effect." instead;
    if not in darkness, say "That spell has no obvious effect." instead;
    if the player is carrying something lit, say "That spell has no obvious effect." instead;
    let b be character number 1 in a;
    if b matches the regular expression "<^A-Z>", say "Sorry, your secret word must begin with a letter." instead;
    say "A hollow voice replies '[encryption of a]'";
    change the score to 621;
    change endgame flag to true;
    move the battery-powered brass lantern to the player;
    move the sword to the player;
    move the player to Top of Stairs.
    else if i is 2;
    let c be character number one in a;
    let d be character number one in b;
    if c matches the regular expression "<^A-Z>", say "That spell has no obvious effect." instead;
    if d matches the regular expression "<^A-Z>", say "That spell has no obvious effect.";
    let e be the encryption of a;
    let f be the encryption of b;
    if e is b, skip to the endgame instead;
    if f is a, skip to the endgame instead;
    say "That spell has no obvious effect.";
    else;
    say "That spell has no obvious effect.";
    end if.



  • Is the WTF in the actual implementation of the algorithm, or is it the programming language? On a first glance, the Inform code is much easier to read than the Fortran code (that is without having ever used either language), and I'm impressed that this kind of computation is even possible in Inform. 

    This reminds me of the the Shakespeare Programming Language, but Inform is actually productive. Very cool.



  • @Nandurius said:

    Is the WTF in the actual implementation of the algorithm, or is it the programming language? On a first glance, the Inform code is much easier to read than the Fortran code (that is without having ever used either language), and I'm impressed that this kind of computation is even possible in Inform. 

    This reminds me of the the Shakespeare Programming Language, but Inform is actually productive. Very cool.

     The programming language is not the WTF -- it makes sense to use a programming language for writing Z-code text adventures for implementing a text adventure.

     The WTF is using a bunch of ifs to get the alphabet position rather than a select case. Other than that, the rest of code is actually pretty goodl



  • Compared to what a FORTRAN-to-C compiler would generate this actually looks more readable. A very nice example of how Inform 7 rocks, even if it tends to hyperverbosity.



  • @samanddeanus said:

     The WTF is using a bunch of ifs to get the alphabet position rather than a select case. Other than that, the rest of code is actually pretty goodl

    Inform 7 doesn't seem to have a general purpose switch statement, as far as I can tell, so the only way I can see you'd get it much better is by using "otherwise" (else). Sure, you can drop down to Inform 6 code and just put a block in there, but they might not have wanted to do that.

    (Granted, I haven't really worked with either version of Inform.)



  • @j6cubic said:

    A very nice example of how Inform 7 rocks, even if it tends to hyperverbosity.
     

    It looks decidedly less verbose than ordinary C# + .Net



  • @samanddeanus said:

    Carry out incanting:
    let i be the number of words in the topic understood;
    let a be word number one in the topic understood;
    change a to "[a in upper case]";
    let b be word number two in the topic understood;
    change b to "[b in upper case]";

    Good God, that looks like an unholy love-child of code from Graham Nelson and Eric S. Raymond. No, wait, if ESR was involved, this would have more proto-anci-fennoscandonian rune-poemtry. I don't know if Futhark works in these forums, so here's a reasonable approximation of what I pictured...

    Før værilþy, We šalt chantt,
    inne ðeus wenne øeure harþs wert fyl øf joye,
    ánde fyl øf zeale ánde fyl øf brevry førre fáþer-landynn:
      værilþy šalt be "i", numbyr be øf wordes inne topícyn knéwnstød;
      værilþy šalt be "á", þe word fyrst, by Odin, offe topícyn knéwnstød;...

    Okay, joking aside, the obvious question: Is there a reason why the implementation has to use this particular encryption method? Why can't it use something that would be, uh, more Inform-friendly?

    (Edit: Okay I didn't read the code before writing the above AltGr-orgy, so it's not an exact dupe, but I guess I made the point =)



  • @WWWWolf said:

    Okay, joking aside, the obvious question: Is there a reason why the implementation has to use this particular encryption method? Why can't it use something that would be, uh, more Inform-friendly?
    Backwards compatibility? :)



  • That piece of code is not working for me in inform 7, why?

    List of Problems:

    Problem. You wrote 'else if i is 2' : but this seems to say that a thing is a value, like saying 'the chair is 10'.


    Problem. You wrote 'let c be character number one in a' : but I can't find a verb here that I know how to deal with, so I am ignoring this sentence altogether.

    See the manual: 2.17 > Review of Chapter 2: The Source Text


    Problem. You wrote 'let d be character number one in b' : again, I can't find a verb here that I know how to deal with.


    Problem. You wrote 'if c matches the regular expression "<^A-Z>", say "That spell has no obvious effect." instead' : but I can't find a verb that I know how to deal with. This looks like an 'if' phrase which has slipped its moorings, so I am ignoring it. ('If' phrases, like all other such instructions, belong inside definitions of rules or phrases - not as sentences which have no context. Maybe a full stop was accidentally used instead of semicolon, so that you inadvertently ended the last rule early?)

    See the manual: 11.6 > If


    Problem. You wrote 'if d matches the regular expression "<^A-Z>", say "That spell has no obvious effect."' : again, I can't find a verb that I know how to deal with. This looks like an 'if' phrase which has slipped its moorings.


    Problem. You wrote 'let e be the encryption of a' : again, I can't find a verb here that I know how to deal with.


    Problem. You wrote 'let f be the encryption of b' : again, I can't find a verb here that I know how to deal with.


    Problem. I am reading the sentence 'if e is b, skip to the endgame instead' as a declaration of the initial state of the world, so I'm expecting that it will be definite. The only way I can construe it that way is by thinking that 'if e' and 'b' are two different things, but that doesn't make sense, and the 'if' makes me think that perhaps you did not mean this as a definite statement after all. Although 'if...' is often used in rules and definitions of what to do in given circumstances, it shouldn't be used in a direct assertion.


    Problem. You wrote 'if f is a, skip to the endgame instead' : but this seems to give something a name which consists only of an article, that is, 'a', 'an', 'the' or 'some'. This is not allowed since the potential for confusion is too high. (If you need, say, a room which the player sees as just 'A', you can get this effect with: 'A-Room is a room with printed name "A".')


    Problem. You wrote 'say "That spell has no obvious effect."' : again, I can't find a verb here that I know how to deal with.


    Problem. You wrote 'else' : again, I can't find a verb here that I know how to deal with.


    Problem. You wrote 'say "That spell has no obvious effect."' : again, I can't find a verb here that I know how to deal with.


    Problem. You wrote 'end if' : again, I can't find a verb here that I know how to deal with.


    Problem. You wrote 'Incanting is an action applying to one topic' : but that seems to be an action already existing, so it cannot be redefined now. If you would like to reconfigure an action in the standard set - for instance if you prefer 'unlocking' to apply to only one thing, not two - create a new action for what you need ('keyless unlocking', perhaps) and then change the grammar to use the new action rather than the old ('Understand "unlock [something]" as keyless unlocking.').

    See the manual: 12.7 > New actions



  • @m4u said:

    That piece of code is not working for me in inform 7, why?

    List of Problems:

    ................................ See the manual: 12.7 > New actions

    This somehow reads like a poem



  • To decide what indexed text is the encryption of (x - an indexed text):
    let keyw be {5, 3, 15, 22, 24, 18, 13, 19};
    let outw be an indexed text;
    let uinws be 0;

    O_O

    I'm not sure whether to be amazed that the language is able to pull natural language processing off, or terrified that it actually attempts to. Since it's a domain-specific language, I'm not going to have nightmares about it, but still... O_O.



  • @Maciejasjmj said:

    I'm not sure whether to be amazed that the language is able to pull natural language processing off, or terrified that it actually attempts to. Since it's a domain-specific language, I'm not going to have nightmares about it, but still... O_O.

    It's not very good at it, either; they had to take a number of shortcuts that can end up biting you. For instance, IIRC, fuzzy matching of object names was implemented in such a way that the parser cannot distinguish between two things if one is a prefix of the other. So "coffee" and "coffee maker" are the same thing as far as the parser is concerned. Plus, it's fairly easy to confuse the parser with perfectly valid input (although this seems improve as newer versions come out).



    I once tried to write a text adventure where the material an item was made of mattered. That ran into a brick wall when I found out that it was impossible to have rubber boots made of rubber, leading to an elaborate dance where materials had one name internally but reported a different one for text output. I finally gave up when [i]that[/i] ended up confusing the parser. I probably should've implemented that mechanic in Inform 6 but I didn't feel like learning yet another language just to write a text adventure.



    Inform 7 is kinda neat in that it makes writing a text adventure very straightforward. It's easy to pick up and comes with a lot of stuff baked right in and provides well as an elaborate help/tutorial document. On the other hand, it's hair-pullingly frustrating to implement any sort of advanced functionality yourself as blocks of code can somehow work fine on their own but confuse the parser when unrelated code is added.


Log in to reply
 

Looks like your connection to What the Daily WTF? was lost, please wait while we try to reconnect.