/* Copyright 2004 Louis Jean­Richard (www.ljr.ch). All Rights Reserved. */
//	-----------------------------------
var	noCell = -1
var	transparent = 0, gray = 1
var	right = 1, left = 2, up = 6, down = 3
//	-----------------------------------
var	BOARD_ROWS = 5
var	BOARD_COLUMNS = 9
var	BOARD_CELLS = BOARD_ROWS * BOARD_COLUMNS
var	MAX_COLOURS = 6
var	firstTriangleOrientation = down

//	============================================================
//							T R I A N G L E
//	============================================================

var triangleImage = new Preload("../aa/game/4/")
triangleImage.load("triang2", 8, ".gif")
triangleImage.load("triang1", 8, ".gif")
triangleImage.load("triang0", 8, ".gif")

//	-----------------------------------
function			Triangle(rightColour, leftColour, downColour)
{
	function	_imageIndex(orientation, side, colour)
	{
		if (side == down)
			return 16 + colour
		else
			if (colour == transparent)
				return 8
			else
				if ((orientation == up) == (side == right))
					return colour
				else
					return 8 + colour
	}
	this.ix = new Array(10)
	this.ix[right] = rightColour
	this.ix[left] = leftColour
	this.ix[down] = downColour
	this.ix[up + right] = _imageIndex(up, right, rightColour)
	this.ix[up + left] = _imageIndex(up, left, leftColour)
	this.ix[up + down] = _imageIndex(up, down, downColour)
	this.ix[down + right] = _imageIndex(down, right, rightColour)
	this.ix[down + left] = _imageIndex(down, left, leftColour)
	this.ix[down + down] = _imageIndex(down, down, downColour)
}
//	-----------------------------------
var triangleColourIndex =
	new Array(down, right, left, down, left, right)
function				colourTriangle(side, orientation)
{
	return this.ix[triangleColourIndex[orientation - side]]
}
Triangle.prototype.colour = colourTriangle
//	-----------------------------------
function				displayTriangle(name, orientation)
{
	triangleImage.display(name[right], this.ix[orientation + right])
	triangleImage.display(name[left], this.ix[orientation + left])
	triangleImage.display(name[down], this.ix[orientation + down])
}
Triangle.prototype.display = displayTriangle
//	-----------------------------------
var noTriangle =
	new Triangle(transparent, transparent, transparent)
var gridTriangle = new Triangle(gray, gray, gray)


//	============================================================
//					T R I A N G L E   A R R A Y
//	============================================================

function								TriangleArray(colours)
{
	this.colours = colours
	var perm = new Permutation(colours, 3)
	this.triangle = new Array(perm.permutations)
	var last = this.triangle.length
	for (var i=0; i < last; i++)
	{
		this.triangle[i] = new Triangle
			( gray + perm.index[right]
			, gray + perm.index[left]
			, gray + perm.index[down]
			)
		this.triangle[i].ix[0] = i + 1
		perm.next()
	}
	this.triangle[i - 1].ix[0] = -1
	this.firstTriangle = 0
	this.currentTriangle = this.firstTriangle
	this.reset()
}

//	-----------------------------------
function                                currentTriangleArray()
{
	if (this.currentTriangle < 0)
		return noTriangle
	else
		return this.triangle[this.currentTriangle]
}
TriangleArray.prototype.current = currentTriangleArray

//	-----------------------------------
function                                nextTriangleArray()
{
	if (this.currentTriangle < 0)
		return noTriangle
	else
	{
		this.currentTriangle =
			this.triangle[this.currentTriangle].ix[0]

		return this.triangle[this.currentTriangle]
	}
}
TriangleArray.prototype.next = nextTriangleArray

//	-----------------------------------
function			randomTriangleArray(colours, lastTriangle)
{
	this.reset()
	var pool = permutations(colours, 3)
	if (lastTriangle > pool)
		lastTriangle = pool
	this.colours = colours
	var readOrder = new Permutation(pool, lastTriangle)
	readOrder.random()
	this.firstTriangle = readOrder.index[1] - 1
	var ct = this.firstTriangle
	for (var i=2; i <= readOrder.subset; i++)
	{
		var next_triangle = readOrder.index[i] - 1
		this.triangle[ct].ix[0] = next_triangle
		ct = next_triangle
	}
	this.triangle[ct].ix[0] = -1	// end of linked list
	this.currentTriangle = this.firstTriangle
}
TriangleArray.prototype.random = randomTriangleArray

