Movement#
Direction#
SolvingMode#
- class SolvingMode(value)#
An enumeration.
- FORWARD = 0#
Forward solving mode
pusher is allowed to push single box at the time
pusher can’t pull boxes
pusher can’t jump over boxes or walls
- REVERSE = 1#
Reverse solving mode
pusher is allowed to pull single box at the time
if position allows pull that pull is optional (pusher is allowed to move without pull even if pull is possible).
default behavior is to always pull boxes but that can be changed any time through
Mover.pulls_boxes
pusher can’t push boxes
pusher is allowed to jump over boxes and walls
jumps are allowed only before first pull is done
board starts in solved state: positions of boxes and goals are switched
when boxes and goals are switched, pusher might end up “standing on box”. In this situation, fist move in game must be jump.
PusherStep#
- class PusherStep(direction: Direction = Direction.LEFT, moved_box_id: int = - 1, is_jump: bool = False, is_pusher_selection: bool = False, pusher_id: int = 1, is_current_pos: bool = False)#
Represents single step of pusher movement.
Single step can be:
move
: pusher moved without pushing boxpush/pull
: pusher pushed or pulled a boxjump
: pusher jumpedpusher selection
: pusher was selected among other pushers on board
- Parameters
direction – direction in which movement was performed.
moved_box_id – ID of a box that was pushed or
Config.NO_ID
. Box usually gets it’s ID fromBoardManager
.is_jump – flag marking this step as part of pusher jump in reverse solving mode. See
Mover
for more details about reverse movement.is_pusher_selection – marks this step as part of pusher selecting sequence on boards with multiple pushers (Multiban game variant)
pusher_id – ID of pusher that performed movement. Pusher usually gets it’s ID from
BoardManager
.is_current_pos – flags this step as current position in game snapshot
- Raises
ValueError – single step can only be one thing at a time:
move
,push/pull
orjump
.
See also
- is_current_pos#
flags this step as current position in game snapshot
- property is_jump: bool#
True if this move is part of jump sequence in
SolvingMode.REVERSE
games.
- property is_move: bool#
True if pusher didn’t move box, didn’t jump and didn’t select another pusher.
- property is_pusher_selection: bool#
True if this step is part of pusher selection sequence in
Multiban
games.
- property moved_box_id: int#
ID of box that was moved or
Config.NO_ID
if no box was moved.When setting box ID on ie.
jump
, thatjump
will becomepush
. To changepush
intomove
, set box ID toConfig.NO_ID
.Setting it to invalid value will silently set it to
Config.NO_ID
.
- property pusher_id: int#
ID of pusher that performed movement.
Pusher ID must always be valid. When setting it to invalid value, PusherStep will silently set pusher ID to
Config.DEFAULT_ID
.
Mover#
- class Mover(board: BoardGraph, solving_mode: SolvingMode = SolvingMode.FORWARD)#
Implements game rules (on-board movement). Supports forward and reverse game solving mode.
History management
Mover only stores last performed move in history and it doesn’t offer redo. Failed moves, undo and non-moves (ie. selecting already selected pusher or jumping on same position pusher is already standing on) clear undo history.
Warning
Mover
operates directly on referenced game board. Because of that, this board should not be edited outside ofMover
afterMover
instance had been attached to it: editing the board will corruptMover
internal state. For the same reason, there should not be more than one mover attached to the same board.- Raises
NonPlayableBoardError – when attaching mover to non playable board (see
BoardManager.is_playable
)
- property board: BoardGraph#
- property solving_mode: SolvingMode#
- property board_manager: HashedBoardManager#
- property pulls_boxes: bool#
Select behavior in
SolvingMode.REVERSE
mode when pusher is moving away from box.See also
- property last_move: List[PusherStep]#
Sequence of
PusherStep
that contains most recent movement.Whenever
Mover
performs any movement or pusher selection, it puts resultingPusherStep
into this sequence in order pusher steps happened.This is useful for movement animation in GUI. After Mover performs movement, GUI has enough information to know what was performed and to choose which animations to render for that.
It is also possible to set this to some external sequence of moves. In that case, calling
undo_last_move()
will cause Mover to try to undo that external sequence of pusher steps.Example:
>>> from sokoenginepy import Direction, Tessellation, Mover, PusherStep, BoardGraph, Puzzle >>> puzzle = Puzzle(Tessellation.SOKOBAN, board='\n'.join([ ... ' #####', ... ' # @#', ... ' #$ #', ... ' ### $##', ... ' # $ $ #', ... '### # ## # ######', ... '# # ## ##### ..#', ... '# $ $ ..#', ... '##### ### #@## ..#', ... ' # #########', ... ' #######' ... ])) >>> board = BoardGraph(puzzle) >>> mover = Mover(board) >>> mover.last_move = [PusherStep(Direction.UP), PusherStep(Direction.RIGHT)] >>> mover.undo_last_move() >>> print(mover.board.to_board_str()) ##### # # #$@ # ### $## # $ $ # ### # ## # ###### # # ## ##### ..# # $ $ ..# ##### ### #@## ..# # ######### ####### >>> mover.last_move [PusherStep(Direction.LEFT), PusherStep(Direction.DOWN)]
Warning
Subsequent movement overwrites this meaning that Mover can only undo last move performed (it doesn’t keep whole history of movement, only the last performed move).
- select_pusher(pusher_id: int)#
Selects pusher that will perform next move. If this pusher is already selected, does nothing.
From current position, generates sequence of steps needed to select pusher_id and stores them into last_move(). Sets internal selected pusher_id to newly selected pusher
Mover initially always selects
Config.DEFAULT_ID
. This means that for single-pusher boards, single pusher is always automatically selected and this method doesn’t need to be called.See also
- Raises
KeyError – no pusher with ID
pusher_id
- move(direction: Direction)#
Moves currently selected pusher in
direction
.In
SolvingMode.FORWARD
mode, pushes the box in front of pusher (if there is one).In
SolvingMode.REVERSE
mode pulls box together with pusher (if there is one and ifpulls_boxes
isTrue
).- Raises
IllegalMoveError – for illegal moves
- jump(new_position: int)#
Currently selected pusher jumps to
new_position
.Fails if
Mover
is inSolvingMode.FORWARD
modepusher can’t be dropped on
new_position
first pull had been made
- Raises
IllegalMoveError – for illegal jumps
IndexError –
new_position
is off board
- exception IllegalMoveError#
- exception NonPlayableBoardError#