Sunday, January 12, 2014

Parsing C2 GameLog files with python.

In this post we will see how to precisely parse a C2 Gamelog file.
This file is an ordered collection of all main events happening in Albia : Birth, Ageing, Dieing, getting a Name, Exports or Imports.
Parsing it can be useful to redraw a full timeline of stuff happening in your world, or to see which Norns are still alive or were ever used, if you need to perform some cleanup in the game folder ( by default, genomes and sprites files accumulate in the game folder for each Norn and are never removed )

Whatever your needs are, I hope yo will find this quick reference useful.



The file format:

Once again, this is a format for which documentation exists.

Oddly enough, the file in my game seems to be messed up regarding this format ( and also by any logical standards.)

The standard defines the file as a series of entries, one by line; having the following format :


<MONIKER> | <TIMESTAMP> | <ACTION> | <PARAMS> |

Despite this , the GameLog file in my own game seems to rather be of the form:

<MONIKER> | <TIMESTAMP> | <ACTION><PARAMS> | 



It doesn't seem that the game cares that much about this mess though.
Chances are the file is as it name implies merely a log, and the information is never pulled out of it again.

Here are the fields meanings:

<Moniker>: the 4 char identifier, unique for each creature that ever lived.

<TIMESTAMP>: The date at which the event occurred. This is in the UNIX timestamp format.We can easily convert it to readable formats inside our programs, but keeping it in this numerical format allows for quick and painless ordering of events.

<Action>: is the registered event, it is composed of only one letter , with the following meaning :

B : Birth
A : Creature has aged.
D : Creature has died
N : Creature was given a name( we used that there )
E : Creature was exported
I : Creature was imported

<PARAMS> is optional and is an additional information regarding the event.
Only A and N events have additional params.

For A : the additional param is a number, describing the lifestage a creature has reached.

0:Baby
1:Child
2:Adolescent
3:Youth
4:Adult
5:Old
6 :Senile


For N: the additional parameter is the Name the creature was given.


That's it, there's not much to it , we can get to

Parsing a Gamelog file with python:

This will read the GameLog, pack it in a convenient structure, and then print out the timeline for any Norn you want.
Obviously, depending on the information you're interested in, other structures might provide quicker lookup methods( if you wanted to lookup events by Norn name for example.But keep in mind the moniker is the de-facto creature "unique identifier" to use wherever possible.Converting it to a name should only be a post processing commodity).


from datetime import datetime

GameLogPath="c:/Creatures2/History/Gamelog"
GameLog=open(GameLogPath,).readlines()

Lifestages=["Baby","Child","Adolescent","Youth","Adult","Old","Senile","Kaputt"]


Evts=[]
for line in GameLog:
    line=line.rstrip('\n')
    Fields=line.split("|")

    # Parsing the structure
    if Fields[2][0] == "N":
        Evts.append({"Moniker":Fields[0],"Timestamp":Fields[1],"Action":Fields[2][0],"Name":Fields[2][1:]})
    elif Fields[2][0] == "A":
        Evts.append({"Moniker":Fields[0],"Timestamp":Fields[1],"Action":Fields[2][0],"Stage":Fields[2][1:]})
    else:
        Evts.append({"Moniker":Fields[0],"Timestamp":Fields[1],"Action":Fields[2]})


who = raw_input("Enter a moniker: ")

for event in Evts:
    if event["Moniker"]==who:
        date=datetime.fromtimestamp(int(event["Timestamp"])).strftime("%a, %d %b %Y %X %Z GMT")
        print who,
        if event["Action"]=="B":
            print "is born on", date
        if event["Action"]=="A":
            print "aged to",Lifestages[int(event["Stage"])], "on" ,date
        if event["Action"]=="D":
            print "died on", date
        if event["Action"]=="N":
            print " Was named",event["Name"],"on", date
        if event["Action"]=="E":
            print " Was exported on", date
        if event["Action"]=="I":
            print " Was imported on", date



Running this code produces this kind of output :
Enter a moniker: 7TML
7TML is born on Sat, 14 Dec 2013 14:57:36  GMT
7TML aged to Child on Sat, 14 Dec 2013 15:05:26  GMT
7TML aged to Adolescent on Sat, 14 Dec 2013 17:45:56  GMT
7TML aged to Youth on Sat, 14 Dec 2013 17:52:39  GMT
7TML aged to Adult on Sun, 15 Dec 2013 18:58:46  GMT
7TML aged to Old on Sun, 22 Dec 2013 19:43:00  GMT
7TML aged to Senile on Sun, 29 Dec 2013 15:26:24  GMT
7TML aged to Kaputt on Sun, 29 Dec 2013 18:03:49  GMT
7TML died on Sun, 29 Dec 2013 18:03:49  GMT



Poor "7TML", he lived such a long Norn life without even getting a name.
Well, at least he died peacefully.

No comments:

Post a Comment