3 display options - coloured text, coloured background and emojis

This commit is contained in:
Vincent Rodley 2025-08-13 10:10:31 +12:00
parent cf288b348d
commit 24112abebb
3 changed files with 182 additions and 24 deletions

View File

@ -1,8 +1,10 @@
# SGR color constants # SGR color constants
# rene-d 2018 # rene-d 2018, modified 2025 for background support
class Colours: class Colours:
""" ANSI color codes """ """ ANSI color codes """
# Foreground colours
BLACK = "\033[0;30m" BLACK = "\033[0;30m"
RED = "\033[0;31m" RED = "\033[0;31m"
GREEN = "\033[0;32m" GREEN = "\033[0;32m"
@ -19,6 +21,26 @@ class Colours:
LIGHT_PURPLE = "\033[1;35m" LIGHT_PURPLE = "\033[1;35m"
LIGHT_CYAN = "\033[1;36m" LIGHT_CYAN = "\033[1;36m"
LIGHT_WHITE = "\033[1;37m" LIGHT_WHITE = "\033[1;37m"
# Background colours
BG_BLACK = "\033[40m"
BG_RED = "\033[41m"
BG_GREEN = "\033[42m"
BG_YELLOW = "\033[43m"
BG_BLUE = "\033[44m"
BG_PURPLE = "\033[45m"
BG_CYAN = "\033[46m"
BG_LIGHT_GRAY = "\033[47m"
BG_DARK_GRAY = "\033[100m"
BG_LIGHT_RED = "\033[101m"
BG_LIGHT_GREEN = "\033[102m"
BG_LIGHT_YELLOW = "\033[103m"
BG_LIGHT_BLUE = "\033[104m"
BG_LIGHT_PURPLE = "\033[105m"
BG_LIGHT_CYAN = "\033[106m"
BG_WHITE = "\033[107m"
# Styles
BOLD = "\033[1m" BOLD = "\033[1m"
FAINT = "\033[2m" FAINT = "\033[2m"
ITALIC = "\033[3m" ITALIC = "\033[3m"
@ -27,15 +49,16 @@ class Colours:
NEGATIVE = "\033[7m" NEGATIVE = "\033[7m"
CROSSED = "\033[9m" CROSSED = "\033[9m"
END = "\033[0m" END = "\033[0m"
# cancel SGR codes if we don't write to a terminal
if not __import__("sys").stdout.isatty(): # Cancel codes if not in a TTY
import sys, platform, ctypes
if not sys.stdout.isatty():
for _ in dir(): for _ in dir():
if isinstance(_, str) and _[0] != "_": if isinstance(_, str) and _[0] != "_":
locals()[_] = "" locals()[_] = ""
else: else:
# set Windows console in VT mode if platform.system() == "Windows":
if __import__("platform").system() == "Windows": kernel32 = ctypes.windll.kernel32
kernel32 = __import__("ctypes").windll.kernel32
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7) kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
del kernel32 del kernel32
@ -43,4 +66,4 @@ class Colours:
if __name__ == '__main__': if __name__ == '__main__':
for i in dir(Colours): for i in dir(Colours):
if i[0:1] != "_" and i != "END": if i[0:1] != "_" and i != "END":
print("{:>16} {}".format(i, getattr(Colours, i) + i + Colours.END)) print("{:>20} {}".format(i, getattr(Colours, i) + i + Colours.END))

156
main.py
View File

