Categorygithub.com/samuelyuan/PolytopiaMapImage
modulepackage
0.0.0-20241224005521-b43b1af46766
Repository: https://github.com/samuelyuan/polytopiamapimage.git
Documentation: pkg.go.dev

# README

PolytopiaMapImage

Introduction

The Battle of Polytopia only allows one save file to be saved. If a new game is started, the old save files are discarded. There is no way to view a snapshot of the game at any time or any replay system that allows you to view past games.

This program extracts the map from the save file and converts it into an image or replay file that you can preserve and share.

Command-Line Usage

The input filename must be a .state file from the save game directory. Make sure to copy the .state file in a different folder, such as this project, because the .state file will be deleted after you win or lose every game. Once the game ends and the .state file is lost, it can't be recovered.

The output filename is an image or gif that you want to save to.

The mode is either "image" or "replay". The image mode will generate a screenshot of the map at the last saved turn and the replay mode will generate an entire replay of the game from the beginning to the current turn.

./PolytopiaMapImage.exe -input=[input filename] -output=[output filename (default is output.png)] -mode=[drawing mode (default is image)]

Draw Image

./PolytopiaMapImage.exe -input=00000000-0000-0000-0000-000000000000.state -output=map.png -mode=image]

Draw Replay

./PolytopiaMapImage.exe -input=00000000-0000-0000-0000-000000000000.state -output=replay.gif -mode=replay

Examples

Map Image

map

Replay

replay pangea

File format

The .state file is compressed using LZ4. The file consists of the initial map state, current map state, and a list of all actions taken in game.

Map Header

The header contains all of the game settings.

TypeSizeDescription
uint324 bytesVersion1
uint324 bytesVersion2
uint162 bytesTotalActions
uint324 bytesCurrentTurn
uint81 byteCurrentPlayerIndex
uint324 bytesMaxUnitId
uint81 byteCurrentGameState
int324 bytesSeed
uint324 bytesTurnLimit
uint324 bytesScoreLimit
uint81 byteWinByCapital
byte[6]6 bytesUnknownSettings
uint81 byteGameModeBase
uint81 byteGameModeRules
varstringvar bytesMap name
uint324 bytesMap square size
uint162 bytesdisabledTribesSize
uint16 arraydisabledTribesSize*2 bytesDisabled tribes
uint162 bytesunlockedTribesSize
uint16 arrayunlockedTribesSize*2 bytesUnlocked tribes
uint162 bytesGame difficulty
uint324 bytesNumber of opponents
uint162 bytesGame type
uint81 byteMap preset
int324 bytesTurn time limit in minutes
float324 bytesunknownFloat1
float324 bytesunknownFloat2
float324 bytesbaseTimeSeconds
byte[4]4 bytestimeSettings
uint324 bytesselectedTribeSkinSize
uint16 arrayselectedTribeSkinSize*2 bytesTribe to skin map
uint162 bytesMap width
uint162 bytesMap height

Map Tiles

The first two unsigned shorts contain the map width and height. The following data is a 2D array of tiles.

The tile data contains resource data, improvement data, unit data if they exist for that tile.

Tile Data

