Add new PNG images for clean and preview outputs
- Added `image_clean.png` to the output directory for the clean image representation. - Added `image_clean_preview.png` for the preview of the clean image. - Introduced `image_svg_clean.png` for the SVG clean image representation.
This commit is contained in:
+43
-10
@@ -5,6 +5,20 @@ from units import gas, rat, bomb, mine
|
||||
|
||||
|
||||
class UnitManager:
|
||||
def _spawnable_rat_positions(self):
|
||||
positions = []
|
||||
for y in range(1, self.map.height - 1):
|
||||
for x in range(1, self.map.width - 1):
|
||||
if not self.map.is_empty(x, y):
|
||||
continue
|
||||
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
|
||||
nx = x + dx
|
||||
ny = y + dy
|
||||
if self.map.in_bounds(nx, ny) and self.map.is_empty(nx, ny):
|
||||
positions.append((x, y))
|
||||
break
|
||||
return positions
|
||||
|
||||
def has_weapon_at(self, position):
|
||||
"""Check if there's a weapon (bomb, gas, mine) at the given position"""
|
||||
for unit in self.units.values():
|
||||
@@ -13,6 +27,16 @@ class UnitManager:
|
||||
if isinstance(unit, (bomb.Timer, bomb.NuclearBomb, gas.Gas, mine.Mine)):
|
||||
return True
|
||||
return False
|
||||
|
||||
def can_place_weapon_at(self, position):
|
||||
x, y = position
|
||||
if not self.map.in_bounds(x, y):
|
||||
return False
|
||||
if not self.map.is_empty(x, y):
|
||||
return False
|
||||
if self.has_weapon_at(position):
|
||||
return False
|
||||
return True
|
||||
|
||||
def count_rats(self):
|
||||
count = 0
|
||||
@@ -22,7 +46,7 @@ class UnitManager:
|
||||
return count
|
||||
|
||||
def spawn_gas(self, parent_id=None):
|
||||
if self.map.is_wall(self.pointer[0], self.pointer[1]):
|
||||
if not self.can_place_weapon_at(self.pointer):
|
||||
return
|
||||
if self.ammo["gas"]["count"] <= 0:
|
||||
return
|
||||
@@ -33,23 +57,33 @@ class UnitManager:
|
||||
def spawn_rat(self, position=None):
|
||||
if position is None:
|
||||
position = self.choose_start()
|
||||
if position is None:
|
||||
print("[flow] spawn_rat aborted: no valid spawn position", flush=True)
|
||||
return
|
||||
|
||||
print(f"[flow] spawn_rat using position={position}", flush=True)
|
||||
|
||||
# Don't spawn rats on top of weapons
|
||||
if self.has_weapon_at(position):
|
||||
# Try nearby positions
|
||||
for dx, dy in [(0,1), (1,0), (0,-1), (-1,0), (1,1), (-1,-1), (1,-1), (-1,1)]:
|
||||
alt_pos = (position[0] + dx, position[1] + dy)
|
||||
if not self.map.is_wall(alt_pos[0], alt_pos[1]) and not self.has_weapon_at(alt_pos):
|
||||
if not self.map.in_bounds(alt_pos[0], alt_pos[1]):
|
||||
continue
|
||||
if self.map.is_empty(alt_pos[0], alt_pos[1]) and not self.has_weapon_at(alt_pos):
|
||||
position = alt_pos
|
||||
break
|
||||
else:
|
||||
# All nearby positions blocked, abort spawn
|
||||
print(f"[flow] spawn_rat aborted: weapon blocks spawn near {position}", flush=True)
|
||||
return
|
||||
|
||||
rat_class = rat.Male if random.random() < 0.5 else rat.Female
|
||||
self.spawn_unit(rat_class, position)
|
||||
|
||||
def spawn_bomb(self, position):
|
||||
if not self.can_place_weapon_at(position):
|
||||
return
|
||||
if self.ammo["bomb"]["count"] <= 0:
|
||||
return
|
||||
self.render_engine.play_sound("PUTDOWN.WAV")
|
||||
@@ -60,7 +94,7 @@ class UnitManager:
|
||||
"""Spawn a nuclear bomb at the specified position"""
|
||||
if self.ammo["nuclear"]["count"] <= 0:
|
||||
return
|
||||
if self.map.is_wall(position[0], position[1]):
|
||||
if not self.can_place_weapon_at(position):
|
||||
return
|
||||
self.render_engine.play_sound("NUCLEAR.WAV")
|
||||
self.ammo["nuclear"]["count"] -= 1
|
||||
@@ -69,7 +103,7 @@ class UnitManager:
|
||||
def spawn_mine(self, position):
|
||||
if self.ammo["mine"]["count"] <= 0:
|
||||
return
|
||||
if self.map.is_wall(position[0], position[1]):
|
||||
if not self.can_place_weapon_at(position):
|
||||
return
|
||||
self.render_engine.play_sound("PUTDOWN.WAV")
|
||||
self.ammo["mine"]["count"] -= 1
|
||||
@@ -83,12 +117,11 @@ class UnitManager:
|
||||
self.units[id] = unit(self, position, id, **kwargs)
|
||||
|
||||
def choose_start(self):
|
||||
if not hasattr(self, '_valid_positions'):
|
||||
self._valid_positions = [
|
||||
(x, y) for y in range(1, self.map.height-1)
|
||||
for x in range(1, self.map.width-1)
|
||||
if self.map.matrix[y][x]
|
||||
]
|
||||
if not hasattr(self, '_valid_positions') or self._valid_positions is None:
|
||||
self._valid_positions = self._spawnable_rat_positions()
|
||||
print(f"[flow] choose_start computed {len(self._valid_positions)} spawnable cells", flush=True)
|
||||
if not self._valid_positions:
|
||||
return None
|
||||
return random.choice(self._valid_positions)
|
||||
|
||||
def get_unit_by_id(self, id):
|
||||
|
||||
Reference in New Issue
Block a user