diff options
Diffstat (limited to 'source/board.d')
-rw-r--r-- | source/board.d | 241 |
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; + } +} |