expanded basic game features

This commit is contained in:
2026-04-27 08:45:44 -07:00
parent 0217d6636f
commit 5ff452ba2c
21 changed files with 5001 additions and 172 deletions

359
test_database.py Normal file
View File

@@ -0,0 +1,359 @@
#!/usr/bin/env python3
"""
Test script to check MariaDB database connection and status for VCK Online
"""
import sys
def test_database_connection():
"""Test the database connection and basic functionality"""
# Database connection parameters from game.py
# Using localhost for SSH port forwarding (ssh -L 3306:localhost:3306 lukesau.com)
db_config = {
'user': 'vckonline',
'password': 'vckonline',
'host': '127.0.0.1',
'database': 'vckonline'
}
print("Testing VCK Online Database Connection")
print("=" * 50)
# Test 1: Check if mariadb module is available
print("\n1. Checking mariadb module...")
try:
import mariadb
print(" ✓ mariadb module found")
except ImportError:
print(" ✗ mariadb module not found")
print(" Install with: pip install mariadb")
print(" Or with user flag: pip install --user mariadb")
print(" Or use virtualenv: python3 -m venv .env && source .env/bin/activate && pip install mariadb")
return False
# Test 1.5: Check if database server is accessible
print("\n1.5. Checking if database server is accessible on localhost:3306...")
print(" (Make sure SSH port forwarding is active: ssh -L 3306:localhost:3306 lukesau.com)")
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(2)
result = sock.connect_ex(('127.0.0.1', 3306))
sock.close()
if result == 0:
print(" ✓ Database server is accessible on localhost:3306")
else:
print(" ✗ Cannot reach localhost:3306")
print("\n Make sure SSH port forwarding is active:")
print(" ssh -L 3306:localhost:3306 lukesau.com")
return False
# Test 2: Test connection
print("\n2. Testing database connection...")
try:
connection = mariadb.connect(**db_config)
print(f" ✓ Successfully connected to database '{db_config['database']}'")
cursor = connection.cursor(dictionary=True)
except mariadb.Error as e:
print(f" ✗ Connection failed: {e}")
print("\n Possible issues:")
print(" - Database 'vckonline' does not exist")
print(" - User 'vckonline' does not exist or password is incorrect")
print(" - User does not have permission to access from this IP")
return False
# Test 3: Check if required tables exist
print("\n3. Checking required tables...")
required_tables = ['citizens', 'monsters', 'domains', 'dukes', 'starters']
existing_tables = []
try:
cursor.execute("SHOW TABLES")
# SHOW TABLES returns a dict with key like 'Tables_in_vckonline'
tables = [list(row.values())[0] for row in cursor.fetchall()]
for table in required_tables:
if table in tables:
print(f" ✓ Table '{table}' exists")
existing_tables.append(table)
else:
print(f" ✗ Table '{table}' is missing")
except mariadb.Error as e:
print(f" ✗ Error checking tables: {e}")
connection.close()
return False
# Test 4: Check table row counts
print("\n4. Checking table data...")
for table in existing_tables:
try:
cursor.execute(f"SELECT COUNT(*) as count FROM {table}")
count = cursor.fetchone()['count']
print(f" {table}: {count} rows")
except mariadb.Error as e:
print(f" ✗ Error counting rows in '{table}': {e}")
# Test 4.5: Display all card data
print("\n4.5. Displaying all card data...")
# Citizens
try:
cursor.execute("SELECT name, gold_cost, roll_match1, roll_match2, shadow_count, holy_count, soldier_count, worker_count, expansion FROM citizens ORDER BY expansion, roll_match1")
citizens = cursor.fetchall()
print(f"\n CITIZENS ({len(citizens)} total):")
for c in citizens:
name, gc, r1, r2, sh, ho, so, wo, exp = c
roles = []
if sh: roles.append(f"{sh} Shadow")
if ho: roles.append(f"{ho} Holy")
if so: roles.append(f"{so} Soldier")
if wo: roles.append(f"{wo} Worker")
role_str = ", ".join(roles) if roles else "No roles"
roll_str = f"{r1}" + (f"/{r2}" if r2 else "")
print(f" {name:20} | Cost: {gc:2}gp | Roll: {roll_str:5} | {role_str:20} | {exp}")
except mariadb.Error as e:
print(f" ✗ Error fetching citizens: {e}")
# Monsters
try:
cursor.execute("SELECT name, area, monster_type, monster_order, strength_cost, magic_cost, vp_reward, gold_reward, strength_reward, magic_reward, expansion FROM monsters ORDER BY area, monster_order")
monsters = cursor.fetchall()
print(f"\n MONSTERS ({len(monsters)} total):")
for m in monsters:
name, area, mtype, order, sc, mc, vp, gr, sr, mr, exp = m
cost_str = f"{sc}sp" + (f" + {mc}mp" if mc else "")
reward_str = f"{vp}vp" + (f" + {gr}gp" if gr else "") + (f" + {sr}sp" if sr else "") + (f" + {mr}mp" if mr else "")
print(f" {name:25} | {area:10} | {mtype:8} | Cost: {cost_str:10} | Reward: {reward_str:15} | {exp}")
except mariadb.Error as e:
print(f" ✗ Error fetching monsters: {e}")
# Domains
try:
cursor.execute("SELECT name, gold_cost, shadow_count, holy_count, soldier_count, worker_count, vp_reward, text, expansion FROM domains ORDER BY expansion, gold_cost")
domains = cursor.fetchall()
print(f"\n DOMAINS ({len(domains)} total):")
for d in domains:
name, gc, sh, ho, so, wo, vp, text, exp = d
roles = []
if sh: roles.append(f"{sh} Shadow")
if ho: roles.append(f"{ho} Holy")
if so: roles.append(f"{so} Soldier")
if wo: roles.append(f"{wo} Worker")
role_str = ", ".join(roles) if roles else "No roles"
text_preview = (text[:40] + "...") if text and len(text) > 40 else (text or "No effect")
print(f" {name:25} | Cost: {gc:2}gp | {role_str:20} | {vp}vp | {text_preview} | {exp}")
except mariadb.Error as e:
print(f" ✗ Error fetching domains: {e}")
# Dukes
try:
cursor.execute("SELECT name, gold_mult, strength_mult, magic_mult, shadow_mult, holy_mult, soldier_mult, worker_mult, monster_mult, citizen_mult, domain_mult, expansion FROM dukes ORDER BY expansion, name")
dukes = cursor.fetchall()
print(f"\n DUKES ({len(dukes)} total):")
for d in dukes:
name, gm, sm, mm, shm, hom, som, wom, mom, cm, dom, exp = d
mults = []
if gm: mults.append(f"Gold×{gm}")
if sm: mults.append(f"Str×{sm}")
if mm: mults.append(f"Mag×{mm}")
if shm: mults.append(f"Shadow×{shm}")
if hom: mults.append(f"Holy×{hom}")
if som: mults.append(f"Soldier×{som}")
if wom: mults.append(f"Worker×{wom}")
if mom: mults.append(f"Monster×{mom}")
if cm: mults.append(f"Citizen×{cm}")
if dom: mults.append(f"Domain×{dom}")
mult_str = ", ".join(mults) if mults else "No multipliers"
print(f" {name:30} | {mult_str} | {exp}")
except mariadb.Error as e:
print(f" ✗ Error fetching dukes: {e}")
# Starters
try:
cursor.execute("SELECT name, roll_match1, roll_match2, gold_payout_on_turn, gold_payout_off_turn, strength_payout_on_turn, strength_payout_off_turn, magic_payout_on_turn, magic_payout_off_turn, expansion FROM starters ORDER BY roll_match1")
starters = cursor.fetchall()
print(f"\n STARTERS ({len(starters)} total):")
for s in starters:
name, r1, r2, gpot, gpoff, spot, spoff, mpot, mpoff, exp = s
roll_str = f"{r1}" + (f"/{r2}" if r2 else "")
payouts = []
if gpot: payouts.append(f"{gpot}gp (on)")
if gpoff: payouts.append(f"{gpoff}gp (off)")
if spot: payouts.append(f"{spot}sp (on)")
if spoff: payouts.append(f"{spoff}sp (off)")
if mpot: payouts.append(f"{mpot}mp (on)")
if mpoff: payouts.append(f"{mpoff}mp (off)")
payout_str = ", ".join(payouts) if payouts else "No payouts"
print(f" {name:20} | Roll: {roll_str:5} | {payout_str} | {exp}")
except mariadb.Error as e:
print(f" ✗ Error fetching starters: {e}")
# Test 5: Test stored procedures
print("\n5. Checking stored procedures...")
print(" (These are helper functions used by the game code to select cards)")
required_procedures = [
'select_base1_citizens',
'select_base1_monsters',
'select_base2_citizens',
'select_base2_monsters',
'select_random_domains',
'select_random_dukes'
]
try:
cursor.execute("SHOW PROCEDURE STATUS WHERE Db = 'vckonline'")
procedures = [row['Name'] for row in cursor.fetchall()]
missing_procedures = []
for proc in required_procedures:
if proc in procedures:
print(f" ✓ Procedure '{proc}' exists")
else:
print(f" ✗ Procedure '{proc}' is missing")
missing_procedures.append(proc)
if missing_procedures:
print(f"\n Note: {len(missing_procedures)} stored procedures are missing.")
print(" These can be created from the SQL files in the sql/ directory:")
print(" - select_base1_citizens_sp.sql")
print(" - select_base1_monsters_sp.sql")
print(" - select_base2_citizens_sp.sql")
print(" - select_base2_monsters_sp.sql")
print(" - select_random_domains_sp.sql")
print(" - select_random_dukes_sp.sql")
except mariadb.Error as e:
print(f" ✗ Error checking procedures: {e}")
# Test 6: Test a sample query
print("\n6. Testing sample query...")
try:
cursor.execute("SELECT * FROM starters LIMIT 1")
result = cursor.fetchone()
if result:
name = result.get('name', 'N/A')
print(f" ✓ Sample query successful (found starter: {name})")
else:
print(" ⚠ Sample query returned no results (table may be empty)")
except mariadb.Error as e:
print(f" ✗ Sample query failed: {e}")
# Test 7: Test all stored procedures and display results
print("\n7. Testing stored procedures and displaying results...")
# Get list of available procedures
try:
cursor.execute("SHOW PROCEDURE STATUS WHERE Db = 'vckonline'")
available_procedures = {row['Name']: True for row in cursor.fetchall()}
except mariadb.Error as e:
print(f" ✗ Error checking procedures: {e}")
available_procedures = {}
# Test each procedure
procedure_tests = [
('select_base1_citizens', 'Citizens'),
('select_base1_monsters', 'Monsters'),
('select_base2_citizens', 'Citizens'),
('select_base2_monsters', 'Monsters'),
('select_random_domains', 'Domains'),
('select_random_dukes', 'Dukes')
]
for proc_name, card_type in procedure_tests:
if proc_name not in available_procedures:
print(f"\n{proc_name} - Procedure not found (skipping)")
continue
try:
print(f"\n Testing {proc_name}():")
cursor.callproc(proc_name)
results = cursor.fetchall()
if not results:
print(f" ⚠ No results returned")
continue
print(f" ✓ Returned {len(results)} {card_type.lower()}")
# Display results based on card type (using dictionary access)
if card_type == 'Citizens':
print(f" {card_type} returned:")
for row in results:
name = row.get('name', 'N/A')
gc = row.get('gold_cost')
r1 = row.get('roll_match1')
r2 = row.get('roll_match2')
sh = row.get('shadow_count', 0) or 0
ho = row.get('holy_count', 0) or 0
so = row.get('soldier_count', 0) or 0
wo = row.get('worker_count', 0) or 0
exp = row.get('expansion')
roles = []
if sh: roles.append(f"{sh} Shadow")
if ho: roles.append(f"{ho} Holy")
if so: roles.append(f"{so} Soldier")
if wo: roles.append(f"{wo} Worker")
role_str = ", ".join(roles) if roles else "No roles"
roll_str = f"{r1}" + (f"/{r2}" if r2 and r2 > 0 else "")
gc_str = f"{gc}gp" if gc is not None else "N/A"
exp_str = f" | {exp}" if exp else ""
print(f" {name:20} | Cost: {gc_str:5} | Roll: {roll_str:5} | {role_str:20}{exp_str}")
elif card_type == 'Monsters':
print(f" {card_type} returned:")
for row in results:
name = row.get('name', 'N/A')
area = row.get('area')
mtype = row.get('monster_type')
sc = row.get('strength_cost', 0) or 0
mc = row.get('magic_cost', 0) or 0
vp = row.get('vp_reward', 0) or 0
gr = row.get('gold_reward', 0) or 0
exp = row.get('expansion')
cost_str = f"{sc}sp" + (f" + {mc}mp" if mc else "")
reward_str = f"{vp}vp" + (f" + {gr}gp" if gr else "")
exp_str = f" | {exp}" if exp else ""
print(f" {name:25} | {area:10} | {mtype:8} | Cost: {cost_str:10} | Reward: {reward_str:15}{exp_str}")
elif card_type == 'Domains':
print(f" {card_type} returned:")
for row in results:
name = row.get('name', 'N/A')
gc = row.get('gold_cost')
vp = row.get('vp_reward')
text = row.get('text')
text_preview = (text[:50] + "...") if text and len(text) > 50 else (text or "No effect")
print(f" {name:25} | Cost: {gc:2}gp | {vp}vp | {text_preview}")
elif card_type == 'Dukes':
print(f" {card_type} returned:")
for row in results:
name = row.get('name', 'N/A')
gm = row.get('gold_mult', 0) or 0
sm = row.get('strength_mult', 0) or 0
mm = row.get('magic_mult', 0) or 0
mults = []
if gm: mults.append(f"Gold×{gm}")
if sm: mults.append(f"Str×{sm}")
if mm: mults.append(f"Mag×{mm}")
mult_str = ", ".join(mults) if mults else "No multipliers"
print(f" {name:30} | {mult_str}")
except mariadb.Error as e:
print(f" ✗ Error calling {proc_name}: {e}")
# Cleanup
cursor.close()
connection.close()
print("\n" + "=" * 50)
print("Database test completed")
return True
if __name__ == "__main__":
success = test_database_connection()
sys.exit(0 if success else 1)