use array,graph,math,ui .lang=0; //0 -english, 1 - cesky .t=[ 'game': ['KyblGo-Moku','KýblPiškvorky'], 'youwon': ['You won, congratulation!','Vyhrál(a) jsi, gratuluji!'], 'youlost': ['You lost, I\'m sorry','Prohrál jsi, bohužel.'], 'tie': ['Tie','Remíza'] ]; size=graph.full(true); graph.size(size[0],size[1]); .s=[]; .s['size']=20; .s['sizes']=graph.size(); .countx=math.floor((.s['sizes'][0]-1)/(.s['size']+1)); .county=math.floor((.s['sizes'][1]-1)/(.s['size']+1)); .s['paddingx']=math.floor(((.s['sizes'][0]-1-.countx*(.s['size']+1))+1)/2); .s['paddingy']=math.floor(((.s['sizes'][1]-1-.county*(.s['size']+1))+1)/2); function DrawBoard() graph.pen(0xF0E0A0); graph.brush(0xF0E0A0); graph.rect(0,0,.s['sizes'][0],.s['sizes'][1]); graph.pen(0xE0D0A0); maxlen=.s['sizes'][0]/5; for i=0 to 1000 do posx=math.random()*.s['sizes'][0]; posy=math.random()*.s['sizes'][1]; graph.line(posx,posy,posx+(math.random()-0.5)*maxlen,posy+(math.random()-0.5)*maxlen); end; graph.pen(0x908030); for posx=.s['paddingx']-1 to .s['sizes'][0] by .s['size']+1 do graph.line(posx,.s['paddingy']-1,posx,.s['paddingy']+.county*(.s['size']+1)); end; for posy=.s['paddingy']-1 to .s['sizes'][1] by .s['size']+1 do graph.line(.s['paddingx']-1,posy,.s['paddingx']+.countx*(.s['size']+1),posy); end; graph.show(); graph.pen(0x000000); .s['board']=[]; for i=0 to .county-1 do append(.s['board'],[]); for i2=0 to .countx-1 do append(.s['board'][i],null); end; end; end; function DrawField(x,y,pict,color,bgcolor=null) posx=x*(.s['size']+1); posy=y*(.s['size']+1); if bgcolor # null then graph.pen(bgcolor); graph.brush(bgcolor); graph.rect(.s['paddingx']+posx,.s['paddingy']+posy,.s['size'],.s['size']); else graph.brush(false); end; graph.pen(color); case pict in 'O': graph.circle(.s['paddingx']+posx+.s['size']/6,.s['paddingy']+posy+.s['size']/6,.s['size']*2/3); graph.circle(.s['paddingx']+posx+.s['size']/6+1,.s['paddingy']+posy+.s['size']/6+1,.s['size']*2/3-2); in 'X': graph.line(math.floor(.s['paddingx']+posx+.s['size']/6),math.floor(.s['paddingy']+posy+.s['size']/6),math.floor(.s['paddingx']+posx+.s['size']*5/6),math.floor(.s['paddingy']+posy+.s['size']*5/6)); graph.line(math.floor(.s['paddingx']+posx+.s['size']/6)+1,math.floor(.s['paddingy']+posy+.s['size']/6),math.floor(.s['paddingx']+posx+.s['size']*5/6)+1,math.floor(.s['paddingy']+posy+.s['size']*5/6)); graph.line(math.round(.s['paddingx']+posx+.s['size']*5/6) /* ? */ -1,math.round(.s['paddingy']+posy+.s['size']/6),math.round(.s['paddingx']+posx+.s['size']/6) /* ? */ -1,math.round(.s['paddingy']+posy+.s['size']*5/6)); graph.line(math.round(.s['paddingx']+posx+.s['size']*5/6),math.round(.s['paddingy']+posy+.s['size']/6),math.round(.s['paddingx']+posx+.s['size']/6),math.round(.s['paddingy']+posy+.s['size']*5/6)); else throw null; end; end; function GetPosition(posx,posy) posx-=.s['paddingx']; posy-=.s['paddingy']; if (posx%(.s['size']+1)) = .s['size'] or (posy%(.s['size']+1)) = .s['size'] then return null; //click to line at intersection, not valid end; x=math.floor(posx/(.s['size']+1)); y=math.floor(posy/(.s['size']+1)); if x < 0 or y < 0 or x >= .countx or y >= .county then return null; end; return [x,y]; end; function Max(value1,value2) if not isarray(value1) then if value1 > value2 then return value1; else return value2; end; else //array for i=0 to len(value1)-1 do if value1[i] > value2[i] then return value1; elsif value1[i] < value2[i] then return value2; end; end; return value1;//the same values end; end; function GetValue(x,y) if x >= 0 and y >= 0 and x < .countx and y < .county then return .s['board'][y][x]; else return false; end; end; function GetRatingOneDirection(player,x,y,dirx,diry) newx=x+dirx; newy=y+diry; realplayer=null; startholes=0; playerfields=0; totalfields=0; do while true do value=GetValue(newx,newy); newx+=dirx; newy+=diry; if value # null then break; else startholes++; totalfields++; end; end; if value = false then break; end; realplayer=value; if realplayer = player then playerfields=1.1; else playerfields=0.9; end; case startholes in 0: in 1: playerfields-=0.6; end; totalfields++; while true do value=GetValue(newx,newy); if value # realplayer then if value # null then playerfields-=0.5; end; break; else newx+=dirx; newy+=diry; playerfields++; totalfields++; end; end; for i=totalfields to 5 do value=GetValue(newx,newy); if value # null and value # realplayer then break; end; newx+=dirx; newy+=diry; totalfields++; end; until true; if startholes > 1 then playerfields=0; end; return [realplayer,startholes,playerfields,totalfields]; end; function GetRatingBothDirections(player,x,y,dirx,diry,verbose=false) left=GetRatingOneDirection(player,x,y,-dirx,-diry); right=GetRatingOneDirection(player,x,y,dirx,diry); if verbose then ui.msg(str(dirx)+','+str(diry)+'\n'+str(left)+'\n'+str(right)); end; if left[0] # right[0] then if left[0] = null then left[0]=right[0]; elsif right[0] = null then right[0]=left[0]; end; end; if left[0] # right[0] then if left[3]+right[1] < 5-1 then left[2]=-1; //no place to 5 end; if right[3]+left[1] < 5-1 then right[2]=-1; //no place to 5 end; ret=Max([left[2],left[3],left[0]],[right[2],right[3],right[0]]); if ret[2] = player then ret[0]-=0.2; end; return [ret[0],ret[1]]; else if left[3]+right[3] < 5-1 then return [-1,0]; //no place to 5 end; if left[1] > 0 and right[1] > 0 then return Max([left[2],left[3]],[right[2],right[3]]); end; return [left[2]+right[2],left[3]+right[3]]; end; end; function GetDirections() return [[-1,1],[0,1],[1,1],[1,0]]; end; function GetRating(player,x,y) directions=GetDirections(); rating=[-10,0]; for dir in directions do rating=Max(rating,GetRatingBothDirections(player,x,y,dir[0],dir[1])); // rating+=math.pow(10,GetRatingBothDirections(player,x,y,dir[0],dir[1])); end; return rating; end; function GetBestMove(player) rating=-10*100; bestmoves=[]; for y=0 to .county-1 do for x=0 to .countx-1 do if .s['board'][y][x] = null then newrating=GetRating(player,x,y); newrating=newrating[0]*100+newrating[1]; if newrating >= rating then if newrating > rating then rating=newrating; bestmoves=[]; end; append(bestmoves,[x,y]); end; end; end; end; move=math.floor(math.random()*len(bestmoves)); return [bestmoves[move][0],bestmoves[move][1]]; end; function CheckEndGame(x,y,pict) directions=GetDirections(); player=GetValue(x,y); winfields=[]; for dir in directions do tmpfields=[[x,y]]; newx=x-dir[0]; newy=y-dir[1]; while GetValue(newx,newy) = player do append(tmpfields,[newx,newy]); newx-=dir[0]; newy-=dir[1]; end; newx=x+dir[0]; newy=y+dir[1]; while GetValue(newx,newy) = player do append(tmpfields,[newx,newy]); newx+=dir[0]; newy+=dir[1]; end; if len(tmpfields) >= 5 then winfields=array.concat(winfields,tmpfields); end; end; if len(winfields) # 0 then for field in winfields do DrawField(field[0],field[1],pict,0x000000,0x90E8FF); end; graph.show(); sleep(1000); return true; end; return false; end; endgame=false; while not endgame do DrawBoard(); comppos=null; fieldsleft=.countx*.county; tie=false; while true do if fieldsleft = 0 then tie=true; break; end; ui.ptr(false); ui.keys(false); input=ui.cmd(); if not isarray(input) then if input = 98 then if comppos # null then .s['board'][comppos[1]][comppos[0]]=null; end; graph.pen(graph.black); graph.bg(graph.white); graph.font(['SwissA',10,false,false]); for y=0 to .county-1 do for x=0 to .countx-1 do if .s['board'][y][x] = null then rating=''; for dir in GetDirections() do rating=rating+GetRatingBothDirections(2,x,y,dir[0],dir[1])+':'; end; graph.pen(graph.white); graph.rect(x*(.s['size']+1)+.s['paddingx'],(y+1)*(.s['size']+1)+.s['paddingy']-13,.s['size'],12); graph.pen(0x606060); graph.text(x*(.s['size']+1)+.s['paddingx']+1,(y+1)*(.s['size']+1)+.s['paddingy']-1,str(rating)); else picts=[null,'X','O']; DrawField(x,y,picts[.s['board'][y][x]],0x000000,0xF0E0A0); end; end; end; graph.show(); ui.ptr(false); ui.keys(false); input=ui.cmd(); if isarray(input) then pos=GetPosition(input[0],input[1]); if pos # null and .s['board'][pos[1]][pos[0]] = null then //valid posit. for dir in GetDirections() do GetRatingBothDirections(2,pos[0],pos[1],dir[0],dir[1],true); end; end; end; if comppos # null then .s['board'][comppos[1]][comppos[0]]=2; end; else endgame=true; break; end; elsif input[2] = 1 then pos=GetPosition(input[0],input[1]); if pos # null and .s['board'][pos[1]][pos[0]] = null then //valid posit. DrawField(pos[0],pos[1],'X',0x000000); .s['board'][pos[1]][pos[0]]=1; fieldsleft--; if comppos # null then DrawField(comppos[0],comppos[1],'O',0x000000); end; if CheckEndGame(pos[0],pos[1],'X') then ui.msg(.t['youwon'][.lang],.t['game'][.lang]); break; end; graph.show(); if fieldsleft = 0 then tie=true; break; end; comppos=GetBestMove(2); DrawField(comppos[0],comppos[1],'O',0xFF0000); .s['board'][comppos[1]][comppos[0]]=2; fieldsleft--; if CheckEndGame(comppos[0],comppos[1],'O') then ui.msg(.t['youlost'][.lang],.t['game'][.lang]); break; end; graph.show(); end; end; end; if tie then sleep(1000); ui.msg(.t['tie'][.lang],.t['game'][.lang]); end; end; graph.hide();