5
\$\begingroup\$

You're playing TF2, and you want to make a bot that will just put voice commands into the chat box. Typically, to "call" a voice command, one would press a key (Z, X, or C) and a number (1-8) to create an audio dialogue. Here are the text equivalents of the audios displayed when pressing these keys:

Voice Menu 1
Default key: Z
==============
1. MEDIC!
2. Thanks!
3. Go Go Go!
4. Move Up!
5. Go Left
6. Go Right
7. Yes
8. No


Voice Menu 2
Default key: X
==============
1. Incoming
2. Spy!
3. Sentry Ahead!
4. Teleporter Here
5. Dispenser Here
6. Sentry Here
7. Activate ÜberCharge!
8. MEDIC: ÜberCharge Ready   ; ignore the MEDIC: bit


Voice Menu 3
Default key: C
==============
1. Help!
2. Battle Cry    ; see bonus
3. Cheers
4. Jeers
5. Positive
6. Negative
7. Nice Shot
8. Good Job

Objective Given an input string (or input character + character, character + number, etc.; whatever is most relevant/convenient to your language), take the respective message from the chart above and output it. If the input is invalid, do not output anything. This is a , so the shortest program in bytes wins.

Example IOs

> Z3
Go Go Go!

> Z1
MEDIC!

> Z5
Go Left

> X8
ÜberCharge Ready

> X7
Activate ÜberCharge!

> C1
Help!

> C8
Good Job

Bonuses/penalties

These bonuses are applied in the order of appearance in this list.

  • -1 byte for every byte used in the physical text of C2 (i.e., Battle Cry); I will not add points for errors on C2, so be creative if you wish! (By physical text, I mean every byte used for constructing (not outputting) the string. For example, for STDOUT "AHHHHHHHH!", "AHHHHHHHH!" is free, but nothing else is. In console.log(`${v="Tha"}t's too you, you idiot!`), the free characters are `"Tha" t's too you, you idiot!`. These characters are the only ones that make up part of the string and their respective quotes.)
  • -15% if your program takes input and outputs the respective entry until an invalid input is given, at which point your program should terminate.
  • +5 bytes for every capitalization, punctuation, or spacing error
  • +10 bytes for every wrong/missing letter
  • -20 bytes if you can take a string like "X5C3Z6..." and output each respective message, separated by newlines.
  • -30 bytes if you take a class input (either Scout, Soldier, Pyro, Demoman, Heavy, Engineer, Sniper, Medic, or Spy) and verify if the class can say the given expression. The only expression that applies is X8, i.e., MEDIC: ÜberCharge Ready; only the Medic can say this. If any other class besides the medic attempts to say this, do not output anything. (The names are case insensitive.)

Leaderboard

var QUESTION_ID=63370,OVERRIDE_USER=8478;function answersUrl(e){return"http://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"http://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>

\$\endgroup\$
  • \$\begingroup\$ I'm guessing the Ü is mandatory? \$\endgroup\$ – phase Nov 9 '15 at 3:22
  • \$\begingroup\$ Are we allowed to exit with an error when we're done taking input (i.e. if it's invalid or there is none left)? \$\endgroup\$ – cole Nov 9 '15 at 4:08
  • 9
    \$\begingroup\$ If I choose MEDIC!Thanks!Go Go Go!Move Up!... as battle cry, I should be able to get a fairly low score... \$\endgroup\$ – Dennis Nov 9 '15 at 4:26
  • \$\begingroup\$ In the examples, shouldn't there be a ! after Activate ÜberCharge? \$\endgroup\$ – LegionMammal978 Nov 9 '15 at 11:52
  • \$\begingroup\$ @LegionMammal978 Indeed. \$\endgroup\$ – Conor O'Brien Nov 9 '15 at 12:02
1
\$\begingroup\$

Perl, 280 - 15% - 20 = 218 bytes

