Up to Main Index Up to Journal for February, 2016 JOURNAL FOR FRIDAY 12TH FEBRUARY, 2016 ______________________________________________________________________________ SUBJECT: Details for latest public Git dev branch update DATE: Fri 12 Feb 22:25:37 GMT 2016 Just pushed some updates out to the public Git dev branch. This includes updating all of the commands to use the location Inventory stashed in the command processing state: // Instead of... if a := attr.FindLocate(s.actor); a != nil { where = a.Where() } what := where.Search(name) // We can use... what := s.where.Search(name) When processing commands we always find out where we are so we can lock the location. It therefore makes sense to cache this information in the state as most commands can make use of it. Another convenience / cleanup is the addition of the s.msg.observer message buffer. s.msg.observer is now aliased to s.msg.observers[s.where] - they both point to the same message buffer. This means, for the common case, sending messages to the actor, participant and observers is consistent: s.msg.actor.WriteString("You wave at Bob.") s.msg.participant.WriteString("Diddymus waves to you.") s.msg.observer.WriteString("Diddymus waves to Bob.") The only time you have to use s.msg.observers[where] is when you want to notify observers in a location other than to the actor's current location. Another silly example just to illustrate: to := exits.LeadsTo("south") s.msg.actor.WriteString("You roll a barrel through the south door.") s.msg.observer.WriteString("Diddymus rolls a barrel through the south door.") s.msg.observers[to].WriteString("A barrel rolls in through the north door.") For a real working example of multiple locations see the source for the MOVE command: cmd/move.go The command processing state has a new silent method. Its signature is: func (s *state) silent(actor, participant, observers bool, cmd func(*state)) This enables you to wrap any command method and control who receives messages. As an example, when using the LOOK command observers would see: You see Diddymus looking around. However the MOVE command uses the LOOK command to describe the location you enter. In this case observers would see: You see Diddymus enter. You see Diddymus looking around. You don't need to see the second message, which can get a bit annoying. By wrapping the call to Look with silence we can supress messages to participants and observers: // Instead of this... s.Look() // We can do this... s.silent(false, true, true, Look) The three boolean flags indicate who to silence: actor, participant and / or observers. Then you specify the command method. In the case above, the actor is not silenced but the participant and observers are - so only the actor will see the output of the LOOK command. All of the attributes have been updated as well. All attribute finders now return a typed nil instead of an untyped nil and all methods can handle a nil receiver. This has cleaned up a lot of the code implementing commands as we can now chain other methods to finders. Another fun example: // Instead of... who := "Someone" if a := attr.FindName(s.actor); a != nil { who = a.Name() } // We can now write... who := attr.FindName(s.actor).Name("someone") I picked that example to show another update: the Name method now takes a default / preset name. So if there is no name attribute available - or it has not been set - you can use a preset "someone", "something", "somewhere" as appropriate instead. The default name is called 'preset' rather than 'default' as default is a reserved keyword and cannot be used as a variable name: func (n *Name) Name(preset string) string Another use for the preset is that you can use the alias for something as the name until you can find out it's actual name. Example time again: // name starts as what the player typed, e.g. BALL name := s.word[0] // search for "BALL" what := attr.FindInventory(where).Search(name) // "BALL" found? if what == nil { // If not found we can display "You see no 'BALL' here." s.msg.actor.WriteJoin("You see no '", name, "' here.") return } // get actuall name of the "BALL" e.g. "A small rubber ball" name = attr.FindName(what).Name("something") // Display "You drop a small rubber ball." s.msg.actor.WriteJoin("You drop", name, ".") I think that's all of the changes covered with more on the way soon, I hope. -- Diddymus Up to Main Index Up to Journal for February, 2016