Ticking Quine-Bomb!

Challenge:

Create a program or function that takes an integer input, which outputs a new program/function as specified below.

Input:

Integer n: Time in seconds before the Time Bomb explodes.

Output:

The original program which had the time in seconds n as input, will output a new program/function that does the following:

• Has n seconds passed since the previous program was run? Print BOOM!
• Else: Print a program/function which, when run itself, resets the timer back to n seconds (and acts the same as the first outputted program/function).

NOTE: It is not exactly the same as the first outputted program/function (in most languages at least), because the starting time has changed (see clarification example below).

Pseudo-code Example:

Let's say the original program is ABC and the input is 60 seconds:

ABC & 60 outputs DEF(60).

• If DEF(60) is run within 60 seconds, it will output DEF_G(60), which acts exactly the same as DEF(60), but with a new starting time.
• If DEF(60) is run after 60 seconds, it will output BOOM!.

Clarification example what I mean with 'starting time':

1. Base program with input 60 seconds is run at 12:00:00. It outputs the first output program with a starting time of 12:00:00.
2. This first output program with starting time of 12:00:00 is run at 12:00:45. It outputs a second output program with a starting time of 12:00:45.
3. This third output program with a starting time of 12:00:45 is run at 12:01:25. It outputs a fourth output program with a starting time of 12:01:25.
4. This fourth output program with a starting time of 12:01:25 is run at 12:05:00. It will output BOOM!.

Note how the first output would print BOOM! after 12:01:00, but the output program has progressed so even though it's 12:01:25 at step 3, it will still output the next program instead of BOOM! (because the output-of-output programs has starting times beyond that first output program).

Challenge Rules:

