home

GAME ENGINE AND GAME EDITING TOOLS

We could create a game for linux. But instead of trying to make a game, we could try to make a game engine with a set of game editing tools, so that it would be easy for other people to create games for the game engine, and it would be easy for people to borrow things from other games to incorporate into their own games. Hopefully many people would create games for the game engine, and we could collect all the games and distribute the games with the game engine.

Some games already include level editors. However, the level editors are usually not very powerful. The developers usually put most of their efforts into their games, not into their game editing tools. The developers do not really want people to create new games for their game engines which might be better than the developer's games. And if I did create a game for a commercial game engine, the game engine's owner would not want me to distribute the game engine with my game and would not want to distribute my game with the game engine.

Most games have the levels and components compiled into the game engine. It would be easier to borrow things from games if each level, icon, object, enemy, terrain type, etc was a seperate file.

Most people who create games first think of the game they want to create, and then create a game engine to run that game. I am suggesting we do the reverse: first create a flexible game engine, then create games for it. The people who are good at creating game engines may not be so good at creating games, and the people who are good at creating games may not be so good at creating game engines. If we could create a good game engine with good game editing tools, then people who are not good programmers but are good at imagining cool games could create games for the game engine.

A game engine that works like doom would be good, but that would be complicated. A game engine that works sort of like repton would be much simpler and easier. I found repton in the contrib section of my redhat 5.0 cdrom. In repton the board is divided into squares, you move from square to square with the arrow keys, you do not interact with enemies or things unless you are in the same square, interactions with enemies or things occur and are completed instantly as soon as you enter the square.

A vaguely repton like game engine might work as follows. When you start the game, you specify a map file. The map file is a text file which lists the squares on the board, the type of each square, the objects in each square, what square you start in, etc. For each type of square, there should be a text file which describes the properties of the square, what icon file to use to represent the square, what happens if you move into the square, what happens if you move into the square carrying certain objects, etc. For each type of object there should be a text file describing the properties of the object, the large icon file to represent the object in a square, the small icon file to represent the object in the inventory/status display, if the object can be picked up, what happens when you enter the square containing the object, what happens if you are carrying a certain object when you enter the square containing the object, etc.

For example, you could move onto a square which contains a pail of water and pick up the pail of water. Then you could move onto a square with a fire. The pail of water puts the fire out; without the pail of water you would die of burns. Then you could move onto a square which contains an ax and pick up the ax. Then you could move onto a square which contains a tree. The ax cuts down the tree; without the ax you could not move onto the square with the tree. Then you could move onto a square which contains a sword and pick up the sword. Then you could move onto a square which contains a goblin. The sword kills the goblin; without the sword the goblin kills you. Behind the goblin you pick up a pot of gold.

A square which contains a tree could be a square of type tree, which converts to type ordinary when you enter the square with an ax. Thus the game engine be able to convert a square type to a different type, and remember the new type, and write the new type to a new map file if you save the game. On the other hand, a square which contains a tree could be a square of type ordinary which contains an object of type tree. All square properties could be defined as objects; this would probably be simpler and better because then we would not have to worry about square types because all squares would be of type ordinary but with different objects; also we would not have to worry about converting one type of square to a different type of square. When the ax cuts down the tree, perhaps the tree should disappear, or perhaps the tree should become a log which you can carry with you and perhaps use to cross a pit.

Some squares should have the property of unloading the current map file and loading a new map file. Thus you could move onto a square of type stairs_down and go down to the next level. But note that which map file to load is variable; it is not the same for all stairs. Perhaps there should a graphic and/or message to be displayed while changing maps, like 'you are falling down a pit'.

Maybe should should have types of death, so we can have different graphics and different messages depending on how you die. Or maybe the object definition file should include death messages and graphics.

Probably the game should pick things up automatically when the player enters a square. Or maybe there could be an autopickup feature which the player could turn on or off as desired.

