Current section
Files
Jump to
Current section
Files
src/yog@render@ascii.erl
-module(yog@render@ascii).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/yog/render/ascii.gleam").
-export([grid_to_string/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" ASCII art rendering for grids and mazes.\n"
"\n"
" Renders grid structures as text using simple ASCII characters (+, -, |).\n"
" Perfect for terminal output and following along with\n"
" \"Mazes for Programmers\" book examples.\n"
"\n"
" ## Quick Start\n"
"\n"
" ```gleam\n"
" import yog/render/ascii\n"
" import yog/builder/grid\n"
"\n"
" let map = [\n"
" [\">\", \">\", \".\"],\n"
" [\".\", \"V\", \">\"],\n"
" [\".\", \".\", \".\"],\n"
" ]\n"
" let maze =\n"
" grid.from_2d_list(\n"
" map,\n"
" model.Directed,\n"
" grid.including([\">\", \"<\", \"V\", \"^\"]),\n"
" )\n"
"\n"
" io.println(ascii.grid_to_string(maze))\n"
" ```\n"
"\n"
" ## Output\n"
"\n"
" ```\n"
" +---+---+---+\n"
" | | |\n"
" +---+ +---+\n"
" | | |\n"
" +---+---+---+\n"
" | | | |\n"
" +---+---+---+\n"
" ```\n"
).
-file("src/yog/render/ascii.gleam", 79).
-spec draw_top_border(integer()) -> binary().
draw_top_border(Cols) ->
<<"+"/utf8, (gleam@string:repeat(<<"---+"/utf8>>, Cols))/binary>>.
-file("src/yog/render/ascii.gleam", 132).
?DOC(" Checks if an edge exists from one node to another.\n").
-spec has_edge(yog@model:graph(any(), any()), integer(), integer()) -> boolean().
has_edge(Graph, From, To) ->
case gleam_stdlib:map_get(erlang:element(4, Graph), From) of
{ok, Neighbors} ->
gleam@dict:has_key(Neighbors, To);
{error, _} ->
false
end.
-file("src/yog/render/ascii.gleam", 127).
?DOC(
" Checks if there's a passage (edge) between two cells.\n"
"\n"
" A passage exists if there's an edge in either direction\n"
" (since mazes can be directed or undirected).\n"
).
-spec has_passage(yog@model:graph(any(), any()), integer(), integer()) -> boolean().
has_passage(Graph, From, To) ->
has_edge(Graph, From, To) orelse has_edge(Graph, To, From).
-file("src/yog/render/ascii.gleam", 83).
-spec draw_cell_row(yog@builder@grid:grid(any(), any()), integer()) -> binary().
draw_cell_row(Grid, Row) ->
_pipe = yog@internal@utils:range(0, erlang:element(4, Grid) - 1),
gleam@list:fold(
_pipe,
<<"|"/utf8>>,
fun(Acc, Col) ->
Cell_id = yog@builder@grid:coord_to_id(
Row,
Col,
erlang:element(4, Grid)
),
Right_id = yog@builder@grid:coord_to_id(
Row,
Col + 1,
erlang:element(4, Grid)
),
Wall = case has_passage(erlang:element(2, Grid), Cell_id, Right_id) of
true ->
<<" "/utf8>>;
false ->
<<" |"/utf8>>
end,
<<Acc/binary, Wall/binary>>
end
).
-file("src/yog/render/ascii.gleam", 101).
-spec draw_horizontal_walls(yog@builder@grid:grid(any(), any()), integer()) -> binary().
draw_horizontal_walls(Grid, Row) ->
_pipe = yog@internal@utils:range(0, erlang:element(4, Grid) - 1),
gleam@list:fold(
_pipe,
<<"+"/utf8>>,
fun(Acc, Col) ->
Cell_id = yog@builder@grid:coord_to_id(
Row,
Col,
erlang:element(4, Grid)
),
Below_id = yog@builder@grid:coord_to_id(
Row + 1,
Col,
erlang:element(4, Grid)
),
Wall = case has_passage(erlang:element(2, Grid), Cell_id, Below_id) of
true ->
<<" +"/utf8>>;
false ->
<<"---+"/utf8>>
end,
<<Acc/binary, Wall/binary>>
end
).
-file("src/yog/render/ascii.gleam", 58).
?DOC(
" Converts a grid to ASCII art using simple characters (+, -, |).\n"
"\n"
" Each cell is represented as a 3-character wide space. Walls are drawn\n"
" where edges don't exist between adjacent cells.\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" let maze = // ... create grid\n"
" io.println(ascii.grid_to_string(maze))\n"
" ```\n"
).
-spec grid_to_string(yog@builder@grid:grid(any(), any())) -> binary().
grid_to_string(Grid) ->
case {erlang:element(3, Grid), erlang:element(4, Grid)} of
{0, _} ->
<<""/utf8>>;
{_, 0} ->
<<""/utf8>>;
{_, _} ->
Top_line = draw_top_border(erlang:element(4, Grid)),
Body_lines = begin
_pipe = yog@internal@utils:range(0, erlang:element(3, Grid) - 1),
gleam@list:flat_map(
_pipe,
fun(Row) ->
[draw_cell_row(Grid, Row),
draw_horizontal_walls(Grid, Row)]
end
)
end,
_pipe@1 = [Top_line | Body_lines],
gleam@string:join(_pipe@1, <<"\n"/utf8>>)
end.