Subversion Repositories jumper

Rev

Rev 7 | Rev 9 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 7 Rev 8
1
unit Main;
1
unit Main;
2
 
2
 
3
interface
3
interface
4
 
4
 
5
uses
5
uses
6
  Windows, SysUtils, Classes, Graphics, Dialogs, StdCtrls, Menus, Controls,
6
  Windows, SysUtils, Classes, Graphics, Dialogs, StdCtrls, Menus, Controls,
7
  ComCtrls, ExtCtrls, Forms, MMSystem, LevelFunctions, Registry;
7
  ComCtrls, ExtCtrls, Forms, MMSystem, LevelFunctions, Registry;
8
 
8
 
9
type
9
type
10
  TField = record
10
  TField = record
11
    FieldType: TFieldType;
11
    FieldType: TFieldType;
12
    Goal: Boolean;
12
    Goal: Boolean;
13
    Panel: TPanel;
13
    Panel: TPanel;
14
    Stone: TImage;
14
    Stone: TImage;
15
  end;
15
  end;
16
 
16
 
-
 
17
  TGoalStatus = (gsNoGoal, gsMultipleStonesRemaining, gsLastStoneInGoalRed, gsLastStoneInGoalYellow, gsLastStoneInGoalGreen, gsLastStoneOutsideGoal);
-
 
18
 
17
  TFieldState = (fsError, fsLocked, fsAvailable, fsStone);
19
  TFieldState = (fsError, fsLocked, fsAvailable, fsStone);
18
 
20
 
19
  TPlayGroundMatrix = array of array of TField;
21
  TPlayGroundMatrix = array of array of TField;
20
 
22
 
21
  TMainForm = class(TForm)
23
  TMainForm = class(TForm)
22
    Playground: TPanel;
24
    Playground: TPanel;
23
    MainMenu: TMainMenu;
25
    MainMenu: TMainMenu;
24
    Help1: TMenuItem;
26
    Help1: TMenuItem;
25
    MExit: TMenuItem;
27
    MExit: TMenuItem;
26
    Statistics: TStatusBar;
28
    Statistics: TStatusBar;
27
    Timer: TTimer;
29
    Timer: TTimer;
28
    MNewGame: TMenuItem;
30
    MNewGame: TMenuItem;
29
    Help2: TMenuItem;
31
    Help2: TMenuItem;
30
    MAbout: TMenuItem;
32
    MAbout: TMenuItem;
31
    MHelp: TMenuItem;
33
    MHelp: TMenuItem;
32
    N5: TMenuItem;
34
    N5: TMenuItem;
33
    MJumpHistory: TMenuItem;
35
    MJumpHistory: TMenuItem;
34
    N2: TMenuItem;
36
    N2: TMenuItem;
35
    N4: TMenuItem;
37
    N4: TMenuItem;
36
    MHighScores: TMenuItem;
38
    MHighScores: TMenuItem;
37
    MRestartGame: TMenuItem;
39
    MRestartGame: TMenuItem;
38
    MSettings: TMenuItem;
40
    MSettings: TMenuItem;
39
    MEnableSound: TMenuItem;
41
    MEnableSound: TMenuItem;
40
    MPauseTime: TMenuItem;
42
    MPauseTime: TMenuItem;
41
    N1: TMenuItem;
43
    N1: TMenuItem;
42
    MUndo: TMenuItem;
44
    MUndo: TMenuItem;
43
    N3: TMenuItem;
45
    N3: TMenuItem;
44
    procedure MExitClick(Sender: TObject);
46
    procedure MExitClick(Sender: TObject);
45
    procedure TimerTimer(Sender: TObject);
47
    procedure TimerTimer(Sender: TObject);
46
    procedure MNewGameClick(Sender: TObject);
48
    procedure MNewGameClick(Sender: TObject);
47
    procedure MAboutClick(Sender: TObject);
49
    procedure MAboutClick(Sender: TObject);
48
    procedure FormShow(Sender: TObject);
50
    procedure FormShow(Sender: TObject);
49
    procedure FormCreate(Sender: TObject);
51
    procedure FormCreate(Sender: TObject);
50
    procedure FormDestroy(Sender: TObject);
52
    procedure FormDestroy(Sender: TObject);
51
    procedure MJumpHistoryClick(Sender: TObject);
53
    procedure MJumpHistoryClick(Sender: TObject);
52
    procedure MRestartGameClick(Sender: TObject);
54
    procedure MRestartGameClick(Sender: TObject);
53
    procedure MHighScoresClick(Sender: TObject);
55
    procedure MHighScoresClick(Sender: TObject);
54
    procedure MPauseTimeClick(Sender: TObject);
56
    procedure MPauseTimeClick(Sender: TObject);
55
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
57
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
56
    procedure MHelpClick(Sender: TObject);
58
    procedure MHelpClick(Sender: TObject);
57
    procedure MEnableSoundClick(Sender: TObject);
59
    procedure MEnableSoundClick(Sender: TObject);
58
    procedure MUndoClick(Sender: TObject);
60
    procedure MUndoClick(Sender: TObject);
59
  private
61
  private
60
    CountedSeconds: Integer;
62
    CountedSeconds: Integer;
61
    LevelFile: String;
63
    LevelFile: String;
62
    LookupFieldCoordinateArray: array of TPoint;
64
    LookupFieldCoordinateArray: array of TPoint;
63
    OriginalPlayGroundMatrix: TPlayGroundMatrix;
65
    OriginalPlayGroundMatrix: TPlayGroundMatrix;
64
    PrevPlaygroundMatrixes: array of TPlayGroundMatrix;
66
    PrevPlaygroundMatrixes: array of TPlayGroundMatrix;
65
    PlaygroundMatrix: TPlayGroundMatrix;
67
    PlaygroundMatrix: TPlayGroundMatrix;
66
    Points: Integer;
68
    Points: Integer;
67
    LevelTotalStones: Integer;
69
    LevelTotalStones: Integer;
68
    LevelRemovedStones: Integer;
70
    LevelRemovedStones: Integer;
69
    JumpHistory: TStringList;
71
    JumpHistory: TStringList;
70
    procedure LoadSettings;
72
    procedure LoadSettings;
71
    procedure SaveSettings;
73
    procedure SaveSettings;
72
    procedure RestartLevel;
74
    procedure RestartLevel;
73
    procedure SetNewPlayGroundMatrix(Matrix: TPlayGroundMatrix);
75
    procedure SetNewPlayGroundMatrix(Matrix: TPlayGroundMatrix);
74
    procedure RedrawStonesFromMatrix(Matrix: TPlayGroundMatrix);
76
    procedure RedrawStonesFromMatrix(Matrix: TPlayGroundMatrix);
75
    function AskForLevel: String;
77
    function AskForLevel: String;
76
    function AreJumpsPossible: boolean;
78
    function AreJumpsPossible: boolean;
77
    procedure StoneDraggingAllow(Stone: TImage; Allow: boolean);
79
    procedure StoneDraggingAllow(Stone: TImage; Allow: boolean);
78
    procedure NewGame(Filename: string);
80
    procedure NewGame(Filename: string);
79
    function LevelTime: String;
81
    function LevelTime: String;
80
    procedure DestroyLevel;
82
    procedure DestroyLevel;
81
    procedure RefreshTime;
83
    procedure RefreshTime;
82
    procedure RefreshPoints;
84
    procedure RefreshPoints;
83
    procedure RefreshStonesRemoved;
85
    procedure RefreshStonesRemoved;
84
    procedure CountPoints(t: TFieldType);
86
    procedure CountPoints(t: TFieldType);
85
    procedure RemoveStone(x, y: integer; count_points: boolean);
87
    procedure RemoveStone(x, y: integer; count_points: boolean);
86
    procedure DoJump(SourceTag, DestTag: integer);
88
    procedure DoJump(SourceTag, DestTag: integer);
87
    function CanJump(x, y: integer): boolean;
89
    function CanJump(x, y: integer): boolean;
88
    function MayJump(SourceX, SourceY, DestX, DestY: integer): boolean; overload;
90
    function MayJump(SourceX, SourceY, DestX, DestY: integer): boolean; overload;
89
    function MayJump(SourceTag, DestTag: integer): boolean; overload;
91
    function MayJump(SourceTag, DestTag: integer): boolean; overload;
90
    procedure StoneDragOver(Sender, Source: TObject; X,
92
    procedure StoneDragOver(Sender, Source: TObject; X,
91
      Y: Integer; State: TDragState; var Accept: Boolean);
93
      Y: Integer; State: TDragState; var Accept: Boolean);
92
    procedure StoneDragDrop(Sender, Source: TObject; X, Y: Integer);
94
    procedure StoneDragDrop(Sender, Source: TObject; X, Y: Integer);
93
    procedure DrawField(x, y: integer; t: TFieldProperties; halftabs: integer);
95
    procedure DrawField(x, y: integer; t: TFieldProperties; halftabs: integer);
94
    function DrawStone(fieldtype: TFieldType; panel: TPanel): TImage;
96
    function DrawStone(fieldtype: TFieldType; panel: TPanel): TImage;
