import random

# Define the attributes for the player and monsters
player_attributes = {
    "life_points": 100,
    "strength": 10,
    "experience_points": 0,
    "x": None,
    "y": None
}

monster_attributes = {
    "life_points": 50,
    "strength": 5
}

# Define the size of the world
world_size = 200

# Define the number of monsters
min_monsters = 50
max_monsters = 100

# Define the functions for moving the player and checking for collisions
def move_player(direction):
    if direction == "north":
        player_attributes["y"] -= 1
    elif direction == "south":
        player_attributes["y"] += 1
    elif direction == "east":
        player_attributes["x"] += 1
    elif direction == "west":
        player_attributes["x"] -= 1

def check_collision():
    for monster in monsters:
        if monster["x"] == player_attributes["x"] and monster["y"] == player_attributes["y"]:
            return monster
    if treasure["x"] == player_attributes["x"] and treasure["y"] == player_attributes["y"]:
        return "treasure"
    return None

# Generate the world
monsters = []
while len(monsters) < random.randint(min_monsters, max_monsters):
    monster_x = random.randint(0, world_size-1)
    monster_y = random.randint(0, world_size-1)
    if monster_x != player_attributes["x"] and monster_y != player_attributes["y"]:
        monsters.append({
            "life_points": monster_attributes["life_points"],
            "strength": monster_attributes["strength"],
            "x": monster_x,
            "y": monster_y
        })

treasure = {
    "x": random.randint(0, world_size-1),
    "y": random.randint(0, world_size-1)
}
while treasure["x"] == player_attributes["x"] and treasure["y"] == player_attributes["y"]:
    treasure = {
        "x": random.randint(0, world_size-1),
        "y": random.randint(0, world_size-1)
    }

# Place the player in a random location
player_attributes["x"] = random.randint(0, world_size-1)
player_attributes["y"] = random.randint(0, world_size-1)
while check_collision() is not None:
    player_attributes["x"] = random.randint(0, world_size-1)
    player_attributes["y"] = random.randint(0, world_size-1)

# Define the main game loop
while True:
    # Ask the player for a direction
    direction = input("Which direction do you want to go? (north/south/east/west) ")

    # Move the player and check for collisions
    move_player(direction)
    collision = check_collision()

    # Handle the collision
    if collision is None:
        # No collision, keep exploring
        print("You keep exploring...")
    elif collision == "treasure":
        # Treasure found, game over
        print("Congratulations! You found the treasure and won the game!")
        break
    else:
        # Collision with a monster, fight it

class Creature:
    def __init__(self, life_points, strength):
        self.life_points = life_points
        self.strength = strength

    def attack(self, other):
        damage = self.strength
        print(f"{self.__class__.__name__} attacks {other.__class__.__name__} for {damage} damage")
        other.take_damage(damage)

    def take_damage(self, damage):
        self.life_points -= damage
        if self.life_points <= 0:
            print(f"{self.__class__.__name__} is defeated")

class Player(Creature):
    def __init__(self):
        super().__init__(INITIAL_LIFE_POINTS, INITIAL_STRENGTH)
        self.experience_points = 0

class Monster(Creature):
    def __init__(self, strength):
        super().__init__(INITIAL_LIFE_POINTS, strength)

def move_player(direction):
    global player_x, player_y
    if direction == "north" and player_x > 0:
        player_x -= 1
    elif direction == "south" and player_x < GRID_SIZE-1:
        player_x += 1
    elif direction == "west" and player_y > 0:
        player_y -= 1
    elif direction == "east" and player_y < GRID_SIZE-1:
        player_y += 1

# Define constants
GRID_SIZE = 200
NUM_MONSTERS = random.randint(50, 100)
DIRECTIONS = ["north", "south", "east", "west"]
INITIAL_LIFE_POINTS = 100
INITIAL_STRENGTH = 10

# Initialize game
grid = generate_grid()
creatures = generate_creatures()
player_x, player_y, player = creatures[0]

# Main game loop
find_treasure()

def generate_grid():
    return [[None for _ in range(GRID_SIZE)] for _ in range(GRID_SIZE)]
La fonction qui génère les créatures génère bien le joueur et les monstres en quantité demandée, et place bien tout ce petit monde sur le terrain à des positions aléatoires en veillant apparemment à ce qu’ils ne se marchent pas sur les pieds :
def generate_creatures():
    creatures = []
    # Generate player at random location
    player = Player()
    player_x, player_y = generate_random_location()
    creatures.append((player_x, player_y, player))
    # Generate monsters at random locations
    for _ in range(NUM_MONSTERS):
        monster_strength = random.randint(1, 10)
        monster_x, monster_y = generate_random_location()
        monster = Monster(monster_strength)
        creatures.append((monster_x, monster_y, monster))
    return creatures

def generate_random_location():
    while True:
        x, y = random.randint(0, GRID_SIZE-1), random.randint(0, GRID_SIZE-1)
        if grid[x][y] is None:
            return x, y

def find_treasure():
    treasure_x, treasure_y = generate_random_location()
    while grid[treasure_x][treasure_y] is not None:
        treasure_x, treasure_y = generate_random_location()
    grid[treasure_x][treasure_y] = "treasure"
    print(f"Treasure is located at ({treasure_x}, {treasure_y})")

random_locations = [i for i in range (GRID_SIZE * GRID_SIZE)]
for i in range (len (random_locations) - 1, 0, -1):
    j = random.randint (0, i)
    random_locations[i], random_locations[j] = random_locations[j], random_locations[i]
