incognitolm commited on
Commit
665603b
·
verified ·
1 Parent(s): 5c0e13e

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +72 -136
app.py CHANGED
@@ -91,11 +91,9 @@ async def handle_action(request: Request):
91
 
92
  game = games[pin]
93
 
94
- # Return pending challenge status.
95
  if action == 'getStatus':
96
  return {"success": True, "challenge": game.get("challenge", None)}
97
 
98
- # STEAL action (existing)
99
  if action == 'steal':
100
  if game["permissions"].get(player, {}).get("steal", True):
101
  game["challenge"] = {
@@ -110,7 +108,6 @@ async def handle_action(request: Request):
110
  else:
111
  return {"success": False, "message": "You can only steal once per turn."}
112
 
113
- # COUP action (existing)
114
  if action == 'coup':
115
  player_data = next((p for p in game["players"] if p["name"] == player), None)
116
  if not player_data:
@@ -127,10 +124,11 @@ async def handle_action(request: Request):
127
  }
128
  return {"success": True, "message": f"Coup initiated by {player} targeting {target}."}
129
 
130
- # ASSASSIN action and Contessa flow (existing from previous update)
131
  if action == 'assassin':
 
132
  if game["turn"] != player:
133
  return {"success": False, "message": "Not your turn."}
 
134
  game["challenge"] = {
135
  "action": "assassin",
136
  "challenger": player, # the assassin
@@ -141,45 +139,11 @@ async def handle_action(request: Request):
141
  }
142
  return {"success": True, "message": f"Assassin action initiated by {player} targeting {target}. Awaiting target's response."}
143
 
144
- # DUKE TAX action (new)
145
- if action == 'duke':
146
- if game["turn"] != player:
147
- return {"success": False, "message": "Not your turn."}
148
- # Claiming Duke for Tax: create a challenge for all opponents.
149
- game["challenge"] = {
150
- "action": "duke",
151
- "challenger": player, # the one claiming Duke Tax
152
- "challengeType": "duke",
153
- "status": "pending",
154
- "responses": {}
155
- }
156
- # Mark that the player cannot perform any further gain actions this turn.
157
- game["permissions"][player]["gain"] = False
158
- return {"success": True, "message": f"{player} claims Duke for Tax. Waiting for opponents to respond."}
159
-
160
- # Foreign Aid action (modified to store initiator)
161
- if action == 'foreignAid':
162
- if game["turn"] != player:
163
- return {"success": False, "message": "Not your turn."}
164
- if not game["permissions"].get(player, {}).get("gain", True):
165
- return {"success": False, "message": "You can only earn money once per turn."}
166
- game["challenge"] = {
167
- "action": "foreignAid",
168
- "challenger": player,
169
- "initiator": player, # store who initiated foreign aid
170
- "challengeType": "foreignAid",
171
- "responses": {},
172
- "status": "pending"
173
- }
174
- game["permissions"][player]["gain"] = False
175
- return {"success": True, "message": f"Foreign Aid initiated by {player}. Waiting for opponents to respond."}
176
-
177
- # CHALLENGE RESPONSE branch.
178
  if action == 'challengeResponse':
179
  if not game.get("challenge"):
180
  return {"success": False, "message": "No challenge pending."}
181
 
182
- # STEAL challenge response (existing)
183
  if game["challenge"]["challengeType"] == "steal":
184
  challenger_player = next(p for p in game["players"] if p["name"] == game["challenge"]["challenger"])
185
  target_player = next(p for p in game["players"] if p["name"] == game["challenge"]["target"])
@@ -202,151 +166,123 @@ async def handle_action(request: Request):
202
  game["challenge"]["status"] = 'choose'
203
  return {"success": True, "message": f"Challenge successful. {challenger_player['name']} must choose a card to lose.", "challenge": game["challenge"]}
204
 
205
- # DUKE Tax challenge response (new)
206
- elif game["challenge"]["challengeType"] == "duke":
207
- if response == "allow":
208
  if "responses" not in game["challenge"]:
209
  game["challenge"]["responses"] = {}
210
- game["challenge"]["responses"][player] = "allow"
211
  total_opponents = len(game["players"]) - 1
212
  if len(game["challenge"]["responses"]) == total_opponents:
213
- duke_player = next(p for p in game["players"] if p["name"] == game["challenge"]["challenger"])
214
- duke_player["coins"] += 3
215
  game["challenge"] = None
