Skip to main content

HVBattle

HVBattle provides reusable HentaiVerse battle-domain APIs. It builds on hvbrowser for the authenticated Hentaiverse browser session and keeps the private command-line runner in a separate application workspace.

The package exposes a policy-neutral BattleSession, atomic battle actions, and a BattleRunner that runs exactly one already-active battle using a client-supplied BattleStrategy. It never repairs equipment, recovers stamina, or starts Arena, Ring of Blood, or GrindFest on its own. Campaign policy and post-battle work belong to the calling application.

BattleSession is a facade, not an HVDriver subclass. It composes an explicit HentaiVerseSession, a battle-scoped state store, a battle launcher, and shared action/item/skill/buff collaborators. The raw browser used by battle components is session.hentaiverse.browser; non-battle operations remain grouped under the other session.hentaiverse services instead of leaking into the battle-domain surface. The legacy battle_dashboard name remains a compatibility alias for the state store.

Version 0.2.7 restores the game's final completion acknowledgement as a runner-owned safety step. BattleRunner captures the immutable completion and round summary before clicking the exact finishbattle.png control at most once, revalidating that the selected control still belongs to the observed completion document first. It returns BattleCompleted only after a new, ready document on the same realm has no battle, finish, next-floor, or PonyChart controls. A click or navigation error is reconciled through read-only state probes and is never resent; missing positive exit evidence raises BattleInterruptedError.

Turn preparation uses BattleTurnState and BattleTurnPhase to distinguish an active turn, next-floor transition, PonyChart challenge, positive completion, and an absent battle page. BattleRunner consumes this typed state directly; the former sentinel-returning prepare_turn() remains only as a compatibility adapter.

Next-floor transition DOM is never accepted over a retained duplicate XHR receipt: a matching monitor must be either unsent with count zero or sent once with count one, even when the next round is already visible. If transition evidence remains unknown, recovery evidence freezes its XHR fields from that same retained monitor, so a duplicate cannot be hidden behind an unrelated count-one record.

An ambiguous turn or next-floor action is eligible for same-browser recovery only when immutable evidence binds the server-communication-failed dialog to that exact action token and the XHR is either the precise terminal status-zero error shape or has an incomplete zero/one-send receipt with null status and outcome. Recovery never replays the cached action. It accepts only a new, ready document on the expected persistent/Isekai realm after at least two stable state signatures. Complete and next-floor controls take priority over PonyChart; an active phase additionally needs its log/action-control markers and must parse with a live monster. The runner then returns to turn preparation and asks strategy for a fresh decision. A second ambiguity before a confirmed ACTED or next-floor receipt exhausts that browser's recovery budget. Only this typed exhaustion may open one fresh authenticated browser, whose own same-browser budget starts unused; it can never open a third browser. Final-completion acknowledgement ambiguity never enters that fresh-browser path.

A ZendriverOperationTimeout is not treated like an ordinary retryable TimeoutError, because its CDP command deliberately remains live. A live timeout while arming or cleaning an action monitor, or while parsing session state, interrupts and closes the current browser without retry. After a click, it leaves the post-click document unobservable, so that unknown action is not eligible for first-use recovery. If it occurs inside recovery after incident evidence was already established, the failed old-browser reconciliation is typed exhaustion and may use only the one fresh-browser stage described above.

BattleSession preloads the PonyChart classifier and ONNX model before opening the browser, so a timed challenge never pays the first-load cost. The runner checks for and resolves PonyChart before parsing an ordinary battle turn or calling client strategy code. Set ponychart_image_directory to retain the image captured for every detected challenge, including successful resolutions and failures. Each capture receives a collision-resistant pony_chart_*.png name, and callers own retention for that directory. Without an image directory, classifier screenshots remain temporary and are removed after each attempt.

import asyncio

from hvbrowser import HentaiVerseSession
from hvbattle import BattleCompleted, BattleRunner, BattleSession, TurnDecision


class MyStrategy:
    async def take_turn(self, session: BattleSession, /) -> TurnDecision:
        if await session.go_next_floor():
            return TurnDecision.ACTED
        if not session.alive_monster_ids:
            return TurnDecision.IDLE
        if await session.attack_monster(session.alive_monster_ids[0]):
            return TurnDecision.ACTED
        return TurnDecision.IDLE


async def after_battle(session: BattleSession, completed: BattleCompleted) -> None:
    print(completed)


async def main() -> None:
    hentaiverse = HentaiVerseSession(headless=True)
    async with BattleSession(
        hentaiverse=hentaiverse,
        ponychart_image_directory="pony_chart",
    ) as session:
        result = await BattleRunner(session, MyStrategy()).run_current()
        if isinstance(result, BattleCompleted):
            await after_battle(session, result)


asyncio.run(main())

The example requires credentials through the normal EH_USERNAME and EH_PASSWORD indirection and an already-active server battle; otherwise run_current() returns None. TurnDecision.STOP deliberately returns a BattleStopped result. Leaving the battle page without positive final-round completion evidence raises BattleInterruptedError, so callers cannot mistake an expired login or unexpected navigation for a completed battle.

