/* PATH_TO_MOVES.P */ section path_to_moves => path_to_moves; /* SPECIFICATION ------------- This module defines a routine for converting a path, expressed as a list of points, into a list of bug moves. You supply it with the path and the bug's initial heading, and it returns a list of actions, and a new heading. PUBLIC path_to_moves( heading, path ) -> new_heading -> moves: 'heading' must be a unit vector giving the bug's current direction. 'path' is a list of points. Each point must be horizontally or vertically adjacent to the next. The routine returns two results, the new heading, also as a unit vector, and a list of moves. Each element of this is a word, one of "left", "right", "forward", or "back". Example: path_to_moves( [0 1], [ [1 2] [1 3] [2 3] [3 3] [3 2] ] ) -> d -> moves; d=> moves=> gives ** [0 -1] ** [forward right forward forward right forward] */ /* IMPLEMENTATION -------------- The routine works by taking pairs of points at a time, subtracting them to give a direction, and calculating the turn needed to convert the bug's current heading into this direction. This is done using routines from VEC.P. This module comes with a file HELP PATH_TO_MOVES. Make sure the two are kept in step. */ needs vec; vars path_to_moves_1;/*forward*/ define path_to_moves( dir, path ); lvars path, dir; lvars dir1, p, q, rest_path; if path matches [=] then []; dir else path(1) -> p; path(2) -> q; tl(tl(path)) -> rest_path; vec_sub( q, p ) -> dir1; path_to_moves_1( turn2(dir,dir1), dir1, [ ^q ^^rest_path ] ); endif; enddefine; define path_to_moves_1( move, dir, rest_path ); lvars move, dir, rest_path; lvars new_dir, rest_moves; path_to_moves( dir, rest_path ) -> new_dir -> rest_moves; if move = "forward" then [ forward ^^rest_moves ]; new_dir elseif move = "back" then [ left left forward ^^rest_moves ]; new_dir else [ ^move forward ^^rest_moves ]; new_dir endif; enddefine; endsection;