AGI for Newbies Chapter 3 - An Introduction to Logic

From AGI Wiki
Jump to navigationJump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Tutorials and Guides Table of Contents
AGI for Newbies Index

Page: 1 | 2 | 3

 

An Introduction to Logic
By Nat Budin and Dark Fiber


Page: 1 2 [ 3 ]


 
A few words about the interpreter

Scrolly.png
The "scrolly" example in this chapter


The AGI interpreter works in cycles. This means that the interpreter executes the current Logic not just once, but many times. Here's an outline of what happens in each interpreter cycle:

  • The interpreter delays for a specified amount of time. The delay is different depending on what speed the game is set to run at. Faster speeds mean shorter delays. On "Fastest" speed, there is no delay.
  • The interpreter clears the keyboard buffer. This means that if any keys were pressed and for some reason were not accepted by the game, the game forgets about them at this stage.
  • Interpreter flags 2 and 4 are set to false (more on flags further down).
  • The interpreter polls the keyboard and joystick to accept new input.
  • The interpreter handles the direction that the ego (main character) should be facing.
  • The interpreter recalculates movement for animated objects.
  • The interpreter updates the status display (score and sound on/off).
  • The interpreter calls Logic 0 (more on this further down).
  • The interpreter updates objects on the screen.

This is not a complete listing of what goes on in each stage. For more information about it, check the AGI Specifications ("How The Interpreter Works").

 

Programming in an AGI game

The AGI programming language, Logic, is a scripting language. High level scripts are compiled into byte-code which is interpreted by the game interpreter. The interpreter gives you access to up to 256 compiled scripts. Each script has global access to 256 8-bit unsigned variables, and 256 Boolean flags.

 

Logic Files

