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 sp_player = sp_order[sp_turn]
72 function sp_deal( shuf)
74 say("/me deals the cards")
75 asorti(sp_deck, shuf, "sp_usort")
77 sp_hands[sp_order[i%4]][shuf[i]] = 1
79 sp_dealer = (sp_dealer+1)%4
81 sp_player = sp_order[sp_turn]
82 say("Bidding starts with " sp_player "!")
85 function sp_hand(who, sort, str)
87 asorti(sp_hands[who], sort, "sp_csort")
88 for (i=0; i<length(sort); i++)
89 str = str "" sprintf("%4s", sort[i])
90 gsub(/^ +| +$/, "", str)
91 return sp_pretty(str, who)
94 function sp_hasa(who, expr)
96 for (c in sp_hands[who]) {
103 function sp_type(card)
105 return substr(card, length(card))
108 function sp_usort(a,b,c,d) {
112 function sp_csort(i1,v1,i2,v2) {
113 return sp_deck[i1] > sp_deck[i2] ? +1 :
114 sp_deck[i1] < sp_deck[i2] ? -1 : 0;
117 function sp_winner( card, tmp)
119 for (card in sp_pile)
120 if (card !~ sp_suit && card !~ /s/)
122 asorti(sp_pile, tmp, "sp_csort")
123 #print "pile: " tmp[1] ">" tmp[2] ">" tmp[3] ">" tmp[4]
129 #return "{" sp_order[i+0] "," sp_order[i+2] "}"
130 return sp_order[i+0] "/" sp_order[i+2]
133 function sp_bags(i, bags)
135 bags = sp_scores[i] % 10
141 function sp_score( bids, tricks)
143 for (i=0; i<2; i++) {
144 bids = sp_bids[i] + sp_bids[i+2]
145 tricks = sp_tricks[i] + sp_tricks[i+2]
147 if (sp_bags(i) + bags >= 10) {
148 say(sp_team(i) " bag out")
151 if (tricks >= bids) {
152 say(sp_team(i) " make their bid: " tricks "/" bids)
153 sp_scores[i] += bids*10 + bags;
155 say(sp_team(i) " go bust: " tricks "/" bids)
156 sp_scores[i] -= bids*10;
159 for (i=0; i<4; i++) {
162 say(sp_order[i] " " \
163 (sp_nil[i] == 1 && !sp_tricks[i] ? "makes nil!" :
164 sp_nil[i] == 1 && sp_tricks[i] ? "fails at nil!" :
165 sp_nil[i] == 2 && !sp_tricks[i] ? "makes blind nil!" :
166 sp_nil[i] == 2 && sp_tricks[i] ? "fails miserably at blind nil!" :
168 sp_scores[i%2] += 100 * sp_nil[i] * \
169 (sp_tricks[i] == 0 ? 1 : -1)
173 function sp_play(card, winner, pi)
175 delete sp_hands[FROM][card]
176 sp_pile[card] = sp_player
177 sp_piles = sp_piles (sp_piles?",":"") card
184 if (length(sp_pile) == 1)
185 sp_suit = sp_type(card)
188 if (length(sp_pile) == 4) {
190 pi = sp_players[sp_pile[winner]]
192 say(sp_pile[winner] " wins with " sp_pretty(winner, FROM) \
193 " (" sp_pretty(sp_piles, FROM) ")")
194 sp_next(sp_pile[winner])
199 if (sp_tricks[0] + sp_tricks[1] + \
200 sp_tricks[2] + sp_tricks[3] == 13) {
203 if (sp_scores[0] >= sp_playto || sp_scores[1] >= sp_playto &&
204 sp_scores[0] != sp_scores[1]) {
206 winner = sp_scores[0] > sp_scores[1] ? 0 : 1
208 say(sp_team(winner) " wins the game " \
209 sp_scores[winner] " to " sp_scores[looser])
210 say(sp_order[winner+0] "++")
211 say(sp_order[winner+2] "++")
212 say(sp_order[looser+0] "--")
213 say(sp_order[looser+2] "--")
217 if (sp_scores[0] == sp_scores[1] &&
218 sp_scores[0] >= sp_playto)
219 say("It's tie! Playing an extra round!");
228 cmd = "od -An -N4 -td4 /dev/random"
237 sp_valid = (FROM && FROM == sp_player)
242 say("Spades! " sp_pretty("As,Ah,Ad,Ac", FROM))
246 /^\.help [Ss]pades$/ {
247 say("Spades -- play a game of spades")
249 say(".newgame [score] -- start a game to <score> points, default 500")
250 say(".endgame -- abort the current game")
251 say(".join -- join the current game")
252 say(".look -- look at your cards")
253 say(".bid n -- bid for <n> tricks")
254 say(".play [card] -- play a card")
255 say(".score -- check the score")
256 say(".tricks -- check how many trick have been taken")
257 say(".bids -- check what everyone bid")
263 /^\.deal (\w+) (.*)/ {
265 for (i=3; i<=NF; i++)
267 say(sp_channel, FROM " is cheating for " $2)
272 /^\.newgame ?([0-9]+)?/ {
273 if (sp_state != "new") {
274 reply("There is already a game in progress.")
277 sp_playto = $2 ? $2 : 200
280 say(sp_owner " starts a game of Spades to " sp_playto "!")
281 #say("#rhnoise", sp_owner " starts a game of Spades in " DST "!")
285 (FROM == sp_owner || FROM == OWNER) &&
287 if (sp_state == "new") {
288 reply("There is no game in progress.")
290 say(FROM " ends the game")
296 if (sp_state == "new") {
297 reply("There is no game in progress")
299 else if (sp_state == "play") {
300 reply("The game has already started")
302 else if (sp_state == "join" && FROM in sp_players) {
303 reply("You are already playing")
305 else if (sp_state == "join") {
309 say(FROM " joins the game!")
311 if (sp_state == "join" && sp_turn == 0)
316 (sp_state "bid" || sp_state == "play") &&
318 if (FROM in sp_players)
319 say(".slap " FROM ", it is not your turn.")
321 say(".slap " FROM ", you are not playing.")
327 if ($2 < 0 || $2 > 13) {
328 say("You can only bid from 0 to 13")
332 if ($2 == 0 && !sp_looked[i]) {
333 say(FROM " goes blind nil!")
335 } else if ($2 == 0) {
336 say(FROM " goes nil!")
339 if (sp_turn != sp_dealer) {
340 say("Bidding goes to " sp_player "!")
342 for (p in sp_players)
343 say(p, "You have: " sp_hand(p))
345 for (i=0; i<2; i++) {
346 if (sp_nil[i] == 2 || sp_nil[i+2] == 2) {
347 say(sp_team(i) ": select a card to pass " \
348 "(/msg " NICK " .pass <card>)")
352 if (sp_state == "play")
353 say("Play starts with " sp_player "!")
358 sp_state == "pass" &&
361 team = sp_players[FROM] % 2
362 if (!(FROM in sp_players)) {
363 say(".slap " FROM ", you are not playing.")
365 else if (sp_nil[team] != 2 && sp_nil[team+2] != 2) {
366 reply("Your team did not go blind")
368 else if (sp_pass[sp_players[FROM]]) {
369 reply("You have already passed a card")
371 else if (!(card in sp_deck)) {
372 reply("Invalid card")
374 else if (!(card in sp_hands[FROM])) {
375 reply("You do not have that card")
378 sp_pass[sp_players[FROM]] = $2
379 say(sp_channel, FROM " passes a card")
381 if (((sp_nil[0] != 2 && sp_nil[2] != 2) || (sp_pass[0] && sp_pass[2])) &&
382 ((sp_nil[1] != 2 && sp_nil[3] != 2) || (sp_pass[1] && sp_pass[3]))) {
386 delete sp_hands[sp_order[i]][card]
387 sp_hands[sp_order[partner]][card] = 1
389 say(sp_channel, "Cards have been passed, play starts with " sp_player "!")
390 for (p in sp_players)
391 say(p, "You have: " sp_hand(p))
396 sp_state ~ "(play|bid)" &&
398 if (!(FROM in sp_players)) {
399 say(".slap " FROM ", you are not playing.")
401 sp_looked[sp_players[FROM]] = 1
402 say(FROM, "You have: " sp_hand(FROM))
407 sp_state == "play" &&
410 if (!(card in sp_deck)) {
411 reply("Invalid card")
413 else if (!(card in sp_hands[FROM])) {
414 reply("You do not have that card")
416 else if (sp_suit && card !~ sp_suit && sp_hasa(FROM, sp_suit)) {
417 reply("You must follow suit (" sp_suit ")")
419 else if (card ~ /s/ && length(sp_hands[FROM]) == 13 && sp_hasa(FROM, "[^s]$")) {
420 reply("You cannot trump on the first hand")
422 else if (card ~ /s/ && length(sp_pile) == 0 && sp_hasa(FROM, "[^s]$") && !sp_broken) {
423 reply("Spades have not been broken")
427 if (sp_state == "play") {
429 say(FROM, "You have: " sp_hand(FROM))
431 say(sp_player ": it is your turn! " \
432 "(" sp_pretty(sp_piles, sp_player) ")")
434 say(sp_player ": it is your turn!")
439 /^\.bids$/ && sp_state == "play" {
440 say(sp_order[0] " bid " sp_bids[0] ", " \
441 sp_order[2] " bid " sp_bids[2] ", " \
442 "total: " sp_bids[0] + sp_bids[2])
443 say(sp_order[1] " bid " sp_bids[1] ", " \
444 sp_order[3] " bid " sp_bids[3] ", " \
445 "total: " sp_bids[1] + sp_bids[3])
448 /^\.tricks$/ && sp_state == "play" {
449 say(sp_order[0] " took " int(sp_tricks[0]) "/" int(sp_bids[0]) ", " \
450 sp_order[2] " took " int(sp_tricks[2]) "/" int(sp_bids[2]))
451 say(sp_order[1] " took " int(sp_tricks[1]) "/" int(sp_bids[1]) ", " \
452 sp_order[3] " took " int(sp_tricks[3]) "/" int(sp_bids[3]))
455 (TO == NICK || DST == sp_channel) &&
456 /^\.(score|status)$/ {
457 if (sp_state == "new") {
458 say("There is no game in progress")
460 if (sp_state == "join") {
461 say("Waiting for players: " \
462 sp_order[0] " " sp_order[1] " " \
463 sp_order[2] " " sp_order[3])
465 if (sp_state == "bid" || sp_state == "play") {
466 say(sp_team(0) ": " \
467 int(sp_scores[0]) " points, " \
468 int(sp_bags(0)) " bags")
469 say(sp_team(1) ": " \
470 int(sp_scores[1]) " points, " \
471 int(sp_bags(1)) " bags")
476 #/^\.playfor [^ ]*$/ {
479 #/^\.standin [^ ]*$/ {
480 # if (p in sp_players) {
482 # for (p in sp_standin) {
483 # if ($2 in sp_standin)
484 # say(here " is already playing for " sp_standin[p]);
486 # sp_standin[away] = here