Skip to content

Commit

Permalink
Parse PlayerOwners and PlayerSides from map data
Browse files Browse the repository at this point in the history
  • Loading branch information
icza committed Jun 9, 2022
1 parent 4d2f1f6 commit 49dacdb
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 2 deletions.
2 changes: 1 addition & 1 deletion cmd/screp/screp.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (

const (
appName = "screp"
appVersion = "v1.7.1"
appVersion = "v1.7.2"
appAuthor = "Andras Belicza"
appHome = "https://github.com/icza/screp"
)
Expand Down
16 changes: 16 additions & 0 deletions rep/mapdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ type MapData struct {
// Scenario description
Description string

// PlayerOwners defines the player types (player owners).
PlayerOwners []*repcore.PlayerOwner

// PlayerSides defines the player sides (player races).
PlayerSides []*repcore.PlayerSide

// Tiles is the tile data of the map (within the tile set): width x height elements.
// 1 Tile is 32 units (pixel)
Tiles []uint16
Expand All @@ -41,6 +47,16 @@ type MapData struct {
Debug *MapDataDebug `json:"-"`
}

// MaxHumanPlayers returns the max number of human players on the map.
func (md *MapData) MaxHumanPlayers() (count int) {
for _, owner := range md.PlayerOwners {
if owner == repcore.PlayerOwnerHumanOpenSlot {
count++
}
}
return
}

// Resource describes a resource (mineral field of vespene geyser).
type Resource struct {
// Location of the resource
Expand Down
86 changes: 86 additions & 0 deletions rep/repcore/enums.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,3 +389,89 @@ func TileSetByID(ID uint16) *TileSet {
}
return &TileSet{UnknownEnum(ID), ID}
}

// PlayerOwner describes a player owner.
type PlayerOwner struct {
Enum

// ID as it appears in replays
ID uint8
}

// PlayerOwners is an enumeration of the possible player owners
var PlayerOwners = []*PlayerOwner{
{Enum{"Inactive"}, 0x00},
{Enum{"Computer (game)"}, 0x01},
{Enum{"Occupied by Human Player"}, 0x02},
{Enum{"Rescue Passive"}, 0x03},
{Enum{"Unused"}, 0x04},
{Enum{"Computer"}, 0x05},
{Enum{"Human (Open Slot)"}, 0x06},
{Enum{"Neutral"}, 0x07},
{Enum{"Closed slot"}, 0x08},
}

// Named player owners
var (
PlayerOwnerInactive = PlayerOwners[0]
PlayerOwnerComputerGame = PlayerOwners[1]
PlayerOwnerOccupiedByHumanPlayer = PlayerOwners[2]
PlayerOwnerRescuePassive = PlayerOwners[3]
PlayerOwnerUnused = PlayerOwners[4]
PlayerOwnerComputer = PlayerOwners[5]
PlayerOwnerHumanOpenSlot = PlayerOwners[6]
PlayerOwnerNeutral = PlayerOwners[7]
PlayerOwnerClosedSlot = PlayerOwners[8]
)

// PlayerOwnerByID returns the PlayerOwner for a given ID.
// A new PlayerOwner with Unknown name is returned if one is not found
// for the given ID (preserving the unknown ID).
func PlayerOwnerByID(ID uint8) *PlayerOwner {
if int(ID) < len(PlayerOwners) {
return PlayerOwners[ID]
}
return &PlayerOwner{UnknownEnum(ID), ID}
}

// PlayerSide describes a player side (race).
type PlayerSide struct {
Enum

// ID as it appears in replays
ID uint8
}

// PlayerSides is an enumeration of the possible player sides
var PlayerSides = []*PlayerSide{
{Enum{"Zerg"}, 0x00},
{Enum{"Terran"}, 0x01},
{Enum{"Protoss"}, 0x02},
{Enum{"Invalid (Independent)"}, 0x03},
{Enum{"Invalid (Neutral)"}, 0x04},
{Enum{"User Selectable"}, 0x05},
{Enum{"Random (Forced)"}, 0x06}, // Acts as a selected race
{Enum{"Inactive"}, 0x07},
}

// Named player sides
var (
PlayerSideZerg = PlayerSides[0]
PlayerSideTerran = PlayerSides[1]
PlayerSideProtoss = PlayerSides[2]
PlayerSideInvalidIndependent = PlayerSides[3]
PlayerSideInvalidNeutral = PlayerSides[4]
PlayerSideUserSelectable = PlayerSides[5]
PlayerSideRandomForced = PlayerSides[6]
PlayerSideInactive = PlayerSides[7]
)

// PlayerSideByID returns the PlayerSide for a given ID.
// A new PlayerSide with Unknown name is returned if one is not found
// for the given ID (preserving the unknown ID).
func PlayerSideByID(ID uint8) *PlayerSide {
if int(ID) < len(PlayerSides) {
return PlayerSides[ID]
}
return &PlayerSide{UnknownEnum(ID), ID}
}
24 changes: 23 additions & 1 deletion repparser/repparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ https://github.com/neivv/jssuh
Map Data format:
https://www.starcraftai.com/wiki/CHK_Format
http://www.staredit.net/wiki/index.php/Scenario.chk
http://blog.naver.com/PostView.nhn?blogId=wisdomswrap&logNo=60119755717&parentCategoryNo=&categoryNo=19&viewDate=&isShowPopularPosts=false&from=postView
Expand Down Expand Up @@ -59,7 +61,7 @@ import (

const (
// Version is a Semver2 compatible version of the parser.
Version = "v1.8.1"
Version = "v1.8.2"
)

var (
Expand Down Expand Up @@ -735,6 +737,26 @@ func parseMapData(data []byte, r *rep.Replay, cfg Config) error {
r.Header.MapHeight = height
}
}
case "OWNR": // StarCraft Player Types
count := uint32(12) // 12 bytes, 1 for each player
if count > ssSize {
count = ssSize
}
owners := sr.readSlice(count)
md.PlayerOwners = make([]*repcore.PlayerOwner, len(owners))
for i, id := range owners {
md.PlayerOwners[i] = repcore.PlayerOwnerByID(id)
}
case "SIDE": // Player races
count := uint32(12) // 12 bytes, 1 for each player
if count > ssSize {
count = ssSize
}
sides := sr.readSlice(count)
md.PlayerSides = make([]*repcore.PlayerSide, len(sides))
for i, id := range sides {
md.PlayerSides[i] = repcore.PlayerSideByID(id)
}
case "MTXM": // Tile sub-section
// map_width*map_height (a tile is an uint16 value)
maxI := ssSize / 2
Expand Down

0 comments on commit 49dacdb

Please sign in to comment.