public static bool mineable(Terrain terrain)
        {
            switch(terrain.getCode())
            {
                case TerrainCode.ROCK:
                case TerrainCode.STONE_FLOOR:
                case TerrainCode.STREAM_BED:
                return true;

                default:
                return false;
            }
        }
        public static bool growable(Terrain terrain, int x, int y, LightMap lightMap, TerrainParameter thingToGrow)
        {
            //check for doors, trees, signs, graves
            if(TerrainManager.hasParameter(terrain, TerrainParameter.HAS_TREE)
            || TerrainManager.hasParameter(terrain, TerrainParameter.HAS_SIGN)
            || TerrainManager.hasParameter(terrain, TerrainParameter.HAS_GRAVE)
            || TerrainManager.hasParameter(terrain, TerrainParameter.HAS_DOOR))
            {
                return false;
            }

            switch(thingToGrow)
            {
                //crops
                case TerrainParameter.HAS_SEED:
                if(terrain.getCode() == TerrainCode.FERTILE_LAND
                && !TerrainManager.hasParameter(terrain, TerrainParameter.HAS_SEED)
                && !TerrainManager.hasParameter(terrain, TerrainParameter.HAS_MOSS))
                {
                    return true;
                }
                return false;

                //mushrooms
                case TerrainParameter.HAS_MUSHROOM_SPORES:
                if(lightMap.getCalc(x, y) <= TerrainManager.SPORE_LIGHT_LEVEL_MAX
                && !TerrainManager.hasParameter(terrain, TerrainParameter.HAS_MUSHROOM_SPORES)
                && !TerrainManager.hasParameter(terrain, TerrainParameter.HAS_CLOVER)
                && !TerrainManager.hasParameter(terrain, TerrainParameter.HAS_SEED)
                && terrain.getCode() != TerrainCode.STONE_WALL
                && terrain.getCode() != TerrainCode.ROCK)
                {
                    return true;
                }
                return false;

                //clover
                case TerrainParameter.HAS_CLOVER:
                if(!TerrainManager.hasParameter(terrain, TerrainParameter.HAS_MUSHROOM_SPORES)
                && !TerrainManager.hasParameter(terrain, TerrainParameter.HAS_CLOVER)
                && !TerrainManager.hasParameter(terrain, TerrainParameter.HAS_SEED)
                && !TerrainManager.hasParameter(terrain, TerrainParameter.HAS_MOSS)
                && terrain.getCode() != TerrainCode.STONE_WALL
                && terrain.getCode() != TerrainCode.ROCK
                && terrain.getCode() != TerrainCode.STREAM_BED
                && terrain.getCode() != TerrainCode.PATH)
                {
                    return true;
                }
                return false;

                //moss
                case TerrainParameter.HAS_MOSS:
                if(terrain.getWater() <= 0
                && !TerrainManager.hasParameter(terrain, TerrainParameter.HAS_MUSHROOM_SPORES)
                && !TerrainManager.hasParameter(terrain, TerrainParameter.HAS_CLOVER)
                && !TerrainManager.hasParameter(terrain, TerrainParameter.HAS_SEED)
                && !TerrainManager.hasParameter(terrain, TerrainParameter.HAS_MOSS)
                && (terrain.getCode() == TerrainCode.STONE_FLOOR
                || terrain.getCode() == TerrainCode.STONE_WALL
                || terrain.getCode() == TerrainCode.ROCK))
                {
                    return true;
                }
                return false;

                default:
                return true;
            }
        }
        public static void mine(Terrain terrain, int x, int y, Quinoa quinoa)
        {
            switch(terrain.getCode())
            {
                case TerrainCode.ROCK:
                terrain.setCode(TerrainCode.STONE_FLOOR);

                if(TerrainManager.hasParameter(terrain, TerrainParameter.HAS_MINERALS))
                {
                    int mineralCode = Int32.Parse(TerrainManager.getParameter(terrain, TerrainParameter.HAS_MINERALS));
                    switch(mineralCode)
                    {
                        case 1:
                        if(RandomNumber.RandomDouble() > 0.5)
                        {
                            Item gem = new Item();
                            gem.itemClass = ItemClass.AMETHYST;
                            gem.setPosition(x, y);
                            quinoa.getCurrentRegionHeader().getRegion().getItems().Add(gem);
                        }
                        else
                        {
                            //do nothing
                        }
                        break;

                        case 2:
                        if(RandomNumber.RandomDouble() > 0.5)
                        {
                            Item gem = new Item();
                            gem.itemClass = ItemClass.SAPPHIRE;
                            gem.setPosition(x, y);
                            quinoa.getCurrentRegionHeader().getRegion().getItems().Add(gem);
                        }
                        else
                        {
                            Item gem = new Item();
                            gem.itemClass = ItemClass.EMERALD;
                            gem.setPosition(x, y);
                            quinoa.getCurrentRegionHeader().getRegion().getItems().Add(gem);
                        }
                        break;

                        case 3:
                        if(RandomNumber.RandomDouble() > 0.33)
                        {
                            Item gem = new Item();
                            gem.itemClass = ItemClass.RUBY;
                            gem.setPosition(x, y);
                            quinoa.getCurrentRegionHeader().getRegion().getItems().Add(gem);
                        }
                        else
                        {
                            Item gem = new Item();
                            gem.itemClass = ItemClass.DIAMOND;
                            gem.setPosition(x, y);
                            quinoa.getCurrentRegionHeader().getRegion().getItems().Add(gem);
                        }
                        break;

                    }
                }

                break;

                case TerrainCode.STONE_FLOOR:
                terrain.setCode(TerrainCode.STREAM_BED);
                break;

                case TerrainCode.STREAM_BED:
                if(TerrainManager.hasParameter(terrain, TerrainParameter.HAS_DRAIN))
                {
                    terrain.getParameters().Remove(TerrainParameter.HAS_DRAIN);
                }
                else
                {
                    terrain.getParameters().Add(TerrainParameter.HAS_DRAIN, TerrainManager.DRAIN_RATE+"");
                }
                break;

                default:
                //do nothing
                break;
            }
        }
        public static bool flammable(Terrain terrain, int x, int y, Quinoa quinoa)
        {
            //See if the area is wet
            if(terrain.getWater() > 0)
            {
                return false;
            }

            if(containsItem(ItemClass.LOG, x, y, quinoa) != null)
            {
                return true;
            }

            switch(terrain.getCode())
            {
                case TerrainCode.PATH:
                case TerrainCode.DIRT:
                case TerrainCode.STONE_WALL:
                case TerrainCode.STONE_FLOOR:
                case TerrainCode.FERTILE_LAND:
                case TerrainCode.ROCK:
                case TerrainCode.STREAM_BED:
                default:
                return false;

                case TerrainCode.GRASS:
                return true;
            }
        }
        public static int fuelsFire(Terrain terrain, int x, int y, Quinoa quinoa)
        {
            if(containsItem(ItemClass.LOG, x, y, quinoa) != null)
            {
                return 10;
            }

            if(TerrainManager.hasParameter(terrain, TerrainParameter.HAS_TREE))
            {
                return 2;
            }

            if(TerrainManager.hasParameter(terrain, TerrainParameter.HAS_DOOR))
            {
                return 1;
            }

            if(TerrainManager.hasParameter(terrain, TerrainParameter.HAS_SIGN))
            {
                return 1;
            }

            switch(terrain.getCode())
            {
                default:
                return 0;
            }
        }
        public static void dig(Terrain terrain, int x, int y, Quinoa quinoa)
        {
            //check for graves
            if(TerrainManager.hasParameter(terrain, TerrainParameter.HAS_GRAVE))
            {
                GraveCode gc = (GraveCode)Enum.Parse(typeof(GraveCode), TerrainManager.getParameter(terrain, TerrainParameter.HAS_GRAVE));
                if(gc == GraveCode.NORMAL && RandomNumber.RandomDouble() < TerrainManager.GRAVE_ROB_CHANCE)
                {
                    Item reward = ItemManager.getTreasure(RandomNumber.RandomDouble());
                    reward.setPosition(x, y);
                    quinoa.getCurrentRegionHeader().getRegion().getItems().Add(reward);
                }

                //open the grave
                terrain.getParameters().Add(TerrainParameter.HAS_GRAVE, EnumUtil.EnumName<GraveCode>(GraveCode.BROKEN));

                //drop bones
                Item bones = new Item();
                bones.itemClass = ItemClass.BONES;
                bones.setPosition(x, y);
                bones.itemState = ItemState.GROUND;
                quinoa.getCurrentRegionHeader().getRegion().getItems().Add(bones);

                return;
            }

            switch(terrain.getCode())
            {
                case TerrainCode.GRASS:
                terrain.setCode(TerrainCode.DIRT);
                break;

                case TerrainCode.DIRT:
                terrain.setCode(TerrainCode.STONE_FLOOR);
                break;

                case TerrainCode.STREAM_BED:
                if(!TerrainManager.hasParameter(terrain, TerrainParameter.HAS_DRAIN))
                {
                    if(!TerrainManager.hasParameter(terrain, TerrainParameter.HAS_SPRING))
                    {
                        terrain.getParameters().Add(TerrainParameter.HAS_SPRING, TerrainManager.SPRING_RATE+"");
                    }
                    else
                    {
                        terrain.getParameters().Remove(TerrainParameter.HAS_SPRING);
                    }
                }
                break;

                default:
                //Do nothing, can not dig
                break;

            }
        }
        public static bool diggable(Terrain terrain)
        {
            if(TerrainManager.hasParameter(terrain, TerrainParameter.HAS_TREE)
            || TerrainManager.hasParameter(terrain, TerrainParameter.HAS_DOOR)
            || TerrainManager.hasParameter(terrain, TerrainParameter.HAS_SIGN))
            {
                return false;
            }

            if(TerrainManager.hasParameter(terrain, TerrainParameter.HAS_GRAVE))
            {
                GraveCode gc = (GraveCode)Enum.Parse(typeof(GraveCode), TerrainManager.getParameter(terrain, TerrainParameter.HAS_GRAVE));
                return (gc != GraveCode.BROKEN);
            }

            switch(terrain.getCode())
            {
                case TerrainCode.PATH:
                case TerrainCode.STONE_WALL:
                case TerrainCode.STONE_FLOOR:
                case TerrainCode.FERTILE_LAND:
                case TerrainCode.ROCK:
                default:
                return false;

                case TerrainCode.GRASS:
                case TerrainCode.DIRT:
                case TerrainCode.STREAM_BED:
                return true;
            }
        }
        public static void burn(Terrain terrain, int x, int y, Quinoa quinoa)
        {
            bool dropAsh = false;

            //Look for items on this squares and remove them
            foreach(Item tempItem in quinoa.getCurrentRegionHeader().getRegion().getItems())
            {
                if(tempItem.x == x && tempItem.y == y)
                {
                    switch(tempItem.itemClass)
                    {
                        case ItemClass.LOG: dropAsh=true; break;
                        default: dropAsh= false; break;
                    }
                    tempItem.RemoveObject();
                }
            }

            //Examine terrain features
            if(TerrainManager.hasParameter(terrain, TerrainParameter.HAS_TREE))
            {
                terrain.getParameters().Remove(TerrainParameter.HAS_TREE);
                if(RandomNumber.RandomDouble() < 0.125)
                {
                    dropAsh = true;
                }
            }

            if(TerrainManager.hasParameter(terrain, TerrainParameter.HAS_DOOR))
            {
                terrain.getParameters().Remove(TerrainParameter.HAS_DOOR);
            }

            if(TerrainManager.hasParameter(terrain, TerrainParameter.HAS_SIGN))
            {
                terrain.getParameters().Remove(TerrainParameter.HAS_SIGN);
            }

            if(TerrainManager.hasParameter(terrain, TerrainParameter.HAS_MUSHROOM_SPORES))
            {
                terrain.getParameters().Remove(TerrainParameter.HAS_MUSHROOM_SPORES);
            }

            if(TerrainManager.hasParameter(terrain, TerrainParameter.HAS_CLOVER))
            {
                terrain.getParameters().Remove(TerrainParameter.HAS_CLOVER);
            }

            switch(terrain.getCode())
            {
                case TerrainCode.GRASS:
                if(RandomNumber.RandomDouble() < 0.98)
                {
                    terrain.setCode(TerrainCode.FERTILE_LAND);
                    terrain.getParameters().Add(TerrainParameter.GROW_COUNTER, TerrainManager.GRASS_GROW_COUNT+"");

                    if(RandomNumber.RandomDouble() < 0.001)
                    {
                        int cloverCount = (int)(RandomNumber.RandomDouble() * (TerrainManager.CLOVER_GROW_COUNT / 4)) + TerrainManager.CLOVER_GROW_COUNT;
                        terrain.getParameters().Add(TerrainParameter.HAS_CLOVER, cloverCount+"");
                    }
                    else
                    {
                        if(RandomNumber.RandomDouble() < 0.001)
                        {
                            MushroomSporeCode msc = EnumUtil.RandomEnumValue<MushroomSporeCode>();
                            terrain.getParameters().Add(TerrainParameter.HAS_MUSHROOM_SPORES, EnumUtil.EnumName<MushroomSporeCode>(msc));
                        }
                    }

                }
                else
                {
                    terrain.setCode(TerrainCode.DIRT);
                }
                break;

                default:
                //Do nothing, does not burn
                break;

            }

            if(dropAsh)
            {
                Item ash = new Item();
                ash.itemClass = ItemClass.ASH;
                ash.setPosition(x, y);
                quinoa.getCurrentRegionHeader().getRegion().getItems().Add(ash);
            }
        }
        public static bool allowWaterToFlowBetween(Terrain oldTerrain, Terrain newTerrain)
        {
            int oldWater = oldTerrain.getWater();
            int newWater = newTerrain.getWater();

            if(newWater >= oldWater || newWater >= TerrainManager.MAX_WATER)
            {
                return false;
            }

            //If terrains are the same, then allow it
            if(oldTerrain.getCode() == newTerrain.getCode())
            {
                return true;
            }

            //Handle water flow out
            switch(oldTerrain.getCode())
            {
                case TerrainCode.STREAM_BED:
                return false;
            }

            return true;
        }
        public static bool allowsMonsterToPass(Terrain newTerrain, Monster monster)
        {
            //blocking newTerrain parameter check
            if(TerrainManager.hasParameter(newTerrain, TerrainParameter.HAS_TREE)
            || TerrainManager.hasParameter(newTerrain, TerrainParameter.HAS_SIGN))
            {
                switch(monster.monsterCode)
                {
                    case MonsterCode.HUMAN: return false;
                    case MonsterCode.SPONGE: return false;
                    case MonsterCode.GHOST: return true;
                    case MonsterCode.SLIME: return false;
                    case MonsterCode.SMALL_SLIME: return false;
                    case MonsterCode.TINY_SLIME: return false;
                    case MonsterCode.DEER: return false;
                    case MonsterCode.PIG: return false;
                    default: return false;
                }
            }

            //door newTerrain check
            if(TerrainManager.hasParameter(newTerrain, TerrainParameter.HAS_DOOR))
            {
                DoorCode doorCode = (DoorCode)Enum.Parse(typeof(DoorCode), TerrainManager.getParameter(newTerrain, TerrainParameter.HAS_DOOR));
                if(doorCode == DoorCode.CLOSED)
                {
                    switch(monster.monsterCode)
                    {
                        case MonsterCode.HUMAN: return false;
                        case MonsterCode.SPONGE: return false;
                        case MonsterCode.GHOST: return true;
                        case MonsterCode.SLIME: return false;
                        case MonsterCode.SMALL_SLIME: return false;
                        case MonsterCode.TINY_SLIME: return false;
                        case MonsterCode.DEER: return false;
                        case MonsterCode.PIG: return false;
                        default: return false;
                    }
                }
            }

            //deep water check
            if(newTerrain.getWater() >= TerrainManager.DEEP_WATER)
            {
                switch(monster.monsterCode)
                {
                    case MonsterCode.GHOST: return false;
                    case MonsterCode.TINY_SLIME: return false;
                    default: break; //do nothing
                }
            }

            //empty newTerrain check
            switch(newTerrain.getCode())
            {
                case TerrainCode.PATH:
                switch (monster.monsterCode)
                {
                    case MonsterCode.HUMAN: return true;
                    case MonsterCode.SPONGE: return true;
                    case MonsterCode.GHOST: return true;
                    case MonsterCode.SLIME: return true;
                    case MonsterCode.SMALL_SLIME: return true;
                    case MonsterCode.TINY_SLIME: return true;
                    case MonsterCode.DEER: return true;
                    case MonsterCode.PIG: return true;
                    default: return false;
                }

                case TerrainCode.DIRT:
                switch (monster.monsterCode)
                {
                    case MonsterCode.HUMAN: return true;
                    case MonsterCode.SPONGE: return true;
                    case MonsterCode.GHOST: return true;
                    case MonsterCode.SLIME: return true;
                    case MonsterCode.SMALL_SLIME: return true;
                    case MonsterCode.TINY_SLIME: return true;
                    case MonsterCode.DEER: return true;
                    case MonsterCode.PIG: return true;
                    default: return false;
                }

                case TerrainCode.ROCK:
                switch (monster.monsterCode)
                {
                    case MonsterCode.HUMAN: return false;
                    case MonsterCode.SPONGE: return false;
                    case MonsterCode.GHOST: return true;
                    case MonsterCode.SLIME: return false;
                    case MonsterCode.SMALL_SLIME: return false;
                    case MonsterCode.TINY_SLIME: return false;
                    case MonsterCode.DEER: return false;
                    case MonsterCode.PIG: return false;
                    default: return false;
                }

                case TerrainCode.STREAM_BED:
                switch (monster.monsterCode)
                {
                    case MonsterCode.HUMAN: return true;
                    case MonsterCode.SPONGE: return true;
                    case MonsterCode.GHOST: return true;
                    case MonsterCode.SLIME: return true;
                    case MonsterCode.SMALL_SLIME: return false;
                    case MonsterCode.TINY_SLIME: return false;
                    case MonsterCode.DEER: return true;
                    case MonsterCode.PIG: return true;
                    default: return false;
                }

                case TerrainCode.GRASS:
                switch (monster.monsterCode)
                {
                    case MonsterCode.HUMAN: return true;
                    case MonsterCode.SPONGE: return true;
                    case MonsterCode.GHOST: return true;
                    case MonsterCode.SLIME: return true;
                    case MonsterCode.SMALL_SLIME: return true;
                    case MonsterCode.TINY_SLIME: return true;
                    case MonsterCode.DEER: return true;
                    case MonsterCode.PIG: return true;
                    default: return false;
                }

                case TerrainCode.STONE_WALL:
                switch (monster.monsterCode)
                {
                    case MonsterCode.HUMAN: return false;
                    case MonsterCode.SPONGE: return false;
                    case MonsterCode.GHOST: return true;
                    case MonsterCode.SLIME: return false;
                    case MonsterCode.SMALL_SLIME: return false;
                    case MonsterCode.TINY_SLIME: return false;
                    case MonsterCode.DEER: return false;
                    case MonsterCode.PIG: return false;
                    default: return false;
                }

                case TerrainCode.STONE_FLOOR:
                switch (monster.monsterCode)
                {
                    case MonsterCode.HUMAN: return true;
                    case MonsterCode.SPONGE: return true;
                    case MonsterCode.GHOST: return true;
                    case MonsterCode.SLIME: return true;
                    case MonsterCode.SMALL_SLIME: return true;
                    case MonsterCode.TINY_SLIME: return true;
                    case MonsterCode.DEER: return true;
                    case MonsterCode.PIG: return true;
                    default: return false;
                }

                case TerrainCode.FERTILE_LAND:
                switch (monster.monsterCode)
                {
                    case MonsterCode.HUMAN: return true;
                    case MonsterCode.SPONGE: return true;
                    case MonsterCode.GHOST: return true;
                    case MonsterCode.SLIME: return true;
                    case MonsterCode.SMALL_SLIME: return true;
                    case MonsterCode.TINY_SLIME: return true;
                    case MonsterCode.DEER: return true;
                    case MonsterCode.PIG: return true;
                    default: return false;
                }
            }

            return false;
        }
        public static bool wetable(Terrain terrain, int x, int y, Quinoa quinoa)
        {
            if(TerrainManager.hasParameter(terrain, TerrainParameter.HAS_DOOR))
            {
                DoorCode doorCode = (DoorCode)Enum.Parse(typeof(DoorCode),TerrainManager.getParameter(terrain, TerrainParameter.HAS_DOOR));
                return (doorCode == DoorCode.OPEN);
            }

            if(TerrainManager.hasParameter(terrain, TerrainParameter.HAS_FLOODGATE))
            {
                DoorCode doorCode = (DoorCode)Enum.Parse(typeof(DoorCode), TerrainManager.getParameter(terrain, TerrainParameter.HAS_FLOODGATE));
                if(doorCode == DoorCode.OPEN)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }

            switch(terrain.getCode())
            {
                case TerrainCode.PATH:
                case TerrainCode.DIRT:
                case TerrainCode.GRASS:
                case TerrainCode.STONE_FLOOR:
                case TerrainCode.FERTILE_LAND:
                case TerrainCode.STREAM_BED:
                return true;

                case TerrainCode.STONE_WALL:
                case TerrainCode.ROCK:
                default:
                return false;
            }
        }
        public static bool transparent(Terrain terrain)
        {
            if(hasParameter(terrain, TerrainParameter.HAS_TREE))
            {
                return false;
            }

            if(hasParameter(terrain, TerrainParameter.HAS_DOOR))
            {
                DoorCode doorCode = (DoorCode)Enum.Parse(typeof(DoorCode), TerrainManager.getParameter(terrain, TerrainParameter.HAS_DOOR));
                return (doorCode == DoorCode.OPEN);
            }

            switch(terrain.getCode())
            {
                case TerrainCode.PATH:
                case TerrainCode.DIRT:
                case TerrainCode.GRASS:
                case TerrainCode.STONE_FLOOR:
                case TerrainCode.FERTILE_LAND:
                case TerrainCode.STREAM_BED:
                default:
                return true;

                case TerrainCode.STONE_WALL:
                case TerrainCode.ROCK:
                return false;
            }
        }