/*
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 �tictactoe� $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 �tictactoe� 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
}
}