for i in range (len (random_locations)):
    random_locations[i] = (random_locations[i] % GRID_SIZE, random_locations[i] // GRID_SIZE)

while True:
    grid[player_x][player_y] = "player"
    print(f"Player is at ({player_x}, {player_y})")
    print_status()
    direction = input("Where do you want to go (north/south/east/west)? ")
    if direction not in DIRECTIONS:
        print("Invalid direction, try again")
        continue
    move_player(direction)
    if grid[player_x][player_y] == "treasure":
        print("Congratulations, you found the treasure and won the game!")
        break
    elif any(x == player_x and y == player_y for x, y, creature in creatures if isinstance(creature, Monster)):
        fight_monster(player_x, player_y)
        if player.life_points <= 0:
            restart_game()
            continue
    else:
        grid[player_x][player_y] = "player"

def print_status():
    print(f"Player: life points={player.life_points}, strength={player.strength}, experience points={player.experience_points}")
    for x, y, creature in creatures:
        if isinstance(creature, Monster):
            print(f"Monster at ({x}, {y}): life points={creature.life_points}, strength={creature.strength}")

def fight_monster(x, y):
    monster = None
    for c_x, c_y, creature in creatures:
        if c_x == x and c_y == y and isinstance(creature, Monster):
            monster = creature
            break
    if monster is None:
        return
    print(f"You encounter a monster at ({x}, {y})")
    while True:
        # Player attacks
        player.attack(monster)
        if monster.life_points <= 0:
            player.experience_points += monster.strength
            creatures.remove((x, y, monster))
            print(f"You defeated the monster and earned {monster.strength} experience points")
            break
        # Monster attacks
        monster.attack(player)
        if player.life_points <= 0:
            print("You were defeated by the monster")
            restart_game()

def restart_game():
    global grid, creatures, player_x, player_y, player
    print("Restarting game...")
    grid = generate_grid()
    creatures = generate_creatures()
    player_x, player_y, player = None, None, None
    while player is None:
        x, y = generate_random_location()
        if grid[x][y] is None:
            player_x, player_y = x, y
            player = creatures[0][2]
            creatures[0] = (x, y, player)

import random

class Creature:
    def __init__(self, life_points=random.randint(10,100), strength=random.randint(10,100), experience=0, coordinates=(0,0)):
        self.life_points = life_points
        self.strength = strength
        self.experience = experience
        self.coordinates = coordinates

class Playfield:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def moveTo(self, playfield, coordinates):
        if coordinates[0] > playfield.width or coordinates[1] > playfield.height:
            print("Coordinates are out of bounds.")
            return
        self.coordinates = coordinates

class Playfield:
    def __init__(self, width, height):
        self.width = width
        self.height = height

class Creature:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def moveTo(self, playfield, x, y):
        if x < 0 or x >= playfield.width or y < 0 or y >= playfield.height:
            print("Cannot move creature outside playfield!")
            return

        self.x = x
        self.y = y

class Game:
    def __init__(self, width, height):
        self.playfield = Playfield(width, height)
        self.creatures = []
        for i in range(random.randint(10, 100)):
            creature = Creature(0, 0)
            self.creatures.append(creature)

        # Use Fisher-Yates algorithm to shuffle the list of creatures
        n = len(self.creatures)
        for i in range(n - 1, 0, -1):
            j = random.randint(0, i)
            self.creatures[i], self.creatures[j] = self.creatures[j], self.creatures[i]

        # Place each creature at a random and empty location on the playfield
        for creature in self.creatures:
            while True:
                x = random.randint(0, self.playfield.width - 1)
                y = random.randint(0, self.playfield.height - 1)
                if all((x, y) != (c.x, c.y) for c in self.creatures):
                    creature.x = x
                    creature.y = y
                    break

        # Create the player
        self.player = Player(0, 0)

        # Use Fisher-Yates algorithm to shuffle a list of all coordinates on the playfield
        coords = [(x, y) for x in range(self.playfield.width) for y in range(self.playfield.height)]
        n = len(coords)
        for i in range(n - 1, 0, -1):
            j = random.randint(0, i)
            coords[i], coords[j] = coords[j], coords[i]

        # Place the player at the first random and empty location on the shuffled list
        for x, y in coords:
            if all((x, y) != (c.x, c.y) for c in self.creatures):
                self.player.x = x
                self.player.y = y
                break

class Game :
    def __init__(self, width, height) :
        self.playfield = Playfield(width, height)

        # Create a list of all possible positions in the playfield
        positions = [(x, y) for x in range(width) for y in range(height)]

        # Shuffle the positions using the Fisher-Yates algorithm
        for i in range(len(positions) – 1, 0, -1) :
            j = random.randint(0, i)
            positions[i], positions[j] = positions[j], positions[i]

        # Create the creatures and place them on the shuffled positions
        self.creatures = []
        for i in range(random.randint(10, 100)) :
            creature = Creature(0, 0)
            self.creatures.append(creature)
            creature.x, creature.y = positions.pop()

        # Create the player and place it on a shuffled position
        self.player = Player(0, 0)
        self.player.x, self.player.y = positions.pop()

def test_game_positions():
    game = Game(10, 10)
    positions = set()
    positions.add((game.player.x, game.player.y))
    for creature in game.creatures:
        positions.add((creature.x, creature.y))
    assert len(positions) == len(game.creatures) + 1  # player + creatures