Packdude v1.0.XX documentation

[ Python Module : packdude ]

Contents


1. Introduction

1.1. What is Packdude

Packdude is nothing more than just a game. Just a regular game like all other games out there. In fact this is even a lame game, it is just a Pacman clone. But at the same time, it has something that gives it much more power than any Pacman clone has ever had. It is most powerful and sophisticated scripting language. ;) That gives this game a great flexibility and allows you to build extremely powerful and complicated adventures complete with different graphics, animations sounds and music. If you like you can build the game as just regular arcader or if you have more fantasy why not to back this thing up with interesting and exciting story.

Packdude is designed for people who want to create, but also for people who enjoy cool two/player activity on their linux box. If you think you belong to one of those two groups then I hope you enjoy my creation and if you find something missing or something annoying, let me know.

1.2. How does it work

It uses quite different system from the normal games or even programs. Normal programs usually come in one executable what does all the thing from reading the configuration files to handling game logic. Packdude doesn't come in executable. It comes in a library (packdudemodule.so) instead, what does the low level functions and handles the general game logic. To get these things working one needs a python script what calls functions from that library. Sounds scary and complicated, doesn't it. In reality it's not so. The Python is really trivial to learn, and I have made the functions to use really simple and basic. Here is an example:

	# This is a comment
	# Very simple missionpack file
	# 
	# Created by JP  on 24th Feb 2003
	# 
	# Bla bla bla
	
	from packdude import * 

	init_system()
	
	load_tileset("mygfx/winter.pcx")
	load_animators("mygfx/winter.anm")
	load_map("mymaps/test.map")
	
	game_main()
	
	shutdown_system()
This is really simple example, in reality things are bit more complicated, you might want to enable music and sounds, display images, menus and other neat things. This thing only loads tileset, animations and map and starts the game. If game finishes for some reason (user quits, lives run out or the level is finished) the gamesystem is shut down (memory is freed, gfx modes are restored) and program exits.

2. Important keys

2.1. Map editor

2.2. Graphics editor

2.3. Animator

NOTE: Animator is NOT yet complete. It works, but not really good.

2.4. Tile selector

NOTE: You can drag around tiles to displace them!

2.5. Game

There might be other keys too...

3. Tag system

NOTE: You don't need to pad numbers with zeros. I use it here only cause it looks better that way...

3.1. The principle of enemies

  1. First digit in enemy tag is 1 (as in 100). This shows the game that user wants to see the enemy there.
  2. Second digit represents enemy type. See table below.
  3. Third digit represents enemy tile offset. First tile in three tile sequence is calculated with following formula: digit * 3 + 6. In another words when the digit is 3 then first tile is 3 * 3 + 6 = 9. Other tiles used in the animation are then 10 and 11.
As you see, you can use up to ten different looking enemies in one tileset. This takes exactly 30 tiles. BUT, if you don't use so many enemies you can use those tiles for whatever you like. Only three first enemy tiles are marked in tile selector. This is cause it's quite normal that user wants to have atleast three different enemies on the map. Ofcourse you can use more, but it's not too common that anyone uses less, so only three are marked.

Enemy looks and behaviour isn't any way connected. Enemy behaviour is modified by second digit in tag. See table below. So you can have several same looking creatures on map, behaving totally different, and several different looking creatures behaving the same. ;)

NOTE: Different enemy tiles don't have to be in a row. You can put any other tiles in those places too in case you just don't use enemies with that tile offset digit. For example, when you use tags like 1?3, 1?4, 1?5 for enemies, you have other places free for other things.

3.2. Enemy types

Slow

0 = Confused wonderer (random)
1 = Commanded wonderer (left)
2 = Commanded wonderer (right)
3 = Manic chaser
4 = Guard (left - right)
5 = Guard (up - down)

Fast

6 = Confused wonderer (random)
7 = Commanded wonderer (left)
8 = Commanded wonderer (right)
9 = Manic chaser

That's right, there is no fast guards. Sorry. :/

EXAMPLE: Let's take an enemy tag 125. It will create an slow commanded wonderer (2) with tiles 21, 22 and 23.

3.3. Run python string

