From 9b80e6eef31b0c852c772ba6552e419856fe0aa9 Mon Sep 17 00:00:00 2001
From: Holden Rohrer
Date: Tue, 31 Aug 2021 18:36:27 -0400
Subject: finished in-world portal features
---
source/app.d | 132 +++++++++++++++++++++++++++--------------------
source/board.d | 111 ++++++++++++++--------------------------
source/lru.d | 63 ++++++++---------------
source/portals.d | 152 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
source/spots.d | 119 +++++++++++++++++++------------------------
5 files changed, 340 insertions(+), 237 deletions(-)
create mode 100644 source/portals.d
(limited to 'source')
diff --git a/source/app.d b/source/app.d
index 1d04fc9..7faaa75 100644
--- a/source/app.d
+++ b/source/app.d
@@ -2,12 +2,12 @@ import deimos.ncurses;
import std.string : toStringz;
import core.stdc.locale;
import std.format;
+import std.stdio;
import board;
import spots;
-import std.stdio;
+import portals;
-void main()
-{
+void main() {
setlocale(LC_CTYPE, ""); // ncurses locales are weird
auto stdscr = initscr();
@@ -20,19 +20,23 @@ void main()
scrollok(stdscr, true); // allows scrolling in up/down arrows
nonl(); // "return" goes through input
- auto overlay = new OverlaySource(new RandomSource());
- auto board = new Board(overlay);
+ auto source = new OverlaySource(new RandomSource());
+ auto portals = new Portals(source);
+ auto board = new Board(source);
auto disp = new BoardDisplay(board, stdscr);
disp.print();
int rocks = 0;
- disp.status = "0";
+ disp.status = "Press [space] to pick up and set down rocks";
refresh();
- outer: while (true)
- {
+ import std.bigint : BigInt;
+
+ BigInt[][int] portal;
+ int lastPortalId;
+
+ outer: while (true) {
auto c = getch();
- switch (c)
- {
+ switch (c) {
case ',':
case KEY_UP:
disp.up();
@@ -53,16 +57,13 @@ void main()
disp.getdims();
break;
case ' ':
- if (overlay[disp.y, disp.x].isRock())
- {
- overlay[disp.y, disp.x] = Spot(' ');
+ if (source[disp.y, disp.x].isRock()) {
+ source[disp.y, disp.x] = Spot(' ');
rocks++;
disp.status = format("%d", rocks);
disp.print();
- }
- else if (rocks > 0)
- {
- overlay[disp.y, disp.x] = Spot('*');
+ } else if (rocks > 0 && source[disp.y, disp.x].isSpace()) {
+ source[disp.y, disp.x] = Spot('*');
rocks--;
disp.status = format("%d", rocks);
disp.print();
@@ -72,38 +73,60 @@ void main()
break outer;
case 's':
auto filename = stdscr.readquery("Save:");
- try
- {
- auto file = File(filename, "wb");
- file.writefln!"%s %s"(disp.y, disp.x);
- file.writefln!"%d"(rocks);
- overlay.save(file);
- disp.print();
- }
- catch (Exception e)
- {
+ if (filename) {
+ try {
+ auto file = File(filename, "wb");
+ file.writefln!"%s %s"(disp.y, disp.x);
+ file.writefln!"%d"(rocks);
+ source.save(file);
+ portals.save(file);
+ } catch (Exception e) {
+ }
}
break;
case 'l':
auto filename = stdscr.readquery("Load:");
- try
- {
- import std.algorithm.iteration : splitter, map;
- import std.conv : to;
- import std.bigint;
+ if (filename) {
+ try {
+ import std.algorithm.iteration : splitter, map;
+ import std.conv : to;
- auto file = File(filename);
- auto coord = file.readln.splitter().map!(to!BigInt);
- disp.y = coord.front;
- coord.popFront;
- disp.x = coord.front;
- file.readf!"%d\n"(rocks);
- disp.status = format("%d", rocks);
- overlay.load(file);
+ auto file = File(filename);
+ auto coord = file.readln.splitter().map!(to!BigInt);
+ disp.y = coord.front;
+ coord.popFront;
+ disp.x = coord.front;
+ file.readf!"%d\n"(rocks);
+ disp.status = format("%d", rocks);
+ source.load(file);
+ portals.load(file);
+ } catch (Exception e) {
+ }
}
- catch (Exception e)
- {
- printw("exception!");
+ disp.print();
+ break;
+ case '/':
+ auto sp = source[disp.y, disp.x];
+ if (sp.isSpace) {
+ if (rocks >= 10) {
+ rocks -= 10;
+ portals.add(disp.y, disp.x);
+ }
+ } else if (sp.isPortal) {
+ rocks += 10;
+ portals.remove(disp.y, disp.x);
+ }
+ disp.status = format("%d", rocks);
+ disp.print();
+ break;
+ case 'g':
+ auto sp = source[disp.y, disp.x];
+ if (sp.isPortal) {
+ auto dest = portals.get(sp.id).pair;
+ if (dest != null) {
+ disp.y = dest.y;
+ disp.x = dest.x;
+ }
}
disp.print();
break;
@@ -113,8 +136,9 @@ void main()
}
}
-string readquery(WINDOW* stdscr, string query)
-{
+immutable char ESC = 27;
+
+string readquery(WINDOW* stdscr, string query) {
import std.range : replicate;
import std.conv : to;
import std.array : appender;
@@ -127,31 +151,29 @@ string readquery(WINDOW* stdscr, string query)
move(height, cast(int) query.length + 1);
scrollok(stdscr, false);
+ scope (success)
+ scrollok(stdscr, true);
auto build = appender!(char[]);
int p = cast(int) query.length + 1;
- while (auto ch = getch())
- {
+ while (auto ch = getch()) {
if (ch == '\r' || ch == EOF)
break;
- if (ch == '\b' || ch == KEY_BACKSPACE || ch == 127)
- {
- if (build[].length > 0)
- {
+ if (ch == '\b' || ch == KEY_BACKSPACE || ch == 127) {
+ if (build[].length > 0) {
p--;
mvaddch(height, p, ' ');
build.shrinkTo(build[].length - 1);
move(height, p);
}
- }
- else
- {
+ } else if (ch == ESC) {
+ return null;
+ } else {
build ~= cast(char) ch;
addch(ch);
p++;
}
}
- scrollok(stdscr, true);
return cast(string) build[];
}
diff --git a/source/board.d b/source/board.d
index 9ec996b..8460f71 100644
--- a/source/board.d
+++ b/source/board.d
@@ -8,84 +8,70 @@ import std.format;
import std.stdio;
import spots : Spot, SpotSource;
-public class Board
-{
+public class Board {
private SpotSource _source;
// uint seed;
// indexed as Spot = Board[y, x]
- this(SpotSource source)
- {
+ this(SpotSource source) {
_source = source;
}
- Spot opIndex(BigInt y, BigInt x)
- {
+ Spot opIndex(BigInt y, BigInt x) {
return _source[y, x];
}
- Spot opIndex(long y, long x)
- {
+ Spot opIndex(long y, long x) {
// possible per improvements
return opIndex(BigInt(y), BigInt(x));
}
- PartialBoard opIndex(BigInt[2] y, BigInt[2] x)
- {
+ PartialBoard opIndex(BigInt[2] y, BigInt[2] x) {
return new PartialBoard(y, x, _source);
}
- PartialBoard opIndex(long[2] y, long[2] x)
- {
+ 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)
- {
+ PartialBoard opIndex(BigInt[2] y, BigInt x) {
return opIndex(y, [x, x + 1]);
}
- PartialBoard opIndex(long[2] y, long x)
- {
+ PartialBoard opIndex(long[2] y, long x) {
return opIndex([BigInt(y[0]), BigInt(y[1])], BigInt(x));
}
- PartialBoard opIndex(BigInt y, BigInt[2] x)
- {
+ PartialBoard opIndex(BigInt y, BigInt[2] x) {
return opIndex([y, y + 1], x);
}
- PartialBoard opIndex(long y, long[2] 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)
- {
+ if (dimension >= 0 && dimension < 2) {
return [x, y];
}
long[2] opSlice(size_t dimension)(long x, long y)
- if (dimension >= 0 && dimension < 2)
- {
+ if (dimension >= 0 && dimension < 2) {
return [x, y];
}
// be more generic. instead of long use T where IsIntegral!T
}
-enum Edge
-{
+enum Edge {
LEFT,
RIGHT,
TOP,
BOT,
}
-class BoardDisplay
-{
+class BoardDisplay {
private Board _board;
private WINDOW* _window;
private int _height, _width;
@@ -93,39 +79,32 @@ class BoardDisplay
BigInt x = 0;
BigInt y = 0;
- this(Board board, WINDOW* window)
- {
+ this(Board board, WINDOW* window) {
_board = board;
_window = window;
getdims();
}
- public void getdims()
- {
+ public void getdims() {
getmaxyx(_window, _height, _width);
}
- private void center()
- {
+ 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()
- {
+ @property string status() {
return _status;
}
- @property status(string s)
- {
+ @property status(string s) {
_status = s;
center();
}
- private BigInt edge(Edge e)
- { // templating??
- switch (e)
- {
+ private BigInt edge(Edge e) { // templating??
+ switch (e) {
case Edge.LEFT:
return BigInt(cast(int) floor(-_width / 2.0)) + x;
case Edge.RIGHT:
@@ -139,8 +118,7 @@ class BoardDisplay
}
}
- void print()
- {
+ void print() {
import std.stdio;
import std.datetime;
@@ -149,8 +127,7 @@ class BoardDisplay
center();
}
- void up()
- { // the cursor moves up, the map scrolls down, leaving an empty line at top
+ 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),
@@ -158,8 +135,7 @@ class BoardDisplay
center();
}
- void down()
- {
+ void down() {
y++;
scrl(1);
mvprintw(_height - 1, 0, toStringz(_board[edge(Edge.BOT) - 1,
@@ -168,21 +144,18 @@ class BoardDisplay
center();
}
- void left()
- {
+ void left() {
x--;
print();
}
- void right()
- {
+ void right() {
x++;
print();
}
}
-unittest
-{
+unittest {
import std.stdio;
import std.datetime;
import lru : LRUCache;
@@ -191,47 +164,37 @@ unittest
SysTime starttime = Clock.currTime();
auto random = new RandomSource();
auto source = new OverlaySource(random);
- foreach (j; iota(100))
- {
- foreach (i; iota(400))
- {
+ 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))
- {
+ foreach (j; iota(100)) {
+ foreach (i; iota(400)) {
random[BigInt(i), BigInt(0)];
}
}
writeln(Clock.currTime() - starttime);
}
-class PartialBoard : Board
-{
+class PartialBoard : Board {
private BigInt[2] _yrange, _xrange;
- this(BigInt[2] y, BigInt[2] x, SpotSource source)
- {
+ this(BigInt[2] y, BigInt[2] x, SpotSource source) {
_yrange = y;
_xrange = x;
super(source);
}
- override Spot opIndex(BigInt y, BigInt x)
- {
+ override Spot opIndex(BigInt y, BigInt x) {
return _source[y + _yrange[0], x + _xrange[0]];
}
- override string toString()
- {
+ 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]))
- {
+ foreach (y; iota(_yrange[0], _yrange[1])) {
+ foreach (x; iota(_xrange[0], _xrange[1])) {
strBuilder.put(_source[y, x].contents);
}
strBuilder.put("\n");
diff --git a/source/lru.d b/source/lru.d
index 6d802df..2e8da73 100644
--- a/source/lru.d
+++ b/source/lru.d
@@ -1,22 +1,18 @@
import std.array : appender;
-private struct Node(T)
-{
+private struct Node(T) {
Node!T* prev;
Node!T* next;
T data;
}
-private struct List(T)
-{
+private struct List(T) {
Node!T* head;
Node!T* tail;
size_t length;
- invariant ()
- {
- if (length > 0)
- {
+ invariant () {
+ if (length > 0) {
assert(head !is null);
assert(tail !is null);
}
@@ -37,8 +33,7 @@ private struct List(T)
}
}*/
- void remove(Node!T* n)
- {
+ void remove(Node!T* n) {
if (n.next)
n.next.prev = n.prev;
if (n.prev)
@@ -50,8 +45,7 @@ private struct List(T)
length--;
}
- void push(Node!T* n)
- {
+ void push(Node!T* n) {
n.prev = null;
n.next = head;
head = n;
@@ -63,12 +57,10 @@ private struct List(T)
}
Node!T* pop()
- in
- {
+ in {
assert(tail);
}
- do
- {
+ do {
Node!T* node = tail;
remove(node);
return node;
@@ -76,8 +68,7 @@ private struct List(T)
}
-unittest
-{
+unittest {
List!int l;
Node!int first;
l.push(&first);
@@ -95,60 +86,49 @@ unittest
l.pop();
}
-class LRUCache(From, To)
-{
+class LRUCache(From, To) {
private size_t _cap;
- private struct Record
- {
+ private struct Record {
To val;
From key;
}
private Node!Record*[From] map;
private List!Record queue;
- this(size_t cap)
- {
+ this(size_t cap) {
_cap = cap;
}
- private void checksz()
- {
- if (queue.length > _cap)
- {
+ private void checksz() {
+ if (queue.length > _cap) {
auto node = queue.pop();
map.remove(node.data.key);
}
}
- bool opBinaryRight(string op : "in")(From key)
- {
+ bool opBinaryRight(string op : "in")(From key) {
return cast(bool)(key in map);
}
To opIndex(From f)
- in
- {
+ in {
assert(f in map);
}
- do
- {
+ do {
auto p = map[f];
queue.remove(p);
queue.push(p);
return p.data.val;
}
- void opIndexAssign(To t, From f)
- {
+ void opIndexAssign(To t, From f) {
auto p = f in map;
Node!Record* node;
bool alloc = p is null;
- if (!alloc)
- {
+ if (!alloc) {
queue.remove(*p);
node = *p;
- }
- else
+ } else
node = new Node!Record();
node.data.val = t;
node.data.key = f;
@@ -159,8 +139,7 @@ class LRUCache(From, To)
}
}
-unittest
-{
+unittest {
auto cache = new LRUCache!(int, int)(2);
cache[0] = 1;
cache[4] = 2;
diff --git a/source/portals.d b/source/portals.d
new file mode 100644
index 0000000..7bb5dc2
--- /dev/null
+++ b/source/portals.d
@@ -0,0 +1,152 @@
+import std.bigint : BigInt;
+import spots : OverlaySource, Spot;
+import std.stdio;
+import std.format;
+
+struct Portal {
+ BigInt y;
+ BigInt x;
+ Portal* pair;
+ this(BigInt y, BigInt x) {
+ this.y = y;
+ this.x = x;
+ }
+
+ void pairWith(ref Portal p) {
+ this.pair = &p;
+ p.pair = &this;
+ }
+
+ void buildMap(ref int[Portal* ] idMap, ref int highId) {
+ idMap[&this] = highId++;
+ }
+
+ string toString(int[Portal* ] idMap)
+ in {
+ assert(pair in idMap);
+ }
+ do {
+ return format!`%s, %s: %d`(y, x, idMap[pair]);
+ }
+
+ void fromString(string s, Portal[int] portalsById) {
+ import std.conv : to;
+ import std.algorithm : until, findSkip;
+ import std.array : array;
+
+ this.y = to!BigInt(s.until(',').array);
+ s.findSkip(", ");
+ this.x = to!BigInt(s.until(':').array);
+ s.findSkip(": ");
+ int id;
+ s.formattedRead!"%d"(id);
+ auto p = id in portalsById;
+ if (p) {
+ p.pairWith(this); // this is a REALLY big bug. Portal() is
+ // being copied by value into the dict,
+ // so it's not using its final ref.
+ }
+
+ }
+}
+
+class Portals {
+ private Portal[int] _portals;
+ private Portal* _lastPortal;
+ private int _nextId;
+ private OverlaySource _overlay;
+
+ this(OverlaySource overlay) {
+ _overlay = overlay;
+ }
+
+ int add(BigInt y, BigInt x) {
+ _portals[_nextId] = Portal(y, x);
+ if (_lastPortal && _lastPortal.pair == null) {
+ _lastPortal.pairWith(_portals[_nextId]);
+ }
+ _lastPortal = &(_portals[_nextId]);
+ _overlay[y, x] = Spot('/', _nextId);
+ return _nextId++;
+ }
+
+ Portal get(int id)
+ in {
+ assert(id in _portals);
+ }
+ do {
+ return _portals[id];
+ }
+
+ void remove(BigInt y, BigInt x) {
+ auto id = _overlay[y, x].id;
+ auto pair = _portals[id].pair;
+ if (pair) {
+ if (_lastPortal.pair == null) {
+ _lastPortal.pairWith(*pair);
+ } else {
+ pair.pair = null;
+ }
+ }
+ _lastPortal = _portals[id].pair;
+ _portals.remove(id);
+ _overlay[y, x] = Spot(' ');
+ }
+
+ immutable string terminator = "END PORTAL DATA\n";
+ void save(File f) {
+ int id = 0;
+ int[Portal* ] idMap;
+ foreach (ref key; _portals.byKey()) {
+ (key in _portals).buildMap(idMap, id);
+ }
+ foreach (ref key; _portals.byKey()) {
+ auto portalRef = key in _portals;
+ f.writefln!`%d @ %s`(idMap[portalRef], portalRef.toString(idMap));
+ }
+
+ f.write(terminator);
+ if (_lastPortal)
+ f.writefln!`%d`(idMap[_lastPortal]);
+ }
+
+ void load(File f) {
+ _nextId = 0;
+ foreach (char[] line; f.lines) {
+ if (line == terminator)
+ break;
+
+ int id;
+ string portalText;
+ line.formattedRead!`%d @ %s`(id, portalText);
+ _portals[id] = Portal();
+ _portals[id].fromString(portalText, _portals);
+ _nextId++;
+ }
+ int id;
+ if (_nextId > 0) {
+ f.readf("%d\n", id);
+ _lastPortal = &(_portals[id]);
+ }
+ }
+
+ unittest {
+ import spots : RandomSource;
+ import std.stdio;
+
+ auto overlay = new OverlaySource(new RandomSource());
+ auto portals = new Portals(overlay);
+
+ portals.add(BigInt(0), BigInt(0));
+ portals.remove(BigInt(0), BigInt(0));
+ int orig = portals.add(BigInt(0), BigInt(0));
+ int sec = portals.add(BigInt(0), BigInt(1));
+ assert(*(portals.get(orig).pair) == portals.get(sec));
+ portals.remove(BigInt(0), BigInt(1));
+ sec = portals.add(BigInt(0), BigInt(2));
+ assert(*(portals.get(orig).pair) == portals.get(sec));
+ orig = portals.add(BigInt(0), BigInt(3));
+ portals.remove(BigInt(0), BigInt(0));
+ assert(*(portals.get(orig).pair) == portals.get(sec));
+ }
+}
diff --git a/source/spots.d b/source/spots.d
index 49b9c85..a0f549e 100644
--- a/source/spots.d
+++ b/source/spots.d
@@ -6,94 +6,96 @@ import std.stdio;
import lru : LRUCache;
import std.traits : isSomeString;
-private BigInt positive(BigInt n)
-{
+private BigInt positive(BigInt n) {
if (n >= 0)
return n * 2;
else
return -n * 2 - 1;
}
-private BigInt pair(BigInt n, BigInt m)
-{
+private BigInt pair(BigInt n, BigInt m) {
// https://stackoverflow.com/a/919661
return (positive(n) + positive(m)) * (positive(n) + positive(m) + 1) / 2 + positive(m);
}
-struct Spot
-{
+struct Spot {
private char _contents;
- this(char c)
- {
+ private int _id;
+ this(char c) {
_contents = c;
}
+ this(char c, int id) {
+ this(c);
+ _id = id;
+ }
+
import std.format : format, formattedRead;
- string toString()
- {
+ string toString() {
- return format!`'%c'`(_contents);
+ return format!`'%c' %d`(_contents, _id);
}
- void fromString(Range)(auto ref Range s)
- {
- s.formattedRead!`'%c'`(_contents);
+ void fromString(Range)(auto ref Range s) {
+ s.formattedRead!`'%c' %d`(_contents, _id);
}
- @property contents()
- {
+ @property contents() {
return _contents;
}
- bool opEqual(const Spot s)
- {
+ @property id() {
+ return _id;
+ }
+
+ bool opEqual(const Spot s) {
return s._contents == _contents;
}
- bool isRock()
- {
+ bool isSpace() {
+ return _contents == ' ';
+ }
+
+ bool isRock() {
return _contents == '*';
}
+
+ bool isPortal() {
+ return _contents == '/';
+ }
}
-interface SpotSource
-{
+interface SpotSource {
Spot opIndex(BigInt y, BigInt x);
void save(File);
void load(File);
}
-class RandomSource : SpotSource
-{
+class RandomSource : SpotSource {
uint seed;
double density = .0025;
private LRUCache!(BigInt[2], Spot) cache;
- this()
- {
+ this() {
seed = unpredictableSeed;
cache = new LRUCache!(BigInt[2], Spot)(50000);
}
- this(uint seed)
- {
+ this(uint seed) {
this.seed = seed;
}
- this(uint seed, double density)
- {
+ this(uint seed, double density) {
this.density = density;
this(seed);
}
- private uint hash(BigInt n)
- {
+ private uint hash(BigInt n) {
CRC32 crc;
crc.start();
crc.put((cast(ubyte*)&seed)[0 .. seed.sizeof]);
- foreach (i; iota(n.ulongLength))
- {
+ foreach (i; iota(n.ulongLength)) {
auto digit = n.getDigit(i);
crc.put((cast(ubyte*)&digit)[0 .. digit.sizeof]);
}
@@ -102,8 +104,7 @@ class RandomSource : SpotSource
return hash;
}
- public Spot opIndex(BigInt y, BigInt x)
- {
+ public Spot opIndex(BigInt y, BigInt x) {
if ([y, x] in cache)
return cache[[y, x]];
auto roll = cast(double) hash(pair(y, x)) / uint.max;
@@ -116,44 +117,35 @@ class RandomSource : SpotSource
return ret;
}
- public void save(File f)
- {
+ public void save(File f) {
f.writefln!"%d %f"(seed, density);
}
- public void load(File f)
- {
+ public void load(File f) {
f.readf!"%d %f\n"(seed, density);
cache = new LRUCache!(BigInt[2], Spot)(50000);
}
}
-class OverlaySource : SpotSource
-{
+class OverlaySource : SpotSource {
private SpotSource _base;
private Spot[BigInt[2]] _overlay;
immutable private string terminator = "END OVERLAY\n";
- this(SpotSource base)
- {
+ this(SpotSource base) {
_base = base;
}
- void opIndexAssign(Spot spot, BigInt y, BigInt x)
- {
+ void opIndexAssign(Spot spot, BigInt y, BigInt x) {
Spot* p = [y, x] in _overlay;
- if (p !is null && spot == _base[y, x])
- {
+ if (p !is null && spot == _base[y, x]) {
_overlay.remove([y, x]);
- }
- else
- {
+ } else {
_overlay[[y, x]] = spot;
}
}
- Spot opIndex(BigInt y, BigInt x)
- {
+ Spot opIndex(BigInt y, BigInt x) {
Spot* p = [y, x] in _overlay;
if (p !is null)
return *p;
@@ -161,25 +153,21 @@ class OverlaySource : SpotSource
return _base[y, x];
}
- void save(File f)
- {
+ void save(File f) {
_base.save(f);
- foreach (coord; _overlay.keys())
- {
+ foreach (coord; _overlay.keys()) {
f.writefln!"%s %s: %s"(coord[0], coord[1], _overlay[coord]);
}
f.write(terminator);
}
- void load(File f)
- {
+ void load(File f) {
import std.conv : to;
import std.algorithm;
//_overlay = _overlay.init;
_base.load(f);
- foreach (char[] line; f.lines)
- {
+ foreach (char[] line; f.lines) {
if (line == terminator)
break;
@@ -189,14 +177,13 @@ class OverlaySource : SpotSource
ints.popFront;
coord[1] = ints.front;
- auto s = new Spot();
- (*s).fromString(line.find(':').find('\''));
- _overlay[coord] = *s;
+ auto s = Spot();
+ s.fromString(line.find(':').find('\''));
+ _overlay[coord] = s;
}
}
- unittest
- {
+ unittest {
auto base = new RandomSource(0, 0.0);
auto src = new OverlaySource(base);
src[BigInt(0), BigInt(0)] = Spot('*');
--
cgit