1 (*
2 * Hedgewars, a free turn based strategy game
3 * Copyright (c) 2004-2015 Andrey Korotaev <unC0Rr@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 *)
18
19 {$INCLUDE "options.inc"}
20
21 unit uRandom;
22 (*
23 * This unit supplies platform-independent functions for getting various
24 * pseudo-random values based on a shared seed.
25 *
26 * This is necessary for accomplishing pseudo-random behavior in the game
27 * without causing a desynchronisation of different clients when playing over
28 * a network.
29 *)
30 interface
31 uses uFloat;
32
33 procedure SetRandomSeed(Seed: shortstring; dropAdditionalPart: boolean); // Sets the seed that should be used for generating pseudo-random values.
GetRandomfnull34 function GetRandomf: hwFloat; // Returns a pseudo-random hwFloat.
GetRandomnull35 function GetRandom(m: LongWord): LongWord; inline; // Returns a positive pseudo-random integer smaller than m.
36 procedure AddRandomness(r: LongWord); inline;
rndSignnull37 function rndSign(num: hwFloat): hwFloat; // Returns num with a random chance of having a inverted sign.
38
39
40 implementation
41
42 var cirbuf: array[0..63] of Longword;
43 n: byte;
44
45 procedure AddRandomness(r: LongWord); inline;
46 begin
47 n:= (n + 1) and $3F;
48 cirbuf[n]:= cirbuf[n] xor r;
49 end;
50
GetNextnull51 function GetNext: Longword; inline;
52 begin
53 n:= (n + 1) and $3F;
54 cirbuf[n]:=
55 (cirbuf[(n + 40) and $3F] + {n - 24 mod 64}
56 cirbuf[(n + 9) and $3F]) {n - 55 mod 64}
57 and $7FFFFFFF; {mod 2^31}
58
59 GetNext:= cirbuf[n];
60 end;
61
62 procedure SetRandomSeed(Seed: shortstring; dropAdditionalPart: boolean);
63 var i, t, l: Longword;
64 begin
65 n:= 54;
66
67 if Length(Seed) > 54 then
68 Seed:= copy(Seed, 1, 54); // not 55 to ensure we have odd numbers in cirbuf
69
70 t:= 0;
71 l:= Length(Seed);
72
73 while (t < l) and ((not dropAdditionalPart) or (Seed[t + 1] <> '|')) do
74 begin
75 cirbuf[t]:= byte(Seed[t + 1]);
76 inc(t)
77 end;
78
79 for i:= t to 54 do
80 cirbuf[i]:= $A98765 + 68; // odd number
81
82 for i:= 0 to 2047 do
83 GetNext;
84 end;
85
GetRandomfnull86 function GetRandomf: hwFloat;
87 begin
88 GetNext;
89 GetRandomf.isNegative:= false;
90 GetRandomf.QWordValue:= GetNext
91 end;
92
GetRandomnull93 function GetRandom(m: LongWord): LongWord; inline;
94 begin
95 GetNext;
96 GetRandom:= GetNext mod m
97 end;
98
rndSignnull99 function rndSign(num: hwFloat): hwFloat;
100 begin
101 num.isNegative:= odd(GetNext);
102 rndSign:= num
103 end;
104
105 end.
106