I'm currently working on the roborally boardgame. In short it boils down to small robots that are programmed by the player (e.g. 2 forward, turn left, 1 backward, turn right, 1 forward). The robot is on a grid map. Let me add an
example
As you may have gathered, I'd like to create this in maptool.
The challenge I lay before thee (and myself) is: how do I store the mapping of the board?
Note that there are different types of 'coordinates' that are of importance:
1. CELL coordinate e.g. one of the
pits
2. GRID-LINE coordinate e.g. one of the
walls
3. COMBINATION coordinate e.g. an
converging express band
4. DEPENDENT coordinate e.g. a
laser
obviously everything needs to be fast enough to keep it going.
What I'm looking for is: what method can I best use to 'store' this information and 'retrieve' it when the robots starts moving.
Additional info:
- There are 100'sof boards. What I want to do is 'prep' a few of them (and create the tools for user to prep others) using some editor. These boards should contain the relevant information (although the info could also be on a lib stored with the name of the map). Point is: these boards can be ROTATED and CONNECTED. So you can create a map of multiple (rotated) boards. Something to take into consideration.
- If you follow the above link you will see that there are many many many different types of board tiles (beside the wall, pit, laser, express band), but they all fit into one of the 4 categories.
What I have initially in mind, but pls shoot if you have a better idea. Feel free to discard this as TLDNR and just blurt your opinion/advi…
- type: pit, laser, express band, gear left, gear rigth, etc.
- direction: 0,1,2,3,4 OR 0,E,N,W,S OR 0, TOP, LEFT, BOTTOM, RIGHT. Where '0' means none (e.g. with a pit it is of no importance).
Im inclined to use the numerical reprisentation due to its potential cyclic nature (with the use of a mod) so multiple rotations can be added.
note: with the combined expressband this could be tricky as you have three types:
- turn in from left side
- turn in from right side
- turn in from both sides!
--> im inclined to use the direction of the expressband as the direction of the tile and make them 3 different types.
What is tricky in this is that there are 4 rotation factors:
1. the orientation of the 'feature' on the tile (e.g. wall facing west)
2. the orientation of the tile on the board e.g. 90 degrees
3. the orientation of the board on the map! e.g. 180 degrees
4. the orientation of the robot riding over the board and over the tile
this makes it a bit tricky to keep track of the lot.
When the tiles have been placed:
- I use some parser to store each tile and its position and rotation in e.g. a strprop. (Structure ???)
- then store that strprop either in a lib:token with the board name, including the board orientation (although maybe it should be unrotated to begin with. check this!) or store it directly on the board.
--> what would the structure look like...?: lets give this also a stab.
ASSUMPTIONS (which can be checked):
- board tile is UNROTATED
- board tile UPPER LEFT is 0,0
- board tile is UNFLIPPED (IRC cannot be checked).
- board is 10x10 (as an example)
STORAGE:
- strprops are key value pairs so xCoord_yCoord=type_rotation e.g. "5_3=pit_0 ; 0_0=floor_0 ; 10_10=wall_3"
- The exception (and real pain the donkey) here are the lasers, I guess the 'origin' can be the same where type is 'laser1' or 'laser2', etc. and the direction is where the laser points to (so exits the tile). The pain is however keeping track of it afterwards....
RETRIEVAL:
- when using numerical representation of the rotation for the tiles I *think* you can simply add them (mod4) to see the current actual position. And deducting the entrance point of the robot from this number should result in 0 to have a trigger... need to check. (correct!!)
example: E=0 dg=0, N=90 dg=1, W=180=2, S=3. A tile facing south (hence rotated 270 dg) has rotation=3, on a board rotate 180 dg (so rotation 2) results in 5 mod 4 = 1 or 90 dg or north. This is correct.
Note: bot_getTokenFacing() results in the above dg (e.g. N==90)
Next the entry of the robot should be determined on FROM WHERE it enters the tile, if this is also 1 or 90 or NORTH then the tile property is activated.
Thus:
IF ((TR+BR) mod 4) - RE == 0 THEN tile is 'active' on robot. In case of e.g. wall, this would result in the token not moving. In case of express band... this would require additional investigation as the 'rotation activation' are 90dg off of the tile rotation.
direction of the robot can simply be deduced from its movement (if any). Movement is ALWAYS forward or backward hence the direction of movement is the direction its facing and if moving backwards, just add 2 (mod 4) to that directionnumber.
Note that there do exist 'move sideways' cards, but they are not CORE, so ignore for now.
Note that with walls you also need to check the current tile the robot is on.
Note when moving OVER tiles (e.g. when moving 3 squares at once), some tiles are active when moved over (like walls and pits) while some tiles are NOT active when moving over (like lasers and express bands).
The info of the tiles themselves
- varsfromstrprop on the big board variable.
- This creates variables like: '2_3' (= x_y)
- with those defined you can use [eval(getTokenX(0, robot)+"_"+getTokenY(0, robot))] which returns the cell type and orientation of the CURRENT tile
- then there are 4 movementtypes: -1, 0,1,2 and 3 (these are NOT directions but #cells). Direction only needs to be determined ONCE after that check all the cell BEFORE moving the robot.
could use a count(moveCount) option and simply retrieve all info from all tiles. While loop is better as it can be exited earlier (in case of e.g. pit and wall).
--> checkRobotFloorInteraction(robot, direction, currentTile, nextTile) returns true false. True means that robot moves, False means the robot cannot move.
or something like that.
TO BE CONTINUED
Board Rotation effect on tile position
Yb = the length of the UNROTATED board (y direction) - 1
Xt = the x position of the robot on the board, or the tile coord. You wish to check
Yt = the y position of the robot on the board, or the tile coord. You wish to check
Code: Select all
rotation Xtn Ytn
0 Xt Yt
1 Yt Xb-Xt
2 Xb-Xt Yb-Yt
3 Yb-Yb Xt
This also helps with future offsets when more boards are used.
IDENTIFIED ISSUE: when using multiple boards e.g. 4 then when executing the strprop you will overwrite the results of the former board e.g. all boards have keys 0_0, 0_1, 0_2 etc. so maybe add unique identifier like name.
Possible other solution: store x/y board coordinates not as 3_4 but as 3+Xo_4+Yo and use replace()...need to check.
BATs and MATs
- 'move activated tiles' (pit, wall, etc.): you only need to check these tiles when the robot moves. These tiles are 'location' activated (that means that you check the current location of the robot and its next and reference a 'table' to see of there are 'move activated tiles'. Lets call these MATs
- 'board activated tiles' (laser, express band, etc.): you need to check these tiles during the board fase and in this case you cycle through those tiles and check if a robot is standing on them (laser is here an annoying exception). Lets call these BATs
Hence per board you need to store two things: a (translatable) coordinate map with all the floortiles and MATs and a list of all the BATs with there (translatable) coordinates.
Thus a laser (which is always combined with a wall) is both a MAT (wall) and a BAT (laser).
Looking from that perspective its probly easier to do lasers anyway. As during the board fase you cycle through all BATs and when you encounter a laser you can use the canMoveCheck() macro (either recursively or while ?) in the direction of the laser to work through all the tiles until you reach either a wall, the edge or a robot.
Core ruleset:
BATs: Checkpoint & Repair Site, (express) conveyor belt, Pusher, Gears, Crusher
MATs: Wall, Pit
I guess I will split up the laser into the laser and wall part. Ive seen more element overlapping on some boards so thats not so uncommon.
Same thing thus for the pusher!! (which also has a wall)
Checking for for BATs I could create a json object of the current coordinates where they are and use a json.get(batList, locationRobot) to see if anything comes up.... which won't work as you need to do them in order. So potentially one json object per tile_type (probly less as you can group certain types in a smart way). I see potential issue with two robots on e.g. express band right behind eachother...
rules of order
Board Elements Move
1. Express conveyor belts move 1 space in the direction of the arrows.
2. Express conveyor belts and normal conveyor belts move 1 space in the direction of the arrows.
3. Pushers push if active.
4. Gears rotate 90° in the direction of the arrows.
5. Crushers destroy robot
6. lasers inflict one damage per beam.
7. Robots touch Flags and place Archive Markers. Note that 'safety copy' is placed when robot moves OVER (or onto) the checkpoint. Repairs ONLY take place when the robot moves ONTO the repairs site or check site (1 point for a wrench and 1 additional for the hammer. Checkpoints only 1).
End of Turn: Robots on wrench spaces discard 1 Damage Token. Robots on wrench/Hammer spaces also draw 1 Option card (new rules: additional repair).
this means that to use the json.get() trick you will need
1. json object with all express belts
2. json object with ALL belts
3. json object with pushers
4. json object with the rest
and check these in that order. Seperate macro check is required when two robots 'meet' while on an a belt. E.g. opposite direction push == standoff, same direction push == both move ONE space
collision check by jagged
Code: Select all
[h:bot1=arg(0)]
[h:bot2=arg(1)]
[h:c1=getTokenX(0,bot1)+":"+getTokenY(0,bot1)]
[h:n1=getProperty("nextX",bot1)+":"+getProperty("nextY",bot1)]
[h:c2=getTokenX(0,bot2)+":"+getTokenY(0,bot2)]
[h:n2=getProperty("nextX",bot2)+":"+getProperty("nextY",bot2)]
[h:result=0]
[h,if(n1==n2):result=1]
[h,if(c1==n2 && c2==n1):result=1]
[h:macro.return=result]