SenseConnectors and RoomParts

I miss you guys! Been on kind of a roll, in the sense that WIP is progressing and am effectively debugging strange behavior on my own. Debugging is time consuming still, but able to get there. Which is why you haven’t heard from me. Here’s something maybe of interest?

Been using SenseConnector and Occluder what felt like pretty effectively to manage PC’s visual messages until I engaged RoomParts. The scenario is an OutdoorRoom SenseConnected to a (Indoor) Room. I had been managing shouldn’t-see things kinda like this:

    occludeObj(obj, sense, pov) {
        // these items not visible if not collocated
        //
        if ((obj is in (rock, path, flower))
             && (!pov.isIn(obj.getOutermostRoom())))
                return true;

        return inherited(obj, sense, pov);
    }

This breaks down in roomparts. Specifically when outdoors (no walls), thanks to connector, examining walls gives:

>x walls
west wall: You see nothing unusual about it.
east wall: You see nothing unusual about it.
north wall: You see nothing unusual about it.
south wall: You see nothing unusual about it.

SenseConnected indoor walls are quietly in scope and giving what I deem an unacceptably deceptive message. My solution is to mandate that roomParts in connected locations are uninteresting, like so:

    occludeObj(obj, sense, pov) {

        // make roomparts only visible if included in room
        //
        if (obj.ofKind(RoomPart)
          && !pov.getOutermostRoom().roomParts.indexOf(obj))
                return true;

        return inherited(obj, sense, pov);
    }

Since I have a class that combines SenseConnector and Occluder I can do it globally. Would need to be manually added to local SenseConnectors in this situation otherwise. Will be playing with RoomPartItem later in my WIP, to see if the solution holds or needs further attention. Will update if interesting.

Yes, this is a really niche problem, but the fix’s lines of code/hour rate was embarrassingly small because I failed to realize that indexOf(obj) returned nil, not 0 if no match.

The latest from JJMcC’s FIDIW (Fixing Issues Deep In the Weeds).

1 Like

It may be obvious, but the problem exists wherever Rooms with different roomParts are SenseConnected. It would arguably be worse connecting a room with custom walls to a standard one.

>x walls
unusual west wall: Super unusual wall!
unusual east wall: Super unusual wall!
unusual north wall: Super unusual wall!
unusual south wall: Super unusual wall!
west wall: You see nothing unusual about it.
east wall: You see nothing unusual about it.
north wall: You see nothing unusual about it.
south wall: You see nothing unusual about it.

Fix should address any permutations of that.

1 Like

If you’re just worried about the default description being misleading in this situation, how about just:

modify DefaultWall
        remoteDesc(pov) { "You can\'t get a good look from here."; }
;

…perhaps adding more elaborate logic to present different views from different POVs.

1 Like

Glad to hear from you again!

On a related topic, I created a Walls class, which, by simply being defined and located within a Room, will oust all of the defaultWalls out, and will field vocab for all of the directions unless a custom roompart wall is present, in which case it doesn’t take that vocab on. No manual twiddling of the Room’s roomParts is necessary… done in preinit.
So most of the time, the walls of any room can be summarized with one desc in one object, with the freedom to add special walls as needed which will automatically supersede the collective walls (for that direction). Also with a simply property addition you can determine your walls to respond to nw/ne/sw/se or any other configuration instead of the default nesw.

1 Like

To me, it was the presence of the enumerated walls that felt misleading, not just the description. I started by trying to figure out how to communicate where the walls being described actually were, which was not so easy to do since RoomParts are by nature everywhere and have no .location to check. I mean, God forbid you have MULTIPLE open doors chiming in! Add sky vs ceiling and to a lesser extent floor v ground and… I quickly decided sidestepping the issue was most preferable given it was kind of a pathological case to start with.

This seems really interesting to me. While I infrequently do anything with walls, I find that when I do I am consistently replacing the 4 walls with a single customAllWalls (manually in roomParts) because interacting seems less annoying that way.

1 Like

Maybe?

I can see not wanting >X WALLS to include the walls of a room visible only via a senseConnector. But I also don’t know that I’d generally want it to be impossible to examine the remote room’s walls if other things in the room are visible.

If the game’s a mystery and the player can stand in the yard and look through windows to see what the killer/thief/spy/whatever saw, I’d expect them to try examining the walls at some point. In fact that’s more or less the kind of problem that got me thinking about sense connectors—and what can and cannot be seen through them, and how—in the first place.

