## THE100 written by Yさ ## ## HELP 表示 ## function helpDisp() { print ""; ## 0....5....0....5....0....5....0....5....0....5 print " 1 ... +1 or +11 2 ... +2 or Nominate"; print " 9 ... +0 - +9 J ... +11 or Skip "; print " 10 ... +10 or -10 Q ... +12 or Reverse "; print " K ... +13 or 99 "; } function rnd(N){ return int(N * rand()); } ## 乱数 BEGIN{ ## カード ## Cards[key, 52]; ## カード本体 split("H,D,C", StrSuit, ","); StrSuit[0]="S"; split(" 2, 3, 4, 5, 6, 7, 8, 9,10, J, Q, K", StrRank, ","); StrRank[0]=" A"; ## Table[52]; ## 台札 ## CardPos; ## 台札の一番上のカードを表す位置 ## Hands[4, 3]; ## 手札 ## プレイヤー名 split("COM1,COM2,COM3", Player, ","); Player[0]="YOU "; srand(); ## 乱数の初期化 makeCards(); ## カードを用意して... CardPos = shuffle(); ## カードを切り... firstDeal(); ## 手札を配って ## 場に1枚出す ##  [0-11]の12枚は手札として配られています ##  場札を[CardPos-12]へ出してから[CardPos]から手札を1枚引きます Total=Cards["rank", Table[CardPos]] +1; ## 0-12 -> 1-13 Table[CardPos-12]=Table[CardPos]; ++CardPos; ## Turn, Dir, Total; ## 順番, 方向, 合計 ## Times[2]; ## 回数 Dir=1; ## YOU→COM1→... Turn=-1; ## next = Turn + Dir = 0 = YOU Times[0]=Times[1]=0; ## 0....5....0....5....0....5....0 ## <- 10 -><- 20 ->## [D K] Total:99 ## printf("\n%*s", 10+20, " "); ## 表示調整 ## 場の合計が100未満の間繰り返し while(Total<100){ Turn += Dir; if(Turn>3) Turn=0; else if(Turn<0) Turn=3; printf("## [%s%s] total:%-2d", StrSuit[Cards["suit", Table[CardPos-12-1]]], StrRank[Cards["rank", Table[CardPos-12-1]]], Total); printf("\n%2d >> %4s", 1+Times[0]+Times[1], Player[Turn]); if(Turn==0) man(); else com(); if(Total<100) ++Times[((Turn==0)?(0):(1))]; } exit; } END{ ## Game Over msg = sprintf("%4s 100", ((Total==100)?("Just"):("Over"))); printf(" ... %-*s", 20-5, msg); printf("## [%1s%2s] Total:%-2d", StrSuit[Cards["suit", Table[CardPos-12]]], StrRank[Cards["rank", Table[CardPos-12]]], Total); printf("\n\n %4s lose\n", Player[Turn]); printf("\n## Result: %d/%-d (%d%%)\n", Times[0], Times[0]+Times[1], Times[0]*100/(Times[0]+Times[1])); } ## ## カード本体 と 台札 の作成 ## function makeCards( i, j) { for(i=0; i<4; ++i){ for(j=0; j<13; ++j){ Cards["suit", (i*13 +j)] = i; ## マーク Cards["rank", (i*13 +j)] = j; ## 数字 Table[i*13 +j] = i*13 +j; } } } ## ## カードを切る ## function swap(p1, p2, tmp){ tmp = Table[p1]; Table[p1] = Table[p2]; Table[p2] = tmp; } function shuffle( i) { for(i=0; i<52; ++i) swap(rnd(52), i); ## 台札から適当な一枚を選んで... ## それを i番目のカードと入れ替えましょう return 0; ## (次の札は台札の先頭) } ## ## 台札無いのでカードを切る ## function reShuffle( i, x, tmp, last, stock) { ## 最初に[0-11]の12枚は手札として配られています ## 場札を[CardPos-12]へ出してから[CardPos]から手札を1枚引きます ## → 最後の場札は[51-12]です last=51-12; ## 最後の場札を退避 stock=Table[last]; for(i=0; i<=last-1; ++i) swap(rnd(last), i); ## 出ていた札をシャッフル for(i=0; i<=last-1; ++i) Table[51-i]=Table[51-i -12]; ## ずらして... Table[0]=stock; ## 退避した場札を戻す return 12+1; ## (台札の先頭) } ## ## 手札の並べ替え ## function sortHands(who, i, j, tmp) { ## 数字順(同じ数字ならマーク順)に並べ替える for(i=0; i<=1; ++i){ for(j=i+1; j<=2; ++j){ tmp = Hands[who, i]; if(Cards["rank", tmp]51) CardPos = reShuffle(); } } function firstDeal( who, te) { for(te=0; te<3; ++te){ for(who=0; who<4; ++who) deal(who, te); } } ## ## 手札の表示 ## function putHands( i) { printf("\n%2s", " "); for(i=0; i<3; ++i) printf("[%1s%2s]", StrSuit[Cards["suit", Hands[0, i]]], StrRank[Cards["rank", Hands[0, i]]]); printf("\n%2s -1- -2- -3- %2s", " ", " "); ## <- 2 +5*3 + 2 -> の幅 } ## ## 1を使う ## function use1( tmp, no) { no = 1; ## 仮 if(Total+11 <= 99){ do{ printf("%*sHow? (1 or 11) > ", 2 +5*3 +2, " "); no=0; getline no; }while(no!=1 && no!=11); } Total += no; } ## ## 2を使う ## function use2( tmp, no) { do{ printf("%*sNominate? (Yes:1-3 or No:0) > ", 2 +5*3 +2, " "); no=0; getline no; }while(no<0 || 30) Turn = no - Dir; else Total += 2; } ## ## 9を使う ## function use9( tmp, no) { if(Total<99){ do{ printf("%*sHow? (0-9) > ", 2 +5*3 +2, " "); no=0; getline no; }while(no<0 || 9 ", 2 +5*3 +2, " "); no=0; getline no; }while(no!=10 && no!=-10); } Total += no; } ## ## 11を使う ## function use11( tmp, no) { no = 0; ## 仮 if(Total+11 <= 99){ do{ printf("%*sSkip? (Yes:0 or No:11) > ", 2 +5*3 +2, " "); no=0; getline no; }while(no!=0 && no!=11); } if(no==0) Turn = 2 - Dir; ## スキップするとCOM2 else Total += 11; } ## ## 12を使う ## function use12( tmp, no) { no = 0; ## 仮 if(Total+12 <= 99){ do{ printf("%*sReverse? (Yes:0 or No:12) > ", 2 +5*3 +2, " "); no=0; getline no; }while(no!=0 && no!=12); } if(no==0) Dir *= -1; else Total += 12; } ## ## 13を使う ## function use13( tmp, no) { no = 99; ## 仮 if(Total+13 <= 99){ do{ printf("%*s99? (Yes:99 or No:13) > ", 2 +5*3 +2, " "); no=0; getline no; }while(no!=99 && no!=13); } if(no==99) Total = 99; else Total += 13; } ## ## 人間main ## function man( tmp, no, val) { sortHands(0); ## 手札の表示 putHands(); do{ ## カードの番号を入力 printf("Which (1-3)? > "); no=0; getline no; if(no=="h" || no=="H" || no=="?"){ ## help ! helpDisp(); putHands(); } }while(no<1 || 3 0-2 ## カードの役を使うかを入力 val=Cards["rank", Hands[0, no]] +1; ## 0-12 -> 1->13 if(val== 1) use1(); else if(val== 2) use2(); else if(val== 9) use9(); else if(val==10) use10(); else if(val==11) use11(); else if(val==12) use12(); else if(val==13) use13(); else Total += val; deal(0, no); ## 手札を引く printf("\n%*s", ((Total<100)?(10+20):(10)), " "); ## ゲーム続行/終了時表示調整 } ## ## COM main ## function com( no, val, use, nextTurn) { sortHands(Turn); ## カス札から出す use = 0; ## 役は使わない for(no=2; no>=0; --no){ val=Cards["rank", Hands[Turn, no]] +1; if(Total+val<=99 && val<9 && val!=2) return com_PUT_HAND(val, use, no, Turn, nextTurn); } ## 役札を出す nextTurn = Turn+Dir; if(nextTurn<0 || 3=100-13-1){ if(Turn==2){ ## COM2 は 両隣を助ける for(no=2; no>=0; --no){ val=Cards["rank", Hands[Turn, no]] +1; if(val==11 || val==10 || val==2){ use=1; return com_PUT_HAND(val, use, no, Turn, nextTurn); } } }else if(nextTurn!=0){ ## 次が人間ではないので助ける for(no=2; no>=0; --no){ val=Cards["rank", Hands[Turn, no]] +1; if(val==10 || (val==12 && Turn-Dir==0) || (val==9 && Total<99)){ use=1; return com_PUT_HAND(val, use, no, Turn, nextTurn); } } }else if(nextTurn==0){ ## 次が人間 for(no=2; no>=0; --no){ val=Cards["rank", Hands[Turn, no]] +1; if(val==1 && Total+11<=99){ use=1; return com_PUT_HAND(val, use, no, Turn, nextTurn); } } for(no=2; no>=0; --no){ val=Cards["rank", Hands[Turn, no]] +1; if(val==13){ use=1; return com_PUT_HAND(val, use, no, Turn, nextTurn); } } for(no=2; no>=0; --no){ val=Cards["rank", Hands[Turn, no]] +1; if(val==10 || val==9) return com_PUT_HAND(val, use, no, Turn, nextTurn); } } } ## とりあえず自分が負けないように(役札があればそれを)出す for(no=2; no>=0; --no){ val=Cards["rank", Hands[Turn, no]] +1; if(val>=9 || val==2) return com_PUT_HAND(val, use, no, Turn, nextTurn); } if(no<0) no=0; com_PUT_HAND(val, use, no, Turn, nextTurn); } function com_PUT_HAND(val, use, no, nowTurn, nextTurn) { if(Total+val>99 || use==1){ ## 役札なら使う if(val== 2){ msg = "Nominate YOU"; Turn = -Dir; ## next = Turn + Dir = 0 -> YOU val = 0; }else if(val== 9){ if(nextTurn!=0) val=0; else{ val = 99-Total; if(val>9) val=9; } msg = sprintf("+%2d", val); Total+=val; val = 0; }else if(val==10){ msg = "-10"; Total-=10; val = 0; }else if(val==11){ msg = "Skip"; Turn += Dir; if(Turn>3) Turn=0; else if(Turn<0) Turn=3; val = 0; }else if(val==12){ msg = "Reverse"; Dir *= -1; val = 0; }else if(val==13){ msg = "99"; Total = 99; val = 0; }else if(val== 1 && Total+11<=99){ msg = "+11"; Total+=11; val = 0; } } Total += val; if(val==0) printf(" ... %-*s", 20-5, msg); else if(Total<=99) printf("%*s", 20, " "); ## 続行時表示調整 deal(nowTurn, no); ## 手札を引く }