|
@@ -148,11 +148,12 @@
|
148
|
148
|
(and tile (not (typep tile 'floor-tile))))))
|
149
|
149
|
|
150
|
150
|
(defun bad-move-p (object map old-location new-location)
|
151
|
|
- (let ((old-effective-location (calculate-effective-location object map old-location))
|
152
|
|
- (new-effective-location (calculate-effective-location object map new-location)))
|
153
|
|
- (or (out-of-bounds-p new-effective-location map)
|
154
|
|
- (collision-p new-effective-location map)
|
155
|
|
- (overrun-p old-effective-location new-effective-location map))))
|
|
151
|
+ (when old-location new-location object
|
|
152
|
+ (let ((old-effective-location (calculate-effective-location object map old-location))
|
|
153
|
+ (new-effective-location (calculate-effective-location object map new-location)))
|
|
154
|
+ (or (out-of-bounds-p new-effective-location map)
|
|
155
|
+ (collision-p new-effective-location map)
|
|
156
|
+ (overrun-p old-effective-location new-effective-location map)))))
|
156
|
157
|
|
157
|
158
|
(defmethod update-location ((object entity) map old-location new-location)
|
158
|
159
|
(unless (bad-move-p object map old-location new-location)
|
|
@@ -164,6 +165,17 @@
|
164
|
165
|
(setf (gethash new-location (game-map-mobiles map)) object)
|
165
|
166
|
(remhash old-location (game-map-mobiles map))))
|
166
|
167
|
|
|
168
|
+(defmethod update-location :after ((player player-character) map old-location new-location)
|
|
169
|
+ (declare (ignore old-location new-location))
|
|
170
|
+ (make-dijkstra-map (list player) 'player-map-value (game-map-terrain map)))
|
|
171
|
+
|
|
172
|
+(defmethod update-location :after ((enemy enemy) map old-location new-location)
|
|
173
|
+ (declare (ignore old-location new-location))
|
|
174
|
+ (make-dijkstra-map
|
|
175
|
+ (remove-if-not #'enemy-p
|
|
176
|
+ (alexandria:hash-table-values (game-map-mobiles map)))
|
|
177
|
+ 'enemy-map-value (game-map-terrain map)))
|
|
178
|
+
|
167
|
179
|
(defmethod move-left ((object entity) map)
|
168
|
180
|
(let ((old-location (slot-value object 'location))
|
169
|
181
|
(new-location (1- (slot-value object 'location))))
|
|
@@ -294,30 +306,31 @@
|
294
|
306
|
(aref mapping number)))
|
295
|
307
|
|
296
|
308
|
(defun write-map-to-terminal (player map viewport)
|
297
|
|
- (let* ((player-location (slot-value player 'location))
|
298
|
|
- (current-room (find-room player-location map))
|
299
|
|
- (vision-range (if current-room
|
300
|
|
- (with-slots ((x1 crawler::x1) (y1 crawler::y1) (x2 crawler::x2) (y2 crawler::y2)) current-room
|
301
|
|
- (list (list (1- x1) (1- y1))
|
302
|
|
- (list x2 y2)))
|
303
|
|
- (progn
|
304
|
|
- (multiple-value-bind (x y) (calc-coord player-location map)
|
305
|
|
- (list (list (1- x) (1- y))
|
306
|
|
- (list (1+ x) (1+ y))))))))
|
307
|
|
- (labels ((write-cell (key tile)
|
308
|
|
- (multiple-value-bind (x y) (calc-coord (- key (slot-value viewport 'location)) map)
|
309
|
|
- (let ((x1 (caar vision-range))
|
310
|
|
- (x2 (caadr vision-range))
|
311
|
|
- (y1 (cadar vision-range))
|
312
|
|
- (y2 (cadadr vision-range)))
|
313
|
|
- (when (and (>= x x1)
|
314
|
|
- (<= x x2)
|
315
|
|
- (>= y y1)
|
316
|
|
- (<= y y2))
|
317
|
|
- (terminal-color (slot-value tile 'color))
|
318
|
|
- (terminal-put x y (slot-value tile 'codepoint)))))))
|
319
|
|
- (maphash #'write-cell (game-map-terrain map))
|
320
|
|
- (maphash #'write-cell (game-map-mobiles map)))))
|
|
309
|
+ (when (get-location player)
|
|
310
|
+ (let* ((player-location (slot-value player 'location))
|
|
311
|
+ (current-room (find-room player-location map))
|
|
312
|
+ (vision-range (if current-room
|
|
313
|
+ (with-slots ((x1 crawler::x1) (y1 crawler::y1) (x2 crawler::x2) (y2 crawler::y2)) current-room
|
|
314
|
+ (list (list (1- x1) (1- y1))
|
|
315
|
+ (list x2 y2)))
|
|
316
|
+ (progn
|
|
317
|
+ (multiple-value-bind (x y) (calc-coord player-location map)
|
|
318
|
+ (list (list (1- x) (1- y))
|
|
319
|
+ (list (1+ x) (1+ y))))))))
|
|
320
|
+ (labels ((write-cell (key tile)
|
|
321
|
+ (multiple-value-bind (x y) (calc-coord (- key (slot-value viewport 'location)) map)
|
|
322
|
+ (let ((x1 (caar vision-range))
|
|
323
|
+ (x2 (caadr vision-range))
|
|
324
|
+ (y1 (cadar vision-range))
|
|
325
|
+ (y2 (cadadr vision-range)))
|
|
326
|
+ (when (and (>= x x1)
|
|
327
|
+ (<= x x2)
|
|
328
|
+ (>= y y1)
|
|
329
|
+ (<= y y2))
|
|
330
|
+ (terminal-color (slot-value tile 'color))
|
|
331
|
+ (terminal-put x y (slot-value tile 'codepoint)))))))
|
|
332
|
+ (maphash #'write-cell (game-map-terrain map))
|
|
333
|
+ (maphash #'write-cell (game-map-mobiles map))))))
|
321
|
334
|
|
322
|
335
|
(defun adjacent-open-tiles (tile map)
|
323
|
336
|
(when tile
|
|
@@ -481,9 +494,14 @@
|
481
|
494
|
|
482
|
495
|
(defun initialize-map (map player)
|
483
|
496
|
(fill-map-from-crawler map player)
|
|
497
|
+ (update-location player map nil (get-location player))
|
484
|
498
|
(setf (gethash (slot-value player 'location) (game-map-mobiles map)) player)
|
485
|
499
|
(spawn-enemies map player)
|
486
|
500
|
(spawn-tombs map)
|
|
501
|
+ (make-dijkstra-map
|
|
502
|
+ (remove-if-not #'enemy-p
|
|
503
|
+ (alexandria:hash-table-values (game-map-mobiles map)))
|
|
504
|
+ 'enemy-map-value (game-map-terrain map))
|
487
|
505
|
map)
|
488
|
506
|
|
489
|
507
|
(defun get-neighbors (tile map layer &key (filter-fun #'identity))
|
|
@@ -495,7 +513,7 @@
|
495
|
513
|
(remove-if-not filter-fun (list w n e s))))
|
496
|
514
|
|
497
|
515
|
(defun walkablep (tile)
|
498
|
|
- (and tile (typep tile 'floor-tile)))
|
|
516
|
+ (and tile (or (typep tile 'floor-tile) (typep tile 'tomb))))
|
499
|
517
|
|
500
|
518
|
(defun make-dijkstra-map (sources slot tiles)
|
501
|
519
|
(labels ((get-slot (tile)
|
|
@@ -522,40 +540,6 @@
|
522
|
540
|
(cl-heap:enqueue pending neighbor (get-slot neighbor))))
|
523
|
541
|
tiles)))
|
524
|
542
|
|
525
|
|
-(defun handle-input (key map viewport player prev-key)
|
526
|
|
- (cond
|
527
|
|
- ;; Ranged attack
|
528
|
|
- ((equal prev-key bearlibterminal-ffi:+tk-r+)
|
529
|
|
- (cond
|
530
|
|
- ((= key bearlibterminal-ffi:+tk-up+) (shoot-up player map))
|
531
|
|
- ((= key bearlibterminal-ffi:+tk-down+) (shoot-down player map))
|
532
|
|
- ((= key bearlibterminal-ffi:+tk-right+) (shoot-right player map))
|
533
|
|
- ((= key bearlibterminal-ffi:+tk-left+) (shoot-left player map))
|
534
|
|
- ((= key bearlibterminal-ffi:+tk-enter+) t))) ; cancel
|
535
|
|
- ;; Melee attack
|
536
|
|
- ((equal prev-key bearlibterminal-ffi:+tk-m+)
|
537
|
|
- (cond
|
538
|
|
- ((= key bearlibterminal-ffi:+tk-up+) (bash-up player map))
|
539
|
|
- ((= key bearlibterminal-ffi:+tk-down+) (bash-down player map))
|
540
|
|
- ((= key bearlibterminal-ffi:+tk-right+) (bash-right player map))
|
541
|
|
- ((= key bearlibterminal-ffi:+tk-left+) (bash-left player map))
|
542
|
|
- ((= key bearlibterminal-ffi:+tk-enter+) t))) ; cancel
|
543
|
|
- ;; Not a stateful command
|
544
|
|
- (:otherwise
|
545
|
|
- (cond
|
546
|
|
- ((= key bearlibterminal-ffi:+tk-r+) t) ; Prepare for ranged
|
547
|
|
- ((= key bearlibterminal-ffi:+tk-m+) t) ; Prepare for melee
|
548
|
|
- ((= key bearlibterminal-ffi:+tk-enter+) t) ; idle
|
549
|
|
- ((= key bearlibterminal-ffi:+tk-up+) (move-up player map))
|
550
|
|
- ((= key bearlibterminal-ffi:+tk-down+) (move-down player map))
|
551
|
|
- ((= key bearlibterminal-ffi:+tk-right+) (move-right player map))
|
552
|
|
- ((= key bearlibterminal-ffi:+tk-left+) (move-left player map))
|
553
|
|
- ((= key bearlibterminal-ffi:+tk-w+) (move-up viewport map))
|
554
|
|
- ((= key bearlibterminal-ffi:+tk-a+) (move-left viewport map))
|
555
|
|
- ((= key bearlibterminal-ffi:+tk-d+) (move-right viewport map))
|
556
|
|
- ((= key bearlibterminal-ffi:+tk-s+) (move-down viewport map))
|
557
|
|
- ((= key bearlibterminal-ffi:+tk-space+) (update-location viewport map (slot-value viewport 'location) (slot-value player 'location)))))))
|
558
|
|
-
|
559
|
543
|
(defun create-viewport (map)
|
560
|
544
|
(multiple-value-bind (width height) (get-window-size)
|
561
|
545
|
(when (> width (game-map-width map))
|
|
@@ -598,12 +582,7 @@
|
598
|
582
|
(setf (slot-value object 'location) nil)
|
599
|
583
|
(remhash location (game-map-mobiles map)))
|
600
|
584
|
(end-of-turn object)))) (game-map-mobiles map))
|
601
|
|
- (wake-the-dead map player)
|
602
|
|
- (make-dijkstra-map (list player) 'player-map-value (game-map-terrain map))
|
603
|
|
- (make-dijkstra-map
|
604
|
|
- (remove-if-not #'enemy-p
|
605
|
|
- (alexandria:hash-table-values (game-map-mobiles map)))
|
606
|
|
- 'enemy-map-value (game-map-terrain map)))
|
|
585
|
+ (wake-the-dead map player))
|
607
|
586
|
|
608
|
587
|
(defun write-status-to-terminal (player prev-key map)
|
609
|
588
|
(multiple-value-bind (width height) (get-window-size)
|
|
@@ -668,9 +647,7 @@
|
668
|
647
|
(let* ((tiles (adjacent-open-tiles mobile map))
|
669
|
648
|
(best-tile (first (sort tiles #'< :key #'get-player-map-value))))
|
670
|
649
|
(when best-tile
|
671
|
|
- (remhash (get-location mobile) (game-map-mobiles map))
|
672
|
|
- (setf (slot-value mobile 'location) (get-location best-tile))
|
673
|
|
- (setf (gethash (get-location best-tile) (game-map-mobiles map)) mobile))))
|
|
650
|
+ (update-location mobile map (get-location mobile) (get-location best-tile)))))
|
674
|
651
|
|
675
|
652
|
(defun adjacent-enemies (mobile map)
|
676
|
653
|
(get-neighbors mobile map (game-map-mobiles map) :filter-fun #'enemy-p))
|
|
@@ -705,8 +682,15 @@
|
705
|
682
|
(allies-do-stuff map player)
|
706
|
683
|
(enemies-do-stuff map player))
|
707
|
684
|
|
|
685
|
+(defun enemy-p (thing)
|
|
686
|
+ (typep thing 'enemy))
|
|
687
|
+
|
|
688
|
+(defun no-enemies-left-p (map)
|
|
689
|
+ (not (find-if #'enemy-p (alexandria:hash-table-values (game-map-mobiles map)))))
|
|
690
|
+
|
708
|
691
|
(defun display-lose ()
|
709
|
692
|
(terminal-clear)
|
|
693
|
+ (terminal-color (color-from-name "white"))
|
710
|
694
|
(terminal-print 0 0 "You lose!")
|
711
|
695
|
(terminal-print 0 1 "Press escape key to exit.")
|
712
|
696
|
(terminal-refresh)
|
|
@@ -715,17 +699,73 @@
|
715
|
699
|
|
716
|
700
|
(defun display-win ()
|
717
|
701
|
(terminal-clear)
|
|
702
|
+ (terminal-color (color-from-name "white"))
|
718
|
703
|
(terminal-print 0 0 "You win!")
|
719
|
704
|
(terminal-print 0 1 "Press escape key to exit.")
|
720
|
705
|
(terminal-refresh)
|
721
|
706
|
(loop as key = (terminal-read)
|
722
|
707
|
while (not (eq key bearlibterminal-ffi:+tk-escape+))))
|
723
|
708
|
|
724
|
|
-(defun enemy-p (thing)
|
725
|
|
- (typep thing 'enemy))
|
726
|
709
|
|
727
|
|
-(defun no-enemies-left-p (map)
|
728
|
|
- (not (find-if #'enemy-p (alexandria:hash-table-values (game-map-mobiles map)))))
|
|
710
|
+(defun display-instructions ()
|
|
711
|
+ (multiple-value-bind (win-width win-height) (get-window-size)
|
|
712
|
+ (terminal-clear)
|
|
713
|
+ (terminal-color (color-from-name "white"))
|
|
714
|
+ (terminal-print 0 0 "Instructions")
|
|
715
|
+ (terminal-print 0 1 "This is you: ")
|
|
716
|
+ (terminal-color (color-from-name "#800080"))
|
|
717
|
+ (terminal-put 13 1 #x2639)
|
|
718
|
+ (terminal-color (color-from-name "white"))
|
|
719
|
+ (terminal-print 0 2 "Move with arrow keys.")
|
|
720
|
+ (terminal-print 0 3 "Ranged attack with r. Choose a direction. Press enter to cancel. Canceling still takes up your turn. Costs 5 mana.")
|
|
721
|
+ (terminal-print 0 4 "Melee attack with m. Choose a direction. Press enter to cancel. Canceling still takes up your turn.")
|
|
722
|
+ (terminal-print 0 5 "You do not regenerate health.")
|
|
723
|
+ (terminal-print 0 6 "You regenerate 3 mana per a turn (including turns in which you use mana)")
|
|
724
|
+ (terminal-color (color-from-name "#ffff00"))
|
|
725
|
+ (terminal-put 13 7 #x2616)
|
|
726
|
+ (terminal-color (color-from-name "white"))
|
|
727
|
+ (terminal-color (color-from-name "#ffff00"))
|
|
728
|
+ (terminal-put 13 8 #x2639)
|
|
729
|
+ (terminal-color (color-from-name "white"))
|
|
730
|
+ (terminal-color (color-from-name "#1919ff"))
|
|
731
|
+ (terminal-put 13 9 #x263a)
|
|
732
|
+ (terminal-color (color-from-name "white"))
|
|
733
|
+ (terminal-refresh)))
|
|
734
|
+
|
|
735
|
+(defun handle-input (key map viewport player prev-key)
|
|
736
|
+ (cond
|
|
737
|
+ ;; Ranged attack
|
|
738
|
+ ((equal prev-key bearlibterminal-ffi:+tk-r+)
|
|
739
|
+ (cond
|
|
740
|
+ ((= key bearlibterminal-ffi:+tk-up+) (shoot-up player map))
|
|
741
|
+ ((= key bearlibterminal-ffi:+tk-down+) (shoot-down player map))
|
|
742
|
+ ((= key bearlibterminal-ffi:+tk-right+) (shoot-right player map))
|
|
743
|
+ ((= key bearlibterminal-ffi:+tk-left+) (shoot-left player map))
|
|
744
|
+ ((= key bearlibterminal-ffi:+tk-enter+) t))) ; cancel
|
|
745
|
+ ;; Melee attack
|
|
746
|
+ ((equal prev-key bearlibterminal-ffi:+tk-m+)
|
|
747
|
+ (cond
|
|
748
|
+ ((= key bearlibterminal-ffi:+tk-up+) (bash-up player map))
|
|
749
|
+ ((= key bearlibterminal-ffi:+tk-down+) (bash-down player map))
|
|
750
|
+ ((= key bearlibterminal-ffi:+tk-right+) (bash-right player map))
|
|
751
|
+ ((= key bearlibterminal-ffi:+tk-left+) (bash-left player map))
|
|
752
|
+ ((= key bearlibterminal-ffi:+tk-enter+) t))) ; cancel
|
|
753
|
+ ;; Not a stateful command
|
|
754
|
+ (:otherwise
|
|
755
|
+ (cond
|
|
756
|
+ ((= key bearlibterminal-ffi:+tk-r+) t) ; Prepare for ranged
|
|
757
|
+ ((= key bearlibterminal-ffi:+tk-m+) t) ; Prepare for melee
|
|
758
|
+ ((= key bearlibterminal-ffi:+tk-enter+) t) ; idle
|
|
759
|
+ ((= key bearlibterminal-ffi:+tk-h+) (display-instructions))
|
|
760
|
+ ((= key bearlibterminal-ffi:+tk-up+) (move-up player map))
|
|
761
|
+ ((= key bearlibterminal-ffi:+tk-down+) (move-down player map))
|
|
762
|
+ ((= key bearlibterminal-ffi:+tk-right+) (move-right player map))
|
|
763
|
+ ((= key bearlibterminal-ffi:+tk-left+) (move-left player map))
|
|
764
|
+ ((= key bearlibterminal-ffi:+tk-w+) (move-up viewport map))
|
|
765
|
+ ((= key bearlibterminal-ffi:+tk-a+) (move-left viewport map))
|
|
766
|
+ ((= key bearlibterminal-ffi:+tk-d+) (move-right viewport map))
|
|
767
|
+ ((= key bearlibterminal-ffi:+tk-s+) (move-down viewport map))
|
|
768
|
+ ((= key bearlibterminal-ffi:+tk-space+) (update-location viewport map (slot-value viewport 'location) (slot-value player 'location)))))))
|
729
|
769
|
|
730
|
770
|
(defun main-loop ()
|
731
|
771
|
(loop with player = (make-instance 'player-character)
|