Problem with maze solving backtracking algorithm with setting visited rooms - java

i seek if somebody could help me out with my room searching algorithm
I'm trying to implement a backtracking algorhitm for maze solving. I'm stuck in the place where i should memorize the rooms which i have already visited.
The maze is made up from rooms and each room has 4 sides - north, east, south and west. Each room is linked to next room by making a door to desired side, i.e room1.createNorth(roomName) which creates a new room up north and a new room has southern door to link back to the first as you can see in my Room class.
Here is my chopped room class, which represents each room in a maze. I removed south, west and east directions which are identical to my methods which deal with northern side.
public class Room {
private String name;
private Room north;
private Room east;
private Room west;
private Room south;
private boolean isExit = false;
private Maze maze;
/**
* #return name room
*/
public String getName() {
return this.name;
}
/**
* Sets room name
*
* #param name
*/
public void setName(String name) {
this.name = name;
}
/**
* Gets northern room if any
*
* #return pointer to northern room if any, otherwise <code>null</code>
*/
public Room getNorth() {
return this.north;
}
/**
* Sets the door to the next room to the north in that room and in the other
* room sets southern door as connecting back to that room
*
* #param otherRoom
*/
public void setNorth(Room otherRoom) {
this.north = otherRoom;
otherRoom.south = this;
}
/**
* creates a new room to the north and connects back to this room
*
* #param name
* of the room
* #return created room
*/
public Room createNorth(String name) {
Room otherRoom = null;
// create new room in that direction ONLY if there is no room yet
if (this.getNorth() == null) { // get northern direction, if it's null,
// then it's okay to create there
otherRoom = new Room(); // create!
this.setNorth(otherRoom); // set the door
otherRoom.setName(name); // set the name
} else { // there is a room in that direction, so don't create a new
// room and drop a warning
System.out.println("There is already a room in northern direction");
}
return otherRoom;
}
/**
* Asdf
*
* #return maze
*/
public Maze getMaze() {
return this.maze;
}
/**
* Set maze
*
* #param maze
*/
public void setMaze(Maze maze) {
this.maze = maze;
}
/**
* #param roomName path to this room must be found
*/
public void findPathTo(String roomName) {
Room soughtRoom = this.getMaze().getEntry();
while (!(soughtRoom.getName().equalsIgnoreCase(roomName))) {
// here should be also a method such as setRoomAsVisited()
if (this.getWest() != null) {
soughtRoom = this.getWest();
this.getMaze().getPaths().push(soughtRoom);
}
else if (this.getNorth() != null) {
soughtRoom = this.getNorth();
this.getMaze().getPaths().push(soughtRoom);
}
else if (this.getEast() != null) {
soughtRoom = this.getEast();
this.getMaze().getPaths().push(soughtRoom);
}
else if (this.getSouth() != null) {
soughtRoom = this.getSouth();
this.getMaze().getPaths().push(soughtRoom);
}
else {
if (this.getMaze().getPaths().isEmpty()) {
break; // no more path for backtracking, exit (no solution found)
}
// dead end, go back!
soughtRoom = this.getMaze().getPaths().pop();
}
System.out.println(this.getMaze().getPaths().toString());
}
}
#Override
public String toString() {
return "Room name is " + this.getName();
}
}
Maze looks like this: http://i.stack.imgur.com/2KePs.jpg where S is the start point
My Maze class
public class Maze {
Room room;
/**
* helper collection path stack for findPathTo() method
*/
private Stack<Room> paths = new Stack<Room>();
/**
* #return path for exit
*/
public Stack<Room> getPaths() {
return this.paths;
}
/**
* Singleton method for first room in the maze which is entry room
*
* #return room if no room is created then creates new, otherwise returns
* already created room
*/
public Room getEntry() {
if (this.room == null) {
this.room = new Room();
return this.room;
}
return this.room;
}
}
Here is my main class
public class Main {
public static void main(String[] args) {
Maze maze = new Maze();
maze.getEntry().setName("A4"); // set first room's name A4
// labyrinth creation
maze.getEntry().createEast("B4").createNorth("B3").createWest("A3");
maze.getEntry().getEast().getNorth().createNorth("B2").createWest("A2")
.createNorth("A1");
maze.getEntry().getEast().getNorth().getNorth().createNorth("B1");
maze.getEntry().getEast().getNorth().getNorth().createEast("C2")
.createNorth("C1").createEast("D1");
maze.getEntry().getEast().createEast("C4").createEast("D4");
maze.getEntry().getEast().getEast().createNorth("C3").createEast("D3")
.createNorth("D2").setExit(true);
System.out.println("=====Test findPathTo method======");
maze.getEntry().setMaze(maze); // set maze instance to our entrance room
maze.getEntry().findPathTo("B4");
System.out.println("=====End of testing findPathTo method======");
}
}
The problem is in my findPathTo(roomName) method, which finds the route to the room.
If i enter the room D4 then my algorithm moves only once to east to "B4" room from "A4" and there it just loops infinitely and the stack just grows with room "B4" only. Why doesn't it move ahead for example to next room "B3" or "C4" ?
EDIT: here is the working code
public void findPathTo(String roomName) {
Room soughtRoom = this.getMaze().getEntry();
while (!(soughtRoom.getName().equalsIgnoreCase(roomName))) {
if (soughtRoom.getWest() != null && soughtRoom.getWest().isVisited != true) {
this.getMaze().getPaths().push(soughtRoom);
soughtRoom = soughtRoom.getWest();
soughtRoom.isVisited = true;
}
else if (soughtRoom.getNorth() != null && soughtRoom.getNorth().isVisited != true) {
this.getMaze().getPaths().push(soughtRoom);
soughtRoom = soughtRoom.getNorth();
soughtRoom.isVisited = true;
}
else if (soughtRoom.getEast() != null && soughtRoom.getEast().isVisited != true) {
this.getMaze().getPaths().push(soughtRoom);
soughtRoom = soughtRoom.getEast();
soughtRoom.isVisited = true;
}
else if (soughtRoom.getSouth() != null && soughtRoom.getSouth().isVisited != true) {
this.getMaze().getPaths().push(soughtRoom);
soughtRoom = soughtRoom.getSouth();
soughtRoom.isVisited = true;
}
else {
if (this.getMaze().getPaths().isEmpty()) {
System.out.println("No solutions found :(");
break; // no more path for backtracking, exit (no solution found)
}
// dead end, go back!
soughtRoom = this.getMaze().getPaths().pop();
}
System.out.println("Path rooms: " + this.getMaze().getPaths().toString());
}
}