@ -1,42 +1,91 @@
import os import os
import sys import sys
from copy import deepcopy
from colours import Colours as C from colours import Colours as C
import random import random
import time import json
# =========================== # ===========================
# | Helper functions | # | Helper functions |
# =========================== # ===========================
def clear(): def clear():
os.system('cls' if sys.platform.startswith('win') else 'clear') os.system('cls' if sys.platform.startswith('win') else 'clear')
def colourTile(tile): def colourTile(tile):
try:
with open("settings.json", "r") as f:
settings = json.load(f)
mode = settings.get("display_mode", "coloured_text")
except (FileNotFoundError, json.JSONDecodeError):
mode = "coloured_text"
if mode == "coloured_text":
if tile == 'R': if tile == 'R':
return f"{C.BOLD}{C.RED}R{C.END}" return f"{C.BOLD}{C.RED} R {C.END}"
elif tile == 'Y': elif tile == 'Y':
return f"{C.BOLD}{C.YELLOW}Y{C.END}" return f"{C.BOLD}{C.YELLOW} Y {C.END}"
elif tile == 'r': elif tile == 'r':
return f"{C.BOLD}{C.LIGHT_GREEN}R{C.END}" return f"{C.BOLD}{C.LIGHT_GREEN} R {C.END}"
elif tile == 'y': elif tile == 'y':
return f"{C.BOLD}{C.LIGHT_GREEN}Y{C.END}" return f"{C.BOLD}{C.LIGHT_GREEN} Y {C.END}"
else: else:
return "O" return " O "
elif mode == "coloured_background":
if tile == 'R':
return f"{C.BG_RED} {C.END}"
elif tile == 'Y':
return f"{C.BG_LIGHT_YELLOW} {C.END}"
elif tile == 'r':
return f"{C.BG_LIGHT_GREEN}{C.BOLD} R {C.END}"
elif tile == 'y':
return f"{C.BG_LIGHT_GREEN}{C.BOLD} Y {C.END}"
else:
return " "
elif mode == "emojis":
if tile.lower() == 'r':
return "🔴"
elif tile.lower() == 'y':
return "🟡"
else:
return ""
return tile
def printBoard(board): def printBoard(board):
try:
with open("settings.json", "r") as f:
settings = json.load(f)
mode = settings.get("display_mode", "coloured_text")
except (FileNotFoundError, json.JSONDecodeError):
mode = "coloured_text"
rows = [] rows = []
for i in range(6): for i in range(6):
row = "" row = ""
for column in board: for column in board:
row += f"{C.BOLD}| {C.END}" + colourTile(column[i]) + " " row += f"{C.BOLD}|{C.END}{colourTile(column[i])}"
row += f"{C.BOLD}|{C.END}" row += f"{C.BOLD}|{C.END}"
rows.append(row) rows.append(row)
rows.reverse() rows.reverse()
print(f""" {C.BOLD}CONNECT FOUR if mode == "emojis":
============================={C.END} top = f""" {C.BOLD}CONNECT FOUR
{'\n'.join(rows)} ======================{C.END}"""
{C.BOLD}==1===2===3===4===5===6===7=={C.END}""") bottom = f"{C.BOLD}==1==2==3==4==5==6==7=={C.END}"
else:
top = f""" {C.BOLD}CONNECT FOUR
============================={C.END}"""
bottom = f"{C.BOLD}==1===2===3===4===5===6===7=={C.END}"
# print(f""" {C.BOLD}CONNECT FOUR
# ============================={C.END}
# {'\n'.join(rows)}
# {C.BOLD}==1===2===3===4===5===6===7=={C.END}""")
print(f"{top}\n{'\n'.join(rows)}\n{bottom}")
def getIntInput(prompt, board=None): def getIntInput(prompt, board=None):
while True: while True:
@ -326,12 +375,93 @@ def play_vs_computer():
# =========================== # ===========================
# | Menu | # | Menu |
# =========================== # ===========================
def edit_settings():
settings_file = "settings.json"
# Default settings if no file exists
default_settings = {
"display_mode": "coloured_text" # options: coloured_text, coloured_background, emojis
}
# Load existing settings
if os.path.exists(settings_file):
with open(settings_file, "r") as f:
try:
settings = json.load(f)
except json.JSONDecodeError:
settings = default_settings.copy()
else:
settings = default_settings.copy()
# Keep a copy for detecting unsaved changes
original_settings = settings.copy()
def save_settings():
with open(settings_file, "w") as f:
json.dump(settings, f, indent=4)
print("Settings saved.")
input("Press Enter to return to main menu...")
while True:
clear()
print("=== Settings Menu ===")
print("1. Display Mode")
print("--------------------")
print("S. Save and Exit")
print("E. Exit without Saving")
print()
print(f"Current Settings: {settings}")
choice = input("Choose a setting to edit, or Save/Exit: ").strip().lower()
if choice == "1":
# Display Mode submenu
while True:
clear()
print("=== Display Mode ===")
modes = [
("coloured_text", "Coloured Text"),
("coloured_background", "Coloured Background"),
("emojis", "Emojis")
]
for i, (key, label) in enumerate(modes, start=1):
if settings["display_mode"] == key:
print(f"{i}. {C.BOLD}{label}{C.END}")
else:
print(f"{i}. {label}")
print("B. Go Back")
sub_choice = input("Choose a display mode: ").strip().lower()
if sub_choice == "b":
break
elif sub_choice in [str(i) for i in range(1, len(modes) + 1)]:
settings["display_mode"] = modes[int(sub_choice) - 1][0]
print(f"Display mode set to {settings['display_mode']}")
else:
input("Invalid choice. Press Enter to try again...")
elif choice == "save" or choice == "s":
save_settings()
return
elif choice == "exit" or choice == "e":
if settings != original_settings:
confirm = input("You have unsaved changes. Exit without saving? (y/n): ").lower()
if confirm == "y":
return
else:
return
else:
input("Invalid choice. Press Enter to try again...")
while True: while True:
clear() clear()
print("How do you want to play?") print("How do you want to play?")
print("1. PvP (same device)") print("1. PvP (same device)")
print("2. PvP (LAN)") print("2. PvP (LAN)")
print("3. PvC (vs computer)") print("3. PvC (vs computer)")
print("4. Edit settings")
print("4. Quit") print("4. Quit")
choice = input("Choose 1-4: ").strip() choice = input("Choose 1-4: ").strip()
if choice == "1": if choice == "1":
@ -344,6 +474,8 @@ while True:
elif choice == "3": elif choice == "3":
play_vs_computer() play_vs_computer()
elif choice == "4": elif choice == "4":
edit_settings()
elif choice == "5":
break break
else: else:
input("Invalid choice. Press Enter to try again...") input("Invalid choice. Press Enter to try again...")

3
settings.json Normal file
View File

@ -0,0 +1,3 @@
{
"display_mode": "coloured_background"
}