Most powerful thing in the tag system is the set of RunPythonString tags. These evaluate a short (32 byte) Pyhton string each time someone is discovered in that sector. The 32 byte limit might sound rediculously small, but this is really all you need. You can define the function itself in the game file, and later on call only that function from the map file. Anyway it's not intelligent to write too long scripts as they might take too long time to execute and may cause breakups in the game.

The string also may contain magic symbol '%i' three times. The first %i will be replaced by the number of creature on the sector. Second with x coordinates of the sector and third one with y coordinate. For example let's say creature number 1 (what happens to be the number of second player) steps into the sector at coordinates 10x, 13y. If the string for this sector is:

do_evil_stuff(%i, %i, %i)

Then it will be passed to Python as:

do_evil_stuff(1, 10, 13)

You can leave out some or all %i's if you want to, but you can't access coordinates without also getting player number. If for example you need only the y coordinate of the array, but none of the other things you still have to define them in your function, but you just don't have to use them.

NOTE: The function is evaluated every time something is found from that sector. If a player or enemy is standing on the sector this function is called on every logic update what kindof means 60 times in one second. ;) If this behaviour is not desireable then you should use some sort of variable to make sure that function won't be called several times, or even better set the corresponding block tag to 0 with set_block().

There also are timers, what can be useful to use timing events like restoring the sector after some time or things like that. You can get more info about stuff like that in the right section.


4. Important things to know

Tiles marked in tile selector are special. If your maps don't use certain number enemies then you are safe to use those tiles for something else. Otherwise they will be used for enemy animation. Tile nr 255 is marked EMP, it means "empty" and it should be always left that way. Game uses this tile as empty tile. You can put some graphics to that slot, but it's not very intelligent. Try it out, and see what happens. ;) Nothing to worry really, as you know: *you can displace tiles with simple drag'n'drop in tile selector. (SPACE)*

You can check the block tags in maped by entering tag display mode by pressing M. You can get back by pressing M again.

Currently built in number of players (that includes players and enemies) is 20. If you try to put more of those things on map the game will evilly crash. ;) I still don't recommend you to put more than 10 enemies on map. It will make the map fuzzy, and difficult to play, not to mention that many players make game run slower.


5. Teleporters

To make a teleporter you just have to make two blocks with same tag from the 40 to 49. Teleporters don't yet work perfectly. When they are placed in the center of field they might not work when entered from some positions if you create a some sort of hole for teleporter, it should work nicely.

###   # - Blocking cell (20)
#T    T - Teleporter
###

6. Configuration

Packdude has powerful configuration system. And that both for players and developers. This section explains some details of this sophisticated yet simple to use system.

The game has built in databases for storing integers and 32 character strings what can be accessed with very simple functions. As there are two separate databases there are two separate classes of functions for the thing, these are functions beginning with 'cfg_' and others beginning with 'scfg_'. Only difference between those two is that scfg_* functions work with string database and cfg_* functions with integer database. As they are so similar of nature I am going to explain only cfg_* functions to detail in this chapter.

Every directive changes something in the game, for example if we give the command cfg_set("gfx_fullscreen", 1) then the game runs on fullscreen. (Which is default anyway) if we give cfg_set("gfx_fullscreen", 0) it switches to windowed mode if possible. So you can see the functions are pretty self explanatory. 0 is false and everything other than zero is true. And the configuration strings make sense aswell. To get list of them use included utility packdude-cfgls.

NOTE: Right now (1.0.03) not all configuration strings are working, and some are allready obsolete. I am working on this.


7. Knowng bugs

I have been writing this code for about a year now, and I started it when my C skills were worse than bad. Strangely enough parts of this thing can even be called bit less than elegant but still usable. But there are many bugs also... Let's list few...


8. FAQ

Q: I have seen you mentioning AS in many places, what that means?
A: AS is acronym for Artificial Stupidity. ;)

Q: Is Packdude game or library?
A: I am afraid that it is still a game. It looks like a library or Pyton module, but in reality it is too highlevel to be a library. It is a game, but it just uses different approach. Most programs create their own sophisticated interfaces with lots of buttons and bars. I just picked the Python as a interface, what leaves me a lot of energy to develop the game itself and gives much more power than buttons or scrollbars ever could.

