public void calculate(Region region) { width = region.getWidth(); height = region.getHeight(); values = new int[width,height]; calc = new double[width,height]; lights = new List<Light>(); lightingModel = region.getLightingModel(); //Blank out the entire region with base light for(int x=0; x < width; x++) { for(int y=0; y < height; y++) { if(TerrainManager.hasParameter(region.getTerrain(x, y), TerrainParameter.FIRE)) { calc[x,y] = ((MAX_LIGHT / 2) * RandomNumber.RandomDouble()) + (MAX_LIGHT / 2); lights.Add(new Light(x,y,calc[x,y])); } else { calc[x,y] = baseLight(); } } } //Add lights for appropriate monsters calculateMonsterLights(); //Add lights for appropriate building features calculateBuildingFeatureLight(); //Add lights for items calculateItemLights(); //Propogate light from point sources foreach(Light tempLight in lights) { spreadLight(tempLight.x, tempLight.y, tempLight.intensity, baseLight()); } //Cover buildings if roofs prevent lighting calculateBuildingCoverLight(); //Converate raw values to graded values calcToValue(); }
public static void addGraveyard(int width, int height, int stx, int sty, Region region) { int treesPlaced = 0; region.getTerrain(stx, sty).setCode(TerrainCode.ROCK); TerrainManager.removeParameters(region.getTerrain(stx, sty)); region.getTerrain(stx + width, sty).setCode(TerrainCode.ROCK); TerrainManager.removeParameters(region.getTerrain(stx + width, sty)); region.getTerrain(stx, sty + height).setCode(TerrainCode.ROCK); TerrainManager.removeParameters(region.getTerrain(stx, sty + height)); region.getTerrain(stx + width, sty + height).setCode(TerrainCode.ROCK); TerrainManager.removeParameters(region.getTerrain(stx + width, sty + height)); for(int x=stx; x < stx + width; x++) { for(int y=sty; y < sty + height; y++) { if(x >= 0 && x < region.getWidth() && y >= 0 && y < region.getHeight()) { if(x % 2 == 0 && y % 3 == 0) { if(RandomNumber.RandomDouble() < 0.75) { if(RandomNumber.RandomDouble() < 0.01) { region.getTerrain(x, y).getParameters().Add(TerrainParameter.HAS_GRAVE, EnumUtil.EnumName<GraveCode>(GraveCode.SPECIAL)); } else { region.getTerrain(x, y).getParameters().Add(TerrainParameter.HAS_GRAVE, EnumUtil.EnumName<GraveCode>(GraveCode.NORMAL)); } } else { if(region.getTerrain(x, y).getCode() == TerrainCode.GRASS) { if(RandomNumber.RandomDouble() < 0.25 && treesPlaced < 2) { region.getTerrain(x, y).getParameters().Add(TerrainParameter.HAS_TREE, EnumUtil.EnumName<TreeCode>(TreeCode.APPLE_TREE)); treesPlaced++; } } else if(region.getTerrain(x, y).getCode() == TerrainCode.STONE_FLOOR) { if(RandomNumber.RandomDouble() < 0.25 && treesPlaced < 5) { region.getTerrain(x, y).getParameters().Add(TerrainParameter.HAS_MOSS, ""); treesPlaced++; } } } } else { //do nothing } } } } }
public static void makePath(Region region, bool nExit, bool eExit, bool sExit, bool wExit) { int pathX = 0; int pathY = 0; region.getTerrain((int)(region.getWidth() / 2), (int)(region.getHeight() / 2)).setCode(TerrainCode.PATH); region.getTerrain((int)(region.getWidth() / 2)-1, (int)(region.getHeight() / 2)).setCode(TerrainCode.PATH); region.getTerrain((int)(region.getWidth() / 2)+1, (int)(region.getHeight() / 2)).setCode(TerrainCode.PATH); region.getTerrain((int)(region.getWidth() / 2), (int)(region.getHeight() / 2)-1).setCode(TerrainCode.PATH); region.getTerrain((int)(region.getWidth() / 2), (int)(region.getHeight() / 2)+1).setCode(TerrainCode.PATH); if(nExit) { pathX = (int)(region.getWidth() / 2); for(pathY = 0; pathY < region.getHeight() / 2; pathY++) { region.getTerrain(pathX, pathY).setCode(TerrainCode.PATH); region.getTerrain(pathX-1, pathY).setCode(TerrainCode.PATH); region.getTerrain(pathX+1, pathY).setCode(TerrainCode.PATH); } } if(eExit) { pathY = (int)(region.getWidth() / 2); for(pathX = 0; pathX < region.getWidth() / 2; pathX++) { region.getTerrain((region.getWidth()/2) + pathX, pathY).setCode(TerrainCode.PATH); region.getTerrain((region.getWidth()/2) + pathX, pathY-1).setCode(TerrainCode.PATH); region.getTerrain((region.getWidth()/2) + pathX, pathY+1).setCode(TerrainCode.PATH); } } if(sExit) { pathX = (int)(region.getWidth() / 2); for(pathY = 0; pathY < region.getHeight() / 2; pathY++) { region.getTerrain(pathX, (region.getHeight()/2) + pathY).setCode(TerrainCode.PATH); region.getTerrain(pathX-1, (region.getHeight()/2) + pathY).setCode(TerrainCode.PATH); region.getTerrain(pathX+1, (region.getHeight()/2) + pathY).setCode(TerrainCode.PATH); } } if(wExit) { pathY = (int)(region.getWidth() / 2); for(pathX = 0; pathX < region.getWidth() / 2; pathX++) { region.getTerrain(pathX, pathY).setCode(TerrainCode.PATH); region.getTerrain(pathX, pathY-1).setCode(TerrainCode.PATH); region.getTerrain(pathX, pathY+1).setCode(TerrainCode.PATH); } } }
public static List<Position> getTerrainPositions(TerrainCode code, Region region, bool allowParameters, bool includeEdges) { int edgeAdjust=0; if(!includeEdges) { edgeAdjust=1; } List<Position> positions = new List<Position>(); for(int x=0+edgeAdjust; x < region.getWidth() - (edgeAdjust * 2); x++) { for(int y=0+edgeAdjust; y < region.getHeight() - (edgeAdjust * 2); y++) { if(region.getTerrain(x, y).getCode() == code && ((!allowParameters && region.getTerrain(x, y).getParameters().Count == 0) || allowParameters)) { positions.Add(new Position(x,y)); } } } return positions; }
public List<Position> findPath(Region region, int maxSearchDistance, Monster mover, int sx, int sy, int tx, int ty) { //Initialize this.region = region; nodes = new PathNode[region.getWidth(),region.getHeight()]; for (int x=0;x<region.getWidth();x++) { for (int y=0;y<region.getHeight();y++) { nodes[x,y] = new PathNode(x,y); } } // easy first check, if the destination is blocked, we can't get there if(!TerrainManager.allowsMonsterToPass(region.getTerrain(tx, ty), mover)) { return null; } // initial state for A*. The closed group is empty. Only the starting // tile is in the open list and it's cost is zero, i.e. we're already there nodes[sx,sy].cost = 0; nodes[sx,sy].depth = 0; closed.Clear(); open.clear(); open.add(nodes[sx,sy]); nodes[tx,ty].parent = null; // while we haven't found the goal and haven't exceeded our max search depth int maxDepth = 0; while ((maxDepth < maxSearchDistance) && (open.size() != 0)) { // pull out the first node in our open list, this is determined to // be the most likely to be the next step based on our heuristic PathNode current = getFirstInOpen(); if (current == nodes[tx,ty]) { break; } removeFromOpen(current); addToClosed(current); // search through all the neighbours of the current node evaluating // them as next steps for (int x=-1;x<2;x++) { for (int y=-1;y<2;y++) { // not a neighbour, its the current tile if ((x == 0) && (y == 0)) { continue; } // if we're not allowing diaganol movement then only // one of x or y can be set if ((x != 0) && (y != 0)) { continue; } // determine the location of the neighbour and evaluate it int xp = x + current.x; int yp = y + current.y; if (isValidLocation(mover,sx,sy,xp,yp)) { // the cost to get to this node is cost the current plus the movement // cost to reach this node. Note that the heursitic value is only used // in the sorted open list float nextStepCost = current.cost + getMovementCost(mover, current.x, current.y, xp, yp); PathNode neighbour = nodes[xp,yp]; // if the new cost we've determined for this node is lower than // it has been previously makes sure the node hasn't been discarded. We've // determined that there might have been a better path to get to // this node so it needs to be re-evaluated if (nextStepCost < neighbour.cost) { if (inOpenList(neighbour)) { removeFromOpen(neighbour); } if (inClosedList(neighbour)) { removeFromClosed(neighbour); } } // if the node hasn't already been processed and discarded then // reset it's cost to our current cost and add it as a next possible // step (i.e. to the open list) if (!inOpenList(neighbour) && !(inClosedList(neighbour))) { neighbour.cost = nextStepCost; neighbour.heuristic = getHeuristicCost(mover, xp, yp, tx, ty); maxDepth = Math.Max(maxDepth, neighbour.setParent(current)); addToOpen(neighbour); } } } } } // since we've got an empty open list or we've run out of search // there was no path. Just return null if (nodes[tx,ty].parent == null) { return null; } // At this point we've definitely found a path so we can uses the parent // references of the nodes to find out way from the target location back // to the start recording the nodes on the way. List<Position> path = new List<Position>(); PathNode target = nodes[tx,ty]; while (target != nodes[sx,sy]) { Position pos = new Position(target.x, target.y); path.Insert(0, pos); target = target.parent; } Position pos2 = new Position(sx, sy); path.Insert(0, pos2); // thats it, we have our path return path; }
public static void buildByArray(Region region, int startX, int startY, Building building, int[,] plan) { for (int x = 0; x < BuildingManager.getWidth(building.getBuildingType()); x++) { for (int y = 0; y < BuildingManager.getHeight(building.getBuildingType()); y++) { if (x + startX < region.getWidth() && x + startX > 0 && y + startY < region.getHeight() && y + startY > 0) { switch (plan[y,x]) { case 0: region.getTerrain(startX + x, startY + y).setCode(TerrainCode.STONE_FLOOR); break; case 1: region.getTerrain(startX + x, startY + y).setCode(TerrainCode.STONE_WALL); break; case 9: region.getTerrain(startX + x, startY + y).setCode(TerrainCode.STONE_FLOOR); region.getTerrain(startX + x, startY + y).getParameters().Add(TerrainParameter.HAS_DOOR, Enum.GetName(typeof(DoorCode), DoorCode.CLOSED)); building.setDoor(startX + x, startY + y); break; case 8: region.getTerrain(startX + x, startY + y).setCode(TerrainCode.STONE_WALL); region.getTerrain(startX + x, startY + y).getParameters().Add(TerrainParameter.HAS_SIGN, building.getName()); break; case 2: region.getTerrain(startX + x, startY + y).setCode(TerrainCode.STONE_FLOOR); Monster newMon = new Monster(); switch (building.getBuildingType()) { case BuildingType.BANK: newMon.monsterCode = MonsterCode.HUMAN; newMon.role = MonsterRole.BANKER; break; case BuildingType.INN: newMon.monsterCode = MonsterCode.HUMAN; newMon.role = MonsterRole.NULL; break; case BuildingType.FOOD_STORE: newMon.monsterCode = MonsterCode.HUMAN; newMon.role = MonsterRole.CHEF; break; case BuildingType.TOOL_STORE: newMon.monsterCode = MonsterCode.HUMAN; newMon.role = MonsterRole.HANDYMAN; break; } MonsterActionManager.initialize(newMon); newMon.setPosition(startX + x, startY + y); region.getMonsters().Add(newMon); break; case 3: //Add a bed region.getTerrain(startX + x, startY + y).setCode(TerrainCode.STONE_FLOOR); region.getTerrain(startX + x, startY + y).getParameters().Add(TerrainParameter.HAS_BED, ""); break; } } } } }