-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathplayer-base.rkt
118 lines (95 loc) · 4.82 KB
/
player-base.rkt
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
#lang racket
;; ===================================================================================================
;; basic functionality for both internal and external players (to keep up-to-date, if they wish)
;; EXTERNAL SERVICES
(require "board.rkt" (only-in "cards.rkt" card?) (only-in "basics.rkt" natural? natural+?))
(define species-index-list/c [listof natural?])
(define species-list/c [listof species/c])
(define species-attack/c [list/c species/c natural? natural? natural?])
(define base-player/c
(class/c
(field [boards species-list/c]
[bag natural?]
[cards [listof card?]])
[separate-hungries (->m (values species-index-list/c species-index-list/c))]
[with-fat-tissue (->m [listof [list/c natural? natural+?]])]
[all-attackables (->m natural? species-list/c [listof species-attack/c])]
[can-attack (->m natural? species-list/c (or/c #false [list/c natural? natural? natural?]))]
[can-attack+ (->m natural? natural? species-list/c [listof species-attack/c])]))
(provide
(contract-out
[base-player% base-player/c]))
;; ===================================================================================================
;; DEPENDENCIES
(require "traits.rkt" (except-in "cards.rkt" card?) (except-in "basics.rkt" natural? natural+?)
2htdp/image)
;; for debugging
(require "common.rkt")
;; ===================================================================================================
;; IMPLEMENTATION
;; the base class for players: every player must have these fields and methods
(define base-player%
(class* object% (equal<%>)
(super-new)
(field
[boards
;; [Listof Species]
;; the species that the player currently owns
'()]
[bag
;; the food bag counts the number of points accumulated from prior turns
0]
[cards
;; the cards that the player owns
'()])
;; -----------------------------------------------------------------------------------------------
;; equality
(define/public (equal-to? other r)
(and (r (get-field boards other) boards)
(= (get-field bag other) bag)
(r (get-field cards other) cards)))
;; this is basically nonsense
(define/public (equal-hash-code-of hash-code)
(hash-code boards))
;; this is basically nonsense
(define/public (equal-secondary-hash-code-of hash-code)
(hash-code cards))
;; -----------------------------------------------------------------------------------------------
;; methods for communicating between external player and intenal representation
(abstract start feed-next choose)
;; -----------------------------------------------------------------------------------------------
;; methods for managing the bag, the species boards, and the cards
(define/public (separate-hungries)
(define-values (vegetarians carnivores)
(for/fold ([veg '()][car '()]) ([s boards][i (in-naturals)]#:when (not (send s all-fed?)))
(if (send s has carnivore?) (values veg (cons i car)) (values (cons i veg) car))))
(values (reverse vegetarians) (reverse carnivores)))
;; -> [Listof [List N N]]
(define/public (with-fat-tissue)
(for/list ([s boards]
[i (in-naturals)]
#:when (and (send s has fat-tissue?) (> (send s fat-food-needed) 0)))
(list i (send s fat-food-needed))))
;; N [Listof Species] -> [Maybe [List N N N]]
;; can the given carnviore board attack any of the other players' board?
(define/public (can-attack carnivore-species others (>-species (lambda (x y) #t)))
(define attackables (all-attackables carnivore-species others))
(rest/c (first/c (sort attackables >-species #:key first))))
;; N [Listof Species] -> [Listof [List board N N N]]
(define/public (all-attackables carnivore-species others)
(for/fold ((attackables '())) ([other-species others][index-for-other (in-naturals)])
(define a (can-attack+ carnivore-species index-for-other other-species))
(append attackables a)))
;; N N [Listof Board] -> [Listof [List board N N N]]
(define/public (can-attack+ carnivore-index other-player other-player-s-species)
(define v (list->vector other-player-s-species))
(for/fold ((attacks '())) ([attackee-index (in-range (vector-length v))])
(define left (vector-ref/c v (- attackee-index 1)))
(define attackee (vector-ref v attackee-index))
(define right (vector-ref/c v (+ attackee-index 1)))
(define attackable? (send attackee attackable? (list-ref boards carnivore-index) left right))
(cond
[(not attackable?) attacks]
[else
(define an-attack (list attackee carnivore-index other-player attackee-index))
(cons an-attack attacks)])))))