Jelajahi Sumber

Testing - Energiekosten der einzelnen Tiles, Testing - Finetuning der Parameter, Bug - manchmal bei Score screen Anzeigefehler, Character - Home Town functionality, HUD - Movement Cost Overlay

Hudriwudri 4 tahun lalu
induk
melakukan
51ecfd9176

TEMPAT SAMPAH
resources/config.bin


TEMPAT SAMPAH
resources/config.txt


TEMPAT SAMPAH
resources/energyBar.png


TEMPAT SAMPAH
resources/energyBarGrey.png


+ 2 - 1
src/pathgame/PathGame.java

@@ -34,7 +34,8 @@ public class PathGame implements IGame
         
         if(Keys.TEST_KEY.getTime() == 1)
         {
-            level.nextLevel();
+            //level.nextLevel();
+            level.getPlayer().win();
         }
     }
 

+ 4 - 2
src/pathgame/algorithm/DijkstraMagic.java

@@ -6,6 +6,7 @@ import pathgame.tilemap.TileMap;
 import pathgame.tilemap.Tiles;
 
 import java.util.ArrayList;
+import pathgame.gameplay.Player;
 
 public class DijkstraMagic {
     private int townID = Tiles.TOWN.getId();
@@ -339,9 +340,10 @@ public class DijkstraMagic {
                 //translate map to weightMap
                 //TODO: boats
 
-                PlayerAbilities test = new PlayerAbilities("", 0, 0, 0, 0, 0, 0, 0);
+                Player p = new Player();
+                p.setAbilities(PlayerAbilities.NORMAL);
 
-                weightMap[x][y] = new Node2D(map.getTile(x, y).getEnergyCost(test));
+                weightMap[x][y] = new Node2D(map.getTile(x, y).getEnergyCost(p));
             }
         }
     }

+ 7 - 5
src/pathgame/gameplay/Keys.java

@@ -24,19 +24,21 @@ public class Keys
     public static final KeyBinding CAM_LEFT_KEY = KeyHandler.register(GLFW.GLFW_KEY_LEFT);
     public static final KeyBinding CAM_RIGHT_KEY = KeyHandler.register(GLFW.GLFW_KEY_RIGHT);
     public static final KeyBinding TEST_KEY = KeyHandler.register(GLFW.GLFW_KEY_T);
+    public static final KeyBinding OVERLAY_KEY = KeyHandler.register(GLFW.GLFW_KEY_TAB);
+    public static final KeyBinding BOAT_KEY = KeyHandler.register(GLFW.GLFW_KEY_E);
 
     public static final KeyBinding[] KEYS = new KeyBinding[]
     {
         UP_KEY, DOWN_KEY, LEFT_KEY, RIGHT_KEY, ZOOM_IN_KEY, ZOOM_OUT_KEY, 
-        CONFIRM_KEY, ESCAPE_KEY, CAM_UP_KEY, CAM_DOWN_KEY, CAM_LEFT_KEY, 
-        CAM_RIGHT_KEY
+        CAM_UP_KEY, CAM_DOWN_KEY, CAM_LEFT_KEY, 
+        CAM_RIGHT_KEY, OVERLAY_KEY, BOAT_KEY
     };
-
+    
     public static final String[] KEYNAMES =
     {
         "Up Key", "Down Key", "Left Key", "Right Key", "Zoom In Key",
-        "Zoom Out Key", "Confirm Key", "Escape Key", "Cam Up Key", 
-        "Cam Down Key", "Cam Left Key", "Cam Right Key"
+        "Zoom Out Key", "Cam Up Key", "Cam Down Key", "Cam Left Key",
+         "Cam Right Key", "Overlay Key", "Boat Key"
     };
 
     static

+ 4 - 4
src/pathgame/gameplay/Level.java

@@ -51,9 +51,9 @@ public final class Level
         player.reset(map.getHomeX(), map.getHomeY());
         player.setObjectivesAmount(map.getNumberOfTowns());
         
-        //TravellingSalesAlg.calcSalesPathLen(map);
+        TravellingSalesAlg.calcSalesPathLen(map);
         
-        player.setEnergySupply(100); // ToDo: insert value of algorithm
+        player.setEnergySupply(1000); // ToDo: insert value of algorithm
     }
 
     public TileMap getMap()
@@ -71,7 +71,7 @@ public final class Level
         return level;
     }
     