95
    function DrawStoneBox(x, y, tag, halftabs: integer; isGoal: boolean): TPanel;
97
    function DrawStoneBox(x, y, tag, halftabs: integer; isGoal: boolean): TPanel;
96
    procedure BuildPlayground(LevelArray: TLevelArray);
98
    procedure BuildPlayground(LevelArray: TLevelArray);
97
    function FieldState(t: TFieldType): TFieldState; overload;
99
    function FieldState(t: TFieldType): TFieldState; overload;
98
    function FieldState(f: TField): TFieldState; overload;
100
    function FieldState(f: TField): TFieldState; overload;
99
    function FieldState(x, y: integer): TFieldState; overload;
101
    function FieldState(x, y: integer): TFieldState; overload;
100
    procedure ClearMatrix(Matrix: TPlayGroundMatrix; FreeVCL: boolean);
102
    procedure ClearMatrix(Matrix: TPlayGroundMatrix; FreeVCL: boolean);
101
    function CloneMatrix(Source: TPlayGroundMatrix): TPlayGroundMatrix;
103
    function CloneMatrix(Source: TPlayGroundMatrix): TPlayGroundMatrix;
-
 
104
    function MatrixHasGoal(Matrix: TPlayGroundMatrix): boolean;
102
    procedure LoadPictureForType(FieldType: TFieldType; Picture: TPicture);
105
    procedure LoadPictureForType(FieldType: TFieldType; Picture: TPicture);
103
    function MatrixWorth(Matrix: TPlayGroundMatrix): integer;
106
    function MatrixWorth(Matrix: TPlayGroundMatrix): integer;
-
 
107
    function GoalStatus: TGoalStatus;
104
    function FieldTypeWorth(t: TFieldType): integer;
108
    function GoalFieldType(Matrix: TPlayGroundMatrix): TFieldType;
105
  end;
109
  end;
106
 
110
 
107
var
111
var
108
  MainForm: TMainForm;
112
  MainForm: TMainForm;
109
 
113
 
110
implementation
114
implementation
111
 
115
 
112
uses
116
uses
113
  About, Finish, Choice, Functions, History, HighScore, Help, Constants;
117
  About, Finish, Choice, Functions, History, HighScore, Help, Constants;
114
 
118
 
115
{$R *.dfm}
119
{$R *.dfm}
116
 
120
 
-
 
121
function TMainForm.MatrixHasGoal(Matrix: TPlayGroundMatrix): boolean;
-
 
122
var
-
 
123
  i, j: integer;
-
 
124
begin
-
 
125
  result := false;
-
 
126
  for i := Low(Matrix) to High(Matrix) do
-
 
127
  begin
-
 
128
    for j := Low(Matrix[i]) to High(Matrix[i]) do
-
 
129
    begin
-
 
130
      result := result or Matrix[i][j].Goal;
-
 
131
    end;
-
 
132
  end;
-
 
133
end;
-
 
134
 
-
 
135
function TMainForm.GoalFieldType(Matrix: TPlayGroundMatrix): TFieldType;
-
 
136
var
-
 
137
  i, j: integer;
-
 
138
begin
-
 
139
  for i := Low(Matrix) to High(Matrix) do
-
 
140
  begin
-
 
141
    for j := Low(Matrix[i]) to High(Matrix[i]) do
-
 
142
    begin
-
 
143
      if Matrix[i][j].Goal then result := Matrix[i][j].FieldType
-
 
144
    end;
-
 
145
  end;
-
 
146
end;
-
 
147
 
117
function TMainForm.MatrixWorth(Matrix: TPlayGroundMatrix): integer;
148
function TMainForm.MatrixWorth(Matrix: TPlayGroundMatrix): integer;
118
var
149
var
119
  i, j: integer;
150
  i, j: integer;
120
begin
151
begin
121
  result := 0;
152
  result := 0;
122
  for i := Low(Matrix) to High(Matrix) do
153
  for i := Low(Matrix) to High(Matrix) do
123
  begin
154
  begin
124
    for j := Low(Matrix[i]) to High(Matrix[i]) do
155
    for j := Low(Matrix[i]) to High(Matrix[i]) do
125
    begin
156
    begin
126
      Inc(result, FieldTypeWorth(Matrix[i][j].FieldType));
157
      Inc(result, FieldTypeWorth(Matrix[i][j].FieldType));
127
    end;
158
    end;
128
  end;
159
  end;
129
end;
160
end;
130
 
161
 
131
procedure TMainForm.ClearMatrix(Matrix: TPlayGroundMatrix; FreeVCL: boolean);
162
procedure TMainForm.ClearMatrix(Matrix: TPlayGroundMatrix; FreeVCL: boolean);
132
var
163
var
133
  i, j: integer;
164
  i, j: integer;
134
begin
165
begin
135
  for i := Low(Matrix) to High(Matrix) do
166
  for i := Low(Matrix) to High(Matrix) do
136
  begin
167
  begin
137
    for j := Low(Matrix[i]) to High(Matrix[i]) do
168
    for j := Low(Matrix[i]) to High(Matrix[i]) do
138
    begin
169
    begin
139
      if FreeVCL then
170
      if FreeVCL then
140
      begin
171
      begin
141
        if Assigned(Matrix[i][j].Stone) then Matrix[i][j].Stone.Free;
172
        if Assigned(Matrix[i][j].Stone) then Matrix[i][j].Stone.Free;
142
        if Assigned(Matrix[i][j].Panel) then Matrix[i][j].Panel.Free;
173
        if Assigned(Matrix[i][j].Panel) then Matrix[i][j].Panel.Free;
143
      end;
174
      end;
144
    end;
175
    end;
145
    SetLength(Matrix[i], 0);
176
    SetLength(Matrix[i], 0);
146
  end;
177
  end;
147
  SetLength(Matrix, 0);
178
  SetLength(Matrix, 0);
148
end;
179
end;
149
 
180
 
150
procedure TMainForm.RedrawStonesFromMatrix(Matrix: TPlayGroundMatrix);
181
procedure TMainForm.RedrawStonesFromMatrix(Matrix: TPlayGroundMatrix);
151
var
182
var
152
  i, j: integer;
183
  i, j: integer;
153
begin
184
begin
154
  for i := Low(Matrix) to High(Matrix) do
185
  for i := Low(Matrix) to High(Matrix) do
155
  begin
186
  begin
156
    for j := Low(Matrix[i]) to High(Matrix[i]) do
187
    for j := Low(Matrix[i]) to High(Matrix[i]) do
157
    begin
188
    begin
158
      if Assigned(Matrix[i][j].Stone) then
189
      if Assigned(Matrix[i][j].Stone) then
159
      begin
190
      begin
160
        LoadPictureForType(Matrix[i][j].FieldType, Matrix[i][j].Stone.Picture);
191
        LoadPictureForType(Matrix[i][j].FieldType, Matrix[i][j].Stone.Picture);
161
        StoneDraggingAllow(Matrix[i][j].Stone, FieldState(Matrix[i][j].FieldType) <> fsAvailable);
192
        StoneDraggingAllow(Matrix[i][j].Stone, FieldState(Matrix[i][j].FieldType) <> fsAvailable);
162
      end;
193
      end;
163
    end;
194
    end;
164
  end;
195
  end;
165
end;
196
end;
166
 
197
 
167
procedure TMainForm.DestroyLevel;
198
procedure TMainForm.DestroyLevel;
168
var
199
var
169
  i: Integer;
200
  i: Integer;
170
begin
201
begin
171
  MPauseTime.Enabled := false;
202
  MPauseTime.Enabled := false;
172
  Timer.Enabled := false;
203
  Timer.Enabled := false;
173
 
204
 
174
  MRestartGame.Enabled := false;
205
  MRestartGame.Enabled := false;
175
 
206
 
176
  LevelFile := '';
207
  LevelFile := '';
177
 
208
 
178
  CountedSeconds := 0;
209
  CountedSeconds := 0;
179
  RefreshTime;
210
  RefreshTime;
180
 
211
 
181
  Points := 0;
212
  Points := 0;
182
  RefreshPoints;
213
  RefreshPoints;
183
 
214
 
184
  LevelRemovedStones := 0;
215
  LevelRemovedStones := 0;
185
  LevelTotalStones := 0;
216
  LevelTotalStones := 0;
186
  RefreshStonesRemoved;
217
  RefreshStonesRemoved;
187
 
218
 
188
  JumpHistory.Clear;
219
  JumpHistory.Clear;
189
 
220
 
190
  ClearMatrix(PlayGroundMatrix, true);
221
  ClearMatrix(PlayGroundMatrix, true);
191
  ClearMatrix(OriginalPlayGroundMatrix, false);
222
  ClearMatrix(OriginalPlayGroundMatrix, false);
192
  for i := 0 to Length(PrevPlaygroundMatrixes)-1 do
223
  for i := 0 to Length(PrevPlaygroundMatrixes)-1 do
193
    ClearMatrix(PrevPlaygroundMatrixes[i], false);
224
    ClearMatrix(PrevPlaygroundMatrixes[i], false);
194
  SetLength(PrevPlaygroundMatrixes, 0);
225
  SetLength(PrevPlaygroundMatrixes, 0);