//	-----------------------------------
function                                resetTriangleArray()
{
	this.currentTriangle = this.firstTriangle
}
TriangleArray.prototype.reset = resetTriangleArray

//	============================================================
//							G R I D
//	============================================================

//	this constants control the functions packBinary, unpackBinary
var CODE_STRING = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"
var CODE_CHAR = CODE_STRING.split("")
//	-----------------------------------
function text4(N)
{
	switch (langCode)
	{
	case 'de':
		return 'Gitter ' + N
	case 'es':
		return 'rejilla ' + N
	case 'fr':
		return 'grille ' + N
	case 'it':
		return 'griglia ' + N
	default:
		return 'grid ' + N
	}
}
//	-----------------------------------
function   								Grid(mapString, title)
{
	if (mapString.length == BOARD_CELLS)
		this.codedMap = packBinary(mapString)
	else
		this.codedMap = mapString	// packed
	this.setFlag(this.codedMap)
	if ((title != undefined) && (title.length > 0))
		this.optionText = title
	else
		this.optionText = text4()
	this.optionText += '  (' + this.cellCount + ')'
}

//	-----------------------------------
function   								setFlagGrid(aCodedMap)
{
	var last = BOARD_CELLS
	var flag = unpackBinary(aCodedMap).split("")
	this.cellFlag = new Array(last)
	this.cellCount = 0
	for (var cix=0; cix < last; cix++)
		if (flag[cix] == '0')
			this.cellFlag[cix] = false
		else
		{
			this.cellFlag[cix] = true
			this.cellCount++
		}
}
Grid.prototype.setFlag = setFlagGrid

//	-----------------------------------
function								editGrid(aCodedMap)
{
	this.oldCodedMap = this.codedMap
	if (aCodedMap != '')
	{
		this.codedMap = aCodedMap
		this.setFlag(aCodedMap)
	}
}
Grid.prototype.edit = editGrid

//	-----------------------------------
function								updateGrid()
{
	var mapString = ""
	var last = this.cellFlag.length
	for (var cix=0; cix < last; cix++)
		if (this.cellFlag[cix])
			mapString += '1'
		else
			mapString += '0'
	var editedMap = packBinary(mapString)
	//
	if (editedMap == this.oldCodedMap)
		return ''
	else
		if (confirm(text8 + '  (' + editedMap + ')'))
		{
			this.codedMap = editedMap
			return ''
		}
		else {
			this.codedMap = this.oldCodedMap
			this.setFlag(this.codedMap)
			return editedMap
		}
}
Grid.prototype.update = updateGrid


//	============================================================
//							C E L L
//	============================================================

function							Cell(row, column, isOnEdge)
{
	this.isVisible = false
	this.row = row
	this.column = column
	if (((row + column) % 2 == 0)
			== (firstTriangleOrientation == down))
		this.orientation = down
	else
		this.orientation = up
	this.isOnEdge = isOnEdge
	this.nextCell = new Array(4)
	if (isOnEdge)
	{
		this.nextSide = new Array(4)
		this.visited = false
	}
	var nameRoot = 'C' + (100 * row + column + 101)
	this.name = new Array
		("", nameRoot + '1', nameRoot + '2', nameRoot + '3')
	this.reset()
}
//	-----------------------------------
function                                displayCell(aTriangle)
{
	if (aTriangle != undefined)
	{
		this.triangle = aTriangle
		this.isVisible = (aTriangle !== noTriangle)
		this.isEmpty =
			((aTriangle === gridTriangle) || !this.isVisible)
	}
	this.triangle.display(this.name, this.orientation)
}
Cell.prototype.display = displayCell

//	-----------------------------------
function                                htmlCell(side)
{
	with (this)
		return triangleImage.html(name[side]
			, orientation + right
			, (side == down))
}
Cell.prototype.html = htmlCell

//	-----------------------------------
function                                resetCell()
{
	if (this.isVisible)
		this.triangle = gridTriangle
	else
		this.triangle = noTriangle
	this.isEmpty = true
}
Cell.prototype.reset = resetCell

//	-----------------------------------
function                                toggleCell()
{
	this.isVisible = !this.isVisible
	this.reset()
	this.display()
}
Cell.prototype.toggle = toggleCell

//	============================================================
//							B O A R D
//	============================================================

