Subversion Repositories jumper

Rev

Rev 25 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 daniel-mar 1
unit LevelFunctions;
2
 
3
interface
4
 
5
uses
26 daniel-mar 6
  SysUtils, Dialogs, Functions, Classes;
1 daniel-mar 7
 
8
type
25 daniel-mar 9
  TFieldType = (ftUndefined, ftFullSpace, ftEmpty, ftRed, ftYellow, ftGreen);
10
 
11
  TFieldState = (fsUndefined, fsLocked, fsAvailable, fsOccupied);
12
 
13
  TGameMode = (gmUndefined, gmNormal, gmDiagonal);
14
 
15
  TLevelError = (leUndefined, leNone, leInvalidElement, leEmptyBoard,
16
                 leRowInvalidLength, leUnsupportedVersion, leUnsupportedMode);
17
 
18
  TGoalStatus = (gsUndefined, gsNoGoal, gsMultipleStonesRemaining,
19
                 gsLastStoneInGoalRed, gsLastStoneInGoalYellow,
20
                 gsLastStoneInGoalGreen, gsLastStoneOutsideGoal);
21
 
23 daniel-mar 22
  TCoord = record
26 daniel-mar 23
    X: integer; // fields. not pixels
24
    Y: integer; // fields. not pixels
23 daniel-mar 25
  end;
26
 
21 daniel-mar 27
  TField = record
26 daniel-mar 28
    Indent: integer; // half steps
21 daniel-mar 29
    FieldType: TFieldType;
30
    Goal: Boolean;
26 daniel-mar 31
    Data: TObject; // can be used to hold VCL references. Is not cloned when calling CloneMatrix!
32
    function FieldState: TFieldState;
21 daniel-mar 33
  end;
34
 
35
  TPlayGroundMatrix = record
36
    Fields: array of array of TField;
37
  public
23 daniel-mar 38
    procedure InitFieldArray(width, height: integer);
21 daniel-mar 39
    function MatrixHasGoal: boolean;
25 daniel-mar 40
    function GoalStatus(StonesRemaining: integer): TGoalStatus;
21 daniel-mar 41
    function GoalFieldType: TFieldType;
42
    function MatrixWorth: integer;
43
    procedure ClearMatrix(FreeVCL: boolean);
44
    function CloneMatrix: TPlayGroundMatrix;
45
    function FieldState(x, y: integer): TFieldState; overload;
25 daniel-mar 46
    function FieldState(c: TCoord): TFieldState; overload;
22 daniel-mar 47
    function CanJump(SourceX, SourceY, DestX, DestY: integer; DiagonalOK: boolean): boolean; overload;
24 daniel-mar 48
    function CanJump(Source, Dest: TCoord; DiagonalOK: boolean): boolean; overload;
22 daniel-mar 49
    function CanJump(SourceX, SourceY: integer; DiagonalOK: boolean): boolean; overload;
24 daniel-mar 50
    function CanJump(Source: TCoord; DiagonalOK: boolean): boolean; overload;
22 daniel-mar 51
    function CanJump(DiagonalOK: boolean): boolean; overload;
23 daniel-mar 52
    function IndexToCoord(index: integer): TCoord;
53
    function CoordToIndex(coord: TCoord): integer; overload;
54
    function CoordToIndex(x, y: integer): integer; overload;
55
    function Width: integer;
56
    function Height: integer;
21 daniel-mar 57
  end;
58
 
24 daniel-mar 59
  TLevel = class(TObject)
60
  private
61
    FStringList: TStringList;
62
    procedure Load(ABoardFile: string);
63
    function GetGameMode: TGameMode;
64
  public
65
    constructor Create(ABoardFile: string);
66
    destructor Destroy; override;
67
    procedure FillPlaygroundMatrix(var matrix: TPlayGroundMatrix; ShowErrors: boolean);
68
    function CheckLevelIntegrity: TLevelError; overload;
69
    function CheckLevelIntegrity(ShowErrors: boolean): TLevelError; overload;
70
    property GameMode: TGameMode read GetGameMode;
71
  end;
72
 
8 daniel-mar 73
function FieldTypeWorth(t: TFieldType): integer;
1 daniel-mar 74
 
75
implementation
76
 
25 daniel-mar 77
uses
78
  Constants;
79
 
21 daniel-mar 80
function FieldTypeWorth(t: TFieldType): integer;
81
begin
25 daniel-mar 82
  if      t = ftGreen  then result := WORTH_GREEN
83
  else if t = ftYellow then result := WORTH_YELLOW
84
  else if t = ftRed    then result := WORTH_RED
21 daniel-mar 85
  else result := 0;
86
end;
87
 
88
{ TPlayGroundMatrix }
89
 
90
function TPlayGroundMatrix.MatrixHasGoal: boolean;
1 daniel-mar 91
var
22 daniel-mar 92
  x, y: integer;
1 daniel-mar 93
begin
21 daniel-mar 94
  result := false;
22 daniel-mar 95
  for x := Low(Fields) to High(Fields) do
21 daniel-mar 96
  begin
22 daniel-mar 97
    for y := Low(Fields[x]) to High(Fields[x]) do
21 daniel-mar 98
    begin
23 daniel-mar 99
      result := result or Fields[x,y].Goal;
21 daniel-mar 100
    end;
101
  end;
102
end;
1 daniel-mar 103
 
25 daniel-mar 104
function TPlayGroundMatrix.GoalStatus(StonesRemaining: integer): TGoalStatus;
105
var
106
  ft: TFieldType;
107
begin
108
  if not MatrixHasGoal then
109
    result := gsNoGoal
110
  else if StonesRemaining > 1 then
111
    Result := gsMultipleStonesRemaining
112
  else
113
  begin
114
    ft := GoalFieldType;
115
    if ft = ftRed then
116
      result := gsLastStoneInGoalRed
117
    else if ft = ftYellow then
118
      result := gsLastStoneInGoalYellow
119
    else if ft = ftGreen then
120
      result := gsLastStoneInGoalGreen
121
    else
122
      result := gsUndefined;
123
  end;
124
end;
125
 
21 daniel-mar 126
function TPlayGroundMatrix.GoalFieldType: TFieldType;
127
var
22 daniel-mar 128
  x, y: integer;
21 daniel-mar 129
begin
130
  result := ftEmpty; // Damit der Compiler nicht meckert
22 daniel-mar 131
  for x := Low(Fields) to High(Fields) do
21 daniel-mar 132
  begin
22 daniel-mar 133
    for y := Low(Fields[x]) to High(Fields[x]) do
21 daniel-mar 134
    begin
23 daniel-mar 135
      if Fields[x,y].Goal then result := Fields[x,y].FieldType
21 daniel-mar 136
    end;
137
  end;
138
end;
1 daniel-mar 139
 
23 daniel-mar 140
function TPlayGroundMatrix.Height: integer;
141
begin
142
  if Length(Fields) = 0 then
143
    result := 0
144
  else
145
    result := Length(Fields[0]);
146
end;
147
 
148
function TPlayGroundMatrix.IndexToCoord(index: integer): TCoord;
149
begin
150
  result.X := index mod Width;
151
  result.Y := index div Width;
152
end;
153
 
154
procedure TPlayGroundMatrix.InitFieldArray(width, height: integer);
155
var
156
  x, y: integer;
157
begin
158
  SetLength(Fields, width, height);
159
  for x := Low(Fields) to High(Fields) do
160
  begin
161
    for y := Low(Fields[x]) to High(Fields[x]) do
162
    begin
24 daniel-mar 163
      Fields[x,y].FieldType := ftUndefined
23 daniel-mar 164
    end;
165
  end;
166
end;
167
 
21 daniel-mar 168
function TPlayGroundMatrix.MatrixWorth: integer;
169
var
22 daniel-mar 170
  x, y: integer;
21 daniel-mar 171
begin
172
  result := 0;
22 daniel-mar 173
  for x := Low(Fields) to High(Fields) do
21 daniel-mar 174
  begin
22 daniel-mar 175
    for y := Low(Fields[x]) to High(Fields[x]) do
21 daniel-mar 176
    begin
23 daniel-mar 177
      Inc(result, FieldTypeWorth(Fields[x,y].FieldType));
21 daniel-mar 178
    end;
179
  end;
180
end;
1 daniel-mar 181
 
23 daniel-mar 182
function TPlayGroundMatrix.Width: integer;
183
begin
184
  result := Length(Fields);
185
end;
186
 
24 daniel-mar 187
function TPlayGroundMatrix.CanJump(Source: TCoord;
188
  DiagonalOK: boolean): boolean;
189
begin
190
  result := CanJump(Source.X, Source.Y, DiagonalOK);
191
end;
192
 
193
function TPlayGroundMatrix.CanJump(Source, Dest: TCoord;
194
  DiagonalOK: boolean): boolean;
195
begin
196
  result := CanJump(Source.X, Source.Y, Dest.X, Dest.Y, DiagonalOK);
197
end;
198
 
21 daniel-mar 199
procedure TPlayGroundMatrix.ClearMatrix(FreeVCL: boolean);
200
var
22 daniel-mar 201
  x, y: integer;
21 daniel-mar 202
begin
24 daniel-mar 203
  if FreeVCL then
1 daniel-mar 204
  begin
24 daniel-mar 205
    for x := Low(Fields) to High(Fields) do
1 daniel-mar 206
    begin
24 daniel-mar 207
      for y := Low(Fields[x]) to High(Fields[x]) do
21 daniel-mar 208
      begin
26 daniel-mar 209
        if Assigned(Fields[x,y].Data) then Fields[x,y].Data.Free;
1 daniel-mar 210
      end;
21 daniel-mar 211
    end;
212
  end;
23 daniel-mar 213
  SetLength(Fields, 0, 0);
21 daniel-mar 214
end;
1 daniel-mar 215
 
21 daniel-mar 216
function TPlayGroundMatrix.CloneMatrix: TPlayGroundMatrix;
217
var
22 daniel-mar 218
  x, y: integer;
21 daniel-mar 219
begin
220
  SetLength(result.Fields, Length(Fields));
22 daniel-mar 221
  for x := Low(Fields) to High(Fields) do
21 daniel-mar 222
  begin
22 daniel-mar 223
    SetLength(result.Fields[x], Length(Fields[x]));
224
    for y := Low(Fields[x]) to High(Fields[x]) do
21 daniel-mar 225
    begin
23 daniel-mar 226
      result.Fields[x,y].FieldType := Fields[x,y].FieldType;
227
      result.Fields[x,y].Goal      := Fields[x,y].Goal;
26 daniel-mar 228
      result.Fields[x,y].Data      := Fields[x,y].Data;
1 daniel-mar 229
    end;
230
  end;
231
end;
232
 
23 daniel-mar 233
function TPlayGroundMatrix.CoordToIndex(x, y: integer): integer;
1 daniel-mar 234
begin
24 daniel-mar 235
  result := x + y * Width;
23 daniel-mar 236
end;
237
 
25 daniel-mar 238
function TPlayGroundMatrix.FieldState(c: TCoord): TFieldState;
239
begin
240
  result := FieldState(c.X, c.Y);
241
end;
242
 
23 daniel-mar 243
function TPlayGroundMatrix.CoordToIndex(coord: TCoord): integer;
244
begin
24 daniel-mar 245
  result := CoordToIndex(coord.X, coord.Y);
23 daniel-mar 246
end;
247
 
21 daniel-mar 248
function TPlayGroundMatrix.FieldState(x, y: integer): TFieldState;
249
begin
24 daniel-mar 250
  result := fsUndefined;
21 daniel-mar 251
  if (x < Low(Fields)) or (x > High(Fields)) then exit;
252
  if (y < Low(Fields[x])) or (y > High(Fields[x])) then exit;
253
 
26 daniel-mar 254
  result := Fields[x,y].FieldState;
21 daniel-mar 255
end;
256
 
22 daniel-mar 257
function TPlayGroundMatrix.CanJump(SourceX, SourceY, DestX, DestY: integer; DiagonalOK: boolean): boolean;
258
begin
259
  result := false;
260
 
261
  // Check 1: Ist das Zielfeld überhaupt leer?
262
  if FieldState(DestX, DestY) <> fsAvailable then exit;
263
 
264
  // Check 2: Befindet sich ein Stein zwischen Source und Destination und ist der Abstand 2?
265
  if DiagonalOK then
266
  begin
24 daniel-mar 267
    if (SourceX-2 = DestX) and (SourceY-2 = DestY) and (FieldState(SourceX-1, SourceY-1) = fsOccupied) then result := true;
268
    if (SourceX-2 = DestX) and (SourceY+2 = DestY) and (FieldState(SourceX-1, SourceY+1) = fsOccupied) then result := true;
269
    if (SourceX+2 = DestX) and (SourceY-2 = DestY) and (FieldState(SourceX+1, SourceY-1) = fsOccupied) then result := true;
270
    if (SourceX+2 = DestX) and (SourceY+2 = DestY) and (FieldState(SourceX+1, SourceY+1) = fsOccupied) then result := true;
22 daniel-mar 271
  end;
272
 
24 daniel-mar 273
  if (SourceX+2 = DestX) and (SourceY   = DestY) and (FieldState(SourceX+1, SourceY  ) = fsOccupied) then result := true;
