Subversion Repositories jumper

Rev

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

Rev 23 Rev 24
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
  TMainForm = class(TForm)
10
  TMainForm = class(TForm)
11
    Playground: TPanel;
11
    Playground: TPanel;
12
    MainMenu: TMainMenu;
12
    MainMenu: TMainMenu;
13
    Help1: TMenuItem;
13
    Help1: TMenuItem;
14
    MExit: TMenuItem;
14
    MExit: TMenuItem;
15
    Statistics: TStatusBar;
15
    Statistics: TStatusBar;
16
    Timer: TTimer;
16
    Timer: TTimer;
17
    MNewGame: TMenuItem;
17
    MNewGame: TMenuItem;
18
    Help2: TMenuItem;
18
    Help2: TMenuItem;
19
    MAbout: TMenuItem;
19
    MAbout: TMenuItem;
20
    MHelp: TMenuItem;
20
    MHelp: TMenuItem;
21
    N5: TMenuItem;
21
    N5: TMenuItem;
22
    MJumpHistory: TMenuItem;
22
    MJumpHistory: TMenuItem;
23
    N2: TMenuItem;
23
    N2: TMenuItem;
24
    N4: TMenuItem;
24
    N4: TMenuItem;
25
    MHighScores: TMenuItem;
25
    MHighScores: TMenuItem;
26
    MRestartGame: TMenuItem;
26
    MRestartGame: TMenuItem;
27
    MSettings: TMenuItem;
27
    MSettings: TMenuItem;
28
    MEnableSound: TMenuItem;
28
    MEnableSound: TMenuItem;
29
    MPauseTime: TMenuItem;
29
    MPauseTime: TMenuItem;
30
    N1: TMenuItem;
30
    N1: TMenuItem;
31
    MUndo: TMenuItem;
31
    MUndo: TMenuItem;
32
    N3: TMenuItem;
32
    N3: TMenuItem;
33
    Aboutthislevel1: TMenuItem;
33
    Aboutthislevel1: TMenuItem;
34
    procedure MExitClick(Sender: TObject);
34
    procedure MExitClick(Sender: TObject);
35
    procedure TimerTimer(Sender: TObject);
35
    procedure TimerTimer(Sender: TObject);
36
    procedure MNewGameClick(Sender: TObject);
36
    procedure MNewGameClick(Sender: TObject);
37
    procedure MAboutClick(Sender: TObject);
37
    procedure MAboutClick(Sender: TObject);
38
    procedure FormShow(Sender: TObject);
38
    procedure FormShow(Sender: TObject);
39
    procedure FormCreate(Sender: TObject);
39
    procedure FormCreate(Sender: TObject);
40
    procedure FormDestroy(Sender: TObject);
40
    procedure FormDestroy(Sender: TObject);
41
    procedure MJumpHistoryClick(Sender: TObject);
41
    procedure MJumpHistoryClick(Sender: TObject);
42
    procedure MRestartGameClick(Sender: TObject);
42
    procedure MRestartGameClick(Sender: TObject);
43
    procedure MHighScoresClick(Sender: TObject);
43
    procedure MHighScoresClick(Sender: TObject);
44
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
44
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
45
    procedure MHelpClick(Sender: TObject);
45
    procedure MHelpClick(Sender: TObject);
46
    procedure MUndoClick(Sender: TObject);
46
    procedure MUndoClick(Sender: TObject);
47
    procedure Aboutthislevel1Click(Sender: TObject);
47
    procedure Aboutthislevel1Click(Sender: TObject);
48
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
48
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
49
  private
49
  private
50
    NoCloseQuery: boolean;
50
    NoCloseQuery: boolean;
51
    CountedSeconds: Integer;
51
    CountedSeconds: Integer;
52
    LevelFile: String;
52
    LevelFile: String;
53
    PrevPlaygroundMatrixes: array of TPlayGroundMatrix;
53
    PrevPlaygroundMatrixes: array of TPlayGroundMatrix;
54
    PlaygroundMatrix: TPlayGroundMatrix;
54
    PlaygroundMatrix: TPlayGroundMatrix;
55
    Points: Integer;
55
    Points: Integer;
56
    LevelTotalStones: Integer;
56
    LevelTotalStones: Integer;
57
    LevelRemovedStones: Integer;
57
    LevelRemovedStones: Integer;
58
    JumpHistory: TStringList;
58
    JumpHistory: TStringList;
59
    Level: TLevel;
59
    Level: TLevel;
60
    procedure LoadSettings;
60
    procedure LoadSettings;
61
    procedure SaveSettings;
61
    procedure SaveSettings;
62
    procedure RestartLevel;
62
    procedure RestartLevel;
63
    procedure SetNewPlayGroundMatrix(Matrix: TPlayGroundMatrix);
63
    procedure SetNewPlayGroundMatrix(Matrix: TPlayGroundMatrix);
64
    procedure RedrawStonesFromMatrix(Matrix: TPlayGroundMatrix);
64
    procedure RedrawStonesFromMatrix(Matrix: TPlayGroundMatrix);
65
    function AskForLevel: String;
65
    function AskForLevel: String;
66
    procedure StoneDraggingAllow(Stone: TImage; Allow: boolean);
66
    procedure StoneDraggingAllow(Stone: TImage; Allow: boolean);
67
    procedure NewGame(Filename: string);
67
    procedure NewGame(Filename: string);
68
    function LevelTime: String;
68
    function LevelTime: String;
69
    procedure DestroyLevel;
69
    procedure DestroyLevel;
70
    procedure RefreshTime;
70
    procedure RefreshTime;
71
    procedure RefreshPoints;
71
    procedure RefreshPoints;
72
    procedure RefreshStonesRemoved;
72
    procedure RefreshStonesRemoved;
73
    procedure RemoveStone(x, y: integer; count_points: boolean);
73
    procedure RemoveStone(x, y: integer; count_points: boolean);
74
    procedure DoJump(SourceTag, DestTag: integer);
74
    procedure DoJump(SourceTag, DestTag: integer);
75
    function MayJump(SourceTag, DestTag: integer): boolean; overload;
75
    function MayJump(SourceTag, DestTag: integer): boolean; overload;
76
    procedure StoneDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
76
    procedure StoneDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
77
    procedure StoneDragDrop(Sender, Source: TObject; X, Y: Integer);
77
    procedure StoneDragDrop(Sender, Source: TObject; X, Y: Integer);
78
    function DrawField(x, y: integer; t: TFieldProperties; indent: integer): TField;
78
    procedure DrawField(x, y: integer; var f: TField);
79
    function DrawStone(fieldtype: TFieldType; panel: TPanel): TImage;
79
    function DrawStone(fieldtype: TFieldType; panel: TPanel): TImage;
80
    function DrawStoneBox(x, y, tag, halftabs: integer; isGoal: boolean): TPanel;
80
    function DrawStoneBox(x, y, tag, halftabs: integer; isGoal: boolean): TPanel;
81
    procedure BuildPlayground(LevelArray: TLevelArray);
-
 
82
    procedure LoadPictureForType(FieldType: TFieldType; Picture: TPicture);
81
    procedure LoadPictureForType(FieldType: TFieldType; Picture: TPicture);
83
    function GoalStatus: TGoalStatus;
82
    function GoalStatus: TGoalStatus;
84
  end;
83
  end;
85
 
84
 
86
var
85
var
87
  MainForm: TMainForm;
86
  MainForm: TMainForm;
88
 
87
 
89
implementation
88
implementation
90
 
89
 
91
uses
90
uses
92
  About, Finish, Choice, Functions, History, HighScore, Help, Constants, Math;