You have 256 Logic files available for you to use. The way Sierra used Logic files, and the way the AGI Studio template is set up to use Logic files, is that each room in the game has its own Logic file, which helps for tidier programming. In that sense, you can have up to 256 rooms. Some Logic files are special to the interpreter, Logic 0 being the example. Logic 0 is what runs the entire game. Logic 0 is used to 'call' your other Logic files. (For C and C programmers, it's your main loop. Logic 0 can be likened to having a re-entrant main() function.)  Logic 1 is set up to be your 'introduction' system, and Logics 90 through 99 are set up to perform other game functions, like initialization, debugging, and death handling.

When a AGI game is first started:

  • Logic 0 is executed, which calls Logic 1.
  • Logic 1 plays the introduction of the game.
  • Logic 1 then jumps to the first room in your game, which is by default set up to be Logic 2.
  • After the first cycle, Logic 0 is set up to call the Logic of your current room.

 

Flags and Variables

All flags and variables can be accessed by any script (0-255). If you need to pass information between one script and another, you have to use variables and flags. Flags are Boolean and store 0 or 1 (True or False). When a flag is set to True, we say it is "set."  When you set a flag to False, you can say you have "reset" it. Flags are good for storing simple information in. Instead of using a variable to just store a 0 or 1, you can use a flag. But, like Logic files, some variables and some flags are used by the system. Your best bet is not to use any flags or variables under 40 for yourself.

For example,
You are in an old belfry. Dangling right in front
of your face is a tattered and frayed rope.

You want the rope to break after the player pulls it. There are several ways you can code this, as with any language, you are not locked into any one way of programming it.

You have a flag  "fPulledRope", at the start of the game it is set to False. When the player types in "pull rope" you check to see if "fPulledRope" is False, and if it is, you can set it to TRUE and then say "the rope breaks." The next time the player tries to pull the rope, checking "fPulledRope" is set to True, you can say "Sorry, the rope is broken and you can't reach what is left of it dangling to pull it."

In that scenario a flag was good, as the rope only had two states, pulled and not pulled. What if you wanted the rope to break after the player had pulled it three times?  Obviously a flag is not enough to hold 3 different states, so using a variable would be best.


A quick less technical recap on flags and variables, flags are good for storing single state items, on or off. Variables are good for counters and multiple state items.

Example

A tutorial on Logic programming is not much good without examples, is it?

First off, we'll program something simple, such as using a message box to show numbers. We'll create a popup message box in the middle of the screen that has the contents of the variable 40.

We'll use AGI Studio and create a blank game, create the directory called test-01 and hit OK. Next click on the "Logic editor" icon.

In that Logic type:

Code:
return();

and save it as Logic 0.

Now above that return we can put our code.

The code for our little problem is quite simple, you need one print statement, one goto, one if, and one quit. To find what these statements mean, look them up in the AGI Studio help file.

How did you go? A very easy exercise, I know. This is my solution.


Code:
inner_loop:
print("%v40"); /* our message box command */
v40++; /* increment our variable */
    if(v40!=255) { /* test our variable */
    goto(inner_loop); /* jump if it’s not 255 */
}

quit(1); /* quit program */
return();

The syntax here should be familiar to you if you know C or C . If not, here's a line-by-line breakdown of the code:

  • Line 1 is a label command. It sets up a point to jump to later in the program.
  • Line 2 tells the interpreter to put a message box on the screen containing the value of variable number 40.
  • Line 3 adds 1 to the value of variable 40 and stores the result in variable 40.
  • Line 4 tests to see if variable 40 has a value of 255.
  • If variable 40 does not have a value of 255, then line 5 tells the interpreter to jump back to line 1. If variable 40 has a value of 255, then line 5 is skipped.
  • Line 8 tells the interpreter to quit. The 1 means to quit right away. If the command was quit(0), then the interpreter would ask the player, "Do you want to quit?"
  • Line 9 is not really necessary in this program, because the interpreter can never reach line 9 because of the quit(1) statement in line 8. However, in most cases, return(); tells the interpreter to return to Logic 0.

OK, now that's done, I want you to make a copy of that example. Alter the code so that the message box closes after 1/2 a second. (HINT: Look up "special variables" in the AGI Studio help.)

Code:
reset(f15);      /* set message box to use timed closure */

inner_loop:
  v21=1;      /* set message box to close after ½ second */
  print("%v40");
  v40++;
  if(v40!=255) {
    goto(inner_loop);
  }
 
quit(1);
return();


"Ok, No more sissy examples," I hear you cry!  Right-o, how about something far more complex without being really complex?  Try to code the scrolling credits of the Kings Quest 1 intro, obviously without the graphics of course. Still think it's easy? It is!  It has some heavy use of variables though.

How did you do? (Without looking at the actual code from Kings Quest 1!!)  This is my solution (there are others possible):
 

Code:
#define speed v10
#define new_room f5
#define start_line 10
#define start_col 10
#define end_line 14
#define start_msg 20
#define end_msg 35

#define cur_line v40
#define cur_col v41
#define cur_msg v42
#define begin_msg v43

if(new_room)
{
  speed=12;
  set.text.attribute(15, 0);
  clear.lines(0, 24, 1);
  cur_line=start_line;
  cur_col=start_col;
  cur_msg=start_msg;
  begin_msg=cur_msg;
} 
 
inner_loop:
  cur_msg=begin_msg;
  begin_msg++;
  if(begin_msg==end_msg){ begin_msg=start_msg; }
  cur_line=start_line; 
  clear.text.rect(10, 9, 13, 31, 0);

  jump_01:
    display.v(cur_line, cur_col, cur_msg);
    cur_line++;

    /* increment message number, wrap if need be */
    cur_msg++;
    if(cur_msg==end_msg){ cur_msg=start_msg; }
 
    /* we only want to print 4 lines of text */
    if(cur_line<end_line){ goto(jump_01); }
 
  if(have.key()){ quit(1); }
return();

#message 20 ""
#message 21 ""
#message 22 ""
#message 23 "  This is our test"
#message 24 "example of a scrolly"
#message 25 "    in AGI Logic"
#message 26 ""
#message 27 "It is supposed to be"
#message 28 "   similar to the"
#message 29 "Kings Quest 1 intro"
#message 30 "  scrolly credits"
#message 31 "only better coz ours"
#message 32 "wraps at the end of"
#message 33 "  the scroller! ^_^"
#message 34 ""
#message 35 ""

 

Page: 1 | 2 | 3

Tutorials and Guides Table of Contents
AGI for Newbies Index

< Previous: Chapter 2 - Nuts and BoltsNext: >