1- /*
2- * Currently uses a grid based system, will upgrade to more fancy stuff later
3- * The movement is simulated, then a series of movement points is passed to the module context, which the frontend then uses to render
4- */
5-
61import context from 'js-slang/context' ;
72import {
8- accumulate ,
93 head ,
104 tail ,
115 type List
126} from 'js-slang/dist/stdlib/list' ;
137
148type Point = { x : number , y : number } ;
15- type Intersection = { x : number , y : number , dist : number }
9+ type PointWithRotation = { x : number , y : number , angle : number }
10+
11+ type CommandData = {
12+ type : String ,
13+ location : PointWithRotation
14+ }
1615
1716type Polygon = Point [ ] ;
1817
@@ -24,8 +23,7 @@ type StateData = {
2423 movePoints : Point [ ] ,
2524 message : string ,
2625 success : boolean ,
27- messages : string [ ] ,
28- rotations : Point [ ]
26+ messages : string [ ]
2927} ;
3028
3129type Robot = {
@@ -44,8 +42,7 @@ const stateData: StateData = {
4442 movePoints : [ ] ,
4543 message : 'moved successfully' ,
4644 success : true ,
47- messages : [ ] ,
48- rotations : [ ]
45+ messages : [ ]
4946} ;
5047
5148const robot : Robot = {
@@ -58,6 +55,7 @@ const robot: Robot = {
5855
5956let bounds : Point [ ] = [ ] ;
6057
58+ // sets the context to the statedata obj, mostly for convenience so i dont have to type context.... everytime
6159context . moduleContexts . robot_minigame . state = stateData ;
6260
6361export function set_pos ( x : number , y : number ) : void {
@@ -73,11 +71,15 @@ export function set_height(height: number) {
7371 stateData . height = height ;
7472}
7573
74+ // condenses setting the width and height of map, and the initial position of robot in one call
7675export function init ( width : number , height : number , posX : number , posY : number ) {
76+ if ( stateData . isInit ) return ; // dont allow init more than once
77+
7778 set_width ( width ) ;
7879 set_height ( height ) ;
7980 set_pos ( posX , posY ) ;
80- stateData . movePoints . push ( { x : posX , y : posY } ) ;
81+
82+ stateData . movePoints . push ( { x : posX , y : posY } ) ; // push starting point to movepoints data
8183 stateData . isInit = true ;
8284
8385 bounds = [
@@ -86,7 +88,6 @@ export function init(width: number, height: number, posX: number, posY: number)
8688 { x : width , y : height } ,
8789 { x : 0 , y : height }
8890 ] ;
89-
9091}
9192
9293export function turn_left ( ) {
@@ -97,9 +98,11 @@ export function turn_left() {
9798 robot . dx = Math . cos ( currentAngle ) ;
9899 robot . dy = - Math . sin ( currentAngle ) ;
99100
101+ // prevent floating point issues
100102 if ( robot . dx < 0.00001 && robot . dx > - 0.00001 ) robot . dx = 0 ;
101103 if ( robot . dy < 0.00001 && robot . dy > - 0.00001 ) robot . dy = 0 ;
102104
105+ // debug log
103106 logCoordinates ( ) ;
104107}
105108
@@ -114,6 +117,7 @@ export function turn_right() {
114117 if ( robot . dx < 0.00001 && robot . dx > - 0.00001 ) robot . dx = 0 ;
115118 if ( robot . dy < 0.00001 && robot . dy > - 0.00001 ) robot . dy = 0 ;
116119
120+ // debug log
117121 logCoordinates ( ) ;
118122}
119123
@@ -124,10 +128,11 @@ export function rotate_right(angle: number) {
124128
125129 robot . dx = Math . cos ( currentAngle ) ;
126130 robot . dy = - Math . sin ( currentAngle ) ;
127-
131+
128132 if ( robot . dx < 0.00001 && robot . dx > - 0.00001 ) robot . dx = 0 ;
129133 if ( robot . dy < 0.00001 && robot . dy > - 0.00001 ) robot . dy = 0 ;
130134
135+ // debug log
131136 logCoordinates ( ) ;
132137}
133138
@@ -145,6 +150,7 @@ export function rotate_left(angle: number) {
145150 logCoordinates ( ) ;
146151}
147152
153+ // easily set up a rectangular wall using the x and y of the top left corner, and width/height
148154export function set_rect_wall ( x : number , y : number , width : number , height : number ) {
149155 const polygon : Polygon = [
150156 { x : x , y : y } ,
@@ -156,8 +162,11 @@ export function set_rect_wall(x: number, y: number, width: number, height: numbe
156162 stateData . walls . push ( polygon ) ;
157163}
158164
165+ // creates irregularly shaped wall
166+ // takes in a list of vertices as its argument
159167export function set_polygon_wall ( vertices : List ) {
160168 const polygon : Polygon = [ ]
169+
161170 while ( vertices != null ) {
162171 const p = head ( vertices ) ;
163172 polygon . push ( { x : head ( p ) , y : tail ( p ) } ) ;
@@ -175,80 +184,114 @@ export function getY():number {
175184 return robot . y ;
176185}
177186
178- export function move_forward ( ) : void {
187+ // moves robot to the nearest wall
188+ export function move_forward_to_wall ( ) : void {
179189 if ( alrCollided ( ) ) return ;
180190
181- let distance = findCollision ( ) ;
191+ let distance = findMoveDistance ( ) ; // do the raycast, figure out how far the robot is from the nearest wall
192+
193+ // a lil extra offset from wall
182194 distance = Math . max ( distance - robot . radius - 5 , 0 )
183195
184196 const nextPoint : Point = {
185197 x : robot . x + distance * robot . dx ,
186198 y : robot . y + distance * robot . dy
187199 }
188200
189-
190201 robot . x = nextPoint . x ;
191202 robot . y = nextPoint . y ;
192203 stateData . movePoints . push ( nextPoint ) ;
204+
205+ // for debug
193206 stateData . messages . push ( `Distance is ${ distance } Collision point at x: ${ nextPoint . x } , y: ${ nextPoint . y } ` ) ;
194207}
195208
196- function findCollision ( ) : number {
197- let nearest : Point | null = null ;
209+ // Moves forward by a small amount
210+ export function move_forward ( moveDist : number ) : void {
211+ const nextPoint : Point = {
212+ x : robot . x + moveDist * robot . dx ,
213+ y : robot . y + moveDist + robot . dy
214+ }
215+
216+ // need to check for collision with wall
217+
218+ robot . x = nextPoint . x ;
219+ robot . y = nextPoint . y ;
220+ stateData . movePoints . push ( nextPoint ) ;
221+
222+ logCoordinates ( ) ;
223+ }
224+
225+ export function sensor ( ) : boolean {
226+ return false ;
227+ }
228+
229+ // returns the distance from the nearest wall
230+ function findMoveDistance ( ) : number {
198231 let minDist : number = Infinity ;
199232
233+ // loop through all the walls
200234 for ( const wall of stateData . walls ) {
201- const intersection : Intersection | null = raycast ( wall ) ;
202- if ( intersection !== null && intersection . dist < minDist ) {
203- minDist = intersection . dist ;
204- nearest = { x : intersection . x , y : intersection . y } ;
235+ const intersectionDist = raycast ( wall ) ; // do the raycast
236+
237+ // if intersection is closer, update minDist
238+ if ( intersectionDist !== null && intersectionDist < minDist ) {
239+ minDist = intersectionDist ;
205240 }
206241 }
207242
208243 // check outer bounds as well
209- const intersection : Intersection | null = raycast ( bounds ) ;
210- if ( intersection !== null && intersection . dist < minDist ) {
211- minDist = intersection . dist ;
212- nearest = { x : intersection . x , y : intersection . y } ;
244+ const intersectionDist = raycast ( bounds ) ;
245+ if ( intersectionDist !== null && intersectionDist < minDist ) {
246+ minDist = intersectionDist ;
213247 }
214248
215- return minDist === Infinity ? 0 : minDist ; // Closest intersection point
249+ // Closest intersection point
250+ // By all rights, there should always be an intersection point since the robot is always within the bounds
251+ // and the bounds should be a collision
252+ // but something goes wrong, will just return 0
253+ return minDist === Infinity ? 0 : minDist ;
216254}
217255
218- function raycast ( polygon : Polygon ) : Intersection | null {
256+ // does the raycast logic for one particular wall
257+ // three rays are cast: one from the center, one from the top and one from the bottom. the minimum dist is returned
258+ // return null if no collision
259+ function raycast ( polygon : Polygon ) : number | null {
219260 let minDist = Infinity ;
220- let nearest : Intersection | null = null ;
221261
222262 for ( let i = 0 ; i < polygon . length ; i ++ ) {
263+ // wall line segment
223264 const x1 = polygon [ i ] . x , y1 = polygon [ i ] . y ;
224265 const x2 = polygon [ ( i + 1 ) % polygon . length ] . x , y2 = polygon [ ( i + 1 ) % polygon . length ] . y ;
225266
267+ // calculate the top and bottom coordinates of the robot
226268 const topX = robot . x - robot . radius * robot . dy ;
227269 const topY = robot . y - robot . radius * robot . dx ;
228270
229271 const bottomX = robot . x + robot . radius * robot . dy ;
230272 const bottomY = robot . y + robot . radius * robot . dx ;
231273
274+ // raycast from 3 sources: top, middle, bottom
232275 const raycast_sources : Point [ ] = [
233276 { x : robot . x , y : robot . y } ,
234277 { x : topX , y : topY } ,
235278 { x : bottomX , y : bottomY }
236279 ]
237280
238281 for ( const source of raycast_sources ) {
239- const intersection = getIntersection ( source . x , source . y , robot . dx + source . x , robot . dy + source . y , x1 , y1 , x2 , y2 ) ;
240- if ( intersection !== null && intersection . dist < minDist ) {
241- minDist = intersection . dist ;
242- nearest = intersection ;
282+ const intersectionDist = getIntersection ( source . x , source . y , robot . dx + source . x , robot . dy + source . y , x1 , y1 , x2 , y2 ) ;
283+ if ( intersectionDist !== null && intersectionDist < minDist ) {
284+ minDist = intersectionDist ;
243285 }
244286 }
245287 }
246288
247- return nearest ;
289+ return minDist === Infinity ? null : minDist ;
248290}
249291
250292// Determine if a ray and a line segment intersect, and if so, determine the collision point
251- function getIntersection ( x1 , y1 , x2 , y2 , x3 , y3 , x4 , y4 ) : Intersection | null {
293+ // returns null if there's no collision, or the distance to the line segment if collides
294+ function getIntersection ( x1 , y1 , x2 , y2 , x3 , y3 , x4 , y4 ) : number | null {
252295 const denom = ( ( x2 - x1 ) * ( y4 - y3 ) - ( y2 - y1 ) * ( x4 - x3 ) ) ;
253296 let r ;
254297 let s ;
@@ -276,9 +319,9 @@ function getIntersection(x1, y1, x2, y2, x3, y3, x4, y4): Intersection | null {
276319 }
277320 }
278321
279- if ( ! b ) return null
322+ if ( ! b ) return null ;
280323
281- return { x : x , y : y , dist : r }
324+ return r ;
282325}
283326
284327function alrCollided ( ) {
0 commit comments