91
  About, Finish, Choice, Functions, History, HighScore, Help, Constants, Math;
93
 
92
 
94
{$R *.dfm}
93
{$R *.dfm}
95
 
94
 
96
{ TMainForm }
95
{ TMainForm }
97
 
96
 
98
procedure TMainForm.RedrawStonesFromMatrix(Matrix: TPlayGroundMatrix);
97
procedure TMainForm.RedrawStonesFromMatrix(Matrix: TPlayGroundMatrix);
99
var
98
var
100
  x, y: integer;
99
  x, y: integer;
101
begin
100
begin
102
  for x := Low(Matrix.Fields) to High(Matrix.Fields) do
101
  for x := Low(Matrix.Fields) to High(Matrix.Fields) do
103
  begin
102
  begin
104
    for y := Low(Matrix.Fields[x]) to High(Matrix.Fields[x]) do
103
    for y := Low(Matrix.Fields[x]) to High(Matrix.Fields[x]) do
105
    begin
104
    begin
106
      if Assigned(Matrix.Fields[x][y].Stone) then
105
      if Assigned(Matrix.Fields[x,y].Stone) then
107
      begin
106
      begin
108
        LoadPictureForType(Matrix.Fields[x][y].FieldType, Matrix.Fields[x][y].Stone.Picture);
107
        LoadPictureForType(Matrix.Fields[x,y].FieldType, Matrix.Fields[x,y].Stone.Picture);
109
        StoneDraggingAllow(Matrix.Fields[x][y].Stone, Matrix.FieldState(Matrix.Fields[x][y].FieldType) <> fsAvailable);
108
        StoneDraggingAllow(Matrix.Fields[x,y].Stone, Matrix.FieldState(Matrix.Fields[x,y].FieldType) <> fsAvailable);
110
      end;
109
      end;
111
    end;
110
    end;
112
  end;
111
  end;
113
end;
112
end;
114
 
113
 
115
procedure TMainForm.DestroyLevel;
114
procedure TMainForm.DestroyLevel;
116
var
115
var
117
  i: Integer;
116
  i: Integer;
118
begin
117
begin
119
  MPauseTime.Checked := false;
118
  MPauseTime.Checked := false;
120
  MPauseTime.Enabled := false;
119
  MPauseTime.Enabled := false;
121
  Timer.Enabled := false;
120
  Timer.Enabled := false;
122
 
121
 
123
  MRestartGame.Enabled := false;
122
  MRestartGame.Enabled := false;
124
 
123
 
125
  LevelFile := '';
124
  LevelFile := '';
126
 
125
 
127
  CountedSeconds := 0;
126
  CountedSeconds := 0;
128
  RefreshTime;
127
  RefreshTime;
129
 
128
 
130
  Points := 0;
129
  Points := 0;
131
  RefreshPoints;
130
  RefreshPoints;
132
 
131
 
133
  LevelRemovedStones := 0;
132
  LevelRemovedStones := 0;
134
  LevelTotalStones := 0;
133
  LevelTotalStones := 0;
135
  RefreshStonesRemoved;
134
  RefreshStonesRemoved;
136
 
135
 
137
  JumpHistory.Clear;
136
  JumpHistory.Clear;
138
 
137
 
139
  PlayGroundMatrix.ClearMatrix(true);
138
  PlayGroundMatrix.ClearMatrix(true);
140
  for i := 0 to Length(PrevPlaygroundMatrixes)-1 do
139
  for i := 0 to Length(PrevPlaygroundMatrixes)-1 do
141
    PrevPlaygroundMatrixes[i].ClearMatrix(false);
140
    PrevPlaygroundMatrixes[i].ClearMatrix(false);
142
  SetLength(PrevPlaygroundMatrixes, 0);
141
  SetLength(PrevPlaygroundMatrixes, 0);
143
  MUndo.Enabled := false;
142
  MUndo.Enabled := false;
144
 
143
 
145
  if Assigned(Level) then FreeAndNil(Level);
144
  if Assigned(Level) then FreeAndNil(Level);
146
end;
145
end;
147
 
146
 
148
procedure TMainForm.LoadPictureForType(FieldType: TFieldType; Picture: TPicture);
147
procedure TMainForm.LoadPictureForType(FieldType: TFieldType; Picture: TPicture);
149
begin
148
begin
150
  case FieldType of
149
  case FieldType of
151
    ftEmpty:  Picture.Bitmap.LoadFromResourceName(HInstance, RES_EMPTY);
150
    ftEmpty:  Picture.Bitmap.LoadFromResourceName(HInstance, RES_EMPTY);
152
    ftGreen:  Picture.Bitmap.LoadFromResourceName(HInstance, RES_GREEN);
151
    ftGreen:  Picture.Bitmap.LoadFromResourceName(HInstance, RES_GREEN);
153
    ftYellow: Picture.Bitmap.LoadFromResourceName(HInstance, RES_YELLOW);
152
    ftYellow: Picture.Bitmap.LoadFromResourceName(HInstance, RES_YELLOW);
154
    ftRed:    Picture.Bitmap.LoadFromResourceName(HInstance, RES_RED);
153
    ftRed:    Picture.Bitmap.LoadFromResourceName(HInstance, RES_RED);
155
  end;
154
  end;
156
end;
155
end;
157
 
156
 
158
function TMainForm.DrawStone(fieldtype: TFieldType; panel: TPanel): TImage;
157
function TMainForm.DrawStone(fieldtype: TFieldType; panel: TPanel): TImage;
159
begin
158
begin
160
  result := TImage.Create(panel);
159
  result := TImage.Create(panel);
161
  result.Parent := panel;
160
  result.Parent := panel;
162
  LoadPictureForType(fieldtype, result.Picture);
161
  LoadPictureForType(fieldtype, result.Picture);
163
  result.Width := panel.Width - 2*MET_SHAPE_MARGIN;
162
  result.Width := panel.Width - 2*MET_SHAPE_MARGIN;
164
  result.Height := panel.Height - 2*MET_SHAPE_MARGIN;
163
  result.Height := panel.Height - 2*MET_SHAPE_MARGIN;
165
  result.Left := MET_SHAPE_MARGIN;
164
  result.Left := MET_SHAPE_MARGIN;
166
  result.Top := MET_SHAPE_MARGIN;
165
  result.Top := MET_SHAPE_MARGIN;
167
  result.Center := true;
166
  result.Center := true;
168
  result.Transparent := true;
167
  result.Transparent := true;
169
 
168
 
170
  result.Tag := panel.Tag;
169
  result.Tag := panel.Tag;
171
  result.OnDragOver := panel.OnDragOver;
170
  result.OnDragOver := panel.OnDragOver;
172
  result.OnDragDrop := panel.OnDragDrop;
171
  result.OnDragDrop := panel.OnDragDrop;
173
 
172
 
174
  StoneDraggingAllow(result, PlayGroundMatrix.FieldState(fieldtype) <> fsAvailable);
173
  StoneDraggingAllow(result, PlayGroundMatrix.FieldState(fieldtype) <> fsAvailable);
175
end;
174
end;
176
 
175
 
177
procedure TMainForm.StoneDraggingAllow(Stone: TImage; Allow: boolean);
176
procedure TMainForm.StoneDraggingAllow(Stone: TImage; Allow: boolean);
178
begin
177
begin
179
  if Allow then
178
  if Allow then
180
  begin
179
  begin
181
    Stone.DragMode := dmAutomatic;
180
    Stone.DragMode := dmAutomatic;
182
    (Stone.Parent as TPanel).DragMode := dmAutomatic;