-    public boolean getShowAfterScore()
+    public boolean isShowingAfterScore()
     {
         return showAfterScore;
     }
@@ -80,7 +80,7 @@ public final class Level
     {
         showAfterScore = show;
     }
-    public boolean getShowScoreMenu()
+    public boolean isShowingScoreMenu()
     {
         return showScoreMenu; 
     }

+ 20 - 14
src/pathgame/gameplay/Player.java

@@ -2,15 +2,13 @@ package pathgame.gameplay;
 
 import java.util.Iterator;
 import java.util.LinkedList;
-import me.hammerle.snuviengine.api.KeyBinding;
 import pathgame.tilemap.Tile;
 import pathgame.tilemap.TileMap;
-import pathgame.tilemap.Tiles;
 
 public class Player
 {
 
-    private static final float SPEED = 0.125f;
+    private static final float SPEED = 0.25f;
 
     private PlayerAbilities abilities = PlayerAbilities.NORMAL;
 
@@ -24,6 +22,7 @@ public class Player
     private boolean isMoving = false;
     private int currSpeedSlowdown = 1;
     private boolean isSailing = false;
+    private boolean hasWon = false;
 
     private int energySupply;
     private int energyUsed = 0;
@@ -75,14 +74,9 @@ public class Player
 
         int currentTileX = Math.round(x);
         int currentTileY = Math.round(y);
-        //System.out.println(currentTileY + " " + y);
-        //TODO: Bug beheben: Exception, wenn Spieler sofort an den unteren Levelrand geht (auch am rechten Levelrand)
-        //ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 10
-        //System.out.println(currentTileY);
-        //currentTile = Tiles.GRASS;
         currentTile = map.getTile(currentTileX, currentTileY);
-        //System.out.println(currentTile);
-        currSpeedSlowdown = currentTile.getEnergyCost(abilities);
+
+        currSpeedSlowdown = currentTile.getEnergyCost(this);
         lastX = x;
         lastY = y;
 
@@ -97,6 +91,7 @@ public class Player
                 energyUsed += currSpeedSlowdown;
             }
             isMoving = false;
+            currentTile.isStandingOn(this, map, currentTileX, currentTileY);
         }
 
         if(Keys.LEFT_KEY.isDown() && !isMoving && currentTileX > 0 && !map.getTile(currentTileX - 1, currentTileY).isBlockingMovement(this))
@@ -236,17 +231,27 @@ public class Player
         this.energySupply = energySupply;
     }
 
-    public boolean hasWon()
+    public boolean canWin()
     {
         return objectivesVisited >= objectivesAmount;
     }
+    
+    public boolean hasWon()
+    {
+        return hasWon;
+    }
+
+    public void win()
+    {
+        this.hasWon = true;
+    }
 
     public boolean hasLost()
     {
         return energyUsed >= energySupply;
     }
 
-    public void reset(int sx, int sy, int energySupply, int objectivesAmount, PlayerAbilities abilities)
+    public void reset(int sx, int sy, int energySupply, int objectivesAmount)
     {
         lastX = sx;
         lastY = sy;
@@ -257,19 +262,20 @@ public class Player
         velY = 0;
         isMoving = false;
         currSpeedSlowdown = 1;
+        hasWon = false;
 
         energyUsed = 0;
 
+        isSailing = false;
         objectivesVisited = 0;
         steps.clear();
         this.energySupply = energySupply;
         this.objectivesAmount = objectivesAmount;
-        this.abilities = abilities;
     }
 
     public void reset(int sx, int sy)
     {
-        reset(sx, sy, 1000, 10, PlayerAbilities.NORMAL);
+        reset(sx, sy, 1000, 10);
     }
 
     public boolean isMoving()

+ 4 - 5
src/pathgame/gameplay/PlayerAbilities.java

@@ -25,15 +25,14 @@ public class PlayerAbilities
     }
 
     public final static PlayerAbilities NORMAL = new PlayerAbilities("Normal", 0, 0, 0, 0, 0, 0, 0);
