In this second blog post I’m showing how I implemented objects - things the player can interact with - for a text adventure written in Rust. As usual, the full code is available on GitHub.
The unend engine defines a trait which anything which the player can interact with (objects at present time; people, animals etc in the future) must implement:
interact() method accepts an interaction as a parameter, and returns a result for that.
Among the “planned for the future” things, there’s method like this:
in order to allow interaction between objects, such as use ink with paper. It would also allow the give interaction (as in give book to Alice) to exist. This is, however, absolutely too advanced for current development status. 😆
InteractionRes are enums defined as follows:
The first object I wanted to implement was a very simple one, that would just show a text message for each interaction: a description if it’s looked at, a nice “no, thank you” message if the player attempted to take it, etc. So, leaving aside trait instantiation and other boilerplate, all the action happens in this code:
The implementation of
interact() method is just a few lines: the code looks into
HashMap (contained in the
InfoObject struct) to see if there is a result for the interaction
requested (we’ll see in a while how possible results are added when creating a new
if a match is found, we return an
Info value of the
InteractionRes enum, which contains a
simple string to show to the player; with no match, we return the same type, but with a default string.
Now to the main loop code:
The parser is just a regular expression at the moment. Once it matches the type of the target
(the enum in which it’s contained was previously looked up via the object’s tag), the main loop
interact() method, passing the (previously looked up)
We use match in order to unwrap the
InteractionRes enum: if the value is
Info we show the contained string to the player; other result values are not supported for this
specific kind of object, so a
panic!() is probably the best option (=forces somebody to debug
Now that we have all of this setup, it is possible to modify the code - shown in previous article - which was used to create the kitchen, so that is becomes:
The code should be self-explanatory enough. The only thing worth noting is that
InfoObject is wrapped
UnendObject::Info enum value: as we did for sections, this allows to have different object
Interagible) types inside the same containing
So, let’s see if this works somehow:
And now… a slightly different implementation: a
PortalObject, which we define as an object which
transports the player to another section of the game when used.
Skipping the struct constructor and other service code (which you can find the in the repository),
the interesting part comes (as before) with the
Only two interactions are supported by
PortalObject: the player can only look at it or use it.
Everything else shows a default string. Compared to
InfoObject, the difference here lies in how
Interaction::Use is handled, that is by returning an
a string with the tag of the destination section. The main loop code will therefore know how
to use that tag:
Dead easy: either show the description or change the section the player is in and skip to the next loop cycle. Now we only need to actually create the portal object and put it inside a section/room.
A fireplace which happens to be a portal… how interesting! The secretroom, defined elsewhere, is a section for which there is no access from any of the other sections; the secretroom itself, however, has an exit which brings the player back to the hallway.
That’s all! See you next time with something else. I’ll likely try to implement
inventory, and therefore objects which can be taken. This poses some challenges: as of now,
everything in the game has an immutable state; using mutable states, besides the programming aspects
(which may be non-trivial for a Rust newbie like me), will also likely lead to some changes in how
Visitables are structures: if an object is taken, it must disappear from the section, and the
section description (which is now a monolithic text block) should change. We’ll see…