Fallout Terminal Hacking

13

1

Anyone here a die-hard Bethesda fan? Maybe you prefer Obsidian Entertainment? Well, if you're either of those things than the following picture should be relatively familiar to you.

The fallout terminal.

I've taken the liberty of preparing a rather unique ASCII-Art challenge, so here's the first clue as to what I'm going to have you do:

  _____________________________________________________
 /                                                     \ 
|     _____________________________________________     |
|    |                                             |    |
|    | Welcome to ROBCO Industries (TM) Termlink   |    |
|    | Password Required                           |    |
|    | Attempts Remaining:                         |    |
|    |                                             |    |
|    | 0x01                 | 0x0D                 |    |
|    | 0x02                 | 0x0E                 |    |
|    | 0x03                 | 0x0F                 |    |
|    | 0x04                 | 0x10                 |    |
|    | 0x05                 | 0x11                 |    |
|    | 0x06                 | 0x12                 |    |
|    | 0x07                 | 0x13                 |    |
|    | 0x08                 | 0x14                 |    |
|    | 0x09                 | 0x15                 |    |
|    | 0x0A                 | 0x16                 |    |
|    | 0x0B                 | 0x17                 |    |
|    | 0x0C                 | 0x18                 |    |
|    |_____________________________________________|    |
|                                                       |
\_______________________________________________________/ 
       \_______________________________________/        

This is a very basic (blank) template for the RobCo Fallout terminal design in pure ASCII, your job will be to:

  • First, generate this template.
  • Then, given a list of strings l and a number 0 <= n <= 4 to fill it up!

The two dynamic parts of a fallout hacking terminal are:

