diff --git a/game.js b/game.js index 0725c8d..160450f 100644 --- a/game.js +++ b/game.js @@ -218,7 +218,10 @@ var MENU = { buttons:[CONVEYOR_BUILD_BUTTON,BRANCH_BUILD_BUTTON,WRITER_BUILD_BUTTON,ROTATE_COUNTERCLOCKWISE_BUTTON,ROTATE_CLOCKWISE_BUTTON,DELETE_BUTTON,PLAY_BUTTON,RESET_BUTTON,HOME_BUTTON] } - +var TUTORIALMENU={ + title:"Introduction to Conversion", + levels:[] +} function saveLevelData() { completedStages[gameStage.name].data=deepCopy(gameGrid) @@ -388,6 +391,51 @@ var STAGE2 = { return true; } } +var TUTORIAL1 = { + name:"Conveyors!", + objective:"To convert your robots, you must send them from the entrance to the exit. Select a belt and send robots to where they truly belong.", + level:createGrid(5,5,4,2), + start:{x:0,y:2}, + locked:[BRANCH_BUILD_BUTTON,WRITER_BUILD_BUTTON], + tutorial:true, + accept:(tape)=>{ + return true; + } + } +var TUTORIAL2 = { + name:"Branches", + objective:"We have to make sure we are sending robots that meet our needs! Use the branch to filter out robots that start with a red signal. Send only those to the exit!", + level:createGrid(5,5,4,2), + start:{x:0,y:2}, + locked:[WRITER_BUILD_BUTTON], + tutorial:true, + accept:(tape)=>{ + if (tape[0]===RED) { + return true; + } else { + return false; + } + } + } +var TUTORIAL3 = { + name:"Writers", + objective:"CONVERSION! It's time to convert robots to what they should be. Add 3 blue signals to every bot that comes through. We shall convert them all!", + level:createGrid(5,5,4,2), + start:{x:0,y:2}, + tutorial:true, + accept:(tape)=>{ + return true; + } + } +var TUTORIAL4 = { + name:"More Colors", + objective:"You may be required to use different colors, either for your purposes or mine. For this robot cycle, convert all blue and red signals to yellow signals.", + level:createGrid(5,5,4,2), + start:{x:0,y:2}, + accept:(tape)=>{ + return true; + } + } var gameGrid = [] var completedStages = {"Blue Blue":{data:[],complete:false}} //Example completed structure. @@ -467,7 +515,24 @@ function generateBotQueue() { RESULT=false BOT_QUEUE.push(tape) } - if (BOT_QUEUE.length===3) { + var reversedTape=tape.split("").reverse().join("") + //console.log(tape) + var wrongBot=false //Set to true if a bot that's supposed to pass fails, or a bot that's supposed to fail passes. + var isSupposedToBeAccepted=gameStage.accept(reversedTape) + var result=getSimulatedBotResult(reversedTape) + if (result===isSupposedToBeAccepted) { + wrongBot=false; + } else { + wrongBot=true; + } + if (wrongBot) { + if (BOT_QUEUE.length===0) { + EXPECTED = isSupposedToBeAccepted; + } + RESULT=false + BOT_QUEUE.push(reversedTape) + } + if (BOT_QUEUE.length>=3) { break; } } @@ -645,8 +710,8 @@ function setupGame() { } }catch{} //console.log(completedStages) - //loadStage(STAGE2) - gameState=MAINMENU + loadStage(TUTORIAL4) + //gameState=MAINMENU } function setupTitleScreen() { @@ -706,28 +771,30 @@ function clickEvent(e) { if (MENU.visible) { for (var button of MENU.buttons) { - if (mouseOverButton(canvas,e,button)) { - if (button.cb!==undefined) { - button.cb() - return; - } else { - DELETEMODE=false - document.body.style.cursor="url('cursor.png') 8 8,auto" - if (button.submenu_buttons&&button.submenu_buttons.length>0) { - BUTTON_SELECTED=button; - SUBMENU.visible=true; - SUBMENU.buttons=[] - var index = 0; - for (var button2 of BUTTON_SELECTED.submenu_buttons) { - var buttonX = ((index%3)*48)+16 - var buttonY = canvas.height*0.8-(Math.floor(index/3)*48)-40 - SUBMENU.buttons.push({def:button2,img:button2.img,x:buttonX,y:buttonY,w:32,h:32}) - index++; + if (ButtonIsUnlocked(button)) { + if (mouseOverButton(canvas,e,button)) { + if (button.cb!==undefined) { + button.cb() + return; + } else { + DELETEMODE=false + document.body.style.cursor="url('cursor.png') 8 8,auto" + if (button.submenu_buttons&&button.submenu_buttons.length>0) { + BUTTON_SELECTED=button; + SUBMENU.visible=true; + SUBMENU.buttons=[] + var index = 0; + for (var button2 of BUTTON_SELECTED.submenu_buttons) { + var buttonX = ((index%3)*48)+16 + var buttonY = canvas.height*0.8-(Math.floor(index/3)*48)-40 + SUBMENU.buttons.push({def:button2,img:button2.img,x:buttonX,y:buttonY,w:32,h:32}) + index++; + } } + ITEM_SELECTED=button.lastselected + //console.log(button) + return } - ITEM_SELECTED=button.lastselected - //console.log(button) - return } } } @@ -808,12 +875,14 @@ function releaseEvent(e) { function loadLevel(level,botx,boty) { placeBot(botx,boty) gameGrid = deepCopy(level) + MENU.visible=true } function loadStage(stage) { //gameGrid=deepCopy(stage.level) loadLevel(stage.level,stage.start.x,stage.start.y) gameStage=stage + ITEM_SELECTED=undefined if (completedStages[stage.name]===undefined) { completedStages[stage.name]={} } else { @@ -822,6 +891,7 @@ function loadStage(stage) { console.log(gameGrid) } } + } function deepCopy(arr) { @@ -1112,7 +1182,7 @@ function RenderSpeedbar(x,y,w,ctx) { ctx.stroke(); } -function DrawWrapText(text,x,y,w,fontHeight,ctx) { +function DrawWrapText(text,x,y,w,fontHeight,ctx,topToBottom=false/*Set to true to draw from the position downward. Defaults to drawing upwards.*/) { var arr = text.split(" ") var finalText = [] for (var i=0;i=buttonX&&LAST_MOUSE_X<=buttonX+32&&LAST_MOUSE_Y>=buttonY&&LAST_MOUSE_Y<=buttonY+32)?"#555555":"#b5b5b5") - index++; + if (SubmenuButtonIsUnlocked(button)) { + var buttonX = ((index%3)*48)+16 + var buttonY = canvas.height*0.8-(Math.floor(index/3)*48)-40 + RenderIcon(buttonX,buttonY,ctx,button,ITEM_DIRECTION,(LAST_MOUSE_X>=buttonX&&LAST_MOUSE_X<=buttonX+32&&LAST_MOUSE_Y>=buttonY&&LAST_MOUSE_Y<=buttonY+32)?"#555555":"#b5b5b5") + index++; + } } } } +function SubmenuButtonIsUnlocked(button) { + return gameStage.tutorial===undefined||!gameStage.tutorial||button.color1===RED||button.color1===BLUE +} + +function ButtonIsUnlocked(button) { + if (button===HOME_BUTTON&&gameStage.tutorial&&!LevelIsBeat(gameStage.name)) { + return false + } + return gameStage.locked===undefined||(!gameStage.locked.includes(button)) +} + function RenderMenu(ctx) { if (MENU.visible) { ctx.fillStyle="#20424a" @@ -1560,10 +1651,12 @@ function RenderMenu(ctx) { var buttonX = 16 var buttonY = canvas.height*0.8+16 for (var button of MENU.buttons) { - if (button.lastselected) { - RenderIcon(buttonX,buttonY,ctx,button.lastselected,(button.cb===undefined)?ITEM_DIRECTION:0,"#b5b5b5") - } else { - AddButton(button.img,buttonX,buttonY,ctx,button,(button.cb===undefined)?ITEM_DIRECTION:0) + if (ButtonIsUnlocked(button)) { + if (button.lastselected) { + RenderIcon(buttonX,buttonY,ctx,button.lastselected,(button.cb===undefined)?ITEM_DIRECTION:0,"#b5b5b5") + } else { + AddButton(button.img,buttonX,buttonY,ctx,button,(button.cb===undefined)?ITEM_DIRECTION:0) + } } button.x=buttonX button.y=buttonY diff --git a/game.test.js b/game.test.js index 6eb08b4..568b3b1 100644 --- a/game.test.js +++ b/game.test.js @@ -319,7 +319,7 @@ function runTests() { expect(BOT_QUEUE.length===0&&gameState!==TESTING,true,"Bot queue should not be modified while state is not TESTING") gameState=TESTING generateBotQueue() - expect(BOT_QUEUE.length===3,true,"There should be 3 bots in queue for an unbuilt level, as all bots are supposed to pass.") + expect(BOT_QUEUE.length>=3,true,"There should be at least 3 bots in queue for an unbuilt level, as all bots are supposed to pass.") }) .it("A stage should have an Exit.",()=>{ loadStage(STAGE1) @@ -417,7 +417,7 @@ function runTests() { expect(BOT_QUEUE.length===0&&gameState!==TESTING,true,"Bot queue should not be modified while state is not TESTING") gameState=TESTING generateBotQueue() - expect(BOT_QUEUE.length===3,true,"There should be 3 bots in queue for an unbuilt level, as there are cases that do not pass.") + expect(BOT_QUEUE.length>=3,true,"There should be at least 3 bots in queue for an unbuilt level, as there are cases that do not pass.") }) .it("A stage should have an Exit.",()=>{ loadStage(STAGE2)