Posted to tcl by hypnotoad at Mon Dec 08 22:00:08 GMT 2014view pretty

/*
** Advance a crew member by ms milliseconds or less.  Return any time
** remaining.
*/
int Crew_Member_Step(Crew *crewPtr, int ms){
  Waypoint *pW=NULL;
  Portal *pPortal=NULL;
  if (crewPtr->public_paused) {
    return 0;
  }
  if (crewPtr->public_team > 1 && crewPtr->public_team != crewPtr->id) {
    return 0;
  }

  if(!crewPtr->aStep) {
    crewPtr->public_operation=CREW_OPERATION_DONE;
  }

  switch( crewPtr->public_operation ){
    case CREW_OPERATION_ERROR:
      crewPtr->public_operation=CREW_OPERATION_ERROR;
      crewPtr->public_countdown=0;
      return 0;
    case CREW_OPERATION_BLOCKED:
      crewPtr->public_operation=CREW_OPERATION_BLOCKED;
      crewPtr->public_countdown=0;
      return 0;
    case CREW_OPERATION_TRAFFIC:
    case CREW_OPERATION_QUEUED:
    case CREW_OPERATION_MOVE:
    case CREW_OPERATION_OPEN:
    case CREW_OPERATION_VTRANS: 
    case CREW_OPERATION_TRANS:
    case CREW_OPERATION_CLOSE:
      crewPtr->blockedReason=NULL;
      break;

    case CREW_OPERATION_ARRIVED:
    case CREW_OPERATION_STOPPED:
    case CREW_OPERATION_DONE:
    default:
      crewPtr->blockedReason=NULL;
      crewPtr->public_operation=CREW_OPERATION_DONE;
      crewPtr->public_countdown=0;
      return 0;
  }

  /*
  ** If we are in a countdown mode,
  ** finish the countdown
  */
  if( crewPtr->public_countdown>ms ){
    crewPtr->public_countdown -= ms;
    return 0;
  }
  ms-=crewPtr->public_countdown;
  crewPtr->public_countdown=0;
  
  crewPtr->public_moved=1;
  pW = &crewPtr->aStep[crewPtr->iStep];
  
  
  
  if(pW->pid) {
    pPortal=Portal_ById(pW->pid,0);
    if(!pPortal) {
      /* Treat any transition with a non-existent portal as a move */
      crewPtr->public_operation=CREW_OPERATION_MOVE;
    }
  }
  crewPtr->public_moved=1;
  if(crewPtr->public_operation==CREW_OPERATION_MOVE || crewPtr->public_operation==CREW_OPERATION_TRAFFIC) {
    int msUsed,offset=0;
    if(crewPtr->iStep<(crewPtr->nStep-1)) {
      offset=0;
    } else {
      offset=crewPtr->targetDistance;     
    }
    if(pW->pid) {
      crewPtr->public_operation = CREW_OPERATION_OPEN;
    } else {
      int movecode=advanceCrewToWaypoint(crewPtr,ms,pW,offset,&msUsed);
      switch(movecode) {
        case 0: {
          ms-=msUsed;
          crewPtr->public_compartment_entering = 0;
          LinkRemove(&crewPtr->link2);
          return ms;
        }
        case 1: {
          if(pW->pid) {
            crewPtr->public_portal = pW->pid;
          } else {
            gotoNextStep(crewPtr);
            msUsed = 0;
            return ms;
          }
        }
        case 2: {
          Crew_Halt(crewPtr,CREW_OPERATION_ERROR);
          return 0;
        }
      }
    }
  }

  if(crewPtr->public_operation==CREW_OPERATION_OPEN) {
    /* Trying to open a portal.  If the portal is on an airlock and
    ** the airlock is open, then reset the timer and keep trying.
    */
    int code=0;
    
    crewPtr->public_portal = pW->pid;
    code=Portal_Action(pPortal,crewPtr,PORTAL_ACTION_OPEN,pW->openTm*100);
    if(code<0) {
      /*
      ** Portal could not be opened
      */
      Portal_Release(pPortal,crewPtr);
      Crew_Halt(crewPtr,CREW_OPERATION_BLOCKED);
      return 0;
    }
    if(code>0) {
      /*
      ** Waiting for the door to become available
      ** or for the door to finish opening
      */
      return 0;
    }
    if(crewPtr->public_moving!=CREW_MOVING_FLEEING) {
      Compartment *pTo=Compartment_ById(pW->cid,0);
      if(pTo->public_accessible > crewPtr->public_protected) {
        Compartment *pFrom=Compartment_ById(crewPtr->public_compartment,0);
        if (pTo->public_accessible > pFrom->public_accessible) {
          /*
          ** RULE: crew-movement-0001
          ** A crewman will not transition from a compartment with
          ** a lower accessible score to a higher accessible score
          ** unless the higher accessible score is less than or
          ** equal to the crew's protection rating
          */
          /*
          ** Cannot transit, close the door and halt
          */
          if(!anybodyWantsPortalOpen(crewPtr, pW->pid, pW->x, pW->y, pW->deckid) ){
            code=Portal_Action(pPortal,crewPtr,PORTAL_ACTION_CLOSE,pW->closeTm*100);
            if(code==1) {
              /*
              ** Waiting for portal to close
              */
              return 0;
            }
          }
          Portal_Release(pPortal,crewPtr);
          crewPtr->blockedReason="crew-movement-0001";
          Crew_Halt(crewPtr,CREW_OPERATION_BLOCKED);
          return 0;
        }
      }
    }
    crewPtr->public_operation=CREW_OPERATION_QUEUED;
    if(pPortal->delta->public_door_state != pPortal->public_door_state) {
      /*
      ** If we did change the state of the door, count that
      ** as time served
      */
      return 0;
    }
  }
  if(crewPtr->public_operation==CREW_OPERATION_QUEUED) {
    int msUsed=0;
    /*
    ** Count the crew going through the portal. If it
    ** exceeds the number of crew rated, enter wait state
    */
    if(pPortal->public_transit_count) {
      Crew *p;
      int count=0;
      for(p=CurrentSim->pAllCrew; p; p=p->pNext){
        if(p->id==crewPtr->id) continue;
        if(p->public_portal==pW->pid) {
          if(p->public_operation==CREW_OPERATION_VTRANS || p->public_operation==CREW_OPERATION_TRANS) {
            count++;
          }
        }
      }
      /*
      ** Waiting for portal
      */
      if(count>=pPortal->public_transit_count) {
        return 0;
      }
    }
    int transitTime=pW->transTm*100;
    if(pPortal->public_transit_count && crewPtr->public_team) {
      transitTime=pW->transTm*100*(crewPtr->inParty+1)/pPortal->public_transit_count;
    }
    crewPtr->public_compartment_entering = pW->cid;
    crewPtr->public_countdown=transitTime;
    if(crewPtr->deckid != pW->deckid) {
      crewPtr->deckchange=1;
      crewPtr->public_operation=CREW_OPERATION_VTRANS;
    } else {
      crewPtr->deckchange=0;
      crewPtr->public_operation=CREW_OPERATION_TRANS;
    }
    pW->cost =  transitTime/1000 + pW->closeTm*0.1;
    
    return 0;
  }
  if(crewPtr->public_operation==CREW_OPERATION_VTRANS
  || crewPtr->public_operation==CREW_OPERATION_TRANS) {
    int code=2;
    code=Portal_Action(pPortal,crewPtr,PORTAL_ACTION_TRANSIT,1);
    /* Manage Airlock */
    if(code<0) {
      Portal_Release(pPortal,crewPtr);
      Crew_Halt(crewPtr,CREW_OPERATION_BLOCKED);
      return 0;
    }
    if(code>0) {
      /*
      ** Waiting for the transit time to elapse
      */
      return 0;
    }
    /* Move the crew to the waypoint */
    crewPtr->tx=pW->x;
    crewPtr->ty=pW->y;
    crewPtr->x=pW->x;
    crewPtr->y=pW->y;
    crewPtr->deckid=pW->deckid;
    crewPtr->public_countdown = 0;
    /* Start the close operation */
    crewPtr->public_operation = CREW_OPERATION_CLOSE;
    pW->cost = pW->closeTm*0.1;
  }
  if(crewPtr->public_operation==CREW_OPERATION_CLOSE) {
    /* Close a portal after moving through it.
    */
    crewPtr->public_compartment=pW->cid;
    crewPtr->public_compartment_entering=0;
    int close=0;
    crewPtr->nextPid = 0;
    if(!anybodyWantsPortalOpen(crewPtr, pW->pid, pW->x, pW->y, pW->deckid) ){
      close=Portal_Action(pPortal,crewPtr,PORTAL_ACTION_CLOSE,pW->closeTm/10.0);
      if(close==1) {
        /*
        ** Waiting for portal to close
        */
        return 0;
      }
    }
    crewPtr->public_portal=0;
    crewPtr->public_compartment_entering = 0;
    Portal_Release(pPortal,crewPtr);
    pW->cost = 0;
    gotoNextStep(crewPtr);
    return 0;
  }
  return ms;
}