author | koda |
Sat, 15 Jan 2011 21:32:44 +0100 | |
branch | 0.9.15 |
changeset 4751 | 849740a91d36 |
parent 4665 | fa7ad5f3725f |
child 4737 | ca03ce7e0c3f |
permissions | -rw-r--r-- |
4374 | 1 |
{$INCLUDE "options.inc"} |
2 |
unit uUtils; |
|
3 |
||
4 |
interface |
|
5 |
uses uTypes, uFloat, GLunit; |
|
6 |
||
7 |
procedure SplitBySpace(var a, b: shortstring); |
|
8 |
procedure SplitByChar(var a, b: ansistring; c: char); |
|
9 |
||
10 |
function EnumToStr(const en : TGearType) : shortstring; overload; |
|
4453 | 11 |
function EnumToStr(const en : TVisualGearType) : shortstring; overload; |
4374 | 12 |
function EnumToStr(const en : TSound) : shortstring; overload; |
13 |
function EnumToStr(const en : TAmmoType) : shortstring; overload; |
|
14 |
function EnumToStr(const en : THogEffect) : shortstring; overload; |
|
15 |
||
16 |
function Min(a, b: LongInt): LongInt; inline; |
|
17 |
function Max(a, b: LongInt): LongInt; inline; |
|
18 |
||
19 |
function IntToStr(n: LongInt): shortstring; |
|
20 |
function FloatToStr(n: hwFloat): shortstring; |
|
21 |
||
22 |
function DxDy2Angle(const _dY, _dX: hwFloat): GLfloat; |
|
23 |
function DxDy2Angle32(const _dY, _dX: hwFloat): LongInt; |
|
24 |
function DxDy2AttackAngle(const _dY, _dX: hwFloat): LongInt; |
|
25 |
||
26 |
procedure SetLittle(var r: hwFloat); |
|
27 |
||
28 |
function Str2PChar(const s: shortstring): PChar; |
|
29 |
function DecodeBase64(s: shortstring): shortstring; |
|
30 |
||
31 |
function isPowerOf2(i: Longword): boolean; |
|
32 |
function toPowerOf2(i: Longword): Longword; inline; |
|
33 |
||
34 |
function endian(independent: LongWord): LongWord; inline; |
|
35 |
||
4380 | 36 |
function CheckCJKFont(s: ansistring; font: THWFont): THWFont; |
37 |
||
4374 | 38 |
{$IFDEF DEBUGFILE} |
39 |
procedure AddFileLog(s: shortstring); |
|
40 |
{$ENDIF} |
|
41 |
||
4398
36d7e4b6ca81
Move some command handlers out of uCommands into more appropriate places, thus removing some dependencies. Ideally uCommands shouldn't depend on anything (except for uTypes and uConsts probably)
unc0rr
parents:
4385
diff
changeset
|
42 |
function CheckNoTeamOrHH: boolean; inline; |
36d7e4b6ca81
Move some command handlers out of uCommands into more appropriate places, thus removing some dependencies. Ideally uCommands shouldn't depend on anything (except for uTypes and uConsts probably)
unc0rr
parents:
4385
diff
changeset
|
43 |
|
4403 | 44 |
function GetLaunchX(at: TAmmoType; dir: LongInt; angle: LongInt): LongInt; |
45 |
function GetLaunchY(at: TAmmoType; angle: LongInt): LongInt; |
|
46 |
||
4374 | 47 |
procedure initModule; |
48 |
procedure freeModule; |
|
49 |
||
4385 | 50 |
|
4374 | 51 |
implementation |
52 |
uses typinfo, Math, uConsts, uVariables, SysUtils; |
|
53 |
||
54 |
{$IFDEF DEBUGFILE} |
|
4437
05192cdbce9b
un-break build (wrong merge in uConsole) and update project file with the new sources
koda
parents:
4403
diff
changeset
|
55 |
var f: textfile; |
4374 | 56 |
{$ENDIF} |
57 |
||
58 |
// should this include "strtolower()" for the split string? |
|
59 |
procedure SplitBySpace(var a, b: shortstring); |
|
60 |
var i, t: LongInt; |
|
61 |
begin |
|
62 |
i:= Pos(' ', a); |
|
63 |
if i > 0 then |
|
64 |
begin |
|
65 |
for t:= 1 to Pred(i) do |
|
66 |
if (a[t] >= 'A')and(a[t] <= 'Z') then Inc(a[t], 32); |
|
67 |
b:= copy(a, i + 1, Length(a) - i); |
|
68 |
byte(a[0]):= Pred(i) |
|
69 |
end else b:= ''; |
|
70 |
end; |
|
71 |
||
72 |
procedure SplitByChar(var a, b: ansistring; c: char); |
|
73 |
var i: LongInt; |
|
74 |
begin |
|
75 |
i:= Pos(c, a); |
|
76 |
if i > 0 then |
|
77 |
begin |
|
78 |
b:= copy(a, i + 1, Length(a) - i); |
|
79 |
setlength(a, Pred(i)); |
|
80 |
end else b:= ''; |
|
81 |
end; |
|
82 |
||
83 |
function EnumToStr(const en : TGearType) : shortstring; overload; |
|
84 |
begin |
|
85 |
EnumToStr:= GetEnumName(TypeInfo(TGearType), ord(en)) |
|
86 |
end; |
|
4453 | 87 |
function EnumToStr(const en : TVisualGearType) : shortstring; overload; |
88 |
begin |
|
89 |
EnumToStr:= GetEnumName(TypeInfo(TVisualGearType), ord(en)) |
|
90 |
end; |
|
4374 | 91 |
|
92 |
function EnumToStr(const en : TSound) : shortstring; overload; |
|
93 |
begin |
|
94 |
EnumToStr:= GetEnumName(TypeInfo(TSound), ord(en)) |
|
95 |
end; |
|
96 |
||
97 |
function EnumToStr(const en : TAmmoType) : shortstring; overload; |
|
98 |
begin |
|
99 |
EnumToStr:= GetEnumName(TypeInfo(TAmmoType), ord(en)) |
|
100 |
end; |
|
101 |
||
102 |
function EnumToStr(const en: THogEffect) : shortstring; overload; |
|
103 |
begin |
|
104 |
EnumToStr := GetEnumName(TypeInfo(THogEffect), ord(en)) |
|
105 |
end; |
|
106 |
||
107 |
||
108 |
function Min(a, b: LongInt): LongInt; |
|
109 |
begin |
|
110 |
if a < b then Min:= a else Min:= b |
|
111 |
end; |
|
112 |
||
113 |
function Max(a, b: LongInt): LongInt; |
|
114 |
begin |
|
115 |
if a > b then Max:= a else Max:= b |
|
116 |
end; |
|
117 |
||
118 |
||
119 |
function IntToStr(n: LongInt): shortstring; |
|
120 |
begin |
|
121 |
str(n, IntToStr) |
|
122 |
end; |
|
123 |
||
124 |
function FloatToStr(n: hwFloat): shortstring; |
|
125 |
begin |
|
126 |
FloatToStr:= cstr(n) + '_' + inttostr(Lo(n.QWordValue)) |
|
127 |
end; |
|
128 |
||
129 |
||
130 |
function DxDy2Angle(const _dY, _dX: hwFloat): GLfloat; |
|
131 |
var dY, dX: Extended; |
|
132 |
begin |
|
133 |
dY:= _dY.QWordValue / $100000000; |
|
134 |
if _dY.isNegative then dY:= - dY; |
|
135 |
dX:= _dX.QWordValue / $100000000; |
|
136 |
if _dX.isNegative then dX:= - dX; |
|
137 |
DxDy2Angle:= arctan2(dY, dX) * 180 / pi |
|
138 |
end; |
|
139 |
||
140 |
function DxDy2Angle32(const _dY, _dX: hwFloat): LongInt; |
|
141 |
const _16divPI: Extended = 16/pi; |
|
142 |
var dY, dX: Extended; |
|
143 |
begin |
|
144 |
dY:= _dY.QWordValue / $100000000; |
|
145 |
if _dY.isNegative then dY:= - dY; |
|
146 |
dX:= _dX.QWordValue / $100000000; |
|
147 |
if _dX.isNegative then dX:= - dX; |
|
148 |
DxDy2Angle32:= trunc(arctan2(dY, dX) * _16divPI) and $1f |
|
149 |
end; |
|
150 |
||
151 |
function DxDy2AttackAngle(const _dY, _dX: hwFloat): LongInt; |
|
152 |
const MaxAngleDivPI: Extended = cMaxAngle/pi; |
|
153 |
var dY, dX: Extended; |
|
154 |
begin |
|
155 |
dY:= _dY.QWordValue / $100000000; |
|
156 |
if _dY.isNegative then dY:= - dY; |
|
157 |
dX:= _dX.QWordValue / $100000000; |
|
158 |
if _dX.isNegative then dX:= - dX; |
|
159 |
DxDy2AttackAngle:= trunc(arctan2(dY, dX) * MaxAngleDivPI) |
|
160 |
end; |
|
161 |
||
162 |
||
163 |
procedure SetLittle(var r: hwFloat); |
|
164 |
begin |
|
165 |
r:= SignAs(cLittle, r) |
|
166 |
end; |
|
167 |
||
168 |
||
169 |
function isPowerOf2(i: Longword): boolean; |
|
170 |
begin |
|
171 |
if i = 0 then exit(true); |
|
172 |
while not odd(i) do i:= i shr 1; |
|
173 |
isPowerOf2:= (i = 1) |
|
174 |
end; |
|
175 |
||
176 |
function toPowerOf2(i: Longword): Longword; |
|
177 |
begin |
|
178 |
toPowerOf2:= 1; |
|
179 |
while (toPowerOf2 < i) do toPowerOf2:= toPowerOf2 shl 1 |
|
180 |
end; |
|
181 |
||
182 |
||
183 |
function DecodeBase64(s: shortstring): shortstring; |
|
184 |
const table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; |
|
185 |
var i, t, c: Longword; |
|
186 |
begin |
|
187 |
c:= 0; |
|
188 |
for i:= 1 to Length(s) do |
|
189 |
begin |
|
190 |
t:= Pos(s[i], table); |
|
191 |
if s[i] = '=' then inc(c); |
|
192 |
if t > 0 then byte(s[i]):= t - 1 else byte(s[i]):= 0 |
|
193 |
end; |
|
194 |
||
195 |
i:= 1; |
|
196 |
t:= 1; |
|
197 |
while i <= length(s) do |
|
198 |
begin |
|
199 |
DecodeBase64[t ]:= char((byte(s[i ]) shl 2) or (byte(s[i + 1]) shr 4)); |
|
200 |
DecodeBase64[t + 1]:= char((byte(s[i + 1]) shl 4) or (byte(s[i + 2]) shr 2)); |
|
201 |
DecodeBase64[t + 2]:= char((byte(s[i + 2]) shl 6) or (byte(s[i + 3]) )); |
|
202 |
inc(t, 3); |
|
203 |
inc(i, 4) |
|
204 |
end; |
|
205 |
||
206 |
if c < 3 then t:= t - c; |
|
207 |
||
208 |
byte(DecodeBase64[0]):= t - 1 |
|
209 |
end; |
|
210 |
||
211 |
||
212 |
function Str2PChar(const s: shortstring): PChar; |
|
213 |
const CharArray: array[byte] of Char = ''; |
|
214 |
begin |
|
215 |
CharArray:= s; |
|
216 |
CharArray[Length(s)]:= #0; |
|
217 |
Str2PChar:= @CharArray |
|
218 |
end; |
|
219 |
||
220 |
||
221 |
function endian(independent: LongWord): LongWord; inline; |
|
222 |
begin |
|
223 |
{$IFDEF ENDIAN_LITTLE} |
|
224 |
endian:= independent; |
|
225 |
{$ELSE} |
|
226 |
endian:= (((independent and $FF000000) shr 24) or |
|
227 |
((independent and $00FF0000) shr 8) or |
|
228 |
((independent and $0000FF00) shl 8) or |
|
229 |
((independent and $000000FF) shl 24)) |
|
230 |
{$ENDIF} |
|
231 |
end; |
|
232 |
||
233 |
||
234 |
{$IFDEF DEBUGFILE} |
|
235 |
procedure AddFileLog(s: shortstring); |
|
236 |
begin |
|
237 |
writeln(f, GameTicks: 6, ': ', s); |
|
238 |
flush(f) |
|
239 |
end; |
|
240 |
{$ENDIF} |
|
241 |
||
242 |
||
4380 | 243 |
function CheckCJKFont(s: ansistring; font: THWFont): THWFont; |
244 |
var l, i : LongInt; |
|
245 |
u: WideChar; |
|
246 |
tmpstr: array[0..256] of WideChar; |
|
247 |
begin |
|
248 |
||
249 |
{$IFNDEF IPHONEOS} |
|
250 |
// remove chinese fonts for now |
|
251 |
if (font >= CJKfnt16) or (length(s) = 0) then |
|
252 |
{$ENDIF} |
|
253 |
exit(font); |
|
254 |
||
255 |
l:= Utf8ToUnicode(@tmpstr, Str2PChar(s), length(s))-1; |
|
256 |
i:= 0; |
|
257 |
while i < l do |
|
258 |
begin |
|
259 |
u:= tmpstr[i]; |
|
260 |
if (#$2E80 <= u) and ( |
|
261 |
(u <= #$2FDF ) or // CJK Radicals Supplement / Kangxi Radicals |
|
262 |
((#$2FF0 <= u) and (u <= #$303F)) or // Ideographic Description Characters / CJK Radicals Supplement |
|
263 |
((#$31C0 <= u) and (u <= #$31EF)) or // CJK Strokes |
|
264 |
((#$3200 <= u) and (u <= #$4DBF)) or // Enclosed CJK Letters and Months / CJK Compatibility / CJK Unified Ideographs Extension A |
|
265 |
((#$4E00 <= u) and (u <= #$9FFF)) or // CJK Unified Ideographs |
|
266 |
((#$F900 <= u) and (u <= #$FAFF)) or // CJK Compatibility Ideographs |
|
267 |
((#$FE30 <= u) and (u <= #$FE4F))) // CJK Compatibility Forms |
|
268 |
then exit(THWFont( ord(font) + ((ord(High(THWFont))+1) div 2) )); |
|
269 |
inc(i) |
|
270 |
end; |
|
271 |
exit(font); |
|
272 |
(* two more to check. pascal WideChar is only 16 bit though |
|
273 |
((#$20000 <= u) and (u >= #$2A6DF)) or // CJK Unified Ideographs Extension B |
|
274 |
((#$2F800 <= u) and (u >= #$2FA1F))) // CJK Compatibility Ideographs Supplement *) |
|
275 |
end; |
|
276 |
||
4385 | 277 |
|
278 |
function GetLaunchX(at: TAmmoType; dir: LongInt; angle: LongInt): LongInt; |
|
279 |
begin |
|
4665
fa7ad5f3725f
Make basic training solvable again. Freeze RNG at current version for less of this kind of issue in future, and a bit more savable of seeds. Disable offsets in preparation for release.
nemo
parents:
4453
diff
changeset
|
280 |
GetLaunchX:= 0 |
fa7ad5f3725f
Make basic training solvable again. Freeze RNG at current version for less of this kind of issue in future, and a bit more savable of seeds. Disable offsets in preparation for release.
nemo
parents:
4453
diff
changeset
|
281 |
(* |
4385 | 282 |
if (Ammoz[at].ejectX <> 0) or (Ammoz[at].ejectY <> 0) then |
283 |
GetLaunchX:= sign(dir) * (8 + hwRound(AngleSin(angle) * Ammoz[at].ejectX) + hwRound(AngleCos(angle) * Ammoz[at].ejectY)) |
|
284 |
else |
|
4665
fa7ad5f3725f
Make basic training solvable again. Freeze RNG at current version for less of this kind of issue in future, and a bit more savable of seeds. Disable offsets in preparation for release.
nemo
parents:
4453
diff
changeset
|
285 |
GetLaunchX:= 0 *) |
4385 | 286 |
end; |
287 |
||
288 |
function GetLaunchY(at: TAmmoType; angle: LongInt): LongInt; |
|
289 |
begin |
|
4665
fa7ad5f3725f
Make basic training solvable again. Freeze RNG at current version for less of this kind of issue in future, and a bit more savable of seeds. Disable offsets in preparation for release.
nemo
parents:
4453
diff
changeset
|
290 |
GetLaunchY:= 0 |
fa7ad5f3725f
Make basic training solvable again. Freeze RNG at current version for less of this kind of issue in future, and a bit more savable of seeds. Disable offsets in preparation for release.
nemo
parents:
4453
diff
changeset
|
291 |
(* |
4385 | 292 |
if (Ammoz[at].ejectX <> 0) or (Ammoz[at].ejectY <> 0) then |
293 |
GetLaunchY:= hwRound(AngleSin(angle) * Ammoz[at].ejectY) - hwRound(AngleCos(angle) * Ammoz[at].ejectX) - 2 |
|
294 |
else |
|
4665
fa7ad5f3725f
Make basic training solvable again. Freeze RNG at current version for less of this kind of issue in future, and a bit more savable of seeds. Disable offsets in preparation for release.
nemo
parents:
4453
diff
changeset
|
295 |
GetLaunchY:= 0*) |
4385 | 296 |
end; |
297 |
||
4398
36d7e4b6ca81
Move some command handlers out of uCommands into more appropriate places, thus removing some dependencies. Ideally uCommands shouldn't depend on anything (except for uTypes and uConsts probably)
unc0rr
parents:
4385
diff
changeset
|
298 |
function CheckNoTeamOrHH: boolean; |
36d7e4b6ca81
Move some command handlers out of uCommands into more appropriate places, thus removing some dependencies. Ideally uCommands shouldn't depend on anything (except for uTypes and uConsts probably)
unc0rr
parents:
4385
diff
changeset
|
299 |
begin |
36d7e4b6ca81
Move some command handlers out of uCommands into more appropriate places, thus removing some dependencies. Ideally uCommands shouldn't depend on anything (except for uTypes and uConsts probably)
unc0rr
parents:
4385
diff
changeset
|
300 |
CheckNoTeamOrHH:= (CurrentTeam = nil) or (CurrentHedgehog^.Gear = nil); |
36d7e4b6ca81
Move some command handlers out of uCommands into more appropriate places, thus removing some dependencies. Ideally uCommands shouldn't depend on anything (except for uTypes and uConsts probably)
unc0rr
parents:
4385
diff
changeset
|
301 |
end; |
4385 | 302 |
|
4374 | 303 |
procedure initModule; |
304 |
{$IFDEF DEBUGFILE}{$IFNDEF IPHONEOS}var i: LongInt;{$ENDIF}{$ENDIF} |
|
305 |
begin |
|
306 |
{$IFDEF DEBUGFILE} |
|
307 |
{$I-} |
|
308 |
{$IFDEF IPHONEOS} |
|
309 |
Assign(f,'../Documents/hw-' + cLogfileBase + '.log'); |
|
310 |
Rewrite(f); |
|
311 |
{$ELSE} |
|
312 |
if (ParamStr(1) <> '') and (ParamStr(2) <> '') then |
|
313 |
if (ParamCount <> 3) and (ParamCount <> cDefaultParamNum) then |
|
314 |
begin |
|
315 |
for i:= 0 to 7 do |
|
316 |
begin |
|
317 |
assign(f, ExtractFileDir(ParamStr(2)) + '/' + cLogfileBase + inttostr(i) + '.log'); |
|
318 |
rewrite(f); |
|
319 |
if IOResult = 0 then break; |
|
320 |
end; |
|
321 |
if IOResult <> 0 then f:= stderr; // if everything fails, write to stderr |
|
322 |
end |
|
323 |
else |
|
324 |
begin |
|
325 |
for i:= 0 to 7 do |
|
326 |
begin |
|
327 |
assign(f, ParamStr(1) + '/Logs/' + cLogfileBase + inttostr(i) + '.log'); |
|
328 |
rewrite(f); |
|
329 |
if IOResult = 0 then break; |
|
330 |
end; |
|
331 |
if IOResult <> 0 then f:= stderr; // if everything fails, write to stderr |
|
332 |
end |
|
333 |
else |
|
334 |
f:= stderr; |
|
335 |
{$ENDIF} |
|
336 |
{$I+} |
|
337 |
{$ENDIF} |
|
338 |
||
339 |
end; |
|
340 |
||
341 |
procedure freeModule; |
|
342 |
begin |
|
343 |
recordFileName:= ''; |
|
344 |
||
345 |
{$IFDEF DEBUGFILE} |
|
346 |
writeln(f, 'halt at ', GameTicks, ' ticks. TurnTimeLeft = ', TurnTimeLeft); |
|
347 |
flush(f); |
|
348 |
close(f); |
|
349 |
{$ENDIF} |
|
350 |
end; |
|
351 |
||
4453 | 352 |
end. |