evennia.contrib.barter

Barter system

Evennia contribution - Griatch 2012

This implements a full barter system - a way for players to safely trade items between each other using code rather than simple free-form talking. The advantage of this is increased buy/sell safety but it also streamlines the process and makes it faster when doing many transactions (since goods are automatically exchanged once both agree).

This system is primarily intended for a barter economy, but can easily be used in a monetary economy as well – just let the “goods” on one side be coin objects (this is more flexible than a simple “buy” command since you can mix coins and goods in your trade).

In this module, a “barter” is generally referred to as a “trade”.

  • Trade example

A trade (barter) action works like this: A and B are the parties.

  1. opening a trade

A: trade B: Hi, I have a nice extra sword. You wanna trade? B sees: A says: “Hi, I have a nice extra sword. You wanna trade?”

A wants to trade with you. Enter ‘trade A <emote>’ to accept.

B: trade A: Hm, I could use a good sword … A sees: B says: “Hm, I could use a good sword …

B accepts the trade. Use ‘trade help’ for aid.

B sees: You are now trading with A. Use ‘trade help’ for aid.

  1. negotiating

A: offer sword: This is a nice sword. I would need some rations in trade. B sees: A says: “This is a nice sword. I would need some rations in trade.”

[A offers Sword of might.]

B evaluate sword B sees: <Sword’s description and possibly stats> B: offer ration: This is a prime ration. A sees: B says: “This is a prime ration.”

[B offers iron ration]

A: say Hey, this is a nice sword, I need something more for it. B sees: A says: “Hey this is a nice sword, I need something more for it.” B: offer sword,apple: Alright. I will also include a magic apple. That’s my last offer. A sees: B says: “Alright, I will also include a magic apple. That’s my last offer.”

[B offers iron ration and magic apple]

A accept: You are killing me here, but alright. B sees: A says: “You are killing me here, but alright.”

[A accepts your offer. You must now also accept.]

B accept: Good, nice making business with you.

You accept the deal. Deal is made and goods changed hands.

A sees: B says: “Good, nice making business with you.”

B accepts the deal. Deal is made and goods changed hands.

At this point the trading system is exited and the negotiated items are automatically exchanged between the parties. In this example B was the only one changing their offer, but also A could have changed their offer until the two parties found something they could agree on. The emotes are optional but useful for RP-heavy worlds.

  • Technical info

The trade is implemented by use of a TradeHandler. This object is a common place for storing the current status of negotiations. It is created on the object initiating the trade, and also stored on the other party once that party agrees to trade. The trade request times out after a certain time - this is handled by a Script. Once trade starts, the CmdsetTrade cmdset is initiated on both parties along with the commands relevant for the trading.

  • Ideas for NPC bartering:

This module is primarily intended for trade between two players. But it can also in principle be used for a player negotiating with an AI-controlled NPC. If the NPC uses normal commands they can use it directly – but more efficient is to have the NPC object send its replies directly through the tradehandler to the player. One may want to add some functionality to the decline command, so players can decline specific objects in the NPC offer (decline <object>) and allow the AI to maybe offer something else and make it into a proper barter. Along with an AI that “needs” things or has some sort of personality in the trading, this can make bartering with NPCs at least moderately more interesting than just plain ‘buy’.

  • Installation:

Just import the CmdTrade command into (for example) the default cmdset. This will make the trade (or barter) command available in-game.

class evennia.contrib.barter.TradeTimeout(*args, **kwargs)[source]

Bases: evennia.scripts.scripts.DefaultScript

This times out the trade request, in case player B did not reply in time.

at_script_creation()[source]

Called when script is first created

at_repeat()[source]

called once

is_valid()[source]

Only valid if the trade has not yet started

exception DoesNotExist

Bases: evennia.scripts.scripts.DefaultScript.DoesNotExist

exception MultipleObjectsReturned

Bases: evennia.scripts.scripts.DefaultScript.MultipleObjectsReturned

path = 'evennia.contrib.barter.TradeTimeout'
typename = 'TradeTimeout'
class evennia.contrib.barter.TradeHandler(part_a, part_b)[source]

Bases: object

Objects of this class handles the ongoing trade, notably storing the current offers from each side and wether both have accepted or not.

__init__(part_a, part_b)[source]

Initializes the trade. This is called when part A tries to initiate a trade with part B. The trade will not start until part B repeats this command (B will then call the self.join() command)

Parameters
  • part_a (object) – The party trying to start barter.

  • part_b (object) – The party asked to barter.

Notes

We also store the back-reference from the respective party to this object.

msg_other(sender, string)[source]

Relay a message to the other party without needing to know which party that is. This allows the calling command to not have to worry about which party they are in the handler.

Parameters
  • sender (object) – One of A or B. The method will figure out the other party to send to.

  • string (str) – Text to send.

