Package generator

Source Code of generator.MixGenerator

package generator;
import java.util.Random;
import engine.Board;
import engine.Scheme;

/**
* Class is used to moving the blocks on the board.
*/
public final class MixGenerator {
 
  private static Random rand = new Random();
 
  /**
   * Generates a new situation with moves, which execution leads to the given board.
   * The blocks can't be raised.
   *
   * @param pbb - probability of moving a block
   * @param originalScheme - the scheme, which contains the board
   * @return scheme with the new board and the moves
   */
  public static Scheme generateEquivalent(double pbb, Scheme originalScheme) {
    Scheme s = new Scheme(new Board(originalScheme.start));
   
    int width = s.start.width, height = s.start.height;
    int[] rows = MixGenerator.randomPermutation(height);
    for (int y : rows) {
      int[] columns = MixGenerator.randomPermutation(width);
      boolean[] row = new boolean[width];
      for(int x : columns)
        if (!row[x] && rand.nextDouble() < pbb)
          row[moveBlock(x, y, false, s)] = true;
    }
    s.optimizeMoves();
    return s;
  }

  /**
   * Generates a new situation with moves, which execution leads to the board from
   * given scheme. The blocks can be raised.
   *
   * @param pbb - probability of moving a block
   * @param originalScheme - the given scheme
   * @return scheme with the new board and the moves
   */
  public static Scheme generatePrevious(double pbb, Scheme originalScheme) {
    Scheme s = new Scheme(new Board(originalScheme.start));
    int width = s.start.width, height = s.start.height;
   
    for (int y = 0; y < height; y++) {
      int[] columns = MixGenerator.randomPermutation(width);
      boolean[] row = new boolean[width];
      for(int x : columns)
        if (!row[x] && rand.nextDouble() < pbb)
          row[moveBlock(x, y, true, s)] = true;
    }
    s.optimizeMoves();   
    return s;
  }
 
