Browse Source

initial commit

psy 1 year ago
parent
commit
9a740e4bb5
48 changed files with 1966 additions and 2 deletions
  1. 10 0
      NoINIW
  2. 48 2
      README.md
  3. 50 0
      data/docs/AUTHOR
  4. 209 0
      data/docs/LICENSE.txt
  5. BIN
      data/fonts/DejaVuSerif-BoldItalic.ttf
  6. BIN
      data/fonts/Vera.ttf
  7. BIN
      data/fonts/VeraBold.ttf
  8. BIN
      data/fonts/whitrabt.ttf
  9. BIN
      data/images/author.png
  10. BIN
      data/images/cheats.png
  11. BIN
      data/images/exit.png
  12. BIN
      data/images/forum.png
  13. BIN
      data/images/howto.png
  14. BIN
      data/images/icon.png
  15. BIN
      data/images/logo.png
  16. BIN
      data/images/options.png
  17. BIN
      data/images/play.png
  18. BIN
      data/images/topA.png
  19. BIN
      data/images/topB.png
  20. BIN
      data/images/update.png
  21. 39 0
      data/levels/help.txt
  22. 3 0
      data/levels/level0/data/CONTRIBUTE.txt
  23. 30 0
      data/levels/level0/data/FAQ.txt
  24. 3 0
      data/levels/level0/data/FINANCES.txt
  25. 3 0
      data/levels/level0/data/HELP.txt
  26. 3 0
      data/levels/level0/data/LEVEL.txt
  27. 3 0
      data/levels/level0/data/PUBLISH_YOUR_LEVELS.txt
  28. 4 0
      data/levels/level0/data/last_connections.txt
  29. 191 0
      data/levels/level0/level0.py
  30. 345 0
      data/levels/level0/level0_1.py
  31. 185 0
      data/levels/level0/level0_2.py
  32. 12 0
      data/levels/level0/tree.py
  33. 112 0
      data/levels/shell.py
  34. 3 0
      data/menu.cfg
  35. 598 0
      data/menu.py
  36. 1 0
      data/profile/username.txt
  37. BIN
      data/sounds/menu.ogg
  38. 5 0
      data/translations/cheats.txt
  39. 9 0
      data/translations/credits_EN.txt
  40. 10 0
      data/translations/credits_ES.txt
  41. 1 0
      data/translations/forum_EN.txt
  42. 1 0
      data/translations/forum_ES.txt
  43. 13 0
      data/translations/level0.txt
  44. 29 0
      data/translations/menu.txt
  45. 16 0
      data/translations/tutorial_EN.txt
  46. 16 0
      data/translations/tutorial_ES.txt
  47. 7 0
      data/translations/updates_EN.txt
  48. 7 0
      data/translations/updates_ES.txt

+ 10 - 0
NoINIW

@@ -0,0 +1,10 @@
+#!/usr/bin/env python3 
+# -*- coding: utf-8 -*-"
+"""
+NOINIW 2051 - by psy (epsylon@riseup.net)
+"""
+from data.menu import main
+
+if __name__ == "__main__":
+    app = main()
+    app.run()

+ 48 - 2
README.md

