Reputation: 31
I’m not advanced Lisper, I’m trying to learn the language. So, I'm trying to write a simple card game engine. The bidding is realized in the following way: players are asked about their bids. If a complete list of players accept the bid, the bidding is closed and the data stored. Otherwise all the necessary data are passed to the recursive call. Data transferred to the next call are the following lists: players, their current billings, a true-false list with an information if the player is active, and the history of the game (all payments).
The problem is that the function doesn’t return values from the recursive call.
The initial input data are:
(defparameter *billings* (list 0 0 0 0 0 0 50 100))
(defparameter *players* '(Alice Bob Carol Eve Frank Oscar Trent Walter))
(defparameter *participants* (list t t t t t t t t))
(defparameter *history* (list))
The code (without the bodies of the helper functions) looks like that:
(defun make-round(rel-players rel-billings rel-participants game-history)
(let((max-billing (maxval rel-billings))
(curr 0))
(loop
for billing in rel-billings
for player in rel-players
for participant in rel-participants
do (if(not participant) (setf game-history (add2->history 0 game-history (length rel-players)))
(let((bid (ask player billing max-billing)))
(cond ((not bid) (set-assoc-list-val player nil rel-players rel-participants)
(setf game-history (add2->history 0 game-history (length rel-players))) )
(t (setf curr (+ bid billing))
(set-assoc-list-val player curr rel-players rel-billings)
(setf game-history (add2->history bid game-history (length rel-players)))
(when (> curr max-billing)
(make-round (divide-players (next-player player rel-players) rel-players)
(divide-players-list (next-player player rel-players) rel-players rel-billings)
(divide-players-list (next-player player rel-players) rel-players rel-participants)
game-history)
))))))
(values rel-players rel-billings rel-participants game-history)))
I suppose I made a stupid mistake but actually I can’t manage it. Please help
input:
(make-round *players* *billings* *participants* *history*)
Player ALICE has paid 0 dollars but 100 is required. Player ALICE has to pay at least 100 dollars
100
Player BOB has paid 0 dollars but 100 is required. Player BOB has to pay at least 100 dollars
100
Player CAROL has paid 0 dollars but 100 is required. Player CAROL has to pay at least 100 dollars
100
Player EVE has paid 0 dollars but 100 is required. Player EVE has to pay at least 100 dollars
100
Player FRANK has paid 0 dollars but 100 is required. Player FRANK has to pay at least 100 dollars
100
Player OSCAR has paid 0 dollars but 100 is required. Player OSCAR has to pay at least 100 dollars
100
Player TRENT has paid 50 dollars but 100 is required. Player TRENT has to pay at least 50 dollars
150
Player WALTER has paid 100 dollars but 200 is required. Player WALTER has to pay at least 100 dollars
100
Player ALICE has paid 100 dollars but 200 is required. Player ALICE has to pay at least 100 dollars
100
Player BOB has paid 100 dollars but 200 is required. Player BOB has to pay at least 100 dollars
100
Player CAROL has paid 100 dollars but 200 is required. Player CAROL has to pay at least 100 dollars
100
Player EVE has paid 100 dollars but 200 is required. Player EVE has to pay at least 100 dollars
100
Player FRANK has paid 100 dollars but 200 is required. Player FRANK has to pay at least 100 dollars
100
Player OSCAR has paid 100 dollars but 200 is required. Player OSCAR has to pay at least 100 dollars
100
Player TRENT has paid 200 dollars but 200 is required. Player TRENT has to pay at least 0 dollars
0
output:
(ALICE BOB CAROL EVE FRANK OSCAR TRENT WALTER)
(100 100 100 100 100 100 200 100)
(T T T T T T T T)
((100 100 100 100 100 100 150))
Upvotes: 3
Views: 354
Reputation: 8421
Look at the call to MAKE-ROUND
and see where it returns its value to by working up: MAKE-ROUND
-> WHEN
-> COND
-> LET
-> IF
which returns to the loop DO
-keyword that discards the value.
To prevent the return value from being discarded, you'll have to do an explicit early return with RETURN-FROM
.
(defun make-round (rel-players rel-billings rel-participants game-history)
(let ((max-billing (maxval rel-billings))
(curr 0))
(loop
for billing in rel-billings
for player in rel-players
for participant in rel-participants
do (if (not participant)
(setf game-history (add2->history 0 game-history (length rel-players)))
(let ((bid (ask player billing max-billing)))
(cond ((not bid)
(set-assoc-list-val player nil rel-players rel-participants)
(setf game-history (add2->history 0 game-history (length rel-players))) )
(t
(setf curr (+ bid billing))
(set-assoc-list-val player curr rel-players rel-billings)
(setf game-history (add2->history bid game-history (length rel-players)))
(when (> curr max-billing)
(return-from make-round
(make-round (divide-players (next-player player rel-players) rel-players)
(divide-players-list (next-player player rel-players) rel-players rel-billings)
(divide-players-list (next-player player rel-players) rel-players rel-participants)
game-history))))))))
(values rel-players rel-billings rel-participants game-history)))
Since the code isn't runnable I haven't checked if the logic actually works, but this solves the problem of not returning the value. I recommend that you refactor the code to be more readable at some point.
Upvotes: 1