Perhaps you should be allowed to carry an unlimited number of objects, but only one object in your hands; when you enter a square, the objects in your pack do not count, only the object in your hands counts. For this to work, there would have to be a way for the player to select which object is in the player's hands.

Maybe the object definition file should include a message to be displayed when you enter a square containing that object. Perhaps the message string should include escape sequences like '\n' for newlin; '\p' for pause; '\w{2}' for wait 2 seconds; \g{foo.xpm}' for display graphic; '\c', '\r', or '\g' for clear messages and graphics and continue game; etc.

Or maybe the object definition file should include a script to run when you enter a square containing that object. Script commands might include display message, pause, display graphic, run external program, clear messages and graphics, etc.

The game should have a lib directory, like /usr/lib/nameofgame or something. The lib directory should have a subdirectory for map files, a subdirectory for object definition files, a subdirectory for icon files, etc. So when a map calls for a certain object, the game searches the object directory for a definition file; this makes it easy for a game to use objects from other games.

Saved games should be stored in the user's home directory, not in the lib directory.

The game engine would be based on simple components; you could make complex games by combining the simple components. The game engine would be simple, but it would support complex games. Besides running boulder dash/rockford/repton type games, the game engine could also run pacman type games, and nethack/moria type games.

A more complex game engine would be harder to create, would be harder to create games for, and would require more and more complex game editing tools. I would vote to keep the game engine simple, because I am not ambitious enough to attempt a complex game engine. But if you want to attempt a complex game engine, do not let me stop you.

MODEM TELCOMMUNICATIONS PROGRAM

In DOS I have used a modem telcommunications program named Rbcomm. Rbcomm does not have scripting functions, but it has macro functions; the macro functions can be used as scripting functions; in fact the macro functions are better than the scripting functions of other modem telcommunications programs. Rbcomm can do several things no other modem telcommunications program can do.

You can type something at the keyboard while a macro/script is running, and what you typed is sent to the modem and on to the other computer without disrupting the macro/script. For example, if you have a script which waits for a prompt, sends a command, then waits for the next prompt; and if the BBS sysop changes the menu structure so that there is now a new prompt before the second prompt; then your script will halt at the new prompt; but with Rbcomm you can type a response to the new prompt, and then your script will continue when the second prompt appears.

Rbcomm allows you to wait for one of several possible prompts, and to branch depending on which prompt was received (it is not easy; you have to set one WAITFOR and several WHENs, and if one of the WHENs succeeds, you have to do LOAD_MACRO to cancel the WAITFOR; but it is possible, unlike other modem telcommunications programs).

Rbcomm allows you to map macros/scripts to almost all keys and many key combinations. Rbcomm also allows you to switch from one set of macro/script key bindings to a different set. Thus you can have one set of hotkeys for one menu and a different set of hotkeys for a different menu. The commands to some task, like logoff, vary depending on what menu you are currently at; you could assign alt-g the logoff command for the current menu, and when you change to a different menu, you could reassign alt-g to the logoff command for that menu.

Rbcomm allows you to run a macro/script while another macro/script is running; thus you can have more than one script running at the same time. (Actually, when I do this I am usually interrupting a failed script and running a cleanup script, and the cleanup script will exit Rbcomm, so it does not matter whether the first script continues or not. Also, it works for some scripts and not for others, I am not sure why. I have not thought of any real use for running more than one script at the same time, but why not?)

To the best of my knowledge, there is no other modem telcommunications program for any operating system which can do these things, except Rbcomm. So how about a modem telecommunications program like Rbcomm, only for linux and without the limitations of Rbcomm?

Rbcomm is designed to run under DOS and use very little memory. A linux program need not be so fanatical about using very little memory, and could allow longer strings and macros. A linux program could have additional features like variables and functions.

