ready!
This commit is contained in:
489
src/inf101/v18/rogue101/game/Game.java
Normal file
489
src/inf101/v18/rogue101/game/Game.java
Normal file
@@ -0,0 +1,489 @@
|
||||
package inf101.v18.rogue101.game;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import inf101.v18.gfx.Screen;
|
||||
import inf101.v18.gfx.gfxmode.ITurtle;
|
||||
import inf101.v18.gfx.gfxmode.TurtlePainter;
|
||||
import inf101.v18.gfx.textmode.Printer;
|
||||
import inf101.v18.grid.GridDirection;
|
||||
import inf101.v18.grid.IGrid;
|
||||
import inf101.v18.grid.ILocation;
|
||||
import inf101.v18.rogue101.Main;
|
||||
import inf101.v18.rogue101.examples.Carrot;
|
||||
import inf101.v18.rogue101.examples.Rabbit;
|
||||
import inf101.v18.rogue101.map.GameMap;
|
||||
import inf101.v18.rogue101.map.IGameMap;
|
||||
import inf101.v18.rogue101.map.IMapView;
|
||||
import inf101.v18.rogue101.map.MapReader;
|
||||
import inf101.v18.rogue101.objects.Dust;
|
||||
import inf101.v18.rogue101.objects.IActor;
|
||||
import inf101.v18.rogue101.objects.IItem;
|
||||
import inf101.v18.rogue101.objects.INonPlayer;
|
||||
import inf101.v18.rogue101.objects.IPlayer;
|
||||
import inf101.v18.rogue101.objects.Wall;
|
||||
import javafx.scene.canvas.GraphicsContext;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.paint.Color;
|
||||
|
||||
public class Game implements IGame {
|
||||
/**
|
||||
* All the IActors that have things left to do this turn
|
||||
*/
|
||||
private List<IActor> actors = Collections.synchronizedList(new ArrayList<>());
|
||||
/**
|
||||
* For fancy solution to factory problem
|
||||
*/
|
||||
private Map<String, Supplier<IItem>> itemFactories = new HashMap<>();
|
||||
/**
|
||||
* Useful random generator
|
||||
*/
|
||||
private Random random = new Random();
|
||||
/**
|
||||
* The game map. {@link IGameMap} gives us a few more details than
|
||||
* {@link IMapView} (write access to item lists); the game needs this but
|
||||
* individual items don't.
|
||||
*/
|
||||
private IGameMap map;
|
||||
private IActor currentActor;
|
||||
private ILocation currentLocation;
|
||||
private int movePoints = 0;
|
||||
private final ITurtle painter;
|
||||
private final Printer printer;
|
||||
private int numPlayers = 0;
|
||||
|
||||
public Game(Screen screen, ITurtle painter, Printer printer) {
|
||||
this.painter = painter;
|
||||
this.printer = printer;
|
||||
|
||||
// TODO: (*very* optional) for advanced factory technique, use
|
||||
// something like "itemFactories.put("R", () -> new Rabbit());"
|
||||
// must be done *before* you read the map
|
||||
|
||||
// NOTE: in a more realistic situation, we will have multiple levels (one map
|
||||
// per level), and (at least for a Roguelike game) the levels should be
|
||||
// generated
|
||||
//
|
||||
// inputGrid will be filled with single-character strings indicating what (if
|
||||
// anything)
|
||||
// should be placed at that map square
|
||||
IGrid<String> inputGrid = MapReader.readFile("maps/level1.txt");
|
||||
if (inputGrid == null) {
|
||||
System.err.println("Map not found – falling back to builtin map");
|
||||
inputGrid = MapReader.readString(Main.BUILTIN_MAP);
|
||||
}
|
||||
this.map = new GameMap(inputGrid.getArea());
|
||||
for (ILocation loc : inputGrid.locations()) {
|
||||
IItem item = createItem(inputGrid.get(loc));
|
||||
if (item != null) {
|
||||
map.add(loc, item);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Game(String mapString) {
|
||||
printer = new Printer(1280, 720);
|
||||
painter = new TurtlePainter(1280, 720, null);
|
||||
IGrid<String> inputGrid = MapReader.readString(mapString);
|
||||
this.map = new GameMap(inputGrid.getArea());
|
||||
for (ILocation loc : inputGrid.locations()) {
|
||||
IItem item = createItem(inputGrid.get(loc));
|
||||
if (item != null) {
|
||||
map.add(loc, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addItem(IItem item) {
|
||||
map.add(currentLocation, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addItem(String sym) {
|
||||
IItem item = createItem(sym);
|
||||
if (item != null)
|
||||
map.add(currentLocation, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ILocation attack(GridDirection dir, IItem target) {
|
||||
ILocation loc = map.go(currentLocation, dir);
|
||||
if (map.has(loc, target))
|
||||
throw new IllegalMoveException("Target isn't there!");
|
||||
|
||||
// TODO: implement attack
|
||||
|
||||
|
||||
map.clean(loc);
|
||||
|
||||
if (target.isDestroyed()) {
|
||||
return move(dir);
|
||||
} else {
|
||||
movePoints--;
|
||||
return currentLocation;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin a new game turn, or continue to the previous turn
|
||||
*
|
||||
* @return True if the game should wait for more user input
|
||||
*/
|
||||
public boolean doTurn() {
|
||||
do {
|
||||
if (actors.isEmpty()) {
|
||||
// System.err.println("new turn!");
|
||||
|
||||
// no one in the queue, we're starting a new turn!
|
||||
// first collect all the actors:
|
||||
beginTurn();
|
||||
}
|
||||
|
||||
// process actors one by one; for the IPlayer, we return and wait for keypresses
|
||||
// Possible TODO: for INonPlayer, we could also return early (returning
|
||||
// *false*), and then insert a little timer delay between each non-player move
|
||||
// (the timer
|
||||
// is already set up in Main)
|
||||
while (!actors.isEmpty()) {
|
||||
// get the next player or non-player in the queue
|
||||
currentActor = actors.remove(0);
|
||||
if (currentActor.isDestroyed()) // skip if it's dead
|
||||
continue;
|
||||
currentLocation = map.getLocation(currentActor);
|
||||
if (currentLocation == null) {
|
||||
displayDebug("doTurn(): Whoops! Actor has disappeared from the map: " + currentActor);
|
||||
}
|
||||
movePoints = 1; // everyone gets to do one thing
|
||||
|
||||
if (currentActor instanceof INonPlayer) {
|
||||
// computer-controlled players do their stuff right away
|
||||
((INonPlayer) currentActor).doTurn(this);
|
||||
// remove any dead items from current location
|
||||
map.clean(currentLocation);
|
||||
} else if (currentActor instanceof IPlayer) {
|
||||
if (currentActor.isDestroyed()) {
|
||||
// a dead human player gets removed from the game
|
||||
// TODO: you might want to be more clever here
|
||||
displayMessage("YOU DIE!!!");
|
||||
map.remove(currentLocation, currentActor);
|
||||
currentActor = null;
|
||||
currentLocation = null;
|
||||
} else {
|
||||
// For the human player, we need to wait for input, so we just return.
|
||||
// Further keypresses will cause keyPressed() to be called, and once the human
|
||||
// makes a move, it'll lose its movement point and doTurn() will be called again
|
||||
//
|
||||
// NOTE: currentActor and currentLocation are set to the IPlayer (above),
|
||||
// so the game remembers who the player is whenever new keypresses occur. This
|
||||
// is also how e.g., getLocalItems() work – the game always keeps track of
|
||||
// whose turn it is.
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
displayDebug("doTurn(): Hmm, this is a very strange actor: " + currentActor);
|
||||
}
|
||||
}
|
||||
} while (numPlayers > 0); // we can safely repeat if we have players, since we'll return (and break out of
|
||||
// the loop) once we hit the player
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Go through the map and collect all the actors.
|
||||
*/
|
||||
private void beginTurn() {
|
||||
numPlayers = 0;
|
||||
// this extra fancy iteration over each map location runs *in parallel* on
|
||||
// multicore systems!
|
||||
// that makes some things more tricky, hence the "synchronized" block and
|
||||
// "Collections.synchronizedList()" in the initialization of "actors".
|
||||
// NOTE: If you want to modify this yourself, it might be a good idea to replace
|
||||
// "parallelStream()" by "stream()", because weird things can happen when many
|
||||
// things happen
|
||||
// at the same time! (or do INF214 or DAT103 to learn about locks and threading)
|
||||
map.getArea().parallelStream().forEach((loc) -> { // will do this for each location in map
|
||||
List<IItem> list = map.getAllModifiable(loc); // all items at loc
|
||||
Iterator<IItem> li = list.iterator(); // manual iterator lets us remove() items
|
||||
while (li.hasNext()) { // this is what "for(IItem item : list)" looks like on the inside
|
||||
IItem item = li.next();
|
||||
if (item.getCurrentHealth() < 0) {
|
||||
// normally, we expect these things to be removed when they are destroyed, so
|
||||
// this shouldn't happen
|
||||
synchronized (this) {
|
||||
formatDebug("beginTurn(): found and removed leftover destroyed item %s '%s' at %s%n",
|
||||
item.getName(), item.getSymbol(), loc);
|
||||
}
|
||||
li.remove();
|
||||
map.remove(loc, item); // need to do this too, to update item map
|
||||
} else if (item instanceof IPlayer) {
|
||||
actors.add(0, (IActor) item); // we let the human player go first
|
||||
synchronized (this) {
|
||||
numPlayers++;
|
||||
}
|
||||
} else if (item instanceof IActor) {
|
||||
actors.add((IActor) item); // add other actors to the end of the list
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canGo(GridDirection dir) {
|
||||
return map.canGo(currentLocation, dir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItem createItem(String sym) {
|
||||
switch (sym) {
|
||||
case "#":
|
||||
return new Wall();
|
||||
case ".":
|
||||
// TODO: add Dust
|
||||
return null;
|
||||
case "R":
|
||||
return new Rabbit();
|
||||
case "C":
|
||||
return new Carrot();
|
||||
case "@":
|
||||
// TODO: add Player
|
||||
case " ":
|
||||
return null;
|
||||
default:
|
||||
// alternative/advanced method
|
||||
Supplier<IItem> factory = itemFactories.get(sym);
|
||||
if (factory != null) {
|
||||
return factory.get();
|
||||
} else {
|
||||
System.err.println("createItem: Don't know how to create a '" + sym + "'");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayDebug(String s) {
|
||||
printer.clearLine(Main.LINE_DEBUG);
|
||||
printer.printAt(1, Main.LINE_DEBUG, s, Color.DARKRED);
|
||||
System.err.println(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayMessage(String s) {
|
||||
// it should be safe to print to lines Main.LINE_MSG1, Main.LINE_MSG2,
|
||||
// Main.LINE_MSG3
|
||||
// TODO: you can save the last three lines, and display/scroll them
|
||||
printer.clearLine(Main.LINE_MSG1);
|
||||
printer.printAt(1, Main.LINE_MSG1, s);
|
||||
System.out.println("Message: «" + s + "»");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayStatus(String s) {
|
||||
printer.clearLine(Main.LINE_STATUS);
|
||||
printer.printAt(1, Main.LINE_STATUS, s);
|
||||
System.out.println("Status: «" + s + "»");
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
map.draw(painter, printer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drop(IItem item) {
|
||||
if (item != null) {
|
||||
map.add(currentLocation, item);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void formatDebug(String s, Object... args) {
|
||||
displayDebug(String.format(s, args));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void formatMessage(String s, Object... args) {
|
||||
displayMessage(String.format(s, args));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void formatStatus(String s, Object... args) {
|
||||
displayStatus(String.format(s, args));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return map.getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IItem> getLocalItems() {
|
||||
return map.getItems(currentLocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ILocation getLocation() {
|
||||
return currentLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ILocation getLocation(GridDirection dir) {
|
||||
if (currentLocation.canGo(dir))
|
||||
return currentLocation.go(dir);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the game map. {@link IGameMap} gives us a few more details than
|
||||
* {@link IMapView} (write access to item lists); the game needs this but
|
||||
* individual items don't.
|
||||
*/
|
||||
@Override
|
||||
public IMapView getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GridDirection> getPossibleMoves() {
|
||||
// TODO
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ILocation> getVisible() {
|
||||
// TODO: maybe replace 3 by some sort of visibility range obtained from
|
||||
// currentActor?
|
||||
return map.getNeighbourhood(currentLocation, 3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return map.getWidth();
|
||||
}
|
||||
|
||||
public void keyPressed(KeyCode code) {
|
||||
// only an IPlayer/human can handle keypresses, and only if it's the human's
|
||||
// turn
|
||||
if (currentActor instanceof IPlayer) {
|
||||
((IPlayer) currentActor).keyPressed(this, code); // do your thing
|
||||
if (movePoints <= 0)
|
||||
doTurn(); // proceed with turn if we're out of moves
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ILocation move(GridDirection dir) {
|
||||
if (movePoints < 1)
|
||||
throw new IllegalMoveException("You're out of moves!");
|
||||
ILocation newLoc = map.go(currentLocation, dir);
|
||||
map.remove(currentLocation, currentActor);
|
||||
map.add(newLoc, currentActor);
|
||||
currentLocation = newLoc;
|
||||
movePoints--;
|
||||
return currentLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItem pickUp(IItem item) {
|
||||
if (item != null && map.has(currentLocation, item)) {
|
||||
// TODO: bruk getAttack()/getDefence() til å avgjøre om man får til å plukke opp
|
||||
// tingen
|
||||
// evt.: en IActor kan bare plukkes opp hvis den har få/ingen helsepoeng igjen
|
||||
map.remove(currentLocation, item);
|
||||
return item;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ILocation rangedAttack(GridDirection dir, IItem target) {
|
||||
return currentLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITurtle getPainter() {
|
||||
return painter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Printer getPrinter() {
|
||||
return printer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getFreeTextAreaBounds() {
|
||||
int[] area = new int[4];
|
||||
area[0] = getWidth() + 1;
|
||||
area[1] = 1;
|
||||
area[2] = printer.getLineWidth();
|
||||
area[3] = printer.getPageHeight() - 5;
|
||||
return area;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearFreeTextArea() {
|
||||
printer.clearRegion(getWidth() + 1, 1, printer.getLineWidth() - getWidth(), printer.getPageHeight() - 5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearFreeGraphicsArea() {
|
||||
painter.as(GraphicsContext.class).clearRect(getWidth() * printer.getCharWidth(), 0,
|
||||
painter.getWidth() - getWidth() * printer.getCharWidth(),
|
||||
(printer.getPageHeight() - 5) * printer.getCharHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] getFreeGraphicsAreaBounds() {
|
||||
double[] area = new double[4];
|
||||
area[0] = getWidth() * printer.getCharWidth();
|
||||
area[1] = 0;
|
||||
area[2] = painter.getWidth();
|
||||
area[3] = getHeight() * printer.getCharHeight();
|
||||
return area;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IActor getActor() {
|
||||
return currentActor;
|
||||
}
|
||||
|
||||
public ILocation setCurrent(IActor actor) {
|
||||
currentLocation = map.getLocation(actor);
|
||||
if (currentLocation != null) {
|
||||
currentActor = actor;
|
||||
movePoints = 1;
|
||||
}
|
||||
return currentLocation;
|
||||
}
|
||||
|
||||
public IActor setCurrent(ILocation loc) {
|
||||
List<IActor> list = map.getActors(loc);
|
||||
if (!list.isEmpty()) {
|
||||
currentActor = list.get(0);
|
||||
currentLocation = loc;
|
||||
movePoints = 1;
|
||||
}
|
||||
return currentActor;
|
||||
}
|
||||
|
||||
public IActor setCurrent(int x, int y) {
|
||||
return setCurrent(map.getLocation(x, y));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Random getRandom() {
|
||||
return random;
|
||||
}
|
||||
}
|
@@ -1,23 +1,235 @@
|
||||
package inf101.v18.rogue101.game;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import inf101.v18.gfx.gfxmode.ITurtle;
|
||||
import inf101.v18.gfx.textmode.Printer;
|
||||
import inf101.v18.grid.GridDirection;
|
||||
import inf101.v18.grid.ILocation;
|
||||
import inf101.v18.rogue101.map.IMapView;
|
||||
import inf101.v18.rogue101.objects.IItem;
|
||||
import inf101.v18.rogue101.objects.IActor;
|
||||
import inf101.v18.rogue101.objects.INonPlayer;
|
||||
import inf101.v18.rogue101.objects.IPlayer;
|
||||
|
||||
/**
|
||||
* Game interface
|
||||
* <p>
|
||||
* The game has a map and a current {@link IActor} (the player or non-player
|
||||
* whose turn it currently is). The game also knows the current location of the
|
||||
* actor. Most methods that deal with the map will use this current location –
|
||||
* they are meant to be used by the current actor for exploring or interacting
|
||||
* with its surroundings.
|
||||
* <p>
|
||||
* In other words, you should avoid calling most of these methods if you're not
|
||||
* the current actor. You know you're the current actor when you're inside your
|
||||
* {@link IPlayer#keyPressed()} or {@link INonPlayer#doTurn()} method.
|
||||
*
|
||||
* @author anya
|
||||
*
|
||||
*/
|
||||
public interface IGame {
|
||||
IMapView getMap();
|
||||
/**
|
||||
* Add an item to the current location
|
||||
* <p>
|
||||
* If the item is an actor, it won't move until the next turn.
|
||||
*
|
||||
* @param item
|
||||
*/
|
||||
void addItem(IItem item);
|
||||
|
||||
ILocation move(GridDirection dir);
|
||||
/**
|
||||
* Add a new item (identified by symbol) to the current location
|
||||
* <p>
|
||||
* If the item is an actor, it won't move until the next turn.
|
||||
*
|
||||
* @param sym
|
||||
*/
|
||||
void addItem(String sym);
|
||||
|
||||
/**
|
||||
* Perform an attack on the target.
|
||||
* <p>
|
||||
* Will use your {@link IActor#getAttack()} against the target's
|
||||
* {@link IItem#getDefence()}, and then possiblyu find the damage you're dealing
|
||||
* with {@link IActor#getDamage()} and inform the target using
|
||||
* {@link IItem#handleDamage(IGame, IItem, int)}
|
||||
*
|
||||
* @param dir
|
||||
* Direction
|
||||
* @param target
|
||||
* A target item, which should be in the neighbouring square in the
|
||||
* given direction
|
||||
* @return Your new location if the attack resulted in you moving
|
||||
*/
|
||||
ILocation attack(GridDirection dir, IItem target);
|
||||
|
||||
ILocation rangedAttack(GridDirection dir, IItem target);
|
||||
/**
|
||||
* @param dir
|
||||
* @return True if it's possible to move in the given direction
|
||||
*/
|
||||
boolean canGo(GridDirection dir);
|
||||
|
||||
Collection<IItem> getLocalItems();
|
||||
/**
|
||||
* Create a new item based on a text symbol
|
||||
* <p>
|
||||
* The item won't be added to the map unless you call {@link #addItem(IItem)}.
|
||||
*
|
||||
* @param symbol
|
||||
* @return The new item
|
||||
*/
|
||||
IItem createItem(String symbol);
|
||||
|
||||
/**
|
||||
* Displays a message in the debug area on the screen (bottom line)
|
||||
*
|
||||
* @param s
|
||||
* A message
|
||||
*/
|
||||
void displayDebug(String s);
|
||||
|
||||
/**
|
||||
* Displays a message in the message area on the screen (below the map and the
|
||||
* status line)
|
||||
*
|
||||
* @param s
|
||||
* A message
|
||||
*/
|
||||
void displayMessage(String s);
|
||||
|
||||
/**
|
||||
* Displays a status message in the status area on the screen (right below the
|
||||
* map)
|
||||
*
|
||||
* @param s
|
||||
* A message
|
||||
*/
|
||||
void displayStatus(String s);
|
||||
|
||||
/**
|
||||
* Displays a message in the message area on the screen (below the map and the
|
||||
* status line)
|
||||
*
|
||||
* @param s
|
||||
* A message
|
||||
* @see String#format(String, Object...)
|
||||
*/
|
||||
void formatDebug(String s, Object... args);
|
||||
|
||||
/**
|
||||
* Displays a formatted message in the message area on the screen (below the map
|
||||
* and the status line)
|
||||
*
|
||||
* @param s
|
||||
* A message
|
||||
* @see String#format(String, Object...)
|
||||
*/
|
||||
void formatMessage(String s, Object... args);
|
||||
|
||||
/**
|
||||
* Displays a formatted status message in the status area on the screen (right
|
||||
* below the map)
|
||||
*
|
||||
* @param s
|
||||
* A message
|
||||
* @see String#format(String, Object...)
|
||||
*/
|
||||
void formatStatus(String s, Object... args);
|
||||
|
||||
/**
|
||||
* Pick up an item
|
||||
* <p>
|
||||
* This should be used by IActors who want to pick up an item and carry it. The
|
||||
* item will be returned if picking it succeeded (the actor <em>might</em> also
|
||||
* make a mistake and pick up the wrong item!).
|
||||
*
|
||||
* @param item
|
||||
* An item, should be in the current map location
|
||||
* @return The item that was picked up (normally <code>item</code>), or
|
||||
* <code>null</code> if it failed
|
||||
*/
|
||||
IItem pickUp(IItem item);
|
||||
|
||||
/**
|
||||
* Drop an item
|
||||
* <p>
|
||||
* This should be used by IActors who are carrying an item and want to put it on
|
||||
* the ground. Check the return value to see if it succeeded.
|
||||
*
|
||||
* @param item
|
||||
* An item, should be carried by the current actor and not already be
|
||||
* on the map
|
||||
* @return True if the item was placed on the map, false means you're still
|
||||
* holding it
|
||||
*/
|
||||
boolean drop(IItem item);
|
||||
|
||||
/**
|
||||
* Clear the unused graphics area (you can fill it with whatever you want!)
|
||||
*/
|
||||
void clearFreeGraphicsArea();
|
||||
|
||||
/**
|
||||
* Clear the unused text area (you can fill it with whatever you want!)
|
||||
*/
|
||||
void clearFreeTextArea();
|
||||
|
||||
/**
|
||||
* Get the bounds of the free graphics area.
|
||||
* <p>
|
||||
* You can fill this with whatever you want, using {@link #getPainter()} and
|
||||
* {@link #clearFreeGraphicsArea()}.
|
||||
*
|
||||
* @return Array of coordinates; ([0],[1]) are the top-left corner, and
|
||||
* ([2],[3]) are the bottom-right corner (exclusive).
|
||||
*/
|
||||
double[] getFreeGraphicsAreaBounds();
|
||||
|
||||
/**
|
||||
* Get the bounds of the free texxt area.
|
||||
* <p>
|
||||
* You can fill this with whatever you want, using {@link #getPrinter()} and
|
||||
* {@link #clearFreeTextArea()}.
|
||||
* <p>
|
||||
* You'll probably want to use something like:
|
||||
*
|
||||
* <pre>
|
||||
* int[] bounds = getFreeTextArea();
|
||||
* int x = bounds[0];
|
||||
* int y = bounds[1];
|
||||
* game.getPrinter().printAt(x, y++, "Hello");
|
||||
* game.getPrinter().printAt(x, y++, "Do you have any carrot cake?", Color.ORANGE);
|
||||
* </pre>
|
||||
*
|
||||
* @return Array of column/line numbers; ([0],[1]) is the top-left corner, and
|
||||
* ([2],[3]) is the bottom-right corner (inclusive).
|
||||
*/
|
||||
int[] getFreeTextAreaBounds();
|
||||
|
||||
/**
|
||||
* See {@link #getFreeGraphicsAreaBounds()}, {@link #clearFreeGraphicsArea()}.
|
||||
*
|
||||
* @return A Turtle, for painting graphics
|
||||
*/
|
||||
ITurtle getPainter();
|
||||
|
||||
/**
|
||||
* See {@link #getFreeTextAreaBounds()}, {@link #clearFreeTextArea()}.
|
||||
*
|
||||
* @return A printer, for printing text
|
||||
*/
|
||||
Printer getPrinter();
|
||||
|
||||
/**
|
||||
* @return The height of the map
|
||||
*/
|
||||
int getHeight();
|
||||
|
||||
/**
|
||||
* @return A list of the non-actor items at the current map location
|
||||
*/
|
||||
List<IItem> getLocalItems();
|
||||
|
||||
/**
|
||||
* Get the current actor's location.
|
||||
@@ -27,22 +239,38 @@ public interface IGame {
|
||||
* @return Location of the current actor
|
||||
*/
|
||||
ILocation getLocation();
|
||||
|
||||
|
||||
/**
|
||||
* Get the current actor
|
||||
* <p>
|
||||
* You can check if it's your move by doing game.getActor()==this.
|
||||
*
|
||||
* @return The current actor (i.e., the (IPlayer/INonPlayer) player who's turn it currently is)
|
||||
*/
|
||||
IActor getActor();
|
||||
|
||||
/**
|
||||
* Get the neighbouring map location in direction <code>dir</code>
|
||||
* <p>
|
||||
* Same as <code>getLocation().go(dir)</code>
|
||||
*
|
||||
* @param dir A direction
|
||||
* @return A location, or <code>null</code> if the location would be outside the map
|
||||
* @param dir
|
||||
* A direction
|
||||
* @return A location, or <code>null</code> if the location would be outside the
|
||||
* map
|
||||
*/
|
||||
ILocation getLocation(GridDirection dir);
|
||||
|
||||
IItem pickUp(IItem item);
|
||||
/**
|
||||
* @return The map
|
||||
*/
|
||||
IMapView getMap();
|
||||
|
||||
boolean drop(IItem item);
|
||||
|
||||
boolean canGo(GridDirection dir);
|
||||
/**
|
||||
* @return A list of directions we can move in, for use with
|
||||
* {@link #move(GridDirection)}
|
||||
*/
|
||||
List<GridDirection> getPossibleMoves();
|
||||
|
||||
/**
|
||||
* Get a list of all locations that are visible from the current location.
|
||||
@@ -54,26 +282,39 @@ public interface IGame {
|
||||
* @return A list of grid cells visible from the {@link #getLocation()}
|
||||
*/
|
||||
List<ILocation> getVisible();
|
||||
|
||||
|
||||
/**
|
||||
* @return Width of the map
|
||||
*/
|
||||
int getWidth();
|
||||
|
||||
int getHeight();
|
||||
|
||||
IItem createItem(String symbol);
|
||||
/**
|
||||
* Move the current actor in the given direction.
|
||||
* <p>
|
||||
* The new location will be returned.
|
||||
*
|
||||
* @param dir
|
||||
* @return A new location
|
||||
* @throws IllegalMoveException
|
||||
* if moving in that direction is illegal
|
||||
*/
|
||||
ILocation move(GridDirection dir);
|
||||
|
||||
void addItem(IItem item);
|
||||
/**
|
||||
* Perform a ranged attack on the target.
|
||||
* <p>
|
||||
* Rules for this are up to you!
|
||||
*
|
||||
* @param dir
|
||||
* Direction
|
||||
* @param target
|
||||
* A target item, which should in some square in the given direction
|
||||
* @return Your new location if the attack resulted in you moving (unlikely)
|
||||
*/
|
||||
ILocation rangedAttack(GridDirection dir, IItem target);
|
||||
|
||||
void addItem(String sym);
|
||||
|
||||
void displayMessage(String s);
|
||||
|
||||
void formatMessage(String s, Object... args);
|
||||
|
||||
void displayStatus(String s);
|
||||
|
||||
void formatStatus(String s, Object...args);
|
||||
|
||||
void displayDebug(String s);
|
||||
|
||||
void formatDebug(String s, Object... args);
|
||||
/**
|
||||
* @return A random generator
|
||||
*/
|
||||
Random getRandom();
|
||||
}
|
||||
|
Reference in New Issue
Block a user