2023-12-21 16:15:21 +01:00

80 lines
2.9 KiB
Python

from marl_factory_grid.environment.entity.entity import Entity
from ...utils.utility_classes import RenderEntity
from marl_factory_grid.environment import constants as c
from marl_factory_grid.utils.results import TickResult
from . import constants as m
class Machine(Entity):
@property
def encoding(self):
return self._encodings[self.status]
def __init__(self, *args, work_interval: int = 10, pause_interval: int = 15, **kwargs):
"""
Represents a machine entity that the maintainer will try to maintain by performing the maintenance action.
Machines' health depletes over time.
:param work_interval: How long should the machine work before pausing.
:type work_interval: int
:param pause_interval: How long should the machine pause before continuing to work.
:type pause_interval: int
"""
super(Machine, self).__init__(*args, **kwargs)
self._intervals = dict({m.STATE_IDLE: pause_interval, m.STATE_WORK: work_interval})
self._encodings = dict({m.STATE_IDLE: pause_interval, m.STATE_WORK: work_interval})
self.status = m.STATE_IDLE
self.health = 100
self._counter = 0
def maintain(self) -> bool:
"""
Attempts to maintain the machine by increasing its health, which is only possible if the machine is at a maximum
of 98/100 HP.
"""
if self.status == m.STATE_WORK:
return c.NOT_VALID
if self.health <= 98:
self.health = 100
return c.VALID
else:
return c.NOT_VALID
def tick(self, state):
"""
Updates the machine's mode (work, pause) depending on its current counter and whether an agent is currently on
its position. If no agent is standing on the machine's position, it decrements its own health.
:param state: The current game state.
:type state: GameState
:return: The result of the tick operation on the machine.
:rtype: TickResult | None
"""
others = state.entities.pos_dict[self.pos]
if self.status == m.STATE_MAINTAIN and any([c.AGENT in x.name for x in others]):
return TickResult(identifier=self.name, validity=c.VALID, entity=self)
elif self.status == m.STATE_MAINTAIN and not any([c.AGENT in x.name for x in others]):
self.status = m.STATE_WORK
self.reset_counter()
return None
elif self._counter:
self._counter -= 1
self.health -= 1
return None
else:
self.status = m.STATE_WORK if self.status == m.STATE_IDLE else m.STATE_IDLE
self.reset_counter()
return None
def reset_counter(self):
"""
Internal Usage
"""
self._counter = self._intervals[self.status]
def render(self):
return RenderEntity(m.MACHINE, self.pos)