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 * Find the grid cells between this location (exclusive) and another location
* (inclusive). * (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>. * the cells that a chess queen would visit when moving to <code>other</code>.
* <p> * <p>
* Computes the maximum of the horizontal and the vertical distance. For * 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 attack;
private int defence; private int defence;
private int visibility; private int visibility;
private Backpack<IItem> backpack = new Backpack<>(); private Backpack backpack = new Backpack();
private static final Random random = new Random(); private static final Random random = new Random();
private List<Class<?>> validItems; private List<Class<?>> validItems;

View File

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

View File

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

View File

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

View File

@ -1,14 +1,10 @@
package inf101.v18.rogue101.items; package inf101.v18.rogue101.items;
import inf101.v18.rogue101.objects.IItem; import inf101.v18.rogue101.objects.IItem;
import java.util.List; import java.util.List;
/** public interface IContainer extends IItem {
* A container for storing anything extending IItem.
*
* @param <T> The item type to store
*/
public interface IContainer<T extends IItem> extends IItem {
/** /**
* Retrieves an item from a container in index i * 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 * @return A list of Objects extending IItem
*/ */
List<T> getContent(); List<IItem> getContent();
/** /**
* Checks if we can add anything at all to the container. * 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.grid.MultiGrid;
import inf101.v18.rogue101.Main; import inf101.v18.rogue101.Main;
import inf101.v18.rogue101.examples.Carrot; import inf101.v18.rogue101.examples.Carrot;
import inf101.v18.rogue101.game.IGame;
import inf101.v18.rogue101.game.IllegalMoveException; import inf101.v18.rogue101.game.IllegalMoveException;
import inf101.v18.rogue101.items.Manga; import inf101.v18.rogue101.items.Manga;
import inf101.v18.rogue101.objects.IActor; import inf101.v18.rogue101.objects.IActor;
import inf101.v18.rogue101.objects.IItem; import inf101.v18.rogue101.objects.IItem;
import inf101.v18.rogue101.objects.IPlayer;
import inf101.v18.rogue101.objects.Wall; import inf101.v18.rogue101.objects.Wall;
import javafx.scene.canvas.GraphicsContext; import javafx.scene.canvas.GraphicsContext;
@ -117,7 +119,7 @@ public class GameMap implements IGameMap {
try { try {
for (ILocation loc : cells) { for (ILocation loc : cells) {
List<IItem> list = grid.get(loc); List<IItem> list = grid.get(loc);
String sym = " "; String sym = ".";
if (!list.isEmpty()) { if (!list.isEmpty()) {
if (Main.MAP_DRAW_ONLY_DIRTY_CELLS) { if (Main.MAP_DRAW_ONLY_DIRTY_CELLS) {
ctx.clearRect(loc.getX() * w, loc.getY() * h, w, h); ctx.clearRect(loc.getX() * w, loc.getY() * h, w, h);
@ -141,6 +143,88 @@ public class GameMap implements IGameMap {
dirtyLocs.clear(); 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 @Override
public List<IActor> getActors(ILocation loc) { public List<IActor> getActors(ILocation loc) {
List<IActor> items = new ArrayList<>(); List<IActor> items = new ArrayList<>();
@ -263,105 +347,32 @@ public class GameMap implements IGameMap {
} else if (dist == 0) { } else if (dist == 0) {
return new ArrayList<>(); // empty! return new ArrayList<>(); // empty!
} }
List<ILocation> neighbours = new ArrayList<>();
List<ILocation> locations = new ArrayList<>(); int startX = loc.getX();
for (int i = 1; i <= dist; i++) { int startY = loc.getY();
ILocation current = loc; for (int i = 1; i <= dist; i++) {
boolean blockedNorth = false, blockedSouth = false, blockedWest = false, blockedEast = false; int leftX = startX - i;
for (int j = 0; j < i; j++) { //Checks if we reach out of bounds in the North or West direction. int rightX = startX + i;
if (current.canGo(GridDirection.NORTHWEST)) { int topY = startY - i;
current = current.go(GridDirection.NORTHWEST); int bottomY = startY + i;
} else if (current.canGo(GridDirection.WEST)) { for (int x = leftX; x <= rightX; x++) {
current = current.go(GridDirection.WEST); if (grid.isValid(x, topY)) {
blockedNorth = true; neighbours.add(getLocation(x, topY));
} else if (current.canGo(GridDirection.NORTH)) { }
current = current.go(GridDirection.NORTH); if (grid.isValid(x, bottomY)) {
blockedWest = true; neighbours.add(getLocation(x, bottomY));
} else { }
blockedNorth = true; }
blockedWest = true; for (int y = topY; y <= bottomY; y++) {
break; if (grid.isValid(leftX, y)) {
} neighbours.add(getLocation(leftX, y));
} }
current = loc; if (grid.isValid(rightX, y)) {
for (int j = 0; j < i; j++) { //Checks if we reach out of bounds in the South or East direction. neighbours.add(getLocation(rightX, y));
if (current.canGo(GridDirection.SOUTHEAST)) { }
current = current.go(GridDirection.SOUTHEAST); }
} else if (current.canGo(GridDirection.EAST)) { }
current = current.go(GridDirection.EAST); return neighbours;
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;
} }
/** /**

View File

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

View File

@ -13,7 +13,7 @@ import java.util.List;
public class Player implements IPlayer { public class Player implements IPlayer {
private int hp = getMaxHealth(); 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 // True if the player wants to pick up something using the digit keys
private boolean dropping = false; private boolean dropping = false;
// True if the player wants to drop something using the digit keys // 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 * @param i The wanted index
*/ */
private void pickUp(IGame game, int i) { private void pickUp(IGame game, int i) {
if (equipped.size() < 5) { if (!equipped.isFull()) {
List<IItem> items = game.getLocalItems(); List<IItem> items = game.getLocalItems();
if (items.size() >= i) { if (items.size() >= i) {
IItem pickedUp = game.pickUp(items.get(i)); IItem pickedUp = game.pickUp(items.get(i));
@ -204,7 +204,9 @@ public class Player implements IPlayer {
List<String> items = new ArrayList<>(); List<String> items = new ArrayList<>();
for (IItem item : equipped.getContent()) { for (IItem item : equipped.getContent()) {
String name = item.getName(); String name = item.getName();
items.add(firstCharToUpper(name)); if (name != null) {
items.add(firstCharToUpper(name));
}
} }
//TODO: Add item bonuses to visible stats. //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)); 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; return amount;
} }
@Override
public int getVision() {
//TODO: Increase vision based on equipped items
return 3;
}
} }