Closed GoogleCodeExporter closed 9 years ago
This is an interesting MUD problem...
How do you handle the acceptance? Waiting for the user to respond would require
taking the user out of play state and into a special STATE_ACCEPT_GIVE. This
could
effectively disable the player's ability to interact with the world (and could
end up
being exploitable from a PVP combat perspective).
Did this feature exist in DR? How was it handled?
I could see queueing item transfers in the intended-receiving Player object,
then
adding an "accept" command that would target an exchange in the queue. The
queue
would be dumped after leaving the room, and queued exchanges would be
invalidated if
the offering player has left the room upon "accept"ing the item.
The above solution would be essentially asynchronous (and I can't see how async
wouldn't be the preferable universal solution in MUDs), and changing the state
would
be very close to synchronous (less error, more blockage).
Original comment by bmcca...@gmail.com
on 12 Aug 2008 at 12:08
Yep, you've pretty much got it. The give would set up a queue that would last
say, 30
seconds, in which the receiving player can use an ACCEPT command which would
then
allow the transfer. Note that the receiving player and the giving player must
be in
the same room at the time the command is ACCEPTed (I don't think that the queue
needs
to be dumped at a leave -- they can always come back, and if it has a timer,
then its
not a problem of someone's give queue being permanently disabled, as it will
cease to
exist as soon as it ends). You're right, it has to be asynchronous.
A player should only be able to be GIVEn one thing at a time, as this reduces
confusion on what exactly they're accepting.
I could also if the player has the ability to set a preference to always accept
items, but I don't think it should be on by default.
Original comment by meagains...@gmail.com
on 12 Aug 2008 at 12:27
This leads to the next question: Is there a mechanic for an 'ad-hoc' timer yet?
Tasks
seem suited for cases like checking for a certain status at a steady interval,
but it
doesn't seem like its the right structure for something like this. If another
structure is needed, I'm willing to create it, and own this issue.
Original comment by meagains...@gmail.com
on 12 Aug 2008 at 5:58
Revision 90's libsigma allows for ad hoc one-shot timers by inserting a task
with a
TTL of 1 (meaning one iteration before it's deleted from the task queue). The
rewrite of say(...) below has a nasty crash bug (with debug activated) if the
active
player leaves the room or game, but replacing the stock function with this
illustrates how the timer functionality would work with a more complete
function.
In this example, everyone in the speaker's room would hear two echoes, 10
seconds
apart from each other and from the original speaking.
@handler
def say(data):
speaker = data["speaker"]
tail = data["tail"]
report(SELF | ROOM, "$actor $verb, '" + tail + "'", speaker, ("say", "says"))
def echo(speaker):
return lambda: report(SELF | ROOM, "You hear an echo.", speaker)
insert_task("echo", echo(speaker), 10, 2)
Original comment by bmcca...@gmail.com
on 12 Aug 2008 at 4:02
Proposed solution:
. Implement a task for item acceptance management. This runs every 20 seconds.
. Add a dictionary object to the world module with the id(...) of the recipient
character object as the key and values being a tuple of the item to be
transferred,
the offering character, and the system time of the offer. The recipient gets a
message asking them to "accept" the item if they wish. The room hears a
report(...).
. When the task runs, iterating over each offer in the dictionary:
.. Offers more than 60 seconds old are terminated. Both sides are notified.
.. Offers older than 40 seconds give a strong warning to the recipient.
.. Offers older than 20 seconds give a weak warning to the recipient.
. The "give" handler checks that a recipient doesn't already have an
outstanding
offer before queuing a new one. This is easy because the recipient object is
keyed
to the dictionary. No report(...) to the room for a failure, but messages are
sent
to the two active characters in the proposed transaction.
. The "accept" and "refuse" functions dequeue the offer (removing the key from
the
dictionary). If the item is accepted, both characters must still be in the
same
room, the offering character must still have the specific item offered, and the
recipient must have enough inventory room to accept. If so, the transfer is
made
with a report(...) to the room.
. Outright refusals are noted in a room report(...), but implicit (60 second
timeout) refusals are not.
Original comment by bmcca...@gmail.com
on 17 Mar 2009 at 8:54
Fixed in r129. Privacy is not addressed significantly, so there is room for
future
improvement.
Original comment by bmcca...@gmail.com
on 9 Jan 2010 at 7:22
I'd definitely advice against using timers for this. Not only it makes code
more complex but I also find
the resulting functionality unrealistic.
Here's my suggestion:
1) a reference to an offered item is kept in a 'offered_items' table, together
with a reference of the
recipient.
2) as long as the item is listed in this dict, it is susceptible to a 'take'
command from the recipient
3) if the giver uses the item or stores it (say, put in a bag), the item is
cleared from the
'offered_items' dict.
4) If the giver moves, the 'offered_items' dict is emptied.
Original comment by hello.ja...@gmail.com
on 5 Feb 2010 at 5:38
Already implemented using the task framework. This implementation is superior
to the
suggested because of the following:
- Creates an automatic sunset for any offer.
- Allows giving while en-route (will be important once grouping mechanics are
implemented)
- Does not overload what will be a 'popular' verb in 'take' (the proposed
suggestion
would make 'take' have to access another collection, which would make a
requirement
to implement a 'from X' implementation on the verb. We may already need to do
this
for allowing taking from freestanding containers, throwing people in the mix
makes
this more difficult)
There is room for improvement, but for 1.0, the current implementation is
sufficient.
Original comment by meagains...@gmail.com
on 16 Feb 2010 at 7:25
Original issue reported on code.google.com by
meagains...@gmail.com
on 11 Aug 2008 at 4:40