$Id: README,v 1.1.1.1 2004/10/16 08:36:53 efalk Rel $ (from: @(#)README 1.1 92/05/28 SMI) "dstar" is a multi-player network 3-d video game. In dstar, you are the pilot of a spaceship armed with lasers and missiles. You have the pilot's-eye view out of the spaceship's front window. Other people playing the game on their workstations are playing in the same "space" as you are. Everybody sees everybody else in the game. You fly up to other spaceships and shoot them with your laser or launch rockets at them. Obviously, they want to do the same to you. (WARNING: This is a horrible, militaristic, fascist, violent game. It desensitizes you from the brutal reality of warfare and acts as a blatant propaganda tool for high-tech weaponry and the militarization of space. So sue me.) This is the source code to the game "dstar". Dstar is not complete by any stretch of the imagination. If you make any bug fixes/extensions to the game, or even think of new features you'd like to see, please send them back to me at efalk@sourceforge.net so I can incorporate them into the game. There's a "to do" list at the end of this README file. HOW TO RUN: To simply run dstar, type % dstar If you are the first player, dstar will spend about 5 seconds looking for other players. If it doesn't find any, it assumes that you are the first player in the game. It's a good idea to use a robot as the first player in the game (see below.) Dstar uses broadcast packets to locate players playing on your local net. If you want to join a game running on a different network, type % dstar where is the name of any machine playing dstar. To control the spaceship, move the cursor near the center of the screen and click the left mouse button. The cursor will change from an arrow to an aiming box. At this point, the cursor steers the ship; moving it away from the center of the screen starts turning the ship in that direction. The further you move the cursor, the faster the ship turns. If you click the left mouse button again, the cursor returns to being an arrow and the ship stops turning. The buttons roll the ship left and right along its axis. This has almost no utility, but can help you navigate sometimes. To fire the lasers, press and hold the right button. The lasers can fire indefinately, but firing them makes you easier to see from a distance. The lasers fire in the direction indicated by the cursor. The lasers have a limited range, and the target has to be quite close in order to shoot it. To turn the radar on, press 'r'. The center of the screen changes from blue to yellow or red. Yellow indicates that the radar is on, red indicates that the radar is on and is locked on a target. The center of the screen will switch back and forth between yellow and red as you acquire and lose targets. When you have a radar lock on someone, that person will be alerted, so use radar sparingly. The radar locks on the nearest object within a certain range and near the center of the screen. Once the radar locks on a target, it stays locked on that target until the target either leaves the radar's range, leaves the area near the center of the screen or is destroyed. Other objects coming into range will not confuse the radar. Pressing 'r' again will turn the radar back off. The tab key will cycle between targets within the radar's range. To turn the auto pilot on, press 'a'. When the auto pilot is on, it will chase whatever the radar has locked onto. If the radar is not locked onto a target, the auto pilot will fly lazy circles. If you press 'A' instead of 'a', you get the "agressive" auto pilot which will shoot the target if it comes within range. Pressing 'a' again will turn the auto pilot back off. Note that the auto pilot is rarely as good at flying or shooting as a human is, so don't think you'll win the game on automatic. When autopilot is on, the left mouse button switches between manual control and autopilot, rather than flying straight. To arm a missile, press 'q' or F2. You cannot launch a missile until you've armed it. If you have more than a certain number (currently eight) of missiles launched at the same time, you will not be able to arm another. To launch a missile, press 'w' or F3. The missile will chase whatever the radar is locked onto. If the radar is not locked (or is not on), the missile will fly in a straight line. Missiles launched without radar lock are harmless and just fly until they run out of fuel. Missiles travel three times as fast as spaceships and last 15 seconds. Missiles are not very maneuverable and can be dodged if you see them coming. Missiles launched from too far away will run out of steam before hitting their target. Missiles launched from too close will fly past their targets before they can stabalize on course unless you have the target right in the center of the screen when you launch. Once a missile loses its target, it flies harmlessly in circles until it times out. THE ROBOT: The robot is a simple fighter program that flies around in circles and can be used for target practice, etc. The robot is not a graphics program and can thus be run from any system on the net. to run: % dstar-robot [-auto] [hostname] Hostname is used for linking the robot to a game in progress on a different sub-net. This is the same as the hostname argument to dstar. The -auto flag turns on the robot's auto-pilot. The robot will chase and attack anything that comes within the (narrow) view of its radar. HINTS: Run the robot first. The first player (the master) has extra work to do, so you may as well let the robot do it. Also, there are certain bugs that occur when players enter and leave the game frequently these are mostly eliminated if the master is a robot. All ships fly at the same speed; if someone is flying away from you, you can't possibly catch them. If they're not too far away, a missile will get them, otherwise you'll have to wait for them to turn around and come back. If someone (or something) is flying in a constant circle, you can catch up to them by getting behind them and then flying a tighter circle than they are flying; since your speeds are the same, you'll catch up on the inside. If you fly to keep your quarry in the center of your screen, you're flying almost the exact same circle they are and you'll never catch up. Instead, figure out which way they're turning (not hard to do) and turn a little tighter than they're turning. Keep the image of the other ship about halfway between the center and the edge of the screen. For instance, if you're chasing a ship making a constant turn to the right, keep it in the left half of your screen: +-------------------------------+ | | | | | +-------+ | | | | | | | X- |- -| | | | | | | | +-------+ | | | | | +-------------------------------+ ^ enemy ship, turning to the right. When fighting someone head to head, you usually both lose. Using the agressive autopilot in this situation almost guarantees that you won't miss unless your opponent is good at dogfighting, in which case the autopilot will probably get you killed. Various tricks may be tried when in a head-to-head situation: wiggling back and forth or spiraling may make it difficult for your opponent to aim at you. You might try waiting until just before you come within range and then doing a tight (but not too tight) 360-degree turn. This can be very effective if done right since it causes your opponent to lose sight of you and you usually come back behind them for an easy shot. Robots make good bait. Put a couple of robots into a game, and from time to time someone will chase one thinking it's another player. When you see this happening, fall in behind and get them while they're chasing the robot. Sometimes whole convoys of players line up behind a robot. If you're lucky, you can come up behind this convoy and pick off all the members one by one. Caution: when you're chasing people this way, count the number of players ahead of you. If you can't account for all the players in the game, there's a good chance that someone's behind you. INTERNAL NOTES FOR DEVELOPERS: Networking: Unlike mazewar or spacewar, dstar does not require a daemon to keep things synchronized. Instead, when the game starts up it sends out a broadcast packet onto the local net. If there is no answer for five seconds, the program assumes that it is the first player in the game. In this case, the program becomes "master" and takes on the duties that would have been assigned to a daemon otherwise. There are three networking roles the program can take: Master, Submaster or Slave. The Master is the program that coordinates all communications in the game. Id numbers and missile ids are assigned by the master; in short, the master's job is to act as a clearing house to keep all the other players in touch with each other. Initially, the master is the first program to come up on the net, but this task can be re-assigned to another program if the master leaves the game. Submasters are programs that were the first to come up on the local net. Their job is to acts as relays between subnets. When a new program comes up and sends out the initial broadcast packet, the submaster catches this broadcast and forwards it to the master. The job of being submaster can also be re-assigned as players leave the game. A Slave is any program that is not master or submaster. If a program comes up and there is already a submaster on the local network, then the program is a slave. Slaves are not really "slaved" to any other program, they are really clients with the master providing the service of assigning id's etc.. Communications in the game are in the form of UDP "datagram" packets sent directly from player to player. These packets contain things like requests to join the game, status updates, scoring information etc. Internet addressing is used. All networking code is contained in "netio.c". This file contains two kinds of subroutines, routines called from within the program to send data over the net and routines called asynchronously by the notifier when a message arrives. Outgoing messages are queued internally to save network bandwidth. The queue is flushed whenever the intended recipient changes or when net_flush() is called. Here is how the game is run, a complete description of the individual message packets are built can be found in h/netio.h: When the program starts up, it calls init_netio which broadcasts a NET_JOINING message to the local net. This message asks the master to give the game an id number and a list of other players in the game. If the game was started with the command "dstar ", the NET_JOINING message is wrapped in a NET_BROADCAST message (see below) and sent directly to the named host instead of being broadcast. If there is no answer for five seconds, the program assumes that there are no other players and becomes the master (assigning itself id # 0). When the master receives a NET_JOINING message, it assigns an id number to the new player and sends a NET_WELCOME message informing the new player of its id number, team (not implemented yet) and other information. This is followed by NET_CURRENT_STATUS packets for all of the other players in the game. The new player is now in the game. If the master does not hear from a player for 30 seconds, it sends a NET_ARE_YOU_THERE packet to make sure the player is still active. If the master still has not heard from the player for 60 seconds, it sends a NET_DIED packet to all of the other players informing them that the player has left the game. If a player or one of its missiles leaves the game, it sends out a NET_DIED message to all of the other players. If a player shoots something, it sends a NET_JUST_SCORED message out to let everybody know about it. If the destroyed object is a missile, the owner of that missile will then send out a NET_DIED message to remove the missile from the game. All players periodically send out NET_CURRENT_STATUS packets to let all the other players know its current status. NET_CURRENT_STATUS packets are also sent out on behalf of all of the player's missiles. The master periodically sends out a NET_CURRENT_STATUS on all of the static objects in the game to keep them synchronized (not yet implemented). When a player arms a missile, it sends a NET_REQUEST_MISSILE packet to the master. This is similar to a NET_JOINING packet. The master will assign an id number to the missile and return a NET_MISSILE packet to the requesting player. If any player receives a NET_BROADCAST packet, it rebroadcasts the contents of the packet onto the local net. This is used when programs are joining games on other subnets and for reducing net bandwidth (see below). Broadcasting messages to all the players in the game can be a tricky business. When there are a small number of players, each player sends status packets directly to all of the other players in the game. This means that net bandwidth goes up with the square of the number of players. This is avoided with a "netlist" mechanism: The game maintains a list of players sorted by the subnets on which they reside. When the game wants to send a message to all of the other players, it calls the routine "broadcast". Broadcast goes through the list of subnets in the game. For each subnet, broadcast checks the number of players on that subnet. If this number is less than BROADCAST_THRESH (currently 4), individual transmissions are made. If the number of players is greater than BROADCAST_THRESH and it is the local network being examined, then a broadcast packet is sent to the local network. If the number of players is greater than BROADCAST_THRESH and they are on a different subnet, then the entire message is wrapped in a NET_BROADCAST packet and sent to the submaster of that net. The submaster will then rebroadcast the packet. The net lists are re-computed every time a player enters or leaves the game. Static objects and missiles are not included in the lists. Status block description: The game maintains a block of data for every object. This block contains the following information (for more info, see h/object_types.h) id object id, assigned by master name object's name, assigned by object or object's owner team object's team for players (not implemented), object's owner for missiles and static object. score score (not implemented) status object's type: OBJ_EMPTY=empty slot in status block array, OBJ_SLEEPING=player who has closed the window, OBJ_DEAD= player who has just been shot, OBJ_STATIC=planets and things, OBJ_MISSILE=missile. flags flag word, indicates lasers or radar on. Posn object's position in 3-space Forward, three normalized normal vectors describing object's Up, Right orientation. These three vectors plus Posn describe a 4x4 transformation matrix to convert object modelling coords to world coords and back. Delta vector in object modelling coords describing control inputs. Delta plus Speed can be used to calculate object's position over time. Pointing vector describing the direction the object is "looking". indicates where the laser beam is. Speed Objects speed. Currently fixed at 25.0 units/sec. target object radar is locked onto. time used for missiles etc. description index into table describing objects visual appearance. address object's (or object's owner's) internet address sequence data packet sequence number, not currently checked. last_rep time of last status report from object; used by master to detect dead players. net_addr first three bytes of object's internet address -- used as subnet id. net_status MASTER, SUBMASTER or SLAVE. net_next link to next player in this netlist. net_num number of players in this netlist. Header Files: dstar.h General declarations used everywhere parameters.h Compile-time parameters types.h Common types. object_types.h Describe objects in the game. graphics.h Graphics definitions bsp_object.h Describe a node in a BSP tree line_object.h Describe a point in a line drawing */ netio.h networking-related definitions blast_line0.h Data to describe a line-drawing of an explosion blast_line1.h Data to describe a line-drawing of an explosion fighter1_bsp.h Data to describe one fighter fighter1_line.h Data to describe the line drawing of a fighter fighter2_bsp.h Data to describe fighter type 2 fighter2_line.h Data to describe the line drawing of a fighter missile_line.h Data to describe a missile monolith_bsp.h Monolith planet1.h planet planet2.h planet starfield.h stars hsi.h Head-up display data general files: dstar.c - main program, used by all programs control.c - routines useful for controlling object behavior netio.c - communications routines laser.c - tests to see if a laser hit a target prioritizer.c - special prioritizer for the notifier files that vary from program to program: special.c - routines specific to this program control_ship.c - routine to control this ship files used for the fighter only create_eship.c - build enemy fighter image blast.c - build explosion image draw_image.c - draw the image on the screen draw_hsi.c - draw the hsi draw_starfield.c - draw the star field draw_objects.c - draw all objects in list draw_bsp.c - draw a bsp tree routines provided in special.c: init_me() - initialize ships position, state etc. Called once at startup init_game_graphics(&argc,argv) - initializes graphics (if any). Called once at startup init_communications() - open communications. dstar_main_loop() - start the game terminate_game() - called from sigint handler to finish the game normal_action() - called once per time slice when state = OBJ_ACTIVE blast_action() - called once per time slice when state = OBJ_DEAD set_blast_state(state) - called once per state change when state = OBJ_DEAD $Id: TODO,v 1.1.1.1 2004/10/16 08:37:03 efalk Rel $ THINGS TO DO: o Improved speed control. o Ships using their radars are easier to see. o Ships appear as white dots rather than red dots when not under power, unless lit up by radar. o Add a rear-view mirror. o "Warp" command, lets you travel across space quickly. Warp command should have all sorts of limitations to keep the game playable: . Can only use warp command once in a while; perhaps only once per life. . Warp command makes ship very visible; perhaps a long trail . Warp command makes ship vulnerable Something like that. o Spacewars-style weapons -- space bar launches an inert bullet. Bullet travels at same speed as missile, but only in a straight line and without using radar. Bullets are unlimited and many more can be on the board at the same time. o Currently, both ships are designed by hand (that's why there's only two of them.) It would be nice to have a ship-building tool. My original idea was to have a large variety of ships taken from SCI-FI movies. o Collisions with planet/monolith should be fatal o map generic terrain onto surface of planet so there's something to see. o "team" play, in which the team you're on determines what kind of ship you're flying. There ought to be a way to communicate with them. A situation display that shows all your teammates positions would be nice, but how to do this in 3d? o Change the planet into the Death Star. Ultimately have battles to destroy/protect the death star. o Since it's been ported to OpenGL, go all the way with lighting, more colors, etc. Find out why stars causes memory leak; find out why glut/programs/examples/stars does not. Auto-generate planet Add Sun Gravity Lighting Classic spacewars play? o Master should sanity-check incoming message addresses. o #2 player should poll the master.