function								Board(rows, columns)
{
	this.columns = columns
	this.rows = rows
	this.cell = new Array(rows * columns)
	var cix = 0
	for (var row=0; row < rows; row++)
	{
		var isOnHorizontalEdge = ((row == 0) || (row == rows - 1))
		for (var col=0; col < columns; col++)
		{
			var isOnEdge = (isOnHorizontalEdge
				|| (col == 0) || (col == columns - 1))
			this.cell[cix] = new Cell(row, col, isOnEdge)
			cix++
		}
	}
	this.visibleCells = 0
	this.preselectedCell = noCell
	this.displayed = false
}

//	-----------------------------------
function							autoCompleteBoard(aTriangle)
{
	last = this.cell.length
	for (var cix=0; cix < last; cix++)
		with(this.cell[cix])
		if (isEmpty && isVisible)
		{
			display(aTriangle)
			return true
		}
	return false
}
Board.prototype.autoComplete = autoCompleteBoard

//	-----------------------------------
function                                clearBoard()
{
	this.reset()
	this.repaint()
}
Board.prototype.clear = clearBoard
//	-----------------------------------
function                                drawGridBoard(aFlagArray)
{
	this.flagArray = aFlagArray
	this.visibleCells = 0
	var last = this.cell.length
	for (var cix=0; cix < last; cix++)
		if (!aFlagArray[cix])
			this.cell[cix].display(noTriangle)
		else
		{
			this.visibleCells++
			this.cell[cix].display(gridTriangle)
		}
}
Board.prototype.drawGrid = drawGridBoard

//	-----------------------------------
function							exchangeTrianglesBoard(cix)
{
	var otherCell = this.preselectedCell
	this.preselectedCell = noCell
	if (cix == otherCell)
		return false
	var aTriangle1 = this.cell[cix].triangle
	var aTriangle2 = this.cell[otherCell].triangle
	this.cell[cix].display(aTriangle2)
	this.cell[otherCell].display(aTriangle1)
	return true
}
Board.prototype.exchangeTriangles = exchangeTrianglesBoard

//	-----------------------------------
function							fillBoard(aTriangleArray)
{
	var last = this.cell.length
	aTriangleArray.reset()
	var aTriangle = aTriangleArray.current()
	for (var cix=0; cix < last; cix++)
		with(this.cell[cix])
		if (isVisible)
		{
			display(aTriangle)
			aTriangle = aTriangleArray.next()
		}
}
Board.prototype.fill = fillBoard

//	-----------------------------------
function                                htmlBoard()
{
	var lastColumn = this.columns
	var lastRow = this.rows
	var	output = '<table>'
	var	spacerRow = '<tr><td colspan="' + this.columns + '">'
	spacerRow +=
		triangleImage.html('', noTriangle.ix[up + down], true)
	spacerRow += '</td></tr>'
	var clickHandler = '<td><a href="javascript:clickedCell'
	var firstColumn = 0
	for (var row=0; row < lastRow; row++)
	{
		if (firstColumn > 0)
			output += spacerRow
		output += '<tr>'
		for (var col=firstColumn; col < lastColumn; col++)
			with (this.cell[col])
			if (orientation == down)
				output += '<td></td>'
			else {
				output += clickHandler
				output += '(' + col + ')">'
				output += html(left)
				output += html(right)
				output += '</a></td>'
			}
		output += '</tr><tr>'
		for (var col=firstColumn; col < lastColumn; col++)
			with (this.cell[col])
			{
				output += '<td>'
				output += html(down)
				output += '</td>'
			}
		output += '</tr><tr>'
		for (var col=firstColumn; col < lastColumn; col++)
			with (this.cell[col])
			if (orientation == up)
				output += '<td></td>'
			else {
				output += clickHandler
				output += '(' + col + ')">'
				output += html(left)
				output += html(right)
				output += '</a></td>'
			}
		output += '</tr>'
		firstColumn = lastColumn
		lastColumn += this.columns
	}
	output += '</table>'
	this.displayed = true
	return output
}
Board.prototype.html = htmlBoard

//	-----------------------------------
function								linkCellsBoard()
{
	var last_start_cell = -1
	var start_cell = 0
	var last_cell = this.cell.length
	while (start_cell < last_cell)
	{
		if (!this.cell[start_cell].visited)
		{
			if (last_start_cell > -1)
				this.cell[last_start_cell].nextGroup = start_cell
			var last_start_cell = start_cell
			this.linkCellGroup(start_cell)
		}
		start_cell += this.columns
	}
	this.cell[last_start_cell].nextGroup = -1
}
Board.prototype.linkCells = linkCellsBoard

