Generate a map for a roguelike Today, we'll be generating a map for a roguelike RPG!
Example Map:
##########
####    F#
####    ##
##    C#C#
#     ## #
# C   #E #
####  #  #
#        #
#P       #
##########

# are walls, P is the player's starting location, F is the finish that must be reached, C are coins that can be collected, and E are enemies that can be fought.
Map specifications:

Height and Width should both be between 10 and 39, inclusive. Height does not have to equal width.
The maps borders should be filled in with walls.
P should be placed in the bottom left corner.
F should be placed in the top right corner.
There should be between 1 and 3 enemies.
There should be between 2 and 4 coins.
There should be some amount of walls in the middle. There should be a path to get from P to Every C, E, and F, keeping in mind that the player cannot move diagonally.
Every possible combination should have some chance of occurring.

Rules

Fewest byte program wins.
Your program should not take any input.
Your program may not exit with an error (non-fatal output is STDERR is ok, but we can't have our rogue-like crash after map generation!)
A single trailing newline is allowed and trailing space is allowed.
No other output is allowed.
Perl, 293 bytes

-9 bytes thanks to @Dom Hastings

{$==7+rand 30;@r=$"=();@a=((C)x4,(E)x3,("#")x1369,(" ")x1369);for$i(0..7+rand 30){$r[$i][$_]=splice@a,rand@a,1for 0..$=}$r[0][$=]=F;$r[-1][0]=P;$_=$r=join$/,$v="#"x($=+=3),(map"#@$_#",@r),$v;1while$r=~s/F(.{$=})?[^#F]/F$1F/s||$r=~s/[^#F](.{$=})?F/F$1F/s;$r!~/[CEP]/&amp;&amp;/C.*C/s&amp;&amp;/E/?last:redo}say


Add -E flag to run it:

perl -E '{$==7+rand 30;@r=$"=();@a=((C)x4,(E)x3,("#")x1369,(" ")x1369);for$i(0..7+rand 30){$r[$i][$_]=splice@a,rand@a,1for 0..$=}$r[0][$=]=F;$r[-1][0]=P;$_=$r=join$/,$v="#"x($=+=3),(map"#@$_#",@r),$v;1while$r=~s/F(.{$=})?[^#F]/F$1F/s||$r=~s/[^#F](.{$=})?F/F$1F/s;$r!~/[CEP]/&amp;&amp;/C.*C/s&amp;&amp;/E/?last:redo}say'


However, it takes a long time to run, so I recommend using this version instead:

perl -E '{${$_}=8+rand 30for"=","%";@r=$"=();@a=((C)x4,(E)x3,("#")x($v=rand $=*$%),(" ")x($=*$%-$v));for$i(0..$%-1){$r[$i][$_]=splice@a,rand@a,1for 0..$=-1}$r[0][$=-1]=F;$r[$%-1][0]=P;$_=$r=join$/,$v="#"x($=+=2),(map"#@$_#",@r),$v;1while$r=~s/F(.{$=})?[^#F]/F$1F/s||$r=~s/[^#F](.{$=})?F/F$1F/s;$r!~/[CEP]/&amp;&amp;/C.*C/s&amp;&amp;/E/?last:redo}say'


Try it online!

Explanation


{                     # enter a block (which is used as a loop)
    {$==7+rand 30;                   # randomly select the width of the map -2
                                     # (-2 because we don't include the borders yet)
    @r=$"=();                        # reset @r, and set $" to undef
    @a=(                             # create a list of the character that can be on the board
     (C)x4,                          #  4 coins 'C'
     (E)x3,                          #  3 enemies 'E'
     ("#")x1369,                     #  37*37 '#'
     (" ")x1369);                    #  37*37 spaces
    for$i(0..7+rand 30)                # create the 2D map (7+rand 30 is the height, which is generated just now)
      for$_(0..$=-1){
        $r[$i][$_]=                    # index [$i][$_] receives ...
           splice@a,rand@a,1           # .. a random character from the list previously generated
                                       # (the character is then removed from the list thanks to 'splice')
      }
    }
    $r[0][$=]=F;                       # add the finish cell
    $r[-1][0]=P;                       # add the start cell
    $_=$r=                             # here we generate a string representation of the map
          join$/,                      # join the following elements with newlines
            $v="#"x($=+=3),            # a first line of # only
            (map"#@$_#",@r),           # add a # to the beginning and the end of each line
            $v;                        # the last line of #

    1while                # the following regex will replace every accessible cell with a F
       $r=~s/F(.{$=})?[^#F]/F$1F/s  # a cell on the right or the bottom of a F cell is replaced  
         ||                         # or
       $r=~s/[^#F](.{$=})?F/F$1F/s; # a cell on the left or the top of a F cell is replaced
    $r!~/[CEP]/         # if there is no C, E or P on the map (meaning they were all accessible)
     && /C.*C/s         #  and there are at least 2 coins
     && /E/ ?           #  and 1 enemy
      last:             # the the map is valid, we exit the loop
      redo              # else, start over
}
say                     # and print the board


It takes a long time to run, because the list from which we randomly pick the characters to put on the board (@a) contains 1369 whitespaces and #, and only 4 coins and 3 enemies. So if the size of the width and height are small, there are a lot of spaces and # compared to the coin and the enemies, so it's quite likely that a random map won't be valid. That's why the "optimized" version is faster: the list from which we pick the characters is just a little bigger than the map (the list is @a=((C)x4,(E)x3,("#")x($v=rand $=*$%),($")x($=*$%-$v)) : a random number $v of # (inferior to the size of the map), and size of the map - $v whitespaces).