public void Remove(EnvKey key) { if (this.values == null) { return; } this.values.Remove(key); if (this.values.Count == 0) { this.values = null; } }
public object this[EnvKey key] { get { return(this.values[key]); } set { if (this.values == null) { this.values = new Dictionary <EnvKey, object>(); } this.values[key] = value; } }
public T Get <T>(EnvKey key) { if (this.values == null || !this.values.ContainsKey(key)) { return(default(T)); } object value = values[key]; try { return((T)value); } catch (InvalidCastException e) { throw new Exception($"不能把{value.GetType()}转换为{typeof (T)}", e); } }
public string this[string name] { get { if (name == "EnvKey") { if (EnvKey.Trim() == "") { return("Key is required, and can't be all spaces."); } else if (checkDup(EnvKey)) { return(string.Format("Key {0} is duplicate!!!", EnvKey)); } } return(null); } }
//--------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------- //bot makes a plan of action (determines place to reach) and starts moving private void figureOutWhereToHeadTo() { //resest action lists + variables possibleLeftActions.Clear(); possibleRightActions.Clear(); jumpPlatforms.Clear(); holeSpottedB4 = false; //get x position of closest left and right wall float rightWallLocation = info[new EnvKey('R', 0, 0)].location().x; float leftWallLocation = info[new EnvKey('L', 0, 0)].location().x; //bot takes into account it's last action/location lastAction = action.Equals(null) ? 'A' : action.direction; lastMovement = action.Equals(null) ? 1 : (int)Mathf.Sign(action.x); //the bot looks to its left for 1) openings in the floor it can drop down in 2) seperate platforms it can jump to for (int offset = -1; offset >= -5; offset--) { EnvKey floorCheck = new EnvKey('G', offset, 0); EnvKey prevFloorCheck = new EnvKey('G', offset + 1, 0); //make sure this opening in the floor is not behind a wall (as the bot can't just walk straight to it then) if (info[floorCheck].location().x > leftWallLocation) { //consider going to the first drop down opening on it's left if (info[floorCheck].location().y <= transform.position.y - 3.2f && !holeSpottedB4) { holeSpottedB4 = true; possibleLeftActions.Add(floorCheck); } //consider going to the first seperate platform it can jump to on it's left if (offset != -1 && info[floorCheck].location().y > transform.position.y - 6.5f && info[prevFloorCheck].location().y <= info[floorCheck].location().y - 0.1f && holeSpottedB4) { possibleLeftActions.Add(floorCheck); } } } //reset hole spotted variable holeSpottedB4 = false; //the bot looks to its right for 1) openings in the floor it can drop down in 2) seperate platforms it can jump to for (int offset = 1; offset <= 5; offset++) { EnvKey floorCheck = new EnvKey('G', offset, 0); EnvKey prevFloorCheck = new EnvKey('G', offset - 1, 0); //make sure this opening in the floor is not behind a wall (as the bot can't just walk straight to it then) if (info[floorCheck].location().x < rightWallLocation) { //consider going to the first drop down opening on it's right if (info[floorCheck].location().y <= transform.position.y - 3.2f && !holeSpottedB4) { holeSpottedB4 = true; possibleRightActions.Add(floorCheck); } //consider going to the first seperate platform it can jump to on it's right else if (offset != 1 && info[floorCheck].location().y > transform.position.y - 6.5f && info[prevFloorCheck].location().y <= info[floorCheck].location().y - 0.1f && holeSpottedB4) { possibleRightActions.Add(floorCheck); } } } //if there is a hallway to the right, consider going there if (possibleRightActions.Count <= 1 && rightWallLocation > transform.position.x + 2f) { //bot should usually consider going right (if it wasn't already going left or if it can't go LEFT next turn) if (lastAction != 'L' || leftWallLocation >= transform.position.x - 2.5f) { possibleRightActions.Add(new EnvKey('R', 0, 0)); } //if the bot was previously heading left, it should rarely consider going right else if (lastAction == 'L') { int r = Random.Range(0, 10); if (r >= 9) { possibleRightActions.Add(new EnvKey('R', 0, 0)); } } } //if there is a hallway to the left, still consider going there if (possibleLeftActions.Count <= 1 && leftWallLocation < transform.position.x - 2f) { //bot should usually consider going left (if it wasn't already going right or if it can't go right next turn) if (lastAction != 'R' || rightWallLocation <= transform.position.x + 2.5f) { possibleLeftActions.Add(new EnvKey('L', 0, 0)); } //if the bot was previously heading right, it should rarely consider going left else if (lastAction == 'R') { int r = Random.Range(0, 10); if (r >= 9) { possibleLeftActions.Add(new EnvKey('L', 0, 0)); } } } //the bot checks for openings in the ceiling for (int offset = -5; offset <= 5; offset++) { //get the y coordinate of the ceiling above the player EnvKey ceilingCheck = new EnvKey('C', offset, 0); EnvInfo ceiling = info[ceilingCheck]; //get the expected height a ceiling should be (for a normal ceiling with no opening) float expectedHeight = 4f + transform.position.y; float ceilingHeight = ceiling.location().y; //if there is a gap in the ceiling, and its not behind a left or right wall if (ceilingHeight > expectedHeight && ceiling.location().x < rightWallLocation && ceiling.location().x > leftWallLocation) { //if the bot theoretically jumped through the ceiling gap, calculate how far back the left and right walls are on the new platform they would land on Vector2 rayCastOrigin = new Vector2(transform.position.x + offset * 1.5f, transform.position.y + 4f); RaycastHit2D leftHit = Physics2D.Raycast(rayCastOrigin, Vector2.left, 9f, Constants.map); RaycastHit2D rightHit = Physics2D.Raycast(rayCastOrigin, Vector2.right, 9f, Constants.map); float leftUpperWall = (leftHit.collider != null) ? leftHit.point.x : rayCastOrigin.x - 9; float rightUpperWall = (rightHit.collider != null) ? rightHit.point.x : rayCastOrigin.x + 9; float rightUpperWallDistance = rightUpperWall - rayCastOrigin.x; float leftUpperWallDistance = rayCastOrigin.x - leftUpperWall; //setting these variables to miscellaneous values to avoid null errors EnvInfo leftCeiling = info[new EnvKey('C', 0, 0)]; EnvInfo rightCeiling = info[new EnvKey('C', 0, 0)]; float leftCeilingHeight = 0, rightCeilingHeight = 0; GameObject leftCeilingObject = null, rightCeilingObject = null; //can't do left ceiling checks for the left most ceiling and vice versa on the right side if (offset != -5) { leftCeiling = info[new EnvKey('C', offset - 1, 0)]; leftCeilingHeight = leftCeiling.location().y; leftCeilingObject = leftCeiling.gameObject(); } if (offset != 5) { rightCeiling = info[new EnvKey('C', offset + 1, 0)]; rightCeilingHeight = rightCeiling.location().y; rightCeilingObject = rightCeiling.gameObject(); } GameObject groundObject = info[new EnvKey('G', 0, 0)].gameObject(); //get the tilt of the walls directly to the left and right of the bot right now EnvInfo rightWall = info[new EnvKey('R', 0, 0)]; float rightWallTilt = rightWall.gameObject() ? rightWall.gameObject().transform.eulerAngles.z : 0f; EnvInfo leftWall = info[new EnvKey('L', 0, 0)]; float leftWallTilt = leftWall.gameObject() ? leftWall.gameObject().transform.eulerAngles.z : 0f; //if bot spots an opening in the ceiling to its left or right and there is ceiling directly to the right of the opening, //then add this jump as a possible action as long as there is no nearby ramp to the right if (offset != 5 && rightCeilingHeight < expectedHeight && rightUpperWallDistance > 2f && rightCeilingObject != groundObject && (!rightWall.gameObject() || Mathf.Abs(rightCeiling.location().x - rightWall.location().x) > 1.51f || !wallIsActuallyARamp(rightWallTilt))) { if (offset > 0) { possibleRightActions.Add(ceilingCheck); } else if (offset < 0) { possibleLeftActions.Add(ceilingCheck); } else if (offset == 0) { if (ceiling.location().x >= transform.position.x) { possibleRightActions.Add(ceilingCheck); } else { possibleLeftActions.Add(ceilingCheck); } } jumpPlatforms.Add(ceilingCheck, "right"); jumpToHeight = transform.position.y + 4f; } //if bot spots an opening in the ceiling to its left or right, but there is ceiling directly to the left of the opening in the ceiling, then add this jump as a possible action else if (offset != -5 && leftCeilingHeight < expectedHeight && leftUpperWallDistance > 2f && leftCeilingObject != groundObject && (!leftWall.gameObject() || Mathf.Abs(leftCeiling.location().x - leftWall.location().x) > 1.51f || !wallIsActuallyARamp(leftWallTilt))) { if (offset > 0) { possibleRightActions.Add(ceilingCheck); } else if (offset < 0) { possibleLeftActions.Add(ceilingCheck); } else if (offset == 0) { if (ceiling.location().x <= transform.position.x) { possibleLeftActions.Add(ceilingCheck); } else { possibleRightActions.Add(ceilingCheck); } } jumpPlatforms.Add(ceilingCheck, "left"); jumpToHeight = transform.position.y + 4f; } } } //bot chooses where to head to action = pickPossibleAction(); endSpot = info[action].location(); action.printColored(); //bot heads to the place it chose if (action.direction == 'G') { check = 1; dir = Mathf.Sign(action.x); } else if (action.direction == 'R') { check = 201; dir = 1; } else if (action.direction == 'L') { check = 201; dir = -1; } else if (action.direction == 'C') { dir = Mathf.Sign(action.x); check = 301; } rig.velocity = new Vector2(botSpeed * dir, rig.velocity.y); actionsTakenToExecutePath(); }
//--------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------- //Now that the bot has chosen a place to reach, tell it how to get there private void actionsTakenToExecutePath() { //check for gaps in the way if the bot is heading far right if (action.x > 0 && action.direction == 'G') { for (int i = 1; i < action.x; i++) { EnvInfo nextRaycast = info[new EnvKey('G', i, action.y)]; //some gap is in the way, so the bot will remember its coordinate to jump over it if (nextRaycast.location().y < info[action].location().y - 0.1f) { check = 2; jumpCoordinate = nextRaycast.location().x; ceilingCheckAboveJump = new EnvKey('C', i, action.y); break; } } } //check for gaps in the way if the bot is heading far left if (action.x < 0 && action.direction == 'G') { for (int i = -1; i > action.x; i--) { EnvInfo nextRaycast = info[new EnvKey('G', i, action.y)]; //some gap is in the way, so the bot will remember its coordinate to jump over it if (nextRaycast.location().y < info[action].location().y - 0.1f) { check = 2; jumpCoordinate = nextRaycast.location().x; ceilingCheckAboveJump = new EnvKey('C', i, action.y); break; } } } //if there is a gap in the way as the bot heads left or right if (action.x != 0 && action.direction == 'G' && check == 2) { dontJump = false; //if there is a ceiling in the way, the bot will jump when its closer to its end destination to avoid head butting into the ceiling if (info[new EnvKey(ceilingCheckAboveJump.direction, ceilingCheckAboveJump.x + (int)Mathf.Sign(action.x), ceilingCheckAboveJump.y)].location().y < transform.position.y + 2f) { dontJump = true; } } //if heading left or right in a hallway, define the spot where the bot must refigure out what to do if (action.direction == 'R') { endSpot = new Vector2(info[action].location().x - 2, 0); } if (action.direction == 'L') { endSpot = new Vector2(info[action].location().x + 2, 0); } }
public static string VarToken(TInput input, EnvKey key) => input[key];
public static SyntaxNode Var(TInput input, EnvKey key) => input.inputTree.Leaves().Where(l => l.code == input[key]).ArgMin(l => l.depth);
public static double EnvKey(EnvKey key) => 1;
public override int GetHashCode() { return(EnvKey.GetHashCode()); }
private ProgramNode VarToken(EnvKey key) => new NonterminalNode(Op(nameof(Semantics.VarToken)), Input, Key(key));
private ProgramNode Key(EnvKey key) => new LiteralNode(Symbol("key"), key);
public string this[EnvKey key] { get => env[key];