-    public final static PlayerAbilities HIKER = new PlayerAbilities("Hiker", 0, 0, 0, 0, 1, 0, 0);
-    public final static PlayerAbilities CLIMBER = new PlayerAbilities("Climber", 0, 0, 0, 0, 0, 1, 0);
-    public final static PlayerAbilities HUNTER = new PlayerAbilities("Hunter", 0, 1, 0, 0, 0, 0, 0);
-    public final static PlayerAbilities SWIMMER = new PlayerAbilities("Swimmer", 0, 0, 2, 0, 0, 0, 0);
+    public final static PlayerAbilities HIKER = new PlayerAbilities("Hiker", 0, 0, 0, 0, 2, 4, 0);
+    public final static PlayerAbilities HUNTER = new PlayerAbilities("Hunter", 0, 1, 0, 0, 0, 0, 1);
+    public final static PlayerAbilities SWIMMER = new PlayerAbilities("Swimmer", 0, 0, 3, 0, 0, 0, 0);
     public final static PlayerAbilities SAILOR = new PlayerAbilities("Sailor", 0, 0, 0, 1, 0, 0, 0);
     
     public final static PlayerAbilities[] ABILITIES = new PlayerAbilities[] 
     {
-        NORMAL, HIKER, CLIMBER, HUNTER, SWIMMER, SAILOR
+        NORMAL, HIKER, HUNTER, SWIMMER, SAILOR
     };
 
     public int getFasterGrass()

+ 1 - 1
src/pathgame/gameplay/menu/Menu.java

@@ -55,7 +55,7 @@ public class Menu
             gamestate.setState(Gamestates.MENU);
             menus[currentIndex].resetIndex();
         }
