11
\$\begingroup\$

Warning: This challenge contains some mild spoilers for The Secret of Monkey Island.

Towards the end of the game, you're being led through the catacombs by a magically preserved head of a navigator:

enter image description here

You need its eyeball necklace, but the Head is reluctant to give it to you. One way to get it is just to keep begging:

Guybrush: May I please have that necklace?
Head: No, but thanks for asking so politely.
Guybrush: Oh come on, pleeeeease?
Head: You can beg all you want, but you can't have it.
Guybrush: Pretty please?
Head: You can beg all you want, but you can't have it.
Guybrush: Pretty PRETTY please?
Head: You can beg all you want, but you can't have it.
Guybrush: Pretty please with sugar on top?
Head: Oh, all right, you big baby. You can have it. Hey, what good's a necklace if you don't have shoulders?

The Challenge

Write a full program which prints the above dialogue. The catch is that each time the program is called it should only print two lines (one pleading by Guybrush and the Head's response). E.g. if your submission is written in Python, usage should look like this:

$> python please.py
Guybrush: May I please have that necklace?
Head: No, but thanks for asking so politely.
$> python please.py
Guybrush: Oh come on, pleeeeease?
Head: You can beg all you want, but you can't have it.
$> python please.py
Guybrush: Pretty please?
Head: You can beg all you want, but you can't have it.
$> python please.py
Guybrush: Pretty PRETTY please?
Head: You can beg all you want, but you can't have it.
$> python please.py
Guybrush: Pretty please with sugar on top?
Head: Oh, all right, you big baby. You can have it. Hey, what good's a necklace if you don't have shoulders?

Invoking the program more than 5 times may result in undefined behaviour, so you could either loop, keep printing the last two lines or the program could even be broken after the 5th invocation.

You may write to a file in the working directory, or you can modify the source code of the program itself to keep track of invocations. In the latter case, your program must not depend its own filename. (In the former case, you can assume that your program's file name will not clash with any file names your program depends on.)

You must not assume a REPL-like environment or that any data is kept in RAM between invocations. E.g. if you answer in Mathematica, you have to assume that I quit the kernel between invocations.

This is code golf, the shortest answer (in bytes) wins. If your program depends on any additional files to exist before the first invocation, add its name and contents to your byte count.

\$\endgroup\$
  • \$\begingroup\$ So no putting value to global variables and then reusing in JS ? \$\endgroup\$ – Optimizer Sep 22 '14 at 18:02
  • \$\begingroup\$ @Optimizer Nope, sorry. I think if you want to use JS for this one, you'll have to use node. \$\endgroup\$ – Martin Ender Sep 22 '14 at 18:04
  • \$\begingroup\$ We can have global variables in node as well. Are you suggesting that wrt node, we should be able to exit node and still continue on the dialogue sequence ? \$\endgroup\$ – Optimizer Sep 22 '14 at 18:08
  • \$\begingroup\$ @Optimizer Yes. You should write a full program, which I can invoke 5 times with node please.js yielding 5 different outputs. \$\endgroup\$ – Martin Ender Sep 22 '14 at 18:09
  • \$\begingroup\$ Can my program depend on an external file to start off? I'll include its byte count in my score \$\endgroup\$ – Claudiu Sep 22 '14 at 18:26
9
\$\begingroup\$

Python, 224 + 97 + 1 = 322 characters

A most straightforward solution to start us all off. Thanks to gnibbler for helping me shave off 18 bytes!

n=0
print open('z','rb').read().decode('zip').split('|')[n]
open(__file__,'r+').write("n="+`n+1`)

Requires the file z to be present in the same directory (+1 for filename, +224 for file size):

$ hexdump z
0000000 9c78 d1ad 6e3d 30c3 050c bde0 78a7 165b
0000010 0723 92c8 48a9 b43a 8209 192c 9b29 0491
0000020 a2ab 9fa1 021a f87a 715a f46c d100 1026
0000030 1efc 1e41 5172 4721 c3b3 1527 607c 4c70
0000040 6191 87e8 0c91 7825 7b6e 2d47 dfef 4c8e
0000050 0edd d25f e540 8b54 8fbe 4bb8 c500 7ade
0000060 288d c418 c4d9 6cae 0f7f 7bab 6832 9be5
0000070 be21 7aa9 537d c2c2 24dd 25a3 c50f e41a
0000080 ca1c 1ff4 a7c9 a439 d5cc 9a4d b207 3fe9
0000090 0e7c 529c 4e79 3afc 7cef bf79 6f5e 672f
00000a0 8b9f 6d1d 8832 5359 1698 2482 92c3 3270
00000b0 43cd 560e 899b a4ad 1ab2 548a aed9 0bf1
00000c0 238f 0697 bd63 168f 36e9 b411 0a1e fef6
00000d0 eee8 1d64 1a28 aec9 10e3 7ff7 3a0b d9ab
00000e0

$ ls -l z
-rw-r--r--+ 1 Laxori mkpasswd 224 2014-09-22 22:35 z

You can generate z with the following:

>>> open('z','wb').write("""eJyt0T1uwzAMBeC9p3hbFiMHyJKpSDq0CYIsGSmbkQSroqGfGgJ6+FpxbPQA0SYQ/B5BHnJRIUez
wycVfGBwTJFh6IeRDCV4bntHLe/fjkzdDl/SQOVUi76PuEsAxd56jSgYxNnErmx/D6t7MmjlmyG+
qXp9U8LC3SSjJQ/FGuQcyvQfyac5pMzVTZoHsuk/fA6cUnlO/DrvfHm/Xm8vZ5+LHW0yiFlTmBaC
JMOScDLNQw5Wm4mtpLIailTZrvELjyOXBmO9jxbpNhG0Hgr2/ujuZB0oGsmu4xD3fws6q9k=""".decode('base64'))

Output:

$ python monkeyisland.py
Guybrush: May I please have that necklace?
Head: No, but thanks for asking so politely.
$ python monkeyisland.py
Guybrush: Oh come on, pleeeeease?
Head: You can beg all you want, but you can't have it.
$ python monkeyisland.py
Guybrush: Pretty please?
Head: You can beg all you want, but you can't have it.
$ python monkeyisland.py
Guybrush: Pretty PRETTY please?
Head: You can beg all you want, but you can't have it.
$ python monkeyisland.py
Guybrush: Pretty please with sugar on top?
Head: Oh, all right, you big baby. You can have it. Hey, what good's a necklace if you don't have shoulders?
$ python monkeyisland.py
Traceback (most recent call last):
  File "monkeyisland.py", line 2, in <module>
    print open('z','rb').read().decode('zip').split('|')[n]
IndexError: list index out of range
\$\endgroup\$
  • 1
    \$\begingroup\$ Use a different delimiter for between the pairs of lines, so for example you have line1\nline2|line3\nline4|line5\nline6|line7\nline8|line9\nline10 Now you can split on | and just print D[n] \$\endgroup\$ – gnibbler Sep 23 '14 at 0:40
  • \$\begingroup\$ @gnibbler: Well spotted sir! \$\endgroup\$ – Claudiu Sep 23 '14 at 2:46
5
\$\begingroup\$

Common Lisp (SBCL) : 659 characters

(defparameter *d*
  '#1=("~A May I please have that necklace?"
       "~A No, but thanks for asking so politely."
       "~A Oh come on, pleeeeease?"
       #2="~A You can beg all you want, but you can't have it."
       "~A Pretty please?"
       #2#
       "~A Pretty PRETTY please?"
       #2#
       "~A Pretty please with sugar on top?"
       "~A Oh, all right, you big baby. You can have it. Hey, what good's a necklace if you don't have shoulders?" . #1#))
(defun d ()
  (format t (pop *d*) "Guybrush:") (terpri)
  (format t (pop *d*) "Head:") (terpri)
  (terpri)
  (finish-output)
  (sb-ext:save-lisp-and-die "please" :toplevel 'd :executable t))
(d)

Explanations

  • I dump the lisp image after each invocation, which saves current state.
  • The circular list let me restart the dialogue after all lines have been displayed (not required, but at least it doesn't error on format with nil).
  • Reader macros allow me to reuse some identical lines.

This won't be the shortest submission, but I thought this was a nice approach to the problem.

Firt invocation

 $sbcl --noinform --noprint --load please.lisp
 Guybrush: May I please have that necklace?
 Head: No, but thanks for asking so politely.

 [undoing binding stack and other enclosing state... done]
 [saving current Lisp image into please:
 writing 5856 bytes from the read-only space at 0x0x20000000
 writing 4032 bytes from the static space at 0x0x20100000
 writing 67960832 bytes from the dynamic space at 0x0x1000000000
 done]

Subsequent invocations

$./please 
Guybrush: Oh come on, pleeeeease?
Head: You can beg all you want, but you can't have it.

[undoing binding stack and other enclosing state... done]
[saving current Lisp image into please:
writing 5856 bytes from the read-only space at 0x0x20000000
writing 4032 bytes from the static space at 0x0x20100000
writing 68091904 bytes from the dynamic space at 0x0x1000000000
done]

$./please 
Guybrush: Pretty please?
Head: You can beg all you want, but you can't have it.

[undoing binding stack and other enclosing state... done]
[saving current Lisp image into please:
writing 5856 bytes from the read-only space at 0x0x20000000
writing 4032 bytes from the static space at 0x0x20100000
writing 68091904 bytes from the dynamic space at 0x0x1000000000
done]
\$\endgroup\$
3
\$\begingroup\$

C# - 593 + 1 + 1 Characters (595)

Edits: Updated with suggestions from Martin and various other optimisations

First +1 is a filename. Second +1 is contents of that file. Without all the spaces and line breaks removed so you can read it:

using System.IO;
using s=System.String;
class P
{
    static void Main()
    {
        s g="Guybrush: ",h="Head: ",p=" please",q="Pretty";
        s[]b=new s[]{"May I"+p+" have that necklace","No, but thanks for asking so politely.",
        "Oh come on, pleeeeease","You can beg all you want, but you can't have it.",q+p,
        "Oh, all right, you big baby. You can have it. Hey, what good's a necklace if you don't have shoulders?",
        q+" PRETTY"+p,"",q+p+" with sugar on top"};
        int a=int.Parse(File.ReadAllText("x",System.Text.Encoding.UTF8));
        System.Console.WriteLine(g+b[a]+"?\n"+h+b[(a+5)/6*2+1]);
        File.WriteAllText("x",(a+2).ToString());
    }
}

Explanation

Relies on a text file called "x" to be present in the directory. Should initially contain a zero and is used to store progress.

Program plucks relevant element out of the string array according to progress and writes progress at end. Some lines reused to shorten length, hence index selection logic h+b[(a+5)/6*2+1] for answer selection.

Output

D:\Projects\Junk\MI\bin\Debug>MI
Guybrush: May I please have that necklace?
Head: No, but thanks for asking so politely.

D:\Projects\Junk\MI\bin\Debug>MI
Guybrush: Oh come on, pleeeeease?
Head: You can beg all you want, but you can't have it.

D:\Projects\Junk\MI\bin\Debug>MI
Guybrush: Pretty please?
Head: You can beg all you want, but you can't have it.

D:\Projects\Junk\MI\bin\Debug>MI
Guybrush: Pretty PRETTY please?
Head: You can beg all you want, but you can't have it.

D:\Projects\Junk\MI\bin\Debug>MI
Guybrush: Pretty please with sugar on top?
Head: Oh, all right, you big baby. You can have it. Hey, what good's a necklace
if you don't have shoulders?

D:\Projects\Junk\MI\bin\Debug>

My first code golf, probably not the shortest possible in C# but hey - Monkey Island, couldn't resist!

Stripped code:

using System.IO;using s=System.String;class P{static void Main(){s g="Guybrush: ",h="Head: ",p=" please",q="Pretty";s[]b=new s[]{"May I"+p+" have that necklace","No, but thanks for asking so politely.","Oh come on, pleeeeease","You can beg all you want, but you can't have it.",q+p,"Oh, all right, you big baby. You can have it. Hey, what good's a necklace if you don't have shoulders?",q+" PRETTY"+p,"",q+p+" with sugar on top"};int a=int.Parse(File.ReadAllText("x",System.Text.Encoding.UTF8));System.Console.WriteLine(g+b[a]+"?\n"+h+b[(a+5)/6*2+1]);File.WriteAllText("x",(a+2).ToString());}}
\$\endgroup\$
  • 1
    \$\begingroup\$ Welcome to PPCG! A few golfing tips: I think you can simplify that ternary operator a bit. At least to a<1?1:a<8?3:9, if C# supports truthy integers, then also a?a<8?3:9:1. But you can probably even make use of integer division and do (a+5)/6*2 and move the final string of the head to replace the first empty one (index 5). And try stuff like using s=System.String;. (Oh and you might be able to omit the namespace, or even use namespace System to avoid System in all the using.) \$\endgroup\$ – Martin Ender Sep 23 '14 at 12:00
  • \$\begingroup\$ So I can. All this learning to code for maintainability is really putting me at a disadvantage here ;) \$\endgroup\$ – Gareth Sep 23 '14 at 13:33
3
\$\begingroup\$

JS, 488 473

Refreshing 5 times the page containing this code displays the 5 different dialogs.

l=localStorage;a="<p>Guybrush: ";b=a+"Pretty please";d="<br>Head: ";c=d+"You can beg all you want, but you can't have it.";document.write(a+"May I please have that necklace?"+d+"No, but thanks for asking so politely."+a+"Oh come on, pleeeeease?"+c+b+"?"+c+a+"Pretty PRETTY please?"+c+b+" with sugar on top?"+d+"Oh, all right, you big baby. You can have it. Hey, what good's a necklace if you don't have shoulders?<style>p:not(:nth-child("+(l[0]=~~l[0]+1)+")){display:none")

Demo:

http://c99.nl/f/212197.html

\$\endgroup\$
2
\$\begingroup\$

Perl - 356 bytes

2=~//;@d=qw"No6|thanks|for|asking|so|pol8ely. 5|beg72want62can't18.
Oh,7|right,2big|baby.|518.|Hey,|what|good's|a4|if2don't1shoulders?
May|I01that4 Oh|come|on,|pleeeeease 30 3|PRETTY0
30|w8h|sugar|on|top";print"Guybrush: $d[$'+print F$'+sysopen F,$0,1]?
Head: $d[$'/3]"=~s/\d/qw(|please |have| |you| Pretty |necklace You|can
,|but |all it)[$&]/ger=~y/|/ /r

A self-modifying approach, with substitutions for common strings.

Sample Usage:

$ perl please.pl
Guybrush: May I please have that necklace?
Head: No, but thanks for asking so politely.

$ perl please.pl
Guybrush: Oh come on, pleeeeease?
Head: You can beg all you want, but you can't have it.

$ perl please.pl
Guybrush: Pretty please?
Head: You can beg all you want, but you can't have it.

$ perl please.pl
Guybrush: Pretty PRETTY please?
Head: You can beg all you want, but you can't have it.

$ perl please.pl
Guybrush: Pretty please with sugar on top?
Head: Oh, all right, you big baby. You can have it. Hey, what good's a necklace if you don't have shoulders?
\$\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.