]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/lib/bits.qh
Merge branch 'master' into martin-t/dmgtext
[xonotic/xonotic-data.pk3dir.git] / qcsrc / lib / bits.qh
index 33d719a0792e93fb90e2de1828fdb64b9cb46847..c158ea032d497cb29a8709c2e02ad4fa8e2bd610 100644 (file)
@@ -1,5 +1,6 @@
-#ifndef BITS_H
-#define BITS_H
+#pragma once
+
+#include "log.qh"
 
 #define BIT(n) (1 << (n))
 #define BITS(n) (BIT(n) - 1)
@@ -9,6 +10,7 @@
        #define BITSET(var, mask, flag) ((var) ^ (-(flag) ^ (var)) & (mask))
 #endif
 
+ERASEABLE
 int lowestbit(int f)
 {
        f &= ~(f << 1);
@@ -19,4 +21,110 @@ int lowestbit(int f)
        return f;
 }
 
-#endif
+ERASEABLE
+int randombit(int bits)
+{
+       if (!(bits & (bits - 1)))  // this ONLY holds for powers of two!
+               return bits;
+
+       int r = random();
+       int b = 0;
+       int n = 0;
+
+       for (int f = 1; f <= bits; f *= 2)
+       {
+               if (bits & f)
+               {
+                       ++n;
+                       r *= n;
+                       if (r <= 1) b = f;
+                       else r = (r - 1) / (n - 1);
+               }
+       }
+       return b;
+}
+
+ERASEABLE
+int randombits(int bits, int k, bool error_return)
+{
+       int r = 0;
+       while (k > 0 && bits != r)
+       {
+               r += randombit(bits - r);
+               --k;
+       }
+       if (error_return)
+               if (k > 0) return -1;
+       // all
+       return r;
+}
+
+/*
+void randombit_test(int bits, int iter)
+{
+       while (iter > 0)
+       {
+               LOG_INFO(ftos(randombit(bits)), "\n");
+               --iter;
+       }
+}
+*/
+
+enum {
+       OP_SET,
+       OP_MIN,
+       OP_MAX,
+       OP_PLUS,
+       OP_MINUS
+};
+
+ERASEABLE
+bool GiveBit(entity e, .int fld, int bit, int op, int val)
+{
+       int v0 = (e.(fld) & bit);
+       switch (op)
+       {
+               case OP_SET:
+                       if (val > 0) e.(fld) |= bit;
+                       else e.(fld) &= ~bit;
+                       break;
+               case OP_MIN:
+               case OP_PLUS:
+                       if (val > 0) e.(fld) |= bit;
+                       break;
+               case OP_MAX:
+                       if (val <= 0) e.(fld) &= ~bit;
+                       break;
+               case OP_MINUS:
+                       if (val > 0) e.(fld) &= ~bit;
+                       break;
+       }
+       int v1 = (e.(fld) & bit);
+       return v0 != v1;
+}
+
+ERASEABLE
+bool GiveValue(entity e, .int fld, int op, int val)
+{
+       int v0 = e.(fld);
+       switch (op)
+       {
+               case OP_SET:
+                       e.(fld) = val;
+                       break;
+               case OP_MIN:
+                       e.(fld) = max(e.(fld), val);  // min 100 cells = at least 100 cells
+                       break;
+               case OP_MAX:
+                       e.(fld) = min(e.(fld), val);
+                       break;
+               case OP_PLUS:
+                       e.(fld) += val;
+                       break;
+               case OP_MINUS:
+                       e.(fld) -= val;
+                       break;
+       }
+       int v1 = e.(fld);
+       return v0 != v1;
+}