-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfield.js
146 lines (122 loc) · 3.56 KB
/
field.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
const hatCharacter = "^";
const hole = "O";
const fieldCharacter = "░";
class Field {
constructor(width = 40, height = 20) {
this.height = height;
this.width = width;
this._field = this.generateField();
this.hat = this.placeHat();
this.player = this.placePlayer();
}
playerCharacter = "@'";
collision = "None";
// randomly generate a 2D game map
generateField() {
// Randomly return a hole 10% of the time
const getTerrain = () => (Math.random() > 0.1 ? fieldCharacter : hole);
// Populate each row on the map with terrain
const getRow = () => [...Array(this.width)].map(getTerrain);
// Fill in the field with rows(2D Array)
return [...Array(this.height)].map(getRow);
}
placeHat() {
const [x, y] = this.somePlace();
this._field[y][x] = hatCharacter;
return [x, y];
}
somePlace() {
const y = Math.floor(Math.random() * this.height);
const x = Math.floor(Math.random() * this.width);
return [x, y];
}
placePlayer() {
const [x, y] = this.getPlayerPosition();
this.makeSpaceOnField(x, y);
return [x, y];
}
makeSpaceOnField(x, y) {
this._field[y][x] = fieldCharacter;
this._field[y][x+1] = fieldCharacter;
}
getPlayerPosition() {
const player = this.somePlace();
const minDist = this.getMinDistFromHat();
const distance = this.getHatDistance(player);
if (distance >= minDist) {
return player;
} else {
return this.getPlayerPosition();
}
}
getMinDistFromHat() {
// No matter where the hat is,
// We can always put the player at least this far away:
return Math.max(this.height, this.width) / 2;
}
getHatDistance(player) {
// vector subtraction
const difference = player.map((e, i) => e - this.hat[i]);
// pythagorean theorem returns the magnitude
const square = (x) => x ** 2;
const sum = (x, y) => x + y;
return Math.sqrt(difference.map(square).reduce(sum));
}
movePlayer(direction) {
let [x, y] = this.player;
const moves = {
l: () => (x -= 2) /* move left */,
r: () => (x += 2) /* move right */,
u: () => y-- /* move up */,
d: () => y++ /* move down */,
};
moves[direction]();
this.player = [x, y];
this.updateCollisionState();
}
updateCollisionState() {
if (this.checkIfOutOfBounds()) {
this.collision = "Edge";
} else {
this.collision = this.getCurrentCollision();
}
}
checkIfOutOfBounds() {
const [x, y] = this.player;
if (x < -1 || y < 0 || x > this.width - 1 || y > this.height - 1) {
return true;
}
}
getCurrentCollision() {
const [x, y] = this.player;
// Retrieve the two map characters at the player's current position
const leftChar = this._field[y][x];
const rightChar = this._field[y][x + 1];
// Check for special characters
const isHat = [leftChar, rightChar].includes(hatCharacter);
const isHole = [leftChar, rightChar].includes(hole);
return isHat ? "Hat" : isHole ? "Hole" : "None";
}
display() {
const field = this.copyField();
this.addPlayerToField(field);
this.print(field);
}
copyField() {
return this._field.map((row) => row.map((element) => element));
}
addPlayerToField(field) {
const [x, y] = this.player;
const [leftChar, rightChar] = this.playerCharacter.split('');
field[y][x] = leftChar;
field[y][x + 1] = rightChar;
}
print(field=this.field) {
field.forEach(row => console.log(row.join("")));
}
}
module.exports.Field = Field;
if (require.main === module) {
field = new Field();
field.display();
}