home · contact · privacy
0ca95ed908a1a8d3c42bcf276e896560a2b7db85
[plomrogue2-experiments] / new2 / rogue_chat_nocanvas_monochrome.html
1 <!DOCTYPE html>
2 <html><head>
3 <style>
4 </style>
5 </head><body>
6 <pre id="terminal" style="display: inline-block; color: white; background-color: black;"></pre>
7 <script>
8 "use strict";
9 let websocket_location = "ws://localhost:8000";
10
11 let terminal = {
12   rows: 24,
13   cols: 80,
14   initialize: function() {
15     this.pre_el = document.getElementById("terminal");
16     this.content = [];
17       let line = []
18     for (let y = 0, x = 0; y <= this.rows; x++) {
19         if (x == this.cols) {
20             x = 0;
21             y += 1;
22             this.content.push(line);
23             line = [];
24             if (y == this.rows) {
25                 break;
26             }
27         }
28         line.push(' ');
29     }
30       console.log(this.content);
31   },
32   refresh: function() {
33       let pre_string = '';
34       for (let y = 0; y < this.rows; y++) {
35           let line = this.content[y].join('');
36           pre_string += line + '\n';
37       }
38       this.pre_el.textContent = pre_string;
39   },
40   write: function(start_y, start_x, msg) {
41       for (let x = start_x, i = 0; x < this.cols, i < msg.length; x++, i++) {
42           this.content[start_y][x] = msg[i];
43       }
44   },
45   drawBox: function(start_y, start_x, height, width) {
46     let end_y = start_y + height;
47     let end_x = start_x + width;
48     for (let y = start_y, x = start_x; y < end_y; x++) {
49         this.content[y][x] = ' ';
50         if (x == end_x) {
51             x = start_x - 1;
52             y += 1;
53         }
54     }
55   },
56 }
57
58 let parser = {
59   tokenize: function(str) {
60     let tokens = [];
61     let token = ''
62     let quoted = false;
63     let escaped = false;
64     for (let i = 0; i < str.length; i++) {
65       let c = str[i];
66       if (quoted) {
67         if (escaped) {
68           token += c;
69           escaped = false;
70         } else if (c == '\\') {
71           escaped = true;
72         } else if (c == '"') {
73             quoted = false
74         } else {
75           token += c;
76         }
77       } else if (c == '"') {
78         quoted = true
79       } else if (c === ' ') {
80         if (token.length > 0) {
81           tokens.push(token);
82           token = '';
83         }
84       } else {
85         token += c;
86       }
87     }
88     if (token.length > 0) {
89       tokens.push(token);
90     }
91     return tokens;
92   },
93   parse_yx(position_string) {
94     let coordinate_strings = position_string.split(',')
95     let position = [0, 0];
96     position[0] = parseInt(coordinate_strings[0].slice(2));
97     position[1] = parseInt(coordinate_strings[1].slice(2));
98     return position;
99   }
100 }
101
102 let tui = {
103   draw_history: function() {
104     terminal.drawBox(1, terminal.cols / 2, terminal.rows - 2, terminal.cols / 2);
105     let i = 0;
106     for (let line of chat.history) {
107       terminal.write(terminal.rows - 2 - i, terminal.cols / 2, line);
108       i += 1;
109     }
110   },
111   draw_map: function() {
112     let map_lines = [];
113     let line = '';
114     for (let i = 0, j = 0; i < game.map.length; i++, j++) {
115         if (j == game.map_size[1]) {
116             map_lines.push(line);
117             line = '';
118             j = 0;
119         };
120         line += game.map[i];
121     };
122     map_lines.push(line);
123     for (let y = 0; y < game.map_size[0]; y++) {
124         terminal.write(y, 0, map_lines[y]);
125     }
126     for (const t in game.things) {
127       terminal.write(game.things[t][0], game.things[t][1], '@');
128     }
129   },
130   draw_turn_line: function(n) {
131     terminal.drawBox(0, terminal.cols / 2, 1, terminal.cols / 2);
132     terminal.write(0, terminal.cols / 2, 'turn: ' + game.turn);
133   },
134   draw_input_line: function() {
135     terminal.drawBox(terminal.rows - 1, terminal.cols / 2, 1, terminal.cols / 2);
136     terminal.write(terminal.rows - 1, terminal.cols / 2, chat.input_line);
137   },
138   log_msg: function(msg, indent=0) {
139     let line_length = (terminal.cols / 2) - indent;
140     let chunk = "";
141     for (let i = 0, x = 0; i < msg.length; i++, x++) {
142       if (x >= line_length) {
143         chat.history.unshift(' '.repeat(indent) + chunk);
144         chunk = "";
145         x = 0;
146       };
147       chunk += msg[i];
148     }
149     chat.history.unshift(' '.repeat(indent) + chunk);
150     while (chat.history.length > terminal.rows - 2) {
151       chat.history.pop();
152     };
153     this.draw_history();
154   },
155   refresh: function() {
156     terminal.refresh();
157   }
158 }
159
160 let game = {
161   things: {},
162   turn: 0,
163   map: "",
164   map_size: [0,0]
165 }
166
167 let chat = {
168   input_line: "",
169   history: []
170 }
171
172 terminal.initialize();
173
174 tui.draw_map();
175 tui.draw_turn_line();
176 tui.draw_history();
177 tui.draw_input_line();
178 tui.refresh();
179
180 tui.log_msg("basic commands:", 1);
181 tui.log_msg("LOGIN USER - register as USER", 3);
182 tui.log_msg("ALL TEXT - send TEXT to all users", 3);
183 tui.log_msg("QUERY USER TEXT - send TEXT to USER", 3);
184 tui.log_msg("");
185 tui.log_msg("Use arrow keys to move your avatar. You can only move over \".\" map cells.", 1);
186 tui.log_msg("");
187 tui.log_msg("Use double quotes for strings that contain whitespace, escape them with \\.", 1);
188 tui.log_msg("");
189 tui.log_msg("To change the map cell you are standing on, type the desired ASCII character into the prompt and hit Return.", 1);
190 tui.log_msg("");
191 tui.log_msg("more commands:", 1);
192 tui.log_msg("FLATTEN - transform surrounding map cells to \".\" ones", 3);
193 tui.log_msg("");
194
195 let websocket = new WebSocket(websocket_location);
196 websocket.onmessage = function (event) {
197   let tokens = parser.tokenize(event.data);
198   if (tokens[0] === 'TURN') {
199     game.things = {}
200     game.turn = parseInt(tokens[1]);
201   } else if (tokens[0] === 'THING_POS') {
202     game.things[tokens[1]] = parser.parse_yx(tokens[2]);
203   } else if (tokens[0] === 'MAP') {
204     game.map_size = parser.parse_yx(tokens[1]);
205     game.map = tokens[2]
206   } else if (tokens[0] === 'GAME_STATE_COMPLETE') {
207     tui.draw_turn_line();
208     tui.draw_map();
209     tui.refresh();
210   } else if (tokens[0] === 'LOG') {
211      tui.log_msg(tokens[1], 1);
212      tui.refresh();
213   } else if (tokens[0] === 'META') {
214      tui.log_msg(tokens[1]);
215      tui.refresh();
216   } else if (tokens[0] === 'UNHANDLED_INPUT') {
217      tui.log_msg('unknown command');
218      tui.refresh();
219   } else if (tokens[0] === 'ARGUMENT_ERROR') {
220      tui.log_msg('syntax error: ' + tokens[1]);
221      tui.refresh();
222   } else if (tokens[0] === 'GAME_ERROR') {
223      tui.log_msg('game error: ' + tokens[1]);
224      tui.refresh();
225   } else if (tokens[0] === 'PONG') {
226     console.log('PONG');
227   } else {
228      tui.log_msg('unhandled input: ' + event.data);
229      tui.refresh();
230   }
231 }
232
233 document.addEventListener('keydown', (event) => {
234   if (chat.input_line === '') {
235     tui.draw_input_line();
236     tui.refresh();
237   }
238   if (event.key && event.key.length === 1) {
239     chat.input_line += event.key;
240     tui.draw_input_line();
241     tui.refresh();
242   } else if (event.key === 'Backspace') {
243     chat.input_line = chat.input_line.slice(0, -1);
244     tui.draw_input_line();
245     tui.refresh();
246   } else if (event.key === 'Enter') {
247     if (chat.input_line.length === 1) {
248       websocket.send("TASK:WRITE " + chat.input_line);
249     } else if (chat.input_line.trimEnd() === 'FLATTEN') {
250       websocket.send("TASK:FLATTEN_SURROUNDINGS");
251     } else {
252       websocket.send(chat.input_line);
253     }
254     chat.input_line = '';
255     tui.draw_input_line();
256   } else if (event.key === 'ArrowLeft') {
257     websocket.send('TASK:MOVE LEFT');
258   } else if (event.key === 'ArrowRight') {
259     websocket.send('TASK:MOVE RIGHT');
260   } else if (event.key === 'ArrowUp') {
261     websocket.send('TASK:MOVE UP');
262   } else if (event.key === 'ArrowDown') {
263     websocket.send('TASK:MOVE DOWN');
264   };
265 }, false);
266
267 window.setInterval(function() { websocket.send('PING') }, 30000);
268 </script>
269 </body></html>