  /**
   * Moves the block into other field.
   *
   * @param x - coordinate of the block
   * @param y - coordinate of the block
   * @param canJump -true if block can be raised
   * @param s - the given scheme
   * @return new field's x of the block
   */
  public static int moveBlock(int x, int y, boolean canJump, Scheme s) {
    if (!s.start.isBlock(x,y) || s.start.isBlock(x,y-1) ||
        s.start.getType(x, y+1) == Board.BLOCK_BALLOON) return x;    
    int i=0, j=0, color = s.start.getColor(x,y), type  = s.start.getType(x, y);  
    if (type == Board.BLOCK_GLASS) canJump = false;
   
    // columns
    while (x-1+i >=0 && s.start.isEmpty(x-1+i,y) &&
        (!s.start.isBlock(x-1+i,y+1) || s.start.getColor(x-1+i,y+1) != color) &&
        (!s.start.isBlock(x-1+i,y-1) || s.start.getColor(x-1+i,y-1) != color) &&
        (!s.start.isBlock(x-1+i-1,y) || s.start.getColor(x-1+i-1,y) != color) &&
        (type != Board.BLOCK_BALLOON && (s.start.isBlock(x-1+i,y+1) ||
            s.start.isSolid(x-1+i,y+1) || s.start.getType(x-1+i,y+1) == Board.CONCRETE)
            || type == Board.BLOCK_BALLOON && (s.start.isBlock(x-1+i,y-1) ||
                s.start.isSolid(x-1+i,y-1) || s.start.getType(x-1+i,y-1) == Board.CONCRETE)))
      i--;
    while (x+1+j < s.start.width && s.start.isEmpty(x+1+j,y) &&
        (!s.start.isBlock(x+1+j,y+1) || s.start.getColor(x+1+j,y+1) != color) &&
        (!s.start.isBlock(x+1+j,y-1) || s.start.getColor(x+1+j,y-1) != color) &&
        (!s.start.isBlock(x+1+j+1,y) || s.start.getColor(x+1+j+1,y) != color) &&
        (type != Board.BLOCK_BALLOON && (s.start.isBlock(x+1+j,y+1) ||
            s.start.isSolid(x+1+j,y+1) ||s.start.getType(x+1+j,y+1) == Board.CONCRETE)
            || type == Board.BLOCK_BALLOON && (s.start.isBlock(x+1+j,y-1) ||
                s.start.isSolid(x+1+j,y-1) ||s.start.getType(x+1+j,y-1) == Board.CONCRETE)))
      j++;

    if (!canJump) {
      if (j==0 && i==0) return x;
      int pos = rand.nextInt(j-i) + i;
      if (pos >= 0) pos++;
      s.start.setElement(x,y,Board.EMPTY);
      s.start.setElement(x+pos,y,type,color);
      while (pos > 0) {x++; s.moves.addFirst(new Scheme.Move(false,x,y)); pos--; }
      while (pos < 0) {x--; s.moves.addFirst(new Scheme.Move(true,x,y)); pos++; }
      return pos+x;    
    }  
   
    // jumps
    int[][] fields = new int[s.start.width][s.start.height];
    int total = 0;
   
    for (int k = 0; k < j-i+1; k++) {
      int h = y,  pos = k+i+x;
      boolean lok = false, rok = false;
      while (h>0 && s.start.isEmpty(pos, h-1)) h--;

      while (h <= y) {       
        lok = correctMove(pos-1, h-1, pos-1, h, -1, -1, s.start, lok);
        rok = correctMove(pos+1, h-1, pos+1, h, -1, -1, s.start, rok);
        if (correctMove(pos-1, h, pos, y, color, type, s.start, lok) && fields[pos-1][h] == 0) {
            fields[pos-1][h] = -1; total++;   
        }
        if (correctMove(pos+1, h, pos, y, color, type, s.start, rok) && fields[pos+1][h] == 0) {
            fields[pos+1][h] = 1; total++; 
        }
        h++;       
      }
    }
   
    if (total < 1) return x;
    int newX = -1, newY = -1, t, c, posY = -1, r = rand.nextInt(total);
    for (int k=0; k < s.start.width; k++)
      for (int l=0; l < s.start.height; l++)
        if (fields[k][l] != 0)
          if (r == 0) {newX = k; posY = newY = l; k = s.start.width; break;}  
          else r--;

    // move
    while (!s.start.isEmpty(newX, posY) && posY > 0) {
      t = s.start.getType(newX, posY);
      c = s.start.getColor(newX, posY);
      s.start.setElement(newX, posY, s.start.getType(x, y), s.start.getColor(x, y));
      s.start.setElement(x, y, t, c);
      posY--;
    }
    s.start.setElement(newX, posY, s.start.getType(x, y), s.start.getColor(x, y));
    s.start.setElement(x, y, Board.EMPTY);
   
    int pos = (fields[newX][newY] == 1)? newX-1 : newX+1;
   
    while (pos-x > 0) {x++; s.moves.addFirst(new Scheme.Move(false,x,y)); }
    while (pos-x < 0) {x--; s.moves.addFirst(new Scheme.Move(true,x,y)); }
    if (fields[newX][newY] == 1) s.moves.addFirst(new Scheme.Move(false,newX,newY));
    else s.moves.addFirst(new Scheme.Move(true,newX,newY));    
   
    return newX;
  }
 
  /**
   * Checks if the block can be moved in other field.
   *
   * @param x - coordinate of the block
   * @param y - coordinate of the block
   * @param canJump -true if the block can be raised
   * @param s - the given scheme
   * @return true if the block can be moved
   */
  public static boolean canMoveBlock(int x, int y, boolean canJump, Scheme s) {
    if (!s.start.isBlock(x,y) || s.start.isBlock(x,y-1) ||
        s.start.getType(x, y+1) == Board.BLOCK_BALLOON) return false;
    int color = s.start.getColor(x, y), type = s.start.getType(x, y);   
    if (type == Board.BLOCK_GLASS) canJump = false;
   
    if (!canJump)
      return correctMove(x-1,y,x,y,color,type,s.start,false) ||
          correctMove(x+1,y,x,y,color,type,s.start,false);
   
    int h = y, total = 0;
    boolean lok = false, rok = false;
    while (h>0 && s.start.isEmpty(x, h-1)) h--;
    while (h <= y && total==0) {       
      lok = MixGenerator.correctMove(x-1, h-1, x-1, h, -1, -1, s.start, lok);
      rok = MixGenerator.correctMove(x+1, h-1, x+1, h, -1, -1, s.start, rok);
      if (MixGenerator.correctMove(x-1, h, x, y, color, type, s.start, lok)) total++;
      if (MixGenerator.correctMove(x+1, h, x, y, color, type, s.start, rok)) total++;
      h++;       
    }
   
    if (total > 0) return true;
    return false;
  }
 
