-
Notifications
You must be signed in to change notification settings - Fork 0
/
textgame.js
165 lines (125 loc) · 4.5 KB
/
textgame.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/*
A tiny learning project library to help implement text games.
Subclass TextGame to use it. The baseclass only echoes what it recieves.
Additional classes and functions are also included to
speed up development of games.
*/
class TextGame {
createUI() {
const textLogArea = document.createElement("OL");
textLogArea.classList.add("text-display");
this.textLogArea = textLogArea;
this.containerElement.appendChild(textLogArea);
const inputForm = document.createElement("form")
inputForm.parentTextGame = this;
inputForm.classList.add("game-repl-form");
const promptElement = document.createElement("textarea");
promptElement.spellcheck = false;
inputForm.appendChild(promptElement);
this.promptElement = promptElement;
this.inputForm = inputForm;
this.inputForm.promptElement = promptElement;
this.containerElement.appendChild(inputForm);
}
// smooths over locking the input element against user interference
set inputLocked(state) {
this.promptElement.disabled = state;
}
// smooths checking whether the input element is currently locked
get inputLocked() {
return this.promptElement.disabled;
}
handleInput(inputLine) {
/*
User games should override this method when they subclass.
*/
//by default, the behavior is to just be an echo prompt
this.addLine(inputLine);
}
constructor(containerElement) {
this.containerElement = containerElement;
containerElement.classList.add("game-container");
//bind this object to the game so we can access it later.
containerElement.controllingGame = this;
this.createUI();
// bind all pressing of the enter key to "submit" the text.
this.inputForm.addEventListener("keypress",
/* "this" keyword refers to the form in the context of the bound
* function rather than the this in the local context as expected
* in python lambdas. */
function(event) {
if (event.key === "Enter") {
event.preventDefault();
const input = this.promptElement.value;
this.promptElement.value = "";
const game = this.parentTextGame;
game.inputLocked = true;
game.handleInput(input);
game.inputLocked = false;
//todo: for longer-running calls, this may not be a good idea.
this.promptElement.focus();
}
}
);
/* make all click events within the parent element focus the textbox
so it behaves like a terminal window without cursor support enabled. */
containerElement.addEventListener("click",
function(e) {
containerElement.controllingGame.promptElement.focus();
}
);
this.promptElement.focus();
};
addLine(message) {
const newMessage = document.createElement("LI");
newMessage.classList.add("text-message");
newMessage.innerText = message;
this.textLogArea.appendChild(newMessage);
}
clearLines() {
// Remove all lines of text from the display area
const lines = this.textLogArea;
while ( lines.firstChild ) {
lines.removeChild(lines.lastChild);
}
}
}
const chooseIndex = (indexedArray) => {
//Choose a random index in the passed array and return it
return Math.floor(Math.random() * indexedArray.length);
}
class ChoicePool extends Set {
/*
Extends basic set with choice-related functionality.
Currently repackages an implementation of choices that
was a quick hack. Future implementation details may change.
*/
constructor(iterable) {
if(iterable) {
super(iterable);
}
else {
super();
}
this._rebuildArrayCache();
}
_rebuildArrayCache() {
this._arrayCache = [...this];
}
add(elt) {
if(! this.has(elt)) {
super.add(elt);
this._rebuildArrayCache();
}
}
delete(elt) {
if( this.has(elt) ) {
super.delete(elt);
this._rebuildArrayCache();
}
}
choose() {
return this._arrayCache[chooseIndex(this._arrayCache)];
}
}
export { TextGame , ChoicePool };