274
  if (SourceX-2 = DestX) and (SourceY   = DestY) and (FieldState(SourceX-1, SourceY  ) = fsOccupied) then result := true;
275
  if (SourceX   = DestX) and (SourceY+2 = DestY) and (FieldState(SourceX  , SourceY+1) = fsOccupied) then result := true;
276
  if (SourceX   = DestX) and (SourceY-2 = DestY) and (FieldState(SourceX  , SourceY-1) = fsOccupied) then result := true;
22 daniel-mar 277
end;
278
 
279
function TPlayGroundMatrix.CanJump(SourceX, SourceY: integer; DiagonalOK: boolean): boolean;
280
begin
24 daniel-mar 281
  if FieldState(SourceX, SourceY) <> fsOccupied then
22 daniel-mar 282
  begin
283
    result := false;
284
    exit;
285
  end;
286
 
287
  result := true;
288
 
289
  if CanJump(SourceX, SourceY, SourceX+2, SourceY, DiagonalOK) then exit;
290
  if CanJump(SourceX, SourceY, SourceX-2, SourceY, DiagonalOK) then exit;
291
  if CanJump(SourceX, SourceY, SourceX, SourceY+2, DiagonalOK) then exit;
292
  if CanJump(SourceX, SourceY, SourceX, SourceY-2, DiagonalOK) then exit;
293
 
294
  if DiagonalOK then
295
  begin
296
    if CanJump(SourceX, SourceY, SourceX-2, SourceY-2, DiagonalOK) then exit;
297
    if CanJump(SourceX, SourceY, SourceX+2, SourceY-2, DiagonalOK) then exit;
298
    if CanJump(SourceX, SourceY, SourceX-2, SourceY+2, DiagonalOK) then exit;
299
    if CanJump(SourceX, SourceY, SourceX+2, SourceY+2, DiagonalOK) then exit;
300
  end;
301
 
302
  result := false;
303
end;
304
 
305
function TPlayGroundMatrix.CanJump(DiagonalOK: boolean): boolean;
306
var
307
  x, y: integer;
308
begin
309
  result := false;
310
  for x := Low(Fields) to High(Fields) do
311
  begin
312
    for y := Low(Fields[x]) to High(Fields[x]) do
313
    begin
314
      if CanJump(x, y, DiagonalOK) then
315
      begin
316
        result := true;
317
        break;
318
      end;
319
      if result then break;
320
    end;
321
  end;
322
end;
323
 
11 daniel-mar 324
{ TLevel }
325
 
326
const NUM_HEADERS = 2;
327
 
328
constructor TLevel.Create(ABoardFile: string);
1 daniel-mar 329
begin
11 daniel-mar 330
  inherited Create;
331
  FStringList := TStringList.Create;
332
  Load(ABoardFile);
1 daniel-mar 333
end;
334
 
11 daniel-mar 335
destructor TLevel.Destroy;
1 daniel-mar 336
begin
11 daniel-mar 337
  FreeAndNil(FStringList);
338
 
339
  inherited;
1 daniel-mar 340
end;
341
 
11 daniel-mar 342
function TLevel.GetGameMode: TGameMode;
343
begin
344
  if LowerCase(FStringList.Strings[1]) = 'mode: normal' then
345
    result := gmNormal
346
  else if LowerCase(FStringList.Strings[1]) = 'mode: diagonal' then
347
    result := gmDiagonal
348
  else
349
    result := gmUndefined;
350
end;
351
 
352
procedure TLevel.Load(ABoardFile: string);
1 daniel-mar 353
var
11 daniel-mar 354
  i: Integer;
1 daniel-mar 355
begin
11 daniel-mar 356
  FStringList.Clear;
357
  FStringList.LoadFromFile(ABoardFile);
1 daniel-mar 358
 
11 daniel-mar 359
  // Remove whitespaces and empty lines
360
  for i := FStringList.Count-1 downto NUM_HEADERS do
1 daniel-mar 361
  begin
11 daniel-mar 362
    FStringList.Strings[i] := StringReplace(FStringList.Strings[i], ' ', '', [rfReplaceAll]);
363
    if FStringList.Strings[i] = '' then FStringList.Delete(i);
1 daniel-mar 364
  end;
11 daniel-mar 365
end;
1 daniel-mar 366
 
24 daniel-mar 367
procedure TLevel.FillPlaygroundMatrix(var matrix: TPlayGroundMatrix; ShowErrors: boolean);
11 daniel-mar 368
var
369
  i: integer;
370
  t: TFieldType;
