NullBot goes through big refactoring

Get some help with creating maps or modding.
Need a map editor or other tools, look here!
User avatar
NoQ
Special
Special
Posts: 6219
Joined: 24 Dec 2009, 11:35
Location: /var/zone

NullBot goes through big refactoring

Post by NoQ » 15 Jan 2013, 06:59

Or maybe rather through rewriting from scratch.
Not sure if the new AI is worth calling itself NullBot v3.0. Maybe "ZeroBot"? (:

Now it should not only play well, but also be easy to understand. I will provide a download and a git repository as soon as anything is ready; right now it already plays, but hardly better than Semperfi-JS.

Now NullBot shouldn't contain tons of dead code coming from ideas that proved ineffective. The code is now split into many small files, that should be relatively intuitive to navigate. Also, i'd like to make it 3.2-only, so that to be able to use some fancy functions without too much thinking.

Out of what is done, probably the thing i like the most is personality definition. It should be much more flexible (defining personalities for third-party mods should no longer be hacking), and it pretty much includes most of the suggestions by Shadow Wolf TJC.

To achieve that, i'm introducing a separate entity called a "ruleset". It is an include file that can be used by many personalities. It provides a summary of game stats and rules for the AI to use.

Personality definition is now in the main .js file. It includes the head, then its ruleset, then defines the personality, then includes the rest of the code.

Here is what i currently use as proof of concept.

nb_rulesets/standard.js.inc - Standard game's ruleset. Some things are still missing, like list of construction turrets or repair facilities.

Code: Select all

/*
 * This file describes standard stats and strategies of 
 * the base (unmodded) game.
 * 
 * If you want to make an AI specially designed for your mod, start by
 * making a copy of this file and modifying it according to your mod's rules.
 * 
 * Then provide a personality to use the ruleset, similar to 
 * how nb_generic.[js|ai] is provided for this ruleset.
 * 
 */

const structures = {
	factories: [ "A0LightFactory", ],
	templateFactories: [ "A0CyborgFactory", ],
	vtolFactories: [ "A0VTolFactory1", ],
	labs: [ "A0ResearchFacility", ],
	gens: [ "A0PowerGenerator", ],
	hqs: [ "A0CommandCentre", ],
	derricks: [ "A0ResourceExtractor", ],
	extras: [ "A0Sat-linkCentre", "A0LasSatCommand", ],
};

// NOTE: you cannot use specific stats as bases, but only stattypes
// probably better make use of .name rather than of .stattype here?
const modules = [
	{ base: POWER_GEN, module: "A0PowMod1", count: 1, cost: MODULECOST.CHEAP },
	{ base: FACTORY, module: "A0FacMod1", count: 2, cost: MODULECOST.EXPENSIVE },
	{ base: VTOL_FACTORY, module: "A0FacMod1", count: 2, cost: MODULECOST.EXPENSIVE },
	{ base: RESEARCH_LAB, module: "A0ResearchModule1", count: 1, cost: MODULECOST.EXPENSIVE },
];

const targets = []
	.concat(structures.factories)
	.concat(structures.templateFactories)
	.concat(structures.vtolFactories)
	.concat(structures.extras)
;

// body and propulsion arrays don't affect fixed template droids
const propulsionStats = {
	ground: [
		{ res: "R-Vehicle-Prop-Wheels", stat: "wheeled01" },
		{ res: "R-Vehicle-Prop-Halftracks", stat: "HalfTrack" },
		{ res: "R-Vehicle-Prop-Tracks", stat: "tracked01" },
	],
	hover: [
		{ res: "R-Vehicle-Prop-Hover", stat: "hover01" },
	],
	vtol: [
		{ res: "R-Vehicle-Prop-VTOL", stat: "V-Tol" },
	],
}

const bodyStats = {
	kinetic: [
		{ res: "R-Vehicle-Body01", stat: "Body1REC", weight: WEIGHT.LIGHT, usage: BODYUSAGE.UNIVERSAL }, // viper
		{ res: "R-Vehicle-Body05", stat: "Body5REC", weight: WEIGHT.MEDIUM, usage: BODYUSAGE.UNIVERSAL }, // cobra
		{ res: "R-Vehicle-Body02", stat: "Body2SUP", weight: WEIGHT.LIGHT, usage: BODYUSAGE.UNIVERSAL }, // leopard
		{ res: "R-Vehicle-Body11", stat: "Body11ABT", weight: WEIGHT.HEAVY, usage: BODYUSAGE.GROUND }, // python
	],
	thermal: [
		{ res: "R-Vehicle-Body04", stat: "Body4ABT", weight: WEIGHT.LIGHT, usage: BODYUSAGE.UNIVERSAL }, // bug
		{ res: "R-Vehicle-Body08", stat: "Body8MBT", weight: WEIGHT.MEDIUM, usage: BODYUSAGE.UNIVERSAL }, // scorpion
	],
}

// Unlike bodies and propulions, weapon lines don't have any specific meaning.
// You can make as many weapon lines as you want for your ruleset.
const weaponStats = {
	machineguns: {
		role: ROLE.AP,
		chataliases: "mg",
		weapons: [
			{ res: "R-Wpn-MG1Mk1", stat: "MG1Mk1", weight: WEIGHT.LIGHT }, // mg
			{ res: "R-Wpn-MG2Mk1", stat: "MG2Mk1", weight: WEIGHT.LIGHT }, // tmg
		],
		vtols: [
			{ res: "R-Wpn-MG3Mk1", stat: "MG3-VTOL", weight: WEIGHT.LIGHT }, // vtol hmg
		],
		defenses: [
			{ res: "R-Defense-Tower01", stat: "GuardTower1", defrole: DEFROLE.GATEWAY }, // mg tower
		],
		templates: [
			{ res: "R-Wpn-MG1Mk1", body: "CyborgChain1Ground", prop: "CyborgLegs", weapon: "CyborgChain1Ground" }, // mg cyborg
		],
		extras: [
			"R-Wpn-MG-Damage01",
		],
	},
};
nb_generic.js - the generic AI personality code. Highly incomplete right now: supports only a few weapons and bodies.

Code: Select all

/*
 * This file defines a standard AI personality for the base game. 
 * 
 * It relies on ruleset definition in /rulesets/ to provide
 * standard strategy descriptions and necessary game stat information.
 * 
 * Then it passes control to the main code.
 * 
 */

// You can redefine these paths when you make a customized AI
// for a map or a challenge.
NB_PATH = "/multiplay/skirmish/" ;
NB_INCLUDES = NB_PATH + "nb_includes/";
NB_RULESETS = NB_PATH + "nb_rulesets/";

// please don't touch this line
include(NB_INCLUDES + "_head.js.inc");

////////////////////////////////////////////////////////////////////////////////////////////
// Start the actual personality definition

// the rules in which this personality plays
include(NB_RULESETS + "standard.js.inc");

// variables defining the personality
var personality = {
	weaponPaths: [ weaponStats.machineguns, ], // weapons to use
	maxDispersion: 5, // how dispersed may the tanks be
	minTanks: 4, // minimal attack force at game start
	becomeHarder: 2, // how much to increase attack force every 5 minutes
	maxTanks: 32, // maximum attack force size
}

// this function describes the early build order
function buildOrder() {
	var ret;
	if (countStructList(structures.factories) < 1)
		buildBasicStructure(structures.factories) != BUILDRET.UNAVAILABLE ? return:;
	if (countStructList(structures.labs) < 1) 
		buildBasicStructure(structures.labs) != BUILDRET.UNAVAILABLE ? return:;
	if (countStructList(structures.gens) < 1)
		buildBasicStructure(structures.gens) != BUILDRET.UNAVAILABLE ? return:;
	if (countStructList(structures.hqs) < 1) 
		buildBasicStructure(structures.hqs) != BUILDRET.UNAVAILABLE ? return:;
	}
}