There are several ways of doing this.
One would be to keep a "isVisited" boolean flag in each room object that you set/unset as your tracking and backtracking proceeds. This means taht you can only single-thread-search your maze (this may or may not matter).
Another would be to keep a list of visited rooms that you compare to (advantage here is that it should be relatively easy to just "push" a new room onto the list and have it popped automatically if you use the call-stack to pass this list).
You could also use a per-search hashtable of room to an isVisible, this allows for (possibly) faster lookups than searching a list, allows for multi-threading (as in "more than one thread can search the maze", not "more than one thread can participate in the same search").
There's also probably a few things I haven't thought of, but all three of these should be pretty straight-forward to implement.

A quick and highly unoptimized approach:
For each visited room, store the possible directions (make an enum Direction and a Set<Direction> for example) and remove the one you came from as well as the direction you took from the previous room. Thus, moving from A4 to B4 you'd remove EAST from A4 and WEST from B4. If you have to track back, just unwind the stack until you find a room with an unvisited direction (the list of possible directions is not empty) and try the next one. If the stack becomes empty at this point, you tried all possibilities without finding the target room.
As I said this is highly unoptimized, but it should work.

Some comments:
Your code is missing some functions you are using. There is no getPaths() method in your maze class. If you post code online, try to make sure it is easily compilable and testable. In your case I would have to guess, that getPaths() returns some kind of stack on which you try to store possible paths to be explored, but there is no way to be sure, what it actually does.
Also try to simplify the code before posting. Your maze is rather complicated and one would have to draw it, to see if your constructed maze matches the one on the picture. Try if you can reproduce the problem with a much simpler maze (2 or 3 rooms maybe). Also simplifying will often give you many hints as to where the problem might be. While you are simplifying there will be a point at which the problem will suddenly disappear. This tells you a lot about the actual bug.
Some Ideas on what might be wrong with your Code:
At each direction you set soughtRoom to the one in that direction. I am assuming soughtRoom is the room your search is currently at. Then you push that room on the stack. However for a backtracking you need to store at each branch all the information that brings you back to a previous state. If you first set the current room and then push it, the information from the previous state is lost. Try it the other way round and see what happens.

Related

How should I make my getMove() method interact with my GUI in my chess application?

