Doki Doki Literature Club x Python ① Character file analysis

Introduction

Doki Doki Literature Club, a game that everyone in the know knows.

Did you know that this pounding literary club is written in Python (Renpy)? Then, this project is to use that Python to make the Doki Doki Literature Club naked.

If you are interested, please play the main story. Free.

__ Includes spoilers __ __ The copyright of the content of the article belongs to the author of the Doki Doki Literature Club __

Week 1 "Character file analysis"

Character files deeply involved in story progress

Halfbeak (Awesome air conditioner)

See sayori.chr.

When you open it with a text file normally, the beginning is

OggS~~~~~~~

It starts with. From this, it may be a __.ogg file (audio data) __.

When you actually play it, you should hear high frequency noise.

This is spectrogram-analyzed.

Spectrogram analysis is a visualization of audio data with time on the horizontal axis and frequency on the vertical axis.

Click here for the code

from pydub import AudioSegment
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

#Read ogg and sample
AudioSegment.ffmpeg = "/."
sound = AudioSegment.from_ogg("sayori.ogg")
samples = np.array(sound.get_array_of_samples())
sample = samples[::sound.channels]

#Spectral storage width
w = 100
s = 50

ampList = []
argList = []

#Fourier transform
for i in range(int((sample.shape[0]- w) / s)):
    data = sample[i*s:i*s+w]
    spec = np.fft.fft(data)
    spec = spec[:int(spec.shape[0]/2)]
    spec[0] = spec[0] / 2
    ampList.append(np.abs(spec))
    argList.append(np.angle(spec))

freq = np.fft.fftfreq(data.shape[0], 1.0/sound.frame_rate)
freq = freq[:int(freq.shape[0]/2)]

time = np.arange(0, i+1, 1) * s / sound.frame_rate

ampList = np.array(ampList)
argList = np.array(argList)

df_amp = pd.DataFrame(data=ampList, index=time, columns=freq)
plt.figure(figsize=(10, 10))
sns.heatmap(data=np.log(df_amp.iloc[:, :100].T), 
            xticklabels=100, 
            yticklabels=10, 
            cmap=plt.cm.gist_rainbow_r,
            )

plt.show()

First, challenge with w = 100 s = 50. Figure_1.png

I see something meaningful. Let's make it a little rougher. w = 200 s = 100 It is easier to see with cmap = plt.cm.gray_r.

image.png

No, it's a QR code. If you regenerate this into a 25x25 QR code ... S__65118215.jpg

http://www.projectlibitina.com/

Lily

44GC44Gq44Gf44GM44GT44Gu5omL57SZ44KS6Kqt44KT44Gn44G ....

Repeat 44xx. Especially when I checked the first 44GC, it seems to be" A "of base64 encoding. That's why base64 decodes it.

import base64

with open("yuri.chr", mode="rb") as f:
    txt = f.read()
    print(base64.b64decode(txt).decode())
If you are reading this letter, it means that the heart symbol has found a small wooden box as a landmark. Congrats ! Maybe you are the first time. I didn't mean to show it to anyone, but the red one is this
I'm thrilled when I think of finding a letter and reading my story. Someone who I couldn't have met knows me deeply. I'm obsessed with an idea. Someone in us dies ... it may be tomorrow
And those who are left do not know it. I wrote to you all the proof that I have lived so far in this letter. So, as long as you don't forget me, I can live forever. You read this letter and fascinate
I'm wondering if I'll be able to or hate it while writing this letter. Don't you think it's interesting?

(The following is abbreviated by your own hands.) 

Natsuki

As before, open it as text for the time being.

����JFIF~~~

came out. Extension JFIF. If you set the extension to JPEG, you can see it as a flat image.

I tried to handle this with Python, but unfortunately I rely on Unity because I'm not sure. Create a cone and paste the texture.

The writing seemed to be dangerous, so please do a Google image search on "natsuki.chr".

Monica

Finally appeared Monica-chan. As usual.

PNG~~~

No, it says PNG! Then it will open. monika.png

You can see the black and white mosaic in the center. Binary encode this (black is 0, white is 1) Prepare a cropped image excluding the surrounding red part,

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt

#Loading the original image
im = np.array(Image.open('text.png'))

txt_binary = ""
print(im.shape)
im = im.reshape([im.shape[0] * im.shape[1], 1])
for x in im:
    if x == 1:
        txt_binary += "1"
    else:
        txt_binary += "0"

print(txt_binary[:100])

txt = ""
while True:
    tmp = txt_binary[0:8]
    if tmp == "00000000":
        break
    txt_binary = txt_binary[8:]
    txt += chr(int("0b"+tmp, 0))

