Initial commit

This commit is contained in:
aNNiMON 2024-02-13 22:08:19 +02:00
commit c16628e18d
32 changed files with 3337 additions and 0 deletions

View File

@ -0,0 +1,36 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus;
/**
*
* @author Malcolm
*/
public interface ColorConstants {
int TEXT_COLOR = 0xF9B16B;
int HIGHLIGHTED_TEXT_COLOUR = 0xF9D2AD;
int BACKGROUNG_COLOR = 0x774323;
int HIGHLIGHTED_BORDER_COLOR = 0xB1343A;
int SELECTED_BACKGROUND_COLOR = 0x98562D;
int DARKER_BORDER = 0xA14F12;
int LIGHTER_BORDER = 0xD06D27;
int SLIDER_BACKGROUND = 0x964F20;
int SLIDER_COLOR = 0xD9722E;
}

View File

@ -0,0 +1,644 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus;
import com.malcolmsoft.wumpus.maps.InvalidRoomIdException;
import com.malcolmsoft.wumpus.model.CaveModel;
import com.malcolmsoft.wumpus.model.Event;
import com.malcolmsoft.wumpus.model.EventDefeat;
import com.malcolmsoft.wumpus.model.EventEnd;
import com.malcolmsoft.wumpus.model.EventFeel;
import com.malcolmsoft.wumpus.model.EventLocationChange;
import com.malcolmsoft.wumpus.model.EventVictory;
import com.malcolmsoft.wumpus.model.EventWumpusMoved;
import com.malcolmsoft.wumpus.model.PlayerAction;
import com.malcolmsoft.wumpus.model.PlayerActionMove;
import com.malcolmsoft.wumpus.model.PlayerActionShoot;
import java.util.Vector;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
/**
*
* @author Malcolm
*/
public class GameCanvas extends Canvas implements GameStrings, ColorConstants {
private final int width;
private final int height;
private final int delimiterPos;
private final int statusLinePos;
private final int sliderStripPos;
private final int sliderStripHeight;
private int sliderBottomPos;
private int sliderHeight;
private static final int SLIDER_STRIP_WIDTH = 5;
private static final int TEXT_MARGIN = 5;
private boolean consoleSelected = false;
private int highlightedItem = ITEM_PANEL;
// private static final int ITEM_NONE = 0;
private static final int ITEM_CONSOLE = 1;
private static final int ITEM_PANEL = 2;
private Font smallFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
private Font mediumFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
private int smallFontHeight = smallFont.getHeight();
private int mediumFontHeight = mediumFont.getHeight();
private Vector messages = new Vector();
private final int messagesPerScreen;
private int messagesSkipped; //If we scrolled beyond them
//Status line
private int currRoomId;
private int[] connectedRoomsIds;
private String status;
//Model references
private CaveModel caveModel;
private String currPlayerId;
//Controller (panel)
private volatile boolean blockInput = false;
private int inputState = STATE_ACTION_TYPE;
private static final int STATE_ACTION_TYPE = 0;
private static final int STATE_MOVE_NEXT_ROOM = 1;
private static final int STATE_SHOOT_CHARGES_USED = 2;
private static final int STATE_SHOOT_NEXT_ROOM = 3;
private static final int STATE_START_NEW_GAME = 4;
private String question = QUESTION_SELECT_ACTION;
private String[] options = OPTIONS_SELECT_ACTION;
private int selectedOption;
private static final String[] OPTIONS_SELECT_ACTION = {OPTION_GO, OPTION_SHOOT};
private static final String[] OPTIONS_START_NEW_GAME = {OPTION_PLAY_AGAIN, OPTION_QUIT};
private NumberField currNumberField = null; //Is shown in shooting
private NumberField chargesField = new NumberField(1);
private NumberField roomField = new NumberField(2);
private int numberFieldLeftPos;
private int[] roomsToShoot;
private int shotRoomPos;
private HuntTheWumpus gameStateListener;
public GameCanvas(CaveModel caveModel, String playerId, HuntTheWumpus gameStateListener) {
this.gameStateListener = gameStateListener;
setFullScreenMode(true);
width = getWidth();
height = getHeight();
statusLinePos = height - smallFontHeight;
delimiterPos = statusLinePos - 3 - smallFontHeight * 3 - mediumFontHeight;
sliderStripPos = width - 3 - SLIDER_STRIP_WIDTH;
sliderStripHeight = delimiterPos - 6;
messagesPerScreen = (delimiterPos - 5) / smallFontHeight;
numberFieldLeftPos = (width - roomField.getWidth()) / 2;
startNewGame(caveModel, playerId);
}
public void startNewGame(CaveModel caveModel, String playerId) {
if (caveModel == null || playerId == null)
throw new NullPointerException("Action listener or current player can't be null");
this.caveModel = caveModel;
this.currPlayerId = playerId;
init();
}
private void init() {
consoleSelected = false;
highlightedItem = ITEM_PANEL;
messages.removeAllElements();
messagesSkipped = 0;
blockInput = false;
inputState = STATE_ACTION_TYPE;
question = QUESTION_SELECT_ACTION;
options = OPTIONS_SELECT_ACTION;
selectedOption = 0;
currNumberField = null;
chargesField.clear();
roomField.clear();
}
protected void paint(Graphics g) {
g.setColor(BACKGROUNG_COLOR);
g.fillRect(0, 0, getWidth(), getHeight());
if (consoleSelected) {
g.setColor(SELECTED_BACKGROUND_COLOR);
g.fillRect(2, 2, width - 5, delimiterPos - 3);
}
g.setColor(DARKER_BORDER);
g.drawRect(0, 0, width - 1, height - 1);
g.drawRect(2, 2, width - 5, delimiterPos - 3);
g.drawRect(2, delimiterPos + 1, width - 5, statusLinePos - delimiterPos - 2);
g.drawRect(2, statusLinePos + 1, width - 5, height - statusLinePos - 4);
g.setColor(LIGHTER_BORDER);
g.drawRect(1, 1, width - 3, height - 3);
g.drawLine(2, statusLinePos, width - 2, statusLinePos);
g.drawLine(2, delimiterPos, width - 2, delimiterPos);
g.setColor(HIGHLIGHTED_BORDER_COLOR);
switch (highlightedItem) {
case ITEM_CONSOLE:
paintThickRectangle(g, 2, 2, width - 5, delimiterPos - 3);
break;
case ITEM_PANEL:
paintThickRectangle(g, 2, delimiterPos + 1, width - 5, statusLinePos - delimiterPos - 2);
break;
}
//Messages
g.setColor(TEXT_COLOR);
g.setFont(smallFont);
int messagesToShow = Math.min(messages.size() - messagesSkipped, messagesPerScreen);
int uppermostMessagePos = messagesSkipped + messagesToShow;
for (int lineBottomPos = delimiterPos, messagePos = messagesSkipped; messagePos < uppermostMessagePos;
lineBottomPos -= smallFontHeight, messagePos++) {
String message = (String) messages.elementAt(messagePos);
g.drawString(message, TEXT_MARGIN, lineBottomPos, Graphics.LEFT | Graphics.BOTTOM);
}
if (isConsoleScrollable()) {
g.setColor(SLIDER_BACKGROUND);
g.fillRect(sliderStripPos, 4, SLIDER_STRIP_WIDTH, sliderStripHeight);
g.setColor(SLIDER_COLOR);
g.fillRect(sliderStripPos, sliderBottomPos - sliderHeight, SLIDER_STRIP_WIDTH, sliderHeight);
}
//Panel
int linePos = delimiterPos + 1;
g.setColor(TEXT_COLOR);
g.setFont(mediumFont);
if (question != null) {
g.drawString(question, TEXT_MARGIN, linePos, 0);
linePos += mediumFontHeight;
}
if (currNumberField != null) {
currNumberField.paint(g, numberFieldLeftPos, linePos);
} else {
g.setFont(smallFont);
for (int optionPos = 0; optionPos < options.length; optionPos++, linePos += smallFontHeight) {
g.setColor(selectedOption == optionPos ? HIGHLIGHTED_TEXT_COLOUR : TEXT_COLOR);
g.drawString(options[optionPos], TEXT_MARGIN, linePos, 0);
}
}
//Status
g.setFont(smallFont);
g.setColor(TEXT_COLOR);
g.drawString(status, TEXT_MARGIN, statusLinePos, 0);
}
private void paintThickRectangle(Graphics g, int x, int y, int width, int height) {
g.drawRect(x, y, width, height);
g.drawRect(x + 1, y + 1, width - 2, height - 2);
// g.drawRect(x + 2, y + 2, width - 4, height - 4);
}
private boolean isConsoleScrollable() {
return messages.size() > messagesPerScreen;
}
private void updateSliderParameters() {
if (!isConsoleScrollable()) return;
int messagesTotal = messages.size();
sliderHeight = (int) ((double) sliderStripHeight * messagesPerScreen / messagesTotal + 0.5D);
sliderBottomPos = delimiterPos - 2 - (int) ((double) sliderStripHeight * messagesSkipped /
messagesTotal + 0.5D);
}
private void resetConsoleSliderPosition() {
if (messagesSkipped != 0) {
messagesSkipped = 0;
}
updateSliderParameters();
}
protected void keyPressed(int keyCode) {
if (keyCode == -6 || keyCode == -7) { //Soft keys
gameStateListener.quitCurrentGame();
return;
}
if (highlightedItem == ITEM_CONSOLE) { //Scroll if selected or move selector
int action = getGameAction(keyCode);
switch (action) {
case FIRE:
consoleSelected = !consoleSelected;
repaint();
break;
case DOWN:
if (consoleSelected) {
if (messagesSkipped > 0) {
messagesSkipped--; //Decrement by one if not 0 yet
updateSliderParameters();
repaint();
}
} else {
highlightedItem = ITEM_PANEL; //Move selector to panel
repaint();
}
break;
case UP:
if (consoleSelected && messages.size() - messagesSkipped > messagesPerScreen) {
messagesSkipped++;
updateSliderParameters();
repaint();
}
break;
}
} else if (highlightedItem == ITEM_PANEL) {
if (blockInput) return; //Don't accept input while events from the last action are being processed
if (currNumberField != null) {
switch (keyCode) {
case KEY_NUM0:
case KEY_NUM1:
case KEY_NUM2:
case KEY_NUM3:
case KEY_NUM4:
case KEY_NUM5:
case KEY_NUM6:
case KEY_NUM7:
case KEY_NUM8:
case KEY_NUM9:
currNumberField.numberEntered(keyCode - KEY_NUM0);
repaint();
break;
case KEY_POUND:
case -8: //Clear key
currNumberField.deleteLastChar();
repaint();
break;
case -5: //Fire
int value = currNumberField.getValue();
switch (inputState) {
case STATE_SHOOT_CHARGES_USED:
roomsToShoot = null;
roomsToShoot = new int[Math.min(caveModel.getPlayerCharges(currPlayerId),
value)];
shotRoomPos = 0;
inputState = STATE_SHOOT_NEXT_ROOM;
updatePanelAndRepaint();
break;
case STATE_SHOOT_NEXT_ROOM:
roomsToShoot[shotRoomPos++] = value;
if (shotRoomPos == roomsToShoot.length) {
inputState = STATE_ACTION_TYPE;
updatePanelAndRepaint();
dispatchPlayerAction(new PlayerActionShoot(currPlayerId, roomsToShoot));
} else {
updatePanelAndRepaint();
}
break;
default:
throw new IllegalStateException("Number field shown in illegal state" +
inputState);
}
}
} else {
int action = getGameAction(keyCode);
switch (action) {
case FIRE:
switch (inputState) {
case STATE_ACTION_TYPE:
switch (selectedOption) {
case 0: //Move
inputState = STATE_MOVE_NEXT_ROOM;
updatePanelAndRepaint();
break;
case 1: //Shoot
inputState = STATE_SHOOT_CHARGES_USED;
updatePanelAndRepaint();
break;
}
break;
case STATE_MOVE_NEXT_ROOM:
inputState = STATE_ACTION_TYPE;
updatePanelAndRepaint();
dispatchPlayerAction(new PlayerActionMove(currPlayerId,
connectedRoomsIds[selectedOption]));
break;
case STATE_START_NEW_GAME:
switch (selectedOption) {
case 0: //Play again
gameStateListener.restart();
break;
case 1: //Quit
gameStateListener.quitCurrentGame();
break;
}
break;
}
break;
case DOWN:
if (selectedOption < options.length - 1) {
selectedOption++;
repaint();
}
break;
case UP:
if (selectedOption > 0) {
selectedOption--;
} else {
highlightedItem = ITEM_CONSOLE;
}
repaint();
break;
}
}
} else throw new IllegalStateException("Unknown highlighted item: " + highlightedItem);
}
private void updatePanelAndRepaint() {
switch (inputState) {
case STATE_ACTION_TYPE:
options = OPTIONS_SELECT_ACTION;
selectedOption = 0;
question = QUESTION_SELECT_ACTION;
currNumberField = null;
break;
case STATE_MOVE_NEXT_ROOM:
//Generate options
options = null;
options = new String[connectedRoomsIds.length];
for (int passage = 0; passage < connectedRoomsIds.length; passage++) {
int nextId = connectedRoomsIds[passage];
options[passage] = OPTION_GO_TO_ROOM + nextId;
}
selectedOption = 0;
question = QUESTION_WHERE_TO;
currNumberField = null;
break;
case STATE_SHOOT_CHARGES_USED:
question = QUESTION_HOW_MANY_CHARGES;
currNumberField = chargesField;
break;
case STATE_SHOOT_NEXT_ROOM:
updateRoomShootingQuestion();
currNumberField = roomField;
roomField.clear();
break;
case STATE_START_NEW_GAME:
question = QUESTION_START_NEW_GAME;
options = OPTIONS_START_NEW_GAME;
selectedOption = 0;
currNumberField = null;
break;
}
System.out.println("Current state: " + inputState);
repaint();
}
private void updateStatus() {
StringBuffer buf = new StringBuffer();
buf.append(STATUS_ROOM);
buf.append(currRoomId);
buf.append(STATUS_PASSAGES);
for (int passage = 0; passage < connectedRoomsIds.length; passage++) {
buf.append(connectedRoomsIds[passage]);
buf.append(", ");
}
buf.append(caveModel.getPlayerCharges(currPlayerId));
buf.append(STATUS_CHARGES);
status = buf.toString();
}
private void updateRoomShootingQuestion() {
question = QUESTION_CHARGE_START + (shotRoomPos + 1) + QUESTION_CHARGE_ENDING;
}
private void dispatchPlayerAction(final PlayerAction action) {
blockInput = true;
new Thread() { //Dispatch in a different thread so that UI is not blocked
public void run() {
try {
caveModel.nextGameCycle(action);
} catch (InvalidRoomIdException ex) { //Whoops, wrong room
ex.printStackTrace();
inputState = STATE_ACTION_TYPE; //Init input
} finally {
blockInput = false;
}
}
}.start();
}
public void viewGameEvent(Event event) {
System.out.println(event);
switch (event.getEventType()) {
case Event.EVENT_PLAYER_MOVED:
EventLocationChange locationEvent = (EventLocationChange) event;
currRoomId = locationEvent.getNewRoomId();
connectedRoomsIds = locationEvent.getConnectedRoomsIds();
updateStatus();
String movingMessage = null;
switch (locationEvent.getCause()) {
case EventLocationChange.CAUSE_SPAWN:
movingMessage = MOVED_SPAWNED_IN_NEW_ROOM;
break;
case EventLocationChange.CAUSE_PLAYER:
movingMessage = MOVED_WALKED_TO_NEW_ROOM;
break;
case EventLocationChange.CAUSE_BATS:
addMessage(MOVED_BATS_SNATCHED); //Additional message
movingMessage = MOVED_DRAGGED_TO_NEW_ROOM;
break;
}
addMessage(movingMessage + currRoomId);
StringBuffer buf = new StringBuffer();
buf.append(MOVED_PASSAGES_LEAD_TO);
for (int passage = 0; passage < connectedRoomsIds.length - 1; passage++) {
buf.append(connectedRoomsIds[passage]);
buf.append(", ");
}
buf.append(connectedRoomsIds[connectedRoomsIds.length - 1]);
addMessage(buf.toString());
break;
case Event.EVENT_PLAYER_SHOT:
updateStatus();
addMessage(SHOT_MISSED);
break;
case Event.EVENT_PLAYER_FEELS:
EventFeel feelEvent = (EventFeel) event;
if (feelEvent.isPitNearby()) addMessage(FEEL_DRAFT);
if (feelEvent.areBatsNearby()) addMessage(FEEL_BATS);
if (feelEvent.isWumpusNearby()) addMessage(FEEL_WUMPUS);
break;
case Event.EVENT_WUMPUS_ESCAPED:
EventWumpusMoved wumpusEvent = (EventWumpusMoved) event;
if (wumpusEvent.wasWumpusEncountered()) {
addMessage(WUMPUS_BUMPED_INTO);
}
addMessage(WUMPUS_ESCAPED);
break;
case Event.EVENT_VICTORY:
EventVictory victoryEvent = (EventVictory) event;
addMessage(END_WUMPUS_SHOT);
addMessage(VICTORY_YOU_HAVE_WON);
addWumpusLocationMessage(victoryEvent);
addMessage(VICTORY_WUMPUS_WILL_GET_TO_YOU);
inputState = STATE_START_NEW_GAME;
updatePanelAndRepaint();
return;
case Event.EVENT_DEFEAT:
EventDefeat lastEvent = (EventDefeat) event;
if (lastEvent.isWumpusShot()) {
addMessage(END_WUMPUS_SHOT);
}
String message = null;
switch (lastEvent.getCause()) {
case EventDefeat.CAUSE_CHARGES_DEPLETED:
message = DEFEAT_CHARGES_DEPLETED;
break;
case EventDefeat.CAUSE_FELL_INTO_PIT:
message = DEFEAT_FELL_INTO_PIT;
break;
case EventDefeat.CAUSE_PLAYER_SHOT_HIMSELF:
message = DEFEAT_PLAYER_SHOT_HIMSELF;
break;
case EventDefeat.CAUSE_WUMPUS_MOVED_INTO_CAVE:
message = DEFEAT_WUMPUS_MOVED_INTO_CAVE;
break;
case EventDefeat.CAUSE_WUMPUS_WAS_IN_CAVE:
message = DEFEAT_WUMPUS_WAS_IN_THE_CAVE;
break;
}
addMessage(message);
if (lastEvent.getCause() != EventDefeat.CAUSE_WUMPUS_MOVED_INTO_CAVE) {
addWumpusLocationMessage(lastEvent);
}
inputState = STATE_START_NEW_GAME;
updatePanelAndRepaint();
return;
}
repaint();
}
private void addMessage(String message) {
messages.insertElementAt(message, 0);
resetConsoleSliderPosition();
}
private void addWumpusLocationMessage(EventEnd lastEvent) {
int wumpusRoomId = lastEvent.getWumpusRoomId();
if (wumpusRoomId > 0) { //It is known
addMessage(END_WUMPUS_LOCATION + wumpusRoomId);
}
}
private class NumberField {
private Font font = mediumFont;
private int width;
private int height = font.getHeight();
private StringBuffer text = new StringBuffer();
private final int maxNumbers;
public NumberField(int maxNumbers) {
this.width = font.charWidth('8') * maxNumbers + 2;
this.maxNumbers = maxNumbers;
}
public void paint(Graphics g, int x, int y) {
g.setColor(LIGHTER_BORDER);
g.drawRect(x, y, width, height);
g.setColor(TEXT_COLOR);
g.drawString(text.toString(), x + width, y, Graphics.TOP | Graphics.RIGHT);
}
public void numberEntered(int ch) {
if (ch > 9 || ch < 0) throw new IllegalArgumentException("Not a number: " + ch); //Bad number
if ((ch == 0 && text.length() == 0) || //First number shouldn't be zero
text.length() == maxNumbers) //And no more than maxNumbers numbers can be entered
return;
text.append(ch);
}
public int getValue() { //If nothing is entered, let value be zero
return text.length() > 0 ? Integer.parseInt(text.toString()) : 0;
}
public void deleteLastChar() {
if (text.length() == 0) return;
text.deleteCharAt(text.length() - 1);
}
public void clear() {
text.delete(0, text.length());
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
}
}

View File

@ -0,0 +1,78 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus;
/**
*
* @author Malcolm
*/
public interface GameStrings {
String MENU_HUNT_THE_WUMPUS = "Îõîòà íà Âàìïóñà";
String MENU_RESUME = "Âîçîáíîâèòü";
String MENU_NEW_GAME = "Íîâàÿ èãðà";
String MENU_QUIT = "Âûõîä";
String MENU_MAP_SELECTION_TITLE = "Âûáîð êàðòû";
String ALERT_TITLE = "Îøèáêà!";
String QUESTION_CHARGE_ENDING = ", êóäà ñòðåëÿòü?";
String QUESTION_CHARGE_START = "Çàðÿä ";
String QUESTION_HOW_MANY_CHARGES = "Ñêîëüêî çàðÿäîâ?";
String QUESTION_SELECT_ACTION = "Ñëåäóþùåå äåéñòâèå:";
String QUESTION_START_NEW_GAME = "Ñûãðàòü åùå?";
String QUESTION_WHERE_TO = "Â êàêóþ êîìíàòó?";
String OPTION_GO = "Èäòè";
String OPTION_SHOOT = "Ñòðåëÿòü";
String OPTION_GO_TO_ROOM = "Èäòè â êîìíàòó ";
String OPTION_PLAY_AGAIN = "Èãðàòü ñíîâà!";
String OPTION_QUIT = "Âûéòè";
String STATUS_CHARGES = " çàð.";
String STATUS_PASSAGES = ", ñîåä. ñ ";
String STATUS_ROOM = "Ê. ";
String MOVED_SPAWNED_IN_NEW_ROOM = "Òû â êîìíàòå ";
String MOVED_WALKED_TO_NEW_ROOM = "Òû ïðèøåë â êîìíàòó ";
String MOVED_BATS_SNATCHED = "Òåáÿ ñõâàòèëè ëåòó÷èå ìûøè!";
String MOVED_DRAGGED_TO_NEW_ROOM = "Òåáÿ ïðèòàùèëè â êîìíàòó ";
String MOVED_PASSAGES_LEAD_TO = "Ïðîõîäû âåäóò â ";
String SHOT_MISSED = "Òû ïðîìàõíóëñÿ";
String FEEL_DRAFT = "Òû ÷óâñòâóåøü ñêâîçíÿê";
String FEEL_BATS = "Ñëûøíî õëîïàíüå êðûëüåâ";
String FEEL_WUMPUS = "Òû ÷óåøü, ÷òî âàìïóñ áëèçêî!";
String WUMPUS_BUMPED_INTO = "Òû íàòêíóëñÿ íà âàìïóñà!";
String WUMPUS_ESCAPED = "Âàìïóñ ñáåæàë èç êîìíàòû";
String END_WUMPUS_SHOT = "Òû ïîäñòðåëèë âàìïóñà!";
String END_WUMPUS_LOCATION = "Âàìïóñ áûë â êîìíàòå ";
String DEFEAT_PLAYER_SHOT_HIMSELF = "Óâû, òû ïîäñòðåëèë ñåáÿ...";
String DEFEAT_CHARGES_DEPLETED = "Òû èñòðàòèë âñå çàðÿäû...";
String DEFEAT_FELL_INTO_PIT = "Èèèààà! Òû óïàë â ÿìó...";
String DEFEAT_WUMPUS_WAS_IN_THE_CAVE = "Âàìïóñ òåáÿ ñúåë...";
String DEFEAT_WUMPUS_MOVED_INTO_CAVE = "Ïðèøåë âàìïóñ è ñúåë òåáÿ...";
String VICTORY_YOU_HAVE_WON = "Òû âûèãðàë!";
String VICTORY_WUMPUS_WILL_GET_TO_YOU = "Âàìïóñ åùå äîáåðåòñÿ äî òåáÿ!";
}

View File

@ -0,0 +1,135 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus;
import com.malcolmsoft.wumpus.maps.Map;
import com.malcolmsoft.wumpus.maps.MapReader;
import com.malcolmsoft.wumpus.model.CaveModel;
import java.io.InputStream;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.Display;
import javax.microedition.midlet.MIDlet;
/**
* @author Malcolm
*/
public class HuntTheWumpus extends MIDlet implements ItemSelectionListener, GameStrings {
private Display display = Display.getDisplay(this);
private GameCanvas canvas;
private CaveModel model = new CaveModel();
private Map currentMap;
private MenuItem resume = new MenuItem(MENU_RESUME);
private MenuItem newGame = new MenuItem(MENU_NEW_GAME);
private MenuItem exit = new MenuItem(MENU_QUIT);
private MenuItem[] mainMenuItems = {
resume,
newGame,
exit
};
private Menu mainMenu = new Menu(MENU_HUNT_THE_WUMPUS, mainMenuItems);
private Menu mapSelectionMenu;
private static final String MAZE_MAPS_PATH = "/com/malcolmsoft/wumpus/maps/mazemaps.xml";
private Alert exceptionAlert = new Alert(ALERT_TITLE);
public HuntTheWumpus() {
try {
InputStream is = getMapStream();
String[] mapNames = MapReader.getInstance().readMapNames(is);
is.close();
MenuItem[] mapItems = new MenuItem[mapNames.length];
for (int mapPos = 0; mapPos < mapItems.length; mapPos++) {
mapItems[mapPos] = new MenuItem(mapNames[mapPos]);
}
mapSelectionMenu = new Menu(MENU_MAP_SELECTION_TITLE, mapItems);
mapSelectionMenu.setItemSelectionListener(this);
mainMenu.setItemEnabled(resume, false);
mainMenu.setSelectedItem(newGame);
mainMenu.setItemSelectionListener(this);
display.setCurrent(mainMenu);
} catch (Exception ex) { //Exceptions should never occur if app is built and started properly
viewException(ex);
}
}
public void startApp() {}
public void pauseApp() {}
public void destroyApp(boolean unconditional) {}
public void restart() {
canvas.startNewGame(model, model.getPlayerId());
model.startNewGame(currentMap);
}
public void quitCurrentGame() {
boolean gameActive = model.isGameActive();
mainMenu.setItemEnabled(resume, gameActive);
mainMenu.setSelectedItem(gameActive ? resume : newGame);
display.setCurrent(mainMenu);
}
public void itemSelected(Menu itemList, MenuItem item) {
if (itemList == mainMenu) {
if (item == resume) {
display.setCurrent(canvas);
} else if (item == newGame) {
display.setCurrent(mapSelectionMenu);
} else if (item == exit) {
notifyDestroyed();
}
} else if (itemList == mapSelectionMenu) {
try {
InputStream is = getMapStream();
//item.getText() is not very nice way to do this as it ties view and the model, but it is simple
currentMap = MapReader.getInstance().readMap(is, item.getText());
is.close();
if (canvas == null) {
canvas = new GameCanvas(model, model.getPlayerId(), this);//Reference from controller to model
model.setEventListener(canvas); //Establish reference from model to view
} else {
canvas.startNewGame(model, model.getPlayerId());
}
model.startNewGame(currentMap);
display.setCurrent(canvas);
} catch (Exception ex) {
viewException(ex);
}
}
}
private InputStream getMapStream() {
return getClass().getResourceAsStream(MAZE_MAPS_PATH);
}
private void viewException(Exception ex) {
ex.printStackTrace();
exceptionAlert.setString(ex.toString());
display.setCurrent(exceptionAlert);
}
}

View File

@ -0,0 +1,28 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus;
/**
*
* @author Malcolm
*/
public interface ItemSelectionListener {
void itemSelected(Menu itemList, MenuItem item);
}

View File

@ -0,0 +1,167 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus;
import java.util.Vector;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
/**
*
* @author Malcolm
*/
public class Menu extends Canvas implements ColorConstants {
protected final int width;
protected final int height;
protected final int horCenter;
protected int firstItemPos;
protected Font largeFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_LARGE);
protected Font mediumFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
private Font titleFont = largeFont;
private Font textFont = mediumFont;
private int textFontHeight = textFont.getHeight();
private String title;
private MenuItem[] items;
private Vector disabledItems = new Vector();
private int selectedItem = 0;
private ItemSelectionListener listener;
public Menu(String title, MenuItem[] items) {
this.title = title;
this.items = items;
setFullScreenMode(true);
width = getWidth();
height = getHeight();
horCenter = width / 2;
int textSizeTotal = textFontHeight * items.length;
firstItemPos = (height - largeFont.getHeight() - textSizeTotal) / 2;
}
protected void paint(Graphics g) {
g.setColor(BACKGROUNG_COLOR);
g.fillRect(0, 0, width, height);
g.setColor(TEXT_COLOR);
g.setFont(titleFont);
g.drawString(title, horCenter, 0, Graphics.HCENTER | Graphics.TOP);
g.setFont(textFont);
for (int itemPos = 0, linePos = firstItemPos; itemPos < items.length;
itemPos++, linePos += textFontHeight) {
MenuItem item = items[itemPos];
if (disabledItems.contains(item)) continue;
g.setColor(itemPos == selectedItem ? HIGHLIGHTED_TEXT_COLOUR : TEXT_COLOR);
g.drawString(item.getText(), horCenter, linePos, Graphics.HCENTER | Graphics.TOP);
}
}
protected void keyPressed(int keyCode) {
switch (getGameAction(keyCode)) {
case DOWN:
if (selectedItem == items.length - 1) break;
//Find nearest enabled item
int newSelectedItem;
boolean nextElementFound = false;
for (newSelectedItem = selectedItem + 1; newSelectedItem < items.length; newSelectedItem++) {
if (!isItemDisabled(newSelectedItem)) {
nextElementFound = true;
break;
}
}
if (!nextElementFound) break;
selectedItem = newSelectedItem;
repaint();
break;
case UP:
if (selectedItem == 0) break;
//Find nearest enabled item
nextElementFound = false;
for (newSelectedItem = selectedItem - 1; newSelectedItem >= 0; newSelectedItem--) {
if (!isItemDisabled(newSelectedItem)) {
nextElementFound = true;
break;
}
}
if (!nextElementFound) break;
selectedItem--;
repaint();
break;
case FIRE:
listener.itemSelected(this, items[selectedItem]);
break;
}
}
private boolean isItemDisabled(int itemPos) {
return disabledItems.contains(items[itemPos]);
}
public void setItemEnabled(MenuItem item, boolean enabled) {
if (enabled) {
int itemPos = disabledItems.indexOf(item);
if (itemPos == -1) {
return; //No such disabled items
} else {
disabledItems.removeElementAt(itemPos);
}
} else { //We are disabling the item
if (disabledItems.contains(item)) return; //It has already been disabled
for (int itemPos = 0; itemPos < items.length; itemPos++) {//This is merely a check for item existence
if (items[itemPos] == item) {
disabledItems.addElement(item);
return;
}
}
throw new IllegalArgumentException("Item " + item + " wasn't found in the list");
}
}
public void setSelectedItem(MenuItem item) {
if (disabledItems.contains(item))
throw new IllegalArgumentException("Item " + item + " was disabled");
for (int itemPos = 0; itemPos < items.length; itemPos++) {
if (items[itemPos] == item) {
selectedItem = itemPos;
return;
}
}
throw new IllegalArgumentException("Item " + item + " wasn't found in the list");
}
public void setItemSelectionListener(ItemSelectionListener listener) {
this.listener = listener;
}
}

