[t/spec] Don't use .[^20] on tests which should have finite results.
[pugs.git] / examples / adventure / adventure.pl
blob80f17f2435e29d6ff8dfdff89ed5873f31b113c2
1 #!/usr/bin/perl6
3 # Adventures in Perl6
5 use v6;
7 ### GRAMMAR ###
9 grammar Adventure {
10 token TOP { <command> }
11 token command {
12 | <verb> <ws> <article> <ws> <object>
13 | <verb> <ws> <object>
14 | <verb>
15 | <direction>
18 token verb { look|take|drop|inventory|open|score|help|quit }
19 token object { sign|coin|key|door|vampire|cross }
20 token article { a|an|the|at|in|on|to }
21 token direction { north|south|east|west }
25 ### GAME DATA ####
27 my %player = (
28 place => "chamber",
29 score => 0
32 my %map = (
33 chamber => {
34 north => 'throne room',
35 east => 'dungeon'
37 'throne room' => {
38 south => 'chamber'
40 dungeon => {
41 west => 'chamber',
42 north => 'crypt',
43 BLOCKED_south => 'cell' # there is no "south"... yet
45 crypt => {
46 south => 'dungeon'
48 cell => {
49 north => 'dungeon'
53 my %object = (
54 sign => {
55 place => "chamber",
56 description => "Sign says: bring treasures here, then say SCORE"
58 coin => {
59 place => "cell"
61 key => {
62 place => "crypt"
64 door => {
65 place => "dungeon",
66 description => "The door is closed"
68 vampire => {
69 place => 'crypt'
71 cross => {
72 place => 'throne room'
76 ### ACTIONS ###
77 #module main;
79 sub do_action( $verb, $object ) {
80 say "[$verb] [$object]";
82 my %action = (
83 'look' => sub { look($object) },
84 'take' => sub { take($object) },
85 'drop' => sub { drop($object) },
86 'open' => sub { open($object) },
87 'inventory' => sub { inventory() },
88 'score' => sub { score() },
89 'help' => sub { help() },
90 'quit' => sub { quit() },
93 if %action{$verb} {
94 %action{$verb}();
98 sub help {
99 say "look, take, drop, inventory, open, score, help, quit";
100 say "north, south, east, west";
103 sub quit {
104 score();
105 exit;
108 sub walk_to( $direction ) {
109 my $new_place = %map{%player{'place'}}{$direction};
111 if $new_place { # can go to that direction?
112 say "You entered the $new_place";
113 %player{'place'} = $new_place;
114 } else {
115 say "You can't go $direction";
119 sub look( $object ) {
120 if i_see( $object ) {
121 my $description = %object{$object}{'description'};
122 if $description {
123 say $description;
124 } else {
125 say "It's a regular $object";
127 } else {
128 # special command
129 look_around();
133 sub look_around {
134 say "You are in the " ~ %player{'place'};
136 my @objects = objects_in( %player{'place'} );
137 my $list = join(", ", @objects);
139 say "I see here: $list" if $list;
142 sub inventory {
143 my @objects = objects_in('player');
144 my $list = join(", ", @objects);
146 $list = "nothing" if !$list;
148 say "You're carrying: $list.";
151 sub take( $object ) {
152 if is_here( $object ) {
153 say "You took the $object";
154 %object{$object}{'place'} = 'player';
155 } else {
156 say "I don't see that here";
160 sub drop( $object ) {
161 if i_have( $object ) {
162 say "You dropped the $object on the floor";
163 %object{$object}{'place'} = %player{'place'};
164 } else {
165 say "You don't have that $object";
169 sub open( $object ) {
170 if $object ne 'door' {
171 say "You can't open that!";
172 return;
175 if is_here( $object ) {
176 if i_have('key') {
177 say "You opened the door!";
178 %object{'door'}{'description'} = 'The door is open';
179 %map{ %player{'place'} }{'south'} = 'cell';
180 } else {
181 say "The door is locked";
183 } else {
184 say "I don't see a $object";
188 sub score {
189 if i_have('coin') {
190 say "You got the treasure. Congratulations!";
191 } else {
192 say "You have scored " ~ %player{'score'} ~ " points";
195 ### AUXILIAR FUNCTIONS ###
197 sub is_here ($object) {
198 if $object ~~ %object {
199 return ( %object{$object}{'place'} eq %player{'place'} );
200 } else {
201 return False;
205 sub i_have ($object) {
206 if $object ~~ %object {
207 return ( %object{$object}{'place'} eq 'player' );
208 } else {
209 return False;
213 sub i_see ($object) {
214 return ( is_here( $object) or i_have( $object ) );
217 sub objects_in ($where) {
218 my @objects;
219 for %object.kv -> $name, $obj {
220 if $obj{'place'} eq $where {
221 @objects.push: $name;
224 return @objects;
227 ### MAIN LOOP ###
229 while ( 1 ) {
230 print "> ";
231 my $input = $*IN.get();
232 my $response = Adventure::command($input);
234 if my $direction = $response<direction> {
235 walk_to( ~$direction );
237 elsif my $verb = $response<verb> {
238 do_action( ~$verb, ~($response<object> or "") )
239 } else {
240 say "What?";
243 say '';