What's new
Project Torque Community Forums

Welcome to the ProjectTorque forum! You will need to register an account here to play the game. Click the register button and sign in with Steam. Use a legitimate email as this is used for account recovery if you forget your password. We will never spam you or sell your user data!

Using ChatGPT to automate making games better/fixed.

Jack

Administrator
Staff member
Since the release of ChatGPT 3 towards the end of 2022, I have been fascinated by what AI can do in terms of programming scripts and actual software.

My first test with ChatGPT, I will call it GPT3 from now on, was to read a bit of the ProjectTorque source code and see what it made of it.
To my surprise, it was able to tell me exactly what that code was doing. This is very odd as this is closed source code and I had not given it any hits as to what parts of the code do.

I fed it the following code:
C-like:
public override GameModeDescription getDescriptionForPractice()
        {
            return new GameModeDescription(CommonStrings.CTF, getGameModeDescText(), "gui\\textures\\gmCTF.png", CommonTypes.eGameModeID.CTF, 2, 8, false, false);
        }
This shows the game mode in the game mode list in-game along with the game mode's icon and things like min/max players, team game, or practice game mode.

Here is the output from the AI.
Here's what the above overide is doing:
1. It's overriding the getDescriptionForPractice() method of the base class.
2. It's returning a new GameModeDescription object.
3. The GameModeDescription object is being passed the following parameters:
a. The name of the game mode.
b. The description of the game mode.
c. The path to the image that will be displayed in the game mode selection screen.
d. The game mode ID.
e. The minimum number of players required to play the game mode.
f. The maximum number of players allowed to play the game mode.
g. Whether or not the game mode is a team game mode.
h. Whether or not the game mode is a practice game mode.

This is scarily accurate. Especially the bit about the min/max players, team game, or practice game mode. Nowhere else is this referenced and it is not like this is generic code used by other applications.
It was written for PT. And well maybe the other older Invictus games. Source got leaked or does OpenAI have access to private repositories?


I have also used it to create code. More of a script...

So I have a load of files in a folder that I wanted to extract. But only the .apple and .orange ones.
The thing is, these files are dotted around a load of folders. Wanted to keep the folder structure but not include folders that did not have these files in them.
Instead of going through all the folders and doing it by hand, I typically use CMD or PowerShell to do this for me.

So I asked it.
powershell code to copy .apple and .orange files from a folder to a new folder while keeping their folder structure

It generated this..
C-like:
# Set the source and destination folders
$src = "C:\src"
$dst = "C:\dst"

# Get all .apple and .orange files in the source folder and its subfolders
$files = Get-ChildItem -Path $src -Recurse -Include "*.apple", "*.ornage"

# Iterate through each file
foreach ($file in $files) {
  # Create the destination folder path
  $dstPath = Join-Path $dst $file.Directory.FullName.Substring($src.Length)
  # Create the destination folder if it doesn't exist
  if (!(Test-Path $dstPath)) {
    New-Item -ItemType Directory -Path $dstPath | Out-Null
  }
  # Copy the file to the destination folder
  Copy-Item -Path $file.FullName -Destination $dstPath
}
I ran it and it worked fine! This saved a good few hours of manual labor or just about the same time trying to figure out how to write that script myself.


Today, I am trying to translate ProjectTorque's language files.
While the community did do a lot of work translating them in the Google Sheets, no one has yet been able to export them from there to XML.
So I decided to try to get GPT3 to write some code to do it for me.

I am using Python for this, not because I am an expert in Python, because I am not even a beginner, but because it is easy to install on Windows and installing packages is super easy and fast with pip.

I asked it at first to create some code to translate the file. I just wanted to see what it would spit out.
The default is to just translate everything as I did not specify that I wanted a certain part of the XML translated and it also used Google Translate API.
Python:
import googletrans

# Open the input file in read mode
with open('input.txt', 'r') as file:
  # Read the contents of the file into a variable
  text = file.read()

