Subversion Repositories jumper

Rev

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

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