Tictactoe
From Scriptwiki
/* tic-tac-toe by Vliedel #help.script @ QuakeNet This script is a joke, yet fully functional You can play it over IRC, or at your own client Usage: /tictac [nick] [N M] where: nick: the nick on IRC you want to play against N: field size of N x N (default 3) M: number of crosses/circles you need to connect to win the game (default 3) Notes: -Yes it is slow, that was part of the joke: I draw each pixel seperately -Yes you can cheat, I didn't include enough checks against cheating -The script does not keep up nickchanges or anything like that -If anyting gets stuck, or you want to stop, just: /hfree tictac -You can change the number of the first 4 aliases to change the sizes of the drawings */ alias -l fontsize { return 15 } alias -l pix { return 300 } alias -l bordersize { return 10 } alias -l innersize { return 7 } alias tictac { ; if used as identifier, calculate and show the result if ($isid) { ; field size (square) var %field = $iif(($2 > 1) && (1 // $1),$2,3) ; you need to connect %win to win the game var %win = $iif(($3 > 1) && (1 // $1),$3,3) if ($len($1) !== $calc(%field ^2)) || ($calc($count($1,0) + $count($1,1) + $count($1,2)) < $v1) { return } ; check horizontal winnings var %h = $calc(%field - %win +1) while (%h) { var %i = $calc(%field * (%field - 1) + %h) while (%i > 0) { var %p = $mid($1,%i,1) , %w = %i if (%p) { var %j = $calc(%i + %win -1) while (%j > %i) { if ($mid($1,%j,1) !== %p) { var %p | break } var %w = %w %j dec %j } if (%p) { goto win } } dec %i %field } dec %h } ; check for vertical winnings var %h = $calc(%field - %win +1) , %i = $calc(%field * %h) while (%i) { var %p = $mid($1,%i,1) , %w = %i if (%p) { var %j = $calc(%i + %field * (%win -1)) while (%j > %i) { if ($mid($1,%j,1) !== %p) { var %p | break } var %w = %w %j dec %j %field } if (%p) { goto win } } dec %i } ; check for diagonal winnings (up left to low right) var %h = $calc(%field - %win +1) while (%h) { var %i = $calc(%field * (%h -1) + %h) while (%i > 0) { var %p = $mid($1,%i,1) , %w = %i if (%p) { var %j = $calc(%i + (%win -1) * (%field +1)) while (%j > %i) { if ($mid($1,%j,1) !== %p) { var %p | break } var %w = %w %j dec %j $calc(%field +1) } if (%p) { goto win } } dec %i %field } dec %h } ; check for diagonal winnings (up right to down left) var %h = $calc(%field - %win +1) while (%h) { var %i = $calc(%field * (%h -1) + %win + %h -1) while (%i > 0) { var %p = $mid($1,%i,1) , %w = %i if (%p) { var %j $calc(%i + (%win -1) * (%field -1)) while (%j > %i) { if ($mid($1,%j,1) !== %p) { var %p | break } var %w = %w %j dec %j $calc(%field -1) } if (%p) { goto win } } dec %i %field } dec %h } ; no winner was found, return 0 drawfield $1 %win return 0 ; if a winning player has been found, we end up here with %p the winning player :win drawfield $1 %win %p %w return %p } else { ; start a tictactoe game ; [$1 = nick] [$2 = field size $3 = number of crosses/circles you need to connect to win the game] var %vs if (($1 != $null) && ($1 == $gettok(%tictactoe.req,1,32))) { tokenize 32 %tictactoe.req | var %vs = 1 | .notice $v2 -tictactoe accept } if ($comchan($1,1)) { var %nick = $iif($1 !== $me,$1) | tokenize 32 $2- } var %field = $iif(($1 > 1) && (1 // $1),$1,3) var %win = $iif(($2 > 1) && (1 // $2),$2,3) if (%win > %field) { echo -ag Usage: /tictac [nick] [N M] echo -ag nick: the nick on IRC you want to play against echo -ag N = field size of N x N (default 3) echo -ag M = number of crosses/circles you need to connect to win the game (default 3) return } if ($hget(tictac)) { hfree tictac } var %state = $str(0,$calc(%field ^2)) hmake tictac hadd tictac turn 1 if (%vs) { hadd tictac me 2 } elseif (%nick) { hadd tictac me 1 } hadd tictac field %field hadd tictac win %win hadd tictac state %state hadd tictac nick %nick if (!%vs) && (%nick) { .notice %nick -tictactoe %field %win } else { drawfield %state %win } } } on ^*:NOTICE:-tictactoe state &:?:{ if ($hget(tictac,nick) == $nick) && ($sqrt($len($3)) == $hget(tictac,field)) { haltdef hadd tictac state $3 noop $tictac($3,$hget(tictac,field),$hget(tictac,win)) } } on ^*:NOTICE:-tictactoe & &:?:{ haltdef var %field = $iif(($2 > 1) && (1 // $2),$2,3) var %win = $iif(($3 > 1) && (1 // $3),$3,3) set -u300 %tictactoe.req $nick %field %win echo -ag $+($chr(2),tictactoe,$chr(2)) $nick wants to play a game of tictactoe with you. The field is $+(%field,x,%field) and you need to connect %win to win. echo -ag $+($chr(2),tictactoe,$chr(2)) Use /tictac $nick to accept the game. } on ^*:NOTICE:-tictactoe accept:?:{ if ($hget(tictac,nick) == $nick) { haltdef drawfield $hget(tictac,state) $hget(tictac,win) } } ; $1 = positions $2 = %win [$3 = winning player $4- = winning fields] alias -l drawfield { var %field = $sqrt($len($1)) , %w = $+(@,tictactoe_,%field,_,$2) if ($window(%w)) { window -c %w } window -aBfp +d %w 50 50 $pix $calc($pix + $height(I,Lucida Console,$fontsize) + 10) ; draw border lines var %h = $bordersize - 1 while (%h >= 0) { var %i = $calc($pix - %h -1) , %m = %i var %c = $rgb(255,$calc(255 - 128 / $int($bordersize /2) * %h),$calc(128 * ($bordersize - %h) / $bordersize)) while (%i >= %h) { drawdot -r %w %c 1 %i %h %i %m %m %i %h %i dec %i } dec %h } ; fill field with the background color var %x = $bordersize - 1 , %xm = $calc($pix - $bordersize -1) var %ym = $calc($pix - $bordersize -1) , %c = $rgb(15,15,15) while (%x <= %xm) { var %y = %x while (%y <= %ym) { drawdot -r %w %c 1 %x %y %y %x inc %y } inc %x } ; draw inner lines (innersize must be odd?) var %h = %field - 1 , %innerpix = $calc($pix - 2 * $bordersize) var %tilepix = $calc((%innerpix - (%field -1) * $innersize) / %field) while (%h) { var %i = 0 - $int($calc($innersize / 2)) , %m = $int($calc($innersize / 2)) while (%i <= %m) { var %y = $calc($pix - $bordersize -1) , %ym = $bordersize - 1 var %x = $round($calc($bordersize -1 + %tilepix * %h + $innersize * (%h -1) + $ceil($calc($innersize /2)) + %i),0) var %c = $rgb($calc(128 - 128 / $int($innersize /2) * $abs(%i)),$calc(128 - 128 / $int($innersize /2) * $abs(%i)),255) while (%y >= %ym) { drawdot -r %w %c 1 %x %y %y %x dec %y } inc %i } dec %h } /* ; fill each tile with the background color var %h = %field , %c = $rgb(15,15,15) while (%h) { var %i = %field while (%i >= %h) { var %x = $round($calc($bordersize -1 + (%h -1) * (%tilepix + $innersize)),0) , %xm = $round($calc(%x + %tilepix),0) while (%x <= %xm) { var %y = $round($calc($bordersize -1 + (%i -1) * (%tilepix + $innersize)),0) , %ym = $round($calc(%y + %tilepix),0) while (%y <= %ym) { drawdot -r %w %c 1 %x %y %y %x inc %y } inc %x } dec %i } dec %h } */ ; draw the crosses and circles var %h = %field while (%h) { var %i = %field while (%i) { var %pos = $calc((%h -1) * %field + %i) , %p = $mid($1,%pos,1) if (!%p) { dec %i | continue } var %xc = $round($calc($bordersize -1 + (%i -1) * (%tilepix + $innersize) + %tilepix / 2),0) var %yc = $round($calc($bordersize -1 + (%h -1) * (%tilepix + $innersize) + %tilepix / 2),0) if (%p == 1) { var %j = $round($calc(%tilepix * 0.4),0) , %c = $rgb(0,255,0) while (%j > -1) { drawdot -r %w %c 1 $calc(%xc + %j) $calc(%yc + %j) $calc(%xc - %j) $calc(%yc + %j) $calc(%xc + %j) $calc(%yc - %j) $calc(%xc - %j) $calc(%yc - %j) dec %j } if ($istok($4-,%pos,32)) { var %j = $round($calc(%tilepix * 0.3),0) , %c = $rgb(0,255,0) while (%j > -1) { drawdot -r %w %c 1 $calc(%xc + %j) %yc $calc(%xc - %j) %yc %xc $calc(%yc - %j) %xc $calc(%yc + %j) dec %j } } } elseif (%p == 2) { var %r = $round($calc(%tilepix * 0.4),0) , %c = $rgb(255,0,0) , %t = 360 while (%t) { drawdot -r %w %c 1 $calc(%xc + %r * $cos(%t).deg) $calc(%yc + %r * $sin(%t).deg) dec %t } if ($istok($4-,%pos,32)) { var %r = $round($calc(%tilepix * 0.3),0) , %c = $rgb(255,0,0) , %t = 160 while (%t >= 30) { drawdot -r %w %c 1 $calc(%xc + %r * $cos(%t).deg) $calc(%yc + %r * $sin(%t).deg) dec %t } var %r = $round($calc(%tilepix * 0.25),0) drawdot -r %w %c 3 $calc(%xc + %r * $cos(225).deg) $calc(%yc + %r * $sin(225).deg) drawdot -r %w %c 3 $calc(%xc + %r * $cos(315).deg) $calc(%yc + %r * $sin(315).deg) } } dec %i } dec %h } ;set turn to the correct value if ($hget(tictac)) { hadd tictac turn $iif($count($1,1) > $count($1,2),2,1) } ; display text if ($3) { var %t = Player $3 wins! | if ($hget(tictac)) { hfree tictac } } elseif (0 !isin $1) { var %t = Draw game! | if ($hget(tictac)) { hfree tictac } } elseif ($hget(tictac)) { var %t = Player $hget(tictac,turn) $+ 's turn } drawtext -r %w $rgb(255,128,0) "Lucida Console" $fontsize 5 $calc($pix +5) %t } menu @tictactoe_* { sclick:click $active $mouse.x $mouse.y } ; $1 = window $2 = x $3 = y alias -l click { if ($hget(tictac,me)) && ($v1 !== $hget(tictac,turn)) { return } var %field = $gettok($1,2,95) , %win = $gettok($1,3,95) if (%field !== $hget(tictac,field)) || (%win !== $hget(tictac,win)) { return } var %h = %field , %state = $hget(tictac,state) var %innerpix = $calc($pix - 2 * $bordersize) var %tilepix = $calc((%innerpix - (%field -1) * $innersize) / %field) while (%h) { var %i = %field while (%i) { var %pos = $calc((%h -1) * %field + %i) , %p = $mid(%state,%pos,1) if (!%p) { var %x = $round($calc($bordersize -1 + (%i -1) * (%tilepix + $innersize)),0) var %y = $round($calc($bordersize -1 + (%h -1) * (%tilepix + $innersize)),0) if ($inrect($2,$3,%x,%y,%tilepix,%tilepix)) { var %state = $+($left(%state,$calc(%pos -1)),$hget(tictac,turn),$mid(%state,$calc(%pos +1))) hadd tictac state %state if ($hget(tictac,nick)) { .notice $v1 -tictactoe state %state } noop $tictac(%state,%field,%win) return } } dec %i } dec %h } }