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.
20 ! In this game, you are Robot (#). Your job is to find Kitten. This
21 ! task is complicated by the existance of various things which are not
22 ! kitten. Robot must touch items to determine if they are Kitten or
23 ! not. Move Robot with the cursor keys, the numeric keypad, or
24 ! using the vi/rogue movement keys. The game ends when robotfindskitten.
25 ! Alternatively, you may end the game by hitting the Esc or Q keys.
29 ! 1) More than half of the code is taken up by non kitten items
30 ! (NKIs). When I compiled the code with just five messages and
31 ! no debugging code, the resulting binary was less than 10k bytes.
33 ! 2) If it wasn't already abundantly obvious, this program won't
34 ! compile to Glulx because of copious use of Z-machine assembly
37 ! 3) Compiling for V5 or higher is required due to "style" calls.
38 ! Is there a reason why someone would want to compile this for V4
46 Constant Nonkitten_Default 20;
48 ! Maxmimum possible number of non-kitten items on the playfield at once.
49 ! For whatever reason, this cannot be set dynamically.
51 Constant Nonkitten_Max 589;
56 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
58 Constant Story "robotfindskitten";
59 Constant Headline "^A Zen Simulation^";
61 ! NKIs are generated with nki2inf.pl and put into nki.inf
64 Constant Anim_Meet 10; ! Number of spaces from the left where
65 ! Robot and Kitten meet during animation.
67 Global Height = 0; ! These are set at runtime.
70 Global Back_def = 2; ! Black.
71 Global Fore_def = 9; ! White.
73 Global TopBar = 5; ! Lines from the top.
75 Global player_x = 0; ! Keeping track of where the player was
76 Global player_y = 0; ! 1 move ago allows us to keep the
77 Global player_x_last = 0; ! player from walking through obstacles.
78 Global player_y_last = 0;
82 Global kitten_char = 0;
83 Global kitten_color = 0;
85 Global last_message = ""; ! Always show the last-encountered message.
87 Global nonkitten_count;
89 Array nonkitten_x --> Nonkitten_Max;
90 Array nonkitten_y --> Nonkitten_Max;
91 Array nonkitten_color --> Nonkitten_Max;
92 Array nonkitten_char --> Nonkitten_Max;
93 Array nonkitten_msg --> Nonkitten_Max;
95 Global already_msg_count = 0;
96 Global already_count = 0;
97 Array already_x --> Nonkitten_Max + 2;
98 Array already_y --> Nonkitten_Max + 2;
99 Array already_msg --> Nonkitten_Max;
101 ! If a key is held down while the found_kitten animation is playing,
102 ! (0-->1) & $03ff gets corrupted. Seems like it might be a bug
103 ! somewhere in Unix Frotz.
105 Global Real_Release = 0;
108 @set_colour Fore_def Back_def;
110 if (MESSAGE_NUM < Nonkitten_Default) {
111 nonkitten_count = MESSAGE_NUM;
113 nonkitten_count = Nonkitten_Default;
116 Real_Release = (0-->1)&$03ff;
125 'F': already_count = 0;
131 'D': set_nonkitten_count();
132 'I': print_instructions();
134 'T': print_thoughts();
136 if (key == 'Q' || key == $1b) ! $1b == ESC
146 ! There's a 1:50 chance that the kitten in the title screen
147 ! will have a "psycho" appearance.
162 draw_big_robot(3, 7);
165 draw_big_kitten_psycho(14, 7);
167 draw_big_kitten(15, 7);
170 print "http://www.robotfindskitten.org";
172 print "Leonard Richardson (C) 1997, 2000";
174 print "David Griffith (C) 2002-2019 (Inform Edition)";
176 print " ", MESSAGE_NUM, " different nonkittens!";
180 print " F) Find Kitten^",
181 " D) Difficulty (", nonkitten_count, ")^",
190 ! Copied from module/verblibm.h of the Inform 6.21.3 standard library.
195 print (string) Story;
199 print (string) Headline;
201 print "Release ", Real_Release, " / Serial number ";
202 for (i=18:i<24:i++) print (char) 0->i;
203 print " / Inform v"; inversion; print "";
208 Constant INBUFSIZE 80;
209 Array inbuf -> INBUFSIZE;
211 [ set_nonkitten_count maxnum val;
220 if (MESSAGE_NUM < Nonkitten_Max) {
221 maxnum = MESSAGE_NUM;
223 maxnum = Nonkitten_Max;
226 print "^Please enter the number of nonkittens you
227 wish to search through.^(1 to ", maxnum, " only)^^> ";
230 val = get_number(1, maxnum, nonkitten_count);
234 nonkitten_count = val;
242 [ get_number min max init inbufvar ix cx len val;
244 inbuf->0 = (INBUFSIZE-3);
252 while (cx < len && inbuf->(2+cx) == ' ')
254 if (cx < len && inbuf->(2+cx) == '.')
257 ! If user just hits return, use what we have already.
260 if (cx == len || inbuf->(2+cx) < '0' || inbuf->(2+cx) > '9') {
261 print "Please enter a value from ", min, " to ", max,
262 ", or Enter by itself to exit.^
263 [Press any key to continue.] ";
268 while (cx < len && inbuf->(2+cx) >= '0' && inbuf->(2+cx) <= '9') {
269 val = val * 10 + (inbuf->(2+cx) - '0');
272 if (val < min || val > max) {
273 print "Please enter a value from ", min, " to ", max,
274 ", or Enter by itself to exit.^
275 [Press any key to continue.] ";
286 @split_window TopBar;
293 This Zen simulation is based on the C version v1600003.248b^
294 by Leonard Richardson (C) 1997, 2000.^
295 Written originally for the Nerth Pork robotfindskitten contest.^
296 Reimplemented in Inform by David Griffith (C) 2002.^
298 This code is freely redistributable. Do with it what you will, but
299 don't go about claiming you wrote it. I, David Griffith, retain
300 copyright on this program except for the NKIs imported from the master
303 Lots more information on robotfindskitten is available at
304 http://www.robotfindskitten.org.^
306 To submit new NKI's, please go to the above URL.^
311 Release 1 / Serial number 0211xx to 021214 or so^
312 Initial private release. Limited distribution for beta testing and
315 Release 2 / Serial Number 021216^
316 First public release.^
318 Release 3 / Serial Number 021221^
320 - Movement keys 'J' and 'K' were swapped by mistake. Fixed.^
321 - Special PalmOS movement key support added.^
322 - More NKIs added (401 total).^
324 Release 4 / Serial Number 030131^
325 Light overhaul release.^
326 - Now an official port of robotfindskitten.^
327 - Typos in NKIs fixed.^
328 - Fixed diagonal collision-detection strangeness.^
329 - Added color support.^
330 - Added an easter egg. Can you find it?^
331 - Removed PalmOS movement key support (superfluous and ugly).^
332 - Removed playfield resizing code (superfluous and ugly).^
333 - It's ~robotfindskitten~, not ~Robot Finds Kitten~.^
334 - Merged in new NKIs from the new POSIX release of robotfindskitten.^
335 - More NKIs added (561 total).^
337 Release 5 / Serial Number 030524^
338 Even more NKIs release.^
339 - Idiotic typos fixed.^
340 - More NKIs added (602 total).^
342 Release 6 / Serial Number 031116^
344 - More NKIs added (764 total).^
345 - Increased maximum difficulty to 589.^
346 - Lots more comments in the source code.^
347 - Assorted cleanups in the source code.^
349 Release 7 / Serial Number 130320^
351 - Synchronized NKIs and removed redundancies with the POSIX port.^
352 - NKIs now generated from an external file using nki2inf.pl.^
353 - NKIs reduced to 723 because of redundancies and recommended deletions.^
355 Release 7 / Serial Number 19xxxx^
357 - Fixed a potential problem of wrongly determining screen size.^
362 1) I still don't know why already_seen_xy() occasionally causes Robot to
363 get placed on top of another object when a game is started. Fortunately
364 this seems to happen only very rarely and typically only if the
365 difficulty is set to more than 200. This bug also seems to very
366 occasionally put Kitten underneath an NKI.^
368 2) Under earlier versions of Windows Frotz, Robot used to appear as a
369 solid block. This was because of a bug in Windows Frotz which
370 incorrectly makes the cursor opaque. The cursor is now moved off to
371 the upper-right corner so that the game looks okay on terminals that use
372 something other than reverse for the cursor. I still can't figure out
373 how to make Inform hide the cursor completely. At least on xterm and
374 NetBSD's console, @@64set_cursor -1 doesn't work.^
376 3) Under Windows Frotz, an annoying [MORE] prompt might appear at the
377 main menu. This is another bug in Windows Frotz which causes the
378 interpreter to follow Windows' suggestion that something less than 24 or
381 [Press any key to continue.] ";
386 [ print_instructions;
388 @split_window TopBar;
394 In this game, you are Robot ( ";
395 style reverse; print "#"; style roman;
396 print " ). Your job is to find Kitten. This task is complicated by the
397 existance of various things which are not Kitten. Robot must touch
398 items to determine if they are Kitten or not. Move Robot with the
399 cursor keys, the numeric keypad (make sure numlock is on), or using the
400 vi/rogue/nethack movement keys. The game ends when robotfindskitten.
401 Alternatively, you may end the game by hitting the Esc or Q keys.^
403 [Press any key to continue.] ";
410 @split_window TopBar;
418 Day and night I feverishly worked upon the machine, creating both a soul
419 which could desire its goal, and a body with which it could realize
420 it. Many who saw my creation called it an abomination, and denied me
421 grant money. But they could not dissuade me from my impossible
422 task. It was a spectre that tormented me always, a ghost I had to give
423 a form and a life, lest it consume me from the inside. And when at last
424 my task was done, when the grey box on wheels was complete and when it,
425 as well as I, knew what had to be done, I felt deep sympathy for the
426 machine. For I had not destroyed the phantom, but merely exorcized it
427 into another body. The robot knew not why this task had to be
428 performed, for I could not imbue it with knowledge I did not myself
429 posess. And at the same time, I felt a sweeping sense of relief sweep
430 over me, that somehow, the dream that had driven me for my entire life
431 had come one step closer to fruition.^
433 ~Gort, Klaatu Verada Nikto~^
435 As I vocally activated the robot, I realized that it was following my
436 instructions, but not out of any desire to obey me. Had I remained
437 silent, it would have performed exactly the same operations. We were
438 two beings controlled by the same force now. And yet, seeking vainly to
439 hold some illusion of control over the machine I thought I had created,
440 I gave my final command.^
442 ~GO!~ I told the box as it began to roll out of my workshop into the
443 frozen desert beyond. ~FIND KITTEN!~^
445 -- The Book of Found Kittens, pages 43-4, author unknown.^
447 [Press any key to continue.] ";
452 [ draw_big_robot x y;
458 @set_colour 6 Back_def;
460 @set_colour 4 Back_def;
462 @set_colour 6 Back_def;
467 @set_colour 6 Back_def;
469 @set_colour 3 Back_def;
471 @set_colour 6 Back_def;
473 @set_colour 8 Back_def;
478 @set_colour 6 Back_def;
483 @set_colour 8 Back_def;
486 @set_colour Fore_def Back_def;
490 [ draw_big_kitten x y;
497 @set_colour 5 Back_def;
498 print "|", (char) 92, "_/|";
502 @set_colour 4 Back_def;
504 @set_colour 5 Back_def;
508 @set_colour 9 Back_def;
510 @set_colour 3 Back_def;
512 @set_colour 9 Back_def;
514 @set_colour 5 Back_def;
515 print "__", (char) 92;
520 @set_colour Fore_def Back_def;
524 [ draw_big_kitten_psycho x y;
531 @set_colour 5 Back_def;
532 print " |", (char) 92, "_/|";
535 @set_colour 4 Back_def;
537 @set_colour 5 Back_def;
541 @set_colour 9 Back_def;
543 @set_colour 3 Back_def;
545 @set_colour 9 Back_def;
547 @set_colour 5 Back_def;
548 print "__", (char) 92;
553 @set_colour Fore_def Back_def;
557 ! Something gets messed up if I make this local to findkitten()
558 ! When going right or left, then up or down to hit the Kitten, the
559 ! animation gets reversed.
561 Global last_right = false;
565 @split_window TopBar;
570 print (string) last_message;
573 draw_object(kitten_x, kitten_y, kitten_char, kitten_color);
577 draw_object(player_x, player_y, '#');
588 player_x_last = player_x;
589 player_y_last = player_y;
591 'Q', $1b: rfalse; ! exit game ($1b == Esc)
592 '8', 'K', 129: player_y--; ! up
593 '2', 'J', 130: player_y++; ! down
594 '4', 'H', 131: player_x--; ! left
596 '6', 'L', 132: player_x++; ! right
599 '7', 'Y': player_y--; player_x--; ! up-left
601 '9', 'U': player_y--; player_x++; ! up-right
603 '1', 'B': player_y++; player_x--; ! down-left
605 '3', 'N': player_y++; player_x++; ! down-right
609 ! Keep Robot from falling off edges of playfield.
611 if (player_y == TopBar || player_y > Height) {
612 player_y = player_y_last;
614 if (player_x < 1 || player_x > Width) {
615 player_x = player_x_last;
618 ! Detect and handle collisions.
620 if (player_x == kitten_x && player_y == kitten_y) {
621 animate_kitten(key, last_right);
625 for (i = 0: i < nonkitten_count: i++) {
626 if (player_x == nonkitten_x-->i
627 && player_y == nonkitten_y-->i) {
629 last_message = lookup_msg(nonkitten_msg-->i);
630 player_x = player_x_last;
631 player_y = player_y_last;
638 [ animate_kitten key my_last_right i j junk robot_x anim_finished;
640 '8', 'J', 129: player_y++;
641 '2', 'K', 130: player_y--;
642 '4', 'H', 131: player_x++;
643 '6', 'L', 132: player_x--;
644 '7', 'Y': player_y++; player_x++;
645 '9', 'U': player_y++; player_x--;
646 '1', 'B': player_y--; player_x++;
647 '3', 'N': player_y--; player_x--;
650 anim_finished = false;
651 for (i = 4: i >= 0: i--) {
653 @split_window TopBar;
662 robot_x = Anim_Meet - i;
664 draw_object(robot_x, TopBar - 1, '#');
666 draw_object(Anim_Meet - 1 + i, TopBar - 1,
667 kitten_char, kitten_color);
669 robot_x = Anim_Meet - 1 + i;
671 draw_object(robot_x, TopBar - 1, '#');
673 draw_object(Anim_Meet - i, TopBar - 1,
674 kitten_char, kitten_color);
679 print "You found Kitten! Way to go, Robot!";
680 anim_finished = true;
683 draw_object(kitten_x, kitten_y, kitten_char, kitten_color);
686 draw_object(player_x, player_y, '#');
690 if (anim_finished == false) {
693 @aread junk 0 10 pause -> junk;
696 draw_object(player_x, player_y, '#');
704 [ already_seen_xy x y i;
705 for (i = 0: i < already_count: i++) {
706 if (already_x-->already_count == x &&
707 already_y-->already_count ==y) {
711 already_x-->already_count = x;
712 already_y-->already_count = y;
724 kitten_x = get_random_x();
725 kitten_y = get_random_y();
726 kitten_color = get_random_color();
727 while (already_seen_xy(kitten_x, kitten_y) == true) {
728 kitten_x = get_random_x();
729 kitten_y = get_random_y();
731 kitten_char = get_random_char();
736 player_x = get_random_x();
737 player_y = get_random_y();
738 while (already_seen_xy(player_x, player_y) == true) {
739 player_x = get_random_x();
740 player_y = get_random_y();
746 already_msg_count = 0;
748 for (i = 0: i < nonkitten_count: i++) {
749 nonkitten_x-->i = get_random_x();
750 nonkitten_y-->i = get_random_y();
751 nonkitten_color-->i = get_random_color();
752 while (already_seen_xy(nonkitten_x-->i,
753 nonkitten_y-->i) == true) {
754 nonkitten_x-->i = get_random_x();
755 nonkitten_y-->i = get_random_y();
757 nonkitten_char-->i = get_random_char();
758 nonkitten_msg-->i = get_random_msg();
764 for (i = 0: i < nonkitten_count: i++) {
765 draw_object(nonkitten_x-->i,
768 nonkitten_color-->i);
773 [ draw_object x y character fore back;
781 @set_colour fore Back_def;
783 print (char) character;
785 @set_colour Fore_def Back_def;
791 for (i = 0 : i < Width : i++)
798 if (x >= 'a' && x <= 'z')
804 [ get_random_char num;
807 while (num == 35) { ! avoid choosing '#'
815 [ get_random_msg num;
816 num = random(MESSAGE_NUM);
817 while (is_duplicate_msg(num) == true) {
818 num = random(MESSAGE_NUM);
824 [ get_random_color num;
826 ! 0 and 1 are default color and current color
827 ! and we want to avoid picking the default color explicitly
828 while (num == $2c-->0) {
835 [ is_duplicate_msg num i;
836 for (i = 0: i < already_msg_count: i++) {
837 if (already_msg-->i==num) {
841 already_msg-->already_msg_count = num;
848 ! Maybe this will need to do something more in the future.
849 return random(Width);
854 ! Make sure we don't draw in the status bar.
856 num = random(Height);