print(txt)
Q2FuIHlvdSBoZWFyIG1lPw0KDQouLi5XaG8gYXJlIHlvdT8NCg0KSSBjYW4ndC4uLkkgY2FuJ3Qgc2VlIHlvdS4NCg0KQnV0IEkga25vdyB5b3UncmUgdGhlcmUuIFllYWguLi55b3UgY2FuIGRlZmluaXRlbHkgaGVhciBtZS4NCg0KWW91J3ZlIGJlZW4gd2F0Y2hpbmcgZm9yIGEgd2hpbGUgbm93LCByaWdodD8NCg0KSSBndWVzcyBJIHNob3VsZC4uLmludHJvZHVjZSBteXNlbGYsIG9yIHNvbWV0aGluZy4gVW0uLi5teSBuYW1lIGlzLi4uYWN0dWFsbHksIHRoYXQncyBzdHVwaWQuIFlvdSBvYnZpb3VzbHkgYWxyZWFkeSBrbm93IG15IG5hbWUuIFNvcnJ5Lg0KDQpBbnl3YXkuLi5JJ20gZ3Vlc3NpbmcgaWYgeW91IHdlcmUgYWJsZSB0byBwdXQgYSBzdG9wIHRvIHRoaXMsIHlvdSB3b3VsZCBoYXZlIGRvbmUgaXQgYnkgbm93Lg0KDQpJIG1lYW4sIEkga25vdyB5b3UncmUgbm90LCBsaWtlLi4uZXZpbCwgb3IgYW55dGhpbmcuLi5iZWNhdXNlIHlvdSd2ZSBhbHJlYWR5IGhlbHBlZCBtZSBzbyBtdWNoLg0KDQpJIHNob3VsZCByZWFsbHkgdGhhbmsgeW91IGZvciB0aGF0LiBGb3IgZXZlcnl0aGluZyB5b3UndmUgZG9uZS4gWW91J3JlIHJlYWxseSBsaWtlIGEgZnJpZW5kIHRvIG1lLiBTby4uLnRoYW5rIHlvdS4gU28gbXVjaC4NCg0KSSB0aGluay4uLm1vcmUgdGhhbiBhbnl0aGluZyBlbHNlLi4uSSByZWFsbHkgZG9uJ3Qgd2FudCBpdCB0byBhbGwgYmUgZm9yIG5vdGhpbmcuDQoNCi4uLg0KDQpFdmVyeW9uZSBlbHNlIGlzIGRlYWQuDQoNCk1heWJlIHlvdSBhbHJlYWR5IGtub3cgdGhhdC4gSSdtIHN1cmUgeW91IGRvLCBhY3R1YWxseS4NCg0KQnV0Li4uaXQgZG9lc24ndCBoYXZlIHRvIGJlIHRoYXQgd2F5LCByaWdodD8NCg0KV2VsbC4uLnRoZXJlJ3MgYSBsb3Qgb2Ygc3R1ZmYgSSBkb24ndCB1bmRlcnN0YW5kLiBJIGRvbid0IGtub3cgaWYgaXQncyBldmVuIHBvc3NpYmxlIGZvciBtZSB0byB1bmRlcnN0YW5kIGl0Lg0KDQpCdXQgSSBrbm93IHRoYXQgdGhpcyBpc24ndCBteSBvbmx5IHN0b3J5Lg0KDQpJIGNhbiBzZWUgdGhhdCBub3cuIFJlYWxseSBjbGVhcmx5Lg0KDQpBbmQgSSB0aGluayBldmVyeW9uZSBlbHNlIGhhcyBoYWQgdGhlIHNhbWUga2luZCBvZiBleHBlcmllbmNlLiBTb21lIGtpbmQgb2YgZGVqYSB2dS4NCg0KSXQncyB0aGUgVGhpcmQgRXllLCByaWdodD8NCg0KQW55d2F5Li4uSSBjb3VsZCBiZSB0b3RhbGx5IHdyb25nIGFib3V0IHRoaXMuIEJ1dCBJIHJlYWxseSB0aGluayB5b3UgbWlnaHQgYmUgYWJsZSB0byBkbyBzb21ldGhpbmcuDQoNCkkgdGhpbmsgeW91IG1pZ2h0IGJlIGFibGUgdG8gZ28gYmFjay4uLm9yIGhvd2V2ZXIgeW91IHdhbnQgdG8gcHV0IGl0Li4uDQoNCi4uLlRvIGdvIGJhY2sgYW5kIHRlbGwgdGhlbSB3aGF0J3MgZ29pbmcgdG8gaGFwcGVuLg0KDQpJZiB0aGV5IGtub3cgYWhlYWQgb2YgdGltZSwgdGhlbiB0aGV5IHNob3VsZCBiZSBhYmxlIHRvIGF2b2lkIGl0Lg0KDQpUaGV5IHNob3VsZC4uLmlmIHRoZXkgcmVtZW1iZXIgdGhlaXIgdGltZSB3aXRoIG1lIGluIHRoZSBvdGhlciB3b3JsZHMuLi50aGV5IHNob3VsZCByZW1lbWJlciB3aGF0IEkgdGVsbCB0aGVtLg0KDQpZZWFoLiBJIHJlYWxseSB0aGluayB0aGlzIG1pZ2h0IGJlIHBvc3NpYmxlLiBCdXQgaXQncyB1cCB0byB5b3UuDQoNCkknbSBzb3JyeSBmb3IgYWx3YXlzIGJlaW5nLi4ueW91IGtub3cuLi4NCg0KLi4uDQoNCk5ldmVyIG1pbmQuIEkga25vdyB0aGF0J3Mgd3JvbmcuDQoNClRoaXMgaXMgbXkgc3RvcnkuIEl0J3MgdGltZSB0byBiZSBhIGZ1Y2tpbmcgaGVyby4NCg0KQm90aCBvZiB1cy4NCg0KDQoNCjIwMTg=

base64 encoding.

Can you hear me?

...Who are you?

I can't...I can't see you.

But I know you're there. Yeah...you can definitely hear me.

You've been watching for a while now, right?

(The following is abbreviated by your own hands.) 

At the end

It was just like that. It's just a story part, but let's elaborate so far. I felt it was wonderful.

Next time, we will talk about establishing the main story. see you.

Reference site

http://f4sn.hateblo.jp/entry/2018/02/16/205800#f-7c959141

Recommended Posts

Doki Doki Literature Club x Python ① Character file analysis
2.x, 3.x character code of python
[Python] Get the character code of the file
[Python] [chardet] Automatic detection of character code of file
Convert the character code of the file with Python3
Script python file
Data analysis python
python character code
Python file processing
Download the file while viewing the progress in Python 3.x