Programming games (such as Fleet Commander) require a little more effort to learn and become proficient in. It does not provide as much immediate satisfaction as some games, but the long-term enjoyment and satisfaction can be much greater. If you get stuck, don't give up. There is a community of players on the internet who are happy to assist.
The challange of Fleet Commander is the designing phase - creating and testing a fleet, tweaking and adjusting the stratagies, and continually adding newer and more sophisticated systems. Programming games are the ultimate strategy games. The strategy is designed and set before the battle even begins. After the battle begins, you as a user have no control over the outcome. Your fleet simply plays out your strategy as you designed it.
The great satisfaction in Fleet Commander comes when you watch your fleet do exactly what you told it to do, and the enemy is destroyed. The great satisfaction is knowing that your plan, your strategy, your programming was better than the enemy's.
The type of fleet you build is completely up to you. There are four distinct vehicles you can choose from, but what each ship really does is up to you. The fleets you design are limited only by your imagination.
Individually, the Warchief is the weakest starship available. Although it is fast, it can only scan targets directly ahead of it, and can only fire unguided rockets. Against more advanced starships, a lone Warchief is nearly useless. The Warchief's strength is in its low cost and great numbers. One fighter will never destroy an alert cruiser, but no cruiser can stop a charge of twenty or thirty fighters. Fighters are the backbone of most (but not all) star fleets.
The Gunship is a very versatile starship. It can be used in just about any role you can come up with, including heavy fighter, minelayer, escort, reconnaissance, and missile cruiser. It can take more hits than a fighter, can scan in any direction, and can fire the deadly Mark III Programmable Missiles. The Gunship is just waiting for you to invent a good application for it!
The Assault Cruiser is a key element in every fleet. It is the only starship that can create other units - including more cruisers! It can scan long distances in any direction, letting the Centurion see most enemies coming before the enemies see it. Like all the starships in Fleet Commander, the roles you assign to your Assault Cruiser are entirely up to you. It can be used offesively or defesively. Good uses include long range reconnaissance, fighter interdiction, and blockade running. You can even park a few in tight formation as an ad-hoc starbase!
The Gunship and the Centurion can both launch programmable missiles. These missile are starships in their own right, and follow your instructions and fill your role. Although they cannot scan, they stay locked onto their assigned targets until they either destroy them or run out of fuel. Programmable missiles are far more than just guided rockets. At your command, they can follow elaborate patterns, send information back to the fleet, or even stop dead in their tracks to become mines. Use their ECM hardware to jam enemy scanners, or even to paralyze an enemy altogether!
So you've seen what's available. Or at least, most of it. There are also Starbases, Freighters, and other types of vehicles (and creatures) you'll encounter later.
If you haven't done so already, run a few sample battles to get the idea. Go to the battle menu and choose "Select Fleets." Pick a few sample fleets, then close the box. Go back to the battle menu and choose "Start Battle." Watch as each of the example fleets begins executing the instructions that were pre-set for them. Watch them launch fighters, maneuver, and fire missiles. Hold down the F1 key to see where each starship can scan. Watch what they do when their scanners detect enemies.
How do you create a fleet? You program it. It takes a bit of work, but it's not that hard. First, you'll need a brief overview of events and objects. If you are familiar with events and objects from other programming languages, read the following section anyway. Things work a little differently here. See the "Note to Experienced Programmers" later on.
The sample fleets may win the first mission or two, but very soon, you'll need to design your own fleets.
Each ship gets its own events. For example, if your cruiser takes a point of damage during the same game cycle that your fighter scans an enemy, the cruiser will recieve a "damage" event and the fighter will recieve a "scan" event. If you have more than starship of the same type, the same thing applies: they each recieve their own events. If two events happen simultaneously for the same starship, the event with the highest priority occurs.
The following is the list of events in Fleet Commander, in order of priority:
Once an event occurs, you can either ignore it or respond to it. For example, you may not care whether or not a fighter crosses the edge of the screen, but you certainly care what happens when your cruiser scans an enemy! The first step in designing a fleet is deciding which events you want to respond to, and how you want to respond.
\#name "First Example" \#author "Fleet Commander" \#version "1.0" < anything between these brackets > < is ignored by Fleet Commander. > cruiser.on_idle { < This is the cruiser's idle event. This > < section gets executed when nothing of > < interest happens to a cruiser > launch.fighter < this launches a fighter.> } fighter.on_init { < A fighter executes this event when it > < is first created. It only happens once. > < pick a random heading> nav.setheading(math.random(64)) } fighter.on_scan { < Enemy found! This event occurs when a > < fighter detects an enemy. Fire a rocket! > launch.rocket }
It won't win any battles, but it is simple enough for an adequate demonstration. The first three lines are header information-this is the information that shows up in the "Select Fleets" dialog box when you select your fleet. After this is a comment - anything inside the < > brackets is ignored by Fleet Commander. Fleet Commander also understands the C-type comment /* */ and C++ type comment //.
Below the comment are three separate event handlers, on_idle, on_init, and on_scan. In front of each of these is the type of starship for which the event is written. The on_idle is written for a cruiser, while the on_init is written for a fighter. You can have separate handlers for the same event, one for each starship type. After the name of the handler is a number of commands enclosed in curly brackets { }.
Inside each event handler (between the curly brackets) is an object call. A complete list of these can be found later. An object call is made up of an object and a method. For example, launch.fighter. Launch is the object and represents a whole group of functions (you can launch other things as well, such as launch.rocket or launch.fighter). Fighter is the method. You can call as many methods in your event handler as you wish, but making your event handler too long may make your starships less responsive. (See performance issues later).
In the above example, cruiser.on_idle calls launch.fighter. Assuming the cruiser has enough cash handy and isn't currently recharging, a new fighter will be created. (If the cruiser doesn't have enough cash, nothing happens). Since it is the last instruction in on_idle, when the launch.fighter is finished the starship waits for the next event to occur. The new fighter that was just created has it's own events, and receives the fighter.on_init event.
Remember that every starship handles its events completely independently, and runs simultaneously. If you have multiple fighters, for example, each one gets its own on_init, message when it is created, and on_idle, on_scan, etc. while it is active.
Fighter.on_init is a little more complicated. Its purpose is to pick a random heading for the newly created fighter. Many methods require parameters: additional information inside the parenthesis. For example, nav.setheading needs a new heading to steer towards. nav.setheading(0) sets a course directly east. nav.setheading(32) sets a heading directly west (there are 64 possible directions). In this case, the heading we are choosing is the result of yet another method, math.random(64), which selects a random number less than 64. If you put these two calls together, you get a new heading in a random direction.
Logic and strategy go hand-in-hand in Fleet Commander. Nearly all event handlers will need to make some sort of decisions, and the way to do that in Fleet Commander is with the 'if' statement:
cruiser.on_detect { <event occurs when the cruiser is scanned. > <takes at least 350 credits to launch a gunship.> if (math.greater(status.balance, 350)) { launch.gunship } <keep rotating scanner> scanner.turnright }
This is a handler for the on_detect event. In the above example, the cruiser reacts to being scanned by trying to launch a Gunship. Notice the 'if' in the above example. After the word `if' is an expression in parenthesis. This is usually a math or logic function, but doesn't have to be. If the result is non-zero (not false), the block of commands after the if statement is executed. Otherwise, it is skipped. After the expression is a curly bracket, `{'. This marks the beginning of a block of commands that may or may not happen. The end of the block is marked with a close curly bracket, `}'.
In this case, the cruiser first compares the cash in the fleet's account (status.balance) with 350. If this comparison is true, the block of code afterwards is executed - a new Gunship is launched. If the comparison is false, the block is skipped. In both cases, the cruiser then calls scanner.turnright to change its scan direction.
The other important logic statement is the else. The `else' is what happens if the `if' condition is false. For example:
cruiser.on_detect { <event occurs when the cruiser is scanned. > <takes at least 350 credits to launch a gunship.> if (math.greater(status.balance, 350)) { launch.gunship } else { <--- modification here > launch.fighter() } <keep rotating scanner> scanner.turnright }
The above example is identical to the previous one, except for the addition of an `else.' Now, if the cruiser doesn't have enough credits (math.greater is false), the block of commands after the `else' is executed - the cruiser launches a fighter.
Variables in Fleet Commander come in two forms: private and shared. Shared variables are shared among the entire fleet. Private variables are unique for each individual starship-each starship can store different values in the variable.
To create a variable, put shared or private before your first event handler, followed by the name you want to use for that variable. For example, shared direction, or private last_x. Variables, like everything else in Fleet Commander, are objects. To set the value of a variable, use the method set. For example, direction.set(16) will set the value of the variable "direction" to 16. To use the value of a variable, use the object method get. For example, nav.setheading(direction.get()) sets the starship's heading to the value of direction.
Most variables only store a single value, but variables can store up to 512 separate values if needed. To create an array of values, use the method "size." Using the above example, direction.size(32) sizes status for 32 values. You can then use the method status.getel(10) to retrieve the value of the tenth element, or status.setel(10, 3) to set the value of the tenth element to three. Resizing a variable erases whatever was there before.
Arrays are numbered arbitrarily. Asking for a size of 32 for your array, the numbers can be referred to as elements 0 to 31 (as in languages like C++) or 1 to 32, or even 101 to 132.
Type | Credits | Energy | |
Rocket | 1 | 48 | * |
Missile | 10 | 48 | * |
Fighter | 100 | 55 | |
Gunship | 300 | 100 | |
Cruiser | 1000 | 300 |
Note the asterisks. Cruisers recharge from rockets and missiles three times faster than fighters or gunships - meaning a cruiser can fire an additional missile in only sixteen clock cycles. The status.recharge method can be used to determine whether or not a starship is fully charged and can launch again. The status.balance method can be used to determine how much money is available.
Hold down the debug keys F1 through F5 to get a glimpse of what is really going on. Note that these keys only work if the .FC fleet file is available.
This means that a very long or complicated event handler may require several cycles to execute. During this time, other events are not processed. When the complicated event handler is finished, the pending event with the highest priority is processed. The other events are ignored.
Programmers with experience in C++ or Java will have an advantage over those who have not used those languages, initailly. This advantage is brief and only applies during the first stages of the learning process. Once a novice has mastered the first few missions and understands the Fleet Commander language, he/she should be able to compete on fair terms with even the most advanced "real" programmers.
As an aid for those who do know C++ or Java, the following options exist:
Semicolons: In C++, all statements must end in semi-colons. C++ programmers are used to putting semi-colons everywhere. Fleet Commander ignores semi-colons, but does not give an error. Feel free to use them if you want your source to look more like C++.
Parenthesis: Functions that require no parameters do not require parenthesis in Fleet Commander. You may add an empty set of parenthesis if you like, such as status.getx();
Case Sensitivity: Unlike C++ and Java, case does not matter in Fleet Commander.
If you are using Fleet Commander as an aid in learning C++ or Java, it is recommended that you use empty parenthesis and semicolons.
Remember that this is a Beta-and the very first beta at that. Please give us feedback about the game, the documentation, the idea, etc. If you see something you don't like, tell us! We can't fix it if we don't know. The best way to reach us is at http://fcomm.sourceforge.net
lodsw
Team leader, lead programmer
calash
Real name - Jason
Send the money to P.O. box :)
As for my role here.... Lurker :).
Mission Files
Testing
Mission development (Once i understand the language a bit more)
End user support (as needed)
I am avaialble via ICQ and MSN Messanger.
ojones
folk
Installation task
transients
Nilsarne
Documentation
AI Fleet Commander is copyright Devon Ellis.
The source code is distributed under the GNU General Public License which can be found at http://www.gnu.org/ You may share the source code. You may modify the source code provided this header remains intact and prominent and you provide a means for anyone to obtain the modified source code for free (without having to do anything other than choose to obtain it). If the license allows it, you may charge for reasonable costs you incur ie physical media. No warranty is stated or implied for this software.
1Conversion to LATEX