get_other(party)[source]

Returns the other party of the trade

Parameters

party (object) – One of the parties of the negotiation

Returns

party_other (object) – The other party, not the first party.

join(part_b)[source]

This is used once B decides to join the trade

Parameters

part_b (object) – The party accepting the barter.

unjoin(part_b)[source]

This is used if B decides not to join the trade.

Parameters

part_b (object) – The party leaving the barter.

offer(party, *args)[source]

Change the current standing offer. We leave it up to the command to do the actual checks that the offer consists of real, valid, objects.

Parameters
  • party (object) – Who is making the offer

  • args (objects or str) – Offerings.

list()[source]

List current offers.

Returns

offers (tuple) – A tuple with two lists, (A_offers, B_offers).

search(offername)[source]

Search current offers.

Parameters

offername (str or int) – Object to search for, or its index in the list of offered items.

Returns

offer (object) – An object on offer, based on the search criterion.

accept(party)[source]

Accept the current offer.

Parameters

party (object) – The party accepting the deal.

Returns

result (object)

True if this closes the deal, False

otherwise

Notes

This will only close the deal if both parties have accepted independently. This is done by calling the finish() method.

decline(party)[source]

Decline the offer (or change one’s mind).

Parameters

party (object) – Party declining the deal.

Returns

did_decline (bool)

True if there was really an

accepted status to change, False otherwise.

Notes

If previously having used the accept command, this function will only work as long as the other party has not yet accepted.

finish(force=False)[source]

Conclude trade - move all offers and clean up

Parameters

force (bool, optional) – Force cleanup regardless of if the trade was accepted or not (if not, no goods will change hands but trading will stop anyway)

Returns

result (bool) – If the finish was successful.

class evennia.contrib.barter.CmdTradeBase(**kwargs)[source]

Bases: evennia.commands.command.Command

Base command for Trade commands to inherit from. Implements the custom parsing.

parse()[source]

Parse the relevant parts and make it easily available to the command

aliases = []
help_category = 'general'
key = 'command'
lock_storage = 'cmd:all();'
search_index_entry = {'aliases': '', 'category': 'general', 'key': 'command', 'tags': '', 'text': '\n Base command for Trade commands to inherit from. Implements the\n custom parsing.\n '}
class evennia.contrib.barter.CmdTradeHelp(**kwargs)[source]

Bases: evennia.contrib.barter.CmdTradeBase

help command for the trade system.

Usage:

trade help

Displays help for the trade commands.

key = 'trade help'
locks = 'cmd:all()'
help_category = 'trade'
func()[source]

Show the help

aliases = []
lock_storage = 'cmd:all()'
search_index_entry = {'aliases': '', 'category': 'trade', 'key': 'trade help', 'tags': '', 'text': '\n help command for the trade system.\n\n Usage:\n trade help\n\n Displays help for the trade commands.\n '}
class evennia.contrib.barter.CmdOffer(**kwargs)[source]

Bases: evennia.contrib.barter.CmdTradeBase

offer one or more items in trade.

Usage:

offer <object> [, object2, …][:emote]

Offer objects in trade. This will replace the currently standing offer.

key = 'offer'
locks = 'cmd:all()'
help_category = 'trading'
func()[source]

implement the offer

aliases = []
lock_storage = 'cmd:all()'
search_index_entry = {'aliases': '', 'category': 'trading', 'key': 'offer', 'tags': '', 'text': '\n offer one or more items in trade.\n\n Usage:\n offer <object> [, object2, ...][:emote]\n\n Offer objects in trade. This will replace the currently\n standing offer.\n '}
class evennia.contrib.barter.CmdAccept(**kwargs)[source]

Bases: evennia.contrib.barter.CmdTradeBase

accept the standing offer

Usage:

accept [:emote] agreee [:emote]

This will accept the current offer. The other party must also accept for the deal to go through. You can use the ‘decline’ command to change your mind as long as the other party has not yet accepted. You can inspect the current offer using the ‘offers’ command.

key = 'accept'
aliases = ['agree']
locks = 'cmd:all()'
help_category = 'trading'
func()[source]

accept the offer

lock_storage = 'cmd:all()'
search_index_entry = {'aliases': 'agree', 'category': 'trading', 'key': 'accept', 'tags': '', 'text': "\n accept the standing offer\n\n Usage:\n accept [:emote]\n agreee [:emote]\n\n This will accept the current offer. The other party must also accept\n for the deal to go through. You can use the 'decline' command to change\n your mind as long as the other party has not yet accepted. You can inspect\n the current offer using the 'offers' command.\n "}
class evennia.contrib.barter.CmdDecline(**kwargs)[source]

Bases: evennia.contrib.barter.CmdTradeBase

decline the standing offer

Usage:

decline [:emote]