216
- return {"success": True, "message": f"{duke_player['name']} successfully collects 3 coins with Duke Tax."}
217
- else:
218
- return {"success": True, "message": f"{player} allowed the Duke tax. Awaiting other responses."}
219
- elif response == "challenge":
220
- duke_player = next(p for p in game["players"] if p["name"] == game["challenge"]["challenger"])
221
- if "Duke" in duke_player["cards"]:
222
- game["challenge"]["status"] = "choose"
223
- game["challenge"]["challenger"] = player # challenger loses a card
224
- game["challenge"]["target"] = duke_player["name"]
225
- return {"success": True, "message": f"Challenge failed. {player} must choose a card to lose.", "challenge": game["challenge"]}
226
  else:
 
 
 
 
227
  game["challenge"]["status"] = "choose"
228
- game["challenge"]["challenger"] = duke_player["name"]
229
- return {"success": True, "message": f"Challenge successful. {duke_player['name']} must choose a card to lose.", "challenge": game["challenge"]}
230
-
231
- # FOREIGN AID response branch.
232
- elif game["challenge"]["challengeType"] == "foreignAid":
233
- if player == game["challenge"]["challenger"]:
234
- return {"success": False, "message": "Challenger cannot respond to their own action."}
235
- if response == "block":
236
- # Instead of immediately canceling, create a new challenge for a Duke block.
237
- # The blocking player is claiming Duke to block foreign aid.
238
- game["challenge"] = {
239
- "action": "foreignAidBlock",
240
- "challengeType": "dukeBlock",
241
- "blocker": player,
242
- "initiator": game["challenge"]["initiator"],
243
- "status": "pending"
244
- }
245
- return {"success": True, "message": f"{player} blocks Foreign Aid claiming Duke. {game['challenge']['initiator']} may now challenge this block."}
246
- else: # response == "allow"
247
- if "responses" not in game["challenge"]:
248
- game["challenge"]["responses"] = {}
249
- game["challenge"]["responses"][player] = "allow"
250
- total_opponents = len(game["players"]) - 1
251
- if len(game["challenge"]["responses"]) == total_opponents:
252
- fa_player = next(p for p in game["players"] if p["name"] == game["challenge"]["challenger"])
253
- fa_player["coins"] += 2
254
  game["challenge"] = None
255
- return {"success": True, "message": f"Foreign Aid accepted. {fa_player['name']} gains 2 coins."}
256
- else:
257
- return {"success": True, "message": f"{player} allowed Foreign Aid. Awaiting other responses."}
258
-
259
- # DUKE BLOCK challenge response (new, from a foreign aid block)
260
- elif game["challenge"]["challengeType"] == "dukeBlock":
261
- # Only the Foreign Aid initiator may respond.
262
- if player != game["challenge"]["initiator"]:
263
- return {"success": False, "message": "Only the Foreign Aid initiator can respond to the Duke block challenge."}
264
- if response == "challenge":
265
- blocker = next(p for p in game["players"] if p["name"] == game["challenge"]["blocker"])
266
- if "Duke" in blocker["cards"]:
267
- game["challenge"]["status"] = "choose"
268
- game["challenge"]["challenger"] = player
269
- return {"success": True, "message": f"Block challenge failed. {player} must choose a card to lose.", "challenge": game["challenge"]}
270
  else:
271
  game["challenge"]["status"] = "choose"
272
- game["challenge"]["challenger"] = blocker["name"]
273
- return {"success": True, "message": f"Block challenge successful. {blocker['name']} must choose a card to lose.", "challenge": game["challenge"]}
274
- elif response == "accept":
275
- game["challenge"] = None
276
- return {"success": True, "message": "Foreign Aid blocked."}
277
 
278
- # ASSASSIN/CONTESSA response branch (existing)
279
  elif game["challenge"]["challengeType"] == "assassin":
 
280
  if game["challenge"].get("phase") == "target_decision":
281
  if response == "allow":
 
282
  game["challenge"]["status"] = "choose"
 
283
  game["challenge"]["challenger"] = game["challenge"]["target"]
284
  return {"success": True, "message": f"{game['challenge']['target']} must now choose a card to lose."}
285
  elif response == "challenge":
 
286
  assassin_player = next(p for p in game["players"] if p["name"] == game["challenge"]["challenger"])
287
  if "Assassin" in assassin_player["cards"]:
 
288
  target_player = next(p for p in game["players"] if p["name"] == game["challenge"]["target"])
289
- target_player["cards"] = [] # target loses both cards
290
  game["challenge"] = None
