Untitled
unknown
plain_text
9 months ago
12 kB
6
Indexable
import pygame
import sys
import random
import csv
import time
# ------------------------------
# Constants and Configuration
# ------------------------------
SCREEN_WIDTH = 1280
SCREEN_HEIGHT = 720
FPS = 60
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREY = (200, 200, 200)
CITY_COLOR = (150, 50, 50)
PLAYER_COLOR = (50, 150, 50)
MENU_BG_COLOR = (50, 50, 50)
MENU_TEXT_COLOR = (255, 255, 255)
# ------------------------------
# Helper Functions
# ------------------------------
def load_census_data(filename):
"""
Loads census-like data from a CSV file.
The CSV should have columns: city, population, x, y,
where x and y are normalized coordinates (0.0 to 1.0).
"""
cities = []
try:
with open(filename, mode='r', encoding='utf-8') as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
try:
city = row['city']
population = int(row['population'])
x = float(row['x'])
y = float(row['y'])
cities.append({'name': city, 'population': population, 'x': x, 'y': y})
except ValueError:
continue # skip rows with invalid data
except FileNotFoundError:
print("Census file not found. Make sure 'census.csv' exists in the same directory.")
return cities
# ------------------------------
# Game World Entities
# ------------------------------
class City:
def __init__(self, name, population, x, y):
self.name = name
self.population = population
self.x = int(x * SCREEN_WIDTH)
self.y = int(y * SCREEN_HEIGHT)
# Radius scaled to population (ensuring a minimum and maximum)
self.radius = max(5, min(population // 50000, 30))
self.crime_rate = random.uniform(0, 1) # Scale 0 (low) to 1 (high)
self.economy = random.uniform(0.5, 1.5) # Economic multiplier
self.businesses = [] # List of business opportunities
def draw(self, surface):
pygame.draw.circle(surface, CITY_COLOR, (self.x, self.y), self.radius)
font = pygame.font.SysFont("arial", 14)
text = font.render(self.name, True, BLACK)
surface.blit(text, (self.x - self.radius, self.y - self.radius - 15))
def simulate_day(self):
# Random fluctuation in crime rate and economy
self.crime_rate = max(0, min(self.crime_rate + random.uniform(-0.05, 0.05), 1))
self.economy = max(0.1, self.economy + random.uniform(-0.05, 0.05))
# Future expansion: simulate business growth, local events, etc.
class Player:
def __init__(self, world):
self.world = world
# Start in the middle of the screen
self.x = SCREEN_WIDTH // 2
self.y = SCREEN_HEIGHT // 2
self.size = 20
self.speed = 4
self.wealth = 10000 # Starting money
self.reputation = 50 # Scale from 0 to 100
self.current_city = None
self.role = "Neutral" # Options: "Neutral", "Billionaire", "Mafia Boss"
def handle_input(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] or keys[pygame.K_a]:
self.x -= self.speed
if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
self.x += self.speed
if keys[pygame.K_UP] or keys[pygame.K_w]:
self.y -= self.speed
if keys[pygame.K_DOWN] or keys[pygame.K_s]:
self.y += self.speed
# Constrain player within screen boundaries
self.x = max(0, min(self.x, SCREEN_WIDTH - self.size))
self.y = max(0, min(self.y, SCREEN_HEIGHT - self.size))
def draw(self, surface):
pygame.draw.rect(surface, PLAYER_COLOR, (self.x, self.y, self.size, self.size))
def interact(self):
"""
Check if the player is near a city and return that city if so.
"""
for city in self.world.cities:
dx = city.x - self.x
dy = city.y - self.y
dist = (dx**2 + dy**2) ** 0.5
if dist < city.radius + self.size:
self.current_city = city
return city
self.current_city = None
return None
class Faction:
def __init__(self, name, influence, funds):
self.name = name
self.influence = influence # 0 to 100 scale
self.funds = funds
def update_influence(self):
# Factions fluctuate based on world events; simplistic update for now.
self.influence = max(0, min(self.influence + random.uniform(-1, 1), 100))
class World:
def __init__(self):
self.cities = []
census_data = load_census_data("census.csv")
for data in census_data:
self.cities.append(City(data['name'], data['population'], data['x'], data['y']))
# Create factions representing divergent paths
self.factions = {
"Mafia": Faction("Underground Crime Syndicate", influence=50, funds=500000),
"Corporation": Faction("Global Conglomerate", influence=50, funds=1000000)
}
self.day = 1
self.event_log = ["Welcome to Modern America!"]
def simulate_day(self):
# Update each city's simulation and each faction's influence.
for city in self.cities:
city.simulate_day()
for faction in self.factions.values():
faction.update_influence()
self.day += 1
self.event_log.append(f"Day {self.day}: Global events shift the balance.")
# ------------------------------
# Game Class and Main Loop
# ------------------------------
class Game:
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Open World Sandbox: Modern America")
self.clock = pygame.time.Clock()
self.running = True
self.world = World()
self.player = Player(self.world)
self.last_day_update = time.time()
self.font = pygame.font.SysFont("arial", 18)
# Menu system variables for contextual actions
self.menu_mode = False
self.menu_text = ""
self.menu_options = {}
def draw_ui(self):
# Display player's stats and global state at the top left.
stats = [
f"Wealth: ${self.player.wealth}",
f"Reputation: {self.player.reputation}",
f"Day: {self.world.day}",
f"Role: {self.player.role}"
]
y = 10
for stat in stats:
text = self.font.render(stat, True, BLACK)
self.screen.blit(text, (10, y))
y += 20
# Display the last few events
y_offset = 100
for event in self.world.event_log[-3:]:
event_text = self.font.render(event, True, BLACK)
self.screen.blit(event_text, (10, y_offset))
y_offset += 20
if self.menu_mode:
# Draw semi-transparent overlay for the menu
overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
overlay.set_alpha(200)
overlay.fill(GREY)
self.screen.blit(overlay, (0, 0))
lines = self.menu_text.split('\n')
y = SCREEN_HEIGHT // 2 - len(lines)*15
for line in lines:
menu_line = self.font.render(line, True, MENU_TEXT_COLOR)
self.screen.blit(menu_line, (SCREEN_WIDTH//2 - 200, y))
y += 30
def process_menu_input(self, event):
# Basic menu input processing: choose an option based on number keys.
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_1 and "1" in self.menu_options:
self.menu_options["1"]()
elif event.key == pygame.K_2 and "2" in self.menu_options:
self.menu_options["2"]()
elif event.key == pygame.K_3 and "3" in self.menu_options:
self.menu_options["3"]()
elif event.key == pygame.K_ESCAPE:
self.menu_mode = False
# ------------------------------
# Player Career Choices
# ------------------------------
def choose_billionaire_path(self):
self.player.role = "Billionaire"
self.player.wealth += 1000000
self.player.reputation += 10
self.world.factions["Corporation"].funds += 500000
self.world.event_log.append("Your investments soared! Welcome to the billionaire club.")
self.menu_mode = False
def choose_mafia_path(self):
self.player.role = "Mafia Boss"
self.player.wealth += 500000
self.player.reputation -= 20 # Underground life comes at a cost
self.world.factions["Mafia"].funds += 250000
self.world.event_log.append("You now run an underground crime syndicate.")
self.menu_mode = False
def invest_in_city(self, city):
# A sample economic action where investing can yield gains or losses.
investment = random.randint(1000, 10000)
result = random.choice(["gain", "loss"])
if result == "gain":
profit = int(investment * random.uniform(0.1, 0.5) * city.economy)
self.player.wealth += profit
self.world.event_log.append(f"Invested in {city.name}: +${profit}")
else:
loss = int(investment * random.uniform(0.1, 0.5))
self.player.wealth = max(0, self.player.wealth - loss)
self.world.event_log.append(f"Invested in {city.name}: -${loss}")
self.menu_mode = False
# ------------------------------
# Game Loop Methods
# ------------------------------
def update(self):
# Update the world simulation: every 10 seconds equals a new day.
current_time = time.time()
if current_time - self.last_day_update > 10:
self.world.simulate_day()
self.last_day_update = current_time
# Process player movement
self.player.handle_input()
city = self.player.interact()
# If near a city, open a contextual menu for choices.
if city and not self.menu_mode:
self.menu_mode = True
self.menu_text = (
f"You have arrived in {city.name}.\n"
"Choose your action:\n"
"1. Invest in local businesses (Billionaire path)\n"
"2. Engage in underground operations (Mafia path)\n"
"3. Explore the city further\n"
"Press ESC to cancel."
)
# Map keys to functions. Option 3 just cancels the menu.
self.menu_options = {
"1": self.choose_billionaire_path,
"2": self.choose_mafia_path,
"3": lambda: setattr(self, 'menu_mode', False)
}
def handle_events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.running = False
if self.menu_mode:
self.process_menu_input(event)
def draw(self):
self.screen.fill(WHITE)
# Draw cities on the world map
for city in self.world.cities:
city.draw(self.screen)
# Draw the player
self.player.draw(self.screen)
# Draw the UI overlay
self.draw_ui()
pygame.display.flip()
def run(self):
while self.running:
self.clock.tick(FPS)
self.handle_events()
self.update()
self.draw()
pygame.quit()
sys.exit()
# ------------------------------
# Entry Point
# ------------------------------
if __name__ == '__main__':
game = Game()
game.run()Editor is loading...
Leave a Comment