View File

@ -0,0 +1,40 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus;
/**
*
* @author Malcolm
*/
public class MenuItem {
private String text;
public MenuItem(String text) {
this.text = text;
}
public String getText() {
return text;
}
public String toString() {
return text;
}
}

View File

@ -0,0 +1,30 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus;
import javax.microedition.lcdui.Displayable;
/**
*
* @author Malcolm
*/
public interface ReturnListener {
public void returnFromDisplayable(Displayable d);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

View File

@ -0,0 +1,42 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.maps;
/**
*
* @author Malcolm
*/
public class InvalidRoomIdException extends IllegalArgumentException {
/**
* Creates a new instance of <code>InvalidRoomIdException</code> without detail message.
*/
public InvalidRoomIdException() {
}
/**
* Constructs an instance of <code>InvalidRoomIdException</code> with the specified detail message.
* @param msg the detail message.
*/
public InvalidRoomIdException(String msg) {
super(msg);
}
}

View File

@ -0,0 +1,101 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.maps;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
/**
*
* @author Malcolm
*/
public class Map {
private String name;
private Hashtable roomsNet = new Hashtable();
private int oneWayPassagesTotal;
private int twoWayPassagesTotal;
public Map(String name, Vector rooms) {
this.name = name;
Enumeration roomsEn = rooms.elements();
while (roomsEn.hasMoreElements()) {
Room room = (Room) roomsEn.nextElement();
roomsNet.put(new Integer(room.id), room);
}
//Now link the rooms
roomsEn = null;
roomsEn = roomsNet.elements();
while (roomsEn.hasMoreElements()) {
Room room = (Room) roomsEn.nextElement();
Integer roomId = new Integer(room.id);
Enumeration roomIdsEn = room.connectedRoomsIds.elements();
for (int passagePos = 0; roomIdsEn.hasMoreElements(); passagePos++) {
Room connectedRoom = (Room) roomsNet.get(roomIdsEn.nextElement());
room.connectedRooms[passagePos] = connectedRoom;
if (connectedRoom.connectedRoomsIds.contains(roomId)) {
twoWayPassagesTotal++;
} else {
oneWayPassagesTotal++;
// System.out.println(roomId + ", connected room: " + connectedRoom.id);
}
}
}
twoWayPassagesTotal /= 2;
//And some check for ids
roomsEn = null;
roomsEn = roomsNet.elements();
while (roomsEn.hasMoreElements()) {
Room room = (Room) roomsEn.nextElement();
if (room.id <= 0 || room.id > roomsNet.size())
throw new IllegalArgumentException("Invalid or inconsistent id: " + room.id);
}
}
public String getName() {
return name;
}
public Room getRoom(int id) {
Room room = (Room) roomsNet.get(new Integer(id));
if (room == null)
throw new InvalidRoomIdException("Room " + id + " doesn't exist");
return room;
}
public int getRoomsCount() {
return roomsNet.size();
}
public String toString() {
return "Map \"" + name + "\" with " + roomsNet.size() + " rooms, " +
convertToString(twoWayPassagesTotal) + " two-way passages and " +
convertToString(oneWayPassagesTotal) + " one-way passages";
}
private String convertToString(int number) {
return number == 0 ? "no" : String.valueOf(number);
}
}

View File

@ -0,0 +1,171 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.maps;
import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
*
* @author Malcolm
*/
public class MapReader {
private SAXParser parser;
private static MapReader instance;
private MapReader() throws ParserConfigurationException, SAXException {
parser = SAXParserFactory.newInstance().newSAXParser();
}
public static MapReader getInstance() throws SAXException, ParserConfigurationException {
if (instance == null)
instance = new MapReader();
return instance;
}
public String[] readMapNames(InputStream is) throws IOException {
NamesHandler handler = new NamesHandler();
try {
parser.parse(is, handler);
} catch (SAXException ex) {
ex.printStackTrace();
}
return handler.getMapNames();
}
public Map readMap(InputStream is, String mapName) throws IOException {
MapHandler handler = new MapHandler(mapName);
try {
parser.parse(is, handler);
} catch (SAXException ex) {
ex.printStackTrace();
}
Map map = handler.getMap();
if (map == null) throw new IllegalArgumentException("Map with name \"" + mapName + "\" wasn't found");
return map;
}
private class NamesHandler extends DefaultHandler {
private Vector mapNames;
public NamesHandler() {
mapNames = new Vector();
}
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
if ("maze".equals(qName)) {
mapNames.addElement(attributes.getValue("name"));
}
}
public String[] getMapNames() {
String[] output = new String[mapNames.size()];
mapNames.copyInto(output);
return output;
}
}
private class MapHandler extends DefaultHandler {
private String mapName;
private Map map;
private Vector rooms;
private int currRoomId;
private Vector connectedRoomsIds;
private int state;
private static final int STATE_SKIPPING = 0;
private static final int STATE_READING_MAP = 1;
private static final int STATE_READING_ROOM = 2;
private static final int STATE_READING_PASSAGE = 3;
public MapHandler(String mapName) {
this.mapName = mapName;
}
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
switch (state) {
case STATE_SKIPPING:
if (map == null && "maze".equals(qName) && attributes.getValue("name").equals(mapName)) {
state = STATE_READING_MAP;
rooms = new Vector();
}
break;
case STATE_READING_MAP:
if ("room".equals(qName)) {
currRoomId = Integer.parseInt(attributes.getValue("id"));
connectedRoomsIds = new Vector();
state = STATE_READING_ROOM;
}
break;
case STATE_READING_ROOM:
if ("passage".equals(qName)) {
state = STATE_READING_PASSAGE;
}
break;
}
}
public void characters(char[] ch, int start, int length) throws SAXException {
if (state == STATE_READING_PASSAGE) {
connectedRoomsIds.addElement(Integer.valueOf(new String(ch, start, length)));
}
}
public void endElement(String uri, String localName, String qName) throws SAXException {
switch (state) {
case STATE_READING_MAP:
if ("maze".equals(qName)) {
map = new Map(mapName, rooms);
rooms = null;
state = STATE_SKIPPING;
}
break;
case STATE_READING_ROOM:
if ("room".equals(qName)) {
rooms.addElement(new Room(currRoomId, connectedRoomsIds));
connectedRoomsIds = null;
state = STATE_READING_MAP;
}
break;
case STATE_READING_PASSAGE:
if ("passage".equals(qName)) { //Should always be true
state = STATE_READING_ROOM;
}
break;
}
}
private Map getMap() {
return map;
}
}
}

