"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) *)