{"id":630,"date":"2016-05-25T13:33:54","date_gmt":"2016-05-25T17:33:54","guid":{"rendered":"http:\/\/blog.bulletpattern.com\/?p=630"},"modified":"2016-05-25T13:33:54","modified_gmt":"2016-05-25T17:33:54","slug":"scripting-moba-ai","status":"publish","type":"post","link":"http:\/\/blog.bulletpattern.com\/?p=630","title":{"rendered":"Scripting MOBA AI"},"content":{"rendered":"<p>I have recently gone back to our MOBA, <em>Adventure Time Battle Party<\/em> and it reminded me about how I wanted to write up a post about the AI. There were a number of important lessons we learned and I wanted to share them.<\/p>\n<p>&nbsp;<\/p>\n<h3>Ground Rules<\/h3>\n<p>We didn&#8217;t have much time to pursue, what I would consider, strong AI on this project. However, I <em>love<\/em> working with AI so I made time on weekends to work on this. So to be economical,\u00a0our explicit goal for AI in <em>Battle Party<\/em> was &#8220;don&#8217;t be\u00a0dumb&#8221;, which is very different from &#8220;be\u00a0smart&#8221;. Also, my approach to AI is rooted in &#8220;make it fun&#8221; more than an academic approach to AI, where you might be trying to emulate an algorithm or advanced behavior.<\/p>\n<p>Also, AI was an aspect a number of our team wanted to learn. To keep things simple, I set up and simple state-based AI system and wrote a number of tools for newbie\u00a0AI scripters to use.<\/p>\n<p>One thing that&#8217;s important to me is: don&#8217;t cheat. I try as much as possible to not leverage any data a real player would not have. I don&#8217;t want to rely on letting the computer know every last detail of a player&#8217;s state or inputs and make decisions based on that knowledge. There are times when the CPU overhead of certain checks are just too expensive, and in that case, I allow myself to cheat.<\/p>\n<p>&nbsp;<\/p>\n<h3>The &#8220;Danger&#8221; Measurement<\/h3>\n<p>The backbone of the system was a collection of systems that produced a &#8220;danger&#8221; value. This produced a simple integer that allowed the scripters\u00a0to make decisions. This system took into account:<\/p>\n<ul>\n<li>The number of alive players<\/li>\n<li>The number of nearby (&#8220;nearby&#8221; being 1.5 screens IIRC) enemy\u00a0players<\/li>\n<li>The number of unaccounted players on the mini-map<\/li>\n<li>The number of nearby enemy minions<\/li>\n<li>How far ally\/enemy minions are pushed. This was a +\/- value depending on where the minions were pushed relative to the mid-point of the map.<\/li>\n<li>A queue of when the AI sees a player use powers. This is a good example of not cheating. Instead of looking at the player\u00a0cooldowns, when the AI sees an onscreen player\u00a0use a power, it lowers the danger value by a specific\u00a0value\u00a0for a certain time. Higher value powers lower the danger value more.<\/li>\n<li>The powers currently\u00a0available\u00a0to the AI<\/li>\n<li>Player\/AI health values<\/li>\n<li>Player\/AI buffs<\/li>\n<li>Being close to an ally\/enemy tower<\/li>\n<li>Some other items as well.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h3>Basic States<\/h3>\n<p>The basics were patrol, attack, and flee. Since the more danger there was, the more an AI champ would flee, the back and forth between and attack and flee states\u00a0created some good dive in\/dive out behaviors and some pretty good kiting. If the danger value got too high, the AI would flee to allies, health pick-ups, towers, or the base. If the AI had a power that created movement, it would use this power to run away if pursued (i.e. in a flee state and a champion was close).<\/p>\n<p>If the AI didn&#8217;t have a champ to attack, it would push minions, help allies, capture altars, patrol, or do special actions. more on social actions later.<\/p>\n<p>&nbsp;<\/p>\n<h3>Listen for Events<\/h3>\n<p>Loads\u00a0of events can trigger a decision to change the state \u2013 taking damage, a tower being attacked, the base being attacked, an ally champion being attacked, the danger value changing significantly, altars being open or captured, etc. Many events. Lots.<\/p>\n<p>&nbsp;<\/p>\n<h3>Special Actions<\/h3>\n<p>In my experience, I have found you can throw in 95% of random behaviors and 5% of really smart decisions and player&#8217;s will think your AI is a genius. With this in mind, I did a couple of one-off, hard-scripted behaviors to use occasionally.<\/p>\n<ul>\n<li>Tower Dive \u2013 Very rarely, when the danger rating was very low and a player was hiding under a tower, the AI would tower dive.\u00a0During this brief time, it would just go HAM and ignore the danger rating and try to kill the player.<\/li>\n<li>Ambush \u2013 If the Ai had nothing better to do, it would hide in the brush for a time and wait for players.<\/li>\n<li>Dodge \u2013 If the player used an aimed power and the AI had a power that could be used to dodge, it would do so.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h3>Other Tools<\/h3>\n<p>I wrote a number of tools to facilitate other scripters. Things such as &#8220;do I have a clear shot to my target?&#8221; This mean you could fire a projectile without being blocked by minions. There was a similar check that informed the danger rating on the AI, &#8220;does the player have a clear shot to me?<\/p>\n<p>There were quite a few utilities\u00a0like &#8220;find closest safe point&#8221;, &#8220;are targets in range of my powers&#8221;, etc.<\/p>\n<p>&nbsp;<\/p>\n<h3>Leading the Target<\/h3>\n<p>One of the biggest lessons we learned was about the value of trying to lead the target when aiming powers. Every scripture&#8217;s\u00a0first instinct was to try to predict player movement and fire\u00a0where the player would be in the future. This might be good for a game where player velocity cannot be changed instantly, like FPS or racing game, but in a MOBA a player can &#8220;juke&#8221; (i.e. dodge) in any direction instantly, so\u00a0the value of prediction is\u00a0greatly decreased. Experienced players will nearly always dodge. We found that it&#8217;s statistically more likely to hit player just aiming randomly in a radius\u00a0around the player than trying to lead their current movement.<\/p>\n<p>&nbsp;<\/p>\n<h3>Conclusion<\/h3>\n<p>The AI turned out pretty good\u00a0considered the limited resources we had. Quite a few people got to try their hand at scripting AI and they only needed to worry about strategies around the character&#8217;s power set, instead of learning about managing behaviors states &amp; calculating distances.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I have recently gone back to our MOBA, Adventure Time Battle Party and it reminded me about how I wanted to write up a post about the AI. There were a number of important lessons we learned and I wanted to share them. &nbsp; Ground Rules We didn&#8217;t have much time to pursue, what I [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-630","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"http:\/\/blog.bulletpattern.com\/index.php?rest_route=\/wp\/v2\/posts\/630","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/blog.bulletpattern.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.bulletpattern.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.bulletpattern.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.bulletpattern.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=630"}],"version-history":[{"count":6,"href":"http:\/\/blog.bulletpattern.com\/index.php?rest_route=\/wp\/v2\/posts\/630\/revisions"}],"predecessor-version":[{"id":640,"href":"http:\/\/blog.bulletpattern.com\/index.php?rest_route=\/wp\/v2\/posts\/630\/revisions\/640"}],"wp:attachment":[{"href":"http:\/\/blog.bulletpattern.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=630"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.bulletpattern.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=630"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.bulletpattern.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=630"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}