Code viewer for World: Cells (backup version)

// Cloned by SinfulSalad on 19 Jun 2018 from World "canvas webgl" by Starter user 
// Please leave this clone trail here.
 


// ==== Starter World ===============================================================================================
// (c) Ancient Brain Ltd. All rights reserved.
// This code is only for use on the Ancient Brain site.
// This code may be freely copied and edited by anyone on the Ancient Brain site.
// This code may not be copied, re-published or used on any other website.
// To include a run of this code on another website, see the "Embed code" links provided on the Ancient Brain site.
// ==================================================================================================================
	
	

// ===================================================================================================================
// === Start of tweaker's box ======================================================================================== 
// ===================================================================================================================

// The easiest things to modify are in this box.
// You should be able to change things in this box without being a JavaScript programmer.
// Go ahead and change some of these. What's the worst that could happen?



// These 3 have default values, so this section is optional:

AB.clockTick       = 33;    

	// Speed of run: Step every n milliseconds. Default 100.
	
AB.maxSteps        = 20000;    

	// Length of run: Maximum length of run in steps. Default 1000.

AB.screenshotStep  = 1000;   
  
	// Take screenshot on this step. (All resources should have finished loading.) Default 50.


const SKYCOLOR 	= "#000000";				// this usage will be of color as a string, not as a number 

const MUSIC_BACK  = '/uploads/sinfulsalad/Forest.mp3' ;


var SPEED = 1;

  
// ===================================================================================================================
// === End of tweaker's box ==========================================================================================
// ===================================================================================================================


// You will need to be some sort of JavaScript programmer to change things below the tweaker's box.



// --- music ----------------------------------------



var backmusic = new Audio ( MUSIC_BACK );
 

function initMusic()	
{
	backmusic.loop = true;                 // loop forever 
	backmusic.play();

	$("#w2m_audio1").html( " <img class=audiobutton  onclick='backmusic.play();'  width=25  src='images/audio.on.1.png'  > " );	
	$("#w2m_audio2").html( " <img class=audiobutton  onclick='backmusic.pause();' width=25  src='images/audio.off.1.png' > " );	
} 
 
 
 
//---------------useful functions-----------------------------------------------


function lightenDarkenColor(col, amt) {
  
    var usePound = false;
  
    if (col[0] == "#") {
        col = col.slice(1);
        usePound = true;
    }
 
    var num = parseInt(col,16);
 
    var r = (num >> 16) + amt;
 
    if (r > 255) r = 255;
    else if  (r < 0) r = 0;
 
    var b = ((num >> 8) & 0x00FF) + amt;
 
    if (b > 255) b = 255;
    else if  (b < 0) b = 0;
 
    var g = (num & 0x0000FF) + amt;
 
    if (g > 255) g = 255;
    else if (g < 0) g = 0;
 
    return (usePound?"#":"") + (g | (b << 8) | (r << 16)).toString(16);
  
}


function angle(vect1, vect2)
{
    rst = vect1.x * vect2.x + vect1.y * vect2.y;
    rst /= (Math.sqrt(Math.pow(vect1.x,2)+Math.pow(vect1.y,2)))*(Math.sqrt(Math.pow(vect2.x,2)+Math.pow(vect2.y,2)));
    rst = Math.acos(rst);
    return rst;
}

function getIndexOfItem(item, array)
{
    var index = 0;
    while (array[index] != item && index < array.length) index++;
    if (index == array.length) index = -1;
    return index;
}



function randomfloatAtoB ( A, B )			 
{
 return ( A + ( Math.random() * (B-A) ) );
}


//returns a whole number in from the [A,B[ range
function randomintAtoB ( A, B )			 
{
 return  ( Math.floor ( randomfloatAtoB ( A, B ) ) );
}



//---------------end useful functions-----------------------------------------------



