Listing 4. Full Maze Program import planner. action(State, NewState, Action, Cost) ?=> (R, C, (ExitI, ExitJ), Walls, Doors, Keys, K, (HeroI, HeroJ)) = State, select((HeroI, HeroJ), Keys, NewKeys), Action = $take_key(HeroI, HeroJ), Cost = 1, NewState = (R, C, (ExitI, ExitJ), Walls, Doors, NewKeys, K + 1, (HeroI, HeroJ)). action(State, NewState, Action, Cost) => (R, C, (ExitI, ExitJ), Walls, Doors, Keys, K, (HeroI, HeroJ)) = State, ( Di = 0, Dj = 1 ; Di = 0, Dj = -1 ; Di = 1, Dj = 0 ; Di = -1, Dj = 0 ), NewHeroI = HeroI + Di, NewHeroJ = HeroJ + Dj, NewHeroI >= 1, NewHeroI <= R, NewHeroJ >= 1, NewHeroJ <= C, ( % move to open cell not membchk((NewHeroI, NewHeroJ), Walls), not membchk((NewHeroI, NewHeroJ), Doors), Action = $move(NewHeroI, NewHeroJ), Cost = 1, NewState = (R, C, (ExitI, ExitJ), Walls, Doors, Keys, K, (NewHeroI, NewHeroJ)) ; % open a door and move to that cell K > 0, select((NewHeroI, NewHeroJ), Doors, NewDoors), Action = $open(NewHeroI, NewHeroJ), Cost = 2, NewState = (R, C, (ExitI, ExitJ), Walls, NewDoors, Keys, K - 1, (NewHeroI, NewHeroJ)) ). final((_, _, (I, J), _, _, _, _, (I, J))) => true. main => R = read_int(), C = read_int(), Walls = [], Doors = [], Keys = [], (ExitI, ExitJ) = (_, _), (HeroI, HeroJ) = (_, _), foreach (I in 1..R) Line = read_line(), foreach (J in 1..C) Char = Line[J], if Char == '@' then HeroI := I, HeroJ := J end, if Char == 'X' then ExitI := I, ExitJ := J end, if Char == '#' then Walls := [(I, J) | Walls] end, if Char == '|' then Doors := [(I, J) | Doors] end, if Char == '=' then Keys := [(I, J) | Keys] end end end, InitState = (R, C, (ExitI, ExitJ), Walls, Doors, Keys, 0, (HeroI, HeroJ)), best_plan_unbounded(InitState, Plan), println(Plan).