Version 4 (modified by agentx, 10 years ago) ( diff )

--

Hannibal

Intro

The Hannibal AI/Bot is a new approach to reduce the complexity of programming a bot for 0 A.D. It was started in February 2014 by agentx. This page will document the development process and parts of the source, explains major concepts and provides tips & tricks. The forum has already a few posts discussing the bot's features. Little Query Language, AI Tournaments. Ultimately Hannibal should be unbeatable started with the highest difficulty.

In particular the bot will use:

  • a state machine to handle game phases
    like village, town, city, attack, defense, reconstruction, etc.
  • a triple store to link features of the cultures,
    like who can gather fields, can a healer melee?
  • a simple query language to retrieve information from the triple store
    "food.grain GATHEREDBY WITH costs.metal = 0, costs.stone = 0, costs.wood = 0 SORT < costs.food"
  • a HTN PLanner to calculate attack strategies
    (probably the last implemented feature)
  • a plugin system describing the behavior of groups of units
    (grain-picker, hunter, warrior, guerrilla, miner, etc)

State Machine

The state machines relies on clearly distinguishable states. They are connected and have entry and exit conditions. The game starts in the whiteflag state, which it tries to exit. If that is not possible the game is either lost or the map is unplayable.

example code

states: {
  "ai:ai":              {
    entry:              "whiteflag",
    whiteflag:          ["village"],
    village:            ["populate", "town", "victory"],
    town:               ["expand", "defense", "city", "victory"],
    city:               ["attack", "defense", "attack", "victory"],
    victory:            [],
  },
  "ai:ai:1":            {
   village:            ["populate", "technology", "town", "victory"],
  }
}

If the village state's entry conditions like enough resources are met the machine switches and processes all states or sub states mentioned in the list. Victor is checked every turn, to make sure that doesn't happen unrecognized :) "ai:ai:1" indicates a state set for a higher difficulty and basically overwrites the lower ones (adding technology) if chosen by the user. This hierarchy allows easy editing and provides fine tuned set of game difficulties. The states implemented in states.js, defined in config.js, the function getBehaviour() applies the difficulty. Within OnUpdate() this line:

this.state = this.behaviour.process(this); 

checks the conditions, processes the state and sub-states and returns same or a new state.

Triple Store

During start up Hannibal parses all templates of involved civilizations and builds a mesh network consisting of nodes and edges. Nodes are e.g. classes, resources, technologies and all units and entities. Athen's culture generates around 160 nodes and 2000 edges. Nodes use a sanitized form of the templates name as unique name and are saved as a JS object with additional properties like cost, hit points and size. Maps or Weakmaps might perform better, but are untested. Edges consist of an JS array with source node, a verb and the target node, hence the name triple store. Currently there are 26 verbs for 13 edge types with two directions. During the game the store is updated with created and destroyed entities, so the query language can select these as nodes too. In game nodes have a '#' + their id as name suffix. The parser is coded in cultures.js and the store in store.js. Both are separated so the domain knowledge is in cultures.js only.

    this.verbs = [
      "member",     "contain",
      "provide",    "providedby",
      "gather",     "gatheredby",
      "build",      "buildby",
      "train",      "trainedby",
      "hold",       "holdby",
      "heal",       "healedby",
      "research",   "researchedby",
      "require",    "enable",
      "accept",     "acceptedby",
      "carry",      "carriedby",
      "ingame",     "describedby",
      "techingame", "techdescribedby"
    ];

The verbs are mostly made up and may change into more idiomatic English ones. Proposals are highly welcomed.

Query Language

Examples:

  • query in game entities
    "INGAME" (returns all)
    "INGAME WITH id = 44"
    "INGAME WITH metadata.group = 'none'
  • listing entities of classes
    "healer, hero CONTAIN"
  • checking required technologies
    "units.athen.support.female.citizen.house REQUIRE"
  • looking for trainers (in game)
    "units.athen.infantry.spearman.b TRAINEDBY"
    "units.athen.infantry.spearman.b TRAINEDBY INGAME"

The query engine is already in its second iteration and a few optimizations are still possible. However all above examples deliver results within less than 15 milliseconds on a 3GHZ Intel CPU. Queries starting with a name clause are very fast, usually < 1 msec.

Plugins

Domain Specific Language

HTN Planner

Scratchpad

(just a section for thoughts and experiments)

Attachments (3)

Download all attachments as: .zip

Note: See TracWiki for help on using the wiki.