/*
* FieldModel.java
* Copyright (c) 2004 by University of Hamburg. All Rights Reserved.
* Departament of Informatics.
* Distributed Systems and Information Systems.
*
* Created by 9walczak on Sep 24, 2004.
* Last revision $Revision: 2562 $ by:
* $Author: pokahr $ on $Date: 2005-04-26 16:31:45 +0200 (Di, 26 Apr 2005) $.
*/
package jadex.bdi.examples.hunterprey_classic.creature.hunters.ldahunter.potentialfield;
import jadex.bdi.examples.hunterprey_classic.Location;
/**
*
*/
public final class FieldModel
{
final int w;
final int h;
/**
* <code>obstacles</code> obstacle in field model
*/
public final boolean[][] obstacles;
/**
* <code>visits</code>
*/
public final int[][] visits;
final int[][] distance;
/**
* Constructor: <code>FieldModel</code>.
* @param w width
* @param h height
*/
public FieldModel(int w, int h)
{
this.w = w;
this.h = h;
obstacles = new boolean[w][h];
distance = new int[w][h];
visits = new int[w][h];
}
/**
* @param loc the location the values should be stored to (in, out)
* @return false if this location has distance <= 0, true if location changed
*/
public final boolean getNearerLocation(final Location loc)
{
final int ix = loc.getX();
final int iy = loc.getY();
int ox = ix;
int oy = iy;
double height = distance[ix][iy];
if(height<0.0) return false;
if(distance[(ix+1)%w][iy]<height)
{
height = distance[(ix+1)%w][iy];
ox = (ix+1)%w;
oy = iy;
}
if(distance[(ix+w-1)%w][iy]<height)
{
height = distance[(ix+w-1)%w][iy];
ox = (ix+w-1)%w;
oy = iy;
}
if(distance[ix][(iy+1)%h]<height)
{
height = distance[ix][(iy+1)%h];
ox = ix;
oy = (iy+1)%h;
}
if(distance[ix][(iy+h-1)%h]<height)
{
ox = ix;
oy = (iy+h-1)%h;
}
loc.setX(ox);
loc.setY(oy);
return ox!=ix || oy!=iy;
}
/**
* @param mx - from x
* @param my - from y
*/
public void calcDistance(int mx, int my)
{
clearDistance();
distance[mx][my] = 0;
goR(mx, my, 1);
goD(mx, my, 1);
goL(mx, my, 1);
goU(mx, my, 1);
}
/**
* @param x
* @param y
* @param d
* @return own distance
*/
protected final int goR(int x, int y, final int d)
{
x = (x+1)%w; // go right
if(obstacles[x][y])
{
return distance[x][y] = Integer.MAX_VALUE-2;
}
int step = d+1;
int reverse;
if(distance[x][y]>d)
{ // found new way to x, y
distance[x][y] = d;
reverse = goD(x, y, step);
if(reverse+1<distance[x][y])
{ // wow there is even shorter way
distance[x][y] = reverse+1;
step = reverse+2;
}
reverse = goR(x, y, step);
if(reverse+1<distance[x][y])
{ // wow there is even shorter way
distance[x][y] = reverse+1;
step = reverse+2;
}
reverse = goU(x, y, step);
if(reverse+1<distance[x][y])
{ // wow there is even shorter way
distance[x][y] = reverse+1;
step = reverse+2;
}
}
return distance[x][y];
}
/**
* @param x
* @param y
* @param d
* @return own distance
*/
protected final int goD(int x, int y, final int d)
{
y = (y+1)%h; // go down
if(obstacles[x][y])
{
return distance[x][y] = Integer.MAX_VALUE-2;
}
int step = d+1;
int reverse;
if(distance[x][y]>d)
{ // found new way to x, y
distance[x][y] = d;
reverse = goL(x, y, step);
if(reverse+1<distance[x][y])
{ // wow there is even shorter way
distance[x][y] = reverse+1;
step = reverse+2;
}
reverse = goD(x, y, step);
if(reverse+1<distance[x][y])
{ // wow there is even shorter way
distance[x][y] = reverse+1;
step = reverse+2;
}
reverse = goR(x, y, step);
if(reverse+1<distance[x][y])
{ // wow there is even shorter way
distance[x][y] = reverse+1;
step = reverse+2;
}
}
return distance[x][y];
}
/**
* @param x
* @param y
* @param d
* @return own distance
*/
protected final int goL(int x, int y, final int d)
{
x = (x+w-1)%w; // go left
if(obstacles[x][y])
{
return distance[x][y] = Integer.MAX_VALUE-2;
}
int step = d+1;
int reverse;
if(distance[x][y]>d)
{ // found new way to x, y
distance[x][y] = d;
reverse = goU(x, y, step);
if(reverse+1<distance[x][y])
{ // wow there is even shorter way
distance[x][y] = reverse+1;
step = reverse+2;
}
reverse = goL(x, y, step);
if(reverse+1<distance[x][y])
{ // wow there is even shorter way
distance[x][y] = reverse+1;
step = reverse+2;
}
reverse = goD(x, y, step);
if(reverse+1<distance[x][y])
{ // wow there is even shorter way
distance[x][y] = reverse+1;
step = reverse+2;
}
}
return distance[x][y];
}
/**
* @param x
* @param y
* @param d
* @return own distance
*/
protected final int goU(int x, int y, final int d)
{
y = (y+h-1)%h; // go up
if(obstacles[x][y])
{
return distance[x][y] = Integer.MAX_VALUE-2;
}
int step = d+1;
int reverse;
if(distance[x][y]>d)
{ // found new way to x, y
distance[x][y] = d;
reverse = goR(x, y, step);
if(reverse+1<distance[x][y])
{ // wow there is even shorter way
distance[x][y] = reverse+1;
step = reverse+2;
}
reverse = goU(x, y, step);
if(reverse+1<distance[x][y])
{ // wow there is even shorter way
distance[x][y] = reverse+1;
step = reverse+2;
}
reverse = goL(x, y, step);
if(reverse+1<distance[x][y])
{ // wow there is even shorter way
distance[x][y] = reverse+1;
step = reverse+2;
}
}
return distance[x][y];
}
/**
* clears the first buffer
*/
public void clearDistance()
{
for(int i = w; i-->0;)
{
for(int j = h; j-->0;)
{
distance[i][j] = Integer.MAX_VALUE-2;
}
}
}
/**
* @param x
* @param y
* @param r
* @param round
*/
public void clearRange(int x, int y, int r, int round)
{
for(int i = x-r; i<=x+r; i++)
{
for(int j = y-r; j<=y+r; j++)
{
visits[(i+w)%w][(j+h)%h] = round;
}
}
}
}