The purpose of this Python package is to provide a Tamagotchi emulator as a web service. The clientโserver logic enables two core features from the original game:
-
Ubiquity: Just like the original toy could be carried in a kidโs pocket, the web service can be accessed anytime, anywhere from a smartphone.
-
Real-time consistency: The creature follows a strict schedule that the player must handle throughout the day. The server ensures time is properly tracked.
Unlike the original though, this project also includes a bot able to care for the pet when the user is busy.
It delivers a ready-to-use, secure web application that hosts Tamagotchis for multiple authenticated users.
Its Python core API can also be reused for further development projects.
Clone the repo:
git clone https://github.com/almarch/pygotchi.gitcd pygotchi
docker build -t tama .
docker run -d -p 8000:80 tamaThe app is now available at http://localhost:8000.
Pygotchi can only be built and installed on linux (or the WSL). Build the package with build and install it with pip:
pip install build
python -m build ./pygotchi
pip install ./pygotchiThe app may then be launched using Python:
python -m pygotchiThe app is now available at http://localhost:8000.
The game is controlled with 3 buttons (A, B, C) with respect to the original toy. Click the screen to "poke" the toy.
A menu (โฐ) allows administration over the game.
From the administration menu, flash a ROM. It should be a 12ko .bin file. Use the switch button to get the emulation started. The ROM is loaded on the server, and the emulation runs server-side. The ROM version is automatically detected and the graphical theme (background, icons) is adapted accordindingly.
The game may be saved any time using the Save CPU button from the administration menu. The save.bin file may then be loaded again. Ensure consistency between the loaded CPU and the ROM.
The Tamagotchi won an Ig Nobel prize for diverting millions of people from their professional duties. It is not a fatality: check this option and a friendly bot will care for your pet, freeing you up for more important (though probably less fun) stuff.
The automatic care works on the server side, so the bot keeps caring for the pet when the user session is closed. It is automatically adapted to the ROM version. Currently, only P1 and P2 are supported.
The sound is controlled using the native Tamagotchi functionnality, with the A+C button. This feature works on the server side.
Not all APIs are implemented on the UI, and a swagger allows for a few more functionalities.
If you have a PC that may stay on and a personal fixed IP, then you can turn it into a Tamagotchi server.
You need to know the public IP of your network and the private IP of your server.
- The public IP can be accessed from here ;
- The private IP can be accessed with the command:
hostname -IThe router configuration depends on the internet supplier. The router configuration page may for instance be reached from within the network at http://<your public ip>:80.
The router should be parameterized as such:
- ports 80 and 443 should be open to TCP ;
- ports 80 and 443 should redirect to your linux server, identified with its private IP.
If you don't have a PC that can be used as a server, or you don't have a fixed, personal IP ; then you may opt for a VPS. A "bare-metal" VPS does the job and is relatively cheap. The public IP is provided by the cloud provider. Very little configuration is required.
A firewall is needed to ensure you open the relevant port and this port only. Uncomplicated firewall (ufw) is a fair option.
Warning: if you are connected to a VPS with SSH, open port 22 before enabling ufw or you would be locked out.
Warning: ufw applies to the whole system. If you already have a firewall, configure your existing firewall instead.
sudo apt install ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp # If using a VPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo systemctl enable ufw
sudo ufw statusThe connection has to be encrypted using a SSL key.
From /pygotchi:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout nginx/ssl/ssl.key -out nginx/ssl/ssl.crt -subj "/CN=localhost"This key will have to be renewed after one year. The certificates are self-signed so the browser will present a warning. See this section to use CA-signed certificate.
Then set up the secrets. Still from /pygotchi:
echo "KEYCLOAK_ADMIN_PASSWORD=$(cat /dev/urandom | tr -dc 'A-Za-z0-9' | fold -w 32 | head -n 1)" > .env
echo "KEYCLOAK_DB_PASSWORD=$(cat /dev/urandom | tr -dc 'A-Za-z0-9' | fold -w 32 | head -n 1)" >> .env
cat .envKeep the KEYCLOAK_ADMIN_PASSWORD at hand.
Update the docker daemon to forbid direct iptables manipulation by docker and to enable IPv6.
Warning: this overwrites /etc/docker/daemon.json. If you already have custom parameters, edit the file instead of overwriting it.
echo '{
"iptables": false,
"ipv6": true
}' | sudo tee /etc/docker/daemon.json
sudo systemctl restart dockerLaunch the web app with its dependency services using docker-compose.
From /pygotchi:
docker compose build
docker compose pull
docker compose upAccess keycloak administration board at https://<your public>/keycloak.
The first launch is very long as all services have to be set-up. Once it is ready, authentify as :
- user:
admin - password:
KEYCLOAK_ADMIN_PASSWORD
From there:
- Create a new realm: game.
- From the realm game, create a new client : game_client. For this client:
- Enable client authentication.
- Enable the standard authentication flow. Keep all other authentication flows disabled. This is the standard configuration.
- Configure the valid redirect URI & Web origin:
https://<your public IPv4>/*and/orhttps://[<your public IPv6>]/*. - Collect the game_client secret and keep it at hand.
- Still from the realm game, create one or more new users with custom credentials. Each user access their own Tamagotchi.
Then, update nginx/nginx.conf, in the location / { access_by_lua_block { local opts = {...}}} compartment:
- Replace
your_client_secretby your actual game game_client secret. - Replace
127.0.0.1by either<your public IPv4>or[<your public IPv6>].
Finally, re-launch the docker-compose cluster :
docker compose down
docker compose up -dThe app is now secured & available world-wide at https://<your public IP>.
For further security, purchase a domain name and use a trusted connection. To do so, include certbot to the docker-compose stack and parameterize keycloak and nginx.conf accordingly.
The Tamagotchi has been a social phenomenon back in the 1990's. The original game has been revived through TamaLIB, an agnostic, cross platform emulator. TamaLIB has then been implemented on Arduino with a refactoring. From the Arduino version, TamaLIB was ported on 2 high-abstraction level, object-oriented languages: R, then Python. Currently, all C++ code has been merged into a monolithic tamalib.cpp file as the dependency management was not trivial for binding to Python.
Python is more production oriented, with a broad community and better performances than R. The following features were permitted by switching the project from R to Python:
- implementing the buzzer sound using websockets ;
- switching the carebot server-side using the better distinction between back and front ;
- multiplayer management using the multiprocesses & async framework.
There is still work to do. Pygotchi has to be adapted to all new first generation Tamagotchis, following TamaLIB recent developments (Issue #3). From there, a specific carebot could be developed for each species.
The automatic care feature is inspired from Tamatrix (see also the dockerized version).
The Python core of the project may be distinguished from the auxiliary web application infrastructure. The Python core is nested like Russian dolls of increasing abstraction. Tamalib is the C++ deepest layer. The intermediate abstraction layer is Tama(), a Python object bound to the C++ engine serving as an API for user-level commands. Finally, the last layers are the FastAPI web service and the carebot that both operate on Tama().
The Python core API may directly be interacted with in an async framework.
In CLI:
from pygotchi import Tama
import asyncio
tama = asyncio.run(Tama.new("rom.bin"))
asyncio.run(tama.print())
asyncio.run(tama.click("B"))In a notebook:
from pygotchi import Tama
import nest_asyncio
nest_asyncio.apply()
tama = await Tama.new("rom.bin")
await tama.print()
await tama.click("B")This work is licensed under GPL-2.0.
All graphical resources come from the extraordinarily rich Tamagotchi fandom.