Staredit Network > Forums > General StarCraft > Topic: .chk SC1 Player Numbers field
.chk SC1 Player Numbers field
Feb 3 2014, 5:18 pm
By: khr1  

Feb 3 2014, 5:18 pm khr1 Post #1



Hello,
I am looking for a way to check the number of players of a given .chk map in command-line Linux.
If someone knows which field contains this, I will write a tool that extracts it and share it with the community. (Assuming there is no easier way).
All ideas are welcome.
Thanks!



None.

Feb 3 2014, 6:22 pm Cinolt Post #2



http://www.staredit.net/starcraft/Scenario.chk

IOWN/OWNR section.



None.

Feb 4 2014, 1:24 pm khr1 Post #3



Thanks a lot!
Is there any tool already that can extract it?



None.

Feb 4 2014, 2:21 pm khr1 Post #4



OK, assuming there's no such tool, I wrote one.
Here you go:


/* FEB 2014:
* Reads thru' the sections of .chk file (as outlined in http://www.staredit.net/starcraft/Scenario.chk#Section_headers )
* Returns the number of human players.
*/

# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <string.h>
# include <errno.h>
# include <fcntl.h>

int
main (int argc, char ** argv) {
int fd = 0,
n = 0,
i = 0,
humans = 0;
char buf [2048] = { 0 },
* new = NULL;
unsigned long kolku = 0;

if (argc < 2) {
fprintf (stderr, "%s scenario.chk\n", argv [0]);
exit (EXIT_FAILURE);
}

fd = open (argv [1], O_RDWR, 0);

if (-1 == fd) {
fprintf (stderr, "open: %s: %s\n", argv [1], strerror (errno));
exit (EXIT_FAILURE);
}

while (1) {
memset (buf, 0x00, sizeof (buf));

/* 4-byte starts with the name of the section, always. */
n = read (fd, buf, 4);

if (n != 4) {
fprintf (stderr, "Either we read it all, or wrong datafile given (we need scenario.chk, not mopaq file)\n");
break;
}

/* What follows is unsigned long telling us how long this section actually is. */
n = read (fd, &kolku, sizeof (unsigned long));

fprintf (stdout, "buf = '%s', n = %d, kolku = %ld\n", buf, n, kolku);

/* We need at least `kolku' bytes. */
new = malloc (kolku + 1);
if (new == NULL) {
fprintf (stderr, "Definitely buy RAM.. malloc failed!\n");
exit (EXIT_FAILURE);
}

read (fd, new, kolku); /* read them anyway. If its the section we need, OK, if not - we just skip it. */

if (strcmp (buf, "OWNR") == 0) {
/* THIS is the section we're interested in. Check it out. */

if (kolku != 12) {
/* Should be fixed 12 here, according to http://www.staredit.net/starcraft/Scenario.chk#Section_headers */
fprintf (stdout, "Something sinister is going on... kolku != 12..\n");
}

for (i = 0; i < kolku; i ++) {
switch (new [i]) {
case 0:
fprintf (stdout, "%d byte: Inactive player\n", i);
break;

case 1:
fprintf (stdout, "%d byte: Computer (game)\n", i);
break;

case 2:
fprintf (stdout, "%d byte: Occupied by Human player\n", i);
break;

case 3:
fprintf (stdout, "%d byte: Rescue Passive\n", i);
break;

case 4:
fprintf (stdout, "%d byte: Unused\n", i);
break;

case 5:
fprintf (stdout, "%d byte: Computer\n", i);
break;

case 6:
fprintf (stdout, "%d byte: Human (open slot)\n", i);
humans ++;
break;

case 7:
fprintf (stdout, "%d byte: Neutral\n", i);
break;

case 8:
fprintf (stdout, "%d byte: Closed slot\n", i);
break;

default:
/* wat? shouldn't happen */
break;
}
}
}

free (new);
}

close (fd);
fprintf (stdout, "humans = %d\n", humans);
return (0);
}



None.

Feb 4 2014, 4:46 pm Cinolt Post #5



Code seems functionally alright, but personally I'd just make it standard C instead of UNIX specific.

Also, I'd put the code in a standalone procedure so you can call it after decompressing a chk from a MPQ or such.

