MAKE THE TORUS FUCKING WORK!! I swear to god I am NEVER messing with signedness...
[SmugglerRL.git] / src / map.d
blob1f40b0cc781819131b0b9823baab24bb5ee4bec8
1 import constants;
2 import colour;
3 import glyph;
4 import logging;
6 struct Tile {
7 Glyph glyph;
8 bool blocks_light, visible;
9 bool walkable;
10 RGBColour fgcolour, bgcolour;
11 private struct _attr { bool reverse, italic, bold, underline; }
12 _attr attrs;
14 void setdefglyph() {
15 if (walkable) {
16 glyph = Glyph.middot;
17 fgcolour = RGBColour(0x4c4c4c);
18 } else {
19 glyph = Glyph.dark_square;
20 fgcolour = RGBColour(0x663300);
22 bgcolour = RGBColour(0x000000);
26 // (n)ormalized
27 struct Vector2n {
28 private immutable maxx = map_x, maxy = map_y;
31 private struct Normalint(uint max) {
32 private int _i;
34 // No reason you would want to negate it, deref it, or invert it; unary + literally does nothing,
35 uint opUnary(string op)() if (op == "++" || op = "--") {
36 mixin(op ~ "_i");
37 return _i = normalized(_i, max);
39 uint opBinary(string op)(int other) {
40 int i = mixin("_i" ~ op ~ "other");
41 return normalized(i, max);
44 @property uint i() {
45 // we don't have to normalize i. Because assignment and inc/dec already normalize it
46 return _i;
48 @property int i(int newi) {
49 return _i = normalized(newi, max);
51 alias i this;
53 Normalint!maxx x;
54 Normalint!maxy y;
56 this(uint newy, uint newx) {
57 y.i = newy;
58 x.i = newx;
62 @property uint y() { return _y; }
63 @property uint y(int newy) { return _y = normalized(newy, maxy); }
65 @property uint x() { return _x; }
66 @property uint x(int newx) { return _x = normalized(newx, maxx); }
69 pragma(inline, true) uint normalized(int i, int max) {
70 i %= max;
71 if (i < 0) {
72 i += max;
75 return i;
76 // If this function is a perf problem, use the following to trigger a cmov (compiler should be smart enough to do it that way already though)
78 * int oth = i + max;
79 * i = (i < 0) ? i : oth;
83 class Map {
84 private Tile[][] tiles;
86 this(Tile[][] tiles = null) {
87 this.tiles = tiles ? tiles : new Tile[][](map_x + 2, map_y + 2);
90 Tile[][] get_tiles() {
91 return tiles;
94 // lambda of the form, e.g., (Tile x) => x.visible = false will return bool, not void
95 // so if we take a void function, all is lost. So take a function returning T
96 void for_all(T)(T delegate(ref Tile x) fun) {
97 foreach (ref row; tiles) {
98 foreach (ref tile; row) {
99 fun(tile);
104 //ref Tile opIndexAssign(Tile value, ulong y, ulong x) { return tiles[y][x] = value; }
105 ref Tile opIndex(uint y, uint x) {
106 return tiles[y % map_y][x % map_x];
108 ref Tile opIndex(Vector2n vec) {
109 return tiles[vec.y][vec.x];
111 ref Tile opIndex(int y, int x) {
112 return this[Vector2n(y, x)];
115 Map dup() {
116 Map ret = new Map();
117 ret.tiles = tiles.dup;
118 return ret;