195
  MUndo.Enabled := false;
226
  MUndo.Enabled := false;
196
 
227
 
197
  SetLength(LookupFieldCoordinateArray, 0);
228
  SetLength(LookupFieldCoordinateArray, 0);
198
end;
229
end;
199
 
230
 
200
procedure TMainForm.LoadPictureForType(FieldType: TFieldType; Picture: TPicture);
231
procedure TMainForm.LoadPictureForType(FieldType: TFieldType; Picture: TPicture);
201
begin
232
begin
202
  case FieldType of
233
  case FieldType of
203
    ftEmpty:  Picture.Bitmap.LoadFromResourceName(HInstance, RES_EMPTY);
234
    ftEmpty:  Picture.Bitmap.LoadFromResourceName(HInstance, RES_EMPTY);
204
    ftGreen:  Picture.Bitmap.LoadFromResourceName(HInstance, RES_GREEN);
235
    ftGreen:  Picture.Bitmap.LoadFromResourceName(HInstance, RES_GREEN);
205
    ftYellow: Picture.Bitmap.LoadFromResourceName(HInstance, RES_YELLOW);
236
    ftYellow: Picture.Bitmap.LoadFromResourceName(HInstance, RES_YELLOW);
206
    ftRed:    Picture.Bitmap.LoadFromResourceName(HInstance, RES_RED);
237
    ftRed:    Picture.Bitmap.LoadFromResourceName(HInstance, RES_RED);
207
  end;
238
  end;
208
end;
239
end;
209
 
240
 
210
function TMainForm.DrawStone(fieldtype: TFieldType; panel: TPanel): TImage;
241
function TMainForm.DrawStone(fieldtype: TFieldType; panel: TPanel): TImage;
211
begin
242
begin
212
  result := TImage.Create(panel);
243
  result := TImage.Create(panel);
213
  result.Parent := panel;
244
  result.Parent := panel;
214
  LoadPictureForType(fieldtype, result.Picture);
245
  LoadPictureForType(fieldtype, result.Picture);
215
  result.Width := panel.Width - 2*MET_SHAPE_MARGIN;
246
  result.Width := panel.Width - 2*MET_SHAPE_MARGIN;
216
  result.Height := panel.Height - 2*MET_SHAPE_MARGIN;
247
  result.Height := panel.Height - 2*MET_SHAPE_MARGIN;
217
  result.Left := MET_SHAPE_MARGIN;
248
  result.Left := MET_SHAPE_MARGIN;
218
  result.Top := MET_SHAPE_MARGIN;
249
  result.Top := MET_SHAPE_MARGIN;
219
  result.Center := true;
250
  result.Center := true;
220
  result.Transparent := true;
251
  result.Transparent := true;
221
 
252
 
222
  result.Tag := panel.Tag;
253
  result.Tag := panel.Tag;
223
  result.OnDragOver := panel.OnDragOver;
254
  result.OnDragOver := panel.OnDragOver;
224
  result.OnDragDrop := panel.OnDragDrop;
255
  result.OnDragDrop := panel.OnDragDrop;
225
 
256
 
226
  StoneDraggingAllow(result, FieldState(fieldtype) <> fsAvailable);
257
  StoneDraggingAllow(result, FieldState(fieldtype) <> fsAvailable);
227
end;
258
end;
228
 
259
 
229
procedure TMainForm.StoneDraggingAllow(Stone: TImage; Allow: boolean);
260
procedure TMainForm.StoneDraggingAllow(Stone: TImage; Allow: boolean);
230
begin
261
begin
231
  if Allow then
262
  if Allow then
232
  begin
263
  begin
233
    Stone.DragMode := dmAutomatic;
264
    Stone.DragMode := dmAutomatic;
234
    (Stone.Parent as TPanel).DragMode := dmAutomatic;
265
    (Stone.Parent as TPanel).DragMode := dmAutomatic;
235
  end
266
  end
236
  else
267
  else
237
  begin
268
  begin
238
    Stone.DragMode := dmManual;
269
    Stone.DragMode := dmManual;
239
    (Stone.Parent as TPanel).DragMode := dmManual;
270
    (Stone.Parent as TPanel).DragMode := dmManual;
240
  end;
271
  end;
241
end;
272
end;
242
 
273
 
243
function TMainForm.DrawStoneBox(x, y, tag, halftabs: integer; isGoal: boolean): TPanel;
274
function TMainForm.DrawStoneBox(x, y, tag, halftabs: integer; isGoal: boolean): TPanel;
244
begin
275
begin
245
  result := TPanel.Create(Playground);
276
  result := TPanel.Create(Playground);
246
  result.Parent := Playground;
277
  result.Parent := Playground;
247
  if isGoal then
278
  if isGoal then
248
  begin
279
  begin
249
    result.BevelInner := bvLowered;
280
    result.BevelInner := bvLowered;
250
  end;
281
  end;
251
  result.Color := Playground.Color;
282
  result.Color := Playground.Color;
252
  result.BevelOuter := bvLowered;
283
  result.BevelOuter := bvLowered;
253
  result.Width := MET_FIELD_SIZE;
284
  result.Width := MET_FIELD_SIZE;
254
  result.Height := MET_FIELD_SIZE;
285
  result.Height := MET_FIELD_SIZE;
255
  result.Left := x * (MET_FIELD_SIZE+MET_FIELD_SPACE) + MET_FIELD_SPACE - (halftabs*MET_HALFTAB_SIZE);
286
  result.Left := x * (MET_FIELD_SIZE+MET_FIELD_SPACE) + MET_FIELD_SPACE - (halftabs*MET_HALFTAB_SIZE);
256
  result.Top := y * (MET_FIELD_SIZE+MET_FIELD_SPACE) + MET_FIELD_SPACE;
287
  result.Top := y * (MET_FIELD_SIZE+MET_FIELD_SPACE) + MET_FIELD_SPACE;
257
 
288
 
258
  result.Tag := tag;
289
  result.Tag := tag;
259
  result.OnDragOver := StoneDragOver;
290
  result.OnDragOver := StoneDragOver;
260
  result.OnDragDrop := StoneDragDrop;
291
  result.OnDragDrop := StoneDragDrop;
261
end;
292
end;
262
 
293
 
263
procedure TMainForm.MExitClick(Sender: TObject);
294
procedure TMainForm.MExitClick(Sender: TObject);
264
begin
295
begin
265
  Close;
296
  Close;
266
end;
297
end;
267
 
298
 
268
function TMainForm.FieldState(t: TFieldType): TFieldState;
299
function TMainForm.FieldState(t: TFieldType): TFieldState;
269
begin
300
begin
270
  result := fsError;
301
  result := fsError;
271
  case t of
302
  case t of
272
    ftLocked:        result := fsLocked;
303
    ftLocked:        result := fsLocked;
273
    ftLockedWithTab: result := fsLocked;
304
    ftLockedWithTab: result := fsLocked;
274
    ftEmpty:         result := fsAvailable;
305
    ftEmpty:         result := fsAvailable;
275
    ftGreen:         result := fsStone;
306
    ftGreen:         result := fsStone;
276
    ftYellow:        result := fsStone;
307
    ftYellow:        result := fsStone;
277
    ftRed:           result := fsStone;
308
    ftRed:           result := fsStone;
278
  end;
309
  end;
279
end;
310
end;
280
 
311
 
281
function TMainForm.FieldState(f: TField): TFieldState;
312
function TMainForm.FieldState(f: TField): TFieldState;
282
begin
313
begin
283
  result := FieldState(f.FieldType);
314
  result := FieldState(f.FieldType);
284
end;
315
end;
285
 
316
 
286
function TMainForm.FieldState(x, y: integer): TFieldState;
317
function TMainForm.FieldState(x, y: integer): TFieldState;
287
begin
318
begin
288
  result := fsError;
319
  result := fsError;
289
  if (x < Low(PlayGroundMatrix)) or (x > High(PlayGroundMatrix)) then exit;
320
  if (x < Low(PlayGroundMatrix)) or (x > High(PlayGroundMatrix)) then exit;
290
  if (y < Low(PlayGroundMatrix[x])) or (y > High(PlayGroundMatrix[x])) then exit;
321
  if (y < Low(PlayGroundMatrix[x])) or (y > High(PlayGroundMatrix[x])) then exit;
291
 
322
 
292
  result := FieldState(PlayGroundMatrix[x][y]);
323
  result := FieldState(PlayGroundMatrix[x][y]);
293
end;
324
end;
294
 
325
 
295
procedure TMainForm.RefreshTime;
326
procedure TMainForm.RefreshTime;
296
begin
327
begin
297
  Statistics.Panels.Items[0].Text := Format(LNG_TIME, [LevelTime]);
328
  Statistics.Panels.Items[0].Text := Format(LNG_TIME, [LevelTime]);
298
end;
329
end;
299
 
330
 
300
procedure TMainForm.RefreshStonesRemoved;
331
procedure TMainForm.RefreshStonesRemoved;
301
begin
332
begin
302
  Statistics.Panels.Items[1].Text := Format(LNG_STONES_REMOVED, [LevelRemovedStones, LevelTotalStones]);
