Skip to content

Commit 19d01a8

Browse files
authored
v3
1 parent 31afefb commit 19d01a8

File tree

1 file changed

+161
-55
lines changed

1 file changed

+161
-55
lines changed

main.py

Lines changed: 161 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
1-
from collections import Counter
2-
from typing import Literal
3-
import json
4-
import time
5-
import sys
6-
import os
1+
from collections import Counter #counter for counting resources
2+
from typing import Literal #type hinting for literals
3+
import time #time for sleep
4+
import sys #sys for clearing console
5+
import ast #ast for parsing a python dict
6+
import os #os for clearing console
77

88
players = {}
99
nextprint = ""
1010

11-
def get_numbers(input: str):
11+
def clear(): #clear console
12+
if sys.platform.startswith("win"):
13+
os.system("cls")
14+
else:
15+
os.system("clear")
16+
17+
def get_numbers(input: str): #get list of numbers from input
1218
user_input = input
1319
numbers = [int(num.strip()) for num in user_input.split(",")]
1420
return numbers
1521

16-
def num_to_resource(num: int):
22+
def num_to_resource(num: int): #convert number to resource name
1723
if num == 1:
1824
return "Wood"
1925
elif num == 2:
@@ -24,19 +30,28 @@ def num_to_resource(num: int):
2430
return "Sheep"
2531
elif num == 5:
2632
return "Ore"
27-
28-
def add_player(name: str):
33+
34+
def get_amount_of_resources(name: str, resource: int): #get amount of specific resource a player has
35+
global players
36+
resources = players[name].get("resources", [])
37+
38+
if resource is None:
39+
return 0
40+
else:
41+
return resources.count(int(resource))
42+
43+
def add_player(name: str): #add player to game
2944
global players
3045
players[name] = {"order":len(players)+1}
3146

32-
def get_player_order(order: int):
47+
def get_player_order(order: int): #get player name by order
3348
global players
3449
for name, info in players.items():
3550
if info.get("order") == order:
3651
return name
3752
return None
3853

39-
def get_player_resources(name: str):
54+
def get_player_resources(name: str): #get list of resources a player has
4055
global players
4156
if name not in players:
4257
raise ValueError(f"Player {name} does not exist.")
@@ -45,22 +60,23 @@ def get_player_resources(name: str):
4560
else:
4661
return players[name]["resources"]
4762

48-
def format_resources(name: str, resources: list):
63+
def format_resources(name: str, resources: list): #format resources for printing
4964
global players
5065
counts = Counter(resources)
5166
formatted = " ".join(f"{num}:{num_to_resource(num)} = {counts[num]}," for num in sorted(counts))
5267
return f"{name}: {formatted}"
5368

54-
def add_resource(name: str, resources: list):
69+
def add_resource(name: str, resources: list, dontshow=False): #add resources to player
5570
global players
71+
global nextprint
5672
processed = []
5773
for r in resources:
5874
if r > 6 or r < 1:
59-
raise ValueError("Invalid resource")
75+
print(f"Invalid resource {r}. Skipping.")
6076
elif r == 6:
6177
choice = input(f"Resource '(6) gold' for {name} detected! Enter choice: ")
6278
if not choice or choice == 6:
63-
raise ValueError("Invalid replacement")
79+
print("No valid choice made. Skipping.")
6480
processed.append(int(choice))
6581
else:
6682
processed.append(r)
@@ -69,22 +85,36 @@ def add_resource(name: str, resources: list):
6985
players[name]["resources"] = processed.copy()
7086
else:
7187
players[name]["resources"].extend(processed)
88+
if not dontshow:
89+
nextprint += f"Added {processed} to {name}\n"
7290

73-
def remove_resource(name: str, resource: list):
91+
def remove_resource(name: str, resource: list): #remove resources from player
7492
global players
7593
if name not in players:
76-
raise ValueError(f"Player {name} does not exist.")
94+
print(f"Player {name} does not exist.")
7795
elif "resources" not in players[name]:
78-
raise ValueError(f"Player {name} has no resources.")
96+
print(f"Player {name} has no resources.")
7997
else:
8098
for r in resource:
8199
if r > 0 and r < 7:
82100
players[name]["resources"].remove(r)
83101
else:
84-
raise ValueError("Invalid resource")
102+
print(f"Invalid resource {r}.")
85103

86-
def trade(name1: str, name2: str, resource1: list, resource2: list):
104+
def trade(name1: str, name2: str, resource1: list, resource2: list): #trade resources between players
87105
global players
106+
global nextprint
107+
try:
108+
name1 = int(name1)
109+
except ValueError:
110+
pass
111+
try:
112+
name2 = int(name2)
113+
except ValueError:
114+
pass
115+
if type(name1) == int and type(name2) == int:
116+
name1 = get_player_order(name1)
117+
name2 = get_player_order(name2)
88118
if name1 not in players or name2 not in players:
89119
print("Player does not exist.")
90120
return
@@ -99,13 +129,13 @@ def trade(name1: str, name2: str, resource1: list, resource2: list):
99129
if r not in players[name2]["resources"]:
100130
print(f"{name2} does not have resource {r}. Trade canceled.")
101131
return
102-
add_resource(name1, resource2)
132+
nextprint += f"Traded {resource1} from {name1} to {name2} for {resource2}\n"
133+
add_resource(name1, resource2, dontshow=True)
103134
remove_resource(name2, resource2)
104-
add_resource(name2, resource1)
135+
add_resource(name2, resource1, dontshow=True)
105136
remove_resource(name1, resource1)
106137

