create-asciitorium 0.1.36 → 0.1.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +0 -0
- package/package.json +1 -1
- package/dist/templates/base/index.css +0 -43
- package/dist/templates/base/public/art/asciitorium.art +0 -111
- package/dist/templates/base/public/art/asciitorium.txt +0 -111
- package/dist/templates/base/public/art/borders/bubbles.art +0 -16
- package/dist/templates/base/public/art/borders/bubbles.txt +0 -16
- package/dist/templates/base/public/art/borders/dna.art +0 -9
- package/dist/templates/base/public/art/borders/dna.txt +0 -9
- package/dist/templates/base/public/art/castle.art +0 -4
- package/dist/templates/base/public/art/castle.txt +0 -4
- package/dist/templates/base/public/art/computer.art +0 -17
- package/dist/templates/base/public/art/computer.txt +0 -17
- package/dist/templates/base/public/art/mazes/example.art +0 -21
- package/dist/templates/base/public/art/mazes/example.txt +0 -21
- package/dist/templates/base/public/art/sprites/tatooene.art +0 -5
- package/dist/templates/base/public/art/tatooene.txt +0 -5
- package/dist/templates/base/public/fonts/FreeLicense.txt +0 -20
- package/dist/templates/base/public/fonts/PRNumber3.ttf +0 -0
- package/dist/templates/base/public/fonts/PRNumber3.woff +0 -0
- package/dist/templates/base/public/fonts/PRNumber3.woff2 +0 -0
- package/dist/templates/base/public/fonts/PrintChar21.ttf +0 -0
- package/dist/templates/base/public/fonts/PrintChar21.woff +0 -0
- package/dist/templates/base/public/fonts/PrintChar21.woff2 +0 -0
- package/dist/templates/base/public/images/logo.png +0 -0
- package/dist/templates/base/scripts/maze-builder.js +0 -294
package/dist/index.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
@import url('https://fonts.cdnfonts.com/css/jetbrains-mono');
|
|
2
|
-
@font-face {
|
|
3
|
-
font-family: 'PrintChar21';
|
|
4
|
-
src:
|
|
5
|
-
url('/fonts/PrintChar21.woff2') format('woff2'),
|
|
6
|
-
url('/fonts/PrintChar21.woff') format('woff'),
|
|
7
|
-
url('/fonts/PrintChar21.ttf') format('truetype');
|
|
8
|
-
font-weight: normal;
|
|
9
|
-
font-style: normal;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
body {
|
|
13
|
-
font-family: 'JetBrains Mono', sans-serif;
|
|
14
|
-
margin: 0;
|
|
15
|
-
background: black;
|
|
16
|
-
color: #3fff00;
|
|
17
|
-
|
|
18
|
-
/* Center the screen both horizontally and vertically */
|
|
19
|
-
display: flex;
|
|
20
|
-
justify-content: center;
|
|
21
|
-
align-items: center;
|
|
22
|
-
height: 100vh; /* Full viewport height */
|
|
23
|
-
width: 100vw; /* Full viewport width */
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
#screen {
|
|
27
|
-
/* Use 90% of viewport dimensions to leave some margin */
|
|
28
|
-
width: 90vw;
|
|
29
|
-
height: 90vh;
|
|
30
|
-
margin: 0;
|
|
31
|
-
padding: 0;
|
|
32
|
-
overflow: hidden; /* Hide scrollbars for clean appearance */
|
|
33
|
-
|
|
34
|
-
/* Ensure monospace font for proper character sizing */
|
|
35
|
-
font-family: 'PrintChar21', 'Courier New', Courier, monospace;
|
|
36
|
-
font-size: 16px; /* Base font size for character measurement */
|
|
37
|
-
line-height: 1; /* Tight line spacing for ASCII art */
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.inverted {
|
|
41
|
-
background-color: #3fff00;
|
|
42
|
-
color: black;
|
|
43
|
-
}
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
§ {"loop":true,"duration":120}
|
|
2
|
-
_ _ _ _
|
|
3
|
-
__ _ ___ ___(_|_) |_ ___ _ __(_)_ _ _ __ ___
|
|
4
|
-
/ _` / __|/ __| | | __/ _ \| '__| | | | | '_ ` _ \
|
|
5
|
-
| (_| \__ \ (__| | | || (_) | | | | |_| | | | | | |
|
|
6
|
-
\__,_|___/\___|_|_|\__\___/|_| |_|\__,_|_| |_| |_|
|
|
7
|
-
¶ {"duration":8000}
|
|
8
|
-
_ _ _
|
|
9
|
-
__ _ ___ ___(_| )| _ ___ _ __(_)_ _ _ __ .
|
|
10
|
-
/ _` / __|/ __| | | __/ _ \| '__| | | | | '_ ` _ \.
|
|
11
|
-
| (_| \__ \ (__| | | || (_) | | | | |_| | | | | | |
|
|
12
|
-
\__,_|___/\___|_|_|\__\___/|_| |_|\__,_|_| |_| |_|
|
|
13
|
-
¶ {"duration":1000}
|
|
14
|
-
. _ * _ * .
|
|
15
|
-
__ _ ___ ___(_|_).|_ * _ __(_)_ _ * __
|
|
16
|
-
/ _` / __|/ _ . | __/ . \ '__| | | | ' ` \ .
|
|
17
|
-
| (_| \__ (__| *|.| || (_) | * | | |_| *| | | │ .
|
|
18
|
-
\__,_|___/\__ ._|_|\__\ * /|_| .|\__ |_| |_│
|
|
19
|
-
¶ {"duration":140}
|
|
20
|
-
* _ * . * . *
|
|
21
|
-
__ * (_|_) . * _ __ . . __
|
|
22
|
-
/ ` __| | __/ * \ '__| * ` \
|
|
23
|
-
| * * \__ | | || (_) | . | * * | | │
|
|
24
|
-
. .|___/ |_| \__\___/|_| . . |_| . |_│
|
|
25
|
-
¶ {"duration":140}
|
|
26
|
-
. * . _ * . . .
|
|
27
|
-
__ * * (_|_). . * _ * . __
|
|
28
|
-
/ _` * __| | __/ * * \ '__| . * _ \
|
|
29
|
-
| (_| * \__ | || (_) . | * . * | | │
|
|
30
|
-
. ._|___/ |_| \__\ * |_| . * |_| |_│
|
|
31
|
-
¶ {"duration":160}
|
|
32
|
-
. * . _ * . * . .
|
|
33
|
-
* . (_|_) . . * . * .
|
|
34
|
-
/ ` * __| __/ * . * . * . \
|
|
35
|
-
| * * \__ | (_)* . * . * . | │
|
|
36
|
-
. .|___/ |_| * . * . . |_|
|
|
37
|
-
¶ {"duration":140}
|
|
38
|
-
. * . . * . .
|
|
39
|
-
. . . * . * .
|
|
40
|
-
* . . . * .
|
|
41
|
-
. * . . . *
|
|
42
|
-
. . * . .
|
|
43
|
-
¶ {"duration":240}
|
|
44
|
-
. * . . * .
|
|
45
|
-
. . . * . *
|
|
46
|
-
. * . . . *
|
|
47
|
-
. . * . . .
|
|
48
|
-
* . . * .
|
|
49
|
-
¶ {"duration":240}
|
|
50
|
-
. * . . *
|
|
51
|
-
. . . * .
|
|
52
|
-
. * . . .
|
|
53
|
-
. . * . .
|
|
54
|
-
* . . . *
|
|
55
|
-
¶ {"duration":240}
|
|
56
|
-
|
|
57
|
-
. . * . .
|
|
58
|
-
. * . .
|
|
59
|
-
. . * .
|
|
60
|
-
* . . .
|
|
61
|
-
¶ {"duration":240}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
. . * .
|
|
65
|
-
. * . .
|
|
66
|
-
* . . .
|
|
67
|
-
¶ {"duration":240}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
. * .
|
|
72
|
-
* . .
|
|
73
|
-
¶ {"duration":260}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
. .
|
|
79
|
-
¶ {"duration":280}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
¶ {"duration":1000}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
_ _ _ _
|
|
91
|
-
¶ {"duration":140}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
_ _ _ _
|
|
97
|
-
__ _ ___ ___(_|_) |_ ___ _ __(_)_ _ _ __ ___
|
|
98
|
-
¶ {"duration":140}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
_ _ _ _
|
|
103
|
-
__ _ ___ ___(_|_) |_ ___ _ __(_)_ _ _ __ ___
|
|
104
|
-
╱ _` ╱ __|╱ __| | | __╱ _ ╲| '__| | | | | '_ ` _ ╲
|
|
105
|
-
¶ {"duration":140}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
_ _ _ _
|
|
109
|
-
__ _ ___ ___(_|_) |_ ___ _ __(_)_ _ _ __ ___
|
|
110
|
-
/ _` / __|/ __| | | __/ _ \| '__| | | | | '_ ` _ \
|
|
111
|
-
| (_| \__ \ (__| | | || (_) | | | | |_| | | | | | |
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
§ {"loop":true,"duration":120}
|
|
2
|
-
_ _ _ _
|
|
3
|
-
__ _ ___ ___(_|_) |_ ___ _ __(_)_ _ _ __ ___
|
|
4
|
-
/ _` / __|/ __| | | __/ _ \| '__| | | | | '_ ` _ \
|
|
5
|
-
| (_| \__ \ (__| | | || (_) | | | | |_| | | | | | |
|
|
6
|
-
\__,_|___/\___|_|_|\__\___/|_| |_|\__,_|_| |_| |_|
|
|
7
|
-
¶ {"duration":8000}
|
|
8
|
-
_ _ _
|
|
9
|
-
__ _ ___ ___(_| )| _ ___ _ __(_)_ _ _ __ .
|
|
10
|
-
/ _` / __|/ __| | | __/ _ \| '__| | | | | '_ ` _ \.
|
|
11
|
-
| (_| \__ \ (__| | | || (_) | | | | |_| | | | | | |
|
|
12
|
-
\__,_|___/\___|_|_|\__\___/|_| |_|\__,_|_| |_| |_|
|
|
13
|
-
¶ {"duration":1000}
|
|
14
|
-
. _ * _ * .
|
|
15
|
-
__ _ ___ ___(_|_).|_ * _ __(_)_ _ * __
|
|
16
|
-
/ _` / __|/ _ . | __/ . \ '__| | | | ' ` \ .
|
|
17
|
-
| (_| \__ (__| *|.| || (_) | * | | |_| *| | | │ .
|
|
18
|
-
\__,_|___/\__ ._|_|\__\ * /|_| .|\__ |_| |_│
|
|
19
|
-
¶ {"duration":140}
|
|
20
|
-
* _ * . * . *
|
|
21
|
-
__ * (_|_) . * _ __ . . __
|
|
22
|
-
/ ` __| | __/ * \ '__| * ` \
|
|
23
|
-
| * * \__ | | || (_) | . | * * | | │
|
|
24
|
-
. .|___/ |_| \__\___/|_| . . |_| . |_│
|
|
25
|
-
¶ {"duration":140}
|
|
26
|
-
. * . _ * . . .
|
|
27
|
-
__ * * (_|_). . * _ * . __
|
|
28
|
-
/ _` * __| | __/ * * \ '__| . * _ \
|
|
29
|
-
| (_| * \__ | || (_) . | * . * | | │
|
|
30
|
-
. ._|___/ |_| \__\ * |_| . * |_| |_│
|
|
31
|
-
¶ {"duration":160}
|
|
32
|
-
. * . _ * . * . .
|
|
33
|
-
* . (_|_) . . * . * .
|
|
34
|
-
/ ` * __| __/ * . * . * . \
|
|
35
|
-
| * * \__ | (_)* . * . * . | │
|
|
36
|
-
. .|___/ |_| * . * . . |_|
|
|
37
|
-
¶ {"duration":140}
|
|
38
|
-
. * . . * . .
|
|
39
|
-
. . . * . * .
|
|
40
|
-
* . . . * .
|
|
41
|
-
. * . . . *
|
|
42
|
-
. . * . .
|
|
43
|
-
¶ {"duration":240}
|
|
44
|
-
. * . . * .
|
|
45
|
-
. . . * . *
|
|
46
|
-
. * . . . *
|
|
47
|
-
. . * . . .
|
|
48
|
-
* . . * .
|
|
49
|
-
¶ {"duration":240}
|
|
50
|
-
. * . . *
|
|
51
|
-
. . . * .
|
|
52
|
-
. * . . .
|
|
53
|
-
. . * . .
|
|
54
|
-
* . . . *
|
|
55
|
-
¶ {"duration":240}
|
|
56
|
-
|
|
57
|
-
. . * . .
|
|
58
|
-
. * . .
|
|
59
|
-
. . * .
|
|
60
|
-
* . . .
|
|
61
|
-
¶ {"duration":240}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
. . * .
|
|
65
|
-
. * . .
|
|
66
|
-
* . . .
|
|
67
|
-
¶ {"duration":240}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
. * .
|
|
72
|
-
* . .
|
|
73
|
-
¶ {"duration":260}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
. .
|
|
79
|
-
¶ {"duration":280}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
¶ {"duration":1000}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
_ _ _ _
|
|
91
|
-
¶ {"duration":140}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
_ _ _ _
|
|
97
|
-
__ _ ___ ___(_|_) |_ ___ _ __(_)_ _ _ __ ___
|
|
98
|
-
¶ {"duration":140}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
_ _ _ _
|
|
103
|
-
__ _ ___ ___(_|_) |_ ___ _ __(_)_ _ _ __ ___
|
|
104
|
-
╱ _` ╱ __|╱ __| | | __╱ _ ╲| '__| | | | | '_ ` _ ╲
|
|
105
|
-
¶ {"duration":140}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
_ _ _ _
|
|
109
|
-
__ _ ___ ___(_|_) |_ ___ _ __(_)_ _ _ __ ___
|
|
110
|
-
/ _` / __|/ __| | | __/ _ \| '__| | | | | '_ ` _ \
|
|
111
|
-
| (_| \__ \ (__| | | || (_) | | | | |_| | | | | | |
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
_____________________
|
|
2
|
-
/ ` \
|
|
3
|
-
| .-----------. | |-----.
|
|
4
|
-
| | | | |-=---|
|
|
5
|
-
| | | | |-----|
|
|
6
|
-
| | | | |-----|
|
|
7
|
-
| | | | |-----|
|
|
8
|
-
| `-----------' | |-----'/\
|
|
9
|
-
\________________/___' / \
|
|
10
|
-
/ / / /
|
|
11
|
-
/ // // / / /
|
|
12
|
-
/ / / /
|
|
13
|
-
/ _/_/_/_/_/_/_/_/_/_/ / /
|
|
14
|
-
/ _/_/_/_/_/_/_/_/_/_/ / /
|
|
15
|
-
/ _/_/_/_______/_/_/_/ / __/
|
|
16
|
-
/______________________/ /
|
|
17
|
-
\______________________\/
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
_____________________
|
|
2
|
-
/ ` \
|
|
3
|
-
| .-----------. | |-----.
|
|
4
|
-
| | | | |-=---|
|
|
5
|
-
| | | | |-----|
|
|
6
|
-
| | | | |-----|
|
|
7
|
-
| | | | |-----|
|
|
8
|
-
| `-----------' | |-----'/\
|
|
9
|
-
\________________/___' / \
|
|
10
|
-
/ / / /
|
|
11
|
-
/ // // / / /
|
|
12
|
-
/ / / /
|
|
13
|
-
/ _/_/_/_/_/_/_/_/_/_/ / /
|
|
14
|
-
/ _/_/_/_/_/_/_/_/_/_/ / /
|
|
15
|
-
/ _/_/_/_______/_/_/_/ / __/
|
|
16
|
-
/______________________/ /
|
|
17
|
-
\______________________\/
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
╭───────────────────────────────────┬───╮
|
|
2
|
-
│ │ │
|
|
3
|
-
│ ╷ ╭───────────────┬───────╮ ╰─o─┤
|
|
4
|
-
│ │ │ │ │ │
|
|
5
|
-
│ │ ╵ ╶───────╮ ├─o─╮ ╰───╮ │
|
|
6
|
-
│ │ │ │ │ │ │
|
|
7
|
-
│ ╰───────┬───────╯ ├───┤ ╭───╯ │
|
|
8
|
-
│ │ │ │ │ │
|
|
9
|
-
├───────────╯ ╭───────┴─o─┤ │ ╶───┤
|
|
10
|
-
│ │ │ │ │
|
|
11
|
-
│ ╭───╴ ╭───╯ ╭───────╯ ├───╮ │
|
|
12
|
-
│ │ │ │ │ │ │
|
|
13
|
-
│ ╰───┬─o─┤ ╭───┤ ╶───╮ ├─o─┤ │
|
|
14
|
-
│ │ │ │ │ │ │ │ │
|
|
15
|
-
├───╮ ╰───╯ ├─o─╯ ╷ │ ╵ │ │
|
|
16
|
-
│ │ │ │ │ │ │
|
|
17
|
-
├─o─┴───────────┤ ╭───╯ ├───────┤ │
|
|
18
|
-
│ │ │ │ │ │
|
|
19
|
-
│ ╶───╮ ╶───╯ │ ╶───╯ ╷ ╵ │
|
|
20
|
-
│ │ │ │ │
|
|
21
|
-
╰───────┴───────────┴───────────┴───────╯
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
╭───────────────────────────────────┬───╮
|
|
2
|
-
│ │ │
|
|
3
|
-
│ ╷ ╭───────────────┬───────╮ ╰─o─┤
|
|
4
|
-
│ │ │ │ │ │
|
|
5
|
-
│ │ ╵ ╶───────╮ ├─o─╮ ╰───╮ │
|
|
6
|
-
│ │ │ │ │ │ │
|
|
7
|
-
│ ╰───────┬───────╯ ├───┤ ╭───╯ │
|
|
8
|
-
│ │ │ │ │ │
|
|
9
|
-
├───────────╯ ╭───────┴─o─┤ │ ╶───┤
|
|
10
|
-
│ │ │ │ │
|
|
11
|
-
│ ╭───╴ ╭───╯ ╭───────╯ ├───╮ │
|
|
12
|
-
│ │ │ │ │ │ │
|
|
13
|
-
│ ╰───┬─o─┤ ╭───┤ ╶───╮ ├─o─┤ │
|
|
14
|
-
│ │ │ │ │ │ │ │ │
|
|
15
|
-
├───╮ ╰───╯ ├─o─╯ ╷ │ ╵ │ │
|
|
16
|
-
│ │ │ │ │ │ │
|
|
17
|
-
├─o─┴───────────┤ ╭───╯ ├───────┤ │
|
|
18
|
-
│ │ │ │ │ │
|
|
19
|
-
│ ╶───╮ ╶───╯ │ ╶───╯ ╷ ╵ │
|
|
20
|
-
│ │ │ │ │
|
|
21
|
-
╰───────┴───────────┴───────────┴───────╯
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
KREATIVE SOFTWARE RELAY FONTS FREE USE LICENSE
|
|
2
|
-
version 1.2f
|
|
3
|
-
|
|
4
|
-
Permission is hereby granted, free of charge, to any person or entity (the "User") obtaining a copy of the included font files (the "Software") produced by Kreative Software, to utilize, display, embed, or redistribute the Software, subject to the following conditions:
|
|
5
|
-
|
|
6
|
-
1. The User may not sell copies of the Software for a fee.
|
|
7
|
-
|
|
8
|
-
1a. The User may give away copies of the Software free of charge provided this license and any documentation is included verbatim and credit is given to Kreative Korporation or Kreative Software.
|
|
9
|
-
|
|
10
|
-
2. The User may not modify, reverse-engineer, or create any derivative works of the Software.
|
|
11
|
-
|
|
12
|
-
3. Any Software carrying the following font names or variations thereof is not covered by this license and may not be used under the terms of this license: Jewel Hill, Miss Diode n Friends, This is Beckie's font!
|
|
13
|
-
|
|
14
|
-
3a. Any Software carrying a font name ending with the string "Pro CE" is not covered by this license and may not be used under the terms of this license.
|
|
15
|
-
|
|
16
|
-
4. This license becomes null and void if any of the above conditions are not met.
|
|
17
|
-
|
|
18
|
-
5. Kreative Software reserves the right to change this license at any time without notice.
|
|
19
|
-
|
|
20
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE SOFTWARE OR FROM OTHER DEALINGS IN THE SOFTWARE.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
import fs from 'fs/promises'
|
|
2
|
-
import process from 'process'
|
|
3
|
-
import path from 'path'
|
|
4
|
-
|
|
5
|
-
function parseArgs() {
|
|
6
|
-
const args = process.argv.slice(2)
|
|
7
|
-
|
|
8
|
-
// Check for flags
|
|
9
|
-
let smooth = false
|
|
10
|
-
let filteredArgs = []
|
|
11
|
-
|
|
12
|
-
for (let i = 0; i < args.length; i++) {
|
|
13
|
-
if (args[i] === '--smooth' || args[i] === '--unicode') {
|
|
14
|
-
smooth = true
|
|
15
|
-
} else {
|
|
16
|
-
filteredArgs.push(args[i])
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
if (filteredArgs.length !== 3) {
|
|
21
|
-
console.error('Usage: node maze-builder.js <width> <height> <filename> [--smooth]')
|
|
22
|
-
console.error('Example: node maze-builder.js 10 10 dungeon-level-1.txt --smooth')
|
|
23
|
-
console.error('Mazes will be saved to public/art/mazes/ directory')
|
|
24
|
-
console.error('Use --smooth flag to enable Unicode box drawing characters')
|
|
25
|
-
process.exit(1)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const width = parseInt(filteredArgs[0])
|
|
29
|
-
const height = parseInt(filteredArgs[1])
|
|
30
|
-
const filename = filteredArgs[2]
|
|
31
|
-
|
|
32
|
-
if (isNaN(width) || width <= 0) {
|
|
33
|
-
console.error('Width must be a positive integer')
|
|
34
|
-
process.exit(1)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (isNaN(height) || height <= 0) {
|
|
38
|
-
console.error('Height must be a positive integer')
|
|
39
|
-
process.exit(1)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Construct the full path to the mazes directory
|
|
43
|
-
const mazesDir = path.join(process.cwd(), '../public/art/mazes')
|
|
44
|
-
const fullPath = path.join(mazesDir, filename)
|
|
45
|
-
|
|
46
|
-
return { width, height, filename: fullPath, mazesDir, smooth }
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
class MazeBuilder {
|
|
50
|
-
// Maze is a 2D array of chars.
|
|
51
|
-
// example 10x10 grid = [
|
|
52
|
-
// 0123456789012345678
|
|
53
|
-
// 0'+-0-+---+---+---+---+',
|
|
54
|
-
// 1'0 1 2 3 4 5 6 7 8 9 |',
|
|
55
|
-
// 2'+-2-+---+---+---+---+',
|
|
56
|
-
// 3'| 3 | | |',
|
|
57
|
-
// 4'+-4-+ + + + +',
|
|
58
|
-
// 5'| 5 | | | |',
|
|
59
|
-
// 6'+-6-+ +---+ + +',
|
|
60
|
-
// 7'| 7 | | | |',
|
|
61
|
-
// 8'+-8-+ + +---+ +',
|
|
62
|
-
// 9'| 9 | | |',
|
|
63
|
-
// '+---+---+---+---+---+',
|
|
64
|
-
// ]
|
|
65
|
-
// is actually a 11x19 2d array
|
|
66
|
-
// conversion: y = y, x = x*2
|
|
67
|
-
// only place items and creatures on odd values of y and x
|
|
68
|
-
|
|
69
|
-
constructor(width, height, fileName, mazesDir, smooth = false) {
|
|
70
|
-
this.fileName = fileName
|
|
71
|
-
this.mazesDir = mazesDir
|
|
72
|
-
this.width = width
|
|
73
|
-
this.height = height
|
|
74
|
-
this.smooth = smooth
|
|
75
|
-
this.map = []
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async build() {
|
|
79
|
-
console.log(`--- building maze (${this.width}x${this.height}) ---`)
|
|
80
|
-
|
|
81
|
-
try {
|
|
82
|
-
this.map = this.createMaze()
|
|
83
|
-
console.log(' - created base maze')
|
|
84
|
-
|
|
85
|
-
// Add rooms
|
|
86
|
-
this.addRooms()
|
|
87
|
-
console.log(' - added rooms')
|
|
88
|
-
|
|
89
|
-
// Smooth the maze with Unicode box drawing characters (if requested)
|
|
90
|
-
if (this.smooth) {
|
|
91
|
-
this.mapUpdate(this.map)
|
|
92
|
-
console.log(' - smoothed maze appearance with Unicode characters')
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Save the maze to text file
|
|
96
|
-
await this.saveToText()
|
|
97
|
-
console.log('--- maze build complete ---')
|
|
98
|
-
} catch (error) {
|
|
99
|
-
console.error(`Error building maze: ${error.message}`)
|
|
100
|
-
console.error(error)
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
async saveToText() {
|
|
105
|
-
try {
|
|
106
|
-
// Ensure the mazes directory exists
|
|
107
|
-
await fs.mkdir(this.mazesDir, { recursive: true })
|
|
108
|
-
|
|
109
|
-
// Join the map array with newlines to create plain text
|
|
110
|
-
const textOutput = this.map.join('\n')
|
|
111
|
-
|
|
112
|
-
await fs.writeFile(this.fileName, textOutput, 'utf-8')
|
|
113
|
-
console.log(` - successfully wrote maze data to ${this.fileName}`)
|
|
114
|
-
} catch (error) {
|
|
115
|
-
console.error(`Error writing text to file: ${error.message}`)
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
xOffset(x) {
|
|
120
|
-
return x * 4 + 2
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
yOffset(y) {
|
|
124
|
-
return y * 2 + 1
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Doors are placed at all dead ends with openings to the north and south.
|
|
128
|
-
addRooms() {
|
|
129
|
-
for (let y = 0; y < this.height; y++) {
|
|
130
|
-
const yPos = this.yOffset(y)
|
|
131
|
-
for (let x = 0; x < this.width; x++) {
|
|
132
|
-
const xPos = this.xOffset(x)
|
|
133
|
-
this.replaceSpacesWithDoors(xPos, yPos)
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// identify dead ends to the north or south.
|
|
139
|
-
// If there is a dead end to the north or south, then specify the x and y position of the opening.
|
|
140
|
-
replaceSpacesWithDoors(xPos, yPos) {
|
|
141
|
-
if (this.map[yPos][xPos] != ' ') return
|
|
142
|
-
const wallDirections = []
|
|
143
|
-
if (this.map[yPos][xPos - 2] != ' ' && this.map[yPos][xPos - 2] != 'o') wallDirections.push('west')
|
|
144
|
-
if (this.map[yPos][xPos + 2] != ' ' && this.map[yPos][xPos + 2] != 'o') wallDirections.push('east')
|
|
145
|
-
if (this.map[yPos - 1][xPos] != ' ' && this.map[yPos - 1][xPos] != 'o') wallDirections.push('north')
|
|
146
|
-
if (this.map[yPos + 1][xPos] != ' ' && this.map[yPos + 1][xPos] != 'o') wallDirections.push('south')
|
|
147
|
-
if (wallDirections.length == 3) {
|
|
148
|
-
if (wallDirections.includes('north') && !wallDirections.includes('south')) {
|
|
149
|
-
this.map[yPos + 1] = this.replaceAt(this.map[yPos + 1], xPos - 1, '-')
|
|
150
|
-
this.map[yPos + 1] = this.replaceAt(this.map[yPos + 1], xPos, 'o')
|
|
151
|
-
this.map[yPos + 1] = this.replaceAt(this.map[yPos + 1], xPos + 1, '-')
|
|
152
|
-
} else if (!wallDirections.includes('north') && wallDirections.includes('south')) {
|
|
153
|
-
this.map[yPos - 1] = this.replaceAt(this.map[yPos - 1], xPos - 1, '-')
|
|
154
|
-
this.map[yPos - 1] = this.replaceAt(this.map[yPos - 1], xPos, 'o')
|
|
155
|
-
this.map[yPos - 1] = this.replaceAt(this.map[yPos - 1], xPos + 1, '-')
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
replaceAt(string, index, replacement) {
|
|
161
|
-
return string.substr(0, index) + replacement + string.substr(index + replacement.length)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
mapUpdate(map) {
|
|
165
|
-
const copy = [...map]
|
|
166
|
-
for (let y = 0; y < copy.length; y++) {
|
|
167
|
-
for (let x = 0; x < copy[y].length; x++) {
|
|
168
|
-
if (copy[y][x] === '-') copy[y] = copy[y].substring(0, x) + '─' + copy[y].substring(x + 1)
|
|
169
|
-
if (copy[y][x] === '|') copy[y] = copy[y].substring(0, x) + '│' + copy[y].substring(x + 1)
|
|
170
|
-
if (copy[y][x] === '+') {
|
|
171
|
-
let north = y > 0 && copy[y - 1][x] !== ' '
|
|
172
|
-
let south = y < copy.length - 1 && copy[y + 1][x] !== ' '
|
|
173
|
-
let west = x > 0 && copy[y][x - 1] !== ' '
|
|
174
|
-
let east = x < copy[y].length - 1 && copy[y][x + 1] !== ' '
|
|
175
|
-
if (north && south && west && east) copy[y] = copy[y].substring(0, x) + '┼' + copy[y].substring(x + 1)
|
|
176
|
-
else if (north && south && west) copy[y] = copy[y].substring(0, x) + '┤' + copy[y].substring(x + 1)
|
|
177
|
-
else if (north && south && east) copy[y] = copy[y].substring(0, x) + '├' + copy[y].substring(x + 1)
|
|
178
|
-
else if (north && east && west) copy[y] = copy[y].substring(0, x) + '┴' + copy[y].substring(x + 1)
|
|
179
|
-
else if (south && east && west) copy[y] = copy[y].substring(0, x) + '┬' + copy[y].substring(x + 1)
|
|
180
|
-
else if (north && south) copy[y] = copy[y].substring(0, x) + '│' + copy[y].substring(x + 1)
|
|
181
|
-
else if (west && east) copy[y] = copy[y].substring(0, x) + '─' + copy[y].substring(x + 1)
|
|
182
|
-
else if (north && east) copy[y] = copy[y].substring(0, x) + '╰' + copy[y].substring(x + 1)
|
|
183
|
-
else if (north && west) copy[y] = copy[y].substring(0, x) + '╯' + copy[y].substring(x + 1)
|
|
184
|
-
else if (south && east) copy[y] = copy[y].substring(0, x) + '╭' + copy[y].substring(x + 1)
|
|
185
|
-
else if (south && west) copy[y] = copy[y].substring(0, x) + '╮' + copy[y].substring(x + 1)
|
|
186
|
-
else if (east) copy[y] = copy[y].substring(0, x) + '╶' + copy[y].substring(x + 1)
|
|
187
|
-
else if (west) copy[y] = copy[y].substring(0, x) + '╴' + copy[y].substring(x + 1)
|
|
188
|
-
else if (north) copy[y] = copy[y].substring(0, x) + '╵' + copy[y].substring(x + 1)
|
|
189
|
-
else if (south) copy[y] = copy[y].substring(0, x) + '╷' + copy[y].substring(x + 1)
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
this.map = copy
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
createMaze() {
|
|
197
|
-
// Establish variables and starting grid
|
|
198
|
-
const totalCells = this.height * this.width
|
|
199
|
-
const unvisited = [] // cells that are unvisited.
|
|
200
|
-
const maze = []
|
|
201
|
-
for (let y = 0; y < this.height; y++) {
|
|
202
|
-
unvisited[y] = []
|
|
203
|
-
maze[y * 2] = ''
|
|
204
|
-
maze[y * 2 + 1] = ''
|
|
205
|
-
for (let x = 0; x < this.width; x++) {
|
|
206
|
-
maze[y * 2] += '+---'
|
|
207
|
-
maze[y * 2 + 1] += '| '
|
|
208
|
-
unvisited[y][x] = true
|
|
209
|
-
}
|
|
210
|
-
maze[y * 2] += '+'
|
|
211
|
-
maze[y * 2 + 1] += '|'
|
|
212
|
-
}
|
|
213
|
-
maze[this.height * 2] = ''
|
|
214
|
-
for (let x = 0; x < this.width; x++) {
|
|
215
|
-
maze[this.height * 2] += '+---'
|
|
216
|
-
}
|
|
217
|
-
maze[this.height * 2] += '+'
|
|
218
|
-
|
|
219
|
-
// Set a random position to start from
|
|
220
|
-
let current = [Math.floor(Math.random() * this.height), Math.floor(Math.random() * this.width)]
|
|
221
|
-
const path = [current]
|
|
222
|
-
unvisited[current[0]][current[1]] = false
|
|
223
|
-
let visited = 1
|
|
224
|
-
|
|
225
|
-
// // Loop through all available cell positions (given walls take up half the cells, we divide the total by two)
|
|
226
|
-
while (visited < totalCells) {
|
|
227
|
-
// Determine neighboring cells (0,1) and pathways to them (2,3)
|
|
228
|
-
const south = [current[0] - 1, current[1], 'north']
|
|
229
|
-
const north = [current[0] + 1, current[1], 'south']
|
|
230
|
-
const east = [current[0], current[1] - 1, 'west']
|
|
231
|
-
const west = [current[0], current[1] + 1, 'east']
|
|
232
|
-
const possibleNeighbors = [south, north, east, west]
|
|
233
|
-
const neighbors = []
|
|
234
|
-
|
|
235
|
-
// Determine if each neighboring cell is in game grid, and whether it has already been checked
|
|
236
|
-
for (let i = 0; i < possibleNeighbors.length; i++) {
|
|
237
|
-
if (
|
|
238
|
-
possibleNeighbors[i][0] > -1 &&
|
|
239
|
-
possibleNeighbors[i][0] < this.height &&
|
|
240
|
-
possibleNeighbors[i][1] > -1 &&
|
|
241
|
-
possibleNeighbors[i][1] < this.width &&
|
|
242
|
-
unvisited[possibleNeighbors[i][0]][possibleNeighbors[i][1]] == true
|
|
243
|
-
) {
|
|
244
|
-
neighbors.push(possibleNeighbors[i])
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
// If at least one active neighboring cell has been found
|
|
249
|
-
if (neighbors.length > 0) {
|
|
250
|
-
// Choose one of the neighbors at random
|
|
251
|
-
const next = neighbors[Math.floor(Math.random() * neighbors.length)]
|
|
252
|
-
|
|
253
|
-
// Remove the wall between the current cell and the chosen neighboring cell in the maze view.
|
|
254
|
-
// split maze
|
|
255
|
-
let xBorderToRemove = 0
|
|
256
|
-
let yBorderToRemove = 0
|
|
257
|
-
if (next[2] == 'south') {
|
|
258
|
-
yBorderToRemove = this.yOffset(next[0]) - 1
|
|
259
|
-
xBorderToRemove = this.xOffset(next[1])
|
|
260
|
-
maze[yBorderToRemove] = this.replaceAt(maze[yBorderToRemove], xBorderToRemove - 1, ' ')
|
|
261
|
-
maze[yBorderToRemove] = this.replaceAt(maze[yBorderToRemove], xBorderToRemove + 1, ' ')
|
|
262
|
-
} else if (next[2] == 'north') {
|
|
263
|
-
yBorderToRemove = this.yOffset(next[0]) + 1
|
|
264
|
-
xBorderToRemove = this.xOffset(next[1])
|
|
265
|
-
maze[yBorderToRemove] = this.replaceAt(maze[yBorderToRemove], xBorderToRemove - 1, ' ')
|
|
266
|
-
maze[yBorderToRemove] = this.replaceAt(maze[yBorderToRemove], xBorderToRemove + 1, ' ')
|
|
267
|
-
} else if (next[2] == 'east') {
|
|
268
|
-
yBorderToRemove = this.yOffset(next[0])
|
|
269
|
-
xBorderToRemove = this.xOffset(next[1]) - 2
|
|
270
|
-
} else if (next[2] == 'west') {
|
|
271
|
-
yBorderToRemove = this.yOffset(next[0])
|
|
272
|
-
xBorderToRemove = this.xOffset(next[1]) + 2
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
maze[yBorderToRemove] = this.replaceAt(maze[yBorderToRemove], xBorderToRemove, ' ')
|
|
276
|
-
|
|
277
|
-
// Mark the neighbor as visited, and set it as the current cell
|
|
278
|
-
current = next
|
|
279
|
-
unvisited[current[0]][current[1]] = false
|
|
280
|
-
visited++
|
|
281
|
-
path.push(current)
|
|
282
|
-
}
|
|
283
|
-
// Otherwise go back up a step and keep going
|
|
284
|
-
else {
|
|
285
|
-
current = path.pop()
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
return maze
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
const { width, height, filename, mazesDir, smooth } = parseArgs()
|
|
293
|
-
const builder = new MazeBuilder(width, height, filename, mazesDir, smooth)
|
|
294
|
-
builder.build()
|