1 private import std
.algorithm
: canFind
;
8 import BearLibTerminal
;
13 abstract class Being
{
17 int xp
, hp
= 30, maxhp
, mp
, maxmp
;
19 RGBColour fgcolour
, bgcolour
;
22 private struct _attr
{ bool reverse
, italic
, bold
, underline
; }
25 pragma(inline
, true) {
26 pure void inchp(int amount
=1) {
27 if ((amount
+ hp
) > maxhp
) {
36 pure bool isfemale() {
45 override Action
getaction() {
46 import std
.random
: uniform
;
47 return uniform(Action
.MoveNorth
, Action
.MoveSouthRight
);
50 fgcolour
= RGBColour(0xff00ff);
51 bgcolour
= RGBColour(0x00ff00);
58 Graphicshandler graphics
;
59 this(Graphicshandler g
) {
60 fgcolour
= RGBColour(0xffffff);
61 fgcolour
= RGBColour(0x000000);
64 this.glyph
= Glyph
.at
;
66 override Action
getaction() {
67 import std
.container
: RedBlackTree
; // Like a python set; i.e. faster lookups but unordered
68 immutable RedBlackTree
!int vikeys
= new RedBlackTree
!int('h', 'j', 'k', 'l', 'y', 'u', 'b', 'n', 'q', '.');
73 while (!((c
= graphics
.getch()) in vikeys
)) {}
77 tmp
= Action
.MoveLeft
;
80 tmp
= Action
.MoveRight
;
83 tmp
= Action
.MoveSouth
;
86 tmp
= Action
.MoveNorth
;
89 tmp
= Action
.MoveNorthLeft
;
92 tmp
= Action
.MoveNorthRight
;
95 tmp
= Action
.MoveSouthLeft
;
98 tmp
= Action
.MoveSouthRight
;
115 int x
, y
, dijkstra
= 1000;
116 bool walkable
, visible
= false;
117 RGBColour fgcolour
, bgcolour
;
118 private struct _attr
{ bool reverse
, italic
, bold
, underline
; }
123 glyph
= Glyph
.middot
;
125 import std
.random
: uniform
;
127 fgcolour
= RGBColour(0x663300);
128 bgcolour
= RGBColour(0x000000);
134 Tile
[][] mkdijkstra(Tile
[][] map
) {
135 auto newmap
= map
.dup
;
136 foreach (line
; map
) {
137 foreach (tile
; line
) {
139 newmap
[tile
.y
][tile
.x
] = dijkstrapass(tile
, newmap
);
145 return mkdijkstra(newmap
);
151 Tile
dijkstrapass(Tile t
, ref Tile
[][] map
) {
152 import std
.algorithm
.sorting
: sort
;
153 Tile
[] neighbors
= [map
[t
.y
-1][t
.x
], map
[t
.y
][t
.x
-1], map
[t
.y
+1][t
.x
], map
[t
.y
][t
.x
+1]];
155 neighbors
.sort
!((a
, b
) => a
.dijkstra
< b
.dijkstra
);
157 // The 0th one is the smallest one
158 if (t
.dijkstra
>= 2+neighbors
[0].dijkstra
) {
159 t
.dijkstra
= neighbors
[0].dijkstra
+1;
162 assert (neighbors
[0].dijkstra
<= neighbors
[1].dijkstra
);
172 Graphicshandler graphics
;
174 // it's weird, because although it's declared as [x][y], you assign to it with [y][x]
176 // I mean, it makes sense, but it's weird
178 this(string
[] args
) {
179 import std
.stdio
: write
, writeln
, stdout
;
180 graphics
= new BLThandler(this);
182 write("Allocating map..."); stdout
.flush();
183 // workaround because d doesn't want us to have static arrays larger than
185 this.map
.length
= map_y
+2;
187 foreach (ref row
; map
) {
188 row
.length
= map_x
+2;
192 write("Generating map..."); stdout
.flush();
193 this.genmap(MapType
.caves
);
196 write("Allocating monsters..."); stdout
.flush();
197 u
= new You(graphics
);
199 foreach (_
; 1..1000) {
204 write("Performing operations on map..."); stdout
.flush();
206 foreach (int tmpy
; 0..map_y
+1) {
207 foreach (int tmpx
; 0..map_x
+1) {
208 map
[tmpy
][tmpx
].y
= tmpy
+1;
209 map
[tmpy
][tmpx
].x
= tmpx
+1;
211 // map[tmpy][tmpx].walkable = true;
213 if (map
[tmpy
][tmpx
].walkable
) {
214 map
[tmpy
][tmpx
].fgcolour
= RGBColour(0x4c4c4c);
216 map
[tmpy
][tmpx
].fgcolour
= RGBColour(0xeeeeee);
218 map
[tmpy
][tmpx
].bgcolour
= RGBColour(0x000000);
220 if ((tmpy
== 0) ||
(tmpx
== 0) ||
(tmpy
== map_y
+2) ||
(tmpx
== map_x
+2))
221 map
[tmpy
][tmpx
].walkable
= false;
222 map
[tmpy
][tmpx
].setdefglyph();
228 write("Placing monsters..."); stdout
.flush();
229 // If we didn't have this, then if (0, 0) was walkable, then you would automatically get placed there
230 foreach (ref m
; mons
) {
232 m
.x
= rnd(1, map_x
+1);
233 m
.y
= rnd(1, map_y
+1);
234 } while ((!map
[m
.y
][m
.x
].walkable
) ||
!mon_at(m
.y
, m
.x
));
239 map
[u
.y
][u
.x
].dijkstra
= 0;
243 write("Generating dijkstra map...");
244 //map = mkdijkstra(map);
250 void parseargs(string
[] args
) {
251 if (args
.length
== 2) {
252 if (args
[1] == "dumpmap") {
259 uint mon_at_index(uint y
, uint x
) {
260 foreach (uint index
; 0..cast(uint)mons
.length
-1) {
261 if ((mons
[index
].y
== y
) && (mons
[index
].x
== x
)) {
268 // Name credit to lrogue
269 ref Being
mon_at(uint y
, uint x
) {
270 foreach (ref tmpmon
; mons
) {
271 if ((tmpmon
.y
== y
) && (tmpmon
.x
== x
)) {
275 // Evil hackery so we can return null
276 static Being tmp
= null;
278 // return *(cast(Being*)null);
286 foreach (tile
; row
) {
287 write(cast(string
)tile
.glyph
);
296 pragma(inline
, true) void refresh() {
299 pragma(inline
, true) void pline(T
...)(string s
, T args
) {
300 graphics
.pline(s
, args
);
309 void handlemove(int yshift
, int xshift
, ref Being b
) {
310 if (map
[b
.y
+yshift
][b
.x
+xshift
].walkable
&& !mon_at(b
.y
+yshift
, b
.x
+xshift
)) {
311 map
[b
.y
][b
.x
].setdefglyph();
314 // pline("another message, of exceeding length. You should eat it, if you feel like, but make sure it's still long enough. Ugh, it has to be *LONGER*?? FINE>>>");
316 // only when *you* walk into a wall
317 if (cast(You
)b
) pline("there is a thingy there!");
320 outerloop
: while (true) { refresh(); foreach (ref Being mon
; mons
) {
321 act
= mon
.getaction();
322 // If we're moving, then move!
323 if ((Action
.MoveNorth
<= act
) && (act
<= Action
.MoveSouthRight
)) {
329 case Action
.MoveNorth
:
332 case Action
.MoveSouth
:
336 case Action
.MoveLeft
:
339 case Action
.MoveRight
:
342 case Action
.MoveNorthLeft
:
343 deltay
= deltax
= -1;
345 case Action
.MoveNorthRight
:
349 case Action
.MoveSouthLeft
:
353 case Action
.MoveSouthRight
:
365 handlemove(deltay
, deltax
, mon
);
367 if (cast(You
)mon
) { refresh(); do_fov(this.map
, u
.x
, u
.y
, 100); }