[Question]
  [
## Introduction
In the strategy game Starcraft 2, there are three "races" to choose from: Terran, Zerg, and Protoss. In this challenge we will be focusing on the Protoss and the iconic phrase "You must construct additional pylons!" This message is stated when you run out of supply to build your army. So, to help out the Starcraft community, you must write a program or function that tells players exactly how many pylons they need.
## The Challenge
You will be given an input of a string consisting of a single integer `N` and space-separated list of units. `N` will always be zero or positive, and the list of units will always have one or more valid units. `N` represents the amount of pylons the player currently has. Your job is to calculate if the amount of pylons that the player has is enough to build the units. Your program or function must output/return a truthy value if there is enough supply, or if there is not enough supply you must output `You must construct ZZZ additional pylons` where `ZZZ` is the amount of pylons needed to build the units. Note that `pylon(s)` must be plural when needed and unplural when not (`...1 additional pylon!`, `...2 additional pylons!`).
## Protoss Units and Supply Cost
Here is a list of all units and their corresponding supply cost. Pylons provide an additional 8 supply.
```
Unit            Supply Cost
Probe           1
Zealot          2
Sentry          2
Stalker         2
HighTemplar     2
DarkTemplar     2
Immortal        4
Colossus        6
Archon          4
Observer        1
WarpPrism       2
Phoenix         2
MothershipCore  2
VoidRay         4
Oracle          3
Tempest         4
Carrier         6
Mothership      8
```
## Examples WITHOUT Bonuses
```
Input:
   2 Probe Probe Probe Probe Stalker Zealot Carrier Probe Zealot
Output:
   You must construct 1 additional pylon!
Why?
   Adding up the supply costs for all of the units gives 17. The current 2 pylons provide 16 supply, so one more is needed to provide enough for 17.
Input:
   5 Mothership Carrier Probe Tempest HighTemplar
Output:
   true
Why?
   Adding up the units gets 21. The current 5 pylons provide 40 supply, which is plenty enough.
Input:
  0 Mothership Colossus Zealot
Output:
  You must construct 2 additional pylons!
Why?
  Adding the units gets 16. There is no pylons so 2 need to be built to provide enough supply. 
```
## Bonuses
1. Any experienced Starcraft 2 player would know that you need a mothership core before to transform it into a mothership. Also, you can only have one mothership at a time (whether it is an actual mothership or a mothership core). If neither of these conditions are true, output any falsy value. If your program can check to see that only one mothership is active at a time, and that a mothership core is built *before* the actual mothership, take **20%** off your byte count.
2. Little may you know, but nexuses (protoss command centers) actually provide supply too! If your program can add 11 to the maximum supply every time it encounters a nexus in the unit list, take **10%** off your byte count. Note that it does not matter where the Nexus is in the build order, so `0 Probe Nexus` would still return `true`.
## Examples WITH Bonuses
```
Input (Bonus 1):
  3 Mothership Zealot
Output:
  false
Why?
  According to the first bonus, a mothership core has to be built before a mothership.
Input (Bonus 1):
  3 MothershipCore Mothership MothershipCore
Output:
  false
Why?
  According to the first bonus, only one mothership can be built and here there is two (MothershipCore -> Mothership and a second MothershipCore).
Input (Bonus 2):
  0 Probe Nexus Probe
Output:
  true
Why?
  According to the second bonus, nexuses add 11 to the maximum supply, allowing both probes to be built.
Input (Both Bonuses):
  0 Nexus MothershipCore Mothership Carrier
Output:
  You must construct 1 additional pylon.
Why?
  There are no pylons, but the nexus provides 11 supply. The motherships take up 2 and 8, respectively and the carrier takes up 6. You need one more pylon to have enough to provide for all 16 supply.
```
## TL;DR
Input a string consisting of an integer and space-separated unit names (from the table above). Output a truthy value if you can build all of the units with the supply provided by the `N` pylons (the integer in input). Output `You must construct ZZZ additional pylon(s)` if more pylons are needed, where `ZZZ` is the amount of pylons needed. Make sure to make pylons plural if necessary.
This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), so shortest code in bytes (or your language's counting method) wins!
## Leaderboard
Here is a Stack Snippet to generate both a regular leaderboard and an overview of winners by language.
To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:
```
# Language Name, N bytes
```
where `N` is the size of your submission. If you improve your score, you *can* keep old scores in the headline, by striking them through. For instance:
```
# Ruby, <s>104</s> <s>101</s> 96 bytes
```
If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the *last* number in the header:
```
# Perl, 43 + 2 (-p flag) = 45 bytes
```
You can also make the language name a link which will then show up in the leaderboard snippet:
```
# [><>](http://esolangs.org/wiki/Fish), 121 bytes
```
---
```
var QUESTION_ID=69011,OVERRIDE_USER=36670;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?([\d\.]+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
```
```
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
```
```
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>
```
  
[Answer]
# Python 3, 207\*.9 == 186.3 bytes.
Implements the nexus bonus.  
Saved 26 bytes thanks to DSM.  
Saved 2 bytes thanks to Tim Pederick
```
x,*l=input().split()
d=-((int(x)*8-sum((('vexuobcl'+2*'clsuie'+4*'Ratahoiesuhihi').count(q[-3:-1])*(1-12*(q[0]>'w'))or 2)for q in l))//8)
print((1,"You must construct %s additional pylon"%d+'s!'[d<2:])[d>0])
```
[Answer]
# Ruby, 263 - 30% = 184 bytes
```
v=c=k=0
l,a={PeOr:1,ZtSySrHrDrWmPxMe:2,Oe:3,VyIlAnTt:4,CsCr:6,Mp:8,Ns:-11},ARGV.shift
ARGV.map{|u|k+=l[l.keys.grep(/#{q=u[0]+u[-1]}/)[0]];c+=1if q=="Me";v=!0if c!=1&&q=~/M/}
n=k/8.0-a.to_i
p v ?n<0||"You must construct #{n.ceil} additional pylon#{'s'if n>1}!":nil
```
### Usage
`ruby sc.rb 0 Probe Nexus` 
[Answer]
## JavaScript, ~~274~~ ~~265 bytes (no bonuses)~~ 281 - 10% = 252.9 bytes
```
s=>(c=eval(s[a="replace"](" ","-(")[a](/ /g,"+")[a](/\w+/g,m=>m[b="match"](/^(Pr|Ob)/g)?1:m[b](/^([ZSHDWP]|M\w+C)/g)?2:m[b](/^O/g)?3:m[b](/^[IAVT]/g)?4:m[b](/^N/g)?-11:m[b](/^C/g)?6:+m!=m?8:m*8)+")"))>0?true:`You must construct ${Math.ceil(-c/8)} additional pylon${c/8<-1?"s":""}!`
```
This appears to be pretty lengthy...
Demo + explanation:
```
p = s => (c = eval(
  s[a = "replace"](" ", "-(")         //replace the first space (after the number of pylons) with "-" and open the bracket
   [a](/ /g, "+")                       //replace all the remaining spaces with "+"
   [a](/\w+/g, m =>                     //replace any sequence of characters with...
    m[b = "match"](/^(Pr|Ob)/g) ? 1 :   //with 1, if matches "Probe" or "Observer"
    m[b](/^([ZSHDWP]|M\w+C)/g) ? 2 :    //with 2, if it matches bunch of the units with cost 2. "Probe" didn't match already, so it's safe to catch "Phoenix" by only the first letter.
    m[b](/^O/g) ? 3 :                   //with 3, if match is "Oracle"
    m[b](/^[IAVT]/g) ? 4 :              //with 4, if matches "Immortal", "Archon", "VoidRay" or "Tempest"
    m[b](/^C/g) ? 6 :                   //with 6, if it's "Carrier" or "Colossus"
    m[b](/^N/g) ? -11 :                 //don't forget nexuses!
    +m != m ? 8 : m * 8                 //and if's not a number, then it's "Mothership", so with 8. If it's number, it can only be the number of pylons, replace it with itself multiplied by 8.
  ) + ")"                             //close the opened bracket
)) > 0 ? true : `You must construct ${Math.ceil(-c/8)} additional pylon${c/8<-1?"s":""}!`
document.write(
  p("2 Probe Probe Probe Probe Stalker Zealot Carrier Probe Zealot") + "<br>" +
  p("5 Mothership Carrier Probe Tempest HighTemplar") + "<br>" +
  p("0 Mothership Colossus Zealot") + "<br>" +
  p("0 Probe Nexus Probe")
)
```
[Answer]
## Python 3, 293 − 30% = 205.1 bytes
Implements **both** bonuses. Prints 1 as its truthy value, and either 0 or an empty string as its falsey value.
```
s='5N 8O5P bDbHeM7P6S7S9W6Z 6O 6A8I7T7V . 7C8C . aM'.split()
m=M=n=o=0
p,*u=input().split()
for v in u:
 S=0
 while'%x'%len(v)+v[0]not in s[S]:S+=1
 n+=S or-11;M+=S>7;m+='pC'in v;o+=m>1or M>1or m<1<=M
q=int(p)+n//-8
print([1,'You must construct %d additional pylon'%-q+'s!'[q>-2:]][q<0]*(o<1))
```
Credit to [Dom Hastings' solution](https://codegolf.stackexchange.com/a/69224/13959) for helping me shave off a good few bytes with a "poor man's `ceil`" of my own, and [Morgan Thrapp's](https://codegolf.stackexchange.com/a/69257/13959) for the idea underlying `'s!'[q>-2:]`, which saved me six bytes—not to mention pointing out, in the comments, how to save another byte on that bit.
---
### Explanations
The string in line 1 encodes all of the units and their supply requirements. Each unit is represented as two characters: a hexadecimal digit giving the length of the unit's name, and the first character of the name (e.g. `8O` is the Observer; `aM` is the Mothership). The supply requirement is the index of the encoded unit within the sequence `s`, formed by splitting the string on the spaces. Full stops mark unused amounts of supply (no unit needs 5 or 7 supply), and as a special case, the Nexus (`5N`) is at index 0.
Line 2 initialises values: `m` is the number of mothership cores, `M` is the number of motherships, `n` is the total supply cost, and `o` indicates whether or not the mothership build conditions have been violated. Line 3 takes the input, putting the number of pylons into `p` and the list of units into `u`.
Within the loop that starts at line 4, `S` is an index into `s` and, thus, also the amount of supply needed for the current unit, `v`. In line 6, the `while` statement steps through `s` until the unit is found. (`'%x'%len(v)` turns the length of the unit's name into a hex digit.)
Line 7 updates the total supply cost `n` (note the special case, `-11`, if `S` is zero). It then increments the counts of motherships `M` (identified by the supply cost being over 7) and mothership cores `m` (identified by the substring `pC` in the unit's name). Then, if either of these is greater than 1, or if `M` is at least one while `m` is still zero, the flag `o` is set. (Actually, it's incremented, but later on we only care if it's zero or non-zero.)
The pylon deficit `q` is calculated, a little oddly, in line 8. Naively, it should be `n // 8 - int(p)` (i.e. one eighth of the supply cost, minus any pylons we already have). But that would round down, when we need to round up. Integer division (`//`) rounds towards negative infinity, though, so we just work everything in negatives: `int(p) - -(n // -8)`, which simplifies to the form actually used.
Lastly, the output. If we're just one pylon short, `q` will be -1, hence the test `q>-2` (which slices the `s` out of the string `s!` if true, and keeps it otherwise). If there's no pylon deficit, `q` will be zero or positive, hence `q<0` to select between the truthy value 1 or the output string. Lastly, if the flag `o` isn't zero, multiplying either result (1 or a string) by Boolean `False` (handled as numeric 0) will give a falsey value (0 or the empty string).
[Answer]
# C++11, 732-30% = 512.4 bytes
Uses Dom Hastings's poor man's `ceil` and Martin Büttner suggestions of shorting the dictionary.
```
#include <iostream>
#include <map>
#include <string>
#include <cctype>
using namespace std;
map<int,int>a ={{536,1},{655,2},{677,2},{758,2},{1173,2},{1175,2},{869,4},{891,6},{635,4},{872,1},{997,2},{763,2},{1516,2},{766,4},{630,3},{770,4},{744,6},{1091,8},{563,-11}};
int main(){string b,c;int d,e,l,j,k=0,m=0,n=0,v=0;cin>>d;getline(cin,b);
while(b.size()){e=0;auto z=b.find(" ");c=b.substr(0,z);b.erase(0,((z==string::npos)?z:z+1));
for(int i=0;i<c.size();i++){e+=tolower(c[i]);}
if(e==1516){m++;}else if(e==1091){((m>1)?v=1:v=0);}
if((l=k-(d*8)>0)&&(m==n==1)){j=(int)(((float)l/8)+0.99);cout<<"You must construct "<<j<<" additional pylon"<<((j==1)?"!":"s!")<<endl;}
else{cout<<((m==n==1&&!v)?"True":"False")<<endl;}}
```
[Answer]
# Python 2, ~~442~~ ~~359~~ ~~464~~ ~~332~~ ~~314~~ 306 - 10% = 275.4
```
a,*l=input().split(' ');p=int(a)*8;for i in l:p-={"Ne":-11,"Pr":1,"Ze":2,"Se":2,"St":2,"Hi":2,"Da":2,"Im":4,"Co":6,"Ar":4,"Ob":1,"Wa":2,"Ph":2,"MoC":2,"Vo":4,"Or":3,"Te":4,"Ca":6,"Mo":8}[i[:2]+("C"if i[-4:]=="Core")]
e=int(.9+p/8)+1;print[1,"You must construct "+`e`+" additional pylon"+"s!"[e>1:]][p>=0]
```
[Answer]
# Lua, 418 - 10% = 376,2 bytes
```
function p(i)i=i:gsub("(%w+)",function(w)q=tonumber(w)*8;return""end,1);n=0;i:gsub("(%w+)",function(w)m=w.match;n=n+(m(w,"^Pr.*")and 1 or m(w,"^Ob.*")and 1 or m(w,"^[ZSHDWP]")and 2 or m(w,"^M.*C")and 2 or m(w,"^O")and 3 or m(w,"^[IAVT]")and 4 or m(w,"^C")and 6 or m(w,"^N")and -11 or 8)end)if n>q then a=math.ceil((n-q)/8);print("You must construct "..a.." additional pylon"..(a>1 and"s"or"")..".")else print(1)end end
```
Implements the Nexus bonus.
First time I've posted something here. Was writing Lua scripts for a game, stumbled across this and felt like contributing, hah.
Note: This Lua function assumes that the base library has been loaded, and that the host application defines an appropriate `print` function that accepts any non-nil value.
I'm exploiting Lua's `string.gsub` to the best of my ability, as well as its `and` and `or` operators.
Here's the pretty version:
```
function pylons(i)
    -- Replace the first word, the number, with a space, while also storing it as a number * 8
    i = i:gsub("(%w+)", function(w)
        q = tonumber(w) * 8
        return ""
    end, 1)
    n = 0
    -- the function passed to gsub gets every word in the string,  and then I misuse Lua's and/or
    -- operator order to assign supply values to string.match calls that do not return nil
    i:gsub("(%w+)", function(w)
        m = w.match
        n = n + (m(w,"^Pr.*") and 1 or
        m(w,"^Ob.*") and 1 or
        m(w,"^[ZSHDWP]") and 2 or
        m(w,"^M.*C") and 2 or
        m(w,"^O") and 3 or
        m(w,"^[IAVT]") and 4 or
        m(w,"^C") and 6 or
        m(w,"^N") and -11 or 8)
    end)
    if n>q then
        a = math.ceil((n-q)/8)
        print("You must construct "..a.." additional pylon"..(a>1 and"s"or"")..".")
    else
        print(1)
    end
end
pylons("5 Nexus Probe Observer Zealot Sentry Stalker HighTemplar DarkTemplar WarpPrism Phoenix MothershipCore Oracle Immortal Archon VoidRay Tempest Colossus Carrier Mothership")
pylons("2 Probe Probe Probe Probe Stalker Zealot Carrier Probe Zealot")
pylons("5 Mothership Carrier Probe Tempest HighTemplar")
pylons("0 Mothership Colossus Zealot")
```
[Answer]
# JavaScript (ES6), 228-10% = 206
```
s=>(s.replace(/\w+/g,x=>t+=~~{Ns:-11,Pe:1,Zt:2,Sy:2,Sr:2,Hr:2,Dr:2,Il:4,Cs:6,An:4,Or:1,Wm:2,Px:2,Me:2,Vy:4,Oe:3,Tt:4,Cr:6,Mp:8}[x[0]+x.slice(-1)]-8*~~x,t=7),t=t/8|0,t<=0||`You must construct ${t} additional pylon${t>1?'s':''}!`)
```
**Test**
```
F=s=>(
  t=7,
  s.replace(/\w+/g,
   x=>t+=~~{Ns:-11,Pe:1,Zt:2,Sy:2,Sr:2,Hr:2,Dr:2,Il:4,Cs:6,An:4,Or:1,Wm:2,Px:2,Me:2,Vy:4,Oe:3,Tt:4,Cr:6,Mp:8}[x[0]+x.slice(-1)]-8*~~x),
  t=t/8|0,
  t<=0||`You must construct ${t} additional pylon${t>1?'s':''}!`
)
console.log=x=>O.textContent+=x+'\n';
;['2 Probe Probe Probe Probe Stalker Zealot Carrier Probe Zealot',
'5 Mothership Carrier Probe Tempest HighTemplar',
'0 Mothership Colossus Zealot','0 Probe Nexus Probe'
].forEach(t=>console.log(t+'\n'+F(t)))
```
```
<pre id=O></pre>
```
[Answer]
## Perl, 212 bytes code + 3 for `-p` - 10% = 193.5 bytes
I'm sure I can reduce this some more, not happy about the full `for$s(...){...}` block but I'm done for now!
```
$x=$_*8;s/^\d+ //;map{for$s(Pr,Ob,Or,C,V,I,A,T,Z,S,H,D,W,Ph,'.+C',N,'.+p$'){$x-=(1,1,3,6,(4)x4,(2)x7,-11,8)[$i++%17]*/^$s/}}/\w+/g;$x=int$x/-8+.9;$s=1<$x&&'s';$_=$x>0?"You must construct $x additional pylon$s!":1
```
### Interesting snippets
* Poor mans `ceil`: `int$n+.9` - I tried to use `0|` but got what looks like overflow!
* List duplication: `(9)x9` yields `(9,9,9,9,9,9,9,9,9,9)`
### Usage:
```
perl -p pylons.pl <<< '3 Mothership Zealot'
1
```
Thanks to [Tim Pederick](https://codegolf.stackexchange.com/users/13959/tim-pederick) for helping to save an extra byte!
]