Skip to content

fix(buyer): stop skip-starvation, add cap headroom, escalate own bids to buyout - #30

Merged
icemansparks merged 3 commits into
merkerhoodfrom
fix/buyer-starvation
Aug 12, 2026
Merged

fix(buyer): stop skip-starvation, add cap headroom, escalate own bids to buyout#30
icemansparks merged 3 commits into
merkerhoodfrom
fix/buyer-starvation

Conversation

@icemansparks

Copy link
Copy Markdown
Collaborator

Problem

Player auctions were never bought or only cycles later (#28). Verified live: the 5 lowest-ID player auctions were permanently above the bot's buy cap, and because skips consumed the 5-bids-per-15-min budget and the candidate set was scanned lowest-ID-first, buyable auctions further down the queue (e.g. Runed Copper Bracers at 21090 vs cap 21709) were never even evaluated. Two auctions the bot had bid on were frozen until expiry by the buyguid exclusion.

Changes (all in Buy())

  1. Starvation fix - candidates go into a shuffled vector instead of an ID-ordered set; skipped auctions no longer consume the BidsPerInterval budget, only successful bids/buyouts do. Each candidate is evaluated at most once per run.
  2. Cap headroom - when a price override exists, the max-buy cap gets at least 15% headroom above avgPrice. 64% of override rows currently have minPrice == avgPrice, which collapsed avg + (avg - min) to exactly avg while the seller lists at avg +-10%.
  3. Buyout escalation - the query no longer excludes auctions the bot already leads. It never re-bids (would outbid itself); it escalates to a buyout when the buyout still fits the cap, so sellers get paid promptly instead of waiting for expiry.

Notes

  • With multiple bot GUIDs configured, one bot char can buy out an auction another bot char leads (the previous bidder is refunded by mail). Single-GUID setups (like ours) are unaffected.
  • Worst case per run is now one pass over all non-bot-owned auctions instead of BidsPerInterval set pops; that's tens of rows on a bot-populated AH.

Verification

  • AuctionHouseBot.cpp.o compiles clean on testcore (GCC 12, -Werror).
  • Self-review pass: no blockers; opsDone increments exactly once per DB-writing operation, no self-outbid path, includes already present.

Closes #28

… to buyout

Three stacked causes kept player auctions from ever being bought:

- Candidates were scanned lowest-auction-ID-first and every skipped
  auction consumed the BidsPerInterval budget while re-entering the
  query each cycle, so a handful of permanently-overpriced auctions
  starved everything newer. Candidates are now shuffled and only
  successful operations (bid or buyout) consume the budget.

- Overrides with minPrice == avgPrice collapse the buy cap
  (avg + (avg - min)) to exactly avg while the seller lists at
  avg +-10%, making ordinary undercuts unbuyable. The cap now gets
  at least 15% headroom above avg whenever an override exists.

- Auctions the bot already led were excluded via buyguid, so a single
  bid froze them until expiry. They stay in the candidate set; the bot
  never outbids itself but escalates to a buyout when it fits the cap.

Closes #28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes buyer-side auction evaluation starvation and improves purchase behavior so player listings that are within cap are actually considered and bought promptly, addressing issue #28.

Changes:

  • Randomizes candidate auction evaluation order and ensures each candidate is evaluated at most once per run.
  • Makes skipped auctions not consume the per-interval bid/buyout budget (only successful bid/buyout operations increment the budget counter).
  • Keeps auctions the bot already leads in the candidate set and escalates to buyout (when within cap) instead of re-bidding or abandoning.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/AuctionHouseBot.cpp
Skips no longer consume the bid budget, so a skip-heavy cycle could
scan every candidate. Cap evaluations at 100x BidsPerInterval; the
shuffled order keeps the sample fair across cycles.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

Comment thread src/AuctionHouseBot.cpp
In account-only mode the config GUID list is empty, so JoinGUIDs
rendered an invalid NOT IN () clause and broke the buyer query.
Use the resolved bot character set and bail out when it is empty.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Suppressed comments (2)

src/AuctionHouseBot.cpp:649

  • Log message has an extra space before the comma ("Bought ,"), which makes log searching/aggregation less consistent.
                LOG_INFO("module", "AHBot [{}]: Bought , itemid={}, ah={}, item={}, start={}, current={}, buyout={}", _id, prototype->ItemId, AuctionHouseId(auction->GetHouseId()), auction->item_template, auction->startbid, currentPrice, auction->buyout);

src/AuctionHouseBot.cpp:273

  • Buy() silently returns when gBotsId is empty, which can make misconfiguration or init-order problems hard to diagnose at runtime. Consider logging (ideally once) before returning so operators can see why the buyer loop is doing nothing.
    if (gBotsId.empty())
    {
        return;
    }

@icemansparks
icemansparks merged commit 8141feb into merkerhood Aug 12, 2026
2 checks passed
@icemansparks
icemansparks deleted the fix/buyer-starvation branch August 12, 2026 22:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants