

#process "base2"

class auto_att_right;
class auto_allocate;
class auto_harvest;
class auto_att_left;
class auto_att_fwd;
class auto_att_back;

core_static_hex_C, 6840, 
  {object_repair_other, 0},
  {object_downlink, 0, 
    {component_bowl, // component 1
      {object_uplink, 0},
      {object_interface, 0},
      {object_interface_depth, 0},
      {object_storage, 0},
      {object_pulse_l:auto_att_fwd, 0},
    }
  },
  {object_allocate:auto_allocate, 0},
  {object_downlink, -847, 
    {component_bowl, // component 2
      {object_uplink, 0},
      {object_interface_depth, 0},
      {object_interface, 0},
      {object_storage, 0},
      {object_stream_dir:auto_att_right, -500},
    }
  },
  {object_downlink, 0, 
    {component_bowl, // component 4
      {object_uplink, 0},
      {object_build, 0},
      {object_interface, 0},
      {object_repair, 0},
      {object_stream_dir:auto_att_back, -667},
    }
  },
  {object_downlink, 971, 
    {component_bowl, // component 3
      {object_uplink, 0},
      {object_interface_depth, 0},
      {object_interface, 0},
      {object_harvest:auto_harvest, 0},
      {object_stream_dir:auto_att_left, -1071},
    }
  }

#code


enum
{
TARGET_PARENT, // TM 0 is set to parent process

TARGET_HARVESTER_0,
TARGET_HARVESTER_1,
TARGET_BUILDER,
TARGET_LEADER,

TARGET_JUST_BUILT,

TARGET_LEFT, // target of directional left attack
TARGET_RIGHT, // target of directional right attack
TARGET_FRONT, // target of directional front attack
TARGET_BACK,

TARGET_THREAT,

TM_END
};

enum
{
TEMPLATE_BASE,
TEMPLATE_BUILDER,
TEMPLATE_HARVESTER,
TEMPLATE_LEADER,
TEMPLATE_FIGHTER,
TEMPLATE_FIGHTER2,
TEMPLATE_FASTSCOUT
};

// Variable declaration and initialisation
//  (note that declaration and initialisation cannot be combined)
//  (also, variables retain their values between execution cycles)
int core_x, core_y; // location of core
core_x = get_core_x(); // location is updated each cycle
core_y = get_core_y();
int angle; // direction process is pointing
 // angles are in integer degrees from 0 to 8192, with 0 being right,
 // 2048 down, 4096 left and 6144 up.

int initialised;

int this_is_main_base; // is 1 if this is the main base. Only main base builds harvesters.
int received_main_base_broadcast; // the main base broadcasts an "i am the main base" announcement.
int received_dont_build_broadcast; // is 1 if another process is trying to build something expensive.
int fighter_template, fighter_type_change;
received_dont_build_broadcast = 0;
received_main_base_broadcast = 0;

// This process keeps records of data wells so it can tell harvesters etc where to go:
int known_data_well_x [16];
int known_data_well_y [16];


if (!initialised)
{
 initialised = 1;
 angle = get_core_angle(); // only need to check this once as process is static
 listen_channel(1); // 1 is for messages to bases
 listen_channel(2); // 2 is for messages to builders in general
 received_main_base_broadcast = -1; // when process just spawned, shouldn't assume that it is or is not the main base
 fighter_template = TEMPLATE_FIGHTER;
 fighter_type_change = 8; // will build this many type 1 fighters before starting to build type 2
}



int build_result; // build result code (returned by build call)
int i;

int special_build_counter;

// listen to broadcasts from other processes
while(check_messages()) // returns number of unread messages received since the last cycle
{
 switch(read_message())
 {
  case 10: // 10 is broadcast by main base
   received_main_base_broadcast = 1; 
   break;

  case 20: // 20 means please don't build anything this cycle
   received_dont_build_broadcast = 1;
   break;

 }
 next_message();
}


// check for whether there is another main base
if (received_main_base_broadcast == 0) // main base doesn't exist, or has just been destroyed, and no other base has claimed its place.
 this_is_main_base = 1; // so this base will claim the status of main base

if (this_is_main_base)
{
// every cycle, the main base broadcasts an announcement that the main base exists, so that no other base will try to become the main base
 broadcast(-1, // range of broadcast (in pixels). -1 means unlimited range.
           1, // channel - other processes must be listening on this channel to receive the message
           1, // priority - 0 or 1. 0 means message may be replaced by priority 1 messages
           10); // message contents - 10 means an announcement that this process is the main base.
}



if (received_dont_build_broadcast) // another process is waiting for there to be enough data to build something expensive
 goto finished_building;


