├── exports
└── .gitignore
├── logs
└── .gitignore
├── docs
├── nau03a.pdf
├── pathfinder.pdf
├── passabilities.xcf
├── terrainanalysis.doc
├── HTML5_Canvas_Cheat_Sheet.pdf
├── Hannibal-Mmap.html_files
│ ├── ilink.png
│ ├── minus.png
│ ├── plus.png
│ ├── marktree.js
│ ├── icons
│ │ ├── Mail.png
│ │ ├── back.png
│ │ ├── bell.png
│ │ ├── down.png
│ │ ├── edit.png
│ │ ├── fema.png
│ │ ├── flag.png
│ │ ├── go.png
│ │ ├── help.png
│ │ ├── idea.png
│ │ ├── info.png
│ │ ├── korn.png
│ │ ├── licq.png
│ │ ├── list.png
│ │ ├── stop.png
│ │ ├── up.png
│ │ ├── xmag.png
│ │ ├── yes.png
│ │ ├── attach.png
│ │ ├── clock.png
│ │ ├── closed.png
│ │ ├── family.png
│ │ ├── folder.png
│ │ ├── full-0.png
│ │ ├── full-1.png
│ │ ├── full-2.png
│ │ ├── full-3.png
│ │ ├── full-4.png
│ │ ├── full-5.png
│ │ ├── full-6.png
│ │ ├── full-7.png
│ │ ├── full-8.png
│ │ ├── full-9.png
│ │ ├── gohome.png
│ │ ├── group.png
│ │ ├── kmail.png
│ │ ├── launch.png
│ │ ├── male1.png
│ │ ├── male2.png
│ │ ├── pencil.png
│ │ ├── wizard.png
│ │ ├── bookmark.png
│ │ ├── button_ok.png
│ │ ├── calendar.png
│ │ ├── female1.png
│ │ ├── female2.png
│ │ ├── flag-blue.png
│ │ ├── flag-pink.png
│ │ ├── forward.png
│ │ ├── hourglass.png
│ │ ├── knotify.png
│ │ ├── password.png
│ │ ├── penguin.png
│ │ ├── prepare.png
│ │ ├── smiley-oh.png
│ │ ├── smily_bad.png
│ │ ├── stop-sign.png
│ │ ├── broken-line.png
│ │ ├── clanbomber.png
│ │ ├── desktop_new.png
│ │ ├── flag-black.png
│ │ ├── flag-green.png
│ │ ├── flag-orange.png
│ │ ├── flag-yellow.png
│ │ ├── ksmiletris.png
│ │ ├── button_cancel.png
│ │ ├── kaddressbook.png
│ │ ├── smiley-angry.png
│ │ ├── smiley-neutral.png
│ │ ├── freemind_butterfly.png
│ │ └── messagebox_warning.png
│ ├── map_location.png
│ ├── visorFreemind.swf
│ ├── treestyles.css
│ └── flashobject.js
└── Hannibal-Mmap.html
├── mods
├── hannibal.zip
├── hannibal
│ ├── simulation
│ │ └── ai
│ │ │ └── hannibal
│ │ │ └── data.json
│ ├── mod.json
│ ├── LICENCE.txt
│ └── README.md
└── hannibal.readme.txt
├── source
├── favicon.ico
├── explorer
│ ├── images
│ │ ├── a.png
│ │ ├── b.png
│ │ ├── c.png
│ │ ├── ic_stop_24px.svg
│ │ ├── ic_play_arrow_24px.svg
│ │ ├── ic_pause_24px.svg
│ │ ├── ic_skip_previous_24px.svg
│ │ ├── ic_skip_next_24px.svg
│ │ └── ic_redo_24px.svg
│ ├── data
│ │ ├── athens-01-json.export
│ │ ├── tech-groups.ods
│ │ ├── metadata.export
│ │ ├── passabilityClasses.export
│ │ └── rubble-json.export
│ ├── htn-frame.html
│ └── htn-tree-operators.js
├── gui
│ └── aiconfig
│ │ ├── aiconfig.xml.cached.xmb
│ │ ├── aiconfig.xml
│ │ └── aiconfig.js
├── simulation
│ └── ai
│ │ └── hannibal
│ │ ├── data.json
│ │ ├── _debug.js
│ │ ├── config.js
│ │ ├── military.js
│ │ ├── diplomacy.js
│ │ ├── claims.js
│ │ ├── g.idle.js
│ │ ├── comms.js
│ │ ├── htn-eco-operators.js
│ │ ├── g.patrol.ranged.js
│ │ ├── bot.js
│ │ ├── g.harvester.js
│ │ ├── goals.js
│ │ ├── g.builder.js
│ │ ├── g.shepherds.js
│ │ ├── _hannibal.js
│ │ ├── g.supplier.js
│ │ └── htn-planner.js
└── mod.json
├── maps
├── scenarios
│ ├── Abyss72.pmp
│ ├── Abyss73.pmp
│ ├── Abyss74.pmp
│ ├── Abyss75.pmp
│ ├── brain02.pmp
│ ├── brain03.pmp
│ ├── topo.128.path.pmp
│ └── topo.128.path.xml
├── random
│ ├── brainland.json
│ ├── api.txt
│ ├── rmghelper
│ │ └── rmghelper.js
│ └── brainland_triggers.js
└── scripts
│ ├── WonderVictory.js
│ ├── Conquest.js
│ └── TriggerHelper.js
├── tools
├── http-explorer.sh
├── test.01.html
├── pack.sh
├── data.py
├── prof.typ.loop.js
├── prof.js.loop.js
├── test.01.js
├── prof.obj.loop.js
└── prof.SIMD.js
├── .gitignore
├── LICENCE.txt
├── readme.txt
├── data.py
├── pack.sh
└── README.md
/exports/.gitignore:
--------------------------------------------------------------------------------
1 | [^.]*
--------------------------------------------------------------------------------
/logs/.gitignore:
--------------------------------------------------------------------------------
1 | [^.]*
--------------------------------------------------------------------------------
/docs/nau03a.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/nau03a.pdf
--------------------------------------------------------------------------------
/docs/pathfinder.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/pathfinder.pdf
--------------------------------------------------------------------------------
/mods/hannibal.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/mods/hannibal.zip
--------------------------------------------------------------------------------
/source/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/source/favicon.ico
--------------------------------------------------------------------------------
/docs/passabilities.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/passabilities.xcf
--------------------------------------------------------------------------------
/docs/terrainanalysis.doc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/terrainanalysis.doc
--------------------------------------------------------------------------------
/maps/scenarios/Abyss72.pmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/maps/scenarios/Abyss72.pmp
--------------------------------------------------------------------------------
/maps/scenarios/Abyss73.pmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/maps/scenarios/Abyss73.pmp
--------------------------------------------------------------------------------
/maps/scenarios/Abyss74.pmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/maps/scenarios/Abyss74.pmp
--------------------------------------------------------------------------------
/maps/scenarios/Abyss75.pmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/maps/scenarios/Abyss75.pmp
--------------------------------------------------------------------------------
/maps/scenarios/brain02.pmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/maps/scenarios/brain02.pmp
--------------------------------------------------------------------------------
/maps/scenarios/brain03.pmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/maps/scenarios/brain03.pmp
--------------------------------------------------------------------------------
/source/explorer/images/a.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/source/explorer/images/a.png
--------------------------------------------------------------------------------
/source/explorer/images/b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/source/explorer/images/b.png
--------------------------------------------------------------------------------
/source/explorer/images/c.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/source/explorer/images/c.png
--------------------------------------------------------------------------------
/docs/HTML5_Canvas_Cheat_Sheet.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/HTML5_Canvas_Cheat_Sheet.pdf
--------------------------------------------------------------------------------
/maps/scenarios/topo.128.path.pmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/maps/scenarios/topo.128.path.pmp
--------------------------------------------------------------------------------
/source/explorer/data/athens-01-json.export:
--------------------------------------------------------------------------------
1 | // EXPORTED culture 'athens' at Mon Sep 29 2014 17:03:28 GMT+0200 (CEST)
2 |
--------------------------------------------------------------------------------
/source/explorer/data/tech-groups.ods:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/source/explorer/data/tech-groups.ods
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/ilink.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/ilink.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/minus.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/plus.png
--------------------------------------------------------------------------------
/tools/http-explorer.sh:
--------------------------------------------------------------------------------
1 | ## cd /Daten/Projects/Osiris/ps/trunk/binaries/data/mods
2 | cd ../source
3 | python -m SimpleHTTPServer 8080
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/marktree.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/marktree.js
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/Mail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/Mail.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/back.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/bell.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/bell.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/down.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/edit.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/fema.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/fema.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/flag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/flag.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/go.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/go.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/help.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/help.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/idea.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/idea.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/info.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/korn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/korn.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/licq.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/licq.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/list.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/stop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/stop.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/up.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/xmag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/xmag.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/yes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/yes.png
--------------------------------------------------------------------------------
/source/gui/aiconfig/aiconfig.xml.cached.xmb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/source/gui/aiconfig/aiconfig.xml.cached.xmb
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/attach.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/attach.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/clock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/clock.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/closed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/closed.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/family.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/family.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/folder.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/full-0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/full-0.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/full-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/full-1.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/full-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/full-2.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/full-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/full-3.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/full-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/full-4.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/full-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/full-5.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/full-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/full-6.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/full-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/full-7.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/full-8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/full-8.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/full-9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/full-9.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/gohome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/gohome.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/group.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/group.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/kmail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/kmail.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/launch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/launch.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/male1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/male1.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/male2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/male2.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/pencil.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/pencil.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/wizard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/wizard.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/map_location.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/map_location.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/bookmark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/bookmark.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/button_ok.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/button_ok.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/calendar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/calendar.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/female1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/female1.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/female2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/female2.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/flag-blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/flag-blue.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/flag-pink.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/flag-pink.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/forward.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/forward.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/hourglass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/hourglass.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/knotify.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/knotify.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/password.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/password.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/penguin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/penguin.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/prepare.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/prepare.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/smiley-oh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/smiley-oh.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/smily_bad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/smily_bad.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/stop-sign.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/stop-sign.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/visorFreemind.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/visorFreemind.swf
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/broken-line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/broken-line.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/clanbomber.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/clanbomber.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/desktop_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/desktop_new.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/flag-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/flag-black.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/flag-green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/flag-green.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/flag-orange.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/flag-orange.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/flag-yellow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/flag-yellow.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/ksmiletris.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/ksmiletris.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/button_cancel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/button_cancel.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/kaddressbook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/kaddressbook.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/smiley-angry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/smiley-angry.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/smiley-neutral.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/smiley-neutral.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/freemind_butterfly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/freemind_butterfly.png
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/icons/messagebox_warning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentx-cgn/Hannibal/HEAD/docs/Hannibal-Mmap.html_files/icons/messagebox_warning.png
--------------------------------------------------------------------------------
/source/explorer/data/metadata.export:
--------------------------------------------------------------------------------
1 | // EXPORTED metadata at Thu Nov 20 2014 13:10:11 GMT+0100 (CET)
2 | {
3 | "1": {},
4 | "2": {}
5 | }
6 | // Export end of metadata
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## temp readme
4 | readme.md
5 |
6 | ## local dev path
7 | paths.py
8 |
9 | ## filter
10 | *.pyc
11 |
12 | ## paths
13 | ## exports/*
14 | ## logs/*
15 |
16 | last.log
17 |
--------------------------------------------------------------------------------
/source/simulation/ai/hannibal/data.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Hannibal",
3 | "description": "Advanced 0 A.D AI/Bot",
4 | "moduleName" : "HANNIBAL",
5 | "constructor": "Launcher",
6 | "useShared": true
7 | }
8 |
--------------------------------------------------------------------------------
/source/explorer/images/ic_stop_24px.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/mods/hannibal/simulation/ai/hannibal/data.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Hannibal",
3 | "description": "Advanced 0 A.D AI/Bot",
4 | "moduleName" : "HANNIBAL",
5 | "constructor": "Launcher",
6 | "useShared": true
7 | }
8 |
--------------------------------------------------------------------------------
/source/explorer/images/ic_play_arrow_24px.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/source/explorer/images/ic_pause_24px.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/source/explorer/images/ic_skip_previous_24px.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/source/explorer/images/ic_skip_next_24px.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/source/mod.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Hannibal",
3 | "label": "0 A.D. Bot/AI",
4 | "url": "https://github.com/agentx-cgn/Hannibal",
5 | "description": "Adaptive Bot ",
6 | "dependencies": ["0ad"],
7 | "type": "bot addon",
8 | "version": "0.0.18"
9 | }
--------------------------------------------------------------------------------
/mods/hannibal/mod.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Hannibal",
3 | "label": "0 A.D. Bot/AI",
4 | "url": "https://github.com/agentx-cgn/Hannibal",
5 | "description": "Adaptive Bot ",
6 | "dependencies": ["0ad"],
7 | "type": "bot addon",
8 | "version": "0.0.17"
9 | }
--------------------------------------------------------------------------------
/tools/test.01.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Test
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/source/explorer/images/ic_redo_24px.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/source/explorer/data/passabilityClasses.export:
--------------------------------------------------------------------------------
1 | // EXPORTED passabilityClasses at Thu Nov 20 2014 13:35:06 GMT+0100 (CET)
2 | {
3 | "pathfinderObstruction": 1,
4 | "foundationObstruction": 2,
5 | "building-land": 4,
6 | "building-shore": 8,
7 | "default": 16,
8 | "ship": 32,
9 | "unrestricted": 64
10 | }
11 | // Export end of passabilityClasses
12 |
--------------------------------------------------------------------------------
/maps/random/brainland.json:
--------------------------------------------------------------------------------
1 | {
2 | "settings" : {
3 | "Name" : "Brainland",
4 | "Script" : "brainland.js",
5 | "Description" : "Hannibal test map without any water, based on mainland.js",
6 | "BaseTerrain" : ["medit_sea_depths"],
7 | "BaseHeight" : 3,
8 | "CircularMap" : true,
9 | "XXXXXX" : "Optionally define other things here, like we would for a scenario",
10 | "TriggerScripts": [
11 | "scripts/TriggerHelper.js",
12 | "random/brainland_triggers.js"
13 | ]
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/LICENCE.txt:
--------------------------------------------------------------------------------
1 | Hannibal, a Bot/AI for the RTS game 0 A.D.
2 |
3 | Copyright (C) 2014, Cologne, agentx, agentx-cgn@gmail.com
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 |
--------------------------------------------------------------------------------
/mods/hannibal/LICENCE.txt:
--------------------------------------------------------------------------------
1 | Hannibal, a Bot/AI for the RTS game 0 A.D.
2 |
3 | Copyright (C) 2014, Cologne, agentx, agentx-cgn@gmail.com
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 |
--------------------------------------------------------------------------------
/maps/random/api.txt:
--------------------------------------------------------------------------------
1 | Object.keys(Engine).forEach(k => deb(k));
2 |
3 | ProfileStart
4 | ProfileStop
5 | RegisterComponentType
6 | RegisterSystemComponentType
7 | ReRegisterComponentType
8 | RegisterInterface
9 | RegisterMessageType
10 | RegisterGlobal
11 | QueryInterface
12 | GetEntitiesWithInterface
13 | GetComponentsWithInterface
14 | PostMessage
15 | BroadcastMessage
16 | AddEntity
17 | AddLocalEntity
18 | DestroyEntity
19 | FlushDestroyedEntities
20 | ReadJSONFile
21 | ReadCivJSONFile
22 | FindJSONFiles
23 |
24 |
25 | Object.keys(Trigger.prototype).forEach(k => deb(k));
26 |
27 | Schema
28 | eventNames
29 | Init
30 | RegisterTriggerPoint
31 | RemoveRegisteredTriggerPoint
32 | GetTriggerPoints
33 | RegisterTrigger
34 | DisableTrigger
35 | EnableTrigger
36 | CallEvent
37 | OnGlobalConstructionFinished
38 | OnGlobalTrainingFinished
39 | OnGlobalOwnershipChanged
40 | DoAfterDelay
41 | DoAction
42 | cinema
43 | forceResearch
44 |
--------------------------------------------------------------------------------
/source/explorer/htn-frame.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTN - Frame
5 |
6 |
7 |
8 |
9 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html:
--------------------------------------------------------------------------------
1 |
2 | Hannibal
23 | Flash plugin or Javascript are turned off.
24 | Activate both and reload to view the mindmap
25 |
--------------------------------------------------------------------------------
/tools/pack.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | : << '--COMMENT--'
4 |
5 | Dependencies
6 | sudo apt-get install tree
7 |
8 | --COMMENT--
9 |
10 | # pathRoot="/Daten/Dropbox/Projects/hannibal/"
11 | pathCode="/home/noiv/.local/share/0ad/mods/hannibal/simulation/ai/hannibal"
12 | pathDistri="/Daten/Dropbox/Projects/hannibal"
13 |
14 | echo
15 | echo "-- Start"
16 | echo
17 |
18 | ## STATIC
19 |
20 | cd $pathDistri
21 | cp LICENCE.txt "${pathDistri}/mods/hannibal/LICENCE.txt"
22 | cp README.md "${pathDistri}/mods/hannibal/README.md"
23 | cp readme.txt "${pathDistri}/mods/hannibal.readme.txt"
24 |
25 | cd $pathCode
26 | cp data.json "${pathDistri}/mods/hannibal/simulation/ai/hannibal/data.json"
27 |
28 | ## DYNAMIC
29 |
30 | cd $pathCode
31 | rm -f hannibal.m.js
32 | ls _*.js | xargs cat > _.jss
33 | ls [a-z]*.js | xargs cat > az.jss
34 | cat _.jss az.jss > hannibal.m.js
35 | rm -f \
36 | _.jss \
37 | az.jss
38 | mv hannibal.m.js "${pathDistri}/mods/hannibal/simulation/ai/hannibal/hannibal.m.js"
39 |
40 | ## fake compress
41 | cd "${pathDistri}/mods/hannibal/simulation/ai/hannibal/"
42 | cp hannibal.m.js hannibal.u.js
43 | cp hannibal.u.js hannibal.p.js
44 | cp hannibal.p.js hannibal.js
45 |
46 | ## clearup compress
47 | cd "${pathDistri}/mods/hannibal/simulation/ai/hannibal/"
48 | rm -f \
49 | hannibal.m.js \
50 | hannibal.u.js \
51 | hannibal.p.js
52 |
53 | ## ZIP
54 |
55 | cd "${pathDistri}/mods/"
56 | rm -f hannibal.zip
57 | zip hannibal.zip \
58 | hannibal/mod.json \
59 | hannibal/README.md \
60 | hannibal/LICENCE.txt \
61 | hannibal/simulation/ai/hannibal/data.json \
62 | hannibal/simulation/ai/hannibal/hannibal.js
63 |
64 | ## CHECK
65 |
66 | cd "${pathDistri}/mods/"
67 | tree
68 | unzip -l hannibal.zip
69 |
70 | echo
71 | echo "-- Done --"
72 | echo
73 |
--------------------------------------------------------------------------------
/source/gui/aiconfig/aiconfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | AI Configuration
14 |
15 |
16 |
17 |
18 | AI Player:
19 |
20 |
21 |
22 | selectAI(this.selected);
23 |
24 |
25 |
26 | AI Difficulty:
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | Cancel
37 | Engine.PopGuiPage();
38 |
39 |
40 |
41 | OK
42 | returnAI();
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/source/gui/aiconfig/aiconfig.js:
--------------------------------------------------------------------------------
1 | var g_AIs; // [ {"id": ..., "data": {"name": ..., "description": ..., ...} }, ... ]
2 | var g_PlayerSlot;
3 |
4 | function init(settings)
5 | {
6 | g_PlayerSlot = settings.playerSlot;
7 |
8 | translateObjectKeys(settings.ais, ["name", "description"]);
9 | g_AIs = [
10 | {id: "", data: {name: translateWithContext("ai", "None"), description: translate("AI will be disabled for this player.")}}
11 | ].concat(settings.ais);
12 |
13 | var aiSelection = Engine.GetGUIObjectByName("aiSelection");
14 | aiSelection.list = [ translate(ai.data.name) for each (ai in g_AIs) ];
15 |
16 | var selected = 0;
17 | for (var i = 0; i < g_AIs.length; ++i)
18 | {
19 | if (g_AIs[i].id == settings.id)
20 | {
21 | selected = i;
22 | break;
23 | }
24 | }
25 | aiSelection.selected = selected;
26 |
27 | var aiDiff = Engine.GetGUIObjectByName("aiDifficulty");
28 | // Translation: AI difficulty level.
29 | aiDiff.list = [translateWithContext("aiDiff", "Sandbox"), translateWithContext("aiDiff", "Easy"), translateWithContext("aiDiff", "Medium"), translateWithContext("aiDiff", "Hard"), translateWithContext("aiDiff", "Very Hard")];
30 | aiDiff.selected = settings.difficulty;
31 | }
32 |
33 | function selectAI(idx)
34 | {
35 | var id = g_AIs[idx].id;
36 | var name = g_AIs[idx].data.name;
37 | var description = g_AIs[idx].data.description;
38 |
39 | Engine.GetGUIObjectByName("aiDescription").caption = description;
40 | }
41 |
42 | function returnAI()
43 | {
44 | var aiSelection = Engine.GetGUIObjectByName("aiSelection");
45 | var idx = aiSelection.selected;
46 | var id = g_AIs[idx].id;
47 | var name = g_AIs[idx].data.name;
48 |
49 | var difficulty = Engine.GetGUIObjectByName("aiDifficulty").selected;
50 |
51 | // Pop the page before calling the callback, so the callback runs
52 | // in the parent GUI page's context
53 | Engine.PopGuiPageCB({"id": id, "name": name, "difficulty" : difficulty, "playerSlot" : g_PlayerSlot });
54 | }
55 |
--------------------------------------------------------------------------------
/source/simulation/ai/hannibal/_debug.js:
--------------------------------------------------------------------------------
1 | var HANNIBAL_DEBUG = {
2 | "map": "random/brainland",
3 | "bots": {
4 | "1": {
5 | "dmp": 1,
6 | "num": 0,
7 | "cht": 1,
8 | "log": 4,
9 | "sup": 0,
10 | "xdo": 1,
11 | "tst": 1,
12 | "fil": 1
13 | },
14 | "0": {
15 | "dmp": 0,
16 | "num": 0,
17 | "cht": 0,
18 | "log": 4,
19 | "sup": 1,
20 | "xdo": 0,
21 | "tst": 0,
22 | "fil": 0
23 | },
24 | "3": {
25 | "dmp": 0,
26 | "num": 0,
27 | "cht": 0,
28 | "log": 3,
29 | "sup": 0,
30 | "xdo": 0,
31 | "tst": 1,
32 | "fil": 0
33 | },
34 | "2": {
35 | "dmp": 1,
36 | "num": 0,
37 | "cht": 1,
38 | "log": 3,
39 | "sup": 0,
40 | "xdo": 0,
41 | "tst": 1,
42 | "fil": 0
43 | },
44 | "5": {
45 | "dmp": 0,
46 | "num": 0,
47 | "cht": 0,
48 | "log": 3,
49 | "sup": 0,
50 | "xdo": 0,
51 | "tst": 1,
52 | "fil": 0
53 | },
54 | "4": {
55 | "dmp": 0,
56 | "num": 0,
57 | "cht": 0,
58 | "log": 3,
59 | "sup": 0,
60 | "xdo": 0,
61 | "tst": 1,
62 | "fil": 0
63 | },
64 | "7": {
65 | "dmp": 0,
66 | "num": 0,
67 | "cht": 0,
68 | "log": 3,
69 | "sup": 0,
70 | "xdo": 0,
71 | "tst": 1,
72 | "fil": 0
73 | },
74 | "6": {
75 | "dmp": 0,
76 | "num": 0,
77 | "cht": 0,
78 | "log": 3,
79 | "sup": 0,
80 | "xdo": 0,
81 | "tst": 1,
82 | "fil": 0
83 | },
84 | "8": {
85 | "dmp": 0,
86 | "num": 0,
87 | "cht": 0,
88 | "log": 3,
89 | "sup": 0,
90 | "xdo": 0,
91 | "tst": 1,
92 | "fil": 0
93 | }
94 | },
95 | "counter": [],
96 | "export": "/media/noiv/OS/Octets/Projects/GIT/Hannibal/exports/"
97 | };
--------------------------------------------------------------------------------
/readme.txt:
--------------------------------------------------------------------------------
1 |
2 | BOTS DON'T CHEAT
3 |
4 | Hannibal does not access engine data to find out where your buildings are. He sends out scouts to explore the map and find islands, mines, quarries, food, etc. An internal map is build to keep tracks of buildings and attacks. The basic block of Hannibal are his groups. They all have different goals and can communicate with each other. The difficulty settings control which groups are available during the game and set an upper limit to some buildings. If you are fancy enough and can code JavaScript, you can add your own groups to Hannibal. It is not that difficult as they have a powerful API. Check out the GitHub at: https://github.com/agentx-cgn/Hannibal or the blog: http://agentx.svbtle.com/
5 |
6 | Have fun and don't forget to give feedack at the forum
7 |
8 | DIFFICULTY SETTINGS
9 |
10 | 0 : Sandbox
11 |
12 | Hannibal will not rush or attack you. It only builds a village, gathers resources and advances to city phase. If more resources are needed it may expand its territory. However, if *you* attack Hannibal the unit AI will kick in and may shoot arrows or slaughter your units. Also, the towers may be manned. If you kill the scouts exploring the map some more will come. No ships.
13 |
14 | 1 : Easy
15 |
16 | Same as sandbox, plus walls around villages if possible. Also, Hannibal may build fortress and garrison them.
17 |
18 | 2 : Medium
19 |
20 | Same as easy, but now Hannibal may get active and launch attacks. However, he is not determined to defeat you.
21 |
22 | 3: Hard
23 |
24 | Same as Medium. This is the default settings and you may loose. Hannibal will build two barracks to train recruits and at least one fortresses to buid siege engines.
25 |
26 | 4: Very Hard
27 |
28 | Same as Medium. Three barracks and three fortresses. Groups with champions and heros.
29 |
30 | 5 : Nightmare
31 |
32 | Now Hannibal unleashes all options. Expect multiple and heavy attacks at the same time from different directions, guerilla squads terrorizing your gatherers, early cavalry rushes, war dogs killing your females, targeted attacks on economic installations,
--------------------------------------------------------------------------------
/mods/hannibal.readme.txt:
--------------------------------------------------------------------------------
1 |
2 | BOTS DON'T CHEAT
3 |
4 | Hannibal does not access engine data to find out where your buildings are. He sends out scouts to explore the map and find islands, mines, quarries, food, etc. An internal map is build to keep tracks of buildings and attacks. The basic block of Hannibal are his groups. They all have different goals and can communicate with each other. The difficulty settings control which groups are available during the game and set an upper limit to some buildings. If you are fancy enough and can code JavaScript, you can add your own groups to Hannibal. It is not that difficult as they have a powerful API. Check out the GitHub at: https://github.com/agentx-cgn/Hannibal or the blog: http://agentx.svbtle.com/
5 |
6 | Have fun and don't forget to give feedack at the forum
7 |
8 | DIFFICULTY SETTINGS
9 |
10 | 0 : Sandbox
11 |
12 | Hannibal will not rush or attack you. It only builds a village, gathers resources and advanves to city phase. If more resources are needed it may expand its territory. However, if *you* attack Hannibal the unit AI will kick in and may shoot arrows or slaughter your units. Also, the towers may be manned. If you kill the scouts exploring the map some more will come. No ships.
13 |
14 | 1 : Easy
15 |
16 | Same as sandbox, plus walls around villages if possible. Also, Hannibal may build fortress and garrison them.
17 |
18 | 2 : Medium
19 |
20 | Same as easy, but now Hannibal may get active and launch attacks. However, he is not determined to defeat you.
21 |
22 | 3: Hard
23 |
24 | Same as Medium. This is the default settings and you may loose. Hannibal will build two barracks to train recruits and at least one fortresses to buid siege engines.
25 |
26 | 4: Very Hard
27 |
28 | Same as Medium. Three barracks and three fortresses. Groups with champions and heros.
29 |
30 | 5 : Nightmare
31 |
32 | Now Hannibal unleashes all options. Expect multiple and heavy attacks at the same time from different directions, guerilla squads terrorizing your gatherers, early cavalry rushes, war dogs killing your females, targeted attacks on economic installations,
--------------------------------------------------------------------------------
/source/simulation/ai/hannibal/config.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, todo: true, evil:true, devel: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals HANNIBAL */
3 |
4 | /*--------------- C O N F I G --------------------------------------------
5 |
6 | debug/numerus/tester settings, shortcuts and heuristics
7 |
8 |
9 | tested with 0 A.D. Alpha 18 Rhododactylus
10 | V: 0.1.1, agentx, CGN, Mar, 2015
11 |
12 | */
13 |
14 |
15 | HANNIBAL = (function(H){
16 |
17 | H.Config = {
18 |
19 | //logging 0=zero, 1=errors, 2=1+warnings, 3=2+info, 4=everything
20 | deb: 4, // enables messages to dbgView via _xdebug.js.deb()
21 | con: 1, // enables messages to the in game console via _xdebug.js.con()
22 |
23 | sequence: "random/brainland",
24 | // sequence: "Forest Battle",
25 |
26 | // enable psy-ops
27 | brag: true,
28 |
29 | // angle: 3 * Math.PI/4, // depends on first CC
30 |
31 | data: {
32 | prey: [ // possible food resources
33 | "chicken",
34 | "sheep",
35 | "pig",
36 | "goat"
37 | ],
38 | },
39 |
40 | numerus: {
41 | enabled: true,
42 | file: "/home/noiv/Desktop/0ad/stats.csv",
43 | resolution: 10 // 10 = 16 secs
44 | },
45 |
46 | stats: {
47 | LengthStatsBuffer: 40, // approx 1 minute
48 | },
49 |
50 | economy: {
51 | IntervalMonitorGoals: 10,
52 | MaxQueueLength: 3, // queue length for producers
53 | },
54 |
55 | map: {
56 | DangerEventRadius: 60, // meter
57 | DangerEventRelax: 8, // tick % N => 50%
58 | },
59 |
60 | villages: {
61 | sharedBuildingClasses: [
62 | "civilcentre",
63 | "blacksmith",
64 | "farmstead",
65 | "storehouse",
66 | "barracks", // temporarely
67 | "house", // temporarely
68 | ],
69 | }
70 |
71 |
72 | };
73 |
74 | return H; }(HANNIBAL));
75 |
--------------------------------------------------------------------------------
/maps/scripts/WonderVictory.js:
--------------------------------------------------------------------------------
1 | Trigger.prototype.CheckWonderVictory = function(data)
2 | {
3 | var ent = data.entity;
4 | var cmpWonder = Engine.QueryInterface(ent, IID_Wonder);
5 | if (!cmpWonder)
6 | return;
7 |
8 | var timer = this.wonderVictoryTimers[ent];
9 | var messages = this.wonderVictoryMessages[ent] || {};
10 |
11 | var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
12 | var cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
13 | // remove existing messages if any
14 | if (timer)
15 | {
16 | cmpTimer.CancelTimer(timer);
17 | cmpGuiInterface.DeleteTimeNotification(messages.ownMessage);
18 | cmpGuiInterface.DeleteTimeNotification(messages.otherMessage);
19 | }
20 |
21 | if (data.to <= 0)
22 | return;
23 |
24 | // create new messages, and start timer to register defeat.
25 | var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
26 | var numPlayers = cmpPlayerManager.GetNumPlayers();
27 | var cmpPlayer = QueryOwnerInterface(ent, IID_Player);
28 | var players = [];
29 | for (var i = 1; i < numPlayers; i++)
30 | if (i != data.to)
31 | players.push(i);
32 |
33 | var time = cmpWonder.GetTimeTillVictory()*1000;
34 | messages.otherMessage = cmpGuiInterface.AddTimeNotification({
35 | "message": markForTranslation("%(player)s will have won in %(time)s"),
36 | "players": players,
37 | "duration": time,
38 | "parameters": {"player": cmpPlayer.GetName()},
39 | "translateMessage": true,
40 | "translateParameters": [],
41 | });
42 | messages.ownMessage = cmpGuiInterface.AddTimeNotification({
43 | "message": markForTranslation("You will have won in %(time)s"),
44 | "players": [data.to],
45 | "duration": time,
46 | "translateMessage": true,
47 | });
48 | timer = cmpTimer.SetTimeout(SYSTEM_ENTITY, IID_EndGameManager, "MarkPlayerAsWon", time, data.to);
49 |
50 | this.wonderVictoryTimers[ent] = timer;
51 | this.wonderVictoryMessages[ent] = messages;
52 | };
53 |
54 | var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
55 |
56 | var data = {"enabled": true};
57 | cmpTrigger.RegisterTrigger("OnOwnershipChanged", "CheckWonderVictory", data);
58 | cmpTrigger.wonderVictoryTimers = {};
59 | cmpTrigger.wonderVictoryMessages = {};
60 |
--------------------------------------------------------------------------------
/maps/scenarios/topo.128.path.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | default
6 |
7 |
8 |
9 |
10 |
11 |
12 | 0
13 | 0.5
14 |
15 |
16 |
17 |
18 | ocean
19 |
20 |
21 | 5
22 | 8
23 | 0.45
24 | 0
25 |
26 |
27 |
28 | 0
29 | 1
30 | 0.99
31 | 0.1999
32 | default
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
60 |
61 |
62 | gaia/flora_tree_cypress
63 | 0
64 |
65 |
66 |
67 |
68 |
69 | gaia/flora_tree_cypress
70 | 0
71 |
72 |
73 |
74 |
75 |
76 | gaia/flora_tree_cypress
77 | 0
78 |
79 |
80 |
81 |
82 |
83 | gaia/flora_tree_cypress
84 | 0
85 |
86 |
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/maps/scripts/Conquest.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Check players the next turn. Avoids problems in Atlas, with promoting entities etc
3 | */
4 | Trigger.prototype.CheckConquestCriticalEntities = function()
5 | {
6 | if (this.checkingConquestCriticalEntities)
7 | return;
8 | // wait a turn for actually checking the players
9 | this.DoAfterDelay(0, "CheckConquestCriticalEntitiesNow", null);
10 | this.checkingConquestCriticalEntities = true;
11 | };
12 |
13 | /*
14 | * Check players immediately. Might cause problems with converting/promoting entities.
15 | */
16 | Trigger.prototype.CheckConquestCriticalEntitiesNow = function()
17 | {
18 | this.checkingConquestCriticalEntities = false;
19 | // for all other game types, defeat that player
20 | var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
21 | var cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
22 |
23 | // Ignore gaia
24 | var numPlayers = cmpPlayerManager.GetNumPlayers();
25 | var cmpPlayers = [];
26 |
27 | var allies = [];
28 | var onlyAlliesLeft = true;
29 | // If the player is currently active but needs to be defeated,
30 | // mark that player as defeated
31 | // cache the cmpPlayer instances of the other players and search the allies
32 | for (var i = 1; i < numPlayers; i++)
33 | {
34 | // cmpPlayer should always exist for the player ids from 1 to numplayers
35 | // so no tests on the existance of cmpPlayer are needed
36 | var playerEntityId = cmpPlayerManager.GetPlayerByID(i);
37 | cmpPlayers[i] = Engine.QueryInterface(playerEntityId, IID_Player);
38 | if (cmpPlayers[i].GetState() != "active")
39 | continue;
40 | if (cmpPlayers[i].GetConquestCriticalEntitiesCount() == 0)
41 | Engine.PostMessage(playerEntityId, MT_PlayerDefeated, { "playerId": i } );
42 | else
43 | {
44 | if (!allies.length || cmpPlayers[allies[0]].IsMutualAlly(i))
45 | allies.push(i);
46 | else
47 | onlyAlliesLeft = false;
48 | }
49 | }
50 |
51 | // check if there are winners, or the game needs to continue
52 | if (!allies.length || !onlyAlliesLeft || !(cmpEndGameManager.alliedVictory || allies.length == 1))
53 | return;
54 |
55 | for each (var p in allies)
56 | cmpPlayers[p].SetState("won");
57 |
58 | // Reveal the map to all players
59 | var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
60 | cmpRangeManager.SetLosRevealAll(-1, true);
61 | };
62 |
63 | var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
64 |
65 | var data = {"enabled": true};
66 | cmpTrigger.RegisterTrigger("OnOwnershipChanged", "CheckConquestCriticalEntities", data);
67 | // also check at the start of the game
68 | cmpTrigger.DoAfterDelay(0, "CheckConquestCriticalEntitiesNow", null);
69 | cmpTrigger.checkingConquestCriticalEntities = false;
70 |
71 |
--------------------------------------------------------------------------------
/source/simulation/ai/hannibal/military.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, todo: true, evil:true, devel: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals HANNIBAL, uneval */
3 |
4 | /*--------------- M I L I T A R Y ---------------------------------------------
5 |
6 | knows about buildings and attack plans
7 |
8 |
9 | tested with 0 A.D. Alpha 18 Rhododactylus
10 | V: 0.1.1, agentx, CGN, Mar, 2015
11 |
12 | */
13 |
14 |
15 | HANNIBAL = (function(H){
16 |
17 |
18 | H.LIB.Military = function(context){
19 |
20 | H.extend(this, {
21 |
22 | context: context,
23 |
24 | imports: [
25 | "events",
26 | ],
27 |
28 | });
29 |
30 | };
31 |
32 | H.LIB.Military.prototype = H.mixin (
33 | H.LIB.Serializer.prototype, {
34 | constructor: H.LIB.Military,
35 | log: function(){this.deb();this.deb(" MIL: all good");},
36 | deserialize: function(){
37 | if (this.context.data[this.name]){
38 | H.extend(this, this.context.data[this.name]);
39 | }
40 | },
41 | serialize: function(){
42 | return {};
43 | },
44 | activate: function(){
45 |
46 | this.events.on("EntityAttacked", "*", function (msg){
47 |
48 | });
49 |
50 | },
51 | tick: function(tick, secs){
52 |
53 | var t0 = Date.now();
54 |
55 |
56 | return Date.now() - t0;
57 |
58 | },
59 | getPhaseNecessities: function(options){ // phase, centre, tick
60 |
61 | var
62 | cls = H.class2name,
63 | cc = options.centre,
64 |
65 | technologies = [],
66 | messages = {
67 | "phase.village": [
68 | [ 20, {name: "BroadCast", data: {group: "g.builder", cc: cc, size: 5, building: cls("baracks"), quantity: 2}}],
69 | ],
70 | "phase.town" : [
71 |
72 | ],
73 | "phase.city" : [
74 |
75 | ],
76 | },
77 | launches = {
78 |
79 | "phase.village": [
80 | // tck, act, params
81 | [ 16, 1, "g.builder", {cc: cc, size: 5, building: cls("barracks"), quantity: 1}],
82 | ],
83 |
84 | "phase.town" : [
85 | [ 20, 1, "g.builder", {cc: cc, size: 5, building: cls("temple"), quantity: 1}],
86 | // [ 20, [1, "g.tower", {cc: cc, size: 5, quantity: 1}]],
87 |
88 | ],
89 |
90 | "phase.city" : [
91 |
92 | ],
93 |
94 | };
95 |
96 | return {
97 | launches: launches,
98 | technologies: technologies,
99 | messages: messages,
100 | };
101 |
102 | },
103 |
104 | });
105 |
106 | return H; }(HANNIBAL));
107 |
--------------------------------------------------------------------------------
/data.py:
--------------------------------------------------------------------------------
1 |
2 | data = {
3 | "civs" : [
4 | "athen",
5 | "brit",
6 | "cart",
7 | "celt",
8 | "gaul",
9 | "hele",
10 | "iber",
11 | "mace",
12 | "maur",
13 | "pers",
14 | "ptol",
15 | "rome",
16 | "sele",
17 | "theb",
18 | ],
19 | "pathMaps": "/home/noiv/.local/share/0ad/mods/public/maps/scenarios/",
20 | "testMaps": [
21 | "Arcadia 02.xml",
22 | "Azure Coast.xml",
23 | "Barcania.xml",
24 | "Battle for the Tiber.xml",
25 | "Belgian_Bog_night.xml",
26 | "Eire and Albion.xml",
27 | "Gold_Rush.xml",
28 | "Gorge.xml",
29 | ],
30 | "mapsAll": [
31 | "Abyss39.xml",
32 | "Arcadia 02.xml",
33 | "Azure Coast.xml",
34 | "Azure Coast(2).xml",
35 | "Azure Coast(4).xml",
36 | "Barcania.xml",
37 | "Battle for the Tiber.xml",
38 | "Belgian_Bog_night.xml",
39 | "Bridge_demo.xml",
40 | "Campaign Test Map.xml",
41 | "Campaign Test Map 2 - heightmap.xml",
42 | "Combat_demo.xml",
43 | "Combat_demo_(huge).xml",
44 | "Death Canyon - Invasion Force.xml",
45 | "Demo_Trading.xml",
46 | "Eire and Albion.xml",
47 | "Fast Oasis.xml",
48 | "Fishing_demo.xml",
49 | "Flight_demo.xml",
50 | "Flight_demo_2.xml",
51 | "Gold_Rush.xml",
52 | "Gorge.xml",
53 | "Height Map Import - Demo (Fractal).xml",
54 | "Height Map Import - Demo (Greece).xml",
55 | "Height Map Import - Demo (Greece-Small).xml",
56 | "Introductory Tutorial.xml",
57 | "Laconia 01.xml",
58 | "Migration.xml",
59 | "Miletus.xml",
60 | "Multiplayer_demo.xml",
61 | "Necropolis.xml",
62 | "Pathfinding_demo.xml",
63 | "Pathfinding_terrain_demo.xml",
64 | "Peloponnese.xml",
65 | "Polynesia.xml",
66 | "reservoir.xml",
67 | "Resource_demo.xml",
68 | "road demo.xml",
69 | "Saharan Oases.xml",
70 | "Sahel.xml",
71 | "Sandbox - Athenians.xml",
72 | "Sandbox - Britons.xml",
73 | "Sandbox - Carthaginians.xml",
74 | "Sandbox - Gauls.xml",
75 | "Sandbox - Iberians.xml",
76 | "Sandbox - Macedonians.xml",
77 | "Sandbox - Mauryans.xml",
78 | "Sandbox - Persians.xml",
79 | "Sandbox - Ptolemies.xml",
80 | "Sandbox - Ptolemies 2.xml",
81 | "Sandbox - Romans.xml",
82 | "Sandbox - Seleucids.xml",
83 | "Sandbox - Spartans.xml",
84 | "Savanna Ravine.xml",
85 | "Serengeti.xml",
86 | "shipattacks.xml",
87 | "Ship Formations.xml",
88 | "Siwa Oasis.xml",
89 | "starting_economy_walkthrough.xml",
90 | "temperate map.xml",
91 | "Territory Demo.xml",
92 | "The Massacre of Delphi.xml",
93 | "The Persian Gates.xml",
94 | "Third Macedonian War.xml",
95 | "Tropical Island.xml",
96 | "Units_demo.xml",
97 | "Walls.xml",
98 | "WallTest.xml",
99 | "We are Legion.xml"
100 | ]
101 | }
102 |
--------------------------------------------------------------------------------
/tools/data.py:
--------------------------------------------------------------------------------
1 |
2 | data = {
3 | "civs" : [
4 | "athen",
5 | "brit",
6 | "cart",
7 | "celt",
8 | "gaul",
9 | "hele",
10 | "iber",
11 | "mace",
12 | "maur",
13 | "pers",
14 | "ptol",
15 | "rome",
16 | "sele",
17 | "theb",
18 | ],
19 | "pathMaps": "/home/noiv/.local/share/0ad/mods/public/maps/scenarios/",
20 | "testMaps": [
21 | "Arcadia 02.xml",
22 | "Azure Coast.xml",
23 | "Barcania.xml",
24 | "Battle for the Tiber.xml",
25 | "Belgian_Bog_night.xml",
26 | "Eire and Albion.xml",
27 | "Gold_Rush.xml",
28 | "Gorge.xml",
29 | ],
30 | "mapsAll": [
31 | "Abyss39.xml",
32 | "Arcadia 02.xml",
33 | "Azure Coast.xml",
34 | "Azure Coast(2).xml",
35 | "Azure Coast(4).xml",
36 | "Barcania.xml",
37 | "Battle for the Tiber.xml",
38 | "Belgian_Bog_night.xml",
39 | "Bridge_demo.xml",
40 | "Campaign Test Map.xml",
41 | "Campaign Test Map 2 - heightmap.xml",
42 | "Combat_demo.xml",
43 | "Combat_demo_(huge).xml",
44 | "Death Canyon - Invasion Force.xml",
45 | "Demo_Trading.xml",
46 | "Eire and Albion.xml",
47 | "Fast Oasis.xml",
48 | "Fishing_demo.xml",
49 | "Flight_demo.xml",
50 | "Flight_demo_2.xml",
51 | "Gold_Rush.xml",
52 | "Gorge.xml",
53 | "Height Map Import - Demo (Fractal).xml",
54 | "Height Map Import - Demo (Greece).xml",
55 | "Height Map Import - Demo (Greece-Small).xml",
56 | "Introductory Tutorial.xml",
57 | "Laconia 01.xml",
58 | "Migration.xml",
59 | "Miletus.xml",
60 | "Multiplayer_demo.xml",
61 | "Necropolis.xml",
62 | "Pathfinding_demo.xml",
63 | "Pathfinding_terrain_demo.xml",
64 | "Peloponnese.xml",
65 | "Polynesia.xml",
66 | "reservoir.xml",
67 | "Resource_demo.xml",
68 | "road demo.xml",
69 | "Saharan Oases.xml",
70 | "Sahel.xml",
71 | "Sandbox - Athenians.xml",
72 | "Sandbox - Britons.xml",
73 | "Sandbox - Carthaginians.xml",
74 | "Sandbox - Gauls.xml",
75 | "Sandbox - Iberians.xml",
76 | "Sandbox - Macedonians.xml",
77 | "Sandbox - Mauryans.xml",
78 | "Sandbox - Persians.xml",
79 | "Sandbox - Ptolemies.xml",
80 | "Sandbox - Ptolemies 2.xml",
81 | "Sandbox - Romans.xml",
82 | "Sandbox - Seleucids.xml",
83 | "Sandbox - Spartans.xml",
84 | "Savanna Ravine.xml",
85 | "Serengeti.xml",
86 | "shipattacks.xml",
87 | "Ship Formations.xml",
88 | "Siwa Oasis.xml",
89 | "starting_economy_walkthrough.xml",
90 | "temperate map.xml",
91 | "Territory Demo.xml",
92 | "The Massacre of Delphi.xml",
93 | "The Persian Gates.xml",
94 | "Third Macedonian War.xml",
95 | "Tropical Island.xml",
96 | "Units_demo.xml",
97 | "Walls.xml",
98 | "WallTest.xml",
99 | "We are Legion.xml"
100 | ]
101 | }
102 |
--------------------------------------------------------------------------------
/maps/random/rmghelper/rmghelper.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | // Helper object for Hannibal's RMG
4 |
5 | "use strict";
6 |
7 | var H = {
8 |
9 | fmt: function (){var a=H.toArray(arguments),s=a[0].split("%s"),p=a.slice(1).concat([""]),c=0;return s.map(function(t){return t + p[c++];}).join("");},
10 | toArray: function (a){return Array.prototype.slice.call(a);},
11 | deb: function (){var s = H.fmt.apply(null, arguments); print("RMG : " + s + "\n");},
12 |
13 | biomes: {
14 | "1" : "temperate",
15 | "2" : "snowy",
16 | "3" : "desert",
17 | "4" : "alpine",
18 | "5" : "medit",
19 | "6" : "savanah",
20 | "7" : "tropic",
21 | "8" : "autumn",
22 | },
23 |
24 | logObject: function(o, msg){
25 | var inst = "unidentified";
26 | msg = msg || "";
27 | H.deb();
28 | H.deb("Object [%s] : attributes: %s, comment: %s", inst, Object.keys(o).length, msg);
29 | if (o.constructor){
30 | H.deb("Object: %s", H.getAttribType("constructor", o.constructor));
31 | }
32 | H.logObjectShort(o);
33 | H.deb("Object.prototype: %s attributes", H.count(Object.getPrototypeOf(o)));
34 | if (H.count(Object.getPrototypeOf(o))){
35 | H.logObjectShort(Object.getPrototypeOf(o));
36 | }
37 | H.deb("------: logObject end");
38 | },
39 | logObjectShort: function(o){
40 | H.attribs(o)
41 | .sort()
42 | .forEach(a => H.deb(this.getAttribType(a, o[a])));
43 | },
44 | getAttribType: function(name, value){
45 |
46 | var keys, body;
47 |
48 | function toString(value){
49 | return value.toString ? value.toString() : value+"";
50 | }
51 |
52 | switch (typeof value) {
53 | case "string":
54 | case "number":
55 | case "undefined":
56 | case "boolean":
57 | return H.format(" %s: %s (%s)", name, (typeof value).toUpperCase(), value);
58 | case "object":
59 |
60 | if (Array.isArray(value)){
61 | return H.format(" %s: ARRAY [%s](%s, ...)", name, value.length, value.map(toString).slice(0, 5).join(", "));
62 |
63 | } else if (o instanceof Map) {
64 | keys = o.entries();
65 | return H.format(" %s: MAP [%s](%s, ...)", name, keys.length, keys.slice(0, 5).join(", "));
66 |
67 | } else if (value === null) {
68 | return H.format(" %s: NULL", name);
69 |
70 | } else {
71 | keys = Object.keys(value);
72 | return H.format(" %s: OBJECT [%s](%s, ...)", name, keys.length, keys.slice(0, 5).join(", "));
73 |
74 | }
75 | break;
76 | case "function":
77 | body = value.toString()
78 | .split("\n").join("")
79 | .split("\r").join("")
80 | .split("\t").join(" ")
81 | .split(" ").join(" ")
82 | .split(" ").join(" ")
83 | .split(" ").join(" ")
84 | .split(" ").join(" ")
85 | .slice(0, 100);
86 | return H.format(" %s: FUNCTION %s (...)", name, body);
87 | }
88 | return "WTF";
89 | },
90 |
91 | };
--------------------------------------------------------------------------------
/maps/random/brainland_triggers.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, todo: true, evil:true, devel: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals Engine, TriggerHelper, Trigger, print, uneval */
3 | /*globals SYSTEM_ENTITY, IID_PlayerManager, IID_TechnologyManager, IID_Trigger */
4 |
5 | "use strict";
6 |
7 | // helper
8 |
9 | function fmt (){var a=Array.prototype.slice.call(arguments),s=a[0].split("%s"),p=a.slice(1).concat([""]),c=0;return s.map(function(t){return t + p[c++];}).join("");}
10 | function deb (){var s = fmt.apply(null, arguments); print("RMG : " + s + "\n");}
11 | function loop (n, fn){for (var i=0; i {
19 |
20 | TriggerHelper
21 | .GetPlayerComponent(p)
22 | .SetResourceCounts({
23 | food: 1000,
24 | wood: 1000,
25 | stone: 1000,
26 | metal: 1000
27 | })
28 | ;
29 |
30 | });
31 |
32 | // deb("Triggers.load.out");
33 |
34 |
35 | // GAME INITIALIZATION
36 |
37 | Trigger.prototype.cinema = function(){
38 |
39 | var start = [ 400, 400, 10, 0, 0, 0 ];
40 | var end = [ 10, 10, 10, 0, 0, 0 ];
41 |
42 |
43 | deb("------: Trigger.cinema.in");
44 |
45 | Object.keys(Trigger.prototype).forEach(k => deb(k));
46 |
47 |
48 | Engine.SetCameraData(...start);
49 |
50 | deb("Camera: %s, %s, %s", Engine.CameraGetX(), Engine.CameraGetY(), Engine.CameraGetZ());
51 |
52 | // Engine.SetCameraData(data.camera.PosX, data.camera.PosY, data.camera.PosZ,
53 | // data.camera.RotX, data.camera.RotY, data.camera.Zoom);
54 |
55 | Engine.CameraMoveTo(400, 400);
56 |
57 | deb("------: Trigger.cinema.out");
58 |
59 | };
60 | Trigger.prototype.forceResearch = function(){
61 |
62 | var
63 | player,
64 | cmpTechnologyManager,
65 | technologies = [
66 | // "phase_town_generic",
67 | // "phase_city_generic"
68 | ];
69 |
70 | loop(TriggerHelper.GetNumberOfPlayers(), p => {
71 |
72 | player = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetPlayerByID(p);
73 | cmpTechnologyManager = Engine.QueryInterface(player, IID_TechnologyManager);
74 |
75 | technologies.forEach(tech => {
76 |
77 | if (!cmpTechnologyManager.IsTechnologyResearched(tech)) {
78 | deb("Triggers.forceResearch.tech: player %s researches %s", p, tech);
79 | cmpTechnologyManager.ResearchTechnology(tech);
80 |
81 | } else {
82 | deb("Triggers.forceResearch.tech: %s rejected %s", p, tech);
83 |
84 | }
85 |
86 | });
87 |
88 | });
89 |
90 | };
91 |
92 | Engine
93 | .QueryInterface(SYSTEM_ENTITY, IID_Trigger)
94 | .DoAfterDelay( 0, "forceResearch", {})
95 | ;
96 | Engine
97 | .QueryInterface(SYSTEM_ENTITY, IID_Trigger)
98 | .DoAfterDelay(1000, "cinema", {})
99 | ;
100 |
--------------------------------------------------------------------------------
/source/explorer/data/rubble-json.export:
--------------------------------------------------------------------------------
1 | var RUBBLE = {
2 | "rubble/rubble_1x1": {
3 | "Classes": []
4 | },
5 | "rubble/rubble_1x1pal": {
6 | "Classes": []
7 | },
8 | "rubble/rubble_1x3pal": {
9 | "Classes": []
10 | },
11 | "rubble/rubble_2x2": {
12 | "Classes": []
13 | },
14 | "rubble/rubble_2x4": {
15 | "Classes": []
16 | },
17 | "rubble/rubble_3x3": {
18 | "Classes": []
19 | },
20 | "rubble/rubble_3x6": {
21 | "Classes": []
22 | },
23 | "rubble/rubble_4x2": {
24 | "Classes": []
25 | },
26 | "rubble/rubble_4x4": {
27 | "Classes": []
28 | },
29 | "rubble/rubble_4x4_dock": {
30 | "Classes": []
31 | },
32 | "rubble/rubble_4x6": {
33 | "Classes": []
34 | },
35 | "rubble/rubble_5x5": {
36 | "Classes": []
37 | },
38 | "rubble/rubble_6x4": {
39 | "Classes": []
40 | },
41 | "rubble/rubble_6x4_dock": {
42 | "Classes": []
43 | },
44 | "rubble/rubble_6x6": {
45 | "Classes": []
46 | },
47 | "rubble/rubble_8x8": {
48 | "Classes": []
49 | },
50 | "rubble/rubble_celt_cc": {
51 | "Classes": []
52 | },
53 | "rubble/rubble_celt_dock": {
54 | "Classes": []
55 | },
56 | "rubble/rubble_field": {
57 | "Classes": []
58 | },
59 | "rubble/rubble_hele_cc": {
60 | "Classes": []
61 | },
62 | "rubble/rubble_hele_dock": {
63 | "Classes": []
64 | },
65 | "rubble/rubble_iber_cc": {
66 | "Classes": []
67 | },
68 | "rubble/rubble_iber_dock": {
69 | "Classes": []
70 | },
71 | "rubble/rubble_kart_cc": {
72 | "Classes": []
73 | },
74 | "rubble/rubble_kart_dock": {
75 | "Classes": []
76 | },
77 | "rubble/rubble_maur_cc": {
78 | "Classes": []
79 | },
80 | "rubble/rubble_pers_cc": {
81 | "Classes": []
82 | },
83 | "rubble/rubble_pers_dock": {
84 | "Classes": []
85 | },
86 | "rubble/rubble_rome_cc": {
87 | "Classes": []
88 | },
89 | "rubble/rubble_rome_dock": {
90 | "Classes": []
91 | },
92 | "rubble/rubble_rome_sb": {
93 | "Classes": []
94 | },
95 | "rubble/rubble_stone_2x2": {
96 | "Classes": []
97 | },
98 | "rubble/rubble_stone_3x3": {
99 | "Classes": []
100 | },
101 | "rubble/rubble_stone_4x2": {
102 | "Classes": []
103 | },
104 | "rubble/rubble_stone_4x4": {
105 | "Classes": []
106 | },
107 | "rubble/rubble_stone_4x6": {
108 | "Classes": []
109 | },
110 | "rubble/rubble_stone_5x5": {
111 | "Classes": []
112 | },
113 | "rubble/rubble_stone_6x4": {
114 | "Classes": []
115 | },
116 | "rubble/rubble_stone_6x6": {
117 | "Classes": []
118 | },
119 | "rubble/rubble_stone_wall_long": {
120 | "Classes": []
121 | },
122 | "rubble/rubble_stone_wall_medium": {
123 | "Classes": []
124 | },
125 | "rubble/rubble_stone_wall_short": {
126 | "Classes": []
127 | },
128 | "rubble/rubble_stone_wall_tower": {
129 | "Classes": []
130 | },
131 | "rubble/rubble_wall": {
132 | "Classes": []
133 | }
134 | };
--------------------------------------------------------------------------------
/pack.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | : << '--COMMENT--'
4 |
5 | Dependencies
6 | sudo apt-get install tree
7 |
8 | --COMMENT--
9 |
10 |
11 | ## set file date
12 | ## find ~/.local/share/0ad/mods/hannibal -exec touch -t 201501220000 {} \;
13 |
14 | ## paths
15 | # pathRoot="/Daten/Dropbox/Projects/hannibal/"
16 | pathCode="/home/noiv/.local/share/0ad/mods/hannibal/simulation/ai/hannibal"
17 | pathDistri="/Daten/Dropbox/Projects/hannibal"
18 | pathDiffer="/home/noiv/Sources/prettydiff-master"
19 |
20 | ## files
21 | compiler="/home/noiv/Programs/closure-compiler/compiler.jar"
22 | echo
23 | echo "-- Start"
24 | echo
25 |
26 | ## STATIC
27 |
28 | cd $pathDistri
29 | cp LICENCE.txt "${pathDistri}/mods/hannibal/LICENCE.txt"
30 | cp README.md "${pathDistri}/mods/hannibal/README.md"
31 | cp readme.txt "${pathDistri}/mods/hannibal.readme.txt"
32 |
33 | cd $pathCode
34 | cp data.json "${pathDistri}/mods/hannibal/simulation/ai/hannibal/data.json"
35 |
36 | ## DYNAMIC
37 |
38 | cd $pathCode
39 | rm -f \
40 | hannibal.m.js \
41 | _debug.js
42 | ls _*.js | xargs cat > _.jss
43 | ls [a-z]*.js | xargs cat > az.jss
44 | cat _.jss az.jss > hannibal.m.js
45 | rm -f \
46 | _.jss \
47 | az.jss
48 | mv hannibal.m.js "${pathDistri}/mods/hannibal/simulation/ai/hannibal/hannibal.m.js"
49 |
50 | echo
51 | echo counting locs in hannibal.m.js ...
52 | cd "${pathDistri}/mods/hannibal/simulation/ai/hannibal/"
53 | cat hannibal.m.js | grep -v ^$ | wc -l
54 |
55 |
56 | ## java -jar compiler.jar --help
57 | ## real compress
58 | # --compilation_level SIMPLE_OPTIMIZATIONS \
59 | # --language_out ES5_strict \
60 | # --tracer_mode ALL \
61 | # --language_in ECMASCRIPT6_STRICT \
62 | # --language_out ECMASCRIPT6_STRICT \
63 |
64 | echo
65 | echo compressing...
66 | cd "${pathDistri}/mods/hannibal/simulation/ai/hannibal/"
67 |
68 | # java -jar $compiler \
69 | # --compilation_level WHITESPACE_ONLY \
70 | # --js hannibal.m.js --js_output_file hannibal.js
71 |
72 | fileMini="${pathDistri}/mods/hannibal/simulation/ai/hannibal/hannibal.m.js"
73 | fileFina="${pathDistri}/mods/hannibal/simulation/ai/hannibal/hannibal.js"
74 |
75 | echo "${pathDiffer}/api/node-local.js source:'${fileMini}' mode:'minify' readmethod:'file' output:'hannibal.js'"
76 | js "${pathDiffer}/api/node-local.js source:'${fileMini}' mode:minify" ## source:'hannibal.m.js' mode:'minify' readmethod:'file' output:'hannibal.js'"
77 |
78 |
79 | ## fake compress
80 | # cd "${pathDistri}/mods/hannibal/simulation/ai/hannibal/"
81 | # cp hannibal.m.js hannibal.u.js
82 | # cp hannibal.u.js hannibal.p.js
83 | # cp hannibal.p.js hannibal.js
84 |
85 | ## clearup compress
86 | cd "${pathDistri}/mods/hannibal/simulation/ai/hannibal/"
87 | rm -f \
88 | # hannibal.m.js \
89 | hannibal.u.js \
90 | hannibal.p.js
91 |
92 | ## ZIP
93 | echo
94 | echo zipping...
95 | cd "${pathDistri}/mods/"
96 | rm -f hannibal.zip
97 | zip hannibal.zip \
98 | hannibal/mod.json \
99 | hannibal/README.md \
100 | hannibal/LICENCE.txt \
101 | hannibal/simulation/ai/hannibal/data.json \
102 | hannibal/simulation/ai/hannibal/hannibal.js
103 |
104 | ## CHECK
105 |
106 | cd "${pathDistri}/mods/"
107 | tree
108 | unzip -l hannibal.zip
109 |
110 | echo
111 | echo "-- Done --"
112 | echo
113 |
--------------------------------------------------------------------------------
/source/simulation/ai/hannibal/diplomacy.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, evil:true, devel: true, todo: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals HANNIBAL, uneval */
3 |
4 | /*--------------- D I P L O M A C Y -------------------------------------------
5 |
6 |
7 |
8 |
9 | tested with 0 A.D. Alpha 18 Rhododactylus
10 | V: 0.1.1, agentx, CGN, Mar, 2015
11 |
12 | */
13 |
14 |
15 | HANNIBAL = (function(H){
16 |
17 | H.LIB.Diplomacy = function(context){
18 |
19 | H.extend(this, {
20 | context: context,
21 |
22 | klass: "diplomacy",
23 |
24 | imports: [
25 | "map",
26 | "events",
27 | "query",
28 | "effector",
29 | "entities",
30 | "player",
31 | "players",
32 | ],
33 |
34 | policies: null,
35 | mood: "friendly",
36 |
37 | // color,
38 | defaults: {
39 | "0": {},
40 | "1": {},
41 | "2": {},
42 | "3": {},
43 | "4": {},
44 | "5": {},
45 | "6": {},
46 | "7": {},
47 | "8": {},
48 | }
49 |
50 | });
51 |
52 | };
53 |
54 |
55 | H.LIB.Diplomacy.prototype = H.mixin(
56 | H.LIB.Serializer.prototype, {
57 | constructor: H.LIB.Diplomacy,
58 | log: function(){
59 | this.deb(); this.deb(" DIPLO: mood: %s", this.mood);
60 | H.each(this.policies, (id, policy) => {
61 | if(policy.color){
62 | this.deb(" D: %s : %s", id, uneval(policy));
63 | }
64 | });
65 | },
66 | serialize: function(){
67 | return {
68 | policies: H.deepcopy(this.policies)
69 | };
70 | },
71 | deserialize: function(data){
72 | if(data){
73 | this.policies = data.policies;
74 | }
75 | return this;
76 | },
77 | finalize: function(){return this;},
78 |
79 | initialize: function(){
80 |
81 | if(this.policies === null){
82 | this.policies = H.deepcopy(this.defaults);
83 | this.readPlayerColors();
84 | }
85 |
86 |
87 | return this;
88 |
89 |
90 | },
91 | activate: function(){
92 |
93 | this.events.on("EntityCreated", msg => {
94 | if(this.entities[msg.id]){
95 | if (H.contains(this.entities[msg.id].classes(), "Unit")){
96 | // this.deb(" DIPL: %s, got unit with classes: %s", this.mood, this.entities[msg.id].classes());
97 | } else {
98 | // this.deb(" DIPL: %s, got NON unit with classes: %s", this.mood, this.entities[msg.id].classes());
99 | }
100 | } else {
101 | // this.deb("WARN : DIPL got ID NOT ENTITY: %s", msg.id);
102 | }
103 | });
104 |
105 | return this;
106 |
107 | },
108 |
109 | readPlayerColors: function () {
110 |
111 | var colorName = (id) => {
112 | return this.context.launcher.colorFromRGBA(this.players[id].color);
113 | };
114 |
115 | H.each(this.policies, (id, policy) => {
116 | if (this.players[id]){
117 | policy.color = colorName(id)[1];
118 | }
119 | });
120 | },
121 |
122 | isAlly: function(id){return this.player.isAlly[id];},
123 | isEnemy: function(id){return this.player.isEnemy[id];},
124 |
125 | tribute: function(){},
126 |
127 |
128 |
129 | });
130 |
131 | return H; }(HANNIBAL));
132 |
--------------------------------------------------------------------------------
/tools/prof.typ.loop.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, moz: true, evil:true, devel: true, todo: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals dateNow, uneval, putstr, version, options */
3 |
4 | /*
5 |
6 | tests various tecnics to loop over all properties of an object
7 | and calls a function with with property name + value
8 |
9 | */
10 |
11 | var
12 | t0 = dateNow(),
13 | tab = function (s,l){l=l||8;s=new Array(l+1).join(" ")+s;return s.substr(s.length-l);},
14 | toArray = function (a){return Array.prototype.slice.call(a);},
15 | format = function (){var a=toArray(arguments),s=a[0].split("%s"),p=a.slice(1).concat([""]),c=0;return s.map(function(t){return t + p[c++];}).join("");},
16 | deb = function (){print((dateNow() - t0).toFixed(1), format.apply(null, arguments));},
17 | rnd = function (){return Math.random().toString(36).slice(2);};
18 |
19 | // SOME CHECKS
20 |
21 | // Object.keys(this).sort().forEach(k => print(k));
22 |
23 | // SOME GLOBALS
24 |
25 | var
26 | size, // amount of properties
27 | loops, // amount of tests
28 | timing, // keeps timing matrix
29 | grid; //, = new Uint8ClampedArray(1024);
30 |
31 |
32 | // TEST SUITE
33 |
34 | var DIM1 = {
35 | "i8" : Uint8Array,
36 | "i32" : Uint32Array,
37 | "c8" : Uint8ClampedArray,
38 | "f32" : Float32Array,
39 | };
40 |
41 | var F1 = function(){return 17;};
42 |
43 | var DIM2 = [
44 | ( ) => "CONST",
45 | ( ) => 0,
46 | (v) => v,
47 | (v) => v > 128 ? 255 : 0,
48 | (v) => {if (v > 128) return 180; else return 0;},
49 | ( ) => F1(),
50 | ( ) => Math.random() * 256,
51 | ( ) => Math.sin(Math.random() * 2 * Math.PI),
52 | ];
53 |
54 | // PROFILER
55 |
56 | print();
57 | deb("Start V: %s, O: %s", version(), options());
58 |
59 | print();
60 | size = 512*512; loops = 16;
61 | deb("Testing %s full iterations over Typed Arrays(%s) ", loops, size);
62 |
63 | [0, 1, 2, 3, 4, 5, 6, 7].forEach(idx => {
64 | reset();
65 | profile(idx);
66 | result();
67 | });
68 |
69 | deb("Done");
70 |
71 | // HELPER
72 |
73 | function reset () {
74 | timing = {};
75 | Object.keys(DIM1).forEach((key) => timing[key] = []);
76 | }
77 |
78 | function result () {
79 | Object.keys(DIM1).forEach(k => {
80 |
81 | var len = timing["i8"].length; len2 = ~~(len/2);
82 | var avglow = parseFloat(
83 | (timing[k].sort((a,b) => a < b ? 1 : -1).slice(len2).reduce((a, b) => a + b, 0) / len2)).toFixed(1);
84 | var avg = parseFloat((timing[k].reduce((a, b) => a + b, 0) / len)).toFixed(1);
85 |
86 | if (avg > 2){
87 | deb("T %s a/l: %s, %s, list: %s", tab(k,3), tab(avg, 5), tab(avglow, 5), JSON.stringify(timing[k].map(n => parseFloat(n.toFixed(1)))));
88 | } else {
89 | deb("T %s a/l: %s, %s, list: %s", tab(k,3), tab(avg, 5), tab(avglow, 5), JSON.stringify(timing[k].map(n => Math.round(n))));
90 | }
91 |
92 | });
93 | print();
94 | }
95 |
96 | function profile(index){
97 |
98 | var t0, i, k, fn, keysDIM1;
99 |
100 | keysDIM1 = Object.keys(DIM1);
101 | fn = DIM2[index];
102 |
103 | deb("running: [%s] '%s' ... ", index, fn.toString()) ;
104 |
105 | keysDIM1.forEach(k => {
106 |
107 | // reinit grid
108 | grid = new DIM1[k](size);
109 | var j = size; while(j--){grid[i] = 0;}
110 |
111 | j = loops; while (j--){
112 |
113 | t0 = dateNow();
114 | if(index === 0){
115 | i = grid.length; while(i--){
116 | grid[i] = 0;
117 | }
118 | } else {
119 | i = grid.length; while(i--){
120 | grid[i] = fn(grid[i]);
121 | }
122 | }
123 | timing[k].push(dateNow()-t0);
124 |
125 | }
126 |
127 | });
128 |
129 | print();
130 | }
131 |
132 |
--------------------------------------------------------------------------------
/tools/prof.js.loop.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, moz: true, evil:true, devel: true, todo: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals dateNow, uneval, putstr, version, options */
3 |
4 | /*
5 |
6 | tests various tecnics to loop over all properties of an object
7 | and calls a function with with property name + value
8 |
9 | */
10 |
11 |
12 |
13 | var
14 | t0 = dateNow(),
15 | tab = function (s,l){l=l||8;s=new Array(l+1).join(" ")+s;return s.substr(s.length-l);},
16 | toArray = function (a){return Array.prototype.slice.call(a);},
17 | format = function (){var a=toArray(arguments),s=a[0].split("%s"),p=a.slice(1).concat([""]),c=0;return s.map(function(t){return t + p[c++];}).join("");},
18 | deb = function(){print(tab((dateNow() - t0).toFixed(1), 5), format.apply(null, arguments));};
19 |
20 | print();
21 | deb("Start V: %s, O: %s", version(), options());
22 |
23 | // some globals
24 |
25 | var
26 | repeat, // repeat specific test
27 | loops, // calling the loop
28 | timing; // keeps timing matrix
29 |
30 |
31 | // TEST SUITE
32 |
33 | // functions to profile
34 | var process = {
35 |
36 | "0" : {
37 | title: "reference",
38 | func: null
39 | },
40 |
41 | "1" : {
42 | title: "function",
43 | func: function (){}
44 | },
45 |
46 | "2" : {
47 | title: "lambda",
48 | func: () => null
49 | },
50 |
51 | "3" : {
52 | title: "return number",
53 | func: function (){return 1;}
54 | },
55 |
56 | "4" : {
57 | title: "return function",
58 | func: function (){return function(){};}
59 | },
60 |
61 | "5" : {
62 | title: "invoke function",
63 | func: function (){return function(){}();}
64 | },
65 |
66 | "6" : {
67 | title: "return number with invoked function",
68 | func: function (){return function(){return 1;}();}
69 | },
70 |
71 | "7" : {
72 | title: "return processed number with invoked function",
73 | func: function (){var n = 2; return function(){return n + 1;}();}
74 | },
75 |
76 |
77 | };
78 |
79 |
80 |
81 | // HELPER
82 |
83 | function reset () {
84 | timing = {};
85 | Object.keys(process).forEach((key, idx) => timing[idx] = new Array(repeat).map(()=>NaN));
86 | }
87 |
88 | function result () {
89 | var avg, min, max, lst;
90 | Object.keys(timing).forEach(k => {
91 | avg = parseFloat((timing[k].reduce((a, b) => a + b, 0) / timing[k].length)).toFixed(1);
92 | min = Math.min.apply(Math, timing[k]).toFixed(1);
93 | if (avg > 2){
94 | lst = JSON.stringify(timing[k].map(n => parseFloat(n.toFixed(1))));
95 | deb("p%s avg: %s min: %s list: %s", k, tab(avg, 5), tab(min, 5), lst);
96 | } else {
97 | lst = JSON.stringify(timing[k].map(n => Math.round(n)))
98 | deb("p%s avg: %s min: %s list: %s", k, tab(avg, 5), tab(min, 5), lst);
99 | }
100 | });
101 | print();
102 | }
103 |
104 | function rnd(){return Math.random().toString(36).slice(2);}
105 |
106 | function profile(){
107 |
108 | var t0, i, j, k, len, fn;
109 |
110 | len = Object.keys(process).length;
111 |
112 | for (i=0; i 0) ? costs.population * multiplier : 0;
30 | state.data.ress.popcap -= (costs.population < 0) ? costs.population * multiplier : 0;
31 |
32 | }
33 |
34 | H.HTN.Tree.operators = {
35 |
36 | wait_secs: function wait_secs(state, secs) {
37 |
38 | if (true){
39 |
40 | state.data.cost.time += secs;
41 | state.stamp += secs;
42 |
43 | return state;
44 |
45 | } else {return null;}
46 |
47 | },
48 |
49 | del_entity: function del_entity(state, entity, amount) {
50 |
51 | var ents = state.data.ents;
52 |
53 | if (ents[entity] >= amount){
54 |
55 | ents[entity] -= amount;
56 |
57 | if (ents[entity] === 0) {
58 | delete ents[entity];
59 | }
60 |
61 | return state;
62 |
63 | } else {
64 | deb("WARN : can't del_entity: %s %s", entity, amount);
65 | return null;
66 | }
67 |
68 | },
69 |
70 | inc_resource: function inc_resource(state, res, amount) {
71 |
72 | if (true){
73 |
74 | state.data.ress[res] += amount;
75 |
76 | state.data.cost[res] = ( state.data.cost[res] ?
77 | state.data.cost[res] + amount :
78 | amount
79 | );
80 |
81 | return state;
82 |
83 | } else {return null;}
84 |
85 | },
86 |
87 | train_units: function train_units(state, name, amount) {
88 |
89 | var costs, ents = state.data.ents;
90 |
91 | if (true){
92 |
93 | costs = H.HTN.Tree.nodes[name].costs;
94 | if (costs){applyCosts(state, costs, amount);}
95 | ents[name] = ents[name] || 0;
96 | ents[name] += amount;
97 |
98 | return state;
99 |
100 | } else {return null;}
101 |
102 | },
103 |
104 | build_structures: function build_structures(state, name, amount) {
105 |
106 | var costs, ents = state.data.ents;
107 |
108 | if (true){
109 |
110 | costs = H.HTN.Tree.nodes[name].costs;
111 | if (costs){applyCosts(state, costs, amount);}
112 | ents[name] = ents[name] || 0;
113 | ents[name] += amount;
114 |
115 | return state;
116 |
117 | } else {return null;}
118 |
119 | },
120 |
121 | research_tech: function research_tech(state, name) {
122 |
123 | var costs, techs = state.data.tech;
124 |
125 | if (true){
126 |
127 | costs = H.HTN.Tree.nodes[name].costs;
128 | if (costs) {applyCosts(state, costs, 1);}
129 | techs.push(name);
130 |
131 | // a hack, but works
132 | if (name === 'phase.town.athen') {techs.push('phase.town');}
133 | if (name === 'phase.city.athen') {techs.push('phase.city');}
134 | if (name === 'phase.town.generic'){techs.push('phase.town');}
135 | if (name === 'phase.city.generic'){techs.push('phase.city');}
136 |
137 | return state;
138 |
139 | } else {return null;}
140 |
141 | }
142 |
143 | };
144 |
145 | return H; }(HANNIBAL));
--------------------------------------------------------------------------------
/tools/test.01.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, evil:true, devel: true, todo: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals dateNow, uneval */
3 |
4 | var
5 | isBrowser = typeof window !== "undefined",
6 | print1 = typeof print === "undefined" || isBrowser ? console.log.bind(console) : print,
7 | t0 = dateNow(),
8 | H = {
9 | tab: function (s,l){l=l||8;s=new Array(l+1).join(" ")+s;return s.substr(s.length-l);},
10 | toArray: function (a){return Array.prototype.slice.call(a);},
11 | format: function (){var a=H.toArray(arguments),s=a[0].split("%s"),p=a.slice(1).concat([""]),c=0;return s.map(function(t){return t + p[c++];}).join('');},
12 | },
13 | deb = function(){print((dateNow() - t0).toFixed(1), H.format.apply(H, arguments));},
14 | i, size, loops, source, target,
15 | f1 = function f1 (s){return (s === 1 || s === 2 || s === 4) ? 255 : 0;},
16 | //f2 = s => (s === 1 || s === 2 || s === 4) ? 255 : 0,
17 | tims = {
18 | "0" : [],
19 | "1" : [],
20 | "2" : [],
21 | "3" : [],
22 | };
23 |
24 | size = 512; loops = 30; length = size * size;
25 | source = new Uint8ClampedArray(length);
26 | target = new Uint8ClampedArray(length);
27 |
28 | print();
29 | deb("Start V: %s, O: %s", version(), options());
30 | deb("Testing iteration over Uint8ClampedArray of length: ", length);
31 |
32 | i = length;
33 | while (i--){source[i] = Math.random() * 4;}
34 |
35 | deb("... source array randomized");
36 |
37 | deb("running func: %s", decompileBody(f1));
38 |
39 | function process0(source, target, fn){
40 |
41 | var t0 = Date.now(), s, i = length;
42 |
43 | while (i--) {
44 | s = source[i];
45 | target[i] = (s === 1 || s === 2 || s === 4) ? 255 : 0;
46 | }
47 | tims[0].push(Date.now()-t0);
48 | }
49 |
50 |
51 | function process1(source, target, fn){
52 |
53 | var t0 = Date.now(), s, i = length;
54 |
55 | while (i--) {
56 | s = source[i];
57 | target[i] = fn(s);
58 | }
59 | tims[1].push(Date.now()-t0);
60 | }
61 |
62 | function process2(source, target, fn){
63 |
64 | var t0 = Date.now(), s, p2, body = "";
65 |
66 | body += "var i = " + length + ";";
67 | body += "while (i--) { t[i] = f(s[i]);}";
68 | Function("s", "t", "f", body)(source, target, fn);
69 |
70 | tims[2].push(Date.now()-t0);
71 | }
72 |
73 | function process3(source, target, fn){
74 |
75 | var t0 = Date.now(), body = "", fBody = fnBody(fn);
76 |
77 | body += "var i = " + length + ";";
78 | body += "while (i--) { t[i] = " + fBody + ";}";
79 | Function("s", "t", body)(source, target);
80 | tims[3].push(Date.now()-t0);
81 | }
82 |
83 | function fnBody(fn){
84 |
85 | var body, source = fn.toString();
86 |
87 | if (source.indexOf("return") !== -1){
88 | body = source.slice(source.indexOf("return") + 6, source.lastIndexOf("}")).trim();
89 |
90 | } else if (source.indexOf("=>") !== -1){
91 | body = source.slice(source.indexOf("=>") + 2).trim();
92 |
93 | } else {
94 | throw "can't handle that";
95 | }
96 |
97 | return body;
98 |
99 | }
100 |
101 | function test(){
102 |
103 | deb("size = %s, iterations: %s", size, loops);
104 | putstr(0); i = loops; while (i--){process0(source, target, f1);}
105 | putstr(1); i = loops; while (i--){process1(source, target, f1);}
106 | putstr(2); i = loops; while (i--){process2(source, target, f1);}
107 | putstr(3); i = loops; while (i--){process3(source, target, f1);}
108 | print();
109 |
110 | Object.keys(tims).forEach(function(k){
111 | var avg = (tims[k].reduce(function(a, b){return a + b;}, 0) / tims[k].length).toFixed(1);
112 | print (k, avg, JSON.stringify(tims[k]));
113 | if (isBrowser){
114 | document.body.appendChild(document.createTextNode(k + ", " + avg + ", " + JSON.stringify(tims[k])));
115 | document.body.appendChild(document.createElement("BR"));
116 | }
117 | });
118 | }
119 |
120 | if (isBrowser){
121 | window.onload = function(){test();};
122 | } else {
123 | test();
124 | }
125 |
126 |
127 | deb("Done");
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/source/simulation/ai/hannibal/claims.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, todo: true, evil:true, devel: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals HANNIBAL, uneval */
3 |
4 | /*--------------- C L A I M S -------------------------------------------------
5 |
6 | reservers village space for important structures
7 | village->claims->classes
8 | village->[reserved, ...]-> slot
9 |
10 | tested with 0 A.D. Alpha 18 Rhododactylus
11 | V: 0.1.1, agentx, CGN, Mar, 2015
12 |
13 | */
14 |
15 | HANNIBAL = (function (H){
16 |
17 | const
18 | PI = Math.PI,
19 | TAU = Math.PI * 2,
20 | PI2 = Math.PI / 2,
21 | RADDEG = Math.PI / 180,
22 | DEGRAD = 1 / RADDEG,
23 | SQRT2 = Math.sqrt(2);
24 |
25 | H.LIB.Claim = function (context, config){
26 |
27 | };
28 |
29 | H.LIB.Claims = function (context){
30 |
31 | H.extend(this, {
32 |
33 | context: context,
34 |
35 | klass: "claims",
36 | parent: context,
37 | name: context.name + ":claims",
38 |
39 | imports: [
40 | "map",
41 | "query",
42 | "templates",
43 | ],
44 |
45 | classes : {
46 | "house": {
47 | "block4" : {prio: 0, radius: NaN, position: [], slots: [ [], [], [], [] ]} // prio 0 = top
48 | },
49 | "field": {},
50 | "farmstead": {},
51 | "barracks": {},
52 | "tower": {},
53 | },
54 |
55 | reserved : [],
56 |
57 | });
58 |
59 | };
60 | H.LIB.Claims.prototype = H.mixin(
61 | H.LIB.Serializer.prototype, {
62 | log: function(){},
63 | serialize: function(){
64 | return {
65 | classes: H.deepcopy(this.classes),
66 | reserved: H.deepcopy(this.reserved),
67 | };
68 | },
69 | deserialize: function(data){
70 | if(data){
71 | this.reserved = data.reserved;
72 | this.classes = data.classes;
73 | }
74 | },
75 | initialize: function(){
76 |
77 | // try out 4 houses
78 |
79 | var nodes, tpln, template, size, r, radius;
80 |
81 | this.map.claims.set(0xFF); // 255
82 |
83 | if (this.reserved.length){
84 | this.reserved.forEach(claim => {
85 | this.map.claims.processCircle(claim.coords, claim.radius, () => 0);
86 | });
87 |
88 | } else {
89 |
90 | // prep claims w/ metrics of culture
91 | nodes = this.query("house CONTAIN")
92 | .filter(node => node.key.contains("house")) // get rid of tavern, etc
93 | ;
94 |
95 | tpln = nodes[0].key;
96 | template = this.templates[tpln];
97 | size = H.test(template, "Obstruction.Static");
98 | r = Math.max(+size["@width"], +size["@depth"]);
99 | radius = SQRT2 * r; // 4 block
100 |
101 | this.classes["house"]["block4"].radius = radius;
102 |
103 | this.deb(" CLAIM: rad for house.block4: %s", radius);
104 |
105 |
106 | }
107 |
108 | return this;
109 |
110 | },
111 | findPosition: function(order) {
112 |
113 | var name = H.saniTemplateName(order.product.key);
114 |
115 | if (this.isToClaim(name)){
116 | this.deb(" CLAIM: #%s got order for claimed structure: %s", order.id, name);
117 |
118 |
119 | }
120 |
121 | return null;
122 |
123 | },
124 | isToClaim: function(nodename){
125 |
126 | var
127 | nodes = this.query(nodename + " MEMBER").execute(),
128 | classes = H.attribs(this.classes);
129 |
130 | return nodes.some(node => {
131 | return H.contains(classes, node.name);
132 | });
133 |
134 | },
135 |
136 |
137 |
138 | });
139 |
140 | return H; }(HANNIBAL));
141 |
142 | /*
143 |
144 | INITIALIZE
145 | claim 1 agora
146 | claim 1 centre space, ignoring agora
147 | claim 8 fields (+ dropsite)
148 | claim 6 tower (iber=4)
149 | claim 1 temple (cart=2)
150 | claim 1 market
151 | claim 1-2 corrals
152 | claim 10 houses (needs civ)
153 | claim 1-4 Barracks (needs difficulty)
154 |
155 | INGAME
156 | build structure, needs pos, offset, angle
157 | isClaimed
158 | y -> search claim
159 | n ->
160 |
161 |
162 |
163 | */
--------------------------------------------------------------------------------
/source/simulation/ai/hannibal/g.idle.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, evil:true, devel: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals HANNIBAL */
3 |
4 | /*--------------- GROUP: I D L E --------------------------------------------
5 |
6 | a group to buffer unit requests
7 |
8 |
9 | tested with 0 A.D. Alpha 18 Rhododactylus
10 | V: 0.1.1, agentx, CGN, Mar, 2015
11 |
12 | */
13 |
14 |
15 | HANNIBAL = (function(H){
16 |
17 | H.extend(H.Groups, {
18 |
19 | "g.idle" : {
20 |
21 | /* Behaviour:
22 | centers units at agora
23 | works as buffer
24 | has extra comm caps
25 | */
26 |
27 | // variables available in listener with *this*. All optional
28 |
29 | active: true, // ready to init/launch ...
30 | description: "idle", // text field for humans
31 | civilisations: ["*"], // lists all supported cics
32 | interval: 4, // call onInterval every x ticks
33 |
34 | scripts: {
35 |
36 |
37 | launch: function launch (w, config) {
38 |
39 | var path, pos = w.group.position[0] + " " + w.group.position[1];
40 |
41 | this.minsize = 5;
42 |
43 | w.units = ["exclusive", "citizen CONTAIN"];
44 | w.units.size = 20;
45 |
46 | path = w.units.size + "; translate " + pos + "; circle 32";
47 | w.path = ["path", path];
48 | w.path.size = w.units.size;
49 |
50 | w.nounify("units", "path");
51 | w.path.on.request();
52 |
53 |
54 | // a request was succesful
55 |
56 | }, assign: function assign (w, item) {
57 |
58 | w.deb(" G: assign: %s, %s", this, item);
59 |
60 | w.nounify("item", item);
61 |
62 | // got path, request unit, exits
63 | w.path.on
64 | .member(w.item)
65 | // .echo("path.resources" + item.resources)
66 | .units.do.request(this.minsize)
67 | .exit
68 | ;
69 |
70 | // have too much units, exits
71 | w.units.on
72 | .gt(w.units.count, w.units.size)
73 | .release(w.item)
74 | .exit
75 | ;
76 |
77 | // got a unit, send to path
78 | w.units.on
79 | .member(w.item)
80 | .stance("passive")
81 | .spread(w.path)
82 | ;
83 |
84 |
85 | // resource lost
86 |
87 | }, destroy: function destroy (w, item) {
88 |
89 | w.nounify("item", item);
90 |
91 | // keep minumum units, exits
92 | w.units.on
93 | .member(w.item)
94 | .lt(w.units.count, this.minsize)
95 | .request()
96 | .exit
97 | ;
98 |
99 |
100 | // there are enemies and gaia
101 |
102 | }, attack: function attack (w, attacker, victim, type, damage){
103 |
104 | w.deb(" G: attack: %s, %s, %s", this, attacker, victim);
105 |
106 | w.nounify("attacker", attacker, "victim", victim);
107 |
108 |
109 | // de-garrison
110 |
111 | }, release: function release (w, item) {
112 |
113 | w.deb(" G: release.0: %s, %s", w, item);
114 |
115 |
116 | // group radio
117 |
118 | }, radio: function radio (w, source, msg){
119 |
120 | w.deb(" G: %s onBroadcast from: %s, msg: %s", this, source, msg);
121 |
122 |
123 | // defined by this.interval
124 |
125 | }, interval: function interval (w, secs, ticks){
126 |
127 | // w.deb(" G: interval: %s, secs: %s, intv: %s", this, secs, this.interval);
128 |
129 | // idle units dance
130 |
131 | w.units.on
132 | .match(ticks % 2, 0)
133 | .doing("idle")
134 | .gt(w.units.count, 0)
135 | .path.do.modify("rotate 18")
136 | .units.do.spread(w.path)
137 | ;
138 |
139 | // w.units.on
140 | // .match(ticks % 4, 2)
141 | // .doing("idle")
142 | // // .match(w.units.count, w.units.size)
143 | // .stance("passive")
144 | // .path.do.modify("rotate 342")
145 | // .units.do.spread(w.path)
146 | // ;
147 |
148 | }
149 |
150 |
151 | } // end scripts
152 |
153 | }
154 |
155 | });
156 |
157 | return H; }(HANNIBAL));
158 |
--------------------------------------------------------------------------------
/source/simulation/ai/hannibal/comms.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, evil:true, devel: true, todo: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals HANNIBAL, uneval */
3 |
4 | /*--------------- C O M M U N I C A T I O N -----------------------------------
5 |
6 | Short range communication between citizens
7 |
8 |
9 | tested with 0 A.D. Alpha 18 Rhododactylus
10 | V: 0.1.1, agentx, CGN, Mar, 2015
11 |
12 | */
13 |
14 |
15 | HANNIBAL = (function(H){
16 |
17 | H.LIB.Comms = function(context){
18 |
19 | H.extend(this, {
20 |
21 | context: context,
22 |
23 | klass: "comms",
24 |
25 | imports: [
26 | "map",
27 | "mapsize",
28 | "query",
29 | "events",
30 | "entities",
31 | ],
32 |
33 | actors: null, // Map
34 | raster: null, // Array
35 | cellsize: 8, //
36 |
37 | });
38 |
39 | };
40 |
41 |
42 | H.LIB.Comms.prototype = H.mixin(
43 | H.LIB.Serializer.prototype, {
44 | constructor: H.LIB.Comms,
45 | log: function(){
46 | this.deb(); this.deb(" COMM: %s citizens", this.actors.size);
47 | },
48 | serialize: function(){
49 | return {
50 | raster: H.deepcopy(this.raster),
51 | actors: H.deepcopy(this.actors),
52 | };
53 | },
54 | deserialize: function(data){
55 | if(data){
56 | this.actors = new Map(data.actors);
57 | this.raster = data.raster;
58 | }
59 | return this;
60 | },
61 | finalize: function(){return this;},
62 |
63 | initialize: function(){
64 |
65 | var x, y, size = this.mapsize / this.cellsize;
66 |
67 | if(this.actors === null){
68 |
69 | this.actors = new Map();
70 | this.raster = [];
71 |
72 | x = size; while(x--){
73 | this.raster[x] = [];
74 | y = size; while(y--){
75 | this.raster[x][y] = [];
76 | }
77 | }
78 |
79 | this.update();
80 |
81 | }
82 |
83 | return this;
84 |
85 | },
86 | activate: function(){
87 |
88 | var actor, x, z;
89 |
90 | this.events.on("UnitDestroyed", msg => {
91 |
92 | actor = this.actors.get(msg.id);
93 |
94 | if(actor){
95 | [x, z] = actor;
96 | this.actors.delete(msg.id);
97 | H.delete(this.raster[x][z], id => id === msg.id);
98 | }
99 |
100 | this.deb(" COMM: removed actor: %s", msg.id);
101 |
102 | });
103 |
104 | return this;
105 |
106 | },
107 |
108 | tick: function(secs, ticks){
109 |
110 | var t0 = Date.now();
111 |
112 | this.secs = secs;
113 | this.ticks = ticks;
114 |
115 | this.update();
116 |
117 | return Date.now() - t0;
118 |
119 | },
120 |
121 | update: function(){
122 |
123 | var
124 | t0 = Date.now(),
125 | actor, oldx, oldz, curx, curz, cntold = 0, cntnew = 0;
126 |
127 | this.query("citizen CONTAIN INGAME").forEach(node => {
128 |
129 | // current coords
130 | [curx, curz] = this.map.mapPosToGridCoords(this.entities[node.id].position(), {cellsize: this.cellsize});
131 |
132 | // this.deb("coms.update: x: %s, y: %s, pos: %s", curx, curz, this.entities[node.id].position());
133 |
134 | actor = this.actors.get(node.id);
135 |
136 | // actor known
137 | if (actor){
138 |
139 | cntold += 1;
140 |
141 | [oldx, oldz] = actor;
142 |
143 | // with new position ?
144 | if (oldx !== curx || oldz !== curz){
145 |
146 | // update in raster
147 | H.delete(this.raster[oldx][oldz], id => id === node.id);
148 | this.raster[curx][curz].push(node.id);
149 |
150 | // update in actors
151 | actor[0] = curx;
152 | actor[1] = curz;
153 |
154 | // did not move, nothing to do
155 | } else {return;}
156 |
157 | // actor unknown
158 | } else {
159 |
160 | cntnew += 1;
161 |
162 | // update in actors
163 | this.actors.set(node.id, [curx, curz]);
164 |
165 | // update raster
166 | this.raster[curx][curz].push(node.id);
167 |
168 | }
169 |
170 | });
171 |
172 | // this.deb(" COMM: update took %s msecs (%s/%s/%s)", Date.now() - t0, cntnew, cntold, this.actors.size);
173 |
174 | },
175 |
176 | query: function(){
177 |
178 | },
179 |
180 |
181 | });
182 |
183 | return H; }(HANNIBAL));
184 |
--------------------------------------------------------------------------------
/source/simulation/ai/hannibal/htn-eco-operators.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, todo: true, evil:true, devel: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals HANNIBAL, deb */
3 |
4 | /*--------------- DOMAIN: E C O N O M Y --------------------------------------
5 |
6 | Operators
7 |
8 |
9 | tested with 0 A.D. Alpha 18 Rhododactylus
10 | V: 0.1.1, agentx, CGN, Mar, 2015
11 |
12 | */
13 |
14 | HANNIBAL = (function(H){
15 |
16 | // helper
17 |
18 | function applyCosts(state, costs, multiplier){
19 |
20 | ['food', 'wood', 'metal', 'stone'].forEach(function(res){
21 | state.data.ress[res] -= (costs[res]) ? costs[res] * multiplier : 0;
22 | });
23 |
24 | state.data.ress.pop += (costs.population > 0) ? costs.population * multiplier : 0;
25 | state.data.ress.popcap -= (costs.population < 0) ? costs.population * multiplier : 0;
26 |
27 | }
28 |
29 | H.HTN.Economy.operators = {
30 |
31 | wait_secs: function wait_secs(state, secs) {
32 |
33 | var prop, rate;
34 |
35 | if (true){
36 |
37 | for (prop of ['food', 'wood', 'metal', 'stone']){
38 | if (state.groups[prop] && state.groups[prop].length){
39 | rate = state.groups[prop].length * state.groups[prop][0].rate;
40 | state.data.ress[prop] += rate * secs;
41 | }
42 | }
43 |
44 | state.data.cost.time += secs;
45 | state.stamp += secs;
46 |
47 | return state;
48 |
49 | } else {return null;}
50 |
51 | },
52 |
53 | launch_group: function launch_group(state, group, units, amount) {
54 |
55 | var rate;
56 |
57 | if (true){
58 |
59 | if (!state.groups[group]){state.groups[group] = [];}
60 |
61 | rate = (
62 | group === "food" ? 2 :
63 | group === "wood" ? 4 :
64 | group === "stone" ? 8 :
65 | group === "metal" ? 16 :
66 | deb("launch_group: strange group '%s'", group)
67 | );
68 |
69 | state.groups[group].push({
70 | units: units,
71 | amount: amount,
72 | stamp: state.stamp,
73 | members: 0,
74 | rate: rate
75 | });
76 |
77 | return state;
78 |
79 | } else {return null;}
80 |
81 |
82 | },
83 | del_entity: function del_entity(state, entity, amount) {
84 |
85 | var ents = state.data.ents;
86 |
87 | if (ents[entity] >= amount){
88 |
89 | ents[entity] -= amount;
90 |
91 | if (ents[entity] === 0) {
92 | delete ents[entity];
93 | }
94 |
95 | return state;
96 |
97 | } else {
98 | deb("WARN : can't del_entity: %s %s", entity, amount);
99 | return null;
100 | }
101 |
102 | },
103 |
104 | inc_resource: function inc_resource(state, res, amount) {
105 |
106 | if (true){
107 |
108 | state.data.ress[res] += amount;
109 |
110 | state.data.cost[res] = ( state.data.cost[res] ?
111 | state.data.cost[res] + amount :
112 | amount
113 | );
114 |
115 | return state;
116 |
117 | } else {return null;}
118 |
119 | },
120 |
121 | train_units: function train_units(state, name, amount) {
122 |
123 | var costs, ents = state.data.ents;
124 |
125 | if (true){
126 |
127 | costs = H.HTN.Economy.nodes[name].costs;
128 | if (costs){applyCosts(state, costs, amount);}
129 | ents[name] = ents[name] || 0;
130 | ents[name] += amount;
131 |
132 | return state;
133 |
134 | } else {return null;}
135 |
136 | },
137 |
138 | build_structures: function build_structures(state, name, amount) {
139 |
140 | var costs, ents = state.data.ents;
141 |
142 | if (true){
143 |
144 | costs = H.HTN.Economy.nodes[name].costs;
145 | if (costs){applyCosts(state, costs, amount);}
146 | ents[name] = ents[name] || 0;
147 | ents[name] += amount;
148 |
149 | return state;
150 |
151 | } else {return null;}
152 |
153 | },
154 |
155 | research_tech: function research_tech(state, name) {
156 |
157 | var costs, techs = state.data.tech;
158 |
159 | if (true){
160 |
161 | costs = H.HTN.Economy.nodes[name].costs;
162 | if (costs) {applyCosts(state, costs, 1);}
163 | techs.push(name);
164 |
165 | // a hack, but works
166 | if (name === 'phase.town.athen') {techs.push('phase.town');}
167 | if (name === 'phase.city.athen') {techs.push('phase.city');}
168 | if (name === 'phase.town.generic'){techs.push('phase.town');}
169 | if (name === 'phase.city.generic'){techs.push('phase.city');}
170 |
171 | return state;
172 |
173 | } else {return null;}
174 |
175 | }
176 |
177 | };
178 |
179 | return H; }(HANNIBAL));
--------------------------------------------------------------------------------
/source/simulation/ai/hannibal/g.patrol.ranged.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, evil:true, devel: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals HANNIBAL */
3 |
4 | /*--------------- GROUP: P A T R O L ----------------------------------------
5 |
6 | a group to control and observe a settlment
7 |
8 |
9 | tested with 0 A.D. Alpha 18 Rhododactylus
10 | V: 0.1.1, agentx, CGN, Mar, 2015
11 |
12 | */
13 |
14 |
15 | HANNIBAL = (function(H){
16 |
17 | H.extend(H.Groups, {
18 |
19 | "g.patrol.ranged" : {
20 |
21 | /* Behaviour:
22 | village swat team
23 | relaxes on no attack
24 | attacks attacker
25 | concentrates on success hits
26 | flees enemies to strong
27 | */
28 |
29 | // variables available in listener with *this*. All optional
30 |
31 | active: true, // ready to init/launch ...
32 | description: "patrol", // text field for humans
33 | civilisations: ["*"], // lists all supported cics
34 | interval: 2, // call onInterval every x ticks
35 |
36 | scripts: {
37 |
38 |
39 | launch: function launch (w, config) {
40 |
41 | var path, pos = w.group.position[0] + " " + w.group.position[1];
42 |
43 | w.units = ["exclusive", "archer CONTAIN"];
44 | w.units.size = config.size || 16;
45 |
46 | path = w.units.size + "; translate " + pos + "; circle 30";
47 | w.path = ["path", path];
48 | w.path.size = w.units.size;
49 |
50 | w.nounify("units", "path");
51 | w.path.on.request();
52 |
53 |
54 | }, assign: function assign (w, item) {
55 |
56 | // a request was succesful
57 |
58 | // w.deb(" G: assign.0: %s, %s", w, item);
59 |
60 | w.nounify("item", item);
61 |
62 | // got path, request all units, exits
63 | w.path.on
64 | .member(w.item)
65 | .units.do.request(w.units.size)
66 | .exit
67 | ;
68 |
69 | // have too much units, exits
70 | w.units.on
71 | .gt(w.units.count, w.units.size)
72 | .release(w.item)
73 | .exit
74 | ;
75 |
76 | // got a unit, send to path start
77 | w.units.on
78 | .member(w.item)
79 | .stance("passive")
80 | .item.do.move(w.path.points("0"))
81 | .group.do.format("Box")
82 | ;
83 |
84 | // got final unit, spread them over path
85 | w.units.on
86 | .member(w.item)
87 | .match(w.units.count, w.units.size)
88 | .spread(w.path)
89 | ;
90 |
91 |
92 | }, destroy: function destroy (w, item) {
93 |
94 | // resource lost
95 |
96 | w.nounify("item", item);
97 |
98 | // lost unit, request another, go mad
99 | w.units.on
100 | .member(w.item)
101 | .request()
102 | .stance("agressive")
103 | ;
104 |
105 |
106 | }, attack: function attack (w, attacker, victim, type, damage){
107 |
108 | w.deb(" G: attack: %s, %s, %s", this, attacker, victim);
109 |
110 | w.nounify("attacker", attacker, "victim", victim);
111 |
112 | // we hit someone, I'm good
113 | w.units.on
114 | .member(w.attacker)
115 | .stance("denfensive")
116 | .path.do.modify("center E" + w.attacker.id)
117 | .spread(w.path)
118 | ;
119 |
120 | // someone hit us
121 | w.units.on
122 | .member(w.victim)
123 | .stance("denfensive")
124 | .lt(w.units.count, w.units.size -4)
125 | .flee()
126 | ;
127 |
128 |
129 | }, release: function release (w, item) {
130 |
131 | // de-garrison
132 |
133 | w.deb(" G: release.0: %s, %s", w, item);
134 |
135 |
136 | }, radio: function radio (w, source, msg){
137 |
138 | // group radio
139 |
140 | w.deb(" G: %s onBroadcast from: %s, msg: %s", this, source, msg);
141 |
142 |
143 | }, interval: function interval (w, tick, secs){
144 |
145 | // w.deb(" G: interval: %s, secs: %s, intv: %s", this, secs, this.interval);
146 |
147 | // if complete and idle, change path and spread
148 |
149 | w.units.on
150 | .match(tick % 4, 0)
151 | .doing("idle")
152 | .match(w.units.count, w.units.size)
153 | .stance("passive")
154 | .spread(w.path)
155 | .path.do.modify("rotate 120")
156 | ;
157 |
158 | w.units.on
159 | .match(tick % 4, 2)
160 | .doing("idle")
161 | .match(w.units.count, w.units.size)
162 | .stance("passive")
163 | .spread(w.path)
164 | .path.do.modify("rotate 20")
165 | ;
166 |
167 | }
168 |
169 |
170 | } // end scripts
171 |
172 | }
173 |
174 | });
175 |
176 | return H; }(HANNIBAL));
177 |
--------------------------------------------------------------------------------
/source/simulation/ai/hannibal/bot.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, todo: true, evil:true, devel: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals HANNIBAL, deb, uneval, Engine */
3 |
4 | /*--------------- H A N N I B A L ---------------------------------------------
5 |
6 | this is the actual bot, it loads from start, saved game or context and
7 | runs against the engine or in a simulation
8 |
9 | tested with 0 A.D. Alpha 18 Rhododactylus
10 | V: 0.1.1, agentx, CGN, Mar, 2015
11 |
12 | */
13 |
14 |
15 | HANNIBAL = (function(H){
16 |
17 | H.LIB.Bot = function(context){
18 |
19 | H.extend(this, {
20 |
21 | context: context,
22 |
23 | klass: "bot",
24 | parent: context,
25 | name: H.format("%s:%s#%s", context.name, "bot", context.id),
26 |
27 | imports: [
28 | "id",
29 | "player",
30 | "entities",
31 | "templates",
32 | "events",
33 | "map",
34 | "brain",
35 | "groups",
36 | "comms",
37 | "economy",
38 | "culture",
39 | "effector",
40 | "military",
41 | "villages",
42 | "resources",
43 | ],
44 |
45 | canplay: false, // assuming game/map is incomplete
46 |
47 | plan: null,
48 |
49 | });
50 |
51 | };
52 |
53 | H.LIB.Bot.prototype = H.mixin (
54 | H.LIB.Serializer.prototype, {
55 | constructor: H.LIB.Bot,
56 | log: function(){
57 | this.deb(); this.deb(" BOT: loaded: %s", this);
58 | },
59 | deserialize: function(data){
60 | if (data){
61 | this.canplay = data.canplay;
62 | this.plan = data.plan;
63 | }
64 | return this;
65 | },
66 | serialize: function(){
67 | var data = {};
68 | return data;
69 | },
70 | initialize: function(){
71 |
72 | // launch default groups for all settlements
73 | // get plan to phases city
74 |
75 | this.canplay = this.checkGame();
76 |
77 | if (!this.plan){
78 |
79 | }
80 |
81 |
82 | return this;
83 |
84 | },
85 | activate: function(){
86 | },
87 | tick: function(secs, tick, timing){
88 |
89 | if (tick === 0){
90 |
91 | // allow processing autoresearch first
92 | timing.brn = this.brain.tick( secs, tick);
93 | timing.map = this.map.tick( secs, tick);
94 | timing.gps = this.groups.tick( secs, tick);
95 | timing.mil = this.military.tick( secs, tick);
96 | timing.sts = this.economy.stats.tick( secs, tick);
97 | timing.eco = this.economy.tick( secs, tick);
98 |
99 | } else {
100 |
101 | [
102 |
103 | ["evt", "Events", this.events ],
104 | ["com", "Communication", this.comms ],
105 | ["brn", "Brain", this.brain ],
106 | ["map", "Map", this.map ],
107 | ["gps", "Groups", this.groups ],
108 | ["mil", "Military", this.military ],
109 | ["sts", "Economy.Stats", this.economy.stats],
110 | ["eco", "Economy", this.economy ],
111 |
112 | ].forEach(task => {
113 |
114 | Engine.ProfileStart("Hannibal " + task[1]);
115 | timing[task[0]] = task[2].tick.apply(task[2], [secs, tick]);
116 | Engine.ProfileStop();
117 |
118 | });
119 |
120 | }
121 |
122 | },
123 | checkGame: function(){
124 |
125 | var check = true, checks = [
126 | ["no seeds", () => this.villages.seedTemplates.length > 0],
127 | ];
128 |
129 | checks.forEach(chk => {
130 | if (!chk[1]()){
131 | check = false;
132 | this.deb(" BOT: Game problem: %s !!", chk[0]);
133 | }
134 | });
135 |
136 | if (check){
137 | this.deb(" BOT: game/map is playable");
138 | }
139 |
140 | return check;
141 |
142 | },
143 | unitprioritizer: function(){
144 |
145 | var
146 | phase = this.culture.phases.current,
147 | availability = this.economy.availability;
148 |
149 | function villSorter (nodes){
150 | nodes
151 | .sort((a, b) => a.costs[availability[0]] < b.costs[availability[0]] ? 1 : -1 )
152 | .sort((a, b) => a.costs[availability[1]] < b.costs[availability[1]] ? 1 : -1 )
153 | .sort((a, b) => a.costs[availability[2]] < b.costs[availability[2]] ? 1 : -1 )
154 | .sort((a, b) => a.costs[availability[3]] < b.costs[availability[3]] ? 1 : -1 );
155 | }
156 |
157 | if (phase === "vill"){
158 | return villSorter;
159 |
160 | } else if (phase === "town") {
161 | return villSorter;
162 | // return function(){this.deb("WARN : bot.unitsortorder for town not implemented");};
163 |
164 | } else if (phase === "city") {
165 | return villSorter;
166 | // return function(){this.deb("WARN : bot.unitsortorder for city not implemented");};
167 |
168 | } else {
169 | return function(){this.deb("ERROR : bot.unitsortorder for '%s' not implemented", phase);};
170 |
171 | }
172 |
173 |
174 | }
175 |
176 | });
177 |
178 | return H; }(HANNIBAL));
179 |
180 |
--------------------------------------------------------------------------------
/tools/prof.obj.loop.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, moz: true, evil:true, devel: true, todo: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals dateNow, uneval, putstr, version, options */
3 |
4 | /*
5 |
6 | tests various tecnics to loop over all properties of an object
7 | and calls a function with with property name + value
8 |
9 | */
10 |
11 | var
12 | t0 = dateNow(),
13 | tab = function (s,l){l=l||8;s=new Array(l+1).join(" ")+s;return s.substr(s.length-l);},
14 | toArray = function (a){return Array.prototype.slice.call(a);},
15 | format = function (){var a=toArray(arguments),s=a[0].split("%s"),p=a.slice(1).concat([""]),c=0;return s.map(function(t){return t + p[c++];}).join("");},
16 | deb = function(){print((dateNow() - t0).toFixed(1), format.apply(null, arguments));},
17 |
18 | // http://primes.utm.edu/lists/small/10000.txt
19 | slow = function (n, i){for(i=n;n%--i;);return i===1;};
20 |
21 | print();
22 | deb("Start V: %s, O: %s", version(), options());
23 |
24 | // some globals
25 |
26 | var
27 | obj, // the object looped over
28 | map, // the map looped over
29 | size, // amount of properties
30 | loops, // amount of tests
31 | timing; // keeps timing matrix
32 |
33 |
34 | // TEST SUITE
35 |
36 | // the dummy functions called
37 |
38 | var dummy = {
39 | "0": function (key, value){return;}, // does nothing
40 | "1": function (key, value){return "a";}, // return string
41 | "2": function (key, value){return value === value;}, // a simple compare
42 | // "3": function (key, value){return (value + value + value).slice(0, 10).contains("XXXXXX");}, // do something
43 | // "3": function (key, value){return slow(104729);}, // do something
44 | // "3": function (key, value){return slow(10099);}, // do something
45 | "3": function (key, value){return slow(5011);}, // do something
46 | };
47 |
48 | // the different lopp types
49 | var process = {
50 |
51 | "0" : {
52 | title: "reference",
53 | func: function (obj, map, fn){
54 | var key, test;
55 | for (key in obj){test = (key + key + key).slice(0, 10);}
56 | }},
57 |
58 | "1" : {
59 | // deprecated
60 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for_each...in
61 | title: "using object with for each (.. in ..)",
62 | func: function (obj, map, fn){
63 | var value;
64 | for each (value in obj){fn(undefined, value);}
65 | }},
66 |
67 | "2" : {
68 | title: "using object with for over Object.keys()",
69 | func: function (obj, map, fn){
70 | var i, keys = Object.keys(obj), len = keys.length;
71 | for (i=0; i fn(key, obj[key]));
80 | }},
81 |
82 | "4" : {
83 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in
84 | title: "using object with for (.. in .. )",
85 | func: function (obj, map, fn){
86 | var key;
87 | for (key in obj){fn(key, obj[key]);}
88 | }},
89 |
90 | "5" : {
91 | // experimental
92 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
93 | title: "using map with for (.. of .. )",
94 | func: function (obj, map, fn){
95 | var value;
96 | for (value of map){fn(undefined, value);}
97 | }},
98 |
99 | "6" : {
100 | // experimental
101 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
102 | title: "using map with forEach",
103 | func: function (obj, map, fn){
104 | map.forEach(fn);
105 | }},
106 |
107 |
108 | };
109 |
110 |
111 |
112 | // HELPER
113 |
114 | function reset () {
115 | timing = {};
116 | Object.keys(dummy).forEach((key, idx) => timing[idx] = []);
117 | }
118 |
119 | function result () {
120 | Object.keys(timing).forEach(k => {
121 | var avg = parseFloat((timing[k].reduce((a, b) => a + b, 0) / timing[k].length)).toFixed(1);
122 | if (avg > 2){
123 | deb("p%s avg: %s list: %s", k, tab(avg, 6), JSON.stringify(timing[k].map(n => parseFloat(n.toFixed(1)))));
124 | } else {
125 | deb("p%s avg: %s list: %s", k, tab(avg, 6), JSON.stringify(timing[k].map(n => Math.round(n))));
126 | }
127 | });
128 | print();
129 | }
130 |
131 | function rnd(){return Math.random().toString(36).slice(2);}
132 |
133 | function init(osize){
134 |
135 | obj = {};
136 | map = Map();
137 |
138 | while(osize--){
139 | obj[rnd()] = rnd(); // random prop names with random string values
140 | map.set(rnd(), rnd()); // same
141 | }
142 |
143 | print();
144 |
145 | }
146 |
147 | function profile(index){
148 |
149 | var t0, i, j, len;
150 |
151 | deb("running: [%s] '%s' ... ", index, process[index].title) ;
152 | len = Object.keys(dummy).length;
153 |
154 | for (i=0; i {
174 | reset();
175 | profile(idx);
176 | result();
177 | });
178 |
179 | deb("Done");
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/treestyles.css:
--------------------------------------------------------------------------------
1 |
2 | body {
3 | background-color: #eeeeee;
4 | color: #000000;
5 | font-family:sans-serif;
6 | }
7 |
8 | :link { color: #0000ff; text-decoration:none;}
9 | :visited { color: #6666ff; text-decoration:none; }
10 | a:active { color: #0000ff; text-decoration:none;}
11 | a:hover {color: #0000ff; text-decoration:underline; }
12 |
13 | div.basetext {
14 | background-color:#ffffff;
15 | margin-top:11px;
16 | margin-bottom:11px;
17 | margin-left:1%;
18 | margin-right:1%;
19 | padding-top:11px;
20 | padding-left:11px;
21 | padding-right:11px;
22 | padding-bottom:11px;
23 | text-align:left;
24 | font-weight:normal;
25 | border-width:thin;
26 | border-style:solid;
27 | border-color:#dddddd;
28 | }
29 |
30 | div.basetop {
31 | position: fixed;
32 | width:auto;
33 | height:auto;
34 | right:0em;
35 | top:0em;
36 | left:auto;
37 | top:0;
38 | background-color:#ffffff;
39 | margin-top:0;
40 | margin-bottom:0;
41 | margin-left:1%;
42 | margin-right:1%;
43 | padding-top:2px;
44 | padding-left:11px;
45 | padding-right:11px;
46 | padding-bottom:2px;
47 | text-align:left;
48 | font-weight:normal;
49 | text-align:right;
50 | border-width:thin;
51 | border-style:solid;
52 | border-color:#dddddd;
53 | }
54 |
55 | h1 {
56 | text-align:center;
57 | }
58 |
59 | span.h2 {
60 | font-family:sans-serif;
61 | font-weight:bold;
62 | }
63 |
64 | div.year {
65 | margin-right:2%;
66 | background-color:#eeeeee;
67 | }
68 |
69 | div.form {
70 | }
71 |
72 | span.cpt {
73 | color:#005500;
74 | font-weight:bold;
75 | }
76 |
77 | span.cm {
78 | color:#666666;
79 | }
80 |
81 | .fl {
82 | color:#0000FF;
83 | font-style:italic;
84 | }
85 |
86 | ul {
87 | margin-top:1px;
88 | margin-bottom:1px;
89 | margin-left:0px;
90 | padding-left:3%;
91 | }
92 |
93 | li {
94 | list-style:outside;
95 | margin-top:10px;
96 | margin-bottom:10px;
97 | }
98 |
99 | ul li {
100 | list-style:square;
101 | font-family:sans-serif;
102 | font-weight:normal;
103 | }
104 |
105 | li.basic {
106 | list-style:square;
107 | list-style-image:none;
108 | margin-top:2px;
109 | margin-bottom:2px;
110 | }
111 |
112 | span.links {
113 | }
114 |
115 |
116 |
117 |
118 | .sub { display: none; }
119 | .subexp {display: block; }
120 | .sub { display: none; }
121 |
122 | .subexp {display: block; }
123 |
124 | li.exp {
125 | list-style-image:url("plus.png");
126 | margin-top:10px;
127 | margin-bottom:10px;
128 | cursor:pointer;
129 | }
130 |
131 | li.col {
132 | list-style-image:url("minus.png");
133 | margin-top:10px;
134 | margin-bottom:10px;
135 | cursor:pointer;
136 | }
137 |
138 | li.exp_active {
139 | list-style-image:url("plus.png");
140 | margin-top:10px;
141 | margin-bottom:10px;
142 | background-color:#eeeeff;
143 | cursor:pointer;
144 | }
145 |
146 | li.col_active {
147 | list-style-image:url("minus.png");
148 | margin-top:10px;
149 | margin-bottom:10px;
150 | background-color:#eeeeff;
151 | cursor:pointer; /* if not included, bullets are not shown right in moz*/
152 | }
153 |
154 |
155 | li.basic_active {
156 | list-style:square;
157 | list-style-image:none;
158 | background-color:#eeeeff;
159 | margin-top:2px;
160 | margin-bottom:2px;
161 | }
162 |
163 | /* the 'boxed' and 'attributes' styles are used to display notes and attributes
164 | */
165 |
166 | .boxed,.nodecontent {display:inline;}
167 | .boxed .note-and-attributes {display:none;}
168 |
169 | .boxed:hover .note-and-attributes {
170 | position:fixed; top:2em;right:10px;z-index:3;
171 | display:block;
172 | min-width:33%;
173 | max-width:60%;
174 | max-height:95%;
175 | color:black;
176 | background:#ffffff;
177 | font:normal 16px courier, sans-serif;
178 | border:1px solid black;
179 | padding:10px;
180 | }
181 |
182 | .note:before {
183 | content:"NOTE: ";
184 | font-weight:bold;
185 | }
186 |
187 | table.attributes {
188 | border-collapse:collapse;
189 | empty-cells:show;
190 | border:thin black solid;
191 | }
192 | table.attributes td,th {
193 | border:thin black solid;
194 | padding-top:2px;
195 | padding-bottom:2px;
196 | padding-left:3px;
197 | padding-right:3px;
198 | }
199 | table.attributes th {
200 | text-align:center;
201 | }
202 | table.attributes caption {
203 | margin-top:1em;
204 | font-style:italic;
205 | text-align:center;
206 | }
207 | /* Thanks to wolfgangradke, https://sourceforge.net/forum/message.php?msg_id=5991663 */
208 | div.nodecontent > p {
209 | margin-top:0pt;
210 | margin-bottom:0pt;
211 | display:inline;
212 | }
213 |
214 | p + p {
215 | margin-top: 0.5em !important;
216 | display:block !important;
217 | }
218 |
219 | /* Thanks to erne100, https://sourceforge.net/tracker/?func=detail&atid=107118&aid=2747128&group_id=7118*/
220 | table {
221 | border-collapse:collapse;
222 | empty-cells:show;
223 | border:thin black solid;
224 | }
225 | table td {
226 | border:thin black solid;
227 | padding-top:2px;
228 | padding-bottom:2px;
229 | padding-left:3px;
230 | padding-right:3px;
231 | }
232 |
233 | /* Thanks to erne100, https://sourceforge.net/tracker/?func=detail&atid=107118&aid=2747000&group_id=7118*/
234 | ol {
235 | margin-top:1px;
236 | margin-bottom:1px;
237 | margin-left:0px;
238 | padding-left:3%;
239 | }
240 |
241 | ol li {
242 | list-style:decimal;
243 | font-family:sans-serif;
244 | font-weight:normal;
245 | }
246 |
247 |
248 |
--------------------------------------------------------------------------------
/maps/scripts/TriggerHelper.js:
--------------------------------------------------------------------------------
1 | // Contains standardized functions suitable for using in trigger scripts.
2 | // Do not use them in any other simulation script.
3 |
4 | var TriggerHelper = {};
5 |
6 | TriggerHelper.GetPlayerIDFromEntity = function(ent)
7 | {
8 | var cmpPlayer = Engine.QueryInterface(ent, IID_Player);
9 | if (cmpPlayer)
10 | return cmpPlayer.GetPlayerID();
11 | return -1;
12 | };
13 |
14 | TriggerHelper.GetOwner = function(ent)
15 | {
16 | var cmpOwnership = Engine.QueryInterface(ent, IID_Ownership);
17 | if (cmpOwnership)
18 | return cmpOwnership.GetOwner();
19 | return -1;
20 | };
21 |
22 | /**
23 | * Can be used to "force" a building to spawn a group of entities.
24 | * Only works for buildings that can already train units.
25 | * @param source Entity id of the point where they will be spawned from
26 | * @param template Name of the template
27 | * @param count Number of units to spawn
28 | * @param owner Player id of the owner of the new units. By default, the owner
29 | * of the source entity.
30 | */
31 | TriggerHelper.SpawnUnits = function(source, template, count, owner)
32 | {
33 | var r = []; // array of entities to return;
34 | var cmpFootprint = Engine.QueryInterface(source, IID_Footprint);
35 | var cmpPosition = Engine.QueryInterface(source, IID_Position);
36 | if (!cmpPosition || !cmpPosition.IsInWorld())
37 | {
38 | error("tried to create entity from a source without position");
39 | return r;
40 | }
41 | if (owner == null)
42 | owner = TriggerHelper.GetOwner(source);
43 |
44 | for (var i = 0; i < count; i++)
45 | {
46 | var ent = Engine.AddEntity(template);
47 | var cmpEntPosition = Engine.QueryInterface(ent, IID_Position);
48 | if (!cmpEntPosition)
49 | {
50 | error("tried to create entity without position");
51 | continue;
52 | }
53 | var cmpEntOwnership = Engine.QueryInterface(ent, IID_Ownership);
54 | if (cmpEntOwnership)
55 | cmpEntOwnership.SetOwner(owner);
56 | r.push(ent);
57 | var pos;
58 | if (cmpFootprint)
59 | pos = cmpFootprint.PickSpawnPoint(ent);
60 | // TODO this can happen if the player build on the place
61 | // where our trigger point is
62 | // We should probably warn the trigger maker in some way,
63 | // but not interrupt the game for the player
64 | if (!pos || pos.y < 0)
65 | pos = cmpPosition.GetPosition();
66 | cmpEntPosition.JumpTo(pos.x, pos.z);
67 | }
68 | return r;
69 | };
70 |
71 | /**
72 | * Spawn units from all trigger points with this reference
73 | * If player is defined, only spaw units from the trigger points
74 | * that belong to that player
75 | * @param ref Trigger point reference name to spawn units from
76 | * @param template Template name
77 | * @param count Number of spawned entities per Trigger point
78 | * @param owner Owner of the spawned units. Default: the owner of the origins
79 | * @return A list of new entities per origin like
80 | * {originId1: [entId1, entId2], originId2: [entId3, entId4], ...}
81 | */
82 | TriggerHelper.SpawnUnitsFromTriggerPoints = function(ref, template, count, owner = null)
83 | {
84 | var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
85 | var triggerPoints = cmpTrigger.GetTriggerPoints(ref);
86 | var r = {};
87 | for (var point of triggerPoints)
88 | r[point] = TriggerHelper.SpawnUnits(point, template, count, owner);
89 | return r;
90 | };
91 |
92 | /**
93 | * Returs a function that can be used to filter an array of entities by player
94 | */
95 | TriggerHelper.GetPlayerFilter = function(playerID)
96 | {
97 | return function(entity) {
98 | var cmpOwnership = Engine.QueryInterface(entity, IID_Ownership);
99 | return cmpOwnership && cmpOwnership.GetOwner() == playerID;
100 | }
101 | };
102 |
103 | /**
104 | * Returns the resource type that can be gathered from an entity
105 | */
106 | TriggerHelper.GetResourceType = function(entity)
107 | {
108 | var cmpResourceSupply = Engine.QueryInterface(entity, IID_ResourceSupply);
109 | if (!cmpResourceSupply)
110 | return undefined;
111 | return cmpResourceSupply.GetType();
112 | };
113 |
114 | /**
115 | * Wins the game for a player
116 | */
117 | TriggerHelper.SetPlayerWon = function(playerID)
118 | {
119 | var cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
120 | cmpEndGameManager.MarkPlayerAsWon(playerID);
121 | };
122 |
123 | /**
124 | * Defeats a player
125 | */
126 | TriggerHelper.DefeatPlayer = function(playerID)
127 | {
128 | var cmpPlayerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
129 | var playerEnt = cmpPlayerMan.GetPlayerByID(playerID);
130 | Engine.PostMessage(playerEnt, MT_PlayerDefeated, { "playerId": playerID } );
131 | };
132 |
133 | /**
134 | * Returns the number of current players
135 | */
136 | TriggerHelper.GetNumberOfPlayers = function()
137 | {
138 | var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
139 | return cmpPlayerManager.GetNumPlayers();
140 | };
141 |
142 | /**
143 | * Returns the player component. For more information on its functions, see simulation/components/Player.js
144 | */
145 | TriggerHelper.GetPlayerComponent = function(playerID)
146 | {
147 | var cmpPlayerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
148 | return Engine.QueryInterface(cmpPlayerMan.GetPlayerByID(playerID), IID_Player);
149 | };
150 |
151 | /**
152 | * A function to determine if an entity has a specific class
153 | * @param entity ID of the entity that we want to check for classes
154 | * @param classname The name of the class we are checking if the entity has
155 | */
156 | TriggerHelper.EntityHasClass = function(entity, classname)
157 | {
158 | var cmpIdentity = Engine.QueryInterface(entity, IID_Identity);
159 | if (!cmpIdentity)
160 | return false;
161 | var classes = cmpIdentity.GetClassesList();;
162 | return (classes && classes.indexOf(classname) != -1);
163 | };
164 |
165 | Engine.RegisterGlobal("TriggerHelper", TriggerHelper);
166 |
--------------------------------------------------------------------------------
/docs/Hannibal-Mmap.html_files/flashobject.js:
--------------------------------------------------------------------------------
1 | /*
2 | * FlashObject embed
3 | * by Geoff Stearns (geoff@deconcept.com, http://www.deconcept.com/)
4 | *
5 | * v1.1.1 - 05-17-2005
6 | *
7 | * writes the embed code for a flash movie, includes plugin detection
8 | *
9 | * Usage:
10 | *
11 | * myFlash = new FlashObject("path/to/swf.swf", "swfid", "width", "height", flashversion, "backgroundcolor");
12 | * myFlash.write("objId");
13 | *
14 | * for best practices, see:
15 | * http://blog.deconcept.com/2005/03/31/proper-flash-embedding-flashobject-best-practices/
16 | *
17 | */
18 |
19 | var FlashObject = function(swf, id, w, h, ver, c) {
20 | this.swf = swf;
21 | this.id = id;
22 | this.width = w;
23 | this.height = h;
24 | this.version = ver;
25 | this.align = "middle";
26 |
27 | this.params = new Object();
28 | this.variables = new Object();
29 |
30 | this.redirect = "";
31 | this.sq = document.location.search.split("?")[1] || "";
32 | this.bypassTxt = "Already have Macromedia Flash Player? Click here if you have Flash Player "+ this.version +" installed .
";
33 |
34 | if (c) this.color = this.addParam('bgcolor', c);
35 | this.addParam('quality', 'high'); // default to high
36 | this.doDetect = getQueryParamValue('detectflash');
37 | }
38 |
39 | var FOP = FlashObject.prototype;
40 |
41 | FOP.addParam = function(name, value) { this.params[name] = value; }
42 |
43 | FOP.getParams = function() { return this.params; }
44 |
45 | FOP.getParam = function(name) { return this.params[name]; }
46 |
47 | FOP.addVariable = function(name, value) { this.variables[name] = value; }
48 |
49 | FOP.getVariable = function(name) { return this.variables[name]; }
50 |
51 | FOP.getVariables = function() { return this.variables; }
52 |
53 | FOP.getParamTags = function() {
54 | var paramTags = "";
55 | for (var param in this.getParams()) {
56 | paramTags += ' ';
57 | }
58 | return (paramTags == "") ? false:paramTags;
59 | }
60 |
61 | FOP.getHTML = function() {
62 | var flashHTML = "";
63 | if (navigator.plugins && navigator.mimeTypes.length) { // netscape plugin architecture
64 | flashHTML += ' ';
72 | } else { // PC IE
73 | flashHTML += '';
74 | flashHTML += ' ';
75 | if (this.getParamTags()) {
76 | flashHTML += this.getParamTags();
77 | }
78 | if (this.getVariablePairs() != null) {
79 | flashHTML += ' ';
80 | }
81 | flashHTML += ' ';
82 | }
83 | return flashHTML;
84 | }
85 |
86 | FOP.getVariablePairs = function() {
87 | var variablePairs = new Array();
88 | for (var name in this.getVariables()) {
89 | variablePairs.push(name + "=" + escape(this.getVariable(name)));
90 | }
91 | return (variablePairs.length > 0) ? variablePairs.join("&"):false;
92 | }
93 |
94 | FOP.write = function(elementId) {
95 | if(detectFlash(this.version) || this.doDetect=='false') {
96 | if (elementId) {
97 | document.getElementById(elementId).innerHTML = this.getHTML();
98 | } else {
99 | document.write(this.getHTML());
100 | }
101 | } else {
102 | if (this.redirect != "") {
103 | document.location.replace(this.redirect);
104 | } else if (this.altTxt) {
105 | if (elementId) {
106 | document.getElementById(elementId).innerHTML = this.altTxt +""+ this.bypassTxt;
107 | } else {
108 | document.write(this.altTxt +""+ this.bypassTxt);
109 | }
110 | }
111 | }
112 | }
113 |
114 | /* ---- detection functions ---- */
115 | function getFlashVersion() {
116 | var flashversion = 0;
117 | if (navigator.plugins && navigator.mimeTypes.length) {
118 | var x = navigator.plugins["Shockwave Flash"];
119 | if(x && x.description) {
120 | var y = x.description;
121 | flashversion = y.charAt(y.indexOf('.')-1);
122 | var aux= y.charAt(y.indexOf('.')-2);
123 | if("0123456789".indexOf(aux)!=-1) flashversion=aux+flashversion;
124 | }
125 | } else {
126 | result = false;
127 | for(var i = 15; i >= 3 && result != true; i--){
128 | execScript('on error resume next: result = IsObject(CreateObject("ShockwaveFlash.ShockwaveFlash.'+i+'"))','VBScript');
129 | flashversion = i;
130 | }
131 | }
132 | return flashversion;
133 | }
134 |
135 | function detectFlash(ver) { return (getFlashVersion() >= ver) ? true:false; }
136 |
137 | // get value of query string param
138 | function getQueryParamValue(param) {
139 | var q = document.location.search || document.location.href.split("#")[1];
140 | if (q) {
141 | var detectIndex = q.indexOf(param +"=");
142 | var endIndex = (q.indexOf("&", detectIndex) > -1) ? q.indexOf("&", detectIndex) : q.length;
143 | if (q.length > 1 && detectIndex > -1) {
144 | return q.substring(q.indexOf("=", detectIndex)+1, endIndex);
145 | } else {
146 | return "";
147 | }
148 | }
149 | }
150 |
151 | /* add Array.push if needed */
152 | if(Array.prototype.push == null){
153 | Array.prototype.push = function(item) { this[this.length] = item; return this.length; }
154 | }
155 |
--------------------------------------------------------------------------------
/source/simulation/ai/hannibal/g.harvester.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, evil:true, devel: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals HANNIBAL */
3 |
4 | /*--------------- GROUP: H A R V E S T E R ----------------------------------
5 |
6 | a group to generate food from fields
7 |
8 |
9 | tested with 0 A.D. Alpha 18 Rhododactylus
10 | V: 0.1.1, agentx, CGN, Mar, 2015
11 |
12 | */
13 |
14 |
15 | HANNIBAL = (function(H){
16 |
17 | H.extend(H.Groups, {
18 |
19 | "g.harvester" : {
20 |
21 | /* Behaviour:
22 | to maintain one field resource (food.grain),
23 | to return gathered food to dropsite
24 | to shelter from violence (garrison)
25 | to help with nearby repair
26 | */
27 |
28 | // variables available in listener with *this*. All optional
29 |
30 | active: true, // ready to init/launch ...
31 | description: "harvester", // text field for humans
32 | civilisations: ["*"], // lists all supported cics
33 | interval: 10, // call onInterval every x ticks
34 |
35 | technologies: [ // these techs help
36 | "gather.capacity.wheelbarrow",
37 | "celts.special.gather.crop.rotation",
38 | "gather.farming.plows"
39 | ],
40 |
41 | scripts: {
42 |
43 | // game started, something launched this group
44 | launch: function launch (w, config) {
45 |
46 | w.units = ["exclusive", "food.grain GATHEREDBY WITH costs.metal = 0, costs.stone = 0"];
47 | w.field = ["exclusive", "food.grain PROVIDEDBY"];
48 | w.dropsite = ["shared", "food ACCEPTEDBY"]; //TODO: exclude docks
49 |
50 | w.units.size = 5;
51 | w.field.size = 1;
52 | w.dropsite.size = 1;
53 |
54 | w.nounify("units", "field", "dropsite");
55 |
56 | w.dropsite.on.request();
57 |
58 |
59 | // a request was succesful
60 |
61 | }, assign: function assign (w, item) {
62 |
63 | w.deb(" G: assign: %s, %s", this, item);
64 |
65 | w.nounify("item", item);
66 |
67 | // got dropsite, request unit, exits
68 | w.dropsite.on
69 | .member(w.item)
70 | .units.do.request()
71 | .exit
72 | ;
73 |
74 | // have too much units, release, exits
75 | w.units.on
76 | .gt(w.units.count, w.units.size)
77 | .release(w.item)
78 | .exit
79 | ;
80 |
81 | // keep requesting units until size
82 | w.units.on
83 | .member(w.item)
84 | .lt(w.units.count, w.units.size)
85 | .request()
86 | ;
87 |
88 | // the first unit requests field, exits
89 | w.units.on
90 | .member(w.item)
91 | .match(w.units.count, 1)
92 | .match(w.field.count, 0)
93 | .field.do.request()
94 | .exit
95 | ;
96 |
97 | // got unit let repair/gather, exits
98 | w.units.on
99 | .member(w.item)
100 | .match(w.field.count, 1)
101 | .item.do.repair(w.field) // relies on autocontinue
102 | .exit
103 | ;
104 |
105 | // got the field foundation, update position, all units repair, exits
106 | w.field.on
107 | .member(w.item)
108 | .match(w.item.foundation)
109 | .units.do.repair(w.item)
110 | .group.do.relocate(w.item.position)
111 | .exit
112 | ;
113 |
114 | // got the field, units gather exits
115 | w.field.on
116 | .member(w.item)
117 | .match(!w.item.foundation)
118 | .units.do.gather(w.field)
119 | .exit
120 | ;
121 |
122 |
123 | // resource lost
124 |
125 | }, destroy: function destroy (w, item) {
126 |
127 | w.deb(" G: destroy: %s, %s", this, item);
128 |
129 | w.nounify("item", item);
130 |
131 | // lost unit, request another
132 | w.units.on
133 | .member(w.item)
134 | .request()
135 | ;
136 |
137 | // lost field, request another
138 | w.field.on
139 | .member(w.item)
140 | .request()
141 | ;
142 |
143 |
144 | // there are enemies and gaia
145 |
146 | }, attack: function attack (w, attacker, victim, type, damage){
147 |
148 | w.deb(" G: attack: %s, %s, %s", this, attacker, victim);
149 |
150 | w.nounify("attacker", attacker, "victim", victim);
151 |
152 | w.field.on
153 | .member(w.item)
154 | .units.on.repair(w.item)
155 | ;
156 |
157 | // de-garrison
158 |
159 | }, release: function release (w, item) {
160 |
161 | w.deb(" G: release.0: %s, %s", this, item);
162 |
163 |
164 | // group radio
165 |
166 | }, radio: function radio (w, source, msg){
167 |
168 | w.deb(" G: %s onBroadcast from: %s, msg: %s", this, source, msg);
169 |
170 |
171 | // defined by this.interval
172 |
173 | }, interval: function interval (w, tick, secs){
174 |
175 | // w.deb(" G: interval: %s, secs: %s, intv: %s", this, secs, this.interval);
176 |
177 | // send few idle unit to gather, exits
178 | w.units.on
179 | .doing("idle")
180 | .lt(w.units.count, w.units.size)
181 | .gt(w.units.count, 0)
182 | .units.on.gather(w.field)
183 | .exit
184 | ;
185 |
186 | // if all idle, release group
187 | w.units.on
188 | .doing("idle")
189 | .match(w.units.count, w.units.size)
190 | .group.release()
191 | ;
192 |
193 |
194 | }
195 |
196 |
197 | } // end listener
198 |
199 | }
200 |
201 | });
202 |
203 | return H; }(HANNIBAL));
204 |
205 |
--------------------------------------------------------------------------------
/source/simulation/ai/hannibal/goals.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, todo: true, evil:true, devel: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals HANNIBAL, uneval */
3 |
4 | /*--------------- G O A L S ---------------------------------------------------
5 |
6 | Define goals, depending on victory conditions, civilisation
7 |
8 |
9 | tested with 0 A.D. Alpha 18 Rhododactylus
10 | V: 0.1.1, agentx, CGN, Mar, 2015
11 |
12 | */
13 |
14 |
15 | /*
16 | vcs:
17 | none
18 | conquest
19 | wonder
20 | */
21 |
22 | /*
23 | Goals with method pair action/needsAction are continues and never done, except with parent goal
24 |
25 | */
26 |
27 |
28 |
29 | /*
30 | Postponed:
31 | Civ Specifc Buildings:
32 | wonder, gymnasion, theatron, kennel, super-dock, rotary mill, prytaneion, monument, library, elephant stables, parihuvādā, stables, lighthouse, mercenary camp, gerousia, syssiton,
33 | Units:
34 | Heros
35 |
36 | Vill:
37 | Resources
38 | Group: wood
39 | Group: field
40 | Group: fruit
41 | Group: hunter
42 | Group: breeder
43 | Buildings
44 | Houses
45 | Corral
46 | Dock
47 | Farmstead
48 | Storehouse
49 | Blacksmith
50 | Barracks
51 | Palisade
52 | Strategic:
53 | Group: scouts
54 | Techs
55 | town
56 |
57 | Town:
58 | Resources
59 | Group: wood
60 | Group: stone
61 | Group: metal
62 | Group: field
63 | Group: fruit
64 | Group: hunter
65 | Group: breeder
66 | Buildings
67 | Houses
68 | Corral
69 | Farmstead
70 | Storehouse
71 | Blacksmith
72 | Barracks 2
73 | Temple
74 | Market
75 | Towers
76 | Wall
77 | Strategic:
78 | Group: scouts
79 | Group: patrol
80 | Techs
81 | City
82 | health_regen_units
83 |
84 | City:
85 | Resources
86 | Group: wood
87 | Group: stone
88 | Group: metal
89 | Group: field
90 | Group: fruit
91 | Group: hunter
92 | Group: breeder
93 | Strategic:
94 | Group: scouts
95 | Group: patrol
96 | Buildings
97 | Houses
98 | Corral
99 | Dock
100 | Shipyard
101 | Farmstead
102 | Storehouse
103 | Blacksmith
104 | Barracks 2
105 | Temple
106 | Market
107 | Wall
108 | Fortress
109 | Colony
110 | Outpost
111 | Centre/colony/army camp
112 | Tower
113 | Techs
114 | City
115 |
116 |
117 | What covers a plan?
118 | The buildings and techs to reach next phase.
119 |
120 | What covers monitoring
121 | The resources needed to maintain resource flow of centre+barracks
122 | The plan's resources
123 | The amount of resources needed to fulfill plan
124 |
125 |
126 |
127 |
128 |
129 |
130 | */
131 |
132 |
133 |
134 | HANNIBAL = (function(H){
135 |
136 | H.Data.Goals = {
137 |
138 | "condNone": {
139 | goals: ["condConquest"],
140 | },
141 | "condConquest": {
142 | goals: ["expandVill", "expandTown", "expandCity"],
143 | },
144 | "condWonder": {
145 | goals: ["expandVill", "expandTown", "wonder", "expandCity"],
146 | },
147 |
148 | "expandVill": {
149 | goals: ["houses", "farmstead", "blacksmith", "fields", "dock", "barracks", "town"],
150 | isValid: function(){return true;},
151 | isDone: function(){return this.goals.every(g => g.isDone());},
152 | },
153 | "expandTown": {
154 | goals: ["houses", "market", "temple", "shipyard", "city"],
155 | isValid: function(){return true;},
156 | isDone: function(){return this.phases.current === "city";},
157 | },
158 | "expandCity": {
159 | goals: ["houses", "fortress", "wall"],
160 | isValid: function(){return true;},
161 | isDone: function(){return false;},
162 | },
163 |
164 | "houses": {
165 | action: function () {
166 | this.groups.launch({cc: this.village.main, buildings: "house", quantity: 2});
167 | },
168 | needsAction: function(){
169 | var
170 | popHouse = this.query("house CONTAIN").first().costs.population,
171 | cntHouses = this.query("house CONTAIN INGAME").count();
172 | return this.stats.population > popHouse * cntHouses - 2 * popHouse;
173 | },
174 | },
175 |
176 | "blacksmith": {
177 | action: function () {
178 | this.groups.launch({cc: this.village.main, buildings: "blacksmith", quantity: 1});
179 | },
180 | isDone: function(){return this.query("blacksmith CONTAIN INGAME").count() > 0;},
181 | },
182 |
183 | "farmstead": {
184 | action: function () {
185 | this.groups.launch({cc: this.village.main, buildings: "farmstead", quantity: 1});
186 | },
187 | isDone: function(){return this.query("farmstead CONTAIN INGAME").count() > 0;},
188 | },
189 |
190 | };
191 |
192 |
193 | H.LIB.Goal = function (context){
194 |
195 | H.extend(this, {
196 |
197 | context: context,
198 |
199 | imports: [
200 | "stats",
201 | "query",
202 | "village",
203 | ],
204 |
205 | done: false,
206 | valid: true
207 |
208 | });
209 |
210 | };
211 |
212 |
213 | H.LIB.Goal.prototype = H.mixin (
214 | H.LIB.Serializer.prototype, {
215 | constructor: H.LIB.Goal,
216 | tick: function(tick, secs){
217 |
218 | if (!this.done && this.valid){
219 |
220 | if (this.isValid && !this.isValid()){
221 | this.valid = false;
222 | return;
223 | }
224 |
225 | if (this.isDone()){
226 | this.done = true;
227 | return;
228 | }
229 |
230 | // continous
231 | if (this.needsAction && this.needsAction()){
232 | this.action();
233 | return;
234 |
235 | } else {
236 | // one time
237 | this.action();
238 | this.done = true;
239 | }
240 |
241 | }
242 |
243 | },
244 |
245 | });
246 |
247 | return H; }(HANNIBAL));
248 |
--------------------------------------------------------------------------------
/tools/prof.SIMD.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, evil:true, devel: true, todo: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals dateNow, uneval, decompileBody, putstr, version, options, SIMD */
3 |
4 | // build() *writes* to stdout
5 |
6 | var
7 | t0 = dateNow(),
8 | H = {
9 | tab: function (s,l){l=l||8;s=new Array(l+1).join(" ")+s;return s.substr(s.length-l);},
10 | toArray: function (a){return Array.prototype.slice.call(a);},
11 | format: function (){var a=H.toArray(arguments),s=a[0].split("%s"),p=a.slice(1).concat([""]),c=0;return s.map(function(t){return t + p[c++];}).join("");},
12 | },
13 | deb = function(){print((dateNow() - t0).toFixed(1), H.format.apply(H, arguments));};
14 |
15 | deb("Start V: %s, O: %s", version(), options());
16 |
17 |
18 | // SIMD in JavaScript, By Ivan Jibaja, Senior Software Engineer, Intel Corporation
19 | // https://01.org/node/1495
20 |
21 |
22 | // getBuildConfiguration();
23 | // build();
24 | // isSimdAvailable()
25 | // typein:12:0 ReferenceError: getCompilerOptions is not defined
26 |
27 | // js> Object.getOwnPropertyNames(SIMD)
28 | // ["float32x4", "int32x4"]
29 |
30 | // js> Object.getOwnPropertyNames(SIMD.float32x4)
31 | // ["byteLength", "byteAlignment", "toSource", "array", "equivalent", "prototype", "abs", "fromInt32x4", "fromInt32x4Bits",
32 | // "neg", "not", "reciprocal", "reciprocalSqrt", "splat", "sqrt", "add", "and", "div", "equal", "greaterThan",
33 | // "greaterThanOrEqual", "lessThan", "lessThanOrEqual", "load", "loadXYZ", "loadXY", "loadX", "max", "maxNum",
34 | // "min", "minNum", "mul", "notEqual", "or", "store", "storeXYZ", "storeXY", "storeX", "sub", "withX", "withY", "withZ", "withW",
35 | // "xor", "clamp", "select", "swizzle", "shuffle"]
36 |
37 |
38 | function process0(source, target){
39 |
40 | var t0 = dateNow(), s, i = length;
41 |
42 | while (i--) {
43 | s = source[i];
44 | target[i] = (s === 1 || s === 2 || s === 4) ? 255 : 0;
45 | }
46 | tims[0].push(dateNow()-t0);
47 | // print(uneval(target));
48 | }
49 |
50 |
51 | function process1(source, target, fn){
52 |
53 | var t0 = dateNow(), s, i = length;
54 |
55 | while (i--) {
56 | target[i] = fn(source[i]);
57 | }
58 | tims[1].push(dateNow()-t0);
59 | // print(target[i]);
60 | }
61 |
62 | function process2(source, target, fn){
63 |
64 | var t0 = dateNow(), body = "";
65 |
66 | body += "var i = " + length + ";";
67 | body += "while (i--) { t[i] = f(s[i]);}";
68 | Function("s", "t", "f", body)(source, target, fn);
69 | // print (fn); print (body);
70 |
71 | tims[2].push(dateNow()-t0);
72 | // print(uneval(target));
73 | }
74 |
75 | function process3(source, target, fn){
76 |
77 | var t0 = dateNow(), body = "", fBody = fnBody(fn);
78 |
79 | body += "var s, i = " + length + ";";
80 | body += "while (i--) { s = source[i]; t[i] = " + fBody + "}";
81 | Function("s", "t", body)(source, target);
82 | tims[3].push(dateNow()-t0);
83 | // print(uneval(target));
84 | }
85 |
86 | function process4(source, target, fn){
87 |
88 | var
89 | i, r, len = source.length, t0 = dateNow(),
90 | s = source, t = target,
91 | float32x4 = SIMD.float32x4;
92 |
93 | for (i=0; i") !== -1){
113 | body = source.slice(source.indexOf("=>") + 2).trim();
114 |
115 | } else {
116 | throw "can't handle that";
117 | }
118 |
119 | return body;
120 |
121 | }
122 |
123 |
124 | var i, f0, source, target, size, loops, length, tims;
125 |
126 |
127 | function test(){
128 | putstr("running...");
129 | // putstr(0); i = loops; while (i--){process0(source, target, f0);}
130 | // putstr(1); i = loops; while (i--){process1(source, target, f0);}
131 | // putstr(2); i = loops; while (i--){process2(source, target, f0);}
132 | putstr(3); i = loops; while (i--){process3(source, target, f0);}
133 | putstr(4); i = loops; while (i--){process4(source, target, f0);}
134 | putstr("!")
135 | }
136 |
137 | function result () {
138 | Object.keys(tims).forEach(k => {
139 | var avg = parseFloat((tims[k].reduce((a, b) => a + b, 0) / tims[k].length).toFixed(1));
140 | if (avg > 2){
141 | deb("p%s avg: %s list: %s", k, avg, JSON.stringify(tims[k].map(n => parseFloat(n.toFixed(1)))));
142 | } else {
143 | deb("p%s avg: %s list: %s", k, avg, JSON.stringify(tims[k].map(n => Math.round(n))));
144 | }
145 | });
146 | }
147 |
148 | function reset () {
149 | tims = {"0" : [], "1" : [], "2" : [], "3" : [], "4": [] };
150 | }
151 |
152 |
153 | function init0(psize=128, ploops=10){
154 |
155 | f0 = function f0 (s){return (s === 1 || s === 2 || s === 4) ? 255 : 0;};
156 |
157 | size = psize; loops = ploops; length = size * size;
158 | source = new Uint8ClampedArray(length);
159 | target = new Uint8ClampedArray(length);
160 |
161 | print();
162 | deb("Testing %s full iterations over Uint8ClampedArray of length: ", loops, length);
163 | deb("running func: %s", decompileBody(f0));
164 |
165 | i = length;
166 | while (i--){source[i] = ~~(Math.random() * 5);}
167 | deb("... source array randomized");
168 | print();
169 |
170 | }
171 |
172 | // reset();
173 | // init0(512, 30);
174 | // test();
175 | // print();
176 | // result();
177 | // print();
178 |
179 | function init1(psize=128, ploops=10){
180 |
181 | f0 = function f0 (s){return Math.sqrt(s);};
182 |
183 | size = psize; loops = ploops; length = size * size;
184 | source = new Float32Array(length);
185 | target = new Float32Array(length);
186 |
187 | print();
188 | deb("Testing %s full iterations over Float32Array of length: ", loops, length);
189 | deb("running func: %s", decompileBody(f0));
190 |
191 | i = length;
192 | while (i--){source[i] = Math.random() * 1e10;}
193 | deb("... source array randomized");
194 | print();
195 |
196 | // print(uneval(source));
197 |
198 | }
199 |
200 | reset();
201 | init1(512, 20);
202 | test();
203 | print();
204 | result();
205 | print();
206 |
207 | deb("Done");
208 |
209 |
210 |
--------------------------------------------------------------------------------
/source/simulation/ai/hannibal/g.builder.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, evil:true, devel: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals HANNIBAL, uneval */
3 |
4 | /*--------------- GROUP: B U I L D E R ---------------------------------------
5 |
6 | a group to build any buildings
7 |
8 |
9 | tested with 0 A.D. Alpha 18 Rhododactylus
10 | V: 0.1.1, agentx, CGN, Mar, 2015
11 |
12 | */
13 |
14 |
15 | HANNIBAL = (function(H){
16 |
17 | H.extend(H.Groups, {
18 |
19 | "g.builder" : {
20 |
21 | /*
22 | Behaviour:
23 | builds structures until quantity or
24 | builds houses until
25 | try garrison on attack (female, male)
26 | try healing on hurt
27 | dissolve on nothing to do
28 |
29 | */
30 |
31 | active: true, // prepared for init/launch ...
32 | description: "builder", // text field for humans
33 | civilisations: ["*"], //
34 | interval: 5, // call tick() every x ticks, prefer primes here
35 |
36 |
37 | // DSL World scripts
38 |
39 | scripts: {
40 |
41 | launch: function launch (w, config /* building, quantity */) {
42 |
43 | w.deb(" G: launch %s %s", this, uneval(config));
44 |
45 | w.buildings = ["shared", config.building];
46 | w.units = ["exclusive", config.building + " BUILDBY"];
47 |
48 | w.units.size = w.units.size || config.size || 5;
49 | w.buildings.size = w.buildings.size || config.quantity || 1;
50 |
51 | w.nounify("units", "buildings");
52 | w.units.on.request();
53 |
54 |
55 | // a request was successful
56 |
57 | }, assign: function assign (w, item) {
58 |
59 | // w.deb(" G: assign.0: %s, %s", w, item);
60 |
61 | w.nounify("item", item);
62 |
63 | // have too much units, exits
64 | w.units.on
65 | .gt(w.units.count, w.units.size)
66 | .release(w.item)
67 | .exit
68 | ;
69 |
70 | // keep requesting units until size
71 | w.units.on
72 | .member(w.item)
73 | .lt(w.units.count, w.units.size)
74 | .request()
75 | ;
76 |
77 | // the first unit requests structure to build, exits
78 | w.units.on
79 | .member(w.item)
80 | .match(w.units.count, 1)
81 | .match(w.buildings.count, 0)
82 | .buildings.do.request()
83 | .exit
84 | ;
85 |
86 | // got unit, send to repair, exits
87 | w.units.on
88 | .member(w.item)
89 | .gt(w.buildings.count, 0)
90 | .item.do.repair(w.buildings)
91 | .exit
92 | ;
93 |
94 | // got foundation, all units repair, relocate on first, exits
95 | w.buildings.on
96 | .member(w.item)
97 | .match(w.item.foundation)
98 | .units.do.repair(w.item)
99 | .match(w.buildings.count, 1)
100 | .group.do.relocate(w.item.position)
101 | .exit
102 | ;
103 |
104 | // got a building check order next, exits
105 | w.buildings.on
106 | .member(w.item)
107 | .match(!w.item.foundation)
108 | .lt(w.buildings.count, w.buildings.size)
109 | .request()
110 | .exit
111 | ;
112 |
113 | // got a building, check job done, transfers exits
114 | w.buildings.on
115 | .member(w.item)
116 | .match(!w.item.foundation)
117 | .match(w.buildings.count, w.buildings.size)
118 | .units.do.transfer("g.idle")
119 | .group.do.dissolve()
120 | .echo("dissolved %s/%s", w.buildings.count, w.buildings.size)
121 | .exit
122 | ;
123 |
124 |
125 | }, destroy: function destroy (w, item) {
126 |
127 | w.deb(" G: destroy: %s, %s", this, uneval(item));
128 |
129 | w.nounify("item", item);
130 |
131 | // lost unit, request another
132 | w.units.on
133 | .member(w.item)
134 | .request()
135 | ;
136 |
137 | // lost foundation, request another
138 | w.buildings.on
139 | .echo("requesting foundation 00")
140 | .member(w.item)
141 | .echo("requesting foundation 01: %s", w.item.foundation)
142 | .match(w.item.foundation)
143 | .echo("requesting foundation 02")
144 | .request()
145 | ;
146 |
147 |
148 | // there are enemies and gaya
149 |
150 | }, attack: function attack (w, attacker, victim, type, damage){
151 |
152 | w.deb(" G: attack: %s, %s, %s", this, attacker, victim);
153 |
154 | w.nounify("attacker", attacker, "victim", victim);
155 |
156 | // don't care about buildings, exits
157 | w.buildings.on
158 | .member(w.victim)
159 | .exit
160 | ;
161 |
162 | // // avoid loosing unit
163 | // w.units.on
164 | // .echo("############ HEALTH 0 ###############")
165 | // .member(w.item)
166 | // .echo("############ HEALTH 1 ###############")
167 | // .lt(w.item.health, 50)
168 | // .echo("############ HEALTH 2 ###############")
169 | // // .item.do.garrison()
170 | // ;
171 |
172 | }, radio: function radio (w, msg) {
173 |
174 | w.deb(" G: radio: %s, %s secs", w, msg);
175 |
176 |
177 | }, interval: function interval (w, tick, secs) {
178 |
179 | // w.deb(" G: interval: %s, secs: %s, intv: %s", this, secs, this.interval);
180 |
181 | // w.units.on
182 | // .doing("idle")
183 | // .match(w.units.size)
184 | // .group.do.dissolve()
185 | // ;
186 |
187 | // // avoid loosing units
188 | // w.units.on
189 | // .doing("!garrison")
190 | // .doing("!healing")
191 | // .having("health < 30")
192 | // .heal()
193 | // ;
194 |
195 | }
196 |
197 | } // end scripts
198 |
199 | }
200 |
201 | });
202 |
203 | return H; }(HANNIBAL));
204 |
205 |
--------------------------------------------------------------------------------
/source/simulation/ai/hannibal/g.shepherds.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, evil:true, devel: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals HANNIBAL */
3 |
4 | /*--------------- GROUP: S H E P H E R D S ----------------------------------
5 |
6 | a group to generate food from corrals
7 |
8 |
9 | tested with 0 A.D. Alpha 18 Rhododactylus
10 | V: 0.1.1, agentx, CGN, Mar, 2015
11 |
12 | */
13 |
14 |
15 | HANNIBAL = (function(H){
16 |
17 | H.extend(H.Groups, {
18 |
19 | "g.shepherds" : {
20 |
21 | /* Behaviour:
22 | to build a corral
23 | to use corral to breed sheeps (food.meat),
24 | to return gathered meat to dropsite
25 | to shelter from violence (garrison)
26 | to help with nearby repair
27 | */
28 |
29 | // variables available in listener with *this*. All optional
30 | active: true, // ready to init/launch ...
31 | description: "shepherds", // text field for humans
32 | civilisations: ["*"], // lists all supported cics
33 | interval: 10, // call onInterval every x ticks
34 |
35 | // these techs help
36 | technologies: [
37 | "gather_animals_stockbreeding",
38 | ],
39 |
40 | scripts: {
41 |
42 | // game started, something launched this group
43 | launch: function launch (w, config) {
44 |
45 | w.units = ["exclusive", "food.grain GATHEREDBY WITH costs.metal = 0, costs.stone = 0"];
46 | w.corral = ["exclusive", "gaia.fauna.sheep TRAINEDBY"];
47 | w.dropsite = ["shared", "food ACCEPTEDBY"]; //TODO: exclude docks
48 | w.flock = ["exclusive", "gaia.fauna.sheep"];
49 |
50 | w.units.size = 8;
51 | w.corral.size = 1;
52 | w.dropsite.size = 1;
53 | w.flock.size = 100; // infinty
54 |
55 | w.nounify("units", "corral", "dropsite", "flock");
56 |
57 | w.dropsite.on.request();
58 |
59 |
60 | // a request was succesful
61 |
62 | }, assign: function assign (w, item) {
63 |
64 | w.deb(" G: assign: %s, %s", this, item);
65 |
66 | w.nounify("item", item);
67 |
68 | // got dropsite, request unit, exits
69 | w.dropsite.on
70 | .member(w.item)
71 | .units.do.request()
72 | .exit
73 | ;
74 |
75 | // have too much units, release, exits
76 | w.units.on
77 | .gt(w.units.count, w.units.size)
78 | .release(w.item)
79 | .exit
80 | ;
81 |
82 | // keep requesting units until size
83 | w.units.on
84 | .member(w.item)
85 | .lt(w.units.count, w.units.size)
86 | .request()
87 | ;
88 |
89 | // the first unit requests corral, exits
90 | w.units.on
91 | .member(w.item)
92 | .match(w.units.count, 1)
93 | .match(w.corral.count, 0)
94 | .corral.do.request()
95 | .exit
96 | ;
97 |
98 | // got unit let repair/gather, exits
99 | w.units.on
100 | .member(w.item)
101 | .match(w.corral.count, 1)
102 | .item.do.repair(w.corral) // relies on autocontinue
103 | .exit
104 | ;
105 |
106 | // got the corral foundation, update position, all units repair, exits
107 | w.corral.on
108 | .member(w.item)
109 | .match(w.item.foundation)
110 | .units.do.repair(w.item)
111 | .group.do.relocate(w.item.position)
112 | .exit
113 | ;
114 |
115 | // got the corral, request 2 sheeps
116 | w.corral.on
117 | .member(w.item)
118 | .match(!w.item.foundation)
119 | // .flock.do.request({amount: 2, producer: w.corral.first})
120 | .flock.do.request()
121 | .exit
122 | ;
123 |
124 | // got a sheep, gather, exit
125 | w.flock.on
126 | .member(w.item)
127 | .units.do.gather(w.flock)
128 | .exit
129 | ;
130 |
131 |
132 | // resource lost
133 |
134 | }, destroy: function destroy (w, item) {
135 |
136 | w.deb(" G: destroy: %s, %s", this, item);
137 |
138 | w.nounify("item", item);
139 |
140 | // lost unit, request another
141 | w.units.on
142 | .member(w.item)
143 | .request()
144 | ;
145 |
146 | // lost corral, request another
147 | w.corral.on
148 | .member(w.item)
149 | .request()
150 | ;
151 |
152 | // killed sheep, request another
153 | w.flock.on
154 | .member(w.item)
155 | .flock.do.request({producer: w.corral.first})
156 | ;
157 |
158 |
159 | }, attack: function attack (w, attacker, victim, type, damage){
160 |
161 | w.deb(" G: attack: %s, %s, %s", this, attacker, victim);
162 |
163 | w.nounify("attacker", attacker, "victim", victim);
164 |
165 | w.corral.on
166 | .member(w.victim)
167 | .units.on.repair(w.victim)
168 | .echo("corral attack")
169 | ;
170 |
171 |
172 | }, release: function release (w, item) {
173 |
174 | // de-garrison
175 |
176 | w.deb(" G: release.0: %s, %s", this, item);
177 |
178 |
179 | }, radio: function radio (w, source, msg){
180 |
181 | // group radio
182 |
183 | w.deb(" G: %s onBroadcast from: %s, msg: %s", this, source, msg);
184 |
185 |
186 | }, interval: function interval (w, tick, secs){
187 |
188 | // defined by this.interval
189 |
190 | // w.deb(" G: interval: %s, secs: %s, intv: %s", this, secs, this.interval);
191 |
192 | // // send few idle unit to gather, exits
193 | // w.units.on
194 | // .doing("idle")
195 | // .lt(w.units.count, w.units.size)
196 | // .gt(w.units.count, 0)
197 | // .units.on.gather(w.field)
198 | // .exit
199 | // ;
200 |
201 | // // if all idle, release group
202 | // w.units.on
203 | // .doing("idle")
204 | // .match(w.units.count, w.units.size)
205 | // .group.release()
206 | // ;
207 |
208 |
209 | }
210 |
211 |
212 | } // end listener
213 |
214 | }
215 |
216 | });
217 |
218 | return H; }(HANNIBAL));
219 |
220 |
--------------------------------------------------------------------------------
/source/simulation/ai/hannibal/_hannibal.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, todo: true, evil:true, devel: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals HANNIBAL_DEBUG, Engine, API3, print, uneval */
3 |
4 | /*--------------- H A N N I B A L ---------------------------------------------
5 |
6 | This is loaded first by 0 A.D.
7 | Home: https://github.com/noiv/Hannibal/blob/master/README.md
8 |
9 | tested with 0 A.D. Alpha 18 Rhododactylus
10 | V: 0.1.1, agentx, CGN, Mar, 2015
11 |
12 | Credits:
13 |
14 | kmeans:
15 | helper:
16 |
17 | */
18 |
19 | /*
20 | loading sequence:
21 | _debug
22 | _hannibal
23 | _lhelper
24 | _logger
25 | a-z
26 |
27 | */
28 |
29 |
30 | // very first line, enjoy the rest
31 | print("--------: HANNIBAL.MODUL: " + new Date() + " --- ### --- ### --- ### ---\n");
32 |
33 | Engine.IncludeModule("common-api");
34 |
35 | var HANNIBAL = (function() {
36 |
37 | var H = {
38 |
39 | MODULESTART: Date.now(),
40 |
41 | API: API3,
42 | AI: {},
43 | LIB: {},
44 | HTN: {Economy: {}, Helper: {}},
45 | DSL: {Nouns: {}},
46 | Data: {Groups: {}},
47 | Groups: {},
48 | Geometry: {},
49 |
50 | throw: function(){
51 | var
52 | msg = H.format.apply(null, H.toArray(arguments)),
53 | stack = new Error().stack.split("\n").slice(1);
54 | H.deb();
55 | H.deb(msg);
56 | stack.forEach(line => H.deb(" " + line));
57 | throw "\n*\n*";
58 | // game over
59 | H.deboff(true);
60 | },
61 |
62 | extend: function (o){
63 | Array.prototype.slice.call(arguments, 1)
64 | .forEach(e => {Object.keys(e)
65 | .forEach(k => o[k] = e[k]
66 | );});},
67 |
68 | chat: function(id, msg){
69 | Engine.PostCommand(id, {"type": "chat", "message": id + "::" + msg});
70 | },
71 |
72 | };
73 |
74 | /*
75 |
76 | MIXINS,
77 |
78 | */
79 |
80 | // Serializer needs: this.[klass, name, context, imports])
81 | H.LIB.Serializer = function(){};
82 | H.LIB.Serializer.prototype = {
83 | constructor: H.LIB.Serializer,
84 | toString: function(){return H.format("[%s %s:%s]", this.klass || "no klass", this.context.name, this.name || "no name");},
85 | deb: function(){this.context.launcher.deb.apply(this, arguments);},
86 | log: function(){this.deb(" %s: logging", this.name.slice(0,3).toUpperCase());},
87 | logtick: function(){this.deb(" %s: logticking", this.name.slice(0,3).toUpperCase());},
88 | serialize: function(){return {};},
89 | checkDebug: function(what){
90 | return (
91 | !HANNIBAL_DEBUG ? 0 :
92 | !HANNIBAL_DEBUG.bots[this.context.id] ? 0 :
93 | !HANNIBAL_DEBUG.bots[this.context.id][what] ? 0 :
94 | HANNIBAL_DEBUG.bots[this.context.id][what]
95 | );
96 | },
97 | deserialize: function(){return this;},
98 | initialize: function(){return this;},
99 | finalize: function(){return this;},
100 | activate: function(){return this;},
101 | release: function(){
102 | if(!this.context.importer.delete(this)){
103 | this.deb("WARN : Serializer.release: could not release: %s", this);
104 | }
105 | return this;
106 | },
107 | import: function(){
108 | this.context.importer.add(this);
109 | this.imports.forEach(imp => this[imp] = this.context[imp]);
110 | return this;
111 | },
112 | clone: function(context){
113 | context.data[this.klass] = this.serialize();
114 | return new H.LIB[H.noun(this.name)](context);
115 | },
116 | exportJSON: function(){
117 |
118 | var
119 | file, lines, count,
120 | id = this.context.id,
121 | prefix = id + "::";
122 |
123 | function logg(){
124 | print( arguments.length === 0 ?
125 | prefix + "#! append 0 ://\n" :
126 | prefix + "#! append 0 :" + H.format.apply(H, arguments) + "\n"
127 | );
128 | }
129 |
130 | if (
131 | // make sure to run only if in debug and filename and allowed
132 | HANNIBAL_DEBUG &&
133 | HANNIBAL_DEBUG.export &&
134 | HANNIBAL_DEBUG.bots[id].fil
135 | ){
136 |
137 | this.deb("INFO : exporting: %s", this.name);
138 |
139 | file = HANNIBAL_DEBUG.export + this.name + ".export";
140 | file = file.split(":").join("-");
141 | lines = JSON.stringify(this.serialize(), null, " ").split("\n");
142 | count = lines.length;
143 |
144 | this.deb();
145 | this.deb("EXPORT: %s lines, %s", file, count);
146 |
147 | print(H.format("%s#! open 0 %s\n", prefix, file));
148 | logg("// EXPORTED %s at %s", this.name, new Date());
149 | lines.forEach(line => logg(line));
150 | logg("// Export end of %s", this.name);
151 | print(H.format("%s#! close 0\n", prefix));
152 | // print("#! close 0\n");
153 |
154 | this.deb("EXPORT: Done");
155 | this.deb();
156 |
157 | } else {
158 | this.deb("INFO : did not export %s", this.name);
159 |
160 | }
161 |
162 | }
163 | };
164 |
165 | // extends a context
166 | H.LIB.Tools = function(){};
167 | H.LIB.Tools.prototype = {
168 | constructor: H.LIB.Tools,
169 |
170 | /*
171 | this can be any serializer here,
172 | refer using this.context....
173 | */
174 |
175 | query: function(hcq, debug){
176 | return new H.LIB.Query(this.context.culture.store, hcq, debug);
177 | },
178 |
179 | class2name: function(klass){
180 |
181 | var res = new H.LIB.Query(this.context.culture.store, klass + " CONTAIN").filter(node => {
182 | return klass === "civilcentre" ? true : node.name.contains(klass);
183 | });
184 |
185 | if(!res.length){
186 | this.deb("WARN : class2name: civ: %s class: %s no result", this.culture.civ, klass);
187 | } else {
188 | // this.deb(" TOOLS: class2name: klass: %s, name: %s", klass, res[0].name);
189 | }
190 | return res.length ? res[0].name : null;
191 | },
192 |
193 | health: function(list){
194 | H.throw("################# health");
195 | var
196 | ents = this.context.entities,
197 | health = list
198 | .map(id => Math.round(ents[id].hitpoints() / ents[id].maxHitpoints()))
199 | .reduce( (a, b) => a + b, 0);
200 |
201 | this.deb(" TOOLS: health: %s, %s", health, list);
202 |
203 | return health;
204 |
205 | },
206 |
207 |
208 | unitstate: function(id){
209 |
210 | // print("unitstates: " + id);
211 | // this.deb(" CTX: unitstates of id: %s, %s", id, entities[id]._templateName || "no template");
212 | var
213 | ents = this.context.entities,
214 | state = (
215 | ents[id] && ents[id]._entity.unitAIState ?
216 | H.replace(ents[id]._entity.unitAIState.split(".").slice(-1)[0].toLowerCase(), "ing", "") :
217 | undefined
218 | );
219 |
220 | // this.deb(" TOOLS: unitstate: %s, %s", state, id);
221 |
222 | return state;
223 |
224 | },
225 |
226 | };
227 |
228 | return H;}());
229 |
--------------------------------------------------------------------------------
/mods/hannibal/README.md:
--------------------------------------------------------------------------------
1 | # Hannibal #
2 |
3 | ## An AI/Bot for 0 A.D. ##
4 |
5 | ### Intro ###
6 |
7 | Hannibal is a new approach to reduce the complexity of programming a bot for 0 A.D., a free, open-source, cross-platform real-time strategy game under development by Wildfire Games. Development started in February 2014 by agentx. This git will be updated once a week until the project technically matured enough to support full git based development.
8 |
9 | ### Features ###
10 |
11 | * a **state machine** to handle game phases, like
12 | village, town, city, attack, defense, reconstruction, etc.
13 |
14 | * a **triple store** to interfere features of cultures, like
15 | who can gather fields, can a healer melee?
16 |
17 | * a **simple query language** to retrieve information from the triple store
18 | "food.grain GATHEREDBY WITH costs.metal = 0, costs.stone = 0, costs.wood = 0 SORT < costs.food"
19 |
20 | * a **plugin system** describing the behavior of groups of units
21 | (grain-picker, hunter, warrior, guerrilla, miner, etc)
22 |
23 | * a **domain specific language** used for the plugins
24 | to allow non programmer to define a group's behavior
25 |
26 | * an **economy model** with an order queue, a cost analyzer and
27 | a simple statistic module providing metrics based on resource flows.
28 |
29 | * a **HTN PLanner** to calculate economic development and
30 | attack strategies
31 |
32 | ### Try Out ###
33 |
34 | **Prerequisites**
35 |
36 | * Locate \binaries\data\mods\public\ folder within 0 A.D. installation
37 | * Create \simulation\ai\hannibal within \public
38 | * Extract [all files](https://github.com/noiv/Hannibal/archive/master.zip) into \hannibal keeping directory structure intact
39 |
40 | **Play**
41 |
42 | * Start 0 A.D., select single player new game, select Hannibal as bot
43 |
44 | **Test**
45 |
46 | * Copy the maps to your [map folder](http://trac.wildfiregames.com/wiki/GameDataPaths)
47 | * start 0 A.D. with params: -quickstart -autostart=aitest03 -autostart-ai=1:hannibal
48 |
49 | **HTML Data Explorer**
50 |
51 | * [Web Interface](http://noiv.pythonanywhere.com/agentx/0ad/explorer/hannibal.html)
52 |
53 | ### Testing ###
54 |
55 | Hannibal extensively logs against standard output until switched off in config.js. On Windows best seen using [DebugView](http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx) with option carriage returns unforced.
56 |
57 | ### Progress ###
58 |
59 | * The [web interface](http://noiv.pythonanywhere.com/agentx/0ad/explorer/hannibal.html) aka explorer generates basic plans
60 | * Added data browsing to explorer
61 |
62 | ### Roadmap ###
63 |
64 | **A17**
65 |
66 | * Saved games, given engine support ([cancelled](http://trac.wildfiregames.com/ticket/2495#comment:15), for the time beeing)
67 | * Shared, dynamic and exclusive buildings
68 | * plan based economy taking resource availability into account
69 | * Advanced map analysis
70 | * Fortified cities (towers, walls?)
71 | * Take advantage of all available technologies
72 | * Basic attack plans and execution
73 |
74 | **A18**
75 |
76 | * Walls, palisades
77 | * Advanced attack plans
78 | * Policies via SWOT analysis
79 |
80 | **A19**
81 |
82 | * Seafaring, naval operation
83 |
84 | ### Technology ###
85 |
86 | * SpiderMonkey 29
87 | * Javascript 1.85 + partially ES6
88 | * FF30+
89 |
90 | ### Useful Ingame Hotkeys ###
91 |
92 | * F11: Enable/disable real-time profiler (toggles through the displays of information)
93 | * F12: Show time elapsed since the beginning of the game
94 | * F2: Take screenshot (in .png format, location is displayed in the top left of the GUI
95 | * Alt + F: Show/hide frame counter (FPS)
96 | * Alt + K: Show the 0 A.D. logo and copyright notice as a watermark for images.
97 | * Alt + G: Hide/show the GUI
98 | * Alt + D: Show/hide developer overlay (with developer options)
99 | * Space: If timewarp mode enabled (in the developer overlay), speed up the game
100 | * Backspace: If timewarp mode enabled (in the developer overlay), go back to an earlier point in the game
101 | * More: http://trac.wildfiregames.com/wiki/HotKeys
102 |
103 | ### Project Links ###
104 |
105 | * [Data Explorer](http://noiv.pythonanywhere.com/agentx/0ad/explorer/hannibal.html)
106 | * [Hannibal @ Trac](http://trac.wildfiregames.com/wiki/HannibalBot)
107 |
108 |
109 | ### Videos ###
110 |
111 | * [Playlist](https://www.youtube.com/playlist?list=PLX5qMUEZ8pAr9fTaVkGStzj1xWWvMHV2e)
112 |
113 | * [](http://www.youtube.com/watch?v=i-bJwUk_obk) Grainpicker groups
114 |
115 | ### Further Readings and Links ###
116 |
117 | * [0 A.D. - Home](http://play0ad.com/)
118 | * [0 A.D. - Wikipedia](http://en.wikipedia.org/wiki/0_A.D._%28video_game%29)
119 | * [pyhop - Python Planner](https://bitbucket.org/dananau/pyhop)
120 | * [SHOP - Algo](http://www.cs.umd.edu/projects/shop/)
121 |
122 | ### Literature ###
123 |
124 | * [Artificial Intelligence: A Modern Approach](http://books.google.de/books?id=8jZBksh-bUMC)
125 | Stuart Jonathan Russell, Peter Norvig
126 |
127 | * [A review of computational intelligence in RTS games](http://www.lcc.uma.es/~ccottap/papers/lara13review.pdf)
128 | Raul Lara-Cabrera, Carlos Cotta, Antonio J. Fernandez-Leiva
129 |
130 | * [Planning with Hierarchical Task Networks in Video Games](http://icaps07-satellite.icaps-conference.org/workshop8/Planning%20with%20Hierarchical%20Task%20Networks%20in%20Video%20Games.pdf)
131 | John-Paul Kelly, Adi Botea, Sven Koenig
132 |
133 | * [A HTN Planner For A Real-Time Strategy Game](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.406.8722&rep=rep1&type=pdf)
134 | Jasper Laagland
135 |
136 | * [Wall Building in RTS Games](www.cse.lehigh.edu/~munoz/CSE497/classes/Patrick2.ppt)
137 | Patrick Schmid
138 |
139 | ## License ##
140 |
141 | tbd
142 |
143 |
--------------------------------------------------------------------------------
/source/simulation/ai/hannibal/g.supplier.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, evil:true, devel: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals HANNIBAL, deb, uneval */
3 |
4 | /*--------------- GROUP: S U P P L I E R -------------------------------------
5 |
6 | a group gather wood, stone or metal
7 |
8 |
9 | tested with 0 A.D. Alpha 18 Rhododactylus
10 | V: 0.1.1, agentx, CGN, Mar, 2015
11 |
12 | */
13 |
14 |
15 | HANNIBAL = (function(H){
16 |
17 | H.extend(H.Groups, {
18 |
19 | "g.supplier" : {
20 |
21 | /*
22 | a group to gather many kind of resources (wood, food.fruit, etc.)
23 |
24 | Behaviour:
25 | to request a resource list
26 | to dissolve on empty list
27 | to build a dropsite if needed
28 | to stay calm
29 |
30 | */
31 |
32 | active: true, // prepared for init/launch ...
33 | description: "supplier", // text field for humans
34 | civilisations: ["*"], //
35 | interval: 3, // call scripts.interval every x ticks
36 |
37 | technologies: [ // these techs help
38 | "gather.lumbering.ironaxes",
39 | "gather.capacity.wheelbarrow",
40 | "gather.wicker.baskets", // ?? only fruits
41 | "gather.mining.wedgemallet",
42 | "gather.mining.silvermining",
43 | "gather.mining.shaftmining",
44 | ],
45 |
46 | scripts: {
47 |
48 | launch: function launch (w, config /* supply, size, quantity */){
49 |
50 | var supply = config.supply;
51 |
52 | w.deb(" G: onlaunch %s, %s", this, uneval(config));
53 |
54 | w.resources = ["resource", supply];
55 |
56 | w.data = [
57 | ["metal" , "exclusive", "metal.ore GATHEREDBY", "shared", "metal ACCEPTEDBY", 1, 10],
58 | ["stone" , "exclusive", "stone.rock GATHEREDBY", "shared", "stone ACCEPTEDBY", 1, 10],
59 | ["wood" , "exclusive", "wood.tree GATHEREDBY", "shared", "wood ACCEPTEDBY", 10, 10],
60 | ["food.fruit", "exclusive", "food.fruit GATHEREDBY", "shared", "food ACCEPTEDBY", 1, 5],
61 | ["food.meat" , "exclusive", "food.meat GATHEREDBY", "shared", "food ACCEPTEDBY", 1, 2],
62 | ];
63 |
64 | w.units = w.data.find(d => d[0] === supply).slice(1, 3);
65 | w.dropsite = w.data.find(d => d[0] === supply).slice(3, 5);
66 | w.resources.size = w.data.find(d => d[0] === supply)[5];
67 | w.units.size = w.data.find(d => d[0] === supply)[6];
68 | w.dropsite.size = 1;
69 |
70 | w.nounify("units", "resources", "dropsite");
71 |
72 | w.resources.on.request(w.resources.size); // may get less
73 |
74 |
75 | }, assign: function assign (w, item) {
76 |
77 | w.deb(" G: assign: %s, %s", this, item);
78 |
79 | w.nounify("item", item);
80 |
81 | // got empty resource, transfer units to idle, dissolve group
82 | w.resources.on
83 | .member(w.item)
84 | .match(w.resources.count, 0)
85 | .units.do.transfer("g.idle")
86 | .group.do.dissolve()
87 | .exit
88 | ;
89 |
90 | // got initial resources, relocate, request unit, exits
91 | w.resources.on
92 | .member(w.item)
93 | .match(w.units.count, 0)
94 | .group.do.relocate(w.resources.position)
95 | .units.do.request()
96 | .exit
97 | ;
98 |
99 | // have too many units, transfer, exits
100 | w.units.on
101 | .gt(w.units.count, w.units.size)
102 | .item.do.transfer("g.idle")
103 | .exit
104 | ;
105 |
106 | // got initial unit, request dropsite
107 | w.units.on
108 | .member(w.item)
109 | .match(w.units.count, 1)
110 | .match(w.dropsite.count, 0)
111 | .dropsite.do.request({distance: 10})
112 | ;
113 |
114 | // got initial dropsite foundation, relocate, units repair
115 | w.dropsite.on
116 | .member(w.item)
117 | .match(w.item.foundation)
118 | .group.do.relocate(w.dropsite.position)
119 | .units.do.repair(w.dropsite)
120 | ;
121 |
122 | // got dropsite, relocate, units gather
123 | w.dropsite.on
124 | .member(w.item)
125 | .match(!w.item.foundation)
126 | .group.do.relocate(w.dropsite.position)
127 | .units.do.gather(w.resources)
128 | ;
129 |
130 | // got unit, keep requesting until size
131 | w.units.on
132 | .member(w.item)
133 | .lt(w.units.count, w.units.size)
134 | .request()
135 | ;
136 |
137 | // got unit, let gather on next resource
138 | w.units.on
139 | .member(w.item)
140 | .resources.do.rotate()
141 | .item.do.gather(w.resources)
142 | ;
143 |
144 | // got another resource, relocate, all units gather
145 | w.resources.on
146 | .member(w.item)
147 | .group.do.relocate(w.dropsite.position)
148 | .units.do.gather(w.resources)
149 | ;
150 |
151 |
152 | }, destroy: function destroy (w, item) {
153 |
154 | w.deb(" G: destroy: %s, %s", this, item);
155 |
156 | w.nounify("item", item);
157 |
158 | // lost unit, request another
159 | w.units.on
160 | .member(w.item)
161 | .request()
162 | ;
163 |
164 | // lost dropsite, request another
165 | w.dropsite.on
166 | .member(w.item)
167 | .request()
168 | ;
169 |
170 |
171 | }, attack: function attack (w, attacker, victim, type, damage){
172 |
173 | w.deb(" G: attack: %s, %s, %s", this, attacker, victim);
174 |
175 | w.nounify("attacker", attacker, "victim", victim);
176 |
177 |
178 | }, radio: function radio (w, msg) {
179 |
180 | w.deb(" G: %s radio %s, %s", this, msg);
181 |
182 |
183 | }, interval: function interval(w, secs, tick) {
184 |
185 | // w.deb(" G: interval: %s, secs: %s, intv: %s", this, secs, this.interval);
186 |
187 | // // test, transfer units, exits
188 | // w.units.on
189 | // .transfer("g.idle")
190 | // .echo("DID IDLE")
191 | // .exit
192 | // ;
193 |
194 | // run out of resources, request more, exits
195 | w.resources.on
196 | .refresh()
197 | .match(w.resources.count, 0)
198 | .echo("interval.match: have %s resources", w.resources.count)
199 | .request()
200 | .exit
201 | ;
202 |
203 | // idle units should gather
204 | w.units.on
205 | .doing("idle")
206 | .gt(w.units.count, 0)
207 | .gather(w.resources)
208 | .echo("interval.idle, have %s resources", w.resources.count)
209 | ;
210 |
211 | }
212 |
213 |
214 | } // end script
215 |
216 | }
217 |
218 | });
219 |
220 | return H; }(HANNIBAL));
221 |
222 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Hannibal #
2 |
3 | ## An AI/Bot for 0 A.D. ##
4 |
5 | ### Intro ###
6 |
7 | Hannibal is a new approach to reduce the complexity of programming a bot for 0 A.D., a free, open-source, cross-platform real-time strategy game under development by Wildfire Games. Hannibal tackles the complexity of an RTS with hundreds of units by organizing them into a society of autonomous groups, each with its specific task.
8 |
9 | ### Blog ###
10 |
11 | Read development notes at [agentx.svbtle.com](http://agentx.svbtle.com/)
12 |
13 | ### Features ###
14 |
15 | * A **triple store** to interfere features of cultures, like
16 | who can gather fields, can a healer melee?
17 |
18 | * A **query language** to retrieve information as a set of nodes from the triple store
19 | "food.grain GATHEREDBY WITH costs.metal = 0, costs.stone = 0, costs.wood = 0 SORT < costs.food"
20 |
21 | * A **group system** describing the behavior of groups of units
22 | (grain-picker, hunter, warrior, guerrilla, miner, etc)
23 |
24 | * A **domain specific language** called group script, based on JavaScript
25 | method and property chaining to define a fluent interface and describe
26 | the behaviour of groups in a near natural language
27 |
28 | * An **economy model** with an order queue, a cost analyzer and
29 | a statistic module providing metrics based on resource flows with trends and forecast.
30 |
31 | * A **HTN Planner** to calculate economic development, advancing to next phase
32 | and planning attack strategies
33 |
34 | * **Map Analysis & Pathfinder** for intelligent and adequate game play
35 |
36 | ### Try Out ###
37 |
38 | **Prerequisites**
39 |
40 | * Check [game paths](http://trac.wildfiregames.com/wiki/GameDataPaths) for your system
41 | * Locate folder \binaries\data\mods\ within 0 A.D. installation
42 | * Copy the zip + readme from latest [release](https://github.com/agentx-cgn/Hannibal/releases) into mods/
43 |
44 | **Play**
45 |
46 | * Start 0 A.D.,
47 | * Open mod selection and activate Hannibal
48 | * Select single player/new game, and choose Hannibal as bot
49 | * Choose a difficulty from the settings dialog
50 |
51 | **Test & Development**
52 |
53 | * Start 0 A.D. with params: -quickstart -autostart=aitest03 -autostart-ai=1:hannibal
54 | * Customize launcher.py and launch 0 A.D. from commadline (Linux only)
55 |
56 | **HTML Data Explorer**
57 |
58 | * [Web Interface](http://noiv.pythonanywhere.com/agentx/0ad/explorer/hannibal.html)
59 |
60 | ### Testing ###
61 |
62 | Hannibal extensively logs against standard output until switched off in config.js. On Windows best seen using [DebugView](http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx) with option carriage returns unforced.
63 |
64 | ### Progress ###
65 |
66 | * The [web interface](http://noiv.pythonanywhere.com/agentx/0ad/explorer/hannibal.html) aka explorer generates basic plans
67 | * Added data browsing to explorer
68 |
69 | ### Roadmap ###
70 |
71 | **A18**
72 |
73 | * Saved games, given engine support ([cancelled](http://trac.wildfiregames.com/ticket/2495#comment:15), for the time being)
74 | * Shared, dynamic and exclusive buildings
75 | * Plan based economy, taking resource availability into account
76 | * Advanced map analysis
77 | * Fortified cities (towers, walls?)
78 | * Take advantage of all available technologies
79 | * Basic attack plans and execution
80 |
81 | **A19**
82 |
83 | * Walls, palisades
84 | * Advanced attack plans
85 | * Policies via SWOT analysis
86 |
87 | **A20**
88 |
89 | * Seafaring, naval operation
90 |
91 | ### Technology ###
92 |
93 | * SpiderMonkey 29/31
94 | * Javascript 1.85 + partially ES6
95 | * FF30+
96 |
97 | ### Useful Ingame Hotkeys ###
98 |
99 | * F11: Enable/disable real-time profiler (toggles through the displays of information)
100 | * F12: Show time elapsed since the beginning of the game
101 | * F2: Take screenshot (in .png format, location is displayed in the top left of the GUI
102 | * Alt + F: Show/hide frame counter (FPS)
103 | * Alt + K: Show the 0 A.D. logo and copyright notice as a watermark for images.
104 | * Alt + G: Hide/show the GUI
105 | * Alt + D: Show/hide developer overlay (with developer options)
106 | * Space: If timewarp mode enabled (in the developer overlay), speed up the game
107 | * Backspace: If timewarp mode enabled (in the developer overlay), go back to an earlier point in the game
108 | * More: http://trac.wildfiregames.com/wiki/HotKeys
109 |
110 | ### Project Links ###
111 |
112 | * [Data Explorer](http://noiv.pythonanywhere.com/agentx/0ad/explorer/hannibal.html)
113 | * [Hannibal @ Trac](http://trac.wildfiregames.com/wiki/HannibalBot)
114 |
115 |
116 | ### Videos ###
117 |
118 | * [Playlist](https://www.youtube.com/playlist?list=PLX5qMUEZ8pAr9fTaVkGStzj1xWWvMHV2e)
119 |
120 | * [](http://www.youtube.com/watch?v=i-bJwUk_obk) Grainpicker groups
121 |
122 | ### Further Readings and Links ###
123 |
124 | * [0 A.D. - Home](http://play0ad.com/)
125 | * [0 A.D. - Wikipedia](http://en.wikipedia.org/wiki/0_A.D._%28video_game%29)
126 | * [pyhop - Python Planner](https://bitbucket.org/dananau/pyhop)
127 | * [SHOP - Algo](http://www.cs.umd.edu/projects/shop/)
128 |
129 | ### Literature ###
130 |
131 | * [Artificial Intelligence: A Modern Approach](http://books.google.de/books?id=8jZBksh-bUMC)
132 | Stuart Jonathan Russell, Peter Norvig
133 |
134 | * [A review of computational intelligence in RTS games](http://www.lcc.uma.es/~ccottap/papers/lara13review.pdf)
135 | Raul Lara-Cabrera, Carlos Cotta, Antonio J. Fernandez-Leiva
136 |
137 | * [Planning with Hierarchical Task Networks in Video Games](http://icaps07-satellite.icaps-conference.org/workshop8/Planning%20with%20Hierarchical%20Task%20Networks%20in%20Video%20Games.pdf)
138 | John-Paul Kelly, Adi Botea, Sven Koenig
139 |
140 | * [A HTN Planner For A Real-Time Strategy Game](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.406.8722&rep=rep1&type=pdf)
141 | Jasper Laagland
142 |
143 | * [Wall Building in RTS Games](http://www.cse.lehigh.edu/~munoz/CSE497/classes/Patrick2.ppt)
144 | Patrick Schmid
145 |
146 | ## License ##
147 |
148 | tbd
149 |
150 |
195 |
--------------------------------------------------------------------------------
/source/simulation/ai/hannibal/htn-planner.js:
--------------------------------------------------------------------------------
1 | /*jslint bitwise: true, browser: true, todo: true, evil:true, devel: true, debug: true, nomen: true, plusplus: true, sloppy: true, vars: true, white: true, indent: 2 */
2 | /*globals HANNIBAL */
3 |
4 | /*--------------- P L A N N E R -----------------------------------------------
5 |
6 | Simple HTN Planner based on Pyhop/SHOP written by Dana S. Nau
7 | https://bitbucket.org/dananau/pyhop
8 | http://www.cs.umd.edu/projects/shop/
9 |
10 | tested with 0 A.D. Alpha 18 Rhododactylus
11 | V: 0.1.1, agentx, CGN, Mar, 2015
12 |
13 | */
14 |
15 | HANNIBAL = (function(H){
16 |
17 | var
18 | // simple templates
19 | fmt = function (){
20 | var c=0, a=Array.prototype.slice.call(arguments); a.push("");
21 | return a[0].split("%s").map(function(t){return t + a.slice(1)[c++];}).join('');
22 | },
23 | // JSON w/o quotes
24 | pritj = function(o){return JSON.stringify(o).split('"').join("");},
25 | // prettyfies a task
26 | pritt = function(task){return fmt("[%s: %s]", task[0].name, task.slice(1).join(", "));};
27 |
28 | H.HTN.Planner = function Planner(config) {
29 |
30 | var defaults = {
31 | name: "unknown", // log indentifier
32 | logstack: [], // collect messages
33 | verbose: 0, // defines a log threshhold
34 | msecs: 0, // duration of seekPlan
35 | depth: 0, // current search depth
36 | iterations: 0, // a counter
37 | maxDepth: 200, // seeking stops here
38 | maxIterations: 300, // seeing stops here
39 | tree: null, //
40 | // domain: null, // defines the domain within an app
41 | // noInitialize: false, // suppress domain initialization
42 | methods: null, // object holding the methods
43 | operators: null, // object holding the operators
44 | tasks: null, // the tasks given on first call
45 | state: null, // the state given on first call
46 | operations: null // the final task list
47 | };
48 |
49 | H.extend(this, defaults, config || {});
50 |
51 | // if (this.domain.initialize && !this.noInitialize){this.domain.initialize(this);}
52 | // this.methods = this.domain.methods;
53 | // this.operators = this.domain.operators;
54 |
55 | };
56 |
57 | H.HTN.Planner.prototype = {
58 | constructor: H.HTN.Planner,
59 | log: function(verbose, msg){
60 | if (verbose <= this.verbose){
61 | this.logstack.push({
62 | v: verbose,
63 | d: this.depth,
64 | m: typeof msg !== "function" ? msg : msg(),
65 | now: Date.now()
66 | });
67 | }
68 | },
69 | plan: function plan (state, tasks){
70 |
71 | var t0, t1;
72 |
73 | this.error = undefined;
74 |
75 | this.state = state;
76 | this.tasks = tasks;
77 |
78 | this.msecs = 0;
79 | this.depth = 0;
80 | this.stack = [];
81 | this.logstack = [];
82 | this.iterations = 0;
83 | this.log(1, fmt("START: tasks: %s, state: %s", tasks.map(pritt), pritj(state)));
84 |
85 | this.stack.push([state, tasks, [], this.depth]);
86 |
87 | t0 = Date.now();
88 | [this.operations, this.result, this.error] = this.seekPlan();
89 | t1 = Date.now();
90 |
91 | this.msecs = t1 - t0;
92 |
93 | if (this.error){
94 | this.log(0, fmt("FAILED: %s, plan: %s ops, depth: %s, iter: %s, msecs: %s",
95 | this.error, this.operations.length, this.depth, this.iterations, this.msecs));
96 |
97 | } else if (!this.operations.length) {
98 | this.log(0, fmt("FAILED: %s, plan: %s ops, depth: %s, iter: %s, msecs: %s",
99 | "no solution found", this.operations.length, this.depth, this.iterations, this.msecs));
100 |
101 | } else {
102 | this.operations.unshift([0, "start"]);
103 | this.operations.push([this.result.stamp, "finish"]);
104 | this.log(0, fmt("SUCCESS: plan: %s ops, depth: %s, iter: %s, msecs: %s",
105 | this.operations.length, this.depth, this.iterations, this.msecs));
106 |
107 | }
108 |
109 | return this;
110 |
111 | },
112 | seekPlan: function seekPlan () {
113 |
114 | var state, tasks, plan, depth, exit, stamp,
115 | task, name, result, newstate, newPlan, subtasks, newTasks;
116 |
117 | while (this.stack.length) {
118 |
119 | [state, tasks, plan, depth] = this.stack.pop();
120 |
121 | this.depth = depth > this.depth ? depth : this.depth; // Math.max(depth, this.depth);
122 | this.iterations += 1;
123 |
124 | exit = (
125 | // prefered outcome
126 | !tasks.length ? [plan, state, undefined] :
127 | this.depth > this.maxDepth ? [plan, state, fmt("too deep ( %s )", this.depth)] :
128 | this.iterations > this.maxIterations ? [plan, state, fmt("too many iterations ( %s )", this.iterations)] :
129 | null
130 | );
131 |
132 | if (exit){return exit;}
133 |
134 | task = tasks[0];
135 | name = task[0].name;
136 | stamp = state.stamp;
137 |
138 | if (name === "ANY") {
139 |
140 | result = this.seekAnyMethod(state, tasks, plan, ++this.depth);
141 | if (result){this.stack.push(result);}
142 |
143 | } else if (this.operators.hasOwnProperty(name)){
144 |
145 | newstate = task[0](state.clone(), task[1] || undefined, task[2] || undefined, task[3] || undefined);
146 |
147 | if (newstate){
148 | this.log(2, () => "OP: " + pritt(task));
149 | newPlan = plan.concat([[stamp, task[0].name, task[1], task[2], task[3]]]);
150 | this.stack.push([newstate, tasks.slice(1), newPlan, ++this.depth]);
151 | }
152 |
153 | } else if (this.methods.hasOwnProperty(name)){
154 |
155 | subtasks = task[0](state, task[1] || undefined, task[2] || undefined, task[3] || undefined);
156 |
157 | if (subtasks){
158 | this.log(2, () => "MT: " + pritt(task));
159 | newTasks = subtasks.concat(tasks.slice(1));
160 | this.stack.push([state, newTasks, plan, ++this.depth]);
161 | }
162 |
163 | }
164 |
165 | }
166 |
167 | return (
168 | // if task was valid
169 | depth > 1 ? [plan, state, undefined] :
170 | // if valid solution
171 | plan ? [plan, state, undefined] :
172 | // first task not valid
173 | [plan, state, fmt("no solution for task: [%s, %s], depth: %s", name, tasks[0][1], depth)]
174 | );
175 |
176 | },
177 | seekAnyMethod: function seekAnyMethod (state, tasks, plan, depth){
178 |
179 | var anyTasks = tasks[0][1], anyPointer = 0, anyTask,
180 | i, len, subtasks, anySubTasks, newTasks,
181 | pushUnique = H.HTN.Helper.pushUnique;
182 |
183 | while ((anyTask = anyTasks[anyPointer++])) {
184 |
185 | this.log(2, () => fmt("AT: (%s/%s) [%s: %s, %s, %s]", anyPointer, anyTasks.length, anyTask[0].name, anyTask[1], anyTask[2]||'', anyTask[3]||''));
186 |
187 | this.iterations += 1;
188 | subtasks = anyTask[0](state, anyTask[1], anyTask[2]);
189 |
190 | if(subtasks){
191 |
192 | if (subtasks[0][0].name === "ANY"){
193 | depth += 1;
194 | anySubTasks = subtasks[0][1];
195 | len = anySubTasks.length;
196 | for (i=0; i