181
    (Stone.Parent as TPanel).DragMode := dmAutomatic;
183
  end
182
  end
184
  else
183
  else
185
  begin
184
  begin
186
    Stone.DragMode := dmManual;
185
    Stone.DragMode := dmManual;
187
    (Stone.Parent as TPanel).DragMode := dmManual;
186
    (Stone.Parent as TPanel).DragMode := dmManual;
188
  end;
187
  end;
189
end;
188
end;
190
 
189
 
191
function TMainForm.DrawStoneBox(x, y, tag, halftabs: integer; isGoal: boolean): TPanel;
190
function TMainForm.DrawStoneBox(x, y, tag, halftabs: integer; isGoal: boolean): TPanel;
192
begin
191
begin
193
  result := TPanel.Create(Playground);
192
  result := TPanel.Create(Playground);
194
  result.Parent := Playground;
193
  result.Parent := Playground;
195
  if isGoal then
194
  if isGoal then
196
  begin
195
  begin
197
    result.BevelInner := bvLowered;
196
    result.BevelInner := bvLowered;
198
  end;
197
  end;
199
  result.Color := Playground.Color;
198
  result.Color := Playground.Color;
200
  result.BevelOuter := bvLowered;
199
  result.BevelOuter := bvLowered;
201
  result.Width := MET_FIELD_SIZE;
200
  result.Width := MET_FIELD_SIZE;
202
  result.Height := MET_FIELD_SIZE;
201
  result.Height := MET_FIELD_SIZE;
203
  result.Left := x * (MET_FIELD_SIZE+MET_FIELD_SPACE) + MET_FIELD_SPACE + (halftabs*MET_HALFTAB_SIZE);
202
  result.Left := x * (MET_FIELD_SIZE+MET_FIELD_SPACE) + MET_FIELD_SPACE + (halftabs*MET_HALFTAB_SIZE);
204
  result.Top := y * (MET_FIELD_SIZE+MET_FIELD_SPACE) + MET_FIELD_SPACE;
203
  result.Top := y * (MET_FIELD_SIZE+MET_FIELD_SPACE) + MET_FIELD_SPACE;
205
 
204
 
206
  result.Tag := tag;
205
  result.Tag := tag;
207
  result.OnDragOver := StoneDragOver;
206
  result.OnDragOver := StoneDragOver;
208
  result.OnDragDrop := StoneDragDrop;
207
  result.OnDragDrop := StoneDragDrop;
209
end;
208
end;
210
 
209
 
211
procedure TMainForm.MExitClick(Sender: TObject);
210
procedure TMainForm.MExitClick(Sender: TObject);
212
begin
211
begin
213
  Close;
212
  Close;
214
end;
213
end;
215
 
214
 
216
procedure TMainForm.RefreshTime;
215
procedure TMainForm.RefreshTime;
217
begin
216
begin
218
  Statistics.Panels.Items[0].Text := Format(LNG_TIME, [LevelTime]);
217
  Statistics.Panels.Items[0].Text := Format(LNG_TIME, [LevelTime]);
219
end;
218
end;
220
 
219
 
221
procedure TMainForm.RefreshStonesRemoved;
220
procedure TMainForm.RefreshStonesRemoved;
222
resourcestring
221
resourcestring
223
  LNG_STONES_REMOVED = '%d of %d stones removed';
222
  LNG_STONES_REMOVED = '%d of %d stones removed';
224
begin
223
begin
225
  Statistics.Panels.Items[1].Text := Format(LNG_STONES_REMOVED, [LevelRemovedStones, LevelTotalStones-1]);
224
  Statistics.Panels.Items[1].Text := Format(LNG_STONES_REMOVED, [LevelRemovedStones, LevelTotalStones-1]);
226
end;
225
end;
227
 
226
 
228
procedure TMainForm.RefreshPoints;
227
procedure TMainForm.RefreshPoints;
229
begin
228
begin
230
  Statistics.Panels.Items[2].Text := Format(LNG_POINTS, [Points]);
229
  Statistics.Panels.Items[2].Text := Format(LNG_POINTS, [Points]);
231
end;
230
end;
232
 
231
 
233
procedure TMainForm.RemoveStone(x, y: integer; count_points: boolean);
232
procedure TMainForm.RemoveStone(x, y: integer; count_points: boolean);
234
begin
233
begin
235
  if count_points then
234
  if count_points then
236
  begin
235
  begin
237
    Inc(Points, FieldTypeWorth(PlayGroundMatrix.Fields[x, y].FieldType));
236
    Inc(Points, FieldTypeWorth(PlayGroundMatrix.Fields[x,y].FieldType));
238
    RefreshPoints;
237
    RefreshPoints;
239
 
238
 
240
    Inc(LevelRemovedStones);
239
    Inc(LevelRemovedStones);
241
    RefreshStonesRemoved;
240
    RefreshStonesRemoved;
242
  end;
241
  end;
243
 
242
 
244
  PlayGroundMatrix.Fields[x, y].FieldType := ftEmpty;
243
  PlayGroundMatrix.Fields[x,y].FieldType := ftEmpty;
245
  LoadPictureForType(PlayGroundMatrix.Fields[x, y].FieldType, PlayGroundMatrix.Fields[x, y].Stone.Picture);
244
  LoadPictureForType(PlayGroundMatrix.Fields[x,y].FieldType, PlayGroundMatrix.Fields[x,y].Stone.Picture);
246
  StoneDraggingAllow(PlayGroundMatrix.Fields[x, y].Stone, false);
245
  StoneDraggingAllow(PlayGroundMatrix.Fields[x,y].Stone, false);
247
end;
246
end;
248
 
247
 
249
procedure TMainForm.Aboutthislevel1Click(Sender: TObject);
248
procedure TMainForm.Aboutthislevel1Click(Sender: TObject);
250
var
249
var
251
  mode: string;
250
  mode: string;
252
  goalYeSNo: string;
251
  goalYeSNo: string;
253
resourcestring
252
resourcestring
254
  LNG_BOARD = 'Board: %s';
253
  LNG_BOARD = 'Board: %s';
255
  LNG_MODE = 'Mode: %s';
254
  LNG_MODE = 'Mode: %s';
256
  LNG_STONES_TOTAL = 'Stones: %d';
255
  LNG_STONES_TOTAL = 'Stones: %d';
257
  LNG_GOAL_AVAILABLE = 'Target field defined';
256
  LNG_GOAL_AVAILABLE = 'Target field defined';
258
  LNG_NO_GOAL = 'No target field';
257
  LNG_NO_GOAL = 'No target field';
259
begin
258
begin
260
  case Level.GameMode of
259
  case Level.GameMode of
261
    gmNormal:    mode := 'Diagonal';
260
    gmNormal:    mode := 'Diagonal';
262
    gmDiagonal:  mode := 'Normal';
261
    gmDiagonal:  mode := 'Normal';
263
    gmUndefined: mode := '?';
262
    gmUndefined: mode := '?';
264
  end;
263
  end;
265
 
264
 
266
  if GoalStatus = gsNoGoal then
265
  if GoalStatus = gsNoGoal then
267
    goalYeSNo := LNG_NO_GOAL
266
    goalYeSNo := LNG_NO_GOAL
268
  else
267
  else
269
    goalYeSNo := LNG_GOAL_AVAILABLE;
268
    goalYeSNo := LNG_GOAL_AVAILABLE;
270
 
269
 
