Пример #1
0
bool detect_capture_from_motion(const GameState& gs, const Step& step_taken, Step *capture)
{
  if (!possible_capture_from_motion(gs, step_taken))
    return false;

  const unsigned char color = step_taken.get_color();
  const Board capturable = gs.get_color_board(color) & ~adj_friendly(gs, color);
  const char capture_idxs[] = {18, 21, 42, 45};
  for(int i=0; i < 4; ++i) {
    if (capturable.contains(capture_idxs[i])) {
      // we have a capture!
      int8_t c, p;
      gs.color_and_piece_at(capture_idxs[i], &c, &p);
      // assert(c == color);
      *capture = Step(color, p, capture_idxs[i], CAPTURE);
      return true;
    }
  }
  return false;
}
Пример #2
0
void HdfProcessor::updateStep(Step& step) {
	Group group = _file.openGroup(step.getName());
	unlinkAllDatasets(group);
	for (int i = 0; i < Step::DIMENSION_NUMBER; i++) {
		writeCoordinatesToDataSet(group, COORDINATES_DATASET_NAMES[i],
				step.getParticlesNumber(), i, step.getCoordinates());
	}

	map<string, float*>::iterator begin = step.getAdditionalData().begin();
	map<string, float*>::iterator end = step.getAdditionalData().end();
	while (begin != end) {
		createDataSet(group, begin->first.c_str(), DataSpace::ALL, begin->second,
				step.getParticlesNumber());
		++begin;
	}

	group.close();
}
Пример #3
0
void LocationPath::evaluate(NodeSet& nodes) const
{
    bool resultIsSorted = nodes.isSorted();

    for (unsigned i = 0; i < m_steps.size(); i++) {
        Step* step = m_steps[i];
        NodeSet newNodes;
        HashSet<Node*> newNodesSet;

        bool needToCheckForDuplicateNodes = !nodes.subtreesAreDisjoint() || (step->axis() != Step::ChildAxis && step->axis() != Step::SelfAxis
            && step->axis() != Step::DescendantAxis && step->axis() != Step::DescendantOrSelfAxis && step->axis() != Step::AttributeAxis);

        if (needToCheckForDuplicateNodes)
            resultIsSorted = false;

        // This is a simplified check that can be improved to handle more cases.
        if (nodes.subtreesAreDisjoint() && (step->axis() == Step::ChildAxis || step->axis() == Step::SelfAxis))
            newNodes.markSubtreesDisjoint(true);

        for (unsigned j = 0; j < nodes.size(); j++) {
            NodeSet matches;
            step->evaluate(nodes[j], matches);

            if (!matches.isSorted())
                resultIsSorted = false;

            for (size_t nodeIndex = 0; nodeIndex < matches.size(); ++nodeIndex) {
                Node* node = matches[nodeIndex];
                if (!needToCheckForDuplicateNodes || newNodesSet.add(node).isNewEntry)
                    newNodes.append(node);
            }
        }
        
        nodes.swap(newNodes);
    }

    nodes.markSorted(resultIsSorted);
}
Пример #4
0
bool GameState::move_piece(const Step &s)
{
  assert(s.is_motion());
  const uint8_t c = s.get_color(), p = s.get_piece(), pos = s.get_position(), finish = s.get_finish();
  return move_piece(c, p, pos, finish);
}
Пример #5
0
bool GameState::add_piece_at(const Step &s)
{
  return add_piece_at(s.get_color(), s.get_piece(), s.get_position());
}
Пример #6
0
void Plan::CalcEncoding() {
	int n = mOrderings.size() + mSteps.size() + 1;
	if(mA)
		delete mA;
	mA = new SparceMatrix(n, mSteps.size()*3 + n);

	int row = 0; //The current equation
	int k = 0; //The current slack variable
	for(vector<Step*>::iterator it = mSteps.begin();
			it != mSteps.end(); it++) {
		Step* curStep = *it;
		if(curStep->getAction()->LBDurration() == 
				curStep->getAction()->UBDurration()) {
			//If they are the same we don't need slack variables
			//s_end - s_start = dur
			mA->set(row, getStepCol(curStep, StepTime::End), mgr.addOne());
			mA->set(row, getStepCol(curStep, StepTime::Start), -mgr.addOne());
			(*mb)[row] = mgr.constant(curStep->getAction()->UBDurration());
			row++;
		} else {
			//Other wise we do
			//s_end - s_start - s_k = ub;
			mA->set(row, getStepCol(curStep, StepTime::End), mgr.addOne());
			mA->set(row, getStepCol(curStep, StepTime::Start), -mgr.addOne());
			mA->set(row, getSlackVar(k), -mgr.addOne());
			(*mb)[row] = mgr.constant(curStep->getAction()->UBDurration());
			row++;
			k++;

			//s_start - s_end - s_k+1 = -lb;
			mA->set(row, getStepCol(curStep, StepTime::Start), mgr.addOne());
			mA->set(row, getStepCol(curStep, StepTime::End), -mgr.addOne());
			mA->set(row, getSlackVar(k), -mgr.addOne());
			(*mb)[row] = mgr.constant(curStep->getAction()->LBDurration());
			row++;
			k++;
		}
	}

	for(vector<Ordering*>::iterator it = mOrderings.begin();
			it != mOrderings.end(); it++) {
		Ordering* curOrdering = *it;
		//Post_time - Pre_time - s_k = epsilon
		mA->set(row, getStepCol(curOrdering->Post(), curOrdering->PostTime()), mgr.addOne());
		mA->set(row, getStepCol(curOrdering->Pre(), curOrdering->PreTime()), -mgr.addOne());
		mA->set(row, getSlackVar(k), -mgr.addOne());
		(*mb)[row] = mgr.constant(epsilon);
		row++;
		k++;
	}

	mA->set(row, getStepCol(FrameStep, StepTime::Start), -mgr.addOne());
	mA->set(row, getStepCol(FrameStep, StepTime::End), mgr.addOne());
	mA->set(row, getSlackVar(k), -mgr.addOne());
	(*mb)[row] = mgr.constant(Deadline);
	row++;
	k++;
	int index = 0;
	mf.resize(k+mA->getNumCols());
	for(int i = 0; i < k; i++) {
		mf[index].index = getSlackVar(i);
		mf[index].inverted = false;
		index++;
	}

	for(int i = 0; i < mA->getNumCols(); i++) {
		mf[i].index = i;
	}
}
Пример #7
0
//PreprocessProgram initializes ETA parameters and validates/modifies ramp conditions
void Thermocycler::PreprocessProgram() {
  Step* pCurrentStep;
  Step* pPreviousStep = NULL;

  iProgramHoldDurationS = 0;
  iEstimatedTimeRemainingS = 0;
  iHasCooled = false;

  iProgramControlledRampDurationS = 0;
  iProgramFastRampDegrees = 0;
  iElapsedFastRampDegrees = 0;
  iTotalElapsedFastRampDurationMs = 0;

  ipProgram->BeginIteration();
  while ((pCurrentStep = ipProgram->GetNextStep()) && !pCurrentStep->IsFinal()) {
    //validate ramp
    if (pPreviousStep != NULL && pCurrentStep->GetRampDurationS() * 1000 < absf(pCurrentStep->GetTemp() - pPreviousStep->GetTemp()) * PLATE_FAST_RAMP_THRESHOLD_MS) {
      //cannot ramp that fast, ignored set ramp
      pCurrentStep->SetRampDurationS(0);
    }

    //update eta hold
    iProgramHoldDurationS += pCurrentStep->GetStepDurationS();

    //update eta ramp
    if (pCurrentStep->GetRampDurationS() > 0) {
      //controlled ramp
      iProgramControlledRampDurationS += pCurrentStep->GetRampDurationS();
    }
    else {
      //fast ramp
      double previousTemp = pPreviousStep ? pPreviousStep->GetTemp() : GetPlateTemp();
      iProgramFastRampDegrees += absf(previousTemp - pCurrentStep->GetTemp()) - CYCLE_START_TOLERANCE;
    }

    pPreviousStep = pCurrentStep;
  }
}
Пример #8
0
int main()
{
    int width, height, select;
    int c1,x1=34,y1=10, Y1=1;
    int c, x = Ws+2, y =Hs+1 ,i=Hs,X=0,Y=0;
    int go_on;
    initscr();
    cbreak(); // disable key buffering
    noecho(); // disable echoing
    nodelay( stdscr, 1 );
    start_color();
    keypad(stdscr, TRUE); // enable keypad reading
    getmaxyx(stdscr, height, width); // get screen size
    
    Make_map Map01;
    Menu M;
    M.PrintMenu();
    Time T;
	Step S;
	CheckPosition Check;
	
    select = TRUE;
    while(select)
    {
        move(y1,x1);
        c1 = getch();
        switch(c1)
        {
            case KEY_UP:	 mvprintw(y1,x1,"  "); y1=y1-2;  Y1--; M.Check(y1,Y1); mvprintw( y1, x1, "->" ); break;
            case KEY_DOWN: 	 mvprintw(y1,x1,"  "); y1=y1+2;  Y1++; M.Check(y1,Y1); mvprintw( y1, x1, "->" ); break;
            case KEY_RIGHT:  switch(Y1)
                             {
                                case 1 : erase();
                                
												T.setT1();
												S.set();
												Map01.initialize();
												Map01.setMap();
												Map01.BanSpace();
												Map01.displayMap(); 
				 
													mvaddstr(1,16,  "Pressed Key: [1~9]");
													mvaddstr(21, 17, "Clear space: [0]");
													
													go_on = TRUE;
													while (go_on) {
														move(y, x);
														c = getch();
															switch(c)
															{
															case KEY_LEFT:	 x=x-LRS;  X--; Check.CheckPositionX(x,X); mvaddstr(18, 64, "  "); break;
															case KEY_RIGHT:	 x=x+LRS;  X++; Check.CheckPositionX(x,X); mvaddstr(18, 64, "  "); break;
															case KEY_UP:	 y=y-UDS;  Y--; Check.CheckPositionY(y,Y); mvaddstr(18, 64, "  "); break;
															case KEY_DOWN: 	 y=y+UDS;  Y++; Check.CheckPositionY(y,Y); mvaddstr(18, 64, "  "); break;
															case '0': Map01.getAns(0,X,Y); S.getStep();    break;
															case '1': Map01.getAns(1,X,Y); S.getStep();	break;
															case '2': Map01.getAns(2,X,Y); S.getStep();	break;
															case '3': Map01.getAns(3,X,Y); S.getStep();	break;
															case '4': Map01.getAns(4,X,Y); S.getStep();	break;
															case '5': Map01.getAns(5,X,Y); S.getStep();	break;
															case '6': Map01.getAns(6,X,Y); S.getStep();	break;
															case '7': Map01.getAns(7,X,Y); S.getStep();	break;
															case '8': Map01.getAns(8,X,Y); S.getStep();	break;
															case '9': Map01.getAns(9,X,Y); S.getStep();	break;
															case 'z': go_on = FALSE; break;
															case 'n': Map01.initialize();Map01.setMap();Map01.BanSpace();Map01.displayMap();T.setT1();S.set(); break;
															case 'f': Map01.CheckAns(); break;
															case 'Z': go_on = FALSE; break;
															case 'N': Map01.initialize();Map01.setMap();Map01.BanSpace();Map01.displayMap();T.setT1();S.set(); break;
															case 'F': Map01.CheckAns(); break;
															case 's': Map01.Save();T.Save();S.Save();break;
															case 'S': Map01.Save();T.Save();S.Save();break;
															case 'l': Map01.initialize();Map01.Load();Map01.displayMap();T.setT1();T.Load();S.Load();break;
															case 'L': Map01.initialize();Map01.Load();Map01.displayMap();T.setT1();T.Load();S.Load();break;
															default: T.setT2(); T.displayTime();
															} // switch (c)
													//refresh();
														while (x < 0) x += width;
														while (x >= width) x -= width;
														while (y < 0) y += height;
														while (y >= height) y -= height;
													} // while (go_on)	
													
																			
											erase(); M.PrintMenu(); break;
                                case 2 : select = FALSE; break;
                                default: ;
                             }
                             break;
        }
    }
    endwin();
    return 0;
} // main( )
Пример #9
0
bool StepImpl::operator==(Step& op) {
	return this->get_name() == op.get_name() 
		&& this->is_label() == op.is_label()
		&& this->get_visname() == op.get_visname();
}
Пример #10
0
//PreprocessProgram initializes ETA parameters and validates/modifies ramp conditions
void Thermocycler::PreprocessProgram() {
  Step* pCurrentStep;
  Step* pPreviousStep = NULL;
  
  m_program_hold_duration_sec = 0;
  m_estimated_time_remaining_sec = 0;
  m_has_cooled = false;
  
  m_program_controlled_ramp_duration_sec = 0;
  m_program_fast_ramp_degrees = 0;
  m_elapsed_fast_ramp_degrees = 0;
  m_total_elapsed_fast_ramp_duration_ms = 0;
  
  m_program->BeginIteration();
  while ((pCurrentStep = m_program->GetNextStep()) && !pCurrentStep->IsFinal()) {
    //validate ramp
    if (pPreviousStep != NULL && pCurrentStep->GetRampDurationS() * 1000 < fabs(pCurrentStep->GetTemp() - pPreviousStep->GetTemp()) * PLATE_FAST_RAMP_THRESHOLD_MS) {
      //cannot ramp that fast, ignored set ramp
      pCurrentStep->SetRampDurationS(0);
    }
    
    //update eta hold
    m_program_hold_duration_sec += pCurrentStep->GetStepDurationS();
 
    //update eta ramp
    if (pCurrentStep->GetRampDurationS() > 0) {
      //controlled ramp
      m_program_controlled_ramp_duration_sec += pCurrentStep->GetRampDurationS();
    } else {
      //fast ramp
      double previousTemp = pPreviousStep ? pPreviousStep->GetTemp() : GetPlateTemp();
      m_program_fast_ramp_degrees += fabs(previousTemp - pCurrentStep->GetTemp()) - CYCLE_START_TOLERANCE;
    }
    
    pPreviousStep = pCurrentStep;
  }
}
Пример #11
0
int Gui::drawPage(
  LGraphicsView  *view,
  QGraphicsScene *scene,
  Steps          *steps,
  int             stepNum,
  QString const  &addLine,
  Where          &current,
  QStringList    &csiParts,
  QStringList    &pliParts,
  bool            isMirrored,
  QHash<QString, QStringList> &bfx,
  bool            printing,
  bool            bfxStore2,
  QStringList    &bfxParts,
  bool            calledOut)
{
  bool        global = true;
  QString     line;
  Callout    *callout     = NULL;
  Range      *range       = NULL;
  Step       *step        = NULL;
  bool        pliIgnore   = false;
  bool        partIgnore  = false;
  bool        synthBegin  = false;
  bool        multiStep   = false;
  bool        partsAdded  = false;
  bool        coverPage   = false;
  bool        bfxStore1   = false;
  bool        bfxLoad     = false;
  int         numLines = ldrawFile.size(current.modelName);
  bool        firstStep   = true;
  
  steps->isMirrored = isMirrored;
  
  QList<InsertMeta> inserts;
  
  Where topOfStep = current;
  Rc gprc = OkRc;
  Rc rc;

  statusBar()->showMessage("Processing " + current.modelName);

  page.coverPage = false;

  QStringList calloutParts;

  /*
   * do until end of page
   */
  for ( ; current <= numLines; current++) {

    Meta   &curMeta = callout ? callout->meta : steps->meta;

    QStringList tokens;

    // If we hit end of file we've got to note end of step

    if (current >= numLines) {
      line.clear();
      gprc = EndOfFileRc;
      tokens << "0";
      
      // not end of file, so get the next LDraw line 
     
    } else {
      line = ldrawFile.readLine(current.modelName,current.lineNumber);
      split(line,tokens);
    }
    
    if (tokens.size() == 15 && tokens[0] == "1") {
      
      QString color = tokens[1];
      QString type  = tokens[tokens.size()-1];

      csiParts << line;
      partsAdded = true;

      /* since we have a part usage, we have a valid step */

      if (step == NULL) {
        if (range == NULL) {
          range = newRange(steps,calledOut);
          steps->append(range);
        }

        step = new Step(topOfStep,
                        range,
                        stepNum,
                        curMeta,
                        calledOut,
                        multiStep);

        range->append(step);
      }

      /* addition of ldraw parts */

      if (curMeta.LPub.pli.show.value()
          && ! pliIgnore 
          && ! partIgnore 
          && ! synthBegin) {
        QString colorType = color+type;
        if (! isSubmodel(type) || curMeta.LPub.pli.includeSubs.value()) {
          if (bfxStore2 && bfxLoad) {
            bool removed = false;
            for (int i = 0; i < bfxParts.size(); i++) {
              if (bfxParts[i] == colorType) {
                bfxParts.removeAt(i);
                removed = true;
                break;
              }
            }
            if ( ! removed) {
              pliParts << Pli::partLine(line,current,steps->meta);
            }
          } else {
            pliParts << Pli::partLine(line,current,steps->meta);
          }
        }
        if (bfxStore1) {
          bfxParts << colorType;
        }
      }

      /* if it is a sub-model, then process it */

      if (ldrawFile.contains(type) && callout) {

        /* we are a callout, so gather all the steps within the callout */
        /* start with new meta, but no rotation step */

        if (callout->bottom.modelName != type) {

          Where current2(type,0);
          skipHeader(current2);          
          callout->meta.rotStep.clear();
          SubmodelStack tos(current.modelName,current.lineNumber,stepNum);
          callout->meta.submodelStack << tos;

          Meta saveMeta = callout->meta;
          callout->meta.LPub.pli.constrain.resetToDefault();

          step->append(callout);

          calloutParts.clear();
          QStringList csiParts2;

          QHash<QString, QStringList> calloutBfx;

          int rc;

          rc = drawPage(
                 view,
                 scene,
                 callout,
                 1,
                 line,
                 current2,
                 csiParts2,
                 calloutParts,
                 ldrawFile.mirrored(tokens),
                 calloutBfx,
                 printing,
                 bfxStore2,
                 bfxParts,
                 true);

          callout->meta = saveMeta;

          if (callout->meta.LPub.pli.show.value() &&
            ! callout->meta.LPub.callout.pli.perStep.value() &&
            ! pliIgnore && ! partIgnore && ! synthBegin) {

            pliParts += calloutParts;
          }

          if (rc != 0) {
            steps->placement = steps->meta.LPub.assem.placement;
            return rc;
          }
        } else {
          callout->instances++;
          pliParts += calloutParts;
        }

        /* remind user what file we're working on */

        statusBar()->showMessage("Processing " + current.modelName);
      }
    } else if (tokens.size() > 0 &&
              (tokens[0] == "2" ||
               tokens[0] == "3" ||
               tokens[0] == "4" ||
               tokens[0] == "5")) {

      csiParts << line;
      partsAdded = true;

      /* we've got a line, triangle or polygon, so add it to the list */
      /* and make sure we know we have a step */

      if (step == NULL) {
        if (range == NULL) {            
          range = newRange(steps,calledOut);
          steps->append(range);
        }

        step = new Step(topOfStep,
                        range,
                        stepNum,
                        steps->meta,
                        calledOut,
                        multiStep);
        range->append(step);
      }

    } else if (tokens.size() > 0 && tokens[0] == "0" || gprc == EndOfFileRc) {
      
      /* must be meta-command (or comment) */
      if (global && tokens.contains("!LPUB") && tokens.contains("GLOBAL")) {
        topOfStep = current;
      } else {
        global = false;
      }

      QString part;

      if (gprc == EndOfFileRc) {
        rc = gprc;
      } else {
        rc = curMeta.parse(line,current,true);
      }

      /* handle specific meta-commands */

      switch (rc) {

        /* toss it all out the window, per James' original plan */
        case ClearRc:
          pliParts.clear();
          csiParts.clear();
          steps->freeSteps();
        break;

        /* Buffer exchange */
        case BufferStoreRc:
          bfx[curMeta.bfx.value()] = csiParts;
          bfxStore1 = true;
          bfxParts.clear();
        break;

        case BufferLoadRc:
          csiParts = bfx[curMeta.bfx.value()];
          bfxLoad = true;
        break;

        case MLCadGroupRc:
          csiParts << line;
        break;
        
        case IncludeRc:
          include(curMeta);
        break;

        /* substitute part/parts with this */

        case PliBeginSub1Rc:
          if (pliIgnore) {
            parseError("Nested PLI BEGIN/ENDS not allowed\n",current);
          } 
          if (steps->meta.LPub.pli.show.value() && 
              ! pliIgnore && 
              ! partIgnore && 
              ! synthBegin) {

            SubData subData = curMeta.LPub.pli.begin.sub.value();
            QString addPart = QString("1 0  0 0 0  0 0 0 0 0 0 0 0 0 %1") .arg(subData.part);
            pliParts << Pli::partLine(addPart,current,curMeta);
          }

          if (step == NULL) {
            if (range == NULL) {
              range = newRange(steps,calledOut);
              steps->append(range);
            }
            step = new Step(topOfStep,
                            range,
                            stepNum,
                            curMeta,
                            calledOut,
                            multiStep);
            range->append(step);
          }
          pliIgnore = true;
        break;

        /* substitute part/parts with this */
        case PliBeginSub2Rc:
          if (pliIgnore) {
            parseError("Nested BEGIN/ENDS not allowed\n",current);
          } 
          if (steps->meta.LPub.pli.show.value() &&
              ! pliIgnore &&
              ! partIgnore &&
              ! synthBegin) {

            SubData subData = curMeta.LPub.pli.begin.sub.value();
            QString addPart = QString("1 %1  0 0 0  0 0 0 0 0 0 0 0 0 %2") .arg(subData.color) .arg(subData.part);
            pliParts << Pli::partLine(addPart,current,curMeta);
          }

          if (step == NULL) {
            if (range == NULL) {
              range = newRange(steps,calledOut);
              steps->append(range);
            }
            step = new Step(topOfStep,
                            range,
                            stepNum,
                            curMeta,
                            calledOut,
                            multiStep);
            range->append(step);
          }
          pliIgnore = true;
        break;

        /* do not put subsequent parts into PLI */
        case PliBeginIgnRc:
          if (pliIgnore) {
            parseError("Nested BEGIN/ENDS not allowed\n",current);
          } 
          pliIgnore = true;
        break;
        case PliEndRc:
          if ( ! pliIgnore) {
            parseError("PLI END with no PLI BEGIN",current);
          }
          pliIgnore = false;
        break;

        /* discard subsequent parts, and don't create CSI's for them */
        case PartBeginIgnRc:
        case MLCadSkipBeginRc:
          if (partIgnore) {
            parseError("Nested BEGIN/ENDS not allowed\n",current);
          } 
          partIgnore = true;
        break;

        case PartEndRc:
        case MLCadSkipEndRc:
          if (partIgnore) {
            parseError("Ignore ending with no ignore begin",current);
          }
          partIgnore = false;
        break;

        case SynthBeginRc:
          if (synthBegin) {
            parseError("Nested BEGIN/ENDS not allowed\n",current);
          } 
          synthBegin = true;
        break;

        case SynthEndRc:
          if ( ! synthBegin) {
            parseError("Ignore ending with no ignore begin",current);
          }
          synthBegin = false;
        break;


        /* remove a group or all instances of a part type */
        case GroupRemoveRc:
        case RemoveGroupRc:
        case RemovePartRc:
        case RemoveNameRc:
          {
            QStringList newCSIParts;

            if (rc == RemoveGroupRc) {
              remove_group(csiParts,steps->meta.LPub.remove.group.value(),newCSIParts);
            } else if (rc == RemovePartRc) {
              remove_parttype(csiParts, steps->meta.LPub.remove.parttype.value(),newCSIParts);
            } else {
              remove_partname(csiParts, steps->meta.LPub.remove.partname.value(),newCSIParts);
            }
            csiParts = newCSIParts;

            if (step == NULL) {
              if (range == NULL) {
                range = newRange(steps,calledOut);
                steps->append(range);
              }
              step = new Step(topOfStep,
                              range,
                              stepNum,
                              curMeta,
                              calledOut,
                              multiStep);
              range->append(step);
            }
          }
        break;

        case ReserveSpaceRc:
          /* since we have a part usage, we have a valid step */
          if (calledOut || multiStep) {
            step = NULL;
            Reserve *reserve = new Reserve(current,steps->meta.LPub);
            if (range == NULL) {
              range = newRange(steps,calledOut);
              steps->append(range);
            }
            range->append(reserve);
          }
        break;
        
        case InsertCoverPageRc:
          coverPage = true;
          page.coverPage = true;

        case InsertPageRc:
          partsAdded = true;
        break;
        
        case InsertRc:
          inserts.append(curMeta.LPub.insert);  // these are always placed before any parts in step
        break;

        case CalloutBeginRc:
          if (callout) {
            parseError("Nested CALLOUT not allowed within the same file",current);
          } else {
            callout = new Callout(curMeta,view);
            callout->setTopOfCallout(current);
          }
        break;

        case CalloutDividerRc:
          if (range) {
            range->sepMeta = curMeta.LPub.callout.sep;
            range = NULL;
            step = NULL;
          }
        break;

        case CalloutPointerRc:
          if (callout) {
            callout->appendPointer(current,curMeta.LPub.callout);
          }
        break;

        case CalloutEndRc:
          if ( ! callout) {
            parseError("CALLOUT END without a CALLOUT BEGIN",current);
          } else {
            callout->parentStep = step;
            callout->parentRelativeType = step->relativeType;
            callout->pli.clear();
            callout->placement = curMeta.LPub.callout.placement;
            callout->setBottomOfCallout(current);
            callout = NULL;
          }
        break;

        case StepGroupBeginRc:
          if (calledOut) {
            parseError("MULTI_STEP not allowed inside callout models",current);
          } else {
            if (multiStep) {
              parseError("Nested MULTI_STEP not allowed",current);
            }
            multiStep = true;
          }
          steps->relativeType = StepGroupType;
        break;

        case StepGroupDividerRc:
          if (range) {
            range->sepMeta = steps->meta.LPub.multiStep.sep;
            range = NULL;
            step = NULL;
          }
        break;

        /* finished off a multiStep */
        case StepGroupEndRc:
          if (multiStep) {
            // save the current meta as the meta for step group
            // PLI for non-pli-per-step
            if (partsAdded) {
              parseError("Expected STEP before MULTI_STEP END", current);
            }
            multiStep = false;

            if (pliParts.size() && steps->meta.LPub.multiStep.pli.perStep.value() == false) {
              steps->pli.bom = false;
              steps->pli.setParts(pliParts,steps->stepGroupMeta);
              steps->pli.sizePli(&steps->stepGroupMeta, StepGroupType, false);
            }
            pliParts.clear();

            /* this is a page we're supposed to process */

            steps->placement = steps->meta.LPub.multiStep.placement;
            showLine(steps->topOfSteps());
            
            bool endOfSubmodel = stepNum == ldrawFile.numSteps(current.modelName);
            int  instances = ldrawFile.instances(current.modelName,isMirrored);
            addGraphicsPageItems(steps, coverPage, endOfSubmodel,instances, view, scene,printing);
            return HitEndOfPage;
          }
        break;

        /* we're hit some kind of step, or implied step and end of file */
        case EndOfFileRc:
        case RotStepRc:
        case StepRc:
          if ( ! partsAdded && bfxLoad) {  // special case of no parts added, but BFX load
            if (step == NULL) {
              if (range == NULL) {
                range = newRange(steps,calledOut);
                steps->append(range);
              }
              step = new Step(topOfStep,
                              range,
                              stepNum,
                              curMeta,
                              calledOut,
                              multiStep);
              range->append(step);
            }

            int rc = step->createCsi(
              isMirrored ? addLine : "1 color 0 0 0 1 0 0 0 1 0 0 0 1 foo.ldr",
              csiParts,
              &step->csiPixmap,
              steps->meta);
            partsAdded = true; // OK, so this is a lie, but it works
          }
          if (partsAdded) {
            if (firstStep) {
              steps->stepGroupMeta = curMeta;
              firstStep = false;
            }

            if (pliIgnore) {
              parseError("PLI BEGIN then STEP. Expected PLI END",current);
              pliIgnore = false;
            }
            if (partIgnore) {
              parseError("PART BEGIN then STEP. Expected PART END",current);
              partIgnore = false;
            }
            if (synthBegin) {
              parseError("SYNTH BEGIN then STEP. Expected SYNTH_END",current);
              synthBegin = false;
            }

            bool pliPerStep;

            if (multiStep && steps->meta.LPub.multiStep.pli.perStep.value()) {
              pliPerStep = true;
            } else if (calledOut && steps->meta.LPub.callout.pli.perStep.value()) {
              pliPerStep = true;
            } else if ( ! multiStep && ! calledOut) {
              pliPerStep = true;
            } else {
              pliPerStep = false;
            }

            if (step) {
              Page *page = dynamic_cast<Page *>(steps);
              if (page) {
                page->inserts = inserts;
              }
              if (pliPerStep) {
                PlacementType relativeType;
                if (multiStep) {
                  relativeType = StepGroupType;
                } else if (calledOut) {
                  relativeType = CalloutType;
                } else {
                  relativeType = SingleStepType;
                }
                step->pli.setParts(pliParts,steps->meta);
                pliParts.clear();
                step->pli.sizePli(&steps->meta,relativeType,pliPerStep);
              }

              int rc = step->createCsi(
                 isMirrored ? addLine : "1 color 0 0 0 1 0 0 0 1 0 0 0 1 foo.ldr",
                 csiParts,
                &step->csiPixmap,
                 steps->meta);

              statusBar()->showMessage("Processing " + current.modelName);

              if (rc) {
                return rc;
              }
            } else {
              if (pliPerStep) {
                pliParts.clear();
              }
              
              /*
               * Only pages or step can have inserts.... no callouts
               */
              if ( ! multiStep && ! calledOut) {
                Page *page = dynamic_cast<Page *>(steps);
                if (page) {
                  page->inserts = inserts;
                }
              }
            }

            if ( ! multiStep && ! calledOut) {

              /*
               * Simple step
               */
              if (steps->list.size() == 0) {
                steps->relativeType = PageType;
              }
              steps->placement = steps->meta.LPub.assem.placement;
              showLine(topOfStep);

              int  numSteps = ldrawFile.numSteps(current.modelName);
              bool endOfSubmodel = numSteps == 0 || stepNum == numSteps;
              int  instances = ldrawFile.instances(current.modelName,isMirrored);

              addGraphicsPageItems(steps,coverPage,endOfSubmodel,instances,view,scene,printing);
              stepPageNum += ! coverPage;
              steps->setBottomOfSteps(current);
              return HitEndOfPage;
            }
            steps->meta.pop();
            stepNum += partsAdded;
            topOfStep = current;

            partsAdded = false;
            coverPage = false;
            step = NULL;
            bfxStore2 = bfxStore1;
            bfxStore1 = false;
            bfxLoad = false;
          }
          inserts.clear();
          steps->setBottomOfSteps(current);
        break;
        case RangeErrorRc:
          showLine(current);
          QMessageBox::critical(NULL,
                               QMessageBox::tr("LPub"),
                               QMessageBox::tr("Parameter(s) out of range: %1:%2\n%3")
                               .arg(current.modelName) 
                               .arg(current.lineNumber) 
                               .arg(line));
          return RangeErrorRc;
        break;
        default:
        break;
      }
    } else if (line != "") {
      showLine(current);
      QMessageBox::critical(NULL,
                            QMessageBox::tr("LPub"),
                            QMessageBox::tr("Invalid LDraw Line Type: %1:%2\n  %3")
                            .arg(current.modelName) 
                            .arg(current.lineNumber) 
                            .arg(line));
      return InvalidLDrawLineRc;
    }
  }
  steps->meta.rotStep.clear();
  return 0;
}