var w,h,my={};function battleshipMain(){var version='0.52';w=360;h=500;my.shipSets=[[2,3,4,5],[2,3,3,4,5],[2,3,4,5,6],[6]];my.shipSetN=2
my.bdSzs=[8,10,12];my.playerTypes=[{name:'Human',aiQ:false},{name:'Computer (Beginner)',aiQ:true,levelMax:1,timeMax:3000},{name:'Computer (Medium)',aiQ:true,levelMax:3,timeMax:3000},{name:'Computer (Challenging)',aiQ:true,levelMax:4,timeMax:10000},{name:'Computer (Hard)',aiQ:true,levelMax:6,timeMax:10000}];my.clrs0=[["Light Blue Grey",'#D8D8e8'],["Silver",'#d0d0d0'],["Grey 1",'#a898a8'],["Grey 2",'#b8a8a8']];my.clrs1=[["Blue 1",'#bDD8E6'],["Sky Blue",'#97CEEB'],["Aqua",'#aaffff'],["Antique White",'#FAEBD7'],["Blue 2",'#7A9ACD']];my.players=[new Player('Human','blue','rgba(0,0,255,0.3)','board0',my.clrs0),new Player('Computer','red','rgba(255,0,0,0.4)','board1',my.clrs1)]
my.playerN=0
my.playerStartN=0
my.borderTp=123
var s='';my.sndHome=(document.domain=='localhost')?'/mathsisfun/images/sounds/':'/images/sounds/'
s+=' ';s+=' ';s+=' ';s+=' ';s+=' ';my.snds=[];s+=''
s+='
';s+='
'
s+='
'
s+='
Options '
s+='
New Game '
my.soundQ=true
s+=' '
s+=soundBtnHTML()
s+='
'
s+='
Ready! '
s+='
Next '
s+='
'
s+='
Player X
'
s+='
'
s+='
';s+='
';s+=optPopHTML();s+='
© 2020 MathsIsFun.com v'+version+'
';s+='
';document.write(s);document.getElementById('scores').innerHTML='Human:0 Computer:0'
gameNew()}
function gameNew(){my.placedQ=false
my.activeQ=false
my.nextQ=false
my.bdSz=Math.floor(document.querySelector('input[name="bdSz"]:checked').value)
console.log('bdSz',my.bdSz)
var id=document.querySelector('input[name="shipSet"]:checked').id
my.shipSetN=(id.match(/\d+$/)||[]).pop();console.log('my.shipSetN',my.shipSetN)
my.boxWd=Math.min(70,(Math.min(w,h-90))/my.bdSz)
for(var i=0;i0)s+='Ship Outside! '
if(collideN>0)s+='Ship Collision!'
msg(s)
if(s.length>0){btnVis('readyBtn',false)}else{btnVis('readyBtn',true)}
console.log('placeCheck',s)}
function bdMake(clr,bdName,clrs){my.borderLt=(w-my.bdSz*my.boxWd)/2
var pts=getRandomPts(my.bdSz,my.bdSz,3,clrs);var bd=[]
for(var xn=0;xn=0)
var p=my.players[my.playerN];var winQ=p.winCheck()
if(winQ){msg(p.name+' wins!')
if(p.type.aiQ){soundPlay('sndWinAI')}else{soundPlay('sndWin')}
my.activeQ=false
btnVis('nextBtn',false)
my.players[my.playerN].score++
var s=''
for(var i=0;i=my.bdSz)return-1
if(yn>=my.bdSz)return-1
return bd[xn][yn]}
function bdFmt(bd){var s=''
for(var yn=0;yn';s+=prompt;for(var i=0;i';s+=''+lbl+' ';}
s+='';return s;}
function randomInt(min,max){return Math.floor(Math.random()*(max-min+1))+min;}
function optPopHTML(){var s='';s+='';s+='
';for(var i=0;i
';s+=''+p.name+' player:
';s+='Type: ';s+=dropdownHTML(my.playerTypes,'','playerType'+i,i);s+=' ';}
s+='
';s+='';s+=radioHTML('Board Size','bdSz',my.bdSzs,'',0);s+='
'
s+='';s+=radioHTML('Ships','shipSet',my.shipSets,'',0);s+='
'
s+='';s+='(starts new game)'
s+='✔ ';s+=' '
s+='✘ ';s+='
';s+='';return s;}
function optPop(){var pop=document.getElementById('optpop');pop.style.transitionDuration="0.3s";pop.style.opacity=1;pop.style.zIndex=12;pop.style.left=(w-400)/2+'px';}
function optYes(){var pop=document.getElementById('optpop');pop.style.opacity=0;pop.style.zIndex=1;pop.style.left='-999px';gameNew()}
function optNo(){var pop=document.getElementById('optpop');pop.style.opacity=0;pop.style.zIndex=1;pop.style.left='-999px';}
function dropdownHTML(opts,funcName,id,chkN){var s='';s+='';for(var i=0;i'+opts[i].name+'';}
s+=' ';return s;}
function soundBtnHTML(){var s=''
s+=''
s+='
'
return s}
function soundToggle(){var btn='sound'
if(my.soundQ){my.soundQ=false
document.getElementById(btn).classList.add("mute")}else{my.soundQ=true
document.getElementById(btn).classList.remove("mute")}}
function soundPlay(name,simulQ){if(!my.soundQ)return
simulQ=typeof simulQ!=='undefined'?simulQ:true
if(simulQ){if(name.length>0){var div=document.getElementById(name)
if(div.currentTime>0&&div.currentTime0)soundPlayQueue();};}
function Tile(wd,ht,lt,tp,clr,bdName){this.wd=wd
this.ht=ht
this.xn=Math.round(lt/my.boxWd)
this.yn=Math.round(tp/my.boxWd)
this.bgClr=clr
this.fgClr='black'
this.status='clear'
this.sunkQ=false
var div=document.createElement("div");div.style.width=wd+'px'
div.style.height=ht+'px'
div.style.position='absolute'
div.style.top=tp+'px'
div.style.left=lt+'px'
this.div=div
var me=this
div.addEventListener('mouseover',function(){if(!my.activeQ)return
if(me.status!='clear')return
me.drawStatus('over')})
div.addEventListener('mouseleave',function(){if(!my.activeQ)return
if(me.status!='clear')return
if(!me.onQ)return
me.drawStatus()})
div.addEventListener('click',function(){if(!my.activeQ)return
if(me.status!='clear')return
my.activeQ=false
update(me)})
var can=document.createElement('canvas');can.style.position="absolute";can.style.top='0px'
can.style.left='0px'
can.style.width='100%'
can.style.height='100%'
can.width=wd
can.height=ht
this.g=can.getContext("2d");div.appendChild(can)
document.getElementById(bdName).appendChild(div);this.draw()}
Tile.prototype.hit=function(onQ){if(onQ){this.status='hit'
soundPlay('sndHit')}else{this.status='miss'
soundPlay('sndMiss')}
this.draw()}
Tile.prototype.draw=function(onQ){this.onQ=typeof onQ!=='undefined'?onQ:true
if(this.onQ){this.div.style.pointerEvents="auto";var fgClr=(this.playerN==0)?'darkblue':'darkred'
this.drawStatus(this.status,fgClr)}else{var g=this.g
g.clearRect(0,0,g.canvas.width,g.canvas.height)
this.div.style.pointerEvents="none";}}
Tile.prototype.drawStatus=function(status,fgClr){status=typeof status!=='undefined'?status:this.status
this.fgClr=typeof fgClr!=='undefined'?fgClr:'black'
var g=this.g
g.clearRect(0,0,g.canvas.width,g.canvas.height)
g.fillStyle=this.bgClr
g.beginPath()
g.rect(0,0,this.wd,this.ht)
g.fill()
g.strokeStyle=this.fgClr
switch(status){case 'over':g.strokeStyle='blue'
g.lineWidth=2
g.beginPath()
g.arc(this.wd/2,this.ht/2,this.wd/3,0,2*Math.PI)
g.stroke()
break
case 'hit':g.strokeStyle='black'
g.fillStyle='red'
g.lineWidth=3
g.beginPath()
g.arc(this.wd/2,this.ht/2,this.wd/3,0,2*Math.PI)
g.stroke()
g.fill()
break
case 'miss':g.strokeStyle='rgba(255,255,255,0.3)'
g.fillStyle='rgba(0,0,255,0.2)'
g.lineWidth=3
g.beginPath()
g.arc(this.wd/2,this.ht/2,this.wd/3,0,2*Math.PI)
g.stroke()
g.fill()
break
case 'x':g.lineWidth=2
var edge=this.wd*0.2
g.beginPath()
g.moveTo(edge,edge)
g.lineTo(this.wd-edge,this.wd-edge)
g.stroke()
g.beginPath()
g.moveTo(edge,this.wd-edge)
g.lineTo(this.wd-edge,edge)
g.stroke()
break
default:}}
Tile.prototype.win=function(){this.bgClr='#ffe'
this.draw()}
Tile.prototype.setxy=function(lt,tp){this.div.style.left=lt+'px';this.div.style.top=tp+'px';}
function Player(name,clr,bgClr,bdName,clrs){this.name=name
this.clr=clr
this.clrs=clrs
this.bgClr=bgClr
this.bdName=bdName
this.score=0
this.ships=[];this.bd=[];}
Player.prototype.bestMove=function(){var dirs=[[0,-1],[1,0],[0,1],[-1,0]]
var best={score:-9,xn:0,yn:0}
for(var i=0;ibest.score)best={score:scoreTot,xn:i,yn:j}}}
return best}
function tileType(bd,xn,yn){if(xn<0)return 0
if(yn<0)return 0
if(xn>=my.bdSz)return 0
if(yn>=my.bdSz)return 0
var tile=bd[xn][yn]
if(tile.sunkQ)return 9
if(tile.status=='hit')return 1
if(tile.status=='miss')return 2
return 0}
Player.prototype.autoPlace=function(){this.ships=[];my.zIndex=1;var shipLens=my.shipSets[my.shipSetN];for(var i=0;i=this.sz){this.sunkQ=true
soundPlay('sndSunk')
this.show(true)
console.log('ship just sunk')
for(var i=0;imy.bdSz)return false
if(this.pos.y+this.yn>my.bdSz)return false
return true}
Ship.prototype.intersectsQ=function(ships){for(var i=0;ir.rt)return false
if(yr.bt)return false
return true}
function intersectRect(r1,r2){return!(r2.lt>r1.rt||r2.rtr1.bt||r2.bt