333
  Statistics.Panels.Items[1].Text := Format(LNG_STONES_REMOVED, [LevelRemovedStones, LevelTotalStones]);
303
end;
334
end;
304
 
335
 
305
procedure TMainForm.RefreshPoints;
336
procedure TMainForm.RefreshPoints;
306
begin
337
begin
307
  Statistics.Panels.Items[2].Text := Format(LNG_POINTS, [Points]);
338
  Statistics.Panels.Items[2].Text := Format(LNG_POINTS, [Points]);
308
end;
339
end;
309
 
340
 
310
function TMainForm.FieldTypeWorth(t: TFieldType): integer;
-
 
311
begin
-
 
312
  if t = ftGreen then result := 10
-
 
313
  else if t = ftYellow then result := 20
-
 
314
  else if t = ftRed then result := 30
-
 
315
  else result := 0;
-
 
316
end;
-
 
317
 
-
 
318
procedure TMainForm.CountPoints(t: TFieldType);
341
procedure TMainForm.CountPoints(t: TFieldType);
319
begin
342
begin
320
  inc(Points, FieldTypeWorth(t));
343
  inc(Points, FieldTypeWorth(t));
321
  RefreshPoints;
344
  RefreshPoints;
322
end;
345
end;
323
 
346
 
324
procedure TMainForm.RemoveStone(x, y: integer; count_points: boolean);
347
procedure TMainForm.RemoveStone(x, y: integer; count_points: boolean);
325
begin
348
begin
326
  if count_points then
349
  if count_points then
327
  begin
350
  begin
328
    CountPoints(PlayGroundMatrix[x, y].FieldType);
351
    CountPoints(PlayGroundMatrix[x, y].FieldType);
329
    Inc(LevelRemovedStones);
352
    Inc(LevelRemovedStones);
330
    RefreshStonesRemoved;
353
    RefreshStonesRemoved;
331
  end;
354
  end;
332
  PlayGroundMatrix[x, y].FieldType := ftEmpty;
355
  PlayGroundMatrix[x, y].FieldType := ftEmpty;
333
  LoadPictureForType(PlayGroundMatrix[x, y].FieldType, PlayGroundMatrix[x, y].Stone.Picture);
356
  LoadPictureForType(PlayGroundMatrix[x, y].FieldType, PlayGroundMatrix[x, y].Stone.Picture);
334
  StoneDraggingAllow(PlayGroundMatrix[x, y].Stone, false);
357
  StoneDraggingAllow(PlayGroundMatrix[x, y].Stone, false);
335
end;
358
end;
336
 
359
 
337
function TMainForm.CanJump(x, y: integer): boolean;
360
function TMainForm.CanJump(x, y: integer): boolean;
338
begin
361
begin
339
  if FieldState(x, y) <> fsStone then
362
  if FieldState(x, y) <> fsStone then
340
  begin
363
  begin
341
    result := false;
364
    result := false;
342
    exit;
365
    exit;
343
  end;
366
  end;
344
 
367
 
345
  result := true;
368
  result := true;
346
 
369
 
347
  if MayJump(x, y, x+2, y) then exit;
370
  if MayJump(x, y, x+2, y) then exit;
348
  if MayJump(x, y, x-2, y) then exit;
371
  if MayJump(x, y, x-2, y) then exit;
349
  if MayJump(x, y, x, y+2) then exit;
372
  if MayJump(x, y, x, y+2) then exit;
350
  if MayJump(x, y, x, y-2) then exit;
373
  if MayJump(x, y, x, y-2) then exit;
351
 
374
 
352
  if AllowDiagonalMoves then
375
  if AllowDiagonalMoves then
353
  begin
376
  begin
354
    if MayJump(x, y, x-2, y-2) then exit;
377
    if MayJump(x, y, x-2, y-2) then exit;
355
    if MayJump(x, y, x+2, y-2) then exit;
378
    if MayJump(x, y, x+2, y-2) then exit;
356
    if MayJump(x, y, x-2, y+2) then exit;
379
    if MayJump(x, y, x-2, y+2) then exit;
357
    if MayJump(x, y, x+2, y+2) then exit;
380
    if MayJump(x, y, x+2, y+2) then exit;
358
  end;
381
  end;
359
 
382
 
360
  result := false;
383
  result := false;
361
end;
384
end;
362
 
385
 
363
function TMainForm.AreJumpsPossible: boolean;
386
function TMainForm.AreJumpsPossible: boolean;
364
var
387
var
365
  i, j: integer;
388
  i, j: integer;
366
begin
389
begin
367
  result := false;
390
  result := false;
368
  for i := Low(PlayGroundMatrix) to High(PlayGroundMatrix) do
391
  for i := Low(PlayGroundMatrix) to High(PlayGroundMatrix) do
369
  begin
392
  begin
370
    for j := Low(PlayGroundMatrix[i]) to High(PlayGroundMatrix[i]) do
393
    for j := Low(PlayGroundMatrix[i]) to High(PlayGroundMatrix[i]) do
371
    begin
394
    begin
372
      if CanJump(i, j) then
395
      if CanJump(i, j) then
373
      begin
396
      begin
374
        result := true;
397
        result := true;
375
        break;
398
        break;
376
      end;
399
      end;
377
      if result then break;
400
      if result then break;
378
    end;
401
    end;
379
  end;
402
  end;
380
end;
403
end;
381
 
404
 
382
procedure TMainForm.DoJump(SourceTag, DestTag: integer);
405
procedure TMainForm.DoJump(SourceTag, DestTag: integer);
383
var
406
var
384
  d, s: TPoint;
407
  d, s: TPoint;
385
  old_fieldtype: TFieldType;
408
  old_fieldtype: TFieldType;
386
  res: Integer;
409
  res: Integer;
387
begin
410
begin
388
  if not MayJump(SourceTag, DestTag) then exit;
411
  if not MayJump(SourceTag, DestTag) then exit;
389
 
412
 
390
  d := LookupFieldCoordinateArray[DestTag];
413
  d := LookupFieldCoordinateArray[DestTag];
391
  s := LookupFieldCoordinateArray[SourceTag];
414
  s := LookupFieldCoordinateArray[SourceTag];
392
 
415
 
393
  JumpHistory.Add(Format(LNG_JUMP_LOG, [SourceTag+1, s.x+1, s.y+1, DestTag+1, d.x+1, d.y+1]));
416
  JumpHistory.Add(Format(LNG_JUMP_LOG, [SourceTag+1, s.x+1, s.y+1, DestTag+1, d.x+1, d.y+1]));
394
 
417
 
395
  {$REGION 'Stein entfernen und Punkte vergeben'}
418
  {$REGION 'Stein entfernen und Punkte vergeben'}
396
  if AllowDiagonalMoves then
419
  if AllowDiagonalMoves then
397
  begin
420
  begin
398
    if (s.X-2 = d.X) and (s.Y-2 = d.Y) and (FieldState(s.X-1, s.Y-1) = fsStone) then RemoveStone(s.X-1, s.Y-1, true);
421
    if (s.X-2 = d.X) and (s.Y-2 = d.Y) and (FieldState(s.X-1, s.Y-1) = fsStone) then RemoveStone(s.X-1, s.Y-1, true);
399
    if (s.X-2 = d.X) and (s.Y+2 = d.Y) and (FieldState(s.X-1, s.Y+1) = fsStone) then RemoveStone(s.X-1, s.Y+1, true);
422
    if (s.X-2 = d.X) and (s.Y+2 = d.Y) and (FieldState(s.X-1, s.Y+1) = fsStone) then RemoveStone(s.X-1, s.Y+1, true);
400
    if (s.X+2 = d.X) and (s.Y-2 = d.Y) and (FieldState(s.X+1, s.Y-1) = fsStone) then RemoveStone(s.X+1, s.Y-1, true);
423
    if (s.X+2 = d.X) and (s.Y-2 = d.Y) and (FieldState(s.X+1, s.Y-1) = fsStone) then RemoveStone(s.X+1, s.Y-1, true);
401
    if (s.X+2 = d.X) and (s.Y+2 = d.Y) and (FieldState(s.X+1, s.Y+1) = fsStone) then RemoveStone(s.X+1, s.Y+1, true);
424
    if (s.X+2 = d.X) and (s.Y+2 = d.Y) and (FieldState(s.X+1, s.Y+1) = fsStone) then RemoveStone(s.X+1, s.Y+1, true);
402
  end;
425
  end;
403
 
426
 
404
  if (s.X+2 = d.X) and (s.Y = d.Y) and (FieldState(s.X+1, s.Y  ) = fsStone) then RemoveStone(s.X+1, s.Y, true);
427
  if (s.X+2 = d.X) and (s.Y = d.Y) and (FieldState(s.X+1, s.Y  ) = fsStone) then RemoveStone(s.X+1, s.Y, true);
405
  if (s.X-2 = d.X) and (s.Y = d.Y) and (FieldState(s.X-1, s.Y  ) = fsStone) then RemoveStone(s.X-1, s.Y, true);
428
  if (s.X-2 = d.X) and (s.Y = d.Y) and (FieldState(s.X-1, s.Y  ) = fsStone) then RemoveStone(s.X-1, s.Y, true);