  /**
   * Check if the move is correct.
   *
   * @param newX - coordinate of the new field
   * @param newY - coordinate of the new field
   * @param x - coordinate of the old field
   * @param y - coordinate of the old field
   * @param color - color of the block
   * @param type - type of the block
   * @param board - the board
   * @param canRaise - true if the block can be raised
   * @return true if the move is correct
   */
  public static boolean correctMove(int newX, int newY, int x, int y, int color,
      int type, Board board, boolean canRaise) {   
    if (type == -1) type = board.getType(x, y);
    if (type != Board.BLOCK_BALLOON && type != Board.BLOCK_CONCRETE &&
        type != Board.BLOCK_GLASS && type != Board.BLOCK_SPHERE) return false;
    if (color == -1) color = board.getColor(x, y);
   
    if (type != Board.BLOCK_BALLOON &&
        (board.getType(newX, newY+1) == Board.EMPTY ||
        board.getType(newX, newY+1) == Board.ICE ||
        board.getType(newX, newY+1) == Board.ELEVATOR ||
        board.getType(newX, newY+1) == Board.ELEVATOR_ROOT ||
        board.getType(newX, newY+1) == Board.PAINTER ||
        board.getType(newX, newY+1) == Board.LAVA ||
        board.isBlock(newX, newY+1) && board.getColor(newX, newY+1) == color
        && !(y==newY+1 && x==newX))) return false;
   
    if (type == Board.BLOCK_BALLOON &&
        (board.getType(newX, newY-1) == Board.EMPTY ||
        board.getType(newX, newY-1) == Board.ICE ||
        board.getType(newX, newY-1) == Board.ELEVATOR ||
        board.getType(newX, newY-1) == Board.ELEVATOR_ROOT ||
        board.getType(newX, newY-1) == Board.PAINTER ||
        board.getType(newX, newY-1) == Board.LAVA ||
        board.isBlock(newX, newY-1) && board.getColor(newX, newY-1) == color
        && !(y==newY-1 && x==newX))) return false;

    if (!(board.isEmpty(newX, newY) || board.isBlock(newX, newY) && canRaise) ||
        board.isBlock(newX, newY) && board.getColor(newX, newY) == color ||
        board.getType(newX, newY) == Board.BLOCK_GLASS)
      return false;

    if (board.isEmpty(newX, newY) && (board.isBlock(newX, newY-1) &&
        board.getColor(newX, newY-1) == color  && !(y==newY-1 && x==newX) ||
        board.isBlock(newX, newY+1) && board.getColor(newX, newY+1) == color 
        && !(y==newY+1 && x==newX))) return false;

    if (board.isBlock(newX+1, newY) && board.getColor(newX+1, newY) == color
        && !(y==newY && x==newX+1) ||
        board.isBlock(newX-1, newY) && board.getColor(newX-1, newY) == color
        && !(y==newY && x==newX-1)) return false;

    return true;
  }
 
  /**
   * Generates a random permutation of integers from [0..n).
   *
   * @param n - size of the permutation
   * @return the new permutation
   */
  public final static int[] randomPermutation(int n) {
    int[] t = new int[n];
    for (int i=0;i<n;i++) t[i]=i;
    for (;n>0;n--) {
      int i = rand.nextInt(n);
      int v = t[n-1];
      t[n-1] = t[i];
      t[i] = v;
    }
    return t;
  }
 
}
TOP

Related Classes of generator.MixGenerator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.