"Fossies" - the Fresh Open Source Software Archive 
Member "seed7/prg/violet.dna" (21 Jul 2012, 11250 Bytes) of package /linux/misc/seed7_05_20210223.tgz:
As a special service "Fossies" has tried to format the requested text file into HTML format (style:
standard) with prefixed line numbers.
Alternatively you can here
view or
download the uninterpreted source code file.
1
2 (********************************************************************)
3 (* *)
4 (* dnafight.sd7 Bacterial dna fight programming game *)
5 (* Copyright (C) 1985 Johannes Gritsch *)
6 (* *)
7 (* This program is free software; you can redistribute it and/or *)
8 (* modify it under the terms of the GNU General Public License as *)
9 (* published by the Free Software Foundation; either version 2 of *)
10 (* the License, or (at your option) any later version. *)
11 (* *)
12 (* This program is distributed in the hope that it will be useful, *)
13 (* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
14 (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
15 (* GNU General Public License for more details. *)
16 (* *)
17 (* You should have received a copy of the GNU General Public *)
18 (* License along with this program; if not, write to the *)
19 (* Free Software Foundation, Inc., 51 Franklin Street, *)
20 (* Fifth Floor, Boston, MA 02110-1301, USA. *)
21 (* *)
22 (********************************************************************)
23
24
25 const type: v_ifield is array [direction] integer;
26
27
28 const proc: dna (VIOLET) is func
29
30 local
31 const bactColor: SELF is VIOLET;
32 const power: MINSPLITSIZE is 4;
33
34 var direction: bestDie is HERE;
35 var direction: bestEat is HERE;
36 var direction: bestSplit is HERE;
37 var direction: maxDir is HERE;
38 var v_ifield: splitPrior is direction times 0;
39 var v_ifield: eatPrior is direction times 0;
40 var v_ifield: diePrior is direction times 0;
41 var power: needed is 0;
42 var power: ownSize is 0;
43 var boolean: splitable is FALSE;
44 var boolean: enemies is FALSE;
45 var integer: splitSize is 0;
46
47
48 const proc: findMax (inout direction: dmax, in v_ifield: field) is func
49
50 local
51 var directSet: maxDir is directSet.EMPTY_SET;
52 var direction: fd is HERE;
53 var integer: xmax is 0;
54
55 begin (* findMax *)
56 maxDir := {HERE};
57 xmax := field[HERE];
58 for fd range HERE to EAST do
59 if field[fd] > xmax then
60 maxDir := {fd};
61 xmax := field[fd];
62 elsif field[fd] = xmax then
63 incl(maxDir, fd);
64 end if;
65 end for;
66 dmax := ranDir(maxDir);
67 end func; (* findMax *)
68
69
70 const proc: getMax (inout direction: maxDir) is func
71
72 local
73 var power: gmax is 0;
74 var direction: dir is HERE;
75 var directSet: maxDirSet is directSet.EMPTY_SET;
76
77 begin (* getMax *)
78 maxDirSet := {NORTH};
79 gmax := food(NORTH);
80 for dir range SOUTH to SE do
81 if food(dir) > gmax then
82 maxDirSet := {dir};
83 gmax := food(dir);
84 elsif food(dir) = gmax then
85 incl(maxDirSet, dir);
86 end if;
87 end for;
88 maxDir := ranDir(maxDirSet);
89 end func; (* getMax *)
90
91
92 const proc: init is func
93
94 local
95 var v_ifield: next is direction times 0;
96 var v_ifield: next2 is direction times 0;
97 var direction: dir is HERE;
98 var power: ownSize2 is 0;
99 var power: needed2 is 0;
100 var power: splitSub is 0;
101
102
103 const proc: getPar (inout integer: eatPrior,
104 inout integer: splitPrior, inout integer: next,
105 inout integer: next2, in power: fodder) is func
106
107 begin (* getPar *)
108 if hunger = 0 then
109 if fodder < needed2 then
110 next2 := 0;
111 splitPrior := 0;
112 else
113 next2 := ownSize2 - needed2 + min(fodder, ownSize2);
114 splitPrior := fodder;
115 end if;
116 if fodder < needed then
117 next := 0;
118 eatPrior := fodder - foodReserve;
119 else
120 next := ownSize - needed + min(fodder, ownSize);
121 eatPrior := fodder;
122 end if;
123 else
124 next2 := ownSize2 - needed2 + min(fodder, ownSize2);
125 splitPrior := fodder + 1;
126 next := ownSize - needed + min(fodder, ownSize);
127 eatPrior := fodder;
128 end if;
129 end func; (* getPar *)
130
131
132 begin (* init *)
133 enemies := FALSE;
134 ownSize := strength(HERE);
135 splitSize := 2 * food(HERE);
136 splitSub := 0;
137 needed := max(0, shrinkSize(ownSize));
138 ownSize2 := (ownSize + 1) div 2;
139 needed2 := max(0, shrinkSize(ownSize2));
140 getPar(eatPrior[HERE], splitPrior[HERE], next[HERE], next2[HERE],
141 food(HERE));
142 ownSize2 := ownSize div 2;
143 needed2 := max(0, shrinkSize(ownSize2));
144 diePrior[HERE] := food(HERE);
145
146 for dir range NORTH to EAST do
147
148 case view(dir) of
149
150 when {EDGE}:
151 eatPrior[dir] := -initSize;
152 splitPrior[dir] := 0;
153 next[dir] := 0;
154 next2[dir] := 0;
155 splitSub +:= 2;
156 diePrior[dir] := -3 * foodReserve;
157
158 when {CLEAR}:
159 getPar(eatPrior[dir], splitPrior[dir],
160 next[dir], next2[dir], food(dir));
161 diePrior[dir] := food(dir);
162 if food(dir) = foodReserve then
163 splitSize +:= max(5, foodReserve);
164 else
165 splitSize +:= 2 * food(dir);
166 end if;
167
168 when {SELF}:
169 diePrior[dir] := 0;
170 diePrior[HERE] +:= 1;
171 eatPrior[HERE] -:= 1;
172 eatPrior[dir] := - 2 * foodReserve + 1;
173 if hunger = 0 and strength(dir) < needed then
174 next[dir] := 0;
175 else
176 if strength(dir) <= ownSize then
177 next[dir] := ownSize - needed + strength(dir);
178 else
179 next[dir] := 0;
180 end if;
181 end if;
182 splitPrior[dir] := 0;
183 next2[dir] := 0;
184 splitSize +:= food(dir);
185
186 otherwise:
187 diePrior[HERE] -:= 2 * strength(dir);
188 enemies := TRUE;
189 if hunger = 0 and strength(dir) < needed then
190 diePrior[dir] := foodReserve;
191 eatPrior[dir] := strength(dir) - 1;
192 next[dir] := 0;
193 else
194 if strength(dir) <= ownSize then
195 diePrior[dir] := foodReserve + 1;
196 eatPrior[dir] := strength(dir) + 1;
197 next[dir] := ownSize - needed + strength(dir);
198 else
199 diePrior[dir] := - 2 * foodReserve;
200 if next[HERE] < strength(dir) and
201 shrinkSize(strength(dir)) <= next[HERE] then
202 eatPrior[HERE] := eatPrior[HERE] - 2 * foodReserve;
203 end if;
204 eatPrior[dir] := -2 * foodReserve;
205 next[dir] := 0;
206 end if;
207 end if;
208 splitPrior[dir] := 0;
209 next2[dir] := 0;
210 if next2[HERE] < strength(dir) then
211 splitPrior[HERE] := 0;
212 end if;
213 splitSize +:= food(dir);
214
215 end case;
216 end for;
217
218 for dir range NW to SE do
219
220 case view(dir) of
221
222 when {EDGE}:
223 splitSub +:= 1;
224
225 when {CLEAR}:
226 if hunger > 0 and eatPrior[HERE] < needed then
227 if view(left[dir]) = CLEAR then
228 eatPrior[left[dir]] +:= (food(dir) + 1) div 2;
229 if splitPrior[left[dir]] > 0 then
230 splitPrior[left[dir]] +:= (food(dir) + 1) div 2;
231 end if;
232 end if;
233 if view(right[dir]) = CLEAR then
234 eatPrior[right[dir]] +:= (food(dir) + 1) div 2;
235 if splitPrior[right[dir]] > 0 then
236 splitPrior[right[dir]] +:= (food(dir) + 1) div 2;
237 end if;
238 end if;
239 end if;
240 if food(dir) = foodReserve then
241 splitSize +:= max(5, foodReserve);
242 else
243 splitSize +:= food(dir);
244 end if;
245
246 when {SELF}:
247 splitSize +:= (food(dir) + 1) div 2;
248 if view(left[dir]) in {CLEAR, SELF} then
249 diePrior[left[dir]] +:= 1;
250 end if;
251 if view(right[dir]) in {CLEAR, SELF} then
252 diePrior[right[dir]] +:= 1;
253 end if;
254
255 otherwise:
256 enemies := TRUE;
257 if strength(dir) > ownSize2 then
258 splitPrior[left[dir]] := 0;
259 splitPrior[right[dir]] := 0;
260 end if;
261 if next[left[dir]] <= strength(dir) then
262 eatPrior[left[dir]] -:= foodReserve;
263 else
264 if hunger > 1 and view(left[dir]) = CLEAR then
265 eatPrior[left[dir]] +:= strength(dir) div 2;
266 end if;
267 end if;
268 if next[right[dir]] <= strength(dir) then
269 eatPrior[right[dir]] -:= foodReserve;
270 else
271 if hunger > 1 and view(right[dir]) = CLEAR then
272 eatPrior[right[dir]] +:= strength(dir) div 2;
273 end if;
274 end if;
275 splitSize +:= (food(dir) + 1) div 2;
276 diePrior[left[dir]] -:= 2 * foodReserve;
277 diePrior[right[dir]] -:= 2 * foodReserve;
278
279 end case;
280 end for;
281
282 splitSize := max(MINSPLITSIZE, splitSize div (10 - splitSub));
283 end func; (* init *)
284
285
286 begin (* dna (VIOLET) *)
287 init;
288 splitable := splitPrior[HERE] > 0;
289 splitPrior[HERE] := 0;
290 findMax(bestSplit, splitPrior);
291 if bestSplit <> HERE and splitable and ownSize > splitSize and view(bestSplit) = CLEAR then
292 split(bestSplit, (ownSize + 1) div 2, ownSize div 2);
293 else
294 getMax(maxDir);
295 if hunger = 0 and food(maxDir) < needed and food(HERE) < needed then
296 findMax(bestDie, diePrior);
297 if view(bestDie) in {CLEAR, EDGE, SELF} or
298 strength(bestDie) > ownSize then
299 eat(HERE, ownSize);
300 else
301 kill(bestDie);
302 end if;
303 else
304 if food(maxDir) < needed and food(HERE) > needed then
305 if hunger > 0 then
306 eat(HERE, 1);
307 else
308 eat(HERE, needed);
309 end if;
310 else
311 findMax(bestEat, eatPrior);
312 if view(bestEat) > CLEAR and bestEat <> HERE then
313 kill(bestEat);
314 else
315 if view(bestEat) <> EDGE then
316 eat(bestEat, ownSize);
317 else
318 eat(HERE, ownSize);
319 end if;
320 end if;
321 end if;
322 end if;
323 end if;
324 end func; (* dna (VIOLET) *)