PathFinder

class pygamelib.actuators.PathFinder(game: engine.Game | None = None, actuated_object: board_items.BoardItem | None = None, circle_waypoints=True, parent: board_items.BoardItem | None = None, algorithm=Algorithm.BFS)

Bases: Behavioral

Important

This module assume a one step movement. If you need more than one step, you will need to sub-class this module and re-implement next_waypoint().

This actuator is a bit different than the simple actuators (SimpleActuators) as it requires the knowledge of both the game object and the actuated object.

The constructor takes the following parameters:

Parameters:
  • game (pygamelib.engine.Game) – A reference to the instantiated game engine.

  • actuated_object (pygamelib.board_items.BoardItem) – The object to actuate. Deprecated in favor of parent. Only kept for backward compatibility.

  • parent (pygamelib.board_items.BoardItem) – The parent object to actuate.

  • circle_waypoints (bool) – If True the next_waypoint() method is going to circle between the waypoints (when the last is visited, go back to the first)

  • algorithm (constant) – ALGO_BFS - BFS, ALGO_ASTAR - AStar

__init__(game: engine.Game | None = None, actuated_object: board_items.BoardItem | None = None, circle_waypoints=True, parent: board_items.BoardItem | None = None, algorithm=Algorithm.BFS)

The constructor simply construct an Actuator. It takes on positional parameter: the parent object.

Methods

__init__([game, actuated_object, ...])

The constructor simply construct an Actuator.

add_waypoint(row, column)

Add a waypoint to the list of waypoints.

attach(observer)

Attach an observer to this instance.

clear_waypoints()

Empty the waypoints stack.

current_path()

This method simply return a copy of the current path of the actuator.

current_waypoint()

Return the currently active waypoint.

detach(observer)

Detach an observer from this instance.

find_path()

Find a path to the destination.

handle_notification(subject[, attribute, value])

A virtual method that needs to be implemented by the observer.

load(data)

Load data and create a new PathFinder out of it.

next_action()

That method needs to be implemented by all behavioral actuators or a NotImplementedError exception will be raised.

next_move()

This method return the next move calculated by this actuator.

next_waypoint()

Return the next active waypoint.

notify([modifier, attribute, value])

Notify all the observers that a change occurred.

pause()

Set the actuator state to PAUSED.

remove_waypoint(row, column)

Remove a waypoint from the stack.

serialize()

Return a dictionary with all the attributes of this object.

set_destination([row, column])

Set the targeted destination.

start()

Set the actuator state to RUNNING.

stop()

Set the actuator state to STOPPED.

store_screen_position(row, column)

Store the screen position of the object.

Attributes

screen_column

A property to get/set the screen column.

screen_row

A property to get/set the screen row.

add_waypoint(row: int, column: int)

Add a waypoint to the list of waypoints.

Waypoints are used one after the other on a FIFO basis (First In, First Out).

If not destination (i.e destination == (None, None)) have been set yet, that method sets it.

Parameters:
  • row (int) – The “row” part of the waypoint’s coordinate.

  • column – The “column” part of the waypoint’s coordinate.

Raises:

PglInvalidTypeException – If any of the parameters is not an int.

Example:

pf = PathFinder(game=mygame, actuated_object=npc1)
pf.add_waypoint(3,5)
pf.add_waypoint(12,15)
attach(observer)

Attach an observer to this instance. It means that until it is detached, it will be notified every time that a notification is issued (usually on changes).

An object cannot add itself to the list of observers (to avoid infinite recursions).

Parameters:

observer (PglBaseObject) – An observer to attach to this object.

Returns:

True or False depending on the success of the operation.

Return type:

bool

Example:

myboard = Board()
screen = Game.instance().screen
# screen will be notified of all changes in myboard
myboard.attach(screen)
clear_waypoints()

Empty the waypoints stack.

Example:

pf.clear_waypoints()
current_path() List[Tuple[int, int]]

This method simply return a copy of the current path of the actuator.

The current path is to be understood as: the list of positions still remaining. All positions that have already been gone through are removed from the stack.

Important

A copy of the path is returned for every call to that function so be wary of the performances impact.

Example:

mykillernpc.actuator = PathFinder(
                        game=mygame,
                        actuated_object=mykillernpc
                    )
mykillernpc.actuator.set_destination(
                        mygame.player.pos[0],
                        mygame.player.pos[1]
                    )
mykillernpc.actuator.find_path()
for i in mykillernpc.actuator.current_path():
    print(i)
current_waypoint() Tuple[int | None, int | None]

Return the currently active waypoint.

If no waypoint have been added, this function return None.

Returns:

Either a None tuple or the current waypoint.

Return type:

A None tuple or a tuple of integer.

Example:

(row,column) = pf.current_waypoint()
pf.set_destination(row,column)
detach(observer)

Detach an observer from this instance. If observer is not in the list this returns False.

Parameters:

observer (PglBaseObject) – An observer to detach from this object.

Returns:

True or False depending on the success of the operation.

Return type:

bool

Example:

# screen will no longer be notified of the changes in myboard.
myboard.detach(screen)
find_path() List[Tuple[int, int]]

Find a path to the destination.

Destination (PathFinder.destination) has to be set beforehand.

Example:

mykillernpc.actuator = PathFinder(
        game=mygame, actuated_object=mykillernpc
    )
mykillernpc.actuator.set_destination(
        mygame.player.pos[0], mygame.player.pos[1]
    )
mykillernpc.actuator.find_path()

