This page defines the planned Quagents3 protocol. ProtocolZero is the command protocol used for directly talking to wiki:Quagents. (The naming convention adopted here is that ProtocolOne is the protocol (or API) between the thing that sits on top of Quake and deals with socket I/O and whatever more abstract structure exists above that; ProtocolTwo would be two levels removed.) In particular, ProtocolZero is for the agent-based communication, not for the experimental control. In addition to the command protocol, there is also a protocol which is used exclusively for the automatic periodic transmission of data from the server to the client. This wiki:DataProtocol is enabled by sending the server a list of query opcodes for which the client desires automatic updates. == Overview == ProtocolZero commands are sent as plaintext over a TCP/IP socket to Quake on port 6000. Currently, any new connections to this port result in the creation of a new bot. Initial commands are simply ASCII strings of the form CMD PARAM. The final initial command given is "ready", after which the bot is spawned, and live commands become usable. Live command format is of the form A BB IDNUM PARAM_1 PARAM_2 PARAM_3 PARAM_4... \n * where A is either a 't', 'r', or 'n' character, for 'then', 'replace', or 'now', specifying scheduling (see below). * where BB is the opcode of the instruction (always 2 characters). * where IDNUM is a sequence of numeric characters representing an unsigned 32-bit integer. This code will be returned on completion, for the client's convenience. We imagine that users will typically make this a sequence number, but we do not require or enforce uniqueness. * where P1... are parameters for the instruction, and may be any length. They are delimited by spaces, and therefore cannot contain spaces (even if explicitly quoted or escaped). Parameters should be printed in ASCII, so 253 is '2','5','3', not '\253'. Floats are interpreted by the atof() function. * and \n is a newline. A carriage-return will work just as well. Examples (each of these entries ought to be terminated by a newline): * t ju 653 0 1 * This command means: "after you do everything I've told you to do, jump. This is command id=0, and you should jump in direction 0 degrees at speed 1". * The server will respond after some time "cp ju 653 done". * n po 0 * This command means: "immediately pop what you're doing, this is command id=0". * The server will respond (almost instantly in this case) "cp po 0 done" then some other message about the previous command (say, "cp ju 653 popped"). * t mf 350 0 180 0.4 * This command means: "after you do everything I've told you to do, walk forever, this is command id=350, direction=180 degrees, speed=0.4". * The server might eventually respond "cp mf 350 blocked". Quagents model their behavior in the form of a double-ended queue that has a maximum capacity of 1024 commands. Commands can be pushed onto either the front ("now" commands) or the end ("then" commands). Additionally, the top command can be atomically replaced by a new command ("replace" commands). In addition to individual Quagents, there is also the possibility of commanding a wiki:GOD (Global Overview Descriptor) structure, which collects and returns macroscopic game data. The idea is that there are two types of connection permissions - GOD and Quagent. The GOD entity connects to the game server through port 6010. == Brief Specification == '''INITIAL COMMANDS''' * ''name'' - sets what the name of the bot will be when it spawns. Takes one argument: * string name * ''botfile'' - sets the botfile of the bot. Among other things, this determines the bot's in-game model. See [[botfiles]] for a list of options. FIXME: problem loading bot models? * string filename * ''skill'' - sets the skill level of the bot, which selects subsections from the botfiles. * integer skill * ''team'' - sets the team of the bot ("red" or "blue") in CTF or team deathmatch mode. * string team * ''password'' - sets the password of the bot's datastream socket. If this command is not issued, the password is the empty string. * string password * ''ready'' - spawns the bot. Takes no arguments. Responds with "id X" where X is the unique integer id number of the bot. '''LIVE COMMANDS''' * Movement: * ''[[mi]]'' - "Move Indefinitely". Takes three arguments: * int obstacles * float direction * float speed * ''[[mf]]'' - "Move For". Takes four arguments: * int obstacles * float direction * float speed * float time * ''[[mb]]'' - "Move By". Takes four arguments: * int obstacles * float direction * float speed * float distance * ''[[mt]]'' - "Move To". Takes four arguments: * int obstacles * float speed * float X * float Y * ''[[ju]]'' - "JUmp once". Takes two arguments: * float direction * float speed * ''[[ro]]'' - "ROtate". Takes two arguments: * float yaw * float pitch * Basic Actions * ''[[fw]]'' - "Fire Weapon". Takes no arguments. * ''[[sw]]'' - "Switch Weapon". Takes one argument. * int weapon * ''[[sc]]'' - "Set Crouch". Takes one argument. * int crouching * ''[[sv]]'' - "!ShoVe". Takes three argument. * float strength * float shoveangle_yaw * float shoveangle_pitch * Basic Queries * ''[[hc]]'' - "Health, Current". Takes no arguments. * ''[[hm]]'' - "Health, Maximum". Takes no arguments. * ''[[ac]]'' - "Armor, Current". Takes no arguments. * ''[[am]]'' - "Armor, Maximum". Takes no arguments. * ''[[lc]]'' - "Location, Current". Takes no arguments. * ''[[fc]]'' - "Facing, Current". Takes no arguments. * ''[[cs|cs]]'' - "Can See". Takes one argument. * int entityid * ''[[ra]]'' - "RAdar". Takes one argument. * float range * ''[[wi]]'' - "What Is". Takes one argument. * int entityid * ''[[mc]]'' - "aMmo, Current". Takes one argument. * int weapon * ''[[rf]]'' - "!RangeFinder". Takes four arguments. * int mode * int range * float yaw * float pitch * Complex Sensors * ''[[rb|rb]]'' - "Rangefinder, Batch". Takes eight arguments. * int mode * int range * float starting_yaw * float starting_pitch * int width * int height * float pixel_delta_yaw * float pixel_delta_pitch * Command Queue Management * ''[[po]]'' - "POp". Takes no arguments. * ''[[pa]]'' - "PAuse". Takes no arguments. * ''[[fa]]'' - "Forget All tasks". Takes no arguments. * ''[[fm]]'' - "Forget Most tasks". Takes no arguments. * ''[[sk]]'' - "SKip". Takes no arguments. * ''[[pk]]'' - "PeeK". Takes one argument. * int depth '''GOD''' * God Actions * ''wiki:sh'' - "Set Health". Takes two arguments: * long botid * int newhealth * ''wiki:sg'' - "Set Gravity". Takes one argument: * float gravity * ''wiki:sa;; - "Set Armor". Takes two arguments: * long botid * int newarmor * God Queries * ''wiki:gh'' - "Get Health". Takes one argument: * long botid * ''wiki:ga'' - "Get Armor". Takes one argument: * long botid * ''wiki:gg;; - "Get Gravity". Takes no arguments. * ''wiki:gp'' - "Get Position". Takes one argument: * long botid * ''wiki:fd'' - "Find Distance". Takes four arguments: * double x1 * double y1 * double x2 * double y2 * ''wiki:li'' - "LIsten". Takes two arguments: * double x * double y == Example Quagent Session == All strings here are terminated in a newline. In a program like telnet, this will typically be automatic for you, but if you're writing your own socket code, be sure to separate commands with newlines. * User connects using telnet to open a connection to socket 6000. * User types: "name !ExampleBot" * User types: "ready" * Quake spawns the bot in a spawn location and names it "!ExampleBot". * Quake responds: "id 1" * User types: "n mi 1 0 0 1" * !ExampleBot starts moving forever directly forward at full speed. * User types: "n pa 2" * !ExampleBot pauses motion. * User types: "n hc 3" * Quake responds: "rs hc 3 100" * Quake responds: "cp hc 3 done" * User types "n po 4" * Quake responds: "cp po 4 done" * Quake responds: "cp pa 2 popped" * !ExampleBot resumes motion. == Not Yet Implemented Commands == '''INITIAL COMMANDS''' * General management * initialPosition [LOCATION] - selects where the bot will start '''LIVE COMMANDS''' * Basic robot-like functions for users who want low-level fine control. (Implement first) * get [ENTITYID] - picks up an item from the environment * drop [ENTITYID] - drops an item from inventory * move [LOCATION] - bot moves to specified location. uses native pathfinding. It would be nice if along the way it used Quake's goal system. That would give us free puzzle-solving/button-pushing/surfacing-for-air. * move [OBJECT] - finds the location of specified object, and pathfinds to it using move[LOCATION]. * echo [STRING] - reports a string back over the socket to the user * say [STRING] - Quagent "speaks" the STRING aloud. Has limited range. Possible implementation for user with speech synth. Used during Quagent collaboration. * look [???] - sends an image over the socket back to the user representing what the agent can see - may be zoomed or variable-resolution? Use OpenGL. * lookdepth [???] - like look, but sends the OpenGL Zbuffer not framebuffer back over the socket. * listen [TIME] - sends sounds back to the user for the specified time. This seems like it might be Hard. * Invokable Quake Behavior (Implement last) * whereareyou? - returns what the bot usually says if you ask it that in a team game ("I'm by the rail gun in the blue base." sort of things). * followsmart [ENTITY] - smartly follows the given character using Quake's follow chat command. * Sensors * currentItem - returns description of currently held items. '''GOD''' * getPositions [VOID] - returns list of all Quagent positions. * setGravity [GRAVITY] - sets global gravity. * slomo [SLOW_FACTOR] - slows down all game actions by SLOW_FACTOR. * speedup [SPEED_FACTOR] - speeds up all game actions by SPEED_FACTOR. * drop[ITEM,LOCATION] - places ITEM at LOCATION. * move[BOT,LOCATION] - moves specified Quagent to specified LOCATION. * look[POSITION,DIRECTION] - produces a snapshot taken from POSITION facing DIRECTION. * findDist [POSITION1, POSITION2] - returns the distance between two points. * setHealth [BOT,HEALTH] - sets Quagent's health to HEALTH. * setArmor [BOT,ARMOR] - sets Quagent's armor to ARMOR. * isWithin [BOT,SPACE] - determines if Quagent is within the specified SPACE. * listen [POSITION] - listens for Quagent communications at the given POSITION. * pause [VOID] - global pause. calling this while paused acts as a resume. == WalterAPI == Walter mentioned to me that he would like implementations of the following functions (which we haven't done yet): * SENSORS * current_item * ACTIONS * player_use