3 ! Release 8 / Serial number 19xxxx / Inform v6.34
5 ! [-] |\_/| http://www.robotfindskitten.org
6 ! (+)=C |o o|__ Leonard Richardson (C) 1997, 2000
7 ! | | --*--__\ David Griffith (C) 2002-2019 (Inform Edition)
11 ! This Zen simulation is based on the C version v1600003.248b
12 ! by Leonard Richardson (C) 1997, 2000.
13 ! Written originally for the Nerth Pork robotfindskitten contest.
14 ! Reimplemented in Inform by David Griffith (C) 2002.
16 ! Lots more information on robotfindskitten is available at
17 ! http://www.robotfindskitten.org.
19 ! This rendition of robotfindskitten is distributed under the Artistic
20 ! License 2.0. See the file LICENSE in the robotfindskitten repository
21 ! or https://opensource.org/licenses/Artistic-2.0 for more information.
23 ! In this game, you are Robot (#). Your job is to find Kitten. This
24 ! task is complicated by the existance of various things which are not
25 ! kitten. Robot must touch items to determine if they are Kitten or
26 ! not. Move Robot with the cursor keys, the numeric keypad, or
27 ! using the vi/rogue movement keys. The game ends when robotfindskitten.
28 ! Alternatively, you may end the game by hitting the Esc or Q keys.
31 ! 1) More than half of the code is taken up by non kitten items
32 ! (NKIs). When I compiled the code with just five messages and
33 ! no debugging code, the resulting binary was less than 10k bytes.
35 ! 2) If it wasn't already abundantly obvious, this program won't
36 ! compile to Glulx because of copious use of Z-machine assembly
39 ! 3) Compiling for V5 or higher is required due to "style" calls.
40 ! Is there a reason why someone would want to compile this for V4
48 Constant Nonkitten_Default 20;
50 ! Maxmimum possible number of non-kitten items on the playfield at once.
51 ! For whatever reason, this cannot be set dynamically.
53 Constant Nonkitten_Max 589;
58 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
60 Constant Story "robotfindskitten";
61 Constant Headline "^A Zen Simulation^";
63 ! NKIs are generated with nki2inf.pl and put into nki.inf
66 Constant Anim_Meet 10; ! Number of spaces from the left where
67 ! Robot and Kitten meet during animation.
69 Global Height = 0; ! These are set at runtime.
72 Global Back_def = 2; ! Black.
73 Global Fore_def = 9; ! White.
75 Global TopBar = 5; ! Lines from the top.
77 Global player_x = 0; ! Keeping track of where the player was
78 Global player_y = 0; ! 1 move ago allows us to keep the
79 Global player_x_last = 0; ! player from walking through obstacles.
80 Global player_y_last = 0;
84 Global kitten_char = 0;
85 Global kitten_color = 0;
87 Global last_message = ""; ! Always show the last-encountered message.
89 Global nonkitten_count;
91 Array nonkitten_x --> Nonkitten_Max;
92 Array nonkitten_y --> Nonkitten_Max;
93 Array nonkitten_color --> Nonkitten_Max;
94 Array nonkitten_char --> Nonkitten_Max;
95 Array nonkitten_msg --> Nonkitten_Max;
97 Global already_msg_count = 0;
98 Global already_count = 0;
99 Array already_x --> Nonkitten_Max + 2;
100 Array already_y --> Nonkitten_Max + 2;
101 Array already_msg --> Nonkitten_Max;
103 ! If a key is held down while the found_kitten animation is playing,
104 ! (0-->1) & $03ff gets corrupted. Seems like it might be a bug
105 ! somewhere in Unix Frotz.
107 Global Real_Release = 0;
110 @set_colour Fore_def Back_def;
112 if (MESSAGE_NUM < Nonkitten_Default) {
113 nonkitten_count = MESSAGE_NUM;
115 nonkitten_count = Nonkitten_Default;
118 Real_Release = (0-->1)&$03ff;
127 'F': already_count = 0;
133 'D': set_nonkitten_count();
134 'I': print_instructions();
136 'T': print_thoughts();
138 if (key == 'Q' || key == $1b) ! $1b == ESC
148 ! There's a 1:50 chance that the kitten in the title screen
149 ! will have a "psycho" appearance.
164 draw_big_robot(3, 7);
167 draw_big_kitten_psycho(14, 7);
169 draw_big_kitten(15, 7);
172 print "http://www.robotfindskitten.org";
174 print "Leonard Richardson (C) 1997, 2000";
176 print "David Griffith (C) 2002-2019 (Inform Edition)";
178 print " ", MESSAGE_NUM, " different nonkittens!";
182 print " F) Find Kitten^",
183 " D) Difficulty (", nonkitten_count, ")^",
192 ! Copied from module/verblibm.h of the Inform 6.21.3 standard library.
197 print (string) Story;
201 print (string) Headline;
203 print "Release ", Real_Release, " / Serial number ";
204 for (i=18:i<24:i++) print (char) 0->i;
205 print " / Inform v"; inversion; print "";
210 Constant INBUFSIZE 80;
211 Array inbuf -> INBUFSIZE;
213 [ set_nonkitten_count maxnum val;
222 if (MESSAGE_NUM < Nonkitten_Max) {
223 maxnum = MESSAGE_NUM;
225 maxnum = Nonkitten_Max;
228 print "^Please enter the number of nonkittens you
229 wish to search through.^(1 to ", maxnum, " only)^^> ";
232 val = get_number(1, maxnum, nonkitten_count);
236 nonkitten_count = val;
244 [ get_number min max init inbufvar ix cx len val;
246 inbuf->0 = (INBUFSIZE-3);
254 while (cx < len && inbuf->(2+cx) == ' ')
256 if (cx < len && inbuf->(2+cx) == '.')
259 ! If user just hits return, use what we have already.
262 if (cx == len || inbuf->(2+cx) < '0' || inbuf->(2+cx) > '9') {
263 print "Please enter a value from ", min, " to ", max,
264 ", or Enter by itself to exit.^
265 [Press any key to continue.] ";
270 while (cx < len && inbuf->(2+cx) >= '0' && inbuf->(2+cx) <= '9') {
271 val = val * 10 + (inbuf->(2+cx) - '0');
274 if (val < min || val > max) {
275 print "Please enter a value from ", min, " to ", max,
276 ", or Enter by itself to exit.^
277 [Press any key to continue.] ";
288 @split_window TopBar;
295 This Zen simulation is based on the C version v1600003.248b^
296 by Leonard Richardson (C) 1997, 2000.^
297 Written originally for the Nerth Pork robotfindskitten contest.^
298 Reimplemented in Inform by David Griffith (C) 2002.^
300 This code is distributed according to the Artistic License 2.0. See
301 https://opensource.org/licenses/Artistic-2.0 for more information. I,
302 David Griffith, retain copyright on this program except for the NKIs
303 imported from the master (aka POSIX) port.^
305 Lots more information on robotfindskitten is available at
306 http://www.robotfindskitten.org.^
308 To submit new NKI's, please go to the above URL.^
313 Release 1 / Serial number 0211xx to 021214 or so^
314 Initial private release. Limited distribution for beta testing and
317 Release 2 / Serial Number 021216^
318 First public release.^
320 Release 3 / Serial Number 021221^
322 - Movement keys 'J' and 'K' were swapped by mistake. Fixed.^
323 - Special PalmOS movement key support added.^
324 - More NKIs added (401 total).^
326 Release 4 / Serial Number 030131^
327 Light overhaul release.^
328 - Now an official port of robotfindskitten.^
329 - Typos in NKIs fixed.^
330 - Fixed diagonal collision-detection strangeness.^
331 - Added color support.^
332 - Added an easter egg. Can you find it?^
333 - Removed PalmOS movement key support (superfluous and ugly).^
334 - Removed playfield resizing code (superfluous and ugly).^
335 - It's ~robotfindskitten~, not ~Robot Finds Kitten~.^
336 - Merged in new NKIs from the new POSIX release of robotfindskitten.^
337 - More NKIs added (561 total).^
339 Release 5 / Serial Number 030524^
340 Even more NKIs release.^
341 - Idiotic typos fixed.^
342 - More NKIs added (602 total).^
344 Release 6 / Serial Number 031116^
346 - More NKIs added (764 total).^
347 - Increased maximum difficulty to 589.^
348 - Lots more comments in the source code.^
349 - Assorted cleanups in the source code.^
351 Release 7 / Serial Number 130320^
353 - Synchronized NKIs and removed redundancies with the POSIX port.^
354 - NKIs now generated from an external file using nki2inf.pl.^
355 - NKIs reduced to 723 because of redundancies and recommended deletions.^
357 Release 8 / Serial Number 19xxxx^
359 - Fixed a potential problem of wrongly determining screen size.^
360 - Now distributed under the Artistic License 2.0.^
365 1) I still don't know why already_seen_xy() occasionally causes Robot to
366 get placed on top of another object when a game is started. Fortunately
367 this seems to happen only very rarely and typically only if the
368 difficulty is set to more than 200. This bug also seems to very
369 occasionally put Kitten underneath an NKI.^
371 2) Under earlier versions of Windows Frotz, Robot used to appear as a
372 solid block. This was because of a bug in Windows Frotz which
373 incorrectly makes the cursor opaque. The cursor is now moved off to
374 the upper-right corner so that the game looks okay on terminals that use
375 something other than reverse for the cursor. I still can't figure out
376 how to make Inform hide the cursor completely. At least on xterm and
377 NetBSD's console, @@64set_cursor -1 doesn't work.^
379 3) Under Windows Frotz, an annoying [MORE] prompt might appear at the
380 main menu. This is another bug in Windows Frotz which causes the
381 interpreter to follow Windows' suggestion that something less than 24 or
384 [Press any key to continue.] ";
389 [ print_instructions;
391 @split_window TopBar;
397 In this game, you are Robot ( ";
398 style reverse; print "#"; style roman;
399 print " ). Your job is to find Kitten. This task is complicated by the
400 existance of various things which are not Kitten. Robot must touch
401 items to determine if they are Kitten or not. Move Robot with the
402 cursor keys, the numeric keypad (make sure numlock is on), or using the
403 vi/rogue/nethack movement keys. The game ends when robotfindskitten.
404 Alternatively, you may end the game by hitting the Esc or Q keys.^
406 [Press any key to continue.] ";
413 @split_window TopBar;
421 Day and night I feverishly worked upon the machine, creating both a soul
422 which could desire its goal, and a body with which it could realize
423 it. Many who saw my creation called it an abomination, and denied me
424 grant money. But they could not dissuade me from my impossible
425 task. It was a spectre that tormented me always, a ghost I had to give
426 a form and a life, lest it consume me from the inside. And when at last
427 my task was done, when the grey box on wheels was complete and when it,
428 as well as I, knew what had to be done, I felt deep sympathy for the
429 machine. For I had not destroyed the phantom, but merely exorcized it
430 into another body. The robot knew not why this task had to be
431 performed, for I could not imbue it with knowledge I did not myself
432 posess. And at the same time, I felt a sweeping sense of relief sweep
433 over me, that somehow, the dream that had driven me for my entire life
434 had come one step closer to fruition.^
436 ~Gort, Klaatu Verada Nikto~^
438 As I vocally activated the robot, I realized that it was following my
439 instructions, but not out of any desire to obey me. Had I remained
440 silent, it would have performed exactly the same operations. We were
441 two beings controlled by the same force now. And yet, seeking vainly to
442 hold some illusion of control over the machine I thought I had created,
443 I gave my final command.^
445 ~GO!~ I told the box as it began to roll out of my workshop into the
446 frozen desert beyond. ~FIND KITTEN!~^
448 -- The Book of Found Kittens, pages 43-4, author unknown.^
450 [Press any key to continue.] ";
455 [ draw_big_robot x y;
461 @set_colour 6 Back_def;
463 @set_colour 4 Back_def;
465 @set_colour 6 Back_def;
470 @set_colour 6 Back_def;
472 @set_colour 3 Back_def;
474 @set_colour 6 Back_def;
476 @set_colour 8 Back_def;
481 @set_colour 6 Back_def;
486 @set_colour 8 Back_def;
489 @set_colour Fore_def Back_def;
493 [ draw_big_kitten x y;
500 @set_colour 5 Back_def;
501 print "|", (char) 92, "_/|";
505 @set_colour 4 Back_def;
507 @set_colour 5 Back_def;
511 @set_colour 9 Back_def;
513 @set_colour 3 Back_def;
515 @set_colour 9 Back_def;
517 @set_colour 5 Back_def;
518 print "__", (char) 92;
523 @set_colour Fore_def Back_def;
527 [ draw_big_kitten_psycho x y;
534 @set_colour 5 Back_def;
535 print " |", (char) 92, "_/|";
538 @set_colour 4 Back_def;
540 @set_colour 5 Back_def;
544 @set_colour 9 Back_def;
546 @set_colour 3 Back_def;
548 @set_colour 9 Back_def;
550 @set_colour 5 Back_def;
551 print "__", (char) 92;
556 @set_colour Fore_def Back_def;
560 ! Something gets messed up if I make this local to findkitten()
561 ! When going right or left, then up or down to hit the Kitten, the
562 ! animation gets reversed.
564 Global last_right = false;
568 @split_window TopBar;
573 print (string) last_message;
576 draw_object(kitten_x, kitten_y, kitten_char, kitten_color);
580 draw_object(player_x, player_y, '#');
591 player_x_last = player_x;
592 player_y_last = player_y;
594 'Q', $1b: rfalse; ! exit game ($1b == Esc)
595 '8', 'K', 129: player_y--; ! up
596 '2', 'J', 130: player_y++; ! down
597 '4', 'H', 131: player_x--; ! left
599 '6', 'L', 132: player_x++; ! right
602 '7', 'Y': player_y--; player_x--; ! up-left
604 '9', 'U': player_y--; player_x++; ! up-right
606 '1', 'B': player_y++; player_x--; ! down-left
608 '3', 'N': player_y++; player_x++; ! down-right
612 ! Keep Robot from falling off edges of playfield.
614 if (player_y == TopBar || player_y > Height) {
615 player_y = player_y_last;
617 if (player_x < 1 || player_x > Width) {
618 player_x = player_x_last;
621 ! Detect and handle collisions.
623 if (player_x == kitten_x && player_y == kitten_y) {
624 animate_kitten(key, last_right);
628 for (i = 0: i < nonkitten_count: i++) {
629 if (player_x == nonkitten_x-->i
630 && player_y == nonkitten_y-->i) {
632 last_message = lookup_msg(nonkitten_msg-->i);
633 player_x = player_x_last;
634 player_y = player_y_last;
641 [ animate_kitten key my_last_right i j junk robot_x anim_finished;
643 '8', 'J', 129: player_y++;
644 '2', 'K', 130: player_y--;
645 '4', 'H', 131: player_x++;
646 '6', 'L', 132: player_x--;
647 '7', 'Y': player_y++; player_x++;
648 '9', 'U': player_y++; player_x--;
649 '1', 'B': player_y--; player_x++;
650 '3', 'N': player_y--; player_x--;
653 anim_finished = false;
654 for (i = 4: i >= 0: i--) {
656 @split_window TopBar;
665 robot_x = Anim_Meet - i;
667 draw_object(robot_x, TopBar - 1, '#');
669 draw_object(Anim_Meet - 1 + i, TopBar - 1,
670 kitten_char, kitten_color);
672 robot_x = Anim_Meet - 1 + i;
674 draw_object(robot_x, TopBar - 1, '#');
676 draw_object(Anim_Meet - i, TopBar - 1,
677 kitten_char, kitten_color);
682 print "You found Kitten! Way to go, Robot!";
683 anim_finished = true;
686 draw_object(kitten_x, kitten_y, kitten_char, kitten_color);
689 draw_object(player_x, player_y, '#');
693 if (anim_finished == false) {
696 @read_char 1 10 pause -> junk;
697 @nop; ! This is for padding.
700 draw_object(player_x, player_y, '#');
708 [ already_seen_xy x y i;
709 for (i = 0: i < already_count: i++) {
710 if (already_x-->already_count == x &&
711 already_y-->already_count ==y) {
715 already_x-->already_count = x;
716 already_y-->already_count = y;
728 kitten_x = get_random_x();
729 kitten_y = get_random_y();
730 kitten_color = get_random_color();
731 while (already_seen_xy(kitten_x, kitten_y) == true) {
732 kitten_x = get_random_x();
733 kitten_y = get_random_y();
735 kitten_char = get_random_char();
740 player_x = get_random_x();
741 player_y = get_random_y();
742 while (already_seen_xy(player_x, player_y) == true) {
743 player_x = get_random_x();
744 player_y = get_random_y();
750 already_msg_count = 0;
752 for (i = 0: i < nonkitten_count: i++) {
753 nonkitten_x-->i = get_random_x();
754 nonkitten_y-->i = get_random_y();
755 nonkitten_color-->i = get_random_color();
756 while (already_seen_xy(nonkitten_x-->i,
757 nonkitten_y-->i) == true) {
758 nonkitten_x-->i = get_random_x();
759 nonkitten_y-->i = get_random_y();
761 nonkitten_char-->i = get_random_char();
762 nonkitten_msg-->i = get_random_msg();
768 for (i = 0: i < nonkitten_count: i++) {
769 draw_object(nonkitten_x-->i,
772 nonkitten_color-->i);
777 [ draw_object x y character fore back;
785 @set_colour fore Back_def;
787 print (char) character;
789 @set_colour Fore_def Back_def;
795 for (i = 0 : i < Width : i++)
802 if (x >= 'a' && x <= 'z')
808 [ get_random_char num;
811 while (num == 35) { ! avoid choosing '#'
819 [ get_random_msg num;
820 num = random(MESSAGE_NUM);
821 while (is_duplicate_msg(num) == true) {
822 num = random(MESSAGE_NUM);
828 [ get_random_color num;
830 ! 0 and 1 are default color and current color
831 ! and we want to avoid picking the default color explicitly
832 while (num == $2c-->0) {
839 [ is_duplicate_msg num i;
840 for (i = 0: i < already_msg_count: i++) {
841 if (already_msg-->i==num) {
845 already_msg-->already_msg_count = num;
852 ! Maybe this will need to do something more in the future.
853 return random(Width);
858 ! Make sure we don't draw in the status bar.
860 num = random(Height);