2 function sp_init(cards, tmp0, tmp1)
4 sp_valid = 0 # Message sent from sp_player
5 sp_player = "" # Who's turn it is
6 sp_turn = 0 # Index of who's turn it is
7 delete sp_hands # [p] Each players cards
10 cards ="As Ks Qs Js 10s 9s 8s 7s 6s 5s 4s 3s 2s "\
11 "Ah Kh Qh Jh 10h 9h 8h 7h 6h 5h 4h 3h 2h "\
12 "Ac Kc Qc Jc 10c 9c 8c 7c 6c 5c 4c 3c 2c "\
13 "Ad Kd Qd Jd 10d 9d 8d 7d 6d 5d 4d 3d 2d"
15 for (i=1; i<=length(tmp0); i++)
19 function sp_reset(type)
23 sp_suit = "" # The lead suit {s,h,d,c}
24 sp_piles = "" # [x] Played cards this turn
25 delete sp_pile # [x] Played cards this turn
30 sp_state = "bid" # {new,join,bid,pass,play}
31 sp_broken = 0 # Whether spades are broken
32 delete sp_looked # [i] Whether a player has looked a their cards
33 delete sp_bids # [i] Each players bid
34 delete sp_nil # [i] Nil multiplier 0=regular, 1=nil, 2=blind
35 delete sp_pass # [i] Cards to pass
36 delete sp_tricks # [i] Tricks this round
41 sp_channel = "" # channel to play in
42 sp_state = "new" # {new,join,bid,play}
43 sp_owner = "" # Who started the game
44 sp_playto = 0 # Score the game will go to
45 sp_dealer =-1 # Who is dealing this round
46 delete sp_players # [p] Player names players["name"] -> i
47 delete sp_order # [i] Player order order[i] -> "name"
48 delete sp_scores # [i] Teams score
52 function sp_pretty(cards, who)
55 gsub(/[0-9JQKA]*[sc]/, "\0031,00\002&\017", cards) # black
56 gsub(/[0-9JQKA]*[hd]/, "\0034,00\002&\017", cards) # red
57 gsub(/s/, "\002♠", cards)
58 gsub(/h/, "\002♥", cards)
59 gsub(/d/, "\002♦", cards)
60 gsub(/c/, "\002♣", cards)
65 function sp_next(who, prev)
68 sp_turn = who ? sp_players[who] : (sp_turn + 1) % 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")
154 sp_scores[i] += bids*10 + bags;
156 say(sp_team(i) " go bust")
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 privmsg(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 #privmsg("#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!")
340 if (sp_turn != sp_dealer) {
341 say("Bidding goes to " sp_player "!")
343 for (p in sp_players)
344 privmsg(p, "You have: " sp_hand(p))
346 for (i=0; i<2; i++) {
347 if (sp_nil[i] == 2 || sp_nil[i+2] == 2) {
348 say(sp_team(i) ": select a card to pass " \
349 "(/msg " NICK " .pass <card>)")
353 if (sp_state == "play")
354 say("Play starts with " sp_player "!")
359 sp_state == "pass" &&
362 team = sp_players[FROM] % 2
363 if (!(FROM in sp_players)) {
364 say(".slap " FROM ", you are not playing.")
366 else if (sp_nil[team] != 2 && sp_nil[team+2] != 2) {
367 reply("Your team did not go blind")
369 else if (sp_pass[sp_players[FROM]]) {
370 reply("You have already passed a card")
372 else if (!(card in sp_deck)) {
373 reply("Invalid card")
375 else if (!(card in sp_hands[FROM])) {
376 reply("You do not have that card")
379 sp_pass[sp_players[FROM]] = $2
380 privmsg(sp_channel, FROM " passes a card")
382 if (((sp_nil[0] != 2 && sp_nil[2] != 2) || (sp_pass[0] && sp_pass[2])) &&
383 ((sp_nil[1] != 2 && sp_nil[3] != 2) || (sp_pass[1] && sp_pass[3]))) {
387 delete sp_hands[sp_order[i]][card]
388 sp_hands[sp_order[partner]][card] = 1
390 privmsg(sp_channel, "Cards have been passed, play starts with " sp_player "!")
391 for (p in sp_players)
392 privmsg(p, "You have: " sp_hand(p))
397 sp_state ~ "(play|bid)" &&
399 if (!(FROM in sp_players)) {
400 say(".slap " FROM ", you are not playing.")
402 sp_looked[sp_players[FROM]] = 1
403 privmsg(FROM, "You have: " sp_hand(FROM))
408 sp_state == "play" &&
411 if (!(card in sp_deck)) {
412 reply("Invalid card")
414 else if (!(card in sp_hands[FROM])) {
415 reply("You do not have that card")
417 else if (sp_suit && card !~ sp_suit && sp_hasa(FROM, sp_suit)) {
418 reply("You must follow suit (" sp_suit ")")
420 else if (card ~ /s/ && length(sp_hands[FROM]) == 13 && sp_hasa(FROM, "[^s]$")) {
421 reply("You cannot trump on the first hand")
423 else if (card ~ /s/ && length(sp_pile) == 0 && sp_hasa(FROM, "[^s]$") && !sp_broken) {
424 reply("Spades have not been broken")
428 privmsg(FROM, "You have: " sp_hand(FROM))
429 if (sp_state == "play") {
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 palyers: " \
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