291
  return {"success": True, "message": f"Challenge failed. {target_player['name']} loses both cards."}
292
  else:
 
293
  game["challenge"]["status"] = "choose"
294
  game["challenge"]["challenger"] = assassin_player["name"]
295
  return {"success": True, "message": f"Challenge successful. {assassin_player['name']} must choose a card to lose.", "challenge": game["challenge"]}
296
  elif response == "contessa":
 
297
  game["challenge"]["phase"] = "assassin_contessa"
298
  return {"success": True, "message": f"{game['challenge']['challenger']} must now choose to challenge or accept the Contessa."}
 
299
  elif game["challenge"].get("phase") == "assassin_contessa":
300
  if response == "accept":
 
301
  game["challenge"]["status"] = "choose"
302
  game["challenge"]["challenger"] = game["challenge"]["target"]
303
  return {"success": True, "message": f"{game['challenge']['target']} must now choose a card to lose."}
304
  elif response == "challenge":
 
305
  target_player = next(p for p in game["players"] if p["name"] == game["challenge"]["target"])
306
  if "Contessa" in target_player["cards"]:
 
307
  game["challenge"]["status"] = "choose"
 
308
  game["challenge"]["challenger"] = game["challenge"]["challenger"]
309
  return {"success": True, "message": f"Contessa challenge successful. {game['challenge']['challenger']} must choose a card to lose.", "challenge": game["challenge"]}
310
  else:
 
311
  target_player["cards"] = []
312
  game["challenge"] = None
313
  return {"success": True, "message": f"Contessa challenge failed. {target_player['name']} loses both cards."}
314
- # Ambassador response branch (existing)
315
- elif game["challenge"]["challengeType"] == "ambassador":
316
- if response == 'allow':
317
- if "responses" not in game["challenge"]:
318
- game["challenge"]["responses"] = {}
319
- game["challenge"]["responses"][player] = 'allow'
 
 
 
 
 
320
  total_opponents = len(game["players"]) - 1
321
  if len(game["challenge"]["responses"]) == total_opponents:
322
- ambassador_player = next(p for p in game["players"] if p["name"] == game["challenge"]["challenger"])
323
- ambassador_player["cards"] = generate_cards()
324
  game["challenge"] = None
325
- return {"success": True, "message": f"Ambassador action accepted. {ambassador_player['name']} swaps cards with the deck."}
326
  else:
327
- return {"success": True, "message": f"{player} allowed the Ambassador action. Awaiting other responses."}
328
- elif response == 'challenge':
329
- ambassador_player = next(p for p in game["players"] if p["name"] == game["challenge"]["challenger"])
330
- if "Ambassador" in ambassador_player["cards"]:
331
- game["challenge"]["status"] = "choose"
332
- game["challenge"]["challenger"] = player
333
- game["challenge"]["target"] = ambassador_player["name"]
334
- ambassador_player["cards"] = generate_cards()
335
- game["challenge"] = None
336
- return {"success": True, "message": f"Challenge failed. {player} must lose a card, while {ambassador_player['name']} swaps cards with the deck."}
337
- else:
338
- game["challenge"]["status"] = "choose"
339
- return {"success": True, "message": "Challenge successful. Ambassador user must choose a card to lose.", "challenge": game["challenge"]}
340
- # CHOOSE action to lose a card.
341
- if action == 'choose':
342
- acting_player = next((p for p in game["players"] if p["name"] == game["challenge"]["challenger"]), None)
343
- if acting_player and target in acting_player["cards"]:
344
- acting_player["cards"].remove(target)
345
- game["challenge"] = None
346
- return {"success": True, "message": f"{acting_player['name']} loses the {target} card."}
347
- else:
348
- return {"success": False, "message": f"Card {target} not found in {acting_player['name']}'s hand."}
349
- # INCOME action (existing)
350
  if action == 'income':
351
  player_found = False
352
  for p in game["players"]:
@@ -395,7 +331,7 @@ async def handle_action(request: Request):
395
  else:
396
  return {"success": True, "message": f"{player} allowed Foreign Aid. Awaiting other responses."}
397
 
398
- return {"success": True, "message": f"Action '{action}' received for player {player}."}
399
 
400
  @app.post("/api/joinGame")
401
  async def join_game(request: Request):
 
91
 
92
  game = games[pin]
93
 
 
94
  if action == 'getStatus':
95
  return {"success": True, "challenge": game.get("challenge", None)}