The program would need to get input from the keyboard and the modem simultaneously. Unix processes only get input from source at a time, so the program would have to fork itself into several processes; one process would get input from the keyboard and one would get input from the modem. The processes would have to use interprocess communication and shared memory. Perhaps there should be one process for searching for specific strings in the data received from the modem, one process for key bindings, one process for scripts, one process for timeouts, etc.

Rbcomm changes the set of key bindings by loading a new macro file. For linux, it would be better to allow multiple sets of key bindings in the same file, because then it would not be neccessary to access the disk to get the next file.

The linux serial port drivers is not designed for maximum performance; instead it is designed to minimize cpu usage, to make as much cpu time available to other processes as possible. I wonder if it would be a good idea to rewrite the linux serial port driver so that it has two modes, maximum performance mode and minimum cpu usage mode, and then create some IOCTRL or something, so that a user could switch modes as desired.

On the other hand, a modem telcommunications program for linux probably is not a good idea because modems are an abomination, a kludge for moving digital data across an obsolete analog network. It is a horrible way to network computers.

DEVELOPER'S WEB SITE WITH MULTIPLE WEBMASTERS

Suppose several people are trying to work together on a programming project. They have a web site to share their work with each other and with everyone else. In such situations, there is often one person who is the lead developer. The lead developer is the webmaster. The other developers submit patches to the lead developer, who checks the patches and then integrates the patches into the project.

The situation easily degenerates into the lead developer doing all the work, because he would rather be writing code than explaining his vision of the project to the other developers, checking and integrating other peoples' patches, or telling the other developers that they are a bunch of half witted pinheads and he has no use for their idiotic ideas or their asinine patches.

Or the situation might degenerate into the lead developer doing so much administrivia that he never has time to do any of the programming.

So I was thinking we could create some programs with an html interface to do most of the administrivia of several people working together on a project.

The lead developer is the webmaster. Only the webmaster possesses the password which gives complete control over the web site. The webmaster assigns passwords to the other developers; these passwords give them partial control over the web site.

Suppose one of the developers wants to do some work on the project. He goes to the web site and selects download. The download link runs a program or script which creates an archive with the current versions of all the files and downloads it to the developer. The developer makes some changes, then makes a patch and puts the patch on his personal web site. Then he goes to the web site and goes to the form for applying a patch. He fills in his password and the URL of his patch and clicks submit. This runs a program or script which gets and applies the patch, adds the patch to the list of patches, saves copies of the old versions of the files, and maybe runs some kind of sanity check.

There should be an undo page on the web site, where anyone with a password could select any of the patches from the list of patches and have that patch removed, or revert any of the files to any of the older versions of that file.

For resolving arguments, anyone with a password should be allowed to freeze anyone else with a password. Someone who has been frozen can not apply patches, but can still post messages in the discussion area and freeze others. Thus if two of the developers get in a fight, they will probably freeze each other and prevent each other from disrupting the project. Only the webmaster can unfreeze people.

THE DISINTEGRATED OMNICOMPILER

Once upon a time I set out to learn assembly language programming. I thought that learning assembly language would teach me to think like a cpu, and that would make me a better programmer in all languages.

I soon decided that that all assemblers suck, and I began to fantasize about the ideal assembler.

Assembly language does not really teach you to think like a cpu, because assembly language is not organized in exactly the same way as the program created by the assembler. For example, 'mov' is one assembler keyword, but it corresponds to several different cpu opcodes. Assembler directives are mixed into assembly code, but the directives are instructions to the assembler, not instructions to the cpu. You might have a line like 'mov eax,[bx]'; but if you really want to think like a cpu, you need to read that as two cpu commands: use 32 bits instead of 16 bits for next command, copy 16 bits from the address in bx to ax. You might think that looks strange, you might be confused about whether it is copying 16 bits or 32 bits, but that is the way x86 cpus really work. I think that when Intel designed the x86 assembly language, they were not trying to show how x86 cpus work, they were not trying to create a usable computer language; Intel was trying to hide the fact that the x86 instruction set was badly designed. In other words, standard x86 assembly language is not really assembly language; it is really a slightly higher level language. To the best of my knowledge, there is no true x86 assembly language, unlesss you like coding in hex.