//	-----------------------------------
function						linkCellGroupBoard(start_cell)
{
	var last_row = this.rows - 1
	var columns = this.columns
	var last_column = columns - 1
	var side = down	// side determines also the direction!
	var goForward = true
	var walkedTriangleSides = 0
	var cix = start_cell

	while ((cix != start_cell) || (side != down)
			|| !goForward || (walkedTriangleSides == 0))
	{
		walkedTriangleSides++
		var last_side = side
		with (this.cell[cix])
		{	// determine next cix to visit
			if (side == down)
				if (goForward)
					if (column == last_column)
						if (orientation == up)
						{
							side = right
							goForward = !goForward
						}
						else
							side = left
					else
						cix++
				else
					if (column == 0)
						if (orientation == up)
							side = left
						else {
							side = right
							goForward = !goForward
						}
					else
						cix--
			else
				if (side == left)
					if (orientation == up)
						if (goForward)
							if (column == 0)
								side = down
							else
								cix--
						else
							if (row == 0)
							{
								side = right
								goForward = !goForward
							}
							else
								cix -= columns
					else	// orientation == down
						if (goForward)
							if (row == last_row)
							{
								side = right
								goForward = !goForward
							}
							else
								cix += columns
						else
							if (column == last_column)
								side = down
							else
								cix++
				else	// side == right
					if (orientation == up)
						if (goForward)
							if (column == last_column)
							{
								side = down
								goForward = !goForward
							}
							else
								cix++
						else
							if (row == 0)
							{
								side = left
								goForward = !goForward
							}
							else
								cix -= columns
					else	// orientation == down
						if (goForward)
							if (row == last_row)
							{
								side = left
								goForward = !goForward
							}
							else
								cix += columns
						else
							if (column == 0)
							{
								side = down
								goForward = !goForward
							}
							else
								cix--
			//
			nextCell[last_side] = cix
			if (isOnEdge)
			{
				nextSide[last_side] = side
				visited = (visited || (side != last_side))
			}
		}
	}
}
Board.prototype.linkCellGroup = linkCellGroupBoard

//	-----------------------------------
function			placeTriangleBoard(aTriangle, destination)
{
	with(this.cell[destination])
		if (!isVisible || !isEmpty)
			return false
		else {
			display(aTriangle)
			return true
		}
}
Board.prototype.placeTriangle = placeTriangleBoard

//	-----------------------------------
function								repaintBoard()
{
	var last = this.cell.length
	for (var cix=0; cix < last; cix++)
		this.cell[cix].display()
}
Board.prototype.repaint = repaintBoard

//	-----------------------------------
function                                resetBoard()
{
	this.visibleCells = 0
	this.preselectedCell = noCell
	var last = this.cell.length
	for (var cix=0; cix < last; cix++)
		with(this.cell[cix])
{
			reset()
			if (isVisible)
				this.visibleCells++
		}
}
Board.prototype.reset = resetBoard

//	-----------------------------------
function							toggleGridCellBoard(cix)
{
	this.cell[cix].toggle()
	this.flagArray[cix] = this.cell[cix].isVisible
	if (this.cell[cix].isVisible)
		this.visibleCells++
	else
		this.visibleCells--
}
Board.prototype.toggleGridCell = toggleGridCellBoard


//	============================================================
//					C O L O U R   P E R M U T A T I O N S
//	============================================================

function text1(N,P)
{
	switch (langCode)
	{
	case 'de':
		return N + ' Farben, Menge von ' + P + ' Dreiecke.'
	case 'es':
		return N + ' colores, conjunto de ' + P + ' triangulos.'
	case 'fr':
		return N + ' couleurs, ensemble de ' + P + ' triangles.'
	case 'it':
		return N + ' colori, insieme di ' + P + ' triangoli.'
	default:
		return N + ' colours, set of ' + P + ' triangles.'
	}
}
//	-----------------------------------
function   						ColourPermutations(colours)
{
	this.colours = colours
	this.permutations = permutations(colours, 3)
	this.optionText = text1(colours, this.permutations)
}


//	============================================================
//						P L A Y   M O D E
//	============================================================

function   							PlayMode(mode, title)
{
	this.mode = mode
	this.optionText = title
}

//	============================================================
//						C O N T R O L
//	============================================================

