Up to Main Index Up to Journal for June, 2021 JOURNAL FOR SATURDAY 5TH JUNE, 2021 ______________________________________________________________________________ SUBJECT: I nearly have my world back DATE: Sat 5 Jun 19:15:52 BST 2021 The recent ‘code sprint’ has continued and I’ve been spending most of my spare time continuing to hack away on WolfMini. The above title is somewhat inaccurate. What I actually have are locations and things loading into WolfMini from the zinara.wrj zone file. Walking around the zone is very eerie, nothing is happening — no guards patrolling, the vendor not shouting, the tavern door not closing. Without any events being scheduled everything is frozen in time. The loader I’m using is one heck of a lash up. I’ve copied over the recordjar and text packages from WolfMUD proper. I also copied the zone preprocessor to handle the zone file @refs. I’ve then hacked up a quick loader which only understands a few basic attributes: name, description, narrative, location, inventory, exit and door. The loader can just about manage to resolve item references and cobble the zone together enough for me to go wandering around. Aliases are not handled properly yet, I’m still using a single alias parser. To open the tavern door I have to use "open +tavern” as aliases are defined in the zone file using a qualifier as “+TAVERN DOOR” and I only pick the first alias at the moment. Still, it’s progress… The loader is about 100 lines of code. It still needs to handle the remaining item attributes, multiple zones and a whole bunch of other stuff. To make writing the loader easier I slightly altered the new Thing, dropping the Thing.Name, Thing.Description and Thing.UID struct fields and making them Thing.As entries. Name is retrieved as Thing.As[Name] instead of Thing.Name for example. The UID is the familiar “#UID-xxx” as in WolfMUD. Having made everything an attribute, and not treating the UID, name and description as a special case, greatly simplified the loader. Due to that large refactoring, which I’d planned for, I still have tests to write. I have documented a lot of the code, just need the tests… I’ve still got a few ugly corners I need to poke. The main two being numeric attributes and keyed attributes. The current Thing is: type Thing struct { Is uint32 As map[uint32]string In []*Thing } I need a way to store numeric attributes and multi-value attributes. Numeric attributes I can probably handle with a map[uint32]int. Multi-value attributes can be handled as map[string][]string maybe? The multi-value is mostly for aliases and vetoes where I’d access them with something like item.Any["Alias"] and item.Any["VETO:GET"]. I’m a little unhappy about the composite key being ‘VETO:GET’, but the alternative is something like map[uint32][string][]string… My current Thing as of writing this is defined as: type ( isKey uint32 // index for Thing.Is asKey uint32 // index for Thing.As anyKey string // index for Thing.Any ) type Thing struct { Is isKey // Bit flags for item capability/state As map[asKey]string // Single value for an id Any map[anyKey][]string // Any value in a list for a key In []*Thing // Inventory for the item } All of the key values for Is, As and Any are defined as named constants. The keys for ‘Any’ can be mostly defined as constants, although I need to think more about the composite keys. The reason for defining all of the keys as constants is so that they are documented and values don’t get picked and used willy-nilly. I’m thinking that if an Any key has a colon ‘:’ suffix as in ‘Veto:’ it’s an indication that it’s a composite key. So ‘Veto:’ defined as the constant ‘Veto’ might be used as item.Any[Veto+"GET"] as in the example below. A key of ‘Alias’, on the other hand, defined as the constant Alias, would be used as item.Any[Alias]. Some other usage examples: if item.Is&Open == Open { ... } if item.As[Name] != "" { ... } if item.Any[Veto+"GET"] != nil { ... } for _, v := range item.Any[Alias] { ... } for _, item := range item.In { ... } One really nice Go feature is that zero values work really well here. I think the fields also make the code quite readable. I’m not sure who I’m trying to convince here — you, dear reader, or myself. It’s one of those situations where you have to try an approach and then iterate or start over until it feels right. When does it feel right? Hard to say, as a programmer you know, just like you know when it feels wrong ;) -- Diddymus Up to Main Index Up to Journal for June, 2021