_Title "I Robot - Room Mapper 5 (IR-RM5)" ' b+ 22-02-11 ' 22-02-23 started writing code
' The little guy, say a vaccum cleaner, is plopped down somewhere in it's new home.
' The first order of business is to map out it's area of duty,
' say sweep the whole floor without getting stuck or wasting allot of moves.
' It is square and can sense, resistence on any of its edges.
' It is allowed to go N,S,E,W - the four directions
' If something is sensed on one side it is forbidden to
' enter that square from that direction.
' Rule of economy - don't reenter a square already occupied
' unless that is the only way to go.
' Do we have enough spelled out to map a room?
' A room is a grid of squares, we don't know the dimensions
' and there are objects in many of the middle squares or along
' the walls. Later we may encounter objects that move around
' like pets or results of fickle home decorators.
' God provides a room with objetcs and randomly drops the robot
' into it.
' 22-02-23 first goal is to get an edges mapped. so make up a room
' Upon some more thinking and just to get the ball rolling, I will
' allow robot vaccum sweeper to use the room map and mark it with it's
' own numbers, so now the walls are -1, empty areas 0, places visited
' are positive numbers, everytime the vacuum reoccupies the square
' the number is increased.
' OK the room setup seems satisfactory onto RI = Robot Intelligence
' OK first run it does eventually cover the whole room.
' Need to know when it has done the whole room. There are some
' places that have to be left 0
' IR-RM2 next mod
' 2022-02-24 what I need is path finder, then I can see which squares are
' accessible to robot from middle of the room, so I can mark and then
' I will be able to tell when Robot has visited all spaces it can.
' ALSO I can use pathfinder to get at next closest enpty square.
' OK the subs from PathFinder 3a are loaded and working with Option _Explicit.
' Next job is to mark all places vacuum can access checks, so we can then
' have a check to see if all areas covered by vac.
' 2022-02-26 Got the bug causing once in a blue moon problem with room fills
' ie leaving empty spaces not accessible to vacuum. Could the other once in a blue
' moon problem be similar. RI is trying to path to target at 0,0.
' Ho, ho yes! very likely the same problem!!!
' 2022-02-27 fix some things color the furniture, debug the way the furniture
' was supposed to be placed around the room ie not into the walls!
' IR-RM3 next mod,
' 2022-02-28 give RI a stack to save locations of empty cells it passes by.
' I think that might improve performance because it will get unswept sections
' while it's still nearby? That is the hypothesis, now for the experiment.
' Stack is NOT WORKING this code is dead end!
' IR_RM4 next mod
' Every space the RI occupies, update the 4 cell neighbor status as empty or not
' in an empty cell array, then when RI needs to know closest empty use that map.
' OK that works but now find the shortest path lengths to an empty cell.
' IR-RM5
' 2022-03-01 Today we find the mt cell with shortest path to roby.
' That got working right quick. I want to test another patern for priortizing
' which empty cell order to use.
Const SW
= 1021, SH
= 721 ' cell @30 max 34x24 Const MapW
= 17, MapH
= 17 ' min @30 cell is 17, 17
Dim Shared As Long MagicRequired
' this is to signal that RI could not find the next empty cell without appeal to Gods
Dim Shared As Long BeeLine
, Done
' Roby is in beeLine Mode heading to closet empty (unvac'd) cell using steps from Path Finder app
Done = 0
rx
= Int(MapW
/ 2 + .5): ry
= Int(MapH
/ 2 + .5) ' starts here in middle of room should be clear MakeRoom
drawRoom 'ok the middle of room is staying clear of stuff
' debug check path works
'path rx, ry, 5, 5 'does this still work OH YEAH! Better than ever!
'_Display
RI ' ok roby make your move
' debug just checking rooms made right
'Sleep
'Cls
'Exit Do
'Print "Finished press any for next run zzz..."
'Sleep
sweeps = sweeps + 1
_Title "I Robot - Room Mapper 2 (IR-RM2) " + Str$(sweeps
) + " successful rooms swept, magic needed" + Str$(MagicRequired
) + " times."
Sub RI
' the robot appraises it's current postition rx, ry in Room(x) and makes a move changing rx, ry and that ends the sub Dim As Long mini
, x
, y
, saveX
, saveY
, mtDist
, delayFlag
' I was here! sweeps the spot (again?)
Room(rx, ry) = Room(rx, ry) + 1 ' put roby's presense on map
mt(rx, ry) = 0 'no longer mt
' remember what we found here when we need an empty cell loaction
If Room
(rx
, ry
- 1) = 0 Then mt
(rx
, ry
- 1) = -1 If Room
(rx
+ 1, ry
) = 0 Then mt
(rx
+ 1, ry
) = -1 If Room
(rx
, ry
+ 1) = 0 Then mt
(rx
, ry
+ 1) = -1 If Room
(rx
- 1, ry
) = 0 Then mt
(rx
- 1, ry
) = -1
' after marking current spot see if we have swept all possible
If BeeLine
= 0 Then ' normal sweeping pattern, hey try up/down then right/left see if leaves less spots
' still here ? ========== Decide to make a BeeLine - find the closet empty and make a bee-line to it
BeeLine = -1 'put us into BeeLine Mode
'do we have an empty cell location in the stack
prepStepMap rx, ry ' this will get us a map of how far away all accessible cells are
' now consult stepMap of x,y
mini = 10000000: delayFlag = 0
For y
= 1 To MapH
' now run through step map and find the mini closest empty room If mt
(x
, y
) = -1 Then ' a known empty cell we passed mtDist = StepMap(x, y)
If mtDist
< mini
And mtDist
> 1 Then mini
= mtDist: saveX
= x: saveY
= y
'from a number of runs with IR-RM4 this should not ever be needed but just in case
If mini
= 10000000 Then 'we did not find an empty cell we passed by, not a single one!?!? ' I hope we never have to here!!! I am betting we never should unless a really odd perfect storm
Beep ' signal we had to resort to magically finding and empty cell MagicRequired = MagicRequired + 1 'set flag, no the amount of times
delayFlag = -1 ' I want to see where I had to use magic
For y
= 1 To MapH
' now run through step map and find the mini closest empty room If StepMap
(x
, y
) > 1 Then ' has to be > 1 because 0 is robot and 1 the robot will detect! If StepMap
(x
, y
) < mini
And Room
(x
, y
) = 0 Then mini
= StepMap
(x
, y
): saveX
= x: saveY
= y
'OK we have our target not find a clear short path to it from roby
path rx, ry, saveX, saveY ' path sets stepI, stepX(i), stepY(I) that are shared
If delayFlag
Then Sleep ' let's get a good look at the empty cell we had to magically find
StepI = 1 ' roby is on it's way to closet empty cell
'debug
'Print StepI, StepX(StepI), StepY(StepI)
'_display
'Beep
'Sleep ' let me see that path we made
rx = StepX(StepI): ry = StepY(StepI)
' beeline mode
StepI = StepI + 1 ' roby is on it's way to closet empty cell
rx = StepX(StepI): ry = StepY(StepI)
'turn of beeLine mode when we have hit target
If StepI
= StepDist
- 1 Then BeeLine
= 0 ' we have arrived at our target turn off beeLine mode
drawGridSq
Line ((x
- 1) * 30, (y
- 1) * 30)-Step(30, 30), 8, BF
Line ((x
- 1) * 30, (y
- 1) * 30)-Step(30, 30), 0, BF
Line ((x
- 1) * 30, (y
- 1) * 30)-Step(30, 30), Abs(Room
(x
, y
)) - 15, BF
ElseIf Room
(x
, y
) = 0 Then ' i want to see if the room is listed in the stack between pull and stack If mt
(x
, y
) = -1 Then 'signal an mt cell that is known to RI _PrintString ((x
- 1) * 30 + (30 - 8) / 2, (y
- 1) * 30 + 7), "*" ' and robot
Line ((rx
- 1) * 30, (ry
- 1) * 30)-Step(30, 30), 14, BF
ReDim As Long Room
(1 To MapW
, 1 To MapH
) ' 0 = empty, -1 = wall, -2 = area vac can't access because walled out Dim As Long x
, y
, i
, rw
, rh
, wall
, ys
, xs
, clr
' Here are the walls
Room(x, 1) = -1
Room(x, MapH) = -1
Room(1, y) = -1
Room(MapW, y) = -1
' add random rectangles around the edges
xs = irnd&(2, MapW - 1 - rw)
For y
= ys
To ys
+ rh
- 1 For x
= xs
To xs
+ rw
- 1 Room(x, y) = clr
ys = irnd(2, MapH - 1 - rh)
For y
= ys
To ys
+ rh
- 1 For x
= xs
To xs
+ rw
- 1 Room(x, y) = clr
If Rnd < .5 Then ys
= MapH
- rh
- 1 Else ys
= (MapH
- 2) - rh
- 1 xs = irnd(2, MapW - 1 - rw)
For y
= ys
To ys
+ rh
- 1 For x
= xs
To xs
+ rw
- 1 Room(x, y) = clr
ys = irnd(2, MapH - rh - 1)
For y
= ys
To ys
+ rh
- 1 For x
= xs
To xs
+ rw
- 1 Room(x, y) = clr
' before make map make sure rx, ry is set or reset
prepStepMap rx, ry ' see what cells not accessible to vac mark them -1
If StepMap
(x
, y
) = 0 Then Room
(x
, y
) = -2 Room(rx, ry) = 0 ' not a -2 room!
swept% = -1 ' all clean!
prepStepMap tx, ty
dist = StepMap(sx, sy) 'STEPMAP is DIM SHARED as INTEGER
StepDist = dist
StepI = 0
' Beep
'refresh
StepI = 0 'DIM SHARED error signal
cx = sx: cy = sy
'LOCATE 2, 1: PRINT "cx, cy: "; cx, cy '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< debug
cf = 0
'PRINT "x, y, STEPMAP(x, y) "; x, y, STEPMAP(x, y)
If StepMap
(x
, y
) = dist
- 1 Then StepI = StepI + 1
StepX(StepI) = x: StepY(StepI) = y
Line ((StepX
(StepI
) - 1) * 30 + 1, (StepY
(StepI
) - 1) * 30 + 2)-Step(30 - 2, 30 - 1), 10, B
Line ((StepX
(StepI
) - 1) * 30 + 2, (StepY
(StepI
) - 1) * 30 + 2)-Step(30 - 2, 30 - 2), 10, B
Line ((StepX
(StepI
) - 1) * 30 + 3, (StepY
(StepI
) - 1) * 30 + 2)-Step(30 - 2, 30 - 3), 10, B
Line ((StepX
(StepI
) - 1) * 30 + 4, (StepY
(StepI
) - 1) * 30 + 2)-Step(30 - 2, 30 - 4), 10, B
cx = StepX(StepI): cy = StepY(StepI)
dist = dist - 1
Sub prepStepMap
(tx
As Long, ty
As Long) ' ========================================== no more diagonal steps Dim As Long x
, y
, tick
, changes
, ystart
, ystop
, xstart
, xstop
StepMap(tx, ty) = 1: tick = 1: changes = 1
tick = tick + 1: changes = 0
ystart = max(ty - tick, 1): ystop = min(ty + tick, MapH)
xstart = max(tx - tick, 1): xstop = min(tx + tick, MapW)
'check out the neighbors
If Room
(x
, y
) >= 0 Then ' places OK to go 'cf = 0
' ============================================================= new >>> path finder that won't take diagonal steps
'need to check 4 cells around x, y for parent
If StepMap
(x
- 1, y
) = tick
- 1 And StepMap
(x
, y
) = 0 Then StepMap(x, y) = tick
' 2 line debug =====================================================
's$ = _Trim$(Str$(StepMap(x, y)))
'_PrintString ((x - 1) * 30 + (30 - Len(s$) * 8) / 2, (y - 1) * 30 + 7), s$
If StepMap
(x
+ 1, y
) = tick
- 1 And StepMap
(x
, y
) = 0 Then StepMap(x, y) = tick
' debug
's$ = _Trim$(Str$(StepMap(x, y)))
'_PrintString ((x - 1) * 30 + (30 - Len(s$) * 8) / 2, (y - 1) * 30 + 7), s$
If StepMap
(x
, y
- 1) = tick
- 1 And StepMap
(x
, y
) = 0 Then StepMap(x, y) = tick
' debug
's$ = _Trim$(Str$(StepMap(x, y)))
'_PrintString ((x - 1) * 30 + (30 - Len(s$) * 8) / 2, (y - 1) * 30 + 7), s$
If StepMap
(x
, y
+ 1) = tick
- 1 And StepMap
(x
, y
) = 0 Then StepMap(x, y) = tick
' debug
's$ = _Trim$(Str$(StepMap(x, y)))
'_PrintString ((x - 1) * 30 + (30 - Len(s$) * 8) / 2, (y - 1) * 30 + 7), s$
changes = 1
skip:
'Beep
Function irnd&
(n1
, n2
) 'return an integer between 2 numbers If n1
> n2
Then l%
= n2: h%
= n1
Else l%
= n1: h%
= n2
irnd&
= Int(Rnd * (h%
- l%
+ 1)) + l%