def DiplomacyStanceEnum(ctx):
    """Diplomacy stance."""
    return Enum(
        ctx,
        allied=0,
        neutral=1,
        enemy=3
    ) def FormationEnum(ctx):
    """Types of formations."""
    return Enum(
        ctx,
        line=2,
        box=4,
        staggered=7,
        flank=8
    ) def GameActionModeEnum(ctx):
    """Game Action Modes."""
    return Enum(
        ctx,
        diplomacy=0,
        speed=1,
        instant_build=2,
        quick_build=4,
        allied_victory=5,
        cheat=6,
        unk0=9,
        spy=10,
        unk1=11,
        farm_queue=13,
        farm_unqueue=14,
        farm_autoqueue=16,
        fishtrap_queue=17,
        fishtrap_unqueue=18,
        fishtrap_autoqueue=19,
        default_stance=20,
        default=Pass
    ) def OrderTypeEnum(ctx):
    """Types of Orders."""
    return Enum(
        ctx,
        packtreb=1,
        unpacktreb=2,
        garrison=5,
        default=Pass
    ) def ReleaseTypeEnum(ctx):
    """Types of Releases."""
    return Enum(
        ctx,
        all=0,
        selected=3,
        sametype=4,
        notselected=5,
        inversetype=6,
        default=Pass
    ) def ResourceEnum(ctx):
    """Resource Type Enumeration."""
    return Enum(
        ctx,
        food=0,
        wood=1,
        stone=2,
        gold=3,
        decay=12,
        fish=17,
        default=Pass # lots of resource types exist
    ) def ResourceLevelEnum(ctx):
    """Resource Level Enumeration."""
    return Enum(
        ctx,
        none=-1,
        standard=0,
        low=1,
        medium=2,
        high=3,
        unknown1=4,
        unknown2=5,
        unknown3=6
    ) def RevealMapEnum(ctx):
    """Reveal Map Enumeration."""
    return Enum(
        ctx,
        normal=0,
        explored=1,
        all_visible=2,
        no_fog=3,
    ) def StanceEnum(ctx):
    """Types of stances."""
    return Enum(
        ctx,
        aggressive=0,
        defensive=1,
        stand_ground=2,
        passive=3
    ) def AgeEnum(ctx):
    """Age Enumeration."""
    return Enum(
        ctx,
        what=-2,
        unset=-1,
        dark=0,
        feudal=1,
        castle=2,
        imperial=3,
        postimperial=4,
        dmpostimperial=6,
        default='unknown'
    ) def VictoryEnum(ctx):
    """Victory Type Enumeration."""
    return Enum(
        ctx,
        standard=0,
        conquest=1,
        exploration=2,
        ruins=3,
        artifacts=4,
        discoveries=5,
        gold=6,
        time_limit=7,
        score=8,
        standard2=9,
        regicide=10,
        last_man=11
    ) class TimeSecAdapter(Adapter):
    """Conversion to readable time."""

    def _decode(self, obj, context):
        """Decode timestamp to string."""
        return convert_to_timestamp(obj) def check_flags(peek):
    """Check byte sequence for only flag bytes."""
    for i in peek:
        if i not in [0, 1]:
            return False
    return True
from construct import (Array, Byte, Const, CString, Flag, Float32l, If,
                       Int16ul, Int32sl, Int32ul, Padding, Peek, String,
                       Struct, this, Bytes, Embedded, IfThenElse)
from mgz.body.achievements import achievements
from mgz.enums import (DiplomacyStanceEnum, FormationEnum, GameActionModeEnum,
                       OrderTypeEnum, ReleaseTypeEnum, ResourceEnum,
                       ResourceLevelEnum, RevealMapEnum, StanceEnum,
                       AgeEnum, VictoryEnum)
from mgz.util import TimeSecAdapter, check_flags
    "x"/Float32l,
    "y"/Float32l,
    Padding(4), # const
    "next"/Peek(Bytes(4)),
    "flags"/If(lambda ctx: check_flags(ctx.next), Bytes(4)),
    Array(lambda ctx: ctx.selected, "unit_ids"/Int32ul),
)

gatherpoint = "gatherpoint"/Struct(
    "selected"/Byte,
    Padding(2),
    "target_id"/Int32ul,
    "target_type"/Int32ul,
    "x"/Float32l,
    "y"/Float32l,
    Array(lambda ctx: ctx.selected, "unit_ids"/Int32ul)
)

townbell = "townbell"/Struct(
    Padding(3),
    "towncenter_id"/Int32ul,
    "active"/Int32ul
)

"""Patrol

10 X-coordinates followed by 10 Y-coordinates
First of each is popped off for consistency with other actions
"""
patrol = "patrol"/Struct(
    "selected"/Byte,
    "waypoints"/Int16ul,
    "x"/Float32l,
    Array(9, "x_more"/Float32l),
    "y"/Float32l,
    Array(9, "y_more"/Float32l),
    Array(lambda ctx: ctx.selected, "unit_ids"/Int32ul),
)

waypoint = "waypoint"/Struct(
    Padding(1),
    "selected"/Byte,
    "x"/Byte,
    "y"/Byte,
    "building_ids"/If(lambda ctx: ctx.selected != 255, Array(
        lambda ctx: ctx.selected, Int32ul
    ))
)

ai_waypoint = "ai_waypoint"/Struct(
    "selected"/Byte,
    "waypoint_count"/Byte,
    Array(lambda ctx: ctx.selected, "unit_ids"/Int32ul),
    Array(lambda ctx: ctx.waypoint_count, "x_more"/Byte),
    Array(lambda ctx: ctx.waypoint_count, "y_more"/Byte)
)

backtowork = "backtowork"/Struct(
    Padding(3),
    "towncenter_id"/Int32ul
)

ai_command = "ai_command"/Struct(
    Padding(lambda ctx: ctx._._.length - 1)
)

"""DE Queue

In DE queue and multi queue share the same command
"""
de_queue = "de_queue"/Struct(
    "player_id"/Byte,
    "building_type"/Int16ul,
    "selected"/Byte,
    Padding(1),
    "unit_type"/Int16ul,
    "queue_amount"/Byte,
    Padding(1),
    Array(lambda ctx: ctx.selected, "building_ids"/Int32ul)
)

"""DE Attack Move

It's almost the same as Patrol.

10 X-coordinates followed by 10 Y-coordinates
First of each is popped off for consistency with other actions
"""
de_attackmove = "de_attackmove"/Struct(
    "selected"/Byte,
    "waypoints"/Int16ul,
    "x"/Float32l,
    Array(9, "x_more"/Float32l),
    "y"/Float32l,
    Array(9, "y_more"/Float32l),
    Array(lambda ctx: ctx.selected, "unit_ids"/Int32ul),
)

postgame = "achievements"/Struct(
    Padding(3),
    "scenario_filename"/String(32, padchar=b'\x00', trimdir='right', encoding='latin1'),
    "player_num"/Byte,
    "computer_num"/Byte,
    Padding(2),
    Peek("duration_int"/Int32ul),
    TimeSecAdapter("duration"/Int32ul),
    "cheats"/Flag,
    "complete"/Flag,
    Padding(2),
    "db_checksum"/Int32ul,
    "code_checksum"/Int32ul,
    "version"/Float32l,
    "map_size"/Byte,
    "map_id"/Byte,
    "population"/Int16ul,
    Peek("victory_type_id"/Byte),
    VictoryEnum("victory_type"/Byte),
    Peek("starting_age_id"/Byte),
    AgeEnum("starting_age"/Byte),
    Peek("starting_resources_id"/Byte),

    ResourceLevelEnum("starting_resources"/Byte),