406
  if (s.X = d.X) and (s.Y+2 = d.Y) and (FieldState(s.X  , s.Y+1) = fsStone) then RemoveStone(s.X, s.Y+1, true);
429
  if (s.X = d.X) and (s.Y+2 = d.Y) and (FieldState(s.X  , s.Y+1) = fsStone) then RemoveStone(s.X, s.Y+1, true);
407
  if (s.X = d.X) and (s.Y-2 = d.Y) and (FieldState(s.X  , s.Y-1) = fsStone) then RemoveStone(s.X, s.Y-1, true);
430
  if (s.X = d.X) and (s.Y-2 = d.Y) and (FieldState(s.X  , s.Y-1) = fsStone) then RemoveStone(s.X, s.Y-1, true);
408
  {$ENDREGION}
431
  {$ENDREGION}
409
 
432
 
410
  // Den Timer erst nach dem ersten Zug starten
433
  // Den Timer erst nach dem ersten Zug starten
411
  // oder nach einer Pause neustarten
434
  // oder nach einer Pause neustarten
412
  if not Timer.Enabled then
435
  if not Timer.Enabled then
413
  begin
436
  begin
414
    MPauseTime.Enabled := true;
437
    MPauseTime.Enabled := true;
415
    Timer.Enabled := true;
438
    Timer.Enabled := true;
416
  end;
439
  end;
417
 
440
 
418
  MRestartGame.Enabled := true;
441
  MRestartGame.Enabled := true;
419
 
442
 
420
  // Sound abspielen
443
  // Sound abspielen
421
  if MEnableSound.Checked then PlaySound(RES_JUMP, HInstance, SND_ASYNC or SND_NOWAIT or SND_RESOURCE);
444
  if MEnableSound.Checked then PlaySound(RES_JUMP, HInstance, SND_ASYNC or SND_NOWAIT or SND_RESOURCE);
422
 
445
 
423
  {$REGION 'Nun den Stein springen lassen'}
446
  {$REGION 'Nun den Stein springen lassen'}
424
  old_fieldtype := PlayGroundMatrix[s.X, s.Y].FieldType; // Steinfarbe merken
447
  old_fieldtype := PlayGroundMatrix[s.X, s.Y].FieldType; // Steinfarbe merken
425
  RemoveStone(s.X, s.Y, false); // Eigenen Stein entfernen. Keine Punkte zählen, da das unser eigener Stein ist, der springt
448
  RemoveStone(s.X, s.Y, false); // Eigenen Stein entfernen. Keine Punkte zählen, da das unser eigener Stein ist, der springt
426
  PlayGroundMatrix[d.X, d.Y].FieldType := old_fieldtype; // Farbe wiederherstellen
449
  PlayGroundMatrix[d.X, d.Y].FieldType := old_fieldtype; // Farbe wiederherstellen
427
  LoadPictureForType(PlayGroundMatrix[d.X, d.Y].FieldType, PlayGroundMatrix[d.X, d.Y].Stone.Picture); // Stein an neue Position malen
450
  LoadPictureForType(PlayGroundMatrix[d.X, d.Y].FieldType, PlayGroundMatrix[d.X, d.Y].Stone.Picture); // Stein an neue Position malen
428
  StoneDraggingAllow(PlayGroundMatrix[d.X, d.Y].Stone, true); // Und die Drag-Eigenschaft erneuern
451
  StoneDraggingAllow(PlayGroundMatrix[d.X, d.Y].Stone, true); // Und die Drag-Eigenschaft erneuern
429
  {$ENDREGION}
452
  {$ENDREGION}
430
 
453
 
431
  {$REGION 'Sind weitere Sprünge möglich oder ist das Spiel vorbei?'}
454
  {$REGION 'Sind weitere Sprünge möglich oder ist das Spiel vorbei?'}
432
  if not AreJumpsPossible then
455
  if not AreJumpsPossible then
433
  begin
456
  begin
434
    MPauseTime.Enabled := false;
457
    MPauseTime.Enabled := false;
435
    Timer.Enabled := false;
458
    Timer.Enabled := false;
436
    RefreshTime;
459
    RefreshTime;
437
    if MEnableSound.Checked then
460
    if MEnableSound.Checked then
438
    begin
461
    begin
439
      if LevelRemovedStones = LevelTotalStones then
462
      if LevelRemovedStones = LevelTotalStones-1 then
-
 
463
      begin
-
 
464
        if GoalStatus in [gsLastStoneInGoalRed, gsLastStoneInGoalYellow, gsLastStoneInGoalGreen] then
-
 
465
          PlaySound(RES_WIN2, HInstance, SND_ASYNC or SND_NOWAIT or SND_RESOURCE)
-
 
466
        else
440
        PlaySound(RES_FINISH, HInstance, SND_ASYNC or SND_NOWAIT or SND_RESOURCE)
467
          PlaySound(RES_WIN1, HInstance, SND_ASYNC or SND_NOWAIT or SND_RESOURCE)
-
 
468
      end
441
      else
469
      else
442
        PlaySound(RES_LOSE, HInstance, SND_ASYNC or SND_NOWAIT or SND_RESOURCE);
470
        PlaySound(RES_LOSE, HInstance, SND_ASYNC or SND_NOWAIT or SND_RESOURCE);
443
    end;
471
    end;
444
    res := FinishForm.Execute(ExtractFileNameWithoutExt(LevelFile), Points, LevelTotalStones, LevelRemovedStones, CountedSeconds, JumpHistory);
472
    res := FinishForm.Execute(ExtractFileNameWithoutExt(LevelFile), Points, LevelTotalStones, LevelRemovedStones, CountedSeconds, GoalStatus, JumpHistory);
445
    if (res = mrOK) and FinishForm.ReplayCheckbox.Checked then RestartLevel;
473
    if (res = mrOK) and FinishForm.ReplayCheckbox.Checked then RestartLevel;
446
  end;
474
  end;
447
  {$ENDREGION}
475
  {$ENDREGION}
448
 
476
 
449
  SetLength(PrevPlaygroundMatrixes, Length(PrevPlaygroundMatrixes)+1);
477
  SetLength(PrevPlaygroundMatrixes, Length(PrevPlaygroundMatrixes)+1);
450
  PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1] := CloneMatrix(PlaygroundMatrix);
478
  PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1] := CloneMatrix(PlaygroundMatrix);
451
  MUndo.Enabled := true;
479
  MUndo.Enabled := true;
452
end;
480
end;
453
 
481
 
454
function TMainForm.MayJump(SourceX, SourceY, DestX, DestY: integer): boolean;
482
function TMainForm.MayJump(SourceX, SourceY, DestX, DestY: integer): boolean;
455
begin
483
begin
456
  result := false;
484
  result := false;
457
 
485
 
458
  // Check 1: Ist das Zielfeld überhaupt leer?
486
  // Check 1: Ist das Zielfeld überhaupt leer?
459
  if FieldState(DestX, DestY) <> fsAvailable then exit;
487
  if FieldState(DestX, DestY) <> fsAvailable then exit;
460
 
488
 
461
  // Check 2: Befindet sich ein Stein zwischen Source und Destination und ist der Abstand 2?
489
  // Check 2: Befindet sich ein Stein zwischen Source und Destination und ist der Abstand 2?
462
  if AllowDiagonalMoves then
490
  if AllowDiagonalMoves then
463
  begin
491
  begin
464
    if (SourceX-2 = DestX) and (SourceY-2 = DestY) and (FieldState(SourceX-1, SourceY-1) = fsStone) then result := true;
492
    if (SourceX-2 = DestX) and (SourceY-2 = DestY) and (FieldState(SourceX-1, SourceY-1) = fsStone) then result := true;
465
    if (SourceX-2 = DestX) and (SourceY+2 = DestY) and (FieldState(SourceX-1, SourceY+1) = fsStone) then result := true;
493
    if (SourceX-2 = DestX) and (SourceY+2 = DestY) and (FieldState(SourceX-1, SourceY+1) = fsStone) then result := true;
466
    if (SourceX+2 = DestX) and (SourceY-2 = DestY) and (FieldState(SourceX+1, SourceY-1) = fsStone) then result := true;
494
    if (SourceX+2 = DestX) and (SourceY-2 = DestY) and (FieldState(SourceX+1, SourceY-1) = fsStone) then result := true;
467
    if (SourceX+2 = DestX) and (SourceY+2 = DestY) and (FieldState(SourceX+1, SourceY+1) = fsStone) then result := true;
495
    if (SourceX+2 = DestX) and (SourceY+2 = DestY) and (FieldState(SourceX+1, SourceY+1) = fsStone) then result := true;
468
  end;
496
  end;
469
 
497
 
470
  if (SourceX+2 = DestX) and (SourceY   = DestY) and (FieldState(SourceX+1, SourceY  ) = fsStone) then result := true;
498
  if (SourceX+2 = DestX) and (SourceY   = DestY) and (FieldState(SourceX+1, SourceY  ) = fsStone) then result := true;
471
  if (SourceX-2 = DestX) and (SourceY   = DestY) and (FieldState(SourceX-1, SourceY  ) = fsStone) then result := true;