function								Control(aBoard)
{
	this.sequenceMode = true
	this.gridDesignMode = false
	this.arrangeMode = false
	this.completeInit = true
	this.displayed = false
	this.board = aBoard

	this.nextTriangle =
		new Cell(-1, firstTriangleOrientation - down)
	// 'this.score' will be set to point to the score object
	// so as to update its display
	this.score = this
//	-----------------------------------
	this.triangles = new TriangleArray(MAX_COLOURS)
	this.colourPermutations = new Selector('coloursChanged', 0
		, new ColourPermutations(4)
		, new ColourPermutations(5)
		, new ColourPermutations(6)
		)
	this.playMode = new Selector('playModeChanged', 0
		, new PlayMode(1, text6a)
		, new PlayMode(2, text6b)
		, new PlayMode(3, text6c)
		)
	this.gridMap = new Selector('gridChanged', 3
		, new Grid('AAHAOAAAA', text9a)
		, new Grid('HA1BTBWBY', text9b)
		, new Grid('3Z1QADXHO', text9c)
		, new Grid('55QNRRWBY', text9d)
		, new Grid('5BWB5A1B4', text9e)
		, new Grid('55XN5RWBY', text9f)
		, new Grid('HYNT143XO', text9g)
		, new Grid('HY51155X4', text9h)
		, new Grid('45XP143XO', text9i)
		, new Grid('555555555', text9j)
		)
}

//	-----------------------------------
function								clickedCellControl(cix)
{
	if (this.gridDesignMode)
	{
		this.board.toggleGridCell(cix)
		message(msg2(this.board.visibleCells))
		return
	}
	if (!this.started)
	{
		this.started = true
		this.score.update(this.moves)
	}
	if (this.sequenceMode)
	{
		if (this.moves == this.board.visibleCells)
			return	// game over
		if (this.board.placeTriangle
				(this.triangles.current(), cix))
		{
			this.moves++
			if (this.moves + 1 < this.board.visibleCells)
				this.nextTriangle.display(this.triangles.next())
			else
			{
				this.moves++
				this.board.autoComplete(this.triangles.next())
				this.nextTriangle.display(noTriangle)
			}
			this.score.update(this.moves)
		}
		return
	}
	if ((this.arrangeMode)
		&& (this.board.cell[cix].isVisible))
			if (this.board.preselectedCell < 0)
				this.board.preselectedCell = cix
			else
				if (this.board.exchangeTriangles(cix))
				{
					this.moves++
					this.score.update(this.moves)
				}
}
Control.prototype.clickedCell = clickedCellControl

//	-----------------------------------
function								coloursChangedControl()
{
	this.colourPermutations.read()
	if (!this.gridDesignMode)
		this.board.drawGrid(this.gridMap.selected.cellFlag)
	this.startNew()
}
Control.prototype.coloursChanged = coloursChangedControl

//	-----------------------------------
function								gridChangedControl()
{
	if (this.gridDesignMode)
		document.CONTROL.userMap.value =
			this.gridMap.selected.update()
	this.gridMap.read()
	if (this.gridDesignMode)
		this.gridMap.selected.edit(document.CONTROL.userMap.value)
	this.board.drawGrid(this.gridMap.selected.cellFlag)
	this.startNew()
}
Control.prototype.gridChanged = gridChangedControl

//	-----------------------------------
function								htmlControl(formName)
{
	var output = '<table><tr><td>&nbsp;</td><td style="width: 48px">'
	with (this.nextTriangle)
	{
		output += html(left)
		output += html(right)
		output += '</td><td>&nbsp;</td></tr><tr><td></td><td>'
		output += html(down)
	}
	var newLine = "<br />\n"
	output += '</td><td></td></tr></table>\n'
	output += '<form name=' + quoted(formName) + '>'
	output += '<input class="button" type="button" value='
	output += sQuoted(text2)
	output += " onclick='javascript:newGame()' />"
	output += newLine
	output += '<input class="button" type="button" value='
	output += sQuoted(text3)
	output += " onclick='javascript:restartGame()' />"
	output += newLine
	output += this.colourPermutations.htmlList(formName)
	output += newLine
	output += this.gridMap.htmlList(formName)
	output += newLine
	output += "<fieldset>"
	output += "<legend>" + text7a + "</legend>"
	output += this.playMode.htmlRadio(formName)
	output += "</fieldset>"
	output += newLine
	output += htmlInput('userMap', text7b, BOARD_COLUMNS)
	output += "</form>"
	this.displayed = true
	return output
}
Control.prototype.html = htmlControl

