Help - Search - Members - Calendar
Full Version: very crappy map for console
BatMUD > BatMUD forums > General game-related chat
uki
I just started to teach myself perl, and came up with this as practice. It is really awful and quite useless piece of code, it prints part of map from given cordinates. It needs text file of maps in same dir with name laenor/rothikgen/lucentium etc. you can get them from ggr's map page, just open the html file, ctrl+a and copy paste to text editor and save it with that continents name, just remove the first line, which have the continents name, and the all empty lines from end.

This is done by total beginner and just for practicing some basic stuff, so it might look quite stupid. Still decide to publish here just to get some feedback. I'll start practice curses next, so maybe get something useful done someday, if I have time and find understandable tutorials.

CODE
#!/usr/bin/perl -w
use strict;
use Term::ReadKey;
use Switch;

@ARGV == 3 or die "Usage: map.pl continent x y\n";

my ($continent, $max_x, $max_y) = &select_continent($ARGV[0]);
my $x = $ARGV[1];
my $y = $ARGV[2];


&screen;
sub screen_properties{
  if ($x < 1 || $x > $max_x || $y < 1 || $y > $max_y) {
    die "Invalid cordinates. Minimimum is 1x1 and maximum for ",$continent," is ",$max_x,"x",$max_y,"\n";
  }
  my ($cols,$rows) = GetTerminalSize();
  my $offset = sprintf("%0.f", $x - ($cols / 2));
  my $length = $cols - 1;
  my $start = sprintf("%0.f", $y - ($rows / 2));
  my $end = $y + ($rows - ($y - $start)) - 6;
  if ($length > $max_x) {
    $length = $max_x;
    our $space_l = sprintf("%0.f", ($cols - $max_x) / 2);
    our $space_r = $cols - $max_x - $space_l - 1;
    }
  else {
    our $space_l = 0;
    our $space_r = 0;
  }
  
  if ($start != abs($start)) {$end += abs($start)}
  if ($end > $max_y) {
    $start -= ($end - $max_y);
    $end = $max_y;
  }
  if ($offset < 1) {$offset = 1}
  if ($offset + $length > $max_x) {$offset -= ($offset + $length - $max_x)}
  
  return ($cols,$rows,$offset,$length,$start,$end);
  
}

sub screen {
  our ($cols,$rows,$offset,$length,$start,$end) = &screen_properties();
  system ("clear");
  &print_line("top");
  my $count = 1;
  open(MAP_FILE, $continent) or die "For some reason I can't find map file\n";
  while (<MAP_FILE>) {
    if ($count >= $start && $count <= $end) {
      &print_line("left");
      my $map_line = substr $_, $offset, $length;
      my $line_length = length($map_line);
      for(my $round=1; $round <= $line_length; $round++) {
        my $char_to_print = substr $map_line, $round, 1;
        my $test = $offset + $round + 1;
        if ($count == $y && $x == $test) {$char_to_print = "*"}
        &print_colored_char($char_to_print);
      }
      &print_line("right");
    }
    if ($count >= $end) {
      &print_line("bottom");
      print $continent,": ",$max_x," x ", $max_y, "\nScreen: ",$cols," x ",$rows, "\n";
      exit;
    }
    $count++;
  }
}




sub print_colored_char {
  switch ($_[0]) {
    case ["f","F","v"] {print "\033[0;1;32m"}
    case ["j"] {print "\033[0;0;32m"}
    case ["~","r","R","l"] {print "\033[0;0;34m"}
    case ["S"] {print "\033[0;1;36m"}
    case ["z"] {print "\033[0;1;33m"}
    case ["."] {print "\033[0;0;32m"}
    case ["^"] {print "\033[0;1;35m"}
    case ["h","H"] {print "\033[0;0;35m"}
    case [","] {print "\033[0;1;33m"}
    case ["-","|","+","/","\\","="] {print "\033[0;1;30m"}
    case ["!"] {print "\033[0;0;37m"}
    case ["?","*"] {print "\033[0;1;37m"}
    case ["C","#"] {print "\033[0;1;30m"}
    case ["L","@"] {print "\033[0;1;31m"}
    case ["x","s","V"] {print "\033[0;0;31m"}
    case ["d","b","y"] {print "\033[0;0;33m"}
    else {print "\033[0m"}
  }
  print $_[0];
}