////////////////////////////////////////////////////////////////////////////////////////////
// Proceed with the main code

include(NB_INCLUDES + "_main.js.inc");
As you see, most of the things happen in the ruleset in a way universally readable by personalities. The personality definition is very short. I've decided not to include separate lists for research, components and defenses (which is a pain to maintain and to code), but instead merge these lists together into a single flow of eg. (technology, component) pairs with special marks indicating how to use these components (eg. don't put heavy weapons on light bodies).

I'm also deprecating the notion of a cyborg in favor of a fixed template, since some mods (eg. WZMini) contain fixed templates that aren't on any cyborg propulsion.

Ideally, every object should only be mentioned at most once in these lists. This makes them shorter than NullBot's endless lists of things with tons of duplication.

I'm also trying to make the code ready for reverse adaptation that will become available when we get access to droid.weapon property. That's why, for instance, bodies are split into kinetic and thermal (depending on which armor is better).

_________________________________

If anybody helps me filling in rulesets, i'd be happy (: that's probably the only point of this announcement. The other point is to discuss the limitations of the approach.
Last edited by NoQ on 15 Jan 2013, 09:25, edited 1 time in total.

Lord Apocalypse
Regular
Regular
Posts: 678
Joined: 29 Jul 2009, 18:01

Re: NullBot goes through big refactoring

