From bb6aebe27fb69a2fd5b5c4faf8ae7adec25f1904 Mon Sep 17 00:00:00 2001 From: Tuomo Untinen Date: Thu, 8 Feb 2024 23:11:07 +0200 Subject: [PATCH] #700 Adds scenario Destroyed planet. --- .../player/StartingScenario.java | 19 ++- .../openRealmOfStars/player/fleet/Fleet.java | 11 +- .../openRealmOfStars/starMap/SquareInfo.java | 10 +- .../org/openRealmOfStars/starMap/StarMap.java | 13 ++ .../starMap/StarMapGenerator.java | 140 ++++++++++++++++++ .../org/openRealmOfStars/game/GameTest.java | 4 +- 6 files changed, 183 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/openRealmOfStars/player/StartingScenario.java b/src/main/java/org/openRealmOfStars/player/StartingScenario.java index 6926f9f4f..971434383 100644 --- a/src/main/java/org/openRealmOfStars/player/StartingScenario.java +++ b/src/main/java/org/openRealmOfStars/player/StartingScenario.java @@ -67,7 +67,11 @@ public enum StartingScenario { /** * Temperate Arid planet with 3 farms, 5 population but no starting ships. */ - FARMING_PLANET; + FARMING_PLANET, + /** + * Start without home planet with 4 scouts and 2 colony ships. + */ + DESTROYED_HOME_PLANET; /** @@ -85,7 +89,8 @@ public int getIndex() { case COLD_HUMID_SIZE12: return 6; case TROPICAL_HUMID_SIZE12: return 7; case HOT_ARID_SIZE12: return 8; - case FARMING_PLANET: return 8; + case FARMING_PLANET: return 9; + case DESTROYED_HOME_PLANET: return 10; default: throw new IllegalArgumentException("Unknown starting scenario."); } } @@ -106,6 +111,8 @@ public static StartingScenario getByIndex(final int index) { case 6: return COLD_HUMID_SIZE12; case 7: return TROPICAL_HUMID_SIZE12; case 8: return HOT_ARID_SIZE12; + case 9: return FARMING_PLANET; + case 10: return DESTROYED_HOME_PLANET; default: throw new IllegalArgumentException("Unknown starting scenario."); } } @@ -127,6 +134,7 @@ public String toString() { case TROPICAL_HUMID_SIZE12: return "Tropical, humid planet"; case HOT_ARID_SIZE12: return "Hot, arid planet with extra tech"; case FARMING_PLANET: return "Temperate arid farming planet, but no ships"; + case DESTROYED_HOME_PLANET: return "No home, start from deep space"; } } @@ -140,7 +148,8 @@ public String getDescription() { case RANDOM: return "Random starting scenario."; case TEMPERATE_HUMID_SIZE12: return "Temperate and humid planet with" + " ground size 12. World type is either Swamp or water planet."; - case EARTH: return "Realm starts at Earth and solar system is Sol."; + case EARTH: return "Realm starts at Earth and solar system is Sol." + + " Single start allowed."; case TEMPERATE_ARID_SIZE12: return "Temperate and arid planet with" + " ground size 12. World type is desert. Start with extra 2" + " technology."; @@ -158,6 +167,10 @@ public String getDescription() { case FARMING_PLANET: return "Temperate arid planet with 3 farms," + " ground size 12. World type is desert world. No staring ships. Extra" + " technology."; + case DESTROYED_HOME_PLANET: return "Home planet has been destroyed. Start" + + " from deep space with 4 scouts and 2 colony ships. Colony fleet in" + + " deep space provides extra research point." + + " Single start allowed."; } } diff --git a/src/main/java/org/openRealmOfStars/player/fleet/Fleet.java b/src/main/java/org/openRealmOfStars/player/fleet/Fleet.java index a08057f7b..08183bdd8 100644 --- a/src/main/java/org/openRealmOfStars/player/fleet/Fleet.java +++ b/src/main/java/org/openRealmOfStars/player/fleet/Fleet.java @@ -32,7 +32,6 @@ import org.openRealmOfStars.player.leader.Job; import org.openRealmOfStars.player.leader.Leader; import org.openRealmOfStars.player.leader.Perk; -import org.openRealmOfStars.player.race.SpaceRace; import org.openRealmOfStars.player.ship.Ship; import org.openRealmOfStars.player.ship.ShipHull; import org.openRealmOfStars.player.ship.ShipHullType; @@ -898,18 +897,12 @@ public boolean isColonyFleet() { /** * Fleet has colony ship with working colony module and at least one colonist. - * @param race Required space race for colony ship. Null if non required. * @return True if has working colony ship. */ - public boolean hasColonyShip(final SpaceRace race) { + public boolean hasColonyShip() { for (Ship ship : ships) { if (ship.isColonyShip() && ship.getColonist() > 0) { - if (race == null) { - return true; - } - if (race == ship.getHull().getRace()) { - return true; - } + return true; } } return false; diff --git a/src/main/java/org/openRealmOfStars/starMap/SquareInfo.java b/src/main/java/org/openRealmOfStars/starMap/SquareInfo.java index eff10567d..bab3995f8 100644 --- a/src/main/java/org/openRealmOfStars/starMap/SquareInfo.java +++ b/src/main/java/org/openRealmOfStars/starMap/SquareInfo.java @@ -1,7 +1,7 @@ package org.openRealmOfStars.starMap; /* * Open Realm of Stars game project - * Copyright (C) 2016-2023 Tuomo Untinen + * Copyright (C) 2016-2024 Tuomo Untinen * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -57,6 +57,10 @@ public class SquareInfo { * Black hole info center, value match on list number */ public static final byte TYPE_BLACKHOLE_CENTER = 5; + /** + * Deep space start for realm. + */ + public static final byte TYPE_DEEP_SPACE_START = 6; /** * Asccension vein info, value match on player index. @@ -169,6 +173,8 @@ public boolean isVisibilityBlocked() { return false; case TYPE_BLACKHOLE_CENTER: return true; + case TYPE_DEEP_SPACE_START: + return false; case TYPE_ASCENSION_VEIN: return false; default: @@ -194,6 +200,8 @@ public boolean isBlocked() { return true; case TYPE_BLACKHOLE_CENTER: return true; + case TYPE_DEEP_SPACE_START: + return false; case TYPE_ASCENSION_VEIN: return false; default: diff --git a/src/main/java/org/openRealmOfStars/starMap/StarMap.java b/src/main/java/org/openRealmOfStars/starMap/StarMap.java index e7c39c0d4..8e13d6b3d 100644 --- a/src/main/java/org/openRealmOfStars/starMap/StarMap.java +++ b/src/main/java/org/openRealmOfStars/starMap/StarMap.java @@ -3006,8 +3006,16 @@ public int getTotalProductionByPlayerPerTurn(final int production, && info.getRuler().hasPerk(Perk.MERCHANT)) { result++; } + boolean colonyInDeepSpace = false; for (int i = 0; i < info.getFleets().getNumberOfFleets(); i++) { Fleet fleet = info.getFleets().getByIndex(i); + if (production == Planet.PRODUCTION_RESEARCH + && fleet.hasColonyShip()) { + Planet planet = getPlanetByCoordinate(fleet.getX(), fleet.getY()); + if (planet == null) { + colonyInDeepSpace = true; + } + } if (production == Planet.PRODUCTION_RESEARCH) { result = result + fleet.getTotalReseachBonus(); } @@ -3047,6 +3055,11 @@ public int getTotalProductionByPlayerPerTurn(final int production, result = result + fleet.getTotalCultureBonus(); } } + if (production == Planet.PRODUCTION_RESEARCH && colonyInDeepSpace) { + // Realms which start from deep space get extra research on colony ships + // in deep space. + result = result + 1; + } if (production == Planet.PRODUCTION_RESEARCH) { if (info.getRuler() != null && info.getRuler().hasPerk(Perk.SCIENTIST)) { diff --git a/src/main/java/org/openRealmOfStars/starMap/StarMapGenerator.java b/src/main/java/org/openRealmOfStars/starMap/StarMapGenerator.java index 1f39b646b..6deedbb9d 100644 --- a/src/main/java/org/openRealmOfStars/starMap/StarMapGenerator.java +++ b/src/main/java/org/openRealmOfStars/starMap/StarMapGenerator.java @@ -72,6 +72,11 @@ public class StarMapGenerator { * to starmap. This will not be saved on file. */ private boolean solHasAdded = false; + /** + * Just flag for galaxy generation. When this is true, destroyed planet start + * has been added to starmap. + */ + private boolean destroyedPlanetStartAdded = false; /** Solar System map for generation. */ private int[][] solarSystem; /** Maximum amount of looping when finding free solar system spot. */ @@ -88,6 +93,7 @@ public class StarMapGenerator { */ public StarMapGenerator() { solHasAdded = false; + destroyedPlanetStartAdded = false; nameGenerator = new RandomSystemNameGenerator(); } @@ -312,6 +318,91 @@ public void createRealmToPlanet(final Planet planet, playerInfo.getMsgList().addNewMessage(msgStart); } + /** + * Create realm to galaxy without planet. This will add required ships. + * This will also add message about new realm starting. + * @param x X coordinate where to start + * @param y Y coordinate where to start + * @param playerInfo Realm who is starting + * @param playerIndex Index for player + */ + public void createRealmToGalaxy(final int x, final int y, + final PlayerInfo playerInfo, final int playerIndex) { + Coordinate startCoord = new Coordinate(x, y); + makeStartingTutorialTextsInDeepSpace(playerInfo, startCoord); + Message msg = new Message( + MessageType.FLEET, playerInfo.getEmpireName() + " starts at " + + "deep space.", + Icons.getIconByName(Icons.ICON_CULTURE)); + PlayerStartEvent event = new PlayerStartEvent(startCoord, "Deep space", + playerIndex); + starMap.getHistory().addEvent(event); + msg.setCoordinate(startCoord); + msg.setMatchByString("Colony #0"); + if (playerInfo.getRuler() == null) { + Leader ruler = LeaderUtility.createLeader(playerInfo, null, + LeaderUtility.LEVEL_START_RULER); + ruler.setJob(Job.RULER); + ruler.setTitle(LeaderUtility.createTitleForLeader(ruler, playerInfo)); + playerInfo.getLeaderPool().add(ruler); + playerInfo.getMsgList().addNewMessage(msg); + playerInfo.setRuler(ruler); + } + ShipStat[] stats = playerInfo.getShipStatList(); + int count = 0; + for (ShipStat stat : stats) { + int numShip = 1; + if (playerInfo.getStartingScenario() + == StartingScenario.DESTROYED_HOME_PLANET) { + if (stat.getDesign().isMilitaryShip()) { + numShip = 4; + } + if (stat.getDesign().getName().startsWith("Colony")) { + numShip = 2; + } + } + for (int j = 0; j < numShip; j++) { + if (stat.getDesign().getHull().getHullType() == ShipHullType.ORBITAL) { + continue; + } + Ship ship = new Ship(stat.getDesign()); + stat.setNumberOfBuilt(stat.getNumberOfBuilt() + 1); + stat.setNumberOfInUse(stat.getNumberOfInUse() + 1); + Fleet fleet = new Fleet(ship, x, y); + playerInfo.getFleets().add(fleet); + if (ship.isColonyModule()) { + fleet.setName("Colony #" + count); + fleet.getColonyShip(false).setColonist(2); + makeStartingFleetTutorialTexts(playerInfo, fleet); + } else { + fleet.setName("Scout #" + count); + makeStartingFleetTutorialTexts(playerInfo, fleet); + } + msg = new Message(MessageType.FLEET, + fleet.getName() + " is waiting for orders.", + Icons.getIconByName(Icons.ICON_HULL_TECH)); + msg.setCoordinate(fleet.getCoordinate()); + msg.setMatchByString(fleet.getName()); + playerInfo.getMsgList().addNewMessage(msg); + count++; + } + } + Planet planet = new Planet(startCoord, "Alpha Aurora", 2, false); + planet.setTemperatureType(TemperatureType.TEMPERATE); + planet.setWaterLevel(WaterLevelType.MARINE); + planet.setGroundSize(12); + planet.generateGravityBasedOnSize(); + planet.generateWorldType(); + String backgroundStory = BackgroundStoryGenerator.generateBackgroundStory( + playerInfo, planet, starMap.getStarYear()); + playerInfo.setBackgroundStory(backgroundStory); + Message msgStart = new Message(MessageType.STORY, backgroundStory, + Icons.getIconByName(Icons.ICON_CULTURE)); + msgStart.setCoordinate(startCoord); + msgStart.setMatchByString("Colony #0"); + playerInfo.getMsgList().addNewMessage(msgStart); + } + /** * Smooth ascension veins. */ @@ -790,6 +881,29 @@ private void createSolarSystem(final int sunx, final int suny, } playerInfo.setStartingScenario(StartingScenario.TEMPERATE_HUMID_SIZE12); } + if (playerInfo.getStartingScenario() + == StartingScenario.DESTROYED_HOME_PLANET) { + if (!destroyedPlanetStartAdded) { + destroyedPlanetStartAdded = true; + int sx = sunx + DiceGenerator.getRandom(-1, 1); + int sy = suny + DiceGenerator.getRandom(-1, 1); + if (!elderRealmStart) { + createRealmToGalaxy(sx, sy, playerInfo, playerIndex); + } else if (playerInfo.isElderRealm()) { + createRealmToGalaxy(sx, sy, playerInfo, playerIndex); + } else { + SquareInfo info = new SquareInfo(SquareInfo.TYPE_DEEP_SPACE_START, + playerIndex); + starMap.setSquareInfo(sx, sy, info); + starMap.setTile(sx, sy, Tiles.getTileByName(TileNames.EMPTY) + .getIndex()); + } + solarSystem = StarMapUtilities.setSolarSystem(solarSystem, sx, + sy, getMaxX(), getMaxY()); + return; + } + playerInfo.setStartingScenario(StartingScenario.TEMPERATE_HUMID_SIZE12); + } } if (playerIndex == -1 && !solHasAdded && DiceGenerator.getRandom(99) < 10) { @@ -1619,6 +1733,32 @@ private void makeStartingTutorialTexts(final PlayerInfo playerInfo, } } + /** + * Make starting tutorial texts about starting deep space. + * @param playerInfo Realm must be human player. + * @param coord Coordinate where to start + */ + private void makeStartingTutorialTextsInDeepSpace(final PlayerInfo playerInfo, + final Coordinate coord) { + if (Game.getTutorial() != null && playerInfo.isHuman() + && starMap.isTutorialEnabled()) { + String tutorialText = Game.getTutorial().showTutorialText(0); + if (tutorialText != null) { + Message msg = new Message(MessageType.INFORMATION, tutorialText, + Icons.getIconByName(Icons.ICON_TUTORIAL)); + playerInfo.getMsgList().addNewMessage(msg); + } + tutorialText = Game.getTutorial().showTutorialText(3); + if (tutorialText != null) { + Message msg = new Message(MessageType.FLEET, tutorialText, + Icons.getIconByName(Icons.ICON_TUTORIAL)); + msg.setCoordinate(coord); + msg.setMatchByString("Colony #0"); + playerInfo.getMsgList().addNewMessage(msg); + } + } + } + /** * Make Starting fleet tutorial texts. This will handle tutorial text for * both colony and scout ship. diff --git a/src/test/java/org/openRealmOfStars/game/GameTest.java b/src/test/java/org/openRealmOfStars/game/GameTest.java index 1cf0ac0b1..463a4800d 100644 --- a/src/test/java/org/openRealmOfStars/game/GameTest.java +++ b/src/test/java/org/openRealmOfStars/game/GameTest.java @@ -140,13 +140,15 @@ private static void printEndGameResults(final String testGameName, .getTechList().getTechLevel(techtype); } tech = tech * 10 / 6; + String scenario = game.getPlayers().getPlayerInfoByIndex(i) + .getStartingScenario().toString(); String resultText = i + ": " + game.getPlayers().getPlayerInfoByIndex(i).getEmpireName() + " (" + game.getPlayers().getPlayerInfoByIndex(i).getAiDifficulty() .toString() + ")" + " - planets " + planets[i] + "/" + maxPlanets[i] + " - Charted: " + charted[i] + "% Combats: " + combats[i] + " Conquest: " - + conquest[i] + " Tech:" + tech; + + conquest[i] + " Tech:" + tech+ " Scen:" + scenario; if (game.getPlayers().getPlayerInfoByIndex(i).isElderRealm()) { resultText = resultText + " - Elder"; }