public void Make( int Seed, String Filename ) { System.Console.WriteLine( "Generating Map [{0}]", Filename ); Random Gen = new Random( Seed ); xml.Version = 1; xml.Date = DateTime.Now; xml.Generator = Generator.MAIDynamicRooms; xml.Seed = Seed; xml.LOS = LOS; xml.LOSSpecified = true; xml.Start = new Coord( ); xml.Goal = new Coord( ); if ( UseCorners ) { xml.Start.X = 0; xml.Start.Y = 0; xml.Goal.X = xml.Width - 1; xml.Goal.Y = xml.Height - 1; } else { double Dis; do { xml.Start.X = Gen.Next( xml.Width ); xml.Start.Y = Gen.Next( xml.Height ); xml.Goal.X = Gen.Next( xml.Width ); xml.Goal.Y = Gen.Next( xml.Height ); Dis = Distance.OctileDistance( xml.Start.X, xml.Goal.X, xml.Start.Y, xml.Goal.Y ); } while ( Dis < MinHDistance || Dis > MaxHDistance ); } GenericGridWorldDynamicState DS = new GenericGridWorldDynamicState( ); GenericGridWorldStaticState SS = new GenericGridWorldStaticState( xml.Height, xml.Width, DS ); DS.AddWorldObject( new Unit( xml.Start.X, xml.Start.Y, xml.Height, xml.Width, xml.Goal.X, xml.Goal.Y, LOS, 0 ) ); int RoomWidth = xml.Width / this.NumHorzRooms; int RoomHeight = xml.Height / this.NumVertRooms; bool[,] TilesBlocked = new bool[xml.Width, xml.Height]; for ( int Y = 0 ; Y < xml.Height ; Y++ ) { for ( int X = 0 ; X < xml.Width ; X++ ) { SS.Tiles[Y][X] = new PassableTile<GenericGridWorldStaticState, GenericGridWorldDynamicState>( X, Y, xml.Height, xml.Width ); TilesBlocked[X, Y] = false; } } // Vert Walls for ( int Y = RoomHeight ; Y < xml.Height ; Y+=RoomHeight ) { for ( int X = 0 ; X < xml.Width ; X++ ) { if ( !( X == xml.Start.X && Y == xml.Start.Y ) && !( Y == xml.Goal.Y && X == xml.Goal.X ) ) { SS.Tiles[Y][X] = new BlockedTile<GenericGridWorldStaticState, GenericGridWorldDynamicState>( X, Y, xml.Height, xml.Width ); TilesBlocked[X, Y] = true; } } } // Horz Walls for ( int X = RoomWidth ; X < xml.Width ; X+=RoomWidth ) { for ( int Y = 0 ; Y < xml.Height ; Y++ ) { if ( !( X == xml.Start.X && Y == xml.Start.Y ) && !( Y == xml.Goal.Y && X == xml.Goal.X ) ) { SS.Tiles[Y][X] = new BlockedTile<GenericGridWorldStaticState, GenericGridWorldDynamicState>( X, Y, xml.Height, xml.Width ); TilesBlocked[X, Y] = true; } } } List<Door> Doors = new List<Door>( ); // Vert Doors for ( int Y = RoomHeight ; Y < xml.Height ; Y+=RoomHeight ) { for ( int X = RoomWidth/2 ; X < xml.Width ; X+=RoomWidth ) { if ( !( X == xml.Start.X && Y == xml.Start.Y ) && !( Y == xml.Goal.Y && X == xml.Goal.X ) ) { SS.Tiles[Y][X] = new PassableTile<GenericGridWorldStaticState, GenericGridWorldDynamicState>( X, Y, xml.Height, xml.Width ); if ( ( X/RoomWidth ) % VertRoomModifier == 0 ) { Doors.Add( new Door( ) { Open = true, X = X, Y = Y } ); TilesBlocked[X, Y] = false; } } } } // Horz Doors for ( int X = RoomWidth ; X < xml.Width ; X+=RoomWidth ) { for ( int Y = RoomHeight/2 ; Y < xml.Height ; Y+=RoomHeight ) { if ( !( X == xml.Start.X && Y == xml.Start.Y ) && !( Y == xml.Goal.Y && X == xml.Goal.X ) ) { SS.Tiles[Y][X] = new PassableTile<GenericGridWorldStaticState, GenericGridWorldDynamicState>( X, Y, xml.Height, xml.Width ); if ( ( Y/RoomHeight ) % HorzRoomModifier == 0 ) { Doors.Add( new Door( ) { Open = true, X = X, Y = Y } ); TilesBlocked[X, Y] = false; } } } } xml.Tiles = GridWorldFormat.ToTileString( SS, DS ); try { var sol = new AStar< GenericGridWorldStaticState, GenericGridWorldDynamicState>( new SingleUnitOctileDistanceHeuristic( ), true, null ) .Compute( SS, SS.InitialDynamicState, new DestinationsReachedGoal( ), GridWorldOperator.Ops ).First( ); xml.OptimalSolutionCost = sol.Cost.ToDouble( ); xml.OptimalSolutionCostSpecified = true; if ( !UseCorners && ( xml.OptimalSolutionCost < MinAStarDistance || xml.OptimalSolutionCost > MaxAStarDistance ) ) { throw new ChokepointGridWorldMaker.MapCreationFailed( ); } System.Console.WriteLine( "\tMap Generated Solution Cost [{0}]", sol.Cost ); } catch ( PathNotFoundException ) { System.Console.WriteLine( "\tMap Generation Failed [{0}]", Filename ); throw new ChokepointGridWorldMaker.MapCreationFailed( ); } List<Step> ChangeList = new List<Step>( ); Step step = new Step( ); int sN; List<Coord> Changes; List<Door> DoorChanges; // Add one for skipped. step.StepNum = 0; step.Changes = new Coord[] { }; ChangeList.Add( step ); for ( sN = 1 ; sN < NumSteps + 1; sN++ ) { step = new Step( ); step.StepNum = sN; do { Changes = new List<Coord>( ); DoorChanges = new List<Door>( ); foreach ( Door D in Doors ) { if ( D.Open ) { if ( Gen.NextDouble( ) < ChanceClose ) { D.Open = false; Changes.Add( new Coord( ) { X = D.X, Y = D.Y } ); DoorChanges.Add( D ); TilesBlocked[D.X, D.Y] = true; } } else { if ( Gen.NextDouble( ) < ChanceOpen ) { D.Open = true; Changes.Add( new Coord( ) { X = D.X, Y = D.Y } ); DoorChanges.Add( D ); TilesBlocked[D.X, D.Y] = false; } } } } while ( !ResolveReachability( DoorChanges, Changes, TilesBlocked, new Point( xml.Goal.X, xml.Goal.Y ), xml.Width, xml.Height ) ); step.Changes = Changes.ToArray( ); ChangeList.Insert( ChangeList.Count, step ); } // Add one more step to guarentee repeatablity. step = new Step( ); step.StepNum = sN; Changes = new List<Coord>( ); foreach ( Door D in Doors ) { if ( !D.Open ) { Changes.Add( new Coord( ) { X = D.X, Y = D.Y } ); } } step.Changes = Changes.ToArray( ); ChangeList.Insert( ChangeList.Count, step ); xml.ChangeList = new ChangeList( ); xml.ChangeList.Repeatable = true; xml.ChangeList.BlockOnAgent = false; xml.ChangeList.Steps = ChangeList.ToArray( ); System.Console.WriteLine( "\tMap Generated [{0}]", Filename ); XmlSerializer s = new XmlSerializer( typeof( Map ) ); TextWriter w = new StreamWriter( Filename ); s.Serialize( w, xml ); w.Close( ); }
private static void DrawLine( Point From, Point To, Map xml, GenericGridWorldStaticState SS, Point Unit, bool[][] tiles ) { Point Cur = From; Stack<Point> Blocked = new Stack<Point>( ); while ( !Cur.Equals( To ) ) { Cur = Next( Cur, xml.Width, xml.Height, To ); if ( SS.Tiles[Cur.Y][Cur.X] is ChokeTile<GenericGridWorldStaticState, GenericGridWorldDynamicState> ) { continue; } else if ( Unit.X == Cur.X && Unit.Y == Cur.Y ) { continue; } else if ( SS.Tiles[Cur.Y][Cur.X] is BlockedTile<GenericGridWorldStaticState, GenericGridWorldDynamicState> ) { while ( Blocked.Count != 0 ) { Cur = Blocked.Pop( ); SS.Tiles[Cur.Y][Cur.X] = new PassableTile<GenericGridWorldStaticState, GenericGridWorldDynamicState>( Cur.X, Cur.Y, xml.Height, xml.Width ); tiles[Cur.Y][Cur.X] = false; } break; } else { SS.Tiles[Cur.Y][Cur.X] = new BlockedTile<GenericGridWorldStaticState, GenericGridWorldDynamicState>( Cur.X, Cur.Y, xml.Height, xml.Width ); Blocked.Push( Cur ); tiles[Cur.Y][Cur.X] = true; } } }
public void Make( int Seed, String Filename ) { System.Console.WriteLine( "Generating Map [{0}]", Filename ); Random Gen = new Random( Seed ); xml.Version = 1; xml.Date = DateTime.Now; xml.Generator = Generator.MAIDynamicChokepoint; xml.Seed = Seed; xml.LOS = LOS; xml.Start = new Coord( ); xml.Start.X = Gen.Next( xml.Width ); xml.Start.Y = Gen.Next( xml.Height ); xml.Goal = new Coord( ); xml.Goal.X = Gen.Next( xml.Width ); xml.Goal.Y = Gen.Next( xml.Height ); GenericGridWorldDynamicState DS = new GenericGridWorldDynamicState( ); GenericGridWorldStaticState SS = new GenericGridWorldStaticState( xml.Height, xml.Width, DS ); DS.AddWorldObject( new Unit( xml.Start.X, xml.Start.Y, xml.Height, xml.Width, xml.Goal.X, xml.Goal.Y, LOS, 0 ) ); bool[][] tiles = new bool[xml.Height][]; for ( int i = 0 ; i < xml.Height ; i++ ) { tiles[i] = new bool[xml.Width]; } LinkedList<Point> ChokePoints = new LinkedList<Point>( ); for ( int i = 0 ; i < NumChokepoints ; i++ ) { ChokePoints.AddFirst( new Point( Gen.Next( xml.Width ), Gen.Next( xml.Height ) ) ); } for ( int Y = 0 ; Y < xml.Height ; Y++ ) { for ( int X = 0 ; X < xml.Width ; X++ ) { if ( ChokePoints.Any( cp => Distance.OctileDistance( cp.X, X, cp.Y, Y ) <= ChokepointRadius ) ) { SS.Tiles[Y][X] = new ChokeTile<GenericGridWorldStaticState, GenericGridWorldDynamicState>( X, Y, xml.Height, xml.Width ); tiles[Y][X] = false; } else { SS.Tiles[Y][X] = new PassableTile<GenericGridWorldStaticState, GenericGridWorldDynamicState>( X, Y, xml.Height, xml.Width ); tiles[Y][X] = false; } } } Point U = new Point( xml.Start.X, xml.Start.Y ); foreach ( var From in ChokePoints ) { foreach ( var To in ChokePoints ) { DrawLine( From, To, xml, SS, U, tiles ); } } xml.Tiles = GridWorldFormat.ToTileString( SS, DS ); try { var sol = new AStar< GenericGridWorldStaticState, GenericGridWorldDynamicState>( new SingleUnitOctileDistanceHeuristic( ), true, null ) .Compute( SS, SS.InitialDynamicState, new DestinationsReachedGoal( ), GridWorldOperator.Ops ).First( ); System.Console.WriteLine( "\tMap Generated Solution Cost [{0}]", sol.Cost ); } catch ( PathNotFoundException ) { System.Console.WriteLine( "\tMap Generation Failed [{0}]", Filename ); throw new MapCreationFailed( ); } LinkedList<Point> AgentsLocs = new LinkedList<Point>( ChokePoints.Take( NumAgents ) ); LinkedList<Agent> Agents = new LinkedList<Agent>( ); foreach ( Point Loc in AgentsLocs ) { Agents.AddFirst( new Agent( ) { Location = Loc, Dst = Loc, Start = Loc } ); } LinkedList<Step> ChangeList = new LinkedList<Step>( ); for ( int sN = 0 ; sN < NumSteps || !AllAtStart( Agents ) ; sN++ ) { Step step = new Step( ); step.StepNum = sN; List<Coord> Changes = new List<Coord>( ); if ( sN == 0 ) { foreach ( Agent Agent in Agents ) { ToogleCircle( tiles, Agent.Location, AgentRadius, Changes, xml.Width, xml.Height, Agent.Location, Agents, AgentRadius, false ); } } foreach ( Agent Agent in Agents ) { if ( sN < NumSteps && sN != 0 && Agent.Location.Equals( Agent.Dst ) && ( Gen.NextDouble( ) < MoveRate ) ) { var NotReserved = ChokePoints.Where( x => !Agents.Any( a => a.Dst.Equals( x ) ) ); if ( NotReserved.Count( ) > 0 ) { Agent.Dst = NotReserved.Skip( Gen.Next( NotReserved.Count( ) ) ).First( ); } } else if ( !( sN < NumSteps ) ) { Agent.Dst = Agent.Start; } if ( !Agent.Location.Equals( Agent.Dst ) ) { ToogleCircle( tiles, Agent.Location, AgentRadius, Changes, xml.Width, xml.Height, Agent.Location, Agents, AgentRadius, false ); Agent.Location = NextAll( Agent.Location, xml.Width, xml.Height, Agent.Dst ); ToogleCircle( tiles, Agent.Location, AgentRadius, Changes, xml.Width, xml.Height, Agent.Location, Agents, AgentRadius, false ); } } step.Changes = Optimize( Changes ).ToArray( ); ChangeList.AddLast( step ); } xml.ChangeList = new ChangeList( ); xml.ChangeList.Repeatable = true; xml.ChangeList.BlockOnAgent = true; xml.ChangeList.Steps = ChangeList.ToArray( ); System.Console.WriteLine( "\tMap Generated [{0}]", Filename ); XmlSerializer s = new XmlSerializer( typeof( Map ) ); TextWriter w = new StreamWriter( Filename ); s.Serialize( w, xml ); w.Close( ); }
/// <summary> /// Converts the GridWorld into a simple string representation. This /// is for debugging purposes. /// </summary> /// <param name="GridWorldStaticState">The static state to stringilize /// </param> /// <param name="GridWorldDynamicState">The dynamic state to stringilize /// and yes if you are wondering I just made that word up but I think /// it sounds really cool.</param> /// <returns>A string.</returns> public static string ToString( GenericGridWorldStaticState GridWorldStaticState, GenericGridWorldDynamicState GridWorldDynamicState) { System.Text.StringBuilder sb = new System.Text.StringBuilder( ); sb.Append( " " ); for ( int j = 0 ; j < GridWorldStaticState.Width ; j++ ) { sb.Append( j % 10 ); } sb.Append( "\r\n" ); for ( int i = 0 ; i < GridWorldStaticState.Tiles.Length ; i++ ) { sb.Append( i % 10 + " " ); foreach ( var x in GridWorldStaticState.Tiles[i] ) { sb.Append( GetAscii( x, GridWorldDynamicState. GetWorldObjects( ) ) ); } sb.Append( "\r\n" ); } return sb.ToString( ); }