So should an ideal assembly language format be the way a cpu really works, or should it be a format which is easy to use and understand? I think the best solution would be to do both. For my ideal assembler, I would abandon the standard assembly language format and invent a new format which works the same as a cpu; I would invent an assembly language format which displays the warts of x86 architecture instead of hiding the warts. Then I would invent a second format which was easy to use and understand. Source code could be written in either format, but usually source code would be written in the easy format, then converted to the cpu-like format by a preprocessor, then assembled into binary format.

If we were to design a new assembly language format, we would have to choose whether to make the keywords long or short. Short keywords would be faster to type, so a skilled programmer could write code faster; however short keywords would be cryptic, so source code would be hard to understand and the language would be hard to learn. Long keywords would be slower to type; however longer keywords could describe what the keyword means, so source code would be easier to understand and the language would be easier to learn. Most programming languages use medium length keywords; this is a compromise between long and short keywords. I think the best solution is to have both long and short versions of each keyword, and to have a program which convert long keywords to short and vice versa. Then an expert programmer could write source code with short keywords, and a nonexpert who wanted to study the source code could convert the source code to long keywords and make the source code easier to understand.

Source code written in standard assembly language format is very hard to understand unless it contains many, many comments; this is also a sign that the standard format is not good.

The macro capabilities of traditional assemblers are not very powerful; you cannot do things like ax=ax+bx or if..then. If we had really powerful macro capabilities, we could assemble source code written it higher level languages like basic, pascal, or C.

I have never seen an assembler with optimization capabilities. For example, in a traditional assembler, when you use a macro you have to remember which registers are used by the macro, and push the registers before the macro and pop the registers after the macro. It would be easier to put the push and pop commands inside the macro, but then your code would be less efficient. If the registers contain no meaningful data, then those pushes and pops are a waste of time. If you have one macro followed by a second macro, then the last line of the first macro might be pop ax, and the first line of the second macro might be push ax; so your program would have pop ax followed by push ax, which is probably a waste of time. But if we had an optimizer, we could make easy macros and let the optimizer clean it up. An optimizer could also do things like change mov ax,0 to xor ax,ax.

With powerful macros and optimization, what started out as an ideal assembler has become more like a compiler for a new high level language. Now the question is, why do I want to create a new programming language and compiler? Why don't I just use C++? C++ already allows us to mix assembly language and higher level functions, and allows us to use alternate formats if we have the appropriate macros (someone told me that a typical distribution of gcc for linux is capable of compiling code in pascal format). But there are several things I do not like about C++.

I do not like prototyping functions. The books tell me that the reason C++ requires prototyping of functions is so that the compiler only needs to read the source code once instead of twice. We do more work so the compiler can do less work. I think that is backwards; the compiler should do more work so we can do less work.

C++ uses too many #includes. When we use a function in C++, we have to #include the file which contains the function definition. I often cannot remember which file contains the definition, and I have to waste lots of time searching through files trying to find the definition so I will know which files to #include. Why can't the compiler do that for me? If I use a function without defining the function, the compiler should search through the libraries and find the function definition. The compiler should do more work so we can do less work.

My biggest objection to C++ is that C++ is too integrated. Modular programs are usually easier to debug than integrated programs. Modular programs are more easily worked on by dispersed groups of people, because each person can work on a different module. Modular programs are more customizable, because a user can throw away or rewrite a module if the user does not like that module, or add a new module.

I am envisioning an assembler/compiler with not one processor, not one processor and one preproccessor; but many, many different processors. Each processor might have many configurations. There are many steps to compiling a program; each step should be done by a different processor. Thus if anyone wants to add a feature, they would create another processor which implemented just that feature, and add their new processor to the collection of processors; this would be much easier than integrating the feature into a preexisting processor. Hopefully a large number of people could be inspired to create a large number of processors, and the result would be very flexible because you could decide which processors to use, and in which order to use the processors.

