1
2(********************************************************************)
3(*                                                                  *)
4(*  dnafight.sd7  Bacterial dna fight programming game              *)
5(*  Copyright (C) 1985  Thomas Mertes                               *)
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
25const proc: dna (ORANGE) is func
26
27  local
28    const colorSet: FRIENDS is {ORANGE};
29    var colorSet: enemy is colorSet.EMPTY_SET;
30    var direction: direct is HERE;
31    var directSet: killDirs is directSet.EMPTY_SET;
32    var directSet: eatDirs is directSet.EMPTY_SET;
33    var directSet: splitDirs is directSet.EMPTY_SET;
34    var directSet: helpDirs is directSet.EMPTY_SET;
35    var power: killPow is 0;
36    var power: eatPow is 0;
37    var power: splitPow is 0;
38    var power: helpPow is 0;
39    var power: split1Pow is 0;
40    var power: split2Pow is 0;
41    var power: newPow is 0;
42    var power: new1SplitPow is 0;
43    var power: new2SplitPow is 0;
44    var power: meal is 0;
45    var boolean: dangerHere is FALSE;
46
47
48    const func direction: optimalDir (in directSet: dirs) is func
49      result
50        var direction: optimalDir is HERE;
51
52      local
53        var direction: direct is HERE;
54        var power: pow is 0;
55        var power: help is 0;
56        var directSet: directs is directSet.EMPTY_SET;
57
58      begin (* optimalDir *)
59        if dirs = {HERE} then
60          optimalDir := HERE;
61        else
62          pow := 0;
63          directs := directSet.EMPTY_SET;
64          for direct range MAIN_DIRECTIONS do
65            if direct in dirs then
66              help := food(left[direct]) + food(direct) +
67                  food(right[direct]);
68              if help > pow then
69                pow := help;
70                directs := directSet.EMPTY_SET;
71                incl(directs, direct);
72              elsif help = pow then
73                incl(directs, direct);
74              end if;
75            end if;
76          end for;
77          optimalDir := ranDir(directs);
78        end if;
79      end func;
80
81
82  begin (* dna (ORANGE) *)
83    enemy := ALL_COLORS;
84    excl(enemy, ORANGE);
85    killPow := 0;
86    eatPow := 0;
87    splitPow := 0;
88    helpPow := 0;
89    newPow := strength(HERE) - shrinkSize(strength(HERE));
90    split1Pow := strength(HERE) - strength(HERE) div 2;
91    split2Pow := strength(HERE) div 2;
92    new1SplitPow := split1Pow - shrinkSize(split1Pow);
93    if strength(HERE) > 1 then
94      new2SplitPow := split2Pow - shrinkSize(split2Pow);
95    else
96      new2SplitPow := 0;
97    end if;
98    dangerHere := FALSE;
99    for direct range MAIN_DIRECTIONS do
100      if view(direct) = CLEAR then
101        meal := min(strength(HERE), food(direct));
102        if (view(   left [direct]) in enemy and
103            strength(left [direct]) >= newPow + meal) or
104            (view(   right[direct]) in enemy and
105            strength(right[direct]) >= newPow + meal) then
106          noop;
107        else
108          if meal > eatPow then
109            eatPow := meal;
110            eatDirs := directSet.EMPTY_SET;
111            incl(eatDirs, direct);
112          elsif meal = eatPow then
113            incl(eatDirs, direct);
114          end if;
115        end if;
116        meal := min(strength(HERE) div 2, food(direct));
117        if (view(   left [direct]) in enemy and
118            strength(left [direct]) >= new2SplitPow + meal) or
119            (view(   right[direct]) in enemy and
120            strength(right[direct]) >= new2SplitPow + meal) then
121          noop;
122        else
123          if meal>splitPow then
124            splitPow := meal;
125            splitDirs := directSet.EMPTY_SET;
126            incl(splitDirs, direct);
127          elsif meal = splitPow then
128            incl(splitDirs, direct);
129          end if;
130        end if;
131      else
132        if view(direct) in enemy then
133          if strength(direct)>strength(HERE) then
134             dangerHere := TRUE;
135          else
136            if  (view(    left [direct]) in enemy and
137                strength(left [direct]) >= newPow + strength(direct)) or
138                (view(   right[direct]) in enemy and
139                strength(right[direct]) >= newPow + strength(direct)) then
140              noop;
141            else
142              if strength(direct) > killPow then
143                killPow := strength(direct);
144                killDirs := directSet.EMPTY_SET;
145                incl(killDirs, direct);
146              elsif strength(direct) = killPow then
147                incl(killDirs, direct);
148              end if;
149            end if;
150          end if;
151        else
152          if view(direct) in FRIENDS then
153            if (strength(direct)<=strength(HERE)) then
154              if (view(    left [direct]) in enemy and
155                  strength(left [direct]) >= strength(direct) and
156                  strength(left [direct]) < newPow + strength(direct)) or
157                  (view(   right[direct]) in enemy and
158                  strength(right[direct]) >= strength(direct) and
159                  strength(right[direct]) < newPow + strength(direct)) then
160                if strength(direct) > helpPow then
161                  helpPow := strength(direct);
162                  helpDirs := directSet.EMPTY_SET;
163                  incl(helpDirs, direct);
164                elsif strength(direct) = helpPow then
165                  incl(helpDirs, direct);
166                end if;
167              end if;
168            end if;
169          end if;
170        end if;
171      end if;
172    end for;
173    meal := min(strength(HERE)-strength(HERE) div 2, food(HERE));
174    if dangerHere or strength(HERE) = 1 or
175        killPow >= new1SplitPow + meal then
176      splitPow := 0;
177      splitDirs := directSet.EMPTY_SET;
178    else
179      splitPow := new1SplitPow + meal + new2SplitPow + splitPow;
180    end if;
181    if not dangerHere then
182      meal := min(strength(HERE), food(HERE));
183      if meal > eatPow then
184        eatPow := meal;
185        eatDirs := directSet.EMPTY_SET;
186        incl(eatDirs, HERE);
187      else
188        if meal = eatPow then
189          incl(eatDirs, HERE);
190        end if;
191      end if;
192    end if;
193    eatPow := newPow + eatPow;
194    killPow := newPow + killPow;
195    helpPow := newPow + helpPow;
196    if killDirs <> directSet.EMPTY_SET and
197        killPow >= strength(HERE) - newPow then
198      kill(optimalDir(killDirs))
199    else
200      if max(max(eatPow, splitPow), helpPow)>0 then
201        if splitPow >= eatPow then
202          if helpPow>splitPow then
203            kill(optimalDir(helpDirs));
204          else
205            split(optimalDir(splitDirs), split1Pow, split2Pow);
206          end if;
207        else
208          if helpPow>eatPow then
209            kill(optimalDir(helpDirs));
210          else
211            eat(optimalDir(eatDirs), strength(HERE));
212          end if;
213        end if;
214      else
215        noop;
216      end if;
217    end if;
218  end func; (* dna (ORANGE) *)
219