Class: Pacman::Arcade::World

Inherits:
Object
  • Object
show all
Defined in:
lib/pacman/arcade/world.rb

Overview

The aggregate root: owns every actor and advances the whole game one tick at a time. As the composition root it accepts the full cast — the wide keyword list is deliberate and isolated behind the .classic factory.

Constant Summary collapse

GHOST_STRIDE =
2
FRIGHTENED_STRIDE =
3
STARTING_LIVES =
3

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(maze:, player:, pellets:, scoreboard:, ghosts: [], schedule: nil, rng: Random.new) ⇒ World

Returns a new instance of World.



45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/pacman/arcade/world.rb', line 45

def initialize(maze:, player:, pellets:, scoreboard:, ghosts: [], schedule: nil, rng: Random.new)
  @maze = maze
  @player = player
  @pellets = pellets
  @scoreboard = scoreboard
  @ghosts = ghosts
  @schedule = schedule
  @rng = rng
  @navigator = Navigator.new(maze)
  @lives = STARTING_LIVES
  @level = 1
  @ticks = 0
end

Instance Attribute Details

#ghostsObject (readonly)

Returns the value of attribute ghosts.



13
14
15
# File 'lib/pacman/arcade/world.rb', line 13

def ghosts
  @ghosts
end

#levelObject (readonly)

Returns the value of attribute level.



13
14
15
# File 'lib/pacman/arcade/world.rb', line 13

def level
  @level
end

#livesObject (readonly)

Returns the value of attribute lives.



13
14
15
# File 'lib/pacman/arcade/world.rb', line 13

def lives
  @lives
end

#mazeObject (readonly)

Returns the value of attribute maze.



13
14
15
# File 'lib/pacman/arcade/world.rb', line 13

def maze
  @maze
end

Returns the value of attribute navigator.



13
14
15
# File 'lib/pacman/arcade/world.rb', line 13

def navigator
  @navigator
end

#pelletsObject (readonly)

Returns the value of attribute pellets.



13
14
15
# File 'lib/pacman/arcade/world.rb', line 13

def pellets
  @pellets
end

#playerObject (readonly)

Returns the value of attribute player.



13
14
15
# File 'lib/pacman/arcade/world.rb', line 13

def player
  @player
end

#rngObject (readonly)

Returns the value of attribute rng.



13
14
15
# File 'lib/pacman/arcade/world.rb', line 13

def rng
  @rng
end

Class Method Details

.classic(rng: Random.new) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/pacman/arcade/world.rb', line 15

def self.classic(rng: Random.new)
  maze = Maze.new(Layouts::CLASSIC)
  new(
    maze: maze,
    player: Player.new(position: maze.player_start, direction: Direction.left),
    pellets: PelletField.new(pellets: maze.pellet_positions, powers: maze.power_positions),
    scoreboard: Scoreboard.new,
    ghosts: classic_ghosts(maze, rng),
    schedule: ModeSchedule.new(scatter_ticks: 40, chase_ticks: 120, frightened_ticks: 50),
    rng: rng
  )
end

.classic_ghosts(maze, rng) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/pacman/arcade/world.rb', line 28

def self.classic_ghosts(maze, rng)
  corners = [
    Position.new(row: 1, col: maze.width - 2),
    Position.new(row: 1, col: 1),
    Position.new(row: maze.height - 2, col: maze.width - 2),
    Position.new(row: maze.height - 2, col: 1)
  ]
  brains = [Brains::Chase.new, Brains::Ambush.new, Brains::Wander.new(rng: rng), nil]
  maze.ghost_starts.each_with_index.map do |start, index|
    corner = corners.fetch(index % corners.length)
    Ghost.new(
      spawn: Spawn.new(start: start, corner: corner),
      brain: brains.fetch(index % brains.length) || Brains::Corner.new(corner: corner)
    )
  end
end

Instance Method Details

#modeObject



86
87
88
# File 'lib/pacman/arcade/world.rb', line 86

def mode
  schedule ? schedule.mode : :chase
end

#over?Boolean

Returns:

  • (Boolean)


59
60
61
# File 'lib/pacman/arcade/world.rb', line 59

def over?
  lives <= 0
end

#queue_turn(direction) ⇒ Object



78
79
80
# File 'lib/pacman/arcade/world.rb', line 78

def queue_turn(direction)
  player.queue_turn(direction)
end

#scoreObject



82
83
84
# File 'lib/pacman/arcade/world.rb', line 82

def score
  scoreboard.total
end

#tickObject



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/pacman/arcade/world.rb', line 63

def tick
  return [] if over?

  @ticks += 1
  events = []
  events.concat(advance_schedule)
  player.advance(maze)
  events.concat(eat_at(player.position))
  events.concat(resolve_collisions)
  return events if events.include?(:death)

  advance_ghosts
  events.concat(resolve_collisions)
end