499
  if (SourceX-2 = DestX) and (SourceY   = DestY) and (FieldState(SourceX-1, SourceY  ) = fsStone) then result := true;
472
  if (SourceX   = DestX) and (SourceY+2 = DestY) and (FieldState(SourceX  , SourceY+1) = fsStone) then result := true;
500
  if (SourceX   = DestX) and (SourceY+2 = DestY) and (FieldState(SourceX  , SourceY+1) = fsStone) then result := true;
473
  if (SourceX   = DestX) and (SourceY-2 = DestY) and (FieldState(SourceX  , SourceY-1) = fsStone) then result := true;
501
  if (SourceX   = DestX) and (SourceY-2 = DestY) and (FieldState(SourceX  , SourceY-1) = fsStone) then result := true;
474
end;
502
end;
475
 
503
 
476
function TMainForm.MayJump(SourceTag, DestTag: integer): boolean;
504
function TMainForm.MayJump(SourceTag, DestTag: integer): boolean;
477
var
505
var
478
  s, d: TPoint;
506
  s, d: TPoint;
479
begin
507
begin
480
  d := LookupFieldCoordinateArray[DestTag];
508
  d := LookupFieldCoordinateArray[DestTag];
481
  s := LookupFieldCoordinateArray[SourceTag];
509
  s := LookupFieldCoordinateArray[SourceTag];
482
 
510
 
483
  result := MayJump(s.X, s.Y, d.X, d.Y);
511
  result := MayJump(s.X, s.Y, d.X, d.Y);
484
end;
512
end;
485
 
513
 
486
procedure TMainForm.StoneDragDrop(Sender, Source: TObject; X, Y: Integer);
514
procedure TMainForm.StoneDragDrop(Sender, Source: TObject; X, Y: Integer);
487
begin
515
begin
488
  DoJump(TComponent(Source).Tag, TComponent(Sender).Tag);
516
  DoJump(TComponent(Source).Tag, TComponent(Sender).Tag);
489
end;
517
end;
490
 
518
 
491
procedure TMainForm.StoneDragOver(Sender, Source: TObject; X,
519
procedure TMainForm.StoneDragOver(Sender, Source: TObject; X,
492
  Y: Integer; State: TDragState; var Accept: Boolean);
520
  Y: Integer; State: TDragState; var Accept: Boolean);
493
begin
521
begin
494
  Accept := MayJump(TComponent(Source).Tag, TComponent(Sender).Tag);
522
  Accept := MayJump(TComponent(Source).Tag, TComponent(Sender).Tag);
495
end;
523
end;
496
 
524
 
497
procedure TMainForm.DrawField(x, y: integer; t: TFieldProperties; halftabs: integer);
525
procedure TMainForm.DrawField(x, y: integer; t: TFieldProperties; halftabs: integer);
498
var
526
var
499
  newField: TField;
527
  newField: TField;
500
  index: integer;
528
  index: integer;
501
begin
529
begin
502
  if (t.Typ = ftLocked) or (t.Typ = ftLockedWithTab) then exit;
530
  if (t.Typ = ftLocked) or (t.Typ = ftLockedWithTab) then exit;
503
 
531
 
504
  index := Length(LookupFieldCoordinateArray);
532
  index := Length(LookupFieldCoordinateArray);
505
 
533
 
506
  newField.FieldType := t.Typ;
534
  newField.FieldType := t.Typ;
507
  newField.Goal := t.Goal;
535
  newField.Goal := t.Goal;
508
  newField.Panel := DrawStoneBox(x, y, index, halftabs, t.Goal);
536
  newField.Panel := DrawStoneBox(x, y, index, halftabs, t.Goal);
509
  newField.Stone := DrawStone(t.Typ, newField.Panel);
537
  newField.Stone := DrawStone(t.Typ, newField.Panel);
510
  if FieldState(t.Typ) = fsStone then Inc(LevelTotalStones);
538
  if FieldState(t.Typ) = fsStone then Inc(LevelTotalStones);
511
 
539
 
512
  SetLength(LookupFieldCoordinateArray, index + 1);
540
  SetLength(LookupFieldCoordinateArray, index + 1);
513
  LookupFieldCoordinateArray[index].X := x;
541
  LookupFieldCoordinateArray[index].X := x;
514
  LookupFieldCoordinateArray[index].Y := y;
542
  LookupFieldCoordinateArray[index].Y := y;
515
 
543
 
516
  if Length(PlayGroundMatrix) < x+1 then SetLength(PlayGroundMatrix, x+1);
544
  if Length(PlayGroundMatrix) < x+1 then SetLength(PlayGroundMatrix, x+1);
517
  if Length(PlayGroundMatrix[x]) < y+1 then SetLength(PlayGroundMatrix[x], y+1);
545
  if Length(PlayGroundMatrix[x]) < y+1 then SetLength(PlayGroundMatrix[x], y+1);
518
  PlaygroundMatrix[x, y] := newField;
546
  PlaygroundMatrix[x, y] := newField;
519
end;
547
end;
520
 
548
 
521
function TMainForm.CloneMatrix(Source: TPlayGroundMatrix): TPlayGroundMatrix;
549
function TMainForm.CloneMatrix(Source: TPlayGroundMatrix): TPlayGroundMatrix;
522
var
550
var
523
  i, j: integer;
551
  i, j: integer;
524
begin
552
begin
525
  SetLength(result, Length(Source));
553
  SetLength(result, Length(Source));
526
  for i := Low(Source) to High(Source) do
554
  for i := Low(Source) to High(Source) do
527
  begin
555
  begin
528
    SetLength(result[i], Length(Source[i]));
556
    SetLength(result[i], Length(Source[i]));
529
    for j := Low(Source[i]) to High(Source[i]) do
557
    for j := Low(Source[i]) to High(Source[i]) do
530
    begin
558
    begin
531
      result[i][j].FieldType := Source[i][j].FieldType;
559
      result[i][j].FieldType := Source[i][j].FieldType;
532
      result[i][j].Goal      := Source[i][j].Goal;
560
      result[i][j].Goal      := Source[i][j].Goal;
533
      result[i][j].Panel     := Source[i][j].Panel;
561
      result[i][j].Panel     := Source[i][j].Panel;
534
      result[i][j].Stone     := Source[i][j].Stone;
562
      result[i][j].Stone     := Source[i][j].Stone;
535
    end;
563
    end;
536
  end;
564
  end;
537
end;
565
end;
538
 
566
 
539
procedure TMainForm.BuildPlayground(LevelArray: TLevelArray);
567
procedure TMainForm.BuildPlayground(LevelArray: TLevelArray);
540
var
568
var
541
  i, j, halftabs, cur_x: integer;
569
  i, j, halftabs, cur_x: integer;
542
  max_x, max_y, old_cw, old_ch: integer;
570
  max_x, max_y, old_cw, old_ch: integer;
543
begin
571
begin
544
  PlayGround.Visible := false;
572
  PlayGround.Visible := false;
545
 
573
 
546
  // Die Dimensionen ermitteln
574
  // Die Dimensionen ermitteln
547
  max_x := 0;
575
  max_x := 0;
548
  for i := Low(LevelArray) to High(LevelArray) do
576
  for i := Low(LevelArray) to High(LevelArray) do
549
  begin
577
  begin
550
    halftabs := 0;
578
    halftabs := 0;
551
    for j := Low(LevelArray[i]) to High(LevelArray[i]) do
579
    for j := Low(LevelArray[i]) to High(LevelArray[i]) do
552
    begin
580
    begin
553
      if LevelArray[i][j].Typ = ftLockedWithTab then inc(halftabs);
581
      if LevelArray[i][j].Typ = ftLockedWithTab then inc(halftabs);
554
      DrawField(j, i, LevelArray[i][j], halftabs);
582
      DrawField(j, i, LevelArray[i][j], halftabs);
555
    end;
583
    end;
556
    cur_x := High(LevelArray[i]) + 1;
584
    cur_x := High(LevelArray[i]) + 1;
557
    if cur_x > max_x then max_x := cur_x;
585
    if cur_x > max_x then max_x := cur_x;
558
  end;
586
  end;
559
  max_y := High(LevelArray) + 1;
587
  max_y := High(LevelArray) + 1;
560
 
588
 
561
  PlayGround.Visible := true;
589
  PlayGround.Visible := true;
562
 
590
 
563
  // Die aktuellen Dimensionen merken
591
  // Die aktuellen Dimensionen merken
564
  old_cw := ClientWidth;
592
  old_cw := ClientWidth;
565
  old_ch := ClientHeight;
593
  old_ch := ClientHeight;
566
 
594
 
567
  // Das Form an das Level anpassen
595
  // Das Form an das Level anpassen
568
  PlayGround.Width := MET_FIELD_SPACE + max_x * (MET_FIELD_SPACE + MET_FIELD_SIZE);
596
  PlayGround.Width := MET_FIELD_SPACE + max_x * (MET_FIELD_SPACE + MET_FIELD_SIZE);
569
  PlayGround.Height := MET_FIELD_SPACE + max_y * (MET_FIELD_SPACE + MET_FIELD_SIZE);