For "new = malloc (kolku + 1);" not sure why the +1 is there.

(strcmp (buf, "OWNR") == 0 is the same thing as *(long *)buf == *(long *)"OWNR" which to me seems more expressive.



None.

Feb 4 2014, 7:52 pm khr1 Post #6



The code is ANSI C, of course, and has nothing to do with UNIX. Why would you think that?
It is a 4-byte string. strcmp is prudent here, and should be treated as string, not as long* of course..
1 is a habit.

The code *is* tested and working. Making it into a function should take around 15-30 seconds.

Post has been edited 1 time(s), last time on Feb 5 2014, 7:52 pm by NudeRaider. Reason: removed inciting remark



None.

Feb 4 2014, 8:41 pm O)FaRTy1billion[MM] Post #7

👻 👾 👽 💪

Quote from khr1
It is a 4-byte string. strcmp is prudent here, and should be treated as string, not as long* of course..
It is usually read as an int. Were it a proper string it would be null-terminated.

If you only want to see it for informational purposes it is one of the stats shown in MapStats.



TinyMap2 - Latest in map compression! ( 7/09/14 - New build! )
EUD Action Enabler - Lightweight EUD/EPD support! (ChaosLauncher/MPQDraft support!)
EUDDB - topic - Help out by adding your EUDs! Or Submit reference files in the References tab!
MapSketch - New image->map generator!
EUDTrig - topic - Quickly and easily convert offsets to EUDs! (extended players supported)
SC2 Map Texture Mask Importer/Exporter - Edit texture placement in an image editor!
\:farty\: This page has been viewed [img]http://farty1billion.dyndns.org/Clicky.php?img.gif[/img] times!

Feb 4 2014, 10:44 pm Cinolt Post #8



unistd.h and fcntl.h is not ANSI C.

Never said it wasn't tested, never said it wasn't working.

know how to take constructive criticism.

Post has been edited 1 time(s), last time on Feb 5 2014, 7:56 pm by NudeRaider. Reason: removed response to inciting remark



None.

Feb 5 2014, 1:45 pm khr1 Post #9



You said it was UNIX specific.
But it is not.
You didn't even test it under any Windows compiler to see if you're wrong.
And you are.

I posted the code in case someone has the same problem as me, to save, eventually, someone's time.

Whats the point of your remarks, I can't understand..

Post has been edited 1 time(s), last time on Feb 5 2014, 7:58 pm by NudeRaider. Reason: removed inciting remark



None.

Feb 5 2014, 2:21 pm Heinermann Post #10

SDE, BWAPI owner, hacker.

Here's a version independent of the non-standard headers, with section string bug fixed, redundancy removed, but ultimately untested.

Code
/* FEB 2014:
* Reads thru' the sections of .chk file (as outlined in http://www.staredit.net/starcraft/Scenario.chk#Section_headers )
* Returns the number of human players.
*/

# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <errno.h>