# Use the googletrans library to translate the text from English to French
translator = googletrans.Translator()
translation = translator.translate(text, dest='fr')

# Print the translated text
print(translation.text)

# Write the translated text to the output file
with open('output.txt', 'w') as file:
  file.write(translation.text)
I don't know if this would work as I didn't want to bother logging into my GCP or pay for the API.

So I asked it to use AWS Translate instead.
You have to specify that you want a session and what region you want to use as well as by default it pulls this from a credential file somewhere on your system, of which I could not get to work.

Python:
import boto3

# Set your AWS access keys
ACCESS_KEY = 'your_access_key'
SECRET_KEY = 'your_secret_key'

# Create a session with your access keys
session = boto3.Session(
  aws_access_key_id=ACCESS_KEY,
  aws_secret_access_key=SECRET_KEY
)

# Set up the AWS Translate client using the session
client = session.client('translate', region_name='eu-west-2')

# Open the input file in read mode
with open('input.txt', 'r') as file:
  # Read the contents of the file into a variable
  text = file.read()

# Use the AWS Translate client to translate the text from English to French
response = client.translate_text(Text=text, SourceLanguageCode='en', TargetLanguageCode='fr')
translation = response['TranslatedText']

# Print the translated text
print(translation)

# Write the translated text to the output file
with open('output.txt', 'w') as file:
  file.write(translation)
Worked great!


Now the tricky part is getting it to read out XML files, that are not to standard and contain errors, and to spit them back out again, as their original standard and with the translated text...
This took about 2 hours to get right.

At first, I was having a lot of trouble getting it to read the actual text we wanted. You have to talk to GPT3 like a programmer. You need to have an understanding of how the software works before jumping in.
Basic commands like "read between the quotation marks are too generic and giving it an example results in it just looking for a pattern, then using the first X amount of characters that the sample had for every line of text.
It would also not work because it did not consider the other lines of the file so did something. Not sure what as I am not using any programming checking or debugging. Just a text editor and a CMD window to run the code.

Here is a sample of the XML file we work with on the game.
XML:
<?xml version="1.0" encoding="utf-8"?>
<Language>
  <DialogGroup name="ame/gamelogic/frontend/charactercretationpopup">
    <Dialog id="29604">
      <Line value="enter a nickname" />
    </Dialog>
  </DialogGroup>
  <DialogGroup name="ame/gamelogic/frontend/filepopup">
    <Dialog id="29606">
      <Line value="RENAME SELECTED" />
    </Dialog>
  </DialogGroup>
  <DialogGroup name="ame/gamelogic/frontend/gamewindow">
    <Dialog id="29605">
      <Line value="Press &quot;{0}&quot; to rescue" />
    </Dialog>
  </DialogGroup>
These files are about 3MB in size and contain about 75,000 lines. I did shorten the file down to the first 100 lines of in-game text so as to not be translating loads of text for every code update.


Sadly, I lost the chat session as it has some sort of timeout feature. So I will briefly go over this section without code examples. But I will extract the snippets it created along the way.

The first bit to get right is getting the text that we want and not the rest of the file. This took about 15 attempts to get right but works perfectly now.
It ended up with this regular expression to find the text.
Code:
pattern = r'(.*)<Line value="(.+?)" />(.*)'

This worked well but the output file was just the translated text.
It did not pass through the original file. Again, you have to talk to it like a programmer. No point in just saying "translate this file" because all it will do is translate all the text in that file.
I told it that "the translation worked but the file did not include the original XML formatting or data".

GTP3 actually apologize for the "oversight" and corrected the code to reflect this.

We ended up with this code
Python:
import re
import boto3

# create an AWS Translate client
client = boto3.client('translate', region_name='eu-west-2',
                      aws_access_key_id='keeeeeeeeeeeeey',
                      aws_secret_access_key='shhhhhhhhhhhhhhhhhhh')
                     
