Hi Mike,
I'll try to provide an overview of what's already possible with v3.6.0.3, and how.
a) I presume you read the unit properties from some file, e.g. XML, this is needed to try out other values automatically.
I'll start with a simplified overview of how the game data is structured.
MegaGlest game data can be one of:
- techtrees
- maps
- tilesets
- scenarios
A techtree contains (amongst other) one or more factions. A faction contains (amongst other) one or more units.
The default game data (the Megapack techtree mostly) is installed directly into the installation directory, giving you this directory structure:
tomreyn@atibox:~/megaglest-3.6.0.3$ ls -p --group-directories-first
blender/ core megaglest.ico
data/ editor.ico megaglest_uninstall.ico
docs/ g3dviewer.ico servers.ini
lib/ glest.ini start_megaglest
maps/ glestkeys.ini start_megaglest_configurator
scenarios/ megaglest start_megaglest_g3dviewer
techs/ megaglest.bmp start_megaglest_mapeditor
tilesets/ megaglest_configurator uninstall-megaglest.sh
tutorials/ megaglest_editor
configuration.xml megaglest_g3dviewer
tomreyn@atibox:~/megaglest-3.6.0.3$ ls -p --group-directories-first techs/
megapack/
tomreyn@atibox:~/megaglest-3.6.0.3$ ls -p --group-directories-first techs/megapack/
commondata/ factions/ resources/ megapack.xml
tomreyn@atibox:~/megaglest-3.6.0.3$ ls -p --group-directories-first techs/megapack/factions/
egypt/ indian/ magic/ norsemen/ persian/ romans/ tech/
tomreyn@atibox:~/megaglest-3.6.0.3$ ls -p --group-directories-first techs/megapack/factions/egypt/
music/ units/ upgrades/ egypt.xml loading_screen.jpg
tomreyn@atibox:~/megaglest-3.6.0.3$ ls -p --group-directories-first techs/megapack/factions/egypt/units/
air_pyramid/ desert_camp/ mummy/ pyramid/ snake/ sphinx/
anubis_warrior/ farm/ obelisk/ scarab/ spearman/ temple/
chicken/ ibis/ priest/ slave/ spearthrower/
tomreyn@atibox:~/megaglest-3.6.0.3$ ls -p --group-directories-first techs/megapack/factions/egypt/units/mummy/
images/ models/ sounds/ mummy.xml
As the file name indicates, mummy.xml is a plain text file with an XML structure:
tomreyn@atibox:~/megaglest-3.6.0.3$ cat techs/megapack/factions/egypt/units/mummy/mummy.xml
<?xml version="1.0" standalone="no"?>
<unit>
<parameters>
<size value="1"/>
<height value="2"/>
<max-hp value="600" regeneration="0"/>
<max-ep value="0"/>
<armor value="10"/>
<armor-type value="organic"/>
<sight value="12"/>
<time value="25"/>
<multi-selection value="true"/>
<cellmap value="false"/>
<levels/>
<fields>
<field value="land"/>
</fields>
<properties/>
<light enabled="false"/>
<unit-requirements/>
<upgrade-requirements/>
<resource-requirements>
<resource name="gold" amount="45"/>
<resource name="food" amount="1"/>
</resource-requirements>
<resources-stored/>
<image path="images/daemon.bmp"/>
<image-cancel path="../spearman/images/tech_cancel.bmp"/>
<meeting-point value="false"/>
<selection-sounds enabled="true">
<sound path="sounds/mummy_select1.wav"/>
<sound path="sounds/mummy_select2.wav"/>
<sound path="sounds/mummy_select3.wav"/>
<sound path="sounds/mummy_select4.wav"/>
<sound path="sounds/mummy_select5.wav"/>
<sound path="sounds/mummy_select6.wav"/>
<sound path="sounds/mummy_select7.wav"/>
</selection-sounds>
<command-sounds enabled="true">
<sound path="sounds/mummy_ack1.wav"/>
<sound path="sounds/mummy_ack2.wav"/>
<sound path="sounds/mummy_ack3.wav"/>
<sound path="sounds/mummy_ack4.wav"/>
<sound path="sounds/mummy_ack5.wav"/>
</command-sounds>
</parameters>
<skills>
<skill>
<type value="stop"/>
<name value="stop_skill"/>
<ep-cost value="0"/>
<speed value="1000"/>
<anim-speed value="40"/>
<animation path="models/mummy_standing.g3d"/>
<sound enabled="false"/>
</skill>
<skill>
<type value="move"/>
<name value="move_skill"/>
<ep-cost value="0"/>
<speed value="250"/>
<anim-speed value="120"/>
<animation path="models/mummy_walking.g3d"/>
<sound enabled="false"/>
</skill>
<skill>
<type value="attack"/>
<name value="attack_skill"/>
<ep-cost value="0"/>
<speed value="100"/>
<anim-speed value="100"/>
<animation path="models/mummy_attacking.g3d"/>
<sound enabled="true" start-time="0.0">
<sound-file path="sounds/mummy_attack11.wav"/>
<sound-file path="sounds/mummy_attack12.wav"/>
<sound-file path="sounds/mummy_attack13.wav"/>
<sound-file path="sounds/mummy_attack14.wav"/>
<sound-file path="sounds/mummy_attack10.wav"/>
<!--sound-file path="sounds/mummy_attack1.wav"/>
<sound-file path="sounds/mummy_attack2.wav"/>
<sound-file path="sounds/mummy_attack3.wav"/>
<sound-file path="sounds/mummy_attack4.wav"/>
<sound-file path="sounds/mummy_attack5.wav"/>
<sound-file path="sounds/mummy_attack6.wav"/>
<sound-file path="sounds/mummy_attack7.wav"/>
<sound-file path="sounds/mummy_attack8.wav"/>
<sound-file path="sounds/mummy_attack9.wav"/-->
</sound>
<attack-strenght value="70"/>
<attack-var value="40"/>
<attack-range value="1"/>
<attack-type value="slashing"/>
<attack-fields>
<field value="land"/>
</attack-fields>
<attack-start-time value="0.3"/>
<projectile value="false"/>
<splash value="false"/>
</skill>
<skill>
<type value="die"/>
<name value="die_skill"/>
<ep-cost value="0"/>
<speed value="120"/>
<anim-speed value="20"/>
<animation path="models/mummy_dying.g3d"/>
<sound enabled="true" start-time="0">
<sound-file path="sounds/mummy_die1.wav"/>
<sound-file path="sounds/mummy_die2.wav"/>
<sound-file path="sounds/mummy_die3.wav"/>
<sound-file path="sounds/mummy_die4.wav"/>
</sound>
<fade value="false"/>
</skill>
</skills>
<commands>
<command>
<type value="stop"/>
<name value="stop"/>
<image path="../spearman/images/tech_stop.bmp"/>
<unit-requirements/>
<upgrade-requirements/>
<stop-skill value="stop_skill"/>
</command>
<command>
<type value="move"/>
<name value="move"/>
<image path="../spearman/images/tech_move.bmp"/>
<unit-requirements/>
<upgrade-requirements/>
<move-skill value="move_skill"/>
</command>
<command>
<type value="attack"/>
<name value="attack"/>
<image path="images/mummy_attack.bmp"/>
<unit-requirements/>
<upgrade-requirements/>
<move-skill value="move_skill"/>
<attack-skill value="attack_skill"/>
</command>
</commands>
</unit>
Obviously you could edit these values by scripting, or you could create additional tech trees / factions in a test techtree which use modified values. Generally you should not modify the default game data (installed in the games' installation directory), but you can store additional (custom) data where the
INI directive UserData_Root points to. On Linux, this is usually
~/.megaglest/, where you have the same directory structure as within the main installation directory, i.e. there is a
techs subdirectory there. The game creates checksums on custom data and caches it, so if you modify it then you should (possibly, to be sure, delete the cache, located at UserData_Root/cache/ and) restart the game to have it recalculate the checksums.
To deduplicate data, file references in XML files may point to other existing techtrees (assuming you know their name and the names of factions/units they contain). This allows you, for example, to have a megapack2 techtree which is an exact clone of the existing megapack techtree but only changes the properties (XML files) of one faction and one unit inside of it, which can considerably cut down on disk space (and time involved in copying stuff around).
So if you want to run tests with ten variations of the 'mummy' unit, I can think of two ways to achieve it:
- Create deduplicated clones of the Megapack techtree, modifying files as needed, and place these in UserData_Root/; then run your tests referencing a different one of these techtrees in every pass
- Create a single deduplicated (or not) clone of the Megapack techtree and place it in UserData_Root/; then run your tests referencing always this one cloned techtree in every pass, but using scripting (sed -i) and/or file system properties (symlinks) to apply changes to the game data as needed
On a side note, scenarios may also be of interest to you, as they allow for some
LUA scripting.
b) We would need the possibility to automatically start a game with a specific setting in some kind of batch mode (via command line?), and there shall be some result file we can read so that we know who won.
Basically Softcoder already answered the first part of this question by pointing out that there is a mechanism (
--autostart-lastgame) which allows you to start a game using the last games' settings which are stored in
UserData_Root/lastCustomGamSettings.mgg. This file is a plain text file, looking something like this:
Description=8-players-only-1-will-win
MapFilterIndex=8
Map=8-players-only-1-will-win
Tileset=evergreen
TechTree=megapack
DefaultUnits=1
DefaultResources=1
DefaultVictoryConditions=1
FogOfWar=1
AdvancedIndex=0
AllowObservers=1
FlagTypes1=2
EnableObserverModeAtEndGame=1
AiAcceptSwitchTeamPercentChance=30
PathFinderType=0
EnableServerControlledAI=1
NetworkFramePeriod=20
NetworkPauseGameForLaggedClients=1
FactionThisFactionIndex=0
FactionCount=8
FactionControlForIndex0=7
ResourceMultiplierIndex0=5
FactionTeamForIndex0=0
FactionStartLocationForIndex0=0
FactionTypeNameForIndex0=*Random*
FactionPlayerNameForIndex0=tomreyn
FactionControlForIndex1=3
ResourceMultiplierIndex1=10
FactionTeamForIndex1=1
FactionStartLocationForIndex1=1
FactionTypeNameForIndex1=indian
FactionPlayerNameForIndex1=AI1
FactionControlForIndex2=1
ResourceMultiplierIndex2=0
FactionTeamForIndex2=2
FactionStartLocationForIndex2=2
FactionTypeNameForIndex2=magic
FactionPlayerNameForIndex2=AI2
FactionControlForIndex3=1
ResourceMultiplierIndex3=0
FactionTeamForIndex3=3
FactionStartLocationForIndex3=3
FactionTypeNameForIndex3=norsemen
FactionPlayerNameForIndex3=AI3
FactionControlForIndex4=5
ResourceMultiplierIndex4=5
FactionTeamForIndex4=6
FactionStartLocationForIndex4=4
FactionTypeNameForIndex4=persian
FactionPlayerNameForIndex4=???
FactionControlForIndex5=1
ResourceMultiplierIndex5=0
FactionTeamForIndex5=5
FactionStartLocationForIndex5=5
FactionTypeNameForIndex5=romans
FactionPlayerNameForIndex5=AI4
FactionControlForIndex6=1
ResourceMultiplierIndex6=0
FactionTeamForIndex6=6
FactionStartLocationForIndex6=6
FactionTypeNameForIndex6=tech
FactionPlayerNameForIndex6=AI5
FactionControlForIndex7=1
ResourceMultiplierIndex7=0
FactionTeamForIndex7=7
FactionStartLocationForIndex7=7
FactionTypeNameForIndex7=*Random*
FactionPlayerNameForIndex7=AI6
MegaGlest also supports a headless game(server) mode which stores these settings in
UserData_Root/lastHeadlessGamSettings.mgg instead. It comes with additional options which may be of use for your work: If you start a headless gameserver by invoking the game with
--headless-server-mode=vps,exit it will automatically exit (the process exiting) after the last connected client disconnects, writing out game statistics to standard output:
tomreyn@atibox:~/megaglest-3.6.0.3$ ./megaglest --headless-server-mode=vps,exit
Disabled reading from console [vps]
Forcing quit after game has completed [exit]
megaglest v3.6.0.3
Compiled using: GNUC: 40401 [64bit] on: Jan 24 2012 13:33:42
SVN: [Rev: 3080] - using STREFLOP
Waiting for players to join and start a game...
Headless server is now running...
Starting a new game...
New game has started...
Game ending with stats:
-----------------------
Description: Conflict
Faction count: 2
Game duration (mins): 1
Max Concurrent Units: 27
Total EndGame Concurrent Unit Count: 27
player #0 AI1 (CPU (Easy) x 0.5) faction: Egypt Team: 0 victory: 0 # kills: 5 # enemy kills: 4 # deaths: 1
# units produced: 3 # resources harvested: 12
player #1 tomreyn (Network) faction: Indian Team: 1 victory: 1 # kills: 0 # enemy kills: 0 # deaths: 4
# units produced: 3 # resources harvested: 325
-----------------------
Headless server is about to quit...
tomreyn@atibox:~/megaglest-3.6.0.3$
However, it is not currently possible to combine
--headless-server-mode=vps,exit and
--autostart-lastgame so that, so far, you still need to manually connect a client to the server, make it load the last games' settings, make it start the game, and make it quit the game, all of which currently requires user interaction. You can also not achieve this in single player (non-headless) mode, since then, while you can automatically start the game, you cannot make the process exit automatically, nor will game statistics be written to standard output. And then, having graphic output is probably undesirable since it might impact (falsify) your test results.
So more work would be needed in this area, but much is already possibl, surely more than in Glest 2.0. ;-)