I'm developing an application in Java to help me land my first job as a junior developer. It's a chess game with a GUI that both human players click on from the same machine.
When it's, say, white's turn to move, the application calls white's getMove(Interface interaction) method until a valid MoveAttempt is returned. Here's the getMove(Interface interaction) method of HumanPlayer:
public MoveAttempt getMove(Interface interaction) {
while(!interaction.selectionMade()) {
}
byte pieceFile = interaction.getPenultimateFile();
byte pieceRank = interaction.getPenultimateRank();
byte toFile = interaction.getUltimateFile();
byte toRank = interaction.getUltimateRank();
return new MoveAttempt(pieceFile, pieceRank, toFile, toRank, getIsWhite());
}
penultimateFile, penultimateRank, ultimateFile and ultimateRank are supposed to store the file (column) and rank (row) of the last two chess tiles clicked. This is achieved through this actionPerformed(ActionEvent event) which Interface has because it implements ActionListener
public void actionPerformed(ActionEvent event) {
LocalizedButton button = (LocalizedButton) event.getSource();
if(penultimateFile == -1) {
penultimateFile = button.getFile();
penultimateRank = button.getRank();
}
else {
ultimateFile = button.getFile();
ultimateRank = button.getRank();
}
}
and by calling this method before each call to getMove(Interface interaction)
public void resetClicks() {
penultimateFile = -1;
penultimateRank = -1;
ultimateFile = -1;
ultimateRank = -1;
}
So the idea is that a move attempt is not made until someone has clicked on two chess squares which is why I have a while loop indefinitely calling selectionMade():
public boolean selectionMade() {
return penultimateFile != -1 && penultimateRank != -1 && ultimateFile != -1 && ultimateRank != -1;
}
This didn't work---pieces didn't move---so in an attempt to see what was happening I put this print statement
System.out.println(interaction.getPenultimateFile() + ", " +
interaction.getPenultimateRank() + ", " +
interaction.getUltimateFile() + ", " +
interaction.getUltimateRank());
into the while loop to see what was going on and now it works---pieces move---except I may have encountered times in which it didn't work but I last I tried I couldn't get it to fail.
I don't want to print anything to the console; what should I do in lieu of having this while loop?
Edit: Putting boolean lol = 0 just above the loop and lol = !lol in the loop doesn't allow the code to work. Neither does calling doNothing().
Edit: Here's the source code: https://github.com/JosephBGriffith/Chess
Right now only the pawns work because I have other bugs that I need to fix. En passant works except the opponent piece doesn't get eliminated.
I would invert the control, so that the UI pushes moves to the game, rather than the game trying to pull moves from the UI.
So your game class might have:
class Game {
boolean move(int fromFile, int fromRank, int toFile, int toRank) { ... }
...
}
If the move wasn't legal (e.g. if it was the other player's turn) then move returns false and the move doesn't occur. That is, the internal state of the Game is unchanged.
And your actionPerformed method becomes:
public void actionPerformed(ActionEvent event) {
LocalizedButton button = (LocalizedButton) event.getSource();
if(penultimateFile == -1) {
penultimateFile = button.getFile();
penultimateRank = button.getRank();
}
else {
game.move(penultimateFile, penultimateRank, button.getFile(), button.getRank());
penultimateFile = -1;
}
}
You could use the return value of move to provide some feedback to the user if the move is illegal.
Something to note about this suggestion is that move is executed on the Swing event thread. In theory this is bad practice, although unless your move method is very slow it won't matter.
Read https://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html and consider whether you want to use invokeLater.

Breadth-First-Search for moving dot game