271
  ShowMessage(Format(LNG_BOARD, [ExtractFileNameWithoutExt(LevelFile)]) + #13#10 +
270
  ShowMessage(Format(LNG_BOARD, [ExtractFileNameWithoutExt(LevelFile)]) + #13#10 +
272
              #13#10 +
271
              #13#10 +
273
              Format(LNG_MODE, [mode]) + #13#10 +
272
              Format(LNG_MODE, [mode]) + #13#10 +
274
              Format(LNG_STONES_TOTAL, [LevelTotalStones]) + #13#10 +
273
              Format(LNG_STONES_TOTAL, [LevelTotalStones]) + #13#10 +
275
              goalYesNo);
274
              goalYesNo);
276
end;
275
end;
277
 
276
 
278
procedure TMainForm.DoJump(SourceTag, DestTag: integer);
277
procedure TMainForm.DoJump(SourceTag, DestTag: integer);
279
resourcestring
278
resourcestring
280
  LNG_JUMP_LOG = '%d [%d, %d] -> %d [%d, %d];';
279
  LNG_JUMP_LOG = '[%d, %d] -> [%d, %d];';
281
var
280
var
282
  d, s: TCoord;
281
  d, s: TCoord;
283
  old_fieldtype: TFieldType;
282
  old_fieldtype: TFieldType;
284
  res: Integer;
283
  res: Integer;
285
begin
284
begin
286
  if not MayJump(SourceTag, DestTag) then exit;
285
  if not MayJump(SourceTag, DestTag) then exit;
287
 
286
 
288
  s := PlaygroundMatrix.IndexToCoord(SourceTag);
287
  s := PlaygroundMatrix.IndexToCoord(SourceTag);
289
  d := PlaygroundMatrix.IndexToCoord(DestTag);
288
  d := PlaygroundMatrix.IndexToCoord(DestTag);
290
 
289
 
291
  JumpHistory.Add(Format(LNG_JUMP_LOG, [SourceTag+1, s.x+1, s.y+1, DestTag+1, d.x+1, d.y+1]));
290
  JumpHistory.Add(Format(LNG_JUMP_LOG, [s.x+1, s.y+1, d.x+1, d.y+1]));
292
 
291
 
293
  {$REGION 'Stein entfernen und Punkte vergeben'}
292
  {$REGION 'Stein entfernen und Punkte vergeben'}
294
  if Level.GameMode = gmDiagonal then
293
  if Level.GameMode = gmDiagonal then
295
  begin
294
  begin
296
    if (s.X-2 = d.X) and (s.Y-2 = d.Y) and (PlayGroundMatrix.FieldState(s.X-1, s.Y-1) = fsStone) then RemoveStone(s.X-1, s.Y-1, true);
295
    if (s.X-2 = d.X) and (s.Y-2 = d.Y) and (PlayGroundMatrix.FieldState(s.X-1, s.Y-1) = fsOccupied) then RemoveStone(s.X-1, s.Y-1, true);
297
    if (s.X-2 = d.X) and (s.Y+2 = d.Y) and (PlayGroundMatrix.FieldState(s.X-1, s.Y+1) = fsStone) then RemoveStone(s.X-1, s.Y+1, true);
296
    if (s.X-2 = d.X) and (s.Y+2 = d.Y) and (PlayGroundMatrix.FieldState(s.X-1, s.Y+1) = fsOccupied) then RemoveStone(s.X-1, s.Y+1, true);
298
    if (s.X+2 = d.X) and (s.Y-2 = d.Y) and (PlayGroundMatrix.FieldState(s.X+1, s.Y-1) = fsStone) then RemoveStone(s.X+1, s.Y-1, true);
297
    if (s.X+2 = d.X) and (s.Y-2 = d.Y) and (PlayGroundMatrix.FieldState(s.X+1, s.Y-1) = fsOccupied) then RemoveStone(s.X+1, s.Y-1, true);
299
    if (s.X+2 = d.X) and (s.Y+2 = d.Y) and (PlayGroundMatrix.FieldState(s.X+1, s.Y+1) = fsStone) then RemoveStone(s.X+1, s.Y+1, true);
298
    if (s.X+2 = d.X) and (s.Y+2 = d.Y) and (PlayGroundMatrix.FieldState(s.X+1, s.Y+1) = fsOccupied) then RemoveStone(s.X+1, s.Y+1, true);
300
  end;
299
  end;
301
 
300
 
302
  if (s.X+2 = d.X) and (s.Y = d.Y) and (PlayGroundMatrix.FieldState(s.X+1, s.Y  ) = fsStone) then RemoveStone(s.X+1, s.Y, true);
301
  if (s.X+2 = d.X) and (s.Y = d.Y) and (PlayGroundMatrix.FieldState(s.X+1, s.Y  ) = fsOccupied) then RemoveStone(s.X+1, s.Y, true);
303
  if (s.X-2 = d.X) and (s.Y = d.Y) and (PlayGroundMatrix.FieldState(s.X-1, s.Y  ) = fsStone) then RemoveStone(s.X-1, s.Y, true);
302
  if (s.X-2 = d.X) and (s.Y = d.Y) and (PlayGroundMatrix.FieldState(s.X-1, s.Y  ) = fsOccupied) then RemoveStone(s.X-1, s.Y, true);
304
  if (s.X = d.X) and (s.Y+2 = d.Y) and (PlayGroundMatrix.FieldState(s.X  , s.Y+1) = fsStone) then RemoveStone(s.X, s.Y+1, true);
303
  if (s.X = d.X) and (s.Y+2 = d.Y) and (PlayGroundMatrix.FieldState(s.X  , s.Y+1) = fsOccupied) then RemoveStone(s.X, s.Y+1, true);
305
  if (s.X = d.X) and (s.Y-2 = d.Y) and (PlayGroundMatrix.FieldState(s.X  , s.Y-1) = fsStone) then RemoveStone(s.X, s.Y-1, true);
304
  if (s.X = d.X) and (s.Y-2 = d.Y) and (PlayGroundMatrix.FieldState(s.X  , s.Y-1) = fsOccupied) then RemoveStone(s.X, s.Y-1, true);
306
  {$ENDREGION}
305
  {$ENDREGION}
307
 
306
 
308
  // Den Timer erst nach dem ersten Zug starten
307
  // Den Timer erst nach dem ersten Zug starten
309
  // oder nach einer Pause neustarten
308
  // oder nach einer Pause neustarten
310
  MPauseTime.Checked := false;
309
  MPauseTime.Checked := false;
311
  MPauseTime.Enabled := true;
310
  MPauseTime.Enabled := true;
312
  Timer.Enabled := true;
311
  Timer.Enabled := true;
313
 
312
 
314
  // Sound abspielen
313
  // Sound abspielen
315
  if MEnableSound.Checked then PlaySound(RES_JUMP, HInstance, SND_ASYNC or SND_NOWAIT or SND_RESOURCE);
314
  if MEnableSound.Checked then PlaySound(RES_JUMP, HInstance, SND_ASYNC or SND_NOWAIT or SND_RESOURCE);
316
 
315
 
317
  {$REGION 'Nun den Stein springen lassen'}
316
  {$REGION 'Nun den Stein springen lassen'}
318
  old_fieldtype := PlayGroundMatrix.Fields[s.X, s.Y].FieldType; // Steinfarbe merken
317
  old_fieldtype := PlayGroundMatrix.Fields[s.X, s.Y].FieldType; // Steinfarbe merken
319
  RemoveStone(s.X, s.Y, false); // Eigenen Stein entfernen. Keine Punkte zählen, da das unser eigener Stein ist, der springt
318
  RemoveStone(s.X, s.Y, false); // Eigenen Stein entfernen. Keine Punkte zählen, da das unser eigener Stein ist, der springt
320
  PlayGroundMatrix.Fields[d.X, d.Y].FieldType := old_fieldtype; // Farbe wiederherstellen
319
  PlayGroundMatrix.Fields[d.X, d.Y].FieldType := old_fieldtype; // Farbe wiederherstellen
321
  LoadPictureForType(PlayGroundMatrix.Fields[d.X, d.Y].FieldType, PlayGroundMatrix.Fields[d.X, d.Y].Stone.Picture); // Stein an neue Position malen
320
  LoadPictureForType(PlayGroundMatrix.Fields[d.X, d.Y].FieldType, PlayGroundMatrix.Fields[d.X, d.Y].Stone.Picture); // Stein an neue Position malen
322
  StoneDraggingAllow(PlayGroundMatrix.Fields[d.X, d.Y].Stone, true); // Und die Drag-Eigenschaft erneuern
321
  StoneDraggingAllow(PlayGroundMatrix.Fields[d.X, d.Y].Stone, true); // Und die Drag-Eigenschaft erneuern
323
  {$ENDREGION}
322
  {$ENDREGION}
324
 
323
 
325
  {$REGION 'Sind weitere Sprünge möglich oder ist das Spiel vorbei?'}
324
  {$REGION 'Sind weitere Sprünge möglich oder ist das Spiel vorbei?'}
326
  if not PlayGroundMatrix.CanJump(Level.GameMode = gmDiagonal) then
325
  if not PlayGroundMatrix.CanJump(Level.GameMode = gmDiagonal) then
327
  begin
326
  begin
328
    MPauseTime.Checked := false;
327
    MPauseTime.Checked := false;
329
    MPauseTime.Enabled := false;
328
    MPauseTime.Enabled := false;
330
    Timer.Enabled := false;
329
    Timer.Enabled := false;
331
    RefreshTime;
330
    RefreshTime;
332
    if MEnableSound.Checked then
331
    if MEnableSound.Checked then
333
    begin
332
    begin
334
      if LevelRemovedStones = LevelTotalStones-1 then
333
      if LevelRemovedStones = LevelTotalStones-1 then
335
      begin
334
      begin
336
        if GoalStatus in [gsLastStoneInGoalRed, gsLastStoneInGoalYellow, gsLastStoneInGoalGreen] then
335
        if GoalStatus in [gsLastStoneInGoalRed, gsLastStoneInGoalYellow, gsLastStoneInGoalGreen] then
337
          PlaySound(RES_WIN2, HInstance, SND_ASYNC or SND_NOWAIT or SND_RESOURCE)
336
          PlaySound(RES_WIN2, HInstance, SND_ASYNC or SND_NOWAIT or SND_RESOURCE)
338
        else
337
        else
339
          PlaySound(RES_WIN1, HInstance, SND_ASYNC or SND_NOWAIT or SND_RESOURCE)
338
          PlaySound(RES_WIN1, HInstance, SND_ASYNC or SND_NOWAIT or SND_RESOURCE)
340
      end
339
      end
341
      else
340
      else
342
        PlaySound(RES_LOSE, HInstance, SND_ASYNC or SND_NOWAIT or SND_RESOURCE);
341
        PlaySound(RES_LOSE, HInstance, SND_ASYNC or SND_NOWAIT or SND_RESOURCE);
343
    end;
342
    end;
344
    res := FinishForm.Execute(ExtractFileNameWithoutExt(LevelFile), Points, LevelTotalStones, LevelRemovedStones, CountedSeconds, GoalStatus, JumpHistory);
343
    res := FinishForm.Execute(ExtractFileNameWithoutExt(LevelFile), Points, LevelTotalStones, LevelRemovedStones, CountedSeconds, GoalStatus, JumpHistory);
345
    if (res = mrOK) and FinishForm.ReplayCheckbox.Checked then RestartLevel;
344
    if (res = mrOK) and FinishForm.ReplayCheckbox.Checked then RestartLevel;
346
  end;
345
  end;
347
  {$ENDREGION}
346
  {$ENDREGION}
348
 
347
 
349
  SetLength(PrevPlaygroundMatrixes, Length(PrevPlaygroundMatrixes)+1);
348
  SetLength(PrevPlaygroundMatrixes, Length(PrevPlaygroundMatrixes)+1);
350
  PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1] := PlaygroundMatrix.CloneMatrix;
349
  PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1] := PlaygroundMatrix.CloneMatrix;
351
  MUndo.Enabled := true;
350
  MUndo.Enabled := true;
352
end;
351
end;
353
 
352
 
354
function TMainForm.MayJump(SourceTag, DestTag: integer): boolean;
353
function TMainForm.MayJump(SourceTag, DestTag: integer): boolean;
355
var
354
var
356
  s, d: TCoord;
355
  s, d: TCoord;
357
begin
356
begin
358
  s := PlayGroundMatrix.IndexToCoord(SourceTag);
357
  s := PlayGroundMatrix.IndexToCoord(SourceTag);
359
  d := PlayGroundMatrix.IndexToCoord(DestTag);
358
  d := PlayGroundMatrix.IndexToCoord(DestTag);
360
 
359
 
361
  result := PlaygroundMatrix.CanJump(s.X, s.Y, d.X, d.Y, Level.GameMode = gmDiagonal);
360
  result := PlaygroundMatrix.CanJump(s, d, Level.GameMode = gmDiagonal);
362
end;
361
end;
363
 
362
 
364
procedure TMainForm.StoneDragDrop(Sender, Source: TObject; X, Y: Integer);
363
procedure TMainForm.StoneDragDrop(Sender, Source: TObject; X, Y: Integer);
365
begin
364
begin
366
  DoJump(TComponent(Source).Tag, TComponent(Sender).Tag);
365
  DoJump(TComponent(Source).Tag, TComponent(Sender).Tag);
367
end;
366
end;
368
 
367
 
369
procedure TMainForm.StoneDragOver(Sender, Source: TObject; X,
368
procedure TMainForm.StoneDragOver(Sender, Source: TObject; X,
370
  Y: Integer; State: TDragState; var Accept: Boolean);
369
  Y: Integer; State: TDragState; var Accept: Boolean);
371
begin
370
begin
372
  Accept := MayJump(TComponent(Source).Tag, TComponent(Sender).Tag);
371
  Accept := MayJump(TComponent(Source).Tag, TComponent(Sender).Tag);
373
end;
372
end;
374
 
373
 
375
function TMainForm.DrawField(x, y: integer; t: TFieldProperties; indent: integer): TField;
374
procedure TMainForm.DrawField(x, y: integer; var f: TField);
376
var
375
var
377
  newField: TField;
-
 
378
  index: integer;
376
  index: integer;
379
begin
377
begin
380
  ZeroMemory(@result, SizeOf(result));
-
 
381
  if t.Typ = ftFullSpace then exit;
378
  if f.FieldType = ftFullSpace then exit;
382
 
379
 
383
  index := PlaygroundMatrix.CoordToIndex(x, y);
380
  index := PlaygroundMatrix.CoordToIndex(x, y);
384
 
381
 
-
 
382
  f.Panel := DrawStoneBox(x, y, index, f.indent, f.Goal);
385
  newField.FieldType := t.Typ;
383
  f.Stone := DrawStone(f.FieldType, f.Panel);
-
 
384
end;
-
 
385
 
386
  newField.Goal := t.Goal;
386
procedure TMainForm.TimerTimer(Sender: TObject);
-
 
387
begin
387
  newField.Panel := DrawStoneBox(x, y, index, indent, t.Goal);
388
  if MPauseTime.Checked then exit;
388
  newField.Stone := DrawStone(t.Typ, newField.Panel);
389
  if mainform.Focused then Inc(CountedSeconds);
-
 
390
  RefreshTime;
-
 
391
end;
389
 
392
 
390
  result := newField;
393
function TMainForm.LevelTime: String;
-
 
394
begin
-
 
395
  result := FormatDateTime('hh:nn:ss', CountedSeconds / SecsPerDay)
391
end;
396
end;
392
 
397
 
393
procedure TMainForm.BuildPlayground(LevelArray: TLevelArray);
398
procedure TMainForm.NewGame(Filename: string);
-
 
399
resourcestring
-
 
400
  LNG_LVL_INVALID_NO_JUMP = 'Warning! The level is not playable. There are no jumps possible.';
394
var
401
var
395
  y, x: integer;
402
  y, x: integer;
396
  max_x, max_y: integer;
403
  max_x, max_y: integer;
397
  p: TPanel;
404
  p: TPanel;
398
  newField: TField;
-
 
399
begin
405
begin
400
  PlayGround.Visible := false;
406
  DestroyLevel;
401
 
407
 
-
 
408
  MPauseTime.Checked := true;
-
 
409
  MPauseTime.Enabled := true;
-
 
410
  Timer.Enabled := true;
-
 
411
  MRestartGame.Enabled := true;
-
 
412
 
-
 
413
  LevelFile := Filename;
-
 
414
  Level := TLevel.Create(LevelFile);
-
 
415
 
402
  // Attention: PlaygroundMatrix is indexed [x,y] while LevelArray is indexed [y,x]
416
  Level.FillPlaygroundMatrix(PlaygroundMatrix, true);
403
  // TODO: PlaygroundMatrix and LevelArray are redundant. Can't we just replace one with the other?
417
  if Length(PlaygroundMatrix.Fields) = 0 then Exit;
-
 
418
 
404
  PlaygroundMatrix.InitFieldArray(Length(LevelArray[0].Fields), Length(LevelArray));
419
  PlayGround.Visible := false;
405
 
420
 
406
  max_x := 0;
421
  max_x := 0;
407
  max_y := 0;
422
  max_y := 0;
408
  for y := Low(LevelArray) to High(LevelArray) do
423
  for x := Low(PlaygroundMatrix.Fields) to High(PlaygroundMatrix.Fields) do
409
  begin
424
  begin
410
    for x := Low(LevelArray[y].Fields) to High(LevelArray[y].Fields) do
425
    for y := Low(PlaygroundMatrix.Fields[x]) to High(PlaygroundMatrix.Fields[x]) do
411
    begin
426
    begin
412
      if TPlayGroundMatrix.FieldState(LevelArray[y].Fields[x].Typ) = fsStone then
427
      if TPlayGroundMatrix.FieldState(PlaygroundMatrix.Fields[x,y].FieldType) = fsOccupied then
413
        Inc(LevelTotalStones);
428
        Inc(LevelTotalStones);
414
      newField := DrawField(x, y, LevelArray[y].Fields[x], LevelArray[y].Indent);
429
      DrawField(x, y, PlaygroundMatrix.Fields[x,y]);
415
      PlaygroundMatrix.Fields[x, y] := newField;
430
      p := PlaygroundMatrix.Fields[x,y].Panel;
416
      p := newField.Panel;
-
 
417
      if Assigned(p) then
431
      if Assigned(p) then
418
      begin
432
      begin
419
        max_x := Max(max_x, p.Left + p.Width);
433
        max_x := Max(max_x, p.Left + p.Width);
420
        max_y := Max(max_y, p.Top  + p.Height);
434
        max_y := Max(max_y, p.Top  + p.Height);
421
      end;
435
      end;
422
    end;
436
    end;
423
  end;
437
  end;
424
 
438
 
425
  PlayGround.Visible := true;
439
  PlayGround.Visible := true;
426
 
440
 
427
  // Das Form an das Level anpassen
441
  // Das Form an das Level anpassen
428
  PlayGround.Top    := MET_OUTER_MARGIN;
442
  PlayGround.Top    := MET_OUTER_MARGIN;
429
  PlayGround.Left   := MET_OUTER_MARGIN;
443
  PlayGround.Left   := MET_OUTER_MARGIN;
430
  PlayGround.Width  := max_x;
444
  PlayGround.Width  := max_x;
431
  PlayGround.Height := max_y;
445
  PlayGround.Height := max_y;
432
  ClientWidth       := 2 * MET_OUTER_MARGIN + PlayGround.Width;
446
  ClientWidth       := 2 * MET_OUTER_MARGIN + PlayGround.Width;
433
  ClientHeight      := 2 * MET_OUTER_MARGIN + PlayGround.Height + Statistics.Height;
447
  ClientHeight      := 2 * MET_OUTER_MARGIN + PlayGround.Height + Statistics.Height;
434
 
448
 
435
  // If the board is too small, ClientWidth/ClientHeight will stop at a minimum value
449
  // If the board is too small, ClientWidth/ClientHeight will stop at a minimum value
436
  // in this case, we make sure that the Playground is centered
450
  // in this case, we make sure that the Playground is centered
437
  PlayGround.Left := ClientWidth div 2 - Playground.Width div 2;
451
  PlayGround.Left := ClientWidth div 2 - Playground.Width div 2;
438
  PlayGround.Top := (ClientHeight - Statistics.Height) div 2 - Playground.Height div 2;
452
  PlayGround.Top := (ClientHeight - Statistics.Height) div 2 - Playground.Height div 2;
439
 
453
 
440
  Statistics.Panels.Items[0].Width := Round(ClientWidth*MET_PERCENT_PNL_TIME);
454
  Statistics.Panels.Items[0].Width := Round(ClientWidth * MET_PERCENT_PNL_TIME);
441
  Statistics.Panels.Items[1].Width := Round(ClientWidth*MET_PERCENT_PNL_STONES);
455
  Statistics.Panels.Items[1].Width := Round(ClientWidth * MET_PERCENT_PNL_STONES);
442
 
456
 
443
  SetLength(PrevPlaygroundMatrixes,1);
457
  SetLength(PrevPlaygroundMatrixes,1);
444
  PrevPlaygroundMatrixes[0] := PlayGroundMatrix.CloneMatrix;
458
  PrevPlaygroundMatrixes[0] := PlayGroundMatrix.CloneMatrix;
445
  MUndo.Enabled := false;
459
  MUndo.Enabled := false;
446
end;
-
 
447
 
460
 
448
procedure TMainForm.TimerTimer(Sender: TObject);
-
 
449
begin
-
 
450
  if MPauseTime.Checked then exit;
-
 
451
  if mainform.Focused then Inc(CountedSeconds);
-
 
452
  RefreshTime;
-
 
453
end;
-
 
454
 
-
 
455
function TMainForm.LevelTime: String;
-
 
456
begin
-
 
457
  result := FormatDateTime('hh:nn:ss', CountedSeconds / SecsPerDay)
-
 
458
end;
-
 
459
 
-
 
460
procedure TMainForm.NewGame(Filename: string);
-
 
461
resourcestring
-
 
462
  LNG_LVL_INVALID_NO_JUMP = 'Warning! The level is not playable. There are no jumps possible.';
-
 
463
var
-
 
464
  LevelArray: TLevelArray;
-
 
465
begin
-
 
466
  DestroyLevel;
-
 
467
 
-
 
468
  MPauseTime.Checked := true;
-
 
469
  MPauseTime.Enabled := true;
-
 
470
  Timer.Enabled := true;
-
 
471
  MRestartGame.Enabled := true;
-
 
472
 
-
 
473
  LevelFile := Filename;
-
 
474
  Level := TLevel.Create(LevelFile);
-
 
475
  LevelArray := Level.LevelStringToLevelArray(true);
-
 
476
  if Length(LevelArray) = 0 then Exit;
-
 
477
  BuildPlayground(LevelArray);
-
 
478
  if not PlayGroundMatrix.CanJump(Level.GameMode = gmDiagonal) then
461
  if not PlayGroundMatrix.CanJump(Level.GameMode = gmDiagonal) then
479
  begin
462
  begin
480
    MessageDlg(LNG_LVL_INVALID_NO_JUMP, mtError, [mbOk], 0);
463
    MessageDlg(LNG_LVL_INVALID_NO_JUMP, mtError, [mbOk], 0);
481
  end;
464
  end;
482
  RefreshTime;
465
  RefreshTime;
483
  RefreshStonesRemoved;
466
  RefreshStonesRemoved;
484
  RefreshPoints;
467
  RefreshPoints;
485
end;
468
end;
486
 
469
 
487
procedure TMainForm.MNewGameClick(Sender: TObject);
470
procedure TMainForm.MNewGameClick(Sender: TObject);
488
begin
471
begin
489
  LevelFile := AskForLevel;
472
  LevelFile := AskForLevel;
490
  if LevelFile <> '' then
473
  if LevelFile <> '' then
491
  begin
474
  begin
492
    NewGame(LevelFile);
475
    NewGame(LevelFile);
493
  end;
476
  end;
494
end;
477
end;
495
 
478
 
496
procedure TMainForm.MAboutClick(Sender: TObject);
479
procedure TMainForm.MAboutClick(Sender: TObject);
497
begin
480
begin
498
  AboutBox.ShowModal;
481
  AboutBox.ShowModal;
499
end;
482
end;
500
 
483
 
501
function TMainForm.AskForLevel: String;
484
function TMainForm.AskForLevel: String;
502
begin
485
begin
503
  LevelChoice.ShowModal;
486
  LevelChoice.ShowModal;
504
 
487
 
505
  if LevelChoice.ModalResult <> mrOK then
488
  if LevelChoice.ModalResult <> mrOK then
506
  begin
489
  begin
507
    result := '';
490
    result := '';
508
    exit;
491
    exit;
509
  end;
492
  end;
510
 
493
 
511
  result := LevelChoice.SelectedLevel;
494
  result := LevelChoice.SelectedLevel;
512
end;
495
end;
513
 
496
 
514
procedure TMainForm.FormShow(Sender: TObject);
497
procedure TMainForm.FormShow(Sender: TObject);
515
begin
498
begin
516
  LevelFile := AskForLevel;
499
  LevelFile := AskForLevel;
517
  if LevelFile <> '' then
500
  if LevelFile <> '' then
518
  begin
501
  begin
519
    NewGame(LevelFile);
502
    NewGame(LevelFile);
520
  end
503
  end
521
  else
504
  else
522
  begin
505
  begin
523
    NoCloseQuery := true;
506
    NoCloseQuery := true;
524
    Close;
507
    Close;
525
  end;
508
  end;
526
end;
509
end;
527
 
510
 
528
function TMainForm.GoalStatus: TGoalStatus;
511
function TMainForm.GoalStatus: TGoalStatus;
529
var
512
var
530
  ft: TFieldType;
513
  ft: TFieldType;
531
begin
514
begin
532
  if not PlaygroundMatrix.MatrixHasGoal then
515
  if not PlaygroundMatrix.MatrixHasGoal then
533
    result := gsNoGoal
516
    result := gsNoGoal
534
  else if LevelRemovedStones < LevelTotalStones-1 then
517
  else if LevelRemovedStones < LevelTotalStones-1 then
535
    Result := gsMultipleStonesRemaining
518
    Result := gsMultipleStonesRemaining
536
  else
519
  else
537
  begin
520
  begin
538
    ft := PlaygroundMatrix.GoalFieldType;
521
    ft := PlaygroundMatrix.GoalFieldType;
539
    if ft = ftRed then
522
    if ft = ftRed then
540
      result := gsLastStoneInGoalRed
523
      result := gsLastStoneInGoalRed
541
    else if ft = ftYellow then
524
    else if ft = ftYellow then
542
      result := gsLastStoneInGoalYellow
525
      result := gsLastStoneInGoalYellow
543
    else if ft = ftGreen then
526
    else if ft = ftGreen then
544
      result := gsLastStoneInGoalGreen
527
      result := gsLastStoneInGoalGreen
545
    else
528
    else
546
      result := gsUndefined;
529
      result := gsUndefined;
547
  end;
530
  end;
548
end;
531
end;
549
 
532
 
550
procedure TMainForm.FormCreate(Sender: TObject);
533
procedure TMainForm.FormCreate(Sender: TObject);
551
begin
534
begin
552
  JumpHistory := TStringList.Create;
535
  JumpHistory := TStringList.Create;
553
  LoadSettings;
536
  LoadSettings;
554
end;
537
end;
555
 
538
 
556
procedure TMainForm.FormDestroy(Sender: TObject);
539
procedure TMainForm.FormDestroy(Sender: TObject);
557
begin
540
begin
558
  DestroyLevel;
541
  DestroyLevel;
559
  JumpHistory.Free;
542
  JumpHistory.Free;
560
end;
543
end;
561
 
544
 
562
procedure TMainForm.MJumpHistoryClick(Sender: TObject);
545
procedure TMainForm.MJumpHistoryClick(Sender: TObject);
563
begin
546
begin
564
  HistoryForm.JumpMemo.Lines.Assign(JumpHistory);
547
  HistoryForm.JumpMemo.Lines.Assign(JumpHistory);
565
  HistoryForm.ShowModal;
548
  HistoryForm.ShowModal;
566
end;
549
end;
567
 
550
 
568
procedure TMainForm.RestartLevel;
551
procedure TMainForm.RestartLevel;
569
var
552
var
570
  i: Integer;
553
  i: Integer;
571
begin
554
begin
572
  MPauseTime.Checked := true;
555
  MPauseTime.Checked := true;
573
  MPauseTime.Enabled := true;
556
  MPauseTime.Enabled := true;
574
  Timer.Enabled := true;
557
  Timer.Enabled := true;
575
 
558
 
576
  CountedSeconds := 0;
559
  CountedSeconds := 0;
577
  RefreshTime;
560
  RefreshTime;
578
 
561
 
579
  Points := 0;
562
  Points := 0;
580
  RefreshPoints;
563
  RefreshPoints;
581
 
564
 
582
  LevelRemovedStones := 0;
565
  LevelRemovedStones := 0;
583
  RefreshStonesRemoved;
566
  RefreshStonesRemoved;
584
 
567
 
585
  JumpHistory.Clear;
568
  JumpHistory.Clear;
586
 
569
 
587
  RedrawStonesFromMatrix(PrevPlaygroundMatrixes[0]);
570
  RedrawStonesFromMatrix(PrevPlaygroundMatrixes[0]);
588
  SetNewPlayGroundMatrix(PrevPlaygroundMatrixes[0]);
571
  SetNewPlayGroundMatrix(PrevPlaygroundMatrixes[0]);
589
  for i := 1 to Length(PrevPlaygroundMatrixes)-1 do
572
  for i := 1 to Length(PrevPlaygroundMatrixes)-1 do
590
    PrevPlaygroundMatrixes[i].ClearMatrix(false);
573
    PrevPlaygroundMatrixes[i].ClearMatrix(false);
591
  SetLength(PrevPlaygroundMatrixes, 1);
