Skip to content

Instantly share code, notes, and snippets.

@ninokierulf
Last active December 3, 2020 04:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ninokierulf/75ebea9dceed2718beb5f969d455e56a to your computer and use it in GitHub Desktop.
Save ninokierulf/75ebea9dceed2718beb5f969d455e56a to your computer and use it in GitHub Desktop.
SLU 2010 Among Us Source Code
class AmongUsGame {
init(players: [Player]) {
self.players = players
listenToPlayerEvents()
}
func start() {
assignTasks()
}
private func listenToPlayerEvents() {
for player in players {
player.onReport = { [weak self] deadBody, reporter in
self?.conductMeeting(
reason: MeetingReason.foundDeadBody(player: deadBody),
invoker: reporter,
onEnd: { playerActions in
self.actOnMeetingResult(meetingPlayerActions: playerActions)
})
}
player.onPressEmergencyButton = { [weak self] buttonPresser in
self?.conductMeeting(
reason: MeetingReason.emergency,
invoker: buttonPresser,
onEnd: { playerActions in
self.actOnMeetingResult(meetingPlayerActions: playerActions)
})
}
}
}
private func assignTasks() {
let commonTasksCount = 1
let shortTasksCount = 5
let longTasksCount = 1
let commonTaskStore: [CommonTask] = [
SwipeCardTask()
]
let shortTaskStore: [ShortTask] = [
FixWiresTask()
]
let longTaskStore: [LongTask] = [
ShootAsteriodsTask(),
DowloadUploadTask(),
MedScanTask()
]
for player in players {
player.accept(tasks:
commonTaskStore.random(commonTasksCount)
+ shortTaskStore.random(shortTasksCount)
+ longTaskStore.random(longTasksCount))
}
}
private func conductMeeting(reason: MeetingReason, invoker: Player, onEnd: ([MeetingAction]) -> Void) {
let context = MeetingContext(
reason: reason,
invoker: invoker,
players: players)
var playerActions: [MeetingAction] = []
for player in players {
playerActions.append(player.meetingDecision(context: context))
}
onEnd(playerActions)
}
private func actOnMeetingResult(meetingPlayerActions meetingAction: [MeetingAction]) {
var ejectVoteMap: [String : Int] = [:]
var skipCount: Int = 0
var noActionCount: Int = 0
for action in meetingAction {
switch action {
case .noAction: noActionCount++
case .skip: skipCount++
case .eject(let player):
var count: Int = ejectVoteMap[player.name] ?? 0
ejectVoteMap[player.name] = count++
}
}
var highestEjectVoteCount: Int = 0
for (playerName, voteCount) in ejectVoteMap.enumerated() {
if voteCount > highestEjectVoteCount {
highestEjectVoteCount = voteCount
}
}
var playersWithHighestEjectVoteCount: [Player] = ejectVoteMap
.filter( where: { _, voteCount in
voteCount == highestEjectVoteCount
})
if playersWithHighestEjectVoteCount.count == 1,
skipCount < highestEjectVoteCount {
eject(playersWithHighestEjectVoteCount[0])
}
else {
print("No one was ejected")
}
}
private func eject(player: Player) {
print("Ejected \(player.name)")
}
private let players: [Player]
enum MeetingReason {
case emergency
case foundDeadBody(player: Player)
}
enum MeetingAction {
case noAction
case skip
case eject(Player)
}
struct MeetingContext {
var reason: MeetingReason
var invoker: Player
var players: [Player]
}
class Player {
enum Role {
case crew
case impostor
}
enum State {
case alive
case dead
}
let name: String
let role: Role
var state: State = .alive
private var tasks: [Task] = []
var onReport: (_ deadBody: Player, _ reporter: Player) -> Void = { _ in }
var onPressEmergencyButton: (_ buttonPresser: Player) -> Void = {}
init(name: String, role: Role) {
self.name = name
self.role = role
}
func accept(tasks: [Task]) {
self.tasks = tasks
}
func meetingDecision(context: MeetingContext) -> MeetingAction {
let inDoubt: Bool = true
if inDoubt {
return .eject(context.players.first(
where: { player in player.name == "randall" })
?? Player.notFound)
}
else {
return MeetingAction.skip
}
}
private func report(deadBody: Player) {
onReport(deadBody, self)
}
private func pressEmergencyButton() {
onPressEmergencyButton(self)
}
static let notFound: Player = Player(name: "Ghost", role: .crew)
}
class Task {}
class CommonTask: Task {}
class ShortTask: Task {}
class LongTask: Task {}
class SwipeCardTask: CommonTask {}
class FixWiresTask: ShortTask {}
class ShootAsteriodsTask: LongTask {}
class DowloadUploadTask: LongTask {}
class MedScanTask: LongTask {}
}
class Main {
init() {
let game = AmongUsGame(
players: [
AmongUsGame.Player(name: "Daisy", role: .crew),
AmongUsGame.Player(name: "randall", role: .crew),
AmongUsGame.Player(name: "puster", role: .crew),
AmongUsGame.Player(name: "Gutchi", role: .impostor),
AmongUsGame.Player(name: "Uldridge 1", role: .crew),
AmongUsGame.Player(name: "nino", role: .crew),
AmongUsGame.Player(name: "Chloe", role: .crew),
AmongUsGame.Player(name: "Myel", role: .crew),
AmongUsGame.Player(name: "BossJim", role: .crew),
AmongUsGame.Player(name: "Evita", role: .crew)
])
game.start()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment