Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,9 @@ You can download a release of this AI that is considered to be "the most stable"
All releases are marked with git tags in this repository.

This AI requires Warzone 2100 v3.2 or higher to work. Unless a time machine has been invented, this means that you'd need to get a nightly development snapshot of the game's master version at http://buildbot.wz2100.net/files/ Please use the actually-latest snapshot, because a lot of work is currently being done on the scripting system.

Harold
=======
Harold is my take on expanding NullBot's interaction with human players, using Automated Personalites. By that, this means you, the player, will be given chat messages from this modfied NullBot, whether you are friend or foe. Although, haoNoQ made this impressive AI exist, not many players felt pressured to take on this AI and it's adaptive strategies. So, by giving this AI a more talkative aspect, the Player can engage in mind games with this AI. This, in theory, might result in more player victories over this AI, when the player successfully pressures the AI into making rash decisions.

The ultimate goal of Harold is to make Skirmishes against the AI, fun again. Any suggestions are allowed, but only if they are within scope of this experiment.
21 changes: 21 additions & 0 deletions TO_DO
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
To-do List for Harold -

High Priority:
* Teach Harold to Chat to Human Opponent. Include following responses for following skirmish situations:
- Greeting upon startup
- Be polite when given polite response from human player (0).
- Otherwise, act like an arse when, when human player responds like such.
- On EASY, declare to player when Harold is "going on the offensive" to serve as warning.
- On EASY, declare to player when Harold has built any structure, besides Factory, Research Center, and/or Command Center.
- On EASY, declare to player when Harold has produced the first of any droid and/or cyborg, besides Construction Droid.
- On EASY, declare to player when Harold catches player is using cowardly tactics (examples of cowardly tactics do not include
use of debug cheats, rather not applying self to research new tech, thus relying on the same droids, and constantly fleeing
from enemy presence. As new info on the subject becomes public, updates will follow.)
- On EASY (and beyond), declare to player when Harold catches player using Cheats, and warn player when Harold will use them, as well.

Low Prioity:
- Declare to player unconditional surrender, when Harold is outmatched by player.
- Praise player when player's attacking force defeats opponent Harold's defending force.
- Declare vengeful response when Harold successfully eliminates dominating player force.
- Declare dominating response when Harold continues to eliminate player reinforcements with dominating force.
- Taunt player.
105 changes: 105 additions & 0 deletions har_includes-custom/_events.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@

/*
* This file includes event definitions only.
*
*/

function eventStartLevel() {
queue("setTimers", me * 100);
if (alliancesType === ALLIANCES_TEAMS) {
// initialize subpersonality pseudo-randomly here
// to make sure teammates have the same personality
var j = 1, s = 0;
for (var i = 0; i < maxPlayers; ++i) {
if (allianceExistsBetween(me, i))
s += j;
j *= 2;
}
// the random "s" number obtained here is the same for all players in any team
var s = s + (new Date()).getMinutes();
j = 0;
for (var i in subpersonalities) // count the amount of subpersonalities
++j;
s = s % j;
j = 0;
for (var i in subpersonalities) {
if (j === s)
personality = subpersonalities[i];
++j;
}
} else {
// if teams are not sharing research, or there are no teams at all,
// initialize the subpersonality randomly and don't care
personality = randomItem(subpersonalities);
}
// the following code is necessary to avoid some strange game bug when droids that
// are initially buried into the ground fail to move out of the way when a building
// is being placed right above them
enumTrucks().forEach(function(droid) {
orderDroidLoc(droid, DORDER_MOVE, droid.x + random(3) - 1, droid.y + random(3) - 1);
});
}

function eventDroidBuilt(droid, structure) {
groupDroid(droid);
}

function eventStructureBuilt(structure) {
queue("checkConstruction");
}

function eventAttacked(victim, attacker) {
if (attacker === null)
return; // no idea why it happens sometimes
if (isAlly(attacker.player))
return; // don't respond to accidental friendly fire
if (victim.type === DROID) {
if (!isVTOL(victim) && defined(victim.group)) {
fallBack(victim, attacker);
setTarget(attacker, victim.group);
touchGroup(victim.group);
} else if (isVTOL(victim) && victim.player == me && !throttled(5000, victim.id)) {
orderDroidObj(victim, DORDER_ATTACK, attacker);
pushVtols(attacker);
}
} else if (victim.type === STRUCTURE) {
if (throttled(5000) && victim.player != me)
return;
if (inPanic())
for (var i = 0; i < MAX_GROUPS; ++i)
if (groupSize(i) > 0)
setTarget(attacker, i);
setTarget(attacker, miscGroup);
setTarget(attacker);
}
}