For example, I once saw some source code for a program. The documentation listed several different compilers, and said that none of the compilers could be used to compile the program, because each compiler had bugs. But each compiler had different bugs, and so the author of the program had split the program into several objects, and arranged for each object to be compiled by a different compiler, and then link the objects together, thus avoiding the bugs in each compiler. But with a modular compiler, it would be easier to avoid bugs in the compiler. We could skip the buggy processor, or we could substitute an alternate processor for the buggy processor, or we could pause after running the buggy processor and manually correct the output of the buggy processor before running the next processor.

With so many processors to run to compile a program, we would obviously need to use some kind of a makefile to control which processors to run. It might be useful if we could specify a standard set of processors, rather than an exact list of processors; so the source code's makefile could require set c_to_linux_elf, and somewhere in the compiler configuration, c_to_linux_elf should be defined as a list of processors.

The problem with splitting a compiler into many little processors instead of one big integrated processor is that many of the little processors require data generated by other processors. We could use some kind of interprocess communication among the little processors, but I think it would be better if each little processor adds its data to the source code, and then following processors can read the data from the source code. Many assemblers/compilers can generate a profile file. I am thinking that after all the little processors have run and added data to the source code, the source code will look sort of like a profile file.

Another problem with splitting a compiler into many little processors is speed. An integrated compiler will be a lot faster, which is one of the reasons why compilers are almost always integrated. However, I do not think speed is that important. For recompiling someone else's program to optimize it for your system, speed is not important because you can compile it in the background while you do something else, or compile it while you go out to lunch, or compile it at night. If you are debugging a program, and you make some changes, then speed is important, because you want it recompiled right away so you can continue debugging. However, you probably only made small changes, and you may be able to use an abbreviated compilation, because you may not need to repeat the compilation steps which were successful last time. A large program should be split into objects, and you do not need to recompile the objects which have not changed. If speed is really that important to you, buy a faster computer.

My hypothetical modular compiler will be slow because each little processor will read text data into memory, process the data, and write the data out again; and then the next processor will read the data in again. Furthermore, many of the processors will convert the text data to a binary linked list pointer table data structure before processing the data, then convert back to text. The modular compiler could be speeded up by leaving the data in binary format, thus skipping the multiple text to binary and binary to text conversions. The original source code data would be in text format, the first processor would convert the data to a binary linked list pointer table data structure, and the rest of the processors would process the data in the binary format. The modular compiler could be speeded up more by leaving the data in memory, so that each processor does not need to read the data into memory, and then write the data out afterwards. But if we did that, then we would have an integrated compiler, and we would have lost the advantages of a modular compiler. It would be difficult for nonexpert users to skip or add steps to the compiler.

So would it be possible to create an integrated compiler with the advantages of a modular compiler? We could create an integrated compiler in which the compilation process was divided up into many small steps, and allow the user to decide which steps to use and in which order; but how could a nonexpert user add custom steps? We could organize the source code for the compiler so that each step was a different source code file, and provide many functions for the manipulation of the code being compiled, and provide a template for a new source code file for a new step. But the user would have to create the new step using the same programming language as the rest of the compiler, and possible the same programming style; while with a modular compiler, the user could create a new processor using any programming language and any programming style. Also, with an integrated compiler the user would have to recompile the whole compiler in order to add a new step.

I think the best solution is to have both integrated and modular parts to the compiler. There is no reason why we could not have an integrated compiler which cooperates with external processor programs, or why we could not have a modular compiler in which one or more of the modules are multiple modules integrated together.

