-
Notifications
You must be signed in to change notification settings - Fork 0
/
randomseed.js
395 lines (354 loc) · 12.5 KB
/
randomseed.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
// fonction essentielle à toutes les autres qui va ramener tout nombre (numéros de caractères ou issus des calculs)
// en un entier de 0 à 29 correspondant aux indexs la seedtable
// (ou autre en paramétrant cette limite)
function rebaseNumber(number, limit) {
if (!limit) limit=30 ;
number=Math.round (number);
if (number<0) {number*-1;}
if (number>-1 && number<limit) return number;
if (number >-1) return number-(Math.floor(number/limit)*limit);
// juste au cas où on décide d'utiliser des formules pouvant aboutir à des valeurs négatives
}
// génère aléatoirement une seed
function genSeed () {
let seedtable = new Array (30).fill(-1);
let place, value;
for (var i=0; i<30;++i) {
value=parseInt (i.toString().slice(-1));
place = Math.floor(Math.random()*10)+value;
while (seedtable[place]>-1) {
if (place<29) {
++place;
}
else {
place = 0;
}
}
seedtable [place] = value ;
}
return seedtable;
}
//le constructeur de l'objet RandomSeed
//tous ses paramètres sont optionnels (il dispose de méthodes pour les générer)
//il peut prendre en paramètre une seed, un numéro de tirage et un nombre à ajouter à ceux-ci mais dispose de méthodes pour les générer
export const RandomSeed = function (seed, rollNo, addToRollNo) {
if (seed==undefined) {
// génère aléatoirement la seedtable si aucune n'est fournie
seed = genSeed() ;
}
this.seed = seed;
// si le rollNo n'est pas renseigné on l'initialise à 0
if (rollNo==undefined) {
rollNo=0;
}
this.rollNo=rollNo;
// plutôt que d'utiliser un numéro de tirage partant de 0 on génère à partir de la seed un grand nombre qui s'ajoutera à celui ci
// suite aux tests il a été déterminé qu'un commençant nombre commençant '10' et suivi de 5 chiffres est optimum (ne me demandez pas pourquoi)
// tout ce que je peux en dire c'est qu'enlever le "10" ou ajouter un "0" passé le 2ème chiffre augmente le nombre de répétitions de séries,
// tandis qu'ajouter plus de chiffres issus de la seed ne les diminue pas d'avantage (quand on utilise la méthode roll2)
if (addToRollNo==undefined) {
let tt = "10"+ this.seed[21]+ this.seed [this.seed[11]] + this.seed [15]+ this.seed[27] +this.seed[this.seed[14]];
addToRollNo = parseInt (tt);
}
this.addToRollNo=addToRollNo;
}
// ma toute première méthode qui faisait illusion sur un petit nombre de tirages mais s'est avérée très mauvaise au niveau des tests
// certains résultats possibles ont tendance à ne jamais apparaitre, ou juste une poignée de fois, en 100000 tirages
// et le nombre de répétitions de séries est énorme
RandomSeed.prototype.roll0 = function (dice, rollNo) {
if (rollNo==undefined) {
rollNo=this.rollNo;
this.rollNo++ ;
}
let noDe1, noDe2, noDe3, de1, de2, de3, step, result,rollstring ;
rollNo += this.addToRollNo ; // une constante générée à partir de la seed qui s'ajoute au numéro de tirage
step = rebaseNumber(Math.floor(rollNo+1)/30);
noDe1 = rebaseNumber(rollNo+Math.floor(rollNo/900));
noDe2 = rebaseNumber(rollNo+step);
noDe3 = rebaseNumber(rollNo+2*step);
de1=this.seed[noDe1];
de2=this.seed[noDe2];
de3=this.seed[noDe3];
if (rollNo%3) {
de1 = this.seed [noDe2];
de2 = this.seed [noDe1];
}
else if (rollNo%2) {
de3 = this.seed [noDe1];
de1 = this.seed [noDe3];
}
rollstring = ""+de1+de2+de3;
result = parseInt (rollstring);
if (dice==undefined) {
dice=1000;
}
result = Math.floor((result*dice)/1000) +1;
return parseInt(result);
}
//une méthode intermédiaire produisant déjà beaucoup moins d'anomalies (pas de nombre absent ou sur-répété)
//mais toujours un peu trop de répétitions de séries de nombres
RandomSeed.prototype.roll1 = function (dice, rollNo) {
if (rollNo==undefined) {
rollNo=this.rollNo;
this.rollNo++ ;
}
rollNo += this.addToRollNo ;
let noDe1, noDe2, noDe3, de1, de2, de3, step, result,rollNostring ;
step = rebaseNumber(Math.ceil((rollNo/119)*7));
let t = rollNo+step;
if (rollNo%6) {
t-=57;
}
else if (rollNo%2) {
t+=step;
}
else if (rollNo%3) {
t-=(step+1);
}
if (t%35) {
t+=13;
}
else if (t%5) {
t+=Math.ceil(step/2);
}
else if (t%7) {
t-=Math.ceil(step/2);
}
else if (t%11) {
t+=3;
}
else if (t%13) {
t+=11;
}
else if (t%15) {
t-=3;
}
else if (t%3) {
t+=2;
}
noDe1 = rebaseNumber ((t*Math.PI)/4);
noDe2 = rebaseNumber ((t/47)*17);
noDe3 = rebaseNumber ((t/59)*23);
if (rollNo%3) {
de1 = this.seed [noDe2];
de2 = this.seed [noDe1];
}
else {
de1 = this.seed [noDe1];
de2 = this.seed [noDe2];
}
de3 = this.seed [noDe3];
if (rollNo%5) {
de3=de1;
de1 = this.seed [noDe3];
}
else if (t%5) {
de3=de2;
de2 = this.seed [noDe3];
}
rollNostring = ""+de1+de2+de3;
if (rollNo%4) {
result = 999- parseInt (rollNostring);
}
else {
result = parseInt (rollNostring);
}
if (dice==undefined) {
dice=1000;
}
result = Math.floor((result*dice)/1000) +1;
return parseInt(result);
}
RandomSeed.prototype.roll2 = function (dice, rollNo) {
if (rollNo==undefined) {
rollNo=this.rollNo;
++ this.rollNo ;
}
else {
rollNo = parseInt (rollNo);
}
rollNo += this.addToRollNo ;
// à partir du numéro de tirage on génère 3 valeurs
// peu importe la méthode exacte, le tout est ce qu'elles aient beaucoup de chiffres après la virgule
// des multiplications par des fractions nombre premier / nombre premier supérieur ou utilisant des constantes comme Math.PI marchent très bien pour ça
let v1= ((Math.PI/1.23337)*rollNo);
let v2= (rollNo*(241/617));
let v3= (rollNo*(827/1877));
// on garde de ces valeurs les 5 derniers chiffres en éliminant le tout dernier
// les tests ayant montré que l'inclure crée des déséquilibres (tirages qui reviennent plus que d'autres)
let strv1 = v1.toString().slice(-5,-1);
let strv2 = v2.toString().slice(-5,-1);
let strv3 = v3.toString().slice(-5,-1);
v1= parseInt(strv1);
v2= parseInt (strv2);
v3= parseInt(strv3);
// pour ajouter à l'irrégularité des séries on échange les valeurs si le numéro de tirage est pair ou un multiple 3
let temp;
if (rollNo%2) {
temp = v1;
v1=v2;
v2=v3;
v3=temp;
}
else if (rollNo%3) {
temp = v2;
v2=v1;
v1=v3;
v3=temp;
}
// enfin on utilise rebaseNumber pour aboutir à des numéros de dés de 0 à 29
let noDe1 = rebaseNumber (v1);
let noDe2 = rebaseNumber (v2);
let noDe3 = rebaseNumber (v3);
let rollNoStr = ""+this.seed[noDe1]+this.seed[noDe2]+this.seed[noDe3];
let result=parseInt(rollNoStr);
//et pour limiter encore les répétions de séries on inverse les résultats 1 fois sur 4
if (rollNo%4) {
result = 999 - result;
}
if (dice==undefined) {
dice=1000;
}
result = Math.floor((result*dice)/1000) +1;
return parseInt(result);
}
RandomSeed.prototype.roll3 = function (dice, rollNo) {
if (rollNo==undefined) {
rollNo=this.rollNo;
++ this.rollNo ;
}
else {
rollNo = parseInt (rollNo);
}
rollNo += this.addToRollNo ;
let div1 = 0.137 + rebaseNumber (rollNo,5);
let div2 = 600 + rebaseNumber (rollNo,34);
let div3 = 1850 + rebaseNumber (rollNo,73);
// à partir du numéro de tirage on génère 3 valeurs
// peu importe la méthode exacte, le tout est ce qu'elles aient beaucoup de chiffres après la virgule
// des multiplications par des fractions nombre premier / nombre premier supérieur ou utilisant des constantes comme Math.PI marchent très bien pour ça
let v1= ((Math.PI/div1)*rollNo);
let v2= (rollNo*(241/div2));
let v3= (rollNo*(827/div3));
// on garde de ces valeurs les 5 derniers chiffres en éliminant le tout dernier
// les tests ayant montré que l'inclure crée des déséquilibres (tirages qui reviennent plus que d'autres)
let strv1 = v1.toString().slice(-5,-1).replace('.','');
let strv2 = v2.toString().slice(-5,-1).replace('.','');
let strv3 = v3.toString().slice(-5,-1).replace('.','');
v1= parseInt(strv1);
v2= parseInt (strv2);
v3= parseInt(strv3);
if (isNaN(v1) || isNaN(v2) || isNaN(v3) ) {
console.log (" strv1 "+strv1+ " strv2 "+strv2+" strv3 "+strv3);
}
// pour ajouter à l'irrégularité des séries on échange les valeurs si le numéro de tirage est pair ou un multiple 3
let temp;
if (rollNo%2) {
temp = v1;
v1=v2;
v2=v3;
v3=temp;
}
else if (rollNo%3) {
temp = v2;
v2=v1;
v1=v3;
v3=temp;
}
// enfin on utilise rebaseNumber pour aboutir à des numéros de dés de 0 à 29
let noDe1 = rebaseNumber (v1);
let noDe2 = rebaseNumber (v2);
let noDe3 = rebaseNumber (v3);
let rollNoStr = ""+this.seed[noDe1]+this.seed[noDe2]+this.seed[noDe3];
let result=parseInt(rollNoStr);
//et pour limiter encore les répétions de séries on inverse les résultats 1 fois sur 4
if (rollNo%4) {
result = 999 - result;
}
if (dice) {
result = Math.floor((result*dice)/1000)
}
return result+1;
}
RandomSeed.prototype.rollLarge = function (dice, rollNo) {
if (dice==undefined) {
dice=1000;
}
if (rollNo==undefined) {
rollNo=this.rollNo;
++ this.rollNo ;
}
else {
rollNo = parseInt (rollNo);
}
let mult = [3.114115, 241, 827, 111, 103, 197, 829, 13, 199, 493, 4.1067];
let divBase = [0.137, 600, 1850, 127, 114, 434, 1110, 14, 750, 0.5492];
let divRange = [1+this.seed[0], 11+this.seed[1]+this.seed[2], 50+this.seed[3]+this.seed[4]+this.seed[5], 20+this.seed[6], 15+this.seed[6], 70+this.seed[1], 4+ this.seed[7]+this.seed[8], 17+this.seed[2], 12+this.seed[13], 2+this.seed[14]];
let dicesToRoll = Math.min (dice.toString().length, 10);
let dices=[];
let v, strv, div;
for (let i=0;i<dicesToRoll;++i) {
div= divBase[i]+rebaseNumber(rollNo,divRange[i]);
v= mult[i]*rollNo/div;
strv = "131"+v.toString().slice(-5,-1).replace('.','');
v=parseInt(strv);
dices.push (this.seed[rebaseNumber(v)]);
}
let firstDice=rebaseNumber(rollNo,dicesToRoll);
let resultString="";
for (let i=0;i<dicesToRoll;++i) {
resultString+=dices[rebaseNumber(firstDice+i,dicesToRoll)];
}
let result=parseInt(resultString);
if (isNaN(result)) {
console.log ("dices "+dices);
console.log ("firstDice "+firstDice);
console.log ("divBase "+divBase);
console.log ("divRange "+divRange);
console.log ("dices to roll "+dicesToRoll);
console.log ("v "+v);
throw error;
}
result=rebaseNumber (result,dice);
if (rollNo%4) {
return dice-result;
}
return result+1;
}
// la fonction générant la seedtable à partir d'un mot (qui peut être toute autre combinaison de caractères ASCII)
// elle est exportée pour pouvoir changer le mot dans les texts
export const WordToSeed = function (word) {
// si le mot est absent (ou une chaine vide) elle ne retourne rien/undefined (ce qui active l'autre méthode de génération de seedtable)
if (word) {
let seed = new Array (30).fill(-1);
// sinon on met le mot à la longueur minimum (et seule utile) de 30 caractères
while (word.length<30) { // s'il est plus court on le répète en ajoutant (arbitrairement) 'gk' entre deux répétitions
word=word+'gk'+word; // celà évite que les mots de moins de 3 lettres génèrent des tables trop régulières
}
let charNo, rebasedNo, direction;
let chiffre;
for (let i=0;i<30;++i) {
chiffre=parseInt (i.toString().slice(-1));
charNo=word.charCodeAt(i);
rebasedNo = rebaseNumber(charNo, 30);
if ((i+charNo)%2) {
direction =1;
}
else {
direction=-1;
}
while (seed[rebasedNo]!=-1) {
rebasedNo+=direction;
if (rebasedNo>29) {
rebasedNo=0;
}
if (rebasedNo<0) {
rebasedNo=29;
}
}
seed[rebasedNo]=chiffre;
}
return seed;
}
}