The Number of Attempts

  • The number of attempts you have remaining (indicated by space delimited boxes.
    • For the purpose of this challenge you will be using X instead of .

The Passwords

  • The passwords, defined by l, are interspersed with random printable ASCII symbols.
  • The passwords, as you can tell by the example, can wrap multiple rows (NAMES).
  • All passwords in the terminal screen should have an equal chance of being anywhere.
  • All passwords can be expected to be of equal length, though this doesn't matter.
  • The list of symbols usable to separate passwords are: !"#$%&'()*+/:;<=>?@[\]^_{|}.
  • All passwords in l must be of equal length.
  • PASSWORDS MUST HAVE THE POTENTIAL TO WRAP BETWEEN BOTH COLUMNS.
    • This also goes for rows, but only to a higher byte address (0x18->0x01 is invalid).
  • The display space for passwords on either side is 15 wide (with a space on either side).
    • You may assume no words in l will be longer than this.
  • Passwords are alphabetical only, meaning only letters.

Example:

l = ["SMART","ENACT","SWORE","PITYS","SMELL","CARTS","RACES"], n = 4

  _____________________________________________________
 /                                                     \ 
|     _____________________________________________     |
|    |                                             |    |
|    | Welcome to ROBCO Industries (TM) Termlink   |    |
|    | Password Required                           |    |
|    | Attempts Remaining: X X X X                 |    | # N = 4 drives these X's.
|    |                                             |    |
|    | 0x01 $?_/%$ENACT||"} | 0x0D TYS"_'$\#|^%&{} |    |
|    | 0x02 }:!*@{/_<"[]#>; | 0x0E #{!"^&\]'|}_[$% |    |
|    | 0x03 $%&'()*+/:;<\_' | 0x0F }|[(%SMELL/_$@( |    |
|    | 0x04 ^SMART(!@$*'^_@ | 0x10 []_#!"{|}'%$\&^ |    |
|    | 0x05 (*@#%}*(!%)^(_! | 0x11 %$}[!\#'^&_]{|" |    |
|    | 0x06 $%&'()*+/:;<_@) | 0x12 \SWORE|%'_!}\^" |    |
|    | 0x07 "/')=*%!&>#<:$+ | 0x13 ^{['&$|!_]%\"#} |    |
|    | 0x08 ;'*$&"(<%!#)RAC | 0x14 ']!|^#[$"_\}&{% |    |
|    | 0x09 ES:($&';%#+"<*/ | 0x15 @)($!CARTS*!@$_ |    |
|    | 0x0A ;'*$&"(<%!#)/+: | 0x16 !#%${"'}&[]^|_\ |    |
|    | 0x0B |'_!}$\%["#^{&] | 0x17 ]"_#$&}^%[{|\'! |    |
|    | 0x0C #{!"^&\]'|}_[PI | 0x18 _![&#{$%\^'|}"] |    | # Notice how PITYS wrapped.
|    |_____________________________________________|    |
|                                                       |
\_______________________________________________________/ 
       \_______________________________________/        

If n = 2 on the same example:

  _____________________________________________________
 /                                                     \ 
|     _____________________________________________     |
|    |                                             |    |
|    | Welcome to ROBCO Industries (TM) Termlink   |    |
|    | Password Required                           |    |
|    | Attempts Remaining: X X                     |    | # N = 2 drives these X's.
|    |                                             |    |
|    | 0x01 $?_/%$ENACT||"} | 0x0D TYS"_'$\#|^%&{} |    |
|    | 0x02 }:!*@{/_<"[]#>; | 0x0E #{!"^&\]'|}_[$% |    |
|    | 0x03 $%&'()*+/:;<\_' | 0x0F }|[(%SMELL/_$@( |    |
|    | 0x04 ^SMART(!@$*'^_@ | 0x10 []_#!"{|}'%$\&^ |    |
|    | 0x05 (*@#%}*(!%)^(_! | 0x11 %$}[!\#'^&_]{|" |    |
|    | 0x06 $%&'()*+/:;<_@) | 0x12 \SWORE|%'_!}\^" |    |
|    | 0x07 "/')=*%!&>#<:$+ | 0x13 ^{['&$|!_]%\"#} |    |
|    | 0x08 ;'*$&"(<%!#)RAC | 0x14 ']!|^#[$"_\}&{% |    |
|    | 0x09 ES:($&';%#+"<*/ | 0x15 @)($!CARTS*!@$_ |    |
|    | 0x0A ;'*$&"(<%!#)/+: | 0x16 !#%${"'}&[]^|_\ |    |
|    | 0x0B |'_!}$\%["#^{&] | 0x17 ]"_#$&}^%[{|\'! |    |
|    | 0x0C #{!"^&\]'|}_[PI | 0x18 _![&#{$%\^'|}"] |    | # Notice how PITYS wrapped.
|    |_____________________________________________|    |
|                                                       |
\_______________________________________________________/ 
       \_______________________________________/        

These examples were manually crafted, so the distribution is not randomized, sorry.


This is , lowest byte-count will be the accepted winner. I will bounty this after 3 days if no answers have been submitted for a total of 250 REP.

Magic Octopus Urn

Posted 2017-08-09T21:40:25.047

Reputation: 19 422

Quick! No one answer for 3 days! (kidding). This is my new favorite ascii-art challenge. – nmjcman101 – 2017-08-09T21:43:41.213

2@nmjcman101 what was your last favorite? – Magic Octopus Urn – 2017-08-09T22:05:19.510

What does the NAMES in the 2nd bullet point mean? "All passwords can be expected to be of equal length, though this doesn't matter." or "All passwords in l must* be of equal length.*"? It may just be me being blind (again!) but I don't see RACES in either output - should we take this to mean that there should be a possibility of a password not being used? Is Math.random (and equivalents) sufficiently random for the purposes of this challenge? – Shaggy – 2017-08-09T22:31:55.957

2Do there have to be non-alphanumeric spacers between two passwords or is it fine if they generate right next to each other (non-overlapping)? – HyperNeutrino – 2017-08-09T22:52:54.007

@nmjcman101 Sorry :P but not sorry :P – HyperNeutrino – 2017-08-09T23:02:10.773

5Do the passwords need to have the possibility of wrapping right-around from 0x18 to 0x01? – Jonathan Allan – 2017-08-10T00:48:56.837

Can there can be extra spaces at the end of the lines? – dzaima – 2017-08-10T07:20:24.107

@JonathanAllan all passwords can wrap, but no, that's not possible. They must wrap sequentially from lower byte-address to a higher one. – Magic Octopus Urn – 2017-08-11T13:32:35.573

@dzaima outside of the terminal, yes, inside, no. – Magic Octopus Urn – 2017-08-11T13:32:50.693

@HyperNeutrino there must be junk inbetween words. – Magic Octopus Urn – 2017-08-11T13:33:05.887

Answers

6

JavaScript (ES8), 575 568 564 bytes

Saved 3 bytes thanks to @Shaggy

Takes input in currying syntax (r)(a), where r is the number of remaining attempts and a is the array of passwords.

r=>a=>[...C=`!"#[]^$%&'*+;<{}=`].reduce((s,c)=>(x=s.split(c)).join(x.pop()),`  "%%__
 /;;# \\ 
[ "} $Welcome to ROBCO Industries (TM) Termlink'!Password Required#}'!Attempts Remaining:${" X".repeat(r).padEnd(9)};[$^1=^D<2=^E<3=^F<4*0<5*1<6*2<7*3<8*4<9*5<A*6<B*7<C*8='+"[|
|;;#'|
\\"{_/ 
}'\\&%/= ]]]]] | }' {%%%<='+ ^#}}}+|
[|*=0x1'   "{{{%___$+;#}} !^0x0]ZZZ[|}#;}"&{![+ `).replace(/Z/g,(c,i)=>a.join``[(i%58>>5?y++:x++)%L],x=(R=n=>Math.random()*n|0)(L=360),y=x+180,[...Array(L-(n=a.sort(_=>R(3)-1).length)*a[0].length)].map(_=>a[R(n)]+=(C+`>?@()/:\\_|`)[R(27)]))

Syntax highlighter disabled on purpose. It has no clue what to do with that.

Demo

let f =

r=>a=>[...C=`!"#[]^$%&'*+;<{}=`].reduce((s,c)=>(x=s.split(c)).join(x.pop()),`  "%%__
 /;;# \\ 
[ "} $Welcome to ROBCO Industries (TM) Termlink'!Password Required#}'!Attempts Remaining:${" X".repeat(r).padEnd(9)};[$^1=^D<2=^E<3=^F<4*0<5*1<6*2<7*3<8*4<9*5<A*6<B*7<C*8='+"[|
|;;#'|
\\"{_/ 
}'\\&%/= ]]]]] | }' {%%%<='+ ^#}}}+|
[|*=0x1'   "{{{%___$+;#}} !^0x0]ZZZ[|}#;}"&{![+ `).replace(/Z/g,(c,i)=>a.join``[(i%58>>5?y++:x++)%L],x=(R=n=>Math.random()*n|0)(L=360),y=x+180,[...Array(L-(n=a.sort(_=>R(3)-1).length)*a[0].length)].map(_=>a[R(n)]+=(C+`>?@()/:\\_|`)[R(27)]))

O.innerText = f(3)(["SMART","ENACT","SWORE","PITYS","SMELL","CARTS","RACES"])
<pre id=O>

Arnauld

Posted 2017-08-09T21:40:25.047

Reputation: 111 334

Could you save anything using ES8 to populate the attempts like so: Attempts Remaining:${" X".repeat(r).padEnd(8)}? – Shaggy – 2017-08-10T11:40:03.147

1@Shaggy That does save 3 bytes. Thanks! – Arnauld – 2017-08-10T11:53:22.350

Welcome to ROBCO Industries (TM) Termlink'!Password Required#}'!Attempts Remaining: oof... I should've paraphrased to save non-golfing langs bytes. – Magic Octopus Urn – 2017-08-11T13:35:24.403

4

Python 3, 585 bytes

from random import*
def f(l,n,r=range):
	u,c='_ ';a=[choice('!"#$%&\'()*+/:;<=>?@[\\]^_{|}')for i in c*360];L=len(l[0]);i={*r(360-len(l[0]))};p=lambda x:'0x%02X'%x+c+''.join(a[15*x:][:15])
	for q in l:s=choice([*i]);a[s:s+L]=q;i-={*r(s+~L,s+-~-~L)}
	return'''  %s
 /%s\\
|# %s #|
?%s?
? Welcome to ROBCO Industries (TM) Termlink   ?
? Password Required   ######?
? Attempts Remaining:%-25s?
?%s?
%%s?%s?
|%s|
\%s/
#   \%s/'''.replace('?','|#|').replace('#',c*4)%(u*53,c*53,u*45,c*45,' X'*n,c*45,u*45,c*55,u*55,u*39)%('|    | %s | %s |    |\n'*12)%sum([(p(x),p(x+12))for x in r(12)],())

Try it online!

-70 bytes thanks to Jonathan Allan
-9 bytes thanks to myself (finally!)
-72 bytes thanks to notjagan

HyperNeutrino

Posted 2017-08-09T21:40:25.047

Reputation: 26 575

Another 35 bytes off! – notjagan – 2017-08-10T02:48:42.470

And 15 more.

– notjagan – 2017-08-10T02:54:48.817

16 more removed! (there has to be better way to do this than a bunch of comments) – notjagan – 2017-08-10T03:03:12.753

Another 6 bytes off by half-reverting one of my other changes (I really should stop commenting).

– notjagan – 2017-08-10T05:06:42.600

@notjagan I don't mind comments :) Thanks! – HyperNeutrino – 2017-08-10T15:39:59.750

4

Perl 5, 588 560 + 1 (-a) = 589 561 bytes

Cut 28 bytes with the suggestions Dom pointed out

$,=$/;$_=" X"x pop@F;say"  "."_"x53," /".$"x53 ."\\",$q="|     ".'_'x45 ."     |",$e=($b="|    |").$"x45 .$b,"$b Welcome to ROBCO Industries (TM) Termlink   $b
$b Password Required".$"x27 .$b,"$b Attempts Remaining:$_".$"x(25-length).$b,$e;map{$s.=(grep/[^\w,.`-]|_/,map{chr}33..125)[rand 27]}1..360;($t=substr$s,$r=rand 360-($l=length),$l,$_)=~/[a-z]/i&&(substr$s,$r,$l,$t)&&push@F,$_ while$_=pop@F;@o=$s=~/.{15}/g;printf"$b 0x0%X %s | 0x%02X %s $b\n",$_,$o[$_-1],$_+12,$o[$_+11]for 1..12;say$b.'_'x45 .$b,$q=~y/_/ /r,$q=" \\"."_"x54 ."/",$"x6 .$q=~s/_{15}//r

Try it online!

Previously:

$,=$/;$_=" X"x pop@F;say"  "."_"x53," /".($"x53)."\\",$q="|     ".('_'x45)."     |",$e=($b="|    |").($"x45).$b,"$b Welcome to ROBCO Industries (TM) Termlink   $b
$b Password Required".($"x27).$b,"$b Attempts Remaining:$_".($"x(25-length)).$b,$e;$s=join'',map{(split//,'!"#$%&\'()*+/:;<=>?@[]^_{|}\\')[int rand 27]}1..360;while($_=pop@F){if(($t=substr$s,$r=rand 360-($l=length),$l,$_)=~/[a-z]/i){substr$s,$r,$l,$t;push@F,$_}}@o=$s=~/.{15}/g;printf"$b 0x0%X %s | 0x%02X %s $b\n",$_,$o[$_-1],$_+12,$o[$_+11]for 1..12;say$b.('_'x45).$b,$q=~y/_/ /r,$q=" \\".("_"x54)."/",($"x6).$q=~s/_{15}//r

Try it online!

Input is on one line, space separated: first the strings, then the number

How?

$,=$/;          # delimiter between fields is newline
$_=" X"x pop@F; # set number of attempts left
say             # output the header
"  "."_"x53,
" /".($"x53)."\\",
$q="|     ".('_'x45)."     |",
$e=($b="|    |").($"x45).$b,
"$b Welcome to ROBCO Industries (TM) Termlink   $b
$b Password Required".($"x27).$b,
"$b Attempts Remaining:$_".($"x(25-length)).$b,
$e;
$s=join'',map{(split//,'!"#$%&\'()*+/:;<=>?@[]^_{|}\\')[int rand 27]}1..360; # create random string long enough for entire screen
while($_=pop@F){  # for each given string
if(($t=substr$s,$r=rand 360-($l=length),$l,$_) # attempt to insert it
=~/[a-z]/i)                                    # but check if it overlaps another string
{substr$s,$r,$l,$t;                            # if it does, take it out
push@F,$_}}                                    # and put it back in line
@o=$s=~/.{15}/g;                               # split "memory dump" into chunks
printf"$b 0x0%X %s | 0x%02X %s $b\n",$_,$o[$_-1],$_+12,$o[$_+11]for 1..12; #output the grid
say                                            # output the footer
$b.('_'x45).$b,$q=~y/_/ /r,
$q=" \\".("_"x54)."/",
($"x6).$q=~s/_{15}//r

Xcali

Posted 2017-08-09T21:40:25.047

Reputation: 7 671

Nice answer to a complex problem! You should be able to save almost 30 bytes by removing the brackets around the repetition operator, you can add a space so the . isn't used as a decimal point. Also to get the punctuation you can use something like (grep/[^\w,.`-]|_/,map{chr}33..125) and you don't need to call int on an array index! Changing the while loop to postfix and using && instead of if should save a few too. When you're building $s, if you have $s.= inside the map instead of using join drops a few more. Hope that helps! – Dom Hastings – 2017-08-10T07:37:54.277

4

SOGL V0.12, 225 bytes

R“EC"+w╗─║Z⁰2BΥø‘▓"▲╔⁸‘'²∙+"⅟Δλ≤LK⅟ΗΠ.JN║«⁸⅟‘▓+╬⁷"№D↓tι▲‛Q─Ρδν∙υ4Ρψ▲¦‽↑√Ε┐Ζ5↔‛⅟≤š▼¦⁾○ΔΡ%³‘ū91 tž85ž.ΖX Ο'⁹7žø]Xe@*c{leκψI1ž}_:@øŗ⁄c∑⁄≠}l{"T-)⅞↑°Χpjζ⅓īa0ε+Μ‛⁶ρ\=↔⅟¹‘ψ}¹K@Gŗ'¹nο²²Z+8«m«ο+I{@∑"0x0”Κ}¹6«n_'⁷1ž'⁵16«┐∙ž'⁸4 19∙ž89╬5

Try it Here!
Expects array input on the stack and the number input an an input, so →" is added in the online program for ease-of-use.

dzaima

Posted 2017-08-09T21:40:25.047

Reputation: 19 048

2

JavaScript (ES8), 639 bytes

(w,n,r=i=>Math.random()*i|0,s=b=>{for(i=b[k];i;i--)[b[i-1],b[j]]=[b[j=r(i)],b[i-1]]},a=Array(360-w[k="length"]*--w[0][k]),m=[...a].map((j,i)=>~(j=d.slice(0,w[k]).indexOf(i))?w[j]:`!"#$%&'()*+/:;<=>?@[\\]^_{|}`[r(27)],s(w),s(d=[...a.keys()])).join``.match(/.{15}/g).map((v,i)=>"0x"+(i+1).toString(16).padStart(2,0)+" "+v))=>`  _53
 / 53\\
| 5_45 5|
${["","Welcome to ROBCO Industries (TM) Termlink","Password Required","Attempts Remaining:"+" X".repeat(n),"",...m.slice(0,12).map((x,i)=>x+" | "+m[i+12])].map(x=>"| 4| "+x.padEnd(43)+" | 4|").join`
`}
| 4|_45| 4|
| 55|
\\_55/
 7\\_39/`.replace(/[_ ]([1-9]+)/g,(m,n)=>m[0].repeat(n))

The hex labels are in lowercase; if uppercase was required, that would be an additional 14 bytes for .toUpperCase().

Test Snippet

Better viewed over on CodePen.

Justin Mariner

Posted 2017-08-09T21:40:25.047

Reputation: 4 746

You can save a byte by currying the 2 parameters and moving your variables into the first repeat. – Shaggy – 2017-08-10T20:31:27.717