Automap

version 4 by Mark Tilford

  • Home page
  • Beginning
  • Previous
  • Next



  • Section 3 - Drawing the map - Writing to the character array

    To place (ch - number) of (r - a room) at (x - a number) and (y - a number):
        (- if ( {x} >= 0 && {x} < MAP_WIDTH && {y} >=0 && {y} < MAP_HEIGHT) {
            Automap_Chars -> ( {y} * MAP_WIDTH + {x} ) = {ch};
            #ifdef AUTOMAP_HYPERLINKS;
                Automap_links --> ( {y} * MAP_WIDTH + {x} ) = {r};
            #endif;
        }
        -)

    To place (ch - number) at (x - a number) and (y - a number):
        (- if ( {x} >= 0 && {x} < MAP_WIDTH && {y} >=0 && {y} < MAP_HEIGHT) {
            Automap_Chars -> ( {y} * MAP_WIDTH + {x} ) = {ch};
        }
        -)
        
    To decide what number is the character at (sq - a number):
        (- Automap_Chars -> {sq} -);

    To decide what number is room size: if current zoom is map zoomed in, decide on 4; decide on 2.

    [Map drawn room is a mappable room that varies. Map drawn direction is a direction that varies.]
    Map drawn room is a room that varies. Map drawn direction is a direction that varies. [ Debugging variables ]

    [Automap null room is a room. It is unmappable. ]

    [ Draw Path ]
    To draw a path from (room x - a number) and (room y - a number) to (dir - a direction) for (dist - a number) with (ch - a number):
        [if ch is 76 begin; say "Drawing path with 76 from [map drawn room] to [map drawn direction]."; end if;]
        [say "drawing path from ([room x], [room y]) to the [dir] with [ch]:[line break]";]
        now dist is (dist - 1) times room size + 1;
        let dx be the delta x of dir;
        let dy be the delta y of dir;
        let room x be room x + dx;
        let room y be room y + dy;
        while (room x >= 0 and room x < map width and room y >= 0 and room y < map height and dist > 0) begin;
            let ch1 be ch;
            let sq be (room y * map width) + room x;
            let ch2 be the character at sq;
            if ch2 is 32 or ch2 is ch begin; do nothing; [ Drawing over a space or a matching character is normal. ]
            otherwise if ch2 is 90 or ch2 is 91; now ch1 is ch2; [ Drawing anything over an X or + is a nop. ]
            otherwise if ch1 is 35 or ch1 is 36; now ch1 is 90; [ Drawing a ne/sw over nw/se or v.v makes an X. ]
            [otherwise if ch1 is 35 or ch1 is 36; say "writing [ch] over [ch2] for X at ([room x], [room y])::[sq]."; now ch is 90;]
            otherwise if ch1 is 1 or ch1 is 2; now ch1 is 91; [ Drawing a n/s over e/w or v.v makes a +.]
            otherwise; say "Draw Path got value with [ch1] over [ch2] at ([room x], [room y]): BUG.";
            end if;
            if ch1 is not ch2, place ch1 at room x and room y;
            now dist is dist - 1;
            now room x is room x + dx;
            now room y is room y + dy;
        end while.
        
    To decide what number is the maximum of (x - a number) and (y - a number): if (x < y), decide on y; decide on x.
    To decide what number is the minimum of (x - a number) and (y - a number): if (x < y), decide on x; decide on y.
        
    Include (-
    [ ClearMap i;
        !for (i = 0: i < MAP_WIDTH * MAP_HEIGHT: ++ i)
        for (i = MAP_WIDTH * MAP_HEIGHT - 1; i >= 0; -- i)
            Automap_Chars->i = 32; ! Empty cell
        #ifdef AUTOMAP_HYPERLINKS;
        if (Automap_links ~= 0)
            for (i = MAP_WIDTH * MAP_HEIGHT - 1; i >= 0; -- i)
                Automap_links-->i = 0; ! No room
        #endif;
    ]; -);

    To clear the map: (- ClearMap(); -);

    [ Draw Map ]
    To decide whether the map is drawn:
        if current zoom is map absent, decide no;
        if location is a mappable room begin;
            [start capturing text;]
            [say "location is a mappable room.";]
            begin the automap work activity;
            begin the automap drawing activity;
            let max_x be the map_x of location;
            let max_y be the map_y of location;
            repeat with loop_room running through the mappable rooms coregional with location begin;
                if the map_x of loop_room is greater than max_x, now max_x is the map_x of loop_room;
                if the map_y of loop_room is greater than max_y, now max_y is the map_y of loop_room;
            end repeat;
            let map_min_x be 0;
            [ If the width of the drawn map is no more than the width allocated, center the map horizontally.]
            [ Otherwise, place the map so as to center the location, unless that would go over the edge ]
            [ max (wmost, min (center - WIDTH/2, emost - WIDTH)) ]
            [let n1 be 2 + (room size) * (1 + max_x);]
            [say "[2 + (room size) * (1 + max_x)] ?>= [map width] :: [2 + (1 + the map_x of location) * (room size) - map width / 2] [(1 + max_x) * room size - map width].";]
            [say "Would center x at [((room size * (1 + max_x)) - map width) / 2] == ([room size] * [1 + max_x] - [map width]) / 2.";
            if 2 + (room size) * (1 + max_x) >= map width begin;
                [now map_min_x is the maximum of -2 and (the minimum of (2 + (1 + the map_x of location) * (room size) - map width / 2) and ((1 + max_x) * room size - map width));] [ I have no idea why the parens cause this line to fail.]
                now map_min_x is the maximum of -2 and (the minimum of (2 + (1 + the map_x of location) * (room size) - map width / 2) and (1 + max_x) * room size - map width);
            otherwise;
                now map_min_x is (room size * (1 + max_x) - map width) / 2;
            end if;]
            if 1 is 1 begin;
                [say "room size = [room size], map width = [map width], max_x = [max_x], map_x = [ map_x of location ], ";]
                let shown_map_width be (room size) * (1 + max_x); increase shown_map_width by 1;
                [say "shown_map_width is [shown_map_width], ";]
                [let shown_map_start be shown_map_width - map width;]
                let center_location_start be (1 + the map_x of location) * room size; decrease center_location_start by 1; [ x coordinate of location ]
                [say "center location start is [center_location_start] ";]
                decrease center_location_start by room size / 2;
                [say " to [center_location_start], ";]
                [decrease center_location_start by map height / 2;]
                [decrease center_location_start by map width;
                now center_location_start is center_location_start / 2; [ x coordinate of start position that would center location ]]
                decrease center_location_start by (map width / 2);
                [say " to [center_location_start], ";]
                let eastmost_start be (1 + max_x) * room size; increase eastmost_start by 0; [ x coordinate of eastmost point ]
                now eastmost_start is eastmost_start - map width; [ x coordinate of start position that would be eastmost point at the edge ]
                [say "eastmost_start is [ eastmost_start ], ";]
                if shown_map_width > map width begin;
                    [increase center_location_start by 2;]
                    now map_min_x is the minimum of center_location_start and eastmost_start;
                    now map_min_x is the maximum of -1 and map_min_x;
                otherwise;
                    [[now map_min_x is center_location_start;]
                    [now map_min_x is shown_map_width;
                    decrease map_min_x by ( map width / 2);]]
                    now map_min_x is shown_map_width - map width;
                    decrease map_min_x by 2;
                    now map_min_x is map_min_x / 2;
                    [decrease map_min_x by 1;] [compensate that (0,0) is a corner of a cell, not the center]
                end if;
                [say "map_min_x is [map_min_x].";]
                [say "room size = [room size], map width = [map width], max_x = [max_x], map_x = [ map_x of location ], shown_map_width is [shown_map_width], center location start is [center_location_start], eastmost_start is [ eastmost_start ], map_min_x is [map_min_x].";]
            end if;
            let map_min_y be 0;
            [ If the width of the drawn map is no more than the width allocated, center the map horizontally.]
            [ Otherwise, place the map so as to center the location, unless that would go over the edge ]
            [ max (nmost, min (center - WIDTH/2, smost - WIDTH)) ]
            [if 2 + (room size) * (1 + max_y) >= map height begin;
                now map_min_y is the maximum of -2 and (the minimum of (2 + (1 + the map_y of location) * (room size) - map height / 2) and (1 + max_y) * room size - map height);
            otherwise;
                now map_min_y is (room size * (1 + max_y) - map height) / 2;
            end if;]
            if 1 is 1 begin; [ limiting the scope of the local variables ]
                [say "room size = [room size], map_height = [map height], max_y = [max_y], map_y = [ map_y of location ], ";]
                let shown_map_height be (room size) * (1 + max_y); increase shown_map_height by 1;
                [say "shown_map_height is [shown_map_height], ";]
                let center_location_start be (1 + map_y of location) * room size; decrease center_location_start by 1; [ y coordinate of location ]
                decrease center_location_start by room size / 2;
                [say "center location start is [center_location_start] ";]
                decrease center_location_start by map height / 2; [say "to [center_location_start], ";]
                let southmost_start be (1 + max_y) * room size; increase southmost_start by 0; [ y coordinate of southmost point ]
                decrease southmost_start by map height; [ y coordinate of start position that would be southmost point at the edge ]
                [say "southmost_start is [ southmost_start ], ";]
                if shown_map_height > map height begin;
                    [decrease center_location_start by 2;]
                    now map_min_y is the minimum of center_location_start and southmost_start;
                    [decrease map_min_y by (map height minus 1) / 2;]
                    now map_min_y is the maximum of -1 and map_min_y;
                otherwise;
                    now map_min_y is shown_map_height - map height;
                    decrease map_min_y by 2;
                    now map_min_y is map_min_y / 2;
                    [decrease map_min_y by 1;] [compensate that (0,0) is a corner of a cell, not the center]
                end if;
                [say "map_min_y is [map_min_y].";]
            end if;
            Clear the map;
            [reset 76;]
            repeat with loop_room running through the mappable rooms coregional with location begin;
                now map drawn room is loop_room;
                let temp_x be (the map_x of loop_room * room size) - map_min_x;
                let temp_y be (the map_y of loop_room * room size) - map_min_y;
                [say "Gridding [loop_room] at [temp_x], [temp_y]";]
                [if (temp_x + room size >= 0) and (temp_x < map width) and (temp_y + room size >= 0) and (temp_y < map height), begin;]
                [say "[temp_x + room size] >= 0 && [temp_x] < [map width] && [temp_y + room size] >= 0 && [temp_y] < [map height].";]
                if (temp_x + room size >= 0) and (temp_x < map width) and (temp_y + room size >= 0) and (temp_y < map height) begin;
                    if the current zoom is map zoomed in begin;
                        let offset be 0;
                        if loop_room is location, now offset is 17; [ Difference between empty image chars and full image chars ]
                        [check 76;]
                        now map drawn direction is southwest;
                        if loop_room has an exit to southwest begin;
                            place sw exit + offset of loop_room at temp_x and temp_y + 2;
                            [draw a path from temp_x and temp_y + 2 to -1 and 1 for (the distance from loop_room to the southwest) with ne sw path;]
                            draw a path from temp_x and temp_y + 2 to southwest for the distance southwest from loop_room with ne sw path;
                        otherwise;
                            place sw corner + offset of loop_room at temp_x and temp_y + 2;
                        end if;
                        [check 76;]
                        now map drawn direction is northwest;
                        if loop_room has an exit to northwest begin;
                            place nw exit + offset of loop_room at temp_x and temp_y;
                            draw a path from temp_x and temp_y to northwest for the distance northwest from loop_room with nw se path;
                        otherwise;
                            place nw corner + offset of loop_room at temp_x and temp_y;
                        end if;
                        [check 76;]
                        now map drawn direction is northeast;
                        if loop_room has an exit to northeast begin;
                            place ne exit + offset of loop_room at temp_x + 2 and temp_y;
                            draw a path from temp_x + 2 and temp_y to northeast for the distance northeast from loop_room with ne sw path;
                        otherwise;
                            place ne corner + offset of loop_room at temp_x + 2 and temp_y;
                        end if;
                        [check 76;]
                        now map drawn direction is southeast;
                        if loop_room has an exit to southeast begin;
                            place se exit + offset of loop_room at temp_x + 2 and temp_y + 2;
                            draw a path from temp_x + 2 and temp_y + 2 to southeast for the distance southeast from loop_room with nw se path;
                        otherwise;
                            place se corner + offset of loop_room at temp_x + 2 and temp_y + 2;
                        end if;
                        [check 76;]
                        now map drawn direction is south;
                        if loop_room has an exit to south begin;
                            place south exit + offset of loop_room at temp_x + 1 and temp_y + 2;
                            draw a path from temp_x + 1 and temp_y + 2 to south for the distance south from loop_room with north south path;
                        otherwise;
                            place south wall + offset of loop_room at temp_x + 1 and temp_y + 2;
                        end if;
                        [check 76;]
                        now map drawn direction is north;
                        if loop_room has an exit to north begin;
                            place north exit + offset of loop_room at temp_x + 1 and temp_y;
                            draw a path from temp_x + 1 and temp_y to north for the distance north from loop_room with north south path;
                        otherwise;
                            place north wall + offset of loop_room at temp_x + 1 and temp_y;
                        end if;
                        [check 76;]
                        now map drawn direction is west;
                        if loop_room has an exit to west begin;
                            place west exit + offset of loop_room at temp_x and temp_y + 1;
                            draw a path from temp_x and temp_y + 1 to west for the distance west from loop_room with east west path;
                        otherwise;
                            place west wall + offset of loop_room at temp_x and temp_y + 1;
                        end if;
                        [check 76;]
                        now map drawn direction is east;
                        if loop_room has an exit to east begin;
                            place east exit + offset of loop_room at temp_x + 2 and temp_y + 1;
                            draw a path from temp_x + 2 and temp_y + 1 to east for the distance east from loop_room with east west path;
                        otherwise;
                            place east wall + offset of loop_room at temp_x + 2 and temp_y + 1;
                        end if;
                        [check 76;]
                        now map drawn direction is up;
                        [ Now, draw the central square of the room and, if needed, and up / down / questionmark arrow within ]
                        place 37 + offset of loop_room at temp_x + 1 and temp_y + 1;
                        now offset is 0;
                        if loop_room is location, now offset is 31; [ changes up arrow to full up arrow and the like ]
                        if loop_room has an exit to up and loop_room has an exit to down begin;
                            place up down arrow + offset of loop_room at temp_x + 1 and temp_y + 1;
                        otherwise if loop_room has an exit to up;
                            place up arrow + offset of loop_room at temp_x + 1 and temp_y + 1;
                        otherwise if loop_room has an exit to down;
                            place down arrow + offset of loop_room at temp_x + 1 and temp_y + 1;
                        [otherwise if loop_room has an exit to inside or loop_room has an exit to outside;
                            if loop_room is location begin;
                                place full question arrow at temp_x + 1 and temp_y + 1;
                            otherwise;
                                place question arrow at temp_x + 1 and temp_y + 1;
                            end if;]
                        otherwise if loop_room has an exit to inside or loop_room has an exit to outside;
                            let ch be automap in;
                            if loop_room is location begin;
                                if loop_room has an exit to inside and loop_room has an exit to outside begin;
                                    now ch is automap present inout;
                                otherwise if loop_room has an exit to inside;
                                    now ch is automap present in;
                                otherwise;
                                    now ch is automap present out;
                                end if;
                            otherwise;
                                if loop_room has an exit to inside and loop_room has an exit to outside begin;
                                    now ch is automap inout;
                                otherwise if loop_room has an exit to inside;
                                    now ch is automap in;
                                otherwise;
                                    now ch is automap out;
                                end if;
                            end if;
                            place ch of loop_room at temp_x + 1 and temp_y + 1;
                        end if;
                        [check 76;]
                    otherwise; [ in zoomed out mode ]
                        if loop_room has an exit to southwest, draw a path from temp_x and temp_y to southwest for the distance southwest from loop_room with ne sw path;
                        if loop_room has an exit to northwest, draw a path from temp_x and temp_y to northwest for the distance northwest from loop_room with nw se path;
                        if loop_room has an exit to southeast, draw a path from temp_x and temp_y to southeast for the distance southeast from loop_room with nw se path;
                        if loop_room has an exit to northeast, draw a path from temp_x and temp_y to northeast for the distance northeast from loop_room with ne sw path;
                        if loop_room has an exit to south, draw a path from temp_x and temp_y to south for the distance south from loop_room with north south path;
                        if loop_room has an exit to north, draw a path from temp_x and temp_y to north for the distance north from loop_room with north south path;
                        if loop_room has an exit to east, draw a path from temp_x and temp_y to east for the distance east from loop_room with east west path;
                        if loop_room has an exit to west, draw a path from temp_x and temp_y to west for the distance west from loop_room with east west path;
                        let offset be 0;
                        if loop_room is location, now offset is 31;
                        if loop_room has an exit to up and loop_room has an exit to down begin;
                            place up down arrow + offset of loop_room at temp_x and temp_y;
                        otherwise if loop_room has an exit to up;
                            place up arrow + offset of loop_room at temp_x and temp_y;
                        otherwise if loop_room has an exit to down;
                            place down arrow + offset of loop_room at temp_x and temp_y;
                        otherwise if loop_room has an exit to inside or loop_room has an exit to outside;
                            [if loop_room is location begin;
                                place full question arrow at temp_x and temp_y;
                            otherwise;
                                place question arrow at temp_x and temp_y;
                            end if;]
                            let ch be automap in;
                            if loop_room is location begin;
                                if loop_room has an exit to inside and loop_room has an exit to outside begin;
                                    now ch is automap present inout;
                                otherwise if loop_room has an exit to inside;
                                    now ch is automap present in;
                                otherwise;
                                    now ch is automap present out;
                                end if;
                            otherwise;
                                if loop_room has an exit to inside and loop_room has an exit to outside begin;
                                    now ch is automap inout;
                                otherwise if loop_room has an exit to inside;
                                    now ch is automap in;
                                otherwise;
                                    now ch is automap out;
                                end if;
                            end if;
                            place ch of loop_room at temp_x and temp_y;
                        otherwise if loop_room is location;
                            place full room of loop_room at temp_x and temp_y;
                        otherwise;
                            place empty room of loop_room at temp_x and temp_y;
                        end if;
                    end if;
                    [now map drawn room is nothing;]
                    [now map drawn room is automap null room;]
                end if;
            end repeat;
            end the automap drawing activity;
            end the automap work activity;
            [stop capturing text;]
            decide yes;
        end if;
        [stop capturing text;]
        decide no.