View File

@ -0,0 +1,124 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.maps;
import com.malcolmsoft.wumpus.model.GameObject;
import java.util.Enumeration;
import java.util.Vector;
/**
*
* @author Malcolm
*/
public class Room {
int id;
Room[] connectedRooms = new Room[MAX_PASSAGES_NUM]; //Null passages must be at the end of this array
Vector connectedRoomsIds;
Vector objects = new Vector();
public static final int MAX_PASSAGES_NUM = 3;
public Room(int id, Vector connectedRoomsIds) {
this.id = id;
this.connectedRoomsIds = connectedRoomsIds;
}
public int getId() {
return id;
}
public boolean connectsTo(Room otherRoom) {
for (int roomPos = 0; roomPos < connectedRooms.length; roomPos++) {
if (connectedRooms[roomPos] == otherRoom) return true;
}
return false;
}
public int getPassagesCount() {
int passagesCount = connectedRooms.length;
for (int roomPos = connectedRooms.length - 1; roomPos >= 0; roomPos--) {
if (connectedRooms[roomPos] != null) break;
passagesCount--;
}
return passagesCount;
}
public Room getNextRoom(int passage) {
return connectedRooms[passage];
}
public int[] getConnectedRoomsIds() {
int[] ids = new int[connectedRoomsIds.size()];
for (int passage = 0; passage < ids.length; passage++) {
ids[passage] = ((Integer) connectedRoomsIds.elementAt(passage)).intValue();
}
return ids;
}
public void addObject(GameObject object) {
objects.addElement(object);
}
public boolean isEmpty() {
return objects.isEmpty();
}
public boolean hasObject(GameObject object) {
return objects.contains(object);
}
public boolean hasObjectType(Class clazz) {
Enumeration en = objects.elements();
while (en.hasMoreElements()) {
if (clazz.isInstance(en.nextElement()))
return true;
}
return false;
}
public Enumeration contents() {
return objects.elements();
}
public void removeObject(GameObject object) {
objects.removeElement(object);
}
public void removeAllObjects() {
objects.removeAllElements();
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("Room ");
buf.append(id);
buf.append(", connected to ");
for (int passage = 0; passage < connectedRooms.length; passage++) {
Room room = connectedRooms[passage];
if (room != null) {
buf.append(room.id);
buf.append(", ");
} else break;
}
buf.delete(buf.length() - 2, buf.length()); //Remove last comma and space
return buf.toString();
}
}