function World() { 
    
     /*
            The different steps of colonisations should be :
            1. The mind choses which cell want to colonise which cell
            2. A cellShip is created from ce departure cell
            3. The cellShip moves towards its destination
            4. Once the destination is reached, an outcome is calculated depending
                on the destination's value and the cellShip's value.
            */
    
    //TODO : manage team containers. Not sure I'll use them for now
    //TODO : yeah, i have to rearrange the containers, and create new ones
    
    
     		 
    var timer = 0;
    
    var canvas;
    var context;
    var centerX;
    var centerY;
    
    var cells = [];
    var cellShips = [];
    
    var pinkCells;
    var greenCells;
    var blueCells;
    var orangeCells;

    var score;
    
     //constructor of cells
    function Cell(x,y, type, color = '#555555', destination = cells)
    {
        var cell = Object.create(cellPrototype);
        cell.x = x;
        cell.y = y;
        cell.type = type;
        
        switch (type)
        {
            case "small" :
                cell.radius = 15;
                cell.value = 5;
                break;
            case "avg" :
                cell.radius = 25;
                cell.value = 10;
                break;
            default :
                cell.radius = 50;
                cell.value = 20;
                break;
        }
        cell.maxVal = cell.value*5;
        cell.rate = Math.floor(30/cell.maxVal/AB.clockTick/SPEED*1000);
        cell.color = color;
        
        destination.push(cell);
        
        
        return cell;
    }
    
    
    var cellPrototype = {
        
        draw : function() {
            context.beginPath();
            context.arc(centerX+this.x, centerY+this.y, this.radius, 0, 2 * Math.PI, false);
            context.fillStyle = this.color;
            context.fill();
            context.lineWidth = 2;
            
            context.fillStyle = '#000000';
            
            strokeRGB = lightenDarkenColor(this.color, +100);
            context.strokeStyle = strokeRGB;
            context.fillText(Math.floor(this.value), centerX+this.x-1, centerY+this.y+5);
            
            context.stroke();
        },
        
        drawSymmetry : function() {
            var newcell = Cell(-this.x, this.y, this.type, this.color);
            newcell.draw();
            
            newcell = Cell(-this.x, -this.y, this.type, this.color);
            newcell.draw();
            
            newcell = Cell(this.x, -this.y, this.type, this.color);
            newcell.draw();
        },
        
        drawSurround : function(nbCells, radius, type) {
            var newCell;
            
            for (var i=0 ; i < 2*Math.PI-0.01 ; i += 2*Math.PI/nbCells)
            {
                newCell = Cell(this.x+radius*Math.cos(i), this.y+radius*Math.sin(i), type);
                newCell.draw();
            }
        },
        
        setDirection : function(cell) {
            var vect0 ={
                x : 1,
                y : 0
            };
            var trajectory ={
                x : cell.x-this.x,
                y : cell.y-this.y
            };
            
            var ang = angle(vect0, trajectory);
            
            if (cell.y < this.y) ang = -ang;
            
            this.direction = ang;
        },
        
        //step 2 of colonisation
        split : function(dest) {
            var newCellShip = Cell(this.x, this.y, "small", this.color, cellShips);
            newCellShip.value = Math.floor(this.value/2);
            newCellShip.dest = dest;
            newCellShip.direction;
            newCellShip.setDirection(dest);
            this.value = Math.floor(this.value/2);
        },
        
        infect : function(){
            if (Math.abs(this.x-this.dest.x) < 2*SPEED && Math.abs(this.y-this.dest.y) < 2*SPEED)
            {
                cellShips.splice(getIndexOfItem(this, cellShips), 1);
                
                if (this.dest.color != this.color) this.dest.value -= this.value;
                else this.dest.value += this.value;
                
                if (this.dest.value < 0)
                {
                    this.dest.value = -this.dest.value;
                    this.dest.color = this.color;
                }
                
                if (this.dest.value > this.dest.maxVal) this.dest.value = this.dest.maxVal;
                
            }
        },
        
        individualMind : function(){
            var rand;
            if (this.type == "huge")
            {
                rand = (this.maxVal - this.value);
                //TODO : what if maxval == value?
                if (randomintAtoB(0, rand) === 0)
                {
                    do{
                        rand = randomintAtoB(0, cells.length);
                    }while(cells[rand].color === this.color);
                    //TODO : what if infinite loop?
                            
                    this.split(cells[rand]);
                }
            }
            
            else if ((this.type == "small" || this.type == "avg") && this.value == this.maxVal)
            {
                do{
                        rand = randomintAtoB(0, cells.length);
                    }while(cells[rand].color === this.color);
                    //TODO : what if infinite loop?
                            
                    this.split(cells[rand]);
            }
        
        }
        
    };
    
    function initContext()
    {
        
        context = canvas.getContext('2d');
        
        context.font = "bold 15px Arial";
        context.textAlign = 'center';
        
    }
    
    
    function initStage()
    {
        var newCell = Cell(200, 200, "huge", "#555554");
        newCell.drawSurround(6, 90, "small");
        newCell = Cell(500, 70, "huge");
        newCell = Cell(350, 80, "avg");
        newCell.drawSurround(3, 60, "small");
        newCell = Cell(90*Math.cos(Math.PI/8), 90*Math.sin(Math.PI/8), "avg");
        newCell = Cell(90*Math.cos(3*Math.PI/8), 90*Math.sin(3*Math.PI/8), "avg");
        
        var length = cells.length;
        for (var i=0 ; i<length ; i++)
        {
            cells[i].draw();
            cells[i].drawSymmetry();
        }
        
        newCell = Cell(0, 0, "huge");
        newCell.draw();
        
        newCell = Cell(250, 0, "avg");
        newCell.draw();
        
        newCell = Cell(-250, 0, "avg");
        newCell.draw();
        
        newCell = Cell(0, 250, "avg");
        newCell.draw();
        
        newCell = Cell(0, -250, "avg");
        newCell.draw();
        
        newCell = Cell(160, 0, "small");
        newCell.draw();
        
        newCell = Cell(-160, 0, "small");
        newCell.draw();
        
        newCell = Cell(0, 160, "small");
        newCell.draw();
        
        newCell = Cell(0, -160, "small");
        newCell.draw();
    }
    
    
    function initTeams()
    {
        pinkCells = [];
        greenCells = [];
        blueCells = [];
        orangeCells = [];
        
        var colorArray = ["#FE2E9A", "#FE642E", "#58FAF4", "#80FF00"];
        var counter = 0;
        for (var i=0 ; i<cells.length ; i++)
        {
            if (cells[i].color !== "#555555")
            {
                cells[i].color = colorArray[counter];
                switch (counter)
                {
                    case 0 :
                        pinkCells.push(cells[i]);
                        break;
                    case 1 :
                        orangeCells.push(cells[i]);
                        break; 
                    case 2 :
                        blueCells.push(cells[i]);
                        break; 
                    default :
                        greenCells.push(cells[i]);
                }
                counter ++;
                cells[i].draw();
            }
        }
    }
    
    
    function initChart()
    {
        score ={
            pink : 20,
            orange : 20,
            blue : 20,
            green : 20
        }
    }
    
    
    function initButtons()
    {
        s = "<p><button id='regularButton'>x1</button> <button id='fasterButton'>\> x2 \></button> <button id='f a s t erButton'>\>\> x4 \>\></button></p>";
    	$("#user_span1").html( s );
 	
        document.getElementById("regularButton").addEventListener("click", regularSpeed);
        document.getElementById("fasterButton").addEventListener("click", fastSpeed);
        document.getElementById("f a s t erButton").addEventListener("click", fasterSpeed);
    }
    
    function regularSpeed() 
    {
        SPEED = 1;
        for (var i = 0 ; i < cells.length ; i++)
        {
            cells[i].rate = Math.floor(30/cells[i].maxVal/AB.clockTick/SPEED*1000);
        }
    }
    function fastSpeed() 
    {
        SPEED = 2;
        for (var i = 0 ; i < cells.length ; i++) 
        {
            cells[i].rate = Math.floor(30/cells[i].maxVal/AB.clockTick/SPEED*1000);
        }
    }
    function fasterSpeed() 
    {
        SPEED = 4;
        for (var i = 0 ; i < cells.length ; i++)
        {
            cells[i].rate = Math.floor(30/cells[i].maxVal/AB.clockTick/SPEED*1000);
        }
    }
    
    function updateChart()
    {
        score.pink = 0;
        score.green = 0;
        score.blue = 0;
        score.orange = 0;
        
        //TODO : not optimised
        for (var i = 0 ; i < cells.length ; i++)
        {
            switch (cells[i].color){
                case "#FE2E9A" :
                    score.pink += cells[i].value;
                    break;
                
                case "#FE642E" :
                    score.orange += cells[i].value;
                    break;
                
                case "#58FAF4" :
                    score.blue += cells[i].value;
                    break;
                
                case "#80FF00" :
                    score.green += cells[i].value;
                    break;
            }
        }
        
        for (i = 0 ; i < cellShips.length ; i++)
        {
            switch (cellShips[i].color){
                case "#FE2E9A" :
                    score.pink += cellShips[i].value;
                    break;
                
                case "#FE642E" :
                    score.orange += cellShips[i].value;
                    break;
                
                case "#58FAF4" :
                    score.blue += cellShips[i].value;
                    break;
                
                case "#80FF00" :
                    score.green += cellShips[i].value;
                    break;
            }
        }
    }
    
    
    function drawChart()
    {
        context.font = "12px Arial";
        
        posX = 25;
        posY = 645;
        
        context.fillStyle = "#000000";
        context.fillRect(posX-10, 0, 130, canvas.height); 
        
        
        context.fillStyle = "#FE2E9A";
        context.fillRect(posX, posY-score.pink/6, 30, score.pink/6);
        context.fillStyle = "#FFFFFF";
        context.fillText(Math.floor(score.pink), posX+15, posY-5-score.pink/6);
        
        context.fillStyle = "#FE642E";
        context.fillRect(posX+30, posY-score.orange/6, 30, score.orange/6);
        context.fillStyle = "#FFFFFF";
        context.fillText(Math.floor(score.orange), posX+45, posY-5-score.orange/6);
        
        context.fillStyle = "#58FAF4";
        context.fillRect(posX+60, posY-score.blue/6, 30, score.blue/6);
        context.fillStyle = "#FFFFFF";
        context.fillText(Math.floor(score.blue), posX+75, posY-5-score.blue/6);
        
        context.fillStyle = "#80FF00";
        context.fillRect(posX+90, posY-score.green/6, 30, score.green/6);
        context.fillStyle = "#FFFFFF";
        context.fillText(Math.floor(score.green), posX+105, posY-5-score.green/6);
        
        context.font = "bold 15px Arial";
    }
    
    
    function updateBackground()
    {
        context.globalAlpha = 0.05;
        context.fillRect(0, 0, canvas.width, canvas.height);
        context.globalAlpha = 1;
    }
    
    
    
    function grow()
    {
        for (var i=0 ; i<cells.length ; i++)
        {
            if (cells[i].color !== "#555555" && cells[i].value < cells[i].maxVal)
            {
                if (timer%Math.floor(cells[i].rate) === 0 && timer !== 0)
                {
                    cells[i].value++;
                    cells[i].individualMind();
                }
            }
            
            else if (cells[i].value == cells[i].maxVal) cells[i].individualMind();
        }
    }
    
    
    function move()
    {
        for (var i=0 ; i<cellShips.length ; i++)
        {
            cellShips[i].x += SPEED*Math.cos(cellShips[i].direction);
            cellShips[i].y += SPEED*Math.sin(cellShips[i].direction);
            cellShips[i].infect();
        }
    }
    
    
    function update()
    {
        updateBackground();
        updateChart();
        drawChart();
        
        for (var i=0 ; i<cells.length ; i++)
        {
            cells[i].draw();
        }
        
        for (i=0 ; i<cellShips.length ; i++)
        {
            cellShips[i].draw();
        }
        
    }
    
    this.newRun = function() 
    {
        threeworld.init (  SKYCOLOR  );
        initButtons();
        initMusic();
        
        canvas = threeworld.canvas;
        initContext();
        centerX = 30+canvas.width / 2;
        centerY = canvas.height / 2;
        
        initStage();
        initTeams();
        initChart();
        
    };
    
     
    this.nextStep = function()
    {
        
        grow();
        move();
        update();
        
        timer++;

    };
    
    
    
    this.endRun = function()
    {
        
    };

}