3 Likes

If you think you’d use it, I’d be happy to share code… but it sounds like you’ve already got things covered?

1 Like

Ok, that got me thinking so I played with RoomPartItem a bit (sorry WIP, shiny things!). Turns out, occluding walls as above effectively masks PartItems from remote >look but does NOT occlude them from explicit examines! If you then put '(n) (north) wall' in the item’s vocab, you can examine remote walls without getting stray messages in remote looks! This is quick and dirty and has a few weird side effects: you’d want to to add and remove the wall vocab on room exit/entry to avoid disambiguation when in the room, and the <CR> might need some surgery, but this is what I’m on about:

startRoom: OutdoorRoom 'Front Yard'
    "This is a featureless front yard.  A house is to the north. "
    north = house 
    in asExit(north)
    vocabWords = 'outside'
;
+me: Person;
+rock: Thing 'ordinary rock' 'rock' "An ordinary rock. Only visible outside.  ";

doorwayToOutside :  Occluder, SenseConnector, Fixture
    'ordinary doorway' 'ordinary doorway'
    locationList = [startRoom, house]
    connectorMaterial = glass
    occludeObj(obj, sense, pov) {
        // rock only visible outside, this works
        //
        if ((obj == rock)
             && (!pov.isIn(obj.getOutermostRoom())))
                return true;

        // make roomparts only visible if included in room
        // comment out to show original issue
        //
        if (obj.ofKind(RoomPart)
            && !pov.getOutermostRoom().roomParts.indexOf(obj))
                return true;

        return inherited(obj, sense, pov);
    }
;

house : Room 'Inside House'
    "This is the one room house (apparently with no door).
        The front yard lies to the south.  "
    vocabWords = 'inside/house'
    south = startRoom
    out asExit(south)

    // modifying RoomPartItem vocabulary so do not need disambiguation in house
    // only counts as 'wall' when outside!
    //
    travelerArriving(traveler, origin, connector, backConnector) {
        inherited(traveler, origin, connector, backConnector);
        if (traveler == gPlayerChar)
            cmdDict.removeWord(familyPic, 'wall', &noun);
    }
    travelerLeaving(traveler, dest, connector) {
        if (traveler == gPlayerChar)
            cmdDict.addWord(familyPic, 'wall', &noun);
        inherited(traveler, dest, connector);
    }
;
+pebble: Thing 'small round pebble' 'pebble' "A small, round pebble. "
    remoteDesc(pov) { "A small, round pebble, visible through doorway. "; }
;
// note that one 'trick' is not including *walls plural in the vocab, so doesn't get picked up
//
+familyPic : RoomPartItem, Decoration
    'old family (north) (n) wall/pic/photo/photograph/picture'
    'old family picture' "An old family picture hangs on the north wall. "
    specialNominalRoomPartLocation = defaultNorthWall
    specialDesc = "An old family photo hangs on the north wall.  "
;
gameMain:       GameMainDef initialPlayerChar = me;

It also kind of implies you’d want to add RoomPartItems for the other visible walls (say E and W), cause players gonna hunt. Though for me I’d probably use my customAllWalls in this situation. If I included ‘look at wall’ puzzles I guess I’d have to decide what is clumsier: unwanted scope messages or different >x wall behavior in puzzle area. The coding I don’t mind, particularly if restricted to the exceptional case.

This begs another thought: would I just modify Room globally with my genericAllWalls hack, use construct() to give each instance a generic RoomPartItem that I could modify in the rooms I cared about? I mean, that does sound like me…

Yeah, at this point I am happy with the AllWalls approach, but thanks!

1 Like

I always end up having to do deep modification to Room way more frequently than I would have expected.

Thing and Actor kinda make sense, because you’d expect that you’d have a lot of special behaviors on in-game objects and characters. But you end up having to do a lot of tinkering with Room if you’re not expecting to implement a traditional “passive” environment.

I think I’ve written four or five different subclasses of Room just to add a template that lets you add vocabWords via short form declaration.

1 Like

I could be about to put my foot way deep in my mouth here, but (being too lazy to test it this moment) isn’t construct mainly called with the use of new? Isn’t initializeThing what you’d be looking for, or a separate preinit routine? In any case, for my Walls class, it does all of its automatic roomParts twiddling in a my-game-specific preinit routine, after all the initializeThings are done…

1 Like

You are correct sir. I had been recently toying with construct() and had it on the brain.

1 Like