// Path: src/main/java/pl/joegreen/sergeants/framework/model/Position.java
// @Value
// @Wither
// public class Position {
//     int row;
//     int col;
// 
//     public static Position fromIndex(int index, int columns) {
//         return new Position(index / columns, index % columns);
//     }
// 
//     public int toIndex(int columns) {
//         return getCol() + getRow() * columns;
//     }
// 
//     public boolean isVisibleFrom(Position otherPosition) {
//         return Math.abs(row - otherPosition.row) <= 1 && Math.abs(col - otherPosition.col) <= 1;
//     }
// 
//     public boolean isMovableFrom(Position otherPosition) {
//         return Math.abs(row - otherPosition.row) + Math.abs(col - otherPosition.col) == 1;
//     }
// }
// 
// Path: src/main/java/pl/joegreen/sergeants/simulator/viewer/ViewerField.java
// @Value
// public class ViewerField {
//     Position position;
//     Integer owner;
//     int army;
//     boolean city;
//     boolean general;
//     boolean mountain;
// 
//     public String serializeToString() {
//         StringBuilder builder = new StringBuilder();
//         if (army > 0) {
//             builder.append(army);
//         }
//         if (city) {
//             builder.append("c");
//         }
//         if (general) {
//             builder.append("g");
//         }
//         if (mountain) {
//             builder.append("m");
//         }
//         if (owner != null) {
//             builder.append("o").append(owner);
//         }
//         return builder.toString();
//     }
// }
// 
// Path: src/main/java/pl/joegreen/sergeants/simulator/viewer/ViewerMapState.java
// @Value
// public class ViewerMapState {
//     int tick;
//     int height;
//     int width;
//     Set<ViewerField> fields;
// 
//     public String serializeToString(){
//         StringBuilder builder = new StringBuilder();
//         builder.append(tick);
//         builder.append(";").append(height).append(";").append(width).append(";");
//         Comparator<ViewerField> orderComparator = Comparator.<ViewerField, Integer>comparing(vf -> vf.getPosition().getRow()).thenComparing(vf -> vf.getPosition().getCol());
//         String fields = this.fields.stream().sorted(orderComparator).map(ViewerField::serializeToString).collect(Collectors.joining("|"));
//         builder.append(fields);
//         return builder.toString();
//     }
// }


import pl.joegreen.sergeants.framework.model.Position;
import pl.joegreen.sergeants.simulator.viewer.ViewerField;
import pl.joegreen.sergeants.simulator.viewer.ViewerMapState;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
    private Optional<Tile> getTileBelow(Tile tile) {
        int tileIndex = tile.getTileIndex() + width;
        return tileIndex < tiles.length ? Optional.of(tiles[tileIndex]) : Optional.empty();
    }

    private Optional<Tile> getTileRightOf(Tile tile) {
        boolean isMostRight = tile.getTileIndex() % width == width - 1;
        return isMostRight ? Optional.empty() : Optional.of(tiles[tile.getTileIndex() + 1]);
    }

    private Optional<Tile> getTileLeftOf(Tile tile) {
        int tileIndex = tile.getTileIndex();
        boolean isMostLeft = tileIndex == 0 || tileIndex % width == 0;
        return isMostLeft ? Optional.empty() : Optional.of(tiles[tileIndex - 1]);
    }

    int getHalfTurnCounter() {
        return halfTurnCounter;
    }

    int getHeight() {
        return height;
    }

    int getWidth() {
        return width;
    }


    public static ViewerMapState toViewerMapState(GameMap map) {
// Path: src/main/java/pl/joegreen/sergeants/framework/model/Position.java
// @Value
// @Wither
// public class Position {
//     int row;
//     int col;
// 
//     public static Position fromIndex(int index, int columns) {
//         return new Position(index / columns, index % columns);
//     }
// 
//     public int toIndex(int columns) {
//         return getCol() + getRow() * columns;
//     }
// 
//     public boolean isVisibleFrom(Position otherPosition) {
//         return Math.abs(row - otherPosition.row) <= 1 && Math.abs(col - otherPosition.col) <= 1;
//     }
// 
//     public boolean isMovableFrom(Position otherPosition) {
//         return Math.abs(row - otherPosition.row) + Math.abs(col - otherPosition.col) == 1;
//     }
// }
// 
// Path: src/main/java/pl/joegreen/sergeants/simulator/viewer/ViewerField.java
// @Value
// public class ViewerField {
//     Position position;
//     Integer owner;
//     int army;
//     boolean city;
//     boolean general;
//     boolean mountain;
// 
//     public String serializeToString() {
//         StringBuilder builder = new StringBuilder();
//         if (army > 0) {
//             builder.append(army);
//         }
//         if (city) {
//             builder.append("c");
//         }
//         if (general) {
//             builder.append("g");
//         }
//         if (mountain) {
//             builder.append("m");
//         }
//         if (owner != null) {
//             builder.append("o").append(owner);
//         }
//         return builder.toString();
//     }
// }
// 
// Path: src/main/java/pl/joegreen/sergeants/simulator/viewer/ViewerMapState.java
// @Value
// public class ViewerMapState {
//     int tick;
//     int height;
//     int width;
//     Set<ViewerField> fields;
// 
//     public String serializeToString(){
//         StringBuilder builder = new StringBuilder();
//         builder.append(tick);
//         builder.append(";").append(height).append(";").append(width).append(";");
//         Comparator<ViewerField> orderComparator = Comparator.<ViewerField, Integer>comparing(vf -> vf.getPosition().getRow()).thenComparing(vf -> vf.getPosition().getCol());
//         String fields = this.fields.stream().sorted(orderComparator).map(ViewerField::serializeToString).collect(Collectors.joining("|"));
//         builder.append(fields);
//         return builder.toString();
//     }
// }


// Path: src/main/java/pl/joegreen/sergeants/simulator/GameMap.java
import pl.joegreen.sergeants.framework.model.Position;
import pl.joegreen.sergeants.simulator.viewer.ViewerField;
import pl.joegreen.sergeants.simulator.viewer.ViewerMapState;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

    private Optional<Tile> getTileBelow(Tile tile) {
        int tileIndex = tile.getTileIndex() + width;
        return tileIndex < tiles.length ? Optional.of(tiles[tileIndex]) : Optional.empty();
    }

    private Optional<Tile> getTileRightOf(Tile tile) {
        boolean isMostRight = tile.getTileIndex() % width == width - 1;
        return isMostRight ? Optional.empty() : Optional.of(tiles[tile.getTileIndex() + 1]);
    }

    private Optional<Tile> getTileLeftOf(Tile tile) {
        int tileIndex = tile.getTileIndex();
        boolean isMostLeft = tileIndex == 0 || tileIndex % width == 0;
        return isMostLeft ? Optional.empty() : Optional.of(tiles[tileIndex - 1]);
    }

    int getHalfTurnCounter() {
        return halfTurnCounter;
    }

    int getHeight() {
        return height;
    }

    int getWidth() {
        return width;
    }


    public static ViewerMapState toViewerMapState(GameMap map) {
        Set<ViewerField> viewerFields = Arrays.stream(map.getTiles()).map(