# I challenge you to a game of Sokoban Golf! Graphics of my programmable Sokoban game which this was the prototype for, by Fiverr user applemoment

Before I dived in earnest into writing the new version of my computer game that teaches Python, this time with game mechanics based on the classical puzzle game “Sokoban”, I wanted to make sure that Programmable Sokoban is a fun concept. So I wrote a prototype in a couple of hours.

The programmers among you will enjoy it.

“Golf” is a game played by programmers, where you have to solve a problem in as few keystrokes as possible. I challenge you to solve these Programmable Sokoban levels in as few keystrokes as possible!

 ''' Sokoban Golf by Aur Saraf At line 145 you will find a very naive solution for level 1. You can easily learn the API from it. How few lines do you need for solutions to levels 1, 2, and 3? Do not modify the game or the levels in any way. Just remove the level 1 solution and uncomment the level 2 and level 3 boards, and try to solve all three in as few characters as possible. The challenge is intentionally on ALL THREE LEVELS TOGETHER. You should be writing utility functions that help with more than one level. Good luck, and have fun! ''' WALL = '#' EMPTY = ' ' PLAYER = '@' CRATE = '*' EMPTY_DESTINATION = 'X' CRATE_IN_DESTINATION = 'V' EMPTY_SYMBOLS = (EMPTY, EMPTY_DESTINATION) CRATE_SYMBOLS = (CRATE, CRATE_IN_DESTINATION) DIRECTIONS = SOUTH, WEST, NORTH, EAST = 'SWNE' _dirs = lambda values: dict(zip(DIRECTIONS, values)) DIRECTION_VECTOR = _dirs(( (1, 0), (0, -1), (-1, 0), (0, 1), )) LEFT = _dirs((DIRECTIONS[(i - 1) % 4] for i in xrange(4))) RIGHT = _dirs((DIRECTIONS[(i + 1) % 4] for i in xrange(4))) class QuietBoard(object): def __init__(self, level): self.board = [list(row) for row in level.splitlines()] self.crates_at_large = level.count(CRATE) self.player = self._player_position(self.board) self.orientation = SOUTH self.on_destination = False def _player_position(self, board): for i, row in enumerate(board): if PLAYER in row: return (i, row.index(PLAYER)) assert False def __str__(self): return '\n'.join(''.join(row) for row in self.board) + '\n' + str(self.orientation) def is_win(self): return self.crates_at_large == 0 def at(self, (row, column)): return self.board[row][column] def forward(self): in_front = self._in_front(self.player) if self._is_movable_crate(in_front): self._slide_crate(in_front) if self._is_empty(in_front): self._slide_player() def left(self): self.orientation = LEFT[self.orientation] def right(self): self.orientation = RIGHT[self.orientation] def _is_movable_crate(self, position): return self._is_crate(position) and self._is_empty(self._in_front(position)) def _in_front(self, (row, column)): drow, dcolumn = DIRECTION_VECTOR[self.orientation] return row + drow, column + dcolumn def _is_empty(self, position): return self.at(position) in EMPTY_SYMBOLS def _is_crate(self, position): return self.at(position) in CRATE_SYMBOLS def _slide_crate(self, position): if self.at(position) == CRATE_IN_DESTINATION: empty = EMPTY_DESTINATION self.crates_at_large += 1 else: empty = EMPTY self._put(empty, position) destination = self._in_front(position) if self.at(destination) == EMPTY_DESTINATION: crate = CRATE_IN_DESTINATION self.crates_at_large -= 1 else: crate = CRATE self._put(crate, destination) def _slide_player(self): destination = self._in_front(self.player) empty = EMPTY_DESTINATION if self.on_destination else EMPTY self.on_destination = self.at(destination) == EMPTY_DESTINATION self._put(empty, self.player) self._put(PLAYER, destination) self.player = destination def _put(self, symbol, (row, column)): assert (symbol in EMPTY_SYMBOLS) != self._is_empty((row, column)) self.board[row][column] = symbol class Board(QuietBoard): def __init__(self, level): super(Board, self).__init__(level) print self print 'Start!' def forward(self): super(Board, self).forward() print self if self.is_win(): print 'You beat this level!' print LEVEL0 = '''\ ############# #@ * X# #############''' b = QuietBoard(LEVEL0) b.left() for _ in range(10): b.forward() assert b.is_win() LEVEL1 = '''\ ############# #@ X# # ##*######## # ######## #############''' b = Board(LEVEL1) b.forward() b.forward() b.left() b.forward() b.forward() b.forward() b.left() b.forward() b.left() b.left() b.forward() b.right() b.forward() b.forward() b.forward() b.right() b.forward() b.forward() b.right() for _ in range(9): b.forward() LEVEL2 = '''\ ############# # ###### # #@ # ##*#*# ####X# ## ####X# #############''' #b = Board(LEVEL2) # Mini Cosmos 01 (c) Aymeric Du Peloux LEVEL3 = '''\ ##### ### # # * # ## # # X # # # # ## # # #@ ### ##### ''' #b = Board(LEVEL3)
view raw soko.py hosted with ❤ by GitHub