Post by Lord Apocalypse » 15 Jan 2013, 08:30

hmm why not VoidBot

User avatar
aubergine
Professional
Professional
Posts: 3459
Joined: 10 Oct 2010, 00:58
Contact:

Re: NullBot goes through big refactoring

Post by aubergine » 15 Jan 2013, 08:59

void = undefined = lower than null :P

... in javascript at least.

Trivia: In JS, 'undefined' can be redefined to something that's not undefined, resulting in undefined not being undefined and, perhaps more annoyingly, if you define undefined as being null, then undefined == null and undefined === null, whereas undefined should be only == and not === to null. Void is the only way to get a real undefined that is always === undefined and always == but not === null.
"Dedicated to discovering Warzone artefacts, and sharing them freely for the benefit of the community."
-- https://warzone.atlassian.net/wiki/display/GO

Per
Warzone 2100 Team Member
Warzone 2100 Team Member
Posts: 3767
Joined: 03 Aug 2006, 19:39

Re: NullBot goes through big refactoring

Post by Per » 15 Jan 2013, 09:00

That is an interesting approach. It will be exciting to watch it unfold :)

themac
Trained
Trained
Posts: 355
Joined: 17 Jul 2009, 19:14
Location: Germany

Re: NullBot goes through big refactoring

Post by themac » 15 Jan 2013, 21:40

Why not naming it to "NoQBot" :-)

User avatar
NoQ
Special
Special
Posts: 6219
Joined: 24 Dec 2009, 11:35
Location: /var/zone

Re: NullBot goes through big refactoring

Post by NoQ » 21 Jan 2013, 14:48

The git repository is finally available at
It's far from polished and hardly has all features of the original NullBot (and filled with TODO marks and stupid placeholders), but at least you have a chance to grasp the ideas behind its code (if any, most of them must be concentrated around adapt code and ruleset/personality stat definitions). Also, i'm very happy with the current attack and regroup code. It got many times shorter and yet seems to be much more effective.

You will most likely not be able to run it comfortably until some of these bugs are fixed on the game side. Of course, you won't be able to run it on 3.1.

User avatar
Duha
Trained
Trained
Posts: 287
Joined: 25 Mar 2012, 20:05
Location: SPb, Russia

Re: NullBot goes through big refactoring

Post by Duha » 21 Jan 2013, 15:37

NoQ wrote:The git repository is finally available at
It's far from polished and hardly has all features of the original NullBot (and filled with TODO marks and stupid placeholders), but at least you have a chance to grasp the ideas behind its code (if any, most of them must be concentrated around adapt code and ruleset/personality stat definitions). Also, i'm very happy with the current attack and regroup code. It got many times shorter and yet seems to be much more effective.

