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/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
browser_client, a battle-scoped state store, a battle launcher, and shared
action/item/skill/buff collaborators. Callers that also need non-battle
hvbrowser operations use session.browser_client explicitly; this prevents
maintenance APIs from leaking into the battle-domain surface. The legacy
battle_dashboard name remains a compatibility alias for the state store.
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.
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. Classifier screenshots are temporary and removed
after every attempt. Failure artifacts are retained only when
ponychart_diagnostic_directory is explicitly configured, and that directory
is bounded by ponychart_diagnostic_file_limit.
import asyncio
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:
async with BattleSession(headless=True) 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.
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
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hvbattle-0.2.5.tar.gz.
File metadata
- Download URL: hvbattle-0.2.5.tar.gz
- Upload date:
- Size: 55.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
94844880137cc50a2fcaabb2f96b1f98529147bf6f3c1c87fe2a292cf76a3c9e
|
|
| MD5 |
fecb3dfbf3c62ffdc965f3e99fa5d921
|
|
| BLAKE2b-256 |
a52ca91292faebbf7dbd754894641013604bbb9eff3c670181baee4b495a4576
|
Provenance
The following attestation bundles were made for hvbattle-0.2.5.tar.gz:
Publisher:
publish.yml on Kuan-Lun/hvbattle
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hvbattle-0.2.5.tar.gz -
Subject digest:
94844880137cc50a2fcaabb2f96b1f98529147bf6f3c1c87fe2a292cf76a3c9e - Sigstore transparency entry: 2330308798
- Sigstore integration time:
-
Permalink:
Kuan-Lun/hvbattle@17b7e70fcdc96a32275f9203b0194f113a5aaaef -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Kuan-Lun
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@17b7e70fcdc96a32275f9203b0194f113a5aaaef -
Trigger Event:
push
-
Statement type:
File details
Details for the file hvbattle-0.2.5-py3-none-any.whl.
File metadata
- Download URL: hvbattle-0.2.5-py3-none-any.whl
- Upload date:
- Size: 47.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d28ad964c4dfdb4d321816464c90c279f32849689becd2552769989d9b885e3
|
|
| MD5 |
3f8b1b0f430f949d3aa9782df9dccaf7
|
|
| BLAKE2b-256 |
ebbd8c3e1ed4ab16d0d619f596f4fa9ebb5ce41b7923cde5777cee338347c164
|
Provenance
The following attestation bundles were made for hvbattle-0.2.5-py3-none-any.whl:
Publisher:
publish.yml on Kuan-Lun/hvbattle
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hvbattle-0.2.5-py3-none-any.whl -
Subject digest:
9d28ad964c4dfdb4d321816464c90c279f32849689becd2552769989d9b885e3 - Sigstore transparency entry: 2330308842
- Sigstore integration time:
-
Permalink:
Kuan-Lun/hvbattle@17b7e70fcdc96a32275f9203b0194f113a5aaaef -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Kuan-Lun
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@17b7e70fcdc96a32275f9203b0194f113a5aaaef -
Trigger Event:
push
-
Statement type: