source: tags/1.2.0/Forms/UFormComputer.pas

Last change on this file was 50, checked in by chronos, 5 years ago
  • Added: Support for dark theme.
File size: 6.5 KB
Line 
1unit UFormComputer;
2
3{$mode delphi}
4
5interface
6
7uses
8 Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls,
9 UGame, fgl;
10
11type
12 { TGameTry }
13
14 TGameTry = class
15 Game: TGame;
16 Moves: array of TMoveDirection;
17 constructor Create;
18 destructor Destroy; override;
19 procedure Assign(Source: TGameTry);
20 private
21 function GetFitness: Double;
22 function GetFitnessSnake: Double;
23 end;
24
25 TGameTries = class(TFPGObjectList<TGameTry>)
26 end;
27
28 { TFormComputer }
29
30 TFormComputer = class(TForm)
31 ButtonStart: TButton;
32 ButtonStop: TButton;
33 Label1: TLabel;
34 TrackBar1: TTrackBar;
35 procedure ButtonStartClick(Sender: TObject);
36 procedure ButtonStopClick(Sender: TObject);
37 procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
38 procedure FormCreate(Sender: TObject);
39 procedure FormDestroy(Sender: TObject);
40 procedure FormShow(Sender: TObject);
41 private
42 Stop: Boolean;
43 GameTries1: TGameTries;
44 GameTries2: TGameTries;
45 GameTries3: TGameTries;
46 GameTries4: TGameTries;
47 procedure TryAllDirections(GameTries: TGameTries; GameTry: TGameTry);
48 public
49
50 end;
51
52var
53 FormComputer: TFormComputer;
54
55implementation
56
57{$R *.lfm}
58
59uses
60 UCore;
61
62{ TGameTry }
63
64function TGameTry.GetFitness: Double;
65const
66 DirWeight: array[TMoveDirection] of Double = (0, 0.25, -10000, 0.5, 0.75);
67var
68 I: Integer;
69 WeightSnake: Double;
70 WeightMoves: Double;
71 WeightScore: Double;
72 WeightSteps: Double;
73begin
74 WeightSnake := 1000 * GetFitnessSnake;
75
76 WeightMoves := 0;
77 for I := 0 to Length(Moves) - 1 do
78 WeightMoves := WeightMoves + DirWeight[Moves[I]];
79 WeightMoves := WeightMoves / Length(Moves);
80
81 WeightScore := 100 * Game.Score / Game.Board.GetValueSum;
82 WeightSteps := 1 / Length(Moves) * 0.25;
83
84 Result := WeightScore + WeightSteps + WeightSnake + WeightMoves;
85end;
86
87function TGameTry.GetFitnessSnake: Double;
88var
89 P: TPoint;
90 HorizDir: Integer;
91 Sequence: Integer;
92 HighestValue: Integer;
93begin
94 HighestValue := Game.Board.GetHighestTileValue;
95 Sequence := (Game.Board.Size.X * Game.Board.Size.Y);
96 Result := 0;
97 P := Point(Game.Board.Size.X, Game.Board.Size.Y - 1);
98 HorizDir := -1;
99 while (P.Y >= 0) do begin
100 if ((P.X + HorizDir) < 0) or ((P.X + HorizDir) > (Game.Board.Size.X - 1)) then begin
101 HorizDir := -HorizDir;
102 Dec(P.Y);
103 if P.Y < 0 then Break;
104 end else Inc(P.X, HorizDir);
105 if Game.Board.Tiles[P.Y, P.X].Value <> 0 then begin
106 Result := Result + (Game.Board.Tiles[P.Y, P.X].Value / HighestValue) *
107 (Sequence / (Game.Board.Size.X * Game.Board.Size.Y));
108 end;
109 Dec(Sequence);
110 end;
111 Result := Result / (Game.Board.Size.X * Game.Board.Size.Y);
112end;
113
114constructor TGameTry.Create;
115begin
116 Game := TGame.Create;
117end;
118
119destructor TGameTry.Destroy;
120begin
121 FreeAndNil(Game);
122 inherited;
123end;
124
125procedure TGameTry.Assign(Source: TGameTry);
126var
127 I: Integer;
128begin
129 Game.Assign(Source.Game);
130 SetLength(Moves, Length(Source.Moves));
131 for I := 0 to Length(Moves) - 1 do
132 Moves[I] := Source.Moves[I];
133end;
134
135{ TFormComputer }
136
137procedure TFormComputer.FormClose(Sender: TObject; var CloseAction: TCloseAction
138 );
139begin
140 ButtonStopClick(Self);
141 Core.PersistentForm1.Save(Self);
142end;
143
144function GameCompareScore(const Item1, Item2: TGameTry): Integer;
145var
146 Score1: Double;
147 Score2: Double;
148begin
149 Score1 := Item1.GetFitness;
150 Score2 := Item2.GetFitness;
151 if Score1 > Score2 then Result := -1
152 else if Score1 < Score2 then Result := 1
153 else Result := 0;
154end;
155
156procedure TFormComputer.ButtonStartClick(Sender: TObject);
157var
158 NewTry: TGameTry;
159 S: string;
160 I: Integer;
161 J: Integer;
162 GameTries: TGameTries;
163begin
164 ButtonStart.Enabled := False;
165 ButtonStop.Enabled := True;
166 Stop := False;
167 with Core.Game do begin
168 while CanMove and not Stop do begin
169 NewTry := TGameTry.Create;
170 NewTry.Game.Assign(Core.Game);
171 GameTries1.Clear;
172 TryAllDirections(GameTries1, NewTry);
173 FreeAndNil(NewTry);
174 GameTries2.Clear;
175 for I := 0 to GameTries1.Count - 1 do
176 TryAllDirections(GameTries2, GameTries1[I]);
177 GameTries3.Clear;
178 for I := 0 to GameTries2.Count - 1 do
179 TryAllDirections(GameTries3, GameTries2[I]);
180 GameTries4.Clear;
181 for I := 0 to GameTries3.Count - 1 do
182 TryAllDirections(GameTries4, GameTries3[I]);
183
184 GameTries := GameTries4;
185 GameTries.Sort(GameCompareScore);
186 S := '';
187 for I := 0 to GameTries.Count - 1 do begin
188 S := S + FormatFloat('0.000', GameTries[I].GetFitness) + '(';
189 for J := 0 to Length(GameTries[I].Moves) - 1 do
190 S := S + DirectionText[GameTries[I].Moves[J]] + ' ';
191 S := S + '), ';
192 end;
193 MoveAllAndUpdate(GameTries[0].Moves[0], False);
194{ if CanMergeDirection(drDown) then MoveAllAnimate(drDown)
195 else if CanMergeDirection(drRight) then MoveAllAnimate(drRight)
196 else if CanMergeDirection(drLeft) then MoveAllAnimate(drLeft)
197 else if CanMoveDirection(drDown) then MoveAllAnimate(drDown)
198 else if CanMoveDirection(drRight) then MoveAllAnimate(drRight)
199 else if CanMoveDirection(drLeft) then MoveAllAnimate(drLeft)
200 else if CanMoveDirection(drUp) then MoveAllAnimate(drUp)
201 else Break;
202 }
203 Application.ProcessMessages;
204 Sleep(TrackBar1.Position);
205 end;
206 end;
207 ButtonStart.Enabled := True;
208 ButtonStop.Enabled := False;
209end;
210
211procedure TFormComputer.ButtonStopClick(Sender: TObject);
212begin
213 Stop := True;
214end;
215
216procedure TFormComputer.FormCreate(Sender: TObject);
217begin
218 Core.Translator1.TranslateComponentRecursive(Self);
219 Core.ThemeManager1.UseTheme(Self);
220 GameTries1 := TGameTries.Create;
221 GameTries2 := TGameTries.Create;
222 GameTries3 := TGameTries.Create;
223 GameTries4 := TGameTries.Create;
224end;
225
226procedure TFormComputer.FormDestroy(Sender: TObject);
227begin
228 FreeAndNil(GameTries1);
229 FreeAndNil(GameTries2);
230 FreeAndNil(GameTries3);
231 FreeAndNil(GameTries4);
232end;
233
234procedure TFormComputer.FormShow(Sender: TObject);
235begin
236 Core.PersistentForm1.Load(Self);
237end;
238
239procedure TFormComputer.TryAllDirections(GameTries: TGameTries; GameTry: TGameTry);
240var
241 Direction: TMoveDirection;
242 NewTry: TGameTry;
243begin
244 for Direction := drLeft to drDown do begin
245 if GameTry.Game.CanMoveDirection(Direction) then begin
246 NewTry := TGameTry.Create;
247 NewTry.Assign(GameTry);
248 NewTry.Game.UndoEnabled := False;
249 NewTry.Game.AnimationDuration := 0;
250 NewTry.Game.MoveAll(Direction, False);
251 SetLength(NewTry.Moves, Length(NewTry.Moves) + 1);
252 NewTry.Moves[Length(NewTry.Moves) - 1] := Direction;
253 GameTries.Add(NewTry);
254 end;
255 end;
256end;
257
258end.
259
Note: See TracBrowser for help on using the repository browser.