597
  PlayGround.Height := MET_FIELD_SPACE + max_y * (MET_FIELD_SPACE + MET_FIELD_SIZE);
570
  ClientWidth := 2 * MET_OUTER_MARGIN + PlayGround.Width;
598
  ClientWidth := 2 * MET_OUTER_MARGIN + PlayGround.Width;
571
  ClientHeight := 2 * MET_OUTER_MARGIN + PlayGround.Height + Statistics.Height;
599
  ClientHeight := 2 * MET_OUTER_MARGIN + PlayGround.Height + Statistics.Height;
572
 
600
 
573
  Statistics.Panels.Items[0].Width := Round(ClientWidth*MET_PERCENT_PNL_TIME);
601
  Statistics.Panels.Items[0].Width := Round(ClientWidth*MET_PERCENT_PNL_TIME);
574
  Statistics.Panels.Items[1].Width := Round(ClientWidth*MET_PERCENT_PNL_STONES);
602
  Statistics.Panels.Items[1].Width := Round(ClientWidth*MET_PERCENT_PNL_STONES);
575
 
603
 
576
  // Wenn sich das Form vergrößert oder verkleinert hat, neu justieren
604
  // Wenn sich das Form vergrößert oder verkleinert hat, neu justieren
577
  if (old_cw <> ClientWidth) or (old_ch <> ClientHeight) then
605
  if (old_cw <> ClientWidth) or (old_ch <> ClientHeight) then
578
  begin
606
  begin
579
    Left := Screen.Width div 2 - Width div 2;
607
    Left := Screen.Width div 2 - Width div 2;
580
    Top := Screen.Height div 2 - Height div 2;
608
    Top := Screen.Height div 2 - Height div 2;
581
   
609
   
582
    // Playground mittig setzen, falls die Mindestgröße für die
610
    // Playground mittig setzen, falls die Mindestgröße für die
583
    // Punkteanzeige unterschritten wurde,
611
    // Punkteanzeige unterschritten wurde,
584
    PlayGround.Left := ClientWidth div 2 - PlayGround.Width div 2;
612
    PlayGround.Left := ClientWidth div 2 - PlayGround.Width div 2;
585
    PlayGround.Top := ClientHeight div 2 - PlayGround.Height div 2;
613
    PlayGround.Top := ClientHeight div 2 - PlayGround.Height div 2;
586
  end;
614
  end;
587
 
615
 
588
  OriginalPlayGroundMatrix := CloneMatrix(PlayGroundMatrix);
616
  OriginalPlayGroundMatrix := CloneMatrix(PlayGroundMatrix);
589
  SetLength(PrevPlaygroundMatrixes,1);
617
  SetLength(PrevPlaygroundMatrixes,1);
590
  PrevPlaygroundMatrixes[0] := CloneMatrix(PlayGroundMatrix);
618
  PrevPlaygroundMatrixes[0] := CloneMatrix(PlayGroundMatrix);
591
  MUndo.Enabled := false;
619
  MUndo.Enabled := false;
592
end;
620
end;
593
 
621
 
594
procedure TMainForm.TimerTimer(Sender: TObject);
622
procedure TMainForm.TimerTimer(Sender: TObject);
595
begin
623
begin
596
  if mainform.Focused then Inc(CountedSeconds);
624
  if mainform.Focused then Inc(CountedSeconds);
597
  RefreshTime;
625
  RefreshTime;
598
end;
626
end;
599
 
627
 
600
function TMainForm.LevelTime: String;
628
function TMainForm.LevelTime: String;
601
begin
629
begin
602
  result := SecondsToTimeString(CountedSeconds);
630
  result := SecondsToTimeString(CountedSeconds);
603
end;
631
end;
604
 
632
 
605
procedure TMainForm.NewGame(Filename: string);
633
procedure TMainForm.NewGame(Filename: string);
606
var
634
var
607
  LevelString: String;
635
  LevelString: String;
608
  LevelArray: TLevelArray;
636
  LevelArray: TLevelArray;
609
begin                          
637
begin                          
610
  DestroyLevel;
638
  DestroyLevel;
611
  LevelFile := Filename;
639
  LevelFile := Filename;
612
  LevelString := ReadFile(LevelFile);
640
  LevelString := ReadFile(LevelFile);
613
  LevelArray := LevelStringToLevelArray(LevelString, true);
641
  LevelArray := LevelStringToLevelArray(LevelString, true);
614
  if Length(LevelArray) = 0 then Exit;
642
  if Length(LevelArray) = 0 then Exit;
615
  BuildPlayground(LevelArray);
643
  BuildPlayground(LevelArray);
616
  if not AreJumpsPossible then
644
  if not AreJumpsPossible then
617
  begin
645
  begin
618
    ShowMessage(LNG_LVL_INVALID_NO_JUMP);
646
    ShowMessage(LNG_LVL_INVALID_NO_JUMP);
619
  end;
647
  end;
620
  RefreshTime;
648
  RefreshTime;
621
  RefreshStonesRemoved;
649
  RefreshStonesRemoved;
622
  RefreshPoints;
650
  RefreshPoints;
623
end;
651
end;
624
 
652
 
625
procedure TMainForm.MNewGameClick(Sender: TObject);
653
procedure TMainForm.MNewGameClick(Sender: TObject);
626
begin
654
begin
627
  LevelFile := AskForLevel;
655
  LevelFile := AskForLevel;
628
  if LevelFile <> '' then
656
  if LevelFile <> '' then
629
  begin
657
  begin
630
    NewGame(LevelFile);
658
    NewGame(LevelFile);
631
  end;
659
  end;
632
end;
660
end;
633
 
661
 
634
procedure TMainForm.MAboutClick(Sender: TObject);
662
procedure TMainForm.MAboutClick(Sender: TObject);
635
begin
663
begin
636
  AboutBox.ShowModal;
664
  AboutBox.ShowModal;
637
end;
665
end;
638
 
666
 
639
function TMainForm.AskForLevel: String;
667
function TMainForm.AskForLevel: String;
640
begin
668
begin
641
  LevelChoice.ShowModal;
669
  LevelChoice.ShowModal;
642
 
670
 
643
  if LevelChoice.ModalResult <> mrOK then
671
  if LevelChoice.ModalResult <> mrOK then
644
  begin
672
  begin
645
    result := '';
673
    result := '';
646
    exit;
674
    exit;
647
  end;
675
  end;
648
 
676
 
649
  result := LevelChoice.SelectedLevel;
677
  result := LevelChoice.SelectedLevel;
650
end;
678
end;
651
 
679
 
652
procedure TMainForm.FormShow(Sender: TObject);
680
procedure TMainForm.FormShow(Sender: TObject);
653
begin
681
begin
654
  LevelFile := AskForLevel;
682
  LevelFile := AskForLevel;
655
  if LevelFile <> '' then
683
  if LevelFile <> '' then
656
  begin
684
  begin
657
    NewGame(LevelFile);
685
    NewGame(LevelFile);
658
  end
686
  end
659
  else Close();
687
  else Close();
660
end;
688
end;
-
 
689
 
-
 
690
function TMainForm.GoalStatus: TGoalStatus;
-
 
691
var
-
 
692
  ft: TFieldType;
-
 
693
begin
-
 
694
  if not MatrixHasGoal(PlaygroundMatrix) then
-
 
695
    result := gsNoGoal
-
 
696
  else if LevelRemovedStones < LevelTotalStones-1 then
-
 
697
    Result := gsMultipleStonesRemaining
-
 
698
  else
-
 
699
  begin
-
 
700
    ft := GoalFieldType(PlaygroundMatrix);
-
 
701
    if ft = ftRed then
-
 
702
      result := gsLastStoneInGoalRed
-
 
703
    else if ft = ftYellow then
-
 
704
      result := gsLastStoneInGoalYellow
-
 
705
    else if ft = ftGreen then
-
 
706
      result := gsLastStoneInGoalGreen;
-
 
707
  end;
-
 
708
end;
661
 
709
 
662
procedure TMainForm.FormCreate(Sender: TObject);
710
procedure TMainForm.FormCreate(Sender: TObject);
663
begin
711
begin
664
  JumpHistory := TStringList.Create;
712
  JumpHistory := TStringList.Create;
665
  LoadSettings;
713
  LoadSettings;
666
end;
714
end;
667
 
715
 
668
procedure TMainForm.FormDestroy(Sender: TObject);
716
procedure TMainForm.FormDestroy(Sender: TObject);
669
begin
717
begin
670
  JumpHistory.Free;
718
  JumpHistory.Free;
671
end;
719
end;
672
 
720
 
673
procedure TMainForm.MJumpHistoryClick(Sender: TObject);
721
procedure TMainForm.MJumpHistoryClick(Sender: TObject);
674
begin
722
begin
675
  HistoryForm.JumpMemo.Lines.Assign(JumpHistory);
723
  HistoryForm.JumpMemo.Lines.Assign(JumpHistory);
676
  HistoryForm.ShowModal;
724
  HistoryForm.ShowModal;
677
end;
725
end;
678
 
726
 
