[PREV - BIKE_SAFELY]    [TOP]

MAPGAME

                                             Mon Jul 15, 2002 

The rules of the game are simple: 

Take a map of San Francisco.                     
                                                 (It must be a road 
Check the map coordinates                        map or a MUNI map, the 
across the top, see how wide                     otherwise excellent      
SF is (e.g. 2 through 8).                        bike/ped map 
                                                 doesn't work:            
Check the map coords going                       no coord numbers). 
down, pick a cut-off line     
roughly 7 miles down from the 
top (e.g. A-I).               
                              
Come up with a way of randomly
selecting two coordinates that
fall within these two ranges.        (cards? dice? software?)

Choose a set of goals to 
be accomplished in some 
quadrant of the map.
                                  
Use the random method to           
select a quadrant.                 I'm am not sure that
                                   "quadrant" is the   
(If it's entirely under            right word here.      
water, call it a do-over.)         However I am sure    
                                   that it is more     
                                   appropriate than the
                                   Star Trek usage.    
                    

Ride your bicycle to the       
selected map quadrant.  

Try to accomplish your goals.


   Some possible goals: 
                            
   Find something remarkable           
   you've never seen before.
                     
   Find some place to have lunch           
   and/or coffee.               
          
   Find some red or orange fragments       
   of crunched tail-light plastic   
   left over from a car collision.  
                             
   All of the above.
   (which is what I do). 


===
           

Random methods: 

Simple:  Get some index cards, in two colors (one for each axis)
         Make a card for each valid map coordinate.  
         Shuffle the deck.                 
         Draw two cards, one of each color.

Alt:     Use an ordinary deck of cards, flip through it 
         to pull out a card for each coordinate (e.g. 
         red 2, 3, 4... etc, and black Ace, 2, 3... 
         which you can translate into A, B, C...). 


The way I do it is with this perl script:

use strict;
$|=1;     # makes me feel better
use Getopt::Std;

our %args;
getopts("h?", \%args); 

if ( $args{h} or $args{'?'} ) {
  print_usage();
  exit 0;
}

my ($xrange, $xpick, $yrange, $ypick);

$xrange = $ARGV[0] || "1-7";
$yrange = $ARGV[1] || "G-M";

$xpick = get_random_pick_given_range($xrange);
$ypick = get_random_pick_given_range($yrange);

print "Your mapgame assignment is x: $xpick y: $ypick\n";

sub get_random_pick_given_range {
   my $range = shift;
   my ($min, $max, $pick);

   $range =~ s{ ^ ['"] (.*?) ['"] $ }{ $1 }x; # strip any quotes from argument
   
   ($min, $max) = split /-/, $range;

   if ( is_single_alpha($min) and is_single_alpha($max) ) {  
       $pick = pick_alpha_range($min, $max);
   } elsif ( is_numeric($min) and is_numeric($max) ) { 
       $pick = pick_numeric_range($min, $max);
   } else { 
       die "Ranges should be integers (e.g. 7-18) or alphabetic (e.g. B-H), don't mix them.\n";
   }
   return $pick;
}

sub pick_numeric_range { 
   # Chooses a random integer given a range of integers, e.g. (2,17).
   my ($min, $max) = @_;
   my $pick = int( rand( $max - $min + 1 ) + $min ) ;
 }

sub pick_alpha_range {
   my $min = shift;
   my $max = shift;
   my $pick = chr( pick_numeric_range( ord(uc($min) ), ord(uc($max)) ) );
 }

sub is_single_alpha { 
   my $item = shift;
   my $alpha_rule = qr{ ^ [A-Z] $ }ix;  # just one alpha char, upper or lower
   return ($item =~ m{$alpha_rule});
}

sub is_numeric {
   my $item = shift;
   my $numeric_rule = qr{ ^ [0-9]+ $ }x;  # just digits
   return ($item =~ m{$numeric_rule});
}

sub print_usage {
  # prints a usage message extracted from the perldoc
  my $caller = $0;
  my $begin_usage_rule = qr{ ^ =head[1-3] \s*? USAGE }x;
  open ME, "<$caller";
  LINE: while () {
    if ( m{ $begin_usage_rule }x ) {
      print STDERR "Usage: \n";
      while () {
        last LINE if m{ ^ = }x ;
        print STDERR;
      }
    }
  }
  close ME;
}

__END__

=head1 NAME

mapgame

=head1 SYNOPSIS

  mapgame 1-7 B-K

=head1 DESCRIPTION

Given ranges of map coordinates, returns a randomly 
selected map quadrant.

Ranges default to reasonable values to use with the 
Gousha Travel Publication map of San Francisco:
   "1-7" and "G-M"

The alphabetic range may be expressed using lower-case
(internally, alphas are converted to upper-case, so 
"a-g" and "A-G" are the same, as is "a-G" or "A-g").

The numeric ranges must be integers, and unlike the alpha 
ranges are not restricted to single characters: e.g. "11-23" 
is okay.  

Backwards ranges seem to work, e.g. "23-11", "G-A".

=head1 USAGE

  mapgame [ XRANGE  [YRANGE] ] 

  where ranges are hyphen separated map coordinates. 
  (Singledigit alphanumerics or multidigit numerics are allowed).
  Example:
     mapgame 1-17 A-P

=head1 DISCUSSION

This business gets you a random pick from $xmin to $xmax, inclusive:

   $xpick = chr( int( rand( ord($xmax) - ord($xmin) + 1) ) + ord($xmin) ) ;

The ord/chr transformation allows it to work on alpha characters as 
well as integers (converts the range to the ascii values, does a random 
selection on that range, then converts it back to chracter form).

BUT: this is limited to single integers, which is Not Good.

So, we dance around this problem by doing the conversion only when 
we've got an alpha range, and always use the same random pick 
routine designed to work on integer ranges.  

The is_single_alpha function is used to identify the alpha case.
The is_numeric function is used just for error checking 
(code complains when given mixed ranges like "3-X").

=head1 AUTHOR

Joseph Brenner, Edoom@kzsu.stanford.eduE

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2004 by Joseph Brenner

This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.2 or,
at your option, any later version of Perl 5 you may have available.

=head1 SEE ALSO 

http://www.grin.net/~mirthless/doomfiles/MAPGAME.html


=cut



--------
[NEXT - TRICK_OF_ATTENTION]