Calin said:
who is issuing the orders for computer controlled units in a RTS
Usually the server running a player as AI, or (much less likely) an automated client.
The game server has all the information it needs since it is already simulating everything in the game. It takes relatively little additional work to select items to build, targets to attack, and all the rest. It also could be a dedicated client, it's possible to build a client that takes some parameters to run without graphics, connect exactly the same as any other game client, and simulates a player. They're commonly built for testing as the game is developed.
Note that while it is “relatively little additional work”, that isn't meant to trivialize it. It's still a lot of work, but compared to everything else in an online multiplayer RTS, building AI-controlled players is “relatively easy”.
Calin said:
My question is how did they had things organized in Starcraft. In 1998 people were not using C++ to develop games
You're mistaken. It was mostly C++ code.
Games started making the transition to C++ in the late 80s and early 90s, way before the language was standardized. At first it was PC games as console games were generally in assembly. PC games were already getting pretty comfortable in C, so early games picked up a “C with classes” subset of the language. By the late '90s PC games had widely adopted C++ (among other languages) and console games were increasingly using the language.
Calin said:
Did they had structures to keep the unit data and `common` functions (functions in the global scope) to change/work with the data found in each structure instance.
Yes, both in C and C++ code.
It was quite common (and still is) for idiomatic C to work an awful lot like C++ classes.
In C++ there is a blob of data, and member functions have a hidden pointer parameter called “this”. In C, it is quite common for the first parameter or two to also be a blob of data. If you're not familiar with them, check out the various file functions like fopen(), fclose(), fread(), fwrite(), etc. The first parameter is a pointer to a blob of data (which is opaque to the user) that effectively is the same as a class. The call to fopen() is essentially a factory method that generates the correct blob of data, historically doing work like looking up the correct versions of functions to handle a file being on a hard drive or a network drive or a floppy disk, then giving a pointer to the abstract base class (called FILE) which is passed to every function in the family.
They were often given a prefix for the system, like the fxxx functions for files, gxxx functions for graphics, mxxx functions for math, and later when longer names were standardized (early versions of the language only allowed 6 unique characters for a function and other symbol names) longer names became common. graphics_xxx, math_xxx, network_xxx, and so on.
Stroustrup and other early language pioneers weren't intending to split the language. In that era (late 70s and early 80s) it was common for computer labs to extend and customize the language tools, adapting them to the computers they made and purchased. The changes to both Objective C and C++ were originally rather small, and simplified common practices that remain to this day. Member functions and their scope was just a way to simply naming conventions, ensuring the prefix was valid through using functions inside the structure. What we call virtual functions was already a common practice in C to use a set of function pointers and swap them out with the actual implementation, as demonstrated above in fopen(). In C there was a two-step dance for allocation, one step to allocate memory, the second to initialize memory based on a pattern, so in their customizations to the C language the pattern was simplified to make it a single step, both allocate and construct. Same with teardown, there was often a teardown function, and destructors did that automatically. Back in early 80s they were similar enough and non-standardized enough that they could have been considered just flavors of the same language. It wasn't until about the C89 language standard that the two had diverged enough to be incompatible on advanced features.