Amzi! Quick Tutorial

This section is a tutorial introduction to the Amzi! Prolog development tools. It is not intended to be an introduction to Prolog. If you need an introduction to the Prolog language we recommend Adventure in Prolog.

The tutorial makes use of a simple adventure game, Duck World, to illustrate how to use the Amzi! tools to build complex applications. Accordingly, it is composed of a number of files.

(Why Duck World? Because Amzi! inc. was located in an old farm house backed up on conservation land. We bought ducks out of whimsy one day, which were later discovered by the fox in the woods. The ducks proved to be an adventure.)

The tutorial demonstrates both the command-line and the Amzi! Eclipse IDE interfaces to Amzi! Prolog.

This tutorial starts by testing some of the basic predicates of Duck World in the listener. It then goes through the full example, showing how the program is modularized, how it is compiled and run using the listener, and how it is linked into a distributable application.

The source code for Duck World can be found in the samples/prolog/ducks sub-directory.

Quick Tutorial Contents:

Duck World

An adventure game is a simulation of an environment, real or imagined, that the user explores, usually with some goal in mind. Duck World is a simple adventure game, where the objective is to go from the house, through the yard, to the duck pen to get an egg, and back to the house again, without losing any ducks to the fox.

The commands for manipulating the environment are all entered as legal Prolog goals (ending in periods).

