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.
[05:59 pm]
Pr0nogo -- NudeRaider
NudeRaider shouted: NudeRaider Background: In music this has caused a loudness war, over the past decades where artists amplified their works more and more to sound more prominent than others. In this context it's actually perceived negative, because while for the untrained listener this creates a more effectful (because louder) piece, it actually destroys the finer details artists used to play very quietly. But because the latter is only appreciated by music enthusiasts with good stereo equipment, the former targets a larger audience and thus has proven more commercially successful.
yeah this happens in all media now, sc2's sfx compared to sc1's is a good example of loudness war. also commercials/youtube ads being way louder than the content you're watching
[05:42 pm]
MasterJohnny -- Echo
Echo shouted: My minerals still negative from Moose
We should get minerals for logging for the day.
[05:23 pm]
jjf28 -- Echo
Echo shouted: Did Crescent Dyne ever get finished
:lol:
[05:14 pm]
Echo -- Did Crescent Dyne ever get finished
[05:13 pm]
Echo -- My minerals still negative from Moose
[05:13 pm]
Echo -- I joined 15 years ago and now I'm turning 29 tomorrow. Time zoomed by
[05:12 pm]
Echo -- What you guys still doing here
[05:06 pm]
NudeRaider -- NudeRaider
NudeRaider shouted: SiKiN Don't wanna persuade you to do anything, Sikin, but Pronogo has a point. Uniformly lifting the wave form can only do so much (you noticed that you hit a ceiliing pretty early) but if you use a method that amplifies quiet component more than loud components the resulting perceived loudness will go up much quicker without hitting distortion.
Background: In music this has caused a loudness war, over the past decades where artists amplified their works more and more to sound more prominent than others. In this context it's actually perceived negative, because while for the untrained listener this creates a more effectful (because louder) piece, it actually destroys the finer details artists used to play very quietly. But because the latter is only appreciated by music enthusiasts with good stereo equipment, the former targets a larger audience and thus has proven more commercially successful.
[05:01 pm]
NudeRaider -- SiKiN
SiKiN shouted: Yea cheers but I think I'll land on 20db, hes fine how he is.
Don't wanna persuade you to do anything, Sikin, but Pronogo has a point. Uniformly lifting the wave form can only do so much (you noticed that you hit a ceiliing pretty early) but if you use a method that amplifies quiet component more than loud components the resulting perceived loudness will go up much quicker without hitting distortion.
[03:03 pm]
Zycorax -- :wob:
Please log in to shout.


Members Online: Pandut, Roy