574
  SetLength(PrevPlaygroundMatrixes, 1);
592
 
575
 
593
  MUndo.Enabled := false;
576
  MUndo.Enabled := false;
594
end;
577
end;
595
 
578
 
596
procedure TMainForm.SetNewPlayGroundMatrix(Matrix: TPlayGroundMatrix);
579
procedure TMainForm.SetNewPlayGroundMatrix(Matrix: TPlayGroundMatrix);
597
begin
580
begin
598
  PlayGroundMatrix.ClearMatrix(false); // Memory Leak verhindern
581
  PlayGroundMatrix.ClearMatrix(false); // Memory Leak verhindern
599
  PlayGroundMatrix := Matrix.CloneMatrix;
582
  PlayGroundMatrix := Matrix.CloneMatrix;
600
end;
583
end;
601
 
584
 
602
procedure TMainForm.MRestartGameClick(Sender: TObject);
585
procedure TMainForm.MRestartGameClick(Sender: TObject);
603
begin
586
begin
604
  RestartLevel;
587
  RestartLevel;
605
end;
588
end;
606
 
589
 
607
procedure TMainForm.MUndoClick(Sender: TObject);
590
procedure TMainForm.MUndoClick(Sender: TObject);
608
var
591
var
609
  PrevWorth: integer;
592
  PrevWorth: integer;
610
  NewWorth: integer;
593
  NewWorth: integer;
611
begin
594
begin
612
  if Length(PrevPlaygroundMatrixes) > 1 then
595
  if Length(PrevPlaygroundMatrixes) > 1 then
613
  begin
596
  begin
614
    PrevWorth := PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1].MatrixWorth;
597
    PrevWorth := PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1].MatrixWorth;
615
 
598
 
616
    PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1].ClearMatrix(false);
599
    PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1].ClearMatrix(false);
617
    SetLength(PrevPlaygroundMatrixes, Length(PrevPlaygroundMatrixes)-1);
600
    SetLength(PrevPlaygroundMatrixes, Length(PrevPlaygroundMatrixes)-1);
618
 
601
 
619
    NewWorth := PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1].MatrixWorth;
602
    NewWorth := PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1].MatrixWorth;
620
    RedrawStonesFromMatrix(PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1]);
603
    RedrawStonesFromMatrix(PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1]);
621
    SetNewPlayGroundMatrix(PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1]);
604
    SetNewPlayGroundMatrix(PrevPlaygroundMatrixes[Length(PrevPlaygroundMatrixes)-1]);
622
 
605
 
623
    JumpHistory.Delete(JumpHistory.Count-1);
606
    JumpHistory.Delete(JumpHistory.Count-1);
624
 
607
 
625
    Dec(LevelRemovedStones);
608
    Dec(LevelRemovedStones);
626
    RefreshStonesRemoved;
609
    RefreshStonesRemoved;
627
 
610
 
628
    Dec(Points, NewWorth-PrevWorth);
611
    Dec(Points, NewWorth-PrevWorth);
629
    RefreshPoints;
612
    RefreshPoints;
630
 
613
 
631
    // Sound abspielen
614
    // Sound abspielen
632
    if MEnableSound.Checked then PlaySound(RES_UNDO, HInstance, SND_ASYNC or SND_NOWAIT or SND_RESOURCE);
615
    if MEnableSound.Checked then PlaySound(RES_UNDO, HInstance, SND_ASYNC or SND_NOWAIT or SND_RESOURCE);
633
  end;
616
  end;
634
 
617
 
635
  MUndo.Enabled := Length(PrevPlaygroundMatrixes) > 1;
618
  MUndo.Enabled := Length(PrevPlaygroundMatrixes) > 1;
636
end;
619
end;
637
 
620
 
638
procedure TMainForm.MHighScoresClick(Sender: TObject);
621
procedure TMainForm.MHighScoresClick(Sender: TObject);
639
begin
622
begin
640
  HighScoreForm.Execute(ExtractFileNameWithoutExt(LevelFile));
623
  HighScoreForm.Execute(ExtractFileNameWithoutExt(LevelFile));
641
end;
624
end;
642
 
625
 
643
procedure TMainForm.LoadSettings;
626
procedure TMainForm.LoadSettings;
644
var
627
var
645
  reg: TRegistry;
628
  reg: TRegistry;
646
begin
629
begin
647
  reg := TRegistry.Create;
630
  reg := TRegistry.Create;
648
  try
631
  try
649
    reg.RootKey := HKEY_CURRENT_USER;
632
    reg.RootKey := HKEY_CURRENT_USER;
650
    if reg.OpenKeyReadOnly(REG_KEY) then
633
    if reg.OpenKeyReadOnly(REG_KEY) then
651
    begin
634
    begin
652
      if reg.ValueExists(REG_SOUND) then
635
      if reg.ValueExists(REG_SOUND) then
653
        MEnableSound.Checked := reg.ReadBool(REG_SOUND);
636
        MEnableSound.Checked := reg.ReadBool(REG_SOUND);
654
      reg.CloseKey;
637
      reg.CloseKey;
655
    end;
638
    end;
656
  finally
639
  finally
657
    reg.Free;
640
    reg.Free;
658
  end;
641
  end;
659
end;
642
end;
660
 
643
 
661
procedure TMainForm.SaveSettings;
644
procedure TMainForm.SaveSettings;
662
var
645
var
663
  reg: TRegistry;
646
  reg: TRegistry;
664
begin
647
begin
665
  reg := TRegistry.Create;
648
  reg := TRegistry.Create;
666
  try
649
  try
667
    reg.RootKey := HKEY_CURRENT_USER;
650
    reg.RootKey := HKEY_CURRENT_USER;
668
    if reg.OpenKey(REG_KEY, true) then
651
    if reg.OpenKey(REG_KEY, true) then
669
    begin
652
    begin
670
      reg.WriteBool(REG_SOUND, MEnableSound.Checked);
653
      reg.WriteBool(REG_SOUND, MEnableSound.Checked);
671
      reg.CloseKey;
654
      reg.CloseKey;
672
    end;
655
    end;
673
  finally
656
  finally
674
    reg.Free;
657
    reg.Free;
675
  end;
658
  end;
676
end;
659
end;
677
 
660
 
678
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
661
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
679
begin
662
begin
680
  SaveSettings;
663
  SaveSettings;
681
  if FinishForm.NameEdit.Text <> '' then
664
  if FinishForm.NameEdit.Text <> '' then
682
  begin
665
  begin
683
    FinishForm.SaveSettings;
666
    FinishForm.SaveSettings;
684
  end;
667
  end;
685
end;
668
end;
686
 
669
 
687
procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
670
procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
688
resourcestring
671
resourcestring
689
  LNG_REALLY_QUIT = 'Do you really want to quit?';
672
  LNG_REALLY_QUIT = 'Do you really want to quit?';
690
begin
673
begin
691
  CanClose := NoCloseQuery or (MessageDlg(LNG_REALLY_QUIT, mtConfirmation, mbYesNoCancel, 0) = mrYes);
674
  CanClose := NoCloseQuery or (MessageDlg(LNG_REALLY_QUIT, mtConfirmation, mbYesNoCancel, 0) = mrYes);
692
end;
675
end;
693
 
676
 
694
procedure TMainForm.MHelpClick(Sender: TObject);
677
procedure TMainForm.MHelpClick(Sender: TObject);
695
begin
678
begin
696
  HelpForm.ShowModal;
679
  HelpForm.ShowModal;
697
end;
680
end;
698
 
681
 
699
end.
682
end.
700
 
683