2 # - highest bidder leads
3 # - show card after play
6 function sp_init(cards, tmp0, tmp1)
8 sp_valid = 0 # Message sent from sp_player
9 sp_player = "" # Who's turn it is
10 sp_turn = 0 # Index of who's turn it is
11 delete sp_hands # [p] Each players cards
14 cards ="As Ks Qs Js 10s 9s 8s 7s 6s 5s 4s 3s 2s "\
15 "Ah Kh Qh Jh 10h 9h 8h 7h 6h 5h 4h 3h 2h "\
16 "Ac Kc Qc Jc 10c 9c 8c 7c 6c 5c 4c 3c 2c "\
17 "Ad Kd Qd Jd 10d 9d 8d 7d 6d 5d 4d 3d 2d"
19 for (i=1; i<=length(tmp0); i++)
23 function sp_reset(type)
27 sp_suit = "" # The lead suit {s,h,d,c}
28 sp_piles = "" # [x] Played cards this turn
29 delete sp_pile # [x] Played cards this turn
34 sp_state = "bid" # {new,join,bid,pass,play}
35 sp_broken = 0 # Whether spades are broken
36 delete sp_looked # [i] Whether a player has looked a their cards
37 delete sp_bids # [i] Each players bid
38 delete sp_nil # [i] Nil multiplier 0=regular, 1=nil, 2=blind
39 delete sp_pass # [i] Cards to pass
40 delete sp_tricks # [i] Tricks this round
45 sp_channel = "" # channel to play in
46 sp_state = "new" # {new,join,bid,play}
47 sp_owner = "" # Who started the game
48 sp_playto = 0 # Score the game will go to
49 sp_dealer =-1 # Who is dealing this round
50 delete sp_players # [p] Player names players["name"] -> i
51 delete sp_order # [i] Player order order[i] -> "name"
52 delete sp_scores # [i] Teams score
56 function sp_pretty(cards, who)
59 gsub(/[0-9JQKA]*[sc]/, "\0031,00\002&\017", cards) # black
60 gsub(/[0-9JQKA]*[hd]/, "\0034,00\002&\017", cards) # red
61 gsub(/s/, "\002♠", cards)
62 gsub(/h/, "\002♥", cards)
63 gsub(/d/, "\002♦", cards)
64 gsub(/c/, "\002♣", cards)
69 function sp_next(who, prev)
72 sp_turn = who ? sp_players[who] : (sp_turn + 1) % 4
73 sp_player = sp_order[sp_turn]
77 function sp_deal( shuf)
79 say("/me deals the cards")
80 asorti(sp_deck, shuf, "sp_usort")
82 sp_hands[sp_order[i%4]][shuf[i]] = 1
84 sp_dealer = (sp_dealer+1)%4
86 sp_player = sp_order[sp_turn]
87 say("Bidding starts with " sp_player "!")
90 function sp_hand(who, sort, str)
92 asorti(sp_hands[who], sort, "sp_csort")
93 for (i=0; i<length(sort); i++)
94 str = str "" sprintf("%4s", sort[i])
95 gsub(/^ +| +$/, "", str)
96 return sp_pretty(str, who)
99 function sp_hasa(who, expr)
101 for (c in sp_hands[who]) {
108 function sp_type(card)
110 return substr(card, length(card))
113 function sp_usort(a,b,c,d) {
117 function sp_csort(i1,v1,i2,v2) {
118 return sp_deck[i1] > sp_deck[i2] ? +1 :
119 sp_deck[i1] < sp_deck[i2] ? -1 : 0;
122 function sp_winner( card, tmp)
124 for (card in sp_pile)
125 if (card !~ sp_suit && card !~ /s/)
127 asorti(sp_pile, tmp, "sp_csort")
128 #print "pile: " tmp[1] ">" tmp[2] ">" tmp[3] ">" tmp[4]
134 #return "{" sp_order[i+0] "," sp_order[i+2] "}"
135 return sp_order[i+0] "/" sp_order[i+2]
138 function sp_bags(i, bags)
140 bags = sp_scores[i] % 10
146 function sp_score( bids, tricks)
148 for (i=0; i<2; i++) {
149 bids = sp_bids[i] + sp_bids[i+2]
150 tricks = sp_tricks[i] + sp_tricks[i+2]
152 if (sp_bags(i) + bags > 10) {
153 say(sp_team(i) " bag out")
156 if (tricks >= bids) {
157 say(sp_team(i) " make their bid")
158 sp_scores[i] += bids*10 + bags;
160 say(sp_team(i) " go bust")
161 sp_scores[i] -= bids*10;
164 for (i=0; i<4; i++) {
167 say(sp_order[i] " " \
168 (sp_nil[i] == 1 && !sp_tricks[i] ? "makes nil!" :
169 sp_nil[i] == 1 && sp_tricks[i] ? "fails at nil!" :
170 sp_nil[i] == 2 && !sp_tricks[i] ? "makes blind nil!" :
171 sp_nil[i] == 2 && sp_tricks[i] ? "fails miserably at blind nil!" :
173 sp_scores[i%2] += 100 * sp_nil[i] * \
174 (sp_tricks[i] == 0 ? 1 : -1)
178 function sp_play(card, winner, pi)
180 delete sp_hands[FROM][card]
181 sp_pile[card] = sp_player
182 sp_piles = sp_piles (sp_piles?",":"") card
189 if (length(sp_pile) == 1)
190 sp_suit = sp_type(card)
193 if (length(sp_pile) == 4) {
195 pi = sp_players[sp_pile[winner]]
197 say(sp_pile[winner] " wins with " sp_pretty(winner, FROM) \
198 " (" sp_pretty(sp_piles, FROM) ")")
199 sp_next(sp_pile[winner])
204 if (sp_tricks[0] + sp_tricks[1] + \
205 sp_tricks[2] + sp_tricks[3] == 13) {
208 if (sp_scores[0] >= sp_playto || sp_scores[1] >= sp_playto &&
209 sp_scores[0] != sp_scores[1]) {
211 winner = sp_scores[0] > sp_scores[1] ? 0 : 1
213 say(sp_team(winner) " wins the game " \
214 sp_scores[winner] " to " sp_scores[looser])
215 say(sp_order[winner+0] "++")
216 say(sp_order[winner+2] "++")
217 say(sp_order[looser+0] "--")
218 say(sp_order[looser+2] "--")
222 if (sp_scores[0] == sp_scores[1] &&
223 sp_scores[0] >= sp_playto)
224 say("It's tie! Playing an extra round!");
233 cmd = "od -An -N4 -td4 /dev/random"
242 sp_valid = (FROM && FROM == sp_player)
247 say("Spades! " sp_pretty("As,Ah,Ad,Ac", FROM))
251 /^\.help [Ss]pades$/ {
252 say("Spades -- play a game of spades")
254 say(".newgame [score] -- start a game to <score> points, default 500")
255 say(".endgame -- abort the current game")
256 say(".join -- join the current game")
257 say(".look -- look at your cards")
258 say(".bid n -- bid for <n> tricks")
259 say(".play [card] -- play a card")
260 say(".score -- check the score")
261 say(".tricks -- check how many trick have been taken")
262 say(".bids -- check what everyone bid")
268 /^\.deal (\w+) (.*)/ {
270 for (i=3; i<=NF; i++)
272 privmsg(sp_channel, FROM " is cheating for " $2)
277 /^\.newgame ?([0-9]+)?$/ {
278 if (sp_state != "new") {
279 reply("There is already a game in progress.")
282 sp_playto = $2 ? $2 : 200
285 say(sp_owner " starts a game of Spades to " sp_playto "!")
286 #privmsg("#rhnoise", sp_owner " starts a game of Spades in " DST "!")
290 (FROM == sp_owner || FROM == OWNER) &&
292 if (sp_state == "new") {
293 reply("There is no game in progress.")
295 say(FROM " ends the game")
301 if (sp_state == "new") {
302 reply("There is no game in progress")
304 else if (sp_state == "play") {
305 reply("The game has already started")
307 else if (sp_state == "join" && FROM in sp_players) {
308 reply("You are already playing")
310 else if (sp_state == "join") {
314 say(FROM " joins the game!")
316 if (sp_state == "join" && sp_turn == 0)
321 (sp_state "bid" || sp_state == "play") &&
323 if (FROM in sp_players)
324 say(".slap " FROM ", it is not your turn.")
326 say(".slap " FROM ", you are not playing.")
332 if ($2 < 0 || $2 > 13) {
333 say("You can only bid from 0 to 13")
337 if ($2 == 0 && !sp_looked[i]) {
338 say(FROM " goes blind nil!")
340 } else if ($2 == 0) {
341 say(FROM " goes nil!")
344 if (sp_turn != sp_dealer) {
345 say("Bidding goes to " sp_player "!")
347 for (p in sp_players)
348 privmsg(p, "You have: " sp_hand(p))
350 for (i=0; i<2; i++) {
351 if (sp_nil[i] == 2 || sp_nil[i+2] == 2) {
352 say(sp_team(i) ": select a card to pass " \
353 "(/msg " NICK " .pass <card>)")
357 if (sp_state == "play")
358 say("Play starts with " sp_player "!")
363 sp_state == "pass" &&
366 team = sp_players[FROM] % 2
367 if (!(FROM in sp_players)) {
368 say(".slap " FROM ", you are not playing.")
370 else if (sp_nil[team] != 2 && sp_nil[team+2] != 2) {
371 reply("Your team did not go blind")
373 else if (sp_pass[sp_players[FROM]]) {
374 reply("You have already passed a card")
376 else if (!(card in sp_deck)) {
377 reply("Invalid card")
379 else if (!(card in sp_hands[FROM])) {
380 reply("You do not have that card")
383 sp_pass[sp_players[FROM]] = $2
384 privmsg(sp_channel, FROM " passes a card")
386 if (((sp_nil[0] != 2 && sp_nil[2] != 2) || (sp_pass[0] && sp_pass[2])) &&
387 ((sp_nil[1] != 2 && sp_nil[3] != 2) || (sp_pass[1] && sp_pass[3]))) {
391 delete sp_hands[sp_order[i]][card]
392 sp_hands[sp_order[partner]][card] = 1
394 privmsg(sp_channel, "Cards have been passed, play starts with " sp_player "!")
395 for (p in sp_players)
396 privmsg(p, "You have: " sp_hand(p))
401 sp_state ~ "(play|bid)" &&
403 if (!(FROM in sp_players)) {
404 say(".slap " FROM ", you are not playing.")
406 sp_looked[sp_players[FROM]] = 1
407 privmsg(FROM, "You have: " sp_hand(FROM))
412 sp_state == "play" &&
415 if (!(card in sp_deck)) {
416 reply("Invalid card")
418 else if (!(card in sp_hands[FROM])) {
419 reply("You do not have that card")
421 else if (sp_suit && card !~ sp_suit && sp_hasa(FROM, sp_suit)) {
422 reply("You must follow suit (" sp_suit ")")
424 else if (card ~ /s/ && length(sp_hands[FROM]) == 13 && sp_hasa(FROM, "[^s]$")) {
425 reply("You cannot trump on the first hand")
427 else if (card ~ /s/ && length(sp_pile) == 0 && sp_hasa(FROM, "[^s]$") && !sp_broken) {
428 reply("Spades have not been broken")
432 privmsg(FROM, "You have: " sp_hand(FROM))
433 if (sp_state == "play") {
435 say(sp_player ": it is your turn! " \
436 "(" sp_pretty(sp_piles, sp_player) ")")
438 say(sp_player ": it is your turn!")
443 /^\.bids$/ && sp_state == "play" {
444 say(sp_order[0] " bid " sp_bids[0] ", " \
445 sp_order[2] " bid " sp_bids[2] ", " \
446 "total: " sp_bids[0] + sp_bids[2])
447 say(sp_order[1] " bid " sp_bids[1] ", " \
448 sp_order[3] " bid " sp_bids[3] ", " \
449 "total: " sp_bids[1] + sp_bids[3])
452 /^\.tricks$/ && sp_state == "play" {
453 say(sp_order[0] " took " int(sp_tricks[0]) "/" int(sp_bids[0]) ", " \
454 sp_order[2] " took " int(sp_tricks[2]) "/" int(sp_bids[2]))
455 say(sp_order[1] " took " int(sp_tricks[1]) "/" int(sp_bids[1]) ", " \
456 sp_order[3] " took " int(sp_tricks[3]) "/" int(sp_bids[3]))
459 /^\.(score|status)$/ {
460 if (sp_state == "new") {
461 say("There is no game in progress")
463 if (sp_state == "join") {
464 say("Waiting for palyers: " \
465 sp_order[0] " " sp_order[1] " " \
466 sp_order[2] " " sp_order[3])
468 if (sp_state == "bid" || sp_state == "play") {
469 say(sp_team(0) ": " \
470 int(sp_scores[0]) " points, " \
471 int(sp_bags(0)) " bags")
472 say(sp_team(1) ": " \
473 int(sp_scores[1]) " points, " \
474 int(sp_bags(1)) " bags")
479 #/^\.playfor [^ ]*$/ {
482 #/^\.standin [^ ]*$/ {
483 # if (p in sp_players) {
485 # for (p in sp_standin) {
486 # if ($2 in sp_standin)
487 # say(here " is already playing for " sp_standin[p]);
489 # sp_standin[away] = here