View File

@ -0,0 +1,643 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Document : mazes.xml
Created on : 29 July 2009, 16:07
Author : Malcolm
Description: maps of mazes for Hunt The Wumpus game
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
-->
<mazemaps
xmlns="http://malcolm-soft.com/huntthewumpus"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://malcolm-soft.com/huntthewumpus mazemaps.xsd">
<maze name="Додекаэдр">
<room id="1">
<passage>2</passage>
<passage>5</passage>
<passage>8</passage>
</room>
<room id="2">
<passage>1</passage>
<passage>3</passage>
<passage>10</passage>
</room>
<room id="3">
<passage>2</passage>
<passage>4</passage>
<passage>12</passage>
</room>
<room id="4">
<passage>3</passage>
<passage>5</passage>
<passage>14</passage>
</room>
<room id="5">
<passage>1</passage>
<passage>4</passage>
<passage>6</passage>
</room>
<room id="6">
<passage>5</passage>
<passage>7</passage>
<passage>15</passage>
</room>
<room id="7">
<passage>6</passage>
<passage>8</passage>
<passage>17</passage>
</room>
<room id="8">
<passage>1</passage>
<passage>7</passage>
<passage>9</passage>
</room>
<room id="9">
<passage>8</passage>
<passage>10</passage>
<passage>18</passage>
</room>
<room id="10">
<passage>2</passage>
<passage>9</passage>
<passage>11</passage>
</room>
<room id="11">
<passage>10</passage>
<passage>12</passage>
<passage>19</passage>
</room>
<room id="12">
<passage>3</passage>
<passage>11</passage>
<passage>13</passage>
</room>
<room id="13">
<passage>12</passage>
<passage>14</passage>
<passage>20</passage>
</room>
<room id="14">
<passage>4</passage>
<passage>13</passage>
<passage>15</passage>
</room>
<room id="15">
<passage>6</passage>
<passage>14</passage>
<passage>16</passage>
</room>
<room id="16">
<passage>15</passage>
<passage>17</passage>
<passage>20</passage>
</room>
<room id="17">
<passage>7</passage>
<passage>16</passage>
<passage>18</passage>
</room>
<room id="18">
<passage>9</passage>
<passage>17</passage>
<passage>19</passage>
</room>
<room id="19">
<passage>11</passage>
<passage>18</passage>
<passage>20</passage>
</room>
<room id="20">
<passage>13</passage>
<passage>16</passage>
<passage>19</passage>
</room>
</maze>
<maze name="Лента Мебиуса">
<room id="1">
<passage>20</passage>
<passage>2</passage>
<passage>3</passage>
</room>
<room id="2">
<passage>19</passage>
<passage>1</passage>
<passage>4</passage>
</room>
<room id="3">
<passage>1</passage>
<passage>4</passage>
<passage>5</passage>
</room>
<room id="4">
<passage>2</passage>
<passage>3</passage>
<passage>6</passage>
</room>
<room id="5">
<passage>3</passage>
<passage>6</passage>
<passage>7</passage>
</room>
<room id="6">
<passage>4</passage>
<passage>5</passage>
<passage>8</passage>
</room>
<room id="7">
<passage>5</passage>
<passage>8</passage>
<passage>9</passage>
</room>
<room id="8">
<passage>6</passage>
<passage>7</passage>
<passage>10</passage>
</room>
<room id="9">
<passage>7</passage>
<passage>10</passage>
<passage>11</passage>
</room>
<room id="10">
<passage>8</passage>
<passage>9</passage>
<passage>12</passage>
</room>
<room id="11">
<passage>9</passage>
<passage>12</passage>
<passage>13</passage>
</room>
<room id="12">
<passage>10</passage>
<passage>11</passage>
<passage>14</passage>
</room>
<room id="13">
<passage>11</passage>
<passage>14</passage>
<passage>15</passage>
</room>
<room id="14">
<passage>12</passage>
<passage>13</passage>
<passage>16</passage>
</room>
<room id="15">
<passage>13</passage>
<passage>16</passage>
<passage>17</passage>
</room>
<room id="16">
<passage>14</passage>
<passage>15</passage>
<passage>18</passage>
</room>
<room id="17">
<passage>15</passage>
<passage>18</passage>
<passage>19</passage>
</room>
<room id="18">
<passage>16</passage>
<passage>17</passage>
<passage>20</passage>
</room>
<room id="19">
<passage>2</passage>
<passage>17</passage>
<passage>20</passage>
</room>
<room id="20">
<passage>1</passage>
<passage>18</passage>
<passage>19</passage>
</room>
</maze>
<maze name="След из крошек">
<room id="1">
<passage>2</passage>
<passage>3</passage>
<passage>20</passage>
</room>
<room id="2">
<passage>1</passage>
<passage>3</passage>
<passage>4</passage>
</room>
<room id="3">
<passage>1</passage>
<passage>2</passage>
<passage>4</passage>
</room>
<room id="4">
<passage>2</passage>
<passage>3</passage>
<passage>5</passage>
</room>
<room id="5">
<passage>4</passage>
<passage>6</passage>
<passage>7</passage>
</room>
<room id="6">
<passage>5</passage>
<passage>7</passage>
<passage>8</passage>
</room>
<room id="7">
<passage>5</passage>
<passage>6</passage>
<passage>8</passage>
</room>
<room id="8">
<passage>6</passage>
<passage>7</passage>
<passage>9</passage>
</room>
<room id="9">
<passage>8</passage>
<passage>10</passage>
<passage>11</passage>
</room>
<room id="10">
<passage>9</passage>
<passage>11</passage>
<passage>12</passage>
</room>
<room id="11">
<passage>9</passage>
<passage>10</passage>
<passage>12</passage>
</room>
<room id="12">
<passage>10</passage>
<passage>11</passage>
<passage>13</passage>
</room>
<room id="13">
<passage>12</passage>
<passage>14</passage>
<passage>15</passage>
</room>
<room id="14">
<passage>13</passage>
<passage>15</passage>
<passage>16</passage>
</room>
<room id="15">
<passage>13</passage>
<passage>14</passage>
<passage>16</passage>
</room>
<room id="16">
<passage>14</passage>
<passage>15</passage>
<passage>17</passage>
</room>
<room id="17">
<passage>16</passage>
<passage>18</passage>
<passage>19</passage>
</room>
<room id="18">
<passage>17</passage>
<passage>19</passage>
<passage>20</passage>
</room>
<room id="19">
<passage>17</passage>
<passage>18</passage>
<passage>20</passage>
</room>
<room id="20">
<passage>1</passage>
<passage>18</passage>
<passage>19</passage>
</room>
</maze>
<maze name="Гексагональная сетка">
<room id="1">
<passage>6</passage>
<passage>10</passage>
<passage>16</passage>
</room>
<room id="2">
<passage>6</passage>
<passage>7</passage>
<passage>17</passage>
</room>
<room id="3">
<passage>7</passage>
<passage>8</passage>
<passage>18</passage>
</room>
<room id="4">
<passage>8</passage>
<passage>9</passage>
<passage>19</passage>
</room>
<room id="5">
<passage>9</passage>
<passage>10</passage>
<passage>20</passage>
</room>
<room id="6">
<passage>1</passage>
<passage>2</passage>
<passage>15</passage>
</room>
<room id="7">
<passage>2</passage>
<passage>3</passage>
<passage>11</passage>
</room>
<room id="8">
<passage>3</passage>
<passage>4</passage>
<passage>12</passage>
</room>
<room id="9">
<passage>4</passage>
<passage>5</passage>
<passage>13</passage>
</room>
<room id="10">
<passage>1</passage>
<passage>5</passage>
<passage>14</passage>
</room>
<room id="11">
<passage>7</passage>
<passage>16</passage>
<passage>20</passage>
</room>
<room id="12">
<passage>8</passage>
<passage>16</passage>
<passage>17</passage>
</room>
<room id="13">
<passage>9</passage>
<passage>17</passage>
<passage>18</passage>
</room>
<room id="14">
<passage>10</passage>
<passage>18</passage>
<passage>19</passage>
</room>
<room id="15">
<passage>6</passage>
<passage>19</passage>
<passage>20</passage>
</room>
<room id="16">
<passage>1</passage>
<passage>11</passage>
<passage>12</passage>
</room>
<room id="17">
<passage>2</passage>
<passage>12</passage>
<passage>13</passage>
</room>
<room id="18">
<passage>3</passage>
<passage>13</passage>
<passage>14</passage>
</room>
<room id="19">
<passage>4</passage>
<passage>14</passage>
<passage>15</passage>
</room>
<room id="20">
<passage>5</passage>
<passage>11</passage>
<passage>15</passage>
</room>
</maze>
<maze name="Дендрит">
<room id="1">
<passage>1</passage>
<passage>1</passage>
<passage>5</passage>
</room>
<room id="2">
<passage>2</passage>
<passage>2</passage>
<passage>5</passage>
</room>
<room id="3">
<passage>3</passage>
<passage>3</passage>
<passage>6</passage>
</room>
<room id="4">
<passage>4</passage>
<passage>4</passage>
<passage>6</passage>
</room>
<room id="5">
<passage>1</passage>
<passage>2</passage>
<passage>7</passage>
</room>
<room id="6">
<passage>3</passage>
<passage>4</passage>
<passage>7</passage>
</room>
<room id="7">
<passage>5</passage>
<passage>6</passage>
<passage>10</passage>
</room>
<room id="8">
<passage>8</passage>
<passage>9</passage>
<passage>9</passage>
</room>
<room id="9">
<passage>8</passage>
<passage>8</passage>
<passage>10</passage>
</room>
<room id="10">
<passage>7</passage>
<passage>9</passage>
<passage>11</passage>
</room>
<room id="11">
<passage>10</passage>
<passage>13</passage>
<passage>14</passage>
</room>
<room id="12">
<passage>12</passage>
<passage>13</passage>
<passage>13</passage>
</room>
<room id="13">
<passage>11</passage>
<passage>12</passage>
<passage>12</passage>
</room>
<room id="14">
<passage>11</passage>
<passage>15</passage>
<passage>16</passage>
</room>
<room id="15">
<passage>14</passage>
<passage>17</passage>
<passage>18</passage>
</room>
<room id="16">
<passage>14</passage>
<passage>19</passage>
<passage>20</passage>
</room>
<room id="17">
<passage>15</passage>
<passage>17</passage>
<passage>17</passage>
</room>
<room id="18">
<passage>15</passage>
<passage>18</passage>
<passage>18</passage>
</room>
<room id="19">
<passage>16</passage>
<passage>19</passage>
<passage>19</passage>
</room>
<room id="20">
<passage>16</passage>
<passage>20</passage>
<passage>20</passage>
</room>
</maze>
<maze name="Дорожки в одну сторону">
<room id="1">
<passage>5</passage>
<passage>4</passage>
<passage>8</passage>
</room>
<room id="2">
<passage>1</passage>
<passage>5</passage>
<passage>6</passage>
</room>
<room id="3">
<passage>2</passage>
<passage>6</passage>
<passage>7</passage>
</room>
<room id="4">
<passage>3</passage>
<passage>7</passage>
<passage>8</passage>
</room>
<room id="5">
<passage>8</passage>
<passage>9</passage>
<passage>12</passage>
</room>
<room id="6">
<passage>5</passage>
<passage>9</passage>
<passage>10</passage>
</room>
<room id="7">
<passage>6</passage>
<passage>10</passage>
<passage>11</passage>
</room>
<room id="8">
<passage>7</passage>
<passage>11</passage>
<passage>12</passage>
</room>
<room id="9">
<passage>12</passage>
<passage>13</passage>
<passage>16</passage>
</room>
<room id="10">
<passage>9</passage>
<passage>13</passage>
<passage>14</passage>
</room>
<room id="11">
<passage>10</passage>
<passage>14</passage>
<passage>15</passage>
</room>
<room id="12">
<passage>11</passage>
<passage>15</passage>
<passage>16</passage>
</room>
<room id="13">
<passage>16</passage>
<passage>17</passage>
<passage>20</passage>
</room>
<room id="14">
<passage>13</passage>
<passage>17</passage>
<passage>18</passage>
</room>
<room id="15">
<passage>14</passage>
<passage>18</passage>
<passage>19</passage>
</room>
<room id="16">
<passage>15</passage>
<passage>19</passage>
<passage>20</passage>
</room>
<room id="17">
<passage>1</passage>
<passage>4</passage>
<passage>20</passage>
</room>
<room id="18">
<passage>1</passage>
<passage>2</passage>
<passage>17</passage>
</room>
<room id="19">
<passage>2</passage>
<passage>3</passage>
<passage>18</passage>
</room>
<room id="20">
<passage>3</passage>
<passage>4</passage>
<passage>19</passage>
</room>
</maze>
</mazemaps>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="windows-1251"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://malcolm-soft.com/huntthewumpus"
xmlns="http://malcolm-soft.com/huntthewumpus"
elementFormDefault="qualified">
<xs:element name="mazemaps">
<xs:complexType>
<xs:sequence>
<xs:element name="maze" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element ref="room" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="name" type="xs:token"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="room">
<xs:complexType>
<xs:sequence>
<xs:element name="passage" minOccurs="3" maxOccurs="3"/>
</xs:sequence>
<xs:attribute name="id" use="required" type="xs:integer"/>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@ -0,0 +1,26 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.model;
/**
*
* @author Malcolm
*/
public class Bats extends GameObject {}

View File

@ -0,0 +1,235 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.model;
import com.malcolmsoft.wumpus.GameCanvas;
import com.malcolmsoft.wumpus.maps.Map;
import com.malcolmsoft.wumpus.maps.Room;
import java.util.Vector;
/**
*
* @author Malcolm
*/
public class CaveModel {
//Game model
private volatile boolean gameActive = false;
private Player player = new Player("Player");
private Wumpus wumpus = new Wumpus();
private Pit[] pits = new Pit[PITS_COUNT];
private Bats[] bats = new Bats[BATS_COUNT];
private Map map;
private static final int PITS_COUNT = 2;
private static final int BATS_COUNT = 2;
private static final int HAZARD_NONE = 0;
private static final int HAZARD_PIT = 1;
private static final int HAZARD_WUMPUS = 2;
private GameCanvas eventListener;
public CaveModel() {
for (int pitPos = 0; pitPos < pits.length; pitPos++) {
pits[pitPos] = new Pit();
}
for (int batsPos = 0; batsPos < bats.length; batsPos++) {
bats[batsPos] = new Bats();
}
}
public void startNewGame(Map map) { //Assumes that map is loaded
this.map = map;
player.setRandomLocation(map);
player.resetWeapons();
wumpus.setRandomLocation(map);
wumpus.sleep();
for (int pitPos = 0; pitPos < pits.length; pitPos++) {
pits[pitPos].setRandomLocation(map);
}
for (int batsPos = 0; batsPos < bats.length; batsPos++) {
bats[batsPos].setRandomLocation(map);
}
gameActive = true;
if (eventListener != null) showStartingEvents(); //Check could be omitted, but why waste CPU cycles?
}
public void setEventListener(GameCanvas eventListener) {
if (eventListener == null)
throw new NullPointerException("Event listener can't be null");
this.eventListener = eventListener;
}
private void showStartingEvents() {
viewGameEvent(new EventLocationChange(player.getLocation(), EventLocationChange.CAUSE_SPAWN));
checkFeelings();
}
public synchronized void nextGameCycle(PlayerAction action) {
if (!gameActive) throw new IllegalStateException("Game has not started yet!");
//First player makes his move
boolean wumpusEncountered = false;
switch (action.getActionType()) {
case PlayerAction.ACTION_MOVE:
int newRoomId = ((PlayerActionMove) action).getNewRoomId();
//If room is invalid, exception is thrown and nothing else is done
Room enteredRoom = map.getRoom(newRoomId);
if (!player.getLocation().connectsTo(enteredRoom)) {
throw new IllegalArgumentException("You can't move from room " +
player.getLocation().getId() + " to room " + enteredRoom.getId() + "!");
}
viewGameEvent(new EventLocationChange(enteredRoom, EventLocationChange.CAUSE_PLAYER));
int hazard = moveAndCheckHazards(player, enteredRoom);
switch (hazard) {
case HAZARD_PIT:
gameActive = false;
viewGameEvent(new EventDefeat(EventDefeat.CAUSE_FELL_INTO_PIT,
wumpus.getLocation().getId()));
return;
case HAZARD_WUMPUS:
wumpusEncountered = true;
wumpus.wakeUp(); //Woke up because player bumped into him
break;
}
break;
case PlayerAction.ACTION_SHOOT:
Vector shotObjects = player.shoot(map, ((PlayerActionShoot) action).getRoomsToShoot());
boolean wumpusShot = shotObjects.contains(wumpus);
int wumpusLocationId = wumpus.getLocation().getId();
Event endGameEvent = null;
if (shotObjects.contains(player)) { //Player shot himself
endGameEvent = new EventDefeat(EventDefeat.CAUSE_PLAYER_SHOT_HIMSELF, wumpusLocationId,
wumpusShot);
} else if (wumpusShot) { //Player shot wumpus!
endGameEvent = new EventVictory(wumpusLocationId);
} else if (player.chargesDepleted()) {
endGameEvent = new EventDefeat(EventDefeat.CAUSE_CHARGES_DEPLETED, wumpusLocationId,
wumpusShot);
}
if (endGameEvent != null) { //Something has happened and the game should end
gameActive = false;
viewGameEvent(endGameEvent);
return;
}
viewGameEvent(new EventShot());
wumpus.wakeUp(); //Wakes up because of shooting
break;
}
//Now if wumpus woke up, it moves
if (wumpus.isAwake()) {
wumpus.moveAtRandom();
if (player.getLocation().hasObject(wumpus)) {
gameActive = false;
viewGameEvent(new EventDefeat(wumpusEncountered ?
EventDefeat.CAUSE_WUMPUS_WAS_IN_CAVE : EventDefeat.CAUSE_WUMPUS_MOVED_INTO_CAVE));
return;
} else {
if (wumpusEncountered) { //Don't report anything if wumpus wasn't encountered, he is stealthy
viewGameEvent(new EventWumpusMoved(wumpusEncountered));
}
}
wumpus.sleep();
}
if (action.getActionType() == PlayerAction.ACTION_MOVE)
checkFeelings();
}
private int moveAndCheckHazards(Player player, Room enteredRoom) {
player.setLocation(enteredRoom);
if (enteredRoom.hasObjectType(Pit.class)) {
return HAZARD_PIT;
} else if (enteredRoom.hasObjectType(Bats.class)) {
player.setRandomLocation(map, false);
Room newRoom = player.getLocation();
viewGameEvent(new EventLocationChange(newRoom, EventLocationChange.CAUSE_BATS));
return moveAndCheckHazards(player, newRoom);
} else if (enteredRoom.hasObjectType(Wumpus.class)) {
return HAZARD_WUMPUS;
}
return HAZARD_NONE;
}
private void checkFeelings() {
boolean pitsNearby = false;
boolean batsNearby = false;
boolean wumpusNearby = false;
Room currRoom = player.getLocation();
for (int passage = currRoom.getPassagesCount() - 1; passage >= 0; passage--) {
Room connectedRoom = currRoom.getNextRoom(passage);
if (connectedRoom.hasObjectType(Pit.class)) {
pitsNearby |= true;
}
if (connectedRoom.hasObjectType(Bats.class)) {
batsNearby |= true;
}
if (connectedRoom.hasObjectType(Wumpus.class)) {
wumpusNearby |= true;
}
}
viewGameEvent(new EventFeel(pitsNearby, batsNearby, wumpusNearby));
}
private void viewGameEvent(Event event) {
if (eventListener != null) {
eventListener.viewGameEvent(event);
}
}
public String getPlayerId() { //Currently only one player exists
return player.getId();
}
public Map getMap() {
return map;
}
public int getPlayerCharges(String playerId) {
return player.getChargesLeft();
}
public boolean isGameActive() {
return gameActive;
}
}

