Rev 19 | Rev 22 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 19 | Rev 21 | ||
---|---|---|---|
1 | unit LevelFunctions; |
1 | unit LevelFunctions; |
2 | 2 | ||
3 | interface |
3 | interface |
4 | 4 | ||
5 | uses |
5 | uses |
6 | SysUtils, Dialogs, Functions, ExtCtrls, Graphics, Classes, Math; |
6 | SysUtils, Dialogs, Functions, ExtCtrls, Classes, Math; |
7 | 7 | ||
8 | type |
8 | type |
9 | TFieldType = (ftUndefined, ftFullSpace, ftEmpty, ftRed, ftYellow, ftGreen); |
9 | TFieldType = (ftUndefined, ftFullSpace, ftEmpty, ftRed, ftYellow, ftGreen); |
10 | 10 | ||
11 | TFieldProperties = record |
11 | TFieldProperties = record |
12 | Typ: TFieldType; |
12 | Typ: TFieldType; |
13 | Goal: Boolean; |
13 | Goal: Boolean; |
14 | end; |
14 | end; |
15 | 15 | ||
16 | TGameMode = (gmUndefined, gmNormal, gmDiagonal); |
16 | TGameMode = (gmUndefined, gmNormal, gmDiagonal); |
17 | 17 | ||
18 | TRow = record |
18 | TRow = record |
19 | Indent: integer; |
19 | Indent: integer; |
20 | Fields: array of TFieldProperties; |
20 | Fields: array of TFieldProperties; |
21 | end; |
21 | end; |
22 | TLevelArray = array of TRow; |
22 | TLevelArray = array of TRow; |
23 | 23 | ||
24 | TLevelError = (leUndefined, leNone, leInvalidElement, leEmptyBoard, leRowInvalidLength, |
24 | TLevelError = (leUndefined, leNone, leInvalidElement, leEmptyBoard, leRowInvalidLength, |
25 | leUnsupportedVersion, leUnsupportedMode); |
25 | leUnsupportedVersion, leUnsupportedMode); |
26 | 26 | ||
27 | TLevel = class(TObject) |
27 | TLevel = class(TObject) |
28 | private |
28 | private |
29 | FStringList: TStringList; |
29 | FStringList: TStringList; |
30 | procedure Load(ABoardFile: string); |
30 | procedure Load(ABoardFile: string); |
31 | public |
31 | public |
32 | constructor Create(ABoardFile: string); |
32 | constructor Create(ABoardFile: string); |
33 | destructor Destroy; override; |
33 | destructor Destroy; override; |
34 | function LevelStringToLevelArray(ShowErrors: boolean): TLevelArray; |
34 | function LevelStringToLevelArray(ShowErrors: boolean): TLevelArray; |
35 | function CheckLevelIntegrity: TLevelError; overload; |
35 | function CheckLevelIntegrity: TLevelError; overload; |
36 | function CheckLevelIntegrity(ShowErrors: boolean): TLevelError; overload; |
36 | function CheckLevelIntegrity(ShowErrors: boolean): TLevelError; overload; |
37 | function GetGameMode: TGameMode; |
37 | function GetGameMode: TGameMode; |
38 | end; |
38 | end; |
39 | 39 | ||
- | 40 | TField = record |
|
- | 41 | FieldType: TFieldType; |
|
- | 42 | Goal: Boolean; |
|
- | 43 | Panel: TPanel; |
|
- | 44 | Stone: TImage; |
|
- | 45 | end; |
|
- | 46 | ||
- | 47 | TGoalStatus = (gsUndefined, gsNoGoal, gsMultipleStonesRemaining, gsLastStoneInGoalRed, gsLastStoneInGoalYellow, gsLastStoneInGoalGreen, gsLastStoneOutsideGoal); |
|
- | 48 | ||
- | 49 | TFieldState = (fsUndefined, fsError, fsLocked, fsAvailable, fsStone); |
|
- | 50 | ||
- | 51 | TPlayGroundMatrix = record |
|
- | 52 | Fields: array of array of TField; |
|
- | 53 | public |
|
- | 54 | function MatrixHasGoal: boolean; |
|
- | 55 | function GoalFieldType: TFieldType; |
|
- | 56 | function MatrixWorth: integer; |
|
- | 57 | procedure ClearMatrix(FreeVCL: boolean); |
|
- | 58 | function CloneMatrix: TPlayGroundMatrix; |
|
40 | procedure DrawLevelPreview(Level: TLevel; Image: TImage; BackgroundColor: TColor); |
59 | function FieldState(t: TFieldType): TFieldState; overload; |
- | 60 | function FieldState(f: TField): TFieldState; overload; |
|
- | 61 | function FieldState(x, y: integer): TFieldState; overload; |
|
- | 62 | end; |
|
- | 63 | ||
41 | function FieldTypeWorth(t: TFieldType): integer; |
64 | function FieldTypeWorth(t: TFieldType): integer; |
42 | 65 | ||
43 | implementation |
66 | implementation |
44 | 67 | ||
45 | procedure DrawLevelPreview(Level: TLevel; Image: TImage; BackgroundColor: TColor); |
- | |
46 | var |
- | |
47 | LevelArray: TLevelArray; |
- | |
48 | y, x: integer; |
- | |
49 | t: TFieldType; |
- | |
50 | indent: Integer; |
- | |
51 | const |
- | |
52 | PREVIEW_BLOCK_SIZE = 10; // Enthält Field und Abstand |
68 | function FieldTypeWorth(t: TFieldType): integer; |
53 | PREVIEW_TAB_SIZE = PREVIEW_BLOCK_SIZE div 2; // 5 |
- | |
54 | begin |
69 | begin |
- | 70 | if t = ftGreen then result := 10 |
|
- | 71 | else if t = ftYellow then result := 20 |
|
- | 72 | else if t = ftRed then result := 30 |
|
55 | LevelArray := nil; |
73 | else result := 0; |
- | 74 | end; |
|
56 | 75 | ||
57 | ClearImage(Image, BackgroundColor); |
76 | { TPlayGroundMatrix } |
58 | 77 | ||
- | 78 | function TPlayGroundMatrix.MatrixHasGoal: boolean; |
|
- | 79 | var |
|
- | 80 | i, j: integer; |
|
- | 81 | begin |
|
- | 82 | result := false; |
|
- | 83 | for i := Low(Fields) to High(Fields) do |
|
- | 84 | begin |
|
59 | LevelArray := Level.LevelStringToLevelArray(false); |
85 | for j := Low(Fields[i]) to High(Fields[i]) do |
- | 86 | begin |
|
- | 87 | result := result or Fields[i][j].Goal; |
|
- | 88 | end; |
|
- | 89 | end; |
|
- | 90 | end; |
|
60 | 91 | ||
61 | for y := Low(LevelArray) to High(LevelArray) do |
92 | function TPlayGroundMatrix.GoalFieldType: TFieldType; |
- | 93 | var |
|
- | 94 | i, j: integer; |
|
62 | begin |
95 | begin |
- | 96 | result := ftEmpty; // Damit der Compiler nicht meckert |
|
63 | for x := Low(LevelArray[y].Fields) to High(LevelArray[y].Fields) do |
97 | for i := Low(Fields) to High(Fields) do |
64 | begin |
98 | begin |
65 | t := LevelArray[y].Fields[x].Typ; |
99 | for j := Low(Fields[i]) to High(Fields[i]) do |
- | 100 | begin |
|
66 | indent := LevelArray[y].Indent; |
101 | if Fields[i][j].Goal then result := Fields[i][j].FieldType |
- | 102 | end; |
|
- | 103 | end; |
|
- | 104 | end; |
|
67 | 105 | ||
- | 106 | function TPlayGroundMatrix.MatrixWorth: integer; |
|
- | 107 | var |
|
68 | case t of |
108 | i, j: integer; |
- | 109 | begin |
|
69 | ftFullSpace: Image.Canvas.Brush.Color := BackgroundColor; |
110 | result := 0; |
70 | ftEmpty: Image.Canvas.Brush.Color := clWhite; |
111 | for i := Low(Fields) to High(Fields) do |
- | 112 | begin |
|
71 | ftGreen: Image.Canvas.Brush.Color := clLime; |
113 | for j := Low(Fields[i]) to High(Fields[i]) do |
- | 114 | begin |
|
72 | ftYellow: Image.Canvas.Brush.Color := clYellow; |
115 | Inc(result, FieldTypeWorth(Fields[i][j].FieldType)); |
73 | ftRed: Image.Canvas.Brush.Color := clRed; |
116 | end; |
- | 117 | end; |
|
74 | end; |
118 | end; |
75 | 119 | ||
- | 120 | procedure TPlayGroundMatrix.ClearMatrix(FreeVCL: boolean); |
|
- | 121 | var |
|
- | 122 | i, j: integer; |
|
- | 123 | begin |
|
76 | if LevelArray[y].Fields[x].Goal then |
124 | for i := Low(Fields) to High(Fields) do |
- | 125 | begin |
|
77 | Image.Canvas.Pen.Color := clBlack |
126 | for j := Low(Fields[i]) to High(Fields[i]) do |
- | 127 | begin |
|
- | 128 | if FreeVCL then |
|
78 | else |
129 | begin |
- | 130 | if Assigned(Fields[i][j].Stone) then Fields[i][j].Stone.Free; |
|
79 | Image.Canvas.Pen.Color := BackgroundColor; |
131 | if Assigned(Fields[i][j].Panel) then Fields[i][j].Panel.Free; |
- | 132 | end; |
|
- | 133 | end; |
|
- | 134 | SetLength(Fields[i], 0); |
|
- | 135 | end; |
|
- | 136 | SetLength(Fields, 0); |
|
- | 137 | end; |
|
80 | 138 | ||
- | 139 | function TPlayGroundMatrix.CloneMatrix: TPlayGroundMatrix; |
|
- | 140 | var |
|
- | 141 | i, j: integer; |
|
- | 142 | begin |
|
- | 143 | SetLength(result.Fields, Length(Fields)); |
|
- | 144 | for i := Low(Fields) to High(Fields) do |
|
- | 145 | begin |
|
- | 146 | SetLength(result.Fields[i], Length(Fields[i])); |
|
- | 147 | for j := Low(Fields[i]) to High(Fields[i]) do |
|
- | 148 | begin |
|
81 | Image.Canvas.Rectangle(x*PREVIEW_BLOCK_SIZE + indent*PREVIEW_TAB_SIZE, |
149 | result.Fields[i][j].FieldType := Fields[i][j].FieldType; |
82 | y*PREVIEW_BLOCK_SIZE, |
150 | result.Fields[i][j].Goal := Fields[i][j].Goal; |
83 | x*PREVIEW_BLOCK_SIZE + indent*PREVIEW_TAB_SIZE + PREVIEW_BLOCK_SIZE, |
151 | result.Fields[i][j].Panel := Fields[i][j].Panel; |
84 | y*PREVIEW_BLOCK_SIZE + PREVIEW_BLOCK_SIZE); |
152 | result.Fields[i][j].Stone := Fields[i][j].Stone; |
85 | end; |
153 | end; |
86 | end; |
154 | end; |
87 | end; |
155 | end; |
88 | 156 | ||
89 | function FieldTypeWorth(t: TFieldType): integer; |
157 | function TPlayGroundMatrix.FieldState(t: TFieldType): TFieldState; |
90 | begin |
158 | begin |
- | 159 | result := fsError; |
|
- | 160 | case t of |
|
- | 161 | ftFullSpace: result := fsLocked; |
|
- | 162 | ftEmpty: result := fsAvailable; |
|
91 | if t = ftGreen then result := 10 |
163 | ftGreen: result := fsStone; |
92 | else if t = ftYellow then result := 20 |
164 | ftYellow: result := fsStone; |
93 | else if t = ftRed then result := 30 |
165 | ftRed: result := fsStone; |
- | 166 | end; |
|
- | 167 | end; |
|
- | 168 | ||
- | 169 | function TPlayGroundMatrix.FieldState(f: TField): TFieldState; |
|
- | 170 | begin |
|
- | 171 | result := FieldState(f.FieldType); |
|
- | 172 | end; |
|
- | 173 | ||
- | 174 | function TPlayGroundMatrix.FieldState(x, y: integer): TFieldState; |
|
- | 175 | begin |
|
94 | else result := 0; |
176 | result := fsError; |
- | 177 | if (x < Low(Fields)) or (x > High(Fields)) then exit; |
|
- | 178 | if (y < Low(Fields[x])) or (y > High(Fields[x])) then exit; |
|
- | 179 | ||
- | 180 | result := FieldState(Fields[x][y]); |
|
95 | end; |
181 | end; |
96 | 182 | ||
97 | { TLevel } |
183 | { TLevel } |
98 | 184 | ||
99 | const NUM_HEADERS = 2; |
185 | const NUM_HEADERS = 2; |
100 | 186 | ||
101 | constructor TLevel.Create(ABoardFile: string); |
187 | constructor TLevel.Create(ABoardFile: string); |
102 | begin |
188 | begin |
103 | inherited Create; |
189 | inherited Create; |
104 | FStringList := TStringList.Create; |
190 | FStringList := TStringList.Create; |
105 | Load(ABoardFile); |
191 | Load(ABoardFile); |
106 | end; |
192 | end; |
107 | 193 | ||
108 | destructor TLevel.Destroy; |
194 | destructor TLevel.Destroy; |
109 | begin |
195 | begin |
110 | FreeAndNil(FStringList); |
196 | FreeAndNil(FStringList); |
111 | 197 | ||
112 | inherited; |
198 | inherited; |
113 | end; |
199 | end; |
114 | 200 | ||
115 | function TLevel.GetGameMode: TGameMode; |
201 | function TLevel.GetGameMode: TGameMode; |
116 | begin |
202 | begin |
117 | if LowerCase(FStringList.Strings[1]) = 'mode: normal' then |
203 | if LowerCase(FStringList.Strings[1]) = 'mode: normal' then |
118 | result := gmNormal |
204 | result := gmNormal |
119 | else if LowerCase(FStringList.Strings[1]) = 'mode: diagonal' then |
205 | else if LowerCase(FStringList.Strings[1]) = 'mode: diagonal' then |
120 | result := gmDiagonal |
206 | result := gmDiagonal |
121 | else |
207 | else |
122 | result := gmUndefined; |
208 | result := gmUndefined; |
123 | end; |
209 | end; |
124 | 210 | ||
125 | procedure TLevel.Load(ABoardFile: string); |
211 | procedure TLevel.Load(ABoardFile: string); |
126 | var |
212 | var |
127 | i: Integer; |
213 | i: Integer; |
128 | begin |
214 | begin |
129 | FStringList.Clear; |
215 | FStringList.Clear; |
130 | FStringList.LoadFromFile(ABoardFile); |
216 | FStringList.LoadFromFile(ABoardFile); |
131 | 217 | ||
132 | // Remove whitespaces and empty lines |
218 | // Remove whitespaces and empty lines |
133 | for i := FStringList.Count-1 downto NUM_HEADERS do |
219 | for i := FStringList.Count-1 downto NUM_HEADERS do |
134 | begin |
220 | begin |
135 | FStringList.Strings[i] := StringReplace(FStringList.Strings[i], ' ', '', [rfReplaceAll]); |
221 | FStringList.Strings[i] := StringReplace(FStringList.Strings[i], ' ', '', [rfReplaceAll]); |
136 | if FStringList.Strings[i] = '' then FStringList.Delete(i); |
222 | if FStringList.Strings[i] = '' then FStringList.Delete(i); |
137 | end; |
223 | end; |
138 | end; |
- | |
139 | - | ||
140 | function DotsAtBeginning(s: string): integer; |
- | |
141 | var |
- | |
142 | i: integer; |
- | |
143 | begin |
- | |
144 | result := 0; |
- | |
145 | for i := 1 to Length(s) do |
- | |
146 | begin |
- | |
147 | if s[i] = '.' then |
- | |
148 | Inc(result) |
- | |
149 | else |
- | |
150 | Exit; |
- | |
151 | end; |
- | |
152 | end; |
- | |
153 | - | ||
154 | function DotsAtEnd(s: string): integer; |
- | |
155 | var |
- | |
156 | i: integer; |
- | |
157 | begin |
- | |
158 | result := 0; |
- | |
159 | for i := Length(s) downto 1 do |
- | |
160 | begin |
- | |
161 | if s[i] = '.' then |
- | |
162 | Inc(result) |
- | |
163 | else |
- | |
164 | Exit; |
- | |
165 | end; |
- | |
166 | end; |
224 | end; |
167 | 225 | ||
168 | function TLevel.LevelStringToLevelArray(ShowErrors: boolean): TLevelArray; |
226 | function TLevel.LevelStringToLevelArray(ShowErrors: boolean): TLevelArray; |
169 | var |
227 | var |
170 | i: integer; |
228 | i: integer; |
171 | t: TFieldType; |
229 | t: TFieldType; |
172 | err: TLevelError; |
230 | err: TLevelError; |
173 | y: Integer; |
231 | y: Integer; |
174 | x: Integer; |
232 | x: Integer; |
175 | Line: string; |
233 | Line: string; |
176 | lch, uch: char; |
234 | lch, uch: char; |
177 | ch: char; |
235 | ch: char; |
178 | begin |
236 | begin |
179 | // Zuerst nach Fehlern suchen |
237 | // Zuerst nach Fehlern suchen |
180 | err := CheckLevelIntegrity(ShowErrors); |
238 | err := CheckLevelIntegrity(ShowErrors); |
181 | if err <> leNone then exit; |
239 | if err <> leNone then exit; |
182 | 240 | ||
183 | // Nun Matrix aufbauen |
241 | // Nun Matrix aufbauen |
184 | SetLength(result, 0); |
242 | SetLength(result, 0); |
185 | for i := NUM_HEADERS to FStringList.Count-1 do |
243 | for i := NUM_HEADERS to FStringList.Count-1 do |
186 | begin |
244 | begin |
187 | y := i - NUM_HEADERS; |
245 | y := i - NUM_HEADERS; |
188 | 246 | ||
189 | SetLength(result, Length(result)+1); // add line to matrix |
247 | SetLength(result, Length(result)+1); // add line to matrix |
190 | 248 | ||
191 | Line := FStringList.Strings[i]; |
249 | Line := FStringList.Strings[i]; |
192 | result[y].Indent := DotsAtBeginning(Line) - DotsAtEnd(Line); |
250 | result[y].Indent := DotsAtBeginning(Line) - DotsAtEnd(Line); |
193 | Line := StringReplace(Line, '.', '', [rfReplaceAll]); |
251 | Line := StringReplace(Line, '.', '', [rfReplaceAll]); |
194 | SetLength(result[y].Fields, Length(Line)); |
252 | SetLength(result[y].Fields, Length(Line)); |
195 | 253 | ||
196 | for x := 0 to Length(Line)-1 do |
254 | for x := 0 to Length(Line)-1 do |
197 | begin |
255 | begin |
198 | ch := Line[x+1]; |
256 | ch := Line[x+1]; |
199 | lch := LowerCase(ch)[1]; |
257 | lch := LowerCase(ch)[1]; |
200 | uch := UpperCase(ch)[1]; |
258 | uch := UpperCase(ch)[1]; |
201 | 259 | ||
202 | t := ftUndefined; |
260 | t := ftUndefined; |
203 | case lch of |
261 | case lch of |
204 | '*': t := ftFullSpace; |
262 | '*': t := ftFullSpace; |
205 | 'e': t := ftEmpty; |
263 | 'e': t := ftEmpty; |
206 | 'r': t := ftRed; |
264 | 'r': t := ftRed; |
207 | 'y': t := ftYellow; |
265 | 'y': t := ftYellow; |
208 | 'g': t := ftGreen; |
266 | 'g': t := ftGreen; |
209 | end; |
267 | end; |
210 | 268 | ||
211 | result[y].Fields[x].Typ := t; |
269 | result[y].Fields[x].Typ := t; |
212 | result[y].Fields[x].Goal := (ch = uch) and (ch <> lch); |
270 | result[y].Fields[x].Goal := (ch = uch) and (ch <> lch); |
213 | end; |
271 | end; |
214 | end; |
272 | end; |
215 | end; |
273 | end; |
216 | 274 | ||
217 | function TLevel.CheckLevelIntegrity(ShowErrors: boolean): TLevelError; |
275 | function TLevel.CheckLevelIntegrity(ShowErrors: boolean): TLevelError; |
218 | resourcestring |
276 | resourcestring |
219 | 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 *.'; |
277 | 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 *.'; |
220 | LNG_LVL_UNSUPPORTED_VERSION = 'Level format invalid: Version not supported.'; |
278 | LNG_LVL_UNSUPPORTED_VERSION = 'Level format invalid: Version not supported.'; |
221 | LNG_LVL_UNSUPPORTED_MODE = 'Level format invalid: Mode not supported.'; |
279 | LNG_LVL_UNSUPPORTED_MODE = 'Level format invalid: Mode not supported.'; |
222 | LNG_LVL_EMPTY_BOARD = 'Level invalid: Board is empty.'; |
280 | LNG_LVL_EMPTY_BOARD = 'Level invalid: Board is empty.'; |
223 | LNG_LVL_INVALID_LENGTH = 'Level invalid: Lines don''t have an equal amount of elements.'; |
281 | LNG_LVL_INVALID_LENGTH = 'Level invalid: Lines don''t have an equal amount of elements.'; |
224 | begin |
282 | begin |
225 | result := CheckLevelIntegrity; |
283 | result := CheckLevelIntegrity; |
226 | if ShowErrors then |
284 | if ShowErrors then |
227 | begin |
285 | begin |
228 | case result of |
286 | case result of |
229 | leNone: ; |
287 | leNone: ; |
230 | leInvalidElement: MessageDlg(LNG_LVL_INVALID_ELEMENT, mtError, [mbOk], 0); |
288 | leInvalidElement: MessageDlg(LNG_LVL_INVALID_ELEMENT, mtError, [mbOk], 0); |
231 | leUnsupportedVersion: MessageDlg(LNG_LVL_UNSUPPORTED_VERSION, mtError, [mbOk], 0); |
289 | leUnsupportedVersion: MessageDlg(LNG_LVL_UNSUPPORTED_VERSION, mtError, [mbOk], 0); |
232 | leUnsupportedMode: MessageDlg(LNG_LVL_UNSUPPORTED_MODE, mtError, [mbOk], 0); |
290 | leUnsupportedMode: MessageDlg(LNG_LVL_UNSUPPORTED_MODE, mtError, [mbOk], 0); |
233 | leEmptyBoard: MessageDlg(LNG_LVL_EMPTY_BOARD, mtError, [mbOk], 0); |
291 | leEmptyBoard: MessageDlg(LNG_LVL_EMPTY_BOARD, mtError, [mbOk], 0); |
234 | leRowInvalidLength: MessageDlg(LNG_LVL_INVALID_LENGTH, mtError, [mbOk], 0); |
292 | leRowInvalidLength: MessageDlg(LNG_LVL_INVALID_LENGTH, mtError, [mbOk], 0); |
235 | end; |
293 | end; |
236 | end; |
294 | end; |
237 | end; |
295 | end; |
238 | 296 | ||
239 | function TLevel.CheckLevelIntegrity: TLevelError; |
297 | function TLevel.CheckLevelIntegrity: TLevelError; |
240 | var |
298 | var |
241 | tmp: string; |
299 | tmp: string; |
242 | i: Integer; |
300 | i: Integer; |
243 | Line: string; |
301 | Line: string; |
244 | firstLine: string; |
302 | firstLine: string; |
245 | thisLine: string; |
303 | thisLine: string; |
246 | begin |
304 | begin |
247 | result := leNone; |
305 | result := leNone; |
248 | 306 | ||
249 | // Check 1: Ist der Header OK? |
307 | // Check 1: Ist der Header OK? |
250 | 308 | ||
251 | if LowerCase(FStringList.Strings[0]) <> 'version 2' then |
309 | if LowerCase(FStringList.Strings[0]) <> 'version 2' then |
252 | begin |
310 | begin |
253 | result := leUnsupportedVersion; |
311 | result := leUnsupportedVersion; |
254 | exit; |
312 | exit; |
255 | end; |
313 | end; |
256 | 314 | ||
257 | if ((LowerCase(FStringList.Strings[1]) <> 'mode: normal') and (LowerCase(FStringList.Strings[1]) <> 'mode: diagonal')) then |
315 | if ((LowerCase(FStringList.Strings[1]) <> 'mode: normal') and (LowerCase(FStringList.Strings[1]) <> 'mode: diagonal')) then |
258 | begin |
316 | begin |
259 | result := leUnsupportedMode; |
317 | result := leUnsupportedMode; |
260 | exit; |
318 | exit; |
261 | end; |
319 | end; |
262 | 320 | ||
263 | // Check 2: Ist das Brett leer? |
321 | // Check 2: Ist das Brett leer? |
264 | 322 | ||
265 | tmp := ''; |
323 | tmp := ''; |
266 | for i := NUM_HEADERS to FStringList.Count-1 do tmp := tmp + FStringList.Strings[i]; |
324 | for i := NUM_HEADERS to FStringList.Count-1 do tmp := tmp + FStringList.Strings[i]; |
267 | if Trim(StringReplace(tmp, '.', '', [rfReplaceAll])) = '' then |
325 | if Trim(StringReplace(tmp, '.', '', [rfReplaceAll])) = '' then |
268 | begin |
326 | begin |
269 | result := leEmptyBoard; |
327 | result := leEmptyBoard; |
270 | exit; |
328 | exit; |
271 | end; |
329 | end; |
272 | 330 | ||
273 | // Check 3: Geht das Level nicht in einem Quadrat oder Rechteck auf? |
331 | // Check 3: Geht das Level nicht in einem Quadrat oder Rechteck auf? |
274 | 332 | ||
275 | firstLine := StringReplace(FStringList.Strings[NUM_HEADERS], '.', '', [rfReplaceAll]); |
333 | firstLine := StringReplace(FStringList.Strings[NUM_HEADERS], '.', '', [rfReplaceAll]); |
276 | for i := NUM_HEADERS to FStringList.Count-1 do |
334 | for i := NUM_HEADERS to FStringList.Count-1 do |
277 | begin |
335 | begin |
278 | thisLine := StringReplace(FStringList.Strings[i], '.', '', [rfReplaceAll]); |
336 | thisLine := StringReplace(FStringList.Strings[i], '.', '', [rfReplaceAll]); |
279 | if Length(thisLine) <> Length(firstLine) then |
337 | if Length(thisLine) <> Length(firstLine) then |
280 | begin |
338 | begin |
281 | result := leRowInvalidLength; // at row y-NUM_HEADERS |
339 | result := leRowInvalidLength; // at row y-NUM_HEADERS |
282 | exit; |
340 | exit; |
283 | end; |
341 | end; |
284 | end; |
342 | end; |
285 | 343 | ||
286 | // Check 4: Gibt es ungültige Elemente in den Zeilen? |
344 | // Check 4: Gibt es ungültige Elemente in den Zeilen? |
287 | 345 | ||
288 | for i := NUM_HEADERS to FStringList.Count-1 do |
346 | for i := NUM_HEADERS to FStringList.Count-1 do |
289 | begin |
347 | begin |
290 | Line := FStringList.Strings[i]; |
348 | Line := FStringList.Strings[i]; |
291 | 349 | ||
292 | Line := StringReplace(Line, '.', '', [rfReplaceAll]); |
350 | Line := StringReplace(Line, '.', '', [rfReplaceAll]); |
293 | Line := StringReplace(Line, '*', '', [rfReplaceAll]); |
351 | Line := StringReplace(Line, '*', '', [rfReplaceAll]); |
294 | Line := StringReplace(Line, 'r', '', [rfReplaceAll, rfIgnoreCase]); |
352 | Line := StringReplace(Line, 'r', '', [rfReplaceAll, rfIgnoreCase]); |
295 | Line := StringReplace(Line, 'y', '', [rfReplaceAll, rfIgnoreCase]); |
353 | Line := StringReplace(Line, 'y', '', [rfReplaceAll, rfIgnoreCase]); |
296 | Line := StringReplace(Line, 'g', '', [rfReplaceAll, rfIgnoreCase]); |
354 | Line := StringReplace(Line, 'g', '', [rfReplaceAll, rfIgnoreCase]); |
297 | Line := StringReplace(Line, 'e', '', [rfReplaceAll, rfIgnoreCase]); |
355 | Line := StringReplace(Line, 'e', '', [rfReplaceAll, rfIgnoreCase]); |
298 | 356 | ||
299 | if Length(Line) > 0 then |
357 | if Length(Line) > 0 then |
300 | begin |
358 | begin |
301 | result := leInvalidElement; // at row y-NUM_HEADERS |
359 | result := leInvalidElement; // at row y-NUM_HEADERS |
302 | Exit; |
360 | Exit; |
303 | end; |
361 | end; |
304 | end; |
362 | end; |
305 | 363 | ||
306 | // Check 5: Kann im Level gesprungen werden |
364 | // Check 5: Kann im Level gesprungen werden |
307 | 365 | ||
308 | { Wird hier nicht abgeprüft, da dafür zuerst der PlayGround gebaut sein muss. |
366 | { Wird hier nicht abgeprüft, da dafür zuerst der PlayGround gebaut sein muss. |
309 | Es ist außerdem eher ein logischer Fehler, kein Fehler in der Levelstruktur! } |
367 | Es ist außerdem eher ein logischer Fehler, kein Fehler in der Levelstruktur! } |
310 | end; |
368 | end; |
311 | 369 | ||
312 | end. |
370 | end. |
313 | 371 |