They are:

  • goto(X) - moves you to place X, where X can be either house, yard or pen.
  • take(X) - takes something if it's where you are; the egg is the only thing you're supposed to take.
  • chase(ducks) - how to get the ducks back in their pen.
  • quit - this, or any illegal command, will quit the game for you.
  • When you have brought the egg into the house the game ends.

    Starting the Listener

    Amzi! Prolog programs can be run in interpreted mode using one of two different methods:

    To start the listener from the operating system command-line, type the input shown in the left box. To do this within the IDE, select the menu items shown in the right box. General instructions are given in italics.

    The IDE supports multiple perspectives. A perspective is an arrangement of views on the screen. For developing Prolog code, we will use the Amzi! Prolog and the Debugging perspectives. Perspectives are also available for C++, Java and many other languages and capabilities. A view is a window on the screen. Each view can optionally have its own tool bar and menu. Examples of views are the Project Navigator, Listener, editors and Outline.

    Command-Line alis Amzi! Eclipse IDE
    c>  alis
    Double-Click on Icon for the
    Amzi! Eclipse IDE
    Run / Listener
      or
    ?- button

    The copyright message will be displayed followed by the prompt, ?-

    Amzi! Prolog <version information>
    Amzi! Prolog Listener
    Copyright (c)1987-2002 Amzi! inc. All Rights Reserved.
    Type  'quit.'  to exit
    ?-

    You are now in a Prolog listener, which is awaiting your command. Try out this classic, being careful to remember the single quotes and the ending period.

    ?- write('Hello World').
    Hello World

    Note: You can use the up and down arrow keys in the IDE listeners to bring up the prior commands you typed in and edit them.

    To exit the listener, type "quit."

    Creating a Source File

    Before looking at the Duck World source code, create a small experimental file called dw.pro.

    Command-Line alis Amzi! Eclipse IDE
    Use an editor to type in your code
    Save your file as dw.pro 
    Create a Prolog Project
    File / New / Project / Prolog
    Enter the project name: duckworld
    File / New / File
    Enter the file name: dw.pro
    Type your code into the window
    File / Save 
      or
    Save Button

    Type the following lines of Prolog code into dw.pro:

    :- dynamic loc/2.
    % Experiments nextto(house, yard). nextto(yard, pen). loc(you, house). move(Place) :- retract( loc(you, _) ), assert( loc(you, Place) ).

    In the IDE, you will see an outline for your Prolog code to the right of the editors. There is also a cross-referencing tool available in the view with the same name. To run the Cross Reference for your project, press the Refresh button or select the Refresh command from the Cross Reference View menu (a view menu is the menu under the black, down-facing triangle in the upper right corner of the view).

    Consulting a Source File

    To play with dw.pro, consult it into the listener as shown:

    Command-Line alis Amzi! Eclipse IDE
    ?- consult(dw).
    yes
    Run / Run As / Interpreted Project
      or
    Run / Run As / Interpreted Single File

    You are now in the listener with dw.pro consulted.

    Using the Listener

    Now that you've reached the listener, make sure your file was consulted by using listing.

    ?- listing.

    This will show you the predicates of dw.pro, although they will look a little different because the variables are renamed with an _X and a number, e.g. _X0.

    You can try various queries from the listener.

    ?- loc(you, X).
    X = house

    You can test move.

    ?- move(yard), loc(you, X).
    X = yard
    ?- move(foobar), loc(you, X).
    X = foobar

    Because move doesn't check to see if the move makes sense, you might decide to add a goto predicate with more intelligence. You can enter it directly in the listener using add.

    ?- add.
    |  goto(P) :-
    loc(you, X),
    nextto(X, P),
    move(P).
    |  quit.
    ?-

    This is a useful technique for quick experiments, but the code typed in the listener is not entered into your source file. Because we want goto to be part of the game it is best to type it directly into the source file and then reconsult it.

    This can be done by moving from the listener to the editor. You can use the built-in IDE editor, or invoke the editor of your choice. You can use reconsult/1, or exit out of and restart the listener.

    (You need to reconsult, rather than consult, because consulting will simply add a second copy of your program to the Prolog workspace. Listing would show two of every predicate.)

    Command-Line alis Amzi! Eclipse IDE
    Edit dw.pro in an editor
    then in the listener:
    ?- reconsult(dw).
    yes
    Edit dw.pro in its window
    File / Save
      or
    Save Button
    ?- reconsult(dw).
    or type 'quit.' in the listener then:
    Run / Run As / Interpreted Project

    You can then test it.

    ?- goto(yard).
    yes
    ?- goto(pen).
    yes
    ?- goto(yard).
    no

    It didn't work right, which leads to the next section.

    Debugging

    goto lets you get into the pen, but doesn't let you get back out. In order to figure out why, you need to start the debugger and set-up the state required for testing. The steps are performed in a different order depending upon whether you are using the command-line or IDE. Note, starting the debugger takes you out of the Prolog Perspective and displays the Debug Perspective instead. You can switch back to the Prolog Perspective with Window / Open Perspective or by pressing on the Paw button on the left, vertical tool bar.

    To make sure the game is in the state required for testing, enter the goals to place you in the pen. The listener gives you the ability to dynamically adjust the state of your application, effectively putting you in the middle of it. This, by itself, is a powerful tool for debugging.

    You can now trace the execution of goto(yard) to see why it is failing. To do this you also need to start the debugger. Type:

    Command-Line alis Amzi! Eclipse IDE
    ?- retract(loc(you, _)), assert(loc(you, pen)).
    yes
    ?- debug.
    Type 'quit.' in the listener then:
    Run / Debug As / Interpreted Project
      or
    Run / Debug As / Interpreted Single File
    ?- assert(loc(you, pen)).

    The command line debugger is line-oriented, and is controlled from the keyboard. In the IDE, a separate debugger perspective is opened, which is controlled with the mouse. You enter your normal interaction with the program in the debug listener window.

    Next, type in the goal to be traced at the listener's debugging prompt ??- or ?- for the IDE.

    ??- goto(yard).

    To step through the Prolog code type:

    Command-Line alis Amzi! Eclipse IDE
    ? c
    Alternatively
    ? [Enter]
    Click on the 'Step Over' button

    Here is what the trace looks like for goto(yard). In the IDE you will see only the current call stack. You can click on any entry in the stack to see the associated variable bindings in the Variables view. Also in the IDE, the current line in your source file will be highlighted. The color of the highlight indicates if it is a call, redo, fail or exit.

    Calling: goto(yard)
    CALL:(1) goto(yard)    ? c
       Calling: loc(you,H64)
       CALL: loc(you,pen)    ? c
       EXIT: loc(you,pen)    ? c
       Calling: nextto(pen,yard)
       FAIL: nextto(pen,yard)    ? c
       FAIL: loc(you,pen)    ? c
       FAIL: loc(you,H64)    ? c
    FAIL: goto(yard)    ? c
    FAIL: goto(yard)    ? c
    no

    To leave the debugger:

    Command-Line alis Amzi! Eclipse IDE
    ??- quit.
    Click on the 'Stop' button

    The trace reveals that, although we've defined nextto(yard,pen), we haven't defined nextto(pen, yard). To get our program to work, we need a predicate that equates the two. The solution chosen for Duck World is the predicate connect/2, which is used instead of nextto/2 in the goto/1 definition.

    connect(X, Y) :- nextto(X, Y).
    connect(X, Y) :- nextto(Y, X).

    This code can be added to the source file and the development process continues. This is the normal way to develop a Prolog application. Predicates are gradually added to the source file as the application grows. The application can be tested at any point during the development process and individual predicates can be tested and their execution traced to understand why the application is working the way it does.

    Modules

    As an application grows, it is natural to want to break it up into modules. At the simplest this means splitting the predicate definitions among various source files. These files can be consulted together and the application run from the listener.

    However, it is often preferred to keep some of the predicates hidden within a file and to allow only certain predicates to be called from other source files. This is done with a variety of directives that define modules and the predicates that are imported and exported from them. See modules for details.

    In the directory samples/prolog/duckworld there are two versions of Duck World. 'duckym.pro' has all of the modules in one file. It is also broken up into three files for purposes of illustration here. The three files, and their modules, are:

    The files have many comments that explain the use of modules in Prolog.

    Running a Modular Application

    You can run the modularized Duck World from inside the listener by consulting it and calling main/0, the predicate that starts it running. (You can also call any of the other predicates of Duck World to see if they're working and trace them if they're not.)

    ?- consult([dw_main, dw_rules, dw_data]).
    ?- main.
    Welcome to Duck World
    Go get an egg
    >> goto(yard).
    You are in the yard
    >> .....

    Using Projects in the IDE

    You created a Prolog Project file (.project) in the IDE as described above. You can modify the project's properties by right-clicking on the project and selecting 'Properties'. These properties include:

    Anytime you start the listener, all the project files (except the exclusions) are automatically consulted for you. Also when you build a project all the source files and libraries are compiled and linked as needed into an executable file (.xpl).

    Compiling

    Compiling Duck World is easily done:

    Command-Line alis Amzi! Eclipse IDE
    c>  acmp dw_main
    c>  acmp dw_rules
    c>  acmp dw_data
    Project / Build All
      or
    Project / Rebuild All

    Note, under the IDE we simply build the project. This causes all the modified source files in the project to be recompiled.

    acmp can also be invoked with no arguments, in which case it will prompt you for the names of the files. See the Compiler section for more details.

    The result of compiling is Prolog object files, in this case, dw_main.plm, dw_rules.plm and dw_data.plm.

    Linking and Running

    To build a stand-alone application first create a Prolog load module (.xpl file) with the Amzi! Prolog linker, alnk.

    Command-Line alis Amzi! Eclipse IDE
    c>  alnk dw dw_main dw_rules dw_data
    Project / Build All
      or
    Project / Rebuild All

    Note, under the IDE when a project is built, it is linked to create an .xpl file.

    Using alnk, the first argument is the name of the .xpl file. The next two files are the .plm files that are linked together.

    The .plm files are linked with abin/alib.plm, the Prolog portion of the Amzi! runtime engine, to form an application.

    Alnk can also be invoked with no arguments, in which case it will prompt you for inputs. See the Linker section for more details.

    To run Duck World, just type:

    Command-Line alis Amzi! Eclipse IDE
    c> arun dw
    Run / Run As / Compiled Project

    Instead of typing arun dw, you can create a copy of arun(.exe) and name it dw(.exe). It will then, after examining its own name, automatically run dw.xpl. So the application can be started simply by typing dw.

    Distributing an Application

    If you decided to distribute Duck World, then to do so, you need these files for command-line environments:

    For applications where Prolog is embedded in another tool/language, then dw(.exe) is not necessary.

    Interfacing with Other Tools

    You can enhance the Prolog engine with your own built-in predicates written in C/C++, Java, Delphi or Visual Basic.

    For example, you might want to use a graphical interface for Duck World with quacking ducks and the like. In this case the Logic Server API allows you to either extend the Prolog language with graphics predicates written in C/C++ that are called directly by the Prolog code, or to write the user interface to the code in C/C++ (or Visual Basic under Windows) and call embedded Prolog for the logic. You can combine the techniques, both extending and embedding Prolog in the same application.

    The section on the Logic Server API tells how integrate Prolog with other languages.

    Copyright ©1987-2011 Amzi! inc. All Rights Reserved. Amzi! is a registered trademark and Logic Server is a trademark of Amzi! inc.