So to assemble/compile a program, we start with one or more text files of source code. Then we have a processor which converts source code to a processing text format. Perhaps each line should begin with a special character which tells whether the line is code, compiler directives, compiler data, etc. The processor which creates the processing text format should add a line of compiler data for each line of code; the line of compiler data should have many fields; the field for line number from original source code should be filled in and the rest of the fields left blank to be filled in by other processors. Then we need a processor to convert the processing text format to a processing binary format, and another processor to convert the processing binary format back to the processing text format. Then all the rest of the processors can work on either the text or binary format; we can convert back and forth as needed. Then we need a bunch more processors to remove comments, make macro substitutions, calculate equates, get function definitions from libraries as needed, calculate byte sizes for each line of code, calculate addresses, error checking, optimizations, look up hex values for opcodes, write hex codes to binary output file. Maybe the line of compiler data should include a recognized field, so any processor which recognizes the line could mark the line recognized, and later an error check processor could warn about any unrecognized; maybe compiler directives should also have a recognized field. Optimizing processors which run before the addresses are calculated should remove unneeded code; optimizing processors which run after the addresses have been calculated should replace unneeded code with NOP, and then another processor can remove the NOPs and adjust the addresses. And the processors which are most frequently used can be integrated together.

The complete system is not integrated and can theoretically compile anything; thus I call it the disintegrated omnicompiler. It might be more accurate to call it the modular multi-assembler/compiler, but I think the disintegrated omnicompiler sounds cooler.

dos slowdown program

Some DOS programs were written for old, slow computers and run too fast on more recent computers. There are some slowdown TSRs, but I think none are good enough.

PCs have an 18 per second timer, and ATs have a 1024 per second timer. The slowdown program has two parameters. The first number says how many of the 18 per second timer to skip. The second number says how many of the 1024 per second timer to run. 0 54 would be about full speed. 0 5 would mean for each count of the 18 per second timer, run 5 counts of the 1024 per second timer, which would be about one tenth speed. 4 1 would mean for every fourth count of the 18 per second timer, run 1 count of the 1024 per second timer, which would be about 1/200 speed. It does not make sense to set the first number to more than 0 unless the second number is 1, and it does not make sense to set the second number to less than 1 or more than 40. The slowdown program should reject stupid settings, but should have an option which allows you to use stupid settings if you really want to.

For really slow, run the program with the single step interrupt, like a debugger, with a time delay between each step.

You should be able to tell the program you want a specific speed of computer, like an 8mhz 286, and the program measures the speed of your computer and calculates how much slowdown is required to imitate an 8mhz 286.

Some old programs do not exit properly or tend to crash, so the slowdown program should trap some key like escape, and unload the old program and unload itself when you press escape. Or pressing escape should display a menu where you choose exit old program and slowdown program, exit old program but not slowdown program, change slowdown program settings and then continue running the old program, pass the escape keypress to the old program, or do nothing.

The slowdown program should restore the original display settings when it exits. Thus the slowdown program could be used to slow down a program, to exit from a program which does not exit properly, or to restore the display settings for a program which trashes the display, or any combination of those three things.

But redirecting keyboard input will not work if the old program redirects keyboard input. So the slowdown program should have an option to resteal keyboard input. The slowdown program frequently checks the keyboard interrupt to see if the old program has changed the keyboard interrupt, and changes the keyboard interrupt back. The slowdown program needs to remember two different keyboard interrupts, one for DOS and one for the old program. If the old program has not redirected keyboard input, then the slowdown program needs to pass keyboard input to the DOS keyboard handler. But if the old program has redirected keyboard input, then the slowdown program needs to pass keyboard input to the old program's keyboard handler. Restealing keyboard input makes the computer less stable because restealing creates a closed loop. If you press some key, the keypress will go to the slowdown program's keyboard handler. If the slowdown program passes the keypress to the next program, the keypress will go to the old program. If the old program passes the keypress to the next program, the keypress will go to the slowdown program, which passes the keypress to the old program, which passes the keypress to the slowdown program, etc, and your computer is stuck in the closed loop and crashed. Also, if the old program which redirects keyboard input exits, it should restore the previous keyboard interrupt. If the old program checks the keyboard interrupt before restoring the keyboard interrupt, and finds that keyboard interrupt has been changed, then the old program may become confused and may do bad things.

