Skip to content

Rework role distribution #6

@sudojunior

Description

@sudojunior

Ultimately, I give credit to WolfiaBot for it's implementation in Java for guiding me towards a solution. But I diverge from it's logic by allowing the roles themselves to decide how much they should allocate based on the values provided to them.

  • A new Detective is added every 5 players, after at least 5 players are in game (not including said players).
  • A new Werewolf is added every 4 players.
  • The remaining role slots are handed to Villager

... and the program ends once it logs the role distribution of 1, 2 and 7 respectively.

It is theortically possible to implement this logic into the ratios by having the same failover, and I have no idea how the literal role allocation differs from ratio allocation... likely the same if it's using the same equations. It may also be possible to continue this by allowing multiple greedy roles before it terminates (removing the need for a break, but also offsetting the remaining allocation of roles to the end) - and requiring some sort of distribution code (literal split / round robin / or another ratio).

Role#getChosenRole() is currently set as a placeholder method returning name, but could serve as a role group or wildcard (when extended from Role for both).

Code Source

https://github.com/wolfiabot/Wolfia/blob/5e84f31e/src/main/java/space/npstr/wolfia/game/mafia/MafiaInfo.java#L89
https://github.com/wolfiabot/Wolfia/blob/5e84f31e/src/main/java/space/npstr/wolfia/game/CharakterSetup.java#L30

class Role {
  constructor(name, each, min = 1, afterMin = false) {
    this.name = name;
    this.each = each;
    this.min = min;
    this.afterMin = afterMin;
  }

  // future
  getChosenRole() {
    return this.name;
  }

  quantityFrom(playerCount) {
    // Take any remaining role slots
    if (this.each <= 0) return Infinity;
    if (playerCount < this.min) return 0;
    // ⌊ ({count} - {reset?min:0}) / {each} ⌋
    return Math.floor((playerCount - (this.afterMin ? this.min : 0)) / this.each);
  }
}

const roles = [
  new Role("Detective", 5, 5, true),
  new Role("Villager", 0),
  new Role("Werewolf", 4),
]
  .filter((_, index, array) => array.findIndex((r, i) => r.each === 0 && index === i))
  .sort((a, b) => b.each - a.each);

function getRoleCounts(playerCount) {
  const result = {};
  let remaining = playerCount;

  for (const role of roles) {
    const count = role.quantityFrom(playerCount);

    if (count === 0) continue;

    else if (count === Infinity) {
      result[role.name] = remaining;
      console.log("Found %s, it will take all remaining slots", role.name);
      break;
    }

    else {
      result[role.name] = count;
      remaining -= count;
    }
  }

  return result;
}

console.log(getRoleCounts(10));

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentationenhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions