unit uHCTypeDefs;

{$ifdef FPC}
{$mode objfpc}{H+}
{$endif}

interface

uses Classes,
// ALE 20150820 The Delphi mobile compilers don't support AnsiChar and AnsiString
//  the ORawByteString unit masks this deprecation of capability.
{$IFDEF NEXTGEN} ORawByteString, {System.ByteStrings,}{$ENDIF}
uHCDefines;

type
  CBOOL = Byte; // ALE 20110419 BOOLEAN in HC C code
  uchar = Byte;
  puchar = ^Byte;
  short = SmallInt;
  pshort = ^SmallInt;
  ushort =  Word;
  pushort = ^Word;
  long    = LongInt;
  LONGLONG = Int64;
  plong   = ^long;
  ulong = Cardinal;
  ULONGLONG = UInt64;
  DWORD   = Cardinal;
  PDWORD  = ^DWORD;
  ID = ushort;
  HCALTITUDE = uchar;  // ALE altitude band
  HCALTITUDE_M = Int64; // ALE 20160527 Altitude in Meters
  HCUUID = packed array[0..HCUUID_LEN-1] of AnsiChar;
  HCMT = ShortInt; // ALE 20211103 Marker Type (MT_SHIP, MT_SUB, ...)
  // ALE 20230303 introduced for MessageEvent message text encoding/decoding
  THC_TEXT_TYPES = (
   TEXT_TYPE_ASCII = 0,
   TEXT_TYPE_UTF16 = 1,
   TEXT_TYPE_Markdown = 2,
   TEXT_TYPE_HTML = 3
  );

  TIME = LongInt;

  // ALE 20150713 Forward type declarations so we can use them in later types
  PHCRect = ^THCRect;
  PHCDateTimeRec = ^THCDateTimeRec;
  PURegion = ^URegion;
  PTSidesUChar = ^TSidesUChar; // GE will be passing a pointer so we need to receive as one
  PTURegion = ^TURegion;
  PHCMntRec = ^THCMntRec;
  PHCMagRec = ^THCMagRec;
  PHCAirRec = ^THCAirRec;
  PHCPlaneRec = ^THCPlaneRec;
  PHCMissileRec = ^THCMissileRec;
  PHCS_STAFF_WARNED = ^THCS_STAFF_WARNED;
  PHCPathRec = ^THCPathRec;
  PHCGlobals = ^THCGlobals;
  PHCTimeSidePair = ^THCTimeSidePair;
  PHCVictoryConditions = ^THCVictoryConditions;
  PHCHarpoonEvent = ^THCHarpoonEvent;
  PHCHarpoonEvent34803219 = ^THCHarpoonEvent34803219;
  PHCDeadListItem = ^THCDeadListItem;
  PHCAttackEvent = ^THCAttackEvent;
  PHCSpeedAltEvent = ^THCSpeedAltEvent;
  PHCReadyAirEvent = ^THCReadyAirEvent;
  PHCLaunchAirEvent = ^THCLaunchAirEvent;
  PHCLandAirEvent = ^THCLandAirEvent;
  PHCLaunchLandEvent = ^THCLaunchLandEvent;
  PHCSplitGroupEvent = ^THCSplitGroupEvent;
  PHCJoinGroupEvent = ^THCJoinGroupEvent;
  PHCSensorEvent = ^THCSensorEvent;
  PHCFormationEvent = ^THCFormationEvent;
  PHCRepairEvent = ^THCRepairEvent;
  PHCReloadEvent = ^THCReloadEvent;
  PHCIntelligenceEvent = ^THCIntelligenceEvent;
  PHCMessageEvent = ^THCMessageEvent;
  PHCNukeFreeEvent = ^THCNukeFreeEvent;
  PHCSnorkelEvent = ^THCSnorkelEvent;
  PHCEnemyAIEvent = ^THCEnemyAIEvent;
  PHCDamageEvent = ^THCDamageEvent;
  PHCIntermittentSensorsEvent = ^THCIntermittentSensorsEvent;
  PHCAirAttackEvent = ^THCAirAttackEvent;
  PHCAirRefuelEvent = ^THCAirRefuelEvent;
  PHCInterceptEvent = ^THCInterceptEvent;
  PHCMissileAvoidEvent = ^THCMissileAvoidEvent;
  PHCAltCourseEvent = ^THCAltCourseEvent;
  PHCAirPatrolEvent = ^THCAirPatrolEvent;
  PHCRepeatAirEvent = ^THCRepeatAirEvent;
  PHCOrderAttackEvent = ^THCOrderAttackEvent;
  PHCAlternatePathEvent = ^THCAlternatePathEvent;
  PHCPosition = ^THCPosition;
  PHCVariableStartEvent = ^THCVariableStartEvent;
  PHCSpecialRegion = ^THCSpecialRegion;
  PHCSOSUSRegion = ^THCSOSUSRegion;
  PHCSonobuoyRegion = ^THCSonobuoyRegion;
  PHCMinefieldRegion = ^THCMinefieldRegion;
  PHCDLL_FUNC_REF = ^THCDLL_FUNC_REF;
  PHCUnit = ^THCUnit;
  PHCGroup = ^THCGroup;
  PHCBSVars3 = ^THCBSVars3;
  PHCBS_STRINGS = ^THCBS_STRINGS;
  PHCBS_STRINGS_V2 = ^THCBS_STRINGS_V2;
  PHCMagRecDiskPlatform = ^THCMagRecDiskPlatform;
  PHCMagRecsDiskPlatform = ^THCMagRecsDiskPlatform;
  PHCNameRecDiskPlatform = ^THCNameRecDiskPlatform;
  PHCNameRecsDiskPlatform = ^THCNameRecsDiskPlatform;
  PHCPlatformDescription = ^THCPlatformDescription;
  PHCAI_STAYONPATH = ^THCAI_STAYONPATH;
  PHCDATABASE_VERSION = ^THCDATABASE_VERSION;
  PHCLINEAGE_LIST_ITEM = ^THCLINEAGE_LIST_ITEM;
  PHCSCENARIO_LINEAGE = ^THCSCENARIO_LINEAGE;
  PHCSCENARIO_DATA = ^THCSCENARIO_DATA;
  PHCSCENARIO_SAVE_DATA = ^THCSCENARIO_SAVE_DATA;
  PHCLosTable = ^THCLosTable;

  // ALE 20150713 back to our regularly scheduled type definitions

  THCRect = packed record
    left,
    top,
    right,
    bottom: short;
  end;

  THCDateTimeRec = packed record
    year,           // 1904
    month,          // 1=January
    day,            // 1=1st Day of the month
    hour,           // 0=Midnight
    minute,         // 0
    second,         // 0
    dow: long;   // ALE 20150616 unused day of week
  end;

  URegion = packed record  // uncertainty region
    sLon : packed array[0..3] of long; // in slivers, to deg (double)((sLon*360.0)/SLIVER360))
    sLat : packed array[0..3] of long; // in slivers, to deg (double)(90-(sLat*360.0/SLIVER360))
  end;

  TSidesUChar = packed array[0..SIDES-1] of byte;

  TURegion = packed array[0..SIDES-1] of PURegion;

  THCMntRec = packed record
    {$IFNDEF fpc}
    next: ^THCMntRec;
    {$ELSE}
    next: Pointer;
    {$ENDIF}
    MntId,
    WepId: ushort;
    Ammo_c: packed array[0..MOUNTS_PER_MULTI-1] of ushort;
    Time: short;
    Damage,
    Tubes,
    n_Mounts: uchar;
    KnownUse: packed array[0..MOUNTS_PER_MULTI-1] of uchar;
    PossibleUse: packed array[0..MOUNTS_PER_MULTI-1] of uchar;
    Firing: short;
    Targets: ShortInt;
    DummyUsed: Byte;
  end;

  THCMagRec = packed record
    {$IFNDEF fpc}
    next: ^THCMagRec;
    {$ELSE}
    next: Pointer;
    {$ENDIF}
    WepId: ushort; // AnnexID for weapon
    Count: ushort; // quantity of weapon
    ReloadTime: uchar; // how long it takes to reload qty 1 of this weapon
    Dummy: Byte;
  end;

  THCAirRec = packed record
    {$IFNDEF fpc}
    HomeUnit: PHCUnit;
    {$ELSE}
    HomeUnit: Pointer; // ALE 20090914 is PHCUnit but delphi doesn't allow that
    {$ENDIF}
    Endurance,
    DropTanks: LongInt;
    PlatStart,
    PlatNow,
    Ammo_c,
    Throttle,
    DATA,
    OATA: uchar;
    FuelToOffload: long; // ALE 20150611 HC2015.008+ fuel left in tanker in nm
    GameTimeEstablished: long; // ALE 20160307 HC2016.002+ When was the AirRec created
  end;

  THCPlaneRec = packed record
    {$IFNDEF fpc}
    next: ^THCPlaneRec;
    {$ELSE}
    next: Pointer;
    {$ENDIF}
    Time: TIME;
    PlaneID,
    LoadID: ushort;
    Status: uchar;
    name: packed array[0..CLASS_NAME_LEN-1] of AnsiChar;
    PlatNow,
    PatrolFlag,
    LastKnownNumber: uchar;
    Dummy: Byte;
    UUID: HCUUID; // ALE 20170502 unique identifier
  end;

  THCMissileRec = packed record
    targetUnit,
    sourceUnit: Pointer; // ALE 20090914 PHCUnit but delphi doesn't allow that
    sourceMount: PHCMntRec;
    tLat,
    tLon,
    fTime,
    tTime: LongInt;
    tspd: short;
    PlatNow,
    PlatStart,
    targets,
    tcrs,
    tdepth: uchar;
    last_exact_time: TIME;
    guid_phase,
    is_crossing,
    pattern,
    expanding,
    leg_count: ShortInt;
    leg_timer: short;
  end;

  THCS_STAFF_WARNED = packed record
    current,
    max: LongWord;
    units: Pointer; // ALE 20090914 is UnitPtr[0] but delphi doesn't allow that
  end;

  THCPathRec = packed record
    {$IFNDEF fpc}
    next,
    prev: ^THCPathRec;
    {$ELSE}
    next,
    prev: Pointer;
    {$ENDIF}
    DestLon, DestLat: LongInt;
    pathEvents: Pointer; // ALE 20090914 is HarpoonEventPtr
  end;

  THCTimeSidePair = packed record
    side: uchar;
    gameTime: LongInt;
  end;

  THCVictoryConditionLevel = packed record
    firstMinimumVictory: THCTimeSidePair;
    firstTotalVictory: THCTimeSidePair;
    TotalVictoryOnly: packed array[0..SIDES-1] of Byte;
    CurrentVictoryLevels: packed array[0..SIDES-1, 0..SIDES-1, 0..VIC_LEVELS-1] of LongInt;
  end;

  THCGlobals = packed record
    WhichWindowLast: uchar;
    DummyBefore: packed array[0..225-1] of Byte; // ALE 20211210 as of 2021.009 0x34803218
    CurrentVictoryLevel: uchar;
    VictoryConditionLevels: THCVictoryConditionLevel; // ALE 20211210 added for 2021.009 0x34803218
    //DummyAfter: packed array[0..10-1] of Byte; // TODO ALE 20211210 placeholder
  end;

  THCVictoryConditions = packed record
    {$IFNDEF fpc}
    next: ^THCVictoryConditions;
    {$ELSE}
    next: Pointer;
    {$ENDIF}
    TimeOnStation: long;
    DetailType: ushort;
    AreaOnStation: THCRect; // ALE 20130801 check this for validity
    id,
    VicType,
    AndOrFlag,
    WhichSide,
    unitType,
    itemType: uchar;
    percentDamage: uchar;
    numKilled,
    numDamaged: LongInt;
    enemySide: uchar;
    gameTimeAchieved: LongInt;
  end;

  THCDeadListItem = packed record
    next: PHCDeadListItem;
    Annex,          // Annex_ID of class
    count: ushort;  // how many (for all, only one dead record each class)
    side,           // which side this class belongs to
    typeindex,      // KillCount index
    subtype,        // subtype for this unit
    victype: uchar; // broad category for victory grouping
  end;

  THCHarpoonEvent = packed record
    uuid: HCUUID; // ALE 20221003 added for 0x3480321A
    {$IFNDEF fpc}
    // ALE 20230331 doesn't work ourGroup: ^THCGroup;
    ourGroup: Pointer;
    {$ELSE}
    ourGroup: Pointer;  // each event has a master group ALE 2030801 PHCGroup but delphi doesn't allow that
    {$ENDIF}
    DataPtr: Pointer;   // misc data ptr
    {$IFNDEF fpc}
    next: ^THCHarpoonEvent; // next effect in time sorted list
    {$ELSE}
    next: Pointer;
    {$ENDIF}
    Time: long;     // when to execute this effect
    unit_uuid: HCUUID;  // ALE 20221003 added for 0x3480321A to replace UnitID // unit this is for (if any)
    event_type: ulong;  // ALE 20221003 added for 0x3480321A to replace flag (type)
    time_type: ulong;   // AKE 20221003 added for 0x3480321A to replace flag (TimeFlag)
    in_scroll_flag: uchar; // used for path edit
  end;

  THCHarpoonEvent34803219 = packed record // ALE 20230301 old HarpoonEvent structure pre-2023.001, pre dllVerInterface==34
    {$IFNDEF fpc}
    // ALE 20230331 doesn't work ourGroup: ^THCGroup;
    ourGroup: Pointer;
    {$ELSE}
    ourGroup: Pointer;  // each event has a master group ALE 2030801 PHCGroup but delphi doesn't allow that
    {$ENDIF}
    DataPtr: Pointer;   // misc data ptr
    {$IFNDEF fpc}
    next: ^THCHarpoonEvent34803219; // next effect in time sorted list
    {$ELSE}
    next: Pointer;
    {$ENDIF}
    Time: long;     // when to execute this effect
    UnitID: uchar;  // unit this is for (if any)
    flag: uchar;    // bits 0-5 are type, 6-7 TimeFlag
    in_scroll_flag: uchar; // used for path edit
    {
      type flags are:
      0=Attack
      1=Set Altitude & Speed
      2=Ready Aircraft
      3=Launch Aircraft
      4=Split Group
      5=Join Group
      6=Sensor Settings
      7=Formation Editor
      8=Repair Unit
      9=Manual Reload
     10=Sinking Ship
     11=Random Breakdowns
     12=Special Forces Base Attacks
     13=Visual Detection Intelligence (satellite)
     14=Staff Reminder/Special Msg
     15=Nuclear Free w/msg
     16=False Contact
     17=Weather
     18=Snorkel event
     19=Air landing event
     20=Alt path
     21=Enemy AI event
     22=Random Damage
     23=Intermittent Sensors
     24=Air Attack
     25=Unbend Tails (Towed Array)
     26=Sink Sonobuoy
     27=Air Patrol
     28=Intercept
     29=Repeat Air Event
     30=Attack Order
     31=Launch/Land Air
     32=Variable Start Point Event
     33=Missile Avoidance
     34=Alter Course
     35..61 unused
     62=Air refuel
     63=unused but a reminder that this is the max event type value
     Time flags are:
     0=ignore time do now!
     1=time is delta time from entry in queue
     2=time is absolute game time
    }
  end;

  // ALE 20130801 HarpoonEvent Type = 0
  THCAttackEvent = packed record
    TargetGroup: packed array[0..4-1] of AnsiChar; // id of target group
    UnitID,
    TargetID: uchar;
    ourMount: ushort; // mount AnnexID for our unit
    numberRounds: ushort;  // how many missiles,etc
    mountIndex: uchar; // which of 4 for multi mounts
    Dummy: Byte;
    deltaLat,      // distance from target for activation
    deltaLong: long;
    deltaTime: ushort;  // how many seconds until firing
  end;

  // ALE 20130801 HarpoonEvent Type = 1
  THCSpeedAltEvent = packed record
    newSpeed: short; // -1 if no change
    newAltBand: ShortInt; // -1 if no change
    newThrottle: ShortInt; // -1 if no change
    newAltitude: HCALTITUDE_M;	// ALE 20160409 INVALID_ALTITUDE if no change
  end;

  // ALE 20130801 HarpoonEvent Type = 2
  THCReadyAirEvent = packed record
    Identifier: ShortInt; // what airstrike tied to
    oldLoadIDX: Byte;
    whichPlaneType: ushort;
    LoadID: ushort;          // current loadout AnnexID of planes
    numberAircraft: uchar;
    whichMissionCode: uchar; // only used by SE
  end;

  // ALE 20130801 HarpoonEvent Type = 3
  THCLaunchAirEvent = packed record
    targetGroup: packed array[0..4-1] of AnsiChar;
    sLat, sLon: long;                 // patrol destination
    UnitID: uchar;
    Dummy: Byte;
    whichPlaneType: ushort;           // AnnexID of plane
    LoadoutIDX: uchar;                // prepped for which mission?
    numberAircraft: uchar;            // how many
    patrolling: PHCHarpoonEvent;      // Patrol record
  end;

  // ALE 20130801 HarpoonEvent Type = 19
  THCLandAirEvent = packed record
    landGroup: packed array[0..4-1] of AnsiChar;
    landUnit: uchar;                // unit id of unit to land on
    planeUnit: uchar;               // land just unit or whole group
  end;

  // ALE 20130801 HarpoonEvent Type = 31
  THCLaunchLandEvent = packed record
    planes: PHCPlaneRec;
    baseGroup: packed array[0..LEN_GROUP_ID-1] of AnsiChar;
    baseUnit: uchar;                // unit id of unit to land on
    launch: ShortInt;               // launching or landing flag
    targetGroup: packed array[0..LEN_GROUP_ID-1] of AnsiChar;	// ALE 20160323 added, borrowed from LaunchEvent
  end;

  // ALE 20130801 HarpoonEvent Type = 4
  // ALE 20130828 Note that the THCHarpoonEvent.DataPtr
  //  in this case points to a uchar that tells
  //  you how many THCSplitGroupEvents you have.
  //  i.e.
  //   numsplits := uchar(HarpoonEvent.DataPtr^);
  //   P1stSplitGroupEvent := HarpoonEvent.DataPtr + sizeof(uchar);
  //   P2ndSplitGroupEvent := HarpoonEvent.DataPtr + sizeof(uchar) + sizeof(HCSplitGroupEvent);  // second split if numsplits = 2
  //   ...
  THCSplitGroupEvent = packed record
    UnitID: packed array[0..1-1, 0..2-1] of uchar;  // unit and number(if planes) to move
  end;

  // ALE 20130801 HarpoonEvent Type = 5
  // ALE 20130828 Note that the THCHarpoonEvent.DataPtr
  //  in this case points to a short(int) that tells
  //  you how many THCJoinGroupEvents you have.
  //  i.e.
  //   numjoins := short(HarpoonEvent.DataPtr^);
  //   P1stJoinGroupEvent := HarpoonEvent.DataPtr + sizeof(short);
  //   P2ndJoinGroupEvent := HarpoonEvent.DataPtr + sizeof(short) + sizeof(HCJoinGroupEvent);  // second join if numjoins = 2
  //   ...
  THCJoinGroupEvent = packed record
    SplitGroup: packed array[0..4-1] of AnsiChar;
    JoinGroup: packed array[0..4-1] of AnsiChar;
    UnitID: uchar;  // id of unit to move
    Number: uchar;  // number to move if plane unit
  end;

  // ALE 20130802 HarpoonEvent Type = 6
  THCSensorEvent = packed record
    GroupUnitFlag: ShortInt;   // 0=whole group, else unit
    Sensors: packed array[0..3-1] of uchar; // see Unit for explanation
  end;

  // ALE 20130802 HarpoonEvent Type = 7
  THCFormationEvent = packed record
    Xoffset, Yoffset: long;   // used for slaved units
    oldSpeed: short;           // group speed before reform
    // ALE 20170923 to UInt64 for 0x34803216
    rings,
    sectors: UInt64;        // where it will live or patrol
  end;

  // ALE 20130802 HarpoonEvent Type = 8
  THCRepairEvent = packed record
    repairFlagIndex: uchar;   // 0-4 for 1,4,12,24,48 hrs
    Dummy1: Byte;
    ourMountAnnex: ushort; // if below==255, then use mount
    repairAreaIndex: uchar;  // 0-7 for the major damage or 255
    Dummy2: Byte;
  end;

  // ALE 20130802 HarpoonEvent Type = 9
  THCReloadEvent = packed record
    numberRounds: uchar;   // how many moving to mount
    Dummy: Byte;
    ourMountAnnex: ushort; // mount to reload on unit
  end;

  // ALE 20130802 HarpoonEvent Type = 13
  THCIntelligenceEvent = packed record  // ALE 20130805 aka Satellite event
    Message: packed array[0..60-1] of AnsiChar;   // msg on where it comes from
    HowOld: long;   // how old the info in seconds
  end;

  // ALE 20130805 HarpoonEvent Type = 14
  THCMessageEvent = packed record
    Message: packed array[0..4096-1] of AnsiChar;   // message to show the user
    MessageFormat: long; // ALE 20221007 PlainText, HTML, MarkDown, etc. if and when supported, use THC_TEXT_TYPES
    Side: long; // ALE 20221007 side to which to deliver the message if no group is associated
  end;

  // ALE 20230301 old HarpoonEvent structure pre-2023.001, pre dllVerInterface==34
  // ALE 20130805 HarpoonEvent Type = 14
  THCMessageEvent34803219 = packed record
    Message: packed array[0..64-1] of AnsiChar;   // message to show the user
  end;

  // ALE 20130805 HarpoonEvent Type = 15
  THCNukeFreeEvent = packed record
    Side: uchar;                                  // which side gets nuke release
    Message: packed array[0..63-1] of AnsiChar;   // nuclear release message to user
  end;

  // ALE 20130805 HarpoonEvent Type = 18
  THCSnorkelEvent = packed record                 // depth before snorkel
    depth: uchar;
    Dummy: byte;
    kts: short;                                   // speed before snorkel
  end;

  // ALE 20130805 HarpoonEvent Type = 21
  THCEnemyAIEvent = packed record
    targetGroup: packed array[0..4-1] of AnsiChar; // who the enemy is scheming against
    etype: ShortInt;    // subtype of effect
    order: ShortInt;
    data: short;
    range: short;   // effect range
    oldKts: short;  // speed before orders
    oldSlivers: long; // heading before orders
    sLat, sLon: long; // position at order time
  end;

  // ALE 20130805 HarpoonEvent Type = 22
  THCDamageEvent = packed record
    Damage: ushort; // amount of damage
    dtype: uchar;   // type of damage 0-gun, 1-missile, 2-torpedo
    Dummy: byte;
  end;

  // ALE 20130805 HarpoonEvent Type = 23
  THCIntermittentSensorsEvent = packed record
    gtype: uchar; // 0=group, not 0 = unit
    // ALE 20170923 from uchar to UInt64 for 0x34803216
    Zones: packed array [0..3-1] of UInt64;   //  the sensor and zone(s) array
                                             // 1=main body, 2=AAW, 4=ASW, 8=picket
                                             // which sensor 0=Air, 1=ASW, 2=Sonar
    Interval: short; // how many minutes between activations?
    Duration: short; // how many minutes to leave sensors turned on during each interval
    Variance: uchar; // how many minutes variation to the interval
    Toggle: uchar; // 0 if time to turn on, else turn off
  end;

  // ALE 20130805 HarpoonEvent Type = 24
  THCAirAttackEvent = packed record
    targetGroup: packed array [0..4-1] of AnsiChar; // group being attacked
    attackRange: short;   // range of weapons
    attackType: ShortInt;
    eventType: ShortInt;
    data: ShortInt; // data on next uncertain point
    flag: ShortInt;
    dipping: ShortInt;
    Dummy: Byte;
  end;

  // ALE 20130805 HarpoonEvent Type = 62
  THCAirRefuelEvent = packed record
    targetGroup: packed array[0..4-1] of AnsiChar; // group being refueled
    fuelingUnit: uchar;   // unit with the AvGas
    now_refueling: uchar; // have we started refueling?
    fuel_range: long; // how much fueld
    which_plane_type: ushort; // what kind of plane is tanker
    planestofuel: packed array[0..16-1] of uchar; // unit IDs of planes left to fuel
    fuel_per_plane: packed array[0..16-1] of ushort; // how much fuel for each receiving unit
    side: uchar;    // which side
    num_tankers: uchar; // how many tankers in unit
  end;

  // ALE 20130805 HarpoonEvent Type = 28
  THCInterceptEvent = packed record
    targetGroup: packed array[0..4-1] of AnsiChar;  // group to intercept
    targetUnit: uchar;   // unit in target group
    Dummy1: Byte;
    Irange: short;       // how close to get to target
    action: ShortInt;    // action upon intercept
    data: ShortInt;
    flag: ShortInt;
    Dummy2: Byte;
  end;

  // ALE 20130805 HarpoonEvent Type = 33
  THCMissileAvoidEvent = packed record
    missileGroup: packed array[0..4-1] of AnsiChar;  // group to intercept
    missileUnit: uchar;   // unit in target group
    Dummy: Byte;
    course: short;       // original course
    altBand: uchar;      // original altitude
    throttle: uchar;     // original throttle
  end;

  // ALE 20130805 HarpoonEvent Type = 34
  THCAltCourseEvent = packed record
    ourGroup: packed array[0..4-1] of AnsiChar;
    oldcourse: short;       // original course
    newcourse: short;       // new course
  end;

  // ALE 20130805 HarpoonEvent Type = 27
  THCAirPatrolEvent = packed record
    PlaneID: ushort; // AnnexID for this plane class
    LoadoutIDX: uchar; // mission for this patrol type
    PatrolType: ShortInt; // AAW=3,ASuW=1,ASW=2,ESM,Radar,AEW=4,EW=5
    Numer: uchar; // number to be patrolling at a time
    Status: ShortInt;  // current status of patrol
    // ALE 20170923 widened for 0x34803216
    Rings: UInt64; // formation rings to patrol
    Sectors: UInt64; // formation sectors to patrol
  end;

  // ALE 20130805 HarpoonEvent Type = 29
  THCRepeatAirEvent = packed record
    targetGroup: packed array[0..4-1] of AnsiChar; // target group, if any
    sLat, sLon: long; // patrol destination
    interval: short; // how often to send the attackers
    variance: short; // variability in the attack launch timing
    whichPlaneType: ushort; // AnnexID of plane type to use for attack
    LoadoutIDX: uchar;  // which mission prepped for
    numberAircraft: uchar; // how many in each attack attempt
    UnitID: uchar;
    Dummy: Byte;
  end;

  // ALE 20130805 HarpoonEvent Type = 30
  THCOrderAttackEvent = packed record
    targetGroup: packed array[0..4-1] of AnsiChar;
    attackType: ShortInt;
  end;

  // ALE 20130805 HarpoonEvent Type = 20 (only evaluated at scenario start)
  THCAlternatePathEvent = packed record
    PathHead: PHCPathRec; // ptr to new head of path
    PercentChance: uchar; // probability of taking path
    Dummy: Byte;
    offset: long; // file offset to skip to
  end;

  // ALE 20130805 used in THCVariableStartEvent
  THCPosition = packed record
    longitude: long; // x in slivers
    latitude: long;  // y in slivers
  end;

  // ALE 20130805 HarpoonEvent Type = 32 (only evaluated at scenario start)
  THCVariableStartEvent = packed record
    StartPos: THCPosition;
    PercentChance: uchar; // probability of starting at this alternate
    Dummy: Byte;
  end;

  // ALE 20130805 HarpoonEvent Types that don't have special structures
  //  they just use the generic THCHarpoonEvent
  //
  // HarpoonEvent Type = 10 - Sinking Ship
  // HarpoonEvent Type = 11 - Random Breakdowns
  // HarpoonEvent Type = 12 - Special Forces Attacks
  // HarpoonEvent Type = 16 - False Contact (Submarine)
  // HarpoonEvent Type = 17 - Weather Group Movement, Grow/Shrink
  // HarpoonEvent Type = 25 - Unbend Tails (Towed Array)
  // HarpoonEvent Type = 26 - Sink Sonobuoy (never actually called so call it unused)

  THCSpecialRegion = packed record
    {$IFNDEF fpc}
    next,
    prev: ^THCSpecialRegion;
    {$ELSE}
    next,
    prev: Pointer;
    {$ENDIF}
    sLatTop,                // min and max lat/lon values
    sLatBot,
    sLonLeft,
    sLonRight: long;
    time: long;             // when this sonobuoy should be sunk, if it is a SB
    side: uchar;            // side responsible for this region
    prob: uchar;            // the prob of hit or detection
    result: uchar;          // dp for minefields; detect radius for sonobuoys and SOSUS
    Dummy: byte;            // padding
  end;
  THCSOSUSRegion = THCSpecialRegion;
  THCSonobuoyRegion = THCSpecialRegion;
  THCMinefieldRegion = THCSpecialRegion;

  THCDLL_FUNC_REF = packed record
  //typedef struct S_DLL_FUNC_REF
    {$IFNDEF fpc}
    prev, next: PHCDLL_FUNC_REF; //^THCDLL_FUNC_REF;
    {$ELSE}
    prev, next: Pointer;
    {$ENDIF}
    funcPtr: Pointer;   // pointer to the function the DLL will call
    funcName: packed array[0..255-1] of AnsiChar; // name of the function
  end;

  THCNewPtr = function(size:DWORD): Pointer; cdecl;
  THCDisposPtr = procedure(toDispos:Pointer); cdecl;
  THCdel_HarpoonEvent_list = procedure(HarpEventList: Pointer); cdecl;
  THCEffectVoid = function(): CBOOL; cdecl;
  THCEffectShort = function(flag: short): CBOOL; cdecl;
  // ALE 20130908 more function definitions
  THCQueueHarpoonEvent = procedure(HarpoonEventPtr: PHCHarpoonEvent); cdecl;
  THCNewWeatherGroup = function(): PHCGroup; cdecl; // ALE 20130908 really PHCGroup, not Pointer
  THCKilledOff = procedure(UnitKilledPtr: Pointer); cdecl; // ALE 20130908 really PHCUnit, not Pointer
  THCCreateSonobuoy = function(): PHCSonobuoyRegion; cdecl; // ALE 20130908 really PHCSonobuoyRegion
  THCCreateVictoryCondition = function(): PHCVictoryConditions; cdecl; // ALE 20130908 really PHCVictoryConditions
  THCdllCreateGroup = function(side: uchar; sLon: long; sLat: long): PHCGroup; cdecl; // ALE 20130907 really PHCGroup
  // ALE 20131015 return HC altitude band for a given lat/lon if it exists on the current map
  THCdllCheckLatLonDepth = function(lat: Double; lon: Double): short; cdecl;
  THCannex_id_to_disk_id = function(annex_id: ID): ID; cdecl; // ALE 20150820 memory to disk ID
  THCdisk_id_to_annex_id = function(disk_id: ID): ID; cdecl; // ALE 20150820 disk ID to memory ID if platform in scenario
  // ALE 20170602 typedef uchar(__cdecl *PROCUCHARUSHORTUSHORT)(ushort, ushort); // ALE 20131015 uchar GetLoadoutIndex(ushort PlaneID, ushort LoadoutID)
  THCGetLoadoutIndex = function(PlaneID: ID; LoadoutID: ID): uchar; cdecl;
  // ALE 20170602 typedef void(__cdecl *PROCVOIDPCHAR)(char *); // ALE 20170310 void MessageLogLine(char *), void EndGame(char *)
  THCMessageLogLine = procedure(Message: PAnsiChar); cdecl;
  THCExitGame = procedure(ExitMessage: PAnsiChar); cdecl;
  // ALE 20180212 typedef void(__cdecl *PROCPVOIDGROUPPTR)(GroupPtr); // ALE 20180212 void ResetGroupCenter(GroupPtr group)
  THCResetGroupCenter = procedure(pGroup: PHCGroup); cdecl;
  // ALE 20180222 typedef void(__cdecl *PROCVOIDGROUPPTRSHORTPCHARPCHARLONG)(GroupPtr, short, char *, char *, long); // ALE 20180228 void SetCourseGroupRaw(GroupPtr pGroup, short pCourse, char const *pCallerName, char const *pCallerFile, long const pCallerFileLine)
  THCSetCourseGroup_Raw = procedure(pGroup: PHCGroup; pCourse: short; pCallerName: PChar; pCallerFile: PChar; pCallerFileLine: long); cdecl;
  // ALE 20180222 typedef void(__cdecl *PROCVOIDUNITPTRSHORTPCHARPCHARLONG)(UnitPtr, short, char *, char *, long); // ALE 20180228 void SetCourseUnitRaw(UnitPtr pUnit, short pCourse, char const *pCallerName, char const *pCallerFile, long const pCallerFileLine)
  THCSetCourseUnit_Raw = procedure(pUnit: PHCUnit; pCourse: short; pCallerName: PChar; pCallerFile: PChar; pCallerFileLine: long); cdecl;
  // ALE 20200815 typedef void(__cdecl *PROCGROUPPTRBOOLEAN)(GroupPtr, BOOLEAN); // ALE 20200815 long assign_group_id(GroupPtr group, BOOLEAN allowExportDLL)
  // ALE 20220216 added pAllowExportDLL parameter to specify whether we let an ExportDLL assign group id
  THCassign_group_id = function(pGroup: PHCGroup; pAllowExportDLL: CBOOL): long; cdecl;
  // ALE 20230424 typedef void(__cdecl *PROCPVOIDUNITPTR)(UnitPtr);
  THCfree_Unit = procedure(pUnit: PHCUnit); cdecl;
  // ALE 20230424 typedef void(__cdecl *PROCPVOIDGROUPPTR)(GroupPtr);
  THCfree_Group = procedure(pGroup: PHCGroup); cdecl;
  // ALE 20250220 typedef GroupPtr(__cdecl* PROCPGROUPPTRGROUPPTR)(GroupPtr);
  THCChangeActGroupPtr = function(pGroup: PHCGroup): PHCGroup; cdecl;
  // ALE 20250220 typedef UnitPtr(__cdecl* PROCPUNITPTRUNITPTR)(UnitPtr);
  THCChangeActUnitPtr = function(pUnit: PHCUnit): PHCUnit; cdecl;
  // ALE 20250228 typedef void(__cdecl* PROCVOIDSHORTSHORT)(short, short);
  THCZoomWindow = procedure(ZoomDir: short; GroupUnitWindow: short); cdecl;
  // ALE 20250528 typedef char(__cdecl* PROCCHARPCHARBOOL)(char*, BOOL);
  THCSaveGame = procedure(pSaveName: PAnsiChar; pAutoSave: uchar); cdecl;


  // ALE 20170526 @ 0x34803216 definition
  THCUnit = packed record
    Group: PHCGroup;
    toNorth, toSouth: PHCUnit;
    prev, next: PHCUnit;
    Mnts: ^THCMntRec;
    Mags: ^THCMagRec;
    Air: ^THCAirRec;
    Missile: ^THCMissileRec;
    myPlanes: ^THCPlaneRec;
    staff_warned: ^THCS_STAFF_WARNED;
    sLon, sLat,
    xOff, yOff,
    speed,
    MapXref, MapYref,
    TimeOnStation: LongInt;
    Annex: ushort;
    SensId: packed array[0..MAX_UNIT_SENSORS-1] of ushort;
    crits,
    fireAreas: ushort;
    CurrDp,
    OrigDp,
    TacXref, TacYref,
    maxspeed,
    kts,
    course,
    BestAAWRange,
    BestASuWRange,
    BestASWRange: short;
    UncertaintyRegion: packed array[0..SIDES-1] of PURegion;
    LastLon: packed array[0..SIDES-1] of LongInt;
    LastLat: packed array[0..SIDES-1] of LongInt;
    NumFound: packed array[0..SIDES-1] of ushort;
    CountPassFC: packed array[0..SIDES-1] of ushort;
    Data: packed array[0..SIDES-1] of ushort;
    Method: packed array[0..SIDES-1] of UInt64; // ALE 20170221 for 2017.003 verSaveGame=$34803215, was ushort;
    MinBearing: packed array[0..SIDES-1] of short;
    MaxBearing: packed array[0..SIDES-1] of short;
    MinRange: packed array[0..SIDES-1] of short;
    MaxRange: packed array[0..SIDES-1] of short;
    ClosestActualRange: packed array[0..SIDES-1] of short;
    showing: packed array[0..SIDES-1] of uchar;
    fontIndex,
    flooding,
    maneuver,
    tac_map_flag,
    AltBand: uchar;
    RepTries: packed array[0..6-1] of uchar;
    emit,
    detect: UInt64; // ALE 20170221 for 2017.003 verSaveGame=$34803215 from ushort
    arad_d_rng: packed array[0..3-1] of ushort;
    srad_d_rng: packed array[0..3-1] of ushort;
    UnitSearchRange: ushort;
    jammed: LongInt;
    Sensors: packed array[0..3-1] of uchar;
    SenStat: packed array[0..MAX_UNIT_SENSORS-1] of uchar;
    ir_d_val,
    esm_d_val,
    arad_type,
    srad_type,
    arad_pd,
    srad_pd,
    RCS,
    VCS,
    son_rng,
    son_pd,
    hyd_rng,
    hyd_pd,
    acz, pcz,
    aczpd, pczpd,
    id: uchar;
    rings,
    sectors: UInt64; // ALE 20170526 for 2017.008 verSaveGame=$34803216 from uchar
    independent,
    VisibleDamage: uchar;
    utype: HCMT;
    victype,
    subtype: ShortInt;
    name: packed array[0..CLASS_NAME_LEN-1] of AnsiChar;
    son_pdm,
    hyd_pdm,
    tails: ShortInt;
    WhichVictCond,
    VictoryFlag,
    LaunchFlag,
    CombatFlag,
    Flag: uchar;
    SourceLevel,
    BaseSourceLevel,
    SelfNoise,
    Interference,
    BestFOM,
    DetectionThreshold: ShortInt;
    AgroundFlag: Byte;
    // ALE 20150617 New for 0x3480320F
    NameDB: LongInt; // ALE 20150617 UNIT_USE_CUSTOM_NAME to pull name from DB instead of Scen, for ship/sub index into names from DB, not used by GE
    // ALE 20160315 New for 0x34803213
    Altitude: Int64; // ALE 20160315 in Meters above avg sea level, used for gradual altitude changes
  	// ALE 20170502 New for 0x34803216
	  UUID: HCUUID; // ALE 20170502 unique identifier for this unit
  end;

  // ALE 20170526 @ 0x34803216 definition
  THCGroup = packed record
    toNorth, toSouth: PHCGroup;
    Units: PHCUnit;
    track: ^THCPathRec;
    UncertaintyRegion: PURegion;
    xShow, yShow,
    sLon, sLat,
    slivers,
    speed,
    MapXref, MapYref: LongInt;
    StaffCount: packed array[0..10-1] of short;
    StaffFlags: ushort;
    ecm: ushort;
    PlatStart, PlatNow,
    kts,
    course,
    maxspeed,
    OpXref, OpYref,
    EnemyRange,
    AlertTimer: short;
    BestSensorRange: packed array[0..2-1] of short;
    BestWeaponsRange: packed array[0..2-1] of short;
    side,
    op_map_flag,
    RCS,
    VCS,
    SensorMode,
    showing,
    fontIndex: uchar;
    zones: packed array[0..MAX_FORMATION_ZONES-1] of short; // ALE 20170526 for 2017.008 verSaveGame=$34803216 from count of 4 uchar
    alert,
    SeaState,
    Precip,
    Vis: uchar;
    jammed: LongInt;
    gtype: HCMT;
    id: packed array[0..LEN_GROUP_ID8-1] of AnsiChar; // ALE 20170526 for 2017.008 verSaveGame=$34803216 from 4
    weapons: ShortInt;
    AI: packed array[0..53-1] of Byte; // TODO ALE 20170526 need to unwrap AI_STATE
    // staff flags
    Flag: uchar; // BITFIELD: (0) mark for group scroll
    AIChance: uchar;			// how much chance will the group take?
    // ALE 20170502 New for 0x34803216
    UUID: HCUUID; // ALE 20170502 unique identifier for this group
  end;


 THCBSVars3 = packed record
   StartBSVar3: Byte; // Dummy byte
   DBinBS: uchar; // True or False, database embedded in the battleset file
   MapY: ulong; // Y pixels of non-textured map
   MapX: ulong; // X pixels of non-textured map
   BSVer: ulong; // Version of Battleset structure
   ScenOrSav: array[0..MAX_SCENINBS] of uchar; // V1 and up - True if slot is scenario, False if save
   Spares: array[0..32735] of Byte; // padding
   EndBSVar: Byte; // Dummy byte
 end;

  // ALE 20150916 Start accumulating the non lettered Annex information
  THCBS_STRINGS = packed record // ALE 20230424 RESRSRStructureVersion == 6
    SideName: array[0..MAX_SIDE_NAMES-1, 0..SIDE_NAME_SIZE-1] of AnsiChar;
    CountryName: array[0..MAX_COUNTRIES-1, 0..COUNTRY_NAME_SIZE-1] of AnsiChar;
    ShipType: array[0..MAX_SHIP_TYPES-1, 0..SHIP_TYPE_SIZE-1] of AnsiChar;
    ACType: array[0..MAX_AC_TYPES-1, 0..AC_TYPE_SIZE-1] of AnsiChar;
    ACShortType: array[0..MAX_AC_SHT_TYPES-1, 0..AC_SHT_TYPE_SIZE-1] of AnsiChar;
    ACStatusString: array[0..MAX_AC_STAT_STRS-1, 0..AC_STAT_STR_SIZE-1] of AnsiChar;
    LoadoutString: array[0..MAX_LOADOUT_STRS-1, 0..LOADOUT_STR_SIZE-1] of AnsiChar;
    RunwayString: array[0..MAX_RUNWAY_SIZES-1, 0..RUNWAY_STR_SIZE-1] of AnsiChar; // ALE 20210203 added for V5
    BroadVicType: array[0..MAX_BROAD_TYPES-1, 0..BROAD_TYPE_SIZE-1] of AnsiChar; // ALE 20230424 added for V6
  end;

  THCBS_STRINGS_V5 = packed record // ALE 20201130 RESRSRStructureVersion == 5
    SideName: array[0..MAX_SIDE_NAMES-1, 0..SIDE_NAME_SIZE-1] of AnsiChar;
    CountryName: array[0..MAX_COUNTRIES-1, 0..COUNTRY_NAME_SIZE-1] of AnsiChar;
    ShipType: array[0..MAX_SHIP_TYPES-1, 0..SHIP_TYPE_SIZE-1] of AnsiChar;
    ACType: array[0..MAX_AC_TYPES-1, 0..AC_TYPE_SIZE-1] of AnsiChar;
    ACShortType: array[0..MAX_AC_SHT_TYPES-1, 0..AC_SHT_TYPE_SIZE-1] of AnsiChar;
    ACStatusString: array[0..MAX_AC_STAT_STRS-1, 0..AC_STAT_STR_SIZE-1] of AnsiChar;
    LoadoutString: array[0..MAX_LOADOUT_STRS-1, 0..LOADOUT_STR_SIZE-1] of AnsiChar;
    RunwayString: array[0..MAX_RUNWAY_SIZES-1, 0..RUNWAY_STR_SIZE-1] of AnsiChar; // ALE 20210203 added for V5
  end;

  THCBS_STRINGS_V4 = packed record // ALE 20201130 RESRSRStructureVersion == 4
    SideName: array[0..MAX_SIDE_NAMES-1, 0..SIDE_NAME_SIZE-1] of AnsiChar;
    CountryName: array[0..MAX_COUNTRIES-1, 0..COUNTRY_NAME_SIZE-1] of AnsiChar;
    ShipType: array[0..MAX_SHIP_TYPES-1, 0..SHIP_TYPE_SIZE-1] of AnsiChar;
    ACType: array[0..MAX_AC_TYPES-1, 0..AC_TYPE_SIZE-1] of AnsiChar;
    ACShortType: array[0..MAX_AC_SHT_TYPES-1, 0..AC_SHT_TYPE_SIZE-1] of AnsiChar;
    ACStatusString: array[0..MAX_AC_STAT_STRS-1, 0..AC_STAT_STR_SIZE-1] of AnsiChar;
    LoadoutString: array[0..MAX_LOADOUT_STRS-1, 0..LOADOUT_STR_SIZE-1] of AnsiChar;
  end;

  THCBS_STRINGS_V3 = packed record // ALE 20201130 RESRSRStructureVersion == 3
    SideName: array[0..MAX_SIDE_NAMES-1, 0..SIDE_NAME_SIZE-1] of AnsiChar;
    CountryName: array[0..MAX_COUNTRIES-1, 0..COUNTRY_NAME_SIZE-1] of AnsiChar;
    ShipType: array[0..V3_MAX_SHIP_TYPES-1, 0..V3_SHIP_TYPE_SIZE-1] of AnsiChar;
    ACType: array[0..V3_MAX_AC_TYPES-1, 0..V3_AC_TYPE_SIZE-1] of AnsiChar;
    ACShortType: array[0..V3_MAX_AC_SHT_TYPES-1, 0..V3_AC_SHT_TYPE_SIZE-1] of AnsiChar;
    ACStatusString: array[0..MAX_AC_STAT_STRS-1, 0..AC_STAT_STR_SIZE-1] of AnsiChar;
    LoadoutString: array[0..MAX_LOADOUT_STRS-1, 0..LOADOUT_STR_SIZE-1] of AnsiChar;
  end;
  
  THCBS_STRINGS_V2 = packed record
    SideName: array[0..MAX_SIDE_NAMES-1, 0..SIDE_NAME_SIZE-1] of AnsiChar;
    CountryName: array[0..V2_MAX_COUNTRIES-1, 0..V2_COUNTRY_NAME_SIZE-1] of AnsiChar;
    ShipType: array[0..V2_MAX_SHIP_TYPES-1, 0..V2_SHIP_TYPE_SIZE-1] of AnsiChar;
    ACType: array[0..V2_MAX_AC_TYPES-1, 0..V2_AC_TYPE_SIZE-1] of AnsiChar;
    ACShortType: array[0..V2_MAX_AC_SHT_TYPES-1, 0..V2_AC_SHT_TYPE_SIZE-1] of AnsiChar;
    ACStatusString: array[0..MAX_AC_STAT_STRS-1, 0..AC_STAT_STR_SIZE-1] of AnsiChar;
    LoadoutString: array[0..MAX_LOADOUT_STRS-1, 0..LOADOUT_STR_SIZE-1] of AnsiChar;
  end;


  // ALE 20150923 like MagRec except we add a ->prev so we can free memory more easily
  THCMagRecDiskPlatform = packed record
    next: PHCMagRecDiskPlatform;
    prev: PHCMagRecDiskPlatform;
    WepId: ID;            // weapon id
    Count: ushort;            // how many in magazine
    ReloadTime: uchar;       // how long it takes to load 1 of this weapon
  end;

  // ALE 20150920 wrap up each unit's magazines so we can later use
  //  this to load a scenario
  THCMagRecsDiskPlatform = packed record
    next: PHCMagRecsDiskPlatform;		// ALE 20150923 next platform
    prev: PHCMagRecsDiskPlatform;		// ALE 20150923 previous platform for when we want to free memory
    DiskId: ID;		// ALE 20150920 platform disk ID
    MagStart: long;	// ALE 20150922 starting location of the magazines in bytes
    MagCount: long;	// ALE 20150922 how many magazines for this platform?
    Mags: PHCMagRecDiskPlatform;		// ALE 20150922 the list of magazines for this platform
  end;

  // ALE 20150924 keep track of ship name so we can later use them to load a scenario
  THCNameRecDiskPlatform = packed record
    next: PHCNameRecDiskPlatform;
    prev: PHCNameRecDiskPlatform;
    name_offset: long; // ALE 20150924 starting location of the ship_name in bytes
    name_len: long;    // ALE 20150924 how many characters long is the name
    name: array[0..CLASS_NAME_LEN-1] of AnsiChar;
  end;

  THCNameRecsDiskPlatform = packed record
    next: PHCNameRecsDiskPlatform;
    prev: PHCNameRecsDiskPlatform;
    DiskId: ID; // ALE 20150920 platform disk ID
    count: long;  // ALE 20150924 how many names for this platform?
    names: PHCNameRecDiskPlatform;
  end;

  // ALE 20150916 Platform text descriptions
  THCPlatformDescription = packed record
    index: long; // TextIndex
    description: PAnsiChar; // ALE 20150929 null terminated string of characters;
  end;

  // ALE 20150610 Should the AI chase after targets of opportunity of not
  THCAI_STAYONPATH = packed record
	  ship: packed array[0..SIDES-1] of AnsiChar;
	  sub: packed array[0..SIDES-1] of AnsiChar;
	  land: packed array[0..SIDES-1] of AnsiChar;
  end;

  // ALE 20170923 2017.011 Just widened the timestamp to 64-bits
  THCDATABASE_FILE_VERSION = packed record
    flavor: packed array[0..DATABASE_FLAVER_LEN - 1] of AnsiChar;
    created: Int64;
  end;

  THCDATABASE_VERSION = packed record
    RESFile: THCDATABASE_FILE_VERSION;
    RSRFile: THCDATABASE_FILE_VERSION;
  end;

  // ALE 20170923 Information about the scenario and its lineage
  THCLINEAGE_LIST_ITEM = packed record
    uuid: HCUUID;
    dtstamp: Int64;
    // ALE 20170906 how about we add build, database, scenarioversion, saveversion?
    DatabaseVersion: THCDATABASE_VERSION;
    ScenarioVersion: ulong; // ALE 20170906 0 for no version defined
    SEVersion: packed array[0..32 - 1] of AnsiChar; // ALE 20170906 EOS for no version defined
    next: PHCLINEAGE_LIST_ITEM;
  end;

  THCSCENARIO_LINEAGE = packed record
    // ALE 20170724 Keep track of the UUID history for this scen
    Count: ulong; // How many entries are there in the list?
    Top: THCLINEAGE_LIST_ITEM; // First entry in the list
    Bottom: PHCLINEAGE_LIST_ITEM; // Last entry in the list
  end;

  THCSCENARIO_DATA = packed record
    // ALE 20170726 Backporting SCENARIO_DATA structure
    //  added in v002
    DatabaseVersion: THCDATABASE_VERSION; // Database with which the scen was most recently saved
    //  added in v003
    ai_stayonpath: THCAI_STAYONPATH;
    dt_scen_start: THCDateTimeRec;
    // added in v005
    // ALE 20170724 Keep track of the UUID history for this scen
    Lineage: THCSCENARIO_LINEAGE;
    // ALE 20170724 add more scenario-level items here
  end;

  // ALE 20170923 Information about the saved game to help uniquely identify
  THCSCENARIO_SAVE_DATA = packed record
    // ALE 20151021 Why the orders for each side even though Green can't really have orders
    //  the scenario background is included for each side, there is
    //  no unique separation between background and orders :(.
    Orders: packed array[0..SIDES - 1] of PAnsiChar;
    OrdersShortDesc: PAnsiChar; // ALE 20151022 ofen the scenario file name

    uuid: HCUUID;	// ALE 20170823 uuid of current savegame state
    uuid_prev: HCUUID;	// ALE 20170823 uuid previously used for this session
  end;

  THCLosTable = packed array[0..10, 0..10] of short;

  // ALE 20090914 classes not in HC
  THCUnitList = class(TList)
  private
  protected
    function GetItems(Index: Integer): PHCUnit;
    procedure SetItems(Index: Integer; AUnit: PHCUnit);
  public
    function Add(AUnit: PHCUnit): Integer;
    function Remove(AUnit: PHCUnit): Integer;
    function IndexOf(AUnit: PHCUnit): Integer;
    procedure Insert(Index: Integer; AUnit: PHCUnit);
    property Items[Index: Integer]: PHCUnit read GetItems write SetItems;
  end;

  THCGroupList = class(TList)
  private
  protected
    function GetItems(Index: Integer): PHCGroup;
    procedure SetItems(Index: Integer; AGroup: PHCGroup);
  public
    function Add(AGroup: PHCGroup): Integer;
    function Remove(AGroup: PHCGroup): Integer;
    function IndexOf(AGroup: PHCGroup): Integer;
    procedure Insert(Index: Integer; AGroup: PHCGroup);
    property Items[Index: Integer]: PHCGroup read GetItems write SetItems;
  end;

