-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
495 lines (443 loc) · 23.4 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
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
import random
from tabulate import tabulate
class Carta:
def __init__(self, nombre, habilidad):
self.nombre = nombre
self.habilidad = habilidad
def usar_habilidad(self, jugador, jugadores, corte):
return self.habilidad(jugador, jugadores, corte)
def __str__(self):
return self.nombre
class Jugador:
def __init__(self, nombre):
self.nombre = nombre
self.oro = 6 # Cada jugador comienza con 6 monedas de oro
self.cartas = [] # Cartas que tiene el jugador
def esta_vivo(self):
return self.oro > 0
def __str__(self):
return f"{self.nombre} (Oro: {self.oro})"
class Corte:
def __init__(self):
self.total_oro = 0
def depositar(self, cantidad):
self.total_oro += cantidad
def retirar(self):
cantidad = self.total_oro
self.total_oro = 0
return cantidad
class Juego:
def __init__(self):
self.jugadores = []
self.corte = Corte()
self.mazo = self.crear_mazo()
self.cartas_mesa = []
self.turno_actual = 0 # Contador de turnos
self.campesinos_revelados = 0
def crear_mazo(self):
habilidades = [
self.habilidad_juez,
self.habilidad_obispo,
self.habilidad_rey,
self.habilidad_reina,
self.habilidad_bufon,
self.habilidad_ladron,
self.habilidad_bruja,
self.habilidad_espia,
self.habilidad_campesino,
self.habilidad_tramposo,
self.habilidad_inquisidor,
self.habilidad_viuda,
] * 1 + [self.habilidad_campesino] # Dos campesinos
nombres = [
'El Juez', 'El Obispo', 'El Rey', 'La Reina', 'El Bufón',
'El Ladrón', 'La Bruja', 'El Espía', 'El Campesino',
'El Tramposo', 'El Inquisidor', 'La Viuda',
] * 1 + ['El Campesino']
mazo = [Carta(nombre, habilidad) for nombre, habilidad in zip(nombres, habilidades)]
random.shuffle(mazo)
return mazo
def agregar_jugadores(self):
while True:
try:
num_jugadores = int(input("¿Cuántos jugadores? (2 - 13): "))
if not 2 <= num_jugadores <= 13:
print("Número de jugadores no válido. Debe ser entre 2 y 13.")
continue
break
except ValueError:
print("Entrada no válida. Introduce un número.")
for _ in range(num_jugadores):
while True:
nombre = input("Ingrese el nombre del jugador: ").strip()
if not nombre:
print("El nombre no puede estar vacío.")
continue
if any(j.nombre == nombre for j in self.jugadores):
print("Este nombre ya está en uso. Elige otro.")
continue
break
jugador = Jugador(nombre)
self.jugadores.append(jugador)
self.repartir_cartas(num_jugadores)
self.agregar_cartas_mesa(num_jugadores)
def repartir_cartas(self, num_jugadores):
if num_jugadores == 2:
# Partida de 2 jugadores: cada jugador recibe 3 cartas (izquierda, derecha, protegida)
for jugador in self.jugadores:
jugador.cartas = [self.mazo.pop() for _ in range(3)]
print(f"{jugador.nombre} ha recibido 3 cartas: izquierda, derecha y protegida.")
elif num_jugadores == 3:
# Partida de 3 jugadores: cada jugador recibe 2 cartas (izquierda, derecha)
for jugador in self.jugadores:
jugador.cartas = [self.mazo.pop() for _ in range(2)]
print(f"{jugador.nombre} ha recibido 2 cartas: izquierda y derecha.")
else:
# Partida de 4+ jugadores: cada jugador recibe 1 carta
for jugador in self.jugadores:
jugador.cartas = [self.mazo.pop()]
print(f"{jugador.nombre} ha recibido 1 carta.")
def agregar_cartas_mesa(self, num_jugadores):
if num_jugadores >= 4:
num_cartas_a_agregar = random.randint(1, 2)
for _ in range(num_cartas_a_agregar):
if self.mazo:
carta_mesa = self.mazo.pop()
self.cartas_mesa.append(carta_mesa)
print(f"La carta {carta_mesa} ha sido añadida a la mesa.")
def iniciar_juego(self):
while True:
self.turno_actual += 1
self.mostrar_estado_juego()
for jugador in self.jugadores:
if jugador.esta_vivo():
print(f"\nEs el turno de: {jugador}")
self.turno_jugador(jugador)
self.mostrar_estado_juego()
if jugador.oro >= 13:
print(f"¡{jugador.nombre} ha ganado el juego!")
return
if all(not j.esta_vivo() for j in self.jugadores):
ganador = max(self.jugadores, key=lambda j: j.oro)
print(f"¡{ganador.nombre} gana con {ganador.oro} monedas!")
return
def mostrar_estado_juego(self):
print("\n--- Estado del Juego ---")
print("Jugadores:")
tabla_jugadores = [[j.nombre, j.oro, ", ".join(str(c) for c in j.cartas)] for j in self.jugadores]
print(tabulate(tabla_jugadores, headers=["Nombre", "Oro", "Cartas"], tablefmt="grid"))
print("\nCartas en la mesa:", ", ".join(str(c) for c in self.cartas_mesa))
print("Palacio de Justicia:", self.corte.total_oro, "monedas\n")
def turno_jugador(self, jugador):
while True:
if self.turno_actual <= 4: # Primeros cuatro turnos limitados a intercambios
print(f"{jugador.nombre}, en este turno solo puedes realizar intercambios.")
self.intercambiar_cartas(jugador)
else:
accion = input("Seleccione una opción (1.mirar, 2.intercambiar, 3.usar habilidad): ").strip().lower()
if accion in ["1", "mirar"]:
self.ver_carta(jugador)
break
elif accion in ["2", "intercambiar"]:
self.intercambiar_cartas(jugador)
break
elif accion in ["3", "usar habilidad"]:
if len(jugador.cartas) == 3: # Partida de 2 jugadores
print("Selecciona la carta que deseas usar:")
print("1. Carta izquierda")
print("2. Carta derecha")
eleccion = input("Elige una carta (1 o 2): ").strip()
if eleccion not in ["1", "2"]:
print("Selección no válida. Debes elegir entre tus cartas izquierda o derecha.")
continue
self.usar_habilidad(jugador)
else:
self.usar_habilidad(jugador)
break
else:
print("Acción no válida. Por favor, selecciona una opción válida.")
break
@staticmethod
def ver_carta(jugador):
"""Permite al jugador mirar en secreto su carta."""
if jugador.cartas:
print(f"{jugador.nombre}, tu carta es: {jugador.cartas[0]}")
else:
print(f"{jugador.nombre}, no tienes cartas para mirar.")
def intercambiar_cartas(self, jugador):
print("Intercambia cartas con otro jugador o con la mesa.")
for idx, j in enumerate(self.jugadores):
if j != jugador and j.esta_vivo():
print(f"{idx + 1}. {j.nombre} (Cartas: {[str(carta) for carta in j.cartas]})")
print("0. Intercambiar con la mesa")
try:
idx_objetivo = int(input("Seleccione el número del jugador (o 0 para intercambiar con la mesa): ")) - 1
if 0 <= idx_objetivo < len(self.jugadores):
jugador_objetivo = self.jugadores[idx_objetivo]
# Restricción para partidas de 2 jugadores
if len(jugador_objetivo.cartas) == 3 and idx_objetivo != -1:
print("No puedes intercambiar con la carta protegida del oponente.")
else:
# Realizar el intercambio normalmente
carta_jugador = random.choice(jugador.cartas)
carta_objetivo = random.choice(jugador_objetivo.cartas)
print(
f"{jugador.nombre} intercambia {carta_jugador} con {jugador_objetivo.nombre}, recibiendo {carta_objetivo}.")
jugador.cartas.remove(carta_jugador)
jugador_objetivo.cartas.remove(carta_objetivo)
jugador.cartas.append(carta_objetivo)
jugador_objetivo.cartas.append(carta_jugador)
elif idx_objetivo == -1 and self.cartas_mesa:
# Intercambiar con la mesa
print("\nSelecciona una carta de la mesa para intercambiar:")
for idx, carta in enumerate(self.cartas_mesa):
print(f"{idx + 1}. {carta}")
idx_carta_mesa = int(input("Seleccione el número de la carta (0 para cancelar): ")) - 1
if 0 <= idx_carta_mesa < len(self.cartas_mesa):
carta_mesa = self.cartas_mesa[idx_carta_mesa]
carta_jugador = random.choice(jugador.cartas)
print(f"{jugador.nombre} intercambia {carta_jugador} con la carta de la mesa {carta_mesa}.")
jugador.cartas.remove(carta_jugador)
jugador.cartas.append(carta_mesa)
self.cartas_mesa[idx_carta_mesa] = carta_jugador
else:
print("No se realizó ningún intercambio.")
else:
print("Selección no válida.")
except ValueError:
print("Entrada no válida. Por favor, introduce un número.")
except IndexError:
print("Error: No hay cartas disponibles para intercambiar. Intenta de nuevo.")
def usar_habilidad(self, jugador):
if not jugador.cartas and not self.cartas_mesa:
print(f"{jugador.nombre} no tiene cartas para usar habilidades.")
return
cartas_disponibles = [carta for j in self.jugadores for carta in j.cartas] + self.cartas_mesa
print("Habilidades disponibles:")
for idx, carta in enumerate(cartas_disponibles):
print(f"{idx + 1}. {carta}")
try:
eleccion_habilidad = int(input("Seleccione un número para declarar la habilidad que quiere usar: ")) - 1
if 0 <= eleccion_habilidad < len(cartas_disponibles):
carta_seleccionada = cartas_disponibles[eleccion_habilidad]
habilidad_declarada = carta_seleccionada.habilidad
if carta_seleccionada.nombre == "El Campesino":
self.campesinos_revelados += 1
if self.campesinos_revelados >= 2:
print("¡Dos Campesinos han sido revelados!")
for j in self.jugadores:
if any(carta.nombre == "El Campesino" for carta in j.cartas):
j.oro += 2
print(f"{j.nombre} recibe 2 monedas de oro adicionales.")
# Preguntar a otros jugadores si quieren refutar
refutadores = []
for otro_jugador in self.jugadores:
if otro_jugador != jugador and otro_jugador.esta_vivo():
refutar = input(
f"{otro_jugador.nombre}, ¿quieres refutar la habilidad de {carta_seleccionada}? (sí/no): "
).strip().lower()
if refutar in ["si", "sí", "yes", "y"]:
refutadores.append(otro_jugador)
print(f"{otro_jugador.nombre} ha decidido refutar.")
# Verificar si la habilidad declarada es válida
habilidad_en_posesion = any(carta.habilidad == habilidad_declarada for carta in jugador.cartas)
if refutadores:
if habilidad_en_posesion:
print(f"{jugador.nombre} estaba usando la habilidad correcta. Los que refutaron pierden 1 oro.")
for refutador in refutadores:
refutador.oro = max(0, refutador.oro - 1)
print(f"{refutador.nombre} pierde 1 oro. (Oro actual: {refutador.oro})")
carta_seleccionada.usar_habilidad(jugador, self.jugadores, self.corte)
else:
print(
f"{jugador.nombre} intentó usar una habilidad que no está en su poder. Debe pagar 1 oro a la corte."
)
jugador.oro -= 1
self.corte.depositar(1)
else:
print(f"Nadie ha refutado. {jugador.nombre} usa la habilidad {carta_seleccionada}.")
carta_seleccionada.usar_habilidad(jugador, self.jugadores, self.corte)
else:
print("Selección no válida.")
except (ValueError, IndexError):
print("Entrada no válida o error al usar habilidad. Intenta de nuevo.")
# Métodos estáticos para habilidades
@staticmethod
def habilidad_juez(jugador, jugadores, corte):
cantidad = corte.retirar()
jugador.oro += cantidad
print(f"{jugador.nombre} recibe {cantidad} monedas de oro del Palacio de Justicia.")
@staticmethod
def habilidad_obispo(jugador, jugadores, corte):
jugador_mas_rico = max(jugadores, key=lambda j: j.oro)
cantidad = 2
print(f"{jugador.nombre} toma {cantidad} monedas de {jugador_mas_rico.nombre}.")
jugador_mas_rico.oro -= cantidad
jugador.oro += cantidad
@staticmethod
def habilidad_rey(jugador, jugadores, corte):
jugador.oro += 3
print(f"{jugador.nombre} recibe 3 monedas del banco.")
@staticmethod
def habilidad_reina(jugador, jugadores, corte):
jugador.oro += 2
print(f"{jugador.nombre} recibe 2 monedas del banco.")
@staticmethod
def habilidad_ladron(jugador, jugadores, corte):
jugadores_adyacentes = [j for j in jugadores if j != jugador and j.esta_vivo()]
if len(jugadores_adyacentes) >= 2:
objetivo1, objetivo2 = random.sample(jugadores_adyacentes, 2)
print(f"{jugador.nombre} roba 1 moneda de {objetivo1.nombre} y de {objetivo2.nombre}.")
objetivo1.oro -= 1
objetivo2.oro -= 1
jugador.oro += 2
@staticmethod
def habilidad_bufon(jugador, jugadores):
print(f"{jugador.nombre} usa la habilidad del Bufón.")
jugador.oro += 1
print(f"{jugador.nombre} recibe 1 moneda de oro.")
# Pregunta si el jugador desea intercambiar las cartas de otros dos jugadores
intercambiar = input("¿Deseas intercambiar las cartas de dos jugadores? (sí/no): ").strip().lower()
if intercambiar in ["si", "sí", "yes", "y"]:
print("Selecciona dos jugadores diferentes para intercambiar sus cartas:")
# Lista de jugadores vivos (excluyendo al jugador actual)
jugadores_vivos = [j for j in jugadores if j != jugador and j.esta_vivo()]
if len(jugadores_vivos) < 2:
print("No hay suficientes jugadores vivos para realizar el intercambio.")
return
# Mostrar opciones de jugadores
for idx, j in enumerate(jugadores_vivos):
print(f"{idx + 1}. {j.nombre}")
try:
# Pedir al jugador que seleccione el primer jugador
idx_jugador1 = int(input("Selecciona el número del primer jugador: ")) - 1
if 0 <= idx_jugador1 < len(jugadores_vivos):
jugador1 = jugadores_vivos[idx_jugador1]
else:
print("Selección no válida. No se realizará ningún intercambio.")
return
# Pedir al jugador que seleccione el segundo jugador
idx_jugador2 = int(input("Selecciona el número del segundo jugador: ")) - 1
if 0 <= idx_jugador2 < len(jugadores_vivos) and idx_jugador2 != idx_jugador1:
jugador2 = jugadores_vivos[idx_jugador2]
else:
print("Selección no válida o duplicada. No se realizará ningún intercambio.")
return
# Intercambiar las cartas de los dos jugadores seleccionados
jugador1.cartas, jugador2.cartas = jugador2.cartas, jugador1.cartas
print(f"Se han intercambiado las cartas de {jugador1.nombre} y {jugador2.nombre}.")
except ValueError:
print("Entrada no válida. Intenta de nuevo.")
else:
print("No se intercambiaron cartas.")
@staticmethod
def habilidad_bruja(jugador, jugadores, corte):
print(f"{jugador.nombre} usa la habilidad de la Bruja.")
print("Selecciona un jugador para intercambiar fortunas:")
for idx, j in enumerate(jugadores):
if j != jugador and j.esta_vivo():
print(f"{idx + 1}. {j.nombre} (Oro: {j.oro})")
idx_objetivo = int(input("Selecciona el número del jugador: ")) - 1
if 0 <= idx_objetivo < len(jugadores) and jugadores[idx_objetivo] != jugador and jugadores[
idx_objetivo].esta_vivo():
jugador_objetivo = jugadores[idx_objetivo]
jugador.oro, jugador_objetivo.oro = jugador_objetivo.oro, jugador.oro
print(f"{jugador.nombre} y {jugador_objetivo.nombre} han intercambiado sus fortunas.")
print(f"{jugador.nombre} ahora tiene {jugador.oro} monedas de oro.")
print(f"{jugador_objetivo.nombre} ahora tiene {jugador_objetivo.oro} monedas de oro.")
else:
print("Selección no válida. No se realizará ningún intercambio.")
@staticmethod
def habilidad_espia(jugador, jugadores, corte):
print(f"{jugador.nombre} usa la habilidad del Espía.")
print(f"Tu carta: {jugador.cartas[0]}")
print("Selecciona un jugador para ver su carta:")
for idx, j in enumerate(jugadores):
if j != jugador and j.esta_vivo():
print(f"{idx + 1}. {j.nombre}")
idx_objetivo = int(input("Selecciona el número del jugador: ")) - 1
if 0 <= idx_objetivo < len(jugadores) and jugadores[idx_objetivo] != jugador and jugadores[
idx_objetivo].esta_vivo():
jugador_objetivo = jugadores[idx_objetivo]
carta_objetivo = jugador_objetivo.cartas[0]
print(f"La carta de {jugador_objetivo.nombre} es: {carta_objetivo}")
intercambiar = input("¿Deseas intercambiar las cartas? (sí/no): ").strip().lower()
if intercambiar in ["si", "sí", "yes", "y"]:
jugador.cartas[0], jugador_objetivo.cartas[0] = jugador_objetivo.cartas[0], jugador.cartas[0]
print(f"Se han intercambiado las cartas de {jugador.nombre} y {jugador_objetivo.nombre}.")
else:
print("No se realizará ninguna acción.")
else:
print("Selección no válida. No se realizará ninguna acción.")
@staticmethod
def habilidad_inquisidor(jugador, jugadores, corte):
print(f"{jugador.nombre} usa la habilidad del Inquisidor.")
print("Selecciona un jugador para interrogarlo:")
for idx, j in enumerate(jugadores):
if j != jugador and j.esta_vivo():
print(f"{idx + 1}. {j.nombre}")
idx_objetivo = int(input("Selecciona el número del jugador: ")) - 1
if 0 <= idx_objetivo < len(jugadores) and jugadores[idx_objetivo] != jugador and jugadores[
idx_objetivo].esta_vivo():
jugador_objetivo = jugadores[idx_objetivo]
print(f"{jugador_objetivo.nombre}, adivina el personaje de tu carta.")
print("Opciones disponibles:")
opciones = [
"El Juez", "El Obispo", "El Rey", "La Reina", "El Bufón",
"El Ladrón", "La Bruja", "El Espía", "El Campesino",
"El Tramposo", "El Inquisidor", "La Viuda"
]
for i, opcion in enumerate(opciones, start=1):
print(f"{i}. {opcion}")
eleccion = int(input("Selecciona el número del personaje que crees que eres: ")) - 1
if 0 <= eleccion < len(opciones):
guess = opciones[eleccion]
print(f"{jugador_objetivo.nombre} cree que es {guess}.")
if any(carta.nombre == guess for carta in jugador_objetivo.cartas):
print(f"¡Correcto! {jugador_objetivo.nombre} ha adivinado correctamente su personaje.")
else:
print(f"Incorrecto. {jugador_objetivo.nombre} debe pagar 4 monedas de oro a {jugador.nombre}.")
cantidad = 4
if jugador_objetivo.oro >= cantidad:
jugador_objetivo.oro -= cantidad
jugador.oro += cantidad
print(f"{jugador_objetivo.nombre} paga {cantidad} monedas a {jugador.nombre}.")
else:
print(f"{jugador_objetivo.nombre} no tiene suficiente oro para pagar.")
else:
print("Selección no válida. No se realizará ninguna acción.")
else:
print("Selección no válida. No se realizará ninguna acción.")
@staticmethod
def habilidad_campesino(jugador, jugadores, corte):
print(f"{jugador.nombre} usa la habilidad del Campesino.")
jugador.oro += 1
print(f"{jugador.nombre} recibe 1 moneda de oro.")
cartas_reveladas = [carta for j in jugadores for carta in j.cartas] + juego.cartas_mesa
campesinos_revelados = [carta for carta in cartas_reveladas if carta.nombre == "El Campesino"]
if len(campesinos_revelados) >= 2:
print("¡Dos Campesinos han sido revelados!")
for j in jugadores:
if any(carta.nombre == "El Campesino" for carta in j.cartas):
j.oro += 2
print(f"{j.nombre} recibe 2 monedas de oro adicionales.")
@staticmethod
def habilidad_tramposo(jugador, jugadores, corte):
if jugador.oro >= 10:
print(f"{jugador.nombre} ha ganado el juego como tramposo!")
return True
else:
print(f"{jugador.nombre} no puede ganar aún.")
return False
@staticmethod
def habilidad_viuda(jugador, jugadores, corte):
a_pagar = 10 - jugador.oro
if a_pagar > 0:
jugador.oro += a_pagar
print(f"{jugador.nombre} recibe {a_pagar} monedas del banco, llevando su fortuna a 10 monedas en total.")
else:
print(f"{jugador.nombre} ya tiene suficiente oro.")
if __name__ == "__main__":
juego = Juego()
juego.agregar_jugadores()
juego.iniciar_juego()