/**************************************************************
 * FFTacticsMUD : update.cpp                                  *
 **************************************************************
 * (c) 2002 Damien Dailidenas (Trenton). All rights reserved. *
 **************************************************************/

#include "main.h"

void	idle_update	args(());
void	logout_update	args(());

void battle_update() {
  CH *ch, *ch_next;
  STATUS *status, *status_next;

  for(BATTLE *battle = battle_list, *battle_next; battle; battle = battle_next) {
    battle_next = battle->next;

    if(battle->turn)
      continue;

    for(ch = battle->people; ch; ch = ch->next_in_battle)
      if(ch->CT >= 100)
        goto CR_phase;

    /****************
     * <do>         *
     * S+ phase     *
     * SR phase     *
     * C+ phase     *
     * CR phase     *
     * Status Check *
     * <loop>       *
     ****************/

    /************
     * S+ phase *
     ************/
    for(ch = battle->people; ch; ch = ch->next_in_battle)
      if(ch->action.ctr)
        --ch->action.ctr;

    /************
     * SR phase *
     ************/
    for(ch = battle->people; ch; ch = ch_next) {
      ch_next = ch->next_in_battle;

      if(ch->action.action && !ch->action.ctr) {
        ch->resolve_action();

        if(!battle)
          return;   
      }
    }

    /**********************
     * Status Check phase *
     **********************/
    for(ch = battle->people; ch; ch = ch->next_in_battle) {
      for(status = ch->status_list; status; status = status_next) {
        status_next = status->next;
  
        if(!--status->ctr) 
          ch->remove(status, true);
      }
    }

    /************   
     * C+ phase *
     ************/
    for(ch = battle->people; ch; ch = ch->next_in_battle)
      ch->CT += ch->Sp;
        
    /************
     * CR phase *
     ************/   
  CR_phase:
    for(ch = battle->people; ch; ch = ch->next_in_battle) {
      if(ch->CT >= 100) {
        if(ch->status(status_dead)) {
            ch->CT = 0;
            ch->status_update();
            continue; 
        }
    
        battle->turn = ch;
        battle->echo(ch->name + "'s turn.\n\r");
        ch->cancel(status_defending, false);
      
        if(ch->npc)
          ch->npc_turn();
        else {   
          ch->commands = "move act wait";
          ch->printf("{^MOVE, ACT, or WAIT?{0\n\r");
        }
      
        break;
      }
    }

    if(!battle)
      continue;     
  }
     
  return;
}

void update_handler() {
  static int pulse_point;
  static int pulse_battle;
        
  if(--pulse_point <= 0) {
    pulse_point = PULSE_TICK;
    idle_update();
    logout_update();
  }
    
  if(--pulse_battle <= 0) {
    pulse_battle = PULSE_BATTLE;
    battle_update();
  }
        
  return;
}

void idle_update() {
  for(CH *ch = ch_list; ch; ch = ch->next) {
    if(ch->npc)
      continue;

    ++ch->timer, ++ch->mins_total, ++ch->mins_login;

    if(ch->mins_login % 10 == 0)
      ch->save();
  }

  return;
}

void logout_update() {
  for(CH *ch = ch_list, *ch_next = NULL; ch; ch = ch_next) {
    ch_next = ch->next;

    if((!ch->npc && !ch->desc) || (!ch->npc && !ch->admin && ch->timer > 10))
      do_quit(ch);
  }

  for(DESC *d = desc_list, *d_next = NULL; d; d = d_next) {
    d_next = d->next;

    if(d->connected == CON_GET_NAME && ++d->timer > 1)
      d->close_socket();
  }

  return;
}