#!perl -l
@Z=<0 {MEDIC,Thanks,Go_Go_Go,Move_Up}! Go_{Left,Right} Yes No>;
@X=<0 Incoming Spy! Sentry_Ahead! {Teleporter,Dispenser,Sentry}_Here Activate_ÜberCharge! ÜberCharge_Ready>;
@C=<0 Help! You_Fight_Like_A_Dairy_Farmer! {Ch,J}eers {Posi,Nega}tive Nice_Shot Good_Job>;
y/_/ /,print while$_=${getc=~s/
//r||getc}[getc]

Counting the shebang as one, input is taken from stdin. The newlines after semicolons are not necessary, and have been left for readability.


Sample Usage

$ echo Z3 | perl tf2.pl
Go Go Go!

$ echo X7 | perl tf2.pl
Activate ÜberCharge!

$ echo C2 | perl tf2.pl
You Fight Like A Dairy Farmer!

$ echo X5C3Z6 | perl tf2.pl
Dispenser Here
Cheers
Go Right

Interactive Mode

The code may also be run in interactive mode, in which case it will continue accepting input until an invalid input is given.

$ perl tf2.pl
Z2
Thanks!
X3
Sentry Ahead!
C4
Positive
V5

Perl, 331 - 354 (C2) - 20 - 30 = -73 bytes

#!/usr/bin/env perl -l
@Z=<0 {MEDIC,Thanks,Go_Go_Go,Move_Up}! Go_{Left,Right} Yes No>;
@X=(<0 Incoming Spy! Sentry_Ahead! {Teleporter,Dispenser,Sentry}_Here Activate_ÜberCharge!>,{Medic.$/,'ÜberCharge Ready'});
@C=(0,'Help!',(join!open(0),<0>),<{Ch,J}eers>,<{Posi,Nega}tive>,Nice_Shot,Good_Job);
print%{$_=@{$`}[<>=~/.\K(.)/]}?$_->{$c}:y/_/ /rwhile$c=<>

Supports multiple entries, and filtering by class. The battle cry I've chosen is the entire source code. It can be seen that every byte of the source is necessary for the construction of this particular battle cry - were any byte missing, the battle cry would be different. This includes the entire shebang, which by convention is counted as one.


Sample Usage

$ more in.dat
Medic
X8
Spy
X8
Heavy
C8
Pyro
Z2

$ perl tf2.pl < in.dat
ÜberCharge Ready

Good Job
Thanks!
\$\endgroup\$
  • 1
    \$\begingroup\$ I said These bonuses are applied in the order of appearance in this list. \$\endgroup\$ – Conor O'Brien Nov 9 '15 at 19:23
6
\$\begingroup\$

CJam, -48 bytes

"\"MEDIC!
Thanks!
Go Go Go!
Move Up!
Go Left
Go Right
Yes
No
Incoming
Spy!
Sentry Ahead!
Teleporter Here
Dispenser Here
Sentry Here
Activate ÜberCharge!

Help!

Cheers
Jeers
Positive
Negative
Nice Shot
Good Job
\"N/Fleu\"MEDIC\"=\"ÜberCharge Ready\"*tq2/\"ZXC\"9,1>sm*f{\a#-2$=_S=W$@?N}\?"_~

The source code is 292 bytes long, can handle multiple inputs (-20 bytes) and checks for the class name (-30 bytes). Furthermore, I have chosen

"MEDIC!
Thanks!
Go Go Go!
Move Up!
Go Left
Go Right
Yes
No
Incoming
Spy!
Sentry Ahead!
Teleporter Here
Dispenser Here
Sentry Here
Activate ÜberCharge!

Help!

Cheers
Jeers
Positive
Negative
Nice Shot
Good Job
"N/Fleu"MEDIC"="ÜberCharge Ready"*tq2/"ZXC"9,1>sm*f{\a#-2$=_S=W$@?N}\?

as battle cry, so the first 290 bytes that are used to push this string are free.

Try it online in the CJam interpreter.

\$\endgroup\$
4
\$\begingroup\$

D, 692 bytes

731 - 39(for "B"~"a"~"t"~"t"~"l"~"e"~" "~"C"~"r"~"y")

import std.stdio;import std.conv;import std.utf;void main(char[][] a){char t=a[1][0];int n=to!int(a[1][1])-48;string G="Go ";char z='Z';char x='X';char c='C';string H=" Here";string U=to!string('\u00DC');string[int][char]o;o[z][1]="MEDIC!";o[z][2]="Thanks!";o[z][3]=G~G~"Go!";o[z][4]="Move Up!";o[z][5]=G~"Left";o[z][6]=G~"Right";o[z][7]="Yes";o[z][8]="No";o[x][1]="Incoming";o[x][2]="Spy!";o[x][3]="Sentry Ahead!";o[x][4]="Teleporter"~H;o[x][5]="Dispenser"~H;o[x][6]="Sentry"~H;o[x][7]="Activate "~U~"berCharge!";o[x][8]=U~"berCharge Ready";o[c][1]="Help!";o[c][2]="B"~"a"~"t"~"t"~"l"~"e"~" "~"C"~"r"~"y";o[c][3]="Cheers";o[c][4]="Jeers";o[c][5]="Positive";o[c][6]="Negative";o[c][7]="Nice Job";o[c][8]="Good Job";write(o[t][n]);}

I like D a lot.

D, 724 bytes w/ Classes

793 - 39(same as above) - 30(for class option)

import std.stdio;import std.conv;import std.utf;void main(char[][] a){char t=a[1][0];int n=to!int(a[1][1])-48;string G="Go ";char z='Z';char x='X';char c='C';string H=" Here";string U=to!string('\u00DC');string[int][char]o;o[z][1]="MEDIC!";o[z][2]="Thanks!";o[z][3]=G~G~"Go!";o[z][4]="Move Up!";o[z][5]=G~"Left";o[z][6]=G~"Right";o[z][7]="Yes";o[z][8]="No";o[x][1]="Incoming";o[x][2]="Spy!";o[x][3]="Sentry Ahead!";o[x][4]="Teleporter"~H;o[x][5]="Dispenser"~H;o[x][6]="Sentry"~H;o[x][7]="Activate "~U~"berCharge!";o[x][8]=U~"berCharge Ready";o[c][1]="Help!";o[c][2]="B"~"a"~"t"~"t"~"l"~"e"~" "~"C"~"r"~"y";o[c][3]="Cheers";o[c][4]="Jeers";o[c][5]="Positive";o[c][6]="Negative";o[c][7]="Nice Job";o[c][8]="Good Job";if(a.length>2){if(!(a[2]!="Medic"&&t==x&&n==8))goto P;}else P:write(o[t][n]);}

This version lets you input a class for X8. Use it like tf2 X8 Medic. It will print the correct message if you use the correct class. Yes, this does use a goto. Kill it now.

\$\endgroup\$
4
\$\begingroup\$

Prolog, 371 362 - 11 = 351 bytes

My first attempt at code golf.
I chose a language which seem to be underrepresented here.
I'm far from an expert at prolog, so this can most likely be improved a lot.
I did not go for any optional bonuses. I tried for the 15% one but it cost me more than I gained.

    a(z,['MEDIC!','Thanks!','Go Go Go!','Move Up!','Go Left','Go Right','Yes','No']).
    a(x,['Incoming','Spy!','Sentry Ahead!','Teleporter Here','Dispenser Here','Sentry Here','Activate ÜberCharge!','ÜberCharge Ready']).
    a(c,['Help!','For Pony!','Cheers','Jeers','Positive','Negative','Nice Shot','Good Job']).
    r:-read(X),read(Y),a(X,Z),nth1(Y,Z,A),write(A),1=2.

Try it out

You can try it out online here.

  1. Create new program
  2. Paste code
  3. As query, just use 'r' without quotes.

Input is first a letter then a number.

Example:
Input: z
Press Send
Input 3
Press Send
Outputs: Go Go Go!

Edit:
Saved 9 bytes with input from @Fatalize

\$\endgroup\$
  • \$\begingroup\$ I don't think you need to use writeln according to the specs of the challenge. write seems sufficient. Also 1=2 is a one-byte shorter way to fail than to use fail ;) \$\endgroup\$ – Fatalize Nov 9 '15 at 17:01
  • \$\begingroup\$ I also don't see why you would need the repeat [...] fail construct here, according to the challenge (unless I didn't read it correctly) you only need to take the two inputs once and output the answer, and them the program can terminate. \$\endgroup\$ – Fatalize Nov 9 '15 at 17:06
  • \$\begingroup\$ @Fatalize some very good points, thank you. Your input saves me 9 bytes. I meant the repeat/fail to be used for the 15% bonus, but it ended up costing more than it gained me so I have no use for it as the program is now. \$\endgroup\$ – Emigna Nov 10 '15 at 7:22
1
\$\begingroup\$

TeaScript, 225 - 6 = 219 bytes

b=xS(1)-1
x0¦'Z'?æMEDIC!,Tnks!,Go Go Go!,Move Up!,Go Left,Go Right,Y,No`.s`,`[b]:x0¦'X'?æîa,Spy!,SÀ^y AÊ%!,Tà({Zr He,DáÀ He,SÀ^y He,Acve ürCrge!`.s`,`[b]:x0¦'C'?æHelp!,PÇës!,CÊ8s,JÁÄ,PoÐÓve,Negive,Ni­ St,Good Job`.s`,`[b]:''

As short as I can get it. None of the bonuses save any bytes.

Try it online. If the outputs show up weird for you, tell me and I'll add a hex dump too deal with all the special characters.

\$\endgroup\$
  • \$\begingroup\$ This doesn't work for multiple inputs: X8 => undefined, C7 => Nice S["t"]... \$\endgroup\$ – Conor O'Brien Nov 9 '15 at 12:11
1
\$\begingroup\$

Mathematica, 368 - 24 = 344 bytes

Check[StringExtract["MEDIC!,Thanks!,Go Go Go!,Move Up!,Go Left,Go Right,Yes,No;Incoming,Spy!,Sentry Ahead!,Teleporter Here,Dispenser Here,Sentry Here,Activate ÜberCharge!,ÜberCharge Ready;Help!,Why am I saying this...,Cheers,Jeers,Positive,Negative,Nice Shot,Good Job",";"-><|"Z"->1,"X"->2,"C"->3|>[#~StringTake~1],","->FromDigits[#~StringDrop~1]]/._Missing->"",""]&
\$\endgroup\$
1
\$\begingroup\$

AppleScript, (595-18)*.85 = 490.45 Bytes

I beat somebody.

set a to{"MEDIC!","Thanks!","Go Go Go!","Move Up!","Go Left","Go Right","Yes","No","Incoming","Spy!","Sentry Ahead!","Teleporter Here","Dispenser Here","Sentry Here","Activate ÜberCharge!","ÜberCharge Ready","Help!","FOR APPLESCRIPT!","Cheers","Jeers","Positive","Negative","Nice Shot","Good Job"}
set c to true
considering case
repeat while c
set b to(display dialog""default answer"")'s text returned's characters
set n to 0
set k to item 1 of b
if k="C" then
set n to 0
else if k="X" then
set n to 8
else if k="Z" then
set n to 16
else
exit
end
display dialog(item(n+item 2 of b)of a)
end
end

Basically, I push all the items into an array. I get input through a text window (see gif below) and then an output window displays the referenced text.

gif

The bonuses that apply are for the Battle Cry and the looping until invalid.

\$\endgroup\$
  • \$\begingroup\$ I'm laughing at considering case: what is this, INTERCAL? \$\endgroup\$ – cat Nov 20 '15 at 18:12
  • 1
    \$\begingroup\$ @sysreq ¯\_(ツ)_/¯ AppleScript doesn't consider case by default, because logic. \$\endgroup\$ – Addison Crump Nov 20 '15 at 18:17
  • \$\begingroup\$ I guess that makes sense, considering HFS didn't support/preserve case-sensitive filenames and HFS+ can, if you do some fiddling \$\endgroup\$ – cat Nov 20 '15 at 18:21
1
\$\begingroup\$

Vitsy, 343 - 15 - 20 = 308 Bytes

I only qualify for the Battle Cry bonus and separating the segments by newline. My language can't do that other stuff. ;(

<OaZm+-1;)D]++2f[)-V'Z']+9[)-V'X']+1[)-V'C'Vi0;)/8^/21^2D-*68i
'!CIDEM'
'!sknahT'
'!oG oG oG'
'!pU evoM'
'tfeL oG'
'thgiR oG'
'seY'
'oN'
'gnimocnI'
'!ypS'
'!daehA yrtneS'
'ereH retropeleT'
'ereH resnepsiD'
'ereH yrtneS'
'!egrahCrebÜ etavitcA'
'ydaeR egrahCrebÜ'
'!pleH'
'syawlA ystiV'
'sreehC'
'sreeJ'
'evitisoP'
'evitageN'
'tohS eciN'
'boJ dooG'

This uses method structuring to push items to the stack according to a specific reference. Since it's easier to understand the way I originally wrote it, I have put the original code down below. The only difference is that the one above uses the < character to loop around the line backwards, one of the special ways that Vitsy loops around the line. The explanation for the top layer of code (in executed order) is below:

i86*-D1-D8M-);0iV'C'V-)[1+]'X'V-)[9+]'Z'V-)[f2++]D(;1-+mZ
i86*-                                                     Get the number value of the ASCII input.
     D1-D8M-);                                            If the number is within the range 0-8, continue the program. Otherwise, end execution.
              0                                           Placeholder of zero.
               iV                                         Get the character component and save it as a global variable.
                 'C'V-)[1+]                               If it's 'C', add 1
                           'X'V-)[9+]'Z'V-)[f2++]         Do the same things with 'X' and 'Z', adding 1 and a multiple of 8.
                                                 D(;      If after all this, the number is still zero, end execution.
                                                    1-+   Subtract one and add the components.
                                                       m  Execute that line number.
                                                        Z Print everything in the stack to STDOUT and quit.
\$\endgroup\$
1
\$\begingroup\$

Haskell, 397 -15% - 20 = 317.45 bytes

v=[('Z',["MEDIC!","Thanks!","Go Go Go!","Move Up!","Go Left","Go Right","Yes","No"]),('X',["Incoming","Spy!","Sentry Ahead!","Teleporter Here","Dispenser Here","Sentry Here","Activate ÜberCharge!","ÜberCharge Ready"]),('C',["Help!","Battle Cry","Cheers","Jeers","Positive","Negative","Nice Shot"])]
h(Just k)=k
m(x:y:s)=((h$lookup x v)!!((fromEnum y)-49))++('\n':m s)
m""=""
main=interact$concat.map m.lines

The input is taken from the standard input and it will output messages until there is no more input or an invalid input is given.

P.S. : Changing the order in which to apply the bonuses, according to a comment from the OP.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.