You will most likely not be able to run it comfortably until some of these bugs are fixed on the game side. Of course, you won't be able to run it on 3.1.
You still use "inc" file extensions for js files. :(

May be you can use underscorejs http://underscorejs.org/ it contains a lot of useful features. (Sorry i did not test it compatibility with warzone)
http://addons.wz2100.net/ developer

User avatar
NoQ
Special
Special
Posts: 6219
Joined: 24 Dec 2009, 11:35
Location: /var/zone

Re: NullBot goes through big refactoring

Post by NoQ » 21 Jan 2013, 15:56

Duha wrote:You still use "inc" file extensions for js files. :(
It was asked by the game developers as one of the requirements to merge the code into the game, so that qslint didn't attempt to parse them as standalone files. Originally i called them .inc.js, but i was asked to rename them at some point.

User avatar
aubergine
Professional
Professional
Posts: 3459
Joined: 10 Oct 2010, 00:58
Contact:

Re: NullBot goes through big refactoring

Post by aubergine » 21 Jan 2013, 16:02

I looked at using _ for EggPlant but in the end decided not to -- many of it's features are native in WZ's JS environment, and many didn't seem useful for WZ scripting. Also, I was unsure how to change it from using _ as it's namespace (considering WZ has an immutable global _() function). More specifically, the .noConflict() is not useful because by that time it will already have borked.
"Dedicated to discovering Warzone artefacts, and sharing them freely for the benefit of the community."
-- https://warzone.atlassian.net/wiki/display/GO

Per
Warzone 2100 Team Member
Warzone 2100 Team Member
Posts: 3767
Joined: 03 Aug 2006, 19:39

Re: NullBot goes through big refactoring

Post by Per » 21 Jan 2013, 16:21

The future of qslint is somewhat murky, to say the least, so perhaps the .inc extension thing could be reconsidered...

User avatar
Duha
Trained
Trained
Posts: 287
Joined: 25 Mar 2012, 20:05
Location: SPb, Russia

Re: NullBot goes through big refactoring

Post by Duha » 21 Jan 2013, 17:04

aubergine wrote:I looked at using _ for EggPlant but in the end decided not to -- many of it's features are native in WZ's JS environment, and many didn't seem useful for WZ scripting. Also, I was unsure how to change it from using _ as it's namespace (considering WZ has an immutable global _() function). More specifically, the .noConflict() is not useful because by that time it will already have borked.
Lets name it underscore not _ :)
On quick look I found 4 functs from it implemented by NoQ.
http://addons.wz2100.net/ developer

User avatar
aubergine
Professional
Professional
Posts: 3459
Joined: 10 Oct 2010, 00:58
Contact:

Re: NullBot goes through big refactoring

Post by aubergine » 21 Jan 2013, 19:57

@Duha - which is better than having about 200 functions from it sitting around not being used.

I've done similar in my AI - there are a few things that I've used, but I implement only as needed and to the requirements of the way I use them, for example n.times().

@Per: It's useful to some extent for picking up basic JS errors, but most of the time it misses the stuff that matters and it's only when you get to runtime that you get exceptions thrown. Maybe if jslint could be optional? So, perhaps use it during dev cycles, but have it switched off in releases? For AIs, it could be a setting in the .ai file?
"Dedicated to discovering Warzone artefacts, and sharing them freely for the benefit of the community."
-- https://warzone.atlassian.net/wiki/display/GO

User avatar
NoQ
Special
Special
Posts: 6219
Joined: 24 Dec 2009, 11:35
Location: /var/zone

Re: NullBot goes through big refactoring

Post by NoQ » 21 Jan 2013, 20:32

I'm a bit scared of using a 3rdparty throttle function because it doesn't know what gameTime is (though it may work).

User avatar
aubergine
Professional
Professional
Posts: 3459
Joined: 10 Oct 2010, 00:58
Contact:

Re: NullBot goes through big refactoring

Post by aubergine » 21 Jan 2013, 20:37

@NoQ - some of those underscore functions would, others wouldn't. Libraries aimed at web browsers often have a lot of additional cruft as well, to deal with things like Internet Exploder. So, if anything, just pick at their code for ideas about how to do things and then implement WZ specific code.
"Dedicated to discovering Warzone artefacts, and sharing them freely for the benefit of the community."
-- https://warzone.atlassian.net/wiki/display/GO

User avatar
Duha
Trained
Trained
Posts: 287
Joined: 25 Mar 2012, 20:05
Location: SPb, Russia

Re: NullBot goes through big refactoring

Post by Duha » 21 Jan 2013, 23:39

aubergine wrote:@NoQ - some of those underscore functions would, others wouldn't. Libraries aimed at web browsers often have a lot of additional cruft as well, to deal with things like Internet Exploder. So, if anything, just pick at their code for ideas about how to do things and then implement WZ specific code.
They have good commented code http://documentcloud.github.com/undersc ... score.html it is easy to take part of it.
http://addons.wz2100.net/ developer

Post Reply