I've been fooling around with the MMG a bit recently. Due to pure RNG winnage, I'm actually substantially up, but I have no illusions about that being anything other than pure luck; there is no strategy which will guarantee winnings. All you can do is control your losses, and given bad enough RNG, you are not guaranteed to be able to do that; it's not written anywhere that you CAN'T lose 10 times (or 20 times - or 50 times) in a row.
It's piqued my interest in doing a couple things:
- Tracking all visits/transactions/events to try and maintain your meat totals in the session log. Note that your meat balance is updated every time we get a char pane refresh, so we're good with that, but it would be interesting to see your net winnings/losings correctly in the session tally, rather than only detecting meat coming in when you take and win bets and not detecting meat going out when you place bets or take and lose bets - and not detecting meat coming in when you offer and win bets.
- I could make a little "MMG toolbox", tied in with the above, to enable ASH scripting of MMG strategies. All of them doomed, of course, but still...
Most of this could be done in pure ASH scripting. However, maintaining the session tally, and interacting closely with events, whether they arrive in chat or via refreshing another page seems beyond ASH, so, some built-in support seems reasonable.
In any case, here's what I'm thinking. I am sure some of you have a lot more experience with the MMG than I have - or want to have. Tell me if I'm missing anything. Thanks!
---
Here's what I observe about KoL's UI for the MMG, and what KoLmafia would have to track whenever you visit an MMG page, either in the relay browser or via a KoLmafia request of some sort:
Data structures KoLmafia needs to maintain:
Map int [int] current;
- Your currently outstanding bets. maps from bet # -> amount
Map boolean [int] hagnks;
- true if bet used meat from Hagnk' storage
Map int [int] resolved;
- Your bets which have been taken but for which we have not received the notification.
Map int [int] events;
- Your bets which have been taken and for which we have received the notification, but for which you have not retrieved the event. If you are not running an MMG script, this could grow without bound...
Map int [int] offered
- Bets offered by others, last time the bet page was visited. maps from bet # -> amount
Map String [int] offerers;
= Who is offering a particular bet number. Not especially useful, unless you wish to ignore bets from certain people, for some reason.
Operations: things you can do from the Relay Browser which KoLmafia watches:
Visit Bets: When you visit the "bets" page
- Parses list of bets offered and replaces/refreshes two maps:
-- offered: bet # -> bet amount
-- offerers: bet # -> bet offerer
- Parses list of your current bets and makes a "temp" map of current bets: bet # -> amount
- Iterates over list of "current" bets
-- Move any bet which is not on "temp" to "resolved"
-- Move "temp" to "current"
Place Bet: When you place a bet for xxx meat
- Your bet is accepted and appears in the page text as bet # yyy on the list of "retract bet" buttons
- Your bet is rejected because you don't have the cash
- Your bet is rejected because you already have 5 bets out.
If bet was accepted, subtract xxx from meat tally (unless from Hagnks) and add to map of "current" bets: bet # -> amount
Retract Bet: When you retract a bet
- You successfully retract it
- It can't find the bet
If you retract it, remove the bet from "current" bets and add xxx to your meat tally (unless from Hagnks).
Take Bet: When you take a bet
- If you fail to take it (retracted or otherwise gone), do nothing
- Otherwise, add winnings or subtract losings to meat tally (unless from Hagnks)
MMG Event: When you receive an MMG "event"
- Remove bet from "resolved" or "current", as appropriate and add to "events"
- Add or subtract winnings/losings to meat
The tricky thing is figuring out which bet was taken; I don't think the chat message gives you the bet number, and people are not guaranteed to take the bets in the order you offered them. I certainly didn't, in my tests!
ASH interface:
void visit_bets();
(calls "Visit Bets" as above)
int place_bet( int amount, boolean hagnks );
(calls "Place Bet" as above)
- If successfully place the bet, return the bet #
- If fail (too many outstanding bets, not enough meat), return 0
boolean retract_bet( int xxx );
(calls "Retract Bet" as above)
- If successful, return true
- If bad bet number (possibly because bet is already taken), return false
int [int] current_bets();
This returns whatever "current" is - the outstanding bets you have offered; it does not call Visit Bets to find out what is currently out there
int current_bet_count();
This returns the number of bets in "current" - from 0 to 5. It does not call "Visit Bets" to see if any have been taken with no notification in yet (i.e., now on "resolved")
int [int] offered_bets();
- this returns whatever "offered" is; it does not call Visit Bets to find out what is currently out there
string bettor( int xxx );
- returns name of player who offered bet # xxx
int take_bet( int xxx )
(calls "Take Bet" as above)
- returns winnings or losings if successfully took the specified bet
- returns 0 if failed to take bet, because bet was not available or you didn't have enough money.
int wait_mmg_event()
- waits for the next MMG event and returns the bet number that is finally resolved.
- returns 0 if you have no outstanding bets, there is nothing on "resolved", and there is nothing on "events"
- otherwise, waits until something is added to "events" and pulls off the first one.
This is the only way something is removed from "events".
It's piqued my interest in doing a couple things:
- Tracking all visits/transactions/events to try and maintain your meat totals in the session log. Note that your meat balance is updated every time we get a char pane refresh, so we're good with that, but it would be interesting to see your net winnings/losings correctly in the session tally, rather than only detecting meat coming in when you take and win bets and not detecting meat going out when you place bets or take and lose bets - and not detecting meat coming in when you offer and win bets.
- I could make a little "MMG toolbox", tied in with the above, to enable ASH scripting of MMG strategies. All of them doomed, of course, but still...
Most of this could be done in pure ASH scripting. However, maintaining the session tally, and interacting closely with events, whether they arrive in chat or via refreshing another page seems beyond ASH, so, some built-in support seems reasonable.
In any case, here's what I'm thinking. I am sure some of you have a lot more experience with the MMG than I have - or want to have. Tell me if I'm missing anything. Thanks!
---
Here's what I observe about KoL's UI for the MMG, and what KoLmafia would have to track whenever you visit an MMG page, either in the relay browser or via a KoLmafia request of some sort:
Data structures KoLmafia needs to maintain:
Map int [int] current;
- Your currently outstanding bets. maps from bet # -> amount
Map boolean [int] hagnks;
- true if bet used meat from Hagnk' storage
Map int [int] resolved;
- Your bets which have been taken but for which we have not received the notification.
Map int [int] events;
- Your bets which have been taken and for which we have received the notification, but for which you have not retrieved the event. If you are not running an MMG script, this could grow without bound...
Map int [int] offered
- Bets offered by others, last time the bet page was visited. maps from bet # -> amount
Map String [int] offerers;
= Who is offering a particular bet number. Not especially useful, unless you wish to ignore bets from certain people, for some reason.
Operations: things you can do from the Relay Browser which KoLmafia watches:
Visit Bets: When you visit the "bets" page
- Parses list of bets offered and replaces/refreshes two maps:
-- offered: bet # -> bet amount
-- offerers: bet # -> bet offerer
- Parses list of your current bets and makes a "temp" map of current bets: bet # -> amount
- Iterates over list of "current" bets
-- Move any bet which is not on "temp" to "resolved"
-- Move "temp" to "current"
Place Bet: When you place a bet for xxx meat
- Your bet is accepted and appears in the page text as bet # yyy on the list of "retract bet" buttons
- Your bet is rejected because you don't have the cash
- Your bet is rejected because you already have 5 bets out.
If bet was accepted, subtract xxx from meat tally (unless from Hagnks) and add to map of "current" bets: bet # -> amount
Retract Bet: When you retract a bet
- You successfully retract it
- It can't find the bet
If you retract it, remove the bet from "current" bets and add xxx to your meat tally (unless from Hagnks).
Take Bet: When you take a bet
- If you fail to take it (retracted or otherwise gone), do nothing
- Otherwise, add winnings or subtract losings to meat tally (unless from Hagnks)
MMG Event: When you receive an MMG "event"
- Remove bet from "resolved" or "current", as appropriate and add to "events"
- Add or subtract winnings/losings to meat
The tricky thing is figuring out which bet was taken; I don't think the chat message gives you the bet number, and people are not guaranteed to take the bets in the order you offered them. I certainly didn't, in my tests!
ASH interface:
void visit_bets();
(calls "Visit Bets" as above)
int place_bet( int amount, boolean hagnks );
(calls "Place Bet" as above)
- If successfully place the bet, return the bet #
- If fail (too many outstanding bets, not enough meat), return 0
boolean retract_bet( int xxx );
(calls "Retract Bet" as above)
- If successful, return true
- If bad bet number (possibly because bet is already taken), return false
int [int] current_bets();
This returns whatever "current" is - the outstanding bets you have offered; it does not call Visit Bets to find out what is currently out there
int current_bet_count();
This returns the number of bets in "current" - from 0 to 5. It does not call "Visit Bets" to see if any have been taken with no notification in yet (i.e., now on "resolved")
int [int] offered_bets();
- this returns whatever "offered" is; it does not call Visit Bets to find out what is currently out there
string bettor( int xxx );
- returns name of player who offered bet # xxx
int take_bet( int xxx )
(calls "Take Bet" as above)
- returns winnings or losings if successfully took the specified bet
- returns 0 if failed to take bet, because bet was not available or you didn't have enough money.
int wait_mmg_event()
- waits for the next MMG event and returns the bet number that is finally resolved.
- returns 0 if you have no outstanding bets, there is nothing on "resolved", and there is nothing on "events"
- otherwise, waits until something is added to "events" and pulls off the first one.
This is the only way something is removed from "events".