@schedule1-tools/mixer 0.2.4 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -24
- package/dist/core/effectSet.d.ts +13 -3
- package/dist/core/effectSet.d.ts.map +1 -1
- package/dist/core/effectSet.js +105 -22
- package/dist/core/mixer.d.ts +8 -0
- package/dist/core/mixer.d.ts.map +1 -1
- package/dist/core/mixer.js +88 -103
- package/dist/data/effects.js +3 -7
- package/dist/data/products.d.ts.map +1 -1
- package/dist/data/products.js +15 -6
- package/dist/data/rules.js +1 -5
- package/dist/data/substances.js +4 -8
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -20
- package/dist/types.d.ts +3 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -3
- package/dist/utils/encoding.d.ts +12 -0
- package/dist/utils/encoding.d.ts.map +1 -1
- package/dist/utils/encoding.js +29 -26
- package/package.json +50 -41
- package/dist/bitmaps.d.ts +0 -9
- package/dist/bitmaps.d.ts.map +0 -1
- package/dist/bitmaps.js +0 -45
- package/dist/bitmaps.js.map +0 -1
- package/dist/core/effectSet.js.map +0 -1
- package/dist/core/mixer.js.map +0 -1
- package/dist/core/reverse.d.ts +0 -3
- package/dist/core/reverse.d.ts.map +0 -1
- package/dist/core/reverse.js +0 -89
- package/dist/core/reverse.js.map +0 -1
- package/dist/data/effects.js.map +0 -1
- package/dist/data/products.js.map +0 -1
- package/dist/data/rules.js.map +0 -1
- package/dist/data/substances.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/maskRules.d.ts +0 -8
- package/dist/maskRules.d.ts.map +0 -1
- package/dist/maskRules.js +0 -18
- package/dist/maskRules.js.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils/encoding.js.map +0 -1
package/README.md
CHANGED
|
@@ -34,10 +34,7 @@ import { mixSubstances } from '@schedule1-tools/mixer';
|
|
|
34
34
|
* mixSubstances(product: Product, substances: Substance[])
|
|
35
35
|
* → computes cost, effects, profit, profitMargin, addiction
|
|
36
36
|
*/
|
|
37
|
-
const result = mixSubstances(
|
|
38
|
-
'OG Kush',
|
|
39
|
-
['Cuke', 'Flu Medicine', 'Gasoline']
|
|
40
|
-
);
|
|
37
|
+
const result = mixSubstances('OG Kush', ['Cuke', 'Flu Medicine', 'Gasoline']);
|
|
41
38
|
// result → {
|
|
42
39
|
// effects: ['Be','Se','Eu','To'],
|
|
43
40
|
// cost: 12,
|
|
@@ -71,18 +68,15 @@ const result = mixFromHash('T0cgS3VzaDpBQkM');
|
|
|
71
68
|
### 3. Encode & decode mix state
|
|
72
69
|
|
|
73
70
|
```typescript
|
|
74
|
-
import {
|
|
75
|
-
encodeMixState,
|
|
76
|
-
decodeMixState
|
|
77
|
-
} from '@schedule1-tools/mixer';
|
|
71
|
+
import { decodeMixState, encodeMixState } from '@schedule1-tools/mixer';
|
|
78
72
|
|
|
79
73
|
/**
|
|
80
74
|
* encodeMixState(state: MixState) → string
|
|
81
75
|
* decodeMixState(hash: string) → MixState
|
|
82
76
|
*/
|
|
83
77
|
const encoded = encodeMixState({
|
|
84
|
-
product:
|
|
85
|
-
substances: ['Cuke','Flu Medicine','Gasoline']
|
|
78
|
+
product: 'OG Kush',
|
|
79
|
+
substances: ['Cuke', 'Flu Medicine', 'Gasoline'],
|
|
86
80
|
});
|
|
87
81
|
// encoded → 'T0cgS3VzaDpBQkM'
|
|
88
82
|
|
|
@@ -109,28 +103,23 @@ const newHash = await migrateMixHash('OLD_BASE64_HASH_HERE');
|
|
|
109
103
|
|
|
110
104
|
In addition to the functions above, the package also exports data objects:
|
|
111
105
|
|
|
112
|
-
- `effects`: All effect definitions
|
|
113
|
-
- `products`: All product definitions
|
|
114
|
-
- `substances`: All substance definitions
|
|
115
|
-
- `effectRulesBySubstance`: Transformation rules for each substance
|
|
106
|
+
- `effects`: All effect definitions
|
|
107
|
+
- `products`: All product definitions
|
|
108
|
+
- `substances`: All substance definitions
|
|
109
|
+
- `effectRulesBySubstance`: Transformation rules for each substance
|
|
116
110
|
|
|
117
111
|
```typescript
|
|
118
|
-
import {
|
|
119
|
-
effects,
|
|
120
|
-
products,
|
|
121
|
-
substances,
|
|
122
|
-
effectRulesBySubstance
|
|
123
|
-
} from '@schedule1-tools/mixer';
|
|
112
|
+
import { effectRulesBySubstance, effects, products, substances } from '@schedule1-tools/mixer';
|
|
124
113
|
```
|
|
125
114
|
|
|
126
115
|
---
|
|
127
116
|
|
|
128
117
|
## Contributing
|
|
129
118
|
|
|
130
|
-
1. Fork the repo
|
|
131
|
-
2. Create a branch (`git checkout -b feat/my-feature`)
|
|
132
|
-
3. Run tests & lint (`pnpm test && pnpm run format`)
|
|
133
|
-
4. Open a PR against `main`
|
|
119
|
+
1. Fork the repo
|
|
120
|
+
2. Create a branch (`git checkout -b feat/my-feature`)
|
|
121
|
+
3. Run tests & lint (`pnpm test && pnpm run format`)
|
|
122
|
+
4. Open a PR against `main`
|
|
134
123
|
|
|
135
124
|
Please read [CONTRIBUTING.md](CONTRIBUTING.md) (if present) for more details.
|
|
136
125
|
|
package/dist/core/effectSet.d.ts
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import type { EffectCode } from '../types';
|
|
2
|
+
export declare const EFFECT_INDEX: Record<EffectCode, number>;
|
|
2
3
|
export declare class EffectSet {
|
|
3
|
-
|
|
4
|
+
/** bitmask for effects 0-31 */
|
|
5
|
+
lo: number;
|
|
6
|
+
/** bitmask for effects 32-33 (Tt, Zo) */
|
|
7
|
+
hi: number;
|
|
8
|
+
private _size;
|
|
9
|
+
/** effect indices in insertion order, used by toArray() */
|
|
10
|
+
private _order;
|
|
4
11
|
constructor(initialEffects?: EffectCode[]);
|
|
12
|
+
has(effect: EffectCode): boolean;
|
|
13
|
+
hasBit(idx: number): boolean;
|
|
5
14
|
add(effect: EffectCode): boolean;
|
|
15
|
+
addBit(idx: number): boolean;
|
|
6
16
|
remove(effect: EffectCode): boolean;
|
|
7
|
-
|
|
8
|
-
toArray(): EffectCode[];
|
|
17
|
+
removeBit(idx: number): boolean;
|
|
9
18
|
size(): number;
|
|
19
|
+
toArray(): EffectCode[];
|
|
10
20
|
clone(): EffectSet;
|
|
11
21
|
}
|
|
12
22
|
//# sourceMappingURL=effectSet.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"effectSet.d.ts","sourceRoot":"","sources":["../../src/core/effectSet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"effectSet.d.ts","sourceRoot":"","sources":["../../src/core/effectSet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAyC3C,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAuB,CAAC;AAK5E,qBAAa,SAAS;IACpB,+BAA+B;IAC/B,EAAE,SAAK;IACP,yCAAyC;IACzC,EAAE,SAAK;IACP,OAAO,CAAC,KAAK,CAAK;IAClB,2DAA2D;IAC3D,OAAO,CAAC,MAAM,CAAgB;gBAElB,cAAc,GAAE,UAAU,EAAO;IAI7C,GAAG,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO;IAIhC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI5B,GAAG,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO;IAIhC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAe5B,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO;IAInC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAgB/B,IAAI,IAAI,MAAM;IAId,OAAO,IAAI,UAAU,EAAE;IAIvB,KAAK,IAAI,SAAS;CAQnB"}
|
package/dist/core/effectSet.js
CHANGED
|
@@ -1,34 +1,117 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
// All 34 effect codes in alphabetical order.
|
|
2
|
+
// Effects 0-31 map to `lo`, effects 32-33 (Tt, Zo) map to `hi`.
|
|
3
|
+
const EFFECT_CODES = [
|
|
4
|
+
'Ag',
|
|
5
|
+
'At',
|
|
6
|
+
'Ba',
|
|
7
|
+
'Be',
|
|
8
|
+
'Ca',
|
|
9
|
+
'Cd',
|
|
10
|
+
'Cy',
|
|
11
|
+
'Di',
|
|
12
|
+
'El',
|
|
13
|
+
'En',
|
|
14
|
+
'Eu',
|
|
15
|
+
'Ex',
|
|
16
|
+
'Fc',
|
|
17
|
+
'Fo',
|
|
18
|
+
'Gi',
|
|
19
|
+
'Gl',
|
|
20
|
+
'Je',
|
|
21
|
+
'La',
|
|
22
|
+
'Lf',
|
|
23
|
+
'Mu',
|
|
24
|
+
'Pa',
|
|
25
|
+
'Re',
|
|
26
|
+
'Sc',
|
|
27
|
+
'Se',
|
|
28
|
+
'Sh',
|
|
29
|
+
'Si',
|
|
30
|
+
'Sl',
|
|
31
|
+
'Sm',
|
|
32
|
+
'Sn',
|
|
33
|
+
'Sp',
|
|
34
|
+
'To',
|
|
35
|
+
'Tp',
|
|
36
|
+
'Tt',
|
|
37
|
+
'Zo',
|
|
38
|
+
];
|
|
39
|
+
export const EFFECT_INDEX = Object.create(null);
|
|
40
|
+
for (let i = 0; i < EFFECT_CODES.length; i++) {
|
|
41
|
+
EFFECT_INDEX[EFFECT_CODES[i]] = i;
|
|
42
|
+
}
|
|
43
|
+
export class EffectSet {
|
|
5
44
|
constructor(initialEffects = []) {
|
|
6
|
-
|
|
45
|
+
/** bitmask for effects 0-31 */
|
|
46
|
+
this.lo = 0;
|
|
47
|
+
/** bitmask for effects 32-33 (Tt, Zo) */
|
|
48
|
+
this.hi = 0;
|
|
49
|
+
this._size = 0;
|
|
50
|
+
/** effect indices in insertion order, used by toArray() */
|
|
51
|
+
this._order = [];
|
|
52
|
+
for (const e of initialEffects)
|
|
53
|
+
this.add(e);
|
|
54
|
+
}
|
|
55
|
+
has(effect) {
|
|
56
|
+
return this.hasBit(EFFECT_INDEX[effect]);
|
|
57
|
+
}
|
|
58
|
+
hasBit(idx) {
|
|
59
|
+
return idx < 32 ? (this.lo & (1 << idx)) !== 0 : (this.hi & (1 << (idx - 32))) !== 0;
|
|
7
60
|
}
|
|
8
61
|
add(effect) {
|
|
9
|
-
|
|
10
|
-
this.effects.add(effect);
|
|
11
|
-
return !alreadyExists;
|
|
62
|
+
return this.addBit(EFFECT_INDEX[effect]);
|
|
12
63
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
64
|
+
addBit(idx) {
|
|
65
|
+
if (idx < 32) {
|
|
66
|
+
const bit = 1 << idx;
|
|
67
|
+
if (this.lo & bit)
|
|
68
|
+
return false;
|
|
69
|
+
this.lo |= bit;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
const bit = 1 << (idx - 32);
|
|
73
|
+
if (this.hi & bit)
|
|
74
|
+
return false;
|
|
75
|
+
this.hi |= bit;
|
|
76
|
+
}
|
|
77
|
+
this._size++;
|
|
78
|
+
this._order.push(idx);
|
|
79
|
+
return true;
|
|
17
80
|
}
|
|
18
|
-
|
|
19
|
-
return this.
|
|
81
|
+
remove(effect) {
|
|
82
|
+
return this.removeBit(EFFECT_INDEX[effect]);
|
|
20
83
|
}
|
|
21
|
-
|
|
22
|
-
|
|
84
|
+
removeBit(idx) {
|
|
85
|
+
if (idx < 32) {
|
|
86
|
+
const bit = 1 << idx;
|
|
87
|
+
if (!(this.lo & bit))
|
|
88
|
+
return false;
|
|
89
|
+
this.lo &= ~bit;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
const bit = 1 << (idx - 32);
|
|
93
|
+
if (!(this.hi & bit))
|
|
94
|
+
return false;
|
|
95
|
+
this.hi &= ~bit;
|
|
96
|
+
}
|
|
97
|
+
this._size--;
|
|
98
|
+
const i = this._order.indexOf(idx);
|
|
99
|
+
if (i !== -1)
|
|
100
|
+
this._order.splice(i, 1);
|
|
101
|
+
return true;
|
|
23
102
|
}
|
|
24
103
|
size() {
|
|
25
|
-
return this.
|
|
104
|
+
return this._size;
|
|
105
|
+
}
|
|
106
|
+
toArray() {
|
|
107
|
+
return this._order.map((i) => EFFECT_CODES[i]);
|
|
26
108
|
}
|
|
27
109
|
clone() {
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
110
|
+
const c = new EffectSet();
|
|
111
|
+
c.lo = this.lo;
|
|
112
|
+
c.hi = this.hi;
|
|
113
|
+
c._size = this._size;
|
|
114
|
+
c._order = this._order.slice();
|
|
115
|
+
return c;
|
|
31
116
|
}
|
|
32
117
|
}
|
|
33
|
-
exports.EffectSet = EffectSet;
|
|
34
|
-
//# sourceMappingURL=effectSet.js.map
|
package/dist/core/mixer.d.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import type { MixResult, Product, Substance } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Mixes a list of substances into a product and returns the resulting effects,
|
|
4
|
+
* sell price, profit, and addiction value.
|
|
5
|
+
*/
|
|
2
6
|
export declare function mixSubstances(product: Product, substanceCodes: Substance[]): MixResult;
|
|
7
|
+
/**
|
|
8
|
+
* Decodes a hash and runs it through mixSubstances.
|
|
9
|
+
* Throws if the hash is invalid.
|
|
10
|
+
*/
|
|
3
11
|
export declare function mixFromHash(hash: string): MixResult;
|
|
4
12
|
//# sourceMappingURL=mixer.d.ts.map
|
package/dist/core/mixer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mixer.d.ts","sourceRoot":"","sources":["../../src/core/mixer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA0B,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"mixer.d.ts","sourceRoot":"","sources":["../../src/core/mixer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA0B,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAwDtF;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,GAAG,SAAS,CAkFtF;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAMnD"}
|
package/dist/core/mixer.js
CHANGED
|
@@ -1,54 +1,99 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const rules_1 = require("../data/rules");
|
|
8
|
-
const substances_1 = require("../data/substances");
|
|
9
|
-
const encoding_1 = require("../utils/encoding");
|
|
10
|
-
const effectSet_1 = require("./effectSet");
|
|
1
|
+
import { effects } from '../data/effects';
|
|
2
|
+
import { products } from '../data/products';
|
|
3
|
+
import { effectRulesBySubstance } from '../data/rules';
|
|
4
|
+
import { substances } from '../data/substances';
|
|
5
|
+
import { decodeMixState } from '../utils/encoding';
|
|
6
|
+
import { EFFECT_INDEX, EffectSet } from './effectSet';
|
|
11
7
|
const MAX_EFFECTS = 8;
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
const compiledRulesBySubstance = (() => {
|
|
9
|
+
const out = Object.create(null);
|
|
10
|
+
for (const sub in effectRulesBySubstance) {
|
|
11
|
+
const rules = effectRulesBySubstance[sub];
|
|
12
|
+
out[sub] = rules.map((r) => ({
|
|
13
|
+
ifPresent: EFFECT_INDEX[r.ifPresent[0]],
|
|
14
|
+
ifNotPresent: EFFECT_INDEX[r.ifNotPresent[0]],
|
|
15
|
+
replaceFrom: EFFECT_INDEX[Object.keys(r.replace)[0]],
|
|
16
|
+
replaceTo: EFFECT_INDEX[Object.values(r.replace)[0]],
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
19
|
+
return out;
|
|
20
|
+
})();
|
|
21
|
+
const substanceEffectIndices = (() => {
|
|
22
|
+
const out = Object.create(null);
|
|
23
|
+
for (const sub in substances) {
|
|
24
|
+
out[sub] = substances[sub].effect.map((e) => EFFECT_INDEX[e]);
|
|
25
|
+
}
|
|
26
|
+
return out;
|
|
27
|
+
})();
|
|
28
|
+
// Typed arrays for cache-friendly price/addiction lookups by effect index.
|
|
29
|
+
const EFFECT_COUNT = 34;
|
|
30
|
+
const effectPrices = new Float64Array(EFFECT_COUNT);
|
|
31
|
+
const effectAddictions = new Float64Array(EFFECT_COUNT);
|
|
32
|
+
for (const code in effects) {
|
|
33
|
+
const idx = EFFECT_INDEX[code];
|
|
34
|
+
effectPrices[idx] = effects[code].price;
|
|
35
|
+
effectAddictions[idx] = effects[code].addiction;
|
|
36
|
+
}
|
|
37
|
+
function hasBit(lo, hi, idx) {
|
|
38
|
+
return idx < 32 ? (lo & (1 << idx)) !== 0 : (hi & (1 << (idx - 32))) !== 0;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Mixes a list of substances into a product and returns the resulting effects,
|
|
42
|
+
* sell price, profit, and addiction value.
|
|
43
|
+
*/
|
|
44
|
+
export function mixSubstances(product, substanceCodes) {
|
|
45
|
+
if (!products[product]) {
|
|
14
46
|
throw new Error(`Unknown product: ${product}`);
|
|
15
47
|
}
|
|
16
|
-
const productInfo =
|
|
17
|
-
const effectsSet = new
|
|
48
|
+
const productInfo = products[product];
|
|
49
|
+
const effectsSet = new EffectSet(productInfo.effects);
|
|
18
50
|
let totalCost = 0;
|
|
19
51
|
for (const code of substanceCodes) {
|
|
20
|
-
const substance =
|
|
52
|
+
const substance = substances[code];
|
|
21
53
|
if (!substance)
|
|
22
54
|
continue;
|
|
23
55
|
totalCost += substance.price;
|
|
24
|
-
const rules =
|
|
56
|
+
const rules = compiledRulesBySubstance[code];
|
|
25
57
|
if (rules && rules.length > 0) {
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
|
|
58
|
+
// Snapshot the current state as plain ints to avoid a clone() allocation.
|
|
59
|
+
const initLo = effectsSet.lo;
|
|
60
|
+
const initHi = effectsSet.hi;
|
|
61
|
+
let removedLo = 0;
|
|
62
|
+
let removedHi = 0;
|
|
63
|
+
let appliedRules = 0; // bit i = rule i fired in phase 1
|
|
64
|
+
// Phase 1: apply rules whose conditions are met right now.
|
|
30
65
|
for (let i = 0; i < rules.length; i++) {
|
|
31
66
|
const rule = rules[i];
|
|
32
|
-
if (
|
|
33
|
-
|
|
34
|
-
|
|
67
|
+
if (hasBit(initLo, initHi, rule.ifPresent) &&
|
|
68
|
+
!hasBit(initLo, initHi, rule.ifNotPresent) &&
|
|
69
|
+
hasBit(initLo, initHi, rule.replaceFrom)) {
|
|
70
|
+
effectsSet.removeBit(rule.replaceFrom);
|
|
71
|
+
effectsSet.addBit(rule.replaceTo);
|
|
72
|
+
if (rule.replaceFrom < 32)
|
|
73
|
+
removedLo |= 1 << rule.replaceFrom;
|
|
74
|
+
else
|
|
75
|
+
removedHi |= 1 << (rule.replaceFrom - 32);
|
|
76
|
+
appliedRules |= 1 << i;
|
|
35
77
|
}
|
|
36
78
|
}
|
|
79
|
+
// Phase 2: apply rules that were blocked by a now-removed effect.
|
|
37
80
|
for (let i = 0; i < rules.length; i++) {
|
|
38
|
-
if (appliedRules
|
|
81
|
+
if (appliedRules & (1 << i))
|
|
39
82
|
continue;
|
|
40
83
|
const rule = rules[i];
|
|
41
|
-
if (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
84
|
+
if (hasBit(initLo, initHi, rule.ifPresent) &&
|
|
85
|
+
hasBit(removedLo, removedHi, rule.ifNotPresent) &&
|
|
86
|
+
!hasBit(effectsSet.lo, effectsSet.hi, rule.ifNotPresent) &&
|
|
87
|
+
hasBit(effectsSet.lo, effectsSet.hi, rule.replaceFrom)) {
|
|
88
|
+
effectsSet.removeBit(rule.replaceFrom);
|
|
89
|
+
effectsSet.addBit(rule.replaceTo);
|
|
45
90
|
}
|
|
46
91
|
}
|
|
47
92
|
}
|
|
48
|
-
if (effectsSet.size() < MAX_EFFECTS
|
|
49
|
-
for (const
|
|
50
|
-
if (!effectsSet.
|
|
51
|
-
effectsSet.
|
|
93
|
+
if (effectsSet.size() < MAX_EFFECTS) {
|
|
94
|
+
for (const idx of substanceEffectIndices[code]) {
|
|
95
|
+
if (!effectsSet.hasBit(idx)) {
|
|
96
|
+
effectsSet.addBit(idx);
|
|
52
97
|
if (effectsSet.size() >= MAX_EFFECTS)
|
|
53
98
|
break;
|
|
54
99
|
}
|
|
@@ -71,86 +116,26 @@ function mixSubstances(product, substanceCodes) {
|
|
|
71
116
|
addiction,
|
|
72
117
|
};
|
|
73
118
|
}
|
|
74
|
-
|
|
75
|
-
|
|
119
|
+
/**
|
|
120
|
+
* Decodes a hash and runs it through mixSubstances.
|
|
121
|
+
* Throws if the hash is invalid.
|
|
122
|
+
*/
|
|
123
|
+
export function mixFromHash(hash) {
|
|
124
|
+
const state = decodeMixState(hash);
|
|
76
125
|
if (!state) {
|
|
77
126
|
throw new Error(`Invalid hash: ${hash}`);
|
|
78
127
|
}
|
|
79
128
|
return mixSubstances(state.product, state.substances);
|
|
80
129
|
}
|
|
81
|
-
function checkRulePreconditions(rule, initialEffects) {
|
|
82
|
-
for (const effect of rule.ifPresent) {
|
|
83
|
-
if (!initialEffects.has(effect))
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
for (const effect of rule.ifNotPresent) {
|
|
87
|
-
if (initialEffects.has(effect))
|
|
88
|
-
return false;
|
|
89
|
-
}
|
|
90
|
-
for (const oldEffect of Object.keys(rule.replace)) {
|
|
91
|
-
if (initialEffects.has(oldEffect))
|
|
92
|
-
return true;
|
|
93
|
-
}
|
|
94
|
-
return false;
|
|
95
|
-
}
|
|
96
|
-
function meetsPhaseTwo(rule, initialEffects, currentEffects, removedEffects) {
|
|
97
|
-
for (const effect of rule.ifPresent) {
|
|
98
|
-
if (!initialEffects.has(effect))
|
|
99
|
-
return false;
|
|
100
|
-
}
|
|
101
|
-
let hasRemovedForbidden = false;
|
|
102
|
-
for (const effect of rule.ifNotPresent) {
|
|
103
|
-
if (removedEffects.has(effect)) {
|
|
104
|
-
hasRemovedForbidden = true;
|
|
105
|
-
break;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
if (!hasRemovedForbidden)
|
|
109
|
-
return false;
|
|
110
|
-
for (const effect of rule.ifNotPresent) {
|
|
111
|
-
if (currentEffects.has(effect))
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
return true;
|
|
115
|
-
}
|
|
116
|
-
function applyReplaceEffects(replace, initialEffects, effectsSet, processedEffects, removedEffects) {
|
|
117
|
-
for (const [oldEffect, newEffect] of Object.entries(replace)) {
|
|
118
|
-
if (initialEffects.has(oldEffect)) {
|
|
119
|
-
effectsSet.remove(oldEffect);
|
|
120
|
-
effectsSet.add(newEffect);
|
|
121
|
-
processedEffects.add(oldEffect);
|
|
122
|
-
removedEffects.add(oldEffect);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
function canApplyTransformation(replace, effectsSet) {
|
|
127
|
-
for (const oldEffect of Object.keys(replace)) {
|
|
128
|
-
if (effectsSet.has(oldEffect))
|
|
129
|
-
return true;
|
|
130
|
-
}
|
|
131
|
-
return false;
|
|
132
|
-
}
|
|
133
|
-
function applyTransformations(replace, effectsSet, processedEffects) {
|
|
134
|
-
for (const [oldEffect, newEffect] of Object.entries(replace)) {
|
|
135
|
-
if (effectsSet.has(oldEffect)) {
|
|
136
|
-
effectsSet.remove(oldEffect);
|
|
137
|
-
effectsSet.add(newEffect);
|
|
138
|
-
processedEffects.add(oldEffect);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
130
|
function calculateEffectValue(effectCodes) {
|
|
143
131
|
let value = 0;
|
|
144
|
-
for (const code of effectCodes)
|
|
145
|
-
value +=
|
|
146
|
-
}
|
|
132
|
+
for (const code of effectCodes)
|
|
133
|
+
value += effectPrices[EFFECT_INDEX[code]];
|
|
147
134
|
return value;
|
|
148
135
|
}
|
|
149
136
|
function calculateAddiction(product, effectCodes) {
|
|
150
|
-
let value =
|
|
151
|
-
for (const code of effectCodes)
|
|
152
|
-
value +=
|
|
153
|
-
}
|
|
137
|
+
let value = products[product]?.addiction || 0;
|
|
138
|
+
for (const code of effectCodes)
|
|
139
|
+
value += effectAddictions[EFFECT_INDEX[code]];
|
|
154
140
|
return value;
|
|
155
141
|
}
|
|
156
|
-
//# sourceMappingURL=mixer.js.map
|
package/dist/data/effects.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.bitToEffect = exports.effectBits = exports.effects = void 0;
|
|
4
|
-
exports.effects = {
|
|
1
|
+
export const effects = {
|
|
5
2
|
Pa: {
|
|
6
3
|
name: 'Paranoia',
|
|
7
4
|
description: 'Induces paranoia in the user.',
|
|
@@ -275,14 +272,13 @@ exports.effects = {
|
|
|
275
272
|
addiction: 0.336,
|
|
276
273
|
},
|
|
277
274
|
};
|
|
278
|
-
|
|
275
|
+
export const effectBits = Object.keys(effects)
|
|
279
276
|
.sort()
|
|
280
277
|
.reduce((acc, code, idx) => {
|
|
281
278
|
acc[code] = 1n << BigInt(idx);
|
|
282
279
|
return acc;
|
|
283
280
|
}, {});
|
|
284
|
-
|
|
281
|
+
export const bitToEffect = Object.entries(effectBits).reduce((acc, [code, bit]) => {
|
|
285
282
|
acc[bit.toString()] = code;
|
|
286
283
|
return acc;
|
|
287
284
|
}, {});
|
|
288
|
-
//# sourceMappingURL=effects.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"products.d.ts","sourceRoot":"","sources":["../../src/data/products.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAErD,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"products.d.ts","sourceRoot":"","sources":["../../src/data/products.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAErD,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,WAAW,CA8CjD,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAMxD,CAAC"}
|
package/dist/data/products.js
CHANGED
|
@@ -1,42 +1,51 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.productAbbreviations = exports.products = void 0;
|
|
4
|
-
exports.products = {
|
|
1
|
+
export const products = {
|
|
5
2
|
'OG Kush': {
|
|
6
3
|
price: 35,
|
|
4
|
+
rank: '1',
|
|
7
5
|
effects: ['Ca'],
|
|
8
6
|
abbreviation: 'OH',
|
|
9
7
|
},
|
|
10
8
|
'Sour Diesel': {
|
|
11
9
|
price: 35,
|
|
10
|
+
rank: '4',
|
|
12
11
|
effects: ['Re'],
|
|
13
12
|
abbreviation: 'SL',
|
|
14
13
|
},
|
|
15
14
|
'Green Crack': {
|
|
16
15
|
price: 35,
|
|
16
|
+
rank: '7',
|
|
17
17
|
effects: ['En'],
|
|
18
18
|
abbreviation: 'GK',
|
|
19
19
|
},
|
|
20
20
|
'Grandaddy Purple': {
|
|
21
21
|
price: 35,
|
|
22
|
+
rank: '9',
|
|
22
23
|
effects: ['Se'],
|
|
23
24
|
abbreviation: 'GE',
|
|
24
25
|
},
|
|
25
26
|
Meth: {
|
|
26
27
|
price: 70,
|
|
28
|
+
rank: '6',
|
|
27
29
|
effects: [],
|
|
28
30
|
abbreviation: 'MH',
|
|
29
31
|
addiction: 0.6,
|
|
30
32
|
},
|
|
31
33
|
Cocaine: {
|
|
32
34
|
price: 150,
|
|
35
|
+
rank: '26',
|
|
33
36
|
effects: [],
|
|
34
37
|
abbreviation: 'CE',
|
|
35
38
|
addiction: 0.4,
|
|
36
39
|
},
|
|
40
|
+
Shrooms: {
|
|
41
|
+
price: 65,
|
|
42
|
+
rank: '10',
|
|
43
|
+
effects: [],
|
|
44
|
+
abbreviation: 'SR',
|
|
45
|
+
addiction: 0.05,
|
|
46
|
+
},
|
|
37
47
|
};
|
|
38
|
-
|
|
48
|
+
export const productAbbreviations = Object.entries(products).reduce((acc, [product, data]) => {
|
|
39
49
|
acc[data.abbreviation] = product;
|
|
40
50
|
return acc;
|
|
41
51
|
}, {});
|
|
42
|
-
//# sourceMappingURL=products.js.map
|
package/dist/data/rules.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.effectRulesBySubstance = void 0;
|
|
4
|
-
exports.effectRulesBySubstance = {
|
|
1
|
+
export const effectRulesBySubstance = {
|
|
5
2
|
Cuke: [
|
|
6
3
|
{ ifPresent: ['Eu'], ifNotPresent: ['La'], replace: { Eu: 'La' } },
|
|
7
4
|
{ ifPresent: ['Fo'], ifNotPresent: ['Cy'], replace: { Fo: 'Cy' } },
|
|
@@ -149,4 +146,3 @@ exports.effectRulesBySubstance = {
|
|
|
149
146
|
{ ifPresent: ['Sh'], ifNotPresent: ['Mu'], replace: { Sh: 'Mu' } },
|
|
150
147
|
],
|
|
151
148
|
};
|
|
152
|
-
//# sourceMappingURL=rules.js.map
|
package/dist/data/substances.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.substanceAbbreviations = exports.substances = void 0;
|
|
4
|
-
exports.substances = {
|
|
1
|
+
export const substances = {
|
|
5
2
|
Cuke: {
|
|
6
3
|
abbreviation: 'A',
|
|
7
4
|
rank: '1',
|
|
@@ -76,7 +73,7 @@ exports.substances = {
|
|
|
76
73
|
},
|
|
77
74
|
'Horse Semen': {
|
|
78
75
|
abbreviation: 'M',
|
|
79
|
-
rank: '
|
|
76
|
+
rank: '18',
|
|
80
77
|
price: 9,
|
|
81
78
|
effect: ['Lf'],
|
|
82
79
|
},
|
|
@@ -88,7 +85,7 @@ exports.substances = {
|
|
|
88
85
|
},
|
|
89
86
|
Addy: {
|
|
90
87
|
abbreviation: 'O',
|
|
91
|
-
rank: '
|
|
88
|
+
rank: '17',
|
|
92
89
|
price: 9,
|
|
93
90
|
effect: ['Tp'],
|
|
94
91
|
},
|
|
@@ -99,8 +96,7 @@ exports.substances = {
|
|
|
99
96
|
effect: ['Be'],
|
|
100
97
|
},
|
|
101
98
|
};
|
|
102
|
-
|
|
99
|
+
export const substanceAbbreviations = Object.entries(substances).reduce((acc, [substance, data]) => {
|
|
103
100
|
acc[data.abbreviation] = substance;
|
|
104
101
|
return acc;
|
|
105
102
|
}, {});
|
|
106
|
-
//# sourceMappingURL=substances.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { encodeMixState, decodeMixState, migrateMixHash } from './utils/encoding';
|
|
2
2
|
export { mixSubstances, mixFromHash } from './core/mixer';
|
|
3
|
-
export { effects } from './data/effects';
|
|
4
3
|
export { products, productAbbreviations } from './data/products';
|
|
5
|
-
export { substances } from './data/substances';
|
|
6
4
|
export { effectRulesBySubstance } from './data/rules';
|
|
5
|
+
export { substances } from './data/substances';
|
|
6
|
+
export { effects } from './data/effects';
|
|
7
7
|
export type { EffectCode, Substance, Product, RankCode, EffectData, SubstanceData, ProductData, EffectRule, MixResult, MixState, } from './types';
|
|
8
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElF,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE1D,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,YAAY,EACV,UAAU,EACV,SAAS,EACT,OAAO,EACP,QAAQ,EACR,UAAU,EACV,aAAa,EACb,WAAW,EACX,UAAU,EACV,SAAS,EACT,QAAQ,GACT,MAAM,SAAS,CAAC"}
|