-
Notifications
You must be signed in to change notification settings - Fork 3
/
player.lisp
129 lines (114 loc) · 4.03 KB
/
player.lisp
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
(in-package :lispstone)
(defclass player ()
((avatar
:initarg :avatar
:initform (make-instance 'avatar)
:accessor player-avatar)
(avatar-proto :initarg :avatar-proto)
(mana :accessor player-mana)
(max-mana :accessor player-max-mana)
(hand
:initform (make-instance 'hand)
:accessor player-hand)
(deck :accessor player-deck)
(name :accessor player-name
:initarg :name
:initform (error "Must supply a name"))
(bonuses
:initform 0
:accessor player-bonuses)
(luck :initform nil)))
(defun reset-player (player)
(with-slots (hand deck mana max-mana avatar avatar-proto) player
(reset-hand hand)
(if (slot-boundp player 'avatar-proto)
(with-slots (name hp dmg resist evasion) avatar
(with-slots ((name-x name)
(hp-x hp)
(dmg-x dmg)
(resist-x resist)
(evasion-x evasion)) avatar-proto
(setf name name-x
hp hp-x
dmg dmg-x
resist resist-x
evasion evasion-x)))
(reset-avatar avatar))
(setf mana 0
max-mana 0
deck (random-deck (ecase (type-of player)
(player (available-cards))
(enemy *cards*))))))
(defmethod initialize-instance :after ((player player) &key)
(reset-player player))
(defmethod print-object ((player player) stream)
(with-slots (name mana deck hand) player
(format stream "~a | mana ~2d | hand ~a | deck ~d"
name mana (hand-size hand) (length deck))))
(defun take-card (player)
(with-slots (name hand deck) player
(if deck
(let ((card (pop deck)))
(if (< (hand-size hand) *max-hand-size*)
(progn
(push-and-trace "~a ← ~a" name (card-name card))
(add-to-hand hand card))
(push-and-trace "Dropping ~a card: hand is full" (card-name card))))
(push-and-trace "Deck is empty!"))))
(defun can-play-card (player card)
(>= (player-mana player) (card-cost card)))
(defun remove-card (player card)
(hand-remove-card (player-hand player) card))
(defun play-card (player card)
(with-slots (mana name avatar) player
(remove-card player card)
(apply-card card player))
(let ((clone (clone-card-entity (get-card-entity card) card))
(scene (find-scene *window* :table-scene)))
(with-slots (width height) scene
(with-slots (id x y anchor-x anchor-y) clone
(setf id :played-card
x (ash width -1)
y (+ (ash height -1) 50)
anchor-x :center
anchor-y :center)))
(entity-fade-out clone 1.5)
(add-to-scene scene clone)))
(defun find-playable-card (player)
(with-slots (hand) player
(find-if (lambda (card) (can-play-card player card))
(hand-shuffled-cards hand))))
(defun make-dmg (attacker resist)
(round (* (avatar-dmg attacker) 0.01 (- 100 resist))))
(defun hit (attacker defending)
(with-slots (hp evasion resist) defending
(if (lucky evasion)
'miss
(let ((dmg (make-dmg attacker resist)))
(decf hp dmg)
dmg))))
(defun make-turn (player)
(with-slots (name mana avatar hand) player
(log-trace "~&Turn of ~a~%" name)
(log-trace "Mana ~a~%" mana)
(log-trace "Avatar ~a~%" avatar)
(log-trace "Hand: ~a~%" (format-hand hand)))
(loop
for input = (prompt-read "Play card (index | name | end)")
until (equalp input "end")
for card = (find-card-by-name-or-index player input)
do (if card
(play-card player card)
(log-trace "No card to play"))))
(defun make-ai-turn (player)
(log-trace "~&~%AI Turn of ~a~%" (player-name player))
(loop
for card = (find-playable-card player)
while card
do (play-card player card)))
(defun dead-p (player)
(<= (avatar-hp (player-avatar player)) 0))
(defun consume-bonuses (player)
(with-slots (luck bonuses) player
(setf luck (plusp bonuses)
bonuses 0)))