371
  err: TLevelError;
372
  y: Integer;
373
  x: Integer;
374
  Line: string;
375
  lch, uch: char;
376
  ch: char;
24 daniel-mar 377
  width: Integer;
378
  height: Integer;
379
  lineIndent: Integer;
11 daniel-mar 380
begin
381
  // Zuerst nach Fehlern suchen
382
  err := CheckLevelIntegrity(ShowErrors);
383
  if err <> leNone then exit;
384
 
24 daniel-mar 385
  // Breite feststellen
386
  if FStringList.Count > NUM_HEADERS then
387
  begin
388
    Line := FStringList.Strings[NUM_HEADERS];
389
    Line := StringReplace(Line, '.', '', [rfReplaceAll]);
390
    width := Length(Line);
391
  end
392
  else width := 0;
393
 
394
  // Höhe feststellen
395
  height := FStringList.Count - NUM_HEADERS;
396
 
11 daniel-mar 397
  // Nun Matrix aufbauen
24 daniel-mar 398
  matrix.ClearMatrix(true);
399
  matrix.InitFieldArray(width, height);
11 daniel-mar 400
  for i := NUM_HEADERS to FStringList.Count-1 do
1 daniel-mar 401
  begin
11 daniel-mar 402
    y := i - NUM_HEADERS;
1 daniel-mar 403
 
11 daniel-mar 404
    Line := FStringList.Strings[i];
24 daniel-mar 405
    lineIndent := DotsAtBeginning(Line) - DotsAtEnd(Line);
19 daniel-mar 406
    Line := StringReplace(Line, '.', '', [rfReplaceAll]);
1 daniel-mar 407
 
19 daniel-mar 408
    for x := 0 to Length(Line)-1 do
11 daniel-mar 409
    begin
19 daniel-mar 410
      ch := Line[x+1];
11 daniel-mar 411
      lch := LowerCase(ch)[1];
412
      uch := UpperCase(ch)[1];
19 daniel-mar 413
 
414
      t := ftUndefined;
11 daniel-mar 415
      case lch of
416
        '*': t := ftFullSpace;
417
        'e': t := ftEmpty;
418
        'r': t := ftRed;
419
        'y': t := ftYellow;
420
        'g': t := ftGreen;
421
      end;
1 daniel-mar 422
 
24 daniel-mar 423
      matrix.Fields[x,y].Indent := lineIndent;
424
      matrix.Fields[x,y].FieldType := t;
425
      matrix.Fields[x,y].Goal := (ch = uch) and (ch <> lch);
11 daniel-mar 426
    end;
427
  end;
428
end;
429
 
430
function TLevel.CheckLevelIntegrity(ShowErrors: boolean): TLevelError;
431
resourcestring
432
  LNG_LVL_INVALID_ELEMENT = 'Level invalid: There are invalid elements in the file.'+#13#10#13#10+'Valid elements are r/R, y/Y, g/G, e/E, . and *.';
433
  LNG_LVL_UNSUPPORTED_VERSION = 'Level format invalid: Version not supported.';
434
  LNG_LVL_UNSUPPORTED_MODE = 'Level format invalid: Mode not supported.';
435
  LNG_LVL_EMPTY_BOARD = 'Level invalid: Board is empty.';
436
  LNG_LVL_INVALID_LENGTH = 'Level invalid: Lines don''t have an equal amount of elements.';
437
begin
438
  result := CheckLevelIntegrity;
439
  if ShowErrors then
1 daniel-mar 440
  begin
11 daniel-mar 441
    case result of
442
      leNone: ;
443
      leInvalidElement: MessageDlg(LNG_LVL_INVALID_ELEMENT, mtError, [mbOk], 0);
444
      leUnsupportedVersion: MessageDlg(LNG_LVL_UNSUPPORTED_VERSION, mtError, [mbOk], 0);
445
      leUnsupportedMode: MessageDlg(LNG_LVL_UNSUPPORTED_MODE, mtError, [mbOk], 0);
446
      leEmptyBoard: MessageDlg(LNG_LVL_EMPTY_BOARD, mtError, [mbOk], 0);
447
      leRowInvalidLength: MessageDlg(LNG_LVL_INVALID_LENGTH, mtError, [mbOk], 0);
1 daniel-mar 448
    end;
449
  end;
11 daniel-mar 450
end;
1 daniel-mar 451
 
11 daniel-mar 452
function TLevel.CheckLevelIntegrity: TLevelError;
453
var
19 daniel-mar 454
  tmp: string;