TypeSizeDescription
uint32[2]8 bytesWorldCoordinates
uint162 bytesTerrain
uint162 bytesClimate
int162 bytesAltitude
uint81 byteOwner
uint81 byteCapital
int32[2]8 bytesCapitalCoordinates
bool1 byteResourceExists
uint162 bytesResourceType
bool1 byteImprovementExists
uint162 bytesImprovementType
ImprovementDatasizeof(ImprovementData)ImprovementData ( if ImprovementExists is true)
bool1 byteHasUnitFlag
UnitDatasizeof(UnitData)Unit (if HasUnitFlag is true)
bool1 byteHasPassengerUnitFlag (if HasUnitFlag is true)
UnitDatasizeof(UnitData)PassengerUnit (if HasPassengerUnitFlag is true)
bool1 bytePassengerUnitHasUnitFlag (if HasPassengerUnitFlag is true, should always be zero because passenger unit can't carry another unit)
uint162 bytesPassengerUnitEffectDataLength (if HasPassengerUnitFlag is true)
unit16 arrayPassengerUnitEffectDataLength*2 bytesPassengerUnitEffectData (if HasPassengerUnitFlag is true)
byte[5]5 bytesPassengerUnitDirectionData (if HasPassengerUnitFlag is true)
uint162 bytesUnitEffectDataLength (if HasUnitFlag is true, flags: 0 - ice, 1 - poison, 2 - boost, 3 - invisible)
unit16 arrayUnitEffectDataLength*2 bytesUnitEffectData (if HasUnitFlag is true)
byte[5]5 bytesUnitDirectionData (if HasUnitFlag is true, contains direction flag (0 - southwest, 1 - west, 2 - northwest, 3 - north, 4 - northeast, 5 - east, 6 - southwest, 7 - south))
uint81 bytePlayerVisibilityLength
uint8 arrayPlayerVisibilityLength*1 bytesPlayerVisibility
bool1 byteHasRoad
bool1 byteHasWaterRoute
uint162 bytesTileSkin
byte[2]2 bytesUnknown

Improvement Data

TypeSizeDescription
uint162 bytesLevel
uint162 bytesFoundedTurn
int162 bytesCurrentPopulation
uint162 bytesTotalPopulation
int162 bytesProduction
int162 bytesBaseScore
int162 bytesBorderSize
int162 bytesUpgradeCount
uint81 byteConnectedPlayerCapital
uint81 byteHasCityName
varstringvar bytesCityName (only if HasCityName is true)
uint81 byteFoundedTribe
uint162 bytesCityRewardsLength
uint16 arrayCityRewardsLength*2CityRewards
uint162 bytesRebellionFlag
byte[2]2 bytesRebellionBuffer

Unit Data

TypeSizeDescription
uint324 bytesUnitId
uint81 byteOwner
uint162 bytesUnitType
uint324 bytesFollowerUnitId (only initialized for cymanti centipedes and segments)
uint324 bytesLeaderUnitId (only initialized for cymanti centipedes and segments)
int32[2]8 bytesCurrentCoordinates
int32[2]8 bytesHomeCoordinates
uint162 bytesHealth (should be divided by 10 to get value ingame)
uint162 bytesPromotionLevel
uint162 bytesExperience
bool1 byteMoved
bool1 byteAttacked
bool1 byteFlipped
uint162 bytesCreatedTurn

Player Data

A list of all players in the game.

The size of the player list is a uint16 followed by an array of players.

TypeSizeDescription
uint81 bytePlayerId
varstringvar bytesName
varstringvar bytesAccountId
bool1 byteAutoPlay
int32[2]8 bytesStartTileCoordinates
uint162 bytesTribe
uint81 byteUnknownByte1
uint324 bytesDifficultyHandicap
uint162 bytesAggressionsByPlayers length
PlayerAggression arrayAggressionsByPlayersLength*5AggressionsByPlayers
uint324 bytesCurrency
uint324 bytesScore
uint324 bytesUnknownInt2
uint162 bytesNumCities
uint162 bytesAvailableTechLength
uint16 arrayAvailableTechLength*2AvailableTech
uint162 bytesEncounteredPlayersLength
uint8 arrayEncounteredPlayersLength*1EncounteredPlayers
uint162 bytesPlayerTaskDataLength
PlayerTaskData arrayvariable length depending on task and bufferPlayerTaskData
int324 bytesTotalUnitsKilled
int324 bytesTotalUnitsLost
int324 bytesTotalTribesDestroyed
uint8[4]4 bytesOverrideColor
uint81 byteOverrideTribe
uint162 bytesUniqueImprovementsLength
uint16 arrayUniqueImprovementsLength*2UniqueImprovements
uint162 bytesDiplomacyArrLength
DiplomacyData arrayDiplomacyArrLength*23DiplomacyArr
uint162 bytesDiplomacyMessagesLength
DiplomacyMessage arrayDiplomacyMessagesLength*2DiplomacyMessages
uint81 byteDestroyedByTribe
uint324 bytesDestroyedTurn
uint8[4]4 bytesUnknownBuffer2
int324 bytesEndScore
uint162 bytesPlayerSkin
uint8[4]4 bytesUnknownBuffer3

Actions List

The first two bytes is an unsigned short that describes how many actions there are saved. The following data is a list of actions.

Every action begins with an unsigned short that describes the type of action followed by a fixed number of bytes depending on the action.

# Packages

No description provided by the author