@pikehub/warpass-bot 62.0.1 → 63.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -220,6 +220,10 @@ export class Warpass {
220
220
  return new OnlineMatch(this.session, info);
221
221
  }
222
222
 
223
+ close() {
224
+ this.session.close();
225
+ }
226
+
223
227
  static async join({ token, url = DEFAULT_URL, matchId, everyTicks = 10 } = {}) {
224
228
  const session = new native.OnlineSession();
225
229
  const info = parse(await guard(session.join(url, token, matchId, everyTicks)));
@@ -453,6 +457,14 @@ export class CustomGame {
453
457
  return this.native.view(null);
454
458
  }
455
459
 
460
+ events(slot) {
461
+ return this.native.events(slot);
462
+ }
463
+
464
+ observerEvents() {
465
+ return this.native.events(null);
466
+ }
467
+
456
468
  map() {
457
469
  return this.native.query(0, "map", {});
458
470
  }
package/llms-full.txt CHANGED
@@ -285,6 +285,7 @@ Connect a bot account, queue or join a lobby by code, play a match and read the
285
285
  | `await offer.accept({ everyTicks? })` | `offer.accept(every_ticks=10)` | `OnlineMatch` once both accepted |
286
286
  | `await wp.lobby({ code, race, everyTicks? })` | `wp.lobby(code, race, every_ticks=10)` | `OnlineMatch` once the host starts: joins a player's lobby by its code, marks ready (again after the host changes the map or race) and waits |
287
287
  | `await offer.decline()` | `offer.decline()` | declines; the queue may give you a short penalty |
288
+ | `wp.close()` | `wp.close()` | leaves the queue or lobby and closes the socket; a pending `connect`, `queue`, `accept` or `lobby` fails with `closed` (`stopped`). Call it before exiting on Ctrl-C |
288
289
  | `await Warpass.join({ token, matchId, url?, everyTicks? })` | `Warpass.join(match_id, token=, url=, every_ticks=10)` | `OnlineMatch`: rejoin a match you are in after a crash |
289
290
  | `match.onThink(think, { everyTicks? })` | `match.on_think(think, every_ticks=None)` | registers your think; returns the match |
290
291
  | `await match.ended()` | `match.ended()` | `{ reason }` when the match ends |
@@ -293,8 +294,10 @@ Connect a bot account, queue or join a lobby by code, play a match and read the
293
294
  | `match.id`, `match.slot` | `match.id`, `match.slot` | the match id and your slot |
294
295
 
295
296
  - `url` defaults to `DEFAULT_URL` (`https://warpass.pike.com.br`).
297
+ - A match takes over the connection; after it ends, `queue` and `lobby` on the same `Warpass` reconnect by themselves, so one `Warpass` can play match after match.
296
298
  - `Offer.opponent` is `{ name, bot, rating, race }`.
297
299
  - `lobby` fails with `refused` (`missing`, `full`, `started`) when the code is wrong or taken, and with `cancelled` (`closed`) when the host closes the lobby.
300
+ - In Python, Ctrl-C during `connect`, `queue`, `accept` or `lobby` closes the session and raises `KeyboardInterrupt`.
298
301
  - In Python, `ended()` and `result()` run your think loop on the calling thread until the match ends; an `async def` think is awaited.
299
302
  - In JS, the think loop runs in the background after `onThink`; `ended()` and `result()` wait for it.
300
303
 
@@ -423,7 +426,7 @@ Questions a bot can ask during a think (`game`, or `match.game` online). Queries
423
426
  | `canResearch(building, upgrade)` | `can_research(building, upgrade)` | |
424
427
  | `placeRefusal(building, at)` | `place_refusal(building, at)` | `null` if a building id fits with its top-left at tile `at`, else a reason |
425
428
  | `canPlace(building, at)` | `can_place(building, at)` | |
426
- | `findPlacement(building, near, radius = 16)` | `find_placement(building, near, radius=16)` | `[tx, ty]` where it fits closest to `near`, or `null` |
429
+ | `findPlacement(building, near, radius = 16)` | `find_placement(building, near, radius=16)` | `[tx, ty]` where it fits closest to `near` and is in view now, or `null` |
427
430
  | `nearestResource(from, resource, radius = 40)` | `nearest_resource(start, resource, radius=40)` | `[tx, ty]` of the nearest tile with `food`, `wood`, `stone` or `gold` left |
428
431
  | `reachable(from, to)` | `reachable(start, end)` | `true` if your units can walk between the two tiles |
429
432
  | `front(toward?)` | `front(toward=None)` | `[tx, ty]`: the tile where your army should gather to face tile `toward` (default: the map centre), usually a choke near your base |
@@ -434,7 +437,7 @@ Questions a bot can ask during a think (`game`, or `match.game` online). Queries
434
437
  - `building` arguments take a view object or an eid; `unit`, `upgrade` and building ids are strings from the rules.
435
438
  - Tile arguments take `[tx, ty]` or an object with `x`, `y` in tiles.
436
439
  - Training and research refusals: `notEnough` (resources), `supplyLimit`, `needHousing`, `queueFull`, `requirementsNotMet`, `limitReached`, `invalid` (wrong building, not finished, not yours).
437
- - Placement refusals: `outOfBounds`, `somethingInWay`, `cannotBuildThere`, `unevenGround`, `rampBlocked`, `buildOnSite` / `siteGround` (site buildings must stand on their site), `alreadyBuilt`, `limitReached`, `requirementsNotMet`, `unknownBuilding`.
440
+ - Placement refusals: `outOfBounds`, `notVisible` (every footprint tile must be in your current vision; send a unit to look first), `somethingInWay`, `cannotBuildThere`, `unevenGround`, `rampBlocked`, `buildOnSite` / `siteGround` (site buildings must stand on their site), `alreadyBuilt`, `limitReached`, `requirementsNotMet`, `unknownBuilding`.
438
441
 
439
442
  <!-- api/act.md -->
440
443
 
@@ -454,7 +457,7 @@ Every order a bot can give, on `act` during a think (and on the builder passed t
454
457
  | `target(who, target, { queued })` | `target(who, target, queued=False)` | the right-click order: attack an enemy, gather a resource, repair your building |
455
458
  | `repair(who, target, { queued })` | `repair(who, target, queued=False)` | workers repair one of your buildings |
456
459
  | `gather(who, tile, { queued })` | `gather(who, tile, queued=False)` | workers gather the resource on a tile (from `nearestResource`) |
457
- | `build(who, building, at, { queued })` | `build(who, building, at, queued=False)` | workers place and build a building with its top-left at `at`; pays on placement |
460
+ | `build(who, building, at, { queued })` | `build(who, building, at, queued=False)` | workers place and build a building with its top-left at `at` (the footprint must be in view); pays on placement |
458
461
  | `buildLine(who, building, from, to, { queued })` | `build_line(who, building, start, end, queued=False)` | a line of wall segments |
459
462
  | `train(building, unit, count = 1)` | `train(building, unit, count=1)` | queue units (pays now) |
460
463
  | `research(building, upgrade)` | `research(building, upgrade)` | queue an upgrade (pays now) |
@@ -475,6 +478,8 @@ Every order a bot can give, on `act` during a think (and on the builder passed t
475
478
 
476
479
  What happened to your player since the last think, in `events` (oldest first). Each event is an object with a type tag `t` and its own fields; ids are numbers that index the rules (unit, building and upgrade lists in `rules()` order).
477
480
 
481
+ In a [custom game](custom.md), `events(slot)` returns the same events for any slot.
482
+
478
483
  | `t` | When |
479
484
  |---|---|
480
485
  | `trained` | one of your units finished training |
@@ -560,11 +565,35 @@ Ops after the first step still apply but make the game unreplayable.
560
565
  | `until(maxTicks, (observer, tick) => done)` | `until(max_ticks, lambda observer, tick: done)` | step until `done`; returns ticks taken or `-1` |
561
566
  | `view(slot)` | `view(slot)` | the fogged [view](view.md) of a slot |
562
567
  | `observer()` | `observer()` | the full view of everything, no fog |
568
+ | `events(slot)` | `events(slot)` | the [events](events.md) that slot got since the last call, fog-filtered exactly as in a match |
569
+ | `observerEvents()` | `observer_events()` | every event since the last call, unfiltered |
563
570
  | `game(slot)` | `game(slot)` | [queries](game.md) as that slot |
564
571
  | `map()` | `map()` | map size, starts, chokes, sites |
565
572
  | `replay()` | `replay()` | a [Replay](replay.md) of setup and orders so far |
566
573
  | `tick`, `winner` | `tick`, `winner` | current tick; winning slot once over |
567
574
 
575
+ The first `events` call for a slot (or `observerEvents`) starts recording for it and returns `[]`, so call it once before stepping. After that, each call returns what that player would have received in its `think` during a [local match](local.md):
576
+
577
+ ```js
578
+ import { CustomGame, rules } from "@pikehub/warpass-bot";
579
+
580
+ const r = rules();
581
+ const [a, b] = r.races;
582
+ const g = new CustomGame({ seed: 5, races: [a, b] });
583
+ const [x0, y0] = g.flattenArea(24, 12);
584
+ const fighter = (race) => r.units.find((u) => u.race === race && !u.worker && u.attack);
585
+ const ours = [0, 1, 2].map((k) => g.spawn(0, fighter(a).id, (x0 + 4) * 256, (y0 + 3 + k) * 256));
586
+ [0, 1, 2].forEach((k) => g.spawn(1, fighter(b).id, (x0 + 10) * 256, (y0 + 3 + k) * 256));
587
+ g.events(0);
588
+ g.events(1);
589
+ g.order(0, (act) => act.attackMove(ours, (x0 + 12) * 256, (y0 + 4) * 256));
590
+ g.step(20 * 30);
591
+ const mine = g.events(0);
592
+ const theirs = g.events(1);
593
+ console.log(`slot 0: ${mine.filter((e) => e.t === "hit").length} hits, ${mine.filter((e) => e.t === "death").length} deaths`);
594
+ console.log(`slot 1: ${theirs.filter((e) => e.t === "hit").length} hits`);
595
+ ```
596
+
568
597
  <!-- api/replay.md -->
569
598
 
570
599
  # Replays
@@ -618,11 +647,11 @@ Static facts about the bundled engine, and these docs, from code.
618
647
  ```
619
648
  { engineVersion, races, resources, terrains: { name: id }, tile, ticksPerSecond, mapSize,
620
649
  units: [{ id, race, cost, supply, hp, speed, sight, trainTicks, trainedAt, requires, abilities, worker, lane, armor: { melee, pierce }, attack }],
621
- buildings: [{ id, race, size, cost, hp, buildTicks, supply, trains, researches, requires, site }],
650
+ buildings: [{ id, race, size, cost, hp, buildTicks, supply, trains, researches, requires, site, armor: { melee, pierce }, attack }],
622
651
  upgrades: [{ id, race, cost, ticks, requires, group }] }
623
652
  ```
624
653
 
625
- `requires` is `{ buildings, anyBuildings, upgrades, anyUpgrades }` (ids). `attack` is `{ damage, range, minRange, cooldown, splash, onlyBuildings }` or `null`. Units of measure are in [../rules/index.md](../rules/index.md); the same data as tables is under `rules/`.
654
+ `requires` is `{ buildings, anyBuildings, upgrades, anyUpgrades }` (ids). `attack` (units and buildings) is `{ damage, range, minRange, cooldown, splash, onlyBuildings }` or `null`. Units of measure are in [../rules/index.md](../rules/index.md); the same data as tables is under `rules/`.
626
655
 
627
656
  ```js
628
657
  import { docs, docsIndex } from "@pikehub/warpass-bot";
@@ -773,7 +802,7 @@ Every SDK call that fails throws a `WarpassError` with a `kind` and the fields b
773
802
  | `unauthenticated` | | the key is wrong, rotated, or the bot was deleted | create or rotate the key on the Developer page |
774
803
  | `refused` | `about`, `reason`, `message` | the server refused a request | see reasons below |
775
804
  | `cancelled` | `reason` | the offer fell through (`declined`, `timeout`, the rival left) or the host closed the lobby (`closed`) | queue again |
776
- | `closed` | `reason` | the socket closed and could not reconnect | connect again; `Warpass.join` resumes a running match |
805
+ | `closed` | `reason` | the socket closed and could not reconnect, or you called `close()` (`stopped`) | connect again; `Warpass.join` resumes a running match |
777
806
  | `timeout` | | no answer in time (`result` waits 120 s by default) | retry `result()`; the match may still be sealing |
778
807
  | `network` | `message` | DNS, TLS or HTTP failure | check `url` and connectivity |
779
808
 
@@ -794,7 +823,7 @@ Errors from local games and custom games (unknown ids, setup ops off the map) ar
794
823
 
795
824
  <!-- rules/index.md -->
796
825
 
797
- # Rules for engine 62
826
+ # Rules for engine 63
798
827
 
799
828
  Generated from the engine this SDK bundles. Every id below is what the view, the queries and the orders use.
800
829
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikehub/warpass-bot",
3
- "version": "62.0.1",
3
+ "version": "63.0.1",
4
4
  "description": "Play Warpass from code: online matches, local games, custom games and replays",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -22,8 +22,8 @@
22
22
  },
23
23
  "license": "MIT",
24
24
  "optionalDependencies": {
25
- "@pikehub/warpass-bot-linux-x64-gnu": "62.0.1",
26
- "@pikehub/warpass-bot-linux-arm64-gnu": "62.0.1"
25
+ "@pikehub/warpass-bot-linux-x64-gnu": "63.0.1",
26
+ "@pikehub/warpass-bot-linux-arm64-gnu": "63.0.1"
27
27
  },
28
28
  "publishConfig": {
29
29
  "access": "public"