BattleDriver is only a transitional name alias for BattleSession, not an API-compatible implementation of the old driver. Migrate constructor strategy settings into a BattleStrategy, replace driver.battle() with BattleRunner(driver, strategy).run_current(), and perform maintenance, post-battle tasks, and next-battle selection after the returned BattleCompleted. Arena choice follows the same boundary: list_arena_options() returns data and start_arena(option) starts only the option explicitly selected by the caller. goto_ring_of_blood() and inspect_ring_of_blood() expose the currently startable named challenges, EXP modifiers, entry costs, and live Tokens of Blood balance. start_ring_of_blood(option, expected_before=snapshot) revalidates the page and sanitized snapshot before submitting the existing form. It returns a typed submitted, insufficient-tokens, unavailable, or state-changed outcome; it never chooses a challenge or reads hidden form credentials for the caller. GrindFest uses the equivalent list_grindfest_options() and start_grindfest(option) pair; the package does not silently choose the first or last server option.

BaseControlPanel, ControlPanel, and NullControlPanel provide reusable pause, named-action, named-toggle, and validated integer mechanisms. The set_actions() API is the generic spelling; the older set_skills() spelling remains available as a compatibility alias. Integer edits become live only after Apply or Enter, so partially typed mutation amounts are never published. Closing the interactive window sets the pause flag before the GUI exits.

The package does not register campaign choices or choose their defaults: a calling application owns the control names, labels, initial values, and the policy that reads their committed state. Importing hvbattle does not import Tk or start a GUI process.

Development

The dependency-free Lean model in formal/ covers the safety-critical action and transition evidence predicates, the guarded same-browser recovery budget and no-replay boundary, the final-completion acknowledgement click bound, error-record ordering, and supervisor no-retry exit policy. Run it separately from the Python checks:

(cd formal && lake build)

This is a proved model of the observable decision boundary, not an automatic translation of the Python, browser, network, or log-sink implementations. The offline Python and shell tests cover those implementation boundaries.

Build a clean environment backed by PyPI releases:

bash scripts/rebuild-env.sh

For coordinated local development before all dependent releases are on PyPI, overlay editable checkouts in dependency order:

uv pip install --python .venv/bin/python --reinstall --no-deps --editable \
  /Users/kuanlun_wang/Desktop/git-repo/hbrowser.clone
uv pip install --python .venv/bin/python --reinstall --no-deps --editable \
  /Users/kuanlun_wang/Desktop/git-repo/hvbrowser.clone

Commands that must preserve these editable overlays use uv run --no-sync.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hvbattle-0.4.5.tar.gz (93.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hvbattle-0.4.5-py3-none-any.whl (67.1 kB view details)

Uploaded Python 3

File details

Details for the file hvbattle-0.4.5.tar.gz.

File metadata

  • Download URL: hvbattle-0.4.5.tar.gz
  • Upload date:
  • Size: 93.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for hvbattle-0.4.5.tar.gz
Algorithm Hash digest
SHA256 d147461c40640bbebdc34364fa585bd05d02fcea85a496e9cda5ad85a6220129
MD5 1cbc31afeef124dceefe3d0a47b6c209
BLAKE2b-256 2eff923ebf496e136122c01c4acef3c032ccf8764d9a64ccbcc5fd0f69eeb1e4

See more details on using hashes here.

Provenance

The following attestation bundles were made for hvbattle-0.4.5.tar.gz:

Publisher: publish.yml on Kuan-Lun/hvbattle

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hvbattle-0.4.5-py3-none-any.whl.

File metadata

  • Download URL: hvbattle-0.4.5-py3-none-any.whl
  • Upload date:
  • Size: 67.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for hvbattle-0.4.5-py3-none-any.whl
Algorithm Hash digest
SHA256 a94a001aee1ae432daed03c68a8edf3df3d90195b2d8196c7a3a9787d90dfd81
MD5 30cc5bbfcd11928364bd60fd1dd5f77e
BLAKE2b-256 08222ea6cf6c5be31db47fa75cc1ff1ffb05f194c88c3d8f58acc02868b0b1f6

See more details on using hashes here.

Provenance

The following attestation bundles were made for hvbattle-0.4.5-py3-none-any.whl:

Publisher: publish.yml on Kuan-Lun/hvbattle

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.15.0

2 files

0.14.3

2 files

0.14.2

2 files

0.14.1

2 files

0.13.1

2 files

0.13.0

2 files

0.12.2

2 files

0.11.6

2 files

0.11.5

2 files

0.11.4

2 files

0.11.3

2 files

0.11.0

2 files

0.10.3

2 files

0.10.2

2 files

0.10.1

2 files

0.9.0

2 files

0.8.1

2 files

0.8.0

2 files

0.7.0

2 files

0.6.0

2 files

0.5.0

2 files

0.4.39

2 files

0.4.38

2 files

0.4.37

2 files

0.4.36

2 files

0.4.35

2 files

0.4.34

2 files

0.4.33

2 files

0.4.32

2 files

0.4.31

2 files

0.4.30

2 files

0.4.29

2 files

0.4.28

2 files

0.4.27

2 files

0.4.25

2 files

0.4.24

2 files

0.4.23

2 files

0.4.22

2 files

0.4.21

2 files

0.4.20

2 files

0.4.19

2 files

0.4.18

2 files

0.4.16

2 files

0.4.15

2 files

0.4.14

2 files

0.4.12

2 files

0.4.11

2 files

0.4.10

2 files

0.4.9

2 files

0.4.8

2 files

0.4.7

2 files

This release

0.4.5 This release

2 files

0.4.4

2 files

0.4.3

2 files

0.4.2

2 files

0.4.1

2 files

0.4.0

2 files

0.3.6

2 files

0.3.5

2 files

0.3.4

2 files

0.3.3

2 files

0.3.1

2 files

0.3.0

2 files

0.2.9

2 files

0.2.8

2 files

0.2.7

2 files

0.2.6

2 files

0.2.5

2 files

0.2.4

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page