After finishing the logic to store timestamps in an encrypted database, it became clear that since this project relies heavily on real-time tracking, testing could get quite tricky. Without giving the QA tester a way to modify database items outside the normal game flow, certain scenarios become hard to test. For example, if the critter is tired after playing the defined number of times, the tester would have to wait until the next day just to continue testing.
One simple way to extend the control given to the QA tester was to create a terminal within the project that uses Linux-style commands to set and get specific items stored in the database.
For now, since the game is still a work in progress, the decision was made to begin implementing the logic by creating a base structure for the terminal. Similar to the Unreal Engine terminal, the tilde (~) key is used to open and close the terminal window.
To prevent players from accidentally modifying the database, access should be protected by a username and password. These credentials should include permission levels:
To prevent players from accidentally modifying the database, access should be protected by a username and password. These credentials should include permission levels:
- a standard level with read-only access
- a higher-level account that allows modifying values.

Once logged into the terminal, the user should have an experience similar to that of a standard command-line interface. They should be able to type a command, see it echoed back in the terminal, and receive a response from the system, either a confirmation that the action was successfully executed or a message indicating that the command was not recognized.
private void processInput()
{
if (userInputRepeated && terminalTextArea && userInput)
{
// Clear previous entry if needed
foreach (var entry in newEntries)
{
if (entry != null)
{
Destroy(entry);
}
}
newEntries.Clear();
int inputIndex = userInput.transform.GetSiblingIndex();
// Create user command entry
GameObject userEntry = Instantiate(userInputRepeated, terminalTextArea.transform);
userEntry.transform.SetSiblingIndex(inputIndex);
TextMeshProUGUI userText = userEntry.GetComponentInChildren<TextMeshProUGUI>();
if (userText != null)
{
userText.text = "User: " + userInput.text;
}
// Create terminal reply entry
GameObject systemEntry = determineResponse.findCommand(userInput.text);
if (systemEntry==null)
{
systemEntry = Instantiate(userInputRepeated, terminalTextArea.transform);
TextMeshProUGUI systemText = systemEntry.GetComponentInChildren<TextMeshProUGUI>();
if (systemText != null)
{
systemText.text = "command not recognised";
systemText.color = Color.gray;
}
}
else
{
systemEntry = Instantiate(systemEntry, terminalTextArea.transform);
}
systemEntry.transform.SetSiblingIndex(inputIndex + 1); // Insert below the command
// Clear input and reactivate
userInput.text = "";
userInput.ActivateInputField();
// Rebuild layout
LayoutRebuilder.ForceRebuildLayoutImmediate(terminalTextArea.GetComponent<RectTransform>());
// Scroll to bottom
ScrollRect scrollRect = terminalTextArea.GetComponentInParent<ScrollRect>();
if (scrollRect != null)
{
Canvas.ForceUpdateCanvases();
scrollRect.verticalNormalizedPosition = 0f;
}
// Track both entries if needed
newEntries.Add(userEntry);
newEntries.Add(systemEntry);
}
}

After completing the skeleton logic for the terminal, the next step was to have the first meeting with the tutor to ensure that progress on the project was substantial and that the scope was still on track. The meeting was held on Microsoft Teams on Monday, 16/06/2025. Fortunately, the tutor confirmed that the project was heading in the right direction. However, the next crucial step was to begin implementing the actual gameplay elements.