//	-----------------------------------
function								playModeChangedControl()
{
	if (this.gridDesignMode)
		document.CONTROL.userMap.value =
			this.gridMap.selected.update()
	var extendGame =
		(this.sequenceMode && !this.nextTriangle.isVisible)

	this.playMode.read()
	this.sequenceMode = (this.playMode.selected.mode == 1)
	this.arrangeMode = (this.playMode.selected.mode == 2)
	this.gridDesignMode = (this.playMode.selected.mode == 3)

	if (this.gridDesignMode)
	{
		this.gridMap.selected.edit(document.CONTROL.userMap.value)
		this.board.drawGrid(this.gridMap.selected.cellFlag)
	}
	if (!extendGame || !this.arrangeMode)
		this.startNew()
	// else let continue in arrange mode !
}
Control.prototype.playModeChanged = playModeChangedControl

//	-----------------------------------
function                                resetControl()
{
	if (this.completeInit)
	{
		this.completeInit = false
		this.playMode.read()
		this.colourPermutations.read()
		this.gridMap.read()
		this.board.drawGrid(this.gridMap.selected.cellFlag)
	}
	if (!this.sequenceMode)
		this.nextTriangle.display(noTriangle)
	this.moves = 0
	this.started = false
}
Control.prototype.reset = resetControl

//	-----------------------------------
function								restartControl()
{
	this.reset()
	if (this.sequenceMode)
	{
		this.board.clear()
		this.triangles.reset()
		this.nextTriangle.display(this.triangles.current())
	}
	if (this.gridDesignMode)
	{
		this.board.drawGrid(this.gridMap.selected.cellFlag)
		this.board.repaint()
	}
	if (this.arrangeMode)
	{
		this.board.fill(this.triangles)
	}
	this.score.update(0)
	message(msg2(this.board.visibleCells))
}
Control.prototype.restart = restartControl

//	-----------------------------------
function								startNewControl()
{
	this.reset()
	if (this.sequenceMode)
	{
		this.board.clear()
		this.triangles.random
			(this.colourPermutations.selected.colours
			, this.board.visibleCells)
		this.nextTriangle.display(this.triangles.current())
	}
	if (this.gridDesignMode)
	{
		this.board.repaint()
	}
	if (this.arrangeMode)
	{
		this.triangles.random
			(this.colourPermutations.selected.colours
			, this.board.visibleCells)
		this.board.fill(this.triangles)
		this.score.update(this.moves)
	}
	this.score.update(0)
	message(msg2(this.board.visibleCells))
}
Control.prototype.startNew = startNewControl

//	-----------------------------------
function								updateControl()
{
	message(msg7(this.moves))
}
Control.prototype.update = updateControl


//	============================================================
//							S C O R E
//	============================================================

function 								Score(aGame, aBoard)
{
	this.moves = aGame.moves
	this.chrono = new Chrono()
	this.lines = 0
	this.segments = 0
	this.total = 0
	this.displayed = false
	//
	this.board = aBoard
	this.cellsAreNotLinked = true
	aGame.score = this
}

//	-----------------------------------
function                                computeScore()
{
	this.lines = 0
	this.segments = 0
	var start_cell = 0
	while (start_cell > -1)
	{
		this.computeGroup(start_cell)
		start_cell = this.board.cell[start_cell].nextGroup
	}
	this.total = this.segments * this.lines
	document.SCORE.total.value = this.total
	document.SCORE.lines.value = this.lines
	document.SCORE.segments.value = this.segments
}
Score.prototype.compute = computeScore

//	-----------------------------------
function							computeGroupScore(start_cell)
{
	if (this.cellsAreNotLinked)
	{
		this.board.linkCells()
		this.cellsAreNotLinked = false
	}
	var cix = start_cell
	var side = down	// side determines also the direction!
	var walking_on_a_line = false
	var last_side = right
	var last_sideColour = transparent
	var lineSegments = 1
	var walkedTriangleSides = 0
	while (true)
	{
		walkedTriangleSides++
		with (this.board.cell[cix])
	{
			var sideColour = triangle.colour(side, orientation)
			if (!walking_on_a_line)
			{
				walking_on_a_line = (!isEmpty
					&& ((side != last_side)
						|| (last_sideColour == transparent)))
			}
			else {
				if (sideColour == last_sideColour)
					lineSegments++
				else {
					if ((lineSegments > 1)
						&& ((sideColour == transparent)
							|| (side != last_side)))
					{
						this.lines++
						this.segments += lineSegments
					}
					lineSegments = 1
					walking_on_a_line = (side != last_side)
				}
			}
			last_side = side
			last_sideColour = sideColour
			//
			if ((cix == start_cell) && (side == down)
				&& (walkedTriangleSides > 1))
				return
			// determine next cell to visit
			var last_cell = cix
			cix = nextCell[side]
			if (cix == last_cell)
				side = nextSide[side]
		}
	}
}
Score.prototype.computeGroup = computeGroupScore

//	-----------------------------------
function                                htmlScore()
{
	output = '<form name="SCORE">'
	output += '<table><tr><td id="score">'
	output += text5a + '</td><td>'
	output += htmlDisplay('total', '')
	output += "</td></tr><tr><td>"
	output += text5b + '</td><td>'
	output += text5c
	output += "</td></tr><tr><td>"
	output += htmlDisplay('lines', '') + '</td><td>'
	output += htmlDisplay('segments', '')
	output += "</td></tr><tr><td>"
	output += text5d + '</td><td>'
	output += text5e
	output += "</td></tr><tr><td>"
	output += htmlDisplay('moves', '') + '</td><td>'
	output += htmlDisplay('time', '')
	output += "</td></tr></table>"
	output += "</form>"
	this.displayed = true
	return output
}
Score.prototype.html = htmlScore

//	-----------------------------------
function                                showActualScore(moves)
{
	this.compute()
	this.moves = moves
	message(msg3(this.total, this.lines, this.segments)
		+ ' ' + msg7(this.moves))
}
Score.prototype.show = showActualScore

//	-----------------------------------
function                                resetScore()
{
	this.moves = 0
	document.SCORE.time.value = ''
	document.SCORE.moves.value = this.moves
	this.chrono.stop()
}
Score.prototype.reset = resetScore

//	-----------------------------------
function                                updateScore(moves)
{
	if (moves == 0)
		this.reset()
	else {
		this.moves = moves
		if (moves == 1)
			this.chrono.start()
		document.SCORE.time.value = this.chrono.elapsedMinutes()
		document.SCORE.moves.value = this.moves
	}
	this.compute()
}
Score.prototype.update = updateScore

//	============================================================
//						I N T E R F A C E
//	============================================================