Of course, the best solution to bad old programs is to disassemble the bad old programs and fix them.

dos graphics viewers

I was looking for a dos program to display jpeg images, and I did not like any of the programs I found. Most of the programs were bloated with too many features, like multiple graphics formats and slide shows with music.

I think there should be a set of programs. Each program displays one kind of graphic. The programs should be named dpic, dpcx, dbmp, dico, dgif, djpg, etc. Each program should display the file given on the command line, then restore the original text mode without clearing the display.

The display controller driver should be a set of tsrs. There should be one driver tsr for each kind of display controller, plus a utility program for sending commands to the currently loaded display driver tsr.

Each driver tsr should reserve a few bytes of memory for remembering the default graphics mode. We cannot use the current display mode as the default graphics mode because the current display mode should be a text mode. The default graphics mode is set when you load the driver tsr, or can be set or changed with the utility program which sends commands to the display driver tsr. The graphics display programs should use the default graphics mode unless the default graphics mode was overridden with an environment parameter or command line parameter.

Vbe, the vesa bios extensions, already provides the functions of a display driver tsr. So it would be easier to use vbe than to invent a new system.

If you want a slide show, each graphic display program should have a command line option to delay for a certain number of seconds before displaying the graphic. If the graphic display program needs to process or convert the graphic before displaying the graphic, the processing or converting should occur while the program is waiting.

For music with your slide show, there should be another set of programs to play music. There should be one tsr driver for each kind of sound card, a utility program for sending commands to the driver tsr, like adjusting the volume. And there should be one program for playing each kind of sound file. If there is a lot of memory, the sound play programs should pass the sound data to the sound tsr. But if there is not a lot of memory, it might be better if the sound play programs gave the name of the file to the sound tsr. But if the sound file needs to be converted or processed before playing, the sound play program should do that, so the sound play program might have to create a temporary file and give the sound tsr the name of the temporary file. The sound tsr would have to delete the temporary file when the sound tsr was finished, so the sound play program would have to tell the sound tsr if the file should be deleted or not.

menu program

This is a about computer menus, where a computer program displays a list of possible choices. This has nothing to do with cooking.

If a menu program has very short items, then many items can fit on the display, but there is little information about each item, so it is difficult to understand what each item does. If the items are long, then more information can be displayed about each item, but few items can be displayed at once, and it is hard to find a specific item because you must seach through many different screens to find the item you want.

Most menu programs seem to have medium length items. I think this is the worst of both worlds, because few items can be displayed at once, and the items are too cryptic because too little information is displayed about each item.

Most computer displays are 80 columns by 25 lines. Use one line for the title bar and a message about how to access help. Use 6 lines to display a lot of information about the current item. Use the remaining 18 lines to display items. Each item is seven characters. There are 10 columuns of items, or 180 items displayed per screen. There is one space between each column of items, and the last column of each line can be used for a scroll bar. So this displays 180 items at once, and displays 6 lines of information about each item.

If you do not know what to do, you can go through the menu very slowly, selecting each item in turn and reading the information about the item. If you do know what you are doing, you can go through the menu very quickly and select the item you want.

Also, one key could display the program documentation instead of running the program. Another key could cause the menu program to prompt for a file, and then run the program with that file.

This idea for a menu program would be good for dos or linux in text mode.

This idea is similar to the menus on many grapical operating systems, where if you pause the mouse pointer near a menu item, additional information about that item is displayed.

In dos, the menu program could be set up with two batch files. The first batch file runs the menu program, and then runs the second batch file. The menu program selects a program to run, the menu program creates the second batch file and exits. The second batch file runs the selected program, then runs the menu program. The menu program exits when the selected program runs, then the menu program starts again when the selected program exits, so the menu program does not use any memory, and all memory is available to the selected program.

home