unit uUtil;

interface

uses
  SysUtils, uDefines, uTypeDefs, uHCTypeDefs;

function SideToStr(Side: byte): string;
function ScenUnit_v00_2_v01(ScenUnit_v00: ScenarioUnit_v00): ScenarioUnit_v01;
function assign_group_id(var groupForId: THCGroup; const grouplist:GroupList): group_id;
function ANNEX(const annex_id: ushort): ushort;

implementation

uses uGlobals, uHCDefines;

function SideToStr(Side: byte): string;
begin
  case Side of
//    -1: result := 'NULLSIDE';
    0: result := 'BLUESIDE';
    1: result := 'REDSIDE';
    2: result := 'GREENSIDE';
    3: result := 'UNKNOWNSIDE';
  end;
end;

{*** Convert a version 0 scenario unit to a version 1 scenario unit ***}
function ScenUnit_v00_2_v01(ScenUnit_v00: ScenarioUnit_v00): ScenarioUnit_v01;
var
  ScenUnit_v01: ScenarioUnit_v01;
  intC: integer;
begin
  ScenUnit_v01.xOff := ScenUnit_v00.xOff;
  ScenUnit_v01.yOff := ScenUnit_v00.yOff;
  ScenUnit_v01.disk_id := ScenUnit_v00.disk_id;
  for intC := 0 to 3 do
  begin
    ScenUnit_v01.parent_id[intC] := ScenUnit_v00.parent_id[intC];
  end;
  ScenUnit_v01.parent_base := ScenUnit_v00.parent_base;
  ScenUnit_v01.Dummy := ScenUnit_v00.Dummy;
  ScenUnit_v01.name_offset := ScenUnit_v00.name_offset;
  ScenUnit_v01.name_length := ScenUnit_v00.name_length;
  ScenUnit_v01.PlatStart := ScenUnit_v00.PlatStart;
  ScenUnit_v01.in_air := ScenUnit_v00.in_air;
  ScenUnit_v01.mission := ScenUnit_v00.mission;
  ScenUnit_v01.rings := ScenUnit_v00.rings;
  ScenUnit_v01.sectors := ScenUnit_v00.sectors;
  ScenUnit_v01.percent_chance := ScenUnit_v01.percent_chance;
  for intC := 0 to CLASS_NAME_LEN-1 do
  begin
    ScenUnit_v01.UnitName[intC] := Chr(0);
  end;

  result := ScenUnit_v01;
end;
{*** end ScenUnit_v00_2_v01 ***}

{*** assign an ID to a group ***}
{/*============================== assign_group_id ===========================*/
/*--------------------------------------------------------------------------
 * Purpose:           assign a group's id based on order of introduction to
 *                    game
 * Called By:         CreateGroup
 * Calls:             none
 * Parameters:        group -- the group, or NULL if reset
 * Global Inputs:     none
 * Global Outputs:    none
 * Returns:           nothing
 * Logic Description:
 * Revision History:  5-21-89, RSM, documented.
 *                    5-25-89, RSM, *** FINISHED ***.
 *--------------------------------------------------------------------------*/
void assign_group_id(GroupPtr group)  }
function assign_group_id(var groupForId: THCGroup; const grouplist: GroupList): group_id;
var
  notfound: Boolean;
  foundmatch: Boolean;
  intC1: Integer;
  scanGroup: THCGroup;
begin

  //*---------------------------------------*/
  //* if NULL was passed, reset id counters */
  //*---------------------------------------*/

  // ALE 20081117 assuming we aren't asking for a new group of a scen in progress
  {
  if (group == NULL) then
  begin
    current_id_friendly = current_id_enemy = current_id_other = 0;
    return;
  end;
  }

  // jdk: the group id doesn't get null terminated below.
  // ALE 20081117 already allocated memset ( group->id, 0, sizeof ( group->id ) );

