pydarkstar
pydarkstar copied to clipboard
How to have items bought at a specific frequency?
Hey Adam,
First off, thanks for this. It plays a HUGE role in the XI Private Server space. I realize this isn't really an issue, but I was unsure where else to contact you. A few years ago I managed to get pydarkstar to require meeting conditions in order to buy on an item by item basis (not clearing everything listed in the AH at once), by using randint, giving a "percent chance" for purchasing individual items on every tick. This allowed the flow of the AH to seem more natural rather than just buying up everything 100% of the time. For the life of me, I can't figure out how I did it.
This might be a shot in the dark, but do you have any ideas?
I would search the code for the buy_item method (probably the calls in manager.py).
Before deciding to buy an item, generate a random number between 0 and 1 using the random.random() method from Python. If the random number is less than some threshold (for example 0.10) then the buy item would only be executed 10% of the time.
You will have to do some math to figure out the optimal rate of buying. Something along the lines of executing buy every 1 min, over 1000 for sale items in the auction house, at a rate of 0.1 then only 100 of the items would be purchased per min. That’s probably still too high to simulate reality.
you can also get really fancy and make the threshold a property of each item. You’d have to edit the items CSV and do a lot more coding to get something like that working.
If you get something working feel free to upload it and I’d merge it if it looks OK. I unfortunately don’t work much on on this project anymore but left it up so others could use it.
Much appreciated Adam, I'll try looking into this tomorrow and see if I can get it working.
Had a chance to sit down and tool around with it before bed. The current issue is that if the random number isn't successful for a sale, it triggers the "price too high" else, then immediately adds the row to blacklist. Not only that, but it still just buys everything listed instead of rolling on a per item basis if the random conditions are met. I'm at a loss for what I did to accomplish this last time. Sigh.
Hello @ghost, I added an experimental change in #28. It uses item.rate01
and item.rate12
columns of the CSV, along with a random number, to decide if or not to buy an item that tick of the buying loop.
As I have no way to test the functionality (I do not have dark star setup for quite some time)...
If you get a chance:
- Check out that branch (#28)
- Edit your items.CSV so that the buying rates are some number
>= 0.0
and<= 1.0
- Look at the log file and behavior of the buyer
Do would see logging output that indicates that items are sometimes not being purchased? Can you confirm that items are not being added to the blacklist?
Thanks for your help. If it is working and not breaking things I will merge that pull request.
FYI to check out the branch
git fetch
git checkout implement-buying-rate
It might complain that checking out the branch would overwrite your local changes, in which case it would be more complicated. You might try merging the branch into your local copy of master, but that also brings complicated when you want to undo the changes later. Let me know if you run into issues and need help.
Brilliant, I'll be giving this a try and I'll get back to you!
Adam, I find that the following works within the manager.py without having to edit the items.csv. I'm not really all that smart when it comes to python, but you should be able to add the number in the following portion if rand <= 10:
to a variable that can be changed and defined in the config.yaml? As defined, this should allow a 10% buy rate. Tested on local server and it does in fact seem to be the case, on a per item listing basis. First tick I sold 1, then 0, then 2, then 0, then 1, then 1.
# check permissions
if data.buy12:
# check price
if row.price <= data.price12:
rand = (random.randint(1,100))
if rand <= 10:
date = timeutils.timestamp(datetime.datetime.now())
self.buyer.buy_item(row, date, data.price12)
else:
self.info('price too high! itemid=%d %d <= %d',
row.itemid, row.price, data.price12)
self.add_to_blacklist(row.id)
else:
self.debug('not allowed to buy item! itemid=%d', row.itemid)
self.add_to_blacklist(row.id)
# buy singles
else:
# check permissions
if data.buy01:
# check price
if row.price <= data.price01:
rand = (random.randint(1,100))
if rand <= 10:
date = timeutils.timestamp(datetime.datetime.now())
self.buyer.buy_item(row, date, data.price01)
Could have the variable defined as 100 in the config.yaml by default, which would always be true given that it is <= any number 1-100. That would allow current behavior to continue as it has been, but then customization by lowering that number bit by bit. Oh, also I added import random
at the bottom of the import list at the top of the manager.py, right below import datetime
, though I'm not 100% sure whether that was required or not, just going off other examples I've seen.
@xMANAx
The code in #28 is more what we’d want for the following reasons:
-
random.randint
will not sample correctly for non-integer buying rates - using the columns in
items.csv
allows finer grained customization (different items, different rates)
We have a default buying rate of 100%
already hard coded for items. However, as you suggest , modifying the config.yaml
to specify the default rates when scrubbing makes sense. For example the same is done already for the default stocks:
# scrub
server: bahamut # FFXI server to query
threads: -1 # number of CPU threads
itemids: [] # list of itemids to scrub
stock01: 5 # default stock01 when scrubbing
stock12: 5 # default stock12 when scrubbing
urls: [] # list of category urls to scrub
@AdamGagorik I'm not sure when I'll get around to it, but I'll try my hand at setting up and testing your other method. As of now my previous post "works", so I'll need to set up a 2nd server to run testing on in case everything freaks out.
Ok I will leave this open until someone can test the implementation provided in #28.