class GameError(Exception):
    pass

class AgentWithNameAlreadyExists(GameError):
    def __init__(self, name):
        message = f"There is already an agent named {agent.name} in the game"
        super().__init__(message)

class AgentNotFoundByName(GameError):
    def __init__(self, name):
        message = f"There is no agent named {name} in the game"
        super().__init__(message)

class AgentNotInGame(GameError):
    def __init__(self, agent):
        name = getattr(agent, "name", f"{agent.__class__.__name__}")
        message = f"Agent {name} is not in the game"
        super().__init__(message)

class AgentAlreadyInGame(GameError):
    def __init__(self, agent):
        name = getattr(agent, "name", f"{agent.__class__.__name__}")
        message = f"Cannot add agent {name} to the game; the agent is already in the game"
        super().__init__(message)

class IllegalMove(GameError):
    def __init__(self, agent, position):
        name = getattr(agent, "name",  f"{agent.__class__.__name__}")
        message = f"Agent {name} tried to move to {position}"
        super().__init__(message)

class AgentCharacterTooLarge(GameError):
    def __init__(self, agent, size, char_size):
        name = getattr(agent, "name", agent.__class__.__name__)
        message = (
            f"Agent {name} has size {size} but its character grid is "
            f"{char_size[0]} wide and {char_size[1]} tall, "
            f"which exceeds its declared size."
        )
        super().__init__(message)

class GraphError(GameError):
    pass

class TerminalTooSmall(GameError):
    BORDER_X = 2
    BORDER_Y = 3
    STATE_HEIGHT = 5

    def __init__(self, width=None, width_needed=None, height=None, height_needed=None):
        if width is not None and width_needed is not None and width < width_needed:
            err = f"The terminal width ({width}) is less than the required {width_needed}."
            super().__init__(err)
        elif height is not None and height_needed is not None and height < height_needed:
            err = f"The terminal height ({height}) is less than the required {height_needed}."
            super().__init__(err)
        else:
            raise ValueError(f"TerminalTooSmall called with illegal values.")