View File

@ -0,0 +1,43 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.model;
/**
*
* @author Malcolm
*/
public class Event {
private int eventType;
public static final int EVENT_PLAYER_MOVED = 1;
public static final int EVENT_PLAYER_SHOT = 2;
public static final int EVENT_PLAYER_FEELS = 3;
public static final int EVENT_WUMPUS_ESCAPED = 4;
public static final int EVENT_VICTORY = -1;
public static final int EVENT_DEFEAT = -2;
public Event(int eventType) {
this.eventType = eventType;
}
public int getEventType() {
return eventType;
}
}

View File

@ -0,0 +1,91 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.model;
/**
*
* @author Malcolm
*/
public class EventDefeat extends EventEnd {
private boolean wumpusShot = false; //For a rare case when player shot himself but managed to kill wumpus
public static final int CAUSE_PLAYER_SHOT_HIMSELF = 1;
public static final int CAUSE_CHARGES_DEPLETED = 2;
public static final int CAUSE_FELL_INTO_PIT = 3;
public static final int CAUSE_WUMPUS_WAS_IN_CAVE = 4;
public static final int CAUSE_WUMPUS_MOVED_INTO_CAVE = 5;
private int cause;
public EventDefeat(int cause, int wumpusRoomId, boolean wumpusShot) {
super(EVENT_DEFEAT, wumpusRoomId);
this.cause = cause;
this.wumpusShot = wumpusShot;
}
public EventDefeat(int cause, int wumpusRoomId) {
this(cause, wumpusRoomId, false);
}
public EventDefeat(int cause) {
this(cause, -1);
}
public int getCause() {
return cause;
}
public boolean isWumpusShot() {
return wumpusShot;
}
public String toString() {
StringBuffer result = new StringBuffer();
switch (cause) {
case CAUSE_PLAYER_SHOT_HIMSELF:
if (wumpusShot) {
result.append("You have shot wumpus! ");
}
result.append("Unfortunately, you shot yourself.");
break;
case CAUSE_CHARGES_DEPLETED:
result.append("You have no charges left.");
break;
case CAUSE_FELL_INTO_PIT:
result.append("Yeeeeiiii! You fell into a pit.");
break;
case CAUSE_WUMPUS_MOVED_INTO_CAVE:
result.append("Wumpus moved into your room and ate you.");
break;
case CAUSE_WUMPUS_WAS_IN_CAVE:
result.append("Wumpus decided to stay in the room and ate you.");
break;
}
result.append(" You lose...");
int wumpusRoomId = getWumpusRoomId();
if (wumpusRoomId > 0) {
result.append(" Wumpus was in room ");
result.append(wumpusRoomId);
}
return result.toString();
}
}