sub print_line {
  #my ($cols,$rows) = GetTerminalSize();
  print "\033[41;1;1m";
  switch ($_[0])
  {
    case ["top"]
    {
     for(my $round=1; $round <= $::cols; $round++) {print " "}
     print "\033[0m\n";
    }
    case ["left"]
    {
     print " \033[0m";
     for(my $round=1; $round <= $::space_l; $round++) {print " "}
    }
    case ["right"]
    {
      print "\033[0m";
      for(my $round=1; $round <= $::space_r; $round++) {print " "};
      print "\033[41;1;1m \033[0m\n";
    }
    case ["bottom"]
    {
     for(my $round=1; $round <= $::cols; $round++) {print " "}
     print "\033[0m\n";
    }
  }
  
}

sub select_continent {
  switch ($_[0]) {
    case ["laenor","lae"] {return ("laenor","827","781")}
    case ["rothikgen","roth"] {return ("rothikgen","480","480")}
    case ["lucentium","luc"] {return ("lucentium","700","500")}
    case ["desolathya","deso"] {return ("desolathya","540","530")}
    case ["furnachia","furn"] {return ("furnachia","440","480")}
    case ["renardy","ren"] {return ("renardy","168","86")}
    else {die "No such continent\nUse [lae]nor, [roth]ikgen, [luc]entium, [furn]achia, [deso]lathya or [ren]ardy\n"}
  }
}
Ggr
Not going to comment on the code .. but the whole process of copypasting data from the HTML is probably unnecessary, as the raw data of the maps is freely available. Of course that won't have the labels, tho, but code for the tools I've created to generate the maps in various formats is available as well. Some adventurous person might easily add a feature of a custom output format, given some knowledge of C.

http://pupunen.net/hg/maputils/

and you probably should also read the PupuMaps FAQ item about this:

http://tnsp.org/maps/faq.php#5
uki
I had almost buried this project, as I had my starting programming hobby. But lately have tried to ponder some sequal for this.

First the reason why I didn't used ggr's ansi files, was that they include ansi escape characters. Like "^[[0;0;34m" in those files or "\033[0;0;34m" in my code. This are counted as chars and would get counter act way I don't wish and my program only cuts part of text file and prints it. It doesn't have buffers how it could handle the stuff is cutted out from screen. So cutting the escape character would show print quite weirdly. I also found doing parser for ansi escape characters way too difficult to me, but now when I want to do it with ncurses I have now other choice. Somebody could help me with this little bit.
I found this post from one page
QUOTE
A regexp to parse color escape sequence could be:

m/\\033\[(\d+)(?:;(\d+)(?:;(\d+))?)?m/;


I tested three cases:

\033[0m, gives me $1 = 0, $2 and $3 undefined. Correct;
\033[1;31m, gives me $1 = 1, $2 = 31, and $3 undefined. Correct;
\033[1;31;44m, gives me $1 = 1, $2 = 31, and $3 = 44. Correct.

this seems quite simple idea, and probably the best (or atleast for me). Just have to start figure how to put in on practice.

Another stuff I have been looking for is source code of most (terminal pager, little bit similar to less). I have really don't have any clue about c++, so not really understand fully what happens here, but according to comment this is something I should be looking for.
CODE
/* Here *begp points to the char after \e.
* The general escape sequence parsed here is assumed to look like:
*   \e[ XX; ... m
* If 30 <= XX <= 37, then it specifies the foreground color
* If 40 <= XX <= 47, then a background color is specified
* If  0 <= XX <= 8, then an attribute (e.g, 8) is specified.
* These numbers will be encoded as:
*  offset + (FG-30 + 8*(BG-40 + 9*attribute))
*/
static int parse_escape (unsigned char **begp, unsigned char *end, int *colorp)
{
   unsigned char *beg = *begp;
   int fg = 38, bg = 48, at = 0;
   int xx;

   if ((beg >= end) || (*beg != '['))
     return -1;

   beg++; /* skip [ */
   while (1)
     {
    xx = 0;
    while ((beg < end) && isdigit (*beg))
      {
         xx = xx*10 + (*beg - '0');
         beg++;
      }
    if ((xx >= 0) && (xx <= 8))
      at = xx;
    else if ((xx >= 20) && (xx <= 28))
      xx = 0;
    else if ((xx >= 30) && (xx <= 37))
      fg = xx;
    else if ((xx >= 40) && (xx <= 47))
      bg = xx;
    else return -1;
  
    if ((beg < end) && (*beg == ';'))
      {
         beg++;
         continue;
      }
    
    if ((beg < end) && ((*beg == 'm') || (*beg == ']')))
      {
         *begp = beg + 1;
         if (colorp != NULL)
           {
          if ((fg != 38) || (bg != 48))
            xx = ((fg-30) + 9*((bg-40) + 9*at));
          if (xx != 0)
            xx += MOST_EMBEDDED_COLOR_OFFSET;
          *colorp = xx;
           }
         return 0;
      }
    return -1;
     }
}
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2022 Invision Power Services, Inc.