/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
* Copyright 2008, 2010 Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This file is available and licensed under the following license:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Oracle Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package dukeman;
import javafx.scene.*;
import java.util.Vector;
public def ENEMY_HOME_WIDTH = 8;
public def ENEMY_HOME_HEIGHT = 5;
public def WIDTH = 28;
public def HEIGHT = 31;
public class LevelData {
public-init var levelNumber:Integer;
public-init var maze:Wall[];
public-init var dots:Dot[];
public-init var dukeInitCoord:Coord;
public-init var enemyHome:Coord;
public-init var levelData:Vector;
public function canMove(node: Node, direction: Direction): Boolean {
if (node.translateX mod Config.CELL_SIZE != 0) {
return direction.offsetY == 0;
}
if (node.translateY mod Config.CELL_SIZE != 0) {
return direction.offsetX == 0;
}
var x: Integer = node.translateX / Config.CELL_SIZE +
direction.offsetX as Integer;
var y: Integer = node.translateY / Config.CELL_SIZE +
direction.offsetY as Integer;
if (x < 0) {
x = WIDTH - 1;
}
if (x >= WIDTH) {
x = 0;
}
if (y < 0) {
y = HEIGHT - 1;
}
if (y >= HEIGHT) {
y = 0;
}
return not (levelData.elementAt(x + y*WIDTH) instanceof Wall);
}
public function move(node: Node, direction: Direction) {
var newX = node.translateX + direction.offsetX;
var newY = node.translateY + direction.offsetY;
def half = Config.CELL_SIZE / 2;
def maxX = Config.GAME_FIELD_WIDTH - Config.CELL_SIZE - half - 1;
def maxY = Config.GAME_FIELD_HEIGHT - Config.CELL_SIZE - half - 1;
if (newX < half) {
newX = maxX
} else if (newX > maxX) {
newX = half
}
if (newY < half) {
newY = maxY
} else if (newY > maxY) {
newY = half;
}
node.translateX = newX;
node.translateY = newY;
}
}
public function getLevelsCount(): Integer {
sizeof LEVELS_DATA / HEIGHT;
}
public function getLevelData(level: Integer): LevelData {
if (level < 1 or level > getLevelsCount()) {
null
} else {
var maze: Wall[];
var dots: Dot[];
var levelData = new Vector();
var dukeInitCoord: Coord;
var enemyHome: Coord;
var enemyHomeWall: Wall;
def levelPos = (level - 1) * HEIGHT;
def levelDataArr = LEVELS_DATA[levelPos..levelPos + HEIGHT - 1];
for (y in [0..<HEIGHT]) {
for (x in [0..<WIDTH]) {
def type = levelDataArr[y].substring(x, x + 1);
def xPos = x * Config.CELL_SIZE;
def yPos = y * Config.CELL_SIZE;
var levelDataElement: Node;
if (enemyHome != null and
x >= enemyHome.x and x < enemyHome.x + ENEMY_HOME_WIDTH and
y >= enemyHome.y and y < enemyHome.y + ENEMY_HOME_HEIGHT) {
if (type == ENEMY_HOME) {
levelDataElement = enemyHomeWall;
} else {
println("Invalid level data. Level = {level}, x = {x}, y = {y}");
}
} else if (type == WALL) {
var wallType = "wall";
var edges:String[];
for (i in [0..3]) {
def offsetX = NEIGHBOUR_X[i];
def offsetY = NEIGHBOUR_Y[i];
var neighbourX = x + offsetX;
var neighbourY = y + offsetY;
if (neighbourX < 0) {
neighbourX = WIDTH - 1
} else if (neighbourX >= WIDTH) {
neighbourX = 0
}
if (neighbourY < 0) {
neighbourY = HEIGHT - 1
} else if (neighbourY >= HEIGHT) {
neighbourY = 0
}
def neighbour1 = levelDataArr[y].substring(neighbourX, neighbourX + 1);
def neighbour2 = levelDataArr[neighbourY].substring(neighbourX, neighbourX + 1);
def neighbour3 = levelDataArr[neighbourY].substring(x, x + 1);
if (neighbour1 != WALL or
neighbour2 != WALL or
neighbour3 != WALL) {
wallType += "0";
} else {
wallType += "1";
if ((x == 0 and i mod 3 == 0) or
(x == WIDTH - 1 and i mod 3 != 0)) {
insert "edgevert{i}" into edges;
}
if ((y == 0 and i < 2) or
(y == HEIGHT - 1 and i >= 2)) {
insert "edgehor{i}" into edges;
}
}
}
def wall = Wall {
type: [wallType, edges]
translateX: xPos
translateY: yPos
}
insert wall into maze;
levelDataElement = wall;
} else if (type == DOT or type == BIG_DOT) {
var dot = Dot {
small: type == DOT
translateX: if (type == DOT) xPos else xPos - Config.CELL_SIZE / 2
translateY: if (type == DOT) yPos else yPos - Config.CELL_SIZE / 2
}
insert dot into dots;
levelDataElement = dot;
} else if (type == DUKE_START) {
if (dukeInitCoord == null) {
dukeInitCoord = Coord {
x: xPos
y: yPos
}
} else {
if (dukeInitCoord.x == (x - 1) * Config.CELL_SIZE and
dukeInitCoord.y == yPos) {
dukeInitCoord = Coord {
x: dukeInitCoord.x + Config.CELL_SIZE / 2
y: yPos
}
} else {
println("Invalid level data. Level = {level}, x = {x}, y = {y}");
}
}
} else if (type == ENEMY_HOME) {
if (enemyHome == null) {
enemyHome = Coord {
x: x
y: y
}
enemyHomeWall = Wall {
type: "enemyhome"
translateX: xPos + Config.CELL_SIZE / 2
translateY: yPos + Config.CELL_SIZE / 2
}
insert enemyHomeWall into maze;
levelDataElement = enemyHomeWall;
} else {
println("Invalid level data. Level = {level}, x = {x}, y = {y}");
}
} else if (type != EMPTY) {
println("Invalid level data. Level = {level}, x = {x}, y = {y}");
}
levelData.addElement(levelDataElement);
}
}
if (dukeInitCoord == null) {
println("Duke start position was not found. Level = {level}");
}
LevelData {
levelNumber: level
maze: maze
dots: dots
dukeInitCoord: dukeInitCoord
enemyHome: enemyHome
levelData: levelData
}
}
}
def NEIGHBOUR_X = [-1, 1, 1, -1];
def NEIGHBOUR_Y = [-1, -1, 1, 1];
def EMPTY = " ";
def WALL = "X";
def DOT = ".";
def BIG_DOT = "o";
def DUKE_START = "S";
def ENEMY_HOME = "E";
def LEVELS_DATA = [
"XXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"X..........................X",
"X.XXXX.XXXXX.XX.XXXXX.XXXX.X",
"XoXXXX.XXXXX.XX.XXXXX.XXXXoX",
"X.XXXX.XXXXX.XX.XXXXX.XXXX.X",
"X...XX.......XX.......XX...X",
"XXX.XX.XXXXX.XX.XXXXX.XX.XXX",
"XXX.XX.XXXXX.XX.XXXXX.XX.XXX",
"XXX.XX.XXXXX.XX.XXXXX.XX.XXX",
" ..........XX......... ",
"XXX.XXXXXXXX.XX.XXXXXXXX.XXX",
"XXX.XXXXXXXX.XX.XXXXXXXX.XXX",
"X......XX.... ....XX......X",
"X.XXXX.XX.EEEEEEEE.XX.XXXX.X",
"X.XXXX.XX.EEEEEEEE.XX.XXXX.X",
"X.XXXX....EEEEEEEE....XXXX.X",
"X.XXXX.XX.EEEEEEEE.XX.XXXX.X",
"X.XXXX.XX.EEEEEEEE.XX.XXXX.X",
"X......XX..........XX......X",
"XXX.XXXXXXXX.XX.XXXXXXXX.XXX",
"XXX.XXXXXXXX.XX.XXXXXXXX.XXX",
" ..........XX.......... ",
"XXX.XX.XXXXX.XX.XXXXX.XX.XXX",
"XXX.XX.XXXXX.XX.XXXXX.XX.XXX",
"XXX.XX.XXXXX.XX.XXXXX.XX.XXX",
"X...XX.......SS.......XX...X",
"X.XXXX.XXXXX.XX.XXXXX.XXXX.X",
"XoXXXX.XXXXX.XX.XXXXX.XXXXoX",
"X.XXXX.XXXXX.XX.XXXXX.XXXX.X",
"X..........................X",
"XXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"X.... ....................X",
"X.EEEEEEEE.XX.XXXXX.XXXXXX.X",
"X.EEEEEEEE.XX.XXXXX.XXXXXX.X",
"X.EEEEEEEE.XXo......XXXXXX.X",
"X.EEEEEEEE.XXXXXXXX........X",
"X.EEEEEEEE.XXXXXXXX.XXXXXX.X",
"X...................XXXXXX.X",
"X.XXXXXXXX.XX.XX.XX.XX.....X",
"X.XXXXXXXX.XX.XX.XX.XX.XXX.X",
"X......oXX.XX.XX.XX.XX.XXX.X",
"X.XXXXX.XX.XX.XX.XX.XX.XX..X",
"X.XXXXX.XX.XX.XX.XX.XX.XX.XX",
"X....XX.XX.XX.XX.XX.XX.XX.XX",
"XXXX.XX.XX.XX....XX.XX.XX.XX",
"XXXX.XX.XX.XXXXXXXX.XX.XX.XX",
"XXXX.XX.XX.XXXXXXXX.XX.XX.XX",
" ........................ ",
"XX.XXXXXXXXX.XX.XXXXXXXXX.XX",
"XX.XXXXXXXXX.XX.XXXXXXXXX.XX",
"XX...........XX...........XX",
"XXXX.XX.XXXXXXXXXXXX.XX.XXXX",
"XXXX.XX.XXXXXXXXXXXX.XX.XXXX",
"X....XX......SS......XX....X",
"X.XXXXXXXX.XXXXXX.XXXXXXXX.X",
"X.XXXXXXXX.XXXXXX.XXXXXXXX.X",
"X....XX..............XX....X",
"XXXX.XX.XXXX.XX.XXXX.XX.XXXX",
"XXXX.XX.XXXX.XX.XXXX.XX.XXXX",
"XXo .........XX......... oXX",
"XXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXX XXXXXXXXXXXXXXXXXX XXXX",
"X..........................X",
"XXXXXXX.XXXXXXXXXXXX.XXXXXXX",
"XXXXXXX.XXXXXXXXXXXX.XXXXXXX",
"Xo........................oX",
"X.XXXXXXXXXX.XX.XXXXXXXXXX.X",
"X.XXXXXXXXXX.XX.XXXXXXXXXX.X",
"X.XXXX.......XX.......XXXX.X",
"X.XXXX.XX.XXXXXXXX.XX.XXXX.X",
"X......XX.XXXXXXXX.XX......X",
"X.XXXXXXX. SS .XXXXXXX.X",
"X.XXXXXXX.XXXXXXXX.XXXXXXX.X",
"X.........XXXXXXXX.........X",
"XXXX.XXXX.... ....XXXX.XXXX",
"XXXX.XXXX.EEEEEEEE.XXXX.XXXX",
"X....XXXX.EEEEEEEE.XXXX....X",
"X.XX.XXXX.EEEEEEEE.XXXX.XX.X",
"X.XX......EEEEEEEE......XX.X",
"X.XXXXXXX.EEEEEEEE.XXXXXXX.X",
"X.XXXXXXX..........XXXXXXX.X",
"X.........XXXXXXXX.........X",
"X.XXXXX.XXXXXXXXXXXX.XXXXX.X",
"X.XXXXX.XXXX....XXXX.XXXXX.X",
"X............XX............X",
"XXXX.XXXXXXX.XX.XXXXXXX.XXXX",
"XXXX.XXXXXXX.XX.XXXXXXX.XXXX",
"X............XX............X",
"X.XX.XX.XXXXXXXXXXXX.XX.XX.X",
"X.XX.XX.XXXXXXXXXXXX.XX.XX.X",
"X....XXo............oXX....X",
"XXXX XXXXXXXXXXXXXXXXXX XXXX",
];