-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathChinchon.hs
486 lines (402 loc) · 24.1 KB
/
Chinchon.hs
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
module Chinchon where
import Data.List (sort, permutations, tails, (\\), sortBy, union)
import Data.Ord (comparing)
import System.Random
import Data.Array.ST
import Control.Monad
import Control.Monad.ST
import Data.STRef
--Creacion mazo de 48 cartas con simbolos de poker pero sin los 4 literales (A, J , Q, K)
--Se ordenan de menor a mayor rango de la siguiente forma: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 y 12
data Palo = Treboles | Diamantes | Corazones | Picas deriving (Eq, Ord, Enum)
data Valor = Uno | Dos | Tres | Cuatro | Cinco | Seis | Siete | Ocho | Nueve | Diez | Once | Doce deriving (Show, Eq, Ord, Enum)
obtenerValorNumerico :: Carta -> Int
obtenerValorNumerico (Carta Uno _) = 1
obtenerValorNumerico (Carta Dos _) = 2
obtenerValorNumerico (Carta Tres _) = 3
obtenerValorNumerico (Carta Cuatro _) = 4
obtenerValorNumerico (Carta Cinco _) = 5
obtenerValorNumerico (Carta Seis _) = 6
obtenerValorNumerico (Carta Siete _) = 7
obtenerValorNumerico (Carta Ocho _) = 8
obtenerValorNumerico (Carta Nueve _) = 9
obtenerValorNumerico (Carta Diez _) = 10
obtenerValorNumerico (Carta Once _) = 11
obtenerValorNumerico (Carta Doce _) = 12
data Carta = Carta {valor :: Valor, palo :: Palo} deriving (Eq)
type Mazo = [Carta]
type Mano = [Carta]
type Seguras = [Carta]
type SemiSeguras = [Carta]
type Repartir = Mazo -> (Carta, Mazo)
data Jugador = Jugador { nombre :: String, mano :: Mano, seguras :: Seguras, semiSeguras ::SemiSeguras, puntos :: Int} deriving (Show)
type EstadoDeJuego = (Jugador, Jugador, Mazo, Mazo)
type Descartar = Mano -> Int -> Mazo -> (Mano, Mazo)
data CombinacionPuntaje = CombinacionPuntaje {combinacion :: [Carta], suma :: Int}
--Se asignan simbolo ASCII a cada palo
instance Show Palo where
show Picas = "♠"
show Corazones = "♥"
show Diamantes = "♦"
show Treboles = "♣"
--Se asignan numeros, literales y signos a cada carta depende su valor
instance Show Carta where
show (Carta Uno palo) = "1" ++ show palo
show (Carta Dos palo) = "2" ++ show palo
show (Carta Tres palo) = "3" ++ show palo
show (Carta Cuatro palo) = "4" ++ show palo
show (Carta Cinco palo) = "5" ++ show palo
show (Carta Seis palo) = "6" ++ show palo
show (Carta Siete palo) = "7" ++ show palo
show (Carta Ocho palo) = "8" ++ show palo
show (Carta Nueve palo) = "9" ++ show palo
show (Carta Diez palo) = "10" ++ show palo
show (Carta Once palo) = "11" ++ show palo
show (Carta Doce palo) = "12" ++ show palo
nuevoMazo :: Mazo
nuevoMazo = [Carta n p | p <- [Treboles .. ], n <- [Uno .. ]]
nuevoJugador :: String -> Jugador
nuevoJugador nombre = Jugador nombre [] [] [] 0
-- Repartir cartas
repartir :: Repartir
repartir [] = error "Mazo Vacio"
repartir (x:xs) = (x, xs)
repartirCartaAJugador :: Mazo -> Jugador -> (Mazo, Jugador)
repartirCartaAJugador [] _ = error "Mazo Vacio"
repartirCartaAJugador m (Jugador nombre mano s ss puntos) = let (carta, m') = repartir m
in (m', Jugador nombre (carta:mano) s ss puntos)
repartirNCartasAJugador :: Int -> Mazo -> Jugador -> (Mazo, Jugador)
repartirNCartasAJugador n m j
| n > length m = error "No hay cartas suficientes"
| n < 1 = error "Debes repartir por lo menos 1 carta"
| n == 1 = repartirCartaAJugador m j
| otherwise = repartirNCartasAJugador (n - 1) m' j'
where (m', j') = repartirCartaAJugador m j
-- | Randomly shuffle a list without the IO Monad
-- /O(N)/
shuffle' :: [a] -> StdGen -> ([a],StdGen)
shuffle' xs gen = runST (do
g <- newSTRef gen
let randomRST lohi = do
(a,s') <- liftM (randomR lohi) (readSTRef g)
writeSTRef g s'
return a
ar <- newArray n xs
xs' <- forM [1..n] $ \i -> do
j <- randomRST (i,n)
vi <- readArray ar i
vj <- readArray ar j
writeArray ar j vi
return vj
gen' <- readSTRef g
return (xs',gen'))
where
n = length xs
newArray :: Int -> [a] -> ST s (STArray s Int a)
newArray n xs = newListArray (1,n) xs
shuffleIO :: [a] -> IO [a]
shuffleIO xs = getStdRandom (shuffle' xs)
-- Agarra la carta del mazo (para jugador)
tomarCartaDesconocida :: EstadoDeJuego -> EstadoDeJuego
tomarCartaDesconocida (jugador, computadora, mazo, pilaDescartadas) = (jugador', computadora, mazo', pilaDescartadas)
where (mazo', jugador') = repartirCartaAJugador mazo jugador
-- Agarra la carta del mazo (para computadora)
cartaDesconocida :: [Carta] -> Carta
cartaDesconocida [] = error "Mazo Vacio"
cartaDesconocida mazoCartas = head mazoCartas
-- Agarra la carta dada vuelta (para jugador)
tomarUltimaCartaDescartada :: EstadoDeJuego -> EstadoDeJuego
tomarUltimaCartaDescartada (jugador, computadora, mazo, pilaDescartadas) = (jugador', computadora, mazo, pilaDescartadas')
where (pilaDescartadas', jugador') = repartirCartaAJugador pilaDescartadas jugador
-- Agarra la carta dada vuelta (para computadora)
ultimaCartaDescartada :: [Carta] -> Carta
ultimaCartaDescartada pilaDescartadas = head pilaDescartadas
-- Muestra el valor de la ultima carta descartada
mostrarUltimaCartaDescartada :: EstadoDeJuego -> String
mostrarUltimaCartaDescartada (_, _, _, pilaDescartadas) = show $ head pilaDescartadas
-- Muestra la mano del jugador
mostrarMano :: EstadoDeJuego -> String
mostrarMano ((Jugador _ mano _ _ _), _, _, _) = show mano
-- Descarta la carta seleccionada por el jugador
descartar :: Descartar
descartar mano n mazo = let c = mano !! (n - 1) in (mano \\ [c], c:mazo)
-- Genera las combinaciones de n cartas con las cartas dadas
combinaciones :: Int -> [a] -> [[a]]
combinaciones 0 _ = [[]]
combinaciones n xs = [ y:ys | y:xs' <- tails xs, ys <- combinaciones (n-1) xs']
-- Controla que las combinaciones sean correctas respecto a las reglas
esBuena :: [Carta] -> Bool
esBuena cartas = cartasEnSecuencia cartas || cartasEnGrupo cartas
-- Controla si el jugador tiene la posibilidad de cortar
puedeGanar :: Jugador -> Bool
puedeGanar (Jugador _ mano _ _ _) = puedeGanarMenosDiez mano || puedeGanarSobraUna mano
-- Controla si la mano da la posibilidad de cortar (sin necesidad de enviar Jugador)
noPuedeCortar :: [Carta] -> Bool
noPuedeCortar mano = not (puedeGanar (Jugador "" mano [] [] 0))
-- Controla si la computadora puede ganar
puedeGanarComputadora :: Jugador -> Bool
puedeGanarComputadora (Jugador _ mano _ _ _) = puedeGanarMenosDiez mano || puedeGanarSobraUnaComputadora mano
-- Controla si tiene las combinaciones necesarias para ganar con menos diez
puedeGanarMenosDiez :: [Carta] -> Bool
puedeGanarMenosDiez mano = do
let buenasCombinaciones mano' = [ (cuatro, tres) | cuatro <- combinaciones 4 mano', let tres = mano' \\ cuatro, esBuena cuatro, esBuena tres]
let existeSolucion = \m -> (length $ buenasCombinaciones m) >= 1
any existeSolucion [mano]
puedeGanarSobraUna :: [Carta] -> Bool
puedeGanarSobraUna mano = do
let buenasCombinaciones mano' = [ (tres, tres'') | tres <- combinaciones 3 mano',let tres' = mano' \\ tres, tres'' <- combinaciones 3 tres', esBuena tres, esBuena tres'']
let existeSolucion = \m -> (length $ buenasCombinaciones m) >= 1
any existeSolucion [mano]
puedeGanarSobraUnaComputadora :: [Carta] -> Bool
puedeGanarSobraUnaComputadora mano = do
let buenasCombinaciones mano' = [ (tres, tres'') | tres <- combinaciones 3 mano',let tres' = mano' \\ tres, tres'' <- combinaciones 3 tres', esBuena tres, esBuena tres'']
let restos mano' = concat [ (mano'\\tres)\\tres'' | tres <- combinaciones 3 mano',let tres' = mano' \\ tres, tres'' <- combinaciones 3 tres', esBuena tres, esBuena tres'']
let restoMasBajo = head (ordenarCartasNumero (restos mano))
let existeSolucion = \m -> ((length $ buenasCombinaciones m) >= 1 && (valor restoMasBajo) <= Dos )
any existeSolucion [mano]
-- Obtener por las cartas de una palo determinado
obtenerPorPalo :: Palo -> [Carta] -> [Carta]
obtenerPorPalo paloParam cartas = filter (\carta -> palo carta == paloParam) cartas
-- supone que mandas la cantidad N de cartas en el array y que estan ordenadas de menor a mayor
tieneNSuc :: [Carta] -> Int -> Bool
tieneNSuc [] _ = False
tieneNSuc _ 0 = False
tieneNSuc (x:xs) 1 = True
tieneNSuc (x:xs) _ | valor x == Doce = False
tieneNSuc cartas n | n > length cartas = False
tieneNSuc (x:y:zs) n | (valor y == succ (valor x)) && (palo y == palo x) = tieneNSuc (y:zs) (n-1)
tieneNSuc (x:y:zs) n | valor y == valor x = False
tieneNSuc (x:y:zs) n | valor y > valor x = False
tieneNSuc (x:y:zs) n | (valor y < valor x) && (palo y == palo x) = True
-- supone todas las cartas del mismo Palo
esChinchon :: [Carta] -> Bool
esChinchon cartas = tieneNSuc (ordenarCartasNumero cartas) 7
-- ordernar cartas (supone del mismo Palo)
ordenarCartasNumero :: [Carta] -> [Carta]
ordenarCartasNumero = sortBy (comparing valor)
-- ordenar las cartas por palo
ordenarCartasPalo :: [Carta] -> [Carta]
ordenarCartasPalo = sortBy (comparing palo)
-- ordena todas cartas
ordenarTodasCartas :: [Carta] -> [Carta]
ordenarTodasCartas cartas = ordenarCartasPalo (ordenarCartasNumero cartas)
-- Controla si hay 3 o 4 cartas del mismo valor
cartasEnGrupo :: [Carta] -> Bool
cartasEnGrupo [(Carta n1 _), (Carta n2 _), (Carta n3 _)] = n1 == n2 && n1 == n3
cartasEnGrupo [(Carta n1 _), (Carta n2 _), (Carta n3 _), (Carta n4 _)] = n1 == n2 && n1 == n3 && n1 == n4
cartasEnGrupo _ = False
-- Controla si hay 3 o 4 cartas del mismo palo con valores consecutivos
cartasEnSecuencia :: [Carta] -> Bool
cartasEnSecuencia [(Carta n1 p1), (Carta n2 p2), (Carta n3 p3)] = mismoPalo && enSecuencia
where
mismoPalo = p1 == p2 && p1 == p3
enSecuencia = ordenado !! 0 + 1 == ordenado !! 1 && ordenado !! 1 + 1 == ordenado !! 2
ordenado = map fromEnum $ sort [n1, n2, n3]
cartasEnSecuencia [(Carta n1 p1), (Carta n2 p2), (Carta n3 p3), (Carta n4 p4)] = mismoPalo && enSecuencia
where
mismoPalo = p1 == p2 && p1 == p3 && p1 == p4
enSecuencia = ordenado !! 0 + 1 == ordenado !! 1 && ordenado !! 1 + 1 == ordenado !! 2 && ordenado !! 2 + 1 == ordenado !! 3
ordenado = map fromEnum $ sort [n1, n2, n3,n4]
cartasEnSecuencia _ = False
-- controla si las cartas generan algun conjunto de 2 cartas que puede convertirse en una combinacion para ganar
esSemiSegura :: [Carta] -> Bool
esSemiSegura cartas = esSemiSeguraPalo cartas || esSemiSeguraNumero cartas
-- controla que las cartas sean consecutivas y del mismo palo
esSemiSeguraPalo :: [Carta] -> Bool
esSemiSeguraPalo cartas = do
let cartas' = ordenarCartasNumero cartas
tieneNSuc cartas' 2
-- controla que las cartas sean del mismo valor
esSemiSeguraNumero :: [Carta] -> Bool
esSemiSeguraNumero [(Carta n1 _), (Carta n2 _)] = n1 == n2
-- Saca un item
removeItem _ [] = []
removeItem x (y:ys) | x == y = removeItem x ys
| otherwise = y : removeItem x ys
-- AI de la computadora
jugadaComputadora :: EstadoDeJuego -> EstadoDeJuego
jugadaComputadora estado@(jugador, (Jugador nombre mano seguras ss puntos), mazo, pilaDescartadas) = do
-- VER SI LA DE DESCARTADA SIRVE
let cLevantada = ultimaCartaDescartada pilaDescartadas
let mano' = [cLevantada] ++ mano
let pilaDescartadas' = tail pilaDescartadas
let posibles = [cuatro | cuatro <- combinaciones 4 mano'\\(combinaciones 3 seguras), esBuena cuatro, cLevantada `elem` cuatro]
if length posibles >=1
then do
let combElegida = if length [cartas | cartas <- posibles, cartasEnSecuencia cartas] >= 1 then last [cartas | cartas <- posibles, cartasEnSecuencia cartas] else last posibles
let seguras' = removerDuplicados (seguras ++ combElegida)
let ss' = [carta | carta <- ss, carta `notElem` seguras']
let sobrantes = [carta | carta <- mano', carta `notElem` (seguras' `union` ss')] -- TODAS LAS QUE NO ESTAN EN SEGURAS Y SS
if length sobrantes > 0
then do
descartarSobrante (jugador, (Jugador nombre mano' seguras' ss' puntos), mazo, pilaDescartadas') sobrantes
else do
descartarDeSemiSeguras (jugador, (Jugador nombre mano' seguras' ss' puntos), mazo, pilaDescartadas') cLevantada
else do
let combPosibles = [tres | tres <- combinaciones 3 (mano'\\seguras)\\(combinaciones 2 ss), esBuena tres && cLevantada `elem` tres]
if length combPosibles >=1
then do
-- ES ACA EL PROBLEMA, EL 9D SUPUESTAMENTE LE SIRVE, PERO EN VERDAD NO LE SERVIRIA PORQUE EL 8 YA ESTA USADO
let combElegida = if length [cartas | cartas <- combPosibles, cartasEnSecuencia cartas] >= 1 then last [cartas | cartas <- combPosibles, cartasEnSecuencia cartas] else last combPosibles
let seguras' = seguras ++ combElegida
let ss' = [carta | carta <- ss, carta `notElem` seguras']
let ssComb = [carta | carta <- combinaciones 2 ss', esSemiSegura carta]
let ss'' = removerDuplicados (concat ssComb)
let sobrantes = [carta | carta <- mano', carta `notElem` (seguras' `union` ss'')] -- TODAS LAS QUE NO ESTAN EN SEGURAS Y SS
if length sobrantes > 0
then do
descartarSobrante (jugador, (Jugador nombre mano' seguras' ss'' puntos), mazo, pilaDescartadas') sobrantes
else do
descartarDeSemiSeguras (jugador, (Jugador nombre mano' seguras' ss'' puntos), mazo, pilaDescartadas') cLevantada
else cartaDesconocidaComputadora (estado)
-- descarta una carta de las que no corresponden a ninguna combinacion
descartarSobrante :: EstadoDeJuego -> [Carta]-> EstadoDeJuego
descartarSobrante estado@(jugador, (Jugador nombre mano seguras ss puntos), mazo, pilaDescartadas) sobrantes = do
let cartasOrdenadas = ordenarCartasNumero sobrantes
let descartada = last (cartasOrdenadas) --SACAR UNA (EN LO POSIBLE LA MAS GRANDE)
let mano' = init (cartasOrdenadas) ++ seguras ++ ss -- y poner el resto en mano''
let pilaDescartadas' = [descartada] ++ pilaDescartadas
let computadora' = (Jugador nombre mano' seguras ss puntos)
(jugador, computadora', mazo, pilaDescartadas')
-- si no hay ninguna carta que no corresponda a una combinacion, entonces descarta una de las combinaciones de 2 cartas
descartarDeSemiSeguras :: EstadoDeJuego -> Carta -> EstadoDeJuego
descartarDeSemiSeguras estado@(jugador, (Jugador nombre mano seguras ss puntos), mazo, pilaDescartadas) cLevantada = do
if length ss >= 1 then do
let cartasOrdenadas = ordenarCartasNumero ss
let descartada = last (cartasOrdenadas)
let ssComb = [cartas | cartas <- combinaciones 2 ss, esSemiSegura cartas]
let combEscalera = [cartas | cartas <- ssComb, esSemiSeguraPalo cartas, descartada `elem` cartas]
let combNumeros = [cartas | cartas <- ssComb, esSemiSeguraNumero cartas,descartada `elem` cartas]
let aMover = if length combEscalera >=1 then head combEscalera else head combNumeros
let [aDejar] = [carta | carta <- aMover, not (carta == descartada)]
let ss' = [carta | carta <- cartasOrdenadas, not (carta == descartada), not (carta == aDejar) ]
let pilaDescartadas' = [descartada] ++ pilaDescartadas
let mano' = seguras ++ ss' ++ [aDejar]
let computadora' = (Jugador nombre mano' seguras ss' puntos)
(jugador, computadora', mazo, pilaDescartadas')
else do
let pilaDescartadas' = [cLevantada] ++ pilaDescartadas
let combinacionCLevantada = [comb | comb <- combinaciones 3 seguras, esBuena comb, cLevantada `elem` comb]
let seguras' = seguras \\ (head combinacionCLevantada)
let ss' = ss ++ ((head combinacionCLevantada) \\ [cLevantada])
let mano' = [carta | carta <- mano, not (carta == cLevantada)]
let computadora' = (Jugador nombre mano' seguras' ss' puntos)
(jugador, computadora', mazo, pilaDescartadas')
-- AI de la computadora para cuando la carta dada vuelta no sirve
cartaDesconocidaComputadora :: EstadoDeJuego -> EstadoDeJuego
cartaDesconocidaComputadora estado@(jugador, (Jugador nombre mano seguras ss puntos), mazo, pilaDescartadas) = do
let cLevantada = cartaDesconocida mazo
let mano' = [cLevantada] ++ mano
let mazo' = tail mazo
let posibles = [cuatro | cuatro <- combinaciones 4 mano'\\(combinaciones 3 seguras), esBuena cuatro, cLevantada `elem` cuatro]
if length posibles >=1
then do
let combElegida = if length [cartas | cartas <- posibles, cartasEnSecuencia cartas] >= 1 then last [cartas | cartas <- posibles, cartasEnSecuencia cartas] else last posibles
let seguras' = removerDuplicados (seguras ++ combElegida)
let ss' = [carta | carta <- ss, carta `notElem` seguras']
let sobrantes = (mano' \\ seguras') \\ ss'
if length sobrantes > 0
then do
descartarSobrante (jugador, (Jugador nombre mano' seguras' ss' puntos), mazo', pilaDescartadas) sobrantes
else do
descartarDeSemiSeguras (jugador, (Jugador nombre mano' seguras' ss' puntos), mazo', pilaDescartadas) cLevantada
else do
let combPosibles = [tres | tres <- combinaciones 3 (mano'\\seguras)\\(combinaciones 2 ss), esBuena tres && cLevantada `elem` tres]
if length combPosibles >=1
then do
let combElegida = if length [cartas | cartas <- combPosibles, cartasEnSecuencia cartas] >= 1 then last [cartas | cartas <- combPosibles, cartasEnSecuencia cartas] else last combPosibles
let seguras' = seguras ++ combElegida
let ss' = [carta | carta <- ss, carta `notElem` seguras']
let ssComb = [carta | carta <- combinaciones 2 ss', esSemiSegura carta]
let ss'' = removerDuplicados (concat ssComb)
let sobrantes = [carta | carta <- mano', carta `notElem` (seguras' `union` ss'')] -- TODAS LAS QUE NO ESTAN EN SEGURAS Y SS
if length sobrantes > 0
then do
descartarSobrante (jugador, (Jugador nombre mano' seguras' ss'' puntos), mazo', pilaDescartadas) sobrantes
else do
descartarDeSemiSeguras (jugador, (Jugador nombre mano' seguras' ss'' puntos), mazo', pilaDescartadas) cLevantada
else do
let resto = (mano' \\ seguras) \\ ss
let combinaciones2 = [carta | carta <- combinaciones 2 resto, esSemiSegura carta]
let combPalo = [carta | carta <- combinaciones2, esSemiSeguraPalo carta]
let combNumero = [carta | carta <- combinaciones2, esSemiSeguraNumero carta]
let combElegida = if (length combPalo) >=1 then head combPalo else if length (combNumero) >= 1 then head combNumero else []
let resto' = resto \\ combElegida
let ss' = ss ++ combElegida
if length resto' >= 1
then do
let restoOrdenado = ordenarCartasNumero resto'
let descartada = last restoOrdenado
let pilaDescartadas' = [descartada] ++ pilaDescartadas
let mano'' = [carta | carta <- mano', not (carta == descartada)]
(jugador, (Jugador nombre mano'' seguras ss' puntos), mazo', pilaDescartadas')
else do
let ss' = ss ++ combElegida
descartarDeSemiSeguras (jugador, (Jugador nombre mano' seguras ss' puntos), mazo', pilaDescartadas) cLevantada
-- Arma las combinaciones y pone esas combinaciones en sus respectivos arrays para el AI de la computadora
configurarComputadora :: Jugador -> Jugador
configurarComputadora (Jugador nombre mano seguras ss puntos) = do
let combinaciones4 = [carta | carta <- combinaciones 4 mano, esBuena carta]
let todasCombinaciones4 = removerDuplicados (concat combinaciones4)
let difCombinaciones4 = mano \\ todasCombinaciones4
let sobrantes = if length difCombinaciones4 >= 1 then difCombinaciones4 else mano
let combinaciones3 = [carta | carta <- combinaciones 3 sobrantes, esBuena carta]
let todasCombinaciones3 = removerDuplicados (concat combinaciones3)
let difCombinaciones3 = sobrantes \\ todasCombinaciones3
let sobrantes' = if length difCombinaciones3 >= 1 then difCombinaciones3 else sobrantes
let seguras' = todasCombinaciones4 ++ todasCombinaciones3
let combinaciones2 = [carta | carta <- combinaciones 2 sobrantes', esSemiSegura carta]
let ss' = removerDuplicados (concat combinaciones2)
(Jugador nombre mano seguras' ss' puntos)
-- remueve duplicados dentro de un array
removerDuplicados :: Eq a => [a] -> [a]
removerDuplicados = foldl (\visto x -> if x `elem` visto
then visto
else visto ++ [x]) []
-- muestra la mano de la computadora
mostrarManoCompu :: Jugador -> String
mostrarManoCompu (Jugador _ mano _ _ _) = show mano
-- Devuelve el estado de la computadora
devolverComputadoraEstado :: EstadoDeJuego -> Jugador
devolverComputadoraEstado (_, computadora, _, _) = computadora
-- Calcula los puntos de un juegador al finalizar una ronda
calcularPuntos :: Jugador -> Int
calcularPuntos (Jugador _ mano seguras _ puntos)
-- IF DA MENOS 10 -> 0 porque es el que no corto
| puedeGanarMenosDiez mano = 0
| puedeGanarSobraUna mano = buscarCombinacionesRestoMasBajo mano
| otherwise = calcularRestoCombinaciones mano
-- Calcula los puntos cunado no hay menos diez o sobra solo una carta
calcularRestoCombinaciones :: [Carta] -> Int
calcularRestoCombinaciones mano = do
let mano' = ordenarCartasNumero mano
let combinacionesPosibles = [comb | comb <- combinaciones 5 mano', tieneNSuc comb 5]
if length combinacionesPosibles >= 1
then do
let combinacionMayor = (last combinacionesPosibles)
sum (map obtenerValorNumerico (mano'\\combinacionMayor))
else
calcularDependiendoCombinacion mano 4
-- calcula el menor puntaje dependiendo las combinaciones
calcularDependiendoCombinacion :: [Carta] -> Int -> Int
calcularDependiendoCombinacion mano 2 = sum (map obtenerValorNumerico mano)
calcularDependiendoCombinacion mano nCartas = do
-- Si n == 4 ELIJE 1 SOLA COMBINACION PORQUE SINO HUBIESE ENTRADO EN puedeGanarMenosDiez
-- Si n == 3 ELIJE 1 SOLA COMBINACION PORQUE SINO HUBIESE ENTRADO EN puedeGanarSobraUna
let combinacionesPosibles = [ (CombinacionPuntaje comb suma) | comb <- combinaciones nCartas mano, esBuena comb, let suma = sum (map obtenerValorNumerico comb) ]
if length combinacionesPosibles >= 1
then do
let combinacionesPosiblesOrdenadas = ordernarCombinacionPuntaje combinacionesPosibles
let combinacionMayor = combinacion (last combinacionesPosiblesOrdenadas)
sum (map obtenerValorNumerico (mano\\combinacionMayor))
else
calcularDependiendoCombinacion mano (nCartas-1)
-- calcula el menor puntaje dependiendo las combinaciones
buscarCombinacionesRestoMasBajo :: [Carta] -> Int
buscarCombinacionesRestoMasBajo mano = do
let buenasCombinaciones mano' = [ (tres, tres'') | tres <- combinaciones 3 mano',let tres' = mano' \\ tres, tres'' <- combinaciones 3 tres', esBuena tres, esBuena tres'']
let restos mano' = concat [ (mano'\\tres)\\tres'' | tres <- combinaciones 3 mano',let tres' = mano' \\ tres, tres'' <- combinaciones 3 tres', esBuena tres, esBuena tres'']
obtenerValorNumerico (head (ordenarCartasNumero (restos mano)))
-- ordena las combinaciones dependiendpo del puntaje
ordernarCombinacionPuntaje :: [CombinacionPuntaje] -> [CombinacionPuntaje]
ordernarCombinacionPuntaje = sortBy (comparing suma)