Consider the following world
Does the program written previously work with it? Try it!
As you probably guessed, if you didn't try it (you should, really!), it does not. To make it work, we need to replace the if we just added by a while. Try it! Make sure to save it.
We seem to have designed a program that works in all situations we are likely to encounter. This program, before we forget, is to allow Reeborg to explore his world, going around once. While the program is rather short, and its structure should be clear at this point, it might not be so obvious to someone who just happened to see it for the first time. It's probably a good idea to either add comments and/or introduce more meaningful words. Let's start by adding comments, somewhat more verbose than we think we might need.
# we define a useful instruction def turn_right(): repeat(turn_left, 3) # we mark the starting point by putting down a beeper put_beeper() # We then find a clear direction and start moving. while not front_is_clear(): turn_left() move() # We know we have gone around the world # when we come back to the beeper we put down. while not next_to_a_beeper(): if right_is_clear(): # keep to the right turn_right() move() elif front_is_clear(): # move following the right wall move() else: # follow the wall by turning left turn_left() turn_off()
While this sort of clarifies our intent for each instruction, it is not really that helpful in summarizing the method (also known as the algorithm) used in solving the problem. Therefore, these comments might not be as helpful to another reader as we might have wished. Reading over the comments, we note that the program has two parts:
1) mark the starting point;
2) follow the right wall until we come back to the start.
Let's rewrite this program so that these two parts become clearer, and writing the comments differently.
# This program instructs Reeborg to go around his world # counterclockwise, stopping when he comes # back to his starting point. def turn_right(): repeat(turn_left, 3) def mark_starting_point_and_move(): put_beeper() while not front_is_clear(): turn_left() move() def follow_right_wall(): if right_is_clear(): turn_right() move() elif front_is_clear(): move() else: turn_left() found_starting_point = next_to_a_beeper # beeper marks the starting point. #=== End of definitions; begin solution mark_starting_point_and_move() while not found_starting_point(): follow_right_wall() turn_off()
Isn't this clearer? Now, suppose that each corner has a beeper on it at the start. We could then choose to mark the starting point by removing a beeper. We would need to make some small changes in the definitions, but the solution as such would not need to be changed.
Try the program you just wrote and save with the following hurdle race (file: hurdles3.wld).
Surprise! Other than finishing facing in an unusual direction (perhaps bowing to the crowd after winning), the program we just wrote can solve the hurdle problem. It also works with the uneven hurdle (file: hurdles4.wld) illustrated below - which the program we wrote before for jumping over hurdles could not handle!
You might even note that we don't need mark_starting_point_and_move() in this case. Because we structured our program clearly, it would be very easy to remove that instruction, and its definition, and save the program under a different, more descriptive name (racing_hurdles perhaps).
Try the same program again with the maze problem we introduced in chapter 1 (file: maze1.wld), illustrated below.
As you will see, our simple program can find the exit to this maze! Amazing! Once again, we note that we have a superfluous instruction.
We started with a simple problem to solve (going around a rectangular world) and, by improving little by little (also called stepwise refinement), we manage to write a program that could be used to solve many other apparently unrelated problems. At each step, we kept the changes small, and made sure we had a working solution, before considering more complex problems. We also used more descriptive names for parts of the algorithm which made the program easier to read and, hopefully, to understand. This is a strategy you should use when writing your own programs: