WORLD NAME Four-in-line IMAGESFOLDER_PUBLIC http://www.dimensionex.net/boardgames/ IMAGESFOLDER_LOCAL /dimx/boardgames/ ' Uncomment the following if images don't show up 'IMAGESFOLDER /dimx/boardgames/ VERSION 1.3 'Tested on DimX 5.7.1b AUTHOR Cris SITE http://www.dimensionex.net/turnbased/fourinline.htm HELP http://www.dimensionex.net/turnbased/help_four.htm GUI LOGOSRC greentable.jpg SKINS http://www.dimensionex.net/skins/aqua/aqua.dxs,http://www.dimensionex.net/skins/bloody/bloody.dxs,http://www.dimensionex.net/skins/forest/forest.dxs,default PANEL default BUTTON refresh,"Refresh","Refresh",onRefresh BUTTON help BUTTON logout TEXTBOX BUTTON say PANEL pre VERSION OF default CR CR BUTTON startgame, "Start Game!", "Start Game!", onStartGame PANEL play VERSION OF default PANEL pause VERSION OF default PANEL end VERSION OF default CR CR BUTTON resetgame, "Reset", "Reset", onReset END_GUI ROOMS ROOM board NAME Game Board IMAGE greentable.jpg END_ROOMS CHARACTERS ATTRLIST showmode=0 END_CHARACTERS ITEMS END_ITEMS SETS ARRAY players (empty),(empty) ARRAY turnscore 0,0 ARRAY score 0,0 ARRAY color black,black ARRAY pieces 0 ARRAY dirx 0,1,1,1,0,-1,-1,-1 ARRAY diry 1,1,0,-1,-1,-1,0,1 ARRAY opposite 5,6,7,8,1,2,3,4 END_SETS SCRIPTS Sub config() target_players = 2 target_turns = 0 ' means indefinite auto_start = false has_scores = false turn_reminders = false End_Sub EVENT onStart Call config() mode = "pre" ' modes: pre / play / pause / end nplayers = 0 cycles = 0 SetPanel $WORLD,"pre" Dim i For i=1 to target_players score(i)=0 Next For i=1 to 8 Call initRow(i) Next board.name = $WORLD.name End_EVENT Sub initRow(row) Dim y = 10 + row * 22 Dim x Dim attrs Dim i Dim subscript For i = 1 to 8 x = 60 + i * 22 attrs = "type=cell,showmode=1,showy=" + y + ",showx=" + x + ",row=" + row + ",col=" + i subscript = i+(row-1)*8 pieces(subscript) = NewItem(board,"column "+i,null,NewImage("cross.gif",16,16),attrs) Next End_Sub EVENT onNew If (mode = "pre" Or mode = "pause") And nplayers < target_players Dim slot = addPlayer($AGENT) If nplayers = target_players If mode = "pre" If Not(auto_start) Speak SYS,$WORLD,"You can now start the game by clicking the [START GAME] button." Else Call play() End_If Else If mode="pause" Speak SYS,$AGENT,"You have joined a running game as player #" + slot Call play() End_If End_If End_If End_If board.description = getSituation() RefreshView board End_EVENT Function addPlayer(person) Dim i For i=1 To SetLen(players) If Not(Exists(players(i))) players(i) = person nplayers = nplayers+1 Return i End_If Next End_Function Function getSituation() Dim i Dim x Dim string string = "-- current players: " + nplayers + " (target is: " + target_players + ") --" string = string + "
"
If mode <> "pre"
string = string + "Play cycles: " + cycles + "
"
End_If
If mode = "play"
string = string + "Next player: " + players(nowplays).name
End_If
If mode = "pre" Or mode = "pause"
If nplayers < target_players
string = string + "Waiting for " + (target_players - nplayers) + " more player(s)... Invite friends!"
Else
If nplayers > target_players
string = string + "There is " + (nplayers - target_players) + " person too much..."
Else
string = string + "Ready to start!"
End_If
End_If
End_If
If mode = "end"
string = string + "GAME OVER - Click [RESET] button for another game."
End_If
Return string
End_Function
EVENT onStartGame
If mode = "pre"
If findUser($AGENT) > 0
If nplayers < target_players
Speak "Cannot start a game before at least " + target_players + " players are connected."
Else
Call play()
started_playing = findUser($AGENT)
color(started_playing) = "white"
nowplays = started_playing
If turn_reminders
Speak SYS,$WORLD,"Now plays: " + players(nowplays).name
End_If
End_If
Else
' somebody is trying to play but not in the list of players
If nplayers < target_players
' OK one place is available - join
Call onNew()
Speak "OK you now have joined - click [START GAME] again to start"
Else
Speak "You are not one of the players - sorry. You are welcome to stay as a watcher."
End_If
End_If
Else
Speak "Cannot start game now (mode=" + mode + ")"
End_If
board.description = getSituation()
END_EVENT
Function findUser(user)
For i=1 To SetLen(players)
If user = players(i)
Return i
End_If
Next
Return 0
End_Function
Sub updScore()
If has_scores
If turnscore(1) > turnscore(2)
Speak SYS,$WORLD,"O.K. then " + players(1).name + " wins this round"
score(1) = score(1) + 1
Else
If turnscore(2) > turnscore(1)
Speak SYS,$WORLD,"Look: " + players(2).name + " wins this round"
score(2) = score(2) + 1
Else
Speak SYS,$WORLD,"Hey - this round was even!"
End_If
End_If
End_If
board.description = getSituation()
RefreshView board
End_Sub
Function checkEnd()
Return (target_turns > 0) And (cycles = target_turns)
End_Function
EVENT board.onLoose
If $AGENT=null
' User logs off
Dim loggingout = findUser($TARGET)
If loggingout > 0
players(loggingout) = "(empty)"
nplayers = nplayers - 1
If mode = "play"
mode = "pause"
SetPanel $WORLD,"pause"
End_If
End_If
board.description = getSituation()
End_If
End_EVENT
Sub play()
Speak SYS,$WORLD,"Game has begun... GOOD LUCK!"
PlayBackground $WORLD,"sndMimovie.mid"
mode = "play"
SetPanel $WORLD,"play"
End_Sub
Sub onLook
If mode <> "play"
RefreshView board
Return false
End_If
If $AGENT = players(nowplays)
If $OWNER.type = "cell" Or $OWNER.type = "mark"
If Not(placePiece($OWNER.col,$OWNER.row,color(nowplays)))
Return false
End_If
End_If
' else...
If has_scores
Speak SYS,$WORLD,"" + players(nowplays).name + " has scored: " + roll1 + " + " + roll2 + " = " + turnscore(nowplays)
End_If
nowplays = getNext(nowplays)
Else
Speak "WAIT! It's " + players(nowplays).name + " turn."
End_If
If mode = "play"
If nowplays = started_playing
cycles = cycles + 1
Call updScore()
If checkEnd()
mode = "end"
SetPanel $WORLD,"end"
Else
dummy=0
If turn_reminders
Speak SYS,$WORLD,"Another round. Now plays: " + players(nowplays).name
End_If
End_If
Else
dummy=0
If turn_reminders
Speak SYS,$WORLD,"Now plays: " + players(nowplays).name
End_If
End_If
End_If
board.description = getSituation()
Return false
End_Sub
Function getNext(x)
x = x + 1
If x > nplayers
x = 1
End_If
Return x
End_Function
Function placePiece(x,y,color)
Dim piece
Dim yi
Dim found = 0
For yi = 1 to 8
piece = getPiece(x,yi)
If found=0 And piece.type <> "mark"
found = yi
End_If
Next
If found = 0
Return false
End_If
piece = getPiece(x,found)
piece.type = "mark"
piece.color = color
piece.image = "" + color + ".gif"
'Print "placed " + color + "at " + x + "," + found
If checkWinner(x,found,color)
Call gameOver($AGENT.name + " is the WINNER!!")
End_If
RefreshView board
Return true
End_Function
Function getPiece(x,y)
Return pieces(x+(y-1)*8)
End_Function
' check whether it is possible to have won
' starting from x,y
' with color "color"
' and "missing" missing cells
Function checkWinner(x,y,color)
'Print "Checking " + x + "," + y + " for " + color
If getPiece(x,y).color <> color
Return false
End_If
Dim sum
Dim i
For i = 1 To 4
'Print "direction " + i + " and " + opposite(i)
sum = 1 + checkWinnerAhead(x+dirx(i),y+diry(i),color,i)
sum = sum + checkWinnerAhead(x+dirx(opposite(i)),y+diry(opposite(i)),color,opposite(i))
'Print "Sums: " + sum
If sum >= 4
Return true
End_If
Next
Return false
End_Function
Function checkWinnerAhead(x,y,color,direction)
'Print "checking " + x + "," + y + " for " + color
If x <= 0 Or y <= 0
'Print "out"
Return 0
End_If
If getPiece(x,y).color <> color
'Print "empty or other color"
Return 0
End_If
Return 1 + checkWinnerAhead(x+dirx(direction),y+diry(direction),color,direction)
End_Function
Sub gameOver(message)
Speak SYS,$WORLD,message
mode = "end"
PlayBackground $WORLD,"independenceday.mid"
SetPanel $WORLD,"end"
End_Sub
EVENT onRefresh
RefreshView $AGENT
END_EVENT
EVENT onReset
RefreshView $WORLD
Reset
END_EVENT
END_SCRIPTS
END_WORLD