Skip to content

Commit ba03805

Browse files
committed
Bomberland: make bomb blasts visible and dangerous; document detonate
- Blast (x) cells now persist BLAST_TTL=2 ticks so they actually appear in the observation agents receive (previously set to ttl=1 and cleared before any agent saw them), and store their owner for damage attribution. - A unit moving onto an active blast cell now takes 1 HP of damage, credited to the blast owner (kills/damage_dealt), on top of the existing instant damage at detonation. Fire is now a real, avoidable hazard. - Document the detonate action (already supported by the runtime) in the arena description and runtime README, plus the blast/x hazard behavior.
1 parent cc164ae commit ba03805

3 files changed

Lines changed: 30 additions & 9 deletions

File tree

codeclash/arenas/bomberland/bomberland.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@ class BomberlandArena(CodeArena):
2222
def next_actions(game_state):
2323
return {"unit_0": "up"}
2424
25-
Valid actions are `up`, `down`, `left`, `right`, `bomb`, and `stay`. Each round runs several
26-
deterministic seeded games. Your units move on a destructible grid, place bombs, destroy blocks,
27-
damage opposing units, and score by survival, damage, kills, and block destruction.
25+
Valid actions are `up`, `down`, `left`, `right`, `bomb`, `stay`, and `detonate` (to blow up one of
26+
your own bombs early, e.g. the string `"detonate:x,y"` or `{"type": "detonate", "coordinates": [x, y]}`;
27+
bombs also explode automatically after their timer). Each round runs several deterministic seeded
28+
games. Your units move on a destructible grid, place bombs, destroy blocks, damage opposing units,
29+
and score by survival, damage, kills, and block destruction. Bomb blasts (`x` entities) stay active
30+
briefly and damage any unit standing on or moving into them.
2831
"""
2932
default_args: dict = {
3033
"sims_per_round": 4,

codeclash/arenas/bomberland/runtime/README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,15 @@ def next_actions(game_state):
1212
return {"unit_0": "up"}
1313
```
1414

15-
Valid string actions are `up`, `down`, `left`, `right`, `bomb`, and `stay`.
15+
Valid string actions are `up`, `down`, `left`, `right`, `bomb`, `stay`, and
16+
`detonate` (blow up one of your own bombs early, e.g. `"detonate:x,y"` or
17+
`{"type": "detonate", "coordinates": [x, y]}`; bombs also explode on their timer).
1618
The game-state dictionary follows the upstream starter-kit shape where possible:
1719
`connection.agent_id` identifies the player, `agents[player].unit_ids` lists the
1820
controlled units, `unit_state` contains unit coordinates and health, and
19-
`entities` contains walls, destructible blocks, bombs, and blast tiles.
21+
`entities` contains walls, destructible blocks, bombs, and blast tiles (`x`).
22+
Blast tiles stay active briefly and damage any unit that stands on or moves onto
23+
them, so avoid walking into fire.
2024

2125
Round simulation counts must be even so each player receives both starting sides.
2226

codeclash/arenas/bomberland/runtime/run_bomberland.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
START_BOMBS = 1
2121
BLAST_RADIUS = 3
2222
BOMB_TIMER = 6
23+
# How many ticks a blast (fire) cell stays active. It must be >= 2 so the cell
24+
# survives the start-of-tick decrement and is visible in the observation agents
25+
# receive on the following tick. While active, a blast damages any unit that
26+
# moves onto it.
27+
BLAST_TTL = 2
2328

2429

2530
def load_agent(name, path):
@@ -165,8 +170,8 @@ def entities_for_state(metal, wood, bombs, blasts):
165170
"blast_diameter": bomb["radius"] * 2 - 1,
166171
}
167172
)
168-
for (x, y), ttl in sorted(blasts.items()):
169-
entities.append({"type": "x", "coordinates": [x, y], "ttl": ttl})
173+
for (x, y), info in sorted(blasts.items()):
174+
entities.append({"type": "x", "coordinates": [x, y], "ttl": info["ttl"]})
170175
return entities
171176

172177

@@ -241,7 +246,7 @@ def explode_bomb(index, bombs, metal, wood, units, stats, blasts):
241246
units[unit_id]["inventory"]["bombs"] += 1
242247

243248
for cell in cells:
244-
blasts[cell] = 1
249+
blasts[cell] = {"ttl": BLAST_TTL, "owner": owner}
245250
if cell in wood:
246251
wood.remove(cell)
247252
stats[owner]["wood_destroyed"] += 1
@@ -345,6 +350,15 @@ def apply_actions(players, callbacks, agents, units, metal, wood, bombs, blasts,
345350
stats[player]["invalid_actions"] += 1
346351
continue
347352
units[unit_id]["coordinates"] = list(target)
353+
blast = blasts.get(target)
354+
if blast is not None:
355+
unit = units[unit_id]
356+
unit["hp"] -= 1
357+
owner = blast["owner"]
358+
if unit["agent_id"] != owner:
359+
stats[owner]["damage_dealt"] += 1
360+
if unit["hp"] <= 0:
361+
stats[owner]["kills"] += 1
348362

349363

350364
def tick_bombs(bombs, metal, wood, units, stats, blasts):
@@ -392,7 +406,7 @@ def run_game(players, callbacks, seed, ticks, width, height, unit_count, agent_t
392406
final_tick = 0
393407
for tick in range(ticks):
394408
final_tick = tick
395-
blasts = {pos: ttl - 1 for pos, ttl in blasts.items() if ttl > 1}
409+
blasts = {pos: {**info, "ttl": info["ttl"] - 1} for pos, info in blasts.items() if info["ttl"] > 1}
396410
apply_actions(
397411
players, callbacks, agents, units, metal, wood, bombs, blasts, stats, width, height, tick, agent_timeout
398412
)

0 commit comments

Comments
 (0)