# Trying to solve a Sokoban level with brute force

Before you even think this script will solve a Sokoban level, I must warn you: this script won’t solve a sokoban level, it won’t even recognize whether a level is solved or not.

This script, part of an old project I am going to bring to life again, will just make Sokoban wander around the maze eventually pushing crates here and there, according to Sokoban’s rules.

Feel free to add some backtracking to make it more interesting, but I have to say coding a Sokoban solver could be a nightmare.

If you want to see another Sokoban script (this time to play the game), read Javascript Sokoban game script.

Sokoban levels are shown and created this way:

# = wall
\$ = crate
. = place
* = crate in place
@ = man
+ = man in place

And now the script…

```";
}
return("".\$return."");
}

function is_solved(\$map){
return(!strpos(\$map,"\$"));
}

function is_empty(\$map,\$pos){
return((\$map{\$pos}==" ")or(\$map{\$pos}=="."));
}

function is_crate(\$map,\$pos){
return((\$map{\$pos}=="\$")or(\$map{\$pos}=="*"));
}

function get_player_pos(\$map){
return(strpos(\$map,"@")+strpos(\$map,"+"));
}

function echo_possible_directions(\$map,\$width){
\$player_pos = get_player_pos(\$map);
if (is_empty(\$map,\$player_pos-1) or (is_crate(\$map,\$player_pos-1) and is_empty(\$map,\$player_pos-2))){
\$return .= "L";
}
if (is_empty(\$map,\$player_pos+1) or (is_crate(\$map,\$player_pos+1) and is_empty(\$map,\$player_pos+2))){
\$return .= "R";
}
if (is_empty(\$map,\$player_pos-\$width) or (is_crate(\$map,\$player_pos-\$width) and is_empty(\$map,\$player_pos-2*\$width))){
\$return .= "U";
}
if (is_empty(\$map,\$player_pos+\$width) or (is_crate(\$map,\$player_pos+\$width) and is_empty(\$map,\$player_pos+2*\$width))){
\$return .= "D";
}
return(\$return);
}

function move(\$map,\$width,\$dir){
\$player_pos = get_player_pos(\$map);
if(\$dir=="L"){
if(\$map{\$player_pos}=="@"){
\$map{\$player_pos} = " ";
}
else{
\$map{\$player_pos} = ".";
}
if (!is_empty(\$map,\$player_pos-1)){
if(\$map{\$player_pos-1}=="\$"){
if(\$map{\$player_pos-2}==" "){
\$map{\$player_pos-2}="\$";
\$map{\$player_pos-1}=" ";
}
else{
\$map{\$player_pos-2}="*";
\$map{\$player_pos-1}=" ";
}
}
else{
if(\$map{\$player_pos-2}==" "){
\$map{\$player_pos-2}="\$";
\$map{\$player_pos-1}=".";
}
else{
\$map{\$player_pos-2}="*";
\$map{\$player_pos-1}=".";
}
}
}
if(\$map{\$player_pos-1}==" "){
\$map{\$player_pos-1}="@";
}
else{
\$map{\$player_pos-1}="+";
}
}
if(\$dir=="R"){
if(\$map{\$player_pos}=="@"){
\$map{\$player_pos} = " ";
}
else{
\$map{\$player_pos} = ".";
}
if (!is_empty(\$map,\$player_pos+1)){
if(\$map{\$player_pos+1}=="\$"){
if(\$map{\$player_pos+2}==" "){
\$map{\$player_pos+2}="\$";
\$map{\$player_pos+1}=" ";
}
else{
\$map{\$player_pos+2}="*";
\$map{\$player_pos+1}=" ";
}
}
else{
if(\$map{\$player_pos+2}==" "){
\$map{\$player_pos+2}="\$";
\$map{\$player_pos+1}=".";
}
else{
\$map{\$player_pos+2}="*";
\$map{\$player_pos+1}=".";
}
}
}
if(\$map{\$player_pos+1}==" "){
\$map{\$player_pos+1}="@";
}
else{
\$map{\$player_pos+1}="+";
}
}
if(\$dir=="U"){
if(\$map{\$player_pos}=="@"){
\$map{\$player_pos} = " ";
}
else{
\$map{\$player_pos} = ".";
}
if (!is_empty(\$map,\$player_pos-\$width)){
if(\$map{\$player_pos-\$width}=="\$"){
if(\$map{\$player_pos-2*\$width}==" "){
\$map{\$player_pos-2*\$width}="\$";
\$map{\$player_pos-\$width}=" ";
}
else{
\$map{\$player_pos-2*\$width}="*";
\$map{\$player_pos-\$width}=" ";
}
}
else{
if(\$map{\$player_pos-2*\$width}==" "){
\$map{\$player_pos-2*\$width}="\$";
\$map{\$player_pos-\$width}=".";
}
else{
\$map{\$player_pos-2*\$width}="*";
\$map{\$player_pos-\$width}=".";
}
}
}
if(\$map{\$player_pos-\$width}==" "){
\$map{\$player_pos-\$width}="@";
}
else{
\$map{\$player_pos-\$width}="+";
}
}
if(\$dir=="D"){
if(\$map{\$player_pos}=="@"){
\$map{\$player_pos} = " ";
}
else{
\$map{\$player_pos} = ".";
}
if (!is_empty(\$map,\$player_pos+\$width)){
if(\$map{\$player_pos+\$width}=="\$"){
if(\$map{\$player_pos+2*\$width}==" "){
\$map{\$player_pos+2*\$width}="\$";
\$map{\$player_pos+\$width}=" ";
}
else{
\$map{\$player_pos+2*\$width}="*";
\$map{\$player_pos+\$width}=" ";
}
}
else{
if(\$map{\$player_pos+2*\$width}==" "){
\$map{\$player_pos+2*\$width}="\$";
\$map{\$player_pos+\$width}=".";
}
else{
\$map{\$player_pos+2*\$width}="*";
\$map{\$player_pos-\$width}=".";
}
}
}
if(\$map{\$player_pos+\$width}==" "){
\$map{\$player_pos+\$width}="@";
}
else{
\$map{\$player_pos+\$width}="+";
}
}
return(\$map);
}

/*

# = wall
\$ = crate
. = place
* = crate in place
@ = man
+ = man in place

*/

\$width = 8;
\$map = "  ###     #.#     # #######\$ \$.##. \$@#######\$#     #.#     ###  ";
for(\$x=1;\$x<=100;\$x++){
echo echo_map(\$map,\$width);
\$possible = echo_possible_directions(\$map,\$width);
echo "Possible directions: \$possible";
\$new_dir = \$possible{rand(0,strlen(\$possible)-1)};
echo " - going ".\$new_dir;
\$map = move(\$map,\$width,\$new_dir);
if(is_solved(\$map)){
echo "S";
}
}

?>
```

And this is the result:

Feel free to do something interesting with the script…

215 GAME PROTOTYPES EXPLAINED WITH SOURCE CODE
// 1+2=3
// 10000000
// 2 Cars
// 2048
// Avoider
// Ballz
// Block it
// Blockage
// Bloons
// Boids
// Bombuzal
// Breakout
// Bricks
// Columns
// CubesOut
// Dots
// DROP'd
// Dudeski
// Eskiv
// Filler
// Fling
// Globe
// HookPod
// Hundreds
// InkTd
// Iromeku
// Lumines
// Magick
// MagOrMin
// Maze
// Memdot
// Nano War
// Nodes
// o:anquan
// Ononmin
// Pacco
// Phyballs
// Platform
// Poker
// Pool
// Poux
// Pudi
// qomp
// Racing
// Renju
// SameGame
// Security
// Sling
// Slingy
// Sokoban
// Splitter
// Sproing
// Stack
// Stairs
// Stringy
// Sudoku
// Tetris
// Threes
// Toony
// Turn
// TwinSpin
// vvvvvv
// Wordle
// Worms
// Yanga
// Zhed
// zNumbers