Current Sprint: 2. 實作遊戲開始
repo: https://github.com/side-project-at-SPT/ithome-ironman-2024-san-juan
swagger docs: https://side-project-at-spt.github.io/ithome-ironman-2024-san-juan/
玩家依序從牌庫抽取四張卡片,作為手牌
決定起始玩家
規則書有個變體是:每位玩家抽取
(4 + n(順位))張卡片,並棄至剩 4 張,作為起始手牌
因此,我們將決定起始玩家的時機調整到發牌前,方便變體實作

choose_starting_player 實體方法starting_player
# app/models/game.rb
class Game < ApplicationRecord
# ...
    def start_new_game(seed: nil)
      game = new(status: :playing)
      # 1. generate a random seed
      game.seed = seed || SecureRandom.hex(16)
      game.save
      # 1.1. generate players
      game.game_data[:players] = generate_players(seed: game.seed).to_json
      game.game_data[:current_player_index] = 0
      game.save
      
      # ...
    end
  
    def generate_players(seed: nil)
      srand(seed.to_i(16)) if seed
      human_player = Player.new(1, [], [])
      bot_players = 3.times.map { |i| Player.new(i + 2, [], []) }
      ([ human_player ] + bot_players).shuffle
    end
# ...
end
# app/models/game.rb
class Game < ApplicationRecord
# ...
    def start_new_game(seed: nil)
      # ...
      # 3.3. shuffle the remaining cards to form a supply pile
      deck.shuffle!
      # 4. Give each player 1 indigo plant as their initial building
      players = game.players
      players.each do |player|
        player.buildings += [ Building.new("01") ]
      end
      # 5. deal 4 cards to each player as their initial hand, hidden from other players
      players.each do |player|
        player.hand = deck.shift(4)
      end
      # save the game data
      game.game_data[:players] = players.to_json
      game.game_data[:supply_pile] = deck
      game.save
      
      # ...
    end
# ...
end
1
["0", "0", "0", "0"]
110 - 4 - 4 * 4 = 90
# spec/requests/api/v1/games_spec.rb
# ...
      response '200', 'Game created' do
        schema type: :object,
          properties: {
            id: { type: :integer },
            status: { type: :string }
          },
          required: [ 'id', 'status' ]
        run_test! do
          json = JSON.parse(response.body)
          expect(json['status']).to eq('playing')
          expect(json['game_config']['seed']).to eq('1234567890abcdef')
          expect(json['game_data']['current_price']).to match_array([ 1, 2, 2, 2, 3 ])
          expect(json['game_data']['supply_pile'].size).to eq(110 - 4 - 4 * 4)
          # pp json['game_data']['supply_pile'].index { |card| card == '01' }
          expect(json['game_data']['supply_pile'][27]).to eq("01")
          expect(json['game_data']['players'].size).to eq(4)
          expect(json['game_data']['players'][0]['buildings'].size).to eq(1)
          expect(json['game_data']['players'][0]['buildings'][0]['id']).to eq("01")
          # pp json['game_data']['players'].map { |player| player['id'] }
          expect(json['game_data']['current_player_index']).to eq(0)
          expect(json['game_data']['players'][0]['id']).to eq(1)
          expect(json['game_data']['players'][0]['hand'].size).to eq(4)
          expect(json['game_data']['players'][0]['hand']).to match_array([ "00", "00", "00", "00" ])
        end
      end
# ...
# app/views/api/v1/games/_game.json.jbuilder
# ...
  json.game_data do
    # ...
    json.current_player_index game.game_data["current_player_index"]
    
    # ...
  end
# ...
rails s
# open another session
curl localhost:3000/api/v1/games -d '' | jq
{
  "id": 5,
  "status": "playing",
  "game_config": {
    "seed": "b860708c2dc20e1541a03054ee435951"
  },
  "game_data": {
    "current_price": [
      1,
      1,
      1,
      2,
      2
    ],
    "supply_pile": [], // 略
    "current_player_index": 0,
    "players": [
      {
        "id": 1,
        "hand": [
          "00",
          "00",
          "00",
          "00"
        ],
        "buildings": [
          {
            "id": "01"
          }
        ]
      },
      {
        "id": 2,
        "hand": [
          "01",
          "00",
          "00",
          "00"
        ],
        "buildings": [
          {
            "id": "01"
          }
        ]
      },
      {
        "id": 4,
        "hand": [
          "00",
          "00",
          "00",
          "00"
        ],
        "buildings": [
          {
            "id": "01"
          }
        ]
      },
      {
        "id": 3,
        "hand": [
          "00",
          "00",
          "01",
          "00"
        ],
        "buildings": [
          {
            "id": "01"
          }
        ]
      }
    ]
  }
}
收工.
還沒完成的項目有:
預估每一種回合階段花 2-3 天、行動權轉換 1-2 天、計分 1 天
=> 3 * 5 + 2 + 1 = 18
不含其它的卡片實作 
以上不代表明天會做,如有雷同純屬巧合
SPT (Side Project Taiwan) 的宗旨是藉由Side Project開發來成就自我,透過持續學習和合作,共同推動技術和專業的發展。我們相信每一個參與者,無論是什麼專業,都能在這個社群中找到屬於自己的成長空間。
歡迎所有對Side Project開發有興趣的人加入我們,可以是有點子來找夥伴,也可以是來尋找有興趣的Side Project加入,邀請大家一同打造一個充滿活力且有意義的技術社群!
Discord頻道連結:https://sideproj.tw/dc