source: tags/1.1.0/Forms/UFormComputer.pas

Last change on this file was 38, checked in by chronos, 5 years ago
  • Added: In computer AI form allow to set delay of steps computation. Set to zero means fastest processing.
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 GameTries1 := TGameTries.Create;
220 GameTries2 := TGameTries.Create;
221 GameTries3 := TGameTries.Create;
222 GameTries4 := TGameTries.Create;
223end;
224
225procedure TFormComputer.FormDestroy(Sender: TObject);
226begin
227 FreeAndNil(GameTries1);
228 FreeAndNil(GameTries2);
229 FreeAndNil(GameTries3);
230 FreeAndNil(GameTries4);
231end;
232
233procedure TFormComputer.FormShow(Sender: TObject);
234begin
235 Core.PersistentForm1.Load(Self);
236end;
237
238procedure TFormComputer.TryAllDirections(GameTries: TGameTries; GameTry: TGameTry);
239var
240 Direction: TMoveDirection;
241 NewTry: TGameTry;
242begin
243 for Direction := drLeft to drDown do begin
244 if GameTry.Game.CanMoveDirection(Direction) then begin
245 NewTry := TGameTry.Create;
246 NewTry.Assign(GameTry);
247 NewTry.Game.UndoEnabled := False;
248 NewTry.Game.AnimationDuration := 0;
249 NewTry.Game.MoveAll(Direction, False);
250 SetLength(NewTry.Moves, Length(NewTry.Moves) + 1);
251 NewTry.Moves[Length(NewTry.Moves) - 1] := Direction;
252 GameTries.Add(NewTry);
253 end;
254 end;
255end;
256
257end.
258
Note: See TracBrowser for help on using the repository browser.