Specification for Agora Market
Mission statement and use case:
Agora Market is a great achievement in 1603. It allows real-time entering of buy and sell offers for all the game items and lots, for the user-defined product, quantity and price. The orders stay in the system until canceled or executed. Matching orders are executed automatically and the items and moneretos change owner as a result.
Things to be handled:
- Items and Lots. Items are referred to with their unique Item_id, and Lots with their Lot_id (old version).
The DB needs to enforce that the Item_id and Lot_id's remain unique, by disallowing a new Item_id or Lot_id to be generated by any means, if it conflicts with the existing id.- All Items can be traded, except ones that have Untradable=1 in the ITEMS.
("M" are not tradable due to being the currency to be traded with; "CUL" is forbidden to trade, and some immovable objects properly change owner with the Lot only.)- Gold, silver and stone are not tradable as such. They are embedded in the items that can be traded (STO1...STO9 are items that all include 1 stone, so can be thought as "stone in Borough #"). Gold objects are always trading with their gold value included. Therefore, a 1,500 CKG bowl that could have cost 15 mil (p.o.) a while ago, would now be 1,115 mil (15 mil item premium on top of 1,100 mil worth of gold).
- There is a command line for quick and accurate entering of buy and sell commands. It is a text box that can also be used to copy-paste the commands in text lines format in bulk. If such a batch is entered, it evaluates from the first line, one by one.
- The syntax for entering buy and sell offers and other commands is as follows (item_id means both item_id and lot_id, as they share the idspace; in GIVE, the recipient may be either specified by his shortname (max 12 alphanumerics, case matters) or char_id (a number of max a few digits) - these also have a common idspace):
BUY item_id max_quantity (max_price)
SELL item_id max_quantity (min_price)
GIVE item_id quantity recipient [char_id OR short_name]
CONSUME item_id quantity
TRANSFER item_id quantity giver recipient
Examples of the commands and their parsing:
BUY 1-C-K 1 10000000000 An offer to buy the Lot 1-C-K (Royal Palace) for 10,000 million
SELL W1601B 2200 44000 An offer to sell W1601B (Friar Maximus Barley Wine) up to 2,200 bottles for 44,000 m a piece
GIVE IC1602 10 31 A command to give 10*IC1602 (IC point of the year) to HH of North Face. Same could be accomplished by:
GIVE IC1602 10 djjacket)
CONSUME MEAD 168 A command to take 168*MEAD (168 liters of mead) from your inventory and add to your health. Anything can be consumed, but not all is healthy.
TRANSFER TS136 1 4 cryptonic Admin-only command to take 1*TS136 Trade Silver Coin from the Town and give it to cryptonic.
- Using these commands, the command line, the batch command functionality, and the trading API (defined as a means for a character to authorize a software to type to the command line), most of the game's internal needs can be satisfied in this one subsystem. Character #5 "New" is the place where the system can create new things from - it is the only item owner whose balance is negative in all he owns
Script spex when a command is entered
BUY item_id max_quantity max_price
The command enters a new BID to the trading system for the
max_quantity units of
item_id, at
max_price. The price is expressed in moneretos.
if item_id is not a current item_id or lot_id, print "No such item or lot exists." and abort
if max_quantity is not a positive integer, print "Quantity must be a positive integer." and abort
if max_price is not a positive integer, print "Price must be a positive integer." and abort
if (max_quantity * max_price) < (amount of m the character owns), print "Not enough money to place a bid." and abort
quantity_remaining = max_quantity
repeat
if max_price >= min_price in lowest_ask_for_item_id, call MATCHBID char_id item_id quantity_remaining max_price char_id1 item_id1 max_quantity1 min_price
, this returns new quantity_remaining. The parameters char_id1 item_id1 max_quantity1 min_price come from lowest_ask_for_item_id if max_price < lowest_ask_for_item_id, abort loop and move on (to 30)
if quantity_remaining = 0, abort
(30) newBID char_id item_id quantity_remaining max_price , where char_id = active_character_id
print "New bid added for quantity_remaining units of item_id at a limit price of max_price."
NOTE: since an earlier revision, max_price is a mandatory parameter.SELL item_id max_quantity min_price
The command enters a new ASK to the trading system for the
max_quantity units of
item_id, at
max_price. The price is expressed in moneretos.
if item_id is not a current item_id or lot_id, print "No such item or lot exists." and abort
if max_quantity is not a positive integer, print "Quantity must be a positive integer." and abort
if active_character does not have at least max_quantity units of item_id, print "You do not have item_id (or sufficient quantity of it)." and abort
if min_price is not a positive integer, print "Price must be a positive integer." and abort
quantity_remaining = max_quantity
repeat
if min_price <= max_price in highest_bid_for_item_id, call MATCHASK char_id item_id quantity_remaining min_price char_id1 item_id1 max_quantity1 max_price
, this returns new quantity_remaining. The parameters char_id1 item_id1 max_quantity1 max_price come from highest_bid_for_item_id if min_price > highest_bid_for_item_id, abort loop and move on (to 30)
if quantity_remaining = 0, abort
(30) newASK char_id item_id quantity_remaining min_price , where char_id = active_character_id
print "New ask added for quantity_remaining units of item_id at a limit price of min_price."
NOTE: since an earlier revision, min_price is a mandatory parameter.GIVE item_id quantity recipient
The command transfers the ownership of
quantity units of
item_id from active_character to
recipient. Recipient can be expressed as char_id or char_shortname.
if item_id is not a current item_id or lot_id, print "No such item or lot exists." and abort
if quantity is not a positive integer, print "Quantity must be a positive integer." and abort
if recipient is not found from char_id and char_shortname tables, print "No such recipient." and abort
if active_character does not have at least quantity units of item_id, print "You do not have item_id (or sufficient quantity of it)." and abort
remove quantity units of item_id from active_character and add quantity units of item_id to recipient
print "quantity units of item_id given to recipient."
CONSUME item_id quantity
The command consumes quantity units of item_id. It is intended for consumption for sustenance (at present: drinks) but it can be used to consume all items to get rid of them.
if item_id is not a current item_id, print "No such item exists." and abort
if quantity is not a positive integer, print "Quantity must be a positive integer." and abort
if active_character does not have at least quantity units of item_id, print "You do not have item_id (or sufficient quantity of it)." and abort
remove quantity units of item_id from active_character
print "quantity units of item_id consumed"
call HEALTH_CHALLENGE_EVALUATOR char_id item_id quantity
NOTE: lots cannot be destroyed, or, hence, consumed.TRANSFER item_id quantity giver recipient
The command transfers the ownership of
quantity units of
item_id from
giver to
recipient. Giver and Recipient can be expressed as char_id or char_shortname.
if item_id is not a current item_id or lot_id, print "No such item or lot exists." and abort
if quantity is not a positive integer, print "Quantity must be a positive integer." and abort
if giver is not found from char_id and char_shortname tables, print "No such giver." and abort
if recipient is not found from char_id and char_shortname tables, print "No such recipient." and abort
if giver does not have at least quantity units of item_id, print "giver does not have item_id (or sufficient quantity of it)." and abort
remove quantity units of item_id from giver and add quantity units of item_id to recipient
print "quantity units of item_id given from giver to recipient."
NOTE: Admin only.CANCELASK item_id max_quantity min_price
if in Ask table, there is no order active_character item_id max_quantity min_price, print "You do not have such an order active." and abort
remove order from Ask table: char_id item_id max_quantity min_price , where char_id = active_character_id
print "Order removed."
CANCELBID item_id max_quantity max_price
if in Bid table, there is no order active_character item_id max_quantity max_price, print "You do not have such an order active." and abort
remove order from Ask table: char_id item_id max_quantity max_price , where char_id = active_character_id
print "Order removed."
MOVE source_borough_id destination_borough_id amount
This command is used for changing the location of stone, which technically removes STOx items and creates STOy items, against a cost.
if source_borough_id is not a valid borough_id, print "No such source borough." and abort
if destination_borough_id is not a valid borough_id, print "No such destination borough." and abort
if active_character does not have at least amount units of concatenate("STO";source_borough_id) item, print "Not enough stone in borough source_borough_id." and abort
cost = lookup stone_transport_cost_table for concatenate(source_borough_id;"-";destination_borough_id)
if cost * amount > character has money, print "Not enough funds for operation." and abort
remove amount units of concatenate("STO";source_borough_id) from active_character and add amount units of concatenate("STO";destination_borough_id) to active_character.
remove amount * cost of M from active_character and add amount * cost of M to char_id=37
print "amount stone moved from borough source_borough_id to borough destination_borough_id."
Ask and Bid table datatype
Ask table: char_id item_id max_quantity min_price
Bid table: char_id item_id max_quantity max_price
Separately are kept:
lowest_ask_for_item_id: char_id item_id max_quantity min_price
highest_bid_for_item_id: char_id item_id max_quantity max_price
NOTE: In Ask and Bid tables, all orders submitted are kept perpetually until canceled. In lowest_ask_for_item_id and highest_bid_for_item_id, only one instance of data is kept for each item_id (if any). This is used to display the ASK and BID columns in Items listings and used in evaluating the MATCHBID/MATCHASK.Routines, cannot be commanded
MATCHBID char_id item_id quantity_remaining max_price char_id1 item_id1 max_quantity1 min_price
The routine matches the recently entered bid which the BUY evaluation procedure has deemed needs to be executed.
quantity_traded = min(quantity_remaining;max_quantity1)
remove quantity_traded units of item_id from char_id1 and add quantity_traded units of item_id to char_id
remove quantity_traded * min_price units of M from char_id and add quantity_traded * min_price units of M to char_id1
print "Bought quantity_traded units of item_id at min_price m/unit, for a total of quantity_traded * min_price m."
quantity_remaining -= quantity_traded
// reduce quantity_remaining by quantity_tradedif quantity_traded = quantity1; set new lowest_ask_for_item_id
// put the new best ask to the lowest_ask_for_item_id (first lower price, if same, earlier order timestamp)return quantity_remaining
MATCHASK char_id item_id quantity_remaining min_price char_id1 item_id1 max_quantity1 max_price
The routine matches the recently entered ask which the SELL evaluation procedure has deemed needs to be executed.
quantity_traded = min(quantity_remaining;max_quantity1)
remove quantity_traded units of item_id from char_id and add quantity_traded units of item_id to char_id1
remove quantity_traded * max_price units of M from char_id1 and add quantity_traded * max_price units of M to char_id
print "Sold quantity_traded units of item_id at max_price m/unit, for a total of quantity_traded * max_price m."
quantity_remaining -= quantity_traded
// reduce quantity_remaining by quantity_tradedif quantity_traded = quantity1; set new highest_bid_for_item_id
// put the new best bid to the highest_bid_for_item_id (first higher price, if same, earlier order timestamp)return quantity_remaining
HEALTH_CHALLENGE_EVALUATORreturn