-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.py
344 lines (281 loc) · 11.2 KB
/
main.py
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
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
import json
import re
from collections import Counter
from pathlib import Path
import yaml
from jinja2 import Environment, FileSystemLoader
from tqdm import tqdm
from diplomacy_news.get_backstabbr import get_backstabbr
from diplomacy_news.get_war_map import get_battle_map, get_battles_coords
from diplomacy_news.ping_gpt import ping_gpt
countries = ["Austria", "England", "France", "Germany", "Italy", "Russia", "Turkey"]
def main():
force = True
orders, units_by_player, territories, season = get_backstabbr(force)
print(season)
if orders is None:
return None
summaries = get_battles(orders, territories)
news = get_news(summaries)
# main_headline = create_main_headline(news)
main_headline = ""
news_list = process_news(news)
standing = get_standing(territories)
generate_newspaper(news_list, main_headline, season, standing)
def get_battles(orders, territories):
metadata = json.load(open("diplomacy_news/territories.json"))
all_regions = get_all_regions(orders)
battles = check_battles(all_regions, orders, territories)
battles_orders = get_battles_orders(battles, orders)
battles_possessions = get_battles_possessions(battles, territories)
battles_coords = get_battles_coords(battles, metadata)
summaries = get_summaries(
battles, battles_orders, battles_possessions, battles_coords, metadata
)
return summaries
def get_all_regions(orders):
all_regions = []
for country, country_orders in orders.items():
for source, order in country_orders.items():
involved_regions = get_involved_regions(source, order)
all_regions += involved_regions
all_regions = list(set(all_regions))
return all_regions
def check_battles(all_regions, orders, territories):
unprocessed_regions = set(all_regions.copy())
battles = []
while unprocessed_regions:
processed_region = unprocessed_regions.pop()
unchecked_regions = {processed_region}
checked_regions = set()
while unchecked_regions:
unchecked_region = unchecked_regions.pop()
connected_regions = find_all_connected_regions(
unchecked_region, orders, territories
)
new_regions = connected_regions - checked_regions - set([unchecked_region])
unchecked_regions = unchecked_regions.union(new_regions)
checked_regions = checked_regions.union(set([unchecked_region]))
battles += [checked_regions]
unprocessed_regions = unprocessed_regions - checked_regions
battles.sort(key=lambda x: -len(x))
return battles
def find_all_connected_regions(unchecked_region, orders, territories):
connected_regions = []
for country, country_orders in orders.items():
for source, order in country_orders.items():
involved_regions = get_involved_regions(source, order)
if unchecked_region in involved_regions:
connected_regions += involved_regions
connected_regions = set(connected_regions)
return connected_regions
def get_involved_regions(source, order):
involved_regions = [source]
if "from" in order:
involved_regions += [order["from"]]
if "to" in order:
involved_regions += [order["to"]]
return involved_regions
def get_battles_orders(battles, orders):
battles_orders = []
for battle in battles:
battle_orders = get_battle_orders(battle, orders)
battles_orders += [battle_orders]
return battles_orders
def get_battle_orders(battle, orders):
battle_orders = []
for region in battle:
for country, country_orders in orders.items():
for source, order in country_orders.items():
involved_regions = get_involved_regions(source, order)
if region in involved_regions:
order["origin"] = source
order["country"] = country
battle_orders += [order]
battle_orders = list(
{v["origin"]: v for v in battle_orders}.values()
) # make unique
return battle_orders
def get_battles_possessions(battles, territories):
battles_possessions = []
for battle in battles:
battle_possessions = get_battle_possessions(battle, territories)
battles_possessions += [battle_possessions]
return battles_possessions
def get_battle_possessions(battle, territories):
battle_possessions = []
for region in battle:
if region in territories:
possession = {
"type": "OCCUPIED",
"country": territories[region],
"origin": region,
}
battle_possessions += [possession]
return battle_possessions
def get_summaries(
battles, battles_orders, battles_possessions, battles_coords, metadata
):
summaries = []
for i, battle, battle_orders, battle_possessions, battle_coords in zip(
range(len(battles)),
battles,
battles_orders,
battles_possessions,
battles_coords,
):
countries_involved = get_countries_involved(battle_orders, battle_possessions)
pretty_battle_orders = get_pretty_battle_orders(battle_orders, metadata)
pretty_battle_possessions = get_pretty_battle_possessions(
battle_possessions, metadata
)
battle_map = get_battle_map(battle_coords, i)
summary = dict(
countries_involved=countries_involved,
pretty_battle_orders=pretty_battle_orders,
pretty_battle_possessions=pretty_battle_possessions,
battle_map=battle_map,
)
summaries += [summary]
return summaries
def get_countries_involved(battle_orders, battle_possessions):
countries_ordering = {order["country"] for order in battle_orders}
countries_possessing = {possession["country"] for possession in battle_possessions}
countries_involved_list = countries_ordering.union(countries_possessing)
countries_involved = yaml.dump(list(countries_involved_list))
return countries_involved
def get_pretty_battle_orders(battle_orders, metadata):
long_battle_orders = battle_orders.copy()
long_battle_orders = [
get_full_names_dictionary(battle_order, metadata)
for battle_order in long_battle_orders
]
pretty_battle_orders = yaml.dump(long_battle_orders)
return pretty_battle_orders
def get_full_names_dictionary(any_dict, metadata):
random_dict = any_dict.copy()
for key, value in random_dict.items():
if type(value) == str and value in metadata:
random_dict[key] = metadata[value]["name"]
if type(value) == dict:
subdict = get_full_names_dictionary(value, metadata)
random_dict[key] = subdict
return random_dict
def get_pretty_battle_possessions(battle_possessions, metadata):
territories_by_country = {
country: get_territories_by_country(country, battle_possessions)
for country in countries
}
territories_by_country = {c: t for c, t in territories_by_country.items() if t}
long_ter_by_country = {
c: [metadata[ter]["name"] for ter in t]
for c, t in territories_by_country.items()
}
pretty_battle_possessions = yaml.dump(long_ter_by_country)
return pretty_battle_possessions
def get_territories_by_country(country, battle_possessions):
territories_by_country = [
possession["origin"]
for possession in battle_possessions
if possession["country"] == country
]
return territories_by_country
def get_news(summaries):
news = []
battle_summaries = [s for s in summaries if s["countries_involved"].count("-") > 1]
for summary in tqdm(battle_summaries):
piece_of_news = create_piece_of_news_prompt(summary)
news += [{"newsline": piece_of_news, "summary": summary}]
other_summaries = "\n".join(
[
s["pretty_battle_orders"]
for s in summaries
if s["countries_involved"].count("-") == 1
]
)
other_news = create_other_news_prompt(other_summaries)
other_news_format = f"Title: In other news...\nSubtitle: Other movements around Europe\nParagraph: {other_news}"
news += [{"newsline": other_news_format, "summary": other_summaries}]
return news
def create_piece_of_news_prompt(summary):
prompt = f"""I will share with you the adjudication of orders from a Diplomacy game.
You will invent the headline for a newspaper that covers European Geopolitics that airs in an alternative 1903. Some territories might be owned by different countries than they were in history.
Invent extra drama and fake people involved. Add their quotes on the situation.
For each headline, provide a title, subtitle and a paragraph.
Report:
---
Countries_involved:
{summary['countries_involved']}
Territories before the battles:
{summary['pretty_battle_possessions']}
Orders:
{summary['pretty_battle_orders']}
---
Output example:
---
Title: title goes here
Subtitle: subtitle goes here
Paragraph: paragraph goes here
---
Output:"""
answer = ping_gpt(prompt, temp=1)
return answer
def create_other_news_prompt(other_summaries):
prompt = f"""I will share with you the adjudication of orders from a Diplomacy game.
These are only the moves that did not involve any conflict between countries, but these countries could have been in conflicts elsewhere.
You will write a paragraph that will go to the "In other news" section of a newspaper. Try to briefly describe what happened.
Report:
---
{other_summaries}
---
Output:"""
other_news = ping_gpt(prompt, temp=1)
return other_news
def create_main_headline(news):
prompt = f"""I will share with you a series of news from a newspaper covering a Europe at war.
You will invent the main headline for this edition of the newspaper and a sentence briefly listing the news.
Make it dramatic and sensational.
News:
---
{yaml.dump(news)}
---
Output example:
---
Headline: title goes here
Sentence: sentence goes here
---
Output:"""
answer = ping_gpt(prompt)
return answer
def process_news(news):
news_list = []
for news_meta in news:
news_piece = news_meta["newsline"]
news_piece = news_piece.split("Title: ")[1]
title, news_piece = news_piece.split("Subtitle: ", 1)
subtitle, paragraph = news_piece.split("Paragraph: ", 1)
title = title.strip().strip('"')
subtitle = subtitle.strip().strip('"')
paragraph = paragraph.strip().strip('"')
paragraph = re.sub("^In a.*?, ", "", paragraph)
paragraph = paragraph[0].upper() + paragraph[1:]
news_list += [
{"newsline": (title, subtitle, paragraph), "summary": news_meta["summary"]}
]
return news_list
def get_standing(territories):
standing_list = Counter(territories.values()).most_common()
standing = [s[0] + " " + str(s[1]) for s in standing_list]
return standing
def generate_newspaper(news_list, main_headline, season, standing):
env = Environment(loader=FileSystemLoader("."))
template = env.get_template("template.html")
newspaper = template.render(
news_list=news_list,
main_headline=main_headline,
season=season,
standing=standing,
)
Path("index.html").write_text(newspaper)
if __name__ == "__main__":
main()