implementation


{ THCUnitList }

function THCUnitList.Add(AUnit: PHCUnit): Integer;
begin
  Result := inherited Add(AUnit);
end;

function THCUnitList.GetItems(Index: Integer): PHCUnit;
begin
  result:= inherited Get(Index);
end;

function THCUnitList.IndexOf(AUnit: PHCUnit): Integer;
begin
  Result := inherited IndexOf(AUnit);
end;

procedure THCUnitList.Insert(Index: Integer; AUnit: PHCUnit);
begin
  inherited Insert(Index, AUnit);
end;

function THCUnitList.Remove(AUnit: PHCUnit): Integer;
begin
  Result := IndexOf(AUnit);
  if Result <> -1 then
    Delete(Result);
end;

procedure THCUnitList.SetItems(Index: Integer; AUnit: PHCUnit);
begin
  inherited Put(Index, AUnit);
end;

{ THCGroupList }

function THCGroupList.Add(AGroup: PHCGroup): Integer;
begin
  Result := inherited Add(AGroup);
end;

function THCGroupList.GetItems(Index: Integer): PHCGroup;
begin
  result:= inherited Get(Index);
end;

function THCGroupList.IndexOf(AGroup: PHCGroup): Integer;
begin
  Result := inherited IndexOf(AGroup);
end;

procedure THCGroupList.Insert(Index: Integer; AGroup: PHCGroup);
begin
  inherited Insert(Index, AGroup);
end;

function THCGroupList.Remove(AGroup: PHCGroup): Integer;
begin
  Result := IndexOf(AGroup);
  if Result <> -1 then
    Delete(Result);
end;

procedure THCGroupList.SetItems(Index: Integer; AGroup: PHCGroup);
begin
  inherited Put(Index, AGroup);
end;

end.