function eventStructureReady(structure) {
fireLassat(structure);
}

function eventChat(from, to, message) {
// we are not case-sensitive
message = message.toLowerCase();
handleChatMessage(from, to, message)
}

function eventObjectTransfer(object, from) {
if (object.player !== me)
return; // object was transferred from me, not to me
if (object.type === DROID)
groupDroid(object);
}

function eventBeacon(x, y, from, to) {
noticeBeacon(x, y, from);
}

function eventBeaconRemoved(from, to) {
unnoticeBeacon(from);
}

function eventDestroyed(object) {
if (isEnemy(object.player))
pushVtols(object);
}
107 changes: 107 additions & 0 deletions har_includes-custom/_head.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@

/*
* This file defines generic things that should be defined
* prior to defining a ruleset.
*
* NOTE: This file is not included from main.js .
*
*/

// weapon path role
const ROLE = {
AT: 0,
AP: 1,
AS: 2,
AA: 3,
LENGTH: 4, // number of items in this enum
}

// something dual to the previous enum
const OBJTYPE = {
TANK: 0,
BORG: 1,
DEFS: 2,
VTOL: 3,
LENGTH: 4, // number of items in this enum; should be equal to ROLE.LENGTH
}

// this controls body and weapon compatibility.
// A little explanation:
// w \ b | L | M | H bodies can't be "ultra-",
// UL | + | - | - ultra-light weapons are for light bodies only,
// L | + | + | - light weapons are for light or medium bodies,
// M | + | + | + medium weapons are for all bodies,
// H | - | + | + heavy weapons are for medium or heavy bodies,
// UH | - | - | + ultra-heavy weapons are for heavy bodies only.
const WEIGHT = {
ULTRALIGHT: 0,
LIGHT: 1,
MEDIUM: 2,
HEAVY: 3,
ULTRAHEAVY: 4,
}

// what to use this defensive structure for
const DEFROLE = {
STANDALONE: 0,
GATEWAY: 1,
ARTY: 2,
ANTIAIR: 3,
FORTRESS: 4,
}

// return values of build order calls
const BUILDRET = {
SUCCESS: 0,
UNAVAILABLE: 1,
FAILURE: 2,
}

// should we execute a build call in an unsafe location?
const IMPORTANCE = {
PEACETIME: 0,
MANDATORY: 1,
}

// aspects of every research path
const RESASPECTS = {
WEAPONS: 0,
DEFENSES: 1,
VTOLS: 2,
EXTRAS: 3,
LENGTH: 4, // number of items in this enum
}

const PROPULSIONUSAGE = {
GROUND : 1,
HOVER: 2,
VTOL: 4
}

// what to use this body for? (bit field)
const BODYUSAGE = {
GROUND: 1, // for tanks
AIR: 2, // for VTOLs
COMBAT: 3, // GROUND | AIR
TRUCK: 4, // trucks, sensors and repair droids
UNIVERSAL: 7, // COMBAT | TRUCK
}

// what sort of weapons this body is resistant to?
const BODYCLASS = {
KINETIC: 1,
THERMAL: 2,
}

// should this module be prioritized when not having enough power?
const MODULECOST = {
CHEAP: 0,
EXPENSIVE: 1,
}

// how to micromanage tanks with this sort of weapon
const MICRO = {
RANGED: 0, // normal weapons, such as cannons
MELEE: 1, // weapons that need to get very close to the enemy, such as flamers
DUMB: 2, // weapons that can't fire while moving
}
26 changes: 26 additions & 0 deletions har_includes-custom/_main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

/*
* This file connects all remaining pieces of AI code together.
* It shouldn't contain any code itself.
*
* NOTE: order matters!
*
*/

var personality;

include(HAR_INCLUDES + "math.js");
include(HAR_INCLUDES + "intensity.js");
include(HAR_INCLUDES + "misc.js");
include(HAR_INCLUDES + "stats.js");

include(HAR_INCLUDES + "adapt.js");
include(HAR_INCLUDES + "build.js");
include(HAR_INCLUDES + "research.js");
include(HAR_INCLUDES + "produce.js");
include(HAR_INCLUDES + "tactics.js");
include(HAR_INCLUDES + "lassat.js");
include(HAR_INCLUDES + "chat.js");

include(HAR_INCLUDES + "timers.js");
include(HAR_INCLUDES + "_events.js");
Loading