Dynamic Objects

version 8/140515 by Jesse McGrew

  • Home page
  • Beginning
  • Previous
  • Next



  • Section 3 - Linking the new object into the world model
    [Inform 6 implements objectloop on Glulx by putting all objects in a linked list. We need to add the new object to this linked list so it can be found by objectloop.
    Additionally, Inform 7 optimizes kind-based objectloops by adding properties containing a linked list for each kind: all things are linked together in one list, all containers are linked together in another list, and so on. Each kind has its own link property. There's no direct way to look up the property from the kind, but we can take advantage of the fact that they have similar names which are both available at runtime: a kind whose I6 name is K2_thing uses the link property IK2_Link.]
    Include (-
    ! compatibility with 6F95
    #ifndef KD_Count;
    Constant KD_Count = IK_0;
    #endif;
    [ DO_LinkObject src obj i last prop nk;
        ! add obj to the linked list of all objects
        last = 0;
        for (i=Class: i: i=(i + 1 + NUM_ATTR_BYTES)-->0)
            last = i;
        if (last)
            (last + 1 + NUM_ATTR_BYTES)-->0 = obj;
        ! add obj to the linked lists for each kind it's a member of
        nk = obj.KD_Count;
        while (nk > 0) {
            i = nk*2;
            prop = DO_FindLinkProp(obj, KindHierarchy-->i);
            if (prop) {
                last = src;
                while (last.prop) last = last.prop;
                last.prop = obj;
                obj.prop = 0;
            } else {
                print "*** Failed to find link property for ", (object) KindHierarchy-->i, " ***^";
            }
            nk = KindHierarchy-->(i+1);
        }
    ];
    Constant DO_PROPBUF_LEN 16;
    Array do_propbuf1 buffer DO_PROPBUF_LEN; ! the kind name, e.g. "K2_thing"
    Array do_propbuf2 buffer DO_PROPBUF_LEN; ! the property name, e.g. "IK2_Link"
    [ DO_FindLinkProp obj kind pt i prop;
        ! get kind name
        VM_PrintToBuffer(do_propbuf1, DO_PROPBUF_LEN, DO_PrintObject, kind);
        ! find obj's property table
        pt = (obj + 9 + NUM_ATTR_BYTES)-->0;
        ! check each property
        i = pt-->0;
        pt = pt + 4;
        while (i > 0) {
            prop = ((pt-->0) / $10000) & $FFFF;
            VM_PrintToBuffer(do_propbuf2, DO_PROPBUF_LEN, DO_PrintProperty, prop);
            if (DO_PropBufsMatch()) return prop;
            pt = pt + 10;
            i--;
        }
        rfalse;
    ];
    [ DO_PrintObject x; print (object) x; ];
    [ DO_PrintProperty x; print (property) x; ];
    [ DO_PropBufsMatch len p1 p2 c1 c2 lc2;
        len = do_propbuf1-->0;
        if (do_propbuf2-->0 <= len) len = do_propbuf2-->0 - 1;
        p1 = do_propbuf1 + WORDSIZE;
        p2 = do_propbuf2 + WORDSIZE + 1;
        lc2 = 0;
        while (len > 0) {
            c1 = p1->0; c2 = p2->0;
            ! we used to only have to compare up to the first underscore, but 6G60 added
            ! "IK#_Count" properties so we have to make sure the character after the
            ! underscore is an L
            if (c1 ~= c2) {
                if (lc2 == '_' && c2 == 'l' or 'L') rtrue;
                rfalse;
            }
            len--; p1++; p2++;
            lc2 = c2;
        }
        rfalse;
    ];
    -).