function                                displayGame(language)
{
	initLanguage(language)

	var board = new Board(BOARD_ROWS, BOARD_COLUMNS)
	game = new Control(board)
	var	score = new Score(game, board)

	var output = '<table class="game"><tr><td class="score">'
	output += score.html()
	output += '</td><td class="board" rowspan="2">'
	output += board.html()
	output += '</td></tr><tr><td class="control">'
	output += game.html('CONTROL')
	output += '</td></tr></table>'

	document.open()
	document.write(output)
	document.close()

	game.reset()
	game.startNew()
//	window.onresize=board.repaint
}
//	-----------------------------------
function								coloursChanged()
{
	game.coloursChanged()
}
//	-----------------------------------
function								gridChanged()
{
	game.gridChanged()
}
//	-----------------------------------
function								playModeChanged()
{
	game.playModeChanged()
}
//	-----------------------------------
function								newGame()
{
	game.startNew()
}
//	-----------------------------------
function								restartGame()
{
	game.restart()
}
//	-----------------------------------
function                                clickedCell(n)
{
	game.clickedCell(n)
}
//	============================================================
var langCode = undefined
var text2 = 'New game'
var text3 = 'Restart game'
var text5a = 'Score'
var text5b = 'lines'
var text5c = 'sides'
var text5d = 'moves'
var text5e = 'time'
var text6a = 'Sequence mode'
var text6b = 'Arrange mode'
var text6c = 'Modify grid'
var text7a = 'Play mode'
var text7b = 'user grid map:'
var text8 = 'Save modified grid?'
var text9a = 'star'
var text9b = 'rhombus'
var text9c = '4 stars'
var text9d = 'big triangle'
var text9e = '2 triangles'
var text9f = 'crystal'
var text9g = 'snow flake'
var text9h = 'hexagon'
var text9i = 'fantasy'
var text9j = 'full grid'
//	-----------------------------------
function initLanguage(language)
{
	if (langCode == undefined)
		langCode = language
	else
		return
	switch (langCode)
{
	case 'de':
		text2 = 'Neues Spiel'
		text3 = 'Spiel wiederholen'
		text5a = 'Punkte'
		text5b = 'Gerade'
		text5c = 'Seiten'
		text5d = 'Schritte'
		text5e = 'Zeit'
		text6a = 'Einzeln setzen'
		text6b = 'Umdisponieren'
		text6c = 'Gitter ändern'
		text7a = 'Spielmodalit&auml;t'
		text7b = 'Ben&uuml;tzers Gitter:'
		text8 = 'Ge&auml;ndertes Gitter sichern ?'
		text9a = 'Stern'
		text9b = 'Raute'
		text9c = '4 Sternen'
		text9d = 'grosser Dreieck'
		text9e = '2 Dreiecke'
		text9f = 'Krystall'
		text9g = 'Schneeflocke'
		text9h = 'Sechseck'
		text9i = 'Phantasiebild'
		text9j = 'vollst&auml;ndiges Gitter'
		break
	case 'es':
		text2 = 'Nuevo juego'
		text3 = 'Repetir el juego'
		text5a = 'Puntos'
		text5b = 'droites'
		text5c = 'lados'
		text5d = 'pasos'
		text5e = 'tiempo'
		text6a = 'Modo uno por uno'
		text6b = 'Modo recombinar'
		text6c = 'Cambiar la disposici&ograve;n'
		text7a = 'Manera de jugar'
		text7b = 'Rejilla usuario:'
		text8 = 'Salvar rejilla modificada ?'
		text9a = 'estrella'
		text9b = 'rombo'
		text9c = '4 estrellas'
		text9d = 'grande triangulo'
		text9e = '2 triangulos'
		text9f = 'cristal'
		text9g = 'copito de nieve'
		text9h = 'hexagono'
		text9i = 'fantasia'
		text9j = 'rejilla completa'
		break
	case 'fr':
		text2 = 'Nouveau jeu'
		text3 = 'Recommence le jeu'
		text5a = 'Points'
		text5b = 'droites'
		text5c = 'cot&eacute;s'
		text5d = 'pas'
		text5e = 'temps'
		text6a = 'Mode un par un'
		text6b = 'Mode recombiner'
		text6c = 'Modifie grille'
		text7a = 'Modalit&eacute; de jeu'
		text7b = 'grille usager:'
		text8 = 'Sauver la grille modifi&eacute;e ?'
		text9a = '&eacute;toile'
		text9b = 'losange'
		text9c = '4 &eacute;toiles'
		text9d = 'grand triangle'
		text9e = '2 triangles'
		text9f = 'crystal'
		text9g = 'flocon de neige'
		text9h = 'hexagon'
		text9i = 'fantasie'
		text9j = 'grille compl&egrave;te'
		break
	case 'it':
		text2 = 'Nuovo gioco'
		text3 = 'Ricomincia il gioco'
		text5a = 'Punti'
		text5b = 'righe'
		text5c = 'lati'
		text5d = 'mosse'
		text5e = 'tempo'
		text6a = 'modo uno alla volta'
		text6b = 'modo ricombinare'
		text6c = 'Modifica griglia'
		text7a = 'Modalit&agrave; di gioco'
		text7b = 'griglia utente:'
		text8 = 'Salvare la griglia modificata ?'
		text9a = 'stella'
		text9b = 'rombo'
		text9c = '4 stelle'
		text9d = 'grande triangolo'
		text9e = '2 triangoli'
		text9f = 'cristallo'
		text9g = 'fiocco di neve'
		text9h = 'esagono'
		text9i = 'fantasia'
		text9j = 'griglia completa'
		break
	}
}
//	-----------------------------------
function msg2(A)
{
	switch (langCode)
{
	case 'de':
		return 'Gitter mit ' + A + ' Zellen'
	case 'es':
		return 'Rejilla con ' + A + ' celulas'
	case 'fr':
		return 'Grille avec ' + A + ' cases'
	case 'it':
		return 'Griglia con ' + A + ' caselle'
	default:
		return 'Grid with ' + A + ' cells'
	}
}
//	-----------------------------------
function msg3(N, L, S)
{
	switch (langCode)
{
	case 'de':
		return N + ' Punkte (' + L + ' Geraden, ' + S + ' Dreieckseiten)'
	case 'es':
		return N + ' Puntos (' + L + ' lineas, ' + S + ' lados de triangulo)'
	case 'fr':
		return N + ' Points (' + L  + ' droites, ' + S + ' côtés de triangle)'
	case 'it':
		return N  + ' Punti (' + L + ' righe, ' + S + ' lati di triangolo)'
	default:
		return N + ' points (' + L + ' lines, ' + S + ' sides)'
	}
}
//	-----------------------------------
function msg7(moves)
{
	switch (langCode)
{
	case 'de':
		return moves + ' Schritte'
	case 'es':
		return moves + ' pasos'
	case 'fr':
		return moves + ' pas'
	case 'it':
		return moves + ' mosse'
	default:
		return moves + ' moves'
	}
}
//	-----------------------------------