96
 
 
97
  if action == 'steal':
98
  if game["permissions"].get(player, {}).get("steal", True):
99
  game["challenge"] = {
 
108
  else:
109
  return {"success": False, "message": "You can only steal once per turn."}
110
 
 
111
  if action == 'coup':
112
  player_data = next((p for p in game["players"] if p["name"] == player), None)
113
  if not player_data:
 
124
  }
125
  return {"success": True, "message": f"Coup initiated by {player} targeting {target}."}
126
 
 
127
  if action == 'assassin':
128
+ # Assassin action: must be the player's turn.
129
  if game["turn"] != player:
130
  return {"success": False, "message": "Not your turn."}
131
+ # Create an assassin challenge waiting for the target's decision.
132
  game["challenge"] = {
133
  "action": "assassin",
134
  "challenger": player, # the assassin
 
139
  }
140
  return {"success": True, "message": f"Assassin action initiated by {player} targeting {target}. Awaiting target's response."}
141
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  if action == 'challengeResponse':
143
  if not game.get("challenge"):
144
  return {"success": False, "message": "No challenge pending."}
145
 
146
+ # --- Handle existing steal response ---
147
  if game["challenge"]["challengeType"] == "steal":
148
  challenger_player = next(p for p in game["players"] if p["name"] == game["challenge"]["challenger"])
149
  target_player = next(p for p in game["players"] if p["name"] == game["challenge"]["target"])
 
166
  game["challenge"]["status"] = 'choose'
167
  return {"success": True, "message": f"Challenge successful. {challenger_player['name']} must choose a card to lose.", "challenge": game["challenge"]}
168
 
169
+ # --- Handle Ambassador response (existing) ---
170
+ elif game["challenge"]["challengeType"] == "ambassador":
171
+ if response == 'allow':
172
  if "responses" not in game["challenge"]:
173
  game["challenge"]["responses"] = {}
174
+ game["challenge"]["responses"][player] = 'allow'
175
  total_opponents = len(game["players"]) - 1
176
  if len(game["challenge"]["responses"]) == total_opponents:
177
+ ambassador_player = next(p for p in game["players"] if p["name"] == game["challenge"]["challenger"])
178
+ ambassador_player["cards"] = generate_cards()
179
  game["challenge"] = None
180
+ return {"success": True, "message": f"Ambassador action accepted. {ambassador_player['name']} swaps cards with the deck."}
 
 
 
 
 
 
 
 
 
181
  else:
182
+ return {"success": True, "message": f"{player} allowed the Ambassador action. Awaiting other responses."}
183
+ elif response == 'challenge':
184
+ ambassador_player = next(p for p in game["players"] if p["name"] == game["challenge"]["challenger"])
185
+ if "Ambassador" in ambassador_player["cards"]:
186
  game["challenge"]["status"] = "choose"
187
+ game["challenge"]["challenger"] = player # challenger loses card
188
+ game["challenge"]["target"] = ambassador_player["name"]
189
+ ambassador_player["cards"] = generate_cards()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  game["challenge"] = None
191
+ return {"success": True, "message": f"Challenge failed. {player} must lose a card, while {ambassador_player['name']} swaps cards with the deck."}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  else:
193
  game["challenge"]["status"] = "choose"
194
+ return {"success": True, "message": "Challenge successful. Ambassador user must choose a card to lose.", "challenge": game["challenge"]}
 
 
 
 
195
 
196
+ # --- Handle Assassin/Contessa responses ---
197
  elif game["challenge"]["challengeType"] == "assassin":
198
+ # Phase 1: target's decision on assassination
199
  if game["challenge"].get("phase") == "target_decision":
200
  if response == "allow":
201
+ # Target accepts assassination: must lose one card.
202
  game["challenge"]["status"] = "choose"
203
+ # Set the losing player to the target.
204
  game["challenge"]["challenger"] = game["challenge"]["target"]
205
  return {"success": True, "message": f"{game['challenge']['target']} must now choose a card to lose."}
206
  elif response == "challenge":
207
+ # Target challenges the assassin's claim.
208
  assassin_player = next(p for p in game["players"] if p["name"] == game["challenge"]["challenger"])
209
  if "Assassin" in assassin_player["cards"]:
210
+ # Assassin is truthful: target loses both cards.
211
  target_player = next(p for p in game["players"] if p["name"] == game["challenge"]["target"])
212
+ target_player["cards"] = [] # remove all cards (eliminated)
213
  game["challenge"] = None
