-
Content Count
13,060 -
Joined
-
Last visited
-
Days Won
21
Posts posted by DZ-Jay
-
-
Added text for 8 levels and implemented the return from state/level (but I need to make it depending on input! now is just moving from one page to other to the end :-))
Also I changed the colors to green on black.. is this the best choice?
I have also a box template made... but this is too early to show :-)
one nice add would be using self made fonts.... this I know is possible but again too much work to do... so just an idea
Hey, Valter, I'm back home! Let's get this puppy on going. I'm going to review the P-Machinery code right now just to freshen up on it, and will see how we can best tackle your tasks.
Let's concentrate on a few at firsts. What are your current tasks or issues? I can then help you with sample code or something.
In the meantime, I'll post the missing "pause.asm" file in the other P-Machinery thread for you and others.
-dZ.
what I need now is:
- implement the waiting loop of 3 seconds, that I use in the welcome screen and maybe somewhere else (TASK
- integrate the audio tracker to start a forevew song from level1... the song I have to translate, but I would use the one of the trackerdemo for now (demosong) just to see if it's working
- add you in the credits for the much help you provide :-)
pause.asm what is made for?
Valter,
I'll be sending some sample code within the next few hours for those tasks and some instructions and suggestions on how they could be implemented using P-Mach.
The "pause.asm" allows you to pause and un-pause a scheduled task during execution. Normally, you can either Start a scheduled task, or Stop it. This module offers routines that allow you to Pause the task temporarily. When you Un-Pause it later, it will continue ticking down from where it left off.
It is useful, but not necessary. I just include it for completion's sake, since my Christmas Carol and Pac-Man games use it.
An example of it's use: When a Christmas Carol level starts, a timer is engaged to release the Snowman. However, every time Carol eats a "magical snowflake," it gives Carol the ability to avoid danger by confusing the enemies. Consequently, I "pause" the Snowman attack timer temporarily while the snowflake's effect is on, and then un-pause it when the invulnerability period ends.
The result is that, as long as Carol eats snowflakes, the Snowman's attack is delayed.
-dZ.
-
I like the green text on a black background.
Maybe you could find a publicly available 8x8 font that you could adapt and use. I think the Jupiter Ace rom has been released into the public domain. It had an 8x8 font I think... Just a thought.
Would the colossal cave purists be offended if the text included lower case letters? I find lower case letters easier to read, but I realize that the original game was probably all upper case...
I like the green on black, but perhaps you can try with the brighter green and see how it looks?
Regarding fonts, that's simple: Just load the character set into GRAM and you can still use the PRINT routines included in the SDK-1600, by setting the offset from GRAM in the attributes word. You would need letters, numbers, and some punctuation, which shouldn't take more than about 40 GRAM cards. Unless you want mixed-case, which takes considerably more.
Attached is a simple font set I created originally for Christmas Carol, before I decided to stylize them. They are a bit boxy, but less so than the built-in ROM font.
Use it freely as you wish.
-dZ.
-
1
-
-
Hey, guys! I'm back! Attached is a copy of the missing "pause.asm" file. You should put it along with "taskq.asm," "wait.asm," and "timer.asm," for it is part of the TASKQ library.
-dZ.
-
1
-
-
Added text for 8 levels and implemented the return from state/level (but I need to make it depending on input! now is just moving from one page to other to the end :-))
Also I changed the colors to green on black.. is this the best choice?
I have also a box template made... but this is too early to show :-)
one nice add would be using self made fonts.... this I know is possible but again too much work to do... so just an idea
Hey, Valter, I'm back home! Let's get this puppy on going. I'm going to review the P-Machinery code right now just to freshen up on it, and will see how we can best tackle your tasks.
Let's concentrate on a few at firsts. What are your current tasks or issues? I can then help you with sample code or something.
In the meantime, I'll post the missing "pause.asm" file in the other P-Machinery thread for you and others.
-dZ.
-
is this done in simple way by the procedure WAIT from timer.asm?
I set the WTIMER and call WAIT but everything stop, like the timer never expire...
No. WAIT is a routine Joe used in 4-Tris to pause for a specified time waitin for an event. I don't recall right now it's use, but its application was rather narrow. You are better off using STARTTASK.
dZ.
-
By the way, you should not make any infinite loops when using P-Mach. Let the game engine framework do that for you.
-
Valter,
Your problem is that you broke out of the P-Mach game loop and made your own infinite loop.
Also, you are calling the tracker update routine on "realtime" when you should be calling it only once per frame to keep time.
P-Mach makes this quite easy. In fact, I can give you the code I use in Christmas Carol to update the music tracker. I removed it from P-Mach but I guess it could be kept in there.
I'm at the airport right now, on my way home. I'll be able to offer code samples and more concrete help by tomorrow morning.
dZ.
-
I need to lower some expectation due to the complexity of the coding, in fact pausing the music is not easy to implement, it's easier I guess to stop the music and restart it.. but at the moment all this is far from my capacities so I set more simple milestones for my project.
- INTRO: implement welcome screen disappearing after few seconds
- INIT: implement background music by integrating the Chevallier tracker, this should loop forever
- PLAY ENGINE: implement level to level to show several text description when pushing the disc or a key (like pages of a book)
- PLAY ENGINE: implement input from keypad (8 directions, and disc touch)
- PLAY ENGINE: implement text input from keyboard
- PLAY ENGINE: implement the parser to reconnaise text commands inserted
- CONTENTS: include all the booktext and reconnaisable words
- SCORE: how to implement scoring??
Pausing the music is simple: you stop updating the tracker state.
There's a routine from Arnauld's tracker that you need to call periodically to update the tracker state. You stop calling that routine for the duration of the pause.
You also need to quiet out the PSG (sound chip)
By setting the volume register to zero. I'll send you some code later this week when I return.
About key input, if you're expecting to use the controller, then P-Mach offers a decoder for that. You just need to write the logic for what to do on each key.
Regarding scoring, you can just define a global variable. Check out the constants files, there may be one already defined.
Also, check out the text file included in the docs directory of P-Mach. It offers at least an introduction of the theory behind P-Machinery. It is not finished, but it is a start.
dZ.
-
thanks a lot!
I'm using begin and return it seems working... so I move from a page to the next now
I want to introduce a 3 seconds pause in the first page.. is this done by the timer.asm task somehow?
Yes. You use the STARTTASK routine. It starts a timer for the specified time. When the timer expires, a function you specify will be added to the task queue. It will then be executed at the end of the next game loop cycle.
Note that the timers are all counted in frames per second, which are 60 Hz on NTSC and 50 Hz on PAL. To pause for three seconds, you set the timer to 60 x 3, or 180 frames. The ISR interrupt is the heartbeat of the game engine.
STARTTASK is part of Joe Zbiciak's SDK-1600. For more information on how to use it, you can read the comments on the code. P-Mach offers some macros to simplify its use, but I can't recall them right now, sorry.
Just a note on its use: STARTTASK is intended to deal with recurring and one-off timers in one single interface. One-shot timers are disabled after they expire, while recurring ones are re-scheduled automatically every time they fire. The way it tells the difference is that recurring timers have an even number of frames, and one-off timers have an odd number. Moreover, the scheduler decrements the counter by 2, so you must multiply your timer times by 2. For instance, in your example you need 180 frames, so you set up your timer for (60 x 3 x 2) -1. The minus one is to turn it into an odd number, for a one-shot.
And one more note. You'll notice that STARTTASK accepts two timer counts. The first one is the initial delay, the second is the re-schedule time. For one-shots, you ignore the second one and just use the first one. For recurring, you set them both. The initial delay allows you to set the recurring timer to start after a short delay instead of immediately. It will then reoccur on the period of the second timer.
dZ
-
Additional confusion :-)
I'm just after the title screen
I'm in the st_level section..
inside ST_LVL_INIT, if I write some text onscreen like
CALL PRINT.FLS
DECLE C_GRN, $0200
STRING 'WELCOME STRANGER'
BYTE 0
it works and proceed to SET_GAME_STATE
If I try do to the same by calling a PROC, like
CALL LEVEL_INTRO
where the proc is the following:
LEVEL_INTRO PROC
CALL PRINT.FLS
DECLE C_GRN, $0200
STRING 'WELCOME STRANGER'
BYTE 0
ENDP
the proc is called but it does not come back to ST_LVL_INIT and stop there.... I need to add some return command, but IRET or TRET make the game freeze with black screen.... what it's wrong?
Valter,
IRET and TRET are macros to encapsulate terminating a procedure.
IRET returns from an interrupt routine, or ISR. It gives control back to the EXEC at the point that the ISR was called. If you notice, it is at the end of all the state handling routines like ttl_init.
TRET returns from a task queued with TASKQ. It gives control back to the task manager.
These return routines are abrupt shortcuts. That is, they have return addresses hard-wired to labels, and consequently alleviate the need to keep track of the return address or to push one into the stack.
For regular purpose code, Groovy's example should work. The CALL operation puts the return address into R5, so you cannot touch that register during your procedure. If you need to use it, you'll have to save the address somewhere temporarily. Typically this is done by pushing it into the stack with PSHR. You then pop it to return.
The operations BEGIN and RETURN do this for you. They are the same as saying,
PSHR R5 ; save return address
...
PULR R7 ; pop the return address into the instruction pointer
By the way, if you look at the macro definitions, they are well commented. They all include a boilerplate header that explains their function and usage.
dZ.
-
If I understand, after Title I move to ST_LVL_INIT
from this to level to level?
In fact in my case I need a new level for each text page, when I press a direction I should go to next level(page).... this code implement only one level and tape the text according to the direction..... I should modify so that taping a direction I call next level instead of printing the direction... it's lot different... and messy for me :-)
Valter,
Printing the direction is done as a demonstration of using the controller input decoder.
The input decoder accepts a table that contains "callback" routines for each controller event. For instance, when a keypad key is pressed the routine at the entry in the table for the keypad will be called automatically.
The same happens for disc input. I think the value in R0 (I'm not sure which register right now, sorry) corresponds to either the key or disc direction pressed. The code should specify I the comments.
P-machinery does not have a concept of "levels" per se, so it is open to many types of games. The term "level" may be used in the code, but it is just a vestige of working on Pac-Man. It actually represents the "game-play" state, as opposed to the title screen or game-over states.
For most part, you'll only need three states: title screen, game-play, and game-over.
Once the game enters "game-play" state, the P-Mach state machine should remain there until the player dies. You could add more states, but it is not really necessary.
An example of an extra state is Christmas Carol's intermission screens between levels. It requires special game logic that does not really qualify as "game-play" since it is autonomous.
Keep in mind that each "main" state can be sub-divided in up to 8 sub-states. This allows you to break up, say, the title screen state into something like init, draw, and wait for input.
As an example, consider that the "game-play" state in Christmas Carol is broken down into:
- init level
- play level
- replay level (after player death)
- end level (after completion)
- end game (after last death)
- wait for input.
In the case of a text adventure, I would imagine that you could treat the many rooms like I treat the levels on Carol. In that case, the "game-play" state could be broken up into:
- init room
- wait for input
- process command
- exit room
- player death
You wouldn't need a new state per room, you just keep that state of your world in variables and update them as the player moves from room to room.
That's just an example, of course.
Once I return later this week, I can offer more concrete examples and even code samples.
dZ.
-
I'd like to share info about the progress of this project from time to time... and of corse receive hints and help from devs out there :-)
be patient with me.
first, I'll spend sometime to set up the environment and make the P-machinery game engine run.
second thing, I found what I believe is the complete text contents of the original game on a repository so I will have idea about dimension of the porting
Valter,
Are you planning on using P-Mach for your Colossal Cave project?
I guess it would work. However, there are a couple of things that P-Mach won't do for you, and you'll have to handle them on your own.
First is that P-Mach offers routines to read the controller keypad and the disc, but does not decode the ECS keyboard. That will need to be added. Extending the controller routine with custom decoders is actually quite simple.
Second, you'll need a routine to emulate a command-line, accepting a character at a time, and processing the command when "enter" is keyed.
Third, you'll need a parser and tokenizer. This interprets the ASCII text code strings and allows you to operate on them.
For instance, if the player types "GET LAMP," the interpreter needs to know that the letters G, E, and T represent the verb "get" and correspond to the command "get object." Likewise, the letters L, A, M, and P then need to be interpreted as the noun "lamp," corresponding to the "lamp" object. Only then would your game be able to add the lamp object to the inventory and update the state of the game accordingly.
These things may not be that hard, but they do require some effort.
The good thing is that you only need to write them once and use them for all different commands and actions.
dZ.
-
Valter,
I forgot to say that there is a routine in the SDK-1600 called CLRSCR that clears the screen. It does this by setting all BACKTAB cards to "blank" with a specified background colour.
You can call that routine from the appropriate point in the "st_title.asm" module. It should have a name like TTL_INIT, or something like that (I'm sorry but I can't recall right now).
That should change the background colour at the same time as it clears the screen and leaves it ready for you to draw your custom title screen.
dZ.
-
Ok
the code is running now.. let's move to something a bit more serious :-)
I want to use a custom title screen
the code I have to modify is all inside state/st_title.asm ?
how do I change the background green color?
Ah, great!!
In st_title.asm you'll see comments where it says things like "here you draw custom title screen."
I sorry Valter, I am not at home right now and can't see the code, but when I return I can help you better. I expect to return by Thursday.
To change the background colour, you need to iterate through the BACKTAB (background table) and change the colour of each card (or tile).
For information on what is the BACKTAB and how it works, I suggest you check out the IntelliWiki.
Basically, the screen is composed of 20 columns by 12 rows of "cards," which are just 8 by 8 pixel character tiles.
Each card can have a background and a foreground colour, and display a tile from either GROM or GRAM. The GROM contains the built in fonts and other graphic elements. GRAM offers a 64 tile buffer for custom cards.
dZ.
-
I get error messages for const/ctrl.const
invalid opcode
referring to DEFINE_ENUM(CTRL_KEYPAD, 12)
this command is described in the macro/enum.mac, so whay is not working?
That error is because it is treating a macro as an instruction, and it's failing.
Can you confirm that enum.mac is included properly? This is very strange. There was someone else in the IntvProg that was able to assemble and run the demo, so I assumed it was fine.
Can you please post the resulting listing file?
for whatever reason the error disappear (I did nothing) but now I have error calling SET_GAME_STATE, see the listing file I send to you (too long to be posted here
thanks
That's another macro.
-
I get error messages for const/ctrl.const
invalid opcode
referring to DEFINE_ENUM(CTRL_KEYPAD, 12)
this command is described in the macro/enum.mac, so whay is not working?
That error is because it is treating a macro as an instruction, and it's failing.
Can you confirm that enum.mac is included properly? This is very strange. There was someone else in the IntvProg that was able to assemble and run the demo, so I assumed it was fine.
Can you please post the resulting listing file?
-
Guys,
I indeed use the bleeding edge as1600 assembler that comes with Joe's development kit. Though I'm not sure if the version will matter so much as the SDK libraries.
The "pause.asm" is a recent addition to the TASKQ library. Joe and I worked on it as a means to pause/unpause tasks in the task queue during game play. He intended to add it to the next version of the SDK-1600, but he may not have done it so far.
In any case, you can comment the include from the P-Mach code. The demo does not use it, though it is good to have as part of your game tool kit.
I'll post here a copy of "pause.asm" when I return, but just ignore it for now.
dZ.
-
My criticism is valid. There are some bugs in the game that are distracting, and the control decoding has very little angular tolerance, which may be acceptable on a 4-way stick, but for a round disc is unconscionable. To say that it is better that the 40 year old Exec games at 20 Hz is a cheap shot--most anything is.
That you react so defensively to any other critique on this thread is a bit disconcerting. A simple "I'm sorry you feel that way, but I disagree" would have been more tactful than telling your audience how wrong they are.
As I said, DK Arcade overall is good. The criticisms arise precisely because it is so faithful to the original.
I was mostly criticizing the George Lucas style of re-hashing a once popular work with some modifications, over and over, for the purpose of milking more money from a dedicated audience with minimal creative investment.
Releasing the new version so soon after the first one gave this impression, unwarranted as it may be.
I said I hope the Intellivision home-brew scene does not turn into that. More importantly, I admire your work and would hate it degenerate into that. If this is not your case you have no reason to get offended.
dZ.
-
I'll probably buy D2K, for I like to support the Intellivision home-brew scene, but I hope that this release-before-it's-done, resell-later-the-complete-version-for-more-money does not turn into a trend to milk the dedicated collector's community.
As it stands, I feel a bit cheated. I paid for DK Arcade, and was disappointed in the controls and some of the graphics glitchiness, but thought it was still a good game, overall. But to think I have to pay again to get the game I thought I bought is a bit of a put off.
dZ.
-
Like GroovyBee, I also do not think text adventures are suitable for the Intellivision.
If you are thinking of porting classic, old-school games, you'd be better off choosing something like the old Sierra graphic adventures, such as King's Quest, Space Quest, or dare I say... Leisure Suite Larry.
In those games, text input was limited to "verb noun" constructs, but the story developed graphically, by the actions of the characters and the environments. Plus you got to move your avatar around with a controller, like a regular video game.
Alternatively, you could use the SGI user interface of the later versions of Sierra adventures, where the "verbs" were represented by icons on a menu, and you just "pointed-and-clicked" the item you wanted to operate on. Sort of like the SCUMM interface of LucasArts (Monkey Island, Maniac Mansion, etc.), but simpler.
For bonus points you could imement both! That way, people with the ECS can enter more complex commands than the point-and-click SGI interface would allow on the normal version.
dZ.
-
sorry, I started looking for your p-mach
I have tedious questions :-|
when I try to compile the pmach-test asm, I got error because (I guess) compiler cannot find some include files.... what is missing?
I suppose it's missing
- cart.mac (??)
- gimini.asm (this one is into the jzintv /library right?)
- util.mac (this one is into the jzintv /library right?)
cart.mac comes from intelliwiki I think:
http://wiki.intelliv...?title=Cart.mac
util.mac is from jzintv/examples/macro/util.mac
gimini.asm is from jzintv/examples/library/gimini.asm
ohi ohi
I addedd all the 3 files in the folder but still cannot compile.....
I get error "The program needs Include dependencies: you must save it in IW folder or a sub folder"
I guess those are still missing (I cannot find in jzintv library nor intelliwiki)
INCLUDE "task/taskq.asm"
INCLUDE "task/timer.asm"
INCLUDE "task/pause.asm"
The task folder is in jzintv/examples/task
. My copy doesn't have pause.asm in it. Maybe I don't have the latest version....
pause.asm is the only one I miss
still having the same error message...
the problem is something else I guess because even deleting the include of pause.asm I have same error...
DZ-Jay can you help???
Valter,
First, I'm sorry I haven't responded. I'm away dealing with a family crisis and have limited Internet access.
Regarding your issue, the pause.asm is a new library file to be added to the SDK-1600, but perhaps it's not there yet.
I don't have the file with me right now, I can send it to you when I get home in a few days.
Also, I'm sorry for the messy set up. In my development machine I have all set up with environment variables so that they are all accessible. I guess my code assumes this setup.
I'll make sure to fix that and to include better instructions when I return.
What is other errors you get when assembling?
-
8 directions, seriously?
-
that is all good technical information. enjoyed reading it. i still go with my lamens term of the carts being ntsc. although from the technical side is it just more that the pal/secam systems werent designed properly to begin with?
Pimp,
In layman's terms you are right, most carts are produced for NTSC systems and to heck with the PAL quirks.
I wouldn't say that the PAL/SECAM systems were not designed properly. I would just say that the programmers didn't make the effort to make their games work with PAL/SECAM systems as intended. Remember, most were American enterprises, with American programmers, thinking (as is unfortunately common) in an American-centric way.
dZ.
-
Since the STIC (video chip) used in the Intellivision needs to periodically and very regularly read graphics data in order to maintain a stable signal to the television, this makes it ideal as a timing governor for games. Therefore, games are coded in a way that leverage the regular STIC clock signal to time events, such as regular enemy AI logic or player movements--and it is especially convenient to control the interval of music notes and sound effects timing. This is a standard technique used in many old game consoles, including early PC games.
As you may know, the TV signals in the USA and Europe are different. The NTSC video standard used in television sets in America runs at 60 frames per second, while the PAL standard used in Europe, runs at 50 frames per second. The impact of this difference on Intellivision games is that timers will run slower in PAL consoles, since the "heartbeat" of the game is running at a slower speed.
Moreover, there is an even bigger, but more subtle, impact: for technical reasons a clock circuit of the PSG sound chip in the Intellivision is also synchronized with the STIC clock in a special way. In order to lower the frequency of the clock in the STIC to support the PAL 50 fps timing, the internal clock of the PSG needs to be lowered too. This causes the PSG to generate tones at slightly lower frequencies on PAL machines. This shouldn't be a problem, after all you just need to tell the PSG which frequencies to use to generate tones and they will be at the same pitch in any case.
However, the games were traditionally developed primarily for the US market, by US-centric programmers. So, look up tables that specify which PSG codes translate into which actual musical tones, were designed from an NTSC perspective. The result is that the wrong codes are used on PAL machines causing the PSG to play slightly different tones than intended.
These differences were caused not only by oversight at first, but also by technical and business reasons. Supporting exactly equal NTSC and PAL game versions requires the maintenance of two separate codes, separate testing of the two, and separate production of cartridges. It would also necessarily result in different cartridges that would only play well on their specific target market, and inventory overhead to keep track of them individually.
When confronted with these additional efforts and costs, and balanced against the actual practical downside of not applying them, the decision becomes clearer: so the games in Europe play a bit slower and sound a bit off-key; they still play fine and are enjoyable. It's not optimal, but it doesn't critically impact the game.
It is not impossible to build a single game that works exactly the same on both standards, it just takes some effort and some clever programming. I believe Arnauld Chevallier's games are a good example of this.
dZ.
-
2
-

P-Machinery Theory
in Intellivision Programming
Posted · Edited by DZ-Jay
I thought I'd include some basic theory on the use of P-Machinery, in lieu of writing an actual tutorial and guide (which I truly plan on doing, I swear!).
Overview:
P-Machinery is a simple game engine and programming framework for making Intellivision games. It is not a game designer wizard nor a full-feature development kit, but more of a programming model to simplify making games. It does include some basic infrastructure that takes care of a lot of under-the-hood housekeeping, letting the programmer concentrate on actual game-play logic.
P-Machinery uses an event-driven and task-driven model for the programmer. The game engine tugs along in the background, looping indefinitely, and whenever certain conditions or events arise, the specified handlers are executed.
This means that you don't have to worry about iterating through lists of tasks or figuring out how to put it all together--you just define your events by scheduling tasks or adding them to centralized game state handlers, and the appropriate code will be called at the right time.
A Simple State-Machine:
At its core, P-Machinery is a state machine that describes the various states in which your entire game could engage. By default, P-Machinery includes only three basic states. These should be sufficient for most games, but you can easily add more. The three basic states are:
These three states are sub-divided into various sub-states. For instance, the "Title Screen" state can be sub-divided into "Initialization," in which the title screen is drawn; "Wait," in which the screen is just frozen, waiting for user input; and "End," in which the tittle screen is cleared and the game is engaged. Engaging the game means switching internally from the "Title Screen" state to the "Game-Play" state. P-Machinery provides handy macros and procedures to encapsulate state transitions and a simple dispatch table where you define the individual handlers for each of these states and transitions.
The Task Queue:
The most important part of P-Machinery is the Task Queue. This is the mechanism that P-Machinery uses to manage all game events, states, and scheduled tasks. In order to take advantage of this, you'll need to start thinking of your game as a series of tasks, or events, on which the game logic should react.
Let's consider a simple example, say, Pac-Man. If we break Pac-Man down into a series of reoccurring events, we end up with the following model:
On every game-loop iteration, we must:
By itself, P-Machinery does not do any of these. However, it offers a handy, built-in game-loop that calls a built-in routine on every iteration. This routine by default does absolutely nothing but enable the video display and update the video chip's registers to their latest values.
You can easily update this built-in routine with your own code to do the above. However, rather than just writing all that code in-line, you could create individual routines for each task and just add them to the queue. They will then be executed in the order they were added (FIFO, or First-In, First-Out).
Now, each of those tasks can result in changes to the game state. Consider the second to last task, "Check if a collision occurred." What if Pac-Man collided with a Ghost at this very point? Well, your collision detection code can then add another task to the queue that will update the game state from "playing" to "dying." P-Machinery will then update its own internal state and on the next game-loop iteration the "Pac-Man Death" handler will be engaged.
That way, you do not need to write code to connect one piece of logic to another. Instead of thinking in terms of a straight flow of logic, such as "if Pac-Man collided with Ghost, then we must do this...," you should think in terms of actions and reactions, events and handlers:
You break down the logic into small individual tasks, and write short, concise functions to handle each one. When the conditions are right, you add the appropriate function to the task queue, and let P-Machinery process them.
An Example:
An example of this event-driven model is Christmas Carol's "collision detection" logic. The collision logic is broken down into the following routines:
On each one of these, a set of tasks are added to the queue depending on special conditions. For instance, after PICKUP_PRESENT detects an actual collision, it sets up the following tasks:
In addition to these tasks, if Carol happened to pick up the last present, the game-state is changed to "Level End." This disengages the "Game Play" state. P-Machinery will then call the defined state handler for this new state, and the end-of-level logic is executed.
-dZ.