Birds Bot Manager ----------------- 1. Why I did it I have been playing Half-Life / CS on and off for the last 6 months or so, and recently I have become interested in Halflife bot programming. Being a programmer by trade, I was curious about how it was done. Looking around on the net I found some sample bot code and downloaded it to see what it was all about. I found out that bot writers have to pull a nasty deception on Half-Life - you see, Half-Life doesn't actually support bots at all. The Half-Life engine assumes that all connected players are humans. So how do we add bots? Read on... Half-Life exposes a collection of functions for the use of mod programmers (the "HL Engine API"), but these mods also do not support bots. The mod code assumes that all connected players are remote network clients, and leaves it up to the Half-Life engine to manage their details. The only way to add bot support to Half-Life is to pull a stunt called the "man-in-the-middle" (MITM) attack. This is where you convince the Half-Life engine to load your own custom code as the "mod", and in turn your code loads the real mod. Your code is then in a position to snoop on all the API traffic between the Half-Life engine and the real mod, and it is also in a position where it can modify the parameters as they go past, or even call some of the Half-Life or mod functions directly. Here is a quick diagram to illustrate this: Normal Half-Life multiplayer: +---------------+ +----------------------+ | HL Engine | <--------> | valve/dlls/HL.DLL | +---------------+ +----------------------+ Half-Life using the CounterStrike MOD: +---------------+ +----------------------+ | HL Engine | <--------> | cstrike/dlls/MP.DLL | +---------------+ +----------------------+ Half-Life with "man-in-the-middle" code + the CS MOD: +---------------+ +-----------+ +----------------------+ | HL Engine | <---> | MyLib.DLL | <---> | cstrike/dlls/MP.DLL | +---------------+ +-----------+ +----------------------+ To fool the Half-Life engine into loaded "MyLib.DLL" as the mod all you have to do is modify a file named liblist.gam in the cstrike directory. This same principle holds true for any multiplayer or mod combination. I am using CounterStrike here as an example only because it is the mod that I actually play :-) "MyLib.DLL" can be coded to provide one or more "bots" without either Half-Life or the mod being any the wiser. This was the current state of bot programming - here is a diagram: +---------------+ +----------------+ +----------------------+ | HL Engine | <---> | INTERFACE CODE | <---> | cstrike/dlls/MP.DLL | +---------------+ | BOT CODE | +----------------------+ +----------------+ While this approach certainly works, and seems to be used by all current HL bots, there are some problems that make bot writing more difficult than it ought to be: * The BOT code is all mixed up with the INTERFACE code, so it is not possible to load more than one type of bot into any game. each bot assumes that it is doing the MITM attack. * It is difficult to cleanly separate out the "interface" code and logic from the actual "bot" code and logic. The interface stuff can be a few thousands of lines, most of which is not directly relevant to the bot code, but they both end up tangled together. * The bot code has to work directly with the HL/MOD API functions. This is a problem because those functions do not support "bots" directly, and there are numerous tricks that must be pulled for it to all work properly. Again, the details of this are not relevant to the bot logic and should not be visible to the bot writer. Writing even a very simple bot would involve working with a few thousand lines of code. I believe that a simple bot should be created with less than a hundred lines of C++, making it easy to get started in bot programming. I decided that a new structure was needed that would remove these limitations. What was needed is a generic "Bot Manager" which would perform all the interface logic with HL and the MOD, and also provide a much nicer Bot API to the bot writers. Look at this diagram: +---------------+ +-------------+ +----------------------+ | HL Engine | <---> | Bot Manager | <---> | cstrike/dlls/MP.DLL | +---------------+ +-------------+ +----------------------+ | | +-----------------+ | (Bot API) | | | +------------+ +------------+ | BirdBot | | ImmirBot | +------------+ +------------+ This diagram shows the situation with my proposed "Bot Manager" taking care of all the low-level interface work, and two Bot Classes loaded ("BirdBot" and "ImmirBot"). In any actual game there could be any mixture of bots of type "BirdBot" or "ImmirBot" alongside normal players. I can also imagine the situation if some of the existing bots (NNbot, RealBot etc) were modified to use this API and then they too could be loaded via the Bot Manager and play alongside one another in the same games. The API that is exposed by the Bot Manager is much nicer than the raw HL API. It has the following features: * Each bot gets a message queue and operates in a purely event-driven way. Each bot supplies a "Think" function that is called regularly by the BM. * The BM provides a visibility framework for the bots. Bots receive messages when an entity or point that they are monitoring comes into or leaves their field of view. * Bots interact with their environment via methods supplied to the Bot class. These methods provide a "natural" means of interaction, with all the details of the interface logic hidden. * The API is mod-independant. The same API is supplied for CS, TFC, etc. Only the messages and their contents changes. This makes it much easier to code a bot for multiple mods. With my current implementation of "Birds Bot Manager" a simple bot can be coded up in about 100 lines - exactly what was desired.