

#process "mbuild"

class auto_move;

core_quad_B, 0, 
  {object_build, 0},
  {object_none, 0},
  {object_move:auto_move, -1174},
  {object_move:auto_move, 1114},

#code




// Process AI modes (these reflect the capabilities of the process)
enum
{
  MODE_IDLE, // process isn't doing anything ongoing
  MODE_MOVE, // process is moving to target_x, target_y
  MODE_MOVE_BUILD, // process is moving somewhere to build a process there
  MODES
};

// Commands that the user may give the process
// (these are fixed and should not be changed, although not all processes accept all commands)
enum
{
  COM_NONE, // no command
  COM_LOCATION, // user has right-clicked somewhere on the display or map
  COM_TARGET, // user has right-clicked on an enemy process
  COM_FRIEND, // user has right-clicked on a friendly process
  COM_DATA_WELL, // user has right-clicked on a data well
  COM_NUMBER // user has pressed a number key
};

// Targetting information
// Targetting memory allows processes to track targets (enemy or friend)
// The following enums are used as indices in the process' targetting memory
enum
{
  TARGET_PARENT, // a newly built process starts with its builder in address 0
  TARGET_BUILT, // processes built by this process
};


// 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 (or -2048) up.
angle = get_core_angle(); // angle is updated each cycle

int mode; // what is the process doing? (should be one of the MODE enums)

int move_x, move_y; // destination
int target_x, target_y; // location of target (to attack, follow etc)

int scan_result; // used to hold the results of a scan of nearby processes

// builder variables
int build_multi; // indicates that user has commanded repeat build (by pressing control)
int build_result; // build result code (returned by build call)
int build_x, build_y; // build location for move-build commands
int build_target_angle; // used in calculating target for commands that result in MODE_MOVE_BUILD
int initialised; // set to 1 after initialisation code below run the first time

if (!initialised)
{
   // initialisation code goes here (not all autocoded processes have initialisation code)
  initialised = 1;
  // move the process forward a bit to stop it obstructing the next process to be built
  mode = MODE_MOVE;
  move_x = core_x + cos(angle, 300);
  move_y = core_y + sin(angle, 300);
}

int verbose; // if 1, process will print various things to the console

if (check_selected_single()) // returns 1 if the user has selected this process (and no other processes)
{
  if (!verbose) printf("\nProcess selected.");
  verbose = 1;
  set_debug_mode(1); // 1 means errors for this process will be printed to the console. Resets to 0 each cycle
}
  else
    verbose = 0;


// Accept commands from user
if (check_new_command() == 1) // returns 1 if a command has been given
{
  switch(get_command_type()) // get_command_type() returns the type of command given
  {
    case COM_LOCATION:
    case COM_DATA_WELL: // this process can't harvest, so treat data well commands as location commands
      move_x = get_command_x(); // get_command_x() and ...y() return the target location of the command
      move_y = get_command_y();
      mode = MODE_MOVE;
      if (verbose) printf("\nMoving.");
      break;
    
    case COM_TARGET:
      if (verbose) printf("\nTarget command not recognised.");
      break;
    
    case COM_FRIEND:
      if (verbose) printf("\nFriendly target command not recognised.");
      break;
    
    default:
      if (verbose) printf("\nUnrecognised command.");
      break;
  
  } // end of command type switch
} // end of new command code


if (check_new_build_command() == 1) // build commands are separate from move/attack commands
{
  if (get_build_command_ctrl() == 0) // returns 1 if control was pressed at the last point of giving the build command
  {
    build_multi = 0; // just build one
    if (verbose) printf("\nBuilding.");
  }
    else
    {
      build_multi = 1; // build repeatedly
      if (verbose) printf("\nRepeat building.");
    }
  
  build_x = get_build_command_x();
  build_y = get_build_command_y();
  if (check_build_range(build_x, build_y) == 0) // 0 means the build location is out of range
  {
    mode = MODE_MOVE_BUILD;
    // let's move to somewhere near the build location, but not right on it (or this process might get in the way)
    build_target_angle = atan2(build_y - core_y, build_x - core_x);
    move_x = build_x - cos(build_target_angle, 300); // stop short of target
    move_y = build_y - sin(build_target_angle, 300);
    if (verbose) printf("\nMoving to build location.");
  } // end if (check_build_range(build_x, build_y) == 0)
} // end if (check_new_build_command() == 1)

if (check_build_command() == 1) // check for queued build commands
{
  build_result = build_as_commanded(TARGET_BUILT); // build_as_commanded automatically executes the build command
  if (build_result == 1) // 1 means success
  {
    if (build_multi == 0)
      clear_build_command(); // only clear the command if not multi-building
    if (verbose) printf("\nProcess built.");
  } // end if (build_result == 1)
} // end if (check_build_command() == 1)




// What the process does next depends on its current mode
switch(mode)
{
  
  case MODE_IDLE:
    auto_move.set_power(0); // turn off all objects in the move class
    break;
  
  case MODE_MOVE:
  // stop moving when within 255 pixels of target (can change to higher or lower values if needed)
    if (distance_from_xy_less(move_x, move_y, 255))
    {
      clear_command(); // cancels the current command. If there's a queue of commands (e.g. shift-move waypoints)
       //  this moves the queue forward so that check_new_command() will return 1 next cycle.
      mode = MODE_IDLE;
      if (verbose) printf("\nReached destination.");
    }
      else
        auto_move.move_to(move_x, move_y); // calls move_to for all objects in the move class
    break;
  
  case MODE_MOVE_BUILD:
  // stop moving when within 80 pixels of target (can change to higher or lower values if needed)
    if (distance_from_xy_less(build_x, build_y, 800)) // build range is about 1000
    {
      build_result = build_as_commanded(-1); // -1 means that the newly built process is not targetted
      if (build_result == 1) // 1 means success
      {
        clear_build_command();
        mode = MODE_IDLE;
        if (verbose) printf("\nFinished building.");
      }
    }
      else
        auto_move.move_to(move_x, move_y); // calls move_to for all objects in the move class
    break;

} // end of mode switch
