Improves getNeighbours greatly

This commit is contained in:
Kristian Knarvik 2018-03-14 14:00:48 +01:00
parent 6a21332877
commit d4c7d08df7
9 changed files with 153 additions and 138 deletions

View File

@ -91,7 +91,7 @@ public interface ILocation extends IPosition {
* Find the grid cells between this location (exclusive) and another location
* (inclusive).
*
* This is will be a list of length {@link #gridDistanceTo(other)}, containing
* This is a list of length {@link #gridDistanceTo(other)}, containing
* the cells that a chess queen would visit when moving to <code>other</code>.
* <p>
* Computes the maximum of the horizontal and the vertical distance. For

View File

@ -26,7 +26,7 @@ public class Girl implements INonPlayer {
private int attack;
private int defence;
private int visibility;
private Backpack<IItem> backpack = new Backpack<>();
private Backpack backpack = new Backpack();
private static final Random random = new Random();
private List<Class<?>> validItems;

View File

@ -397,7 +397,9 @@ public class Game implements IGame {
}
public void draw() {
map.draw(painter, printer);
//map.draw(painter, printer);
GameMap aMap = (GameMap) map;
aMap.drawVisible(painter, printer, this);
}
@Override
@ -471,20 +473,17 @@ public class Game implements IGame {
@Override
public List<ILocation> getVisible() {
List<ILocation> neighbours = map.getNeighbourhood(currentLocation, currentActor.getVision());
List<ILocation> valid = new ArrayList<>();
List<ILocation> invalid = new ArrayList<>();
for (ILocation neighbour : neighbours) {
boolean blocked = false;
for (ILocation tile : currentLocation.gridLineTo(neighbour)) {
if (map.hasWall(tile)) {
blocked = true;
invalid.add(neighbour);
break;
}
}
if (!blocked) {
valid.add(neighbour);
}
}
return valid;
neighbours.removeAll(invalid);
return neighbours;
}
@Override

View File

@ -6,15 +6,15 @@ import inf101.v18.rogue101.objects.IItem;
import java.util.ArrayList;
import java.util.List;
public class Backpack<T extends IItem> implements IContainer {
public class Backpack implements IContainer {
/**
* A list containing everything in the backpack.
*/
private List<T> content = new ArrayList<>();
private List<IItem> content = new ArrayList<>();
/**
* The maximum amount of items allowed in a single backpack.
*/
private final int MAX_SIZE = 5;
private final int MAX_SIZE = 50;
@Override
public int getCurrentHealth() {
@ -57,7 +57,11 @@ public class Backpack<T extends IItem> implements IContainer {
* @return
*/
public int size() {
return content.size();
int totalSize = 0;
for (IItem item : content) {
totalSize += item.getSize();
}
return totalSize;
}
/**
@ -75,8 +79,8 @@ public class Backpack<T extends IItem> implements IContainer {
* @param item The item to add
* @return
*/
public boolean add(T item) {
if (content.size() < MAX_SIZE) {
public boolean add(IItem item) {
if (size() < MAX_SIZE) {
content.add(item);
return true;
} else {
@ -99,7 +103,7 @@ public class Backpack<T extends IItem> implements IContainer {
* @param i The index of an element
* @return An object of type T
*/
public T get(int i) {
public IItem get(int i) {
return content.get(i);
}
@ -108,18 +112,12 @@ public class Backpack<T extends IItem> implements IContainer {
*
* @return A list of T
*/
public List<T> getContent() {
public List<IItem> getContent() {
return content;
}
@Override
public boolean isFull() {
return content.size() >= MAX_SIZE;
}
//This shows as an error, but is necessary to compile.
@Override
public int compareTo(Object o) {
return compareTo((IItem)o);
return size() >= MAX_SIZE;
}
}

View File

@ -3,9 +3,12 @@ package inf101.v18.rogue101.items;
import inf101.v18.rogue101.game.IGame;
import inf101.v18.rogue101.objects.IItem;
import java.util.ArrayList;
import java.util.List;
public class Chest implements IContainer {
private List<IItem> container = new ArrayList<>();
@Override
public IItem get(int i) {
return null;
@ -38,12 +41,12 @@ public class Chest implements IContainer {
@Override
public String getName() {
return null;
return "Chest";
}
@Override
public int getSize() {
return 100;
return 10000;
}
public String getPrintSymbol() {

View File

@ -1,14 +1,10 @@
package inf101.v18.rogue101.items;
import inf101.v18.rogue101.objects.IItem;
import java.util.List;
/**
* A container for storing anything extending IItem.
*
* @param <T> The item type to store
*/
public interface IContainer<T extends IItem> extends IItem {
public interface IContainer extends IItem {
/**
* Retrieves an item from a container in index i
*
@ -23,7 +19,7 @@ public interface IContainer<T extends IItem> extends IItem {
*
* @return A list of Objects extending IItem
*/
List<T> getContent();
List<IItem> getContent();
/**
* Checks if we can add anything at all to the container.

View File

@ -11,10 +11,12 @@ import inf101.v18.grid.IMultiGrid;
import inf101.v18.grid.MultiGrid;
import inf101.v18.rogue101.Main;
import inf101.v18.rogue101.examples.Carrot;
import inf101.v18.rogue101.game.IGame;
import inf101.v18.rogue101.game.IllegalMoveException;
import inf101.v18.rogue101.items.Manga;
import inf101.v18.rogue101.objects.IActor;
import inf101.v18.rogue101.objects.IItem;
import inf101.v18.rogue101.objects.IPlayer;
import inf101.v18.rogue101.objects.Wall;
import javafx.scene.canvas.GraphicsContext;
@ -117,7 +119,7 @@ public class GameMap implements IGameMap {
try {
for (ILocation loc : cells) {
List<IItem> list = grid.get(loc);
String sym = " ";
String sym = ".";
if (!list.isEmpty()) {
if (Main.MAP_DRAW_ONLY_DIRTY_CELLS) {
ctx.clearRect(loc.getX() * w, loc.getY() * h, w, h);
@ -141,6 +143,88 @@ public class GameMap implements IGameMap {
dirtyLocs.clear();
}
/**
* Draws only the tiles visible to the player.
*
* @param painter
* @param printer
* @param game
*/
public void drawVisible(ITurtle painter, Printer printer, IGame game) {
Iterable<ILocation> cells;
if (Main.MAP_DRAW_ONLY_DIRTY_CELLS) {
if (dirtyLocs.isEmpty())
return;
else
cells = dirtyLocs;
} else {
cells = grid.locations();
painter.as(GraphicsContext.class).clearRect(0, 0, getWidth() * printer.getCharWidth(),
getHeight() * printer.getCharHeight());
printer.clearRegion(1, 1, getWidth(), getHeight());
}
GraphicsContext ctx = painter.as(GraphicsContext.class);
double h = printer.getCharHeight();
double w = printer.getCharWidth();
if (Main.MAP_AUTO_SCALE_ITEM_DRAW) {
ctx.save();
ctx.scale(w / h, 1.0);
w = h;
}
try {
IPlayer player = null;
ILocation playerPos = null;
for (ILocation loc : cells) {
printer.printAt(loc.getX() + 1, loc.getY() + 1, " ");
if (this.hasActors(loc) && this.getActors(loc).get(0) instanceof IPlayer) {
player = (IPlayer) this.getActors(loc).get(0);
playerPos = loc;
}
}
List<ILocation> positions = getVisible(getNeighbourhood(playerPos,player.getVision()), playerPos);
positions.add(playerPos);
for (ILocation loc : positions) {
List<IItem> list = grid.get(loc);
String sym = ".";
if (!list.isEmpty()) {
if (Main.MAP_DRAW_ONLY_DIRTY_CELLS) {
ctx.clearRect(loc.getX() * w, loc.getY() * h, w, h);
// ctx.fillRect(loc.getX() * w, loc.getY() * h, w, h);
}
painter.save();
painter.jumpTo((loc.getX() + 0.5) * w, (loc.getY() + 0.5) * h);
boolean dontPrint = list.get(0).draw(painter, w, h);
painter.restore();
if (!dontPrint) {
sym = list.get(0).getPrintSymbol();
}
}
printer.printAt(loc.getX() + 1, loc.getY() + 1, sym);
}
} finally {
if (Main.MAP_AUTO_SCALE_ITEM_DRAW) {
ctx.restore();
}
}
dirtyLocs.clear();
}
private List<ILocation> getVisible(List<ILocation> neighbours, ILocation loc) {
List<ILocation> invalid = new ArrayList<>();
for (ILocation neighbour : neighbours) {
if (!hasWall(neighbour)) {
for (ILocation tile : loc.gridLineTo(neighbour)) {
if (hasWall(tile)) {
invalid.add(neighbour);
break;
}
}
}
}
neighbours.removeAll(invalid);
return neighbours;
}
@Override
public List<IActor> getActors(ILocation loc) {
List<IActor> items = new ArrayList<>();
@ -263,105 +347,32 @@ public class GameMap implements IGameMap {
} else if (dist == 0) {
return new ArrayList<>(); // empty!
}
List<ILocation> locations = new ArrayList<>();
for (int i = 1; i <= dist; i++) {
ILocation current = loc;
boolean blockedNorth = false, blockedSouth = false, blockedWest = false, blockedEast = false;
for (int j = 0; j < i; j++) { //Checks if we reach out of bounds in the North or West direction.
if (current.canGo(GridDirection.NORTHWEST)) {
current = current.go(GridDirection.NORTHWEST);
} else if (current.canGo(GridDirection.WEST)) {
current = current.go(GridDirection.WEST);
blockedNorth = true;
} else if (current.canGo(GridDirection.NORTH)) {
current = current.go(GridDirection.NORTH);
blockedWest = true;
} else {
blockedNorth = true;
blockedWest = true;
break;
}
}
current = loc;
for (int j = 0; j < i; j++) { //Checks if we reach out of bounds in the South or East direction.
if (current.canGo(GridDirection.SOUTHEAST)) {
current = current.go(GridDirection.SOUTHEAST);
} else if (current.canGo(GridDirection.EAST)) {
current = current.go(GridDirection.EAST);
blockedSouth = true;
} else if (current.canGo(GridDirection.SOUTH)) {
current = current.go(GridDirection.SOUTH);
blockedEast = true;
} else {
blockedSouth = true;
blockedEast = true;
break;
}
}
if (!blockedNorth && !blockedEast && !blockedWest && !blockedSouth) { //If nothing is blocked, get the top and bottom.
current = goTo(loc, GridDirection.NORTHWEST, i);
addLoc(locations, current, GridDirection.EAST, i * 2 + 1);
current = goTo(loc, GridDirection.SOUTHWEST, i);
addLoc(locations, current, GridDirection.EAST, i * 2 + 1);
} else if (blockedNorth && !blockedEast && !blockedWest) { //If top is blocked, get bottom.
current = goTo(loc, GridDirection.EAST, i);
addLoc(locations, current, GridDirection.SOUTH, i + 1);
current = goTo(loc, GridDirection.WEST, i);
addLoc(locations, current, GridDirection.SOUTH, i + 1);
} else if (blockedSouth && !blockedEast && !blockedWest) { //If bottom is blocked, get top.
current = goTo(loc, GridDirection.EAST, i);
addLoc(locations, current, GridDirection.NORTH, i + 1);
current = goTo(loc, GridDirection.WEST, i);
addLoc(locations, current, GridDirection.NORTH, i + 1);
}
if (blockedNorth && !blockedEast) { //Get sides if we have collided with top or bottom.
current = goTo(loc, GridDirection.EAST, i);
addLoc(locations, current, GridDirection.SOUTH, i + 1);
} else if (blockedNorth && !blockedWest) {
current = goTo(loc, GridDirection.WEST, i);
addLoc(locations, current, GridDirection.SOUTH, i + 1);
} else if (blockedSouth && !blockedEast) {
current = goTo(loc, GridDirection.EAST, i);
addLoc(locations, current, GridDirection.NORTH, i + 1);
} else if (blockedSouth && !blockedWest) {
current = goTo(loc, GridDirection.WEST, i);
addLoc(locations, current, GridDirection.NORTH, i + 1);
}
if (!blockedNorth && !blockedSouth && !blockedWest) { //Get east sides.
current = goTo(loc, GridDirection.NORTHWEST, i);
current = current.go(GridDirection.SOUTH);
addLoc(locations, current, GridDirection.SOUTH, i * 2 - 1);
} else if (blockedNorth && blockedWest) {
current = goTo(loc, GridDirection.SOUTH, i);
addLoc(locations, current, GridDirection.EAST, i);
} else if (blockedSouth && blockedWest) {
current = goTo(loc, GridDirection.NORTH, i);
addLoc(locations, current, GridDirection.EAST, i);
} else if (blockedWest) {
current = goTo(loc, GridDirection.NORTH, i);
addLoc(locations, current, GridDirection.EAST, i + 1);
current = goTo(loc, GridDirection.SOUTH, i);
addLoc(locations, current, GridDirection.EAST, i + 1);
}
if (!blockedNorth && !blockedSouth && !blockedEast) { //Get west sides.
current = goTo(loc, GridDirection.NORTHEAST, i);
current = current.go(GridDirection.SOUTH);
addLoc(locations, current, GridDirection.SOUTH, i * 2 - 1);
} else if (blockedNorth && blockedEast) {
current = goTo(loc, GridDirection.SOUTH, i);
addLoc(locations, current, GridDirection.WEST, i);
} else if (blockedSouth && blockedEast) {
current = goTo(loc, GridDirection.NORTH, i);
addLoc(locations, current, GridDirection.WEST, i);
} else if (blockedEast) {
current = goTo(loc, GridDirection.NORTH, i);
addLoc(locations, current, GridDirection.WEST, i + 1);
current = goTo(loc, GridDirection.SOUTH, i);
addLoc(locations, current, GridDirection.WEST, i + 1);
}
}
return locations;
List<ILocation> neighbours = new ArrayList<>();
int startX = loc.getX();
int startY = loc.getY();
for (int i = 1; i <= dist; i++) {
int leftX = startX - i;
int rightX = startX + i;
int topY = startY - i;
int bottomY = startY + i;
for (int x = leftX; x <= rightX; x++) {
if (grid.isValid(x, topY)) {
neighbours.add(getLocation(x, topY));
}
if (grid.isValid(x, bottomY)) {
neighbours.add(getLocation(x, bottomY));
}
}
for (int y = topY; y <= bottomY; y++) {
if (grid.isValid(leftX, y)) {
neighbours.add(getLocation(leftX, y));
}
if (grid.isValid(rightX, y)) {
neighbours.add(getLocation(rightX, y));
}
}
}
return neighbours;
}
/**

View File

@ -14,7 +14,7 @@
# # #
# G #
# G #
# #
# c #
# #
# #
# G #

View File

@ -13,7 +13,7 @@ import java.util.List;
public class Player implements IPlayer {
private int hp = getMaxHealth();
private final Backpack<IItem> equipped = new Backpack<>();
private final Backpack equipped = new Backpack();
// True if the player wants to pick up something using the digit keys
private boolean dropping = false;
// True if the player wants to drop something using the digit keys
@ -158,7 +158,7 @@ public class Player implements IPlayer {
* @param i The wanted index
*/
private void pickUp(IGame game, int i) {
if (equipped.size() < 5) {
if (!equipped.isFull()) {
List<IItem> items = game.getLocalItems();
if (items.size() >= i) {
IItem pickedUp = game.pickUp(items.get(i));
@ -204,7 +204,9 @@ public class Player implements IPlayer {
List<String> items = new ArrayList<>();
for (IItem item : equipped.getContent()) {
String name = item.getName();
items.add(firstCharToUpper(name));
if (name != null) {
items.add(firstCharToUpper(name));
}
}
//TODO: Add item bonuses to visible stats.
game.formatStatus("HP: %d/%d ATK: %d DEF: %s DMG: %s INV: %s", hp, getMaxHealth(), getAttack(), getDefence(), getDamage(), String.join(",", items));
@ -300,4 +302,10 @@ public class Player implements IPlayer {
}
return amount;
}
@Override
public int getVision() {
//TODO: Increase vision based on equipped items
return 3;
}
}