107-
108-
def add_source(name: str, number: Literal[2,3,4,5,6,7,8,9,10,11,12], resource: Literal[1,2,3,4,5,6]):
138+
def add_source(name: str, number: Literal[2,3,4,5,6,7,8,9,10,11,12], resource: Literal[1,2,3,4,5,6]): #add resource source to player
109139
global players
110140
if resource > 0 and resource < 7 and number > 1 and number < 13 and name in players:
111141
if "sources" not in players[name]:
@@ -116,7 +146,7 @@ def add_source(name: str, number: Literal[2,3,4,5,6,7,8,9,10,11,12], resource: L
116146

117147
players[name]["sources"][number].append(resource)
118148

119-
def new_roll(p, number):
149+
def new_roll(p, number): #process new roll and add resources to players
120150
global players
121151
global nextprint
122152
number = int(number)
@@ -125,20 +155,21 @@ def new_roll(p, number):
125155
sources = data.get("sources", {})
126156
if number in sources:
127157
resources_to_add = sources[number].copy()
128-
add_resource(name, resources_to_add)
129-
nextprint = nextprint +f"Added {resources_to_add, num_to_resource(resources_to_add) } to {name} for roll {number}\n"
158+
add_resource(name, resources_to_add, dontshow=True)
159+
names_to_add = []
160+
for i in range(len(resources_to_add)):
161+
names_to_add.append(num_to_resource(resources_to_add[i]))
162+
nextprint = nextprint +f"Added {resources_to_add}:{names_to_add} to {name} for roll {number}\n"
130163
else:
131164
pass
132-
def main():
165+
166+
def main(): #main game loop
133167
global players
134168
turn = 1
135169
while True:
136170
nextturn = 0
137171
while nextturn == 0:
138-
if sys.platform.startswith("win"):
139-
os.system("cls") #
140-
else:
141-
os.system("clear")
172+
clear()
142173
print(nextprint)
143174
player = 0
144175

@@ -157,16 +188,23 @@ def main():
157188
2 - Trade
158189
3 - Steal
159190
4 - Split
160-
5 - Add source
161-
6 - Add resources
162-
7 - remove latest source
191+
5 - Play action card
192+
6 - Add source
193+
7 - Add resources
163194
8 - Next turn
164-
9 - Input full data\n""")
195+
9 - Advanced options\n""")
165196

166197
print("Debug (full list of players and data):")
167198
print(players)
168199