Q: I made a Python script that does some cool stuff when any creature steps into one perticular sector, I wrote the function name to block callback box but when I run the game... Nothing happens.
A: It is very likely that you forgot to include parentheses. You wrote "my_function" instead of "my_function()". If this is not the case then there might be the same bug as with teleporters (see the fix in teleporters section).


9. Library reference



These functions are those what you can call from your Python scripts
to design new missionpacks or even new games. Ofcourse you can use your
own functions or standard Python ones. These are those what control the
game, and set up the library functions.<p>

	from packdude import *
	

9.1. System functions


init_system()

[ returns int  ]
CALL THIS THING FIRST!!! Initializes the system.   

shutdown_system()

[ returns int  ]
Shuts down the system. Last thing to do.   

9.2. Game functions


game_main()

[ returns int  ]
Starts up the game

returns:
  
  0 - User exit
  1 - Player die
  2 - Mission complete

player_die(number)

[ returns void  ]
Kills the player responding to number.   

9.3. Map functions


edit_map()

[ returns int  ]
Enters the map editor   

load_map(fname)

[ returns int  ]
Loads map file pointed by fname

Returns an integer by the following table:

  0) OK (Map loaded/saved sucessfuly)
  1) Not valid map file
  2) Unsupported map version
  3) File not found or disk read/write error 

save_map(fname)

[ returns int  ]
Saves map file to file pointed by fname. Error codes are same as in the
previous function. I doubt that this function really has any use here. ;)

block_set(x,y,tag,tile,cmd)

[ returns int  ]
Sets the block tag, tile and command pointed by x and y. If you want to
leave one of the things intact then pass negative interger to the tag. It
works for tile and tag, but for cmd you have to pass string containing 
zero. Zero as ASCII zero "0" (48) not zero code "\0" (0). If you pass zero
or empty string the block command will be set to empty string. Also you may
just omit the last parameter.

Returns zero (and prints error message to stderr) on error and non-zero on
success. 

block_get_tile(x,y)

[ returns int  ]
Gets block tile number.

Returns tile number in range 0 to 255. If x or y coordinates are out of grid
the zero is also returned, but also error message is printed to stderr.

block_get_tag(x,y)

[ returns int  ]
Gets the block tag. Everything else is similar to block_get_tile() function.

block_get_cmd(x,y)

[ returns char * ]
Gets block command. On error returns empty string and prints error message to
stderr.

9.4. Tileset functions


load_tileset(fname)

[ returns int  ]
Loads the tileset. Returns zero if it fails and non-zero if it succeeds.   

9.5. Animator functions


load_animators(filename)

[ returns int  ]
Load animators.

Return codes are the same as of the load_map() function.

save_animators(filename)

[ returns int  ]
Save animators

Return codes are the same as of save_map() function.

9.6. Music functions


music_load(fname)

[ returns int  ]
Load music file. Format may be one of those

 - .MOD (protracker/fasttracker modules)
 - .S3M (screamtracker 3 modules)
 - .XM (fasttracker 2 modules)
 - .IT (impulse tracker modules)
 - .MID (MIDI files)
 - .RMI (MIDI files)
 - .SGT (DirectMusic segment files)

Retuns zero on errror and non-zero on success

music_free()

[ returns void  ]
Frees the music. You don't have to call it before loading another song, the
system does it for you   

music_play()

[ returns int  ]
Self commenting   

music_stop()

[ returns int  ]
Self commenting   

music_order_get()

[ returns int  ]
Self commenting   

music_row_get()

[ returns int  ]
Self commenting   

music_order_set(i)

[ returns int  ]
Self commenting   

music_pause(i)

[ returns int  ]
If you pass non zero to this function it will pause the music. Passing zero
will unpause it.

9.7. Configuration array functions


cfg_get(key)

[ returns int  ]
This function gets value out of game configuration array in the memory.

Returns integer found under the key or 0 when the key is not found. Note that
zero will be returned also if the value exists but is set to zero so I don't
recommend you to rely on this. (If key is not found in array the message
about this is printed to stderr).

