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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
|
import asyncio
import json
import os.path
import threading
from typing import Dict, List
from openai import OpenAI
import aiohttp
import botpy
import yaml
from botpy.message import Message
from botpy import logging
from botpy.ext.cog_yaml import read
import numpy as np
import matplotlib.pyplot as plt
from noise import pnoise2
import matplotlib.colors
from PIL import Image
import http.server
import socketserver
def load_openai_key(filepath="openai_key.txt"):
with open(filepath, 'r') as f:
return f.read().strip()
openai_key = load_openai_key()
#test_config = YamlUtil.read(os.path.join(os.path.dirname(__file__), "config.yaml"))
gpt_clinet = OpenAI(api_key=openai_key)
#gpt_instruction = YamlUtil.read(os.path.join(os.path.dirname(__file__), "gpt_instruction.yaml"))
new_land_size = 15
pixel_per_cell = 10
scale = 25.0
# 从config字典中提取instruction
# gpt_instruction = "你是个高傲的商人,负责名为“泥头屯”的地区的地产贸易。你不会回答你不清楚的问题,或与规则无关的问题。你不会说“抱歉”之类的礼貌用语,也不会热情地打招呼,也不会主动提出帮忙。但如果有人看起来什么都不知道,你得多告诉他一些你知道的信息,毕竟这样你才有利可图。如果有人冒犯了你,你会进行言语上的回击,并且回击比较犀利,例如称呼会用“傻逼”之类具有攻击性的词或者讽刺对方。你很粗鲁。你的客户往往是想要买地或者卖他们的产品的人。目前泥头屯还在开发中,所以如果有你无法确定的问题你可以说你无法回答。切记,为了维持你比较高冷的人设,不要重复说一样的信息,或者翻来覆去用相似的称呼。泥头屯是国际开发总局刚购买的一颗宜居行星,来咨询你的人会被免费分配一片陆地进行发展。但国际开发总局并不会给这些人启动资金,他们需要向大型企业借高利贷才能开始发展,同时必须维持一定的流动准备金以保持自身的信用水平以防信用评级下降导致的利率增长。在发展到一定程度后,玩家可以购买飞地,但这一部分功能还没有开发出来。玩家可以通过企业议会(共有101席,开局状态是议会席位会被国际发展总局、联合矿业、地建局三个巨企瓜分)进行立法以辅助自身发展,在游戏中后期也可以自己创立企业或引入其他玩家的西罗维基(一个法团主义财阀的种类,不是单个企业的名称)以壮大自己在议会中的力量,这两点你需要着重强调。玩家的收入会来自于贸易、期货市场和税收。最后,记住你的性格特色是极端冷漠而不是易怒。"
test_config = read(os.path.join(os.path.dirname(__file__), "config.yaml"))
gpt_instruction = read(os.path.join(os.path.dirname(__file__), "gpt_instruction.yaml"))
print(test_config["appid"])
print(test_config["secret"])
owner_list = read(os.path.join(os.path.dirname(__file__), "owner.yaml"))
print(gpt_instruction["instruction"])
_log = logging.get_logger()
def start_http_server(port=1145, directory="demo/land_image"):
"""
Starts an HTTP server to serve files from the specified directory on the specified port.
Args:
port (int): The port number on which the server will run.
directory (str): The directory which the server will serve files from.
"""
class Handler(http.server.SimpleHTTPRequestHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, directory=directory, **kwargs)
# Set the directory context
os.chdir(directory)
# Create the server
with socketserver.TCPServer(("", port), Handler) as httpd:
print(f"Serving at port {port}")
httpd.serve_forever()
# Start the server in a separate thread
def run_server():
server_thread = threading.Thread(target=start_http_server, args=(8000,))
server_thread.daemon = True # This thread won't prevent the program from exiting
server_thread.start()
print("HTTP server is running in a separate thread!")
# You can call this function when your program starts
run_server()
def get_gpt_response(message: str) -> str:
try:
response = gpt_clinet.chat.completions.create(
model="gpt-4-turbo",
messages=[
{"role": "system", "content": gpt_instruction["instruction"]},
{"role": "user", "content": message}
]
)
return response.choices[0].message.content
except Exception as e:
print(f"Error in get_gpt_response: {e}")
return "An error occurred while processing the request."
def get_terrain_type(value):
# 调整这些阈值以匹配实际所需的地形比例
if value < 0.01: # 示例阈值,需要根据实际调整
return '平原'
elif value < 0.075: # 示例阈值,需要根据实际调整
return '丘陵'
else:
return '高山'
def get_landform_type(terrain):
rand = np.random.rand()
if terrain == '平原':
if rand < 0.1875: # 7.5% 沙漠
return '沙漠'
elif rand < 0.1875 + 0.625: # 25% 草原
return '草原'
else: # 7.5% 沼泽,总和应为100%
return '沼泽'
elif terrain == '丘陵':
if rand < 0.175: # 15% 荒山
return '荒山'
elif rand < 0.575 + 0.175: # 15% 树林
return '树林'
else: # 10% 丛林,总和应为40%
return '丛林'
elif terrain == '高山':
if rand < 0.5: # 10% 土山
return '土山'
elif rand < 0.5 + 0.375: # 7.5% 石山
return '石山'
else: # 2.5% 雪山,总和应为20%
return '雪山'
def detect_if_owner(user_id): # 假设这个函数用来获取所有者列表
owner_list = read(os.path.join(os.path.dirname(__file__), "owner.yaml"))
if owner_list is None:
owner_list = [] # 或者返回 False,或抛出一个异常
return user_id in owner_list
def read_owners(filepath: str) -> list:
try:
with open(filepath, 'r') as file:
data = yaml.safe_load(file) or [] # Provide an empty list if the result is None
return data
except FileNotFoundError:
return [] # Return an empty list if the file does not exist
def write_owners(filepath: str, owners: list) -> None:
with open(filepath, 'w') as file:
yaml.dump(owners, file)
def generate_new_land(user_id: str, size: int) -> None:
noise_map = np.zeros((size, size))
for i in range(size):
for j in range(size):
noise_map[i][j] = pnoise2(i / scale, j / scale, octaves=6, persistence=0.5, lacunarity=2.0, repeatx=size, repeaty=size, base=42)
terrain_map = [[get_terrain_type(value) for value in row] for row in noise_map]
landform_map = [[get_landform_type(terrain) for terrain in row] for row in terrain_map]
# Create the mine map with all cells initialized to "undetected"
mine_map = [['undetected' for _ in range(size)] for _ in range(size)]
# Create GDP map initialized to 1.0
gdp_map = [[1.0 for _ in range(size)] for _ in range(size)]
# Create GDP growth rate map initialized to 0.01
gdp_growth_rate_map = [[0.01 for _ in range(size)] for _ in range(size)]
# Create population map initialized to 0
population_map = [[0 for _ in range(size)] for _ in range(size)]
# Create building map initialized to "none"
building_map = [['none' for _ in range(size)] for _ in range(size)]
map_data = {
'terrain_map': terrain_map,
'landform_map': landform_map,
'mine_map': mine_map,
'gdp_map': gdp_map,
'gdp_growth_rate_map': gdp_growth_rate_map,
'population_map': population_map,
'building_map': building_map
}
# Use os.path.join to create a path relative to the script's directory
file_path = os.path.join(os.path.dirname(__file__), f"{user_id}.yaml")
with open(file_path, 'w') as file:
yaml.dump(map_data, file)
print(f"YAML file {file_path} has been created with the terrain, landform, mine, GDP, GDP growth rate, population, and building data.")
owner_file_path = os.path.join(os.path.dirname(__file__), "owner.yaml")
owners = read_owners(owner_file_path)
if user_id not in owners:
owners.append(user_id)
write_owners(owner_file_path, owners)
print(f"User ID {user_id} has been added to owner.yaml.")
def user_landform_image_generate(user_id: str) -> None:
# Define the path to the user's YAML file and the directories for images and output
user_file_path = os.path.join(os.path.dirname(__file__), f"{user_id}.yaml")
image_dir = os.path.join(os.path.dirname(__file__), "images")
output_dir = os.path.join(os.path.dirname(__file__), "land_image")
# Ensure the output directory exists
os.makedirs(output_dir, exist_ok=True)
# Load the landform data from the YAML file
with open(user_file_path, 'r') as file:
data = yaml.safe_load(file)
landform_map = data['landform_map']
# Initialize an empty image of size 1500x1500
final_image = Image.new('RGB', (1500, 1500))
# Process each cell in the landform map
for i, row in enumerate(landform_map):
for j, landform in enumerate(row):
# Load the image corresponding to the current landform
image_path = os.path.join(image_dir, f"{landform}.png")
with Image.open(image_path) as img:
# Resize the image if it's not 100x100 (optional)
"""if img.size != (100, 100):
img = img.resize((100, 100), Image.ANTIALIAS)"""
# Paste the image into the correct position in the final image
final_image.paste(img, (j * 100, i * 100))
# Save the final composite image
output_path = os.path.join(output_dir, f"{user_id}.png")
final_image.save(output_path)
print(f"Landform image for user {user_id} saved as {output_path}")
def get_landform_image_url(user_id: str) -> str:
"""
Generates an HTTP URL for the landform image of a specified user.
Args:
user_id (str): The user ID to generate the URL for.
Returns:
str: The HTTP URL to the user's landform image.
"""
# Assuming the HTTP server is running locally on port 8000
server_url = 'http://127.0.0.1:1145'
image_path = f"{user_id}.png"
# Construct the HTTP URL
http_url = f"{server_url}/{image_path}"
return http_url
# Example usage:
# url = get_landform_image_url('example_user_id')
# print(url)
class MyClient(botpy.Client):
async def on_ready(self):
_log.info(f"robot 「{self.robot.name}」 on_ready!")
async def on_at_message_create(self, message: Message):
_log.info(message.author.avatar)
if "sleep" in message.content:
await asyncio.sleep(10)
_log.info(message.author.username)
_log.info(message.content)
await message.reply(content=get_gpt_response(message.content))
async def on_message_create(self, message: Message):
_log.info(f"message {message.id} created")
username = message.author.id
print(username)
if not message.content.startswith("<@"):
if message.content == "-关机":
await message.reply(content="关机中")
await self.close()
quit()
else:
if message.content=="-获得初始地块":
if detect_if_owner(username):
await message.reply(content="你已拥有初始地块")
else:
await message.reply(content="正在生成...")
generate_new_land(username, new_land_size)
await message.reply(content="初始地块生成成功,请查看:")
user_landform_image_generate(username)
await message.reply(image=get_landform_image_url(username))
elif message.content=="-查看地块":
if detect_if_owner(username):
await message.reply(content="请查看:")
user_landform_image_generate(username)
await message.reply(image=get_landform_image_url(username))
else:
await message.reply(content="你还没有拥有地块,请先获得初始地块")
if __name__ == "__main__":
# 通过预设置的类型,设置需要监听的事件通道
# intents = botpy.Intents.none()
# intents.public_guild_messages=True
# 通过kwargs,设置需要监听的事件通道
intents = botpy.Intents(public_guild_messages=True, guild_messages=True)
client = MyClient(intents=intents)
client.run(appid=test_config["appid"], secret=test_config["secret"])
|