aboutsummaryrefslogtreecommitdiff
path: root/source/board.d
diff options
context:
space:
mode:
authorHolden Rohrer <hr@hrhr.dev>2021-08-03 00:40:58 -0400
committerHolden Rohrer <hr@hrhr.dev>2021-08-03 00:40:58 -0400
commit5f974d83677fc6d7ee229e6a2e2720a45677e4e0 (patch)
tree6c18ef8169ee4986bee3d7b2dc6f59582d7946da /source/board.d
created drocks
Diffstat (limited to 'source/board.d')
-rw-r--r--source/board.d241
1 files changed, 241 insertions, 0 deletions
diff --git a/source/board.d b/source/board.d
new file mode 100644
index 0000000..9ec996b
--- /dev/null
+++ b/source/board.d
@@ -0,0 +1,241 @@
+import std.bigint;
+import deimos.ncurses;
+import std.string : toStringz;
+import std.math : floor, ceil;
+import std.array : appender;
+import std.range;
+import std.format;
+import std.stdio;
+import spots : Spot, SpotSource;
+
+public class Board
+{
+ private SpotSource _source;
+ // uint seed;
+ // indexed as Spot = Board[y, x]
+
+ this(SpotSource source)
+ {
+ _source = source;
+ }
+
+ Spot opIndex(BigInt y, BigInt x)
+ {
+ return _source[y, x];
+ }
+
+ Spot opIndex(long y, long x)
+ {
+ // possible per improvements
+ return opIndex(BigInt(y), BigInt(x));
+ }
+
+ PartialBoard opIndex(BigInt[2] y, BigInt[2] x)
+ {
+ return new PartialBoard(y, x, _source);
+ }
+
+ PartialBoard opIndex(long[2] y, long[2] x)
+ {
+ return opIndex([BigInt(y[0]), BigInt(y[1])], [
+ BigInt(x[0]), BigInt(x[1])
+ ]);
+ }
+
+ PartialBoard opIndex(BigInt[2] y, BigInt x)
+ {
+ return opIndex(y, [x, x + 1]);
+ }
+
+ PartialBoard opIndex(long[2] y, long x)
+ {
+ return opIndex([BigInt(y[0]), BigInt(y[1])], BigInt(x));
+ }
+
+ PartialBoard opIndex(BigInt y, BigInt[2] x)
+ {
+ return opIndex([y, y + 1], x);
+ }
+
+ PartialBoard opIndex(long y, long[2] x)
+ {
+ return opIndex(BigInt(y), [BigInt(x[0]), BigInt(x[1])]);
+ }
+
+ BigInt[2] opSlice(size_t dimension)(BigInt x, BigInt y)
+ if (dimension >= 0 && dimension < 2)
+ {
+ return [x, y];
+ }
+
+ long[2] opSlice(size_t dimension)(long x, long y)
+ if (dimension >= 0 && dimension < 2)
+ {
+ return [x, y];
+ }
+ // be more generic. instead of long use T where IsIntegral!T
+}
+
+enum Edge
+{
+ LEFT,
+ RIGHT,
+ TOP,
+ BOT,
+}
+
+class BoardDisplay
+{
+ private Board _board;
+ private WINDOW* _window;
+ private int _height, _width;
+ private string _status;
+ BigInt x = 0;
+ BigInt y = 0;
+
+ this(Board board, WINDOW* window)
+ {
+ _board = board;
+ _window = window;
+ getdims();
+ }
+
+ public void getdims()
+ {
+ getmaxyx(_window, _height, _width);
+ }
+
+ private void center()
+ {
+ mvprintw(_height, 0, toStringz(_status ~ " ".replicate(_width - status.length)));
+ move(cast(int) ceil(_height / 2.0), cast(int) ceil(_width / 2.0));
+ }
+
+ @property string status()
+ {
+ return _status;
+ }
+
+ @property status(string s)
+ {
+ _status = s;
+ center();
+ }
+
+ private BigInt edge(Edge e)
+ { // templating??
+ switch (e)
+ {
+ case Edge.LEFT:
+ return BigInt(cast(int) floor(-_width / 2.0)) + x;
+ case Edge.RIGHT:
+ return BigInt(cast(int) floor(_width / 2.0)) + x;
+ case Edge.TOP:
+ return BigInt(cast(int) floor(-_height / 2.0)) + y;
+ case Edge.BOT:
+ return BigInt(cast(int) floor(_height / 2.0)) + y;
+ default:
+ assert(0);
+ }
+ }
+
+ void print()
+ {
+ import std.stdio;
+ import std.datetime;
+
+ mvprintw(0, 0, toStringz(_board[edge(Edge.TOP) .. edge(Edge.BOT),
+ edge(Edge.LEFT) .. edge(Edge.RIGHT)].toString()));
+ center();
+ }
+
+ void up()
+ { // the cursor moves up, the map scrolls down, leaving an empty line at top
+ y--;
+ scrl(-1);
+ mvprintw(0, 0, toStringz(_board[edge(Edge.TOP),
+ edge(Edge.LEFT) .. edge(Edge.RIGHT)].toString()));
+ center();
+ }
+
+ void down()
+ {
+ y++;
+ scrl(1);
+ mvprintw(_height - 1, 0, toStringz(_board[edge(Edge.BOT) - 1,
+ // necessary because opSlice is exclusive
+ edge(Edge.LEFT) .. edge(Edge.RIGHT)].toString()));
+ center();
+ }
+
+ void left()
+ {
+ x--;
+ print();
+ }
+
+ void right()
+ {
+ x++;
+ print();
+ }
+}
+
+unittest
+{
+ import std.stdio;
+ import std.datetime;
+ import lru : LRUCache;
+ import spots : RandomSource, OverlaySource;
+
+ SysTime starttime = Clock.currTime();
+ auto random = new RandomSource();
+ auto source = new OverlaySource(random);
+ foreach (j; iota(100))
+ {
+ foreach (i; iota(400))
+ {
+ source[BigInt(i), BigInt(0)];
+ }
+ }
+ writeln(Clock.currTime() - starttime);
+ foreach (j; iota(100))
+ {
+ foreach (i; iota(400))
+ {
+ random[BigInt(i), BigInt(0)];
+ }
+ }
+ writeln(Clock.currTime() - starttime);
+}
+
+class PartialBoard : Board
+{
+ private BigInt[2] _yrange, _xrange;
+ this(BigInt[2] y, BigInt[2] x, SpotSource source)
+ {
+ _yrange = y;
+ _xrange = x;
+ super(source);
+ }
+
+ override Spot opIndex(BigInt y, BigInt x)
+ {
+ return _source[y + _yrange[0], x + _xrange[0]];
+ }
+
+ override string toString()
+ {
+ auto strBuilder = appender!string;
+ strBuilder.reserve(cast(ulong)((_yrange[1] - _yrange[0] + 2) * (_xrange[1] - _xrange[0] + 1)));
+ foreach (y; iota(_yrange[0], _yrange[1]))
+ {
+ foreach (x; iota(_xrange[0], _xrange[1]))
+ {
+ strBuilder.put(_source[y, x].contents);
+ }
+ strBuilder.put("\n");
+ }
+ return strBuilder.data;
+ }
+}