Spaces:
Sleeping
Sleeping
import random | |
from flask_socketio import emit | |
class Game: | |
def __init__(self): | |
self.map_size = 50 # Much larger dungeon | |
self.visible_size = 10 # 10x10 visible area on screen | |
self.door_pos = [48, 48] # Door to next level at far end - set before generating maze | |
self.terrain = self.generate_maze() | |
self.player_pos = [1, 1] # Start near top-left | |
self.player_health = 10 | |
self.player_attack = 2 | |
self.inventory = [] | |
self.monsters = self.generate_monsters() | |
self.items = self.generate_items() | |
self.level = 1 | |
def generate_maze(self): | |
# Simple recursive backtracking maze generation | |
terrain = [['w' for _ in range(self.map_size)] for _ in range(self.map_size)] | |
def carve(x, y): | |
terrain[y][x] = 'f' | |
directions = [(0, 2), (2, 0), (-2, 0), (0, -2)] # Right, Down, Left, Up (2 steps for corridors) | |
random.shuffle(directions) | |
for dx, dy in directions: | |
nx, ny = x + dx, y + dy | |
if (0 <= nx < self.map_size and 0 <= ny < self.map_size and | |
terrain[ny][nx] == 'w'): | |
mid_x, mid_y = x + dx // 2, y + dy // 2 | |
terrain[mid_y][mid_x] = 'f' # Carve path | |
carve(nx, ny) | |
# Start carving from (1,1) to avoid edges | |
carve(1, 1) | |
# Ensure player start and door positions are accessible | |
terrain[1][1] = 'f' | |
if hasattr(self, 'door_pos'): # Safety check | |
terrain[self.door_pos[1]][self.door_pos[0]] = 'd' # 'd' for door | |
else: | |
print("Warning: door_pos not set, using default [48, 48]") | |
terrain[48][48] = 'd' # Fallback if door_pos is not set | |
return terrain | |
def generate_monsters(self): | |
monsters = {} | |
for _ in range(10): # 10 enemies (e.g., 5 goblins, 5 skeletons) | |
while True: | |
x, y = random.randint(2, self.map_size - 3), random.randint(2, self.map_size - 3) | |
if self.terrain[y][x] == 'f' and (x, y) not in monsters and (x, y) != tuple(self.player_pos): | |
monster_type = random.choice(['goblin', 'skeleton']) | |
health = 5 if monster_type == 'goblin' else 6 | |
attack = 1 if monster_type == 'goblin' else 2 | |
monsters[(x, y)] = {'type': monster_type, 'health': health, 'attack': attack} | |
break | |
return monsters | |
def generate_items(self): | |
items = {} | |
item_types = ['potion', 'sword'] | |
for _ in range(5): # 5 items (e.g., 3 potions, 2 swords) | |
while True: | |
x, y = random.randint(2, self.map_size - 3), random.randint(2, self.map_size - 3) | |
if self.terrain[y][x] == 'f' and (x, y) not in items and (x, y) not in self.monsters: | |
items[(x, y)] = random.choice(item_types) | |
break | |
return items | |
def get_visible_area(self): | |
print("Generating visible area for player at:", self.player_pos) # Debug log | |
px, py = self.player_pos | |
half_size = self.visible_size // 2 | |
start_x = max(0, px - half_size) | |
start_y = max(0, py - half_size) | |
end_x = min(self.map_size, px + half_size + 1) | |
end_y = min(self.map_size, py + half_size + 1) | |
visible_terrain = [['' for _ in range(self.visible_size)] for _ in range(self.visible_size)] | |
visible_entities = [['' for _ in range(self.visible_size)] for _ in range(self.visible_size)] | |
for y in range(start_y, end_y): | |
for x in range(start_x, end_x): | |
grid_y = y - (py - half_size) | |
grid_x = x - (px - half_size) | |
if 0 <= grid_y < self.visible_size and 0 <= grid_x < self.visible_size: | |
visible_terrain[grid_y][grid_x] = self.terrain[y][x] if self.terrain[y][x] else 'f' # Default to 'f' | |
if (x, y) == tuple(self.player_pos): | |
visible_entities[grid_y][grid_x] = 'player' | |
elif (x, y) in self.monsters: | |
visible_entities[grid_y][grid_x] = self.monsters[(x, y)]['type'] | |
elif (x, y) in self.items: | |
visible_entities[grid_y][grid_x] = self.items[(x, y)] | |
elif (x, y) == tuple(self.door_pos): | |
visible_entities[grid_y][grid_x] = 'door' | |
print("Visible terrain:", visible_terrain) # Debug log | |
print("Visible entities:", visible_entities) # Debug log | |
return {'terrain': visible_terrain, 'entities': visible_entities} | |
def get_game_state(self): | |
visible = self.get_visible_area() | |
state = { | |
'terrain': visible['terrain'], | |
'entities': visible['entities'], | |
'health': self.player_health, | |
'inventory': self.inventory, | |
'attack': self.player_attack, | |
'level': self.level | |
} | |
print("Game state:", state) # Debug log | |
return state | |
def is_valid_position(self, x, y): | |
return (0 <= x < self.map_size and 0 <= y < self.map_size and | |
self.terrain[y][x] != 'w') | |
def move_player(self, direction): | |
dx, dy = {'up': (0, -1), 'down': (0, 1), 'left': (-1, 0), 'right': (1, 0)}[direction] | |
new_x, new_y = self.player_pos[0] + dx, self.player_pos[1] + dy | |
if self.is_valid_position(new_x, new_y): | |
self.player_pos = [new_x, new_y] | |
pos_tuple = tuple(self.player_pos) | |
# Check for monster | |
if pos_tuple in self.monsters: | |
self.handle_combat(pos_tuple) | |
# Check for item | |
elif pos_tuple in self.items: | |
item = self.items.pop(pos_tuple) | |
self.inventory.append(item) | |
if item == 'sword': | |
self.player_attack += 1 | |
emit('message', 'Picked up a sword! Attack increased.') | |
else: | |
emit('message', f'Picked up a {item}!') | |
# Check for door | |
elif pos_tuple == tuple(self.door_pos): | |
self.level += 1 | |
self.reset_level() | |
emit('message', f'Entered Level {self.level}! New dungeon awaits.') | |
def reset_level(self): | |
self.door_pos = [48, 48] # Reset door position | |
self.terrain = self.generate_maze() | |
self.player_pos = [1, 1] | |
self.player_health = 10 | |
self.monsters = self.generate_monsters() | |
self.items = self.generate_items() | |
def handle_combat(self, pos): | |
from flask_socketio import emit | |
monster = self.monsters[pos] | |
monster_health = monster['health'] | |
while monster_health > 0 and self.player_health > 0: | |
monster_health -= self.player_attack | |
emit('message', f"You attack the {monster['type']} for {self.player_attack} damage.") | |
if monster_health <= 0: | |
emit('message', f"You defeated the {monster['type']}!") | |
del self.monsters[pos] | |
break | |
self.player_health -= monster['attack'] | |
emit('message', f"The {monster['type']} attacks you for {monster['attack']} damage.") | |
if self.player_health <= 0: | |
emit('message', 'Game over! You were defeated.') | |
break |