This will decline a previously ‘accept’ed offer (so this allows you to change your mind). You can only use this as long as the other party has not yet accepted the deal. Also, changing the offer will automatically decline the old offer.

key = 'decline'
locks = 'cmd:all()'
help_category = 'trading'
func()[source]

decline the offer

aliases = []
lock_storage = 'cmd:all()'
search_index_entry = {'aliases': '', 'category': 'trading', 'key': 'decline', 'tags': '', 'text': "\n decline the standing offer\n\n Usage:\n decline [:emote]\n\n This will decline a previously 'accept'ed offer (so this allows you to\n change your mind). You can only use this as long as the other party\n has not yet accepted the deal. Also, changing the offer will automatically\n decline the old offer.\n "}
class evennia.contrib.barter.CmdEvaluate(**kwargs)[source]

Bases: evennia.contrib.barter.CmdTradeBase

evaluate objects on offer

Usage:

evaluate <offered object>

This allows you to examine any object currently on offer, to determine if it’s worth your while.

key = 'evaluate'
aliases = ['eval']
locks = 'cmd:all()'
help_category = 'trading'
func()[source]

evaluate an object

lock_storage = 'cmd:all()'
search_index_entry = {'aliases': 'eval', 'category': 'trading', 'key': 'evaluate', 'tags': '', 'text': "\n evaluate objects on offer\n\n Usage:\n evaluate <offered object>\n\n This allows you to examine any object currently on offer, to\n determine if it's worth your while.\n "}
class evennia.contrib.barter.CmdStatus(**kwargs)[source]

Bases: evennia.contrib.barter.CmdTradeBase

show a list of the current deal

Usage:

status deal offers

Shows the currently suggested offers on each sides of the deal. To accept the current deal, use the ‘accept’ command. Use ‘offer’ to change your deal. You might also want to use ‘say’, ‘emote’ etc to try to influence the other part in the deal.

key = 'status'
aliases = ['offers', 'deal']
locks = 'cmd:all()'
help_category = 'trading'
func()[source]

Show the current deal

lock_storage = 'cmd:all()'
search_index_entry = {'aliases': 'offers deal', 'category': 'trading', 'key': 'status', 'tags': '', 'text': "\n show a list of the current deal\n\n Usage:\n status\n deal\n offers\n\n Shows the currently suggested offers on each sides of the deal. To\n accept the current deal, use the 'accept' command. Use 'offer' to\n change your deal. You might also want to use 'say', 'emote' etc to\n try to influence the other part in the deal.\n "}
class evennia.contrib.barter.CmdFinish(**kwargs)[source]

Bases: evennia.contrib.barter.CmdTradeBase

end the trade prematurely

Usage:

end trade [:say] finish trade [:say]

This ends the trade prematurely. No trade will take place.

key = 'end trade'
aliases = ['finish trade']
locks = 'cmd:all()'
help_category = 'trading'
func()[source]

end trade

lock_storage = 'cmd:all()'
search_index_entry = {'aliases': 'finish trade', 'category': 'trading', 'key': 'end trade', 'tags': '', 'text': '\n end the trade prematurely\n\n Usage:\n end trade [:say]\n finish trade [:say]\n\n This ends the trade prematurely. No trade will take place.\n\n '}
class evennia.contrib.barter.CmdsetTrade(cmdsetobj=None, key=None)[source]

Bases: evennia.commands.cmdset.CmdSet

This cmdset is added when trade is initated. It is handled by the trade event handler.

key = 'cmdset_trade'
at_cmdset_creation()[source]

Called when cmdset is created

path = 'evennia.contrib.barter.CmdsetTrade'
class evennia.contrib.barter.CmdTrade(**kwargs)[source]

Bases: evennia.commands.command.Command

Initiate trade with another party

Usage:

trade <other party> [:say] trade <other party> accept [:say] trade <other party> decline [:say]

Initiate trade with another party. The other party needs to repeat this command with trade accept/decline within a minute in order to properly initiate the trade action. You can use the decline option yourself if you want to retract an already suggested trade. The optional say part works like the say command and allows you to add info to your choice.

key = 'trade'
aliases = ['barter']
locks = 'cmd:all()'
help_category = 'general'
func()[source]

Initiate trade

lock_storage = 'cmd:all()'
search_index_entry = {'aliases': 'barter', 'category': 'general', 'key': 'trade', 'tags': '', 'text': '\n Initiate trade with another party\n\n Usage:\n trade <other party> [:say]\n trade <other party> accept [:say]\n trade <other party> decline [:say]\n\n Initiate trade with another party. The other party needs to repeat\n this command with trade accept/decline within a minute in order to\n properly initiate the trade action. You can use the decline option\n yourself if you want to retract an already suggested trade. The\n optional say part works like the say command and allows you to add\n info to your choice.\n '}