Read more about configuration arrays in corresponding chapter.

cfg_set(key,val)

[ returns int  ]
This function sets some value represented by key to value indicated by val.
Note that this system supports only integer config variables. For strings
see scfg_* functions.

Funcion returns zero if the key is not found (and message about it is printed
to stderr) and non-zero otherwise.

Read more about configuration arrays in corresponding chapter.

cfg_ls()

[ returns void  ]
List contents of configuration array. Not very useful thing to use in
programs, but meant for missionpack writers or game players to get
information about current configuration directives, as this manual doesn't
talk about them all.

The list is printed to stdout.

Read more about configuration arrays in corresponding chapter.

scfg_get(key)

[ returns char * ]
Gets entry from scfg array, what is the same as cfg array but entries here
are strings rather than integers.

Returns string containing the value or empty string if no entry by that key
was found and prints error message to stderr. Also returns empty string if
entry is found, but the value is empty string. Quite logical, isn't it. ;)

Read more about configuration arrays in corresponding chapter.

scfg_set(key,val)

[ returns int  ]
This function sets some value represented by key to value indicated by val
in scfg array. In another words the same thing as cfg array but for strings.
Note that maximum size for the value is 32 characters. If you try to pass
more than the scfg string is left unaltered and error message is printed to
stderr.

Funcion returns zero if the key is not found or val is larger than 32 bytes
(and message about it is printed to stderr) and non-zero otherwise.

Read more about configuration arrays in corresponding chapter.

scfg_ls()

[ returns void  ]
List contents of scfg array. Not very useful thing to use in programs, but meant
for missionpack writers or game players to get information about current
configuration directives, as this manual doesn't talk about them all.

The list is printed to stdout.

Read more about configuration arrays in corresponding chapter.

9.8. Timer functions


clear_timers()

[ returns void  ]
Clears all timers   

timer_add(num,cmd,time,autoremove)

[ returns int  ]
Add a new timer to the timer pool. You can add up to 32 timers to slots
from 0 to 31 (indicated by num). They run a command (32 character string)
after time in the "time" argument has elapsed. The time is given in ticks,
there is hundred ticks in one second. The optional autoremove argument shows
whether to remove the timer after the call has been made.

Returns zero if the timer could not be set (reason is printed to stderr)
and non-zero if the insert was successful.

Timer functions are active only in game, and are paused while game is in
pause mode.

timer_remove(num)

[ returns int  ]
Remove timer.

Returns zero if timer is allready inactive and non-zero if the remove was
sucessful. Also returns zero if request for invalid timer slot was made, but
then there also will be error message sent to stderr.

timer_reset()

[ returns void  ]
Reset all active timers

This doesn't remove timers, it only restarts them.

timer_ls()

[ returns void  ]
List currently active timers.

Not very useful thing for anything really, but added for completness and some
debugging.

Data is print to stdout.

9.9. Simple Interface Creation (SIC) functions


sic_clear()

[ returns void  ]
Clear all the SIC structures including all images and zones.   

sic_image_load(num,fname)

[ returns int  ]
Load image to SIC pool to slot num. You can insert up to 32 images to pool at
once, in another words num can be in range from 0 to 31. Fname must be valid
path to JPEG file on HDD.

If image allready exists in this slot it will be replaced.

Return zero on some on error (and error message will be printed to stderr) or
non-zero on sucess.

sic_image_free(num)

[ returns int  ]
Frees the image in slot num.

Returns zero on error (and prints error message to stderr) and non-zero on
success. Note that non-zero is also returned if the request is made to free
image what is allready free.

sic_image_put(num,x,y)

[ returns int  ]
Put image on screen. The x and y coordinates are interpreted as left top
corner of image.

Note that this function can be only used if SIC is active (sic_do() is
called). And that means you can call this function only from zone mover
and mout callbacks. 

Returns zero (and prints error message to stderr) on error and non-zero
on success.

sic_zone_clear()

[ returns void  ]
Clears the SIC zone table

sic_zone_add(num,x1,y1,x2,y2,mover,mout,click)