-        else if(level.getShowAfterScore())
+        else if(level.isShowingAfterScore())
         {
             currentIndex = AFTER_SCORE_ID;
             gamestate.setState(Gamestates.MENU);

+ 7 - 3
src/pathgame/rendering/LevelRenderer.java

@@ -28,6 +28,10 @@ public class LevelRenderer
 
     public void renderTick(Renderer r, float lag, Level level, Gamestate gamestate)
     {
+        if(level.isShowingAfterScore() || level.isShowingScoreMenu())
+        {
+            lag = 0.0f;
+        }
         TileMap map = level.getMap();
         Player player = level.getPlayer();
 
@@ -42,16 +46,16 @@ public class LevelRenderer
         float offX = getMapOffsetX(map, player, r, lag, interScale);
         float offY = getMapOffsetY(map, player, r, lag, interScale) + HUDRenderer.OFFSET_Y;
 
-        mapRenderer.renderTick(map, r, false, offX, offY);
+        mapRenderer.renderTick(map, r, player, false, offX, offY);
 
         if(gamestate.is(Gamestates.GAMEPLAY))
         {
             playerRenderer.renderTick(map, mapRenderer, r, player, lag, offX, offY);
-            if(!level.getShowScoreMenu())
+            if(!level.isShowingScoreMenu())
             {
                 hudRenderer.renderTick(r, player, lag);
             }
-            else if(level.getShowScoreMenu())
+            else if(level.isShowingScoreMenu())
             {
                 scoreRenderer.renderTick(r, lag, level);
             }

+ 3 - 5
src/pathgame/rendering/ScoreMenuRenderer.java

@@ -21,13 +21,11 @@ public class ScoreMenuRenderer
         r.translateTo(0.0f, 0.0f);
         float scale = scale(r, 1);
 
-        String message;
+        String message = String.format("&2%d&f of &2%d&f Energy used", 
+                level.getPlayer().getEnergyUsed(), level.getPlayer().getEnergySupply());
 
-        message = "&2" + String.valueOf(level.getPlayer().getEnergyUsed()) + "&f of &2"
-                + String.valueOf(level.getPlayer().getEnergySupply()) + "&f Energy used";
         r.getFontRenderer().drawString((windowWidth * scale - getWidth(r, message)) / 2, (windowHeight * scale - getHeight(r, message)) / 2 - windowHeight * scale * 0.5f * 0.15f, message);
 
-        System.out.println((float) level.getPlayer().getEnergyUsed() / level.getPlayer().getEnergySupply());
         if((float) level.getPlayer().getEnergyUsed() / level.getPlayer().getEnergySupply() < 0.5f)
         {
             message = "You were better than the algorithm!";
@@ -63,7 +61,7 @@ public class ScoreMenuRenderer
         }
         r.getFontRenderer().drawString((windowWidth * scale - getWidth(r, message)) / 2, (windowHeight * scale - getHeight(r, message)) / 2, message);
 
-        message = "OK!";
+        message = "[&7PRESS ENTER&f]";
         r.getFontRenderer().drawString((windowWidth * scale - getWidth(r, message)) / 2, (windowHeight * scale - paddingY * scale - getHeight(r, message)) - 10, message);
 
     }

+ 49 - 4
src/pathgame/rendering/TileMapRenderer.java

@@ -1,8 +1,11 @@
 package pathgame.rendering;
 
+import me.hammerle.snuviengine.api.FontRenderer;
 import me.hammerle.snuviengine.api.Renderer;
 import me.hammerle.snuviengine.api.Texture;
 import me.hammerle.snuviengine.api.TextureRenderer;
+import pathgame.gameplay.Keys;
+import pathgame.gameplay.Player;
 import pathgame.tilemap.Tile;
 import pathgame.tilemap.TileMap;
 import pathgame.tilemap.TileRenderType;
@@ -14,6 +17,7 @@ import pathgame.tilemap.TileRenderType;
  */
 public class TileMapRenderer
 {
+
     // prevents rendering artifacts especially on different zoom levels
     private final static float ERROR = 1.0f / 512.0F;
     private final static float T_ERROR = 1.0f / 4096.0F;
@@ -23,6 +27,11 @@ public class TileMapRenderer
     private final TextureRenderer swampWaterOverlayRenderer = new TextureRenderer(20 * 20 * 2); // default to 20x20 map
     private final TextureRenderer grassOverlayRenderer = new TextureRenderer(20 * 20 * 2); // default to 20x20 map
     private float scale = 1.0f;
+    
+    private final static String[] OVERLAY = new String[]
+    {
+        "&a1", "&a2", "&a3", "&e4", "&e5", "&66", "&67", "&68", "&c9"
+    };
 
     /**
      * Creates a new tile map renderer.
@@ -73,7 +82,7 @@ public class TileMapRenderer
     {
         return map.getHeight() * TileRenderer.TILE_SIZE * scale;
     }
-    
+
     private float toTexture(int x)
     {
         return x * TileRenderer.TILE_SIZE / TileTexture.TEXTURE_SIZE;
@@ -87,7 +96,7 @@ public class TileMapRenderer
                 tMinX + T_ERROR, tMinY + T_ERROR,
                 tMaxX - T_ERROR, tMaxY - T_ERROR);
     }
-    
+
     private void addTileOverlay(TextureRenderer tr, int x, int y, int ox, int oy)
     {
         addTile(tr, x, y, toTexture(ox), toTexture(oy), toTexture(ox + 1), toTexture(oy + 1));
@@ -112,7 +121,7 @@ public class TileMapRenderer
         TileRenderType type = map.getTile(x, y).getRenderType();
         return type == TileRenderType.SWAMP || type == TileRenderType.WATER;
     }
-    
+
     private void addWaterSwampOverlay(TileMap map, int x, int y)
     {
         boolean n = isSwamp(map, x, y - 1);
@@ -236,7 +245,7 @@ public class TileMapRenderer
      * @param offX the x coordinate of the offset
      * @param offY the y coordinate of the offset
      */
-    public void renderTick(TileMap map, Renderer r, boolean forceUpdate, float offX, float offY)
+    public void renderTick(TileMap map, Renderer r, Player p, boolean forceUpdate, float offX, float offY)
     {
         r.setTextureEnabled(true);
         r.setColorEnabled(false);
@@ -260,5 +269,41 @@ public class TileMapRenderer
         textureRenderer.draw();
         swampWaterOverlayRenderer.draw();
         grassOverlayRenderer.draw();
+
+        if(Keys.OVERLAY_KEY.isDown())
+        {
+            r.translateTo(0.0f, 0.0f);
+            r.updateMatrix();
+            r.setTextureEnabled(false);
+            r.getColorRenderer().drawRectangle(0, 0, r.getViewWidth(), r.getViewHeight(), 0x44000000);
+            r.setTextureEnabled(true);
+            r.setColorEnabled(true);
+
+            r.translateTo(offX, offY);
+            r.scale(scale * 2.0f, scale * 2.0f);
+            r.updateMatrix();
+
+            FontRenderer fr = r.getFontRenderer();
+
+            float midX = (TileRenderer.TILE_SIZE - fr.getWidth() * 2) * 0.5f * 0.5f;
+            float midY = (TileRenderer.TILE_SIZE - (fr.getHeight() - 1) * 2) * 0.5f * 0.5f;
+            for(int x = 0; x < map.getWidth(); x++)
+            {
+                for(int y = 0; y < map.getHeight(); y++)
+                {
+                    Tile t = map.getTile(x, y);
+                    float tx = midX + TileRenderer.TILE_SIZE * x * 0.5f;
+                    float ty =  midY + TileRenderer.TILE_SIZE * y * 0.5f;
+                    if(t.isBlockingMovement(p))
+                    {
+                        fr.drawString(tx, ty, true, "&4-");
+                    }
+                    else
+                    {
+                        fr.drawString(tx, ty, true, OVERLAY[map.getTile(x, y).getEnergyCost(p) - 1]);
+                    }
+                }
+            }
+        }
     }
 }

+ 18 - 8
src/pathgame/tilemap/Tile.java

@@ -2,7 +2,6 @@ package pathgame.tilemap;
 
 import java.util.function.Function;
 import pathgame.gameplay.Player;
-import pathgame.gameplay.PlayerAbilities;
 
 /** Base class for tiles. Tiles are registered on construction.
  *
@@ -12,9 +11,9 @@ public class Tile
 {
     public static class TileBuilder
     {
-        private int energyCost = 1;
+        private int energyCost = 2;
         private float forestReplaceChance = 1.0f;
-        private Function<PlayerAbilities, Integer> speedUp = (pa) -> 0;
+        private Function<Player, Integer> speedUp = (p) -> 0;
         private boolean canHostTown = true;
         private boolean blocksMovement = false;
         private TileType type = TileType.LAND;
@@ -43,7 +42,7 @@ public class Tile
             return this;
         }
 
-        public TileBuilder setSpeedUp(Function<PlayerAbilities, Integer> speedUp)
+        public TileBuilder setSpeedUp(Function<Player, Integer> speedUp)
         {
             this.speedUp = speedUp;
             return this;
@@ -123,7 +122,7 @@ public class Tile
     private final int id;
     private final int energyCost;
     private final float forestReplaceChance;
-    private final Function<PlayerAbilities, Integer> speedUp;
+    private final Function<Player, Integer> speedUp;
     private final boolean canHostTown;
     private final boolean blocksMovement;
     private final TileType type;
@@ -131,7 +130,7 @@ public class Tile
     private final boolean path;
     private final TileRenderType renderType;
     
-    protected Tile(int energyCost, float forestReplaceChance, Function<PlayerAbilities, Integer> speedUp, 
+    protected Tile(int energyCost, float forestReplaceChance, Function<Player, Integer> speedUp, 
             boolean canHostTown, boolean blocksMovement, TileType type, boolean canHostPath, boolean path,
             TileRenderType renderType)
     {
@@ -156,9 +155,9 @@ public class Tile
         return id;
     }
     
-    public int getEnergyCost(PlayerAbilities pa)
+    public int getEnergyCost(Player p)
     {
-        return energyCost - speedUp.apply(pa);
+        return energyCost - speedUp.apply(p);
     }
 
     /** Returns the chance that this tile is replaced by forest.
@@ -247,4 +246,15 @@ public class Tile
     {
         return renderType;
     }
+    
+    /** Called when the player stands on that tile.
+     *
+     * @param p the player
+     * @param map the current tilemap
+     * @param x the x coordinate of the tile
+     * @param y the y coordinate of the tile
+     */
+    public void isStandingOn(Player p, TileMap map, int x, int y)
+    {
+    }
 }

+ 12 - 2
src/pathgame/tilemap/TileHomeTown.java

@@ -1,10 +1,20 @@
 package pathgame.tilemap;
 
+import pathgame.gameplay.Player;
+
 public class TileHomeTown extends Tile
 {
     public TileHomeTown()
     {
-        super(1, 0.0f, (pa) -> 0, false, false, TileType.LAND, false, false, TileRenderType.NORMAL);
+        super(2, 0.0f, (pa) -> 0, false, false, TileType.LAND, false, false, TileRenderType.NORMAL);
+    }
+
+    @Override
+    public void onEnter(Player p, TileMap map, int x, int y)
+    {
+        if(p.canWin())
+        {
+            p.win();
+        }
     }
-    
 }

+ 3 - 2
src/pathgame/tilemap/TileMapGenerator.java

@@ -67,11 +67,12 @@ public class TileMapGenerator
         forestSize *= forestSize;
         generateForest(map, r, forestSize, 10, 2, Tiles.FOREST);
         generateForest(map, r, forestSize, 5, 2, Tiles.SWAMP, Tiles.SWAMP, Tiles.SWAMP_DECO, Tiles.SWAMP_TREE);
-        removeBadSwampTree(map);
         
         generateTowns(map, r, towns);
         generatePorts(map, r);
         generatePaths(map, r);
+        
+        removeBadSwampTree(map);
         return map;
     }
     
