economy.lisp
1	;;; TRADING ;;;
2 (defparameter *trade-opt-lookup* (list (cons '1 (lambda ()
3 (buy-menu (player-ship-obj *sector*) (market *sector*))))
4 (cons '2 (lambda ()
5 (sell-menu (player-ship-obj *sector*) (market *sector*))))
6 (cons '3 'top-level-game-menu)))
7
8 (defvar *trade-menu-options-display* "
9 Actions:
10 1 | Buy | b
11 2 | Sell | s
12 3 | Return to top level | r
13 ")
14
15 (defun buy-transaction (resource quantity player-ship-obj market-obj)
16 "Do they actual purchase transaction, not intended to be called interactively"
17 (let* ((available-player-funds (credits player-ship-obj))
18 (inventory-obj (inventory player-ship-obj))
19 (price (slot-value market-obj (read-from-string (concatenate 'string "price-of-" resource))))
20 (total-cost (* quantity price)))
21 (if (> total-cost available-player-funds)
22 (progn
23 (format T "Not enough credits to buy ~A ~A at ~A credits~%" quantity resource price)
24 (format T "~%PLAYER CREDITS: ~A~%" (credits player-ship-obj))
25 (return-from buy-transaction NIL))
26 (progn
27 (let ((resource-sym (read-from-string resource))
28 (minus-funds (lambda (amount)
29 (let ((remainder (- available-player-funds amount)))
30 (setf (credits player-ship-obj) remainder)))))
31 (setf (slot-value inventory-obj resource-sym) (+ quantity (slot-value inventory-obj resource-sym)))
32 (funcall minus-funds total-cost)
33 (format T "Successfully purchased ~A ~A~%" quantity resource))))))
34
35 (defun buy-menu (player-ship-obj market-obj)
36 (let ((item-to-buy (prompt-read "Enter a resource to buy: "))
37 (quantity (parse-integer (prompt-read "Enter a quantity to buy: "))))
38 (if (member item-to-buy '("gruel" "ammo" "petrofuel" "archeotech" "spice") :test #'string=)
39 (progn
40 (buy-transaction item-to-buy quantity player-ship-obj market-obj)))))
41
42 (defun sell-transaction (resource quantity player-ship-obj market-obj)
43 "Do the sale transaction, not intended to be called interactively"
44 (let* ((resource-sym (read-from-string resource))
45 (available-player-funds (credits player-ship-obj))
46 (inventory (inventory player-ship-obj))
47 (available-player-resource (slot-value inventory resource-sym))
48 (price (slot-value market-obj (read-from-string (concatenate 'string "price-of-" resource))))
49 (total-profit (* quantity price)))
50 (if (> quantity available-player-resource)
51 (progn
52 (format T "Not enough ~A to sell ~A. You have ~A~%" resource quantity available-player-resource)
53 (return-from sell-transaction NIL))
54 (progn
55 (let ((remove-resource (lambda (amount)
56 (let ((new-credits (+ available-player-funds total-profit)))
57 (setf (credits player-ship-obj) new-credits))
58 (- available-player-resource amount)))) ; This is pretty convoluted
59 ;;; remove-resource lambda is a pretty bad idea?
60 ;;; it is used to set the new credits amount and then return the amount needed to
61 ;;; be removed from the resource in the player inventory. I did it this way
62 ;;; to keep the logic concise, but it smells bad and is probably stupid
63 (setf (slot-value inventory resource-sym) (funcall remove-resource quantity))
64 ;; (archeotech (progn
65 ;; (setf (player-inventory-archeotech inventory) (funcall remove-resource quantity))))))
66 (format T "Successfully sold ~A ~A~%" quantity resource))))))
67
68 (defun sell-menu (player-ship-obj market-obj)
69 (let ((item-to-sell (prompt-read "Enter a resource to sell: "))
70 (quantity (parse-integer (prompt-read "Enter a quantity to sell: "))))
71 (if (member item-to-sell '("gruel" "ammo" "petrofuel" "archeotech" "spice") :test #'string=)
72 (progn
73 (sell-transaction item-to-sell quantity player-ship-obj market-obj)))))
74
75 (defun display-prices (market-obj player-credits)
76 (let ((market-list (loop for resource in (return-slots market-obj)
77 collect (list resource (slot-value market-obj resource)))))
78 (format T "~%PLAYER CREDITS: ~A~%" player-credits)
79 (format T "~%MARKET PRICES~%")
80 (format-table T market-list :column-label '("Resource" "Cost"))))
81
82 (defun trade-menu (sector)
83 (display-prices (market sector) (credits (player-ship-obj sector)))
84 (display-inventory (player-ship-obj sector))
85 (format t *trade-menu-options-display*)
86 (let ((option (prompt-read "Enter an option: ")))
87 (format t "~%")
88 (handle-opt (read-from-string option) *trade-opt-lookup*))
89 (trade-menu sector))
90
91 ;;; END TRADING ;;;
92
93 ;;; MARKET ;;;
94
95 ;;; Use this parameter when randomizing market prices. Used to lookup how
96 ;;; 'random' prices should really be."
97 (defparameter *market-price-bounds*
98 (list (cons 'price-of-petrofuel '(10 41))
99 (cons 'price-of-ammo '(5 31))
100 (cons 'price-of-archeotech '(750 2001))
101 (cons 'price-of-spice '(5 101))
102 (cons 'price-of-gruel '(1 16))))
103
104 (defun randomize-market-prices (market)
105 (let ((get-random-val (lambda (resource-arg)
106 (+ (cadr resource-arg)
107 (random (caddr resource-arg))))))
108 (loop for resource in *market-price-bounds*
109 do (setf (slot-value market (car resource)) (funcall get-random-val resource)))))