[ returns int  ]
Adds zone to SIC zone table (ztab) to slot num. You can define up to 32
zones in the table. Next four parameters give the two opposite corners of
the rectangle to define the zone. And last two parameters define two
callback python strings what will be run if mouse enter the sector (mover) 
and if mouse exits the sector (mout). Note that first if the interface is
intialized the system calls mout strings for _all_ active zones in the ztab,
so you shouldn't do much else than just put images on screen.

mover and mout commands may include up to three symbols '%i' what will be
replaced with (in this order): number of zone, x coordinate of top left
corner of the zone and y coordinate of top left corner of the zone. These
things should aid you a little on the creation of interfaces.

Returns zero on error (and prints the message to stderr) on error and
non-zero on success.

sic_zone_remove(num)

[ returns int  ]
Removes zone from ztab.

Returns zero on error (and prints message to stderr), and non-zero on
success. Note that non-zero is also returned if the slot is already
inactive.

sic_do(background)

[ returns int  ]
Starts the SIC interface. Before calling this you have to initalize atleast
one zone and atleast one image. The background is the image in the SIC image
pool what will be used as the background of the current interface.

Function doesn't return before user has clicked in one zone. (Or pressed
escape). It rerturns the number of the zone where user clicked or 0 if error
occured or user pressed escape. On error the message is also printed to
stderr.

9.10. Sound sample functions


sound_load(num,fname)

[ returns int  ]
Loads sound sample to internal sound pool. You can load up to 32 samples.
The file can be one of WAV, MP2, MP3, OGG or other similar formats.

Returns non-zero on success and zero on error. Error message is also
printed to stderr.

NOTE: Check sample_* configurations to see what samples some events in the
game use.

sound_free(num)

[ returns int  ]
Frees the sample. You don't have to call it before loading new sample
to slot. sound_load() does it automatically for you.

sound_clear()

[ returns void  ]
Free all samples.   

sound_play(num)

[ returns int  ]
Play sound.   

sound_stop(num)

[ returns int  ]
Stop sound.

Be careful with this. If the sample isn't playing the thing may give 
unexpected results.

sound_attr_set(num,frequency,volume,panning)

[ returns int  ]
Set attributes of sample. 

It includes frequenzy, volume and panning. They are all in the scale
of 0 - 255. If you want to leave some of those things untouched while 
setting others pass -1 to arguments you don't want to change.

Note that this thing won't affect the sample while it is playing but
only when it starts playing after making this call.

Returns zero (and prints message to stderr) on error and non-zero
on success.

sound_freq_get(num)

[ returns int  ]
Get sound frequency.   

sound_vol_get(num)

[ returns int  ]
Get sound volume.   

sound_pan_get(num)

[ returns int  ]
Get sound panning.   

9.11. Miscellaneous functions


add_datapath(path)

[ returns void  ]
Add path where to find datafiles. Up to 16 paths can be defined by
multiple calls to this function.

pd_f(path)

[ returns char * ]
Find file on datafile search paths. All functions loading any data
should use this. For example load_music(pd_f("mymusic.xm"))

pd_fw(path)

[ returns char * ]
Find file on datafile search paths and make sure that the file is
writable. If it doesn't find any files by specified name then it
looks up first writable directory and gives path to nonexisting file in
this directory. Useful for saving files.

prompt(question)

[ returns int  ]
Prompts the user for question and provides the dialog box with yes and no
aswers. Returns zero if user hits NO and non-zero otherwise.

select_file(title,extension)

[ returns char * ]
File selection dialog. Returns the filename selected or zero if user
pressed cancel. Note that internal buffer of this thing is 1024 byte
file paths longer than this will be truncated.

set_video(depth)

[ returns int  ]
Sets the video mode. This function is automagically called by all other
functions that need video mode change. But if you need to reset
fullscreen windowed mode for example then calling this function with
the same color depth as using is neccesary.


10. Authors/Contact

The library interface is written by Jaan Pullerits. But as this game is very expandable, I am not responsible for all games or missions based on the system. So please be sure to check the original author of the missionpack before contacting me for a bug, as it may aswell be in the the missionpack instead of program itself.

Jaan Pullerits (jaan@surnuaed.ee)


11. Copyright

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA