bool jump_and_build_platform_somewhere()

in coinrun/coinrun.cpp [481:596]


  bool jump_and_build_platform_somewhere()
  {
    float gravity = .2;
    float max_jump = 1.5;
    float max_speed = 0.5;

    if (rec_stack.empty()) return false;
    int n = int(sqrt(randn(rec_stack.size() * rec_stack.size())));
    assert(n < (int)rec_stack.size());
    Rec r = rec_stack[n];
    float vx = (rand01()*2-1)*0.5*max_speed;
    float vy = (0.8 + 0.2*rand01())*max_jump;

    int top = 1 + int(vy/gravity);
    int ix, iy;
    if (randn(2)==1) {
      int steps = top + (randn(top/2));
      float x = r.x;
      float y = r.y + 1;

      ix = -1;
      iy = -1;
      for (int s=0; s<steps; s++) {
        vy -= gravity;
        x += vx;
        y += vy;
        if (ix != int(x) || iy != int(y)) {
          ix = int(x);
          iy = int(y);
          bool ouch = false;
          ouch |= ix<1;
          ouch |= ix>=maze->w-1;
          ouch |= iy<1;
          ouch |= iy>=maze->h-1;
          if (ouch) return false;
          char c = maze->get_elem(ix, iy);
          ouch |= c!=SPACE && c!=' ';
          if (ouch) return false;
          maze->set_elem(ix, iy, ' ');
        }
      }
    } else {
      ix = r.x;
      iy = r.y;
      if (is_crat(maze->get_elem(ix, iy)) || is_crat(maze->get_elem(ix, iy-1)))
        return false; // don't build ladders starting from crates
      rec_stack.erase(rec_stack.begin()+n);
      std::vector<Rec> future_ladder;
      int ladder_len = 5 + randn(10);
      for (int s=0; s<ladder_len; s++) {
        future_ladder.push_back(Rec({ ix, iy }));
        iy += 1;
        bool ouch = false;
        ouch |= iy>=maze->h-3;
        ouch |= maze->get_elem(ix, iy) != SPACE;
        ouch |= maze->get_elem(ix-1, iy) == LADDER;
        ouch |= maze->get_elem(ix+1, iy) == LADDER;
        if (ouch) return false;
      }
      for (const Rec& f: future_ladder)
        maze->set_elem(f.x, f.y, LADDER);
      maze->set_elem(ix, iy, LADDER);
    }

    char c = maze->get_elem(ix, iy);
    if (c==SPACE || c==' ')
      maze->set_elem(ix, iy, vx>0 ? 'a':'b');
    std::vector<Rec> crates;
    std::vector<Rec> monster_candidates;
    int len = 2 + randn(10);
    int crates_shift = randn(20);
    for (int platform=0; platform<len; platform++) {
      ix += (vx>0 ? +1 : -1);
      int c = maze->get_elem(ix, iy);
      if (c == ' ' || c == SPACE) {
        maze->set_elem(ix, iy, (platform<len-1) ? WALL_SURFACE : (vx>0 ? 'b':'a'));
        rec_stack.push_back(Rec({ ix, iy+1 }));
        if (int(ix*0.2 + iy + crates_shift) % 4 == 0)
          crates.push_back(Rec({ ix, iy+1 }));
        else if (platform>0 && platform<len-1)
          monster_candidates.push_back(Rec({ ix, iy+1 }));
      } else {
        if (c =='a' || c == 'b')
          maze->set_elem(ix, iy, WALL_SURFACE);
        break;
      }
    }

    if (monster_candidates.size() > 1) {
      const Rec& r = monster_candidates[randn(monster_candidates.size())];
      maze->set_elem(r.x, r.y, WALKING_MONSTER);
    }

    while (1) {
      int cnt = crates.size();
      if (cnt==0) break;
      for (int c=0; c<(int)crates.size(); ) {
        char w = maze->get_elem(crates[c].x, crates[c].y);
        char wl = maze->get_elem(crates[c].x-1, crates[c].y);
        char wr = maze->get_elem(crates[c].x+1, crates[c].y);
        char wu = maze->get_elem(crates[c].x, crates[c].y+1);
        int want = 2 + is_crat(wl) + is_crat(wr) - (wr==LADDER) - (wl==LADDER) - is_wall(wu);
        if (randn(4) < want && crates[c].y < maze->h-2) {
          if (w==' ' || w==SPACE)
            maze->set_elem(crates[c].x, crates[c].y, choose_crate());
          crates[c].y += 1;
          rec_stack.push_back(Rec({ crates[c].x, crates[c].y }));  // coins on crates, jumps from crates
          c++;
        } else {
          crates.erase(crates.begin() + c);
        }
      }
    }

    return true;
  }