home *** CD-ROM | disk | FTP | other *** search
/ Action Games (2008) / akcnihry1.iso / AT-Robots 2.10 / ATRT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-06-23  |  31.9 KB  |  944 lines

  1. (*
  2. Copyright (c) 1999, Ed T. Toton III. All rights reserved.
  3.  
  4. Redistribution and use in source and binary forms, with or without
  5. modification, are permitted provided that the following conditions
  6. are met:
  7.  
  8.    Redistributions of source code must retain the above copyright notice,
  9.    this list of conditions and the following disclaimer.
  10.  
  11.    Redistributions in binary form must reproduce the above copyright notice, 
  12.    this list of conditions and the following disclaimer in the documentation
  13.    and/or other materials provided with the distribution.
  14.  
  15.    All advertising materials mentioning features or use of this software
  16.    must display the following acknowledgement:
  17.  
  18.         This product includes software developed by Ed T. Toton III &
  19.         NecroBones Enterprises.
  20.  
  21.    No modified or derivative copies or software may be distributed in the
  22.    guise of official or original releases/versions of this software. Such
  23.    works must contain acknowledgement that it is modified from the original.
  24.  
  25.    Neither the name of the author nor the name of the business or
  26.    contributers may be used to endorse or promote products derived
  27.    from this software without specific prior written permission.
  28.  
  29. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY 
  30. EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  31. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  32. DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
  33. DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  34. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  35. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  36. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  37. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  38. THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  39. *)
  40.  
  41. { This program is a shell for ATR2 that runs tournaments. }
  42.  
  43. {$E+}{$N+}{$G+}{$X+}{$D-}
  44. {$M 12288,0,0}
  45. program AT_Robots_tournament;
  46.  
  47. uses stuff, filelib, myfile, crt, dos;
  48.  
  49. const
  50.  progname       ='ATR-Tournament';
  51.  version        ='1.05';
  52.  cnotice1       ='Copyright (C) 1997, Ed T. Toton III';
  53.  cnotice2       ='All Rights Reserved.';
  54.  main_filename  ='ATR2';
  55.  prog_ext       ='.EXE';
  56.  robot_ext      ='.AT2';
  57.  robot_ext2     ='.ATL';
  58.  config_ext     ='.ATS';
  59.  compile_ext    ='.CMP';
  60.  report_ext     ='.REP';
  61.  tourn_ext      ='.TRN';
  62.  list_ext       ='.LST';
  63.  result_ext     ='.RES';
  64.  data_ext       ='.DAT';
  65.  log_ext        ='.LOG';
  66.  
  67.  max_robots     =512;
  68.  
  69. type
  70.  string8        =string[8];
  71.  robot_ptr      =^string8;
  72.  robot_rec      = record
  73.                    name:string[8];
  74.                    wins,matches,shots,kills,deaths,hits,damage,cycles,errors:longint;
  75.                    locked:boolean;
  76.                   end;
  77.  
  78. var
  79.  tname,robot_dir:string;
  80.  num_robots,matches:longint;
  81.  game_limit:longint;
  82.  robot:array[1..max_robots] of robot_rec;
  83.  unequal_matches,yes_to_all,report_only,sound_on,registered,abort,complete:boolean;
  84.  reg_name:string;
  85.  reg_num:word;
  86.  log_file:text;
  87.  param_line:string;
  88.  bestkiller,bestsurvivor,mostdead,triggerhappy,bestmarksman,
  89.  mostdestructive,longestlived,mosterrors,haphazard,conservative,
  90.  leasteffective,biggestloser,shortestlived,longestreign,newestcontender:integer;
  91.  
  92.  
  93.  
  94. function divide(r1,r2:real):real;
  95. var
  96.  r:real;
  97. begin  {divide, checking for division by zero}
  98.  if (r1=0) or (r2=0) then r:=0
  99.          else r:=r1/r2;
  100.  divide:=r;
  101. end;
  102.  
  103. procedure chirp;
  104. begin
  105.  if (not sound_on) then exit;
  106.  sound(2000);
  107.  delay(100);
  108.  sound(4000);
  109.  delay(100);
  110.  sound(1000);
  111.  delay(100);
  112.  sound(2000);
  113.  delay(100);
  114.  nosound;
  115. end;
  116.  
  117.  
  118.  
  119. procedure check_registration;
  120. var
  121.  w:word;
  122.  i:integer;
  123.  f:text;
  124.  s:String;
  125. begin
  126.  registered:=false;
  127.  if exist('ATR2.REG') then
  128.   begin
  129.    assign(f,'ATR2.REG');
  130.    reset(f);
  131.    readln(f,reg_name);
  132.    readln(f,reg_num);
  133.    close(f);
  134.    w:=0; s:=btrim(ucase(reg_name));
  135.    for i:=1 to length(s) do
  136.      inc(w,ord(s[i]));
  137.    w:=w xor $5AA5;
  138.    if w=reg_num then registered:=true;
  139.   end;
  140. end;
  141.  
  142.  
  143. procedure pause;
  144. begin
  145.  if yes_to_all then exit;
  146.  write('[PAUSE]');
  147.  flushkey;
  148.  if readkey=#27 then halt;
  149.  write(#13,'        ',#13);
  150. end;
  151.  
  152. function cstrr(i:real; k:integer):string;
  153. var
  154.  s1:string[255];
  155. begin
  156.  str(i:0:k,s1);
  157.  cstrr:=s1;
  158. end;
  159.  
  160. procedure shutdown;
  161. begin
  162.  if not report_only then
  163.   begin
  164.    writeln; textcolor(3);
  165.    write  (progname,' ',version,' ');
  166.    writeln(cnotice1);
  167.    writeln(cnotice2);
  168.    textcolor(7);
  169.    writeln;
  170.   end;
  171.  halt;
  172. end;
  173.  
  174. procedure init;
  175. var
  176.  f:text;
  177.  fn:string;
  178.  i,j,k:integer;
  179. begin
  180.  
  181.  registered:=true;
  182.  reg_name:='Unregistered';
  183.  reg_num:=$FFFF;
  184.  {check_registration;}
  185.  
  186.  if not registered then
  187.   begin
  188.    textcolor(30);
  189.    write('UNREGISTERED');
  190.    textcolor(14);
  191.    write(' - ');
  192.    textcolor(12);
  193.    writeln('You must register AT-Robots first.');
  194.    textcolor(7);
  195.    writeln;
  196.    halt;
  197.   end;
  198.  
  199.  tname:=''; robot_dir:='';
  200.  if paramcount<1 then
  201.   begin
  202.    writeln('Usage:  ATRT <tournament name>');
  203.    writeln; halt;
  204.   end;
  205.  tname:=base_name(ucase(btrim(paramstr(1))));
  206.  yes_to_all:=false;
  207.  if paramcount>1 then
  208.   for i:=2 to paramcount do
  209.    begin
  210.     if (ucase(btrim(paramstr(i)))='/Y') or
  211.        (ucase(btrim(paramstr(i)))='-Y') then yes_to_all:=true;
  212.    end;
  213.  sound_on:=false;
  214.  report_only:=false;
  215.  if tname[1]='/' then
  216.   begin
  217.    report_only:=true;
  218.    tname:=base_name(rstr(tname,length(tname)-1));
  219.    writeln('Formatting a report only, using "',tname+report_ext,'"');
  220.    if not exist(tname+report_ext) then
  221.     begin writeln('Report not found!'); halt; end;
  222.   end else begin
  223.    fn:=tname+tourn_ext;
  224.    if not exist(fn) then
  225.     begin
  226.      writeln('Tournament file "',fn,'" not found!');
  227.      writeln; halt;
  228.     end;
  229.    assign(f,fn); reset(f);
  230.    readln(f,robot_dir);
  231.    readln(f,matches);
  232.    readln(f,game_limit);
  233.    readln(f,i);
  234.    readln(f,param_line);
  235.    if i>0 then begin sound_on:=true; writeln('Chirping is on!'); chirp; end
  236.           else sound_on:=false;
  237.    close(f);
  238.    if (rstr(robot_dir,1)<>'\') and (robot_dir<>'') then
  239.       robot_dir:=robot_dir+'\';
  240.    fn:=robot_dir+no_path(fn);
  241.    if not valid(fn) then
  242.     begin
  243.      writeln('Robot directory is invalid or does not exist!');
  244.      writeln('(',robot_dir,')'); writeln; halt;
  245.     end;
  246.   end;
  247.  if matches<1 then matches:=1;
  248.  if matches>1000 then matches:=1000;
  249.  if game_limit<0 then game_limit:=0;
  250.  if game_limit>16000 then game_limit:=16000;
  251.  
  252.  for i:=1 to max_robots do
  253.   with robot[i] do
  254.    begin name:=''; wins:=0; matches:=0; locked:=false; kills:=0; deaths:=0;
  255.    shots:=0; hits:=0; errors:=0; cycles:=0;
  256.    damage:=0; end;
  257.  
  258.  textcolor(7);
  259.  if not report_only then
  260.   begin
  261.    writeln; textcolor(3);
  262.    write  (progname,' ',version,' ');
  263.    writeln(cnotice1);
  264.    writeln(cnotice2);
  265.    textcolor(7);
  266.    writeln;
  267.  end;
  268. end;
  269.  
  270. procedure count_robots;
  271. var
  272.  sr:searchrec;
  273.  i,j,k:integer;
  274.  c:char;
  275. begin
  276.  k:=0;
  277.  findfirst(robot_dir+'*'+robot_ext,archive,sr);
  278.  while doserror=0 do
  279.   begin
  280.    inc(k);
  281.    findnext(sr);
  282.   end;
  283.  findfirst(robot_dir+'*'+robot_ext2,archive,sr);
  284.  while doserror=0 do
  285.   begin
  286.    inc(k);
  287.    findnext(sr);
  288.   end;
  289.  j:=0;
  290.  for i:=k-1 downto 1 do j:=j+i;
  291.  if k<=1 then
  292.   begin
  293.    writeln('Robots found: ',k);
  294.    writeln('There must be at least 2 robots to compete!');
  295.    writeln; halt;
  296.   end;
  297.  writeln(k,' robots found. That means ',j,' one-on-one pairings of');
  298.  writeln(matches,' matches each, for a total of ',j*matches,' matches.');
  299.  writeln;
  300.  writeln('Before matches begin, all robots will undergo a test-compile to');
  301.  writeln('verify their validity as a robot program. Any failed compiles');
  302.  writeln('will be disqualified from this list of competing robots.');
  303.  writeln;
  304.  write('Proceed? [Y/N] ');
  305.  if yes_to_all then c:='Y' else
  306.     repeat c:=upcase(readkey); until c in ['Y','N'];
  307.  writeln(c); writeln;
  308.  if c='N' then shutdown;
  309. end;
  310.  
  311. function test_compile(fn:string):boolean;
  312. var
  313.  ok:boolean;
  314. begin
  315.  ok:=false;
  316.  delete_file(main_filename+compile_ext);
  317.  swapvectors;
  318.  exec(main_filename+prog_ext,param_line+' /S /C '+fn);
  319.  swapvectors;
  320.  if exist(main_filename+compile_ext) then ok:=true;
  321.  test_compile:=ok;
  322. end;
  323.  
  324. procedure make_robot_list;
  325. var
  326.  sr:searchrec;
  327.  i,j,k:integer;
  328.  f:text;
  329. begin
  330.  count_robots;
  331.  num_robots:=0;
  332.  k:=0;
  333.  findfirst(robot_dir+'*'+robot_ext,archive,sr);
  334.  while doserror=0 do
  335.   begin
  336.    if test_compile(robot_dir+base_name(sr.name)) then
  337.     begin
  338.      inc(num_robots);
  339.      robot[num_robots].name:=base_name(sr.name);
  340.      robot[num_robots].wins:=0;
  341.      robot[num_robots].kills:=0;
  342.      robot[num_robots].deaths:=0;
  343.      robot[num_robots].shots:=0;
  344.      robot[num_robots].matches:=0;
  345.      robot[num_robots].locked:=false;
  346.      robot[num_robots].hits:=0;
  347.      robot[num_robots].damage:=0;
  348.      robot[num_robots].cycles:=0;
  349.      robot[num_robots].errors:=0;
  350.     end;
  351.    findnext(sr);
  352.   end;
  353.  findfirst(robot_dir+'*'+robot_ext2,archive,sr);
  354.  while doserror=0 do
  355.   begin
  356.    if test_compile('?'+robot_dir+base_name(sr.name)) then
  357.     begin
  358.      inc(num_robots);
  359.      robot[num_robots].name:=base_name(sr.name);
  360.      robot[num_robots].wins:=0;
  361.      robot[num_robots].kills:=0;
  362.      robot[num_robots].deaths:=0;
  363.      robot[num_robots].shots:=0;
  364.      robot[num_robots].matches:=0;
  365.      robot[num_robots].locked:=true;
  366.      robot[num_robots].hits:=0;
  367.      robot[num_robots].damage:=0;
  368.      robot[num_robots].cycles:=0;
  369.      robot[num_robots].errors:=0;
  370.     end;
  371.    findnext(sr);
  372.   end;
  373.  assign(f,tname+list_ext);
  374.  rewrite(f);
  375.  writeln(f,num_robots);
  376.  for i:=1 to num_robots do
  377.   if robot[i].locked then
  378.     writeln(f,robot[i].name+robot_ext2)
  379.    else
  380.     writeln(f,robot[i].name+robot_ext);
  381.  close(f);
  382. end;
  383.  
  384. procedure read_robot_list;
  385. var
  386.  i,j,k:integer;
  387.  f:text;
  388.  s:string;
  389. begin
  390.  num_robots:=0;
  391.  assign(f,tname+list_ext);
  392.  reset(f);
  393.  readln(f,num_robots);
  394.  for i:=1 to num_robots do
  395.   begin
  396.    readln(f,s);
  397.    robot[i].name:=btrim(base_name(ucase(s)));
  398.    if ucase(btrim(exten(s)))=robot_ext2 then
  399.       robot[i].locked:=true else robot[i].locked:=false;
  400.    robot[i].wins:=0;
  401.    robot[i].matches:=0;
  402.    robot[i].shots:=0;
  403.    robot[i].kills:=0;
  404.    robot[i].deaths:=0;
  405.    robot[i].cycles:=0;
  406.    robot[i].damage:=0;
  407.    robot[i].hits:=0;
  408.    robot[i].errors:=0;
  409.   end;
  410.  close(f);
  411.  writeln('Robot list read.');
  412. end;
  413.  
  414. procedure swap_robots(i,k:integer);
  415. var
  416.  r:robot_rec;
  417. begin
  418.  r:=robot[i];
  419.  robot[i]:=robot[k];
  420.  robot[k]:=r;
  421. end;
  422.  
  423. function higher_score(i,k:integer):boolean;
  424. var
  425.  needswap:boolean;
  426.  score1,score2:real;
  427. begin
  428.  needswap:=false;
  429.  
  430.  if robot[i].matches=0 then score1:=0
  431.     else score1:=robot[i].wins/robot[i].matches;
  432.  if robot[k].matches=0 then score2:=0
  433.     else score2:=robot[k].wins/robot[k].matches;
  434.  (* Sort first by score, then kills, deaths, damage, longevity, errors, then name *)
  435.  if (score1<score2) then
  436.     needswap:=true;
  437.  if (score1=score2) and (robot[i].matches>0) and (robot[k].matches>0) then
  438.   begin
  439.    if (divide(robot[i].kills,robot[i].matches)<divide(robot[k].kills,robot[k].matches)) then
  440.       needswap:=true;
  441.    if (divide(robot[i].kills,robot[i].matches)=divide(robot[k].kills,robot[k].matches)) then
  442.     begin
  443.      if (divide(robot[i].deaths,robot[i].matches)>divide(robot[k].deaths,robot[k].matches)) then
  444.         needswap:=true;
  445.      if (divide(robot[i].deaths,robot[i].matches)=divide(robot[k].deaths,robot[k].matches)) then
  446.       begin
  447.        if (divide(robot[i].damage,robot[i].matches)<divide(robot[k].damage,robot[k].matches)) then
  448.           needswap:=true;
  449.        if (divide(robot[i].damage,robot[i].matches)=divide(robot[k].damage,robot[k].matches)) then
  450.         begin
  451.          if (divide(robot[i].cycles,robot[i].matches)<divide(robot[k].cycles,robot[k].matches)) then
  452.             needswap:=true;
  453.          if (divide(robot[i].cycles,robot[i].matches)=divide(robot[k].cycles,robot[k].matches)) then
  454.           begin
  455.            if (divide(robot[i].errors,robot[i].matches)>divide(robot[k].errors,robot[k].matches)) then
  456.               needswap:=true;
  457.            if (divide(robot[i].errors,robot[i].matches)=divide(robot[k].errors,robot[k].matches)) then
  458.             begin
  459.              if (robot[i].name<robot[k].name) then
  460.                 needswap:=true;
  461.             end;
  462.           end;
  463.         end;
  464.       end;
  465.     end;
  466.   end;
  467.  higher_score:=needswap;
  468. end;
  469.  
  470. procedure rank_robots;
  471. var
  472.  i,k:integer;
  473. begin
  474.  for i:=1 to num_robots do
  475.   for k:=i to num_robots do
  476.    begin
  477.     if (i<>k) then
  478.      begin
  479.       if (higher_score(i,k)) then
  480.          swap_robots(i,k);
  481.      end;
  482.    end;
  483.  bestkiller:=1; bestsurvivor:=1; mostdead:=1; triggerhappy:=1;
  484.  bestmarksman:=1; mostdestructive:=1; longestlived:=1; mosterrors:=1;
  485.  haphazard:=1; conservative:=1; leasteffective:=1; biggestloser:=1;
  486.  shortestlived:=1; newestcontender:=1; longestreign:=1; unequal_matches:=false;
  487.  for i:=1 to num_robots do
  488.   with robot[i] do
  489.    begin
  490.     if divide(wins,matches)>divide(robot[bestsurvivor].wins,robot[bestsurvivor].matches) then bestsurvivor:=i;
  491.     if divide(wins,matches)<=divide(robot[biggestloser].wins,robot[biggestloser].matches) then biggestloser:=i;
  492.     if divide(kills ,matches)>divide(robot[bestkiller].kills,robot[bestkiller].matches) then bestkiller:=i;
  493.     if divide(deaths,matches)>divide(robot[mostdead].deaths,robot[mostdead].matches) then mostdead:=i;
  494.     if divide(shots ,matches)>divide(robot[triggerhappy].shots,robot[triggerhappy].matches) then triggerhappy:=i;
  495.     if divide(shots ,matches)<=divide(robot[conservative].shots,robot[conservative].matches) then conservative:=i;
  496.     if divide(hits,shots)>divide(robot[bestmarksman].hits,robot[bestmarksman].shots) then bestmarksman:=i;
  497.     if (divide(hits,shots)<=divide(robot[haphazard].hits,robot[haphazard].shots)) and (shots>0) then haphazard:=i;
  498.     if divide(damage,matches)>divide(robot[mostdestructive].damage,robot[mostdestructive].matches) then mostdestructive:=i;
  499.     if divide(damage,matches)<=divide(robot[leasteffective].damage,robot[leasteffective].matches) then leasteffective:=i;
  500.     if divide(cycles,matches)>divide(robot[longestlived].cycles,robot[longestlived].matches) then longestlived:=i;
  501.     if divide(cycles,matches)<=divide(robot[shortestlived].cycles,robot[shortestlived].matches) then shortestlived:=i;
  502.     if divide(errors,matches)>divide(robot[mosterrors].errors,robot[mosterrors].matches) then mosterrors:=i;
  503.     if matches>robot[longestreign].matches then begin longestreign:=i; unequal_matches:=true; end;
  504.     if matches<robot[newestcontender].matches then begin newestcontender:=i; unequal_matches:=true; end;
  505.    end;
  506. end;
  507.  
  508. procedure write_results;
  509. var
  510.  f,f2,f3:text;
  511.  i,j,k:integer;
  512.  fn,fn2,s,e:string;
  513.  r,score:real;
  514.  pairings:longint;
  515. begin
  516.  fn:=tname+result_ext;
  517.  fn2:=tname+'.HTM';
  518.  pairings:=0;
  519.  for i:=num_robots-1 downto 1 do pairings:=pairings+i;
  520.  assign(f,fn); rewrite(f);
  521.  assign(f2,fn2); rewrite(f2);
  522.  assign(f3,'ATRT'+report_ext); rewrite(f3); writeln(f3,num_robots);
  523.  {--RES file header--}
  524.  writeln(f,'Tournament results:   (',base_name(tname),')');
  525.  writeln(f);
  526.  writeln(f,'Number of robots:         ',addfront(cstr(num_robots),5));
  527.  if not report_only then
  528.   begin
  529.    writeln(f,'Matches per pairing:      ',addfront(cstr(matches),5));
  530.    writeln(f,'Number of pairings:       ',addfront(cstr(pairings),5));
  531.    writeln(f,'Total matches:            ',addfront(cstr(pairings*matches),5));
  532.   end;
  533.  writeln(f,'-------------------------------');
  534.  if not report_only then
  535.   begin
  536.    writeln(f,'Total pairings per robot: ',addfront(cstr((num_robots-1)),5));
  537.    writeln(f,'Total matches per robot:  ',addfront(cstr((num_robots-1)*matches),5));
  538.   end;
  539.  writeln(f);
  540.  s:=time; s:=lstr(s,length(s)-5);
  541.  writeln(f,'Results completed: ',s,', ',date);
  542.  writeln(f);
  543.  {--HTML file header--}
  544.  writeln(f2,'<HTML>');
  545.  writeln(f2,'<HEAD>');
  546.  writeln(f2,'<TITLE>AT-Robots Tournament Results (',base_name(tname),')</TITLE>');
  547.  writeln(f2,'</HEAD>'); writeln(f2);
  548.  writeln(f2,'<BODY>');
  549.  writeln(f2,'<BODY BGCOLOR="#C0C0C0" TEXT="#000000" LINK="#0000FF" VLINK="#000080">');
  550.  writeln(f2,'<A NAME = "top"></A>');
  551.  writeln(f2,'<H2 align=center>AT-Robots Tournament Results</H2>');
  552.  writeln(f2,'<H2 align=center>(',base_name(tname),')</H2><BR>');
  553.  writeln(f2);
  554.  writeln(f2,'<BR>');
  555.  writeln(f2,'<CENTER><TABLE align=center border=3>');
  556.  writeln(f2,'<TR border=1><TD>Number of robots: </TD><TD align=right>',addrear(cstr(num_robots),5),'</TD>');
  557.  if not report_only then
  558.   begin
  559.    writeln(f2,'<TR border=1><TD>Matches per pairing: </TD><TD align=right>',addrear(cstr(matches),5),'</TD>');
  560.    writeln(f2,'<TR border=1><TD>Number of pairings:  </TD><TD align=right>',addrear(cstr(pairings),5),'</TD>');
  561.    writeln(f2,'<TR border=1><TD>Total matches:    </TD><TD align=right>',addrear(cstr(pairings*matches),5),'</TD>');
  562.    writeln(f2,'</TABLE></CENTER>');
  563.    writeln(f2,'<CENTER><TABLE align=center border=3>');
  564.    writeln(f2,'<TR border=1><TD>Total pairings per robot:  </TD><TD align=right>',addrear(cstr((num_robots-1)),5),'</TD>');
  565.    writeln(f2,'<TR border=1><TD>Total matches per robot:</TD><TD align=right>',addrear(cstr((num_robots-1)*matches),5),
  566.               '</TD>');
  567.   end;
  568.  writeln(f2,'</TABLE></CENTER>');
  569.  writeln(f2);
  570.  writeln(f2,'<BR>');
  571.  writeln(f2,'<CENTER><TABLE align=center border=3>');
  572.  s:=time; s:=lstr(s,length(s)-5);
  573.  writeln(f2,'<TD align=center>Results completed: ',s,', ',date,'</TD>');
  574.  writeln(f2,'</TABLE></CENTER>');
  575.  writeln(f2,'<BR>');
  576.  
  577.  
  578.  {--RES best/worst list--}
  579.  writeln(f,'Best Survivor:      ',addrear(base_name(robot[bestsurvivor].name),9),
  580.            '(',cstrr(divide(robot[bestsurvivor].wins,robot[bestsurvivor].matches)*100,3),'% wins)');
  581.  writeln(f,'Biggest Loser:      ',addrear(base_name(robot[biggestloser].name),9),
  582.            '(',cstrr(divide(robot[biggestloser].wins,robot[biggestloser].matches)*100,3),'% wins)');
  583.  writeln(f,'Best Killer:        ',addrear(base_name(robot[bestkiller].name),9),
  584.            '(',cstrr(divide(robot[bestkiller].kills,robot[bestkiller].matches),3),' kills/match)');
  585.  writeln(f,'Most Dead:          ',addrear(base_name(robot[mostdead].name),9),
  586.            '(',cstrr(divide(robot[mostdead].deaths,robot[mostdead].matches),3),' deaths/match)');
  587.  writeln(f,'Most Trigger-Happy: ',addrear(base_name(robot[triggerhappy].name),9),
  588.            '(',cstrr(divide(robot[triggerhappy].shots,robot[triggerhappy].matches),2),' shots/match)');
  589.  writeln(f,'Most Conservative:  ',addrear(base_name(robot[conservative].name),9),
  590.            '(',cstrr(divide(robot[conservative].shots,robot[conservative].matches),2),' shots/match)');
  591.  writeln(f,'Best Marksman:      ',addrear(base_name(robot[bestmarksman].name),9),
  592.            '(',cstrr(divide(robot[bestmarksman].hits,robot[bestmarksman].shots)*100,2),'% hit)');
  593.  if robot[haphazard].shots>0 then
  594.  writeln(f,'Most Haphazard:     ',addrear(base_name(robot[haphazard].name),9),
  595.            '(',cstrr(divide(robot[haphazard].hits,robot[haphazard].shots)*100,2),'% hit)');
  596.  writeln(f,'Most Destructive:   ',addrear(base_name(robot[mostdestructive].name),9),
  597.            '(',cstrr(divide(robot[mostdestructive].damage,robot[mostdestructive].matches),2),' damage/match)');
  598.  writeln(f,'Least Effective:    ',addrear(base_name(robot[leasteffective].name),9),
  599.            '(',cstrr(divide(robot[leasteffective].damage,robot[leasteffective].matches),2),' damage/match)');
  600.  writeln(f,'Longest Lived:      ',addrear(base_name(robot[longestlived].name),9),
  601.            '(',cstrr(divide(robot[longestlived].cycles,robot[longestlived].matches),2),' cycles/match)');
  602.  writeln(f,'Shortest Lived:     ',addrear(base_name(robot[shortestlived].name),9),
  603.            '(',cstrr(divide(robot[shortestlived].cycles,robot[shortestlived].matches),2),' cycles/match)');
  604.  if unequal_matches then
  605.   begin
  606.    writeln(f,'Longest Reign:      ',addrear(base_name(robot[longestreign].name),9),
  607.              '(',cstr(robot[longestreign].matches),' matches)');
  608.    writeln(f,'Newest Contender:   ',addrear(base_name(robot[newestcontender].name),9),
  609.              '(',cstr(robot[newestcontender].matches),' matches)');
  610.   end;
  611.  if robot[mosterrors].errors>0 then
  612.  writeln(f,'Most Error-Prone:   ',addrear(base_name(robot[mosterrors].name),9),
  613.            '(',cstrr(divide(robot[mosterrors].errors,robot[mosterrors].matches),3),' errors/match)');
  614.  {--HTML best/worst list--} {err}
  615.  writeln(f2,'<P><CENTER><TABLE border=3 cellpadding=3 cellspacing=0>');
  616.  writeln(f2,'<TR><TD>Best Survivor:      </TD><TD align=right>',base_name(robot[bestsurvivor].name),'    </TD>',
  617.           '<TD>[',cstrr(divide(robot[bestsurvivor].wins,robot[bestsurvivor].matches)*100,3),'% wins]</TD></TR>');
  618.  writeln(f2,'<TR><TD>Biggest Loser:      </TD><TD align=right>',base_name(robot[biggestloser].name),'    </TD>',
  619.           '<TD>[',cstrr(divide(robot[biggestloser].wins,robot[biggestloser].matches)*100,3),'% wins]</TD></TR>');
  620.  writeln(f2,'<TR><TD>Best Killer:        </TD><TD align=right>',base_name(robot[bestkiller].name),'      </TD>',
  621.           '<TD>[',cstrr(divide(robot[bestkiller].kills,robot[bestkiller].matches),3),' kills/match]</TD></TR>');
  622.  writeln(f2,'<TR><TD>Most Dead:          </TD><TD align=right>',base_name(robot[mostdead].name),'        </TD>',
  623.           '<TD>[',cstrr(divide(robot[mostdead].deaths,robot[mostdead].matches),3),' deaths/match]</TD></TR>');
  624.  writeln(f2,'<TR><TD>Most Trigger-Happy: </TD><TD align=right>',base_name(robot[triggerhappy].name),'    </TD>',
  625.           '<TD>[',cstrr(divide(robot[triggerhappy].shots,robot[triggerhappy].matches),2),' shots/match]</TD></TR>');
  626.  writeln(f2,'<TR><TD>Most Conservative:  </TD><TD align=right>',base_name(robot[conservative].name),'    </TD>',
  627.           '<TD>[',cstrr(divide(robot[conservative].shots,robot[conservative].matches),2),' shots/match]</TD></TR>');
  628.  writeln(f2,'<TR><TD>Best Marksman:      </TD><TD align=right>',base_name(robot[bestmarksman].name),'    </TD>',
  629.           '<TD>[',cstrr(divide(robot[bestmarksman].hits,robot[bestmarksman].shots)*100,2),'% hit]</TD></TR>');
  630.  if robot[haphazard].shots>0 then
  631.  writeln(f2,'<TR><TD>Most Haphazard:     </TD><TD align=right>',base_name(robot[haphazard].name),'    </TD>',
  632.           '<TD>[',cstrr(divide(robot[haphazard].hits,robot[haphazard].shots)*100,2),'% hit]</TD></TR>');
  633.  writeln(f2,'<TR><TD>Most Destructive:   </TD><TD align=right>',base_name(robot[mostdestructive].name),' </TD>',
  634.           '<TD>[',cstrr(divide(robot[mostdestructive].damage,robot[mostdestructive].matches),2),' damage/match]</TD></TR>');
  635.  writeln(f2,'<TR><TD>Least Effective:    </TD><TD align=right>',base_name(robot[leasteffective].name),' </TD>',
  636.           '<TD>[',cstrr(divide(robot[leasteffective].damage,robot[leasteffective].matches),2),' damage/match]</TD></TR>');
  637.  writeln(f2,'<TR><TD>Longest Lived:      </TD><TD align=right>',base_name(robot[longestlived].name),'    </TD>',
  638.           '<TD>[',cstrr(divide(robot[longestlived].cycles,robot[longestlived].matches),2),' cycles/match]</TD></TR>');
  639.  writeln(f2,'<TR><TD>Shortest Lived:      </TD><TD align=right>',base_name(robot[shortestlived].name),'    </TD>',
  640.           '<TD>[',cstrr(divide(robot[shortestlived].cycles,robot[shortestlived].matches),2),' cycles/match]</TD></TR>');
  641.  if unequal_matches then
  642.   begin
  643.    writeln(f2,'<TR><TD>Longest Reign:      </TD><TD align=right>',base_name(robot[longestreign].name),'    </TD>',
  644.             '<TD>[',cstr(robot[longestreign].matches),' matches]</TD></TR>');
  645.    writeln(f2,'<TR><TD>Newset Contender:    </TD><TD align=right>',base_name(robot[newestcontender].name),'    </TD>',
  646.             '<TD>[',cstr(robot[newestcontender].matches),' matches]</TD></TR>');
  647.   end;
  648.  if robot[mosterrors].errors>0 then
  649.  writeln(f2,'<TR><TD>Most Error-Prone:   </TD><TD align=right>',base_name(robot[mosterrors].name),'      </TD>',
  650.           '<TD>[',cstrr(divide(robot[mosterrors].errors,robot[mosterrors].matches),3),' errors/match]</TD></TR>');
  651.  writeln(f2,'</TABLE></CENTER><P>');
  652.  
  653.  {--RES top of table--}
  654.  writeln(f);
  655.  writeln(f,'Rank  Robot           Score     Wins/Matches  Kills/Deaths     Hits/Shots');
  656.  writeln(f,'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
  657.  {--HTML top of table--}
  658.  writeln(f2,'<BR>');
  659.  writeln(f2,'<CENTER><TABLE align=center border=5 cellspacing=0>');
  660.  writeln(f2,'<TR border=1><TD align=center>Num:</TD><TD align=center>Rank</TD><TD align=center>Robot</TD>',
  661.             '<TD align=center>== Score ==</TD><TD align=center>Wins/Matches</TD>',
  662.             '<TD align=center>Hits/Shots</TD><TD align=center>Kills/Deaths</TD></TR>');
  663.  writeln(f2);
  664.  
  665.  
  666.  k:=0; score:=0;
  667.  for i:=1 to num_robots do
  668.   with robot[i] do
  669.    begin
  670.     if matches>0 then r:=wins/matches*100 else r:=0;
  671.     if score<>r then begin score:=r; inc(k); end;
  672.     if locked then e:=robot_ext2 else e:=robot_ext;
  673.     writeln(f,addfront(cstr(k),4)+'  '+
  674.               addrear(name+e,12)+addfront(cstrr(r,2)+'%',10)+
  675.               addfront(cstr(wins)+'/'+cstr(matches),16)+
  676.               addfront(cstr(kills)+'/'+cstr(deaths),14)+
  677.               addfront(cstr(hits)+'/'+cstr(shots),15));
  678.     writeln(f2,'<TR border=2><TD align=right>',
  679.               addfront(cstr(i),4),'</TD><TD align=right>',
  680.               addfront(cstr(k),4),'</TD><TD>',
  681.               addrear(name+e,12),'</TD>');
  682.     writeln(f2,'    <TD align=right>',
  683.               addfront(cstrr(r,2)+'%',13),'</TD><TD align=right>',
  684.               addfront(cstr(wins)+'/'+cstr(matches),10),'</TD>');
  685.     writeln(f2,'    <TD align=right>',
  686.               addfront(cstr(hits)+'/'+cstr(shots),13),'</TD><TD align=right>',
  687.               addfront(cstr(kills)+'/'+cstr(deaths),10),'</TD></TR>');
  688.     writeln(f2);
  689.     writeln(f3,wins,' ',matches,' ',kills,' ',deaths,' 0 0 ',shots,' ',
  690.                hits,' ',damage,' ',cycles,' ',errors,' ',name);
  691.    end;
  692.  
  693.  
  694.  {--RES file ender--}
  695.  writeln(f);
  696.  writeln(f,'Generated by ',progname,' ',version);
  697.  writeln(f,cnotice1);
  698.  writeln(f,cnotice2);
  699.  {--HTML file ender--}
  700.  writeln(f2,'</TABLE></CENTER>');
  701.  writeln(f2);
  702.  writeln(f2,'<BR>');
  703.  writeln(f2,'<CENTER><P align=center>');
  704.  if not report_only then
  705.    writeln(f2,'<A href="',lcase(no_path(base_name(tname))),
  706.               '.log">Click here for log</A>');
  707.  writeln(f2,'</P></CENTER>');
  708.  writeln(f2);
  709.  writeln(f2,'<BR><BR><HR>');
  710.  writeln(f2,'<CENTER>');
  711.  writeln(f2,'Generated by ',progname,' ',version,'<BR>');
  712.  writeln(f2,cnotice1,'<BR>');
  713.  writeln(f2,cnotice2,'<BR>');
  714.  writeln(f2,'</CENTER>');
  715.  writeln(f2,'</BODY>');
  716.  writeln(f2,'</HTML>');
  717.  close(f);
  718.  close(f2);
  719.  close(f3);
  720.  writeln('Results written to "',fn,'"');
  721.  writeln('HTML copy written to "',fn2,'"');
  722. end;
  723.  
  724. procedure list_from_report;
  725. var
  726.  i,j,k,l:integer;
  727.  f:text;
  728.  s,fn:string;
  729. begin {err}
  730.  fn:=tname+report_ext;
  731.  if not exist(fn) then exit;
  732.  assign(f,fn);
  733.  reset(f);
  734.  readln(f,num_robots);
  735.  for i:=1 to num_robots do
  736.   with robot[i] do
  737.    begin
  738.     read(f,wins);
  739.     read(f,matches);
  740.     read(f,kills);
  741.     read(f,deaths);
  742.     read(f,j);
  743.     read(f,k);
  744.     read(f,shots);
  745.     read(f,hits);
  746.     read(f,damage);
  747.     read(f,cycles);
  748.     read(f,errors);
  749.     readln(f,s);
  750.     name:=btrim(ucase(s));
  751.     {writeln(name);}
  752.    end;
  753.  close(f);
  754. end;
  755.  
  756. procedure read_report(fn,rn1,rn2:string);
  757. var
  758.  f:text;
  759.  i,j,k,n,armor,heat:integer;
  760.  r:robot_rec;
  761.  s:string;
  762. begin
  763.  writeln(log_file);
  764.  rn1:=base_name(no_path(rn1));
  765.  rn2:=base_name(no_path(rn2));
  766.  writeln(log_file,addrear(rn1,8),' vs ',rn2,':');
  767.  assign(f,fn); reset(f);
  768.  readln(f,k);
  769.  for i:=1 to k do
  770.   with r do
  771.    begin
  772.     read(f,wins);
  773.     read(f,matches);
  774.     read(f,kills);
  775.     read(f,deaths);
  776.     read(f,armor);
  777.     read(f,heat);
  778.     read(f,shots);
  779.     read(f,hits);
  780.     read(f,damage);
  781.     read(f,cycles);
  782.     read(f,errors);
  783.     readln(f,s);
  784.     name:=btrim(ucase(s));
  785.     n:=0;
  786.     for j:=1 to num_robots do
  787.      if ucase(btrim(robot[j].name))=ucase(btrim(name)) then n:=j;
  788.     if n>0 then
  789.      begin
  790.       inc(robot[n].wins,wins);
  791.       inc(robot[n].matches,matches);
  792.       inc(robot[n].kills,kills);
  793.       inc(robot[n].deaths,deaths);
  794.       inc(robot[n].shots,shots);
  795.       inc(robot[n].hits,hits);
  796.       inc(robot[n].damage,damage);
  797.       inc(robot[n].cycles,cycles);
  798.       inc(robot[n].errors,errors);
  799.       writeln(log_file,addrear(name,9),': ',wins,'/',matches,'   [Kills: ',kills,',  Deaths: ',deaths,',  Shots: ',shots,']');
  800.      end;
  801.     if n=0 then writeln(name,' not found!');
  802.    end;
  803.  close(f);
  804.  writeln('Report read.');
  805. end;
  806.  
  807. procedure do_matches;
  808. var
  809.  n1,n2,i,j,k:integer;
  810.  c:char;
  811.  f:text;
  812.  s,rn1,rn2:string;
  813.  pairings:longint;
  814. begin
  815.  n1:=1; n2:=1;
  816.  for i:=1 to num_robots do
  817.   with robot[i] do
  818.    begin wins:=0; matches:=0; end;
  819.  
  820.  if exist(tname+data_ext) then
  821.   writeln('Incomplete tournament found! Tournament will resume!');
  822.  
  823.  pairings:=0;
  824.  for i:=num_robots-1 downto 1 do pairings:=pairings+i;
  825.  
  826.  writeln;
  827.  writeln('Robots: ',num_robots,',  Matches per pairing: ',matches);
  828.  writeln('pairings:  ',pairings,',  Total matches: ',matches*pairings);
  829.  writeln; writeln('The matches are about to begin...');
  830.  write('Proceed? [Y/N] ');
  831.  if yes_to_all then c:='Y' else
  832.     repeat c:=upcase(readkey); until c in ['Y','N'];
  833.  writeln(c); writeln;
  834.  if c='N' then shutdown;
  835.  
  836.  delete_file(tname+list_ext);
  837.  
  838.  if exist(tname+data_ext) then
  839.   begin
  840.    {--must read data to resume--}
  841.    assign(f,tname+data_ext); reset(f);
  842.    readln(f,n1);
  843.    readln(f,n2);
  844.    readln(f,num_robots);
  845.    for i:=1 to num_robots do
  846.     with robot[i] do
  847.      begin
  848.       read(f,wins);
  849.       read(f,matches);
  850.       readln(f,s);
  851.       name:=ucase(btrim(s));
  852.      end;
  853.    close(f);
  854.   end
  855.  else
  856.   delete_file(tname+log_ext);
  857.  
  858.  assign(log_file,tname+log_ext);
  859.  if exist(tname+log_ext) then append(log_file) else rewrite(log_file);
  860.  
  861.  writeln(log_file,'Tournament started: ',time,' ',date);
  862.  writeln(log_file);
  863.  
  864.  abort:=false;
  865.  while (n1<num_robots) and (not abort) do
  866.   begin
  867.    while (n2<=num_robots) and (not abort) do
  868.     begin
  869.      if n1<>n2 then
  870.       begin
  871.        writeln(repchar('-',79));
  872.        writeln(robot[n1].name,' vs ',robot[n2].name,':');
  873.        {pause;}
  874.        delete_file(main_filename+report_ext);
  875.        swapvectors;
  876.        if robot[n1].locked then rn1:=robot[n1].name+robot_ext2 else rn1:=robot[n1].name;
  877.        if robot[n2].locked then rn2:=robot[n2].name+robot_ext2 else rn2:=robot[n2].name;
  878.        exec(main_filename+prog_ext,param_line+' /R4 /L'+cstr(game_limit)
  879.                                   +' /M'+cstr(matches)+' '
  880.                                   +robot_dir+rn1+' '
  881.                                   +robot_dir+rn2);
  882.        swapvectors;
  883.        if not exist(main_filename+report_ext) then abort:=true
  884.         else read_report(main_filename+report_ext,robot[n1].name,robot[n2].name);
  885.        if sound_on then chirp;
  886.       end;
  887.      if not abort then inc(n2);
  888.     end;
  889.    if not abort then begin inc(n1); n2:=n1; end;
  890.   end;
  891.  if abort then
  892.   begin
  893.    writeln('Tournament aborted!');
  894.    {--must write data for future continuation--}
  895.    assign(f,tname+data_ext); rewrite(f);
  896.    writeln(f,n1);
  897.    writeln(f,n2);
  898.    writeln(f,num_robots);
  899.    for i:=1 to num_robots do
  900.     with robot[i] do
  901.      writeln(f,wins,' ',matches,' ',name);
  902.    close(f);
  903.   end else delete_file(tname+data_ext);
  904.  writeln(log_file);
  905.  writeln(log_file,'Tournament stopped: ',time,' ',date);
  906.  close(log_file);
  907.  if (n1>=num_robots) or (n2>num_robots) then complete:=true else complete:=false;
  908.  if complete then writeln('Tournament complete!');
  909. end;
  910.  
  911. procedure main;
  912. begin
  913.  if exist(tname+result_ext) then
  914.   begin
  915.    writeln('Result file already exists! Tournament already completed!');
  916.    writeln;
  917.   end
  918.  else
  919.   begin
  920.    abort:=false;
  921.    if not report_only then
  922.     begin
  923.      if not exist(tname+list_ext) then
  924.         make_robot_list else read_robot_list;
  925.      do_matches;
  926.     end else begin
  927.      list_from_report;
  928.      complete:=true;
  929.     end;
  930.    if (not abort) and (complete) then
  931.     begin
  932.      rank_robots;
  933.      write_results;
  934.     end;
  935.   end;
  936. end;
  937.  
  938. begin
  939.  init;
  940.  main;
  941.  shutdown;
  942. end.
  943.  
  944.