@@ -1,3 +1,49 @@
-# NoINIW2051
+  ![NoINIW2051](https://03c8.net/images/NoINIW2051_1.png "NoINIW2051")
 
-Shell-based CyberPunk m-RPG videogame.
+----------
+
+  NoINIW-2051 is Shell-based CyberPunk m-RPG videogame.
+  
+
+  ![NoINIW2051](https://03c8.net/images/NoINIW2051_2.png "NoINIW2051")
+
+----------
+
+#### Installing:
+
+NoINIW2051 runs on many platforms. It requires Python (3.x) and the following libraries:
+
+    - python-pygame - SDL bindings for games development in Python
+    - python-pygame-sdl2 - reimplementation of the Pygame API using SDL2
+
+On Debian-based systems (ex: Ubuntu), run: 
+
+    sudo apt-get install python-pygame python-pygame-sdl2
+
+Also, you must run:
+
+    sudo pip3 install pygame pygame-menu
+
+####  Source libs:
+
+   * Python: https://www.python.org/downloads/
+   * PyGame: https://pypi.org/project/pygame/
+   * PySDL2: https://pypi.org/project/PySDL2/
+   * Pygame-Menu: https://pypi.org/project/pygame-menu/
+
+----------
+
+####  License:
+
+  NoINIW2051 is released under the GPLv3. You can find the full license text
+in the [LICENSE](./data/docs/LICENSE.txt) file.
+
+----------
+
+####  Screenshots:
+
+  ![NoINIW2051](https://03c8.net/images/NoINIW2051_3.png "NoINIW2051")
+
+  ![NoINIW2051](https://03c8.net/images/NoINIW2051_4.png "NoINIW2051")
+
+  ![NoINIW2051](https://03c8.net/images/NoINIW2051_5.png "NoINIW2051")

+ 50 - 0
data/docs/AUTHOR

@@ -0,0 +1,50 @@
+========================
+
+ nick: psy (epsylon)
+  
+  <epsylon@riseup.net> 
+
+ web: https://03c8.net
+
+=======================
+
+ code:
+
+ - https://code.03c8.net/epsylon
+ - https://github.com/epsylon
+
+=======================
+
+ software/projects:
+
+ - Anarcha-Pragmatism: Intellectual model (and movement) based on the culture of the "action/reaction".
+ - AnonTwi: Tool for OAuth2 applications (such as: GNUSocial, Twitter) that provides different layers of privacy/encryption.
+ - BrAInStocker: Tool to predict (using Linear Regression) the next number within a series of random numbers.
+ - Bordercheck: Tool to visualize 'real-time' on a world map the geolocation of data when surfing the web.
+ - CIntruder: Tool to bypass captchas using OCR (Optical Character Recognition) bruteforcing methods.
+ - Collatz: Tool to simulate the Collatz's conjeture.
+ - DiaNA: Tool for the search and recognition of patterns in DNA sequences.
+ - DieKunstDerFuge: Video on different topics related to hacktivism recorded during 2013 from an intimate narrative perspective.
+ - ECOin: Decentralized key/value registration and transfer system based on Bitcoin technology (a cryptocurrency).
+ - Euler-Bricks: Tool to search for Euler's "bricks".
+ - Goldbach: Tool to simulate the Goldbach's conjeture.
+ - Lorea: Social networking autonomous project to build a distributed, encrypted and federated network.
+ - Neuralia: Neural Network that tries to learn and reply the correct answer.
+ - NoINIW-2051: Shell-based CyberPunk m-RPG videogame.
+ - Orb: Tool for massive footprinting.
+ - PandeMaths: Tool that simulates a mathematical model of pandemics.
+ - pArAnoIA-Browser: Tool designed to surf the Internet using some "paranoic" methods.
+ - Propagare: Tool for extraction, organization and semantic analysis of newspapers.
+ - PyAISnake: Tool to train AI models on solve spatial problems through the classic video game "snake".
+ - PyDog4Apache: Tool to sneak logs from Apache web server.
+ - Smuggler: Tool to detect and exploit HTTP Smuggling vulnerabilities.
+ - UFONet: Denial of Service [DDoS & DoS attacks] Toolkit (a botnet of botnets).
+ - XSSer: Automatic -framework- to detect, exploit and report XSS vulnerabilities.
+
+=======================
+
+ BTC: 
+
+  19aXfJtoYJUoXEZtjNwsah2JKN9CK5Pcjw
+
+========================

File diff suppressed because it is too large
+ 209 - 0
data/docs/LICENSE.txt


BIN
data/fonts/DejaVuSerif-BoldItalic.ttf


BIN
data/fonts/Vera.ttf


BIN
data/fonts/VeraBold.ttf


BIN
data/fonts/whitrabt.ttf


BIN
data/images/author.png


BIN
data/images/cheats.png


BIN
data/images/exit.png


BIN
data/images/forum.png


BIN
data/images/howto.png


BIN
data/images/icon.png


BIN
data/images/logo.png


BIN
data/images/options.png


BIN
data/images/play.png


BIN
data/images/topA.png


BIN
data/images/topB.png


BIN
data/images/update.png


+ 39 - 0
data/levels/help.txt

@@ -0,0 +1,39 @@
+ENGLISH-SHELL0_HELP:+ Terminal Working;
+ENGLISH-SHELL0_HELP:    - "install <file.app>" -> install a program
+ENGLISH-SHELL0_HELP:    - "exit" -> stop Terminal from working
+ENGLISH-SHELL0_HELP:    - "clear" -> clear all command lines
+ENGLISH-SHELL0_HELP:+ Machine Working;
+ENGLISH-SHELL0_HELP:    - "id" -> print real and effective user and group IDs
+ENGLISH-SHELL0_HELP:    - "whois" -> client for the whois directory service
+ENGLISH-SHELL0_HELP:    - "hostname" ->  show host name of the current machine
+ENGLISH-SHELL0_HELP:    - "uname" -> print system information
+ENGLISH-SHELL0_HELP:+ Net Working;
+ENGLISH-SHELL0_HELP:    - "connect <ip>" -> connect to another machine
+ENGLISH-SHELL0_HELP:    - "disconnect" -> disconnect from this machine
+ENGLISH-SHELL0_HELP:+ Directory Working;
+ENGLISH-SHELL0_HELP:    - "ls" -> list all the folders and the files at current working directory
+ENGLISH-SHELL0_HELP:    - "pwd" -> print the current working directory
+ENGLISH-SHELL0_HELP:    - "cd new_working_directory" -> Change current working directory to new_working_directory
+ENGLISH-SHELL0_HELP:    - "cd .." -> change current working directory to a previous directory
+ENGLISH-SHELL0_HELP:+ Files And Folders Working;
+ENGLISH-SHELL0_HELP:    - "cat <file>" -> print file contents on the standard output
+#
+SPANISH-SHELL0_HELP:+ Funcionamiento de la Terminal;
+SPANISH-SHELL0_HELP:    - "install <fichero.app>" -> instalar un programa
+SPANISH-SHELL0_HELP:    - "exit" -> parar la Terminal de funcionar
+SPANISH-SHELL0_HELP:    - "clear" -> limpiar todas las líneas de comandos
+SPANISH-SHELL0_HELP:+ Funcionamiento de la Máquina;
+SPANISH-SHELL0_HELP:    - "id" -> mostrar el usuario y los grupos actuales
+SPANISH-SHELL0_HELP:    - "whois" -> cliente para solicitar información sobre servicios
+SPANISH-SHELL0_HELP:    - "hostname" ->  muestra el nombre de la máquina actual
+SPANISH-SHELL0_HELP:    - "uname" -> muestra información del sistema
+SPANISH-SHELL0_HELP:+ Funcionamiento de la Red;
+SPANISH-SHELL0_HELP:    - "connect <ip>" -> conectar a otra máquina
+SPANISH-SHELL0_HELP:    - "disconnect" -> desconectar de ésta máquina
+SPANISH-SHELL0_HELP:+ Funcionamiento del Directorio de Trabajo;
+SPANISH-SHELL0_HELP:    - "ls" -> listar todas las carpetas y ficheros del directorio actual
+SPANISH-SHELL0_HELP:    - "pwd" -> mostrar el directorio actual de trabajo
+SPANISH-SHELL0_HELP:    - "cd nuevo_directorio_trabajo" -> Cambiar el actual directorio de trabajo por otro nuevo
+SPANISH-SHELL0_HELP:    - "cd .." -> cambiar el actual directorio de trabajo por uno previo
+SPANISH-SHELL0_HELP:+ Funcionamiento de Ficheros y Archivos;
+SPANISH-SHELL0_HELP:    - "cat <fichero>" -> muestra el contenido de un fichero por la salida normal

File diff suppressed because it is too large
+ 3 - 0
data/levels/level0/data/CONTRIBUTE.txt


+ 30 - 0
data/levels/level0/data/FAQ.txt

@@ -0,0 +1,30 @@
+'��*����>��D��&�`�u��ՈÌc������c�����]���0��H�����x�E��UBt����1��bN������� ��Ԝ������P,I����/���];��0L'I֑��e��um��
+                                    �[�p         �������E�Q�-�#�p�Y��:�Ɇ��+a�>�#o��W�,K�>��L����Ɇr����ǁ!R(�%�0����Z::Z*����܁��Rp�݆��v��荢|,V�x.P���8c;��X׵�{(��������7�{��t�}����Ggj�,�%��˙mmb�A�hDb������[H:�
+                       �(�,                                    A��s@������7m\6~xĺQ�I�3u9                  zz��71�@1�!����%�
+^����s��x��q%��m�@�)V����u���X��V�e�J���!?��zj��0ay��̤�f���>����u�� O���q�&��)o?��˳�==4�x,"�&ck�<{��uͷ.�����N�yؓ;
+
+0000059135 00000 n
+0000059354 00000 n
+0000059956 00000 n
+0000105347 00000 n
+0000121813 00000 n
+0000145239 00000 n
+0000105324 00000 n
+0000121790 00000 n
+0000145216 00000 n
+0000166615 00000 n
+0000167214 00000 n
+0000168266 00000 n
+0000168441 00000 n
+0000169492 00000 n
+0000169672 00000 n
+trailer
+<<
+/ID [ <FC7516008CD7F3F09392942C330A7299> <FC7516008CD7F3F09392942C330A7299> ]
+/Root 1 0 R
+/Info 111 0 R
+/Size 112
+>>
+startxref
+169866
+%%EOF

File diff suppressed because it is too large
+ 3 - 0
data/levels/level0/data/FINANCES.txt


+ 3 - 0
data/levels/level0/data/HELP.txt

@@ -0,0 +1,3 @@
+ENGLISH-HELP_FILE:You need to connect to other machines to start to explore the world. Search some MAC address on files...
+#
+SPANISH-HELP_FILE:Necesitas conectarte a otras máquinas para empezar a explorar el mundo. Busca alguna dirección MAC en los ficheros...

+ 3 - 0
data/levels/level0/data/LEVEL.txt

@@ -0,0 +1,3 @@
+ENGLISH-LEVEL0_AUTHOR:Level created by; 'psy' (03c8.net] - [30.04.2020]
+#
+SPANISH-LEVEL0_AUTHOR:Nivel creado por; 'psy' (03c8.net] - [30.04.2020]

+ 3 - 0
data/levels/level0/data/PUBLISH_YOUR_LEVELS.txt

@@ -0,0 +1,3 @@
+ENGLISH-LEVEL0_AUTHOR:You can send your levels directly to [epsylon@riseup.net], which will be published together with the main package, so that other players can enjoy your creations. If your ideas are finally published, you will appear in the game credits, in the main menu, along with the other hackers. Dont miss the chance!...
+#
+SPANISH-LEVEL0_LEVELS:Puedes enviar tus niveles directamente a [epsylon@riseup.net], que serán publicado junto con el paquete principal, para que los demás jugadores puedan disfrutar de tus creaciones. Si tus ideas son finalmente publicadas, aparecerás en los créditos del juego, en el menú principal, junto al resto de hackers. No dejes pasar la oportunidad!...

+ 4 - 0
data/levels/level0/data/last_connections.txt

@@ -0,0 +1,4 @@
+|connected from: 32188223...
+|connected from: 17592...
+|connected from: 1111...
+|connected from: 212121...

+ 191 - 0
data/levels/level0/level0.py

@@ -0,0 +1,191 @@
+#!/usr/bin/env python3 
+# -*- coding: utf-8 -*-"
+"""
+NOINIW 2051 - by psy (epsylon@riseup.net)
+"""
+import time
+import pygame
+import pygameMenu
+import data.menu
+
+import os
+import random
+from data.levels.level0.level0_1 import level0_shell as level0_1
+
+translations_level0_intro = "data/translations/level0.txt"
+
+NETWORK_DOMAIN = "X/UNd.NeT" # name for level [0-10] layer network
+NETWORK_MACHINE_NUMBER = None
+
+COLOR_RED = (255 ,0 , 0)
+COLOR_WHITE = (255, 255, 255)
+COLOR_BLACK = (0, 0, 0)
+COLOR_GRAY = (50, 50, 50)
+COLOR_GREEN = (0, 160, 0)
+COLOR_BLUE = (0, 0, 228)
+COLOR_YELLOW = (255, 255, 0)
+COLOR_ORANGE = (242, 91, 37)
+
+pygame.font.init()
+font_type = "data/fonts/Vera.ttf"
+font_type_bold = "data/fonts/VeraBold.ttf"
+font_size = 18
+font_banner_size = 16
+fontObj = pygame.font.Font(font_type, font_size) # create font object for menu
+fontBANNERObj = pygame.font.Font(font_type, font_banner_size) # create font BANNER object
+profile_username_path = "data/profile/username.txt"
+
+PROFILE_PATH = "data/profile"
+DEFAULT_USER_NAME = "ANONYMOUS"
+
+def load_level0_translations(set_language):
+    if set_language == "0": # English
+        language_translation = "ENGLISH"
+    else: # Spanish
+        language_translation = "SPANISH"
+    f = open(translations_level0_intro, "r")
+    translations = f.readlines()
+    f.close()
+    for lost in translations:
+        lost = lost.replace("\n", "")
+        if language_translation in str(lost):
+            if "SERVICE" in lost:
+                TRANS_SERVICE = str(lost.split(":")[1])
+            if "USERNAME" in lost:
+                TRANS_USERNAME = str(lost.split(":")[1])
+            if "PASSWORD" in lost:
+                TRANS_PASSWORD = str(lost.split(":")[1])
+            if "TRY" in lost:
+                TRANS_ACCESS = str(lost.split(":")[1])
+            if "LOGINGUESTGRANTED" in lost:
+                GUEST_ACCESS_GRANTED =  str(lost.split(":")[1])
+            if "LOGINDENIED" in lost:
+                DENIED_ACCESS = str(lost.split(":")[1])
+    return TRANS_SERVICE, TRANS_USERNAME, TRANS_PASSWORD, TRANS_ACCESS, GUEST_ACCESS_GRANTED, DENIED_ACCESS
+
+def extract_username():
+    if os.path.exists(profile_username_path) == True:
+        f = open(profile_username_path, "r")
+        USERNAME = str(f.read().replace("\n",""))
+        f.close()
+    else: # create default profile
+        if not os.path.exists(PROFILE_PATH): # create new profile folder
+            os.mkdir(PROFILE_PATH)
+        f = open(profile_username_path, "w")
+        f.write(DEFAULT_USER_NAME) # default username
+        f.close()
+        USERNAME = DEFAULT_USER_NAME
+    return USERNAME
+
+def extract_web_banner_text():
+   WEB_BANNER_TEXT = "PUBLIC [WEBSITE] for [OPEN-PROXY] MAC: ["+str(NETWORK_MACHINE_NUMBER)+"]" # default web banner for OPEN-PROXY
+   return WEB_BANNER_TEXT
+
+def extract_ssh_banner_text():
+   SSH_BANNER_TEXT = "SSH-ProxyVPN-32.1 (by ChaOsCL4n) for [OPEN-PROXY] MAC: ["+str(NETWORK_MACHINE_NUMBER)+"]" # default SSH banner for OPEN-PROXY
+   return SSH_BANNER_TEXT
+
+def update_menu_service(value, enabled):
+    banner_rect = pygame.draw.rect(login_surface,COLOR_BLACK,(WINDOW[0]/10-105,WINDOW[1]/5+120,WINDOW[0]+100,WINDOW[1])) # machine BANNER back box
+    if enabled == "WEB":
+        WEB_BANNER_TEXT = extract_web_banner_text()
+        banner_surface = fontBANNERObj.render(WEB_BANNER_TEXT, True, COLOR_BLUE)
+        banner_rect.center = (WINDOW[0]-500, WINDOW[1]-200)
+        login_surface.blit(banner_surface, banner_rect)
+        if login_menu.get_widget("user_name") and login_menu.get_widget("user_password"):
+            login(login_surface, COLOR_WHITE, COLOR_BLACK, COLOR_BLUE, COLOR_GRAY, COLOR_YELLOW, COLOR_ORANGE, WINDOW, LANGUAGE)
+    elif enabled == "SSH":
+        SSH_BANNER_TEXT = extract_ssh_banner_text()
+        banner_surface = fontBANNERObj.render(SSH_BANNER_TEXT, True, COLOR_BLUE)
+        banner_rect.center = (WINDOW[0]-500, WINDOW[1]-200)
+        login_surface.blit(banner_surface, banner_rect)
+        if not login_menu.get_widget("user_name") and not login_menu.get_widget("user_password"):
+            TRANS_SERVICE, TRANS_USERNAME, TRANS_PASSWORD, TRANS_ACCESS, GUEST_ACCESS_GRANTED, DENIED_ACCESS = load_level0_translations(LANGUAGE)
+            USERNAME = extract_username()
+            login_menu.add_text_input("* "+str(TRANS_USERNAME)+": ",
+                        default='',
+                        maxchar=12,
+                        textinput_id='user_name',
+                        input_underline='')
+            login_menu.add_text_input("* "+str(TRANS_PASSWORD)+": ",
+                        default='',
+                        maxchar=12,
+                        password=True,
+                        textinput_id='user_password',
+                        input_underline='')
+            def try_login():
+                data = login_menu.get_input_data()
+                if str(data['user_name']) == str(NETWORK_MACHINE_NUMBER): # guest access
+                    msg = str(GUEST_ACCESS_GRANTED) # -guest(whatever-pass) granted- on this level
+                    ACCESS_LEVEL = "guest"
+                else: # rest is denied
+                    msg = str(DENIED_ACCESS)
+                    ACCESS_LEVEL = False
+                show_login_msg(msg, login_surface, COLOR_WHITE, COLOR_BLACK, COLOR_BLUE, COLOR_GRAY, COLOR_YELLOW, COLOR_ORANGE, WINDOW, LANGUAGE, ACCESS_LEVEL, NETWORK_MACHINE_NUMBER)
+            login_menu.add_option("-> "+str(TRANS_ACCESS)+" <-", try_login)
+
+def show_login_msg(msg, surface, COLOR_WHITE, COLOR_BLACK, COLOR_BLUE, COLOR_GRAY, COLOR_YELLOW, COLOR_ORANGE, WINDOW_SIZE, set_language, ACCESS_LEVEL, NETWORK_MACHINE_NUMBER):
+    if ACCESS_LEVEL == "guest": # granted!
+        login_return_text = fontObj.render('[ '+str(msg)+'! ]', True, COLOR_GREEN) # create login GREEN back msg
+    else: # denied!
+        login_return_text = fontObj.render('[ '+str(msg)+'! ]', True, COLOR_RED) # create login RED back msg
+    login_surface.blit(login_return_text, dest=(WINDOW_SIZE[0]/2-100, WINDOW_SIZE[1]/4+42)) # load msg into surface
+    while True:
+        pygame.display.flip()
+        if ACCESS_LEVEL == "guest": # GO FOR NEXT LEVEL: 0-1
+            time.sleep(3) # wait for shell
+            start_level0_1(surface, WINDOW_SIZE, set_language, ACCESS_LEVEL, NETWORK_MACHINE_NUMBER, COLOR_WHITE, COLOR_BLACK, COLOR_BLUE, COLOR_GRAY, COLOR_YELLOW, COLOR_ORANGE, COLOR_GREEN)
+        else: # back to 'login' menu
+            time.sleep(5) # wait until re-login
+            pygame.draw.rect(surface,COLOR_BLACK,(WINDOW_SIZE[1]/10-75,WINDOW_SIZE[1]/2-154,WINDOW_SIZE[0],30)) # used to hide login returned msg
+            login(surface, COLOR_WHITE, COLOR_BLACK, COLOR_BLUE, COLOR_GRAY, COLOR_YELLOW, COLOR_ORANGE, WINDOW_SIZE, set_language)
+
+def login(surface, COLOR_WHITE, COLOR_BLACK, COLOR_BLUE, COLOR_GRAY, COLOR_YELLOW, COLOR_ORANGE, WINDOW_SIZE, set_language):
+    global login_menu
+    global login_surface
+    global LANGUAGE
+    global WINDOW
+    global NETWORK_MACHINE_NUMBER
+    WINDOW = WINDOW_SIZE
+    LANGUAGE = set_language
+    login_surface = surface
+    pygame.draw.rect(surface,COLOR_BLACK,(WINDOW_SIZE[1]/10-75,WINDOW_SIZE[1]/2-154,WINDOW_SIZE[0],30)) # used to hide login returned msg
+    TRANS_SERVICE, TRANS_USERNAME, TRANS_PASSWORD, TRANS_ACCESS, GUEST_ACCESS_GRANTED, DENIED_ACCESS = load_level0_translations(set_language)
+    USERNAME = extract_username()
+    if not NETWORK_MACHINE_NUMBER:
+        NETWORK_MACHINE_NUMBER = random.randrange(1111, 9999) # generate random proxy number (between proxy reserved directions)
+    login_menu = pygameMenu.Menu(surface, # level 0: "login" menu
+                    bgfun=data.menu.level0_login_background,
+                    color_selected=COLOR_YELLOW,
+                    font=font_type,
+                    font_color=COLOR_WHITE,
+                    font_size=18,
+                    font_size_title=35,
+                    menu_alpha=100,
+                    menu_color=COLOR_BLACK,
+                    menu_height=220,
+                    menu_width=int(WINDOW_SIZE[0]),
+                    onclose=data.menu.main, # back to main menu
+                    option_shadow=False,
+                    title="["+str(NETWORK_DOMAIN)+"]>[MAC:"+str(NETWORK_MACHINE_NUMBER)+"]>",
+                    menu_color_title=COLOR_GREEN,
+                    widget_alignment=pygameMenu.locals.ALIGN_LEFT,
+                    window_height=220,
+                    window_width=int(WINDOW_SIZE[0])
+                    )
+    login_menu.add_selector('* '+str(TRANS_SERVICE),
+                    [('SSH', 'SSH'),
+                    ('WEB', 'WEB')],
+                    selector_id='service',
+                    onchange=update_menu_service,
+                    default=1)
+    if login_menu.get_widget("user_name"):
+        login_menu.get_widget("user_name").clear()
+    if login_menu.get_widget("user_password"):
+        login_menu.get_widget("user_password").clear()
+    while True:
+        login_menu.mainloop()
+
+def start_level0_1(surface, WINDOW_SIZE, set_language, ACCESS_LEVEL, NETWORK_MACHINE_NUMBER, COLOR_WHITE, COLOR_BLACK, COLOR_BLUE, COLOR_GRAY, COLOR_YELLOW, COLOR_ORANGE, COLOR_GREEN):
+    time.sleep(5)
+    level0_1(surface, WINDOW_SIZE, set_language, ACCESS_LEVEL, NETWORK_MACHINE_NUMBER, COLOR_WHITE, COLOR_BLACK, COLOR_BLUE, COLOR_GRAY, COLOR_YELLOW, COLOR_ORANGE, COLOR_GREEN)

+ 345 - 0
data/levels/level0/level0_1.py

@@ -0,0 +1,345 @@
+#!/usr/bin/env python3 
+# -*- coding: utf-8 -*-"
+"""
+NOINIW 2051 - by psy (epsylon@riseup.net)
+"""
+import pygame
+import sys, os, random
+
+import data.levels.shell as shell
+import data.menu as menu
+import data.levels.level0.tree as tree
+
+def level0_shell(surface, WINDOW_SIZE, set_language, ACCESS_LEVEL, NETWORK_MACHINE_NUMBER, COLOR_WHITE, COLOR_BLACK, COLOR_BLUE, COLOR_GRAY, COLOR_YELLOW, COLOR_ORANGE, COLOR_GREEN):
+    init(surface, WINDOW_SIZE, set_language, ACCESS_LEVEL, NETWORK_MACHINE_NUMBER, COLOR_WHITE, COLOR_BLACK, COLOR_BLUE, COLOR_GRAY, COLOR_YELLOW, COLOR_ORANGE, COLOR_GREEN)
+
+def init(surface, WINDOW_SIZE, set_language, ACCESS_LEVEL, NETWORK_MACHINE_NUMBER, COLOR_WHITE, COLOR_BLACK, COLOR_BLUE, COLOR_GRAY, COLOR_YELLOW, COLOR_ORANGE, COLOR_GREEN):
+    CURRENT_LEVEL = 0 # set current level
+    CURRENT_LANGUAGE = set_language # set current language
+    ACCESS_LEVEL = str(ACCESS_LEVEL)
+    NETWORK_MACHINE_NUMBER = str(NETWORK_MACHINE_NUMBER)
+    width= WINDOW_SIZE[0]
+    height = WINDOW_SIZE[1]
+    fullLine = 18
+    font_SHELL_type = "data/fonts/Vera.ttf"
+    font_SHELL_size = 15
+    myFont = pygame.font.Font(font_SHELL_type, font_SHELL_size) # create font object for SHELL
+    listColor = [COLOR_WHITE, COLOR_BLUE, COLOR_GREEN, COLOR_YELLOW, COLOR_ORANGE]
+    changeColor = 0
+    showCur = 0
+    colorCur = listColor.pop(listColor.index(random.choice(listColor)))
+    content = []
+    contentDisplay = []
+    listCommand = []
+    indexListCommand = 0
+    contentLineCurrent = ''
+    contentLineCurrentDisplay = '|'
+    posCursor = 0
+    currentLine = True
+    root = ACCESS_LEVEL+'@'+NETWORK_MACHINE_NUMBER+':~% '
+    camTop = 0
+    camBot = 0
+    line = 0
+    mac_uname, mac_root, starting_position, files_tree, macs_tree = tree.init() # extracting basics from shell: uname, root, starting position, trees...
+    current_position = starting_position
+
+    def displayText(text, at, x, y, color, bg=None):
+        if not ACCESS_LEVEL+'@'+NETWORK_MACHINE_NUMBER+':~% ' in text:
+            label = myFont.render(text, at, COLOR_WHITE, bg)
+            surface.blit(label, (x, y))    
+        else:
+            labelUser = myFont.render(ACCESS_LEVEL+'@'+NETWORK_MACHINE_NUMBER, at, (COLOR_ORANGE), bg)
+            labelColon = myFont.render(':', at, (COLOR_WHITE), bg)
+            labelNS = myFont.render('%', at, (COLOR_WHITE), bg)
+            labelTilde = myFont.render('~', at, (COLOR_BLUE), bg)
+            surface.blit(labelUser, (0, y))
+            surface.blit(labelColon, (105, y))
+            surface.blit(labelTilde, (113, y))
+            surface.blit(labelNS, (125, y))
+            text = text.replace(ACCESS_LEVEL+'@'+NETWORK_MACHINE_NUMBER+':~%', '')
+            labelText = myFont.render(text, at, color, bg)
+            surface.blit(labelText, (135, y))
+  
+    def readChar():
+        if event.key == pygame.K_BACKSPACE:
+            return 'backspace'
+        elif event.key == pygame.K_PAGEUP:
+            return 'pageup'
+        elif event.key == pygame.K_PAGEDOWN:
+            return 'pagedown'
+        elif event.key == pygame.K_TAB:
+            return 'tab'
+        elif event.key == pygame.K_RETURN:
+            return 'enter'
+        elif event.key == pygame.K_ESCAPE:
+            return 'esc'
+        elif event.key in (pygame.K_RSHIFT, pygame.K_LSHIFT):
+            return 'shift'
+        elif event.key in (pygame.K_RCTRL, pygame.K_LCTRL):
+            return 'control'
+        elif event.key == pygame.K_RIGHT:
+            return 'kright'
+        elif event.key == pygame.K_LEFT:
+            return 'kleft'
+        elif event.key == pygame.K_UP:
+            return 'kup'
+        elif event.key == pygame.K_DOWN:
+            return 'kdown'
+        elif event.key == pygame.K_CAPSLOCK:
+            return None
+        elif event.key == 283:
+            return 'begincur'
+        elif event.key == 284:
+            return 'endcur'
+        elif event.key == 285:
+            return 'delall'
+        else:
+            return event.unicode
+
+    def progressCommand(cmd, current_position):
+        cmd = cmd.strip()
+        if cmd == '':
+            return []
+        elif cmd == 'clear': # clear
+            return []
+        elif cmd == 'help': # help
+            current_help = helpCommand()
+            return current_position, current_help, True
+        elif cmd == 'exit': # exit
+            menu.main() # return to login menu
+        elif cmd == 'pwd': # pwd
+            current_path = shell.getPWD(current_position)
+            return current_position, current_path, False
+        elif cmd == 'ls' or cmd == 'dir': # ls/dir
+            current_tree = shell.getList(mac_root, current_position, files_tree)
+            return current_position, current_tree, False
+        elif cmd == 'id': # id
+            user_id = shell.getId(ACCESS_LEVEL)
+            return current_position, user_id, False
+        elif cmd == 'whois': # whois
+            whois = shell.getId(ACCESS_LEVEL)
+            return current_position, whois, False
+        elif cmd == 'hostname': # hostname
+            hostname = shell.getHostName(NETWORK_MACHINE_NUMBER)
+            return current_position, hostname, False
+        elif cmd == 'uname': # uname
+            uname = shell.getUname(mac_uname)
+            return current_position, uname, False
+        elif cmd == "cd ..": # cd_up
+            current_path = shell.getCdUP(mac_root, current_position)
+            current_position = current_path
+            return current_position, current_path, False           
+        elif cmd.startswith('cd '):
+            direc = cmd[3:]
+            direc = direc.strip()
+            current_path = shell.changePWD(mac_root, current_position, files_tree, direc)
+            current_position = current_path
+            return current_position, current_path, False
+        elif cmd.startswith('cat '):
+            file_target = cmd[3:]
+            file_target = file_target.strip()
+            file_text = shell.getCAT(CURRENT_LANGUAGE, CURRENT_LEVEL, current_position, files_tree, file_target)
+            return current_position, file_text, False
+        elif cmd.startswith('install '):
+            file_target = cmd[7:]
+            file_target = file_target.strip()
+            file_text = shell.installProgram(current_position, files_tree, file_target)
+            return current_position, file_text, False
+        elif cmd.startswith('connect '):
+            file_target = cmd[7:]
+            file_target = file_target.strip()
+            file_text = shell.connectMac(current_position, macs_tree, file_target, surface, WINDOW_SIZE, CURRENT_LANGUAGE)
+            return current_position, file_text, False
+        elif cmd.startswith('disconnect'):
+            menu.main() # return to login menu
+        else:
+            return current_position, 'y-shell: command not found: "'+ str(cmd)+'"', False
+
+    def helpCommand():
+        lstHelp = []
+        m = open("data/levels/help.txt", "r")
+        shell_help = m.readlines()
+        m.close
+        lstHelp.append("SHELL: "+str(shell.VERSION))
+        lstHelp.append(" ")
+        for text in shell_help:
+            if CURRENT_LANGUAGE == "0": # English
+                if text.startswith("ENGLISH"):        
+                    lstHelp.append(str(text.split(":")[1].replace("\n","")))
+            else: # Spanish
+                if text.startswith("SPANISH"):
+                    lstHelp.append(str(text.split(":")[1].replace("\n","")))
+        lstHelp.append(" ")
+        return lstHelp
+
+    # starting main() loop
+    while 1:
+        fullLine = (height - 120) // 20
+        if currentLine:
+            if camBot - camTop == (fullLine - 1):
+                camBot = len(contentDisplay)
+                camTop = camBot - (fullLine - 1)
+        for event in pygame.event.get():
+            if event.type == pygame.KEYDOWN:
+                newChar = readChar()
+                if newChar not in ('delall', 'begincur', 'endcur', 'backspace', 'tab', 'enter', 'esc', 'pageup', 'pagedown',\
+                    'shift', 'control', None, 'kright', 'kleft', 'kup', 'kdown'):
+                    try:
+                        contentLineCurrent = list(contentLineCurrent)
+                        contentLineCurrent.insert(posCursor, newChar)
+                        contentLineCurrent = ''.join(contentLineCurrent)
+                        posCursor += 1
+                        lstChar = list(contentLineCurrent)
+                        lstChar.insert(posCursor, '|')
+                        contentLineCurrentDisplay = ''.join(lstChar)
+                    except:
+                        posCursor = 0
+                        if camBot - camTop == (fullLine - 1):
+                            camTop += 1
+                        camBot += 1
+                        content.append([root])
+                        contentLineCurrent = ''
+                        contentLineCurrentDisplay = '|'    
+                    indexListCommand = 0
+                    showCur = 0   
+                    currentLine = True
+                elif newChar == 'delall':
+                    contentLineCurrent = ''
+                    posCursor = 0
+                    contentLineCurrentDisplay = '|'
+                    currentLine = True
+                elif newChar == 'begincur':
+                    posCursor = 0
+                    contentLineCurrentDisplay = '|' + contentLineCurrent
+                    currentLine = True
+                elif newChar == 'endcur':
+                    posCursor = len(contentLineCurrent)
+                    contentLineCurrentDisplay = contentLineCurrent + '|'
+                    currentLine = True
+                elif newChar == 'pageup':    
+                    if not len(listCommand) == 0:
+                        if -len(listCommand) != indexListCommand:
+                            indexListCommand -= 1
+                            contentLineCurrent = listCommand[indexListCommand]
+                            contentLineCurrentDisplay = contentLineCurrent + '|'
+                            posCursor = len(contentLineCurrent)
+                    currentLine = True
+                    showCur = 0
+                elif newChar == 'pagedown':
+                    if not len(listCommand) == 0:
+                        if indexListCommand < -1:
+                            indexListCommand += 1
+                            contentLineCurrent = listCommand[indexListCommand]
+                            contentLineCurrentDisplay = contentLineCurrent + '|'
+                            posCursor = len(contentLineCurrent)
+                    currentLine = True
+                    showCur = 0
+                elif newChar == 'kup':
+                    if camTop != 0:
+                        if camBot - camTop == (fullLine - 1):
+                            camBot -= 1
+                            camTop -= 1
+                            currentLine = False
+                    showCur = 0
+                elif newChar == 'kdown':
+                    if camBot < len(contentDisplay):
+                        camBot += 1
+                        camTop += 1
+                    showCur = 0
+                elif newChar == 'kright':
+                    if not len(contentLineCurrent) == posCursor:
+                        posCursor += 1
+                        lstChar = list(contentLineCurrent)
+                        lstChar.insert(posCursor, '|')
+                        contentLineCurrentDisplay = ''.join(lstChar)
+                    currentLine = True
+                    showCur = 0
+                elif newChar == 'kleft':
+                    if posCursor != 0:
+                        posCursor -= 1
+                        lstChar = list(contentLineCurrent)
+                        lstChar.insert(posCursor, '|')
+                        contentLineCurrentDisplay = ''.join(lstChar)
+                    currentLine = True
+                    showCur = 0
+                elif newChar == 'backspace':
+                    if len(contentLineCurrent) != 0 and posCursor != 0:
+                        try:
+                            contentLineCurrent = list(contentLineCurrent)
+                            wordPoped = contentLineCurrent.pop(posCursor - 1)
+                            contentLineCurrent = ''.join(contentLineCurrent)
+                            posCursor -= 1
+                        except:
+                            contentLineCurrent = contentLineCurrent[1:]
+                            posCursor = len(contentLineCurrent)
+                        lstChar = list(contentLineCurrent)
+                        lstChar.insert(posCursor, '|')
+                        contentLineCurrentDisplay = ''.join(lstChar)
+                        currentLine = True
+                    showCur = 0
+                elif newChar == 'enter':
+                    currentLine = True
+                    indexListCommand = 0
+                    if camBot - camTop == (fullLine - 1):
+                        camTop += 1
+                    camBot += 1
+                    content.append([root + contentLineCurrent])
+                    if contentLineCurrent.strip() == 'clear':
+                        camTop = 0
+                        camBot = 0
+                        posCursor = 0
+                        content = []
+                        contentLineCurrent = ''
+                        contentLineCurrentDisplay = '|'
+                    else:
+                        current_position, contentAppend, help_mode = progressCommand(contentLineCurrent, current_position)
+                        if help_mode == False:
+                            content.append(contentAppend)
+                        else:
+                            for eachLine in contentAppend:
+                                if camBot - camTop == (fullLine - 1):
+                                    camTop += 1
+                                camBot += 1
+                                content.append(eachLine)
+                            help_mode = False
+                    if len(contentLineCurrent.strip(' ')) != 0:
+                        listCommand.append(contentLineCurrent)
+                    posCursor = 0
+                    contentLineCurrent = ''
+                    contentLineCurrentDisplay = '|'
+                    showCur = 0
+        surface.fill(COLOR_BLACK)
+        changeColor += 1
+        showCur += 1
+        contentDisplay = []
+        for i in range(len(content)):
+            text = ''.join(content[i])
+            if len(text) * 8 > width:
+                while len(text) * 8 > width:
+                    textMini = text[:width // 8 - 1]
+                    contentDisplay.append(textMini)
+                    text = text[width // 8 - 1:]
+                contentDisplay.append(text)
+            else:
+                contentDisplay.append(text)
+        if currentLine:
+            if len(contentDisplay) >= fullLine:
+                camBot = len(contentDisplay)
+                camTop = camBot - (fullLine - 1)
+            else:
+                camBot = len(contentDisplay)
+                camTop = 0
+        for i in range(camTop, camBot):
+            displayText(contentDisplay[i], 1, 0, line * 20, COLOR_WHITE)
+            line += 1
+        if camBot == len(contentDisplay):
+            if showCur < 500:
+                displayText(root + contentLineCurrentDisplay, 1, 0, line * 20, COLOR_WHITE)
+            else:
+                displayText(root + contentLineCurrent, 1, 0, line * 20, COLOR_WHITE)
+            if showCur > 1000:
+                showCur = 0
+        else:
+            displayText(''.join(contentDisplay[camBot]), 1, 0, line * 20, COLOR_WHITE)
+        line = 0
+        pygame.display.flip()

+ 185 - 0
data/levels/level0/level0_2.py

@@ -0,0 +1,185 @@
+#!/usr/bin/env python3 
+# -*- coding: utf-8 -*-"
+"""
+NOINIW 2051 - by psy (epsylon@riseup.net)
+"""
+import time
+import pygame
+import pygameMenu
+import data.menu
+
+import os
+import random
+
+NETWORK_DOMAIN = "X/UNd.NeT" # name for level [0-10] layer network
+
+COLOR_RED = (255 ,0 , 0)
+COLOR_WHITE = (255, 255, 255)
+COLOR_BLACK = (0, 0, 0)
+COLOR_GRAY = (50, 50, 50)
+COLOR_GREEN = (0, 160, 0)
+COLOR_BLUE = (0, 0, 228)
+COLOR_YELLOW = (255, 255, 0)
+COLOR_ORANGE = (242, 91, 37)
+
+pygame.font.init()
+font_type = "data/fonts/Vera.ttf"
+font_type_bold = "data/fonts/VeraBold.ttf"
+font_size = 18
+font_banner_size = 16
+fontObj = pygame.font.Font(font_type, font_size) # create font object for menu
+fontBANNERObj = pygame.font.Font(font_type, font_banner_size) # create font BANNER object
+profile_username_path = "data/profile/username.txt"
+
+PROFILE_PATH = "data/profile"
+DEFAULT_USER_NAME = "ANONYMOUS"
+
+translations_level0_intro = "data/translations/level0.txt"
+
+def load_level0_translations(set_language):
+    if set_language == "0": # English
+        language_translation = "ENGLISH"
+    else: # Spanish
+        language_translation = "SPANISH"
+    f = open(translations_level0_intro, "r")
+    translations = f.readlines()
+    f.close()
+    for lost in translations:
+        lost = lost.replace("\n", "")
+        if language_translation in str(lost):
+            if "SERVICE" in lost:
+                TRANS_SERVICE = str(lost.split(":")[1])
+            if "USERNAME" in lost:
+                TRANS_USERNAME = str(lost.split(":")[1])
+            if "PASSWORD" in lost:
+                TRANS_PASSWORD = str(lost.split(":")[1])
+            if "TRY" in lost:
+                TRANS_ACCESS = str(lost.split(":")[1])
+            if "LOGINGUESTGRANTED" in lost:
+                GUEST_ACCESS_GRANTED =  str(lost.split(":")[1])
+            if "LOGINDENIED" in lost:
+                DENIED_ACCESS = str(lost.split(":")[1])
+    return TRANS_SERVICE, TRANS_USERNAME, TRANS_PASSWORD, TRANS_ACCESS, GUEST_ACCESS_GRANTED, DENIED_ACCESS
+
+def extract_username():
+    if os.path.exists(profile_username_path) == True:
+        f = open(profile_username_path, "r")
+        USERNAME = str(f.read().replace("\n",""))
+        f.close()
+    else: # create default profile
+        if not os.path.exists(PROFILE_PATH): # create new profile folder
+            os.mkdir(PROFILE_PATH)
+        f = open(profile_username_path, "w")
+        f.write(DEFAULT_USER_NAME) # default username
+        f.close()
+        USERNAME = DEFAULT_USER_NAME
+    return USERNAME
+
+def extract_web_banner_text():
+   WEB_BANNER_TEXT = "PUBLIC [WEBSITE] for [OPEN-PROXY] MAC: ["+str(NETWORK_MACHINE_NUMBER)+"]" # default web banner for OPEN-PROXY
+   return WEB_BANNER_TEXT
+
+def extract_ssh_banner_text():
+   SSH_BANNER_TEXT = "SSH-ProxyVPN-32.1 (by ChaOsCL4n) for [OPEN-PROXY] MAC: ["+str(NETWORK_MACHINE_NUMBER)+"]" # default SSH banner for OPEN-PROXY
+   return SSH_BANNER_TEXT
+
+def update_menu_service(value, enabled):
+    banner_rect = pygame.draw.rect(login_surface,COLOR_BLACK,(WINDOW[0]/10-105,WINDOW[1]/5+120,WINDOW[0]+100,WINDOW[1])) # machine BANNER back box
+    if enabled == "WEB":
+        WEB_BANNER_TEXT = extract_web_banner_text()
+        banner_surface = fontBANNERObj.render(WEB_BANNER_TEXT, True, COLOR_BLUE)
+        banner_rect.center = (WINDOW[0]-500, WINDOW[1]-200)
+        login_surface.blit(banner_surface, banner_rect)
+        if login_menu.get_widget("user_name") and login_menu.get_widget("user_password"):
+            login(login_surface, WINDOW, LANGUAGE, NETWORK_MACHINE_NUMBER)
+    elif enabled == "SSH":
+        SSH_BANNER_TEXT = extract_ssh_banner_text()
+        banner_surface = fontBANNERObj.render(SSH_BANNER_TEXT, True, COLOR_BLUE)
+        banner_rect.center = (WINDOW[0]-500, WINDOW[1]-200)
+        login_surface.blit(banner_surface, banner_rect)
+        if not login_menu.get_widget("user_name") and not login_menu.get_widget("user_password"):
+            TRANS_SERVICE, TRANS_USERNAME, TRANS_PASSWORD, TRANS_ACCESS, GUEST_ACCESS_GRANTED, DENIED_ACCESS = load_level0_translations(LANGUAGE)
+            USERNAME = extract_username()
+            login_menu.add_text_input("* "+str(TRANS_USERNAME)+": ",
+                        default='',
+                        maxchar=12,
+                        textinput_id='user_name',
+                        input_underline='')
+            login_menu.add_text_input("* "+str(TRANS_PASSWORD)+": ",
+                        default='',
+                        maxchar=12,
+                        password=True,
+                        textinput_id='user_password',
+                        input_underline='')
+            def try_login(): # level 0-2 (under development)
+                data = login_menu.get_input_data()
+                #if str(data['user_name']) == str(NETWORK_MACHINE_NUMBER): # guest access
+                #    msg = str(GUEST_ACCESS_GRANTED) # -guest(whatever-pass) granted- on this level
+                #    ACCESS_LEVEL = "guest"
+                #else: # rest is denied
+                msg = str(DENIED_ACCESS)
+                ACCESS_LEVEL = False
+                show_login_msg(msg, login_surface, COLOR_WHITE, COLOR_BLACK, COLOR_BLUE, COLOR_GRAY, COLOR_YELLOW, COLOR_ORANGE, WINDOW, LANGUAGE, ACCESS_LEVEL, NETWORK_MACHINE_NUMBER)
+            login_menu.add_option("-> "+str(TRANS_ACCESS)+" <-", try_login)
+
+def show_login_msg(msg, surface, COLOR_WHITE, COLOR_BLACK, COLOR_BLUE, COLOR_GRAY, COLOR_YELLOW, COLOR_ORANGE, WINDOW_SIZE, set_language, ACCESS_LEVEL, NETWORK_MACHINE_NUMBER):
+    #if ACCESS_LEVEL == "guest": # granted!
+    #    login_return_text = fontObj.render('[ '+str(msg)+'! ]', True, COLOR_GREEN) # create login GREEN back msg
+    #else: # denied!
+    login_return_text = fontObj.render('[ '+str(msg)+'! ]', True, COLOR_RED) # create login RED back msg
+    login_surface.blit(login_return_text, dest=(WINDOW_SIZE[0]/2-100, WINDOW_SIZE[1]/4+42)) # load msg into surface
+    while True:
+        pygame.display.flip()
+        if ACCESS_LEVEL == "guest": # GO FOR NEXT LEVEL: 0-2
+            time.sleep(3) # wait for shell
+        else: # back to 'login' menu
+            time.sleep(5) # wait until re-login
+            pygame.draw.rect(surface,COLOR_BLACK,(WINDOW_SIZE[1]/10-75,WINDOW_SIZE[1]/2-154,WINDOW_SIZE[0],30)) # used to hide login returned msg
+            login(surface, WINDOW_SIZE, set_language, NETWORK_MACHINE_NUMBER)
+
+def login(surface, WINDOW_SIZE, set_language, current_machine):
+    global login_menu
+    global login_surface
+    global WINDOW
+    global LANGUAGE
+    global NETWORK_MACHINE_NUMBER
+    NETWORK_MACHINE_NUMBER = current_machine
+    WINDOW = WINDOW_SIZE
+    LANGUAGE = set_language
+    login_surface = surface
+    pygame.draw.rect(surface,COLOR_BLACK,(WINDOW_SIZE[1]/10-75,WINDOW_SIZE[1]/2-165,WINDOW_SIZE[0],150)) # used to hide login returned msg
+    TRANS_SERVICE, TRANS_USERNAME, TRANS_PASSWORD, TRANS_ACCESS, GUEST_ACCESS_GRANTED, DENIED_ACCESS = load_level0_translations(set_language)
+    USERNAME = extract_username()
+    if not NETWORK_MACHINE_NUMBER:
+        NETWORK_MACHINE_NUMBER = random.randrange(1111, 9999) # generate random proxy number (between proxy reserved directions)
+    login_menu = pygameMenu.Menu(surface, # level 0: "login" menu
+                    bgfun=data.menu.level0_login_background,
+                    color_selected=COLOR_YELLOW,
+                    font=font_type,
+                    font_color=COLOR_WHITE,
+                    font_size=18,
+                    font_size_title=35,
+                    menu_alpha=100,
+                    menu_color=COLOR_BLACK,
+                    menu_height=220,
+                    menu_width=int(WINDOW_SIZE[0]),
+                    onclose=data.menu.main, # back to main menu
+                    option_shadow=False,
+                    title="["+str(NETWORK_DOMAIN)+"]>[MAC:"+str(NETWORK_MACHINE_NUMBER)+"]>",
+                    menu_color_title=COLOR_GREEN,
+                    widget_alignment=pygameMenu.locals.ALIGN_LEFT,
+                    window_height=220,
+                    window_width=int(WINDOW_SIZE[0])
+                    )
+    login_menu.add_selector('* '+str(TRANS_SERVICE),
+                    [('SSH', 'SSH'),
+                    ('WEB', 'WEB')],
+                    selector_id='service',
+                    onchange=update_menu_service,
+                    default=1)
+    if login_menu.get_widget("user_name"):
+        login_menu.get_widget("user_name").clear()
+    if login_menu.get_widget("user_password"):
+        login_menu.get_widget("user_password").clear()
+    while True:
+        login_menu.mainloop()

+ 12 - 0
data/levels/level0/tree.py

@@ -0,0 +1,12 @@
+#!/usr/bin/env python3 
+# -*- coding: utf-8 -*-"
+"""
+NOINIW 2051 - by psy (epsylon@riseup.net)
+"""
+def init():
+    uname = "Linux"
+    starting_position = "/public  "
+    root = "/" #
+    files_tree = {"/contribute  ":("CONTRIBUTE.txt  ","PUBLISH_YOUR_LEVELS.txt  ","FINANCES.txt  "), "/public  ":("FAQ.pdf  ", "HELP.txt  ", "last_connections.log  ", "LEVEL.txt  ")}
+    macs_tree = [212121]
+    return uname, root, starting_position, files_tree, macs_tree

+ 112 - 0
data/levels/shell.py

@@ -0,0 +1,112 @@
+#!/usr/bin/env python3 
+# -*- coding: utf-8 -*-"
+"""
+NOINIW 2051 - by psy (epsylon@riseup.net)
+"""
+import time
+
+from data.levels.level0.level0_2 import login as level0_2
+
+VERSION = "y-shell v0.1 'NoWb1e sh3ll' (23042020)"
+
+def getPWD(current_position): # pwd
+    current_path = current_position
+    if not current_path.startswith("/"):
+       current_path = "/"+current_path
+    return current_path
+
+def changePWD(mac_root, current_position, files_tree, direc): # cd+dir
+   current_path = None
+   for k in files_tree.keys():
+        if direc in k:
+            current_path = direc
+        else:
+            if direc == mac_root:
+                current_path = mac_root
+   if not current_path:
+       current_path = current_position
+   if not current_path.startswith("/"):
+       current_path = "/"+current_path
+   return current_path
+
+def getList(mac_root, current_position, files_tree): # ls/dir
+    for k,v in files_tree.items():
+        if len(current_position) > 2 and current_position in k: # not /
+            listed_files = v
+        else:
+            if current_position == mac_root:
+                listed_files = files_tree.keys()
+    return listed_files
+
+def getId(ACCESS_LEVEL): # id/whois
+    user_id = ACCESS_LEVEL
+    return user_id
+
+def getHostName(NETWORK_MACHINE_NUMBER): # hostname
+    hostname = NETWORK_MACHINE_NUMBER
+    return hostname
+
+def getUname(mac_uname): # uname
+    uname = mac_uname
+    return uname
+
+def getCdUP(mac_root, current_position): # cd_up
+    current_path = mac_root 
+    return current_path
+
+def getCAT(CURRENT_LANGUAGE, level, current_position, files_tree, file_target): # cat
+    file_text = None
+    final_text = []
+    final_file_text = []
+    for k,v in files_tree.items():
+        if current_position in str(k):
+            for f in v:
+                if file_target == str(f).replace("  ",""):
+                    if str(f.replace("  ","")) == "FAQ.pdf": # level_0: fake FAQ.pdf file
+                        f = "FAQ.txt"
+                        CURRENT_LANGUAGE = -1
+                    if str(f.replace("  ","")) == "last_connections.log": # level_0: last connection logs
+                        f = "last_connections.txt"
+                        CURRENT_LANGUAGE = -1
+                    m = open("data/levels/level"+str(level)+"/data/"+str(f.replace("  ","")), "r")
+                    file_text = m.readlines()
+                    for line in file_text:
+                        if CURRENT_LANGUAGE == "0": # ENGLISH
+                            if line.startswith("ENGLISH"):
+                                final_text.append(str(line.split(":")[1]))         
+                        elif CURRENT_LANGUAGE == "1": # SPANISH
+                            if line.startswith("SPANISH"):
+                                final_text.append(str(line.split(":")[1]))
+                        else: # NOT TRANSLATION REQUIRED (CURRENT_LANGUAGE= -1)
+                            final_text.append(str(line))
+                    m.close()
+    if file_text == None:
+        file_text = 'y-shell: file not found: "'+str(file_target)+'"'
+        final_file_text.append(str(file_text))
+    else:
+        for text in final_text:
+            final_file_text.append(str(text).replace("\n", ""))
+    return final_file_text
+
+def installProgram(current_position, files_tree, file_target): # install program
+    file_text = None
+    for k,v in files_tree.items():
+        if current_position in str(k):
+            for f in v:
+                if file_target == str(f).replace("  ","") and file_target.endswith(".app"):
+                    file_text = "y-shell: program '"+str(file_target)+"' has been installed!"
+    if not file_text:
+        file_text = "y-shell: program '"+str(file_target)+"' not valid!"
+    return file_text
+
+def connectMac(current_position, macs_tree, file_target, surface, WINDOW_SIZE, CURRENT_LANGUAGE): # connect to machine
+    file_text = None
+    for v in macs_tree:
+        if file_target == str(v).replace("\n",""):
+            file_text = "y-shell: connecting to: '"+str(file_target)+"' ..."
+            time.sleep(3) # wait for login
+            NETWORK_MACHINE_NUMBER = file_target
+            level0_2(surface, WINDOW_SIZE, CURRENT_LANGUAGE, NETWORK_MACHINE_NUMBER) # go for level 2
+    if not file_text:
+        file_text = "y-shell: connection to: '"+str(file_target)+"' failed!"
+    return file_text

+ 3 - 0
data/menu.cfg

@@ -0,0 +1,3 @@
+LANGUAGE:0
+FULLSCREEN:0
+MUSIC:1

+ 598 - 0
data/menu.py

@@ -0,0 +1,598 @@
+#!/usr/bin/env python3 
+# -*- coding: utf-8 -*-"
+"""
+NoINIW 2051 - by psy (epsylon@riseup.net)
+"""
+import os, sys, time
+os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide"
+os.environ['SDL_VIDEO_CENTERED'] = '1'
+import pygame
+import pygameMenu
+
+from data.levels.level0.level0 import login as level0
+
+FPS=60.0
+
+VERSION = "V:0.1(beta)_25072020"
+CAPTION = "cYpher.PunK! { //Shell_Based//m-RPG// }: [ NoINIW_2051 ]"
+TITLE = "[NoINIW-2051]"
+
+WINDOW_SIZE = (1024, 768)
+COLOR_WHITE = (255, 255, 255)
+COLOR_BLACK = (0, 0, 0)
+COLOR_GRAY = (50, 50, 50)
+COLOR_GREEN = (0, 160, 0)
+COLOR_BLUE = (0, 0, 228)
+COLOR_YELLOW = (255, 255, 0)
+COLOR_ORANGE = (242, 91, 37)
+logo_path = "data/images/logo.png"
+icon_path = "data/images/icon.png"
+play_path = "data/images/play.png"
+options_path = "data/images/options.png"
+exit_path = "data/images/exit.png"
+cheats_path = "data/images/cheats.png"
+howto_path = "data/images/howto.png"
+forum_path= "data/images/forum.png"
+update_path= "data/images/update.png"
+author_path = "data/images/author.png"
+music_path = "data/sounds/menu.ogg"
+menu_cfg = "data/menu.cfg"
+####### start of: translations section ########
+translations_menu = "data/translations/menu.txt"
+tutorial_EN_path = "data/translations/tutorial_EN.txt"
+tutorial_ES_path = "data/translations/tutorial_ES.txt"
+updates_EN_path = "data/translations/updates_EN.txt"
+updates_ES_path = "data/translations/updates_ES.txt"
+forum_EN_path = "data/translations/forum_EN.txt"
+forum_ES_path = "data/translations/forum_ES.txt"
+credits_EN_path = "data/translations/credits_EN.txt"
+credits_ES_path = "data/translations/credits_ES.txt"
+translations_cheats_path = "data/translations/cheats.txt"
+####### end of: translations section ########
+pygame.init() # pygame lib init
+pygame.font.init()
+font_type = "data/fonts/Vera.ttf"
+font_type_bold = "data/fonts/VeraBold.ttf"
+font_type_logo = "data/fonts/DejaVuSerif-BoldItalic.ttf"
+font_size = 18
+font_REA_size = 15
+font_version_size = 16
+font_counter_size = 52
+fontObj = pygame.font.Font(font_type, font_size) # create font object for menu
+fontObjBold = pygame.font.Font(font_type_bold, font_size) # create font bold object for menu
+fontVerObj = pygame.font.Font(font_type, font_version_size) # create font object for version
+fontCounterObj = pygame.font.Font(font_type_bold, font_counter_size) # create font object for counter
+fontREAObj = pygame.font.Font(font_type, font_REA_size) # create font object for REA
+sound = pygameMenu.sound.Sound() # load game menu sounds
+sound.load_example_sounds() # load menu sounds
+music = pygame.mixer.music.load(music_path) # load game menu music
+logo = pygame.image.load(logo_path) # load game logo image
+icon = pygame.image.load(icon_path) # load game icon image
+surface = pygame.display.set_icon(icon) # set icon on window
+surface = pygame.display.set_mode(WINDOW_SIZE) # set display mode
+
+def load_menu_translations(set_language):
+    if set_language == "0": # English
+        language_translation = "ENGLISH"
+    else: # Spanish
+        language_translation = "SPANISH"
+    f = open(translations_menu, "r")
+    translations = f.readlines()
+    f.close()
+    for lost in translations:
+        lost = lost.replace("\n", "")
+        if language_translation in str(lost):
+            if "MENU_GAME_HOWTO" in lost:
+                MENU_GAME_TUTORIAL = str(lost.split(":")[1])
+            elif "MENU_GAME_START" in lost:
+                MENU_GAME_PLAY = str(lost.split(":")[1])
+            elif "MENU_GAME_SETTINGS" in lost:
+                MENU_GAME_OPTIONS = str(lost.split(":")[1])
+            elif "MENU_GAME_UPGRADE" in lost:
+                MENU_GAME_UPDATE = str(lost.split(":")[1])
+            elif "MENU_GAME_PUBLIC" in lost:
+                MENU_GAME_FORUM = str(lost.split(":")[1])
+            elif "MENU_GAME_AUTHOR" in lost:
+                MENU_GAME_AUTHOR = str(lost.split(":")[1])
+            elif "MENU_GAME_CHEATS" in lost:
+                MENU_GAME_CHEATS = str(lost.split(":")[1])
+            elif "MENU_GAME_END" in lost:
+                MENU_GAME_EXIT = str(lost.split(":")[1])
+            elif "MENU_GAME_LANG" in lost:
+                MENU_GAME_LANG = str(lost.split(":")[1])
+            elif "MENU_GAME_L-EN" in lost:
+                MENU_GAME_LANG_EN = str(lost.split(":")[1])
+            elif "MENU_GAME_L-ES" in lost:
+                MENU_GAME_LANG_ES = str(lost.split(":")[1])
+            elif "MENU_GAME_FULLSCREEN" in lost:
+                MENU_GAME_FULLSCREEN = str(lost.split(":")[1])
+            elif "MENU_GAME_MUSIC" in lost:
+                MENU_GAME_MUSIC = str(lost.split(":")[1])
+            elif "MENU_GAME_RETURN_SETTINGS" in lost:
+                MENU_GAME_RETURN_SETTINGS = str(lost.split(":")[1])
+    return MENU_GAME_TUTORIAL, MENU_GAME_PLAY, MENU_GAME_OPTIONS, MENU_GAME_UPDATE, MENU_GAME_FORUM, MENU_GAME_AUTHOR, MENU_GAME_CHEATS, MENU_GAME_EXIT, MENU_GAME_LANG, MENU_GAME_LANG_EN, MENU_GAME_LANG_ES, MENU_GAME_FULLSCREEN, MENU_GAME_MUSIC, MENU_GAME_RETURN_SETTINGS
+
+def load_stored_settings():
+    f = open(menu_cfg, "r")
+    stored_config = f.readlines()
+    f.close()
+    for conf in stored_config:
+        if "LANGUAGE" in conf: # language
+            set_language = conf.replace("\n","").split(":")[1]
+        elif "FULLSCREEN" in conf: # screen size
+            set_fullscreen = conf.replace("\n","").split(":")[1]
+            if set_fullscreen == "0": # window mode
+                surface = pygame.display.set_mode(WINDOW_SIZE)
+            else: # fullscreen
+                surface = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
+        else: # music
+            set_music = conf.replace("\n","").split(":")[1]
+            if set_music == "0": # music disabled
+                music = pygame.mixer.music.stop()
+            else: # music enabled
+                music = pygame.mixer.music.play(-1)
+    return set_language, set_fullscreen, set_music
+
+def button(img, coords, surface):
+    image = pygame.image.load(img)
+    imagerect = image.get_rect()
+    imagerect.topright = coords
+    surface.blit(image, imagerect)
+    return (image, imagerect)
+
+def main_background():
+    surface.fill(COLOR_BLACK) # main menu background color
+    MENU_GAME_TUTORIAL, MENU_GAME_PLAY, MENU_GAME_OPTIONS, MENU_GAME_UPDATE, MENU_GAME_FORUM, MENU_GAME_AUTHOR, MENU_GAME_CHEATS, MENU_GAME_EXIT, MENU_GAME_LANG, MENU_GAME_LANG_EN, MENU_GAME_LANG_ES, MENU_GAME_FULLSCREEN, MENU_GAME_MUSIC, MENU_GAME_RETURN_SETTINGS = load_menu_translations(set_language)
+    pygame.draw.rect(surface,COLOR_WHITE,(0,260,WINDOW_SIZE[0],475))
+    surface.blit(logo, (WINDOW_SIZE[0]/4+25, WINDOW_SIZE[1]/2-85)) # load logo
+    text_surface = fontVerObj.render(VERSION, True, COLOR_WHITE) # load version text with antialiasing
+    surface.blit(text_surface, dest=(WINDOW_SIZE[0]/2-500, WINDOW_SIZE[1]/2+360)) # set version number
+    pygame.draw.rect(surface,COLOR_WHITE,(0,70,WINDOW_SIZE[0],160))
+    howto_rect = pygame.draw.rect(surface,COLOR_WHITE,(160,85,180,60))
+    button_howto = button(howto_path,(WINDOW_SIZE[0]/10+120, WINDOW_SIZE[1]/3-170), surface)
+    howto_surface = fontObjBold.render(str(MENU_GAME_TUTORIAL), True, COLOR_BLACK)
+    surface.blit(howto_surface, dest=(WINDOW_SIZE[0]/10+125, WINDOW_SIZE[1]/3-150))
+    play_rect = pygame.draw.rect(surface,COLOR_WHITE,(160,155,180,60))
+    button_play = button(play_path,(WINDOW_SIZE[0]/10+120, WINDOW_SIZE[1]/3-100), surface)
+    play_surface = fontObjBold.render(str(MENU_GAME_PLAY)+"!", True, COLOR_BLACK)
+    surface.blit(play_surface, dest=(WINDOW_SIZE[0]/10+125, WINDOW_SIZE[1]/3-80))
+    options_rect = pygame.draw.rect(surface,COLOR_WHITE,(340,85,180,60))
+    button_options = button(options_path,(WINDOW_SIZE[0]/10+300, WINDOW_SIZE[1]/3-170), surface)
+    options_surface = fontObjBold.render(str(MENU_GAME_OPTIONS), True, COLOR_BLACK)
+    surface.blit(options_surface, dest=(WINDOW_SIZE[0]/10+305, WINDOW_SIZE[1]/3-150))
+    update_rect = pygame.draw.rect(surface,COLOR_WHITE,(340,155,180,60))
+    button_update = button(update_path,(WINDOW_SIZE[0]/10+300, WINDOW_SIZE[1]/3-100), surface)
+    update_surface = fontObjBold.render(str(MENU_GAME_UPDATE), True, COLOR_BLACK)
+    surface.blit(update_surface, dest=(WINDOW_SIZE[0]/10+305, WINDOW_SIZE[1]/3-80))
+    forum_rect = pygame.draw.rect(surface,COLOR_WHITE,(520,85,180,60))
+    button_forum = button(forum_path,(WINDOW_SIZE[0]/10+480, WINDOW_SIZE[1]/3-170), surface)
+    forum_surface = fontObjBold.render(str(MENU_GAME_FORUM), True, COLOR_BLACK)
+    surface.blit(forum_surface, dest=(WINDOW_SIZE[0]/10+485, WINDOW_SIZE[1]/3-150))
+    author_rect = pygame.draw.rect(surface,COLOR_WHITE,(520,155,180,60))
+    button_author = button(author_path,(WINDOW_SIZE[0]/10+480, WINDOW_SIZE[1]/3-100), surface)
+    author_surface = fontObjBold.render(str(MENU_GAME_AUTHOR), True, COLOR_BLACK)
+    surface.blit(author_surface, dest=(WINDOW_SIZE[0]/10+485, WINDOW_SIZE[1]/3-80))
+    cheats_rect = pygame.draw.rect(surface,COLOR_WHITE,(700,85,200,60))
+    button_cheats = button(cheats_path,(760, WINDOW_SIZE[1]/3-170), surface)
+    cheats_surface = fontObjBold.render(str(MENU_GAME_CHEATS)+"!", True, COLOR_BLACK)
+    surface.blit(cheats_surface, dest=(765, WINDOW_SIZE[1]/3-150))
+    exit_rect = pygame.draw.rect(surface,COLOR_WHITE,(700,155,200,60))
+    button_exit = button(exit_path,(760, WINDOW_SIZE[1]/3-100), surface)
+    exit_surface = fontObjBold.render(str(MENU_GAME_EXIT), True, COLOR_BLACK)
+    surface.blit(exit_surface, dest=(765, WINDOW_SIZE[1]/3-80))
+    check_menu_events(howto_rect, play_rect, options_rect, update_rect, forum_rect, author_rect, cheats_rect, exit_rect, MENU_GAME_OPTIONS, MENU_GAME_LANG, MENU_GAME_LANG_EN, MENU_GAME_LANG_ES, MENU_GAME_FULLSCREEN, MENU_GAME_MUSIC, MENU_GAME_RETURN_SETTINGS)
+
+def settings_background():
+    pygame.draw.rect(surface,COLOR_WHITE,(0,0,0,0))
+
+def display_text_animation(rect, string, l):
+    text = ''
+    for i in range(len(string)):
+        text += string[i]
+        text_surface = fontREAObj.render(text, True, COLOR_ORANGE)
+        text_rect = rect
+        text_rect.center = (WINDOW_SIZE[0]/2+10, WINDOW_SIZE[0]/2-10+l)
+        surface.blit(text_surface, text_rect)
+        pygame.display.update()
+        pygame.time.wait(100)
+
+def show_tutorial():
+    tutorial_menu = pygameMenu.Menu(surface, # main menu menu
+                    bgfun=settings_background,
+                    color_selected=COLOR_YELLOW,
+                    font=font_type_bold,
+                    font_color=COLOR_WHITE,
+                    font_size=16,
+                    font_size_title=28,
+                    menu_alpha=100,
+                    menu_color=COLOR_BLACK,
+                    menu_height=40,
+                    menu_width=int(WINDOW_SIZE[0]),
+                    onclose=pygameMenu.events.EXIT,
+                    option_shadow=False,
+                    title="",
+                    menu_color_title=COLOR_ORANGE,
+                    widget_alignment=pygameMenu.locals.ALIGN_LEFT,
+                    window_height=40,
+                    window_width=WINDOW_SIZE[0]
+                    )
+    topA = "data/images/topA.png"
+    topB = "data/images/topB.png"
+    top_menu_A = pygame.image.load(topA) # load game top front A
+    top_menu_B = pygame.image.load(topB) # load game top front B (exit)
+    surface.blit(top_menu_A, (WINDOW_SIZE[0]-1025, WINDOW_SIZE[1]-770)) # load top main image
+    surface.blit(top_menu_B, (WINDOW_SIZE[0]-25, WINDOW_SIZE[1]-769)) # load top exit image
+    tutorial_rect = pygame.draw.rect(surface,COLOR_BLACK,(WINDOW_SIZE[0]/9+95,WINDOW_SIZE[1]/2-100,600,400)) # tutorial back box
+    if set_language == "0": # English
+        f = open(tutorial_EN_path, "r")
+    else: # Spanish
+        f = open(tutorial_ES_path, "r")
+    tutorial = f.readlines()
+    f.close()
+    l = 0
+    for line in tutorial:
+        l = l+20 # used to create spaces between lines
+        line = line.replace("\n", "")
+        display_text_animation(tutorial_rect, line, l)
+        for event in pygame.event.get():
+            if event.type == 5: # "5" = click DOWN event
+                main() # whatever click goes to main menu
+    create_counter(10) # create visual ETA counter for return to main menu
+
+def update_menu():
+    update_m = pygameMenu.Menu(surface, # main menu menu
+                    bgfun=settings_background,
+                    color_selected=COLOR_YELLOW,
+                    font=font_type_bold,
+                    font_color=COLOR_WHITE,
+                    font_size=16,
+                    font_size_title=28,
+                    menu_alpha=100,
+                    menu_color=COLOR_BLACK,
+                    menu_height=40,
+                    menu_width=int(WINDOW_SIZE[0]),
+                    onclose=pygameMenu.events.EXIT,
+                    option_shadow=False,
+                    title="",
+                    menu_color_title=COLOR_ORANGE,
+                    widget_alignment=pygameMenu.locals.ALIGN_LEFT,
+                    window_height=40,
+                    window_width=WINDOW_SIZE[0]
+                    )
+    topA = "data/images/topA.png"
+    topB = "data/images/topB.png"
+    top_menu_A = pygame.image.load(topA) # load game top front A
+    top_menu_B = pygame.image.load(topB) # load game top front B (exit)
+    surface.blit(top_menu_A, (WINDOW_SIZE[0]-1025, WINDOW_SIZE[1]-770)) # load top main image
+    surface.blit(top_menu_B, (WINDOW_SIZE[0]-25, WINDOW_SIZE[1]-769)) # load top exit image
+    update_rect = pygame.draw.rect(surface,COLOR_BLACK,(WINDOW_SIZE[0]/9+95,WINDOW_SIZE[1]/2-100,600,400)) # update back box
+    if set_language == "0": # English
+        f = open(updates_EN_path, "r")
+    else: # Spanish
+        f = open(updates_ES_path, "r")
+    updates = f.readlines()
+    f.close()
+    l = 0
+    for line in updates:
+        l = l+35 # used to create spaces between lines
+        line = line.replace("\n", "")
+        display_text_animation(update_rect, line, l)
+        for event in pygame.event.get():
+            if event.type == 5: # "5" = click DOWN event
+                main() # whatever click goes to main menu
+    l = 150
+    r = 9
+    create_counter(10) # create visual ETA counter for return to main menu
+
+def forum_menu():
+    forum_m = pygameMenu.Menu(surface, # main menu menu
+                    bgfun=settings_background,
+                    color_selected=COLOR_YELLOW,
+                    font=font_type_bold,
+                    font_color=COLOR_WHITE,
+                    font_size=16,
+                    font_size_title=28,
+                    menu_alpha=100,
+                    menu_color=COLOR_BLACK,
+                    menu_height=40,
+                    menu_width=int(WINDOW_SIZE[0]),
+                    onclose=pygameMenu.events.EXIT,
+                    option_shadow=False,
+                    title="",
+                    menu_color_title=COLOR_ORANGE,
+                    widget_alignment=pygameMenu.locals.ALIGN_LEFT,
+                    window_height=40,
+                    window_width=WINDOW_SIZE[0]
+                    )
+    topA = "data/images/topA.png"
+    topB = "data/images/topB.png"
+    top_menu_A = pygame.image.load(topA) # load game top front A
+    top_menu_B = pygame.image.load(topB) # load game top front B (exit)
+    surface.blit(top_menu_A, (WINDOW_SIZE[0]-1025, WINDOW_SIZE[1]-770)) # load top main image
+    surface.blit(top_menu_B, (WINDOW_SIZE[0]-25, WINDOW_SIZE[1]-769)) # load top exit image
+    forum_rect = pygame.draw.rect(surface,COLOR_BLACK,(WINDOW_SIZE[0]/9+95,WINDOW_SIZE[1]/2-100,600,400)) # update back box
+    if set_language == "0": # English
+        f = open(forum_EN_path, "r")
+    else: # Spanish
+        f = open(forum_ES_path, "r")
+    forums = f.readlines()
+    f.close()
+    l = 0
+    for line in forums:
+        l = l+35 # used to create spaces between lines
+        line = line.replace("\n", "")
+        display_text_animation(forum_rect, line, l)
+        for event in pygame.event.get():
+            if event.type == 5: # "5" = click DOWN event
+                main() # whatever click goes to main menu
+    create_counter(10) # create visual ETA counter for return to main menu
+
+def author_menu():
+    credits_m = pygameMenu.Menu(surface, # main menu menu
+                    bgfun=settings_background,
+                    color_selected=COLOR_YELLOW,
+                    font=font_type_bold,
+                    font_color=COLOR_WHITE,
+                    font_size=16,
+                    font_size_title=28,
+                    menu_alpha=100,
+                    menu_color=COLOR_BLACK,
+                    menu_height=40,
+                    menu_width=int(WINDOW_SIZE[0]),
+                    onclose=pygameMenu.events.EXIT,
+                    option_shadow=False,
+                    title="",
+                    menu_color_title=COLOR_ORANGE,
+                    widget_alignment=pygameMenu.locals.ALIGN_LEFT,
+                    window_height=40,
+                    window_width=WINDOW_SIZE[0]
+                    )
+    topA = "data/images/topA.png"
+    topB = "data/images/topB.png"
+    top_menu_A = pygame.image.load(topA) # load game top front A
+    top_menu_B = pygame.image.load(topB) # load game top front B (exit)
+    surface.blit(top_menu_A, (WINDOW_SIZE[0]-1025, WINDOW_SIZE[1]-770)) # load top main image
+    surface.blit(top_menu_B, (WINDOW_SIZE[0]-25, WINDOW_SIZE[1]-769)) # load top exit image
+    author_rect = pygame.draw.rect(surface,COLOR_BLACK,(WINDOW_SIZE[0]/9+95,WINDOW_SIZE[1]/2-100,600,400)) # update back box
+    if set_language == "0": # English
+        f = open(credits_EN_path, "r")
+    else: # Spanish
+        f = open(credits_ES_path, "r")
+    credits = f.readlines()
+    f.close()
+    l = 0
+    for line in credits:
+        l = l+35 # used to create spaces between lines
+        line = line.replace("\n", "")
+        display_text_animation(author_rect, line, l)
+        for event in pygame.event.get():
+            if event.type == 5: # "5" = click DOWN event
+                main() # whatever click goes to main menu
+    create_counter(10) # create visual ETA counter for return to main menu
+
+def cheats_menu():
+    cheats_m = pygameMenu.Menu(surface, # cheats menu menu
+                    bgfun=settings_background,
+                    color_selected=COLOR_YELLOW,
+                    font=font_type_bold,
+                    font_color=COLOR_WHITE,
+                    font_size=16,
+                    font_size_title=28,
+                    menu_alpha=100,
+                    menu_color=COLOR_BLACK,
+                    menu_height=40,
+                    menu_width=int(WINDOW_SIZE[0]),
+                    onclose=pygameMenu.events.EXIT,
+                    option_shadow=False,
+                    title="",
+                    menu_color_title=COLOR_ORANGE,
+                    widget_alignment=pygameMenu.locals.ALIGN_LEFT,
+                    window_height=40,
+                    window_width=WINDOW_SIZE[0]
+                    )
+    topA = "data/images/topA.png"
+    topB = "data/images/topB.png"
+    top_menu_A = pygame.image.load(topA) # load game top front A
+    top_menu_B = pygame.image.load(topB) # load game top front B (exit)
+    surface.blit(top_menu_A, (WINDOW_SIZE[0]-1025, WINDOW_SIZE[1]-770)) # load top main image
+    surface.blit(top_menu_B, (WINDOW_SIZE[0]-25, WINDOW_SIZE[1]-769)) # load top exit image
+    if set_language == "0": # English
+        language_translation = "ENGLISH"
+    else: # Spanish
+        language_translation = "SPANISH"
+    f = open(translations_cheats_path, "r")
+    translations_cheats = f.readlines()
+    f.close()
+    for lost in translations_cheats:
+        lost = lost.replace("\n", "")
+        if language_translation in str(lost):
+            if "MENU_CHEATS_ENTER" in lost:
+                MENU_CHEATS_ENTER = str(lost.split(":")[1])
+            elif "MENU_CHEATS_TRY" in lost:
+                MENU_CHEATS_TRY = str(lost.split(":")[1])
+    cheats_menu = pygameMenu.Menu(surface, # cheats menu
+                    bgfun=settings_background,
+                    color_selected=COLOR_YELLOW,
+                    font=font_type_bold,
+                    font_color=COLOR_WHITE,
+                    font_size=14,
+                    font_size_title=35,
+                    menu_alpha=100,
+                    menu_color=COLOR_BLACK,
+                    menu_height=220,
+                    menu_width=int(WINDOW_SIZE[0]),
+                    onclose=main,
+                    option_shadow=False,
+                    title="",
+                    menu_color_title=COLOR_ORANGE,
+                    widget_alignment=pygameMenu.locals.ALIGN_LEFT,
+                    window_height=220,
+                    window_width=WINDOW_SIZE[0]
+                    )
+    cheats_menu.add_text_input("* "+str(MENU_CHEATS_ENTER)+": ",
+                        default='',
+                        maxchar=16,
+                        textinput_id='cheat_code',
+                        input_underline='')
+    def try_cheat(): # add some code cheats: free shell upgrade, etc. (leaked during videogame unboxing!)
+        #data = cheats_menu.get_input_data()
+        main() # (btm) returning to main menu
+    cheats_menu.add_option("-> "+str(MENU_CHEATS_TRY)+" <-", try_cheat)
+    while True:
+        cheats_menu.mainloop()
+
+def create_counter(counter):
+    l = 150
+    r = counter
+    for i in range(0,counter): # create counter for reset
+        text = str(r)
+        text_surface = fontCounterObj.render(text, True, COLOR_BLACK)
+        text_rect = pygame.draw.rect(surface,COLOR_WHITE,(WINDOW_SIZE[0]/2-480,WINDOW_SIZE[1]/2-170,100,100)) # counter back box
+        text_rect.center = (WINDOW_SIZE[0]/2-420, WINDOW_SIZE[0]/2-250)
+        surface.blit(text_surface, text_rect)
+        r = r - 1
+        time.sleep(1)
+        pygame.display.flip()
+        if r < 0:
+            main()
+
+def check_menu_events(howto_rect, play_rect, options_rect, update_rect, forum_rect, author_rect, cheats_rect, exit_rect, MENU_GAME_OPTIONS, MENU_GAME_LANG, MENU_GAME_LANG_EN, MENU_GAME_LANG_ES, MENU_GAME_FULLSCREEN, MENU_GAME_MUSIC, MENU_GAME_RETURN_SETTINGS):
+    for event in pygame.event.get():
+        if event.type == 5: # "5" = click DOWN event
+            mouse = pygame.mouse.get_pos()
+            m1 = mouse[0]
+            m2 = mouse[1]
+            mouse_rect = pygame.draw.rect(surface,COLOR_ORANGE,(m1,m2,1,1)) # locate cursor position!
+            howto_event_zone = pygame.Rect.colliderect(howto_rect, mouse_rect) # tutorial
+            play_event_zone = pygame.Rect.colliderect(play_rect, mouse_rect) # play
+            options_event_zone = pygame.Rect.colliderect(options_rect, mouse_rect) # options
+            update_event_zone = pygame.Rect.colliderect(update_rect, mouse_rect) # update
+            forum_event_zone = pygame.Rect.colliderect(forum_rect, mouse_rect) # forum
+            author_event_zone = pygame.Rect.colliderect(author_rect, mouse_rect) # credits
+            cheats_event_zone = pygame.Rect.colliderect(cheats_rect, mouse_rect) # cheats
+            exit_event_zone = pygame.Rect.colliderect(exit_rect, mouse_rect) # exit
+            if howto_event_zone == 1:
+                show_tutorial()
+            elif play_event_zone == 1:
+                start_game()
+            elif options_event_zone == 1:
+                config_menu(MENU_GAME_OPTIONS, MENU_GAME_LANG, MENU_GAME_LANG_EN, MENU_GAME_LANG_ES, MENU_GAME_FULLSCREEN, MENU_GAME_MUSIC, MENU_GAME_RETURN_SETTINGS)
+            elif update_event_zone == 1:
+                update_menu()
+            elif forum_event_zone == 1:
+                forum_menu()
+            elif author_event_zone == 1:
+                author_menu()
+            elif cheats_event_zone == 1:
+                cheats_menu()
+            elif exit_event_zone == 1:
+                sys.exit()
+
+def config_menu(MENU_GAME_OPTIONS, MENU_GAME_LANG, MENU_GAME_LANG_EN, MENU_GAME_LANG_ES, MENU_GAME_FULLSCREEN, MENU_GAME_MUSIC, MENU_GAME_RETURN_SETTINGS):
+    global settings_menu
+    settings_menu = pygameMenu.Menu(surface, # settings menu
+                    bgfun=settings_background,
+                    color_selected=COLOR_YELLOW,
+                    font=font_type_bold,
+                    font_color=COLOR_WHITE,
+                    font_size=14,
+                    font_size_title=35,
+                    menu_alpha=100,
+                    menu_color=COLOR_BLACK,
+                    menu_height=220,
+                    menu_width=int(WINDOW_SIZE[0]),
+                    onclose=main,
+                    option_shadow=False,
+                    title="",
+                    menu_color_title=COLOR_ORANGE,
+                    widget_alignment=pygameMenu.locals.ALIGN_LEFT,
+                    window_height=220,
+                    window_width=WINDOW_SIZE[0]
+                    )
+    settings_menu.add_selector(MENU_GAME_LANG+":",
+                    [(MENU_GAME_LANG_EN, 'EN'),
+                    (MENU_GAME_LANG_ES, 'ES')],
+                    selector_id='language',
+                    default=int(set_language))
+    settings_menu.add_selector(MENU_GAME_FULLSCREEN+":",
+                    [('OFF', 'OFF'),
+                    ('ON', 'ON')],
+                    selector_id='fullscreen',
+                    default=int(set_fullscreen))
+    settings_menu.add_selector(MENU_GAME_MUSIC+":",
+                    [('OFF', 'OFF'),
+                    ('ON', 'ON')],
+                    selector_id='music',
+                    default=int(set_music))
+    settings_menu.add_option(MENU_GAME_RETURN_SETTINGS, check_form_settings, align=pygameMenu.locals.ALIGN_CENTER)
+    while True:
+        settings_menu.mainloop()
+
+def check_form_settings():
+    data = settings_menu.get_input_data()
+    for k in data.keys():
+        if k == "language": # set language
+            set_language = data[k][1]
+        elif k == "fullscreen":  # set fullscreen
+            set_fullscreen = data[k][1]
+        else: # set music
+            set_music =  data[k][1]
+    save_stored_settings(set_language, set_fullscreen, set_music) # store settings to menu.cfg
+    main() # return back to main menu
+
+def save_stored_settings(set_language, set_fullscreen, set_music):
+    f = open(menu_cfg, "r")
+    menu_config = f.readlines()
+    f.close()
+    menuc = open(menu_cfg, "w")
+    for conf in menu_config:
+        if "LANGUAGE" in conf: # language
+            menuc.write("LANGUAGE:"+str(set_language)+os.linesep)
+        elif "FULLSCREEN" in conf: # screen size
+            menuc.write("FULLSCREEN:"+str(set_fullscreen)+os.linesep)
+        else: # music
+            menuc.write("MUSIC:"+str(set_music))
+    menuc.close()
+
+def main(test=False):
+    global set_fullscreen
+    global set_language
+    global set_music
+    global main_menu
+    pygame.display.set_caption(CAPTION)
+    clock = pygame.time.Clock()
+    set_language, set_fullscreen, set_music = load_stored_settings()
+    main_menu = pygameMenu.Menu(surface, # main menu
+                    bgfun=main_background,
+                    color_selected=COLOR_YELLOW,
+                    font=font_type,
+                    font_color=COLOR_BLACK,
+                    font_size=14,
+                    font_size_title=35,
+                    menu_alpha=100,
+                    menu_color=COLOR_GRAY,
+                    menu_height=1,
+                    menu_width=int(WINDOW_SIZE[0]),
+                    onclose=pygameMenu.events.EXIT,
+                    option_shadow=False,
+                    title=TITLE+":",
+                    menu_color_title=COLOR_ORANGE,
+                    window_height=1,
+                    window_width=WINDOW_SIZE[0]
+                    )
+    main_menu.set_sound(sound, recursive=True) # set menu sounds
+    while True:
+        clock.tick(FPS)
+        main_menu.mainloop(disable_loop=test)
+        pygame.display.flip()
+        if test == True:
+            break
+
+def start_game():
+    level0(surface, COLOR_WHITE, COLOR_BLACK, COLOR_BLUE, COLOR_GRAY, COLOR_YELLOW, COLOR_ORANGE, WINDOW_SIZE, set_language)
+
+def level0_login_background():
+    None
+
+if __name__ == '__main__':
+    main()

+ 1 - 0
data/profile/username.txt

@@ -0,0 +1 @@
+ANONYMOUS

BIN
data/sounds/menu.ogg


+ 5 - 0
data/translations/cheats.txt

@@ -0,0 +1,5 @@
+ENGLISH-MENU_CHEATS_ENTER:ENTER CODE
+ENGLISH-MENU_CHEATS_TRY:TRY
+#
+SPANISH-MENU_CHEATS_ENTER:INTRODUCE CÓDIGO
+SPANISH-MENU_CHEATS_TRY:PROBAR

+ 9 - 0
data/translations/credits_EN.txt

@@ -0,0 +1,9 @@
+  [NoINIW-2051] is a -videogame- with license GPLv3 and development 
+fully in Python (3.x.y), that uses like main engine the library: PyGAME ...
+
+----------
+
+* CREATED BY: psy - (epsylon@riseup.net)
+* GPG: DE23 E4E2 B1A1 C982 41C5 43D0 B3C1 FD78 B8AC 3776
+* WEBSITE: https://03c8.net
+* BTC: 19aXfJtoYJUoXEZtjNwsah2JKN9CK5Pcjw

+ 10 - 0
data/translations/credits_ES.txt

@@ -0,0 +1,10 @@
+  [NoINIW-2051] es un -videjuego- con licencia GPLv3 y desarrollado 
+íntegramente en Python (3.x.y), que utiliza como motor principal 
+la librería: PyGAME ...
+
+----------
+
+* CREADOR POR: psy - (epsylon@riseup.net)
+* GPG: DE23 E4E2 B1A1 C982 41C5 43D0 B3C1 FD78 B8AC 3776
+* WEBSITE: https://03c8.net
+* BTC: 19aXfJtoYJUoXEZtjNwsah2JKN9CK5Pcjw

+ 1 - 0
data/translations/forum_EN.txt

@@ -0,0 +1 @@
+Sorry, but currently we haven't any forum online ... ;-(

+ 1 - 0
data/translations/forum_ES.txt

@@ -0,0 +1 @@
+Lo siento, pero actuálmente no tenemos ningún foro en línea ... ;-(

+ 13 - 0
data/translations/level0.txt

@@ -0,0 +1,13 @@
+ENGLISH-LEVEL0_SERVICE:SERVICE
+ENGLISH-LEVEL0_USERNAME:USER
+ENGLISH-LEVEL0_PASSWORD:PASSWORD
+ENGLISH-LEVEL0_TRY:TRY ACCESS
+ENGLISH-LEVEL0_LOGINGUESTGRANTED:ACCESS GRANTED
+ENGLISH-LEVEL0_LOGINDENIED:ACCESS DENIED
+#
+SPANISH-LEVEL0_SERVICE:SERVICIO
+SPANISH-LEVEL0_USERNAME:USUARIO
+SPANISH-LEVEL0_PASSWORD:CONTRASEÑA
+SPANISH-LEVEL0_TRY:PROBAR ACCESO
+SPANISH-LEVEL0_LOGINGUESTGRANTED:ACCESO CORRECTO
+SPANISH-LEVEL0_LOGINDENIED:ACCESO DENEGADO

+ 29 - 0
data/translations/menu.txt

@@ -0,0 +1,29 @@
+ENGLISH-MENU_GAME_HOWTO:TUTORIAL
+ENGLISH-MENU_GAME_START:PLAY
+ENGLISH-MENU_GAME_SETTINGS:OPTIONS
+ENGLISH-MENU_GAME_UPGRADE:UPDATES
+ENGLISH-MENU_GAME_PUBLIC:FORUMS
+ENGLISH-MENU_GAME_AUTHOR:CREDITS
+ENGLISH-MENU_GAME_CHEATS:CHEATS
+ENGLISH-MENU_GAME_END:EXIT
+ENGLISH-MENU_GAME_LANG:LANGUAGE
+ENGLISH-MENU_GAME_L-EN:ENGLISH
+ENGLISH-MENU_GAME_L-ES:SPANISH
+ENGLISH-MENU_GAME_FULLSCREEN:FULLSCREEN
+ENGLISH-MENU_GAME_MUSIC:MUSIC
+ENGLISH-MENU_GAME_RETURN_SETTINGS:RETURN TO MAIN MENU
+#
+SPANISH-MENU_GAME_HOWTO:TUTORIAL
+SPANISH-MENU_GAME_START:JUGAR
+SPANISH-MENU_GAME_SETTINGS:OPCIONES
+SPANISH-MENU_GAME_UPGRADE:CÓDIGO
+SPANISH-MENU_GAME_PUBLIC:FOROS
+SPANISH-MENU_GAME_AUTHOR:CRÉDITOS
+SPANISH-MENU_GAME_CHEATS:TRUCOS
+SPANISH-MENU_GAME_END:SALIR
+SPANISH-MENU_GAME_LANG:IDIOMA
+SPANISH-MENU_GAME_L-EN:INGLÉS
+SPANISH-MENU_GAME_L-ES:ESPAÑOL
+SPANISH-MENU_GAME_FULLSCREEN:VENTANA COMPLETA
+SPANISH-MENU_GAME_MUSIC:MÚSICA
+SPANISH-MENU_GAME_RETURN_SETTINGS:VOLVER AL MENÚ PRINCIPAL

+ 16 - 0
data/translations/tutorial_EN.txt

@@ -0,0 +1,16 @@
+[NoINIW-2051] Welcomes you ...
+
+  To locate yourself, you are in one of the possible dystopian futures
+technocrats, in which networks, AIs, cyborgs and many others
+more -cyberpunk- subcultures, along with complex algorithms, 
+converge in a single SIMULATED SHELL ENVIRONMENT ... 
+
+----------
+
+TIP: Public proxies (those with a 4-digit MAC), they usually have 
+a ["guest"] user, which matches their number of location and that 
+will allow you to start "snooping" ...
+
+----------
+
+Keep calm & ... Hack the planet! ;-)

+ 16 - 0
data/translations/tutorial_ES.txt

@@ -0,0 +1,16 @@
+[NoINIW-2051] Te da la bienvenida ...
+
+  Para situarte, te encuentras en uno de los posibles futuros distópicos 
+tecnócratas, en los que las redes, las IA, los cyborgs y muchas otras
+subculturas -cyberpunk- más, junto a complejos algoritmos, 
+convergen en un único ENTORNO SHELL SIMULADO ... 
+
+----------
+
+CONSEJO: Los proxies públicos (los que tienen una MAC de 4 cifras), 
+suelen tener un usuario ["invitado"], que coincide con su número 
+de ubicación y que te permitirá comenzar a "husmear" ...
+
+----------
+
+Mantén la calma y ... Hackea el planeta! ;-)

+ 7 - 0
data/translations/updates_EN.txt

@@ -0,0 +1,7 @@
+More info to -maintain updated- your copy, visiting:
+
+   https://code.03c8.net/epsylon/NoINIW2051
+
+Or:
+
+   https://github.com/epsylon/NoINIW2051

+ 7 - 0
data/translations/updates_ES.txt

@@ -0,0 +1,7 @@
+Más información para -mantener tu copia actualizada-, visitando:
+
+   https://code.03c8.net/epsylon/NoINIW2051
+
+O:
+
+   https://github.com/epsylon/NoINIW2051