11 daniel-mar 455
  i: Integer;
456
  Line: string;
19 daniel-mar 457
  firstLine: string;
458
  thisLine: string;
11 daniel-mar 459
begin
460
  result := leNone;
1 daniel-mar 461
 
11 daniel-mar 462
  // Check 1: Ist der Header OK?
1 daniel-mar 463
 
11 daniel-mar 464
  if LowerCase(FStringList.Strings[0]) <> 'version 2' then
1 daniel-mar 465
  begin
11 daniel-mar 466
    result := leUnsupportedVersion;
467
    exit;
1 daniel-mar 468
  end;
469
 
24 daniel-mar 470
  if ((LowerCase(FStringList.Strings[1]) <> 'mode: normal') and
471
      (LowerCase(FStringList.Strings[1]) <> 'mode: diagonal')) then
1 daniel-mar 472
  begin
11 daniel-mar 473
    result := leUnsupportedMode;
474
    exit;
1 daniel-mar 475
  end;
476
 
11 daniel-mar 477
  // Check 2: Ist das Brett leer?
1 daniel-mar 478
 
19 daniel-mar 479
  tmp := '';
480
  for i := NUM_HEADERS to FStringList.Count-1 do tmp := tmp + FStringList.Strings[i];
481
  if Trim(StringReplace(tmp, '.', '', [rfReplaceAll])) = '' then
1 daniel-mar 482
  begin
11 daniel-mar 483
    result := leEmptyBoard;
484
    exit;
1 daniel-mar 485
  end;
486
 
11 daniel-mar 487
  // Check 3: Geht das Level nicht in einem Quadrat oder Rechteck auf?
1 daniel-mar 488
 
19 daniel-mar 489
  firstLine := StringReplace(FStringList.Strings[NUM_HEADERS], '.', '', [rfReplaceAll]);
11 daniel-mar 490
  for i := NUM_HEADERS to FStringList.Count-1 do
1 daniel-mar 491
  begin
19 daniel-mar 492
    thisLine := StringReplace(FStringList.Strings[i], '.', '', [rfReplaceAll]);
493
    if Length(thisLine) <> Length(firstLine) then
11 daniel-mar 494
    begin
24 daniel-mar 495
      result := leRowInvalidLength; // at row y = i-NUM_HEADERS
11 daniel-mar 496
      exit;
497
    end;
1 daniel-mar 498
  end;
499
 
11 daniel-mar 500
  // Check 4: Gibt es ungültige Elemente in den Zeilen?
1 daniel-mar 501
 
11 daniel-mar 502
  for i := NUM_HEADERS to FStringList.Count-1 do
503
  begin
504
    Line := FStringList.Strings[i];
1 daniel-mar 505
 
11 daniel-mar 506
    Line := StringReplace(Line, '.', '', [rfReplaceAll]);
507
    Line := StringReplace(Line, '*', '', [rfReplaceAll]);
508
    Line := StringReplace(Line, 'r', '', [rfReplaceAll, rfIgnoreCase]);
509
    Line := StringReplace(Line, 'y', '', [rfReplaceAll, rfIgnoreCase]);
510
    Line := StringReplace(Line, 'g', '', [rfReplaceAll, rfIgnoreCase]);
511
    Line := StringReplace(Line, 'e', '', [rfReplaceAll, rfIgnoreCase]);
1 daniel-mar 512
 
11 daniel-mar 513
    if Length(Line) > 0 then
1 daniel-mar 514
    begin
24 daniel-mar 515
      result := leInvalidElement; // at row y = i-NUM_HEADERS
11 daniel-mar 516
      Exit;
1 daniel-mar 517
    end;
518
  end;
519
 
22 daniel-mar 520
  // Check 5: Kann im Level gesprungen werden?
11 daniel-mar 521
 
522
  { Wird hier nicht abgeprüft, da dafür zuerst der PlayGround gebaut sein muss.
523
    Es ist außerdem eher ein logischer Fehler, kein Fehler in der Levelstruktur! }
8 daniel-mar 524
end;
525
 
26 daniel-mar 526
{ TField }
527
 
528
function TField.FieldState: TFieldState;
529
begin
530
  result := fsUndefined;
531
  case FieldType of
532
    ftFullSpace: result := fsLocked;
533
    ftEmpty:     result := fsAvailable;
534
    ftGreen:     result := fsOccupied;
535
    ftYellow:    result := fsOccupied;
536
    ftRed:       result := fsOccupied;
537
  end;
538
end;
539
 
1 daniel-mar 540
end.