{*
keene 12/95
MAJOR BUG, id's can cross over in big scenarios, essentially each side
is limited to about 338 groups each (13x26 characters), such that only
676 groups can be created during the scenario.  There is NO CHECKING done
to ensure an id used by the other side is not used!
The fix is to scan from AA up or ZZ down for unused group id's, as new ones
are added, this slows down this routine dramatically, but is the only
solid alternative.
*}
  //*------------------------------------*/
  //* BLUE id's go from AA, AB to ZY, ZZ */
  //*------------------------------------*/

  // NEUTRALSIDE here is a huge kludge!
  if (groupForId.side = BLUESIDE) then
  begin
    if (intCurrent_ID_Friendly < 8*26) then
    begin
      groupForId.id[0] := AnsiChar(Chr(Ord(AnsiChar('A')) + intCurrent_ID_Friendly div 26));
      groupForId.id[1] := AnsiChar(Chr(Ord(AnsiChar('A')) + intCurrent_ID_Friendly mod 26));
      Inc(intCurrent_ID_Friendly);
    end
    else
    begin
      //* scan from the beginning till we find an empty group */
      groupForId.id[0] := 'A';
      groupForId.id[1] := 'A';
      notfound := True;
      while (notfound = True) do
      begin
        scanGroup := grouplist[0];
        foundmatch := False;
        for intC1 := 0 to Length(grouplist)-1 do
        begin
          if ((groupForId.id[0] = scanGroup.id[0]) AND
              (groupForId.id[1] = scanGroup.id[1])) then
          begin
            foundmatch := True;
            Break;
          end;
        end;
        if (foundmatch = False) then
        begin
          notfound := False;
          //* use the id [0][1] as is */
        end
        else
        begin
          Inc(groupForId.id[1]);
          if (groupForId.id[1] > 'Z') then
          begin
            groupForId.id[1] := 'A';
            Inc(groupForId.id[0]);
            if (groupForId.id[0] > 'Z') then
            begin
              notfound := False;
              //Debugger(); // this is a fatal condition, no groups left
            end;
          end;
        end;
      end;
    end;
  end

  //*-----------------------------------*/
  //* RED id's go from ZZ, ZY to AB, AA */
  //*-----------------------------------*/
  else if (groupForId.side = REDSIDE) then
  begin
    if (intCurrent_ID_Enemy < 8*26) then
    begin
      groupForId.id[0] := AnsiChar(Chr(Ord(AnsiChar('Z')) - intCurrent_ID_Enemy div 26));
      groupForId.id[1] := AnsiChar(Chr(Ord(AnsiChar('Z')) - intCurrent_ID_Enemy mod 26));
      Inc(intCurrent_ID_Enemy);
    end
    else
    begin
      //* scan from the end till we find an empty group */
      groupForId.id[0] := 'Z';
      groupForId.id[1] := 'Z';
      notfound := True;
      while (notfound = True) do
      begin
        scanGroup := grouplist[0];
        foundmatch := False;
        for intC1 := 0 to Length(grouplist)-1 do
        begin
          if ((groupForId.id[0] = scanGroup.id[0]) AND
              (groupForId.id[1] = scanGroup.id[1])) then
          begin
            foundmatch := True;
            Break;
          end;
        end;
        if (foundmatch = False) then
        begin
          notfound := False;
          //* use the id [0][1] as is */
        end
        else
        begin
          Dec(groupForId.id[1]);
          if (groupForId.id[1] < 'A') then
          begin
            groupForId.id[1] := 'Z';
            Dec(groupForId.id[0]);
            if (groupForId.id[0] < 'A') then
            begin
              notfound := False;
              //Debugger(); // this is a fatal condition, no groups left
            end;
          end;
        end;
      end;
    end;
  end

  //*------------------------------------*/
  //* NEUTRAL id's go from 0A to 9Z		 */
  //*------------------------------------*/
  else if (groupForId.side = GREENSIDE) then
  begin
    if (intCurrent_ID_Other < 10*26) then
    begin
      groupForId.id[0] := AnsiChar(Chr(Ord(AnsiChar('0')) + intCurrent_ID_Other div 26));
      groupForId.id[1] := AnsiChar(Chr(Ord(AnsiChar('A')) + intCurrent_ID_Other mod 26));
      Inc(intCurrent_ID_Other);
    end
    else
    begin
      //* scan from the beginning till we find an empty group */
      groupForId.id[0] := '0';
      groupForId.id[1] := 'A';
      notfound := True;
      while (notfound = True) do
      begin
        scanGroup := grouplist[0];
        foundmatch := False;
        for intC1 := 0 to Length(grouplist)-1 do
        begin
          if ((groupForId.id[0] = scanGroup.id[0]) AND
              (groupForId.id[1] = scanGroup.id[1])) then
          begin
            foundmatch := True;
            Break;
          end;
        end;
        if (foundmatch = False) then
        begin
          notfound := False;
          //* use the id [0][1] as is */
        end
        else
        begin
          Inc(groupForId.id[1]);
          if (groupForId.id[1] > 'Z') then
          begin
            groupForId.id[1] := 'A';
            Inc(groupForId.id[0]);
            if (groupForId.id[0] > '9') then
            begin
              notfound := False;
              //Debugger(); // this is a fatal condition, no groups left
            end;
          end;
        end;
      end;
    end;
  end;
end;
{*** end assign_group_id ***}

function ANNEX(const annex_id: ushort): ushort;
begin
//		  ((ID)((annex_id) & ANNEX_MASK))
  result := annex_id AND ANNEX_MASK;
end;
end.