int main (int argc, char ** argv)
{
    int n = 0, i = 0, humans = 0;
    FILE *fd;

    char buf[2048] = { 0 }, *pdata = NULL, *playertype;
    unsigned long kolku = 0;

    if (argc < 2)
    {
        fprintf(stderr, "%s scenario.chk\n", argv [0]);
        return 1;
    }

    fd = fopen(argv[1], "r+");
    if (NULL == fd)
    {
        fprintf(stderr, "open: %s: %s\n", argv [1], strerror(errno));
        return 1;
    }

    while (1)
    {
        memset(buf, 0, sizeof (buf));

        /* 4-byte starts with the name of the section, always. */
        n = fread(buf, 4, 1, fd);
        if (n == 0)
        {
            fprintf(stderr, "Either we read it all, or wrong datafile given (we need scenario.chk, not mopaq file)\n");
            break;
        }

        /* What follows is unsigned long telling us how long this section actually is. */
        n = fread(&kolku, sizeof (kolku), 1, fd);

        printf("buf = '%s', n = %d, kolku = %ld\n", buf, n, kolku);

        /* We need at least `kolku' bytes. */
        pdata = malloc(kolku + 1);
        if (pdata == NULL)
        {
            fprintf(stderr, "Definitely buy RAM.. malloc failed!\n");
            return 1;
        }

        fread(pdata, 1, kolku, fd); /* read them anyway. If its the section we need, OK, if not - we just skip it. */

        if ( strncmp(buf, "OWNR", 4) == 0 )
        {
            /* THIS is the section we're interested in. Check it out. */

            if (kolku != 12)
            {
                /* Should be fixed 12 here, according to http://www.staredit.net/starcraft/Scenario.chk#Section_headers */
                printf("Something sinister is going on... kolku != 12..\n");
            }

            for (i = 0; i < (int)kolku; ++i )
            {
                switch (pdata[i])
                {
                case 0:
                    playertype = "Inactive";
                    break;
                case 1:
                    playertype = "Computer (game)";
                    break;
                case 2:
                    playertype = "Occupied by human";
                    break;
                case 3:
                    playertype = "Rescue Passive";
                    break;
                case 4:
                    playertype = "Unused";
                    break;
                case 5:
                    playertype = "Computer";
                    break;
                case 6:
                    playertype = "Human (open)";
                    humans ++;
                    break;
                case 7:
                    playertype = "Neutral";
                    break;
                case 8:
                    playertype = "Closed";
                    break;
                default:
                    /* wat? shouldn't happen */
                    playertype = "WAT??";
                    break;
                }
                printf("%d byte: %s\n", i, playertype);
            }
        }

        free (pdata);
    }

    fclose(fd);
    printf("humans = %d\n", humans);

    return 0;
}


Post has been edited 1 time(s), last time on Feb 5 2014, 2:28 pm by Heinermann.




Feb 5 2014, 4:42 pm Cinolt Post #11



I don't give a shit that it works for whatever compiler you happened to test it with, I never said it didn't work.

Those header files that I mentioned are not ANSI C, and you said it was ANSI C, and it's not ANSI C, so you're wrong.

http://en.wikipedia.org/wiki/Unistd.h

"In the C and C programming languages, unistd.h is the name of the header file that provides access to the POSIX operating system API. It is defined by the POSIX.1 standard, the base of the Single Unix Specification, and should therefore be available in any conforming (or quasi-conforming) operating system/compiler (all official versions of UNIX, including Mac OS X, GNU/Linux, etc.)."

POSIX is not ANSI C.

By the way you wouldn't even have made this thread if you just searched "scenario.chk".

Post has been edited 1 time(s), last time on Feb 5 2014, 7:59 pm by NudeRaider. Reason: removed inciting remark



None.

Options
  Back to forum
Please log in to reply to this topic or to report it.
Members in this topic: None.
[03:27 am]
m.0.n.3.y -- Maybe because it's an EUD map?
[03:27 am]
m.0.n.3.y -- Can't upload maps to the DB. Error says "The action you have performed caused an Error". Any word?
[07:46 am]
RIVE -- :wob:
[2024-4-22. : 6:48 pm]
Ultraviolet -- :wob:
[2024-4-21. : 1:32 pm]
Oh_Man -- I will
[2024-4-20. : 11:29 pm]
Zoan -- Oh_Man
Oh_Man shouted: yeah i'm tryin to go through all the greatest hits and get the runs up on youtube so my senile ass can appreciate them more readily
You should do my Delirus map too; it's a little cocky to say but I still think it's actually just a good game lol
[2024-4-20. : 8:20 pm]
Ultraviolet -- Goons were functioning like stalkers, I think a valk was made into a banshee, all sorts of cool shit
[2024-4-20. : 8:20 pm]
Ultraviolet -- Oh wait, no I saw something else. It was more melee style, and guys were doing warpgate shit and morphing lings into banelings (Infested terran graphics)
[2024-4-20. : 8:18 pm]
Ultraviolet -- Oh_Man
Oh_Man shouted: lol SC2 in SC1: https://youtu.be/pChWu_eRQZI
oh ya I saw that when Armo posted it on Discord, pretty crazy
[2024-4-20. : 8:09 pm]
Vrael -- thats less than half of what I thought I'd need, better figure out how to open SCMDraft on windows 11
Please log in to shout.


Members Online: jun3hong