679
procedure TMainForm.RestartLevel;
727
procedure TMainForm.RestartLevel;
680
begin
728
begin
681
  MPauseTime.Enabled := false;
729
  MPauseTime.Enabled := false;
682
  Timer.Enabled := false;
730
  Timer.Enabled := false;
683
 
731
 
684
  MRestartGame.Enabled := false;
732
  MRestartGame.Enabled := false;
685
 
733
 
686
  CountedSeconds := 0;
734
  CountedSeconds := 0;
687
  RefreshTime;
735
  RefreshTime;
688
 
736
 
689
  Points := 0;
737
  Points := 0;
690
  RefreshPoints;
738
  RefreshPoints;
691
 
739
 
692
  LevelRemovedStones := 0;
740
  LevelRemovedStones := 0;
693
  RefreshStonesRemoved;
741
  RefreshStonesRemoved;
694
 
742
 
695
  JumpHistory.Clear;
743
  JumpHistory.Clear;
696
 
744
 
697
  RedrawStonesFromMatrix(OriginalPlayGroundMatrix);
745
  RedrawStonesFromMatrix(OriginalPlayGroundMatrix);
698
  SetNewPlayGroundMatrix(OriginalPlayGroundMatrix);
746
  SetNewPlayGroundMatrix(OriginalPlayGroundMatrix);
699
  SetLength(PrevPlaygroundMatrixes,1);
747
  SetLength(PrevPlaygroundMatrixes,1);
700
  PrevPlaygroundMatrixes[0] := CloneMatrix(OriginalPlayGroundMatrix);
748
  PrevPlaygroundMatrixes[0] := CloneMatrix(OriginalPlayGroundMatrix);
701
  MUndo.Enabled := false;
749
  MUndo.Enabled := false;
702
end;
750
end;
703
 
751
 
704
procedure TMainForm.SetNewPlayGroundMatrix(Matrix: TPlayGroundMatrix);
752
procedure TMainForm.SetNewPlayGroundMatrix(Matrix: TPlayGroundMatrix);
705
begin
753
begin
706
  ClearMatrix(PlayGroundMatrix, false); // Memory Leak verhindern
754
  ClearMatrix(PlayGroundMatrix, false); // Memory Leak verhindern
707
  PlayGroundMatrix := CloneMatrix(Matrix);
755
  PlayGroundMatrix := CloneMatrix(Matrix);
708
end;
756
end;
709
 
757
 
710
procedure TMainForm.MRestartGameClick(Sender: TObject);
758
procedure TMainForm.MRestartGameClick(Sender: TObject);
711
begin
759
begin
712
  RestartLevel;
760
  RestartLevel;
713
end;
761
end;
714
 
762
 
715
procedure TMainForm.MUndoClick(Sender: TObject);
763
procedure TMainForm.MUndoClick(Sender: TObject);
716
var
764
var
717
  PrevWorth: integer;
765
  PrevWorth: integer;
718
  NewWorth: integer;
766
  NewWorth: integer;
719
begin
767
begin
720
  if Length(PrevPlaygroundMatrixes) > 1 then
768
  if Length(PrevPlaygroundMatrixes) > 1 then
721
  begin
769
  begin
722
    PrevWorth := MatrixWorth(PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1]);
770
    PrevWorth := MatrixWorth(PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1]);
723
 
771
 
724
    ClearMatrix(PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1], false);
772
    ClearMatrix(PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1], false);
725
    SetLength(PrevPlaygroundMatrixes, Length(PrevPlaygroundMatrixes)-1);
773
    SetLength(PrevPlaygroundMatrixes, Length(PrevPlaygroundMatrixes)-1);
726
 
774
 
727
    NewWorth := MatrixWorth(PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1]);
775
    NewWorth := MatrixWorth(PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1]);
728
    RedrawStonesFromMatrix(PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1]);
776
    RedrawStonesFromMatrix(PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1]);
729
    SetNewPlayGroundMatrix(PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1]);
777
    SetNewPlayGroundMatrix(PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1]);
730
 
778
 
731
    JumpHistory.Delete(JumpHistory.Count-1);
779
    JumpHistory.Delete(JumpHistory.Count-1);
732
 
780
 
733
    Dec(LevelRemovedStones);
781
    Dec(LevelRemovedStones);
734
    RefreshStonesRemoved;
782
    RefreshStonesRemoved;
735
 
783
 
736
    Dec(Points, NewWorth-PrevWorth);
784
    Dec(Points, NewWorth-PrevWorth);
737
    RefreshPoints;
785
    RefreshPoints;
738
 
786
 
739
    // Sound abspielen
787
    // Sound abspielen
740
    if MEnableSound.Checked then PlaySound(RES_UNDO, HInstance, SND_ASYNC or SND_NOWAIT or SND_RESOURCE);
788
    if MEnableSound.Checked then PlaySound(RES_UNDO, HInstance, SND_ASYNC or SND_NOWAIT or SND_RESOURCE);
741
  end;
789
  end;
742
 
790
 
743
  MUndo.Enabled := Length(PrevPlaygroundMatrixes) > 1;
791
  MUndo.Enabled := Length(PrevPlaygroundMatrixes) > 1;
744
end;
792
end;
745
 
793
 
746
procedure TMainForm.MHighScoresClick(Sender: TObject);
794
procedure TMainForm.MHighScoresClick(Sender: TObject);
747
begin
795
begin
748
  HighScoreForm.Execute(ExtractFileNameWithoutExt(LevelFile));
796
  HighScoreForm.Execute(ExtractFileNameWithoutExt(LevelFile));
749
end;
797
end;
750
 
798
 
751
procedure TMainForm.MPauseTimeClick(Sender: TObject);
799
procedure TMainForm.MPauseTimeClick(Sender: TObject);
752
begin
800
begin
753
  MPauseTime.Enabled := false;
801
  MPauseTime.Enabled := false;
754
  Timer.Enabled := false;
802
  Timer.Enabled := false;
755
end;
803
end;
756
 
804
 
757
procedure TMainForm.LoadSettings;
805
procedure TMainForm.LoadSettings;
758
var
806
var
759
  reg: TRegistry;
807
  reg: TRegistry;
760
begin
808
begin
761
  reg := TRegistry.Create;
809
  reg := TRegistry.Create;
762
  try
810
  try
763
    reg.RootKey := HKEY_CURRENT_USER;
811
    reg.RootKey := HKEY_CURRENT_USER;
764
    if reg.OpenKeyReadOnly(REG_KEY) then
812
    if reg.OpenKeyReadOnly(REG_KEY) then
765
    begin
813
    begin
766
      if reg.ValueExists(REG_SOUND) then
814
      if reg.ValueExists(REG_SOUND) then
767
        MEnableSound.Checked := reg.ReadBool(REG_SOUND);
815
        MEnableSound.Checked := reg.ReadBool(REG_SOUND);
768
      reg.CloseKey;
816
      reg.CloseKey;
769
    end;
817
    end;
770
  finally
818
  finally
771
    reg.Free;
819
    reg.Free;
772
  end;
820
  end;
773
end;
821
end;
774
 
822
 
775
procedure TMainForm.SaveSettings;
823
procedure TMainForm.SaveSettings;
776
var
824
var
777
  reg: TRegistry;
825
  reg: TRegistry;
778
begin
826
begin
779
  reg := TRegistry.Create;
827
  reg := TRegistry.Create;
780
  try
828
  try
781
    reg.RootKey := HKEY_CURRENT_USER;
829
    reg.RootKey := HKEY_CURRENT_USER;
782
    if reg.OpenKey(REG_KEY, true) then
830
    if reg.OpenKey(REG_KEY, true) then
783
    begin
831
    begin
784
      reg.WriteBool(REG_SOUND, MEnableSound.Checked);
832
      reg.WriteBool(REG_SOUND, MEnableSound.Checked);
785
      reg.CloseKey;
833
      reg.CloseKey;
786
    end;
834
    end;
787
  finally
835
  finally
788
    reg.Free;
836
    reg.Free;
789
  end;
837
  end;
790
end;
838
end;
791
 
839
 
792
 
840
 
793
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
841
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
794
begin
842
begin
795
  SaveSettings;
843
  SaveSettings;
796
  if FinishForm.NameEdit.Text <> '' then
844
  if FinishForm.NameEdit.Text <> '' then
797
  begin
845
  begin
798
    FinishForm.SaveSettings;
846
    FinishForm.SaveSettings;
799
  end;
847
  end;
800
end;
848
end;
801
 
849
 
802
procedure TMainForm.MHelpClick(Sender: TObject);
850
procedure TMainForm.MHelpClick(Sender: TObject);
803
begin
851
begin
804
  HelpForm.ShowModal;
852
  HelpForm.ShowModal;
805
end;
853
end;
806
 
854
 
807
procedure TMainForm.MEnableSoundClick(Sender: TObject);
855
procedure TMainForm.MEnableSoundClick(Sender: TObject);
808
begin
856
begin
809
  MEnableSound.Checked := not MEnableSound.Checked;
857
  MEnableSound.Checked := not MEnableSound.Checked;
810
end;
858
end;
811
 
859
 
812
end.
860
end.
813
 
861