economy.lisp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. ;;; TRADING ;;;
  2. (defparameter *trade-opt-lookup* (list (cons '1 'buy-menu)
  3. (cons 'b 'buy-menu)
  4. (cons '2 'sell-menu)
  5. (cons 's 'sell-menu)
  6. (cons '3 'display-prices)
  7. (cons 'd 'display-prices)
  8. (cons '4 'top-level-game-menu)
  9. (cons 'r 'top-level-game-menu)))
  10. (defvar *trade-menu-options-display* "
  11. Actions:
  12. 1 | Buy | b
  13. 2 | Sell | s
  14. 3 | Display Prices | d
  15. 4 | Return to top level | r
  16. ")
  17. (defun buy-transaction (resource quantity)
  18. "Do they actual purchase transaction, not intended to be called interactively"
  19. (let* ((available-player-funds (player-ship-credits *player-ship*))
  20. (inventory (player-ship-inventory *player-ship*))
  21. (price (funcall (symbol-function (find-symbol (string-upcase
  22. (concatenate 'string "market-price-of-" resource))))
  23. (sector-market *sector*)))
  24. (total-cost (* quantity price)))
  25. (if (> total-cost available-player-funds)
  26. (progn
  27. (format T "Not enough credits to buy ~A ~A at ~A credits~%" quantity resource price)
  28. (format T "~%PLAYER CREDITS: ~A~%" (player-ship-credits *player-ship*))
  29. (return-from buy-transaction NIL))
  30. (progn
  31. (let ((resource-sym (read-from-string resource))
  32. (minus-funds (lambda (amount)
  33. (let ((remainder (- available-player-funds amount)))
  34. (setf (player-ship-credits *player-ship*) remainder)))))
  35. (case resource-sym
  36. ;;; This is insanely annoying, and will need to be duplicated
  37. ;;; for the sell logic, but don't know how else to handle this here
  38. (gruel (progn
  39. (funcall minus-funds total-cost)
  40. (setf (player-inventory-gruel inventory)
  41. (+ (player-inventory-gruel inventory) quantity))))
  42. (archeotech (progn
  43. (funcall minus-funds total-cost)
  44. (setf (player-inventory-archeotech inventory)
  45. (+ (player-inventory-archeotech inventory) quantity))))
  46. (petrofuel (progn
  47. (funcall minus-funds total-cost)
  48. (setf (player-inventory-petrofuel inventory)
  49. (+ (player-inventory-petrofuel inventory) quantity))))
  50. (spice (progn
  51. (funcall minus-funds total-cost)
  52. (setf (player-inventory-spice inventory)
  53. (+ (player-inventory-spice inventory) quantity))))
  54. (ammo (progn
  55. (funcall minus-funds total-cost)
  56. (setf (player-inventory-ammo inventory)
  57. (+ (player-inventory-ammo inventory) quantity))))))
  58. (format T "Successfully purchased ~A ~A~%" quantity resource)))))
  59. (defun buy-menu ()
  60. (let ((item-to-buy (prompt-read "Enter a resource to buy: "))
  61. (quantity (parse-integer (prompt-read "Enter a quantity to buy: "))))
  62. (if (member item-to-buy '("gruel" "ammo" "petrofuel" "archeotech" "spice") :test #'string=)
  63. (progn
  64. (buy-transaction item-to-buy quantity)
  65. (trade-menu)))))
  66. (defun sell-transaction (resource quantity)
  67. "Do the sale transaction, not intended to be called interactively"
  68. (let* ((available-player-funds (player-ship-credits *player-ship*))
  69. (inventory (player-ship-inventory *player-ship*))
  70. (available-player-resource (funcall (symbol-function (find-symbol (string-upcase
  71. (concatenate 'string "player-inventory-" resource))))
  72. inventory))
  73. (price (funcall (symbol-function (find-symbol (string-upcase
  74. (concatenate 'string "market-price-of-" resource))))
  75. (sector-market *sector*)))
  76. (total-profit (* quantity price)))
  77. (if (> quantity available-player-resource)
  78. (progn
  79. (format T "Not enough ~A to sell ~A. You have ~A~%" resource quantity available-player-resource)
  80. (return-from sell-transaction NIL))
  81. (progn
  82. (let ((resource-sym (read-from-string resource))
  83. (remove-resource (lambda (amount)
  84. (let ((new-credits (+ available-player-funds total-profit)))
  85. (setf (player-ship-credits *player-ship*) new-credits))
  86. (- available-player-resource amount)))) ; This is pretty convoluted
  87. ;;; remove-resource lambda is a pretty bad idea
  88. ;;; it is used to set the new credits amount and then return the amount needed to
  89. ;;; be removed from the resource in the player inventory. I did it this way
  90. ;;; to keep the logic concise, but it smells bad and is probably stupid
  91. (case resource-sym
  92. ;;; This is insanely annoying, and will need to be duplicated
  93. ;;; for the sell logic, but don't know how else to handle this here
  94. (gruel (progn
  95. (setf (player-inventory-gruel inventory) (funcall remove-resource quantity))))
  96. (petrofuel (progn
  97. (setf (player-inventory-petrofuel inventory) (funcall remove-resource quantity))))
  98. (spice (progn
  99. (setf (player-inventory-spice inventory) (funcall remove-resource quantity))))
  100. (ammo (progn
  101. (setf (player-inventory-ammo inventory) (funcall remove-resource quantity))))
  102. (archeotech (progn
  103. (setf (player-inventory-archeotech inventory) (funcall remove-resource quantity))))))
  104. (format T "Successfully sold ~A ~A~%" quantity resource)))))
  105. (defun sell-menu ()
  106. (let ((item-to-sell (prompt-read "Enter a resource to sell: "))
  107. (quantity (parse-integer (prompt-read "Enter a quantity to sell: "))))
  108. (if (member item-to-sell '("gruel" "ammo" "petrofuel" "archeotech" "spice") :test #'string=)
  109. (progn
  110. (sell-transaction item-to-sell quantity)
  111. (trade-menu)))))
  112. ;;; This is kept around in case I need it. I'm not sure
  113. ;;; this is any less 'bad' than how buy/sell-transaction
  114. ;;; currently work
  115. (defmacro dynamic-slot-access (predicate slotname accessor)
  116. "Given a predicate where the predicate is a struct slot accessor like 'market-price-of-',
  117. a slotname like 'petrofuel', and a struct location, return the result of the slot accessor function"
  118. `(funcall ,(symbol-function (find-symbol (string-upcase (concatenate 'string predicate slotname)))) ,accessor))
  119. (defmacro dynamic-slot-setting (predicate slotname accessor value)
  120. `(setf ,(funcall (symbol-function (find-symbol (string-upcase (concatenate 'string predicate slotname)))) accessor) ,value))
  121. (defun display-prices ()
  122. (let ((market-list (list
  123. (list "Petrofuel" (market-price-of-petrofuel (sector-market *sector*)))
  124. (list "Gruel" (market-price-of-gruel (sector-market *sector*)))
  125. (list "Spice" (market-price-of-spice (sector-market *sector*)))
  126. (list "Ammo" (market-price-of-ammo (sector-market *sector*)))
  127. (list "Archeotech" (market-price-of-archeotech (sector-market *sector*))))))
  128. (format T "~%PLAYER CREDITS: ~A~%" (player-ship-credits *player-ship*))
  129. (format T "~%MARKET PRICES~%")
  130. (format-table T market-list :column-label '("Resource" "Cost"))))
  131. (defun trade-menu ()
  132. (format t *trade-menu-options-display*)
  133. (let ((option (prompt-read "Enter an option: ")))
  134. (format t "~%")
  135. (handle-opt (read-from-string option) *trade-opt-lookup*))
  136. (trade-menu))
  137. ;;; END TRADING ;;;
  138. ;;; MARKET ;;;
  139. (defun range (start end)
  140. "Basic function to generate a list that
  141. contains a range of ints"
  142. (loop for i from start below end collect i))
  143. ;;; Use this parameter when randomizing market prices. Used to lookup how
  144. ;;; 'random' prices should really be."
  145. (defparameter *market-price-bounds*
  146. (list (cons 'petrofuel (range 10 41))
  147. (cons 'ammo (range 5 31))
  148. (cons 'archeotech (range 750 2001))
  149. (cons 'spice (range 5 101))
  150. (cons 'gruel (range 1 16))))
  151. (defun randomize-market-prices (market)
  152. (loop for resource in *market-price-bounds*
  153. do (progn
  154. (