Rennovate mapgen internal api. Now you're more likely to encounter one of smuglerl...
[SmugglerRL.git] / src / util.d
blob350d33054a1a8dd255145fa0d225845414e5763b
1 public import std.random: uniform;
2 import std.exception: Exception;
3 import std.functional: memoize;
4 import std.string: format;
6 import colour;
7 import constants;
8 import game;
11 // provides dynamic function dispatch with objects, not classes
12 mixin template funcwrapper(alias func) {
13 import std.traits: ReturnType;
14 mixin(ReturnType!func.stringof ~ " "
15 ~ __traits(identifier, func)[1 .. $] // [1:$] to get rid of the leading _
16 ~ "(T...)(T args) {" // (Parameters!func).stringof
17 ~ (ReturnType!func.stringof == "void" ? "" : "return ")
18 ~ __traits(identifier, func) ~ "(this, args);"
19 ~ "}");
21 /*mixin template funcwrappers(funcs...) {
22 static foreach (func; funcs) {
23 mixin funcwrapper!func;
25 }*/
27 // example:
29 struct Bla {
30 int n;
32 void delegate(ref Bla self) _func;
34 mixin funcwrapper!_func;
35 void doshit() {
36 writeln(ReturnType!doshit.stringof);
40 void main() {
41 Bla bla;
42 bla.n = 15;
43 bla._func = (ref Bla self) {
44 writefln("I have %s", self.n);
46 bla.doshit();
48 bla.func();
53 public alias rnd = uniform;
55 class DException: Exception {
56 pragma(inline, true) pure this(T...)(T args) {
57 super(format(args));
61 class InternalError: DException {
62 pragma(inline, true) pure this(T...)(T args) {
63 super(args);
67 void exit(ubyte code) {
68 import core.runtime: Runtime;
69 static import core.stdc.stdlib;
70 Runtime.terminate();
71 core.stdc.stdlib.exit(code);
74 pure string fillstr(size_t length, char ch=' ') {
75 string buf;
76 while (length --> 0) {
77 buf ~= ch;
79 return buf;
83 // a/b chance of returning true
84 bool chances(uint a, uint b) {
85 //if (a > b) return chances(b, a);
86 // mod 100 -- 123% = 23%
87 // e.g., 8/5 = 3/5 + 5/5 = 3/5 + 100%. -100%. = 3/5
88 //if (a > b) return chances(a%b, b);
89 //if (a > b) throw new InternalError("HELP ME I DON'T KNOW HOW TO ADD SHIT
90 //if (a >= b) return true; // boring as it is, this is probably the sane choice
91 if (a > b) return *(cast(bool*)null); // actually fuck sanity let's SEGFAULT
93 return (a/b)*uint.max > uniform!uint();
98 // Taken directly from http://stackoverflow.com/a/41978310
99 /* It's supposed to be incredibly performant...but honestly I used it because
100 * I could copy-paste it easily.
102 alias get256colour = memoize!((RGBColour colour) {
103 enum ubyte[6] i2cv = [0, 0x5f, 0x87, 0xaf, 0xd7, 0xff];
104 pragma(inline, true) {
105 auto v2ci = (int v) => v < 48 ? 0 : v < 115 ? 1 : (v - 35) / 40;
106 auto colour_index = (int r, int g, int b) => 36*r + 6*g + b;
107 auto distance = (int r1, int g1, int b1, int r2, int g2, int b2) => (r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2);
110 int ir = v2ci(colour.r), ig = v2ci(colour.g), ib = v2ci(colour.b);
111 int average = (colour.r + colour.g + colour.b) / 3;
112 int igray = average > 238 ? 23 : (average-3) / 10;
113 int cr = i2cv[ir], cg = i2cv[ig], cb = i2cv[ib];
114 int gv = 8 + 10 * igray;
116 int colour_err = distance(cr, cg, cb, colour.r, colour.g, colour.b);
117 int gray_err = distance(gv, gv, gv, colour.r, colour.g, colour.b);
119 return cast(ubyte)(colour_err <= gray_err ? 16 + colour_index(ir, ig, ib) : 232 + igray);
123 // Overloads...
124 pragma(inline, true) ubyte get256colour(ubyte r, ubyte g, ubyte b) { return get256colour(RGBColour(r, g, b)); }
125 pragma(inline, true) ubyte get256colour(string colour) { return get256colour(RGBColour(colour)); }
128 auto newmap = (ushort height = map_y+2, ushort width = map_x+2) => new Tile[][](width, height);