# open the file in read mode
with open('crcen.dlg', 'r') as file:
    # read the contents of the file
    contents = file.read()

# use a regular expression to find all lines that match the pattern
pattern = r'(.*)<Line value="(.+?)" />(.*)'

# create an empty list to store the translated lines
translated_lines = []

# iterate over the lines
for line in contents.split('\n'):
    # check if the line matches the pattern
    match = re.match(pattern, line)
    if match:
        # get the groups from the match
        prefix = match.group(1)
        text = match.group(2)
        suffix = match.group(3)
        # translate the text from English to French
        translation = client.translate_text(Text=text, SourceLanguageCode='en', TargetLanguageCode='fr')
        # get the translated text from the response
        translated_text = translation['TranslatedText']
        # add the translated line to the list
        translated_lines.append(f'{prefix}<Line value="{translated_text}" />{suffix}')
    else:
        # add the original line to the list
        translated_lines.append(line)

# open the new file in write mode
with open('crcen.dlg.txt', 'w') as file:
    # write the translated lines to the file
    file.write('\n'.join(translated_lines))

This looked like it worked and it exported the file with the translated text.
1671416937205.png
As you can see, there are a few formatting issues. This was resolved by asking GPT3 "why are these funny characters showing up in the exported file" and it gave me a great explanation of why and how to fix it.

I asked for a few more things to fix the character entities.
1671417438240.png
1671417473586.png


This resulted in it pretty much getting there.
Here is the 1st generation vs 2nd generation translated file.
1671417244118.png

This is the 2nd generation Python script
Python:
import boto3
import html
import re

# Set your AWS access key and secret key
ACCESS_KEY = "your_access_key"
SECRET_KEY = "your_secret_key"

# Set the region you want to use
REGION = "eu-west-2"  # London region

# Create a boto3 session
session = boto3.session.Session(
    aws_access_key_id=ACCESS_KEY,
    aws_secret_access_key=SECRET_KEY,
    region_name=REGION
)

# Create a client for the AWS Translate service
client = session.client("translate")

# open the file in read mode
with open('crcen.dlg', 'r') as file:
    # read the contents of the file
    contents = file.read()

# use a regular expression to find all lines that match the pattern
pattern = r'(.*)<Line value="(.+?)" />(.*)'

# create an empty list to store the translated lines
translated_lines = []

# iterate over the lines
for line in contents.split('\n'):
    # check if the line matches the pattern
    match = re.match(pattern, line)
    if match:
        # get the groups from the match
        prefix = match.group(1)
        text = match.group(2)
        suffix = match.group(3)
        # decode the character entities in the text
        decoded_text = html.unescape(text)
        # check if the text should be skipped
        if decoded_text.startswith('/') or '<' in decoded_text or '>' in decoded_text:
            # add the original line to the list
            translated_lines.append(line)
        else:
            # translate the text from English to French
            translation = client.translate_text(Text=decoded_text, SourceLanguageCode='en', TargetLanguageCode='fr')
            # get the translated text from the response
            translated_text = translation['TranslatedText']
            # add the translated line to the list
            translated_lines.append(f'{prefix}<Line value="{translated_text}" />{suffix}')
    else:
        # add the original line to the list
        translated_lines.append(line)

# open the new file in write mode
with open('crcen.dlg.txt', 'w', encoding="utf-8") as file:
    # write the translated lines to the file
    file.write('\n'.join(translated_lines))


I am going to now try with a much larger amount of the dialogue lines in the language file to see if there are any more errors.
1st generation took about 12 minutes to translate the whole file.

AWS Translate was processing around 160,000 characters per minute when I did the whole file. It did drop off about halfway through down to 50,000 cpm.
1671417855981.png


I don't expect us to use this translation method any time soon. I need French-speaking individuals to go through it and evaluate the files.
It won't be as good as human translation. There are other AI translation services out there. Google's is better than AWS but not by much.

TLDR; While AI can write some decent programming scripts, it has yet to master translating languages.
 
Top