You control 9 cats via two methods: move() and pew(). The map has barricades (collision obstacles) and pods (areas where you can replenish energy). There is a death_circle that slowly shrinks, forcing cats to engage in a fight.
Energy is the only resource of the game. You attack and defend yourself with it – see details below.
Apart from cats, there are two other objects on the map. Barricades and Pods:
| Variable | Type | Description |
|---|---|---|
| barricades | array | Array of [x, y] coordinates of the barricade's center. Barricades are circular obstacles that cats have to walk around. |
| pods | array | Array of [x, y] coordinates of the pod's center. Cats inside or on the edge of a pod replenish energy. |
Game's global variables:
| Variable | Type | Description |
|---|---|---|
| memory | object | Empty object. Use it to store values across ticks. |
| my_cats | array | Array of your units (all, even dead ones) |
| cats | object | Object containing all cat objects in the game |
| tick | number | Current game tick (e.g. 75) |
| death_circle | number | Current radius of the shrinking circle centered on the map |
| this_player_id | string | Your username |
Cats are the game's units. These are their properties:
| Variable | Type | Description |
|---|---|---|
| id | string | username + _ + number. E.g. 'jane_7' |
| position | array | cat's [x, y] coordinates, e.g. [750, 900] |
| energy | number | current energy (starts at 10) |
| hp | number | 1 when alive, 0 when dead |
| mark | string | custom label assignable via set_mark() |
| last_pewed | string | id of the last pewed target |
| player_id | string | username of the owner |
| sight | object | show example |
my_cats[1].sight = {
friends: ['jane_2', 'jane_3', 'jane_4'],
enemies: ['karl_4'],
friends_pewable: ['jane_2'],
enemies_pewable: []
}
Cats see other cats within 400 radius. There are 3 friendly and 1 enemy cat within sight range. 1 friendly cat is within pew() distance.
And the available methods:
| Method | Argument | Example |
|---|---|---|
| pew(target) | target is a cat object within 200 units | my_cats[0].pew(cats['jane_7']) |
|
Costs 1 energy per tick. When an enemy cat is hit, it loses 2 energy. When a friendly cat is hit, it restores 1 energy. If there are other enemy cats within 20 units radius of the target, they are hit as well (all lose 2 energy per tick) |
||
| move(target) | target is [x, y] array | my_cats[0].move([100,100]) |
|
Cats move by max. 20 units per tick |
||
| shout(message) | message max 20 characters | my_cats[0].shout('meow') |
| set_mark(label) | label max 60 characters | my_cats[0].set_mark('purring') |
This is also the order of operations. Cats first pew, then move (within the cycle of one tick) more details
Distance between cats
function dist_sq(pos1, pos2) {
return (pos2[0]-pos1[0])**2 + (pos2[1]-pos1[1])**2;
}
// pew hits if dist_sq(from, to) <= range**2
// where range = 200
Position / move calculations
let direction = [target[0] - pos[0], target[1] - pos[1]];
let len_sq = direction[0]**2 + direction[1]**2;
if (len_sq > speed**2) {
let len = Math.sqrt(len_sq);
direction = [speed / len * direction[0], speed / len * direction[1]];
}
position = [pos[0] + direction[0], pos[1] + direction[1]];
// speed = 20 units per tick
Rounding of positions
// After each move, both x and y are rounded to 5 decimal places: position = position.map(c => +c.toFixed(5));
Game Constants show all
| Constant | Value |
|---|---|
| Movement speed | 20 units/tick |
| Pew range | 200 units (inclusive) |
| Pew cost | 1 energy/tick |
| Pew enemy damage | 2 energy |
| Pew friendly heal | 1 energy |
| Splash (AOE) radius | 20 units (inclusive) |
| Sight range | 400 units (inclusive) |
| Energy capacity | 10 |
| Starting energy | 10 |
| Cats per player | 9 |
| Barricade collision radius | 100 units (exclusive) |
| Pod area | 40×40 units (inclusive) |
| Pod heal | 1 energy/tick |
| Death circle start radius | 1200 |
| Death circle min radius | 50 |
| Death circle shrink rate | 2 units/tick |
| Death circle drain | 2 energy/tick |
| Tick duration | 500ms |
Code examples
for (let cat of my_cats) {
if (cat.sight.enemies.length == 0) continue;
let enemy = cats[cat.sight.enemies[0]];
cat.move(enemy.position);
cat.pew(enemy);
}
function distance(a, b) {
let dx = a[0] - b[0];
let dy = a[1] - b[1];
return Math.sqrt(dx * dx + dy * dy);
}
function closest_enemy(cat) {
let best = null;
let best_dist = Infinity;
for (let id of cat.sight.enemies) {
let d = distance(cat.position, cats[id].position);
if (d < best_dist) {
best_dist = d;
best = cats[id];
}
}
return best;
}
for (let cat of my_cats) {
let enemy = closest_enemy(cat);
if (!enemy) continue;
cat.move(enemy.position);
cat.pew(enemy);
}
Credits
Author: Vilem Ries
Special thanks: VendanLots of infra work and backend optimization on the 'v1' of Yare that is still in use in this version, jmHelped with optimizations around game logic, swzPython transpiler and other help (Python not ready yet in this version of Yare, but coming soon!) and rozLots of help with testing