View File

@ -0,0 +1,41 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.model;
/**
*
* @author Malcolm
*/
public class EventEnd extends Event {
private final int wumpusRoomId;
public EventEnd(int eventType, int wumpusRoomId) {
super(eventType);
this.wumpusRoomId = wumpusRoomId;
}
public EventEnd(int eventType) {
this(eventType, 0);
}
public int getWumpusRoomId() {
return wumpusRoomId > 0 ? wumpusRoomId : -1;
}
}

View File

@ -0,0 +1,57 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.model;
/**
*
* @author Malcolm
*/
public class EventFeel extends Event {
private boolean pitNearby;
private boolean batsNearby;
private boolean wumpusNearby;
public EventFeel(boolean pitNearby, boolean batsNearby, boolean wumpusNearby) {
super(EVENT_PLAYER_FEELS);
this.pitNearby = pitNearby;
this.batsNearby = batsNearby;
this.wumpusNearby = wumpusNearby;
}
public boolean isPitNearby() {
return pitNearby;
}
public boolean areBatsNearby() {
return batsNearby;
}
public boolean isWumpusNearby() {
return wumpusNearby;
}
public String toString() {
if (pitNearby || batsNearby || wumpusNearby) {
return (pitNearby ? "You feel a draft. " : "") +
(batsNearby ? "You hear bats flapping their wings. " : "") +
(wumpusNearby ? "You feel wumpus is near!" : "");
} else return "You feel nothing";
}
}