@@ -283,7 +284,7 @@ public class TileMapGenerator
         
         //System.out.println(String.format("Lake Size: %d, (%d, %d) -> (%d, %d)", 
         //        waterSize, waterMinX, waterMinY, waterMaxX, waterMaxY));
-        int ports = waterSize / 10;
+        int ports = waterSize / 30;
         int diffX = waterMaxX - waterMinX + 1;
         int diffY = waterMaxY - waterMinY + 1;
         int failCounter = 0;

+ 7 - 3
src/pathgame/tilemap/TilePort.java

@@ -1,17 +1,21 @@
 package pathgame.tilemap;
 
+import pathgame.gameplay.Keys;
 import pathgame.gameplay.Player;
 
 public class TilePort extends Tile
 {
     public TilePort()
     {
-        super(1, 0.0f, (pa) -> 0, false, false, TileType.PORT, false, false, TileRenderType.NORMAL);
+        super(2, 0.0f, (pa) -> 0, false, false, TileType.PORT, false, false, TileRenderType.NORMAL);
     }
 
     @Override
-    public void onEnter(Player p, TileMap map, int x, int y)
+    public void isStandingOn(Player p, TileMap map, int x, int y)
     {
-        p.switchSailing();
+        if(Keys.BOAT_KEY.getTime() == 1)
+        {
+            p.switchSailing();
+        }
     }
 }

