Beispiel #1
0
group_t* emitterEmit(emitter_t* emitter, double deltaT){
    part_t* part = NULL;
    group_t* group = NULL;
    
    if(!emitter) return group;
    
    // init
    vect_t speed;
    double speedAngle;
    double random = (double) rand() / RAND_MAX;
    
    // check random value
    if(random < deltaT * emitter->flow){
        part = partNew();
        partSetPos(part, emitter->pos);
        
        group = groupNew();
        groupSetPos(group, emitter->pos);
        
        // calculate speed
        speedAngle = emitter->alpha * (1.0 - 2.0 * rand() / RAND_MAX);
        speed.x = emitter->speed * cos(emitter->angle + speedAngle);
        speed.y = emitter->speed * sin(emitter->angle + speedAngle);
        groupSetSpeed(group, speed);
        
        groupSetType(group, GROUP_TYPE_HARMLESS);
        groupAdd(group, part);
    }
    
    return group;
}
void multitrain_driver() {
  MultiTrainDriver me;

  initDriver(&me);
  unsigned int naggCount = 0;
  unsigned int updateStoppingDistanceCount = 0;

  for (;;) {
    int tid = -1;
    MultiTrainDriverMsg actualMsg;
    DriverMsg* msg = (DriverMsg*)&actualMsg;
    msg->data3 = 0;
    Receive(&tid, (char *)msg, sizeof(MultiTrainDriverMsg));
    if (msg->type != REPORT_INFO &&
        msg->type != QUERY_STOP_COUNT &&
        msg->type != MULTI_TRAIN_DRIVER_COURIER &&
        msg->type != SENSOR_TRIGGER &&
        msg->type != DELTA_DISTANCE) {
      Reply(tid, (char*)1, 0);
    }

    switch (msg->type) {
      case SET_SPEED: {
        if (!me.tailMode) {
          Reply(msg->replyTid, (char*)1, 0);
        }

        groupSetSpeed(&me, msg->data2);
        break;
      }
      case SENSOR_TRIGGER: {
        if (me.tailMode && tid == me.sensorWatcher) {
          Reply(tid, (char *)NULL, 0);
          break;
        }

        if (me.tailMode) {
          int isHandled = 0;
          Send(me.trainId[0],
              (char*)msg, sizeof(DriverMsg), (char *)&isHandled, sizeof(int));
          Reply(tid, (char *)&isHandled, sizeof(int));
        } else {
          int isSensorReserved = QueryIsSensorReserved(&me, msg->data2, msg->data3);
          if (isSensorReserved) {
            // sensor is reserved
            for (int i = 0; i < me.numTrainInGroup; i ++) {
              int isHandled = 0;
              Send(me.trainId[i],
                  (char*)msg, sizeof(DriverMsg), (char *)&isHandled, sizeof(int));
              if (isHandled) {
                break;
              }
            }
          }
          Reply(tid, (char *)NULL, 0);
        }
        break;
      } // case
      case NAVIGATE_NAGGER: {
        if (me.tailMode) break;

        updateInfo(&me);

        if (me.routeRemaining != -1) {
          if (!me.stopCommited) {
            if (shouldStopNow(&me)) {
              if (me.route.nodes[me.stopNode].num == REVERSE) {
                //TrainDebug(&me, "Navi reversing.");
                groupSetSpeed(&me, -1); // reverse
              }
              else {
                //TrainDebug(&me, "Navi Nagger stopping.");
                groupSetSpeed(&me, 0); // stopping
                me.route.length = 0; // Finished the route.
                me.testMode = 0;
                me.routeRemaining = -1;
              }
              me.stopCommited = 1;
              me.useLastSensorNow = 0;
              me.stopNow = 0;
              me.stopSensorHit = 0;
            } else {
              if ((++updateStoppingDistanceCount & 15) == 0) updateStopNode(&me);
            }
          }
        }

        if (me.nextSetSwitchNode != -1 && (++me.setSwitchNaggerCount & 3) == 0) {
          trySetSwitch_and_getNextSwitch(&me);
        }
        if (me.rerouteCountdown-- == 0) {
          if (me.testMode) {
            int reserveStatus = makeReservation(&me, 440);
            if (reserveStatus == RESERVE_FAIL) {
              reroute(&me);
            } else {
              me.nextSetSwitchNode = -1;
              updateSetSwitch(&me);
              groupSetSpeed(&me, 8);
            }
          } else {
            // reroute
            if (me.route.length != 0) {
              setRoute(&me, &(me.info[0].pos), &(me.routeMsg));
            }
          }
        }
        break;
      }
      case UPDATE_PREDICTION: {
        if (me.tailMode) {
          MultiTrainDriverCourierMsg cMsg;
          cMsg.destTid = me.headTid;
          cMsg.msg = actualMsg;
          cMsg.msg.data = MyTid();
          Reply(me.courier, (char *)&cMsg, sizeof(MultiTrainDriverCourierMsg));
          break;
        }

        for (int i = 0; i < MAX_TRAIN_IN_GROUP; i++) {
          if (actualMsg.data == me.trainId[i]) {
            for (int j = 0; j < actualMsg.numSensors; j++) {
              me.sensorToReserve[i][j] = actualMsg.sensors[j];
            }
            me.numSensorToReserve[i] = actualMsg.numSensors;
          }
        }
        makeReservation(&me, me.info[0].maxStoppingDistance);
        break;
      }
      case STOP_COMPLETED: {
        // notify actual train controller.
        if (me.tailMode) {
          MultiTrainDriverCourierMsg cMsg;
          cMsg.destTid = me.headTid;
          cMsg.msg = actualMsg;
          cMsg.msg.data = MyTid();
          Reply(me.courier, (char *)&cMsg, sizeof(MultiTrainDriverCourierMsg));
          break;
        }
        me.stoppedCount++;

        if (me.stoppedCount == me.numTrainInGroup) {
          makeReservation(&me, 1);
          if (me.isReversing) {
            handleReverse(&me);
          } else if (me.route.length != 0) {
            // Reroute.
            setRoute(&me, &(me.info[0].pos), &(me.routeMsg));
          }
        }

        if (!me.reserveTrackMode) {
          clearReservation(me.trackManager, me.trainNum);
        }
        break;
      }
      case SET_ROUTE: {
        Reply(msg->replyTid, (char*)1, 0);
        me.routeMsg = *msg;
        setRoute(&me, &(me.info[0].pos), msg);
        break;
      }
      case GET_POSITION: {
        if (me.tailMode) {
          PrintDebug(me.ui, "Get position from a tail train ??");
          break;
        }
        // If don't have any valid info yet, reply empty message
        if (me.infoUpdater == -1) {
          Reply(msg->replyTid, (char*)1, 0);
        } else {
          Reply(msg->replyTid, (char*)&(me.info[0]), sizeof(DumbDriverInfo));
        }
        break;
      }
      case FIND_POSITION: {
        if (me.tailMode) {
          PrintDebug(me.ui, "find position while merge????");
          break;
        }
        me.reserveTrackMode = (msg->data2 == RESERVE);

        PrintDebug(me.ui, "Train locking %d", me.trainNum);
        // Only 1 train can lock at the same time.
        lock(me.timeserver);
        // begin finding position in a slow speed
        DumbTrainSetSpeed(me.trainId[0], 5);
        Reply(msg->replyTid, (char*)1, 0);
        for (;;) {
          Receive(&tid, (char*)msg, sizeof(MultiTrainDriverMsg));
          Reply(tid, (char*)1, 0);
          if (msg->type == SENSOR_TRIGGER) {
            Send(me.trainId[0], (char*)msg,
                sizeof(DriverMsg), (char*)NULL, 0);
            DumbTrainSetSpeed(me.trainId[0], 0);
            break;
          } else if (msg->type == GET_POSITION) {
            Reply(msg->replyTid, (char*)1, 0);
          } else {
            PrintDebug(me.ui, "WARNN Drop %d", msg->type);
          }
        }
        DriverMsg dMsg;
        dMsg.type = REPORT_INFO;
        for (int i = 0; i < me.numTrainInGroup; i++) {
          Send(me.trainId[i],
              (char *)&dMsg, sizeof(DriverMsg),
              (char*)&me.info[i], sizeof(DumbDriverInfo));
        }
        me.infoUpdater = Create(3, trainNavigateNagger);
        unlock();
        break;
      }
      case MERGE_HEAD: {
        if (me.tailMode) {
          PrintDebug(me.ui, "Cannot be a head when in tail mode??");
          break;
        }
        me.reserveTrackMode = 1; //  Head always reserves track.
        // Other train controller's id.
        me.trainId[me.numTrainInGroup] = msg->data2;
        me.numTrainInGroup++;
        Reply(msg->replyTid, (char*)1, 0);
        DriverMsg dMsg;
        dMsg.type = QUERY_STOP_COUNT;
        int tailStopCount = 0;
        Send(msg->data2, (char *)&dMsg, sizeof(DriverMsg), (char *)&tailStopCount, sizeof(int));
        me.stoppedCount += tailStopCount;

        dMsg.type = UPDATE_PARENT_ABOUT_PREDICTION;
        Send(msg->data2, (char *)&dMsg, sizeof(DriverMsg), (char *)NULL, 0);

        PrintDebug(me.ui, "merged. head is %d", me.trainNum);
        break;
      }
      case MERGE_TAIL: {
        if (me.tailMode) {
          PrintDebug(me.ui, "Double merge tail??");
          break;
        }
        // Enters courier mode that passes dumb_train msg to 'real' controller
        me.tailMode = 1;
        me.headTid = msg->data2;
        clearReservation(me.trackManager, me.trainNum);
        Reply(msg->replyTid, (char*)1, 0);
        PrintDebug(me.ui, "Train %d is tail", me.trainNum);
        break;
      }
      case SEPARATE_TAIL: {
        if (!me.tailMode) {
          PrintDebug(me.ui, "Not in tail mode..??"); break;
        }
        me.tailMode = 0;
        me.headTid = 0;
        // TODO, behaviour is not clearly defined yet.
        // reserve my own track and prediction??
        break;
      }
      case REPORT_INFO: {
        if (!me.tailMode) {
          PrintDebug(me.ui, "Report info Not in tail mode..??"); break;
        }

        // ASSUME ONLY 1 train when in tail mode.
        Send(me.trainId[0], (char*)msg, sizeof(DriverMsg),
            (char*)&me.info[0], sizeof(DumbDriverInfo));
        // Reply the head that made query.
        Reply(me.headTid, (char*)&me.info[0], sizeof(DumbDriverInfo));
        break;
      }
      case DELTA_DISTANCE: {
        if (!me.tailMode) {
          PrintDebug(me.ui, "Delta distance and not in tail mode..??"); break;
        }

        // ASSUME ONLY 1 train when in tail mode.
        Send(me.trainId[0], (char*)msg,
            sizeof(DriverMsg) - sizeof(Position), (char*)1, 0);
        // Reply the head that made query.
        Reply(me.headTid, (char*)1, 0);
        break;
      }
      case UPDATE_PARENT_ABOUT_PREDICTION: {
        if (!me.tailMode) {
          PrintDebug(me.ui, "%d Update Parent Not in tail mode..??", me.trainNum);
          break;
        }
        // ASSUME ONLY 1 train when in tail mode.
        Send(me.trainId[0], (char*)msg, sizeof(DriverMsg),
            (char*)NULL, 0);
        break;
      }
      case QUERY_STOP_COUNT: {
        // asuumption: no tree strucutre
        Reply(tid, (char *)&me.stoppedCount, sizeof(int));
        break;
      }
      case MULTI_TRAIN_DRIVER_COURIER: {
        // nothing
        break;
      }
      case REVERSE_SPEED: {
        if (!me.tailMode) {
          PrintDebug(me.ui, "Reverse Speed Not in tail mode..??"); break;
        }

        for (int i = 0; i < me.numTrainInGroup; i++) {
          Send(me.trainId[i], (char *)msg, sizeof(DriverMsg), (char*)1, 0);
        }
        break;
      }
      case QUERY_STOPPING_DISTANCE: {
        if (!me.tailMode) {
          PrintDebug(me.ui, "Query stopping dist Not in tail mode..??"); break;
        }

        int stoppingDist = 0;
        // ASSUME ONLY 1 train when in tail mode.
        Send(me.trainId[0], (char*)msg, sizeof(DriverMsg),
            (char*)&stoppingDist, sizeof(int));
        // Reply the head that made query.
        Reply(me.headTid, (char*)&stoppingDist, sizeof(int));
        break;
      }
      case HIT_SECONDARY: {
        if (me.route.length != 0) {
          PrintDebug(me.ui, "Hit secondary rerouting..");
          groupSetSpeed(&me, 0);
        }
        break;
      }
      case SET_FOLLOWING_DISTANCE: {
        me.minFollowingDist = msg->data2;
        me.maxFollowingDist = msg->data3;

        Reply(msg->replyTid, (char*)1, 0);
        break;
      }
      default: {
        PrintDebug(me.ui, "Not Handled %d", msg->type);
      }
    } // switch
  } // for
}
static void reroute(MultiTrainDriver* me) {
  PrintDebug(me->ui, "Rerouting....");
  groupSetSpeed(me, 0);
  me->rerouteCountdown = GET_TIMER4() % 2 == 0 ? 145 : 155; // wait ~1 seconds then reroute.
}