| 1 | const socket = io(); |
| 2 | |
| 3 | const getV = (field) => localStorage.getItem(field); |
| 4 | |
| 5 | const Login = { |
| 6 | view: function() { |
| 7 | return m("input[type=text][placeholder=User name]", { |
| 8 | autofocus: true, |
| 9 | onchange(e) {Login.username = e.currentTarget.value}, |
| 10 | onkeyup: Login.process |
| 11 | }); |
| 12 | }, |
| 13 | process: function(e) { |
| 14 | if (e.keyCode == 13) socket.emit("login", e.target.value); |
| 15 | } |
| 16 | }; |
| 17 | |
| 18 | let Seek = { |
| 19 | searching: false, |
| 20 | seekGame: function() { |
| 21 | // If not logged in, redirect |
| 22 | if (!getV("name")) m.route.set("/login"); |
| 23 | else { |
| 24 | socket.emit("seek", {uid: getV("uid"), name: getV("name")}); |
| 25 | Seek.searching = true; |
| 26 | } |
| 27 | }, |
| 28 | view: function(vnode) { |
| 29 | if (Seek.searching) |
| 30 | return m("img.animated", {src: "assets/searching.gif"}); |
| 31 | return m("button", {onclick: Seek.seekGame}, "Play"); |
| 32 | } |
| 33 | }; |
| 34 | |
| 35 | const Choices = |
| 36 | {'r':"Rock",'p':"Paper",'s':"Scissors",'l':"Lizard",'k':"Spock",'?':"what"}; |
| 37 | const Win = |
| 38 | {'r':['s','l'], 'p':['r','k'], 's':['p','l'], 'l':['p','k'], 'k':['r','s']}; |
| 39 | const MAX_POINTS = 7; |
| 40 | |
| 41 | let Play = { |
| 42 | gid: 0, |
| 43 | mymove: "", |
| 44 | oppmove: "", |
| 45 | myselect: "?", |
| 46 | oppselect: "?", |
| 47 | mypoints: 0, |
| 48 | oppoints: 0, |
| 49 | mnum: 0, |
| 50 | oppid: 0, |
| 51 | oppname: "", |
| 52 | gameover: false, |
| 53 | initGame: function(msg) { |
| 54 | Play.gid = msg.gid; |
| 55 | Play.oppid = msg.oppid; |
| 56 | Play.oppname = msg.oppname; |
| 57 | Play.gameover = false; |
| 58 | for (const v of ["mymove","oppmove"]) Play[v] = ""; |
| 59 | for (const v of ["myselect","oppselect"]) Play[v] = "?"; |
| 60 | for (const v of ["mnum","mypoints","oppoints"]) Play[v] = 0; |
| 61 | }, |
| 62 | compareMoves: function() { |
| 63 | Play.oppselect = Play.oppmove; //reveal opponent's move only now |
| 64 | if (Win[Play.mymove].includes(Play.oppmove)) { |
| 65 | if (++Play.mypoints == MAX_POINTS) Play.endGame(true); |
| 66 | socket.emit("inc_pts", {uid: getV("uid"), gid:Play.gid}); |
| 67 | } |
| 68 | else if (Win[Play.oppmove].includes(Play.mymove)) { |
| 69 | if (++Play.oppoints == MAX_POINTS) Play.endGame(false); |
| 70 | } |
| 71 | Play.mnum++; |
| 72 | Play.mymove = ""; |
| 73 | Play.oppmove = ""; |
| 74 | }, |
| 75 | endGame: function(Iwin) { |
| 76 | Play.gameover = true; |
| 77 | setTimeout(() => { |
| 78 | if (Iwin) alert("Bravo t'as gagné !"); |
| 79 | else alert("Pas de chance, t'as perdu..."); |
| 80 | m.route.set("/seek"); |
| 81 | }, 1000); |
| 82 | }, |
| 83 | playMove: function(code) { |
| 84 | if (Play.mymove || Play.gameover) |
| 85 | // I already played, or game is over |
| 86 | return; |
| 87 | Play.mymove = code; |
| 88 | Play.myselect = code; |
| 89 | socket.emit("move", { |
| 90 | uid: getV("uid"), |
| 91 | gid: Play.gid, |
| 92 | choice: Play.mymove, |
| 93 | mnum: Play.mnum, |
| 94 | oppid: Play.oppid |
| 95 | }); |
| 96 | if (Play.oppmove) Play.compareMoves(); |
| 97 | else Play.oppselect = "?"; |
| 98 | }, |
| 99 | view: function() { |
| 100 | return m("div", {}, |
| 101 | [m("h2", {}, |
| 102 | `${getV("name")} [${Play.mypoints}] vs. ${Play.oppname} [${Play.oppoints}]`)] |
| 103 | .concat( |
| 104 | [m(".choices", {}, [ |
| 105 | m("img", {src: "assets/" + Choices[Play.myselect] + ".png"}), |
| 106 | m("img", {src: "assets/" + Choices[Play.oppselect] + ".png"}) |
| 107 | ])]).concat( |
| 108 | [m(".options", |
| 109 | {style: `opacity:${Play.mymove==''?'1':'0.5'}`}, |
| 110 | ["r","p","s","l","k"].map((code) => { |
| 111 | return m("img", { |
| 112 | src: "assets/" + Choices[code] + ".png", |
| 113 | onclick: () => Play.playMove(code) |
| 114 | }) |
| 115 | }))]) |
| 116 | ); |
| 117 | } |
| 118 | }; |
| 119 | |
| 120 | socket.on("login", (msg) => { |
| 121 | if (!msg.err) { |
| 122 | localStorage.setItem("name", msg.name); |
| 123 | localStorage.setItem("uid", msg.uid); |
| 124 | m.route.set("/seek"); |
| 125 | } |
| 126 | else alert(msg.err); |
| 127 | }); |
| 128 | socket.on("play", (msg) => { |
| 129 | Seek.searching = false; |
| 130 | if (msg.oppid == getV("uid")) { |
| 131 | alert("Cannot play against self!"); |
| 132 | m.redraw(); //TODO: because no DOM interaction... ? |
| 133 | } |
| 134 | else { |
| 135 | Play.initGame(msg); |
| 136 | m.route.set("/play"); |
| 137 | } |
| 138 | }); |
| 139 | socket.on("move", (msg) => { |
| 140 | Play.oppmove = msg.choice; |
| 141 | Play.oppselect = "?"; //not showing opponent selection yet! |
| 142 | if (Play.mymove) Play.compareMoves(); |
| 143 | else Play.myselect = "?"; |
| 144 | m.redraw(); //TODO... (because no DOM interactions) |
| 145 | }); |
| 146 | |
| 147 | m.route(document.body, "/seek", { |
| 148 | "/seek": Seek, |
| 149 | "/play": Play, |
| 150 | "/login": Login |
| 151 | }); |