+ 1 - 1
src/pathgame/tilemap/TileTown.java

@@ -6,7 +6,7 @@ public class TileTown extends Tile
 {
     public TileTown()
     {
-        super(1, 0.0f, (pa) -> 0, false, false, TileType.LAND, false, false, TileRenderType.NORMAL);
+        super(2, 0.0f, (pa) -> 0, false, false, TileType.LAND, false, false, TileRenderType.NORMAL);
     }
 
     @Override

+ 42 - 25
src/pathgame/tilemap/Tiles.java

@@ -1,7 +1,10 @@
 package pathgame.tilemap;
 
+import pathgame.gameplay.PlayerAbilities;
+
 public class Tiles
 {
+
     public final static Tile GRASS = buildGrass();
     public final static Tile GRASS_WITH_STONE = buildGrass();
     public final static Tile GRASS_WITH_6_BUSHES = buildGrass();
@@ -12,49 +15,61 @@ public class Tiles
     public final static Tile GRASS_WITH_FLOWERS_4 = buildGrass();
     public final static Tile GRASS_WITH_HILL = buildGrass();
     public final static Tile GRASS_WITH_EARTH = buildGrass();
-    
+
     public final static Tile[] GRASS_VARIANTS = new Tile[]
     {
-        GRASS, GRASS_WITH_STONE, GRASS_WITH_6_BUSHES, GRASS_WITH_3_BUSHES, 
+        GRASS, GRASS_WITH_STONE, GRASS_WITH_6_BUSHES, GRASS_WITH_3_BUSHES,
         GRASS_WITH_FLOWERS_1, GRASS_WITH_FLOWERS_2, GRASS_WITH_FLOWERS_3,
         GRASS_WITH_FLOWERS_4, GRASS_WITH_HILL, GRASS_WITH_EARTH
     };
-    
+
     public final static Tile FOREST = Tile.TileBuilder.create()
-            .setEnergyCost(2)
+            .setEnergyCost(4)
             .setForestReplaceChance(0.0f)
-            .setSpeedUp((pa) -> pa.getFasterForest())
+            .setSpeedUp((p) -> p.getAbilities().getFasterForest())
             .pathHost()
             .build();
     public final static Tile SWAMP = buildSwamp();
     public final static Tile SWAMP_DECO = buildSwamp();
     public final static Tile SWAMP_TREE = buildSwamp();
     public final static Tile SHALLOW_WATER = Tile.TileBuilder.create()
-            .setEnergyCost(3)
+            .setEnergyCost(6)
             .setForestReplaceChance(0.0f)
-            .setSpeedUp((pa) -> pa.getFasterShallowWater())
+            .setSpeedUp((p) ->
+            {
+                int speedUp = p.getAbilities().getFasterShallowWater();
+                if(p.isSailing())
+                {
+                    speedUp += 4;
+                    if(p.getAbilities() == PlayerAbilities.SAILOR)
+                    {
+                        speedUp++;
+                    }
+                }
+                return speedUp;
+            })
             .noTown()
             .setRenderType(TileRenderType.WATER)
             .setType(TileType.SHALLOW_WATER)
             .build();
     public final static Tile DEEP_WATER = Tile.TileBuilder.create()
-            .setEnergyCost(3)
+            .setEnergyCost(2)
             .setForestReplaceChance(0.0f)
-            .setSpeedUp((pa) -> pa.getFasterDeepWater())
+            .setSpeedUp((p) -> p.getAbilities().getFasterDeepWater())
             .noTown()
             .setRenderType(TileRenderType.WATER)
             .setType(TileType.DEEP_WATER)
             .build();
     public final static Tile HILL = Tile.TileBuilder.create()
-            .setEnergyCost(3)
+            .setEnergyCost(6)
             .setForestReplaceChance(0.5f)
-            .setSpeedUp((pa) -> pa.getFasterHill())
+            .setSpeedUp((p) -> p.getAbilities().getFasterHill())
             .pathHost()
             .build();
     public final static Tile MOUNTAIN = Tile.TileBuilder.create()
-            .setEnergyCost(5)
+            .setEnergyCost(9)
             .setForestReplaceChance(0.0f)
-            .setSpeedUp((pa) -> pa.getFasterMountain())
+            .setSpeedUp((p) -> p.getAbilities().getFasterMountain())
             .noTown()
             .build();
     public final static Tile TOWN = new TileTown();
@@ -62,31 +77,33 @@ public class Tiles
     public final static Tile TOWN_BLOCKED_2 = buildBlockedTown();
     public final static Tile TOWN_BLOCKED_3 = buildBlockedTown();
     public final static Tile TOWN_BLOCKED_4 = buildBlockedTown();
-    
+
     public final static Tile[] TOWN_BLOCKED = new Tile[]
     {
         TOWN_BLOCKED_1, TOWN_BLOCKED_2, TOWN_BLOCKED_3, TOWN_BLOCKED_4
     };
-    
+
     public final static Tile PORT = new TilePort();
-    
+
     public final static Tile buildGrass()
     {
         return Tile.TileBuilder.create()
-                .setSpeedUp((pa) -> pa.getFasterGrass())
+                .setSpeedUp((p) -> p.getAbilities().getFasterGrass())
                 .pathHost()
+                .setEnergyCost(3)
                 .build();
     }
-    
+
     public final static Tile buildSwamp()
     {
         return Tile.TileBuilder.create()
-                .setEnergyCost(3)
+                .setEnergyCost(5)
                 .setForestReplaceChance(0.0f)
                 .setRenderType(TileRenderType.SWAMP)
+                .setSpeedUp((p) -> p.getAbilities().getFasterSwamp())
                 .build();
     }
-    
+
     public final static Tile buildBlockedTown()
     {
         return Tile.TileBuilder.create()
@@ -94,9 +111,9 @@ public class Tiles
                 .noTown()
                 .build();
     }
-    
+
     public final static Tile HOME_TOWN = new TileHomeTown();
-    
+
     public final static Tile buildPath()
     {
         return Tile.TileBuilder.create()
@@ -104,7 +121,7 @@ public class Tiles
                 .path()
                 .build();
     }
-    
+
     public final static Tile PATH_N_E_S_W = buildPath();
     public final static Tile PATH_N_E_S = buildPath();
     public final static Tile PATH_N_E_W = buildPath();
@@ -120,7 +137,7 @@ public class Tiles
     public final static Tile PATH_S_W = buildPath();
     public final static Tile PATH_S = buildPath();
     public final static Tile PATH_W = buildPath();
-    
+
     public final static Tile[] PATH = new Tile[]
     {
         PATH_N_E_S_W, PATH_N_E_S, PATH_N_E_W, PATH_N_E,
@@ -128,7 +145,7 @@ public class Tiles
         PATH_E_S_W, PATH_E_S, PATH_E_W, PATH_E,
         PATH_S_W, PATH_S, PATH_W, GRASS
     };
-    
+
     public static Tile getPath(boolean north, boolean east, boolean south, boolean west)
     {
         return PATH[(north ? 0 : 8) + (east ? 0 : 4) + (south ? 0 : 2) + (west ? 0 : 1)];