File size: 5,659 Bytes
ebd0b97
 
4f27caf
ebd0b97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ee84e6b
ebd0b97
 
 
 
 
 
424940d
4124932
424940d
ebd0b97
 
ee84e6b
ebd0b97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9a31c2a
ebd0b97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9a31c2a
 
ebd0b97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9a31c2a
ebd0b97
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import google.generativeai as genai
from google.api_core import retry
import os
import pathlib
import textwrap
import json

GOOGLE_API_KEY = os.environ['GOOGLE_API_KEY']

genai.configure(api_key=GOOGLE_API_KEY)

model = genai.GenerativeModel(model_name='models/gemini-1.5-pro-latest')

def generate_story(available_items):
    response = model.generate_content(f"""
      You are game master in a roguelike game. You should help me create an consise objective for the player to fulfill in the current level.
      Our protagonist, A girl with a red hood is wandering inside a dungeon.
      You are ONLY allowed to only use the following elements and not modify either the map or the enemies:
      {available_items}
      Example of possible Objectives:
      Example 1 : Defeat N monster $monster_name and then report it to npc :$npc_name
      Example 2 : Loot two treasure chest then defeat the boss $boss_name to exit.
      A object of type NPC can be talked to but can't move and can't be fought, an ennemy type object can be fought but not talked to. A boss can be fought but not talked to
      To escape, the player will have to pass by the portal.
      
      """, request_options={'retry': retry.Retry()})
    story = response.text
    return story

def place_objects(available_items,story,myMap):
    prompt = f"""
    Please return JSON describing the objective of this level, the objects that should be placed as well as all enemies/npcs that shall be placed:
    
    {{"objective": str, "objects":list[OBJECT], "enemies":list[ENEMIES], "boss":list[BOSS],"npcs": list[NPC]}}
    In all of the following example, placement is the id of the room to place the object in.
    # The Objects that should be placed in the treasure chests
    OBJECT = {{"name": str, "description": str,"placement": int, "strength": str, "speed": str}}
    # The infos necessary about the enemies
    ENEMIES = {{"name": str, "placement": int}}
    # The NPC that should be added to the map
    NPC = {{"name": str, "persona": str, "placement": int}}
    # The Boss monster of this level.
    BOSS = {{"name": str, "placement": int}}

    For objects, the name key represents the name of the object inside the treasure chest
    when placement is requiered, it is the id of the room on the map.
    
    All fields are not necessarily required; if null, don't add it. it should make sense with the crafted story.
    Items can only be weapons or objects that can be useful for a special quest. "strength" and "speed" should only be declared for weapons and can only range between 0 and 1. 0 being a rusty sword and 1 being the best sword in the game.
    
    Important: Only return a single piece of valid JSON text.
    
    Here is the map:
    
    {myMap}
    
    X: is the starting position of the player
    ?: represent and interesting room where it could be interesting to place an object
    numbers represent the index of the room
    
    and the objective of this level: {story}
    The objective MUST be feasible, otherwise the player will be stuck.
    
    REMEMBER, You are ONLY allowed to only use the following elements and not modify either the map or the enemies:
      {available_items}
      
    """

    print(prompt)
    response = model.generate_content(
      prompt,
      generation_config={'response_mime_type':'application/json'}
    )
    try:
        map_placements=json.dumps(json.loads(response.text), indent=4)
    except:
        map_placements="error"
    return map_placements

def get_items_string_representation(items_list):
    result = ""
    for item in items_list:
        item_str = "Name: " + item["name"] + ", Type: " + item["type"] + ", Description: " + item["description"] + "\n"
        result += item_str
    return result

def generate_map_markdown(rooms, room_of_interest,index_exit):
    import numpy as np
    
    # Define the room structure with walls and markers
    def create_room(room_char, index):
        index_str = f"{index}".zfill(2)  # Zero pad index to 2 digits if needed
        if index_str[0] !="0":
            first_number=index_str[0]
        else:
            first_number=" "
        return [
            f"╔═{room_char}═╗",
            f"β•‘ {first_number}{index_str[1]}β•‘",
            f"β•šβ•β•β•β•"
        ]
    
    # Extract rooms and rooms of interest
    rooms = [eval(room) for room in rooms]
    rooms_of_interest = [eval(room) for room in room_of_interest]
    
    # Determine grid size
    min_x = min(room[0] for room in rooms)
    max_x = max(room[0] for room in rooms)
    min_y = min(room[1] for room in rooms)
    max_y = max(room[1] for room in rooms)
    
    # Create grid with empty spaces represented by a room-like structure
    map_height = (max_y - min_y + 1) * 3
    map_width = (max_x - min_x + 1) * 5
    grid = np.full((map_height, map_width), " ")
    
    # Populate grid with rooms and their characteristics
    for i, room in enumerate(rooms):
        x, y = room
        x_offset = (x - min_x) * 5
        y_offset = (max_y - y) * 3
        if room == (0, 0):
            room_char = "X"
        elif room in rooms_of_interest:
            room_char = "P" if i == index_exit else "?"
        else:
            room_char = " "
        room_structure = create_room(room_char, i)
        for j, row in enumerate(room_structure):
            grid[y_offset + j, x_offset:x_offset + 5] = list(row)
    
    # Convert grid to a string format suitable for display
    markdown_map = "\n".join("".join(row) for row in grid)
    
    # Return the map wrapped in triple backticks for proper display in markdown
    return f"```\n{markdown_map}\n```"