if (special_build_counter < 4)
{

 if (special_build_counter == 3
  && process[TARGET_LEADER].visible()) // only build scout if leader present
 {
  build_result = build_process(TEMPLATE_FASTSCOUT, cos(angle, 400), sin(angle, 400), angle, TARGET_JUST_BUILT);
  if (build_result == 1)
   special_build_counter ++;
  goto finished_building;
 }

 build_result = build_process(fighter_template, cos(angle, 400), sin(angle, 400), angle, TARGET_JUST_BUILT);
 if (build_result == 1)
 {
  special_build_counter ++;
  fighter_type_change --;
  if (fighter_type_change < 0)
  {
   fighter_template = TEMPLATE_FIGHTER2;
   fighter_type_change = 0;
  }
  if (process[TARGET_LEADER].visible())
  {
   if (special_build_counter & 1)
    transmit(TARGET_JUST_BUILT, 1, 41); // 41 means "please guard me"
     else
      transmit_target(TARGET_JUST_BUILT, 1, TARGET_LEADER, 42); // 42 means "please guard the target attached to the transmission"
  }
 }
 goto finished_building;
}



if (this_is_main_base) // only the main base tries to build harvesters and builders
{

// check whether each harvester entry in targetting memory has something:
 for (i = TARGET_HARVESTER_0; i < TARGET_BUILDER; i ++)
 {
  if (process[i].visible() <= 0) // doesn't exist
  {
// a harvester is missing or has never been built. Try to build one.
   if (get_available_data() < get_template_cost(TEMPLATE_HARVESTER))
   {
    gosub please_dont_build;
   }
    else
    {
      build_result = build_process(TEMPLATE_HARVESTER, cos(angle, 400), sin(angle, 400), angle, i);
//   if (build_result == 1)
//    special_build_counter = 0;
      goto finished_building;
    }
  }
 }

 if (process[TARGET_PARENT].visible() <= 0) // build builder only if parent doesn't exist
 {
  i = TARGET_BUILDER;
  if (process[i].visible() <= 0) // doesn't exist
  {
   if (get_available_data() < get_template_cost(TEMPLATE_BUILDER))
   {
    gosub please_dont_build;
   }
    else
    {
      build_result = build_process(TEMPLATE_BUILDER, cos(angle, 400), sin(angle, 400), angle, i);
//   if (build_result == 1)
//    special_build_counter = 0;
      goto finished_building;
    }
  }
 }
}


// try to build a large attacking process
 if (process[TARGET_LEADER].visible() <= 0) // doesn't exist
 {
  if (get_available_data() < get_template_cost(TEMPLATE_LEADER))
  {
    gosub please_dont_build;
  }
    else
    {
      build_result = build_process(TEMPLATE_LEADER, cos(angle, 400), sin(angle, 400), angle, TARGET_LEADER);
      if (build_result == 1)
       special_build_counter = 0;
    }
  goto finished_building;
 }


special_build_counter = 0;



finished_building:

auto_att_back.attack_scan(4096, 400, TARGET_BACK);

auto_att_left.attack_scan(-3000, 400, TARGET_LEFT);

auto_att_right.attack_scan(3000, 400, TARGET_RIGHT);

auto_att_fwd.attack_scan(0, 400, TARGET_FRONT);

if (scan_for_threat(0, 0, TARGET_THREAT))
{
// tell nearby processes about the target:
   broadcast_target(4000, // range of broadcast, in pixels
                    4, // channel
                    1, // priority
                    TARGET_THREAT, // the target will be broadcast so other processes can find it directly
// message contents:
                    1, // indicates target found
                    process[TARGET_THREAT].get_core_x(),
                    process[TARGET_THREAT].get_core_y());

}


charge_interface_max(); // charges the process' interface. Since the interface is shared across all
 // components with interface objects, this call is not specific to any object or class.
 // charge_interface_max() charges the interface using any power left over.


restore_self(); // tries to restore any destroyed components

repair_self(); // tries to repair any damaged components

restore_scan(0,0); // scans for nearby processes with destroyed components and tries to restore them

repair_scan(0,0); // scans for nearby damaged processes and tries to repair them



auto_harvest.gather_data();

auto_allocate.allocate_data(4); // actually I think the maximum is 2

exit;

// subroutine that asks other processes not to build (while this one waits for more data)
please_dont_build:
     broadcast(-1, // range of broadcast (in pixels). -1 means unlimited range.
               2, // channel - other processes must be listening on this channel to receive the message
               0, // priority - 0 or 1. 0 means message may be replaced by priority 1 messages
               20); // message contents
 return;