• Default quine rules apply.
• At least n seconds should have passed. So if the input is 60 and starting time was 12:00:00, at 12:01:00 it will still output the v2 program, but at 12:01:01 it will output BOOM!.
• The output programs will not take any input (except for an empty unused parameter if it's shorter). The starting time should be given to the next programs as 'hard-coded' value (which is why the output of an output program isn't exactly the same as the previous (in most languages).
• Only the size of your main program/function is counted in terms of bytes.
• You can output the program/function either as string (or comparable reasonable format, like byte/character array/list), as function if your language supports this, or other reasonable formats (please ask if you aren't sure).

General rules:

• This is , so shortest answer in bytes wins.
Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
• Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
• Default Loopholes are forbidden.
• What does "output a program" mean? output source code as string? or returning a function? – tsh Mar 27 '18 at 9:06
• @tsh Added a rule to allow both string and function. – Kevin Cruijssen Mar 29 '18 at 13:27

JavaScript, 51 bytes

f=(t,o=setTimeout(_=>o=0,t*1e3))=>_=>o?f(t):'BOOM!'

Test in browser

old version

f=(t,o=0)=>{setTimeout(()=>o=1,t*1000);return ()=>o?'BOOM!':f(t)}

Test in browser

• Looks like it isn't working as expected. – Maarten Bicknese Mar 27 '18 at 9:54
• You may delete the post, and undelete it once fixed, to avoid any down votes. – tsh Mar 27 '18 at 11:02
• You can golf the space at return()=>. And although I almost never program in JavaScript, I checked your test-script and even modified it by adding a test for the function of function output: Test it here with fourth function-of-function test. Everything seems to work, and it's surprisingly short I might add, so +1 from me. PS: In the rules it stated it should output a string instead of a function. But I'll change the rules a bit to allow both. Could you perhaps modify the script so it also outputs the functions to log during the test? – Kevin Cruijssen Mar 29 '18 at 13:25
• f=(t,o=setTimeout(_=>o=0,t*1e3))=>_=>o?f(t):'BOOM!' should work – tsh Mar 30 '18 at 2:15
• Are you a wizard?! Never thought of using logic as parameter default value 🤩 – Maarten Bicknese Mar 30 '18 at 6:56

JavaScript, 53 bytes

f=(d,t=1/0,n=Date.now()/1e3)=>n>t?'BOOM!':_=>f(d,d+n)

g=
f=(d,t=1/0,n=Date.now()/1e3)=>n>t?'BOOM!':_=>f(d,d+n)

// please notice that delay may take longer time than experted time on a slow / busy machine
// which may lead an incorrect result
delay=n=>new Promise(r=>setTimeout(r,n*1e3));

assertFine=s=>console.log(s!=='BOOM!'?s:'FAIL');
assertBoom=s=>console.log(s==='BOOM!'?s:'FAIL');

(async function () {
console.log('start test');
let p1 = g(3);
assertFine(p1); // should not boom
await delay(2);
let p2 = p1();
assertFine(p2); // should not boom
await delay(2);
let b1 = p1();
assertBoom(b1); // should boom
let p3 = p2();
assertFine(p3); // should not boom
await delay(2);
let b2 = p2();
assertBoom(b2); // should boom
}());

Old answer (returning should be a string)

JavaScript, 78 bytes

(f=(o,t,d)=>(x=d,n=Date.now()/1e3)=>o&&n>t?'BOOM!':(f=${f})(${[1,n+x,x]}))()

g=
(f=(o,t,d)=>(x=d,n=Date.now()/1e3)=>o&&n>t?'BOOM!':(f=${f})(${[1,n+x,x]}))()

// please notice that delay may take longer time than experted time on a slow / busy machine
// which may lead an incorrect result
delay=n=>new Promise(r=>setTimeout(r,n*1e3));

assertFine=s=>console.log(s!=='BOOM!'?s:'FAIL');
assertBoom=s=>console.log(s==='BOOM!'?s:'FAIL');

(async function () {
console.log('start test');
let p1 = g(3);
assertFine(p1); // should not boom
await delay(2);
let p2 = eval(p1)();
assertFine(p2); // should not boom
await delay(2);
let b1 = eval(p1)();
assertBoom(b1); // should boom
let p3 = eval(p2)();
assertFine(p3); // should not boom
await delay(2);
let b2 = eval(p2)();
assertBoom(b2); // should boom
}());

• Nice answer, and surprisingly readable. I did some testing and everything seems to work just fine. +1 from me. – Kevin Cruijssen Mar 27 '18 at 10:12

Java 8, 234 bytes

n->"v->{long t=System.nanoTime();t/=1e9;String s=\"v->{long t=System.nanoTime();t/=1e9;String s=%c%s%1$c;return t-%d>"+n+"?%1$cBOOM!%1$c:s.format(s,34,s,t);}\";return t-"+(System.nanoTime()/1e9)+">"+n+"?\"BOOM!\":s.format(s,34,s,t);}" Sorry to post my own challenge right away. It is mainly meant as further clarification of the challenge, and I was doubting whether to add it to the question itself or post it as an answer (and decided to post it as an answer to not clutter the challenge post). And although I would like to say it's also something to (try and) beat, that isn't even worth mentioning because, well.. Java (almost) always gets beaten. ;p Try it online. Example output: v->{long t=System.nanoTime();t/=1e9;String s="v->{long t=System.nanoTime();t/=1e9;String s=%c%s%1$c;return t-%d>60?%1$cBOOM!%1$c:s.format(s,34,s,t);}";return t-70492.687613232>60?"BOOM!":s.format(s,34,s,t);}

Try the outputted lambda-function here.

Example output:

v->{long t=System.nanoTime();t/=1e9;String s="v->{long t=System.nanoTime();t/=1e9;String s=%c%s%1$c;return t-%d>60?%1$cBOOM!%1$c:s.format(s,34,s,t);}";return t-70548>60?"BOOM!":s.format(s,34,s,t);} Explanation: The main function takes an integer input and returns a String. It basically returns a function which is a quine, with the integer input and starting time (in seconds as timestamp) as hard-coded values. Main function: n-> // Method with integer parameter and String return-type "v->{long t=System.nanoTime();t/=1e9;String s=\"v->{long t=System.nanoTime();t/=1e9;String s=%c%s%1$c;return t-%d>"
//  First part of the output-function
+n      //  With the integer input placed as hard-coded value
+"?%1$cBOOM!%1$c:s.format(s,34,s,t);}\";return t-"
//  The second part of the output-function
+(System.nanoTime()/1e9)
//  With the current time in seconds as hard-coded starting time
+">"+n  //  And the integer input again (for the output of the output function)
+"?\"BOOM!\":s.format(s,34,s,t);}"
//  The final part of the output-function

n=60 was used in the examples below:

First output program:

v->{                   // Method with empty unused parameter and String return-type
long t=System.nanoTime();t/=1e9;
//  New starting time in seconds
String s="v->{long t=System.nanoTime();t/=1e9;String s=%c%s%1$c;return t-%d>60?%1$cBOOM!%1$c:s.format(s,34,s,t);}"; // Unformatted (quine) result-function return t- // If the difference between the new starting time 70492.687613232 // and hard-coded starting time from the main function >60? // is larger than the hard-coded integer from the main function "BOOM!" // Return "BOOM!" : // Else: s.format(s,34,s, // Return the formatted (quine) result-function, t);} // with this new starting time as new hardcoded value Second output program: The same as the first output program, except that 70492.687613232 is replaced with 70548. Perl 5 + -p, 88 bytes$_="$s=_;$t=$^T;".'$_=q{say$^T-$t<$s?qq{$t=^T;$s=$s;\$_=q{$_};eval}:"BOOM!"};eval'

Output programs must be run with -M5.010 for say, but not -p.

Try it online!

05AB1E, 50 bytes

Can definitely be golfed a bit more, but it's quite tricky to output a semi-quine which outputs a quine-program with modified values.

Explanation:

"‘ÒÞ!"                     # Push the string "‘ÒÞ!"
"žažb‚žcª60β"              # Push the string "žažb‚žcª60β"
D                         # Duplicate it
.V                       # Execute it as 05AB1E code:
#  ža          : Push the current hours
#    žb        : Push the current minutes
#      ‚       : Pair them together
#       žcª    : Append the current seconds
#          60β : Convert from this integer list to base-60
s                          # Swap the seconds-integer and duplicated "žažb‚žcª60β"-string
I                          # Push the input
# where the ÿ are automatically replaced with the stack-values
D«                        # Duplicate it, and append them together
# (after which the string is output implicitly as result)

Example resulting program:

Which is based on the default quine: "34çìD«"34çìD«.

# Push this string
34ç                       # Push 34, converted to a character: '"'
ì                      # Prepend it in front of the string
D«                    # Duplicate this string, and append them together
# (we now have the quine-string at the top of the stack)
žažb‚žcª60β              # Get the current time in seconds similar as above
©             # Store it in variable ® (without popping)
35555        # Push the time this program was generated
DU      # Store a copy in variable X
-     # Subtract the two times
30                    ›i   # If the original input-integer is larger than this:
X®:                      #  Replace integer X with ® in the generated quine-string
ë   # Else:
‘ÒÞ!                     #  Push dictionary string "BOOM!"
# (and output the top of the stack implicitly as result)

See this 05AB1E tip of mine (section How to use the dictionary?) to understand why ‘ÒÞ! is "BOOM!".
NOTE: The reason the space is there between çì is because otherwise it's interpret as a dictionary-string (triumph) due to the ’...’.