|  | @@ -41,87 +41,6 @@ void Starfield::regenerate(void) {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#ifdef NOMORE
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -void Starfield::animate(void) {
 | 
	
		
			
				|  |  | -  int rx = uni_x(rng);
 | 
	
		
			
				|  |  | -  int ry = uni_y(rng);
 | 
	
		
			
				|  |  | -  int mx = door.width;
 | 
	
		
			
				|  |  | -  int my = door.height;
 | 
	
		
			
				|  |  | -  int cx = mx / 2;
 | 
	
		
			
				|  |  | -  int cy = my / 2;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  std::set<star_pos> original = sky;
 | 
	
		
			
				|  |  | -  sky.clear();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  for (auto &spos : original) {
 | 
	
		
			
				|  |  | -    star_pos orig = spos;
 | 
	
		
			
				|  |  | -    star_pos newpos = orig;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    int dx = mx - abs(orig.x - cx);
 | 
	
		
			
				|  |  | -    int dy = my - abs(orig.y - cy);
 | 
	
		
			
				|  |  | -    if (dx > rx) {
 | 
	
		
			
				|  |  | -      // something x
 | 
	
		
			
				|  |  | -      if (newpos.x > cx)
 | 
	
		
			
				|  |  | -        ++newpos.x;
 | 
	
		
			
				|  |  | -      else
 | 
	
		
			
				|  |  | -        --newpos.x;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    if (dy > ry) {
 | 
	
		
			
				|  |  | -      // something y
 | 
	
		
			
				|  |  | -      if (newpos.y > cy)
 | 
	
		
			
				|  |  | -        ++newpos.y;
 | 
	
		
			
				|  |  | -      else
 | 
	
		
			
				|  |  | -        --newpos.y;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    if ((newpos.x == 0) or (newpos.x >= mx) or (newpos.y == 0) or
 | 
	
		
			
				|  |  | -        (newpos.y >= my)) {
 | 
	
		
			
				|  |  | -      newpos = make_pos();
 | 
	
		
			
				|  |  | -      newpos.color = orig.color;
 | 
	
		
			
				|  |  | -      newpos.symbol = orig.symbol;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    if (sky.find(newpos) == sky.end()) {
 | 
	
		
			
				|  |  | -      door << door::Goto(orig.x, orig.y) << " ";
 | 
	
		
			
				|  |  | -      sky.insert(newpos);
 | 
	
		
			
				|  |  | -      door << door::Goto(newpos.x, newpos.y);
 | 
	
		
			
				|  |  | -      if (newpos.color)
 | 
	
		
			
				|  |  | -        door << dark;
 | 
	
		
			
				|  |  | -      else
 | 
	
		
			
				|  |  | -        door << white;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      if (newpos.symbol)
 | 
	
		
			
				|  |  | -        door << stars[0];
 | 
	
		
			
				|  |  | -      else
 | 
	
		
			
				|  |  | -        door << stars[1];
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      // rats!
 | 
	
		
			
				|  |  | -      if (sky.find(orig) == sky.end()) {
 | 
	
		
			
				|  |  | -        sky.insert(orig);
 | 
	
		
			
				|  |  | -      } else {
 | 
	
		
			
				|  |  | -        door << door::Goto(orig.x, orig.y) << " ";
 | 
	
		
			
				|  |  | -        newpos = make_pos();
 | 
	
		
			
				|  |  | -        newpos.color = orig.color;
 | 
	
		
			
				|  |  | -        newpos.symbol = orig.symbol;
 | 
	
		
			
				|  |  | -        sky.insert(newpos);
 | 
	
		
			
				|  |  | -        door << door::Goto(newpos.x, newpos.y);
 | 
	
		
			
				|  |  | -        if (newpos.color)
 | 
	
		
			
				|  |  | -          door << dark;
 | 
	
		
			
				|  |  | -        else
 | 
	
		
			
				|  |  | -          door << white;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        if (newpos.symbol)
 | 
	
		
			
				|  |  | -          door << stars[0];
 | 
	
		
			
				|  |  | -        else
 | 
	
		
			
				|  |  | -          door << stars[1];
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  void Starfield::display(void) {
 | 
	
		
			
				|  |  |    door << door::reset << door::cls;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -180,100 +99,6 @@ void Starfield::display(void) {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#ifdef NOMORE
 | 
	
		
			
				|  |  | -void display___starfield(door::Door &door, std::mt19937 &rng) {
 | 
	
		
			
				|  |  | -  door << door::reset << door::cls;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  int mx = door.width;
 | 
	
		
			
				|  |  | -  int my = door.height;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // display Starfield
 | 
	
		
			
				|  |  | -  const char *stars[2];
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  stars[0] = ".";
 | 
	
		
			
				|  |  | -  if (door::unicode) {
 | 
	
		
			
				|  |  | -    stars[1] = "\u2219"; // "\u00b7";
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  } else {
 | 
	
		
			
				|  |  | -    stars[1] = "\xf9"; // "\xfa";
 | 
	
		
			
				|  |  | -  };
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  {
 | 
	
		
			
				|  |  | -    // Make uniform random distribution between 1 and MAX screen size X/Y
 | 
	
		
			
				|  |  | -    std::uniform_int_distribution<int> uni_x(1, mx);
 | 
	
		
			
				|  |  | -    std::uniform_int_distribution<int> uni_y(1, my);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    door::ANSIColor white(door::COLOR::WHITE);
 | 
	
		
			
				|  |  | -    door::ANSIColor dark(door::COLOR::BLACK, door::ATTR::BRIGHT);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 10 is too many, 100 is too few. 40 looks ok.
 | 
	
		
			
				|  |  | -    int MAX_STARS = ((mx * my) / 40);
 | 
	
		
			
				|  |  | -    // door.log() << "Generating starmap using " << mx << "," << my << " : "
 | 
	
		
			
				|  |  | -    //           << MAX_STARS << " stars." << std::endl;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    std::set<star_pos> sky;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    for (int i = 0; i < MAX_STARS; i++) {
 | 
	
		
			
				|  |  | -      star_pos pos;
 | 
	
		
			
				|  |  | -      bool valid;
 | 
	
		
			
				|  |  | -      do {
 | 
	
		
			
				|  |  | -        pos.x = uni_x(rng);
 | 
	
		
			
				|  |  | -        pos.y = uni_y(rng);
 | 
	
		
			
				|  |  | -        auto ret = sky.insert(pos);
 | 
	
		
			
				|  |  | -        // was insert a success?  (not a duplicate)
 | 
	
		
			
				|  |  | -        valid = ret.second;
 | 
	
		
			
				|  |  | -      } while (!valid);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    int i = 0;
 | 
	
		
			
				|  |  | -    star_pos last_pos;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    for (auto &pos : sky) {
 | 
	
		
			
				|  |  | -      bool use_goto = true;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      if (i != 0) {
 | 
	
		
			
				|  |  | -        // check last_pos to current position
 | 
	
		
			
				|  |  | -        if (pos.y == last_pos.y) {
 | 
	
		
			
				|  |  | -          // Ok, same row -- try some optimizations
 | 
	
		
			
				|  |  | -          int dx = pos.x - last_pos.x;
 | 
	
		
			
				|  |  | -          if (dx == 0) {
 | 
	
		
			
				|  |  | -            use_goto = false;
 | 
	
		
			
				|  |  | -          } else {
 | 
	
		
			
				|  |  | -            if (dx < 5) {
 | 
	
		
			
				|  |  | -              door << std::string(dx, ' ');
 | 
	
		
			
				|  |  | -              use_goto = false;
 | 
	
		
			
				|  |  | -            } else {
 | 
	
		
			
				|  |  | -              // Use ANSI Cursor Forward
 | 
	
		
			
				|  |  | -              door << "\x1b[" << dx << "C";
 | 
	
		
			
				|  |  | -              use_goto = false;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -          }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      if (use_goto) {
 | 
	
		
			
				|  |  | -        door::Goto star_at(pos.x, pos.y);
 | 
	
		
			
				|  |  | -        door << star_at;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      if (i % 5 < 2)
 | 
	
		
			
				|  |  | -        door << dark;
 | 
	
		
			
				|  |  | -      else
 | 
	
		
			
				|  |  | -        door << white;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      if (i % 2 == 0)
 | 
	
		
			
				|  |  | -        door << stars[0];
 | 
	
		
			
				|  |  | -      else
 | 
	
		
			
				|  |  | -        door << stars[1];
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      ++i;
 | 
	
		
			
				|  |  | -      last_pos = pos;
 | 
	
		
			
				|  |  | -      last_pos.x++; // star output moves us by one.
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  AnimatedStarfield::AnimatedStarfield(door::Door &Door, std::mt19937 &Rng)
 | 
	
		
			
				|  |  |      : door{Door}, rng{Rng}, uni_x{1, Door.width}, uni_y{1, Door.height},
 | 
	
		
			
				|  |  |        white{door::COLOR::WHITE}, dark{door::COLOR::BLACK, door::ATTR::BRIGHT} {
 | 
	
	
		
			
				|  | @@ -288,17 +113,45 @@ AnimatedStarfield::AnimatedStarfield(door::Door &Door, std::mt19937 &Rng)
 | 
	
		
			
				|  |  |    regenerate();
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -moving_star AnimatedStarfield::make_pos(void) {
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * @brief Make a moving_star
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * This makes a new x,y point.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * If "centered", we create a point nearer to the center of the screen.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Also, if centered, we don't allow y == cy.  FIXES BUG: syncterm 80x25.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * moving_star.visible is set by the visibleFunction.
 | 
	
		
			
				|  |  | + * moving_star.xpos, ypos is initialized from x,y.
 | 
	
		
			
				|  |  | + * moving_star.movex, movey is initialized from the rise/run from center.
 | 
	
		
			
				|  |  | + * @param centered
 | 
	
		
			
				|  |  | + * @return moving_star
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +moving_star AnimatedStarfield::make_pos(bool centered) {
 | 
	
		
			
				|  |  |    moving_star pos;
 | 
	
		
			
				|  |  | -  pos.x = uni_x(rng);
 | 
	
		
			
				|  |  | -  pos.y = uni_y(rng);
 | 
	
		
			
				|  |  | -  pos.xpos = pos.x;
 | 
	
		
			
				|  |  | -  pos.ypos = pos.y;
 | 
	
		
			
				|  |  | -  pos.movex = pos.xpos - cx;
 | 
	
		
			
				|  |  | -  pos.movey = pos.ypos - cy;
 | 
	
		
			
				|  |  | -  double bigd = max(abs(pos.movex), abs(pos.movey));
 | 
	
		
			
				|  |  | -  pos.movex /= bigd;
 | 
	
		
			
				|  |  | -  pos.movey /= bigd;
 | 
	
		
			
				|  |  | +  do {
 | 
	
		
			
				|  |  | +    pos.x = uni_x(rng);
 | 
	
		
			
				|  |  | +    pos.y = uni_y(rng);
 | 
	
		
			
				|  |  | +    pos.visible = true;
 | 
	
		
			
				|  |  | +    if (centered) {
 | 
	
		
			
				|  |  | +      pos.x /= 4;
 | 
	
		
			
				|  |  | +      pos.x += cx - (cx / 4);
 | 
	
		
			
				|  |  | +      pos.y /= 4;
 | 
	
		
			
				|  |  | +      pos.y += cy - (cy / 4);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    pos.xpos = pos.x;
 | 
	
		
			
				|  |  | +    pos.ypos = pos.y;
 | 
	
		
			
				|  |  | +    pos.movex = pos.xpos - cx;
 | 
	
		
			
				|  |  | +    pos.movey = pos.ypos - cy;
 | 
	
		
			
				|  |  | +    double bigd = max(abs(pos.movex), abs(pos.movey));
 | 
	
		
			
				|  |  | +    pos.movex /= bigd;
 | 
	
		
			
				|  |  | +    pos.movey /= bigd;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (visible) {
 | 
	
		
			
				|  |  | +      pos.visible = visible(pos.x, pos.y);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  } while (centered and (pos.y == cy));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /*
 | 
	
		
			
				|  |  |      if (get_logger)
 | 
	
	
		
			
				|  | @@ -320,14 +173,8 @@ void AnimatedStarfield::regenerate(void) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    for (int i = 0; i < MAX_STARS; i++) {
 | 
	
		
			
				|  |  |      moving_star pos = make_pos();
 | 
	
		
			
				|  |  | -    // store symbol and color in star_pos.
 | 
	
		
			
				|  |  | -    // If we do any animation, we won't be able to rely on the star_pos keeping
 | 
	
		
			
				|  |  | -    // the same position in the set.
 | 
	
		
			
				|  |  |      pos.symbol = i % 2;
 | 
	
		
			
				|  |  |      pos.color = i % 5 < 2;
 | 
	
		
			
				|  |  | -    pos.xpos = pos.x;
 | 
	
		
			
				|  |  | -    pos.ypos = pos.y;
 | 
	
		
			
				|  |  | -    // calculate movex, movey here and now!
 | 
	
		
			
				|  |  |      sky.push_back(pos);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -343,18 +190,20 @@ void AnimatedStarfield::display(void) {
 | 
	
		
			
				|  |  |    };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    for (auto &pos : sky) {
 | 
	
		
			
				|  |  | -    door::Goto star_at(pos.x, pos.y);
 | 
	
		
			
				|  |  | -    door << star_at;
 | 
	
		
			
				|  |  | +    if (pos.visible) {
 | 
	
		
			
				|  |  | +      door::Goto star_at(pos.x, pos.y);
 | 
	
		
			
				|  |  | +      door << star_at;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (pos.color)
 | 
	
		
			
				|  |  | -      door << dark;
 | 
	
		
			
				|  |  | -    else
 | 
	
		
			
				|  |  | -      door << white;
 | 
	
		
			
				|  |  | +      if (pos.color)
 | 
	
		
			
				|  |  | +        door << dark;
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +        door << white;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (pos.symbol)
 | 
	
		
			
				|  |  | -      door << stars[0];
 | 
	
		
			
				|  |  | -    else
 | 
	
		
			
				|  |  | -      door << stars[1];
 | 
	
		
			
				|  |  | +      if (pos.symbol)
 | 
	
		
			
				|  |  | +        door << stars[0];
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +        door << stars[1];
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -364,7 +213,7 @@ void AnimatedStarfield::animate(void) {
 | 
	
		
			
				|  |  |      // just start with basic movement
 | 
	
		
			
				|  |  |      // double speed = abs((cx / 2) - distance(star.movex, star.movey));
 | 
	
		
			
				|  |  |      double speed = max_d / distance(star.movex, star.movey);
 | 
	
		
			
				|  |  | -    star.xpos += star.movex / (speed * 4);
 | 
	
		
			
				|  |  | +    star.xpos += star.movex / (speed * (mx / my));
 | 
	
		
			
				|  |  |      star.ypos += star.movey / speed;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      int nx = int(star.xpos + 0.5);
 | 
	
	
		
			
				|  | @@ -376,7 +225,7 @@ void AnimatedStarfield::animate(void) {
 | 
	
		
			
				|  |  |      while ((star.xpos < 1) or (star.xpos >= mx - 1) or (star.ypos < 1) or
 | 
	
		
			
				|  |  |             (star.ypos >= my - 1)) {
 | 
	
		
			
				|  |  |        // off the screen!  Whoops!
 | 
	
		
			
				|  |  | -      moving_star new_pos = make_pos();
 | 
	
		
			
				|  |  | +      moving_star new_pos = make_pos(true);
 | 
	
		
			
				|  |  |        nx = new_pos.x;
 | 
	
		
			
				|  |  |        ny = new_pos.y;
 | 
	
		
			
				|  |  |        star.xpos = new_pos.x;
 | 
	
	
		
			
				|  | @@ -390,23 +239,35 @@ void AnimatedStarfield::animate(void) {
 | 
	
		
			
				|  |  |      // if ((star.x != int(star.xpos)) or (star.y == int(star.ypos))) {
 | 
	
		
			
				|  |  |      if ((star.x != nx) or (star.y != ny)) {
 | 
	
		
			
				|  |  |        // star has moved, update time
 | 
	
		
			
				|  |  | -      door << door::Goto(star.x, star.y) << " ";
 | 
	
		
			
				|  |  | +      if (star.visible) {
 | 
	
		
			
				|  |  | +        door << door::Goto(star.x, star.y) << " ";
 | 
	
		
			
				|  |  | +      };
 | 
	
		
			
				|  |  |        star.x = nx; // int(star.xpos);
 | 
	
		
			
				|  |  |        star.y = ny; // int(star.ypos);
 | 
	
		
			
				|  |  | -      door << door::Goto(star.x, star.y);
 | 
	
		
			
				|  |  | -      if (star.color)
 | 
	
		
			
				|  |  | -        door << dark;
 | 
	
		
			
				|  |  | -      else
 | 
	
		
			
				|  |  | -        door << white;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -      if (star.symbol)
 | 
	
		
			
				|  |  | -        door << stars[0];
 | 
	
		
			
				|  |  | -      else
 | 
	
		
			
				|  |  | -        door << stars[1];
 | 
	
		
			
				|  |  | +      if (visible) {
 | 
	
		
			
				|  |  | +        star.visible = visible(star.x, star.y);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // still visible?
 | 
	
		
			
				|  |  | +      if (star.visible) {
 | 
	
		
			
				|  |  | +        door << door::Goto(star.x, star.y);
 | 
	
		
			
				|  |  | +        if (star.color)
 | 
	
		
			
				|  |  | +          door << dark;
 | 
	
		
			
				|  |  | +        else
 | 
	
		
			
				|  |  | +          door << white;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (star.symbol)
 | 
	
		
			
				|  |  | +          door << stars[0];
 | 
	
		
			
				|  |  | +        else
 | 
	
		
			
				|  |  | +          door << stars[1];
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  double AnimatedStarfield::distance(double x, double y) {
 | 
	
		
			
				|  |  |    return sqrt(((cx - x) * (cx - x)) + ((cy - y) * (cy - y)));
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void AnimatedStarfield::setVisible(checkVisibleFunction cvf) { visible = cvf; }
 |