Hi I having been trying to program an algorithm using breadth-first-search that finds the shortest path for the blue dot to exit in the game. I am new to java and having trouble running/understanding the algorithm for the class. I have a class called gameModel which stores the statuses of each dot. The algoirthm is meant to test the fastest way the blue dot can exit the board without going through an orange dot (SELECTED) and if no way out than the player wins. I keep running the program and getting compile errors which i dont know how to fix. I included the controller class where the short dot was ran.
import java.util.Random;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.*;
/**
* The class <b>GameController</b> is the controller of the game. It implements
* the interface ActionListener to be called back when the player makes a move. It computes
* the next step of the game, and then updates model and view.
*/
public class GameController implements ActionListener {
private int size;
private GameModel gameModel;
private GameView gameView;
private boolean click;
/**
* Constructor used for initializing the controller. It creates the game's view
* and the game's model instances
*
* #param size
* the size of the board on which the game will be played
*/
public GameController(int size) {
this.size = size;
this.gameModel = new GameModel(size);
this.gameView = new GameView (gameModel, this);
click = false;
}
/**
* Starts the game
*/
public void start(){
if (click){
List start = new List {gameModel.getCurrentDot().getX(), gameModel.getCurrentDot().getY()};
List<int> targets = new ArrayList<>();
List<int> blocked = nwq ArrayList<>();
for (int i = 0; i < size; i++){
targets.add(i, 0);
targets.add(i, size);
targets.add(1, size);
targets.add(1, 0);
}
for (int i = 0; i < size; i++){
for (int j = 0; j < size; j++)
if(gameModel.getstatus(i, j) == SELECTED){
blocked.add(i, j);
}
String path = Breadth-First-Start(start, targets, blocked);
gameView = new GameView(gameModel, this);
gameView.getBoardView().update();
}
}
public Breadth-First-Start(start, targets, blocked){ // Need help with
Queue queue = new LinkedList();
queue.add(start + "");
while(!queue.isEmpty()){
String p = queue.remove();
if (p != blocked){ //If p is not in blocked paths
if (p == targets){ //If p is in targets
return "q + {p}";
} else {
queue.add("q + {p}");
blocked.add(p);
}
}
}
You method public Breadth-First-Start(start, targets, blocked) is declared wrong. You cant have - in method name, also you need to specify the return type (only constructors dont have a return type to be defined). Also you need to specify parameter types. From what I understand targets and start look like of type String and blocked looks like a List, please try replace the method head by the following public void breadthFirstSearch(String start, String targets, List blocked) not sure what return type you want as you dont have any returns in the method. But in your case you probably want the path so maybe of type List, or a boolean to know if there is a path or not.
What you're wanting to do has to do with graph theory. If two nodes are connected, an edge between them is created. In this case the orange dots would not be connected to anything as a path cannot exist through them. Dijkstra's algorithm is very useful for doing what you want, although it's breadth first instead of depth first. I'd recommend starting there, I'm sure there are examples of that algorithm being implemented in java.
The edges of the graph have weights which are compared in order to find the shortest path between two nodes.
I see that your blocked list declaration has nwq in it instead of new. That may be your issue right there.
Hope this helps

Beginner: Adding a Teleport Room to World Of Zuul

I have a compsci lab in which we must complete the text adventure game "World of Zuul". To do this we had to complete several steps such as creating more rooms, creating an items class, and adding items to rooms. The final step is to add a Teleport room to the game. Here is the text from the project sheet:
Implement a “teleport room” that has an entrance but no exit. The
short description is “in a room with blank walls and no obvious exit”.
When you perform the look command in the teleport room, there is a 75%
chance that you will just stay in the teleport room and see the
description above. There is a 25% chance that you will teleport
randomly into one of the other N rooms and then you will see a
description of that room. You will need to think about re-organizing
the relationship between the Room class and the Game class to make
this happen.
I can't figure out how to do this. Any help is much appreciated.
Room Class:
import java.util.Set;
import java.util.HashMap;
import java.util.HashSet;
/**
* Class Room - a room in an adventure game.
*
* This class is part of the "World of Zuul" application.
* "World of Zuul" is a very simple, text based adventure game.
*
* A "Room" represents one location in the scenery of the game. It is
* connected to other rooms via exits. For each existing exit, the room
* stores a reference to the neighboring room.
*
* #author Michael Kölling and David J. Barnes
* #version 2011.08.08
*/
public class Room
{
private String description;
private HashMap<String, Room> exits; // stores exits of this room.
private HashSet<Item> items;
/**
* Create a room described "description". Initially, it has
* no exits. "description" is something like "a kitchen" or
* "an open court yard".
* #param description The room's description.
*/
public Room(String description)
{
this.description = description;
exits = new HashMap<String, Room>();
items = new HashSet<Item>();
}
/**
* Define an exit from this room.
* #param direction The direction of the exit.
* #param neighbor The room to which the exit leads.
*/
public void setExit(String direction, Room neighbor)
{
exits.put(direction, neighbor);
}
/**
* Add items into a room
* #param item The item which will be added to the room
*/
public void addItem(Item item)
{
items.add(item);
}
/**
* #return The short description of the room
* (the one that was defined in the constructor).
*/
public String getShortDescription()
{
return description;
}
/**
* Return a description of the room in the form:
* You are in the kitchen.
* Exits: north west
* #return A long description of this room
*/
public String getLongDescription()
{
return "You are " + description + ".\n" + getExitString() + "\n" + getItemString();
}
/**
* Return a string describing the room's exits, for example
* "Exits: north west".
* #return Details of the room's exits.
*/
private String getExitString()
{
String returnString = "Exits:";
Set<String> keys = exits.keySet();
for(String exit : keys) {
returnString += " " + exit;
}
return returnString;
}
/**
* Return a string describing the room's items and descriptions, for example
* "Items: Book, (insert description here".
* #return Details of the room's items.
*/
private String getItemString()
{
String itemString = "items: ";
if(items.size() < 1) {
itemString = itemString += "There are no items here.";
}
else {
for(Item item : items) {
itemString+= item.getName() + "; " + item.getDescription() + ". ";
}
}
return itemString;
}
/**
* Return the room that is reached if we go from this room in direction
* "direction". If there is no room in that direction, return null.
* #param direction The exit's direction.
* #return The room in the given direction.
*/
public Room getExit(String direction)
{
return exits.get(direction);
}
}
Game Class:
public class Game
{
private Parser parser;
private Room currentRoom;
/*
* Create the game and initialise its internal map.
*/
public Game()
{
createRooms();
parser = new Parser();
}
/**
* Create all the rooms and link their exits together.
*/
private void createRooms()
{
Room outside, theater, pub, lab, office, labyrinth, teleport_room;
Item book, stick, knife, spoon;
// create the rooms
outside = new Room("outside the main entrance of the university");
theater = new Room("in a lecture theater");
pub = new Room("in the campus pub");
lab = new Room("in a computing lab");
office = new Room("in the computing admin office");
labyrinth = new Room("in the University Labyrinth");
teleport_room = new Room("in a room with blank walls and no obvious exit");
//create the items
book = new Item("Book", "A book containing useless information", 5);
stick = new Item("Stick", "A large stick, can be used for protection", 10);
knife = new Item("Knife", "A dull butter knife", 5);
spoon = new Item("Spoon", "A tablespoon, good for consumption of cereal", 5);
// initialise room exits
outside.setExit("east", theater);
outside.setExit("south", lab);
outside.setExit("west", pub);
outside.setExit("north", labyrinth);
theater.setExit("west", outside);
pub.setExit("east", outside);
pub.setExit("west", labyrinth);
lab.setExit("north", outside);
lab.setExit("east", office);
office.setExit("west", lab);
office.setExit("north", teleport_room);
labyrinth.setExit("south", pub);
labyrinth.setExit("east", outside);
//initialize room items
outside.addItem(book);
labyrinth.addItem(stick);
lab.addItem(knife);
office.addItem(spoon);
currentRoom = outside; // start game outside
}
/**
* Main play routine. Loops until end of play.
*/
public void play()
{
printWelcome();
// Enter the main command loop. Here we repeatedly read commands and
// execute them until the game is over.
boolean finished = false;
while (! finished) {
Command command = parser.getCommand();
finished = processCommand(command);
}
System.out.println("Thank you for playing. Good bye.");
}
/**
* Print out the opening message for the player.
*/
private void printWelcome()
{
System.out.println();
System.out.println("Welcome to the World of Zuul!");
System.out.println("World of Zuul is a new, incredibly boring adventure game.");
System.out.println("Type 'help' if you need help.");
System.out.println();
System.out.println(currentRoom.getLongDescription());
}
/**
* Given a command, process (that is: execute) the command.
* #param command The command to be processed.
* #return true If the command ends the game, false otherwise.
*/
private boolean processCommand(Command command)
{
boolean wantToQuit = false;
if(command.isUnknown()) {
System.out.println("I don't know what you mean...");
return false;
}
String commandWord = command.getCommandWord();
if (commandWord.equals("help")) {
printHelp();
}
else if (commandWord.equals("go")) {
goRoom(command);
}
else if (commandWord.equals("look")) {
System.out.println(currentRoom.getLongDescription());
}
else if (commandWord.equals("quit")) {
wantToQuit = quit(command);
}
// else command not recognised.
return wantToQuit;
}
// implementations of user commands:
/**
* Print out some help information.
* Here we print some stupid, cryptic message and a list of the
* command words.
*/
private void printHelp()
{
System.out.println("You are lost. You are alone. You wander");
System.out.println("around at the university.");
System.out.println();
System.out.println("Your command words are:");
parser.showCommands();
}
/**
* Try to in to one direction. If there is an exit, enter the new
* room, otherwise print an error message.
*/
private void goRoom(Command command)
{
if(!command.hasSecondWord()) {
// if there is no second word, we don't know where to go...
System.out.println("Go where?");
return;
}
String direction = command.getSecondWord();
// Try to leave current room.
Room nextRoom = currentRoom.getExit(direction);
if (nextRoom == null) {
System.out.println("There is no door!");
}
else {
currentRoom = nextRoom;
System.out.println(currentRoom.getLongDescription());
}
}
/**
* "Quit" was entered. Check the rest of the command to see
* whether we really quit the game.
* #return true, if this command quits the game, false otherwise.
*/
private boolean quit(Command command)
{
if(command.hasSecondWord()) {
System.out.println("Quit what?");
return false;
}
else {
return true; // signal that we want to quit
}
}
}
You basically have to create a class "TeleporterRoom" that inherits from "Room"
Then you overwrite the method "getExit" in your new Class. This is where you calculate the probability of changing to another room.

extensive symbol/method/variable confusion

I am working on a project that creates a simple text-based adventure game. It's a little complicated, but basically there are about eight rooms in the game, each with a certain item. You can only move in certain directions depending on the room, and the goal is to get to the last room. I have a class called Item, a class called Room, and then the main Game class.
Anyway, I'm having some trouble with my checkForItem and drop methods at this point. I have to check my itemsHeld ArrayList for a certain item, but whenever I type in "item" it says it can't find the symbol item. Similar issues arise with my drop method. Any suggestions? Here is the (very lengthy) code.
import java.util.ArrayList;
public class Game
{
private ArrayList<Item> itemsHeld = new ArrayList<Item>();
private Room planetHarvest;
private Room planetReach;
private Room alphaHalo;
private Room newMombasa;
private Room deltaHalo;
private Room voi;
private Room theArk;
private Room forerunnerShieldWorld;
private Item DMR;
private Item Launcher;
private Item Shotgun;
private Item Health;
private Item Key;
private Room currentLocation;
private String msg;
public Game(){
createRooms();
ArrayList<Item> itemsHeld = new ArrayList<Item>(0);
currentLocation = planetHarvest;
}
private void createRooms(){
DMR = new Item("DMR", "The Designated Marksman Rifle fires a medium-range shot that defeats one enemy at a time.",
10, false);
Launcher = new Item("Launcher", "The rocket launcher fires a long-range rocket that defeats two enemies at a time.",
30, false);
Shotgun = new Item("Shotgun", "The shotgun fires a short-range buckshot blast that defeats one enemy at a time.",
10, false);
Health = new Item("Health", "The health pack heals you if you've been attacked.", 10, true);
Key = new Item("Key", "The Key is the secret to saving the galaxy.", 10000, false);
planetHarvest = new Room("a farming colony at the edge of human-controlled space. Though usually quiet, it has now been disturbed by an invasion from extraterrestrials who call themselves the Covenant. The Covenant will not let you escape without a fight.", DMR);
planetReach = new Room("twenty-seven years in the future. The Covenant has invaded every human colony world and bombarded each one with plasma, reducing the surface to molten glass. Planet Reach is the only human colony that remains. The aliens know their campaign to exterminate humanity is almost over and they show it in their ferocity on the battlefield.", Launcher);
alphaHalo = new Room("a strange, alien, planet-sized ring following your escape from the doomed planet Reach. The inside of the mysterious non-Covenant hoop structure has continents, oceans, ecosystems, breathable atmosphere – and two relentless foes. The Covenant has arrived; so has the Flood, a terrifying alien parasite that will eat both you and the Covenant. On top of that, you learn that this Halo is not just a habitat but also a weapon that will destroy all life in the galaxy if you don’t stop it.", Key);
newMombasa = new Room("an African city on Earth, humanity's last safe haven in the universe. A Covenant invasion force has landed. You’ll need to fend them off and follow them to wherever they’re headed next.", Health);
deltaHalo = new Room("where the Covenant and the Flood are already waiting. The same rules from Alpha Halo apply here, but now you learn that there are a total of eleven Halos and that the only way to stop them all is to shut them down from a structure outside the galaxy called the Ark. Meanwhile, the Covenant is still attacking Earth.", Key);
voi = new Room("The Flood has arrived and is infecting humans and aliens; meanwhile, the Covenant is in civil war and some of the aliens are helping you. Following your escape from Delta Halo, all of the Halos in the galaxy have been put on standby, so if you don’t find the Ark soon then it’s the end of life as we know it.", Shotgun);
theArk = new Room("a massive installation many times bigger than even a Halo. Shutting down the Ark will mean saving the galaxy. However, most of the Covenant and the Flood are still after you. Finish the fight.", Key);
forerunnerShieldWorld = new Room("an artificial planet made by a super-advanced alien civilization that disappeared 100,000 years ago – the makers of the Halos and the Ark. The war against the Covenant is finally over, the Flood has been defeated, and the galaxy is safe. The mysteries of the Forerunners, however, are just beginning to be unraveled.");
planetHarvest.addNeighbor("Slipspace Forward", planetReach);
planetReach.addNeighbor("Slipspace Out", alphaHalo);
alphaHalo.addNeighbor("Slipspace Back", planetReach);
alphaHalo.addNeighbor("Slipspace Forward", newMombasa);
newMombasa.addNeighbor("Slipspace Out", deltaHalo);
newMombasa.addNeighbor("Forward", voi);
deltaHalo.addNeighbor("Slipspace Back", newMombasa);
voi.addNeighbor("Slipspace Out", theArk);
voi.addNeighbor("Back", newMombasa);
theArk.addNeighbor("Slipspace Unknown", forerunnerShieldWorld);
}
private void setWelcomeMessage(){
msg = "You are John-117, an augmented soldier fighting for Earth and its colonies in the year 2552. You battle the Covenant, an alien religious alliance, and the Flood, an alien parasite that infects both humans and Covenant and turns them into zombies. Your battles take you to planetary colonies like Harvest and Reach, ancient alien ring-worlds called Halos, futuristic cities in Africa, and the Halos’ control station called the Ark, located outside the galaxy. The goal of the game is to defeat all enemies and make it to the safety of the Forerunner Shield World.";
}
public String getMessage(){
return msg;
}
public void help(){
msg = "Every place you enter is crawling with Covenent and/or Flood. You'll have to neutralize them before they neutralize you. As a Reclaimer, you're the only one who can use Keys on a Halo or Ark. Some places involve more than one mission.";
}
public void look(){
msg = currentLocation.getLongDescription();
}
public void move (String direction){
Room nextRoom = currentLocation.getNeighbor(direction);
if (nextRoom == null){
msg = "You can't go there.";
}else{
currentLocation = nextRoom;
msg = currentLocation.getLongDescription();
}
}
public void list(){
if(itemsHeld != null){
msg += itemsHeld;
}else{
msg = "You are not holding anything.";
}
}
public boolean gameOver(){
if(currentLocation == forerunnerShieldWorld){
msg = "You defeated the Covenant and survived the war. You won!";
}
return false;
}
public void pickup(){
if(currentLocation.hasItem()){
if(currentLocation.getItem().getWeight() < 50){
msg = "You are now holding the" + currentLocation.getItem().getName();
itemsHeld.add(currentLocation.getItem());
currentLocation.removeItem();
}else{
msg = "This item is too heavy to pick up.";
}
}else{
msg = "There is no item to pick up.";
}
}
private Item checkForItem (String name){
if(itemsHeld.contains(name)){
return ();
}else{
return null;
}
}
public void drop (String item){
if(itemsHeld.contains(item)){
itemsHeld.remove(item);
currentLocation.addItem;
}
}
}
Item is the type in this case. Not the variable name, which is what you want. You have several variables of type Item, but no variables named item.
Also, you have no field named itemsHeld. In your constructor you create a local variable with that name, but a variable by that name on the class is not defined.
Add
private ArrayList<Item> itemsHeld
to your field declarations, and in the constructor do
itemsHeld = new ArrayList<Item>(0);
to initialize it.
Or just do
private List<Item> itemsHeld = new ArrayList<Item>(0);
in your field declarations...
if(!PlayerLocation.hasItem()){
msg = "The player does not have that Item";
}
if(PlayerLocation.hasItem()){
for(Item lookfor: ItemsHeld){
String result = lookfor.getName();
if(result.contains(PlayerLocation.getItem().getName())){
msg = "The room already has an item " +
PlayerLocation.getItem().getName() +
".";
}
}
}
else {
for(Item lookfor: ItemsHeld){
String result = lookfor.getName();
if(result.contains(name)){
dropped = lookfor;
ItemsHeld.remove(lookfor);
PlayerLocation.addItem(dropped);
msg = "the player has successfully" +
"dropped the item in the room";
}
}
}
Idk if we have the same java teacher, but I was googling around
and browsing the interwebs for some answers and came accross your question.
Mine method works for droping the item; however, I'm degubbing my code for if the array list is empty, and has no items for it.

Using PathModifier or MoveYModifier to simulate sprite jumping

I am using this method in AndEngine to determine the scene being touched by the user.
#Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
if(pSceneTouchEvent.isActionDown()) {
Log.e("Arcade", "Scene Tapped");
//Simulate player jumping
}
return false;
}
What i want to do is when the scene is tapped, i want to allow the player to jump.
Now two things for this would it be better to use PathModifier, or MoveYModifier considering it is landscape mode?
If either please provide an example of such.
Thanks
EDIT:
ive managed to use Physics to simulate a jump using this..
#Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
if(pSceneTouchEvent.isActionDown()) {
Log.e("Arcade", "Scene Tapped");
final Vector2 velocity = Vector2Pool.obtain(mPhysicsWorld.getGravity().x * -0.5f,mPhysicsWorld.getGravity().y * -0.5f);
body.setLinearVelocity(velocity);
Vector2Pool.recycle(velocity);
return true;
}
return false;
}
As you said in the answer by changing the gravity. The only issue is, when the user keeps touching the screen the sprites keep going up and up and up. How can i set it where the user can only click once and cant make him jump again until the sprite hits the ground, which is a rectangle?
Use the MoveYModifier. remember, you can register as many modifiers as you want. So if, for example, the game a platform game and the character always moves on the X axis, and he can jumpt if he wants (Like Gravity Guy or Yoo Ninja, although these games change the gravity which is something else).
You could do like:
Entity playerEntity = ..//It doesn't matter if the player is a sprite, animated sprite, or anything else. So I'll just use Entity here, but you can declare your player as you wish.
final float jumpDuration = 2;
final float startX = playerEntity.getX();
final float jumpHeight = 100;
final MoveYModifier moveUpModifier = new MoveYModifier(jumpDuration / 2, startX, startX + jumpHeight);
final MoveYModifier moveDownModifier = new MoveYModifier(jumpDuration / 2, startX + jumpHeight, startX);
final SequenceEntityModifier modifier = new SequenceEntityModifier(moveUpModifier, moveDownModifier);
playerEntity.registerEntityModifier(modifier);
EDIT:
For your second question:
Create a variable boolean mIsJumping in your scene; When the jump starts - set it to true. If the user taps the screen and mIsJumping == true, don't jump.
Now, register a ContactListener to your PhysicsWorld. Whenever there is contact between the player and the ground, set mIsJumping to false.
There are many samples of using ContactListeners in AndEngine forums, a quick search yields some. If you need an example, you can ask for one :)
EDIT 2: ContactListener sample:
Have 2 variables to hold IDs for the player and the ground: private static final String PLAYER_ID = "player", GROUND_ID = "ground";
When you create the ground body and the player body, set their IDs as the user data: playerBody.setUserData(PLAYER_ID); and groundBody.setUserData(GROUND_ID);
Create a ContactListener as a field in your scene:
private ContactListener mContactListener = new ContactListener() {
/**
* Called when two fixtures begin to touch.
*/
public void beginContact (Contact contact) {
final Body bodyA = contact.getFixtureA().getBody();
final Body bodyB = contact.getFixtureB().getBody();
if(bodyA.getUserData().equals(PLAYER_ID)) {
if(bodyB.getUserData().equals(GROUND_ID))
mIsJumping = false;
}
else if(bodyA.getUserData().equals(GROUND_ID)) {
if(bodyB.getUserData().equals(PLAYER_ID))
mIsJumping = false;
}
}
/**
* Called when two fixtures cease to touch.
*/
public void endContact (Contact contact) { }
/**
* This is called after a contact is updated.
*/
public void preSolve(Contact pContact) { }
/**
* This lets you inspect a contact after the solver is finished.
*/
public void postSolve(Contact pContact) { }
};
Lastly, register that contact listener: physicsWorld.setContactListener(mContactListener);
EDIT 3:
To move your sprite over the X axis, you can apply a force using Body.applyForce method, or apply an impulse using Body.applyLinearImpulse method. Play around with the arguments and find what works the next.
The vector should consist a X part only; Try Vector2 force = Vector2Pool.obtain(50, 0);. Then apply the force this way: body.applyForce(force, body.getWorldCenter());.

Categories

Resources