214
  return {"success": True, "message": f"Challenge failed. {target_player['name']} loses both cards."}
215
  else:
216
+ # Assassin is lying: assassin must lose one card.
217
  game["challenge"]["status"] = "choose"
218
  game["challenge"]["challenger"] = assassin_player["name"]
219
  return {"success": True, "message": f"Challenge successful. {assassin_player['name']} must choose a card to lose.", "challenge": game["challenge"]}
220
  elif response == "contessa":
221
+ # Target opts to block with Contessa. Shift phase.
222
  game["challenge"]["phase"] = "assassin_contessa"
223
  return {"success": True, "message": f"{game['challenge']['challenger']} must now choose to challenge or accept the Contessa."}
224
+ # Phase 2: assassin responding to contessa claim.
225
  elif game["challenge"].get("phase") == "assassin_contessa":
226
  if response == "accept":
227
+ # Assassin accepts contessa block: target loses one card.
228
  game["challenge"]["status"] = "choose"
229
  game["challenge"]["challenger"] = game["challenge"]["target"]
230
  return {"success": True, "message": f"{game['challenge']['target']} must now choose a card to lose."}
231
  elif response == "challenge":
232
+ # Assassin challenges contessa.
233
  target_player = next(p for p in game["players"] if p["name"] == game["challenge"]["target"])
234
  if "Contessa" in target_player["cards"]:
235
+ # Contessa is truthful: assassin loses one card.
236
  game["challenge"]["status"] = "choose"
237
+ # Losing player is the assassin.
238
  game["challenge"]["challenger"] = game["challenge"]["challenger"]
239
  return {"success": True, "message": f"Contessa challenge successful. {game['challenge']['challenger']} must choose a card to lose.", "challenge": game["challenge"]}
240
  else:
241
+ # Contessa is bluffing: target loses both cards.
242
  target_player["cards"] = []
243
  game["challenge"] = None
244
  return {"success": True, "message": f"Contessa challenge failed. {target_player['name']} loses both cards."}
245
+
246
+ # --- Handle Foreign Aid responses ---
247
+ elif game["challenge"]["challengeType"] == "foreignAid":
248
+ if player == game["challenge"]["challenger"]:
249
+ return {"success": False, "message": "Challenger cannot respond to their own action."}
250
+ game["challenge"]["responses"][player] = response
251
+ if response == "block":
252
+ game["challenge"]["status"] = "blocked"
253
+ game["challenge"] = None
254
+ return {"success": True, "message": f"Foreign Aid blocked by {player}."}
255
+ else:
256
  total_opponents = len(game["players"]) - 1
257
  if len(game["challenge"]["responses"]) == total_opponents:
258
+ challenger_player = next(p for p in game["players"] if p["name"] == game["challenge"]["challenger"])
259
+ challenger_player["coins"] += 2
260
  game["challenge"] = None
261
+ return {"success": True, "message": f"Foreign Aid accepted. {challenger_player['name']} gains 2 coins."}
262
  else:
263
+ return {"success": True, "message": f"{player} allowed Foreign Aid. Awaiting other responses."}
264
+
265
+ if action == 'ambassador':
266
+ if game["turn"] != player:
267
+ return {"success": False, "message": "Not your turn."}
268
+ game["challenge"] = {
269
+ "action": "ambassador",
270
+ "challenger": player,
271
+ "challengeType": "ambassador",
272
+ "status": "pending",
273
+ "responses": {}
274
+ }
275
+ return {"success": True, "message": f"Ambassador action initiated by {player}. Waiting for opponents to respond."}
276
+
277
+ if action == 'choose':
278
+ acting_player = next((p for p in game["players"] if p["name"] == game["challenge"]["challenger"]), None)
279
+ if acting_player and target in acting_player["cards"]:
280
+ acting_player["cards"].remove(target)
281
+ game["challenge"] = None
282
+ return {"success": True, "message": f"{acting_player['name']} loses the {target} card."}
283
+ else:
284
+ return {"success": False, "message": f"Card {target} not found in {acting_player['name']}'s hand."}
285
+
286
  if action == 'income':
287
  player_found = False
288
  for p in game["players"]:
 
331
  else:
332
  return {"success": True, "message": f"{player} allowed Foreign Aid. Awaiting other responses."}
333
 
334
+ return {"success": True, "message": f"Action '{action}' processed for player {player}."}
335
 
336
  @app.post("/api/joinGame")
337
  async def join_game(request: Request):