Warning

PathFinder.destination is a tuple! Please use PathFinder.set_destination(x,y) to avoid problems.

Path Finding Algorithm Description:

Breadth First Search: This method implements a Breadth First Search algorithm (Wikipedia: BFS) to find the shortest path to destination.

A* Search: This method implements a A* Search algorithm (Wikipedia: A*) to find the shortest path to destination.

handle_notification(subject, attribute=None, value=None)

A virtual method that needs to be implemented by the observer. By default it does nothing but each observer needs to implement it if something needs to be done when notified.

This method always receive the notifying object as first parameter. The 2 other parameters are optional and can be None.

You can use the attribute and value as you see fit. You are free to consider attribute as an event and value as the event’s value.

Parameters:
  • subject (PglBaseObject) – The object that has changed.

  • attribute (str) – The attribute that has changed, it is usually a “FQDN style” string. This can be None.

  • value (Any) – The new value of the attribute. This can be None.

classmethod load(data: dict) PathFinder

Load data and create a new PathFinder out of it.

Parameters:

data (dict) – Data to create a new actuator (usually generated by serialize())

Returns:

A new actuator.

Return type:

PathFinder

Example:

path_finder = PathFinder.load(actuator_data)
next_action()

That method needs to be implemented by all behavioral actuators or a NotImplementedError exception will be raised.

Raises:

NotImplementedError

next_move() int

This method return the next move calculated by this actuator.

In the case of this PathFinder actuator, next move does the following:

  • If the destination is not set return NO_DIR (see constants) - If the destination is set, but the path is empty and actuated object’s position is different from destination: call find_path()

  • Look at the current waypoint, if the actuated object is not at that position return a direction from the constants module. The direction is calculated from the difference between actuated object’s position and waypoint’s position.

  • If the actuated object is at the waypoint position, then call next_waypoint(), set the destination and return a direction. In this case, also call find_path().

  • In any case, if there is no more waypoints in the path this method returns NO_DIR (see constants)

Example:

seeker = NPC(model=graphics.Models.SKULL)
seeker.actuator = PathFinder(game=mygame,actuated_object=seeker)
while True:
    seeker.actuator.set_destination(mygame.player.pos[0],mygame.player.pos[1])
    # next_move() will call find_path() for us.
    next_move = seeker.actuator.next_move()
    if next_move == Direction.NO_DIR:
        seeker.actuator.set_destination(mygame.player.pos[0],mygame.player.pos[1])
    else:
        mygame.current_board().move(seeker,next_move,1)
next_waypoint() Tuple[int | None, int | None]

Return the next active waypoint.

If no waypoint have been added, this function return None. If there is no more waypoint in the stack:

  • if PathFinder.circle_waypoints is True this function reset the waypoints stack and return the first one.

  • else, return None.

Returns:

Either a None tuple or the next waypoint.

Return type:

A None tuple or a tuple of integer.

Example:

pf.circle_waypoints = True
(row,column) = pf.next_waypoint()
pf.set_destination(row,column)
notify(modifier=None, attribute: str = None, value: Any = None) None

Notify all the observers that a change occurred.

Parameters:
  • modifier (PglBaseObject) – An optional parameter that identify the modifier object to exclude it from the notified objects.

  • attribute (str) – An optional parameter that identify the attribute that has changed.

  • value (Any) – An optional parameter that identify the new value of the attribute.

Example:

# This example is silly, you would usually notify other objects from inside
# an object that changes a value that's important for the observers.
color = Color(255,200,125)
color.attach(some_text_object)
color.notify()
pause()

Set the actuator state to PAUSED.

Example:

mygame.pause()
remove_waypoint(row: int, column: int)

Remove a waypoint from the stack.

This method removes the first occurrence of a waypoint in the stack.

If the waypoint cannot be found, it raises a ValueError exception. If the row and column parameters are not int, an PglInvalidTypeException is raised.

Parameters:
  • row (int) – The “row” part of the waypoint’s coordinate.

  • column – The “column” part of the waypoint’s coordinate.

Raises:
  • PglInvalidTypeException – If any of the parameters is not an int.

  • ValueError – If the waypoint is not found in the stack.

Example:

path_finder.remove_waypoint(2,5)
property screen_column: int

A property to get/set the screen column.

Parameters:

value (int) – the screen column

Return type:

int

property screen_row: int

A property to get/set the screen row.

Parameters:

value (int) – the screen row

Return type:

int

serialize() dict

Return a dictionary with all the attributes of this object.

Returns:

A dictionary with all the attributes of this object.

Return type:

dict

set_destination(row: int = 0, column: int = 0)

Set the targeted destination.

Parameters:
  • row (int) – “row” coordinate on the board grid

  • column (int) – “column” coordinate on the board grid

Raises:

PglInvalidTypeException – if row or column are not int.

Example:

mykillernpc.actuator.set_destination(
    mygame.player.pos[0], mygame.player.pos[1]
)
start()

Set the actuator state to RUNNING.

If the actuator state is not RUNNING, actuators’ next_move() function (and all derivatives) should not return anything.

Example:

mygame.start()
stop()

Set the actuator state to STOPPED.

Example:

mygame.stop()
store_screen_position(row: int, column: int) bool

Store the screen position of the object.

This method is automatically called by Screen.place().

Parameters:
  • row (int) – The row (or y) coordinate.

  • column (int) – The column (or x) coordinate.

Example:

an_object.store_screen_coordinate(3,8)