[PREV - NOISEWALL]    [TOP]

MAPGAME


                                              July 15, 2002

The rules of the Map 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 well:
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.

Then use your
random method to
select a quadrant.                 I 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.

   Or 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

[ref]


=cut



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