169-
choice = int(input("Enter choice (1-8): "))
200+
choice = input("Enter choice (1-9): ").strip()
201+
try:
202+
choice = int(choice)
203+
except ValueError:
204+
print("Invalid choice. Please try again.")
205+
time.sleep(0.75)
206+
continue
207+
170208
if choice == 1: #build
171209
buildingchoice = input("Enter building (VI, CI, CA, ST, SH or 1-5): ")
172210
if buildingchoice == "q":
@@ -183,34 +221,69 @@ def main():
183221
remove_resource(player, [1,4])
184222
else:
185223
remove_resource(player, [buildingchoice])
224+
186225
elif choice == 2: #trade
187226
trade(input("Enter player 1: "), input("Enter player 2: "), get_numbers(input("Enter resources 1 (1:wood 2:stone 3:wheet 4:sheep 5:ore): ")), get_numbers(input("Enter resources 2 (1:wood 2:stone 3:wheet 4:sheep 5:ore): ")))
227+
188228
elif choice == 3: #Steal
189229
victim = input("Enter victim: ")
190230
if victim == "q":
191231
continue
192232
else:
193233
card = input("Enter card (1:wood 2:stone 3:wheet 4:sheep 5:ore): ")
194234
remove_resource(victim, [card])
235+
195236
elif choice == 4: #split
196237
player_a = input("Enter amount of players: ")
197238
if player_a == "q":
198239
continue
199240
else:
200241
for i in range(int(player_a)):
201242
remove_resource(input("Enter player name: "), get_numbers(input("Enter resources (1:wood 2:stone 3:wheet 4:sheep 5:ore): ")))
202-
elif choice == 5: #add source
243+
244+
elif choice == 5: #play action card
245+
card_a = input("Enter card (1:mon,2:inv): ")
246+
if card_a == "q":
247+
continue
248+
elif card_a in ("1", "mon", "mo", "monopoly"):
249+
card_chosen = input("Enter card (1:wood 2:stone 3:wheet 4:sheep 5:ore): ")
250+
total_amount = 0
251+
for name in players:
252+
amount_of_card_chosen = get_amount_of_resources(name,int(card_chosen))
253+
total_amount += amount_of_card_chosen
254+
for i in range(amount_of_card_chosen):
255+
remove_resource(name, [int(card_chosen)])
256+
add_resource(player, [int(card_chosen)] * total_amount)
257+
258+
elif card_a in ("2", "inv", "in", "invention"):
259+
player_name = input("Enter player name: ")
260+
add_resource(player_name, input("Enter resources (1:wood 2:stone 3:wheet 4:sheep 5:ore): "))
261+
add_resource(player_name, input("Enter resources (1:wood 2:stone 3:wheet 4:sheep 5:ore): "))
262+
263+
elif choice == 6: #add source
203264
source_a = input("Enter amount of sources: ")
204265
if source_a == "q":
205266
continue
206267
else:
207268
source_a = int(source_a)
208269
for i in range(source_a):
209-
add_source(player, int(input(f"Enter source ({i+1}/{source_a}) number (2-12): ")), int(input("Enter resource (1:wood 2:stone 3:wheet 4:sheep 5:ore 6:custom): ")))
210-
elif choice == 6: #add resources
270+
source_n = str(input(f"Enter source ({i+1}/{source_a}) number (2-12): "))
271+
if source_n == "q" or source_a == "q":
272+
continue
273+
source_r = str(input("Enter resource (1:wood 2:stone 3:wheet 4:sheep 5:ore 6:custom): "))
274+
if source_r == "q":
275+
continue
276+
else:
277+
source_n = int(source_n)
278+
for i in range(len(source_r)):
279+
if source_r[i] == ",":
280+
pass
281+
else:
282+
add_source(player, source_n, int(source_r[i]))
283+
284+
elif choice == 7: #add resources
211285
add_resource(player, get_numbers(input("Enter resources (1:wood 2:stone 3:wheet 4:sheep 5:ore): ")))
212-
elif choice == 7: #remove latest source
213-
players[player]["sources"].popitem()
286+
214287
elif choice == 8: #next turn
215288
roll = input("Enter roll (2-12): ")
216289
if roll == "q":
@@ -219,29 +292,62 @@ def main():
219292
new_roll(player, roll)
220293
turn += 1
221294
nextturn = 1
295+
222296
elif choice == 9: #input custom data
223-
data = input("Enter full data (The data must me in the correct format):")
224-
if data == "q":
225-
continue
297+
clear()
298+
if turn == 1:
299+
player = get_player_order(1)
300+
print("Starting player:", player)
226301
else:
227-
players = json.loads(data)
302+
player = get_player_order((turn - 1) % len(players) + 1)
303+
print("Current player:", player)
304+
305+
for name in players:
306+
print(format_resources(name, get_player_resources(name)))
307+
print("""\nAdvanced options:
308+
1. Remove resources
309+
2. Remove latest source
310+
3. Import full data (Python dict format)\n""")
311+
choice_a = input("Enter choice (1-3): ").strip()
312+
if choice_a == "q":
313+
continue
314+
elif choice_a == "1":
315+
remove_resource(player, get_numbers(input("Enter resources (1:wood 2:stone 3:wheet 4:sheep 5:ore): ")))
316+
elif choice_a == "2": #remove latest source
317+
if "sources" not in players[player] or len(players[player]["sources"]) == 0:
318+
print("No sources to remove.")
319+
else:
320+
players[player]["sources"].popitem()
321+
elif choice_a == "3":
322+
data = input("Enter full data (The data must me in the correct format):")
323+
if data == "q":
324+
continue
325+
else:
326+
try:
327+
parsed = ast.literal_eval(data)
328+
if not isinstance(parsed, dict):
329+
print("Parsed value is not a dict.")
330+
else:
331+
players = parsed
332+
print("Imported players successfully.")
333+
except Exception as e:
334+
print("Failed to parse input as Python literal:", e)
335+
228336
else:
229-
print("Invalid choice.")
230-
time.sleep(0.5)
337+
print("Invalid choice. Please try again.")
338+
339+
time.sleep(0.75)
231340

232-
def init_game():
341+
def init_game(): #initialize game and players
233342
print("""╔═╗╔═╗╔╦╗╔═╗╔╗╔ ┌┬┐┬─┐┌─┐┌─┐┬┌─┌─┐┬─┐
234343
║ ╠═╣ ║ ╠═╣║║║ │ ├┬┘├─┤│ ├┴┐├┤ ├┬┘
235-
╚═╝╩ ╩ ╩ ╩ ╩╝╚╝ ┴ ┴└─┴ ┴└─┘┴ ┴└─┘┴└─ V2.0
344+
╚═╝╩ ╩ ╩ ╩ ╩╝╚╝ ┴ ┴└─┴ ┴└─┘┴ ┴└─┘┴└─ V3.0
236345
──────────────────────────────────────
237346
A simple irl Settlers of Catan card and player tracker. (With the seafarers gold resource)\n""")
238347
amount_of_players = int(input("Enter the amount of players: "))
239348
for i in range(amount_of_players):
240349
name = input(f"Enter player name ({i+1}/{amount_of_players}): ")
241350
add_player(name)
242351

243-
244-
245-
246352
init_game()
247-
main()
353+
main()

0 commit comments

Comments
 (0)