2 function sp_init(cards, tmp0, tmp1)
5 cards ="As Ks Qs Js 10s 9s 8s 7s 6s 5s 4s 3s 2s "\
6 "Ah Kh Qh Jh 10h 9h 8h 7h 6h 5h 4h 3h 2h "\
7 "Ac Kc Qc Jc 10c 9c 8c 7c 6c 5c 4c 3c 2c "\
8 "Ad Kd Qd Jd 10d 9d 8d 7d 6d 5d 4d 3d 2d"
10 for (i=1; i<=length(tmp0); i++)
14 function sp_reset(type)
18 sp_suit = "" # The lead suit {s,h,d,c}
19 sp_piles = "" # [x] Played cards this turn
20 delete sp_pile # [x] Played cards this turn
25 sp_state = "bid" # {new,join,bid,pass,play}
26 sp_broken = 0 # Whether spades are broken
27 delete sp_looked # [i] Whether a player has looked a their cards
28 delete sp_bids # [i] Each players bid
29 delete sp_nil # [i] Nil multiplier 0=regular, 1=nil, 2=blind
30 delete sp_pass # [i] Cards to pass
31 delete sp_tricks # [i] Tricks this round
36 sp_channel = "" # channel to play in
37 sp_state = "new" # {new,join,bid,play}
38 sp_owner = "" # Who started the game
39 sp_playto = 0 # Score the game will go to
40 sp_dealer =-1 # Who is dealing this round
41 sp_turn = 0 # Index of who's turn it is
42 sp_player = "" # Who's turn it is
43 sp_valid = 0 # Message sent from sp_player
44 delete sp_hands # [p] Each players cards
45 delete sp_players # [p] Player names players["name"] -> i
46 delete sp_order # [i] Player order order[i] -> "name"
47 delete sp_scores # [i] Teams score
51 function sp_pretty(cards, who)
54 gsub(/[0-9JQKA]*[sc]/, "\0031,00\002&\017", cards) # black
55 gsub(/[0-9JQKA]*[hd]/, "\0034,00\002&\017", cards) # red
56 gsub(/s/, "\002♠", cards)
57 gsub(/h/, "\002♥", cards)
58 gsub(/d/, "\002♦", cards)
59 gsub(/c/, "\002♣", cards)
64 function sp_next(who, prev)
67 sp_turn = who ? sp_players[who] : (sp_turn + 1) % 4
68 if (length(sp_order) == 4)
69 sp_player = sp_order[sp_turn]
73 function sp_deal( shuf)
75 say("/me deals the cards")
76 asorti(sp_deck, shuf, "sp_usort")
78 sp_hands[sp_order[i%4]][shuf[i]] = 1
80 sp_dealer = (sp_dealer+1)%4
82 sp_player = sp_order[sp_turn]
83 say("Bidding starts with " sp_player "!")
86 function sp_hand(who, sort, str)
88 asorti(sp_hands[who], sort, "sp_csort")
89 for (i=0; i<length(sort); i++)
90 str = str "" sprintf("%4s", sort[i])
91 gsub(/^ +| +$/, "", str)
92 return sp_pretty(str, who)
95 function sp_hasa(who, expr)
97 for (c in sp_hands[who]) {
104 function sp_type(card)
106 return substr(card, length(card))
109 function sp_usort(a,b,c,d) {
113 function sp_csort(i1,v1,i2,v2) {
114 return sp_deck[i1] > sp_deck[i2] ? +1 :
115 sp_deck[i1] < sp_deck[i2] ? -1 : 0;
118 function sp_winner( card, tmp)
120 for (card in sp_pile)
121 if (card !~ sp_suit && card !~ /s/)
123 asorti(sp_pile, tmp, "sp_csort")
124 #print "pile: " tmp[1] ">" tmp[2] ">" tmp[3] ">" tmp[4]
130 #return "{" sp_order[i+0] "," sp_order[i+2] "}"
131 return sp_order[i+0] "/" sp_order[i+2]
134 function sp_bags(i, bags)
136 bags = sp_scores[i] % 10
142 function sp_score( bids, tricks)
144 for (i=0; i<2; i++) {
145 bids = sp_bids[i] + sp_bids[i+2]
146 tricks = sp_tricks[i] + sp_tricks[i+2]
148 if (sp_bags(i) + bags >= 10) {
149 say(sp_team(i) " bag out")
152 if (tricks >= bids) {
153 say(sp_team(i) " make their bid: " tricks "/" bids)
154 sp_scores[i] += bids*10 + bags;
156 say(sp_team(i) " go bust: " tricks "/" bids)
157 sp_scores[i] -= bids*10;
160 for (i=0; i<4; i++) {
163 say(sp_order[i] " " \
164 (sp_nil[i] == 1 && !sp_tricks[i] ? "makes nil!" :
165 sp_nil[i] == 1 && sp_tricks[i] ? "fails at nil!" :
166 sp_nil[i] == 2 && !sp_tricks[i] ? "makes blind nil!" :
167 sp_nil[i] == 2 && sp_tricks[i] ? "fails miserably at blind nil!" :
169 sp_scores[i%2] += 100 * sp_nil[i] * \
170 (sp_tricks[i] == 0 ? 1 : -1)
174 function sp_play(card, winner, pi)
176 delete sp_hands[FROM][card]
177 sp_pile[card] = sp_player
178 sp_piles = sp_piles (sp_piles?",":"") card
185 if (length(sp_pile) == 1)
186 sp_suit = sp_type(card)
189 if (length(sp_pile) == 4) {
191 pi = sp_players[sp_pile[winner]]
193 say(sp_pile[winner] " wins with " sp_pretty(winner, FROM) \
194 " (" sp_pretty(sp_piles, FROM) ")")
195 sp_next(sp_pile[winner])
200 if (sp_tricks[0] + sp_tricks[1] + \
201 sp_tricks[2] + sp_tricks[3] == 13) {
204 if (sp_scores[0] >= sp_playto || sp_scores[1] >= sp_playto &&
205 sp_scores[0] != sp_scores[1]) {
207 winner = sp_scores[0] > sp_scores[1] ? 0 : 1
209 say(sp_team(winner) " wins the game " \
210 sp_scores[winner] " to " sp_scores[looser])
211 say(sp_order[winner+0] "++")
212 say(sp_order[winner+2] "++")
213 say(sp_order[looser+0] "--")
214 say(sp_order[looser+2] "--")
218 if (sp_scores[0] == sp_scores[1] &&
219 sp_scores[0] >= sp_playto)
220 say("It's tie! Playing an extra round!");
229 cmd = "od -An -N4 -td4 /dev/random"
238 sp_valid = (FROM && FROM == sp_player)
243 say("Spades! " sp_pretty("As,Ah,Ad,Ac", FROM))
247 /^\.help [Ss]pades$/ {
248 say("Spades -- play a game of spades")
250 say(".newgame [score] -- start a game to <score> points, default 500")
251 say(".endgame -- abort the current game")
252 say(".join -- join the current game")
253 say(".look -- look at your cards")
254 say(".bid n -- bid for <n> tricks")
255 say(".play [card] -- play a card")
256 say(".score -- check the score")
257 say(".tricks -- check how many trick have been taken")
258 say(".bids -- check what everyone bid")
264 /^\.deal (\w+) (.*)/ {
266 for (i=3; i<=NF; i++)
268 say(sp_channel, FROM " is cheating for " $2)
273 /^\.newgame ?([0-9]+)?/ {
274 if (sp_state != "new") {
275 reply("There is already a game in progress.")
278 sp_playto = $2 ? $2 : 200
281 say(sp_owner " starts a game of Spades to " sp_playto "!")
282 #say("#rhnoise", sp_owner " starts a game of Spades in " DST "!")
286 (FROM == sp_owner || FROM == OWNER) &&
288 if (sp_state == "new") {
289 reply("There is no game in progress.")
291 say(FROM " ends the game")
297 if (sp_state == "new") {
298 reply("There is no game in progress")
300 else if (sp_state == "play") {
301 reply("The game has already started")
303 else if (sp_state == "join" && FROM in sp_players) {
304 reply("You are already playing")
306 else if (sp_state == "join") {
310 say(FROM " joins the game!")
312 if (sp_state == "join" && sp_turn == 0)
317 (sp_state "bid" || sp_state == "play") &&
319 if (FROM in sp_players)
320 say(".slap " FROM ", it is not your turn.")
322 say(".slap " FROM ", you are not playing.")
328 if ($2 < 0 || $2 > 13) {
329 say("You can only bid from 0 to 13")
333 if ($2 == 0 && !sp_looked[i]) {
334 say(FROM " goes blind nil!")
336 } else if ($2 == 0) {
337 say(FROM " goes nil!")
342 if (sp_turn != sp_dealer) {
343 say("Bidding goes to " sp_player "!")
345 for (p in sp_players)
346 say(p, "You have: " sp_hand(p))
348 for (i=0; i<2; i++) {
349 if (sp_nil[i] == 2 || sp_nil[i+2] == 2) {
350 say(sp_team(i) ": select a card to pass " \
351 "(/msg " NICK " .pass <card>)")
355 if (sp_state == "play")
356 say("Play starts with " sp_player "!")
361 sp_state == "pass" &&
364 team = sp_players[FROM] % 2
365 if (!(FROM in sp_players)) {
366 say(".slap " FROM ", you are not playing.")
368 else if (sp_nil[team] != 2 && sp_nil[team+2] != 2) {
369 reply("Your team did not go blind")
371 else if (sp_pass[sp_players[FROM]]) {
372 reply("You have already passed a card")
374 else if (!(card in sp_deck)) {
375 reply("Invalid card")
377 else if (!(card in sp_hands[FROM])) {
378 reply("You do not have that card")
381 sp_pass[sp_players[FROM]] = $2
382 say(sp_channel, FROM " passes a card")
384 if (((sp_nil[0] != 2 && sp_nil[2] != 2) || (sp_pass[0] && sp_pass[2])) &&
385 ((sp_nil[1] != 2 && sp_nil[3] != 2) || (sp_pass[1] && sp_pass[3]))) {
389 delete sp_hands[sp_order[i]][card]
390 sp_hands[sp_order[partner]][card] = 1
392 say(sp_channel, "Cards have been passed, play starts with " sp_player "!")
393 for (p in sp_players)
394 say(p, "You have: " sp_hand(p))
399 sp_state ~ "(play|bid)" &&
401 if (!(FROM in sp_players)) {
402 say(".slap " FROM ", you are not playing.")
404 sp_looked[sp_players[FROM]] = 1
405 say(FROM, "You have: " sp_hand(FROM))
410 sp_state == "play" &&
413 if (!(card in sp_deck)) {
414 reply("Invalid card")
416 else if (!(card in sp_hands[FROM])) {
417 reply("You do not have that card")
419 else if (sp_suit && card !~ sp_suit && sp_hasa(FROM, sp_suit)) {
420 reply("You must follow suit (" sp_suit ")")
422 else if (card ~ /s/ && length(sp_hands[FROM]) == 13 && sp_hasa(FROM, "[^s]$")) {
423 reply("You cannot trump on the first hand")
425 else if (card ~ /s/ && length(sp_pile) == 0 && sp_hasa(FROM, "[^s]$") && !sp_broken) {
426 reply("Spades have not been broken")
430 if (sp_state == "play") {
431 if (length(sp_hands[FROM]))
432 say(FROM, "You have: " sp_hand(FROM))
434 say(sp_player ": it is your turn! " \
435 "(" sp_pretty(sp_piles, sp_player) ")")
437 say(sp_player ": it is your turn!")
442 /^\.bids$/ && sp_state == "play" {
443 say(sp_order[0] " bid " sp_bids[0] ", " \
444 sp_order[2] " bid " sp_bids[2] ", " \
445 "total: " sp_bids[0] + sp_bids[2])
446 say(sp_order[1] " bid " sp_bids[1] ", " \
447 sp_order[3] " bid " sp_bids[3] ", " \
448 "total: " sp_bids[1] + sp_bids[3])
451 /^\.tricks$/ && sp_state == "play" {
452 say(sp_order[0] " took " int(sp_tricks[0]) "/" int(sp_bids[0]) ", " \
453 sp_order[2] " took " int(sp_tricks[2]) "/" int(sp_bids[2]))
454 say(sp_order[1] " took " int(sp_tricks[1]) "/" int(sp_bids[1]) ", " \
455 sp_order[3] " took " int(sp_tricks[3]) "/" int(sp_bids[3]))
458 (TO == NICK || DST == sp_channel) &&
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 players: " \
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