View File

@ -0,0 +1,82 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.model;
import com.malcolmsoft.wumpus.maps.Room;
/**
*
* @author Malcolm
*/
public class EventLocationChange extends Event {
public static final int CAUSE_PLAYER = 0;
public static final int CAUSE_BATS = 1;
public static final int CAUSE_SPAWN = 2;
private int newRoomId;
private int[] connectedRoomsIds;
private int cause;
public EventLocationChange(Room newRoom, int cause) {
super(EVENT_PLAYER_MOVED);
this.newRoomId = newRoom.getId();
this.connectedRoomsIds = newRoom.getConnectedRoomsIds();
this.cause = cause;
}
public int getNewRoomId() {
return newRoomId;
}
public int[] getConnectedRoomsIds() {
return connectedRoomsIds;
}
public int getCause() {
return cause;
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append(connectedRoomsIds[0]);
if (connectedRoomsIds.length > 1) {
for (int passagePos = 1; passagePos < connectedRoomsIds.length - 1; passagePos++) {
buf.append(", ");
buf.append(connectedRoomsIds[passagePos]);
}
buf.append(" and ");
buf.append(connectedRoomsIds[connectedRoomsIds.length - 1]);
}
String messageStart = null;
switch (cause) {
case CAUSE_PLAYER:
messageStart = "You moved into room ";
break;
case CAUSE_BATS:
messageStart = "Bats snatched you and dragged into room ";
break;
case CAUSE_SPAWN:
messageStart = "You start in the room ";
break;
}
return messageStart + newRoomId + " with passages leading to " + buf.toString() + ".";
}
}

View File

@ -0,0 +1,34 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.model;
/**
*
* @author Malcolm
*/
public class EventShot extends Event {
public EventShot() {
super(EVENT_PLAYER_SHOT);
}
public String toString() {
return "You have missed";
}
}

View File

@ -0,0 +1,40 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.model;
/**
*
* @author Malcolm
*/
public class EventVictory extends EventEnd {
public EventVictory(int wumpusRoomId) {
super(EVENT_VICTORY, wumpusRoomId);
}
public EventVictory() {
this(-1);
}
public String toString() {
int wumpusRoomId = getWumpusRoomId();
return "You have shot wumpus!" + (wumpusRoomId > 0 ? " Wumpus was in room " +
Integer.toString(wumpusRoomId) : "") + " You win!";
}
}

View File

@ -0,0 +1,41 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.model;
/**
*
* @author Malcolm
*/
public class EventWumpusMoved extends Event {
private boolean wumpusEncountered;
public EventWumpusMoved(boolean wumpusEncountered) {
super(EVENT_WUMPUS_ESCAPED);
this.wumpusEncountered = wumpusEncountered;
}
public boolean wasWumpusEncountered() {
return wumpusEncountered;
}
public String toString() {
return (wumpusEncountered ? "You bump into wumpus! " : "") + "Wumpus moved to another cave.";
}
}

View File

@ -0,0 +1,77 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.model;
import com.malcolmsoft.wumpus.maps.Map;
import com.malcolmsoft.wumpus.maps.Room;
import java.util.Random;
/**
*
* @author Malcolm
*/
public class GameObject {
private Room location;
private boolean shootable;
protected static final Random RANDOM = new Random();
public GameObject(boolean shootable) {
this.shootable = shootable;
}
public GameObject() {
this.shootable = false;
}
public Room getLocation() {
return location;
}
public void setRandomLocation(Map map, boolean searchEmptyLocation) {
if (location != null) {
location.removeObject(this);
}
do {
int newId = RANDOM.nextInt(map.getRoomsCount()) + 1;
location = map.getRoom(newId);
} while (searchEmptyLocation && !location.isEmpty());
location.addObject(this); //Add backwards link to this object
}
public void setRandomLocation(Map map) {
setRandomLocation(map, true);
}
public void setLocation(Room room) {
if (location != null) {
location.removeObject(this);
}
location = room;
location.addObject(this);
}
public boolean isShootable() {
return shootable;
}
}

View File

@ -0,0 +1,26 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.model;
/**
*
* @author Malcolm
*/
public class Pit extends GameObject {}

View File

@ -0,0 +1,103 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.model;
import com.malcolmsoft.wumpus.maps.InvalidRoomIdException;
import com.malcolmsoft.wumpus.maps.Map;
import com.malcolmsoft.wumpus.maps.Room;
import java.util.Enumeration;
import java.util.Vector;
/**
*
* @author Malcolm
*/
public class Player extends GameObject {
private String id;
private int chargesLeft;
public static final int STARTING_CHARGES = 5;
public Player(String id) {
super(true);
this.id = id;
resetWeapons();
}
Vector shoot(Map map, int[] roomIds) { //From current location
Vector shotObjects = new Vector();
int chargesUsed = Math.min(chargesLeft, roomIds.length);
Room previousRoom = null;
Room currRoom = getLocation();
for (int roomPos = 0; roomPos < chargesUsed; roomPos++) {
Room nextRoom = null;
try {
nextRoom = map.getRoom(roomIds[roomPos]);
} catch (InvalidRoomIdException ex) {}
//You can't shoot through non-existent passage or back and forth, so...
if (nextRoom == null || nextRoom == previousRoom || !currRoom.connectsTo(nextRoom)) {
int passagesTotal = currRoom.getPassagesCount();
int randomPassage = RANDOM.nextInt(passagesTotal); //Choose random passage
nextRoom = currRoom.getNextRoom(randomPassage);
if (nextRoom == previousRoom) { //Impossible, so we fix this
if (randomPassage == passagesTotal - 1) {
randomPassage--;
} else {
randomPassage++;
}
nextRoom = currRoom.getNextRoom(randomPassage);
}
}
previousRoom = currRoom;
currRoom = nextRoom;
Enumeration contentsEn = currRoom.contents();
while (contentsEn.hasMoreElements()) {
GameObject nextObject = (GameObject)contentsEn.nextElement();
if (nextObject.isShootable()) {
shotObjects.addElement(nextObject);
}
}
}
chargesLeft -= chargesUsed; //Only if shooting is successful
return shotObjects;
}
public String getId() {
return id;
}
public int getChargesLeft() {
return chargesLeft;
}
public boolean chargesDepleted() {
return chargesLeft <= 0;
}
public void resetWeapons() {
chargesLeft = STARTING_CHARGES;
}
}

View File

@ -0,0 +1,45 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.model;
/**
*
* @author Malcolm
*/
public class PlayerAction {
private String playerId;
private int actionType;
static final int ACTION_MOVE = 0;
static final int ACTION_SHOOT = 1;
public PlayerAction(String playerId, int actionType) {
this.playerId = playerId;
this.actionType = actionType;
}
public String getPlayerId() {
return playerId;
}
public int getActionType() {
return actionType;
}
}

View File

@ -0,0 +1,37 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.model;
/**
*
* @author Malcolm
*/
public class PlayerActionMove extends PlayerAction {
private int newRoomId;
public PlayerActionMove(String playerId, int newRoomId) {
super(playerId, ACTION_MOVE);
this.newRoomId = newRoomId;
}
public int getNewRoomId() {
return newRoomId;
}
}

View File

@ -0,0 +1,37 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.model;
/**
*
* @author Malcolm
*/
public class PlayerActionShoot extends PlayerAction {
private int[] roomsToShoot;
public PlayerActionShoot(String playerId, int[] roomsToShoot) {
super(playerId, ACTION_SHOOT);
this.roomsToShoot = roomsToShoot;
}
public int[] getRoomsToShoot() {
return roomsToShoot;
}
}

View File

@ -0,0 +1,54 @@
/*
Copyright © 2009 Alexander Gazarov
This file is part of Hunt The Wumpus, Java ME application based on BASIC game by Gregory Yob.
Hunt The Wumpus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hunt The Wumpus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Hunt The Wumpus. If not, see <http://www.gnu.org/licenses/>.
*/
package com.malcolmsoft.wumpus.model;
import com.malcolmsoft.wumpus.maps.Room;
/**
*
* @author Malcolm
*/
public class Wumpus extends GameObject {
private boolean awake = false;
public Wumpus() {
super(true);
}
public void moveAtRandom() {
if (RANDOM.nextInt(4) == 0) return; //1 in 4 chance that wumpus won't move (he's lazy)
Room currRoom = getLocation();
int randomPassage = RANDOM.nextInt(currRoom.getPassagesCount());
setLocation(currRoom.getNextRoom(randomPassage));
}
public void sleep() {
awake = false;
}
public void wakeUp() {
awake = true;
}
public boolean isAwake() {
return awake;
}
}